[mutter] stack: Delegate layer calculation to a window vfunc



commit c843102eecff1248e4256488f5a254c7ab07b800
Author: Florian Müllner <fmuellner gnome org>
Date:   Tue Nov 26 20:53:24 2019 +0100

    stack: Delegate layer calculation to a window vfunc
    
    While most of the code to compute a window's layer isn't explicitly
    windowing backend specific, it is in practice: On wayland there are
    no DESKTOP windows(*), docks(*) or groups.
    
    Reflect that by introducing a calculate_layer() vfunc that computes
    (and sets) a window's layer.
    
    (*) they shall burn in hell, amen!
    
    https://gitlab.gnome.org/GNOME/mutter/merge_requests/949

 src/core/stack.c                  | 128 +-------------------------------------
 src/core/window-private.h         |   4 ++
 src/core/window.c                 |   6 ++
 src/wayland/meta-window-wayland.c |   7 +++
 src/x11/window-x11.c              | 119 +++++++++++++++++++++++++++++++++++
 5 files changed, 137 insertions(+), 127 deletions(-)
---
diff --git a/src/core/stack.c b/src/core/stack.c
index f97909a58..6518be9b3 100644
--- a/src/core/stack.c
+++ b/src/core/stack.c
@@ -441,132 +441,6 @@ meta_stack_update_window_tile_matches (MetaStack     *stack,
   g_list_free (windows);
 }
 
-/* Get layer ignoring any transient or group relationships */
-static MetaStackLayer
-get_standalone_layer (MetaWindow *window)
-{
-  MetaStackLayer layer;
-
-  switch (window->type)
-    {
-    case META_WINDOW_DESKTOP:
-      layer = META_LAYER_DESKTOP;
-      break;
-
-    case META_WINDOW_DOCK:
-      if (window->wm_state_below ||
-          (window->monitor && window->monitor->in_fullscreen))
-        layer = META_LAYER_BOTTOM;
-      else
-        layer = META_LAYER_DOCK;
-      break;
-
-    case META_WINDOW_DROPDOWN_MENU:
-    case META_WINDOW_POPUP_MENU:
-    case META_WINDOW_TOOLTIP:
-    case META_WINDOW_NOTIFICATION:
-    case META_WINDOW_COMBO:
-    case META_WINDOW_OVERRIDE_OTHER:
-      switch (window->client_type)
-        {
-        case META_WINDOW_CLIENT_TYPE_X11:
-          layer = META_LAYER_OVERRIDE_REDIRECT;
-          break;
-        case META_WINDOW_CLIENT_TYPE_WAYLAND:
-          layer = META_LAYER_NORMAL;
-          break;
-        default:
-          g_assert_not_reached ();
-        }
-      break;
-    default:
-      layer = meta_window_get_default_layer (window);
-      break;
-    }
-
-  return layer;
-}
-
-/* Note that this function can never use window->layer only
- * get_standalone_layer, or we'd have issues.
- */
-static MetaStackLayer
-get_maximum_layer_in_group (MetaWindow *window)
-{
-  GSList *members;
-  MetaGroup *group;
-  GSList *tmp;
-  MetaStackLayer max;
-  MetaStackLayer layer;
-
-  max = META_LAYER_DESKTOP;
-
-  group = meta_window_get_group (window);
-
-  if (group != NULL)
-    members = meta_group_list_windows (group);
-  else
-    members = NULL;
-
-  tmp = members;
-  while (tmp != NULL)
-    {
-      MetaWindow *w = tmp->data;
-
-      if (!w->override_redirect)
-        {
-          layer = get_standalone_layer (w);
-          if (layer > max)
-            max = layer;
-        }
-
-      tmp = tmp->next;
-    }
-
-  g_slist_free (members);
-
-  return max;
-}
-
-static void
-compute_layer (MetaWindow *window)
-{
-  window->layer = get_standalone_layer (window);
-
-  /* We can only do promotion-due-to-group for dialogs and other
-   * transients, or weird stuff happens like the desktop window and
-   * nautilus windows getting in the same layer, or all gnome-terminal
-   * windows getting in fullscreen layer if any terminal is
-   * fullscreen.
-   */
-  if (window->layer != META_LAYER_DESKTOP &&
-      meta_window_has_transient_type (window) &&
-      window->transient_for == NULL)
-    {
-      /* We only do the group thing if the dialog is NOT transient for
-       * a particular window. Imagine a group with a normal window, a dock,
-       * and a dialog transient for the normal window; you don't want the dialog
-       * above the dock if it wouldn't normally be.
-       */
-
-      MetaStackLayer group_max;
-
-      group_max = get_maximum_layer_in_group (window);
-
-      if (group_max > window->layer)
-        {
-          meta_topic (META_DEBUG_STACK,
-                      "Promoting window %s from layer %u to %u due to group membership\n",
-                      window->desc, window->layer, group_max);
-          window->layer = group_max;
-        }
-    }
-
-  meta_topic (META_DEBUG_STACK, "Window %s on layer %u type = %u has_focus = %d\n",
-              window->desc, window->layer,
-              window->type, window->has_focus);
-}
-
 /* Front of the layer list is the topmost window,
  * so the lower stack position is later in the list
  */
