[gnome-flashback] monitor-config: keep track of disabled monitors for stored configs



commit 0f3e3a826f2989187abd5dc8c6b3403ea2e198a3
Author: Jonas Ådahl <jadahl gmail com>
Date:   Thu Sep 28 11:34:33 2017 -0400

    monitor-config: keep track of disabled monitors for stored configs
    
    When saving and restoring monitor configurations, we must take disabled
    monitors into account, as otherwise one cannot store/restore a
    configuration where one or more monitors are explicitly disabled. Make
    this possible by adding a <disabled> element to the <configure> element
    which lists the monitors that are explicitly disabled. These ones are
    included when generating the configuration key, meaning they'll be
    picked up correctly.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=787629

 backends/gf-logical-monitor-config-private.h |   13 +++--
 backends/gf-logical-monitor-config.c         |   24 ++++++++
 backends/gf-monitor-config-manager.c         |   36 ++++++++-----
 backends/gf-monitor-config-migration.c       |   38 ++++++++++++-
 backends/gf-monitor-config-store.c           |   69 ++++++++++++++++++++++-
 backends/gf-monitor-manager.c                |    4 +-
 backends/gf-monitors-config-private.h        |   10 +++-
 backends/gf-monitors-config.c                |   75 ++++++++++++++++++++++++--
 8 files changed, 237 insertions(+), 32 deletions(-)
---
diff --git a/backends/gf-logical-monitor-config-private.h b/backends/gf-logical-monitor-config-private.h
index 618e9ef..c301822 100644
--- a/backends/gf-logical-monitor-config-private.h
+++ b/backends/gf-logical-monitor-config-private.h
@@ -37,12 +37,15 @@ typedef struct
   gboolean            is_presentation;
 } GfLogicalMonitorConfig;
 
-void     gf_logical_monitor_config_free   (GfLogicalMonitorConfig      *config);
+void     gf_logical_monitor_config_free          (GfLogicalMonitorConfig      *config);
 
-gboolean gf_verify_logical_monitor_config (GfLogicalMonitorConfig      *config,
-                                           GfLogicalMonitorLayoutMode   layout_mode,
-                                           GfMonitorManager            *monitor_manager,
-                                           GError                     **error);
+gboolean gf_logical_monitor_configs_have_monitor (GList                       *logical_monitor_configs,
+                                                  GfMonitorSpec               *monitor_spec);
+
+gboolean gf_verify_logical_monitor_config        (GfLogicalMonitorConfig      *config,
+                                                  GfLogicalMonitorLayoutMode   layout_mode,
+                                                  GfMonitorManager            *monitor_manager,
+                                                  GError                     **error);
 
 G_END_DECLS
 
diff --git a/backends/gf-logical-monitor-config.c b/backends/gf-logical-monitor-config.c
index 6b687ee..975c379 100644
--- a/backends/gf-logical-monitor-config.c
+++ b/backends/gf-logical-monitor-config.c
@@ -25,6 +25,7 @@
 
 #include "gf-logical-monitor-config-private.h"
 #include "gf-monitor-config-private.h"
+#include "gf-monitor-spec-private.h"
 
 void
 gf_logical_monitor_config_free (GfLogicalMonitorConfig *config)
@@ -38,6 +39,29 @@ gf_logical_monitor_config_free (GfLogicalMonitorConfig *config)
 }
 
 gboolean
