[mutter] monitor-manager: Add support for suggested position for outputs



commit f6f5f624d4e1bf13a8368110f695a393bc47c739
Author: Jonathon Jongsma <jjongsma redhat com>
Date:   Mon Nov 10 15:36:47 2014 -0600

    monitor-manager: Add support for suggested position for outputs
    
    In recent versions of the QXL driver, it may set "suggested X|Y" connector
    properties. These properties are used to indicate the position at which
    multiple displays should be aligned.  If all outputs have a suggested position,
    the displays are arranged according to these positions, otherwise we fall back
    to the default configuration.
    
    At the moment, we trust that the driver has chosen sane values for the
    suggested position.

 src/backends/meta-monitor-config.c             |   53 ++++++++++++++++++++++++
 src/backends/meta-monitor-manager.h            |    2 +
 src/backends/native/meta-monitor-manager-kms.c |    2 +
 src/backends/x11/meta-monitor-manager-xrandr.c |   52 +++++++++++++++++++++++
 4 files changed, 109 insertions(+), 0 deletions(-)
---
diff --git a/src/backends/meta-monitor-config.c b/src/backends/meta-monitor-config.c
index 74239a3..81f0a5e 100644
--- a/src/backends/meta-monitor-config.c
+++ b/src/backends/meta-monitor-config.c
@@ -34,6 +34,7 @@
 
 #include "config.h"
 
+#include "boxes-private.h"
 #include "meta-monitor-config.h"
 
 #include <string.h>
@@ -1096,6 +1097,55 @@ init_config_from_preferred_mode (MetaOutputConfig *config,
   config->is_presentation = FALSE;
 }
 
+/* This function handles configuring the outputs when the driver provides a
+ * suggested layout position for each output. This is done in recent versions
+ * of qxl and allows displays to be aligned on the guest in the same order as
+ * they are aligned on the client.
+ */
+static gboolean
+make_suggested_config (MetaMonitorConfig *self,
+                       MetaOutput        *outputs,
+                       unsigned           n_outputs,
+                       int                max_width,
+                       int                max_height,
+                       MetaConfiguration *config)
+{
+  unsigned int i;
+  MetaOutput *primary;
+  GList *region = NULL;
+
+  g_return_if_fail (config != NULL);
+  primary = find_primary_output (outputs, n_outputs);
+
+  for (i = 0; i < n_outputs; i++)
+    {
+      gboolean is_primary = (&outputs[i] == primary);
+
+      if (outputs[i].suggested_x < 0 || outputs[i].suggested_y < 0)
+          return FALSE;
+
+      init_config_from_preferred_mode (&config->outputs[i], &outputs[i]);
+      config->outputs[i].is_primary = is_primary;
+
+      config->outputs[i].rect.x = outputs[i].suggested_x;
+      config->outputs[i].rect.y = outputs[i].suggested_y;
+
+      /* Reject the configuration if the suggested positions result in
+       * overlapping displays */
+      if (meta_rectangle_overlaps_with_region (region, &config->outputs[i].rect))
+        {
+          g_warning ("Overlapping outputs, rejecting suggested configuration");
+          g_list_free (region);
+          return FALSE;
+        }
+
+      region = g_list_prepend (region, &config->outputs[i].rect);
+    }
+
+  g_list_free (region);
+  return TRUE;
+}
+
 static void
 make_linear_config (MetaMonitorConfig *self,
                     MetaOutput        *outputs,
@@ -1228,6 +1278,9 @@ make_default_config (MetaMonitorConfig *self,
       return ret;
     }
 
+  if (make_suggested_config (self, outputs, n_outputs, max_width, max_height, ret))
+      return ret;
+
   if (use_stored_config &&
       extend_stored_config (self, outputs, n_outputs, max_width, max_height, ret))
       return ret;
diff --git a/src/backends/meta-monitor-manager.h b/src/backends/meta-monitor-manager.h
index 4d1b3b7..102759f 100644
--- a/src/backends/meta-monitor-manager.h
+++ b/src/backends/meta-monitor-manager.h
@@ -116,6 +116,8 @@ struct _MetaOutput
 
   /* get a new preferred mode on hotplug events, to handle dynamic guest resizing */
   gboolean hotplug_mode_update;
+  gint suggested_x;
+  gint suggested_y;
 };
 
 struct _MetaCRTC
diff --git a/src/backends/native/meta-monitor-manager-kms.c b/src/backends/native/meta-monitor-manager-kms.c
index 6334487..c528516 100644
--- a/src/backends/native/meta-monitor-manager-kms.c
+++ b/src/backends/native/meta-monitor-manager-kms.c
@@ -415,6 +415,8 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
          meta_output->name = make_output_name (connector);
          meta_output->width_mm = connector->mmWidth;
          meta_output->height_mm = connector->mmHeight;
+         meta_output->suggested_x = -1;
+         meta_output->suggested_y = -1;
 
           switch (connector->subpixel)
             {
diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c
index 3fdfca2..dd32bd4 100644
--- a/src/backends/x11/meta-monitor-manager-xrandr.c
+++ b/src/backends/x11/meta-monitor-manager-xrandr.c
@@ -140,6 +140,34 @@ meta_monitor_transform_from_xrandr_all (Rotation rotation)
 }
 
 static gboolean
+output_get_integer_property (MetaMonitorManagerXrandr *manager_xrandr,
+                             MetaOutput *output, const char *propname,
+                             gint *value)
+{
+  gboolean exists = FALSE;
+  Atom atom, actual_type;
+  int actual_format;
+  unsigned long nitems, bytes_after;
+  unsigned char *buffer;
+
+  atom = XInternAtom (manager_xrandr->xdisplay, propname, False);
+  XRRGetOutputProperty (manager_xrandr->xdisplay,
+                        (XID)output->winsys_id,
+                        atom,
+                        0, G_MAXLONG, False, False, XA_INTEGER,
+                        &actual_type, &actual_format,
+                        &nitems, &bytes_after, &buffer);
+
+  exists = (actual_type == XA_INTEGER && actual_format == 32 && nitems == 1);
+
+  if (exists && value != NULL)
+    *value = ((int*)buffer)[0];
+
+  XFree (buffer);
+  return exists;
+}
+
+static gboolean
 output_get_property_exists (MetaMonitorManagerXrandr *manager_xrandr,
                             MetaOutput *output, const char *propname)
 {
@@ -356,6 +384,28 @@ output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr,
   return output_get_property_exists (manager_xrandr, output, "hotplug_mode_update");
 }
 
+static gint
+output_get_suggested_x (MetaMonitorManagerXrandr *manager_xrandr,
+                        MetaOutput               *output)
+{
+  gint val;
+  if (output_get_integer_property (manager_xrandr, output, "suggested X", &val))
+    return val;
+
+  return -1;
+}
+
+static gint
+output_get_suggested_y (MetaMonitorManagerXrandr *manager_xrandr,
+                        MetaOutput               *output)
+{
+  gint val;
+  if (output_get_integer_property (manager_xrandr, output, "suggested Y", &val))
+    return val;
+
+  return -1;
+}
+
 static char *
 get_xmode_name (XRRModeInfo *xmode)
 {
@@ -543,6 +593,8 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
          meta_output->height_mm = output->mm_height;
          meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
           meta_output->hotplug_mode_update = output_get_hotplug_mode_update (manager_xrandr, meta_output);
+         meta_output->suggested_x = output_get_suggested_x (manager_xrandr, meta_output);
+         meta_output->suggested_y = output_get_suggested_y (manager_xrandr, meta_output);
 
          meta_output->n_modes = output->nmode;
          meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);


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