@@ -957,7 +831,7 @@ stack_do_relayer (MetaStack *stack)
       w = tmp->data;
       old_layer = w->layer;
 
-      compute_layer (w);
+      w->layer = meta_window_calculate_layer (w);
 
       if (w->layer != old_layer)
         {
diff --git a/src/core/window-private.h b/src/core/window-private.h
index 3fd9f146e..6e7563f8e 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -589,6 +589,8 @@ struct _MetaWindowClass
   gboolean (*can_ping)            (MetaWindow *window);
   gboolean (*are_updates_frozen)  (MetaWindow *window);
 
+  MetaStackLayer (*calculate_layer) (MetaWindow *window);
+
   void (* map)   (MetaWindow *window);
   void (* unmap) (MetaWindow *window);
 };
@@ -693,6 +695,8 @@ gboolean meta_window_is_focusable (MetaWindow *window);
 
 gboolean meta_window_can_ping (MetaWindow *window);
 
+MetaStackLayer meta_window_calculate_layer (MetaWindow *window);
+
 void     meta_window_current_workspace_changed (MetaWindow *window);
 
 void meta_window_show_menu (MetaWindow         *window,
diff --git a/src/core/window.c b/src/core/window.c
index 45c9c6ca6..dc6b5c795 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -8582,6 +8582,12 @@ meta_window_is_stackable (MetaWindow *window)
   return META_WINDOW_GET_CLASS (window)->is_stackable (window);
 }
 
