summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/display.c54
-rw-r--r--src/frame.c110
-rw-r--r--src/frame.h9
-rwxr-xr-xsrc/run-metacity.sh12
-rw-r--r--src/screen.c4
-rw-r--r--src/theme.c2
-rw-r--r--src/window.c343
-rw-r--r--src/window.h27
8 files changed, 413 insertions, 148 deletions
diff --git a/src/display.c b/src/display.c
index 1d56840..ec14ee3 100644
--- a/src/display.c
+++ b/src/display.c
@@ -370,6 +370,8 @@ meta_display_grab (MetaDisplay *display)
}
XSync (display->xdisplay, False);
display->server_grab_count += 1;
+ meta_verbose ("Grabbing display, grab count now %d\n",
+ display->server_grab_count);
}
void
@@ -384,10 +386,13 @@ meta_display_ungrab (MetaDisplay *display)
/* FIXME we want to purge all pending "queued" stuff
* at this point, such as window hide/show
*/
-
+ XSync (display->xdisplay, False);
XUngrabServer (display->xdisplay);
}
XSync (display->xdisplay, False);
+
+ meta_verbose ("Ungrabbing display, grab count now %d\n",
+ display->server_grab_count);
}
MetaDisplay*
@@ -532,16 +537,23 @@ event_queue_callback (MetaEventQueue *queue,
meta_window_free (window); /* Unmanage destroyed window */
break;
case UnmapNotify:
- if (window && window->mapped)
+ if (window)
{
- meta_verbose ("Window %s withdrawn\n",
- window->desc);
- meta_window_free (window); /* Unmanage withdrawn window */
+ if (window->unmaps_pending == 0)
+ {
+ meta_verbose ("Window %s withdrawn\n",
+ window->desc);
+ meta_window_free (window); /* Unmanage withdrawn window */
+ }
+ else
+ {
+ window->unmaps_pending -= 1;
+ meta_verbose ("Received pending unmap, %d now pending\n",
+ window->unmaps_pending);
+ }
}
break;
case MapNotify:
- if (window)
- window->mapped = TRUE;
break;
case MapRequest:
if (window == NULL)
@@ -809,7 +821,7 @@ meta_spew_event (MetaDisplay *display,
break;
case EnterNotify:
name = "EnterNotify";
- extra = g_strdup_printf ("win: 0x%lx root: 0x%lx subwindow: 0x%lx mode: %d detail: %d\n",
+ extra = g_strdup_printf ("win: 0x%lx root: 0x%lx subwindow: 0x%lx mode: %d detail: %d",
event->xcrossing.window,
event->xcrossing.root,
event->xcrossing.subwindow,
@@ -818,7 +830,7 @@ meta_spew_event (MetaDisplay *display,
break;
case LeaveNotify:
name = "LeaveNotify";
- extra = g_strdup_printf ("win: 0x%lx root: 0x%lx subwindow: 0x%lx mode: %d detail: %d\n",
+ extra = g_strdup_printf ("win: 0x%lx root: 0x%lx subwindow: 0x%lx mode: %d detail: %d",
event->xcrossing.window,
event->xcrossing.root,
event->xcrossing.subwindow,
@@ -903,7 +915,29 @@ meta_spew_event (MetaDisplay *display,
name = "CirculateRequest";
break;
case PropertyNotify:
- name = "PropertyNotify";
+ {
+ char *str;
+ const char *state;
+
+ name = "PropertyNotify";
+
+ meta_error_trap_push (display);
+ str = XGetAtomName (display->xdisplay,
+ event->xproperty.atom);
+ meta_error_trap_pop (display);
+
+ if (event->xproperty.state == PropertyNewValue)
+ state = "PropertyNewValue";
+ else if (event->xproperty.state == PropertyDelete)
+ state = "PropertyDelete";
+ else
+ state = "(????)";
+
+ extra = g_strdup_printf ("atom: %s state: %s",
+ str ? str : "(unknown atom)",
+ state);
+ XFree (str);
+ }
break;
case SelectionClear:
name = "SelectionClear";
diff --git a/src/frame.c b/src/frame.c
index 4e9d0bb..fc424ae 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -84,74 +84,24 @@ meta_frame_init_info (MetaFrame *frame,
info->current_control_state = META_STATE_PRELIGHT;
}
-
-/* returns values suitable for meta_window_move */
-void
-meta_frame_adjust_for_gravity (int win_gravity,
- int frame_width,
- int frame_height,
- MetaFrameGeometry *fgeom,
- int child_root_x,
- int child_root_y,
- int *win_root_x,
- int *win_root_y)
+static void
+pango_hack_start (MetaDisplay *display)
{
- int x, y;
-
- /* NW coordinate of the frame. We should just
- * compute NW coordinate to return from the start,
- * but I wrote it this way first and am now lazy
- */
- x = 0;
- y = 0;
-
- switch (win_gravity)
+ if (display->server_grab_count > 0)
{
- case NorthWestGravity:
- x = child_root_x;
- y = child_root_y;
- break;
- case NorthGravity:
- x = child_root_x - frame_width / 2;
- y = child_root_y;
- break;
- case NorthEastGravity:
- x = child_root_x - frame_width;
- y = child_root_y;
- break;
- case WestGravity:
- x = child_root_x;
- y = child_root_y - frame_height / 2;
- break;
- case CenterGravity:
- x = child_root_x - frame_width / 2;
- y = child_root_y - frame_height / 2;
- break;
- case EastGravity:
- x = child_root_x - frame_width;
- y = child_root_y - frame_height / 2;
- break;
- case SouthWestGravity:
- x = child_root_x;
- y = child_root_y - frame_height;
- break;
- case SouthGravity:
- x = child_root_x - frame_width / 2;
- y = child_root_y - frame_height;
- break;
- case SouthEastGravity:
- x = child_root_x - frame_width;
- y = child_root_y - frame_height;
- break;
- case StaticGravity:
- default:
- x = child_root_x - fgeom->left_width;
- y = child_root_y - fgeom->top_height;
- break;
+ meta_verbose ("Pango workaround, ungrabbing server\n");
+ XUngrabServer (display->xdisplay);
}
+}
- *win_root_x = x + fgeom->left_width;
- *win_root_y = y + fgeom->top_height;
+static void
+pango_hack_end (MetaDisplay *display)
+{
+ if (display->server_grab_count > 0)
+ {
+ meta_verbose ("Pango workaround, regrabbing server\n");
+ XGrabServer (display->xdisplay);
+ }
}
void
@@ -193,8 +143,10 @@ meta_frame_calc_geometry (MetaFrame *frame,
geom.shape_mask = None;
+ pango_hack_start (frame->window->display);
window->screen->engine->fill_frame_geometry (&info, &geom,
frame->theme_data);
+ pango_hack_end (frame->window->display);
*geomp = geom;
}
@@ -242,6 +194,8 @@ meta_window_ensure_frame (MetaWindow *window)
{
MetaFrame *frame;
XSetWindowAttributes attrs;
+
+ g_return_if_fail (window->display->server_grab_count > 0);
if (window->frame)
return;
@@ -286,16 +240,16 @@ meta_window_ensure_frame (MetaWindow *window)
/* Reparent the client window; it may be destroyed,
* thus the error trap. We'll get a destroy notify later
* and free everything. Comment in FVWM source code says
- * we need the server grab or the child can get its MapNotify
+ * we need a server grab or the child can get its MapNotify
* before we've finished reparenting and getting the decoration
- * window onscreen.
+ * window onscreen, so ensure_frame must be called with
+ * a grab.
*/
- meta_display_grab (window->display);
-
meta_error_trap_push (window->display);
window->mapped = FALSE; /* the reparent will unmap the window,
* we don't want to take that as a withdraw
*/
+ window->unmaps_pending += 1;
XReparentWindow (window->display->xdisplay,
window->xwindow,
frame->xwindow,
@@ -304,11 +258,6 @@ meta_window_ensure_frame (MetaWindow *window)
/* stick frame to the window */
window->frame = frame;
-
- /* Ungrab server (FIXME after fixing Pango not to lock us up,
- * we need to recalc geometry before ungrabbing)
- */
- meta_display_ungrab (window->display);
}
void
@@ -339,6 +288,7 @@ meta_window_destroy_frame (MetaWindow *window)
* can identify a withdraw initiated
* by the client.
*/
+ window->unmaps_pending += 1;
XReparentWindow (window->display->xdisplay,
window->xwindow,
window->screen->xroot,
@@ -366,9 +316,11 @@ meta_frame_sync_to_window (MetaFrame *frame,
gboolean need_move,
gboolean need_resize)
{
- meta_verbose ("Syncing frame geometry %d,%d %dx%d pixel %ld\n",
+ meta_verbose ("Syncing frame geometry %d,%d %dx%d (SE: %d,%d) pixel %ld\n",
frame->rect.x, frame->rect.y,
frame->rect.width, frame->rect.height,
+ frame->rect.x + frame->rect.width,
+ frame->rect.y + frame->rect.height,
frame->bg_pixel);
/* set bg to none to avoid flicker */
@@ -439,10 +391,12 @@ meta_frame_draw_now (MetaFrame *frame,
info.drawable = p;
info.xoffset = - x;
info.yoffset = - y;
+ pango_hack_start (frame->window->display);
frame->window->screen->engine->expose_frame (&info,
0, 0, width, height,
frame->theme_data);
-
+ pango_hack_end (frame->window->display);
+
XCopyArea (frame->window->display->xdisplay,
p, frame->xwindow,
@@ -609,7 +563,8 @@ update_move (MetaFrame *frame,
dx = x - frame->grab->start_root_x;
dy = y - frame->grab->start_root_y;
-
+
+ frame->window->user_has_moved = TRUE;
meta_window_move (frame->window,
frame->grab->start_window_x + dx,
frame->grab->start_window_y + dy);
@@ -623,7 +578,8 @@ update_resize_se (MetaFrame *frame,
dx = x - frame->grab->start_root_x;
dy = y - frame->grab->start_root_y;
-
+
+ frame->window->user_has_resized = TRUE;
meta_window_resize (frame->window,
frame->grab->start_window_x + dx,
frame->grab->start_window_y + dy);
diff --git a/src/frame.h b/src/frame.h
index 4947142..83cfda3 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -76,15 +76,6 @@ void meta_frame_calc_geometry (MetaFrame *frame,
int child_width,
int child_height,
MetaFrameGeometry *geomp);
-/* returns values suitable for meta_window_move */
-void meta_frame_adjust_for_gravity (int win_gravity,
- int frame_width,
- int frame_height,
- MetaFrameGeometry *fgeom,
- int x,
- int y,
- int *win_root_x,
- int *win_root_y);
void meta_frame_sync_to_window (MetaFrame *frame,
gboolean need_move,
gboolean need_resize);
diff --git a/src/run-metacity.sh b/src/run-metacity.sh
index 24e0489..9f150c4 100755
--- a/src/run-metacity.sh
+++ b/src/run-metacity.sh
@@ -9,7 +9,19 @@ elif test -z "$DEBUG"; then
DEBUG=gdb
fi
+if test -z "$CLIENTS"; then
+ CLIENTS=0
+fi
+
Xnest :1 -scrns $SCREENS -geometry 640x480 -bw 15 &
usleep 50000
+
+if test $CLIENTS != 0; then
+ for I in `seq 1 $CLIENTS`; do
+ DISPLAY=:1 xterm -geometry 25x15 &
+ done
+fi
+
+DISPLAY=:1 xsetroot -solid royalblue3
METACITY_UISLAVE_DIR=./uislave DISPLAY=:1 unst libtool --mode=execute $DEBUG ./metacity
killall Xnest
diff --git a/src/screen.c b/src/screen.c
index a13f9a3..90f75d2 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -239,7 +239,8 @@ meta_screen_manage_all_windows (MetaScreen *screen)
meta_display_ungrab (screen->display);
return;
}
-
+
+ meta_stack_freeze (screen->stack);
i = 0;
while (i < n_children)
{
@@ -247,6 +248,7 @@ meta_screen_manage_all_windows (MetaScreen *screen)
++i;
}
+ meta_stack_thaw (screen->stack);
meta_display_ungrab (screen->display);
diff --git a/src/theme.c b/src/theme.c
index 11f911e..c80c2a3 100644
--- a/src/theme.c
+++ b/src/theme.c
@@ -309,7 +309,7 @@ calc_geometry (MetaFrameInfo *info,
if (fgeom->title_rect.width < 0)
fgeom->title_rect.width = 0;
}
-
+
static void
default_fill_frame_geometry (MetaFrameInfo *info,
MetaFrameGeometry *geom,
diff --git a/src/window.c b/src/window.c
index 809bce7..a63b2ec 100644
--- a/src/window.c
+++ b/src/window.c
@@ -29,6 +29,7 @@
#include <X11/Xatom.h>
static void constrain_size (MetaWindow *window,
+ MetaFrameGeometry *fgeom,
int width,
int height,
int *new_width,
@@ -82,18 +83,31 @@ meta_window_new (MetaDisplay *display, Window xwindow)
GSList *tmp;
meta_verbose ("Attempting to manage 0x%lx\n", xwindow);
+
+ /* Grab server */
+ meta_display_grab (display);
- /* round trip */
meta_error_trap_push (display);
- if (XGetWindowAttributes (display->xdisplay,
- xwindow, &attrs) == Success &&
- attrs.override_redirect)
+ XGetWindowAttributes (display->xdisplay,
+ xwindow, &attrs);
+
+ if (meta_error_trap_pop (display))
+ {
+ meta_verbose ("Failed to get attributes for window 0x%lx\n",
+ xwindow);
+ meta_display_ungrab (display);
+ return NULL;
+ }
+
+ if (attrs.override_redirect)
{
meta_verbose ("Deciding not to manage override_redirect window 0x%lx\n", xwindow);
- meta_error_trap_pop (display);
+ meta_display_ungrab (display);
return NULL;
}
+
+ meta_error_trap_push (display);
XAddToSaveSet (display->xdisplay, xwindow);
@@ -110,9 +124,11 @@ meta_window_new (MetaDisplay *display, Window xwindow)
{
meta_verbose ("Window 0x%lx disappeared just as we tried to manage it\n",
xwindow);
-
+ meta_display_ungrab (display);
return NULL;
}
+
+ g_assert (!attrs.override_redirect);
window = g_new (MetaWindow, 1);
@@ -139,6 +155,9 @@ meta_window_new (MetaDisplay *display, Window xwindow)
g_assert (window->screen);
+ /* avoid tons of stack updates */
+ meta_stack_freeze (window->screen->stack);
+
/* Remember this rect is the actual window size */
window->rect.x = attrs.x;
window->rect.y = attrs.y;
@@ -165,6 +184,9 @@ meta_window_new (MetaDisplay *display, Window xwindow)
window->frame = NULL;
window->has_focus = FALSE;
+ window->user_has_resized = FALSE;
+ window->user_has_moved = FALSE;
+
window->maximized = FALSE;
window->on_all_workspaces = FALSE;
window->shaded = FALSE;
@@ -173,6 +195,8 @@ meta_window_new (MetaDisplay *display, Window xwindow)
window->iconic = FALSE;
window->mapped = FALSE;
+ window->unmaps_pending = 0;
+
window->decorated = TRUE;
window->has_close_func = TRUE;
window->has_minimize_func = TRUE;
@@ -220,7 +244,8 @@ meta_window_new (MetaDisplay *display, Window xwindow)
* change it again.
*/
set_wm_state (window, window->iconic ? IconicState : NormalState);
-
+ set_net_wm_state (window);
+
if (window->decorated)
meta_window_ensure_frame (window);
@@ -238,8 +263,13 @@ meta_window_new (MetaDisplay *display, Window xwindow)
meta_stack_add (window->screen->stack,
window);
-
+
+ /* Sync stack changes */
+ meta_stack_thaw (window->screen->stack);
+
meta_window_queue_calc_showing (window);
+
+ meta_display_ungrab (display);
return window;
}
@@ -294,18 +324,54 @@ static int
set_wm_state (MetaWindow *window,
int state)
{
- unsigned long data[1];
+ unsigned long data[2];
/* twm sets the icon window as data[1], I couldn't find that in
* ICCCM.
*/
data[0] = state;
+ data[1] = None;
meta_error_trap_push (window->display);
XChangeProperty (window->display->xdisplay, window->xwindow,
window->display->atom_wm_state,
window->display->atom_wm_state,
- 32, PropModeReplace, (guchar*) data, 1);
+ 32, PropModeReplace, (guchar*) data, 2);
+ return meta_error_trap_pop (window->display);
+}
+
+static int
+set_net_wm_state (MetaWindow *window)
+{
+ int i;
+ unsigned long data[10];
+
+ i = 0;
+ if (window->shaded)
+ {
+ data[i] = window->display->atom_net_wm_state_shaded;
+ ++i;
+ }
+ if (window->wm_state_modal)
+ {
+ data[i] = window->display->atom_net_wm_state_modal;
+ ++i;
+ }
+ if (window->maximized)
+ {
+ data[i] = window->display->atom_net_wm_state_maximized_horz;
+ ++i;
+ data[i] = window->display->atom_net_wm_state_maximized_vert;
+ ++i;
+ }
+
+ meta_verbose ("Setting _NET_WM_STATE with %d atoms\n", i);
+
+ meta_error_trap_push (window->display);
+ XChangeProperty (window->display->xdisplay, window->xwindow,
+ window->display->atom_net_wm_state,
+ XA_ATOM,
+ 32, PropModeReplace, (guchar*) data, i);
return meta_error_trap_pop (window->display);
}
@@ -370,6 +436,7 @@ meta_window_show (MetaWindow *window)
{
meta_verbose ("%s actually needs unmap\n", window->desc);
window->mapped = FALSE;
+ window->unmaps_pending += 1;
meta_error_trap_push (window->display);
XUnmapWindow (window->display->xdisplay, window->xwindow);
meta_error_trap_pop (window->display);
@@ -416,6 +483,7 @@ meta_window_hide (MetaWindow *window)
{
meta_verbose ("%s actually needs unmap\n", window->desc);
window->mapped = FALSE;
+ window->unmaps_pending += 1;
XUnmapWindow (window->display->xdisplay, window->xwindow);
}
@@ -464,6 +532,8 @@ meta_window_maximize (MetaWindow *window)
/* move_resize with new maximization constraints
*/
meta_window_queue_move_resize (window);
+
+ set_net_wm_state (window);
}
}
@@ -479,6 +549,8 @@ meta_window_unmaximize (MetaWindow *window)
window->saved_rect.y,
window->saved_rect.width,
window->saved_rect.height);
+
+ set_net_wm_state (window);
}
}
@@ -490,6 +562,8 @@ meta_window_shade (MetaWindow *window)
window->shaded = TRUE;
meta_window_queue_move_resize (window);
meta_window_queue_calc_showing (window);
+
+ set_net_wm_state (window);
}
}
@@ -504,6 +578,142 @@ meta_window_unshade (MetaWindow *window)
/* focus the window */
/* FIXME CurrentTime is bogus */
meta_window_focus (window, CurrentTime);
+
+ set_net_wm_state (window);
+ }
+}
+
+
+/* returns values suitable for meta_window_move */
+void
+adjust_for_gravity (MetaWindow *window,
+ MetaFrameGeometry *fgeom,
+ gboolean coords_assume_border,
+ int x,
+ int y,
+ int *xp,
+ int *yp)
+{
+ int ref_x, ref_y;
+ int bw;
+ int child_x, child_y;
+ int frame_width, frame_height;
+
+ if (coords_assume_border)
+ bw = window->border_width;
+ else
+ bw = 0;
+
+ if (fgeom)
+ {
+ child_x = fgeom->left_width;
+ child_y = fgeom->top_height;
+ frame_width = child_x + window->rect.width + fgeom->right_width;
+ frame_height = child_y + window->rect.height + fgeom->bottom_height;
+ }
+ else
+ {
+ child_x = 0;
+ child_y = 0;
+ frame_width = window->rect.width;
+ frame_height = window->rect.height;
+ }
+
+ /* We're computing position to pass to window_move, which is
+ * the position of the client window (StaticGravity basically)
+ *
+ * (see WM spec description of gravity computation, but note that
+ * their formulas assume we're honoring the border width, rather
+ * than compensating for having turned it off)
+ */
+ switch (window->size_hints.win_gravity)
+ {
+ case NorthWestGravity:
+ ref_x = x;
+ ref_y = y;
+ break;
+ case NorthGravity:
+ ref_x = x + window->rect.width / 2 + bw;
+ ref_y = y;
+ break;
+ case NorthEastGravity:
+ ref_x = x + window->rect.width + bw * 2;
+ ref_y = y;
+ break;
+ case WestGravity:
+ ref_x = x;
+ ref_y = y + window->rect.height / 2 + bw;
+ break;
+ case CenterGravity:
+ ref_x = x + window->rect.width / 2 + bw;
+ ref_y = y + window->rect.height / 2 + bw;
+ break;
+ case EastGravity:
+ ref_x = x + window->rect.width + bw * 2;
+ ref_y = y + window->rect.height / 2 + bw;
+ break;
+ case SouthWestGravity:
+ ref_x = x;
+ ref_y = y + window->rect.height + bw * 2;
+ break;
+ case SouthGravity:
+ ref_x = x + window->rect.width / 2 + bw;
+ ref_y = y + window->rect.height + bw * 2;
+ break;
+ case SouthEastGravity:
+ ref_x = x + window->rect.width + bw * 2;
+ ref_y = y + window->rect.height + bw * 2;
+ break;
+ case StaticGravity:
+ default:
+ ref_x = x;
+ ref_y = y;
+ break;
+ }
+
+ switch (window->size_hints.win_gravity)
+ {
+ case NorthWestGravity:
+ *xp = ref_x + child_x;
+ *yp = ref_y + child_y;
+ break;
+ case NorthGravity:
+ *xp = ref_x - frame_width / 2 + child_x;
+ *yp = ref_y + child_y;
+ break;
+ case NorthEastGravity:
+ *xp = ref_x - frame_width + child_x;
+ *yp = ref_y + child_y;
+ break;
+ case WestGravity:
+ *xp = ref_x + child_x;
+ *yp = ref_y - frame_height / 2 + child_y;
+ break;
+ case CenterGravity:
+ *xp = ref_x - frame_width / 2 + child_x;
+ *yp = ref_y - frame_height / 2 + child_y;
+ break;
+ case EastGravity:
+ *xp = ref_x - frame_width + child_x;
+ *yp = ref_y - frame_height / 2 + child_y;
+ break;
+ case SouthWestGravity:
+ *xp = ref_x + child_x;
+ *yp = ref_y - frame_height + child_y;
+ break;
+ case SouthGravity:
+ *xp = ref_x - frame_width / 2 + child_x;
+ *yp = ref_y - frame_height + child_y;
+ break;
+ case SouthEastGravity:
+ *xp = ref_x - frame_width + child_x;
+ *yp = ref_y - frame_height + child_y;
+ break;
+ case StaticGravity:
+ default:
+ *xp = ref_x;
+ *yp = ref_y;
+ break;
}
}
@@ -524,10 +734,22 @@ meta_window_move_resize_internal (MetaWindow *window,
gboolean need_resize_client = FALSE;
gboolean need_resize_frame = FALSE;
- meta_verbose ("Move/resize %s to %d,%d %dx%d\n",
- window->desc, root_x_nw, root_y_nw, w, h);
+ meta_verbose ("Move/resize %s to %d,%d %dx%d%s\n",
+ window->desc, root_x_nw, root_y_nw, w, h,
+ is_configure_request ? " (configure request)" : "");
- constrain_size (window, w, h, &w, &h);
+ /* FIXME we're passing old window size to calc_geometry,
+ * I believe the right fix is to remove window size
+ * args from calc_geometry and remove any dependency
+ * on that in frame code.
+ */
+ if (window->frame)
+ meta_frame_calc_geometry (window->frame,
+ window->rect.width,
+ window->rect.height,
+ &fgeom);
+
+ constrain_size (window, &fgeom, w, h, &w, &h);
meta_verbose ("Constrained resize of %s to %d x %d\n", window->desc, w, h);
if (w != window->rect.width ||
@@ -540,11 +762,6 @@ meta_window_move_resize_internal (MetaWindow *window,
if (window->frame)
{
int new_w, new_h;
-
- meta_frame_calc_geometry (window->frame,
- window->rect.width,
- window->rect.height,
- &fgeom);
new_w = window->rect.width + fgeom.left_width + fgeom.right_width;
@@ -563,23 +780,25 @@ meta_window_move_resize_internal (MetaWindow *window,
meta_verbose ("Calculated frame size %dx%d\n",
window->frame->rect.width,
window->frame->rect.height);
-
- if (is_configure_request)
- {
- meta_frame_adjust_for_gravity (window->size_hints.win_gravity,
- window->frame->rect.width,
- window->frame->rect.height,
- &fgeom,
- root_x_nw,
- root_y_nw,
- &root_x_nw,
- &root_y_nw);
-
- meta_verbose ("Compensated position for gravity, new pos %d,%d\n",
- root_x_nw, root_y_nw);
- }
}
+
+ if (is_configure_request)
+ {
+ adjust_for_gravity (window,
+ window->frame ? &fgeom : NULL,
+ /* configure request coords assume
+ * the border width existed
+ */
+ is_configure_request,
+ root_x_nw,
+ root_y_nw,
+ &root_x_nw,
+ &root_y_nw);
+ meta_verbose ("Compensated position for gravity, new pos %d,%d\n",
+ root_x_nw, root_y_nw);
+ }
+
constrain_position (window,
window->frame ? &fgeom : NULL,
root_x_nw, root_y_nw,
@@ -1079,6 +1298,18 @@ meta_window_client_message (MetaWindow *window,
meta_window_unmaximize (window);
}
+ if (first == display->atom_net_wm_state_modal ||
+ second == display->atom_net_wm_state_modal)
+ {
+ window->wm_state_modal =
+ (action == _NET_WM_STATE_ADD) ||
+ (action == _NET_WM_STATE_TOGGLE && !window->wm_state_modal);
+
+ recalc_window_type (window);
+ meta_window_queue_move_resize (window);
+ set_net_wm_state (window);
+ }
+
return TRUE;
}
else if (event->xclient.message_type ==
@@ -1244,6 +1475,9 @@ static int
update_size_hints (MetaWindow *window)
{
int x, y, w, h;
+ gulong supplied;
+
+ meta_verbose ("Updating WM_NORMAL_HINTS\n");
/* Save the last ConfigureRequest, which we put here.
* Values here set in the hints are supposed to
@@ -1255,11 +1489,19 @@ update_size_hints (MetaWindow *window)
h = window->size_hints.height;
window->size_hints.flags = 0;
+ supplied = 0;
meta_error_trap_push (window->display);
- XGetNormalHints (window->display->xdisplay,
- window->xwindow,
- &window->size_hints);
+ XGetWMNormalHints (window->display->xdisplay,
+ window->xwindow,
+ &window->size_hints,
+ &supplied);
+
+ /* as far as I can tell, "supplied" is just
+ * to check whether we had old-style normal hints
+ * without gravity, base size as returned by
+ * XGetNormalHints()
+ */
/* Put it back. */
window->size_hints.x = x;
@@ -1375,6 +1617,8 @@ update_size_hints (MetaWindow *window)
}
else
{
+ meta_verbose ("Window %s doesn't set gravity, using NW\n",
+ window->desc);
window->size_hints.win_gravity = NorthWestGravity;
window->size_hints.flags |= PWinGravity;
}
@@ -1885,7 +2129,6 @@ update_transient_for (MetaWindow *window)
/* update stacking constraints */
meta_stack_update_transient (window->screen->stack, window);
- meta_stack_update_layer (window->screen->stack, window);
return meta_error_trap_pop (window->display);
}
@@ -2004,6 +2247,7 @@ recalc_window_type (MetaWindow *window)
static void
constrain_size (MetaWindow *window,
+ MetaFrameGeometry *fgeom,
int width, int height,
int *new_width, int *new_height)
{
@@ -2023,19 +2267,25 @@ constrain_size (MetaWindow *window,
/* frame member variables should NEVER be used in here */
#define FLOOR(value, base) ( ((gint) ((value) / (base))) * (base) )
-
+
/* Get the allowed size ranges, considering maximized, etc. */
fullw = window->screen->active_workspace->workarea.width;
fullh = window->screen->active_workspace->workarea.height;
if (window->frame)
{
- fullw -= window->frame->child_x + window->frame->right_width;
- fullh -= window->frame->child_y + window->frame->bottom_height;
+ fullw -= fgeom->left_width + fgeom->right_width;
+ fullh -= fgeom->top_height + fgeom->bottom_height;
}
maxw = window->size_hints.max_width;
maxh = window->size_hints.max_height;
- if (window->maximized)
+
+ /* If user hasn't resized or moved, then try to shrink the window to
+ * fit onscreen, while not violating the min size, just as
+ * we do for maximize
+ */
+ if (window->maximized ||
+ !(window->user_has_resized || window->user_has_moved))
{
maxw = MIN (maxw, fullw);
maxh = MIN (maxh, fullh);
@@ -2043,12 +2293,21 @@ constrain_size (MetaWindow *window,
minw = window->size_hints.min_width;
minh = window->size_hints.min_height;
+
+ /* Check that fullscreen doesn't go under app-specified min size, if
+ * so snap back to min size
+ */
+ if (maxw < minw)
+ maxw = minw;
+ if (maxh < minh)
+ maxh = minh;
+
if (window->maximized)
{
minw = MAX (minw, fullw);
minh = MAX (minh, fullh);
}
-
+
/* Check that fullscreen doesn't exceed max width hint,
* if so then snap back to max width hint
*/
diff --git a/src/window.h b/src/window.h
index cd44a96..c214674 100644
--- a/src/window.h
+++ b/src/window.h
@@ -77,17 +77,15 @@ struct _MetaWindow
* have no stupid viewports)
*/
guint on_all_workspaces : 1;
-
- /* Mapped is what we think the mapped state should be;
- * so if we get UnmapNotify and mapped == TRUE then
- * it's a withdraw, if mapped == FALSE the UnmapNotify
- * is caused by us.
- */
- guint mapped : 1 ;
/* Minimize is the state controlled by the minimize button */
guint minimized : 1;
+ /* Whether the window is mapped; actual server-side state
+ * see also unmaps_pending
+ */
+ guint mapped : 1;
+
/* Iconic is the state in WM_STATE; happens for workspaces/shading
* in addition to minimize
*/
@@ -116,7 +114,20 @@ struct _MetaWindow
* determines whether we draw the focus
*/
guint has_focus : 1;
-
+
+ /* Track whether the user has ever manually modified
+ * the window; if so, we remove some constraints
+ * that exist on program modifications.
+ */
+ guint user_has_resized : 1;
+ guint user_has_moved : 1;
+
+ /* Number of UnmapNotify that are caused by us, if
+ * we get UnmapNotify with none pending then the client
+ * is withdrawing the window.
+ */
+ int unmaps_pending;
+
/* The size we set the window to last (i.e. what we believe
* to be its actual size on the server). The x, y are
* the actual server-side x,y so are relative to the frame