[mutter] DisplayConfig: Add new API for configuring monitors



commit 691e7951ea9ef67497484504f16f74d4fa0840a1
Author: Jonas Ådahl <jadahl gmail com>
Date:   Tue Feb 14 19:54:04 2017 +0800

    DisplayConfig: Add new API for configuring monitors
    
    Add a new D-Bus API that uses the state from GetCurrentState to
    configure high level monitors, instead of low level CRTCs and
    connectors. So far persistent configuration is not implemented, as
    writing to the configuration store is still not supported.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=777732

 src/backends/meta-monitor-manager-dummy.c      |   14 +-
 src/backends/meta-monitor-manager-private.h    |   15 +-
 src/backends/meta-monitor-manager.c            |  401 +++++++++++++++++++++++-
 src/backends/native/meta-monitor-manager-kms.c |   14 +-
 src/backends/x11/meta-monitor-manager-xrandr.c |   20 +-
 src/org.gnome.Mutter.DisplayConfig.xml         |   37 +++
 src/tests/meta-monitor-manager-test.c          |   14 +-
 7 files changed, 485 insertions(+), 30 deletions(-)
---
diff --git a/src/backends/meta-monitor-manager-dummy.c b/src/backends/meta-monitor-manager-dummy.c
index b0fbddc..f5b993f 100644
--- a/src/backends/meta-monitor-manager-dummy.c
+++ b/src/backends/meta-monitor-manager-dummy.c
@@ -499,9 +499,10 @@ update_screen_size (MetaMonitorManager *manager,
 }
 
 static gboolean
-meta_monitor_manager_dummy_apply_monitors_config (MetaMonitorManager *manager,
-                                                  MetaMonitorsConfig *config,
-                                                  GError            **error)
+meta_monitor_manager_dummy_apply_monitors_config (MetaMonitorManager      *manager,
+                                                  MetaMonitorsConfig      *config,
+                                                  MetaMonitorsConfigMethod method,
+                                                  GError                 **error)
 {
   GPtrArray *crtc_infos;
   GPtrArray *output_infos;
@@ -519,6 +520,13 @@ meta_monitor_manager_dummy_apply_monitors_config (MetaMonitorManager *manager,
                                            error))
     return FALSE;
 
+  if (method == META_MONITORS_CONFIG_METHOD_VERIFY)
+    {
+      g_ptr_array_free (crtc_infos, TRUE);
+      g_ptr_array_free (output_infos, TRUE);
+      return TRUE;
+    }
+
   apply_crtc_assignments (manager,
                           (MetaCrtcInfo **) crtc_infos->pdata,
                           crtc_infos->len,
diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h
index d5a98c2..ade2c60 100644
--- a/src/backends/meta-monitor-manager-private.h
+++ b/src/backends/meta-monitor-manager-private.h
@@ -74,6 +74,14 @@ typedef enum _MetaMonitorManagerCapability
   META_MONITOR_MANAGER_CAPABILITY_MIRRORING = (1 << 0)
 } MetaMonitorManagerCapability;
 
