[mutter] monitor-config-store: Add way to define config store loading policy



commit c611b64c53d16fe252d9f276e5c43b18868740c7
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Mon Jan 17 11:45:53 2022 +0100

    monitor-config-store: Add way to define config store loading policy
    
    This adds a way to define a way, at the system level, to define a policy
    of how monitor configuration files are loaded.
    
    The intended use case is to e.g. either prefer system level monitor
    configurations before user levels, or only allow system level
    configurations.
    
    Examples:
    
    Prefer system over user level configurations:
    
        <monitors version="2">
          <policy>
            <stores>
              <store>system</store>
              <store>user</store>
            </stores>
          </policy>
          <configuration>
            ...
          </configuration>
        </monitors>
    
    Only allow system level configurations:
    
        <monitors version="2">
          <policy>
            <stores>
              <store>system</store>
            </stores>
          </policy>
          <configuration>
            ...
          </configuration>
        </monitors>
    
    Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2030>

 src/backends/meta-backend-types.h               |   2 +
 src/backends/meta-monitor-config-manager.h      |   4 +-
 src/backends/meta-monitor-config-store.c        | 421 +++++++++++++++++++-----
 src/backends/meta-monitor-config-store.h        |  21 +-
 src/tests/meta-test-utils.c                     |   8 +-
 src/tests/meta-test-utils.h                     |   6 +-
 src/tests/monitor-config-migration-unit-tests.c |   1 +
 src/tests/monitor-configs/policy.xml            |  27 ++
 src/tests/monitor-store-unit-tests.c            |  33 ++
 src/tests/monitor-test-utils.c                  |  16 +-
 src/tests/monitor-test-utils.h                  |   2 +
 src/tests/monitor-unit-tests.c                  |   3 +
 src/tests/native-pointer-constraints.c          |   3 +-
 13 files changed, 452 insertions(+), 95 deletions(-)
---
diff --git a/src/backends/meta-backend-types.h b/src/backends/meta-backend-types.h
index c5e46d87a1..9437536944 100644
--- a/src/backends/meta-backend-types.h
+++ b/src/backends/meta-backend-types.h
@@ -29,6 +29,8 @@ typedef struct _MetaMonitorConfigManager MetaMonitorConfigManager;
 typedef struct _MetaMonitorConfigStore MetaMonitorConfigStore;
 typedef struct _MetaMonitorsConfig MetaMonitorsConfig;
 
+typedef enum _MetaMonitorsConfigFlag MetaMonitorsConfigFlag;
+
 typedef struct _MetaMonitor MetaMonitor;
 typedef struct _MetaMonitorNormal MetaMonitorNormal;
 typedef struct _MetaMonitorTiled MetaMonitorTiled;
diff --git a/src/backends/meta-monitor-config-manager.h b/src/backends/meta-monitor-config-manager.h
index 025bafb8f3..a789e2f088 100644
--- a/src/backends/meta-monitor-config-manager.h
+++ b/src/backends/meta-monitor-config-manager.h
@@ -51,12 +51,12 @@ typedef struct _MetaMonitorsConfigKey
   GList *monitor_specs;
 } MetaMonitorsConfigKey;
 
-typedef enum _MetaMonitorsConfigFlag
+enum _MetaMonitorsConfigFlag
 {
   META_MONITORS_CONFIG_FLAG_NONE = 0,
   META_MONITORS_CONFIG_FLAG_MIGRATED = (1 << 0),
   META_MONITORS_CONFIG_FLAG_SYSTEM_CONFIG = (1 << 1),
-} MetaMonitorsConfigFlag;
+};
 
 struct _MetaMonitorsConfig
 {
diff --git a/src/backends/meta-monitor-config-store.c b/src/backends/meta-monitor-config-store.c
index d2572fa06a..93a494c79b 100644
--- a/src/backends/meta-monitor-config-store.c
+++ b/src/backends/meta-monitor-config-store.c
@@ -120,6 +120,9 @@ struct _MetaMonitorConfigStore
   GFile *user_file;
   GFile *custom_read_file;
   GFile *custom_write_file;
+
+  gboolean has_stores_policy;
+  GList *stores_policy;
 };
 
 #define META_MONITOR_CONFIG_STORE_ERROR (meta_monitor_config_store_error_quark ())
