Blob Blame History Raw
From 13603e46a07f4ece309f5b2ab3196ad306b6008c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Fri, 6 Jun 2014 07:58:20 +0200
Subject: [PATCH 1/3] boxes: Ignore struts that don't attach to the side they
 claim

Like the _NET_WM_STRUT/_NET_WM_STRUT_PARTIAL client properties,
_NET_WORKAREA is defined in terms of screen geometry rather than
taking individual monitors into account. However we do want to
allow system chrome to be attached to a monitor edge rather than
a screen edges under some circumstances. As not all clients can
be assumed to deal gracefully with the resulting workarea, use
those "struts" only internally for constraining windows, but
ignore them when exporting _NET_WORKAREA.

https://bugzilla.gnome.org/show_bug.cgi?id=730527
---
 src/core/boxes.c | 29 ++++++++++++++++++++++++++---
 1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/src/core/boxes.c b/src/core/boxes.c
index 3c4f444..1057528 100644
--- a/src/core/boxes.c
+++ b/src/core/boxes.c
@@ -548,6 +548,26 @@ compare_rect_areas (gconstpointer a, gconstpointer b)
   return b_area - a_area; /* positive ret value denotes b > a, ... */
 }
 
+/* ... and another helper for get_minimal_spanning_set_for_region()... */
+static gboolean
+check_strut_align (MetaStrut *strut, const MetaRectangle *rect)
+{
+  /* Check whether @strut actually aligns to the side of @rect it claims */
+  switch (strut->side)
+    {
+    case META_SIDE_TOP:
+      return BOX_TOP (strut->rect) <= BOX_TOP (*rect);
+    case META_SIDE_BOTTOM:
+      return BOX_BOTTOM (strut->rect) >= BOX_BOTTOM (*rect);
+    case META_SIDE_LEFT:
+      return BOX_LEFT (strut->rect) <= BOX_LEFT (*rect);
+    case META_SIDE_RIGHT:
+      return BOX_RIGHT (strut->rect) >= BOX_RIGHT (*rect);
+    default:
+      return FALSE;
+    }
+}
+
 /**
  * meta_rectangle_get_minimal_spanning_set_for_region:
  * @basic_rect: Input rectangle
@@ -631,8 +651,9 @@ 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;
+      GList *rect_iter;
+      MetaStrut *strut = (MetaStrut*)strut_iter->data;
+      MetaRectangle *strut_rect = &strut->rect;
 
       tmp_list = ret;
       ret = NULL;
@@ -640,7 +661,9 @@ meta_rectangle_get_minimal_spanning_set_for_region (
       while (rect_iter)
         {
           MetaRectangle *rect = (MetaRectangle*) rect_iter->data;
-          if (!meta_rectangle_overlap (rect, strut_rect))
+
+          if (!meta_rectangle_overlap (strut_rect, rect) ||
+              !check_strut_align (strut, basic_rect))
             ret = g_list_prepend (ret, rect);
           else
             {
-- 
2.1.0


From 147decb30f1539b18eb8aeb1e37914d9cccac016 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Thu, 12 Jun 2014 01:06:25 +0200
Subject: [PATCH 2/3] testboxes: Update test cases

Who cares? We do now ...

https://bugzilla.gnome.org/show_bug.cgi?id=730527
---
 src/core/testboxes.c | 42 ++++++++++++++++++------------------------
 1 file changed, 18 insertions(+), 24 deletions(-)

diff --git a/src/core/testboxes.c b/src/core/testboxes.c
index 128efac..44f70b1 100644
--- a/src/core/testboxes.c
+++ b/src/core/testboxes.c
@@ -240,7 +240,7 @@ static GSList*
 get_strut_list (int which)
 {
   GSList *ans;
-  MetaDirection wc = 0; /* wc == who cares? ;-) */
+  MetaSide wc = 0; /* wc == who cares? ;-) */
 
   ans = NULL;
 
@@ -250,32 +250,32 @@ get_strut_list (int which)
     case 0:
       break;
     case 1:
