[mutter] monitor-config: Keep track of disabled monitors for stored configs



commit ea4dbd14bcc2d814479f5fe3399c5075e251c6a7
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

 src/backends/meta-monitor-config-manager.c   |  135 +++++++++++++++++++++++---
 src/backends/meta-monitor-config-manager.h   |   17 +++-
 src/backends/meta-monitor-config-migration.c |   38 +++++++-
 src/backends/meta-monitor-config-store.c     |   70 +++++++++++++-
 src/backends/meta-monitor-manager.c          |    4 +-
 5 files changed, 241 insertions(+), 23 deletions(-)
---
diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c
index d40c2e0..cdc9fb7 100644
--- a/src/backends/meta-monitor-config-manager.c
+++ b/src/backends/meta-monitor-config-manager.c
@@ -612,7 +612,9 @@ meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_mana
       x += logical_monitor_config->layout.width;
     }
 
-  return meta_monitors_config_new (logical_monitor_configs, layout_mode,
+  return meta_monitors_config_new (monitor_manager,
+                                   logical_monitor_configs,
+                                   layout_mode,
                                    META_MONITORS_CONFIG_FLAG_NONE);
 }
 
@@ -641,7 +643,9 @@ meta_monitor_config_manager_create_fallback (MetaMonitorConfigManager *config_ma
   logical_monitor_configs = g_list_append (NULL,
                                            primary_logical_monitor_config);
 
-  return meta_monitors_config_new (logical_monitor_configs, layout_mode,
+  return meta_monitors_config_new (monitor_manager,
+                                   logical_monitor_configs,
+                                   layout_mode,
                                    META_MONITORS_CONFIG_FLAG_NONE);
 }
 
@@ -717,7 +721,9 @@ meta_monitor_config_manager_create_suggested (MetaMonitorConfigManager *config_m
   if (!logical_monitor_configs)
     return NULL;
 
-  return meta_monitors_config_new (logical_monitor_configs, layout_mode,
+  return meta_monitors_config_new (monitor_manager,
+                                   logical_monitor_configs,
+                                   layout_mode,
                                    META_MONITORS_CONFIG_FLAG_NONE);
 }
 
@@ -726,8 +732,11 @@ create_for_builtin_display_rotation (MetaMonitorConfigManager *config_manager,
                                      gboolean                  rotate,
                                      MetaMonitorTransform      transform)
 {
+  MetaMonitorManager *monitor_manager = config_manager->monitor_manager;
   MetaLogicalMonitorConfig *logical_monitor_config;
   MetaLogicalMonitorConfig *current_logical_monitor_config;
+  GList *logical_monitor_configs;
+  MetaLogicalMonitorLayoutMode layout_mode;
   MetaMonitorConfig *monitor_config;
   MetaMonitorConfig *current_monitor_config;
 
@@ -772,8 +781,11 @@ create_for_builtin_display_rotation (MetaMonitorConfigManager *config_manager,
       logical_monitor_config->layout.height = temp;
     }
 
-  return meta_monitors_config_new (g_list_append (NULL, logical_monitor_config),
-                                   config_manager->current_config->layout_mode,
+  logical_monitor_configs = g_list_append (NULL, logical_monitor_config);
+  layout_mode = config_manager->current_config->layout_mode;
+  return meta_monitors_config_new (monitor_manager,
+                                   logical_monitor_configs,
+                                   layout_mode,
                                    META_MONITORS_CONFIG_FLAG_NONE);
 }
 
@@ -796,6 +808,7 @@ create_for_switch_config_all_mirror (MetaMonitorConfigManager *config_manager)
   MetaMonitorManager *monitor_manager = config_manager->monitor_manager;
   MetaLogicalMonitorLayoutMode layout_mode;
   MetaLogicalMonitorConfig *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;
@@ -893,8 +906,10 @@ create_for_switch_config_all_mirror (MetaMonitorConfigManager *config_manager)
     .monitor_configs = monitor_configs
   };
 
+  logical_monitor_configs = g_list_append (NULL, logical_monitor_config);
   layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager);
-  return meta_monitors_config_new (g_list_append (NULL, logical_monitor_config),
+  return meta_monitors_config_new (monitor_manager,
+                                   logical_monitor_configs,
                                    layout_mode,
                                    META_MONITORS_CONFIG_FLAG_NONE);
 }
@@ -935,7 +950,9 @@ create_for_switch_config_external (MetaMonitorConfigManager *config_manager)
       x += logical_monitor_config->layout.width;
     }
 
