[metacity] window: add support for _GNOME_WM_STRUT_AREA



commit 922de13cbd51b38110cf3571131aef6ca6fa6a3a
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date:   Thu Jan 30 16:48:28 2020 +0200

    window: add support for _GNOME_WM_STRUT_AREA
    
    In addition to existing properties use also new _GNOME_WM_STRUT_AREA
    property that allows creating struts between monitors.
    
    https://mail.gnome.org/archives/wm-spec-list/2018-December/msg00000.html
    https://gitlab.freedesktop.org/xdg/xdg-specs/merge_requests/22

 src/core/atomnames.h    |  1 +
 src/core/boxes.c        | 21 ++++++++++--
 src/core/testboxes.c    |  6 +++-
 src/core/window-props.c |  6 ++++
 src/core/window.c       | 88 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/core/workspace.c    |  6 ++--
 src/include/boxes.h     | 18 +++++-----
 7 files changed, 133 insertions(+), 13 deletions(-)
---
diff --git a/src/core/atomnames.h b/src/core/atomnames.h
index 8e2b4593..aacd2285 100644
--- a/src/core/atomnames.h
+++ b/src/core/atomnames.h
@@ -64,6 +64,7 @@ item(_GTK_WORKAREAS)
 item(_GNOME_PANEL_ACTION)
 item(_GNOME_PANEL_ACTION_MAIN_MENU)
 item(_GNOME_PANEL_ACTION_RUN_DIALOG)
+item(_GNOME_WM_STRUT_AREA)
 item(_METACITY_TIMESTAMP_PING)
 item(_METACITY_FOCUS_SET)
 item(_METACITY_SENTINEL)
