[mutter] DisplayConfig: Specify mode ID string instead of mode spec



commit 859b01fc39afd1f7cfad8f4d60853c4180b82ac3
Author: Jonas Ådahl <jadahl gmail com>
Date:   Wed Jun 14 12:04:09 2017 +0800

    DisplayConfig: Specify mode ID string instead of mode spec
    
    To be able to add more modes types that happen to have the same
    resolution and refresh rate, change the API to specify modes using an
    ID string. The ID string is temporary, and only works for associating a
    mode for the monitor instance that it was part of.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=765011

 src/backends/meta-monitor-manager.c    |   75 ++++++++++++-----------
 src/backends/meta-monitor.c            |  100 +++++++++++++++++++++++++++-----
 src/backends/meta-monitor.h            |    5 ++
 src/org.gnome.Mutter.DisplayConfig.xml |   12 ++--
 4 files changed, 135 insertions(+), 57 deletions(-)
---
diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c
index 099a48e..1cccebc 100644
--- a/src/backends/meta-monitor-manager.c
+++ b/src/backends/meta-monitor-manager.c
@@ -1492,7 +1492,7 @@ meta_monitor_manager_legacy_handle_apply_configuration  (MetaDBusDisplayConfig *
 #define META_DISPLAY_CONFIG_MODE_FLAGS_PREFERRED (1 << 0)
 #define META_DISPLAY_CONFIG_MODE_FLAGS_CURRENT (1 << 1)
 
-#define MODE_FORMAT "(iiddadu)"
+#define MODE_FORMAT "(siiddadu)"
 #define MODES_FORMAT "a" MODE_FORMAT
 #define MONITOR_SPEC_FORMAT "(ssss)"
 #define MONITOR_FORMAT "(" MONITOR_SPEC_FORMAT MODES_FORMAT "a{sv})"
@@ -1549,13 +1549,19 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton,
         {
           MetaMonitorMode *monitor_mode = k->data;
           GVariantBuilder supported_scales_builder;
-          MetaMonitorModeSpec *monitor_mode_spec;
+          const char *mode_id;
+          int mode_width, mode_height;
+          float refresh_rate;
           float preferred_scale;
           float *supported_scales;
           int n_supported_scales;
           uint32_t flags = 0;
 
-          monitor_mode_spec = meta_monitor_mode_get_spec (monitor_mode);
+          mode_id = meta_monitor_mode_get_id (monitor_mode);
+          meta_monitor_mode_get_resolution (monitor_mode,
+                                            &mode_width, &mode_height);
+          refresh_rate = meta_monitor_mode_get_refresh_rate (monitor_mode);
+
           preferred_scale =
             meta_monitor_manager_calculate_monitor_mode_scale (manager,
                                                                monitor,
@@ -1580,9 +1586,10 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton,
             flags |= META_DISPLAY_CONFIG_MODE_FLAGS_PREFERRED;
 
           g_variant_builder_add (&modes_builder, MODE_FORMAT,
-                                 monitor_mode_spec->width,
-                                 monitor_mode_spec->height,
-                                 monitor_mode_spec->refresh_rate,
+                                 mode_id,
+                                 mode_width,
+                                 mode_height,
+                                 refresh_rate,
                                  (double) preferred_scale,
                                  &supported_scales_builder,
                                  flags);
@@ -1797,13 +1804,16 @@ meta_monitor_manager_is_config_applicable (MetaMonitorManager *manager,
   return TRUE;
 }
 
-static MetaMonitorSpec *
-find_monitor_spec (MetaMonitorManager *manager,
-                   char               *connector)
+static MetaMonitor *
+find_monitor_from_connector (MetaMonitorManager *manager,
+                             char               *connector)
 {
   GList *monitors;
   GList *l;
 
+  if (!connector)
+    return NULL;
+
   monitors = meta_monitor_manager_get_monitors (manager);
   for (l = monitors; l; l = l->next)
     {
@@ -1811,14 +1821,13 @@ find_monitor_spec (MetaMonitorManager *manager,
       MetaMonitorSpec *monitor_spec = meta_monitor_get_spec (monitor);
 
       if (g_str_equal (connector, monitor_spec->connector))
-        return meta_monitor_spec_clone (monitor_spec);
+        return monitor;
     }
 
   return NULL;
 }
 
-#define MONITOR_MODE_SPEC_FORMAT "(iid)"
-#define MONITOR_CONFIG_FORMAT "(s" MONITOR_MODE_SPEC_FORMAT "a{sv})"
+#define MONITOR_CONFIG_FORMAT "(ssa{sv})"
 #define MONITOR_CONFIGS_FORMAT "a" MONITOR_CONFIG_FORMAT
 
 #define LOGICAL_MONITOR_CONFIG_FORMAT "(iidub" MONITOR_CONFIGS_FORMAT ")"
@@ -1830,49 +1839,43 @@ create_monitor_config_from_variant (MetaMonitorManager *manager,
 {
 
   MetaMonitorConfig *monitor_config = NULL;
-  char *connector;
+  g_autofree char *connector = NULL;
+  g_autofree char *mode_id = NULL;
+  MetaMonitorMode *monitor_mode;
+  MetaMonitor *monitor;
   MetaMonitorSpec *monitor_spec;
   MetaMonitorModeSpec *monitor_mode_spec;
-  GVariant *properties_variant = NULL;
+  g_autoptr (GVariant) properties_variant = NULL;
   gboolean enable_underscanning = FALSE;
-  int32_t mode_width;
-  int32_t mode_height;
-  double mode_refresh_rate;
-
-  monitor_spec = g_new0 (MetaMonitorSpec, 1);
-  monitor_mode_spec = g_new0 (MetaMonitorModeSpec, 1);
 
-  g_variant_get (monitor_config_variant, "(s" MONITOR_MODE_SPEC_FORMAT "@a{sv})",
+  g_variant_get (monitor_config_variant, "(ss@a{sv})",
                  &connector,
-                 &mode_width,
-                 &mode_height,
-                 &mode_refresh_rate,
+                 &mode_id,
                  &properties_variant);
 
-  *monitor_mode_spec = (MetaMonitorModeSpec) {
-    .width = mode_width,
-    .height = mode_height,
-    .refresh_rate = mode_refresh_rate
-  };
-
-  monitor_spec = find_monitor_spec (manager, connector);
-  if (!monitor_spec)
+  monitor = find_monitor_from_connector (manager, connector);
+  if (!monitor)
     {
       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                    "Invalid connector '%s' specified", connector);
-      g_free (monitor_mode_spec);
       return NULL;
     }
 
-  if (!meta_verify_monitor_mode_spec (monitor_mode_spec, error))
+  monitor_mode = meta_monitor_get_mode_from_id (monitor, mode_id);
+  if (!monitor_mode)
     {
-      g_free (monitor_mode_spec);
-      meta_monitor_spec_free (monitor_spec);
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                   "Invalid mode '%s' specified", mode_id);
       return NULL;
     }
 
   g_variant_lookup (properties_variant, "underscanning", "b", &enable_underscanning);
 
+  monitor_spec = meta_monitor_spec_clone (meta_monitor_get_spec (monitor));
+
+  monitor_mode_spec = g_new0 (MetaMonitorModeSpec, 1);
+  *monitor_mode_spec = *meta_monitor_mode_get_spec (monitor_mode);
+
   monitor_config = g_new0 (MetaMonitorConfig, 1);
   *monitor_config = (MetaMonitorConfig) {
     .monitor_spec = monitor_spec,
diff --git a/src/backends/meta-monitor.c b/src/backends/meta-monitor.c
index d86cea1..ba12a13 100644
--- a/src/backends/meta-monitor.c
+++ b/src/backends/meta-monitor.c
@@ -33,6 +33,7 @@
 
 typedef struct _MetaMonitorMode
 {
+  char *id;
   MetaMonitorModeSpec spec;
   MetaMonitorCrtcMode *crtc_modes;
 } MetaMonitorMode;
@@ -50,6 +51,7 @@ typedef struct _MetaMonitorPrivate
 
   GList *outputs;
   GList *modes;
+  GHashTable *mode_ids;
 
   MetaMonitorMode *preferred_mode;
   MetaMonitorMode *current_mode;
@@ -333,6 +335,7 @@ meta_monitor_finalize (GObject *object)
   MetaMonitor *monitor = META_MONITOR (object);
   MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
 
+  g_hash_table_destroy (priv->mode_ids);
   g_list_free_full (priv->modes, (GDestroyNotify) meta_monitor_mode_free);
   g_clear_pointer (&priv->outputs, g_list_free);
   meta_monitor_spec_free (priv->spec);
@@ -341,6 +344,9 @@ meta_monitor_finalize (GObject *object)
 static void
 meta_monitor_init (MetaMonitor *monitor)
 {
+  MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
+
+  priv->mode_ids = g_hash_table_new (g_str_hash, g_str_equal);
 }
 
 static void
@@ -351,6 +357,36 @@ meta_monitor_class_init (MetaMonitorClass *klass)
   object_class->finalize = meta_monitor_finalize;
 }
 
+static char *
+generate_mode_id (MetaMonitorModeSpec *monitor_mode_spec)
+{
+  char refresh_rate_str[G_ASCII_DTOSTR_BUF_SIZE];
+
+  g_ascii_dtostr (refresh_rate_str, G_ASCII_DTOSTR_BUF_SIZE,
+                  monitor_mode_spec->refresh_rate);
+
+  return g_strdup_printf ("%dx%d@%s",
+                          monitor_mode_spec->width,
+                          monitor_mode_spec->height,
+                          refresh_rate_str);
+}
+
+static gboolean
+meta_monitor_add_mode (MetaMonitor     *monitor,
+                       MetaMonitorMode *monitor_mode)
+{
+  MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
+
+  if (g_hash_table_lookup (priv->mode_ids,
+                           meta_monitor_mode_get_id (monitor_mode)))
+    return FALSE;
+
+  priv->modes = g_list_append (priv->modes, monitor_mode);
+  g_hash_table_insert (priv->mode_ids, monitor_mode->id, monitor_mode);
+
+  return TRUE;
+}
+
 static void
 meta_monitor_normal_generate_modes (MetaMonitorNormal *monitor_normal)
 {
@@ -372,6 +408,7 @@ meta_monitor_normal_generate_modes (MetaMonitorNormal *monitor_normal)
         .height = crtc_mode->height,
         .refresh_rate = crtc_mode->refresh_rate
       },
+      mode->id = generate_mode_id (&mode->spec);
       mode->crtc_modes = g_new (MetaMonitorCrtcMode, 1);
       mode->crtc_modes[0] = (MetaMonitorCrtcMode) {
         .output = output,
@@ -383,7 +420,8 @@ meta_monitor_normal_generate_modes (MetaMonitorNormal *monitor_normal)
       if (output->crtc && crtc_mode == output->crtc->current_mode)
         monitor_priv->current_mode = mode;
 
-      monitor_priv->modes = g_list_append (monitor_priv->modes, mode);
+      if (!meta_monitor_add_mode (monitor, mode))
+        meta_monitor_mode_free (mode);
     }
 }
 
@@ -671,15 +709,22 @@ create_tiled_monitor_mode (MetaMonitorTiled *monitor_tiled,
   MetaMonitorPrivate *monitor_priv =
     meta_monitor_get_instance_private (monitor);
   MetaMonitorModeTiled *mode;
+  int width, height;
   GList *l;
   unsigned int i;
   gboolean is_preferred = TRUE;
 
   mode = g_new0 (MetaMonitorModeTiled, 1);
   mode->is_tiled = TRUE;
-  meta_monitor_tiled_calculate_tiled_size (monitor,
-                                           &mode->parent.spec.width,
-                                           &mode->parent.spec.height);
+  meta_monitor_tiled_calculate_tiled_size (monitor, &width, &height);
+
+  mode->parent.spec = (MetaMonitorModeSpec) {
+    .width = width,
+    .height = height,
+    .refresh_rate = refresh_rate,
+  };
+  mode->parent.id = generate_mode_id (&mode->parent.spec);
+
   mode->parent.crtc_modes = g_new0 (MetaMonitorCrtcMode,
                                     g_list_length (monitor_priv->outputs));
   for (l = monitor_priv->outputs, i = 0; l; l = l->next, i++)
@@ -701,8 +746,6 @@ create_tiled_monitor_mode (MetaMonitorTiled *monitor_tiled,
         .crtc_mode = tiled_crtc_mode
       };
 
-      mode->parent.spec.refresh_rate = refresh_rate;
-
       is_preferred = is_preferred && tiled_crtc_mode == output->preferred_mode;
     }
 
@@ -720,6 +763,8 @@ generate_tiled_monitor_modes (MetaMonitorTiled *monitor_tiled)
   MetaOutput *main_output;
   GList *tiled_modes = NULL;
   unsigned int i;
+  MetaMonitorMode *best_mode = NULL;
+  GList *l;
 
   main_output = meta_monitor_get_main_output (META_MONITOR (monitor_tiled));
 
@@ -746,24 +791,28 @@ generate_tiled_monitor_modes (MetaMonitorTiled *monitor_tiled)
         monitor_priv->preferred_mode = mode;
     }
 
-  if (!monitor_priv->preferred_mode)
+  while ((l = tiled_modes))
     {
-      MetaMonitorMode *best_mode = NULL;
-      GList *l;
+      MetaMonitorMode *mode = l->data;
+
+      tiled_modes = g_list_remove_link (tiled_modes, l);
 
-      for (l = tiled_modes; l; l = l->next)
+      if (!meta_monitor_add_mode (monitor, mode))
         {
-          MetaMonitorMode *mode = l->data;
+          meta_monitor_mode_free (mode);
+          continue;
+        }
 
+      if (!monitor_priv->preferred_mode)
+        {
           if (!best_mode ||
               mode->spec.refresh_rate > best_mode->spec.refresh_rate)
             best_mode = mode;
         }
-
-      monitor_priv->preferred_mode = best_mode;
     }
 
-  monitor_priv->modes = g_list_concat (monitor_priv->modes, tiled_modes);
+  if (best_mode)
+    monitor_priv->preferred_mode = best_mode;
 }
 
 static MetaMonitorMode *
@@ -789,6 +838,7 @@ create_untiled_monitor_mode (MetaMonitorTiled *monitor_tiled,
     .height = crtc_mode->height,
     .refresh_rate = crtc_mode->refresh_rate
   };
+  mode->parent.id = generate_mode_id (&mode->parent.spec);
   mode->parent.crtc_modes = g_new0 (MetaMonitorCrtcMode,
                              g_list_length (monitor_priv->outputs));
 
@@ -888,7 +938,11 @@ generate_untiled_monitor_modes (MetaMonitorTiled *monitor_tiled)
       if (!mode)
         continue;
 
-      monitor_priv->modes = g_list_append (monitor_priv->modes, mode);
+      if (!meta_monitor_add_mode (monitor, mode))
+        {
+          meta_monitor_mode_free (mode);
+          continue;
+        }
 
       if (is_monitor_mode_assigned (monitor, mode))
         {
@@ -1130,6 +1184,7 @@ meta_monitor_tiled_class_init (MetaMonitorTiledClass *klass)
 static void
 meta_monitor_mode_free (MetaMonitorMode *monitor_mode)
 {
+  g_free (monitor_mode->id);
   g_free (monitor_mode->crtc_modes);
   g_free (monitor_mode);
 }
@@ -1153,6 +1208,15 @@ meta_monitor_get_logical_monitor (MetaMonitor *monitor)
     return NULL;
 }
 
+MetaMonitorMode *
+meta_monitor_get_mode_from_id (MetaMonitor *monitor,
+                               const char  *monitor_mode_id)
+{
+  MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
+
+  return g_hash_table_lookup (priv->mode_ids, monitor_mode_id);
+}
+
 static gboolean
 meta_monitor_mode_spec_equals (MetaMonitorModeSpec *monitor_mode_spec,
                                MetaMonitorModeSpec *other_monitor_mode_spec)
@@ -1458,6 +1522,12 @@ meta_monitor_mode_get_spec (MetaMonitorMode *monitor_mode)
   return &monitor_mode->spec;
 }
 
+const char *
+meta_monitor_mode_get_id (MetaMonitorMode *monitor_mode)
+{
+  return monitor_mode->id;
+}
+
 void
 meta_monitor_mode_get_resolution (MetaMonitorMode *monitor_mode,
                                   int             *width,
diff --git a/src/backends/meta-monitor.h b/src/backends/meta-monitor.h
index 3e40a9d..7390361 100644
--- a/src/backends/meta-monitor.h
+++ b/src/backends/meta-monitor.h
@@ -145,6 +145,9 @@ gboolean meta_monitor_get_suggested_position (MetaMonitor *monitor,
 
 MetaLogicalMonitor * meta_monitor_get_logical_monitor (MetaMonitor *monitor);
 
+MetaMonitorMode * meta_monitor_get_mode_from_id (MetaMonitor *monitor,
+                                                 const char  *monitor_mode_id);
+
 MetaMonitorMode * meta_monitor_get_mode_from_spec (MetaMonitor         *monitor,
                                                    MetaMonitorModeSpec *monitor_mode_spec);
 
@@ -174,6 +177,8 @@ float * meta_monitor_calculate_supported_scales (MetaMonitor                *mon
                                                  MetaMonitorScalesConstraint constraints,
                                                  int                        *n_supported_scales);
 
+const char * meta_monitor_mode_get_id (MetaMonitorMode *monitor_mode);
+
 MetaMonitorModeSpec * meta_monitor_mode_get_spec (MetaMonitorMode *monitor_mode);
 
 void meta_monitor_mode_get_resolution (MetaMonitorMode *monitor_mode,
diff --git a/src/org.gnome.Mutter.DisplayConfig.xml b/src/org.gnome.Mutter.DisplayConfig.xml
index 62b8265..befd685 100644
--- a/src/org.gnome.Mutter.DisplayConfig.xml
+++ b/src/org.gnome.Mutter.DisplayConfig.xml
@@ -315,7 +315,8 @@
        * s vendor: vendor name
        * s product: product name
        * s serial: product serial
-       * a(iiddadu) modes: available modes
+       * a(siiddad) modes: available modes
+           * s id: mode ID
            * i width: width in physical pixels
            * i height: height in physical pixels
            * d refresh rate: refresh rate
@@ -404,7 +405,7 @@
     -->
     <method name="GetCurrentState">
       <arg name="serial" direction="out" type="u" />
-      <arg name="monitors" direction="out" type="a((ssss)a(iiddadu)a{sv})" />
+      <arg name="monitors" direction="out" type="a((ssss)a(siiddadu)a{sv})" />
       <arg name="logical_monitors" direction="out" type="a(iiduba(ssss)a{sv})" />
       <arg name="properties" direction="out" type="a{sv}" />
     </method>
@@ -431,10 +432,9 @@
        * d: scale
        * u: transform (see GetCurrentState)
        * b primary: true if this is the primary logical monitor
-       * a(siida{sv}): a list of monitors, each consisting of:
+       * a(ssa{sv}): a list of monitors, each consisting of:
            * s: connector
-           * (iid): monitor mode spec (resolution width, resolution height,
-                    refresh rate)
+           * s: monitor mode ID
            * a{sv}: monitor properties, including:
                - "enable_underscanning" (b): enable monitor underscanning;
                                              may only be set when underscanning
@@ -450,7 +450,7 @@
     <method name="ApplyMonitorsConfig">
       <arg name="serial" direction="in" type="u" />
       <arg name="method" direction="in" type="u" />
-      <arg name="logical_monitors" direction="in" type="a(iiduba(s(iid)a{sv}))" />
+      <arg name="logical_monitors" direction="in" type="a(iiduba(ssa{sv}))" />
       <arg name="properties" direction="in" type="a{sv}" />
     </method>
   </interface>


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