-  return meta_monitors_config_new (logical_monitor_configs, layout_mode,
+  return meta_monitors_config_new (monitor_manager,
+                                   logical_monitor_configs,
+                                   layout_mode,
                                    META_MONITORS_CONFIG_FLAG_NONE);
 }
 
@@ -964,7 +981,9 @@ create_for_switch_config_builtin (MetaMonitorConfigManager *config_manager)
   logical_monitor_configs = g_list_append (NULL,
                                            primary_logical_monitor_config);
 
-  return meta_monitors_config_new (logical_monitor_configs, layout_mode,
+  return meta_monitors_config_new (monitor_manager,
+                                   logical_monitor_configs,
+                                   layout_mode,
                                    META_MONITORS_CONFIG_FLAG_NONE);
 }
 
@@ -1087,7 +1106,8 @@ meta_logical_monitor_config_free (MetaLogicalMonitorConfig *logical_monitor_conf
 }
 
 static MetaMonitorsConfigKey *
-meta_monitors_config_key_new (GList *logical_monitor_configs)
+meta_monitors_config_key_new (GList *logical_monitor_configs,
+                              GList *disabled_monitor_specs)
 {
   MetaMonitorsConfigKey *config_key;
   GList *monitor_specs;
@@ -1109,6 +1129,14 @@ meta_monitors_config_key_new (GList *logical_monitor_configs)
         }
     }
 
+  for (l = disabled_monitor_specs; l; l = l->next)
+    {
+      MetaMonitorSpec *monitor_spec = l->data;
+
+      monitor_spec = meta_monitor_spec_clone (monitor_spec);
+      monitor_specs = g_list_prepend (monitor_specs, monitor_spec);
+    }
+
   monitor_specs = g_list_sort (monitor_specs,
                                (GCompareFunc) meta_monitor_spec_compare);
 
@@ -1175,21 +1203,56 @@ meta_monitors_config_key_equal (gconstpointer data_a,
 }
 
 MetaMonitorsConfig *
-meta_monitors_config_new (GList                       *logical_monitor_configs,
-                          MetaLogicalMonitorLayoutMode layout_mode,
-                          MetaMonitorsConfigFlag       flags)
+meta_monitors_config_new_full (GList                        *logical_monitor_configs,
+                               GList                        *disabled_monitor_specs,
+                               MetaLogicalMonitorLayoutMode  layout_mode,
+                               MetaMonitorsConfigFlag        flags)
 {
   MetaMonitorsConfig *config;
 
   config = g_object_new (META_TYPE_MONITORS_CONFIG, NULL);
   config->logical_monitor_configs = logical_monitor_configs;
-  config->key = meta_monitors_config_key_new (logical_monitor_configs);
+  config->disabled_monitor_specs = disabled_monitor_specs;
+  config->key = meta_monitors_config_key_new (logical_monitor_configs,
+                                              disabled_monitor_specs);
   config->layout_mode = layout_mode;
   config->flags = flags;
 
   return config;
 }
 
+MetaMonitorsConfig *
+meta_monitors_config_new (MetaMonitorManager           *monitor_manager,
+                          GList                        *logical_monitor_configs,
+                          MetaLogicalMonitorLayoutMode  layout_mode,
+                          MetaMonitorsConfigFlag        flags)
+{
+  GList *disabled_monitor_specs = NULL;
+  GList *monitors;
+  GList *l;
+
+  monitors = meta_monitor_manager_get_monitors (monitor_manager);
+  for (l = monitors; l; l = l->next)
+    {
+      MetaMonitor *monitor = l->data;
+      MetaMonitorSpec *monitor_spec;
+
+      monitor_spec = meta_monitor_get_spec (monitor);
+      if (meta_logical_monitor_configs_have_monitor (logical_monitor_configs,
+                                                     monitor_spec))
+        continue;
+
+      disabled_monitor_specs =
+        g_list_prepend (disabled_monitor_specs,
+                        meta_monitor_spec_clone (monitor_spec));
+    }
+
+  return meta_monitors_config_new_full (logical_monitor_configs,
+                                        disabled_monitor_specs,
+                                        layout_mode,
+                                        flags);
+}
+
 static void
 meta_monitors_config_finalize (GObject *object)
 {
@@ -1198,6 +1261,8 @@ meta_monitors_config_finalize (GObject *object)
   meta_monitors_config_key_free (config->key);
   g_list_free_full (config->logical_monitor_configs,
                     (GDestroyNotify) meta_logical_monitor_config_free);
+  g_list_free_full (config->disabled_monitor_specs,
+                    (GDestroyNotify) meta_monitor_spec_free);
 
   G_OBJECT_CLASS (meta_monitors_config_parent_class)->finalize (object);
 }