-      ans = g_slist_prepend (ans, new_meta_strut (   0,    0, 1600,   20, wc));
-      ans = g_slist_prepend (ans, new_meta_strut ( 400, 1160, 1600,   40, wc));
+      ans = g_slist_prepend (ans, new_meta_strut (   0,    0, 1600,   20, META_SIDE_TOP));
+      ans = g_slist_prepend (ans, new_meta_strut ( 400, 1160, 1600,   40, META_SIDE_BOTTOM));
       break;
     case 2:
-      ans = g_slist_prepend (ans, new_meta_strut (   0,    0, 1600,   20, wc));
-      ans = g_slist_prepend (ans, new_meta_strut ( 800, 1100,  400,  100, wc));
-      ans = g_slist_prepend (ans, new_meta_strut ( 300, 1150,  150,   50, wc));
+      ans = g_slist_prepend (ans, new_meta_strut (   0,    0, 1600,   20, META_SIDE_TOP));
+      ans = g_slist_prepend (ans, new_meta_strut ( 800, 1100,  400,  100, META_SIDE_BOTTOM));
+      ans = g_slist_prepend (ans, new_meta_strut ( 300, 1150,  150,   50, META_SIDE_BOTTOM));
       break;
     case 3:
-      ans = g_slist_prepend (ans, new_meta_strut (   0,    0, 1600,   20, wc));
-      ans = g_slist_prepend (ans, new_meta_strut ( 800, 1100,  400,  100, wc));
-      ans = g_slist_prepend (ans, new_meta_strut ( 300, 1150,   80,   50, wc));
+      ans = g_slist_prepend (ans, new_meta_strut (   0,    0, 1600,   20, META_SIDE_TOP));
+      ans = g_slist_prepend (ans, new_meta_strut ( 800, 1100,  400,  100, META_SIDE_LEFT));
+      ans = g_slist_prepend (ans, new_meta_strut ( 300, 1150,   80,   50, META_SIDE_BOTTOM));
       ans = g_slist_prepend (ans, new_meta_strut ( 700,  525,  200,  150, wc));
       break;
     case 4:
-      ans = g_slist_prepend (ans, new_meta_strut (   0,    0,  800, 1200, wc));
-      ans = g_slist_prepend (ans, new_meta_strut ( 800,    0, 1600,   20, wc));
+      ans = g_slist_prepend (ans, new_meta_strut (   0,    0,  800, 1200, META_SIDE_LEFT));
+      ans = g_slist_prepend (ans, new_meta_strut ( 800,    0, 1600,   20, META_SIDE_TOP));
       break;
     case 5:
-      ans = g_slist_prepend (ans, new_meta_strut ( 800,    0, 1600,   20, wc));
-      ans = g_slist_prepend (ans, new_meta_strut (   0,    0,  800, 1200, wc));
-      ans = g_slist_prepend (ans, new_meta_strut ( 800,   10,  800, 1200, wc));
+      ans = g_slist_prepend (ans, new_meta_strut ( 800,    0, 1600,   20, META_SIDE_TOP));
+      ans = g_slist_prepend (ans, new_meta_strut (   0,    0,  800, 1200, META_SIDE_LEFT));
+      ans = g_slist_prepend (ans, new_meta_strut ( 800,   10,  800, 1200, META_SIDE_RIGHT));
       break;
     case 6:
-      ans = g_slist_prepend (ans, new_meta_strut (   0,    0, 1600,   40, wc));
-      ans = g_slist_prepend (ans, new_meta_strut (   0,    0, 1600,   20, wc));
+      ans = g_slist_prepend (ans, new_meta_strut (   0,    0, 1600,   40, META_SIDE_TOP));
+      ans = g_slist_prepend (ans, new_meta_strut (   0,    0, 1600,   20, META_SIDE_TOP));
       break;
     }
 
@@ -625,15 +625,9 @@ test_regions_okay ()
   /*************************************************************/  
   region = get_screen_region (3);
   tmp = NULL;
