[mutter] x11/window: Implement _NET_RESTACK_WINDOW and XConfigureRequestEvent sibling



commit e3d59832c56dbc6acb4301836bc54c467889d515
Author: Vasilis Liaskovitis <vliaskovitis suse com>
Date:   Fri Sep 29 16:57:22 2017 +0200

    x11/window: Implement _NET_RESTACK_WINDOW and XConfigureRequestEvent sibling
    
    Implement _NET_RESTACK_WINDOW, based on metacity commit 0b5a50c8.
    
    Also respect "above" field (sibling) of XConfigureRequestEvent. When it is
    set, perform a stack operation relative to that sibling.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=786363
    https://bugzilla.gnome.org/show_bug.cgi?id=786365

 src/core/window-private.h |    3 ++
 src/core/window.c         |   24 ++++++++++++
 src/x11/atomnames.h       |    1 +
 src/x11/window-x11.c      |   86 +++++++++++++++++++++++++++++++++++++--------
 4 files changed, 99 insertions(+), 15 deletions(-)
---
diff --git a/src/core/window-private.h b/src/core/window-private.h
index 013bad7..c3a1c02 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -682,6 +682,9 @@ void meta_window_frame_size_changed (MetaWindow *window);
 void meta_window_stack_just_below (MetaWindow *window,
                                    MetaWindow *below_this_one);
 
+void meta_window_stack_just_above (MetaWindow *window,
+                                   MetaWindow *above_this_one);
+
 void meta_window_set_user_time (MetaWindow *window,
                                 guint32     timestamp);
 
diff --git a/src/core/window.c b/src/core/window.c
index 1fc483d..d450a5c 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -6728,6 +6728,30 @@ meta_window_stack_just_below (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 to %d (making it above window %s).\n",
+                  window->desc,
+                  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);
+    }
+}
+
 /**
  * meta_window_get_user_time:
  * @window: a #MetaWindow
diff --git a/src/x11/atomnames.h b/src/x11/atomnames.h
index e37e8fa..ff6c6cc 100644
--- a/src/x11/atomnames.h
+++ b/src/x11/atomnames.h
@@ -176,6 +176,7 @@ item(_NET_WM_OPAQUE_REGION)
 item(_NET_WM_FRAME_DRAWN)
 item(_NET_WM_FRAME_TIMINGS)
 item(_NET_WM_WINDOW_OPACITY)
+item(_NET_RESTACK_WINDOW)
 
 /* eof atomnames.h */
 
diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c
index ad5058b..bc922c1 100644
--- a/src/x11/window-x11.c
+++ b/src/x11/window-x11.c
@@ -2092,6 +2092,32 @@ meta_window_move_resize_request (MetaWindow *window,
     }
 }
 
+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;
+   }
+}
+
 gboolean
 meta_window_x11_configure_request (MetaWindow *window,
                                    XEvent     *event)
@@ -2125,10 +2151,7 @@ meta_window_x11_configure_request (MetaWindow *window,
    * 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.
+   * Opposite anyway.
    */
   if (event->xconfigurerequest.value_mask & CWStackMode)
     {
@@ -2160,19 +2183,23 @@ meta_window_x11_configure_request (MetaWindow *window,
         }
       else
         {
-          switch (event->xconfigurerequest.detail)
+          MetaWindow *sibling = NULL;
+          /* Handle Above/Below with a sibling set */
+          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;
+              MetaDisplay *display;
+
+              display = meta_window_get_display (window);
+              sibling = meta_display_lookup_x_window (display,
+                                                      event->xconfigurerequest.above);
+              if (sibling == NULL)
+                return TRUE;
+
+              meta_topic (META_DEBUG_STACK,
+                      "xconfigure stacking request from window %s sibling %s stackmode %d\n",
+                      window->desc, sibling->desc, event->xconfigurerequest.detail);
             }
+          restack_window (window, sibling, event->xconfigurerequest.detail);
         }
     }
 
@@ -2245,6 +2272,30 @@ query_pressed_buttons (MetaWindow *window)
   return button;
 }
 
+static void
+handle_net_restack_window (MetaDisplay *display,
+                           XEvent      *event)
+{
+  MetaWindow *window, *sibling = NULL;
+
+  /* Ignore if this does not come from a pager, see the WM spec
+   */
+  if (event->xclient.data.l[0] != 2)
+    return;
+
+  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_x11_client_message (MetaWindow *window,
                                 XEvent     *event)
@@ -2728,6 +2779,11 @@ meta_window_x11_client_message (MetaWindow *window,
 
       meta_window_show_menu (window, META_WINDOW_MENU_WM, x, y);
     }
+  else if (event->xclient.message_type ==
+           display->atom__NET_RESTACK_WINDOW)
+    {
+      handle_net_restack_window (display, event);
+    }
 
   return FALSE;
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]