@@ -1376,6 +1441,38 @@ has_adjecent_neighbour (MetaMonitorsConfig       *config,
 }
 
 gboolean
+meta_logical_monitor_configs_have_monitor (GList           *logical_monitor_configs,
+                                           MetaMonitorSpec *monitor_spec)
+{
+  GList *l;
+
+  for (l = logical_monitor_configs; l; l = l->next)
+    {
+      MetaLogicalMonitorConfig *logical_monitor_config = l->data;
+      GList *k;
+
+      for (k = logical_monitor_config->monitor_configs; k; k = k->next)
+        {
+          MetaMonitorConfig *monitor_config = k->data;
+
+          if (meta_monitor_spec_equals (monitor_spec,
+                                        monitor_config->monitor_spec))
+            return TRUE;
+        }
+    }
+
+  return FALSE;
+}
+
+static gboolean
+meta_monitors_config_is_monitor_enabled (MetaMonitorsConfig *config,
+                                         MetaMonitorSpec    *monitor_spec)
+{
+  return meta_logical_monitor_configs_have_monitor (config->logical_monitor_configs,
+                                                    monitor_spec);
+}
+
+gboolean
 meta_verify_monitors_config (MetaMonitorsConfig *config,
                              MetaMonitorManager *monitor_manager,
                              GError            **error)
