summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Hammond <chipx86@chipx86.com>2011-01-19 09:06:02 -0500
committerThomas Thurman <tthurman@gnome.org>2011-01-19 09:09:49 -0500
commit0b5a50c85095a426f7070c5c8fe0af285ac02f62 (patch)
tree64687e0cadcd819f6c5bd9ec8e69eb869ff58279
parentef0a601819fd0b10932b7ffb1babcbce7ac29daf (diff)
downloadmetacity-0b5a50c85095a426f7070c5c8fe0af285ac02f62.tar.gz
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/
-rw-r--r--src/core/atomnames.h6
-rw-r--r--src/core/display.c43
-rw-r--r--src/core/window-private.h2
-rw-r--r--src/core/window.c116
4 files changed, 95 insertions, 72 deletions
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)
{
@@ -7997,6 +8040,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)
{