2357 lines
79 KiB
Diff
2357 lines
79 KiB
Diff
|
From 9cf4d7b6d8a279a0d2a047f52d9fa5b0586b1ab9 Mon Sep 17 00:00:00 2001
|
||
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
||
|
Date: Fri, 14 Jan 2022 22:11:17 +0100
|
||
|
Subject: [PATCH 1/9] test/utils: Add helper to set custom monitors config
|
||
|
|
||
|
Make the existing implementation a wrapper to avoid changing monitor
|
||
|
config tests.
|
||
|
|
||
|
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2237>
|
||
|
|
||
|
Cherry-picked from 57d1d82ead6392a104a9e9d6c7f1f4f14ad54e48
|
||
|
---
|
||
|
src/tests/monitor-test-utils.c | 18 +-----------------
|
||
|
src/tests/test-utils.c | 23 +++++++++++++++++++++++
|
||
|
src/tests/test-utils.h | 3 +++
|
||
|
3 files changed, 27 insertions(+), 17 deletions(-)
|
||
|
|
||
|
diff --git a/src/tests/monitor-test-utils.c b/src/tests/monitor-test-utils.c
|
||
|
index 54881569102e..d2dc3b2658c6 100644
|
||
|
--- a/src/tests/monitor-test-utils.c
|
||
|
+++ b/src/tests/monitor-test-utils.c
|
||
|
@@ -28,23 +28,7 @@
|
||
|
void
|
||
|
set_custom_monitor_config (const char *filename)
|
||
|
{
|
||
|
- MetaBackend *backend = meta_get_backend ();
|
||
|
- MetaMonitorManager *monitor_manager =
|
||
|
- meta_backend_get_monitor_manager (backend);
|
||
|
- MetaMonitorConfigManager *config_manager = monitor_manager->config_manager;
|
||
|
- MetaMonitorConfigStore *config_store;
|
||
|
- GError *error = NULL;
|
||
|
- const char *path;
|
||
|
-
|
||
|
- g_assert_nonnull (config_manager);
|
||
|
-
|
||
|
- config_store = meta_monitor_config_manager_get_store (config_manager);
|
||
|
-
|
||
|
- path = g_test_get_filename (G_TEST_DIST, "tests", "monitor-configs",
|
||
|
- filename, NULL);
|
||
|
- if (!meta_monitor_config_store_set_custom (config_store, path, NULL,
|
||
|
- &error))
|
||
|
- g_error ("Failed to set custom config: %s", error->message);
|
||
|
+ meta_set_custom_monitor_config (meta_get_backend (), filename);
|
||
|
}
|
||
|
|
||
|
char *
|
||
|
diff --git a/src/tests/test-utils.c b/src/tests/test-utils.c
|
||
|
index 980b20acdcb0..dd6230dc15ec 100644
|
||
|
--- a/src/tests/test-utils.c
|
||
|
+++ b/src/tests/test-utils.c
|
||
|
@@ -24,6 +24,7 @@
|
||
|
#include <gio/gio.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
+#include "backends/meta-monitor-config-store.h"
|
||
|
#include "core/display-private.h"
|
||
|
#include "core/window-private.h"
|
||
|
#include "wayland/meta-wayland.h"
|
||
|
@@ -483,3 +484,25 @@ test_get_plugin_name (void)
|
||
|
else
|
||
|
return "libdefault";
|
||
|
}
|
||
|
+
|
||
|
+void
|
||
|
+meta_set_custom_monitor_config (MetaBackend *backend,
|
||
|
+ const char *filename)
|
||
|
+{
|
||
|
+ MetaMonitorManager *monitor_manager =
|
||
|
+ meta_backend_get_monitor_manager (backend);
|
||
|
+ MetaMonitorConfigManager *config_manager = monitor_manager->config_manager;
|
||
|
+ MetaMonitorConfigStore *config_store;
|
||
|
+ GError *error = NULL;
|
||
|
+ const char *path;
|
||
|
+
|
||
|
+ g_assert_nonnull (config_manager);
|
||
|
+
|
||
|
+ config_store = meta_monitor_config_manager_get_store (config_manager);
|
||
|
+
|
||
|
+ path = g_test_get_filename (G_TEST_DIST, "tests", "monitor-configs",
|
||
|
+ filename, NULL);
|
||
|
+ if (!meta_monitor_config_store_set_custom (config_store, path, NULL,
|
||
|
+ &error))
|
||
|
+ g_error ("Failed to set custom config: %s", error->message);
|
||
|
+}
|
||
|
diff --git a/src/tests/test-utils.h b/src/tests/test-utils.h
|
||
|
index e11f25353a5b..5092f766fdf6 100644
|
||
|
--- a/src/tests/test-utils.h
|
||
|
+++ b/src/tests/test-utils.h
|
||
|
@@ -81,4 +81,7 @@ void test_client_destroy (TestClient *client);
|
||
|
|
||
|
const char * test_get_plugin_name (void);
|
||
|
|
||
|
+void meta_set_custom_monitor_config (MetaBackend *backend,
|
||
|
+ const char *filename);
|
||
|
+
|
||
|
#endif /* TEST_UTILS_H */
|
||
|
--
|
||
|
2.33.1
|
||
|
|
||
|
|
||
|
From 8133ff828e46e19d4afa277c1e013a846b443b9f Mon Sep 17 00:00:00 2001
|
||
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
||
|
Date: Fri, 14 Jan 2022 22:12:36 +0100
|
||
|
Subject: [PATCH 2/9] tests/utils: Add meta_wait_for_paint() helper
|
||
|
|
||
|
This function queues a full stage redraw, then waits for every view to
|
||
|
receive the "presented" signal before returning.
|
||
|
|
||
|
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2237>
|
||
|
(cherry picked from commit d84f7971e476a1e2d727310d9a33ac4080137f58)
|
||
|
---
|
||
|
src/tests/test-utils.c | 27 +++++++++++++++++++++++++++
|
||
|
src/tests/test-utils.h | 2 ++
|
||
|
2 files changed, 29 insertions(+)
|
||
|
|
||
|
diff --git a/src/tests/test-utils.c b/src/tests/test-utils.c
|
||
|
index dd6230dc15ec..f1a688478f67 100644
|
||
|
--- a/src/tests/test-utils.c
|
||
|
+++ b/src/tests/test-utils.c
|
||
|
@@ -506,3 +506,30 @@ meta_set_custom_monitor_config (MetaBackend *backend,
|
||
|
&error))
|
||
|
g_error ("Failed to set custom config: %s", error->message);
|
||
|
}
|
||
|
+
|
||
|
+static void
|
||
|
+on_view_presented (ClutterStage *stage,
|
||
|
+ ClutterStageView *view,
|
||
|
+ ClutterFrameInfo *frame_info,
|
||
|
+ GList **presented_views)
|
||
|
+{
|
||
|
+ *presented_views = g_list_remove (*presented_views, view);
|
||
|
+}
|
||
|
+
|
||
|
+void
|
||
|
+meta_wait_for_paint (MetaBackend *backend)
|
||
|
+{
|
||
|
+ ClutterActor *stage = meta_backend_get_stage (backend);
|
||
|
+ MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
||
|
+ GList *views;
|
||
|
+ gulong handler_id;
|
||
|
+
|
||
|
+ clutter_actor_queue_redraw (stage);
|
||
|
+
|
||
|
+ views = g_list_copy (meta_renderer_get_views (renderer));
|
||
|
+ handler_id = g_signal_connect (stage, "presented",
|
||
|
+ G_CALLBACK (on_view_presented), &views);
|
||
|
+ while (views)
|
||
|
+ g_main_context_iteration (NULL, TRUE);
|
||
|
+ g_signal_handler_disconnect (stage, handler_id);
|
||
|
+}
|
||
|
diff --git a/src/tests/test-utils.h b/src/tests/test-utils.h
|
||
|
index 5092f766fdf6..6d6cdb924d01 100644
|
||
|
--- a/src/tests/test-utils.h
|
||
|
+++ b/src/tests/test-utils.h
|
||
|
@@ -84,4 +84,6 @@ const char * test_get_plugin_name (void);
|
||
|
void meta_set_custom_monitor_config (MetaBackend *backend,
|
||
|
const char *filename);
|
||
|
|
||
|
+void meta_wait_for_paint (MetaBackend *backend);
|
||
|
+
|
||
|
#endif /* TEST_UTILS_H */
|
||
|
--
|
||
|
2.33.1
|
||
|
|
||
|
|
||
|
From 61e384f2b652e5ac774a0cb46daaba3e89ddefdc Mon Sep 17 00:00:00 2001
|
||
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
||
|
Date: Thu, 30 Sep 2021 08:59:03 +0200
|
||
|
Subject: [PATCH 3/9] monitor-config-store: Make parsing a bit more forgiving
|
||
|
|
||
|
Allow unknown XML elements inside <monitors>. This makes extending in
|
||
|
the future easier.
|
||
|
|
||
|
(cherry picked from commit 3cd666c657fa716f06dee69df59356b53b6c5d72)
|
||
|
---
|
||
|
src/backends/meta-monitor-config-store.c | 54 +++++++++++++++---
|
||
|
.../monitor-configs/unknown-elements.xml | 31 ++++++++++
|
||
|
src/tests/monitor-store-unit-tests.c | 56 +++++++++++++++++++
|
||
|
3 files changed, 133 insertions(+), 8 deletions(-)
|
||
|
create mode 100644 src/tests/monitor-configs/unknown-elements.xml
|
||
|
|
||
|
diff --git a/src/backends/meta-monitor-config-store.c b/src/backends/meta-monitor-config-store.c
|
||
|
index 770bef734e6f..9a3daf561a69 100644
|
||
|
--- a/src/backends/meta-monitor-config-store.c
|
||
|
+++ b/src/backends/meta-monitor-config-store.c
|
||
|
@@ -136,6 +136,7 @@ G_DEFINE_QUARK (meta-monitor-config-store-error-quark,
|
||
|
typedef enum
|
||
|
{
|
||
|
STATE_INITIAL,
|
||
|
+ STATE_UNKNOWN,
|
||
|
STATE_MONITORS,
|
||
|
STATE_CONFIGURATION,
|
||
|
STATE_MIGRATED,
|
||
|
@@ -180,12 +181,28 @@ typedef struct
|
||
|
MetaLogicalMonitorConfig *current_logical_monitor_config;
|
||
|
GList *current_disabled_monitor_specs;
|
||
|
|
||
|
+ ParserState unknown_state_root;
|
||
|
+ int unknown_level;
|
||
|
+
|
||
|
MetaMonitorsConfigFlag extra_config_flags;
|
||
|
} ConfigParser;
|
||
|
|
||
|
G_DEFINE_TYPE (MetaMonitorConfigStore, meta_monitor_config_store,
|
||
|
G_TYPE_OBJECT)
|
||
|
|
||
|
+static void
|
||
|
+enter_unknown_element (ConfigParser *parser,
|
||
|
+ const char *element_name,
|
||
|
+ const char *root_element_name,
|
||
|
+ ParserState root_state)
|
||
|
+{
|
||
|
+ parser->state = STATE_UNKNOWN;
|
||
|
+ parser->unknown_level = 1;
|
||
|
+ parser->unknown_state_root = root_state;
|
||
|
+ g_warning ("Unknown element <%s> under <%s>, ignoring",
|
||
|
+ element_name, root_element_name);
|
||
|
+}
|
||
|
+
|
||
|
static void
|
||
|
handle_start_element (GMarkupParseContext *context,
|
||
|
const char *element_name,
|
||
|
@@ -242,8 +259,8 @@ handle_start_element (GMarkupParseContext *context,
|
||
|
{
|
||
|
if (!g_str_equal (element_name, "configuration"))
|
||
|
{
|
||
|
- g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
|
||
|
- "Invalid toplevel element '%s'", element_name);
|
||
|
+ enter_unknown_element (parser, element_name,
|
||
|
+ "monitors", STATE_MONITORS);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
@@ -253,6 +270,13 @@ handle_start_element (GMarkupParseContext *context,
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
+ case STATE_UNKNOWN:
|
||
|
+ {
|
||
|
+ parser->unknown_level++;
|
||
|
+
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
case STATE_CONFIGURATION:
|
||
|
{
|
||
|
if (g_str_equal (element_name, "logicalmonitor"))
|
||
|
@@ -274,9 +298,8 @@ handle_start_element (GMarkupParseContext *context,
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
- g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
|
||
|
- "Invalid configuration element '%s'", element_name);
|
||
|
- return;
|
||
|
+ enter_unknown_element (parser, element_name,
|
||
|
+ "configuration", STATE_CONFIGURATION);
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
@@ -323,9 +346,8 @@ handle_start_element (GMarkupParseContext *context,
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
- g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
|
||
|
- "Invalid monitor logicalmonitor element '%s'", element_name);
|
||
|
- return;
|
||
|
+ enter_unknown_element (parser, element_name,
|
||
|
+ "logicalmonitor", STATE_LOGICAL_MONITOR);
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
@@ -793,6 +815,18 @@ handle_end_element (GMarkupParseContext *context,
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
+ case STATE_UNKNOWN:
|
||
|
+ {
|
||
|
+ parser->unknown_level--;
|
||
|
+ if (parser->unknown_level == 0)
|
||
|
+ {
|
||
|
+ g_assert (parser->unknown_state_root >= 0);
|
||
|
+ parser->state = parser->unknown_state_root;
|
||
|
+ parser->unknown_state_root = -1;
|
||
|
+ }
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
case STATE_MONITORS:
|
||
|
{
|
||
|
g_assert (g_str_equal (element_name, "monitors"));
|
||
|
@@ -912,6 +946,9 @@ handle_text (GMarkupParseContext *context,
|
||
|
|
||
|
switch (parser->state)
|
||
|
{
|
||
|
+ case STATE_UNKNOWN:
|
||
|
+ return;
|
||
|
+
|
||
|
case STATE_INITIAL:
|
||
|
case STATE_MONITORS:
|
||
|
case STATE_CONFIGURATION:
|
||
|
@@ -1099,6 +1136,7 @@ read_config_file (MetaMonitorConfigStore *config_store,
|
||
|
.state = STATE_INITIAL,
|
||
|
.config_store = config_store,
|
||
|
.extra_config_flags = extra_config_flags,
|
||
|
+ .unknown_state_root = -1,
|
||
|
};
|
||
|
|
||
|
parse_context = g_markup_parse_context_new (&config_parser,
|
||
|
diff --git a/src/tests/monitor-configs/unknown-elements.xml b/src/tests/monitor-configs/unknown-elements.xml
|
||
|
new file mode 100644
|
||
|
index 000000000000..f81be95dd9df
|
||
|
--- /dev/null
|
||
|
+++ b/src/tests/monitor-configs/unknown-elements.xml
|
||
|
@@ -0,0 +1,31 @@
|
||
|
+<monitors version="2">
|
||
|
+ <unknownundermonitors>
|
||
|
+ <anotherlevel>text</anotherlevel>
|
||
|
+ </unknownundermonitors>
|
||
|
+ <configuration>
|
||
|
+ <unknownunderconfiguration>
|
||
|
+ <anotherlevel>text</anotherlevel>
|
||
|
+ </unknownunderconfiguration>
|
||
|
+ <logicalmonitor>
|
||
|
+ <unknownunderlogicalmonitor>
|
||
|
+ <anotherlevel>text</anotherlevel>
|
||
|
+ </unknownunderlogicalmonitor>
|
||
|
+ <x>0</x>
|
||
|
+ <y>0</y>
|
||
|
+ <primary>yes</primary>
|
||
|
+ <monitor>
|
||
|
+ <monitorspec>
|
||
|
+ <connector>DP-1</connector>
|
||
|
+ <vendor>MetaProduct's Inc.</vendor>
|
||
|
+ <product>MetaMonitor</product>
|
||
|
+ <serial>0x123456</serial>
|
||
|
+ </monitorspec>
|
||
|
+ <mode>
|
||
|
+ <width>1920</width>
|
||
|
+ <height>1080</height>
|
||
|
+ <rate>60.000495910644531</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 4a73d89db4c6..4ff0e396dda7 100644
|
||
|
--- a/src/tests/monitor-store-unit-tests.c
|
||
|
+++ b/src/tests/monitor-store-unit-tests.c
|
||
|
@@ -836,6 +836,60 @@ meta_test_monitor_store_interlaced (void)
|
||
|
check_monitor_configurations (&expect);
|
||
|
}
|
||
|
|
||
|
+static void
|
||
|
+meta_test_monitor_store_unknown_elements (void)
|
||
|
+{
|
||
|
+ MonitorStoreTestExpect expect = {
|
||
|
+ .configurations = {
|
||
|
+ {
|
||
|
+ .logical_monitors = {
|
||
|
+ {
|
||
|
+ .layout = {
|
||
|
+ .x = 0,
|
||
|
+ .y = 0,
|
||
|
+ .width = 1920,
|
||
|
+ .height = 1080
|
||
|
+ },
|
||
|
+ .scale = 1,
|
||
|
+ .is_primary = TRUE,
|
||
|
+ .is_presentation = FALSE,
|
||
|
+ .monitors = {
|
||
|
+ {
|
||
|
+ .connector = "DP-1",
|
||
|
+ .vendor = "MetaProduct's Inc.",
|
||
|
+ .product = "MetaMonitor",
|
||
|
+ .serial = "0x123456",
|
||
|
+ .mode = {
|
||
|
+ .width = 1920,
|
||
|
+ .height = 1080,
|
||
|
+ .refresh_rate = 60.000495910644531
|
||
|
+ }
|
||
|
+ }
|
||
|
+ },
|
||
|
+ .n_monitors = 1,
|
||
|
+ }
|
||
|
+ },
|
||
|
+ .n_logical_monitors = 1
|
||
|
+ }
|
||
|
+ },
|
||
|
+ .n_configurations = 1
|
||
|
+ };
|
||
|
+
|
||
|
+ g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
|
||
|
+ "Unknown element <unknownundermonitors> "
|
||
|
+ "under <monitors>, ignoring");
|
||
|
+ g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
|
||
|
+ "Unknown element <unknownunderconfiguration> "
|
||
|
+ "under <configuration>, ignoring");
|
||
|
+ g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
|
||
|
+ "Unknown element <unknownunderlogicalmonitor> "
|
||
|
+ "under <logicalmonitor>, ignoring");
|
||
|
+ set_custom_monitor_config ("unknown-elements.xml");
|
||
|
+ g_test_assert_expected_messages ();
|
||
|
+
|
||
|
+ check_monitor_configurations (&expect);
|
||
|
+}
|
||
|
+
|
||
|
void
|
||
|
init_monitor_store_tests (void)
|
||
|
{
|
||
|
@@ -861,4 +915,6 @@ init_monitor_store_tests (void)
|
||
|
meta_test_monitor_store_second_rotated);
|
||
|
g_test_add_func ("/backends/monitor-store/interlaced",
|
||
|
meta_test_monitor_store_interlaced);
|
||
|
+ g_test_add_func ("/backends/monitor-store/unknown-elements",
|
||
|
+ meta_test_monitor_store_unknown_elements);
|
||
|
}
|
||
|
--
|
||
|
2.33.1
|
||
|
|
||
|
|
||
|
From cb3f23d6bdc01f16a0c9236873057faede0a4b32 Mon Sep 17 00:00:00 2001
|
||
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
||
|
Date: Fri, 24 Sep 2021 16:29:47 +0200
|
||
|
Subject: [PATCH 4/9] monitor-config-store: Fix incorrect string comparison
|
||
|
with empty string
|
||
|
|
||
|
strncmp() always return 0 if the passed length is 0. What this means is
|
||
|
that whatever the first string check happens to be, if the parsed XML
|
||
|
cdata was empty (e.g. if we got <element></element>), the first
|
||
|
condition would evaluate to true, which is rather unexpected.
|
||
|
|
||
|
Fix this by making sure the string length is correct first. Also move it
|
||
|
into a helper so we don't need to repeat the same strlen() check every
|
||
|
time.
|
||
|
|
||
|
(cherry picked from commit f798e49502313dd3e7dd67143513a7a6a91b49f8)
|
||
|
---
|
||
|
src/backends/meta-monitor-config-store.c | 25 +++++++++++++++++-------
|
||
|
1 file changed, 18 insertions(+), 7 deletions(-)
|
||
|
|
||
|
diff --git a/src/backends/meta-monitor-config-store.c b/src/backends/meta-monitor-config-store.c
|
||
|
index 9a3daf561a69..f6b5256aa798 100644
|
||
|
--- a/src/backends/meta-monitor-config-store.c
|
||
|
+++ b/src/backends/meta-monitor-config-store.c
|
||
|
@@ -190,6 +190,17 @@ typedef struct
|
||
|
G_DEFINE_TYPE (MetaMonitorConfigStore, meta_monitor_config_store,
|
||
|
G_TYPE_OBJECT)
|
||
|
|
||
|
+static gboolean
|
||
|
+text_equals (const char *text,
|
||
|
+ int len,
|
||
|
+ const char *expect)
|
||
|
+{
|
||
|
+ if (strlen (expect) != len)
|
||
|
+ return FALSE;
|
||
|
+
|
||
|
+ return strncmp (text, expect, len) == 0;
|
||
|
+}
|
||
|
+
|
||
|
static void
|
||
|
enter_unknown_element (ConfigParser *parser,
|
||
|
const char *element_name,
|
||
|
@@ -904,12 +915,12 @@ read_bool (const char *text,
|
||
|
gboolean *out_value,
|
||
|
GError **error)
|
||
|
{
|
||
|
- if (strncmp (text, "no", text_len) == 0)
|
||
|
+ if (text_equals (text, text_len, "no"))
|
||
|
{
|
||
|
*out_value = FALSE;
|
||
|
return TRUE;
|
||
|
}
|
||
|
- else if (strncmp (text, "yes", text_len) == 0)
|
||
|
+ else if (text_equals (text, text_len, "yes"))
|
||
|
{
|
||
|
*out_value = TRUE;
|
||
|
return TRUE;
|
||
|
@@ -1039,13 +1050,13 @@ handle_text (GMarkupParseContext *context,
|
||
|
|
||
|
case STATE_TRANSFORM_ROTATION:
|
||
|
{
|
||
|
- if (strncmp (text, "normal", text_len) == 0)
|
||
|
+ if (text_equals (text, text_len, "normal"))
|
||
|
parser->current_transform = META_MONITOR_TRANSFORM_NORMAL;
|
||
|
- else if (strncmp (text, "left", text_len) == 0)
|
||
|
+ else if (text_equals (text, text_len, "left"))
|
||
|
parser->current_transform = META_MONITOR_TRANSFORM_90;
|
||
|
- else if (strncmp (text, "upside_down", text_len) == 0)
|
||
|
+ else if (text_equals (text, text_len, "upside_down"))
|
||
|
parser->current_transform = META_MONITOR_TRANSFORM_180;
|
||
|
- else if (strncmp (text, "right", text_len) == 0)
|
||
|
+ else if (text_equals (text, text_len, "right"))
|
||
|
parser->current_transform = META_MONITOR_TRANSFORM_270;
|
||
|
else
|
||
|
g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
|
||
|
@@ -1088,7 +1099,7 @@ handle_text (GMarkupParseContext *context,
|
||
|
|
||
|
case STATE_MONITOR_MODE_FLAG:
|
||
|
{
|
||
|
- if (strncmp (text, "interlace", text_len) == 0)
|
||
|
+ if (text_equals (text, text_len, "interlace"))
|
||
|
{
|
||
|
parser->current_monitor_mode_spec->flags |=
|
||
|
META_CRTC_MODE_FLAG_INTERLACE;
|
||
|
--
|
||
|
2.33.1
|
||
|
|
||
|
|
||
|
From 73ae3806396840213eb72376a954262d7132a097 Mon Sep 17 00:00:00 2001
|
||
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
||
|
Date: Mon, 17 Jan 2022 11:45:53 +0100
|
||
|
Subject: [PATCH 5/9] 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>
|
||
|
|
||
|
(cherry picked from commit b747884c1eaf309bb2d9395a655c85c968bd1829)
|
||
|
---
|
||
|
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 +-
|
||
|
.../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/test-utils.c | 8 +-
|
||
|
src/tests/test-utils.h | 6 +-
|
||
|
12 files changed, 450 insertions(+), 94 deletions(-)
|
||
|
create mode 100644 src/tests/monitor-configs/policy.xml
|
||
|
|
||
|
diff --git a/src/backends/meta-backend-types.h b/src/backends/meta-backend-types.h
|
||
|
index 98cac8b9e2a9..15184f513289 100644
|
||
|
--- a/src/backends/meta-backend-types.h
|
||
|
+++ b/src/backends/meta-backend-types.h
|
||
|
@@ -27,6 +27,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 bb847b96e314..a3047b8c6639 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 f6b5256aa798..b320746a4418 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);
|
||
|
|
||
|
@@ -1511,23 +1687,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
|
||
|
@@ -1536,6 +1723,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)
|
||
|
{
|
||
|
@@ -1554,75 +1747,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 configuation.",
|
||
|
- 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);
|
||
|
}
|
||
|
@@ -1645,6 +1771,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);
|
||
|
}
|
||
|
@@ -1715,3 +1842,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 92c24ecaa8b6..cb6759dca00f 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/monitor-config-migration-unit-tests.c b/src/tests/monitor-config-migration-unit-tests.c
|
||
|
index 461035d6304a..096869c84c2a 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 000000000000..760046513e6e
|
||
|
--- /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'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 4ff0e396dda7..478193742ce8 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_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 d2dc3b2658c6..c50fa910e2ad 100644
|
||
|
--- a/src/tests/monitor-test-utils.c
|
||
|
+++ b/src/tests/monitor-test-utils.c
|
||
|
@@ -25,10 +25,24 @@
|
||
|
#include "backends/meta-monitor-config-manager.h"
|
||
|
#include "backends/meta-monitor-config-store.h"
|
||
|
|
||
|
+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 4b9b3f0c790d..2869f271d525 100644
|
||
|
--- a/src/tests/monitor-test-utils.h
|
||
|
+++ b/src/tests/monitor-test-utils.h
|
||
|
@@ -26,6 +26,8 @@ gboolean is_using_monitor_config_manager (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);
|
||
|
|
||
|
#endif /* MONITOR_TEST_UTILS_H */
|
||
|
diff --git a/src/tests/monitor-unit-tests.c b/src/tests/monitor-unit-tests.c
|
||
|
index 725f84173e86..83066289ebe3 100644
|
||
|
--- a/src/tests/monitor-unit-tests.c
|
||
|
+++ b/src/tests/monitor-unit-tests.c
|
||
|
@@ -5721,6 +5721,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);
|
||
|
|
||
|
@@ -5861,6 +5862,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);
|
||
|
|
||
|
@@ -6006,6 +6008,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/test-utils.c b/src/tests/test-utils.c
|
||
|
index f1a688478f67..23e7d92f91d6 100644
|
||
|
--- a/src/tests/test-utils.c
|
||
|
+++ b/src/tests/test-utils.c
|
||
|
@@ -486,8 +486,9 @@ 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);
|
||
|
@@ -503,8 +504,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/test-utils.h b/src/tests/test-utils.h
|
||
|
index 6d6cdb924d01..c426661e38eb 100644
|
||
|
--- a/src/tests/test-utils.h
|
||
|
+++ b/src/tests/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 TEST_RUNNER_ERROR test_runner_error_quark ()
|
||
|
@@ -81,8 +82,9 @@ void test_client_destroy (TestClient *client);
|
||
|
|
||
|
const char * test_get_plugin_name (void);
|
||
|
|
||
|
-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);
|
||
|
|
||
|
void meta_wait_for_paint (MetaBackend *backend);
|
||
|
|
||
|
--
|
||
|
2.33.1
|
||
|
|
||
|
|
||
|
From 5e8e431de7d6874d112d6dcee14ad1736d745a3b Mon Sep 17 00:00:00 2001
|
||
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
||
|
Date: Fri, 24 Sep 2021 19:07:32 +0200
|
||
|
Subject: [PATCH 6/9] tests: Add more monitor config policy parsing tests
|
||
|
|
||
|
(cherry picked from commit 48a3ff845fabf0f23568d3c798e047e9b303bffd)
|
||
|
---
|
||
|
.../monitor-configs/policy-duplicate.xml | 8 ++++
|
||
|
src/tests/monitor-configs/policy-empty.xml | 7 +++
|
||
|
src/tests/monitor-configs/policy-invalid.xml | 8 ++++
|
||
|
src/tests/monitor-configs/policy-multiple.xml | 12 +++++
|
||
|
src/tests/monitor-store-unit-tests.c | 44 +++++++++++++++++++
|
||
|
5 files changed, 79 insertions(+)
|
||
|
create mode 100644 src/tests/monitor-configs/policy-duplicate.xml
|
||
|
create mode 100644 src/tests/monitor-configs/policy-empty.xml
|
||
|
create mode 100644 src/tests/monitor-configs/policy-invalid.xml
|
||
|
create mode 100644 src/tests/monitor-configs/policy-multiple.xml
|
||
|
|
||
|
diff --git a/src/tests/monitor-configs/policy-duplicate.xml b/src/tests/monitor-configs/policy-duplicate.xml
|
||
|
new file mode 100644
|
||
|
index 000000000000..d93cc81a4906
|
||
|
--- /dev/null
|
||
|
+++ b/src/tests/monitor-configs/policy-duplicate.xml
|
||
|
@@ -0,0 +1,8 @@
|
||
|
+<monitors version="2">
|
||
|
+ <policy>
|
||
|
+ <stores>
|
||
|
+ <store>user</store>
|
||
|
+ <store>user</store>
|
||
|
+ </stores>
|
||
|
+ </policy>
|
||
|
+</monitors>
|
||
|
diff --git a/src/tests/monitor-configs/policy-empty.xml b/src/tests/monitor-configs/policy-empty.xml
|
||
|
new file mode 100644
|
||
|
index 000000000000..f56026b66846
|
||
|
--- /dev/null
|
||
|
+++ b/src/tests/monitor-configs/policy-empty.xml
|
||
|
@@ -0,0 +1,7 @@
|
||
|
+<monitors version="2">
|
||
|
+ <policy>
|
||
|
+ <stores>
|
||
|
+ <store></store>
|
||
|
+ </stores>
|
||
|
+ </policy>
|
||
|
+</monitors>
|
||
|
diff --git a/src/tests/monitor-configs/policy-invalid.xml b/src/tests/monitor-configs/policy-invalid.xml
|
||
|
new file mode 100644
|
||
|
index 000000000000..fc4552fbefc7
|
||
|
--- /dev/null
|
||
|
+++ b/src/tests/monitor-configs/policy-invalid.xml
|
||
|
@@ -0,0 +1,8 @@
|
||
|
+<monitors version="2">
|
||
|
+ <policy>
|
||
|
+ <stores>
|
||
|
+ <store>user</store>
|
||
|
+ <store>not-a-store</store>
|
||
|
+ </stores>
|
||
|
+ </policy>
|
||
|
+</monitors>
|
||
|
diff --git a/src/tests/monitor-configs/policy-multiple.xml b/src/tests/monitor-configs/policy-multiple.xml
|
||
|
new file mode 100644
|
||
|
index 000000000000..ffeb79aafe8a
|
||
|
--- /dev/null
|
||
|
+++ b/src/tests/monitor-configs/policy-multiple.xml
|
||
|
@@ -0,0 +1,12 @@
|
||
|
+<monitors version="2">
|
||
|
+ <policy>
|
||
|
+ <stores>
|
||
|
+ <store>user</store>
|
||
|
+ <store>system</store>
|
||
|
+ </stores>
|
||
|
+ <stores>
|
||
|
+ <store>system</store>
|
||
|
+ <store>user</store>
|
||
|
+ </stores>
|
||
|
+ </policy>
|
||
|
+</monitors>
|
||
|
diff --git a/src/tests/monitor-store-unit-tests.c b/src/tests/monitor-store-unit-tests.c
|
||
|
index 478193742ce8..50c220737b20 100644
|
||
|
--- a/src/tests/monitor-store-unit-tests.c
|
||
|
+++ b/src/tests/monitor-store-unit-tests.c
|
||
|
@@ -919,6 +919,42 @@ meta_test_monitor_store_policy (void)
|
||
|
META_CONFIG_STORE_SYSTEM);
|
||
|
}
|
||
|
|
||
|
+static void
|
||
|
+meta_test_monitor_store_policy_empty (void)
|
||
|
+{
|
||
|
+ g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
|
||
|
+ "*Invalid store*");
|
||
|
+ set_custom_monitor_system_config ("policy-empty.xml");
|
||
|
+ g_test_assert_expected_messages ();
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+meta_test_monitor_store_policy_duplicate (void)
|
||
|
+{
|
||
|
+ g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
|
||
|
+ "*Multiple identical stores*");
|
||
|
+ set_custom_monitor_system_config ("policy-duplicate.xml");
|
||
|
+ g_test_assert_expected_messages ();
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+meta_test_monitor_store_policy_invalid (void)
|
||
|
+{
|
||
|
+ g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
|
||
|
+ "*Invalid store*");
|
||
|
+ set_custom_monitor_system_config ("policy-invalid.xml");
|
||
|
+ g_test_assert_expected_messages ();
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+meta_test_monitor_store_policy_multiple (void)
|
||
|
+{
|
||
|
+ g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
|
||
|
+ "*Multiple stores elements under policy*");
|
||
|
+ set_custom_monitor_system_config ("policy-multiple.xml");
|
||
|
+ g_test_assert_expected_messages ();
|
||
|
+}
|
||
|
+
|
||
|
void
|
||
|
init_monitor_store_tests (void)
|
||
|
{
|
||
|
@@ -950,4 +986,12 @@ init_monitor_store_tests (void)
|
||
|
meta_test_monitor_store_policy_not_allowed);
|
||
|
g_test_add_func ("/backends/monitor-store/policy",
|
||
|
meta_test_monitor_store_policy);
|
||
|
+ g_test_add_func ("/backends/monitor-store/policy-empty",
|
||
|
+ meta_test_monitor_store_policy_empty);
|
||
|
+ g_test_add_func ("/backends/monitor-store/policy-duplicate",
|
||
|
+ meta_test_monitor_store_policy_duplicate);
|
||
|
+ g_test_add_func ("/backends/monitor-store/policy-invalid",
|
||
|
+ meta_test_monitor_store_policy_invalid);
|
||
|
+ g_test_add_func ("/backends/monitor-store/policy-multiple",
|
||
|
+ meta_test_monitor_store_policy_multiple);
|
||
|
}
|
||
|
--
|
||
|
2.33.1
|
||
|
|
||
|
|
||
|
From a8f7700df399481d7bbbe42d13127e38dc193143 Mon Sep 17 00:00:00 2001
|
||
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
||
|
Date: Thu, 30 Sep 2021 17:32:31 +0200
|
||
|
Subject: [PATCH 7/9] monitor-config-store: Add test for monitor configuration
|
||
|
policy
|
||
|
|
||
|
The test aims to verify that setting the following policy
|
||
|
|
||
|
<policy>
|
||
|
<stores>
|
||
|
<store>system</store>
|
||
|
</stores>
|
||
|
</policy>
|
||
|
|
||
|
only applies monitor configurations from the system level.
|
||
|
|
||
|
(cherry picked from commit 9969a8aa25623dbff51e120d85ab202026571bb1)
|
||
|
---
|
||
|
src/tests/monitor-configs/system/monitors.xml | 27 ++++
|
||
|
src/tests/monitor-configs/user/monitors.xml | 22 +++
|
||
|
src/tests/monitor-store-unit-tests.c | 17 +++
|
||
|
src/tests/monitor-unit-tests.c | 132 ++++++++++++++++++
|
||
|
4 files changed, 198 insertions(+)
|
||
|
create mode 100644 src/tests/monitor-configs/system/monitors.xml
|
||
|
create mode 100644 src/tests/monitor-configs/user/monitors.xml
|
||
|
|
||
|
diff --git a/src/tests/monitor-configs/system/monitors.xml b/src/tests/monitor-configs/system/monitors.xml
|
||
|
new file mode 100644
|
||
|
index 000000000000..4d2eafec1327
|
||
|
--- /dev/null
|
||
|
+++ b/src/tests/monitor-configs/system/monitors.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's Inc.</vendor>
|
||
|
+ <product>MetaMonitor</product>
|
||
|
+ <serial>0x123456</serial>
|
||
|
+ </monitorspec>
|
||
|
+ <mode>
|
||
|
+ <width>640</width>
|
||
|
+ <height>480</height>
|
||
|
+ <rate>60</rate>
|
||
|
+ </mode>
|
||
|
+ </monitor>
|
||
|
+ </logicalmonitor>
|
||
|
+ </configuration>
|
||
|
+</monitors>
|
||
|
diff --git a/src/tests/monitor-configs/user/monitors.xml b/src/tests/monitor-configs/user/monitors.xml
|
||
|
new file mode 100644
|
||
|
index 000000000000..f125972e01e7
|
||
|
--- /dev/null
|
||
|
+++ b/src/tests/monitor-configs/user/monitors.xml
|
||
|
@@ -0,0 +1,22 @@
|
||
|
+<monitors version="2">
|
||
|
+ <configuration>
|
||
|
+ <logicalmonitor>
|
||
|
+ <x>0</x>
|
||
|
+ <y>0</y>
|
||
|
+ <primary>yes</primary>
|
||
|
+ <monitor>
|
||
|
+ <monitorspec>
|
||
|
+ <connector>DP-1</connector>
|
||
|
+ <vendor>MetaProduct's Inc.</vendor>
|
||
|
+ <product>MetaMonitor</product>
|
||
|
+ <serial>0x123456</serial>
|
||
|
+ </monitorspec>
|
||
|
+ <mode>
|
||
|
+ <width>800</width>
|
||
|
+ <height>600</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 50c220737b20..20860e7aa510 100644
|
||
|
--- a/src/tests/monitor-store-unit-tests.c
|
||
|
+++ b/src/tests/monitor-store-unit-tests.c
|
||
|
@@ -958,6 +958,23 @@ meta_test_monitor_store_policy_multiple (void)
|
||
|
void
|
||
|
init_monitor_store_tests (void)
|
||
|
{
|
||
|
+ char *path;
|
||
|
+
|
||
|
+ path = g_test_build_filename (G_TEST_DIST,
|
||
|
+ "tests",
|
||
|
+ "monitor-configs",
|
||
|
+ "system",
|
||
|
+ NULL);
|
||
|
+ g_setenv ("XDG_CONFIG_DIRS", path, TRUE);
|
||
|
+ g_free (path);
|
||
|
+ path = g_test_build_filename (G_TEST_DIST,
|
||
|
+ "tests",
|
||
|
+ "monitor-configs",
|
||
|
+ "user",
|
||
|
+ NULL);
|
||
|
+ g_setenv ("XDG_CONFIG_HOME", path, TRUE);
|
||
|
+ g_free (path);
|
||
|
+
|
||
|
g_test_add_func ("/backends/monitor-store/single",
|
||
|
meta_test_monitor_store_single);
|
||
|
g_test_add_func ("/backends/monitor-store/vertical",
|
||
|
diff --git a/src/tests/monitor-unit-tests.c b/src/tests/monitor-unit-tests.c
|
||
|
index 83066289ebe3..5401edbc6d7c 100644
|
||
|
--- a/src/tests/monitor-unit-tests.c
|
||
|
+++ b/src/tests/monitor-unit-tests.c
|
||
|
@@ -6043,6 +6043,135 @@ meta_test_monitor_migrated_wiggle (void)
|
||
|
g_error ("Failed to remove test data output file: %s", error->message);
|
||
|
}
|
||
|
|
||
|
+static void
|
||
|
+meta_test_monitor_policy_system_only (void)
|
||
|
+{
|
||
|
+ MetaMonitorTestSetup *test_setup;
|
||
|
+ MonitorTestCase test_case = {
|
||
|
+ .setup = {
|
||
|
+ .modes = {
|
||
|
+ {
|
||
|
+ .width = 1024,
|
||
|
+ .height = 768,
|
||
|
+ .refresh_rate = 60.0
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .width = 800,
|
||
|
+ .height = 600,
|
||
|
+ .refresh_rate = 60.0
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .width = 640,
|
||
|
+ .height = 480,
|
||
|
+ .refresh_rate = 60.0
|
||
|
+ }
|
||
|
+ },
|
||
|
+ .n_modes = 3,
|
||
|
+ .outputs = {
|
||
|
+ {
|
||
|
+ .crtc = 0,
|
||
|
+ .modes = { 0, 1, 2 },
|
||
|
+ .n_modes = 3,
|
||
|
+ .preferred_mode = 0,
|
||
|
+ .possible_crtcs = { 0 },
|
||
|
+ .n_possible_crtcs = 1,
|
||
|
+ .width_mm = 222,
|
||
|
+ .height_mm = 125
|
||
|
+ },
|
||
|
+ },
|
||
|
+ .n_outputs = 1,
|
||
|
+ .crtcs = {
|
||
|
+ {
|
||
|
+ .current_mode = 0
|
||
|
+ }
|
||
|
+ },
|
||
|
+ .n_crtcs = 1
|
||
|
+ },
|
||
|
+
|
||
|
+ .expect = {
|
||
|
+ .monitors = {
|
||
|
+ {
|
||
|
+ .outputs = { 0 },
|
||
|
+ .n_outputs = 1,
|
||
|
+ .modes = {
|
||
|
+ {
|
||
|
+ .width = 1024,
|
||
|
+ .height = 768,
|
||
|
+ .refresh_rate = 60.0,
|
||
|
+ .crtc_modes = {
|
||
|
+ {
|
||
|
+ .output = 0,
|
||
|
+ .crtc_mode = 0
|
||
|
+ }
|
||
|
+ }
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .width = 800,
|
||
|
+ .height = 600,
|
||
|
+ .refresh_rate = 60.0,
|
||
|
+ .crtc_modes = {
|
||
|
+ {
|
||
|
+ .output = 0,
|
||
|
+ .crtc_mode = 1
|
||
|
+ }
|
||
|
+ }
|
||
|
+ },
|
||
|
+ {
|
||
|
+ .width = 640,
|
||
|
+ .height = 480,
|
||
|
+ .refresh_rate = 60.0,
|
||
|
+ .crtc_modes = {
|
||
|
+ {
|
||
|
+ .output = 0,
|
||
|
+ .crtc_mode = 2
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+ },
|
||
|
+ .n_modes = 3,
|
||
|
+ .current_mode = 2,
|
||
|
+ .width_mm = 222,
|
||
|
+ .height_mm = 125
|
||
|
+ },
|
||
|
+ },
|
||
|
+ .n_monitors = 1,
|
||
|
+ .logical_monitors = {
|
||
|
+ {
|
||
|
+ .monitors = { 0 },
|
||
|
+ .n_monitors = 1,
|
||
|
+ .layout = { .x = 0, .y = 0, .width = 640, .height = 480 },
|
||
|
+ .scale = 1
|
||
|
+ },
|
||
|
+ },
|
||
|
+ .n_logical_monitors = 1,
|
||
|
+ .primary_logical_monitor = 0,
|
||
|
+ .n_outputs = 1,
|
||
|
+ .crtcs = {
|
||
|
+ {
|
||
|
+ .current_mode = 2,
|
||
|
+ .x = 0,
|
||
|
+ }
|
||
|
+ },
|
||
|
+ .n_crtcs = 1,
|
||
|
+ .screen_width = 640,
|
||
|
+ .screen_height = 480,
|
||
|
+ }
|
||
|
+ };
|
||
|
+ 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);
|
||
|
+
|
||
|
+ test_setup = create_monitor_test_setup (&test_case.setup,
|
||
|
+ MONITOR_TEST_FLAG_NONE);
|
||
|
+
|
||
|
+ meta_monitor_config_store_reset (config_store);
|
||
|
+ emulate_hotplug (test_setup);
|
||
|
+ check_monitor_configuration (&test_case);
|
||
|
+}
|
||
|
+
|
||
|
static void
|
||
|
test_case_setup (void **fixture,
|
||
|
const void *data)
|
||
|
@@ -6159,6 +6288,9 @@ init_monitor_tests (void)
|
||
|
meta_test_monitor_migrated_wiggle);
|
||
|
add_monitor_test ("/backends/monitor/migrated/wiggle-discard",
|
||
|
meta_test_monitor_migrated_wiggle_discard);
|
||
|
+
|
||
|
+ add_monitor_test ("/backends/monitor/policy/system-only",
|
||
|
+ meta_test_monitor_policy_system_only);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
--
|
||
|
2.33.1
|
||
|
|
||
|
|
||
|
From e4de67a35a70cfe0886b1932c442517ccfa0ca93 Mon Sep 17 00:00:00 2001
|
||
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
||
|
Date: Thu, 30 Sep 2021 21:06:38 +0200
|
||
|
Subject: [PATCH 8/9] monitor-config-store: Allow changing D-Bus configuration
|
||
|
policy
|
||
|
|
||
|
Adding a <dbus/> element containing a boolean (yes/no) determines
|
||
|
whether org.gnome.Mutter.DisplayConfig ApplyMonitorsConfig will be
|
||
|
callable. The state is also introspectable via the
|
||
|
ApplyMonitorsConfigAllowed property on the same interface.
|
||
|
|
||
|
For example
|
||
|
|
||
|
<monitors version="2">
|
||
|
<policy>
|
||
|
<dbus>no</dbus>
|
||
|
</policy>
|
||
|
</monitors>
|
||
|
|
||
|
(cherry picked from commit f2c7ae821b7af7e732e588e7548238dd814e5f84)
|
||
|
---
|
||
|
src/backends/meta-monitor-config-store.c | 68 +++++++++++++++++++
|
||
|
src/backends/meta-monitor-config-store.h | 8 +++
|
||
|
src/backends/meta-monitor-manager-private.h | 1 +
|
||
|
src/backends/meta-monitor-manager.c | 24 +++++++
|
||
|
src/org.gnome.Mutter.DisplayConfig.xml | 7 ++
|
||
|
.../monitor-configs/policy-dbus-invalid.xml | 6 ++
|
||
|
src/tests/monitor-configs/policy-dbus.xml | 5 ++
|
||
|
src/tests/monitor-store-unit-tests.c | 49 +++++++++++++
|
||
|
8 files changed, 168 insertions(+)
|
||
|
create mode 100644 src/tests/monitor-configs/policy-dbus-invalid.xml
|
||
|
create mode 100644 src/tests/monitor-configs/policy-dbus.xml
|
||
|
|
||
|
diff --git a/src/backends/meta-monitor-config-store.c b/src/backends/meta-monitor-config-store.c
|
||
|
index b320746a4418..cc866587c219 100644
|
||
|
--- a/src/backends/meta-monitor-config-store.c
|
||
|
+++ b/src/backends/meta-monitor-config-store.c
|
||
|
@@ -123,6 +123,9 @@ struct _MetaMonitorConfigStore
|
||
|
|
||
|
gboolean has_stores_policy;
|
||
|
GList *stores_policy;
|
||
|
+
|
||
|
+ gboolean has_dbus_policy;
|
||
|
+ MetaMonitorConfigPolicy policy;
|
||
|
};
|
||
|
|
||
|
#define META_MONITOR_CONFIG_STORE_ERROR (meta_monitor_config_store_error_quark ())
|
||
|
@@ -168,6 +171,7 @@ typedef enum
|
||
|
STATE_POLICY,
|
||
|
STATE_STORES,
|
||
|
STATE_STORE,
|
||
|
+ STATE_DBUS,
|
||
|
} ParserState;
|
||
|
|
||
|
typedef struct
|
||
|
@@ -191,9 +195,13 @@ typedef struct
|
||
|
GList *current_disabled_monitor_specs;
|
||
|
gboolean seen_policy;
|
||
|
gboolean seen_stores;
|
||
|
+ gboolean seen_dbus;
|
||
|
MetaConfigStore pending_store;
|
||
|
GList *stores;
|
||
|
|
||
|
+ gboolean enable_dbus_set;
|
||
|
+ gboolean enable_dbus;
|
||
|
+
|
||
|
ParserState unknown_state_root;
|
||
|
int unknown_level;
|
||
|
|
||
|
@@ -574,6 +582,19 @@ handle_start_element (GMarkupParseContext *context,
|
||
|
parser->seen_stores = TRUE;
|
||
|
parser->state = STATE_STORES;
|
||
|
}
|
||
|
+ else if (g_str_equal (element_name, "dbus"))
|
||
|
+ {
|
||
|
+ if (parser->seen_dbus)
|
||
|
+ {
|
||
|
+ g_set_error (error,
|
||
|
+ G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
|
||
|
+ "Multiple dbus elements under policy");
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ parser->seen_dbus = TRUE;
|
||
|
+ parser->state = STATE_DBUS;
|
||
|
+ }
|
||
|
else
|
||
|
{
|
||
|
enter_unknown_element (parser, element_name,
|
||
|
@@ -604,6 +625,13 @@ handle_start_element (GMarkupParseContext *context,
|
||
|
"Invalid store sub element '%s'", element_name);
|
||
|
return;
|
||
|
}
|
||
|
+
|
||
|
+ case STATE_DBUS:
|
||
|
+ {
|
||
|
+ g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
|
||
|
+ "Invalid dbus sub element '%s'", element_name);
|
||
|
+ return;
|
||
|
+ }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@@ -953,6 +981,23 @@ handle_end_element (GMarkupParseContext *context,
|
||
|
parser->state = STATE_POLICY;
|
||
|
return;
|
||
|
|
||
|
+ case STATE_DBUS:
|
||
|
+ if (!parser->config_store->has_dbus_policy)
|
||
|
+ {
|
||
|
+ parser->config_store->has_dbus_policy = TRUE;
|
||
|
+ parser->config_store->policy.enable_dbus = parser->enable_dbus;
|
||
|
+ parser->enable_dbus_set = FALSE;
|
||
|
+ }
|
||
|
+ else
|
||
|
+ {
|
||
|
+ g_warning ("Policy for monitor configuration via D-Bus "
|
||
|
+ "has already been set, ignoring policy from '%s'",
|
||
|
+ g_file_get_path (parser->file));
|
||
|
+ }
|
||
|
+ parser->state = STATE_POLICY;
|
||
|
+
|
||
|
+ return;
|
||
|
+
|
||
|
case STATE_POLICY:
|
||
|
g_assert (g_str_equal (element_name, "policy"));
|
||
|
|
||
|
@@ -1285,6 +1330,15 @@ handle_text (GMarkupParseContext *context,
|
||
|
parser->pending_store = store;
|
||
|
return;
|
||
|
}
|
||
|
+
|
||
|
+ case STATE_DBUS:
|
||
|
+ {
|
||
|
+ parser->enable_dbus_set = TRUE;
|
||
|
+ read_bool (text, text_len,
|
||
|
+ &parser->enable_dbus,
|
||
|
+ error);
|
||
|
+ return;
|
||
|
+ }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@@ -1628,6 +1682,11 @@ meta_monitor_config_store_save (MetaMonitorConfigStore *config_store)
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
+ if (config_store->has_stores_policy &&
|
||
|
+ !g_list_find (config_store->stores_policy,
|
||
|
+ GINT_TO_POINTER (META_CONFIG_STORE_USER)))
|
||
|
+ return;
|
||
|
+
|
||
|
config_store->save_cancellable = g_cancellable_new ();
|
||
|
|
||
|
buffer = generate_config_xml (config_store);
|
||
|
@@ -1704,6 +1763,8 @@ meta_monitor_config_store_set_custom (MetaMonitorConfigStore *config_store,
|
||
|
|
||
|
g_clear_pointer (&config_store->stores_policy, g_list_free);
|
||
|
config_store->has_stores_policy = FALSE;
|
||
|
+ config_store->policy.enable_dbus = TRUE;
|
||
|
+ config_store->has_dbus_policy = FALSE;
|
||
|
|
||
|
if (!read_config_file (config_store,
|
||
|
config_store->custom_read_file,
|
||
|
@@ -1819,6 +1880,7 @@ meta_monitor_config_store_init (MetaMonitorConfigStore *config_store)
|
||
|
meta_monitors_config_key_equal,
|
||
|
NULL,
|
||
|
g_object_unref);
|
||
|
+ config_store->policy.enable_dbus = TRUE;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
@@ -1972,3 +2034,9 @@ meta_monitor_config_store_reset (MetaMonitorConfigStore *config_store)
|
||
|
|
||
|
g_free (user_file_path);
|
||
|
}
|
||
|
+
|
||
|
+const MetaMonitorConfigPolicy *
|
||
|
+meta_monitor_config_store_get_policy (MetaMonitorConfigStore *config_store)
|
||
|
+{
|
||
|
+ return &config_store->policy;
|
||
|
+}
|
||
|
diff --git a/src/backends/meta-monitor-config-store.h b/src/backends/meta-monitor-config-store.h
|
||
|
index cb6759dca00f..a255e370baaf 100644
|
||
|
--- a/src/backends/meta-monitor-config-store.h
|
||
|
+++ b/src/backends/meta-monitor-config-store.h
|
||
|
@@ -32,6 +32,11 @@ typedef enum _MetaConfigStore
|
||
|
META_CONFIG_STORE_USER,
|
||
|
} MetaConfigStore;
|
||
|
|
||
|
+typedef struct _MetaMonitorConfigPolicy
|
||
|
+{
|
||
|
+ gboolean enable_dbus;
|
||
|
+} MetaMonitorConfigPolicy;
|
||
|
+
|
||
|
#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)
|
||
|
@@ -70,4 +75,7 @@ MetaMonitorManager * meta_monitor_config_store_get_monitor_manager (MetaMonitorC
|
||
|
META_EXPORT_TEST
|
||
|
void meta_monitor_config_store_reset (MetaMonitorConfigStore *config_store);
|
||
|
|
||
|
+META_EXPORT_TEST
|
||
|
+const MetaMonitorConfigPolicy * meta_monitor_config_store_get_policy (MetaMonitorConfigStore *config_store);
|
||
|
+
|
||
|
#endif /* META_MONITOR_CONFIG_STORE_H */
|
||
|
diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h
|
||
|
index 223b5dfbda31..030eaf7b9ea1 100644
|
||
|
--- a/src/backends/meta-monitor-manager-private.h
|
||
|
+++ b/src/backends/meta-monitor-manager-private.h
|
||
|
@@ -383,6 +383,7 @@ gboolean meta_monitor_manager_get_max_screen_size (MetaMonitorManager
|
||
|
MetaLogicalMonitorLayoutMode
|
||
|
meta_monitor_manager_get_default_layout_mode (MetaMonitorManager *manager);
|
||
|
|
||
|
+META_EXPORT_TEST
|
||
|
MetaMonitorConfigManager *
|
||
|
meta_monitor_manager_get_config_manager (MetaMonitorManager *manager);
|
||
|
|
||
|
diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c
|
||
|
index 0adf2100db18..f00e7c2abaad 100644
|
||
|
--- a/src/backends/meta-monitor-manager.c
|
||
|
+++ b/src/backends/meta-monitor-manager.c
|
||
|
@@ -51,6 +51,7 @@
|
||
|
#include "backends/meta-logical-monitor.h"
|
||
|
#include "backends/meta-monitor.h"
|
||
|
#include "backends/meta-monitor-config-manager.h"
|
||
|
+#include "backends/meta-monitor-config-store.h"
|
||
|
#include "backends/meta-orientation-manager.h"
|
||
|
#include "backends/meta-output.h"
|
||
|
#include "backends/x11/meta-monitor-manager-xrandr.h"
|
||
|
@@ -776,9 +777,18 @@ experimental_features_changed (MetaSettings *settings,
|
||
|
void
|
||
|
meta_monitor_manager_setup (MetaMonitorManager *manager)
|
||
|
{
|
||
|
+ MetaMonitorConfigStore *config_store;
|
||
|
+ const MetaMonitorConfigPolicy *policy;
|
||
|
+
|
||
|
manager->in_init = TRUE;
|
||
|
|
||
|
manager->config_manager = meta_monitor_config_manager_new (manager);
|
||
|
+ config_store =
|
||
|
+ meta_monitor_config_manager_get_store (manager->config_manager);
|
||
|
+ policy = meta_monitor_config_store_get_policy (config_store);
|
||
|
+ meta_dbus_display_config_set_apply_monitors_config_allowed (manager->display_config,
|
||
|
+ policy->enable_dbus);
|
||
|
+
|
||
|
|
||
|
meta_monitor_manager_read_current_state (manager);
|
||
|
|
||
|
@@ -2033,6 +2043,8 @@ meta_monitor_manager_handle_apply_monitors_config (MetaDBusDisplayConfig *skelet
|
||
|
GVariant *properties_variant,
|
||
|
MetaMonitorManager *manager)
|
||
|
{
|
||
|
+ MetaMonitorConfigStore *config_store;
|
||
|
+ const MetaMonitorConfigPolicy *policy;
|
||
|
MetaMonitorManagerCapability capabilities;
|
||
|
GVariant *layout_mode_variant = NULL;
|
||
|
MetaLogicalMonitorLayoutMode layout_mode;
|
||
|
@@ -2049,6 +2061,18 @@ meta_monitor_manager_handle_apply_monitors_config (MetaDBusDisplayConfig *skelet
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
+ config_store =
|
||
|
+ meta_monitor_config_manager_get_store (manager->config_manager);
|
||
|
+ policy = meta_monitor_config_store_get_policy (config_store);
|
||
|
+
|
||
|
+ if (!policy->enable_dbus)
|
||
|
+ {
|
||
|
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||
|
+ G_DBUS_ERROR_ACCESS_DENIED,
|
||
|
+ "Monitor configuration via D-Bus is disabled");
|
||
|
+ return TRUE;
|
||
|
+ }
|
||
|
+
|
||
|
capabilities = meta_monitor_manager_get_capabilities (manager);
|
||
|
|
||
|
if (properties_variant)
|
||
|
diff --git a/src/org.gnome.Mutter.DisplayConfig.xml b/src/org.gnome.Mutter.DisplayConfig.xml
|
||
|
index 3abfa15d7816..07e2e58df758 100644
|
||
|
--- a/src/org.gnome.Mutter.DisplayConfig.xml
|
||
|
+++ b/src/org.gnome.Mutter.DisplayConfig.xml
|
||
|
@@ -282,6 +282,13 @@
|
||
|
-->
|
||
|
<property name="PowerSaveMode" type="i" access="readwrite" />
|
||
|
|
||
|
+ <!--
|
||
|
+ ApplyMonitorsConfigAllowed:
|
||
|
+
|
||
|
+ Whether calling the ApplyMonitorsConfig method is allowed.
|
||
|
+ -->
|
||
|
+ <property name="ApplyMonitorsConfigAllowed" type="b" access="read" />
|
||
|
+
|
||
|
<!--
|
||
|
MonitorsChanged:
|
||
|
|
||
|
diff --git a/src/tests/monitor-configs/policy-dbus-invalid.xml b/src/tests/monitor-configs/policy-dbus-invalid.xml
|
||
|
new file mode 100644
|
||
|
index 000000000000..67fa6045ff26
|
||
|
--- /dev/null
|
||
|
+++ b/src/tests/monitor-configs/policy-dbus-invalid.xml
|
||
|
@@ -0,0 +1,6 @@
|
||
|
+<monitors version="2">
|
||
|
+ <policy>
|
||
|
+ <dbus>no</dbus>
|
||
|
+ <dbus>yes</dbus>
|
||
|
+ </policy>
|
||
|
+</monitors>
|
||
|
diff --git a/src/tests/monitor-configs/policy-dbus.xml b/src/tests/monitor-configs/policy-dbus.xml
|
||
|
new file mode 100644
|
||
|
index 000000000000..c407e1f02194
|
||
|
--- /dev/null
|
||
|
+++ b/src/tests/monitor-configs/policy-dbus.xml
|
||
|
@@ -0,0 +1,5 @@
|
||
|
+<monitors version="2">
|
||
|
+ <policy>
|
||
|
+ <dbus>no</dbus>
|
||
|
+ </policy>
|
||
|
+</monitors>
|
||
|
diff --git a/src/tests/monitor-store-unit-tests.c b/src/tests/monitor-store-unit-tests.c
|
||
|
index 20860e7aa510..1730dd9d6838 100644
|
||
|
--- a/src/tests/monitor-store-unit-tests.c
|
||
|
+++ b/src/tests/monitor-store-unit-tests.c
|
||
|
@@ -955,6 +955,51 @@ meta_test_monitor_store_policy_multiple (void)
|
||
|
g_test_assert_expected_messages ();
|
||
|
}
|
||
|
|
||
|
+static void
|
||
|
+meta_test_monitor_store_policy_dbus (void)
|
||
|
+{
|
||
|
+ MetaBackend *backend = meta_get_backend ();
|
||
|
+ MetaMonitorManager *monitor_manager =
|
||
|
+ meta_backend_get_monitor_manager (backend);
|
||
|
+ MetaMonitorConfigManager *config_manager =
|
||
|
+ meta_monitor_manager_get_config_manager (monitor_manager);
|
||
|
+ MetaMonitorConfigStore *config_store =
|
||
|
+ meta_monitor_config_manager_get_store (config_manager);
|
||
|
+ const MetaMonitorConfigPolicy *policy;
|
||
|
+
|
||
|
+ policy = meta_monitor_config_store_get_policy (config_store);
|
||
|
+ g_assert_nonnull (policy);
|
||
|
+ g_assert_cmpint (policy->enable_dbus, ==, TRUE);
|
||
|
+
|
||
|
+ set_custom_monitor_system_config ("policy-dbus.xml");
|
||
|
+
|
||
|
+ policy = meta_monitor_config_store_get_policy (config_store);
|
||
|
+ g_assert_nonnull (policy);
|
||
|
+ g_assert_cmpint (policy->enable_dbus, ==, FALSE);
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+meta_test_monitor_store_policy_dbus_invalid (void)
|
||
|
+{
|
||
|
+ MetaBackend *backend = meta_get_backend ();
|
||
|
+ MetaMonitorManager *monitor_manager =
|
||
|
+ meta_backend_get_monitor_manager (backend);
|
||
|
+ MetaMonitorConfigManager *config_manager =
|
||
|
+ meta_monitor_manager_get_config_manager (monitor_manager);
|
||
|
+ MetaMonitorConfigStore *config_store =
|
||
|
+ meta_monitor_config_manager_get_store (config_manager);
|
||
|
+ const MetaMonitorConfigPolicy *policy;
|
||
|
+
|
||
|
+ g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
|
||
|
+ "*Multiple dbus elements under policy*");
|
||
|
+ set_custom_monitor_system_config ("policy-dbus-invalid.xml");
|
||
|
+ g_test_assert_expected_messages ();
|
||
|
+
|
||
|
+ policy = meta_monitor_config_store_get_policy (config_store);
|
||
|
+ g_assert_nonnull (policy);
|
||
|
+ g_assert_cmpint (policy->enable_dbus, ==, FALSE);
|
||
|
+}
|
||
|
+
|
||
|
void
|
||
|
init_monitor_store_tests (void)
|
||
|
{
|
||
|
@@ -1011,4 +1056,8 @@ init_monitor_store_tests (void)
|
||
|
meta_test_monitor_store_policy_invalid);
|
||
|
g_test_add_func ("/backends/monitor-store/policy-multiple",
|
||
|
meta_test_monitor_store_policy_multiple);
|
||
|
+ g_test_add_func ("/backends/monitor-store/dbus",
|
||
|
+ meta_test_monitor_store_policy_dbus);
|
||
|
+ g_test_add_func ("/backends/monitor-store/dbus-invalid",
|
||
|
+ meta_test_monitor_store_policy_dbus_invalid);
|
||
|
}
|
||
|
--
|
||
|
2.33.1
|
||
|
|
||
|
|
||
|
From b39016a5a782f132f380591ab98c7f3eac6af861 Mon Sep 17 00:00:00 2001
|
||
|
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
||
|
Date: Fri, 1 Oct 2021 09:52:15 +0200
|
||
|
Subject: [PATCH 9/9] doc: Add monitor configuration documentation
|
||
|
|
||
|
This describes how the `monitors.xml` file work, and how to override the
|
||
|
newly introduced configurable policy.
|
||
|
|
||
|
(cherry picked from commit 3bbb53db3da07c0e944903ee8dede722cd082d34)
|
||
|
---
|
||
|
doc/monitor-configuration.md | 105 +++++++++++++++++++++++++++++++++++
|
||
|
1 file changed, 105 insertions(+)
|
||
|
create mode 100644 doc/monitor-configuration.md
|
||
|
|
||
|
diff --git a/doc/monitor-configuration.md b/doc/monitor-configuration.md
|
||
|
new file mode 100644
|
||
|
index 000000000000..46c1078379cb
|
||
|
--- /dev/null
|
||
|
+++ b/doc/monitor-configuration.md
|
||
|
@@ -0,0 +1,105 @@
|
||
|
+Monitor configuration
|
||
|
+=====================
|
||
|
+
|
||
|
+File locations
|
||
|
+--------------
|
||
|
+
|
||
|
+Monitor configurations are stored as XML files called `monitors.xml` on the file
|
||
|
+system. There are two types of locations for the XML file: the system level and
|
||
|
+the user level.
|
||
|
+
|
||
|
+The directories for system level configuration is defined in accordance to the
|
||
|
+$XDG_CONFIG_DIRS environment variable defined in the XDG Base Directory
|
||
|
+Specification. The default is `/etc/xdg/monitors.xml`.
|
||
|
+
|
||
|
+The directory for the user level configuration is defined in accordance to the
|
||
|
+$XDG_CONFIG_HOME environment variable defined in the XDG Base Directory
|
||
|
+Specification. The default is `~/.config/monitors.xml`
|
||
|
+
|
||
|
+File contents
|
||
|
+-------------
|
||
|
+
|
||
|
+A configuration file consists of an XML document with the root element
|
||
|
+`<monitors version="2">`. In this document multiple configurations are stored as
|
||
|
+individual `<configuration/>` elements containing all the details of the monitor
|
||
|
+setup. The `version` attribute must be set to `"2"`.
|
||
|
+
|
||
|
+Each configuration corresponds to a specific hardware setup, where a given set
|
||
|
+of monitors are connected to the computer. There can only be one configuration
|
||
|
+per hardware setup.
|
||
|
+
|
||
|
+Writing configuration
|
||
|
+---------------------
|
||
|
+
|
||
|
+Monitor configurations are managed by Mutter via the Display panel in Settings,
|
||
|
+which uses a D-Bus API to communicate with Mutter. Each time a new configuration
|
||
|
+is applied and accepted, the user level configuration file is replaced with
|
||
|
+updated content.
|
||
|
+
|
||
|
+Previously defined monitor configurations for hardware state other than the
|
||
|
+current are left intact.
|
||
|
+
|
||
|
+Configuration policy
|
||
|
+--------------------
|
||
|
+
|
||
|
+The monitor configuration policy determines how Mutter configures monitors. This
|
||
|
+can mean for example in what order configuration files should be preferred, or
|
||
|
+whether configuration via Settings (i.e. D-Bus) should be allowed.
|
||
|
+
|
||
|
+The default policy is to prioritize configurations defined in the user level
|
||
|
+configuration file, and to allow configuring via D-Bus.
|
||
|
+
|
||
|
+Changing the policy is possible by manually adding a `<policy/>` element inside
|
||
|
+the `<monitors version="2"/>` element in the `monitors.xml` file. Note that
|
||
|
+there may only be one `<policy/>` element in each configuration file.
|
||
|
+
|
||
|
+### Changing configuration file priority policy
|
||
|
+
|
||
|
+To change the order of configuration file priority, or to disable configuration
|
||
|
+files completely, add a `<stores/>` element inside the `<policy/>` element
|
||
|
+described above.
|
||
|
+
|
||
|
+In this element, the file policy is defined by a `<stores/>` element, which
|
||
|
+lists stores with the order according to prioritization. Each store is specified
|
||
|
+using a `<store/>` element with either `system` or `user` as the content.
|
||
|
+
|
||
|
+#### Example of only reading monitor configuration from the system level file:
|
||
|
+
|
||
|
+```xml
|
||
|
+<monitors version="2">
|
||
|
+ <policy>
|
||
|
+ <stores>
|
||
|
+ <store>system</store>
|
||
|
+ </stores>
|
||
|
+ </policy>
|
||
|
+</monitors>
|
||
|
+```
|
||
|
+
|
||
|
+#### Example of reversing the priority of monitor configuration:
|
||
|
+
|
||
|
+```xml
|
||
|
+<monitors version="2">
|
||
|
+ <policy>
|
||
|
+ <stores>
|
||
|
+ <store>user</store>
|
||
|
+ <store>system</store>
|
||
|
+ </stores>
|
||
|
+ </policy>
|
||
|
+</monitors>
|
||
|
+```
|
||
|
+
|
||
|
+### Changing D-Bus configuration policy
|
||
|
+
|
||
|
+D-Bus configureability can be configured using a `<dbus/>` element in the
|
||
|
+`<policy/>` element. It's content should either be `yes` or `no` depending on
|
||
|
+whether monitor configuration via D-Bus should be enabled or disable.
|
||
|
+
|
||
|
+#### Example of how to disable monitor configuration via D-Bus:
|
||
|
+
|
||
|
+```xml
|
||
|
+<monitors version="2">
|
||
|
+ <policy>
|
||
|
+ <dbus>no</dbus>
|
||
|
+ </policy>
|
||
|
+</monitors>
|
||
|
+```
|
||
|
--
|
||
|
2.33.1
|
||
|
|