Commit 9cb0dc3d authored by rhp's avatar rhp
Browse files

...

parent f14221e8
......@@ -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";
......
......@@ -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);
......
......@@ -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);
......
......@@ -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
......@@ -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);
......
......@@ -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,
......
......@@ -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;