@@ -1456,6 +1553,18 @@ meta_verify_monitors_config (MetaMonitorsConfig *config,
 
   g_list_free (region);
 
+  for (l = config->disabled_monitor_specs; l; l = l->next)
+    {
+      MetaMonitorSpec *monitor_spec = l->data;
+
+      if (meta_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,
diff --git a/src/backends/meta-monitor-config-manager.h b/src/backends/meta-monitor-config-manager.h
index 04501ee..b99cdab 100644
--- a/src/backends/meta-monitor-config-manager.h
+++ b/src/backends/meta-monitor-config-manager.h
@@ -64,6 +64,8 @@ struct _MetaMonitorsConfig
   MetaMonitorsConfigKey *key;
   GList *logical_monitor_configs;
 
+  GList *disabled_monitor_specs;
+
   MetaMonitorsConfigFlag flags;
 
   MetaLogicalMonitorLayoutMode layout_mode;
@@ -112,9 +114,15 @@ void meta_monitor_config_manager_clear_history (MetaMonitorConfigManager *config
 
 void meta_monitor_config_manager_save_current (MetaMonitorConfigManager *config_manager);
 
-MetaMonitorsConfig * meta_monitors_config_new (GList                       *logical_monitor_configs,
-                                               MetaLogicalMonitorLayoutMode layout_mode,
-                                               MetaMonitorsConfigFlag       flags);
+MetaMonitorsConfig * meta_monitors_config_new_full (GList                        *logical_monitor_configs,
+                                                    GList                        *disabled_monitors,
+                                                    MetaLogicalMonitorLayoutMode  layout_mode,
+                                                    MetaMonitorsConfigFlag        flags);
+
+MetaMonitorsConfig * meta_monitors_config_new (MetaMonitorManager           *monitor_manager,
+                                               GList                        *logical_monitor_configs,
+                                               MetaLogicalMonitorLayoutMode  layout_mode,
+                                               MetaMonitorsConfigFlag        flags);
 
 unsigned int meta_monitors_config_key_hash (gconstpointer config_key);
 
@@ -127,6 +135,9 @@ void meta_logical_monitor_config_free (MetaLogicalMonitorConfig *logical_monitor
 
 void meta_monitor_config_free (MetaMonitorConfig *monitor_config);
 
+gboolean meta_logical_monitor_configs_have_monitor (GList           *logical_monitor_configs,
+                                                    MetaMonitorSpec *monitor_spec);
+
 gboolean meta_verify_monitor_mode_spec (MetaMonitorModeSpec *monitor_mode_spec,
                                         GError             **error);
 
diff --git a/src/backends/meta-monitor-config-migration.c b/src/backends/meta-monitor-config-migration.c
index 6164d9f..c862168 100644
--- a/src/backends/meta-monitor-config-migration.c
+++ b/src/backends/meta-monitor-config-migration.c
@@ -1056,6 +1056,35 @@ generate_config_name (MetaLegacyMonitorsConfig *config)
   return key_name;
 }
 
+static GList *
+find_disabled_monitor_specs (MetaLegacyMonitorsConfig *legacy_config)
+{
+  GList *disabled_monitors = NULL;
+  unsigned int i;
+
+  for (i = 0; i < legacy_config->n_outputs; i++)
+    {
+      MetaOutputKey *output_key = &legacy_config->keys[i];
+      MetaOutputConfig *output_config = &legacy_config->outputs[i];
+      MetaMonitorSpec *monitor_spec;
+
+      if (output_config->enabled)
+        continue;
+
+      monitor_spec = g_new0 (MetaMonitorSpec, 1);
+      *monitor_spec = (MetaMonitorSpec) {
+        .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,
@@ -1068,6 +1097,7 @@ migrate_config (gpointer key,
   GList *logical_monitor_configs;
   MetaLogicalMonitorLayoutMode layout_mode;
   GError *error = NULL;
+  GList *disabled_monitor_specs;
   MetaMonitorsConfig *config;
 
   logical_monitor_configs = derive_logical_monitor_configs (legacy_config,
@@ -1083,9 +1113,13 @@ migrate_config (gpointer key,
       return;
     }
 
+  disabled_monitor_specs = find_disabled_monitor_specs (legacy_config);
+
   layout_mode = META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL;
-  config = meta_monitors_config_new (logical_monitor_configs, layout_mode,
-                                     META_MONITORS_CONFIG_FLAG_MIGRATED);
+  config = meta_monitors_config_new_full (logical_monitor_configs,
+                                          disabled_monitor_specs,
+                                          layout_mode,
+                                          META_MONITORS_CONFIG_FLAG_MIGRATED);
   if (!meta_verify_monitors_config (config, monitor_manager, &error))
     {
       g_autofree char *config_name = NULL;
diff --git a/src/backends/meta-monitor-config-store.c b/src/backends/meta-monitor-config-store.c
index 351cb65..ed0ce34 100644
--- a/src/backends/meta-monitor-config-store.c
+++ b/src/backends/meta-monitor-config-store.c
@@ -83,6 +83,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>
  *
@@ -151,7 +159,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
@@ -169,6 +178,7 @@ typedef struct
   MetaMonitorModeSpec *current_monitor_mode_spec;
   MetaMonitorConfig *current_monitor_config;
   MetaLogicalMonitorConfig *current_logical_monitor_config;
+  GList *current_disabled_monitor_specs;
 } ConfigParser;
 
 G_DEFINE_TYPE (MetaMonitorConfigStore, meta_monitor_config_store,
@@ -256,6 +266,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,
@@ -458,6 +472,22 @@ handle_start_element (GMarkupParseContext  *context,
                      "Invalid element '%s' under underscanning", element_name);
         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 (MetaMonitorSpec, 1);
+        parser->monitor_spec_parent_state = STATE_DISABLED;
+        parser->state = STATE_MONITOR_SPEC;
+
+        return;
+      }
     }
 }
 
@@ -528,6 +558,15 @@ 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;
+      }
 
     default:
       g_assert_not_reached ();
@@ -684,6 +723,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:
       {
         MetaMonitorConfigStore *store = parser->config_store;
@@ -720,11 +767,13 @@ handle_end_element (GMarkupParseContext  *context,
           config_flags |= META_MONITORS_CONFIG_FLAG_MIGRATED;
 
         config =
-          meta_monitors_config_new (parser->current_logical_monitor_configs,
-                                    layout_mode,
-                                    config_flags);
+          meta_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 (!meta_verify_monitors_config (config, store->monitor_manager,
                                           error))
@@ -868,6 +917,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,
@@ -1236,6 +1286,18 @@ generate_config_xml (MetaMonitorConfigStore *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)
+            {
+              MetaMonitorSpec *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/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c
index 3e0d980..2caec1b 100644
--- a/src/backends/meta-monitor-manager.c
+++ b/src/backends/meta-monitor-manager.c
@@ -1934,7 +1934,9 @@ meta_monitor_manager_handle_apply_monitors_config (MetaDBusDisplayConfig *skelet
                                                logical_monitor_config);
     }
 
-  config = meta_monitors_config_new (logical_monitor_configs, layout_mode,
+  config = meta_monitors_config_new (manager,
+                                     logical_monitor_configs,
+                                     layout_mode,
                                      META_MONITORS_CONFIG_FLAG_NONE);
   if (!meta_verify_monitors_config (config, manager, &error))
     {


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