@@ -162,12 +165,18 @@ typedef enum
   STATE_MONITOR_MODE_FLAG,
   STATE_MONITOR_UNDERSCANNING,
   STATE_DISABLED,
+  STATE_POLICY,
+  STATE_STORES,
+  STATE_STORE,
 } ParserState;
 
 typedef struct
 {
   ParserState state;
   MetaMonitorConfigStore *config_store;
+  GFile *file;
+
+  GHashTable *pending_configs;
 
   ParserState monitor_spec_parent_state;
 
@@ -180,6 +189,10 @@ typedef struct
   MetaMonitorConfig *current_monitor_config;
   MetaLogicalMonitorConfig *current_logical_monitor_config;
   GList *current_disabled_monitor_specs;
+  gboolean seen_policy;
+  gboolean seen_stores;
+  MetaConfigStore pending_store;
+  GList *stores;
 
   ParserState unknown_state_root;
   int unknown_level;
@@ -268,16 +281,31 @@ handle_start_element (GMarkupParseContext  *context,
 
     case STATE_MONITORS:
       {
-        if (!g_str_equal (element_name, "configuration"))
+        if (g_str_equal (element_name, "configuration"))
+          {
+            parser->state = STATE_CONFIGURATION;
+            parser->current_was_migrated = FALSE;
+          }
+        else if (g_str_equal (element_name, "policy"))
+          {
+            if (parser->seen_policy)
+              {
+                g_set_error (error,
+                             G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
+                             "Multiple policy definitions");
+                return;
+              }
+
+            parser->seen_policy = TRUE;
+            parser->state = STATE_POLICY;
+          }
+        else
           {
             enter_unknown_element (parser, element_name,
                                    "monitors", STATE_MONITORS);
             return;
           }
 
-        parser->state = STATE_CONFIGURATION;
-        parser->current_was_migrated = FALSE;
-
         return;
       }
 
@@ -523,6 +551,59 @@ handle_start_element (GMarkupParseContext  *context,
 
         return;
       }
+
+    case STATE_POLICY:
+      {
+        if (!(parser->extra_config_flags &
+              META_MONITORS_CONFIG_FLAG_SYSTEM_CONFIG))
+          {
+            g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
+                         "Policy can only be defined in system level configurations");
+            return;
+          }
+
+        if (g_str_equal (element_name, "stores"))
+          {
+            if (parser->seen_stores)
+              {
+                g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
+                             "Multiple stores elements under policy");
+                return;
+              }
+
+            parser->seen_stores = TRUE;
+            parser->state = STATE_STORES;
+          }
+        else
+          {
+            enter_unknown_element (parser, element_name,
+                                   "policy", STATE_POLICY);
+          }
+
+        return;
+      }
+
+    case STATE_STORES:
+      {
+        if (g_str_equal (element_name, "store"))
+          {
+            parser->state = STATE_STORE;
+          }
+        else
+          {
+            enter_unknown_element (parser, element_name,
+                                   "stores", STATE_STORES);
+          }
+
+        return;
+      }
+
+    case STATE_STORE:
+      {
+        g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
+                     "Invalid store sub element '%s'", element_name);
+        return;
+      }
     }
 }
 
@@ -819,13 +900,65 @@ handle_end_element (GMarkupParseContext  *context,
             return;
           }
 
-        g_hash_table_replace (parser->config_store->configs,
+        g_hash_table_replace (parser->pending_configs,
                               config->key, config);
 
         parser->state = STATE_MONITORS;
         return;
       }
 