+/* Equivalent to the 'method' enum in org.gnome.Mutter.DisplayConfig */
+typedef enum _MetaMonitorsConfigMethod
+{
+  META_MONITORS_CONFIG_METHOD_VERIFY = 0,
+  META_MONITORS_CONFIG_METHOD_TEMPORARY = 1,
+  META_MONITORS_CONFIG_METHOD_PERSISTENT = 2
+} MetaMonitorsConfigMethod;
+
 typedef enum
 {
   META_MONITOR_TRANSFORM_NORMAL,
@@ -316,9 +324,10 @@ struct _MetaMonitorManagerClass
 
   void (*ensure_initial_config) (MetaMonitorManager *);
 
-  gboolean (*apply_monitors_config) (MetaMonitorManager *,
-                                     MetaMonitorsConfig *,
-                                     GError            **);
+  gboolean (*apply_monitors_config) (MetaMonitorManager      *,
+                                     MetaMonitorsConfig      *,
+                                     MetaMonitorsConfigMethod ,
+                                     GError                 **);
 
   void (*apply_configuration) (MetaMonitorManager  *,
                                MetaCrtcInfo       **,
diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c
index e60f93a..64a45b6 100644
--- a/src/backends/meta-monitor-manager.c
+++ b/src/backends/meta-monitor-manager.c
@@ -315,14 +315,15 @@ meta_monitor_manager_ensure_initial_config (MetaMonitorManager *manager)
 }
 
 static gboolean
-meta_monitor_manager_apply_monitors_config (MetaMonitorManager *manager,
-                                            MetaMonitorsConfig *config,
-                                            GError            **error)
+meta_monitor_manager_apply_monitors_config (MetaMonitorManager      *manager,
+                                            MetaMonitorsConfig      *config,
+                                            MetaMonitorsConfigMethod method,
+                                            GError                 **error)
 {
   MetaMonitorManagerClass *manager_class =
     META_MONITOR_MANAGER_GET_CLASS (manager);
 
-  return manager_class->apply_monitors_config (manager, config, error);
+  return manager_class->apply_monitors_config (manager, config, method, error);
 }
 
 gboolean
@@ -359,6 +360,10 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager)
 {
   MetaMonitorsConfig *config = NULL;
   GError *error = NULL;
+  gboolean use_stored_config;
+  MetaMonitorsConfigMethod method;
+  MetaMonitorsConfigMethod fallback_method =
+    META_MONITORS_CONFIG_METHOD_TEMPORARY;
 
   if (!manager->config_manager)
     {
@@ -366,12 +371,20 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager)
       return NULL;
     }
 