+gf_logical_monitor_configs_have_monitor (GList         *logical_monitor_configs,
+                                         GfMonitorSpec *monitor_spec)
+{
+  GList *l;
+
+  for (l = logical_monitor_configs; l; l = l->next)
+    {
+      GfLogicalMonitorConfig *logical_monitor_config = l->data;
+      GList *k;
+
+      for (k = logical_monitor_config->monitor_configs; k; k = k->next)
+        {
+          GfMonitorConfig *monitor_config = k->data;
+
+          if (gf_monitor_spec_equals (monitor_spec, monitor_config->monitor_spec))
+            return TRUE;
+        }
+    }
+
+  return FALSE;
+}
+
+gboolean
 gf_verify_logical_monitor_config (GfLogicalMonitorConfig      *config,
                                   GfLogicalMonitorLayoutMode   layout_mode,
                                   GfMonitorManager            *monitor_manager,
diff --git a/backends/gf-monitor-config-manager.c b/backends/gf-monitor-config-manager.c
index 4580dcb..7b0ff4e 100644
--- a/backends/gf-monitor-config-manager.c
+++ b/backends/gf-monitor-config-manager.c
@@ -204,6 +204,7 @@ create_for_switch_config_all_mirror (GfMonitorConfigManager *config_manager)
   GfMonitorManager *monitor_manager = config_manager->monitor_manager;
   GfLogicalMonitorLayoutMode layout_mode;
   GfLogicalMonitorConfig *logical_monitor_config = NULL;
+  GList *logical_monitor_configs;
   GList *monitor_configs = NULL;
   gint common_mode_w = 0, common_mode_h = 0;
   float best_scale = 1.0;
@@ -300,8 +301,10 @@ create_for_switch_config_all_mirror (GfMonitorConfigManager *config_manager)
     .monitor_configs = monitor_configs
   };
 
+  logical_monitor_configs = g_list_append (NULL, logical_monitor_config);
   layout_mode = gf_monitor_manager_get_default_layout_mode (monitor_manager);
-  return gf_monitors_config_new (g_list_append (NULL, logical_monitor_config),
+
+  return gf_monitors_config_new (monitor_manager, logical_monitor_configs,
                                  layout_mode, GF_MONITORS_CONFIG_FLAG_NONE);
 }
 
@@ -339,8 +342,8 @@ create_for_switch_config_external (GfMonitorConfigManager *config_manager)
       x += logical_monitor_config->layout.width;
     }
 
-  return gf_monitors_config_new (logical_monitor_configs, layout_mode,
-                                 GF_MONITORS_CONFIG_FLAG_NONE);
+  return gf_monitors_config_new (monitor_manager, logical_monitor_configs,
+                                 layout_mode, GF_MONITORS_CONFIG_FLAG_NONE);
 }
 
 static GfMonitorsConfig *
@@ -365,8 +368,8 @@ create_for_switch_config_builtin (GfMonitorConfigManager *config_manager)
   primary_logical_monitor_config->is_primary = TRUE;
   logical_monitor_configs = g_list_append (NULL, primary_logical_monitor_config);
 
-  return gf_monitors_config_new (logical_monitor_configs, layout_mode,
-                                 GF_MONITORS_CONFIG_FLAG_NONE);
+  return gf_monitors_config_new (monitor_manager, logical_monitor_configs,
+                                 layout_mode, GF_MONITORS_CONFIG_FLAG_NONE);
 }
 
 static GfMonitorsConfig *
@@ -374,8 +377,11 @@ create_for_builtin_display_rotation (GfMonitorConfigManager *config_manager,
                                      gboolean                rotate,
                                      GfMonitorTransform      transform)
 {
+  GfMonitorManager *monitor_manager = config_manager->monitor_manager;
   GfLogicalMonitorConfig *logical_monitor_config;
   GfLogicalMonitorConfig *current_logical_monitor_config;
+  GList *logical_monitor_configs;
+  GfLogicalMonitorLayoutMode layout_mode;
   GfMonitorConfig *monitor_config;
   GfMonitorConfig *current_monitor_config;
 
@@ -421,9 +427,11 @@ create_for_builtin_display_rotation (GfMonitorConfigManager *config_manager,
       logical_monitor_config->layout.height = temp;
     }
 
-  return gf_monitors_config_new (g_list_append (NULL, logical_monitor_config),
-                                 config_manager->current_config->layout_mode,
-                                 GF_MONITORS_CONFIG_FLAG_NONE);
+  logical_monitor_configs = g_list_append (NULL, logical_monitor_config);
+  layout_mode = config_manager->current_config->layout_mode;
+
+  return gf_monitors_config_new (monitor_manager, logical_monitor_configs,
+                                 layout_mode, GF_MONITORS_CONFIG_FLAG_NONE);
 }
 
 static gboolean