+    case STATE_STORE:
+        g_assert (g_str_equal (element_name, "store"));
+
+        if (parser->pending_store == -1)
+          {
+            g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
+                         "Got an empty store");
+            return;
+          }
+
+        if (g_list_find (parser->stores,
+                         GINT_TO_POINTER (parser->pending_store)))
+          {
+            g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
+                         "Multiple identical stores in policy");
+            return;
+          }
+
+        parser->stores =
+          g_list_append (parser->stores,
+                         GINT_TO_POINTER (parser->pending_store));
+        parser->pending_store = -1;
+
+        parser->state = STATE_STORES;
+        return;
+
+    case STATE_STORES:
+        g_assert (g_str_equal (element_name, "stores"));
+
+        if (parser->config_store->has_stores_policy)
+          {
+            g_warning ("Ignoring stores policy from '%s', "
+                       "it has already been configured",
+                       g_file_peek_path (parser->file));
+            g_clear_pointer (&parser->stores, g_list_free);
+          }
+        else
+          {
+            parser->config_store->stores_policy =
+              g_steal_pointer (&parser->stores);
+            parser->config_store->has_stores_policy = TRUE;
+          }
+
+        parser->state = STATE_POLICY;
+        return;
+
+    case STATE_POLICY:
+        g_assert (g_str_equal (element_name, "policy"));
+
+        parser->state = STATE_MONITORS;
+        return;
+
     case STATE_UNKNOWN:
       {
         parser->unknown_level--;
@@ -970,6 +1103,8 @@ handle_text (GMarkupParseContext *context,
     case STATE_MONITOR_MODE:
     case STATE_TRANSFORM:
     case STATE_DISABLED:
+    case STATE_POLICY:
+    case STATE_STORES:
       {
         if (!is_all_whitespace (text, text_len))
           g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
@@ -1120,6 +1255,36 @@ handle_text (GMarkupParseContext *context,
                    error);
         return;
       }
+
+    case STATE_STORE:
+      {
+        MetaConfigStore store;
+
+        if (parser->pending_store != -1)
+          {
+            g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
+                         "Multiple store strings");
+            return;
+          }
+
+        if (text_equals (text, text_len, "system"))
+          {
+            store = META_CONFIG_STORE_SYSTEM;
+          }
+        else if (text_equals (text, text_len, "user"))
+          {
+            store = META_CONFIG_STORE_USER;
+          }
+        else
+          {
+            g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
+                         "Invalid store %.*s", (int) text_len, text);
+            return;
+          }
+
+        parser->pending_store = store;
+        return;
+      }
     }
 }
 