-  tmp = g_list_prepend (tmp, new_meta_rect ( 380,  675,  420,  525)); /* 220500 */
   tmp = g_list_prepend (tmp, new_meta_rect (   0,   20,  300, 1180)); /* 354000 */
-  tmp = g_list_prepend (tmp, new_meta_rect ( 380,   20,  320, 1180)); /* 377600 */
-  tmp = g_list_prepend (tmp, new_meta_rect (   0,  675,  800,  475)); /* 380000 */
-  tmp = g_list_prepend (tmp, new_meta_rect (1200,   20,  400, 1180)); /* 472000 */
-  tmp = g_list_prepend (tmp, new_meta_rect (   0,  675, 1600,  425)); /* 680000 */
-  tmp = g_list_prepend (tmp, new_meta_rect ( 900,   20,  700, 1080)); /* 756000 */
-  tmp = g_list_prepend (tmp, new_meta_rect (   0,   20,  700, 1130)); /* 791000 */
-  tmp = g_list_prepend (tmp, new_meta_rect (   0,   20, 1600,  505)); /* 808000 */
+  tmp = g_list_prepend (tmp, new_meta_rect ( 380,   20,  1220, 1180)); /* 377600 */
+  tmp = g_list_prepend (tmp, new_meta_rect (   0,   20,  1600, 1130)); /* 791000 */
 #if 0
   printf ("Got to here...\n");
   char region_list[(RECT_LENGTH+2) * g_list_length (region)];
-- 
2.1.0


From 0e1668ea9d4fb070480351021af44932ab04bcc2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Wed, 11 Jun 2014 02:16:13 +0200
Subject: [PATCH 3/3] workspace: Extend builtin struts to screen edge when
 possible

Struts are defined in terms of screen edges, so expand the rectangles
we get via set_builtin_struts() accordingly. However we do want to
allow chrome on edges between monitors, in which case the expansion
would render an entire monitor unusable - don't expand the rectangles
in that case, which means we will only use them for constraining
windows but ignore them for the client-visible _NET_WORKAREA property.

https://bugzilla.gnome.org/show_bug.cgi?id=730527
---
 src/core/workspace.c | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/src/core/workspace.c b/src/core/workspace.c
index e5da6d2..9683baf 100644
--- a/src/core/workspace.c
+++ b/src/core/workspace.c
@@ -1042,6 +1042,45 @@ void
 meta_workspace_set_builtin_struts (MetaWorkspace *workspace,
                                    GSList        *struts)
 {
+  MetaScreen *screen = workspace->screen;
+  GSList *l;
+
+  for (l = struts; l; l = l->next)
+    {
+      MetaStrut *strut = l->data;
+      int idx = meta_screen_get_monitor_index_for_rect (screen, &strut->rect);
+
+      switch (strut->side)
+        {
+        case META_SIDE_TOP:
+          if (meta_screen_get_monitor_neighbor (screen, idx, META_SCREEN_UP))
+            continue;
+
+          strut->rect.height += strut->rect.y;
+          strut->rect.y = 0;
+          break;
+        case META_SIDE_BOTTOM:
+          if (meta_screen_get_monitor_neighbor (screen, idx, META_SCREEN_DOWN))
+            continue;
+
+          strut->rect.height = screen->rect.height - strut->rect.y;
+          break;
+        case META_SIDE_LEFT:
+          if (meta_screen_get_monitor_neighbor (screen, idx, META_SCREEN_LEFT))
+            continue;
+
+          strut->rect.width += strut->rect.x;
+          strut->rect.x = 0;
+          break;
+        case META_SIDE_RIGHT:
+          if (meta_screen_get_monitor_neighbor (screen, idx, META_SCREEN_RIGHT))
+            continue;
+
+          strut->rect.width = screen->rect.width - strut->rect.x;
+          break;
+        }
+    }
+
   /* Reordering doesn't actually matter, so we don't catch all
    * no-impact changes, but this is just a (possibly unnecessary
    * anyways) optimization */
-- 
2.1.0