-  if (should_use_stored_config (manager))
+  use_stored_config = should_use_stored_config (manager);
+  if (use_stored_config)
+    method = META_MONITORS_CONFIG_METHOD_PERSISTENT;
+  else
+    method = META_MONITORS_CONFIG_METHOD_TEMPORARY;
+
+  if (use_stored_config)
     {
       config = meta_monitor_config_manager_get_stored (manager->config_manager);
       if (config)
         {
-          if (!meta_monitor_manager_apply_monitors_config (manager, config,
+          if (!meta_monitor_manager_apply_monitors_config (manager,
+                                                           config,
+                                                           method,
                                                            &error))
             {
               config = NULL;
@@ -390,7 +403,10 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager)
   config = meta_monitor_config_manager_create_suggested (manager->config_manager);
   if (config)
     {
-      if (!meta_monitor_manager_apply_monitors_config (manager, config, &error))
+      if (!meta_monitor_manager_apply_monitors_config (manager,
+                                                       config,
+                                                       method,
+                                                       &error))
         {
           g_clear_object (&config);
           g_warning ("Failed to use suggested monitor configuration: %s",
@@ -406,7 +422,10 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager)
   config = meta_monitor_config_manager_create_linear (manager->config_manager);
   if (config)
     {
-      if (!meta_monitor_manager_apply_monitors_config (manager, config, &error))
+      if (!meta_monitor_manager_apply_monitors_config (manager,
+                                                       config,
+                                                       method,
+                                                       &error))
         {
           g_clear_object (&config);
           g_warning ("Failed to use linear monitor configuration: %s",
@@ -422,7 +441,10 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager)
   config = meta_monitor_config_manager_create_fallback (manager->config_manager);
   if (config)
     {
-      if (!meta_monitor_manager_apply_monitors_config (manager, config, &error))
+      if (!meta_monitor_manager_apply_monitors_config (manager,
+                                                       config,
+                                                       fallback_method,
+                                                       &error))
         {
           g_clear_object (&config);
           g_warning ("Failed to use fallback monitor configuration: %s",
@@ -440,7 +462,10 @@ done:
 
   if (!config)
     {
-      meta_monitor_manager_apply_monitors_config (manager, NULL, &error);
+      meta_monitor_manager_apply_monitors_config (manager,
+                                                  NULL,
+                                                  fallback_method,
+                                                  &error);
       return NULL;
     }
 
@@ -1364,6 +1389,361 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton,
 #undef LOGICAL_MONITOR_FORMAT
 #undef LOGICAL_MONITORS_FORMAT
 
+static gboolean
+meta_monitor_manager_is_scale_supported (MetaMonitorManager *manager,
+                                         float               scale)
+{
+  float *supported_scales;
+  int n_supported_scales;
+  int i;
+
+  meta_monitor_manager_get_supported_scales (manager,
+                                             &supported_scales,
+                                             &n_supported_scales);
+  for (i = 0; i < n_supported_scales; i++)
+    {
+      if (supported_scales[i] == scale)
+        return TRUE;
+    }
+
+  return FALSE;
+}
+
+static gboolean
+meta_monitor_manager_is_config_applicable (MetaMonitorManager *manager,
+                                           MetaMonitorsConfig *config,
+                                           GError            **error)
+{
+  GList *l;
+
+  for (l = config->logical_monitor_configs; l; l = l->next)
+    {
+      MetaLogicalMonitorConfig *logical_monitor_config = l->data;
+      float scale = logical_monitor_config->scale;
+      GList *k;
+
+      if (!meta_monitor_manager_is_scale_supported (manager, scale))
+        {
+          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                       "Scale not supported by backend");
+          return FALSE;
+        }
+
+      for (k = logical_monitor_config->monitor_configs; k; k = k->next)
+        {
+          MetaMonitorConfig *monitor_config = k->data;
+          MetaMonitorSpec *monitor_spec = monitor_config->monitor_spec;
+          MetaMonitorModeSpec *mode_spec = monitor_config->mode_spec;
+          MetaMonitor *monitor;
+          MetaMonitorMode *monitor_mode;
+
+          monitor = meta_monitor_manager_get_monitor_from_spec (manager,
+                                                                monitor_spec);
+          if (!monitor)
+            {
+              g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                           "Specified monitor not found");
+              return FALSE;
+            }
+
+          monitor_mode = meta_monitor_get_mode_from_spec (monitor, mode_spec);
+          if (!monitor_mode)
+            {
+              g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                           "Specified monitor mode not available");
+              return FALSE;
+            }
+        }
+    }
+
+  return TRUE;
+}
+
+static MetaMonitorSpec *
+find_monitor_spec (MetaMonitorManager *manager,
+                   char               *connector)
+{
+  GList *monitors;
+  GList *l;
+
+  monitors = meta_monitor_manager_get_monitors (manager);
+  for (l = monitors; l; l = l->next)
+    {
+      MetaMonitor *monitor = l->data;
+      MetaMonitorSpec *monitor_spec = meta_monitor_get_spec (monitor);
+
+      if (g_str_equal (connector, monitor_spec->connector))
+        return meta_monitor_spec_clone (monitor_spec);
+    }
+
+  return NULL;
+}
+
+#define MONITOR_MODE_SPEC_FORMAT "(iid)"
+#define MONITOR_CONFIG_FORMAT "(s" MONITOR_MODE_SPEC_FORMAT "a{sv})"
+#define MONITOR_CONFIGS_FORMAT "a" MONITOR_CONFIG_FORMAT
+
+#define LOGICAL_MONITOR_CONFIG_FORMAT "(iidb" MONITOR_CONFIGS_FORMAT ")"
+
+static MetaMonitorConfig *
+create_monitor_config_from_variant (MetaMonitorManager *manager,
+                                    GVariant           *monitor_config_variant,
+                                    GError            **error)
+{
+
+  MetaMonitorConfig *monitor_config = NULL;
+  char *connector;
+  MetaMonitorSpec *monitor_spec;
+  MetaMonitorModeSpec *monitor_mode_spec;
+  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})",
+                 &connector,
+                 &mode_width,
+                 &mode_height,
+                 &mode_refresh_rate,
+                 &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)
+    {
+      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))
+    {
+      g_free (monitor_mode_spec);
+      meta_monitor_spec_free (monitor_spec);
+      return NULL;
+    }
+
+  g_variant_lookup (properties_variant, "underscanning", "b", &enable_underscanning);
+
+  monitor_config = g_new0 (MetaMonitorConfig, 1);
+  *monitor_config = (MetaMonitorConfig) {
+    .monitor_spec = monitor_spec,
+    .mode_spec = monitor_mode_spec,
+    .enable_underscanning = enable_underscanning
+  };
+
+  return monitor_config;
+}
+
+static gboolean
+derive_logical_monitor_size (GList  *monitor_configs,
+                             int    *width,
+                             int    *height,
+                             GError **error)
+{
+  MetaMonitorConfig *monitor_config;
+
+  if (!monitor_configs)
+    {
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                   "Empty logical monitor");
+      return FALSE;
+    }
+
+  monitor_config = monitor_configs->data;
+  *width = monitor_config->mode_spec->width;
+  *height = monitor_config->mode_spec->height;
+
+  return TRUE;
+}
+
+static MetaLogicalMonitorConfig *
+create_logical_monitor_config_from_variant (MetaMonitorManager *manager,
+                                            GVariant           *logical_monitor_config_variant,
+                                            GError            **error)
+{
+  MetaLogicalMonitorConfig *logical_monitor_config;
+  int x, y, width, height;
+  double scale;
+  gboolean is_primary;
+  GVariantIter *monitor_configs_iter;
+  GList *monitor_configs = NULL;
+
+  g_variant_get (logical_monitor_config_variant, LOGICAL_MONITOR_CONFIG_FORMAT,
+                 &x,
+                 &y,
+                 &scale,
+                 &is_primary,
+                 &monitor_configs_iter);
+
+  while (TRUE)
+    {
+      GVariant *monitor_config_variant =
+        g_variant_iter_next_value (monitor_configs_iter);
+      MetaMonitorConfig *monitor_config;
+
+      if (!monitor_config_variant)
+        break;
+
+      monitor_config =
+        create_monitor_config_from_variant (manager,
+                                            monitor_config_variant, error);
+      if (!monitor_config)
+        goto err;
+
+      if (!meta_verify_monitor_config (monitor_config, error))
+        {
+          meta_monitor_config_free (monitor_config);
+          goto err;
+        }
+
+      monitor_configs = g_list_append (monitor_configs, monitor_config);
+    }
+  g_variant_iter_free (monitor_configs_iter);
+
+  if (!derive_logical_monitor_size (monitor_configs, &width, &height, error))
+    goto err;
+
+  logical_monitor_config = g_new0 (MetaLogicalMonitorConfig, 1);
+  *logical_monitor_config = (MetaLogicalMonitorConfig) {
+    .layout = {
+      .x = x,
+      .y = y,
+      .width = width,
+      .height = height
+    },
+    .scale = (int) scale,
+    .is_primary = is_primary,
+    .monitor_configs = monitor_configs
+  };
+
+  if (!meta_verify_logical_monitor_config (logical_monitor_config, error))
+    {
+      meta_logical_monitor_config_free (logical_monitor_config);
+      return NULL;
+    }
+
+  return logical_monitor_config;
+
+err:
+  g_list_free_full (monitor_configs, (GDestroyNotify) meta_monitor_config_free);
+  return NULL;
+}
+
+static gboolean
+meta_monitor_manager_handle_apply_monitors_config (MetaDBusDisplayConfig *skeleton,
+                                                   GDBusMethodInvocation *invocation,
+                                                   guint                  serial,
+                                                   guint                  method,
+                                                   GVariant              *logical_monitor_configs_variant,
+                                                   GVariant              *properties_variant)
+{
+  MetaMonitorManager *manager = META_MONITOR_MANAGER (skeleton);
+  GVariantIter logical_monitor_configs_iter;
+  MetaMonitorsConfig *config;
+  GList *logical_monitor_configs = NULL;
+  GError *error = NULL;
+
+  if (!manager->config_manager)
+    {
+      g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
+                                             G_DBUS_ERROR_NOT_SUPPORTED,
+                                             "Used new configuration API with old configuration system");
+      return TRUE;
+    }
+
+  if (serial != manager->serial)
+    {
+      g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
+                                             G_DBUS_ERROR_ACCESS_DENIED,
+                                             "The requested configuration is based on stale information");
+      return TRUE;
+    }
+
+  g_variant_iter_init (&logical_monitor_configs_iter,
+                       logical_monitor_configs_variant);
+  while (TRUE)
+    {
+      GVariant *logical_monitor_config_variant =
+        g_variant_iter_next_value (&logical_monitor_configs_iter);
+      MetaLogicalMonitorConfig *logical_monitor_config;
+
+      if (!logical_monitor_config_variant)
+        break;
+
+      logical_monitor_config =
+        create_logical_monitor_config_from_variant (manager,
+                                                    logical_monitor_config_variant,
+                                                    &error);
+      if (!logical_monitor_config)
+        {
+          g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
+                                                 G_DBUS_ERROR_INVALID_ARGS,
+                                                 error->message);
+          g_error_free (error);
+          g_list_free_full (logical_monitor_configs,
+                            (GDestroyNotify) meta_logical_monitor_config_free);
+          return TRUE;
+        }
+
+      logical_monitor_configs = g_list_append (logical_monitor_configs,
+                                               logical_monitor_config);
+    }
+
+  config = meta_monitors_config_new (logical_monitor_configs);
+  if (!meta_verify_monitors_config (config, &error))
+    {
+      g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
+                                             G_DBUS_ERROR_INVALID_ARGS,
+                                             error->message);
+      g_error_free (error);
+      g_object_unref (config);
+      return TRUE;
+    }
+
+  if (!meta_monitor_manager_is_config_applicable (manager, config, &error))
+    {
+      g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
+                                             G_DBUS_ERROR_INVALID_ARGS,
+                                             error->message);
+      g_error_free (error);
+      g_object_unref (config);
+      return TRUE;
+    }
+
+  if (!meta_monitor_manager_apply_monitors_config (manager,
+                                                   config,
+                                                   method,
+                                                   &error))
+    {
+      g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
+                                             G_DBUS_ERROR_INVALID_ARGS,
+                                             error->message);
+      g_error_free (error);
+      g_object_unref (config);
+      return TRUE;
+    }
+
+  meta_dbus_display_config_complete_apply_monitors_config (skeleton, invocation);
+
+  return TRUE;
+}
+
+#undef MONITOR_MODE_SPEC_FORMAT
+#undef MONITOR_CONFIG_FORMAT
+#undef MONITOR_CONFIGS_FORMAT
+#undef LOGICAL_MONITOR_CONFIG_FORMAT
+
 static void
 legacy_confirm_configuration (MetaMonitorManager *manager,
                               gboolean            confirmed)
