[mutter] monitor-config-manager: Verify that logical monitors are adjecent



commit 2035f2f2e26a013ed4f73e10d40c0f286f426aec
Author: Jonas Ådahl <jadahl gmail com>
Date:   Wed Feb 8 10:32:33 2017 +0800

    monitor-config-manager: Verify that logical monitors are adjecent
    
    Logical monitors in a configuration must be adjecent to each other,
    meaning there will be at least one pixel long side touching some other
    logical monitor.
    
    The exception to this is when there is only one logical monitor, which
    cannot be adjecent to any other.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=777732

 src/backends/meta-monitor-config-manager.c |   35 ++++++++++++++++++++++++++++
 src/core/boxes-private.h                   |    3 ++
 src/core/boxes.c                           |   23 ++++++++++++++++++
 src/tests/unit-tests.c                     |   33 ++++++++++++++++++++++++++
 4 files changed, 94 insertions(+), 0 deletions(-)
---
diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c
index 8533963..d604ba7 100644
--- a/src/backends/meta-monitor-config-manager.c
+++ b/src/backends/meta-monitor-config-manager.c
@@ -893,6 +893,34 @@ meta_verify_logical_monitor_config (MetaLogicalMonitorConfig *logical_monitor_co
   return TRUE;
 }
 
+static gboolean
+has_adjecent_neighbour (MetaMonitorsConfig       *config,
+                        MetaLogicalMonitorConfig *logical_monitor_config)
+{
+  GList *l;
+
+  if (!config->logical_monitor_configs->next)
+    {
+      g_assert (config->logical_monitor_configs->data ==
+                logical_monitor_config);
+      return TRUE;
+    }
+
+  for (l = config->logical_monitor_configs; l; l = l->next)
+    {
+      MetaLogicalMonitorConfig *other_logical_monitor_config = l->data;
+
+      if (logical_monitor_config == other_logical_monitor_config)
+        continue;
+
+      if (meta_rectangle_is_adjecent_to (&logical_monitor_config->layout,
+                                         &other_logical_monitor_config->layout))
+        return TRUE;
+    }
+
+  return FALSE;
+}
+
 gboolean
 meta_verify_monitors_config (MetaMonitorsConfig *config,
                              GError            **error)
@@ -935,6 +963,13 @@ meta_verify_monitors_config (MetaMonitorsConfig *config,
           has_primary = TRUE;
         }
 
+      if (!has_adjecent_neighbour (config, logical_monitor_config))
+        {
+          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                       "Logical monitors not adjecent");
+          return FALSE;
+        }
+
       region = g_list_prepend (region, &logical_monitor_config->layout);
     }
 
diff --git a/src/core/boxes-private.h b/src/core/boxes-private.h
index c2eec0a..9b6811c 100644
--- a/src/core/boxes-private.h
+++ b/src/core/boxes-private.h
@@ -215,4 +215,7 @@ GList* meta_rectangle_find_nonintersected_monitor_edges (
                                            const GList         *monitor_rects,
                                            const GSList        *all_struts);
 
+gboolean meta_rectangle_is_adjecent_to (MetaRectangle *rect,
+                                        MetaRectangle *other);
+
 #endif /* META_BOXES_PRIVATE_H */
diff --git a/src/core/boxes.c b/src/core/boxes.c
index 2a70497..35e9ac3 100644
--- a/src/core/boxes.c
+++ b/src/core/boxes.c
@@ -2013,3 +2013,26 @@ meta_rectangle_find_nonintersected_monitor_edges (
 
   return ret;
 }
+
+gboolean
+meta_rectangle_is_adjecent_to (MetaRectangle *rect,
+                               MetaRectangle *other)
+{
+  int rect_x1 = rect->x;
+  int rect_y1 = rect->y;
+  int rect_x2 = rect->x + rect->width;
+  int rect_y2 = rect->y + rect->height;
+  int other_x1 = other->x;
+  int other_y1 = other->y;
+  int other_x2 = other->x + other->width;
+  int other_y2 = other->y + other->height;
+
+  if ((rect_x1 == other_x2 || rect_x2 == other_x1) &&
+      !(rect_y2 <= other_y1 || rect_y1 >= other_y2))
+    return TRUE;
+  else if ((rect_y1 == other_y2 || rect_y2 == other_y1) &&
+           !(rect_x2 <= other_x1 || rect_x1 >= other_x2))
+    return TRUE;
+  else
+    return FALSE;
+}
diff --git a/src/tests/unit-tests.c b/src/tests/unit-tests.c
index 1138aeb..7e5a1e8 100644
--- a/src/tests/unit-tests.c
+++ b/src/tests/unit-tests.c
@@ -26,6 +26,7 @@
 #include <meta/util.h>
 
 #include "compositor/meta-plugin-manager.h"
+#include "core/boxes-private.h"
 #include "core/main-private.h"
 #include "tests/meta-backend-test.h"
 #include "tests/monitor-unit-tests.h"
@@ -180,6 +181,36 @@ meta_test_util_later_schedule_from_later (void)
   g_assert_cmpint (data.state, ==, META_TEST_LATER_FINISHED);
 }
 
+static void
+meta_test_adjecent_to (void)
+{
+  MetaRectangle base = { .x = 10, .y = 10, .width = 10, .height = 10 };
+  MetaRectangle adjecent[] = {
+    { .x = 20, .y = 10, .width = 10, .height = 10 },
+    { .x = 0, .y = 10, .width = 10, .height = 10 },
+    { .x = 0, .y = 1, .width = 10, .height = 10 },
+    { .x = 20, .y = 19, .width = 10, .height = 10 },
+    { .x = 10, .y = 20, .width = 10, .height = 10 },
+    { .x = 10, .y = 0, .width = 10, .height = 10 },
+  };
+  MetaRectangle not_adjecent[] = {
+    { .x = 0, .y = 0, .width = 10, .height = 10 },
+    { .x = 20, .y = 20, .width = 10, .height = 10 },
+    { .x = 21, .y = 10, .width = 10, .height = 10 },
+    { .x = 10, .y = 21, .width = 10, .height = 10 },
+    { .x = 10, .y = 5, .width = 10, .height = 10 },
+    { .x = 11, .y = 10, .width = 10, .height = 10 },
+    { .x = 19, .y = 10, .width = 10, .height = 10 },
+  };
+  unsigned int i;
+
+  for (i = 0; i < G_N_ELEMENTS (adjecent); i++)
+    g_assert (meta_rectangle_is_adjecent_to (&base, &adjecent[i]));
+
+  for (i = 0; i < G_N_ELEMENTS (not_adjecent); i++)
+    g_assert (!meta_rectangle_is_adjecent_to (&base, &not_adjecent[i]));
+}
+
 static gboolean
 run_tests (gpointer data)
 {
@@ -202,6 +233,8 @@ init_tests (int argc, char **argv)
   g_test_add_func ("/util/meta-later/schedule-from-later",
                    meta_test_util_later_schedule_from_later);
 
+  g_test_add_func ("/core/boxes/adjecent-to", meta_test_adjecent_to);
+
   init_monitor_store_tests ();
   init_monitor_tests ();
 }


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