@@ -846,8 +854,8 @@ gf_monitor_config_manager_create_linear (GfMonitorConfigManager *config_manager)
       x += logical_monitor_config->layout.width;
     }
 
-  return gf_monitors_config_new (logical_monitor_configs, layout_mode,
-                                 GF_MONITORS_CONFIG_FLAG_NONE);
+  return gf_monitors_config_new (monitor_manager, logical_monitor_configs,
+                                 layout_mode, GF_MONITORS_CONFIG_FLAG_NONE);
 }
 
 GfMonitorsConfig *
@@ -873,8 +881,8 @@ gf_monitor_config_manager_create_fallback (GfMonitorConfigManager *config_manage
   primary_logical_monitor_config->is_primary = TRUE;
   logical_monitor_configs = g_list_append (NULL, primary_logical_monitor_config);
 
-  return gf_monitors_config_new (logical_monitor_configs, layout_mode,
-                                 GF_MONITORS_CONFIG_FLAG_NONE);
+  return gf_monitors_config_new (monitor_manager, logical_monitor_configs,
+                                 layout_mode, GF_MONITORS_CONFIG_FLAG_NONE);
 }
 
 GfMonitorsConfig *
@@ -945,8 +953,8 @@ gf_monitor_config_manager_create_suggested (GfMonitorConfigManager *config_manag
   if (!logical_monitor_configs)
     return NULL;
 
-  return gf_monitors_config_new (logical_monitor_configs, layout_mode,
-                                 GF_MONITORS_CONFIG_FLAG_NONE);
+  return gf_monitors_config_new (monitor_manager, logical_monitor_configs,
+                                 layout_mode, GF_MONITORS_CONFIG_FLAG_NONE);
 }
 
 GfMonitorsConfig *
diff --git a/backends/gf-monitor-config-migration.c b/backends/gf-monitor-config-migration.c
index f0aaa81..e262060 100644
--- a/backends/gf-monitor-config-migration.c
+++ b/backends/gf-monitor-config-migration.c
@@ -1086,6 +1086,35 @@ generate_config_name (GfLegacyMonitorsConfig *config)
   return key_name;
 }
 