@@ -1569,6 +1949,7 @@ meta_monitor_manager_display_config_init (MetaDBusDisplayConfigIface *iface)
   iface->handle_get_crtc_gamma = meta_monitor_manager_handle_get_crtc_gamma;
   iface->handle_set_crtc_gamma = meta_monitor_manager_handle_set_crtc_gamma;
   iface->handle_get_current_state = meta_monitor_manager_handle_get_current_state;
+  iface->handle_apply_monitors_config = meta_monitor_manager_handle_apply_monitors_config;
 }
 
 static void
diff --git a/src/backends/native/meta-monitor-manager-kms.c b/src/backends/native/meta-monitor-manager-kms.c
index 1866c38..92be434 100644
--- a/src/backends/native/meta-monitor-manager-kms.c
+++ b/src/backends/native/meta-monitor-manager-kms.c
@@ -1424,9 +1424,10 @@ update_screen_size (MetaMonitorManager *manager,
 }
 
 static gboolean
-meta_monitor_manager_kms_apply_monitors_config (MetaMonitorManager *manager,
-                                                MetaMonitorsConfig *config,
-                                                GError            **error)
+meta_monitor_manager_kms_apply_monitors_config (MetaMonitorManager      *manager,
+                                                MetaMonitorsConfig      *config,
+                                                MetaMonitorsConfigMethod method,
+                                                GError                 **error)
 {
   GPtrArray *crtc_infos;
   GPtrArray *output_infos;
@@ -1444,6 +1445,13 @@ meta_monitor_manager_kms_apply_monitors_config (MetaMonitorManager *manager,
                                            error))
     return FALSE;
 