@@ -1133,6 +1298,7 @@ static gboolean
 read_config_file (MetaMonitorConfigStore  *config_store,
                   GFile                   *file,
                   MetaMonitorsConfigFlag   extra_config_flags,
+                  GHashTable             **out_configs,
                   GError                 **error)
 {
   char *buffer;
@@ -1145,9 +1311,15 @@ read_config_file (MetaMonitorConfigStore  *config_store,
 
   parser = (ConfigParser) {
     .state = STATE_INITIAL,
+    .file = file,
     .config_store = config_store,
+    .pending_configs = g_hash_table_new_full (meta_monitors_config_key_hash,
+                                              meta_monitors_config_key_equal,
+                                              NULL,
+                                              g_object_unref),
     .extra_config_flags = extra_config_flags,
     .unknown_state_root = -1,
+    .pending_store = -1,
   };
 
   parse_context = g_markup_parse_context_new (&config_parser,
@@ -1165,9 +1337,13 @@ read_config_file (MetaMonitorConfigStore  *config_store,
                       meta_monitor_config_free);
       g_clear_pointer (&parser.current_logical_monitor_config,
                        meta_logical_monitor_config_free);
+      g_list_free (parser.stores);
+      g_hash_table_unref (parser.pending_configs);
       return FALSE;
     }
 
+  *out_configs = g_steal_pointer (&parser.pending_configs);
+
   g_markup_parse_context_free (parse_context);
   g_free (buffer);
 
@@ -1526,23 +1702,34 @@ meta_monitor_config_store_remove (MetaMonitorConfigStore *config_store,
 }
 
 gboolean
-meta_monitor_config_store_set_custom (MetaMonitorConfigStore *config_store,
-                                      const char             *read_path,
-                                      const char             *write_path,
-                                      GError                **error)
+meta_monitor_config_store_set_custom (MetaMonitorConfigStore  *config_store,
+                                      const char              *read_path,
+                                      const char              *write_path,
+                                      MetaMonitorsConfigFlag   config_flags,
+                                      GError                 **error)
 {
+  GHashTable *new_configs = NULL;
+
   g_clear_object (&config_store->custom_read_file);
   g_clear_object (&config_store->custom_write_file);
-  g_hash_table_remove_all (config_store->configs);
 
   config_store->custom_read_file = g_file_new_for_path (read_path);
   if (write_path)
     config_store->custom_write_file = g_file_new_for_path (write_path);
 
-  return read_config_file (config_store,
-                           config_store->custom_read_file,
-                           META_MONITORS_CONFIG_FLAG_NONE,
-                           error);
+  g_clear_pointer (&config_store->stores_policy, g_list_free);
+  config_store->has_stores_policy = FALSE;
+
+  if (!read_config_file (config_store,
+                         config_store->custom_read_file,
+                         config_flags,
+                         &new_configs,
+                         error))
+    return FALSE;
+
+  g_clear_pointer (&config_store->configs, g_hash_table_unref);
+  config_store->configs = g_steal_pointer (&new_configs);
+  return TRUE;
 }
 
 int
@@ -1551,6 +1738,12 @@ meta_monitor_config_store_get_config_count (MetaMonitorConfigStore *config_store
   return (int) g_hash_table_size (config_store->configs);
 }
 
+GList *
+meta_monitor_config_store_get_stores_policy (MetaMonitorConfigStore *config_store)
+{
+  return config_store->stores_policy;
+}
+
 MetaMonitorManager *
 meta_monitor_config_store_get_monitor_manager (MetaMonitorConfigStore *config_store)
 {
@@ -1569,75 +1762,8 @@ static void
 meta_monitor_config_store_constructed (GObject *object)
 {
   MetaMonitorConfigStore *config_store = META_MONITOR_CONFIG_STORE (object);
-  const char * const *system_dirs;
-  char *user_file_path;
-  GError *error = NULL;
-
-  for (system_dirs = g_get_system_config_dirs ();
-       system_dirs && *system_dirs;
-       system_dirs++)
-    {
-      g_autofree char *system_file_path = NULL;
-
-      system_file_path = g_build_filename (*system_dirs, "monitors.xml", NULL);
-      if (g_file_test (system_file_path, G_FILE_TEST_EXISTS))
-        {
-          g_autoptr (GFile) system_file = NULL;
-
-          system_file = g_file_new_for_path (system_file_path);
-          if (!read_config_file (config_store,
-                                 system_file,
-                                 META_MONITORS_CONFIG_FLAG_SYSTEM_CONFIG,
-                                 &error))
-            {
-              if (g_error_matches (error,
-                                   META_MONITOR_CONFIG_STORE_ERROR,
-                                   META_MONITOR_CONFIG_STORE_ERROR_NEEDS_MIGRATION))
-                g_warning ("System monitor configuration file (%s) is "
-                           "incompatible; ask your administrator to migrate "
-                           "the system monitor configuration.",
-                           system_file_path);
-              else
-                g_warning ("Failed to read monitors config file '%s': %s",
-                           system_file_path, error->message);
-              g_clear_error (&error);
-            }
-        }
-    }
 
-  user_file_path = g_build_filename (g_get_user_config_dir (),
-                                     "monitors.xml",
-                                     NULL);
-  config_store->user_file = g_file_new_for_path (user_file_path);
-
-  if (g_file_test (user_file_path, G_FILE_TEST_EXISTS))
-    {
-      if (!read_config_file (config_store,
-                             config_store->user_file,
-                             META_MONITORS_CONFIG_FLAG_NONE,
-                             &error))
-        {
-          if (error->domain == META_MONITOR_CONFIG_STORE_ERROR &&
-              error->code == META_MONITOR_CONFIG_STORE_ERROR_NEEDS_MIGRATION)
-            {
-              g_clear_error (&error);
-              if (!meta_migrate_old_user_monitors_config (config_store, &error))
-                {
-                  g_warning ("Failed to migrate old monitors config file: %s",
-                             error->message);
-                  g_error_free (error);
-                }
-            }
-          else
-            {
-              g_warning ("Failed to read monitors config file '%s': %s",
-                         user_file_path, error->message);
-              g_error_free (error);
-            }
-        }
-    }
-
-  g_free (user_file_path);
+  meta_monitor_config_store_reset (config_store);
 
   G_OBJECT_CLASS (meta_monitor_config_store_parent_class)->constructed (object);
 }
@@ -1660,6 +1786,7 @@ meta_monitor_config_store_dispose (GObject *object)
   g_clear_object (&config_store->user_file);
   g_clear_object (&config_store->custom_read_file);
   g_clear_object (&config_store->custom_write_file);
+  g_clear_pointer (&config_store->stores_policy, g_list_free);
 
   G_OBJECT_CLASS (meta_monitor_config_store_parent_class)->dispose (object);
 }
@@ -1730,3 +1857,133 @@ meta_monitor_config_store_class_init (MetaMonitorConfigStoreClass *klass)
 
   g_object_class_install_properties (object_class, PROP_LAST, obj_props);
 }
+
+static void
+replace_configs (MetaMonitorConfigStore *config_store,
+                 GHashTable             *configs)
+{
+  GHashTableIter iter;
+  MetaMonitorsConfigKey *key;
+  MetaMonitorsConfig *config;
+
+  g_hash_table_iter_init (&iter, configs);
+  while (g_hash_table_iter_next (&iter,
+                                 (gpointer *) &key,
+                                 (gpointer *) &config))
+    {
+      g_hash_table_iter_steal (&iter);
+      g_hash_table_replace (config_store->configs, key, config);
+    }
+}
+
+void
+meta_monitor_config_store_reset (MetaMonitorConfigStore *config_store)
+{
+  g_autoptr (GHashTable) system_configs = NULL;
+  g_autoptr (GHashTable) user_configs = NULL;
+  const char * const *system_dirs;
+  char *user_file_path;
+  GError *error = NULL;
+
+  g_clear_object (&config_store->user_file);
+  g_clear_object (&config_store->custom_read_file);
+  g_clear_object (&config_store->custom_write_file);
+  g_hash_table_remove_all (config_store->configs);
+
+  for (system_dirs = g_get_system_config_dirs ();
+       system_dirs && *system_dirs;
+       system_dirs++)
+    {
+      g_autofree char *system_file_path = NULL;
+
+      system_file_path = g_build_filename (*system_dirs, "monitors.xml", NULL);
+      if (g_file_test (system_file_path, G_FILE_TEST_EXISTS))
+        {
+          g_autoptr (GFile) system_file = NULL;
+
+          system_file = g_file_new_for_path (system_file_path);
+          if (!read_config_file (config_store,
+                                 system_file,
+                                 META_MONITORS_CONFIG_FLAG_SYSTEM_CONFIG,
+                                 &system_configs,
+                                 &error))
+            {
+              if (g_error_matches (error,
+                                   META_MONITOR_CONFIG_STORE_ERROR,
+                                   META_MONITOR_CONFIG_STORE_ERROR_NEEDS_MIGRATION))
+                g_warning ("System monitor configuration file (%s) is "
+                           "incompatible; ask your administrator to migrate "
+                           "the system monitor configuration.",
+                           system_file_path);
+              else
+                g_warning ("Failed to read monitors config file '%s': %s",
+                           system_file_path, error->message);
+              g_clear_error (&error);
+            }
+        }
+    }
+
+  user_file_path = g_build_filename (g_get_user_config_dir (),
+                                     "monitors.xml",
+                                     NULL);
+  config_store->user_file = g_file_new_for_path (user_file_path);
+
+  if (g_file_test (user_file_path, G_FILE_TEST_EXISTS))
+    {
+      if (!read_config_file (config_store,
+                             config_store->user_file,
+                             META_MONITORS_CONFIG_FLAG_NONE,
+                             &user_configs,
+                             &error))
+        {
+          if (error->domain == META_MONITOR_CONFIG_STORE_ERROR &&
+              error->code == META_MONITOR_CONFIG_STORE_ERROR_NEEDS_MIGRATION)
+            {
+              g_clear_error (&error);
+              if (!meta_migrate_old_user_monitors_config (config_store, &error))
+                {
+                  g_warning ("Failed to migrate old monitors config file: %s",
+                             error->message);
+                  g_error_free (error);
+                }
+            }
+          else
+            {
+              g_warning ("Failed to read monitors config file '%s': %s",
+                         user_file_path, error->message);
+              g_error_free (error);
+            }
+        }
+    }
+
+  if (config_store->has_stores_policy)
+    {
+      GList *l;
+
+      for (l = g_list_last (config_store->stores_policy); l; l = l->prev)
+        {
+          MetaConfigStore store = GPOINTER_TO_INT (l->data);
+
+          switch (store)
+            {
+            case META_CONFIG_STORE_SYSTEM:
+              if (system_configs)
+                replace_configs (config_store, system_configs);
+              break;
+            case META_CONFIG_STORE_USER:
+              if (user_configs)
+                replace_configs (config_store, user_configs);
+            }
+        }
+    }
+  else
+    {
+      if (system_configs)
+        replace_configs (config_store, system_configs);
+      if (user_configs)
+        replace_configs (config_store, user_configs);
+    }
+
+
+  g_free (user_file_path);
+}
diff --git a/src/backends/meta-monitor-config-store.h b/src/backends/meta-monitor-config-store.h
index 92c24ecaa8..cb6759dca0 100644
--- a/src/backends/meta-monitor-config-store.h
+++ b/src/backends/meta-monitor-config-store.h
@@ -26,6 +26,12 @@
 
 #include "backends/meta-monitor-config-manager.h"
 
+typedef enum _MetaConfigStore
+{
+  META_CONFIG_STORE_SYSTEM,
+  META_CONFIG_STORE_USER,
+} MetaConfigStore;
+
 #define META_TYPE_MONITOR_CONFIG_STORE (meta_monitor_config_store_get_type ())
 G_DECLARE_FINAL_TYPE (MetaMonitorConfigStore, meta_monitor_config_store,
                       META, MONITOR_CONFIG_STORE, GObject)
@@ -46,10 +52,14 @@ void meta_monitor_config_store_remove (MetaMonitorConfigStore *config_store,
                                        MetaMonitorsConfig     *config);
 
 META_EXPORT_TEST
-gboolean meta_monitor_config_store_set_custom (MetaMonitorConfigStore *config_store,
-                                               const char             *read_path,
-                                               const char             *write_path,
-                                               GError                **error);
+gboolean meta_monitor_config_store_set_custom (MetaMonitorConfigStore  *config_store,
+                                               const char              *read_path,
+                                               const char              *write_path,
+                                               MetaMonitorsConfigFlag   flags,
+                                               GError                 **error);
+
+META_EXPORT_TEST
+GList * meta_monitor_config_store_get_stores_policy (MetaMonitorConfigStore *config_store);
 
 META_EXPORT_TEST
 int meta_monitor_config_store_get_config_count (MetaMonitorConfigStore *config_store);
@@ -57,4 +67,7 @@ int meta_monitor_config_store_get_config_count (MetaMonitorConfigStore *config_s
 META_EXPORT_TEST
 MetaMonitorManager * meta_monitor_config_store_get_monitor_manager (MetaMonitorConfigStore *config_store);
 
+META_EXPORT_TEST
+void meta_monitor_config_store_reset (MetaMonitorConfigStore *config_store);
+
 #endif /* META_MONITOR_CONFIG_STORE_H */
diff --git a/src/tests/meta-test-utils.c b/src/tests/meta-test-utils.c
index 61600f107e..281dbc25b5 100644
--- a/src/tests/meta-test-utils.c
+++ b/src/tests/meta-test-utils.c
@@ -594,8 +594,9 @@ meta_test_get_plugin_name (void)
 }
 
 void
-meta_set_custom_monitor_config (MetaBackend *backend,
-                                const char  *filename)
+meta_set_custom_monitor_config (MetaBackend            *backend,
+                                const char             *filename,
+                                MetaMonitorsConfigFlag  configs_flags)
 {
   MetaMonitorManager *monitor_manager =
     meta_backend_get_monitor_manager (backend);
@@ -611,8 +612,9 @@ meta_set_custom_monitor_config (MetaBackend *backend,
   path = g_test_get_filename (G_TEST_DIST, "tests", "monitor-configs",
                               filename, NULL);
   if (!meta_monitor_config_store_set_custom (config_store, path, NULL,
+                                             configs_flags,
                                              &error))
-    g_error ("Failed to set custom config: %s", error->message);
+    g_warning ("Failed to set custom config: %s", error->message);
 }
 
 static void
diff --git a/src/tests/meta-test-utils.h b/src/tests/meta-test-utils.h
index 685d4febe0..2273b78119 100644
--- a/src/tests/meta-test-utils.h
+++ b/src/tests/meta-test-utils.h
@@ -24,6 +24,7 @@
 #include <X11/Xlib.h>
 #include <X11/extensions/sync.h>
 
+#include "backends/meta-backend-types.h"
 #include "meta/window.h"
 
 #define META_TEST_CLIENT_ERROR meta_test_client_error_quark ()
@@ -109,8 +110,9 @@ META_EXPORT
 const char * meta_test_get_plugin_name (void);
 
 META_EXPORT
-void meta_set_custom_monitor_config (MetaBackend *backend,
-                                     const char  *filename);
+void meta_set_custom_monitor_config (MetaBackend            *backend,
+                                     const char             *filename,
+                                     MetaMonitorsConfigFlag  configs_flags);
 
 META_EXPORT
 void meta_wait_for_paint (MetaContext *context);
diff --git a/src/tests/monitor-config-migration-unit-tests.c b/src/tests/monitor-config-migration-unit-tests.c
index bb2ac62ccd..df22ee3a8d 100644
--- a/src/tests/monitor-config-migration-unit-tests.c
+++ b/src/tests/monitor-config-migration-unit-tests.c
@@ -55,6 +55,7 @@ test_migration (const char *old_config,
                                     NULL);
   if (!meta_monitor_config_store_set_custom (config_store, "/dev/null",
                                              migrated_path,
+                                             META_MONITORS_CONFIG_FLAG_NONE,
                                              &error))
     g_error ("Failed to set custom config store: %s", error->message);
 
diff --git a/src/tests/monitor-configs/policy.xml b/src/tests/monitor-configs/policy.xml
new file mode 100644
index 0000000000..760046513e
--- /dev/null
+++ b/src/tests/monitor-configs/policy.xml
@@ -0,0 +1,27 @@
+<monitors version="2">
+  <policy>
+    <stores>
+      <store>system</store>
+    </stores>
+  </policy>
+  <configuration>
+    <logicalmonitor>
+      <x>0</x>
+      <y>0</y>
+      <primary>yes</primary>
+      <monitor>
+       <monitorspec>
+         <connector>DP-1</connector>
+         <vendor>MetaProduct&apos;s Inc.</vendor>
+         <product>MetaMonitor</product>
+         <serial>0x123456</serial>
+       </monitorspec>
+       <mode>
+         <width>1920</width>
+         <height>1080</height>
+         <rate>60</rate>
+       </mode>
+      </monitor>
+    </logicalmonitor>
+  </configuration>
+</monitors>
diff --git a/src/tests/monitor-store-unit-tests.c b/src/tests/monitor-store-unit-tests.c
index 64618174f4..f7efa894b4 100644
--- a/src/tests/monitor-store-unit-tests.c
+++ b/src/tests/monitor-store-unit-tests.c
@@ -890,6 +890,35 @@ meta_test_monitor_store_unknown_elements (void)
   check_monitor_store_configurations (&expect);
 }
 
+static void
+meta_test_monitor_store_policy_not_allowed (void)
+{
+  g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
+                         "*Policy can only be defined in system level "
+                         "configurations*");
+  set_custom_monitor_config ("policy.xml");
+  g_test_assert_expected_messages ();
+}
+
+static void
+meta_test_monitor_store_policy (void)
+{
+  MetaBackend *backend = meta_get_backend ();
+  MetaMonitorManager *monitor_manager =
+    meta_backend_get_monitor_manager (backend);
+  MetaMonitorConfigManager *config_manager = monitor_manager->config_manager;
+  MetaMonitorConfigStore *config_store =
+    meta_monitor_config_manager_get_store (config_manager);
+  GList *stores_policy;
+
+  set_custom_monitor_system_config ("policy.xml");
+  stores_policy = meta_monitor_config_store_get_stores_policy (config_store);
+  g_assert_cmpuint (g_list_length (stores_policy), ==, 1);
+  g_assert_cmpint (GPOINTER_TO_INT (stores_policy->data),
+                   ==,
+                   META_CONFIG_STORE_SYSTEM);
+}
+
 void
 init_monitor_store_tests (void)
 {
@@ -917,4 +946,8 @@ init_monitor_store_tests (void)
                    meta_test_monitor_store_interlaced);
   g_test_add_func ("/backends/monitor-store/unknown-elements",
                    meta_test_monitor_store_unknown_elements);