+MetaStackLayer
+meta_window_calculate_layer (MetaWindow *window)
+{
+  return META_WINDOW_GET_CLASS (window)->calculate_layer (window);
+}
+
 /**
  * meta_window_get_id:
  * @window: a #MetaWindow
diff --git a/src/wayland/meta-window-wayland.c b/src/wayland/meta-window-wayland.c
index 802b7e223..5d193c4f5 100644
--- a/src/wayland/meta-window-wayland.c
+++ b/src/wayland/meta-window-wayland.c
@@ -634,6 +634,12 @@ meta_window_wayland_are_updates_frozen (MetaWindow *window)
   return !wl_window->has_been_shown;
 }
 
+static MetaStackLayer
+meta_window_wayland_calculate_layer (MetaWindow *window)
+{
+  return meta_window_get_default_layer (window);
+}
+
 static void
 meta_window_wayland_map (MetaWindow *window)
 {
@@ -667,6 +673,7 @@ meta_window_wayland_class_init (MetaWindowWaylandClass *klass)
   window_class->is_stackable = meta_window_wayland_is_stackable;
   window_class->can_ping = meta_window_wayland_can_ping;
   window_class->are_updates_frozen = meta_window_wayland_are_updates_frozen;
+  window_class->calculate_layer = meta_window_wayland_calculate_layer;
   window_class->map = meta_window_wayland_map;
   window_class->unmap = meta_window_wayland_unmap;
 }
diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c
index 5389e10ac..4c7956dd1 100644
--- a/src/x11/window-x11.c
+++ b/src/x11/window-x11.c
@@ -1855,6 +1855,124 @@ meta_window_x11_are_updates_frozen (MetaWindow *window)
   return FALSE;
 }
 
+/* Get layer ignoring any transient or group relationships */
+static MetaStackLayer
+get_standalone_layer (MetaWindow *window)
+{
+  MetaStackLayer layer;
+
+  switch (window->type)
+    {
+    case META_WINDOW_DESKTOP:
+      layer = META_LAYER_DESKTOP;
+      break;
+
+    case META_WINDOW_DOCK:
+      if (window->wm_state_below ||
+          (window->monitor && window->monitor->in_fullscreen))
+        layer = META_LAYER_BOTTOM;
+      else
+        layer = META_LAYER_DOCK;
+      break;
+
+    case META_WINDOW_DROPDOWN_MENU:
+    case META_WINDOW_POPUP_MENU:
+    case META_WINDOW_TOOLTIP:
+    case META_WINDOW_NOTIFICATION:
+    case META_WINDOW_COMBO:
+    case META_WINDOW_OVERRIDE_OTHER:
+      layer = META_LAYER_OVERRIDE_REDIRECT;
+      break;
+
+    default:
+      layer = meta_window_get_default_layer (window);
+      break;
+    }
+
+  return layer;
+}
+
+/* Note that this function can never use window->layer only
+ * get_standalone_layer, or we'd have issues.
+ */
+static MetaStackLayer
+get_maximum_layer_in_group (MetaWindow *window)
+{
+  GSList *members;
+  MetaGroup *group;
+  GSList *tmp;
+  MetaStackLayer max;
+  MetaStackLayer layer;
+
+  max = META_LAYER_DESKTOP;
+
+  group = meta_window_get_group (window);
+
+  if (group != NULL)
+    members = meta_group_list_windows (group);
+  else
+    members = NULL;
+
+  tmp = members;
+  while (tmp != NULL)
+    {
+      MetaWindow *w = tmp->data;
+
+      if (!w->override_redirect)
+        {
+          layer = get_standalone_layer (w);
+          if (layer > max)
+            max = layer;
+        }
+
+      tmp = tmp->next;
+    }
+
+  g_slist_free (members);
+
+  return max;
+}
+
+static MetaStackLayer
+meta_window_x11_calculate_layer (MetaWindow *window)
+{
+  MetaStackLayer layer = get_standalone_layer (window);
+
+  /* We can only do promotion-due-to-group for dialogs and other
+   * transients, or weird stuff happens like the desktop window and
+   * nautilus windows getting in the same layer, or all gnome-terminal
+   * windows getting in fullscreen layer if any terminal is
+   * fullscreen.
+   */
+  if (layer != META_LAYER_DESKTOP &&
+      meta_window_has_transient_type (window) &&
+      window->transient_for == NULL)
+    {
+      /* We only do the group thing if the dialog is NOT transient for
+       * a particular window. Imagine a group with a normal window, a dock,
+       * and a dialog transient for the normal window; you don't want the dialog
+       * above the dock if it wouldn't normally be.
+       */
+
+      MetaStackLayer group_max;
+
+      group_max = get_maximum_layer_in_group (window);
+
+      if (group_max > layer)
+        {
+          meta_topic (META_DEBUG_STACK,
+                      "Promoting window %s from layer %u to %u due to group membership\n",
+                      window->desc, layer, group_max);
+          layer = group_max;
+        }
+    }
+
+  meta_topic (META_DEBUG_STACK, "Window %s on layer %u type = %u has_focus = %d\n",
+              window->desc, layer,
+              window->type, window->has_focus);
+  return layer;
+}
+
 static void
 meta_window_x11_map (MetaWindow *window)
 {
@@ -1903,6 +2021,7 @@ meta_window_x11_class_init (MetaWindowX11Class *klass)
   window_class->is_stackable = meta_window_x11_is_stackable;
   window_class->can_ping = meta_window_x11_can_ping;
   window_class->are_updates_frozen = meta_window_x11_are_updates_frozen;
+  window_class->calculate_layer = meta_window_x11_calculate_layer;
   window_class->map = meta_window_x11_map;
   window_class->unmap = meta_window_x11_unmap;
 }


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