+static GList *
+find_disabled_monitor_specs (GfLegacyMonitorsConfig *legacy_config)
+{
+  GList *disabled_monitors = NULL;
+  guint i;
+
+  for (i = 0; i < legacy_config->n_outputs; i++)
+    {
+      GfOutputKey *output_key = &legacy_config->keys[i];
+      GfOutputConfig *output_config = &legacy_config->outputs[i];
+      GfMonitorSpec *monitor_spec;
+
+      if (output_config->enabled)
+        continue;
+
+      monitor_spec = g_new0 (GfMonitorSpec, 1);
+      *monitor_spec = (GfMonitorSpec) {
+        .connector = output_key->connector,
+        .vendor = output_key->vendor,
+        .product = output_key->product,
+        .serial = output_key->serial
+      };
+
+      disabled_monitors = g_list_prepend (disabled_monitors, monitor_spec);
+    }
+
+  return disabled_monitors;
+}
+
 static void
 migrate_config (gpointer key,
                 gpointer value,
@@ -1096,6 +1125,7 @@ migrate_config (gpointer key,
   GfMonitorManager *monitor_manager;
   GList *logical_monitor_configs;
   GError *error;
+  GList *disabled_monitor_specs;
   GfLogicalMonitorLayoutMode layout_mode;
   GfMonitorsConfig *config;
 
@@ -1120,9 +1150,13 @@ migrate_config (gpointer key,
       return;
     }
 
+  disabled_monitor_specs = find_disabled_monitor_specs (legacy_config);
   layout_mode = GF_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL;
-  config = gf_monitors_config_new (logical_monitor_configs, layout_mode,
-                                   GF_MONITORS_CONFIG_FLAG_MIGRATED);
+
+  config = gf_monitors_config_new_full (logical_monitor_configs,
+                                        disabled_monitor_specs,
+                                        layout_mode,
+                                        GF_MONITORS_CONFIG_FLAG_MIGRATED);
 
   if (!gf_verify_monitors_config (config, monitor_manager, &error))
     {
diff --git a/backends/gf-monitor-config-store.c b/backends/gf-monitor-config-store.c
index ecaf61d..3163856 100644
--- a/backends/gf-monitor-config-store.c
+++ b/backends/gf-monitor-config-store.c
@@ -86,6 +86,14 @@
  *       </monitor>
  *       <presentation>yes</presentation>
  *     </logicalmonitor>
+ *     <disabled>
+ *       <monitorspec>
+ *         <connector>LVDS3</connector>
+ *         <vendor>Vendor C</vendor>
+ *         <product>Product C</product>
+ *         <serial>Serial C</serial>
+ *       </monitorspec>
+ *     </disabled>
  *   </configuration>
  * </monitors>
  */
@@ -142,7 +150,8 @@ typedef enum
   STATE_MONITOR_MODE_HEIGHT,
   STATE_MONITOR_MODE_RATE,
   STATE_MONITOR_MODE_FLAG,
-  STATE_MONITOR_UNDERSCANNING
+  STATE_MONITOR_UNDERSCANNING,
+  STATE_DISABLED
 } ParserState;
 
 typedef struct
@@ -160,6 +169,7 @@ typedef struct
   GfMonitorModeSpec      *current_monitor_mode_spec;
   GfMonitorConfig        *current_monitor_config;
   GfLogicalMonitorConfig *current_logical_monitor_config;
+  GList                  *current_disabled_monitor_specs;
 } ConfigParser;
 
 typedef struct
@@ -262,6 +272,10 @@ handle_start_element (GMarkupParseContext  *context,
 
               parser->state = STATE_MIGRATED;
             }
+          else if (g_str_equal (element_name, "disabled"))
+            {
+              parser->state = STATE_DISABLED;
+            }
           else
             {
               g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
@@ -466,6 +480,22 @@ handle_start_element (GMarkupParseContext  *context,
           return;
         }
 
+      case STATE_DISABLED:
+        {
+          if (!g_str_equal (element_name, "monitorspec"))
+            {
+              g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
+                           "Invalid element '%s' under disabled", element_name);
+              return;
+            }
+
+          parser->current_monitor_spec = g_new0 (GfMonitorSpec, 1);
+          parser->monitor_spec_parent_state = STATE_DISABLED;
+          parser->state = STATE_MONITOR_SPEC;
+
+          return;
+        }
+
       default:
         break;
     }
@@ -540,6 +570,16 @@ finish_monitor_spec (ConfigParser *parser)
           return;
         }
 
+      case STATE_DISABLED:
+        {
+          parser->current_disabled_monitor_specs =
+            g_list_prepend (parser->current_disabled_monitor_specs,
+                            parser->current_monitor_spec);
+          parser->current_monitor_spec = NULL;
+
+          return;
+        }
+
       case STATE_INITIAL:
       case STATE_MONITORS:
       case STATE_CONFIGURATION:
@@ -717,6 +757,14 @@ handle_end_element (GMarkupParseContext  *context,
           return;
         }
 