+  g_test_add_func ("/backends/monitor-store/policy-not-allowed",
+                   meta_test_monitor_store_policy_not_allowed);
+  g_test_add_func ("/backends/monitor-store/policy",
+                   meta_test_monitor_store_policy);
 }
diff --git a/src/tests/monitor-test-utils.c b/src/tests/monitor-test-utils.c
index 7f4f092f3e..74e550b49a 100644
--- a/src/tests/monitor-test-utils.c
+++ b/src/tests/monitor-test-utils.c
@@ -38,10 +38,24 @@ test_get_gpu (void)
   return META_GPU (meta_backend_get_gpus (meta_get_backend ())->data);
 }
 
+static void
+set_custom_monitor_config_common (const char             *filename,
+                                  MetaMonitorsConfigFlag  configs_flags)
+{
+  meta_set_custom_monitor_config (meta_get_backend (), filename, configs_flags);
+}
+
 void
 set_custom_monitor_config (const char *filename)
 {
-  meta_set_custom_monitor_config (meta_get_backend (), filename);
+  set_custom_monitor_config_common (filename, META_MONITORS_CONFIG_FLAG_NONE);
+}
+
+void
+set_custom_monitor_system_config (const char *filename)
+{
+  set_custom_monitor_config_common (filename,
+                                    META_MONITORS_CONFIG_FLAG_SYSTEM_CONFIG);
 }
 
 char *