diff --git a/src/core/boxes.c b/src/core/boxes.c
index 1c2905e8..d77b6baf 100644
--- a/src/core/boxes.c
+++ b/src/core/boxes.c
@@ -518,7 +518,8 @@ compare_rect_areas (gconstpointer a, gconstpointer b)
 GList*
 meta_rectangle_get_minimal_spanning_set_for_region (
   const MetaRectangle *basic_rect,
-  const GSList  *all_struts)
+  const GSList        *all_struts,
+  gboolean             skip_middle_struts)
 {
   /* NOTE FOR OPTIMIZERS: This function *might* be somewhat slow,
    * especially due to the call to merge_spanning_rects_in_region() (which
@@ -580,7 +581,23 @@ meta_rectangle_get_minimal_spanning_set_for_region (
   for (strut_iter = all_struts; strut_iter; strut_iter = strut_iter->next)
     {
       GList *rect_iter;
-      MetaRectangle *strut_rect = &((MetaStrut*)strut_iter->data)->rect;
+      MetaStrut *strut = (MetaStrut *) strut_iter->data;
+      MetaRectangle *strut_rect = &strut->rect;
+
+      if (skip_middle_struts && strut->edge == META_EDGE_MONITOR)
+        {
+          if ((strut->side == META_SIDE_LEFT &&
+               strut_rect->x != basic_rect->x) ||
+              (strut->side == META_SIDE_RIGHT &&
+               strut_rect->x + strut_rect->width != basic_rect->width) ||
+              (strut->side == META_SIDE_TOP &&
+               strut_rect->y != basic_rect->y) ||
+              (strut->side == META_SIDE_BOTTOM &&
+               strut_rect->y + strut_rect->height != basic_rect->height))
+            {
+              continue;
+            }
+        }
 
       tmp_list = ret;
       ret = NULL;
diff --git a/src/core/testboxes.c b/src/core/testboxes.c
index f1ae214e..f4cd3a50 100644
--- a/src/core/testboxes.c
+++ b/src/core/testboxes.c
@@ -63,6 +63,7 @@ new_meta_strut (int x, int y, int width, int height, int side)
   temporary = g_new (MetaStrut, 1);
   temporary->rect = meta_rect(x, y, width, height);
   temporary->side = side;
+  temporary->edge = META_EDGE_SCREEN;
 
   return temporary;
 }
@@ -297,7 +298,10 @@ get_screen_region (int which)
   ret = NULL;
 
   struts = get_strut_list (which);
-  ret = meta_rectangle_get_minimal_spanning_set_for_region (&basic_rect, struts);
+  ret = meta_rectangle_get_minimal_spanning_set_for_region (&basic_rect,
+                                                            struts,
+                                                            FALSE);
+
   free_strut_list (struts);
 
   return ret;
diff --git a/src/core/window-props.c b/src/core/window-props.c
index ef877f24..466c06f0 100644
--- a/src/core/window-props.c
+++ b/src/core/window-props.c
@@ -1967,6 +1967,12 @@ meta_display_init_window_prop_hooks (MetaDisplay *display)
       reload_struts,
       NONE
     },
+    {
+      display->atom__GNOME_WM_STRUT_AREA,
+      META_PROP_VALUE_INVALID,
+      reload_struts,
+      NONE
+    },
     {
       display->atom__NET_WM_WINDOW_OPACITY,
       META_PROP_VALUE_CARDINAL,
diff --git a/src/core/window.c b/src/core/window.c
index 3539c316..c2d294ac 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -6385,6 +6385,91 @@ meta_window_update_struts (MetaWindow *window)
   new_struts = NULL;
 
   if (meta_prop_get_cardinal_list (window->display,
+                                   window->xwindow,
+                                   window->display->atom__GNOME_WM_STRUT_AREA,
+                                   &struts, &nitems))
+    {
+      if (nitems != 4)
+        {
+          meta_verbose ("_GNOME_WM_STRUT_AREA on %s has %d values instead of 4\n",
+                        window->desc, nitems);
+        }
+      else
+        {
+          MetaStrut *temp;
+          MetaSide side;
+          gboolean valid;
+          int i;
+
+          temp = g_new (MetaStrut, 1);
+
+          temp->rect.x = struts[0];
+          temp->rect.y = struts[1];
+          temp->rect.width = struts[2];
+          temp->rect.height = struts[3];
+
+          side = META_SIDE_LEFT;
+          valid = FALSE;
+
+          for (i = 0; i < window->screen->n_monitor_infos; i++)
+            {
+              MetaRectangle monitor;
+
+              monitor = window->screen->monitor_infos[i].rect;
+              if (!meta_rectangle_contains_rect (&monitor, &temp->rect))
+                continue;
+
+              if (temp->rect.height > temp->rect.width)
+                {
+                  if (temp->rect.x == monitor.x)
+                    {
+                      side = META_SIDE_LEFT;
+                      valid = TRUE;
+                    }
+                  else if (temp->rect.x + temp->rect.width == monitor.x + monitor.width)
+                    {
+                      side = META_SIDE_RIGHT;
+                      valid = TRUE;
+                    }
+                }
+              else
+                {
+                  if (temp->rect.y == monitor.y)
+                    {
+                      side = META_SIDE_TOP;
+                      valid = TRUE;
+                    }
+                  else if (temp->rect.y + temp->rect.height == monitor.y + monitor.height)
+                    {
+                      side = META_SIDE_BOTTOM;
+                      valid = TRUE;
+                    }
+                }
+            }
+
+          if (valid)
+            {
+              temp->side = side;
+              temp->edge = META_EDGE_MONITOR;
+
+              new_struts = g_slist_prepend (new_struts, temp);
+            }
+          else
+            {
+              g_free (temp);
+            }
+        }
+
+      meta_XFree (struts);
+    }
+  else
+    {
+      meta_verbose ("No _GNOME_WM_STRUT_AREA property for %s\n",
+                    window->desc);
+    }
+
+  if (!new_struts &&
+      meta_prop_get_cardinal_list (window->display,
                                    window->xwindow,
                                    window->display->atom__NET_WM_STRUT_PARTIAL,
                                    &struts, &nitems))
@@ -6410,6 +6495,7 @@ meta_window_update_struts (MetaWindow *window)
 
               temp = g_new (MetaStrut, 1);
               temp->side = 1 << i; /* See MetaSide def.  Matches nicely, eh? */
+              temp->edge = META_EDGE_SCREEN;
               temp->rect = window->screen->rect;
               switch (temp->side)
                 {
@@ -6479,6 +6565,7 @@ meta_window_update_struts (MetaWindow *window)
 
               temp = g_new (MetaStrut, 1);
               temp->side = 1 << i;
+              temp->edge = META_EDGE_SCREEN;
               temp->rect = window->screen->rect;
               switch (temp->side)
                 {
@@ -6524,6 +6611,7 @@ meta_window_update_struts (MetaWindow *window)
       MetaStrut *new_strut = (MetaStrut*) new_iter->data;
 
       if (old_strut->side != new_strut->side ||
+          old_strut->edge != new_strut->edge ||
           !meta_rectangle_equal (&old_strut->rect, &new_strut->rect))
         break;
 
diff --git a/src/core/workspace.c b/src/core/workspace.c
index da714063..19e3a9a8 100644
--- a/src/core/workspace.c
+++ b/src/core/workspace.c
@@ -646,12 +646,14 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
       workspace->monitor_region[i] =
         meta_rectangle_get_minimal_spanning_set_for_region (
           &workspace->screen->monitor_infos[i].rect,
-          workspace->all_struts);
+          workspace->all_struts,
+          FALSE);
     }
   workspace->screen_region =
     meta_rectangle_get_minimal_spanning_set_for_region (
       &workspace->screen->rect,
-      workspace->all_struts);
+      workspace->all_struts,
+      TRUE);
 
   /* STEP 3: Get the work areas (region-to-maximize-to) for the screen and
    *         monitors.
diff --git a/src/include/boxes.h b/src/include/boxes.h
index 4b881753..387a1756 100644
--- a/src/include/boxes.h
+++ b/src/include/boxes.h
@@ -25,6 +25,13 @@
 #include <glib.h>
 #include "common.h"
 
+typedef enum
+{
+  META_EDGE_WINDOW,
+  META_EDGE_MONITOR,
+  META_EDGE_SCREEN
+} MetaEdgeType;
+
 typedef struct _MetaRectangle MetaRectangle;
 struct _MetaRectangle
 {
@@ -39,6 +46,7 @@ struct _MetaStrut
 {
   MetaRectangle rect;
   MetaSide side;
+  MetaEdgeType edge;
 };
 
 #define BOX_LEFT(box)    ((box).x)                /* Leftmost pixel of rect */
@@ -53,13 +61,6 @@ typedef enum
   FIXED_DIRECTION_Y    = 1 << 1,
 } FixedDirections;
 
-typedef enum
-{
-  META_EDGE_WINDOW,
-  META_EDGE_MONITOR,
-  META_EDGE_SCREEN
-} MetaEdgeType;
-
 typedef struct _MetaEdge MetaEdge;
 struct _MetaEdge
 {
@@ -156,7 +157,8 @@ void meta_rectangle_resize_with_gravity (const MetaRectangle *old_rect,
  */
 GList*   meta_rectangle_get_minimal_spanning_set_for_region (
                                          const MetaRectangle *basic_rect,
-                                         const GSList        *all_struts);
+                                         const GSList        *all_struts,
+                                         gboolean             skip_middle_struts);
 
 /* Expand all rectangles in region by the given amount on each side */
 GList*   meta_rectangle_expand_region   (GList               *region,


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