+      case STATE_DISABLED:
+        {
+          g_assert (g_str_equal (element_name, "disabled"));
+
+          parser->state = STATE_CONFIGURATION;
+          return;
+        }
+
       case STATE_CONFIGURATION:
         {
           GfMonitorConfigStore *store = parser->config_store;
@@ -751,10 +799,12 @@ handle_end_element (GMarkupParseContext  *context,
           if (parser->current_was_migrated)
             config_flags |= GF_MONITORS_CONFIG_FLAG_MIGRATED;
 
-          config = gf_monitors_config_new (parser->current_logical_monitor_configs,
-                                           layout_mode, config_flags);
+          config = gf_monitors_config_new_full (parser->current_logical_monitor_configs,
+                                                parser->current_disabled_monitor_specs,
+                                                layout_mode, config_flags);
 
           parser->current_logical_monitor_configs = NULL;
+          parser->current_disabled_monitor_specs = NULL;
 
           if (!gf_verify_monitors_config (config, store->monitor_manager, error))
             {
@@ -898,6 +948,7 @@ handle_text (GMarkupParseContext  *context,
       case STATE_MONITOR_SPEC:
       case STATE_MONITOR_MODE:
       case STATE_TRANSFORM:
+      case STATE_DISABLED:
         {
           if (!is_all_whitespace (text, text_len))
             g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
@@ -1275,6 +1326,18 @@ generate_config_xml (GfMonitorConfigStore *config_store)
           append_logical_monitor_xml (buffer, config, logical_monitor_config);
         }
 
+      if (config->disabled_monitor_specs)
+        {
+          g_string_append (buffer, "    <disabled>\n");
+          for (l = config->disabled_monitor_specs; l; l = l->next)
+            {
+              GfMonitorSpec *monitor_spec = l->data;
+
+              append_monitor_spec (buffer, monitor_spec, "      ");
+            }
+          g_string_append (buffer, "    </disabled>\n");
+        }
+
       g_string_append (buffer, "  </configuration>\n");
     }
 
diff --git a/backends/gf-monitor-manager.c b/backends/gf-monitor-manager.c
index 01c74b9..ec661ea 100644
--- a/backends/gf-monitor-manager.c
+++ b/backends/gf-monitor-manager.c
@@ -1824,8 +1824,8 @@ gf_monitor_manager_handle_apply_monitors_config (GfDBusDisplayConfig   *skeleton
                                                logical_monitor_config);
     }
 
-  config = gf_monitors_config_new (logical_monitor_configs, layout_mode,
-                                   GF_MONITORS_CONFIG_FLAG_NONE);
+  config = gf_monitors_config_new (manager, logical_monitor_configs,
+                                   layout_mode, GF_MONITORS_CONFIG_FLAG_NONE);
 
   if (!gf_verify_monitors_config (config, manager, &error))
     {
diff --git a/backends/gf-monitors-config-private.h b/backends/gf-monitors-config-private.h
index 065378d..4070bc0 100644
--- a/backends/gf-monitors-config-private.h
+++ b/backends/gf-monitors-config-private.h
@@ -44,6 +44,8 @@ struct _GfMonitorsConfig
   GfMonitorsConfigKey        *key;
   GList                      *logical_monitor_configs;
 
+  GList                      *disabled_monitor_specs;
+
   GfMonitorsConfigFlag        flags;
 
   GfLogicalMonitorLayoutMode  layout_mode;
@@ -53,7 +55,13 @@ struct _GfMonitorsConfig
 G_DECLARE_FINAL_TYPE (GfMonitorsConfig, gf_monitors_config,
                       GF, MONITORS_CONFIG, GObject)
 
-GfMonitorsConfig *gf_monitors_config_new       (GList                       *logical_monitor_configs,
+GfMonitorsConfig *gf_monitors_config_new_full  (GList                       *logical_monitor_configs,
+                                                GList                       *disabled_monitor_specs,
+                                                GfLogicalMonitorLayoutMode   layout_mode,
+                                                GfMonitorsConfigFlag         flags);
+
+GfMonitorsConfig *gf_monitors_config_new       (GfMonitorManager            *monitor_manager,
+                                                GList                       *logical_monitor_configs,
                                                 GfLogicalMonitorLayoutMode   layout_mode,
                                                 GfMonitorsConfigFlag         flags);
 
diff --git a/backends/gf-monitors-config.c b/backends/gf-monitors-config.c
index b88393f..1629030 100644
--- a/backends/gf-monitors-config.c
+++ b/backends/gf-monitors-config.c
@@ -55,8 +55,17 @@ has_adjecent_neighbour (GfMonitorsConfig       *config,
   return FALSE;
 }
 
+static gboolean
+gf_monitors_config_is_monitor_enabled (GfMonitorsConfig *config,
+                                       GfMonitorSpec    *monitor_spec)
+{
+  return gf_logical_monitor_configs_have_monitor (config->logical_monitor_configs,
+                                                  monitor_spec);
+}
+
 static GfMonitorsConfigKey *
-gf_monitors_config_key_new (GList *logical_monitor_configs)
+gf_monitors_config_key_new (GList *logical_monitor_configs,
+                            GList *disabled_monitor_specs)
 {
   GfMonitorsConfigKey *config_key;
   GList *monitor_specs;
@@ -78,6 +87,14 @@ gf_monitors_config_key_new (GList *logical_monitor_configs)
         }
     }
 
+  for (l = disabled_monitor_specs; l; l = l->next)
+    {
+      GfMonitorSpec *monitor_spec = l->data;
+
+      monitor_spec = gf_monitor_spec_clone (monitor_spec);
+      monitor_specs = g_list_prepend (monitor_specs, monitor_spec);
+    }
+
   monitor_specs = g_list_sort (monitor_specs, (GCompareFunc) gf_monitor_spec_compare);
 
   config_key = g_new0 (GfMonitorsConfigKey, 1);
@@ -96,6 +113,8 @@ gf_monitors_config_finalize (GObject *object)
   gf_monitors_config_key_free (config->key);
   g_list_free_full (config->logical_monitor_configs,
                     (GDestroyNotify) gf_logical_monitor_config_free);
+  g_list_free_full (config->disabled_monitor_specs,
+                    (GDestroyNotify) gf_monitor_spec_free);
 
   G_OBJECT_CLASS (gf_monitors_config_parent_class)->finalize (object);
 }
@@ -116,21 +135,55 @@ gf_monitors_config_init (GfMonitorsConfig *config)
 }
 
 GfMonitorsConfig *
-gf_monitors_config_new (GList                      *logical_monitor_configs,
-                        GfLogicalMonitorLayoutMode  layout_mode,
-                        GfMonitorsConfigFlag        flags)
+gf_monitors_config_new_full (GList                      *logical_monitor_configs,
+                             GList                      *disabled_monitor_specs,
+                             GfLogicalMonitorLayoutMode  layout_mode,
+                             GfMonitorsConfigFlag        flags)
 {
   GfMonitorsConfig *config;
 
   config = g_object_new (GF_TYPE_MONITORS_CONFIG, NULL);
   config->logical_monitor_configs = logical_monitor_configs;
-  config->key = gf_monitors_config_key_new (logical_monitor_configs);
+  config->disabled_monitor_specs = disabled_monitor_specs;
+  config->key = gf_monitors_config_key_new (logical_monitor_configs,
+                                            disabled_monitor_specs);
   config->layout_mode = layout_mode;
   config->flags = flags;
 
   return config;
 }
 
+GfMonitorsConfig *
+gf_monitors_config_new (GfMonitorManager           *monitor_manager,
+                        GList                      *logical_monitor_configs,
+                        GfLogicalMonitorLayoutMode  layout_mode,
+                        GfMonitorsConfigFlag        flags)
+{
+  GList *disabled_monitor_specs = NULL;
+  GList *monitors;
+  GList *l;
+
+  monitors = gf_monitor_manager_get_monitors (monitor_manager);
+  for (l = monitors; l; l = l->next)
+    {
+      GfMonitor *monitor = l->data;
+      GfMonitorSpec *monitor_spec;
+
+      monitor_spec = gf_monitor_get_spec (monitor);
+      if (gf_logical_monitor_configs_have_monitor (logical_monitor_configs,
+                                                   monitor_spec))
+        continue;
+
+      disabled_monitor_specs =
+        g_list_prepend (disabled_monitor_specs,
+                        gf_monitor_spec_clone (monitor_spec));
+    }
+
+  return gf_monitors_config_new_full (logical_monitor_configs,
+                                      disabled_monitor_specs,
+                                      layout_mode, flags);
+}
+
 guint
 gf_monitors_config_key_hash (gconstpointer data)
 {
@@ -274,6 +327,18 @@ gf_verify_monitors_config (GfMonitorsConfig  *config,
 
   g_list_free (region);
 
+  for (l = config->disabled_monitor_specs; l; l = l->next)
+    {
+      GfMonitorSpec *monitor_spec = l->data;
+
+      if (gf_monitors_config_is_monitor_enabled (config, monitor_spec))
+        {
+          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                       "Assigned monitor explicitly disabled");
+          return FALSE;
+        }
+    }
+
   if (min_x != 0 || min_y != 0)
     {
       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,


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