diff --git a/src/tests/monitor-test-utils.h b/src/tests/monitor-test-utils.h
index 0cada8e4a1..a24f2ec585 100644
--- a/src/tests/monitor-test-utils.h
+++ b/src/tests/monitor-test-utils.h
@@ -201,6 +201,8 @@ MetaGpu * test_get_gpu (void);
 
 void set_custom_monitor_config (const char *filename);
 
+void set_custom_monitor_system_config (const char *filename);
+
 char * read_file (const char *file_path);
 
 void check_monitor_configuration (MonitorTestCaseExpect *expect);
diff --git a/src/tests/monitor-unit-tests.c b/src/tests/monitor-unit-tests.c
index 15054fbc31..4679fa0d63 100644
--- a/src/tests/monitor-unit-tests.c
+++ b/src/tests/monitor-unit-tests.c
@@ -7690,6 +7690,7 @@ meta_test_monitor_migrated_rotated (void)
   if (!meta_monitor_config_store_set_custom (config_store,
                                              "/dev/null",
                                              migrated_path,
+                                             META_MONITORS_CONFIG_FLAG_NONE,
                                              &error))
     g_error ("Failed to set custom config store files: %s", error->message);
 
@@ -7832,6 +7833,7 @@ meta_test_monitor_migrated_wiggle_discard (void)
   if (!meta_monitor_config_store_set_custom (config_store,
                                              "/dev/null",
                                              migrated_path,
+                                             META_MONITORS_CONFIG_FLAG_NONE,
                                              &error))
     g_error ("Failed to set custom config store files: %s", error->message);
 
@@ -8103,6 +8105,7 @@ meta_test_monitor_migrated_wiggle (void)
   if (!meta_monitor_config_store_set_custom (config_store,
                                              "/dev/null",
                                              migrated_path,
+                                             META_MONITORS_CONFIG_FLAG_NONE,
                                              &error))
     g_error ("Failed to set custom config store files: %s", error->message);
 
diff --git a/src/tests/native-pointer-constraints.c b/src/tests/native-pointer-constraints.c
index edee417e7f..027c51a046 100644
--- a/src/tests/native-pointer-constraints.c
+++ b/src/tests/native-pointer-constraints.c
@@ -66,7 +66,8 @@ meta_test_warp_on_hotplug (void)
   virtual_pointer = clutter_seat_create_virtual_device (seat,
                                                         CLUTTER_POINTER_DEVICE);
 
-  meta_set_custom_monitor_config (backend, "pointer-constraint.xml");
+  meta_set_custom_monitor_config (backend, "pointer-constraint.xml",
+                                  META_MONITORS_CONFIG_FLAG_NONE);
 
   monitor_info1 = meta_virtual_monitor_info_new (100, 100, 60.0,
                                                  "MetaTestVendor",


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