From 0b5a50c85095a426f7070c5c8fe0af285ac02f62 Mon Sep 17 00:00:00 2001 From: Christian Hammond Date: Wed, 19 Jan 2011 09:06:02 -0500 Subject: Honour _NET_RESTACK_WINDOW and sibling-relative stacking A test case for this patch is available at https://view.svn.sourceforge.net/svnroot/view/trunk/wm-test-suite/ --- src/core/atomnames.h | 6 +-- src/core/display.c | 43 ----------------- src/core/window-private.h | 2 + src/core/window.c | 116 ++++++++++++++++++++++++++++++++++++---------- 4 files changed, 95 insertions(+), 72 deletions(-) (limited to 'src') diff --git a/src/core/atomnames.h b/src/core/atomnames.h index 43710f37..338d0555 100644 --- a/src/core/atomnames.h +++ b/src/core/atomnames.h @@ -156,11 +156,7 @@ item(_NET_WM_ACTION_ABOVE) item(_NET_WM_ACTION_BELOW) item(_NET_WM_STATE_STICKY) item(_NET_WM_FULLSCREEN_MONITORS) - -#if 0 -/* We apparently never use: */ -/* item(_NET_RESTACK_WINDOW) */ -#endif +item(_NET_RESTACK_WINDOW) /* eof atomnames.h */ diff --git a/src/core/display.c b/src/core/display.c index b59571d5..e816823a 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -1358,44 +1358,6 @@ meta_display_queue_autoraise_callback (MetaDisplay *display, display->autoraise_window = window; } -#if 0 -static void -handle_net_restack_window (MetaDisplay* display, - XEvent *event) -{ - MetaWindow *window; - - window = meta_display_lookup_x_window (display, - event->xclient.window); - - if (window) - { - /* FIXME: The EWMH includes a sibling for the restack request, but we - * (stupidly) don't currently support these types of raises. - * - * Also, unconditionally following these is REALLY stupid--we should - * combine this code with the stuff in - * meta_window_configure_request() which is smart about whether to - * follow the request or do something else (though not smart enough - * and is also too stupid to handle the sibling stuff). - */ - switch (event->xclient.data.l[2]) - { - case Above: - meta_window_raise (window); - break; - case Below: - meta_window_lower (window); - break; - case TopIf: - case BottomIf: - case Opposite: - break; - } - } -} -#endif - /** * This is the most important function in the whole program. It is the heart, * it is the nexus, it is the Grand Central Station of Metacity's world. @@ -2171,11 +2133,6 @@ event_callback (XEvent *event, else if (event->xproperty.atom == display->atom__NET_DESKTOP_NAMES) meta_screen_update_workspace_names (screen); -#if 0 - else if (event->xproperty.atom == - display->atom__NET_RESTACK_WINDOW) - handle_net_restack_window (display, event); -#endif /* we just use this property as a sentinel to avoid * certain race conditions. See the comment for the diff --git a/src/core/window-private.h b/src/core/window-private.h index da3fc526..7cf5b04a 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -622,6 +622,8 @@ const char* meta_window_get_startup_id (MetaWindow *window); void meta_window_recalc_features (MetaWindow *window); void meta_window_recalc_window_type (MetaWindow *window); +void meta_window_stack_just_above (MetaWindow *window, + MetaWindow *above_this_one); void meta_window_stack_just_below (MetaWindow *window, MetaWindow *below_this_one); diff --git a/src/core/window.c b/src/core/window.c index 9af5283d..11994d51 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -58,6 +58,9 @@ static int destroying_windows_disallowed = 0; static void update_sm_hints (MetaWindow *window); static void update_net_frame_extents (MetaWindow *window); +static void restack_window (MetaWindow *window, + MetaWindow *sibling, + int direction); static void recalc_window_type (MetaWindow *window); static void recalc_window_features (MetaWindow *window); static void invalidate_work_areas (MetaWindow *window); @@ -4713,19 +4716,13 @@ meta_window_configure_request (MetaWindow *window, event->xconfigurerequest.width, event->xconfigurerequest.height); - /* Handle stacking. We only handle raises/lowers, mostly because - * stack.c really can't deal with anything else. I guess we'll fix - * that if a client turns up that really requires it. Only a very - * few clients even require the raise/lower (and in fact all client - * attempts to deal with stacking order are essentially broken, - * since they have no idea what other clients are involved or how - * the stack looks). - * - * I'm pretty sure no interesting client uses TopIf, BottomIf, or - * Opposite anyway, so the only possible missing thing is - * Above/Below with a sibling set. For now we just pretend there's - * never a sibling set and always do the full raise/lower instead of - * the raise-just-above/below-sibling. + + /* Handle stacking. We only handle raises/lowers (both absolute and + * relative to siblings), mostly because stack.c really can't deal with + * anything else. I guess we'll fix that if a client turns up that really + * requires it. Only a very few clients even require the raise/lower. I'm + * pretty sure no interesting client uses TopIf, BottomIf, or Opposite + * anyway. */ if (event->xconfigurerequest.value_mask & CWStackMode) { @@ -4757,19 +4754,15 @@ meta_window_configure_request (MetaWindow *window, } else { - switch (event->xconfigurerequest.detail) + MetaWindow *sibling = NULL; + + if (event->xconfigurerequest.above != None) { - case Above: - meta_window_raise (window); - break; - case Below: - meta_window_lower (window); - break; - case TopIf: - case BottomIf: - case Opposite: - break; + sibling = meta_display_lookup_x_window (window->display, + event->xconfigurerequest.above); } + + restack_window(window, sibling, event->xconfigurerequest.detail); } } @@ -4796,6 +4789,51 @@ meta_window_property_notify (MetaWindow *window, #define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 #define _NET_WM_MOVERESIZE_CANCEL 11 +static void +restack_window (MetaWindow *window, + MetaWindow *sibling, + int direction) +{ + switch (direction) + { + case Above: + if (sibling) + meta_window_stack_just_above (window, sibling); + else + meta_window_raise (window); + break; + case Below: + if (sibling) + meta_window_stack_just_below (window, sibling); + else + meta_window_lower (window); + break; + case TopIf: + case BottomIf: + case Opposite: + break; + } +} + +static void +handle_net_restack_window (MetaDisplay* display, + XEvent *event) +{ + MetaWindow *window, *sibling = NULL; + + window = meta_display_lookup_x_window (display, + event->xclient.window); + + if (window) + { + if (event->xclient.data.l[1]) + sibling = meta_display_lookup_x_window (display, + event->xclient.data.l[1]); + + restack_window (window, sibling, event->xclient.data.l[2]); + } +} + gboolean meta_window_client_message (MetaWindow *window, XEvent *event) @@ -4824,6 +4862,11 @@ meta_window_client_message (MetaWindow *window, return TRUE; } + else if (event->xproperty.atom == + display->atom__NET_RESTACK_WINDOW) + { + handle_net_restack_window (display, event); + } else if (event->xclient.message_type == display->atom__NET_WM_DESKTOP) { @@ -7996,6 +8039,31 @@ ensure_mru_position_after (MetaWindow *window, } } +void +meta_window_stack_just_above (MetaWindow *window, + MetaWindow *above_this_one) +{ + g_return_if_fail (window != NULL); + g_return_if_fail (above_this_one != NULL); + + if (window->stack_position < above_this_one->stack_position) + { + meta_topic (META_DEBUG_STACK, + "Setting stack position of window %s (%d) to %d (making it above window %s).\n", + window->desc, + window->stack_position, + above_this_one->stack_position, + above_this_one->desc); + meta_window_set_stack_position (window, above_this_one->stack_position); + } + else + { + meta_topic (META_DEBUG_STACK, + "Window %s was already above window %s.\n", + window->desc, above_this_one->desc); + } +} + void meta_window_stack_just_below (MetaWindow *window, MetaWindow *below_this_one) -- cgit v1.2.1