+  if (method == META_MONITORS_CONFIG_METHOD_VERIFY)
+    {
+      g_ptr_array_free (crtc_infos, TRUE);
+      g_ptr_array_free (output_infos, TRUE);
+      return TRUE;
+    }
+
   apply_crtc_assignments (manager,
                           (MetaCrtcInfo **) crtc_infos->pdata,
                           crtc_infos->len,
diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c
index 06d38cf..d0e5209 100644
--- a/src/backends/x11/meta-monitor-manager-xrandr.c
+++ b/src/backends/x11/meta-monitor-manager-xrandr.c
@@ -1300,9 +1300,10 @@ meta_monitor_manager_xrandr_ensure_initial_config (MetaMonitorManager *manager)
 }
 
 static gboolean
-meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager *manager,
-                                                   MetaMonitorsConfig *config,
-                                                   GError            **error)
+meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager      *manager,
+                                                   MetaMonitorsConfig      *config,
+                                                   MetaMonitorsConfigMethod method,
+                                                   GError                 **error)
 {
   GPtrArray *crtc_infos;
   GPtrArray *output_infos;
@@ -1318,11 +1319,14 @@ meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager *manager,
                                            error))
     return FALSE;
 
-  apply_crtc_assignments (manager,
-                          (MetaCrtcInfo **) crtc_infos->pdata,
-                          crtc_infos->len,
-                          (MetaOutputInfo **) output_infos->pdata,
-                          output_infos->len);
+  if (method != META_MONITORS_CONFIG_METHOD_VERIFY)
+    {
+      apply_crtc_assignments (manager,
+                              (MetaCrtcInfo **) crtc_infos->pdata,
+                              crtc_infos->len,
+                              (MetaOutputInfo **) output_infos->pdata,
+                              output_infos->len);
+    }
 
   g_ptr_array_free (crtc_infos, TRUE);
   g_ptr_array_free (output_infos, TRUE);
diff --git a/src/org.gnome.Mutter.DisplayConfig.xml b/src/org.gnome.Mutter.DisplayConfig.xml
index 60923a8..43ffb28 100644
--- a/src/org.gnome.Mutter.DisplayConfig.xml
+++ b/src/org.gnome.Mutter.DisplayConfig.xml
@@ -359,5 +359,42 @@
       <arg name="max_screen_size" direction="out" type="(ii)" />
       <arg name="properties" direction="out" type="a{sv}" />
     </method>
+
+    <!--
+       ApplyMonitorsConfig:
+       @serial: configuration serial
+       @method: configuration method
+       @logical_monitors: monitors configuration
+       @properties: properties
+
+       @method represents the way the configuration should be handled.
+
+       Possible methods:
+         0: verify
+         1: temporary
+         2: persistent
+
+       @logical_monitors consists of a list of logical monitor configurations.
+       Each logical monitor configuration consists of:
+
+       * i: layout x position
+       * i: layout y position
+       * d: scale
+       * b primary: true if this is the primary logical monitor
+       * a(siida{sv}): a list of monitors, each consisting of:
+           * s: connector
+           * (iid): monitor mode spec (resolution width, resolution height,
+                    refresh rate)
+           * a{sv}: monitor properties, including:
+               - "enable_underscanning" (b): enable monitor underscanning;
+                                             may only be set when underscanning
+                                             is supported (see GetCurrentState).
+    -->
+    <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(iidba(s(iid)a{sv}))" />
+      <arg name="properties" direction="in" type="a{sv}" />
+    </method>
   </interface>
 </node>
diff --git a/src/tests/meta-monitor-manager-test.c b/src/tests/meta-monitor-manager-test.c
index 14afcd9..292abe7 100644
--- a/src/tests/meta-monitor-manager-test.c
+++ b/src/tests/meta-monitor-manager-test.c
@@ -256,9 +256,10 @@ update_screen_size (MetaMonitorManager *manager,
 }
 
 static gboolean
-meta_monitor_manager_test_apply_monitors_config (MetaMonitorManager *manager,
-                                                 MetaMonitorsConfig *config,
-                                                 GError            **error)
+meta_monitor_manager_test_apply_monitors_config (MetaMonitorManager      *manager,
+                                                 MetaMonitorsConfig      *config,
+                                                 MetaMonitorsConfigMethod method,
+                                                 GError                 **error)
 {
   GPtrArray *crtc_infos;
   GPtrArray *output_infos;
@@ -280,6 +281,13 @@ meta_monitor_manager_test_apply_monitors_config (MetaMonitorManager *manager,
                                            error))
     return FALSE;
 
+  if (method == META_MONITORS_CONFIG_METHOD_VERIFY)
+    {
+      g_ptr_array_free (crtc_infos, TRUE);
+      g_ptr_array_free (output_infos, TRUE);
+      return TRUE;
+    }
+
   apply_crtc_assignments (manager,
                           (MetaCrtcInfo **) crtc_infos->pdata,
                           crtc_infos->len,


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