[mutter] monitor-manager: Generate a monitor abstraction from outputs and crtcs



commit d9a0f2a88d2abc2d0862da1691161baddbab5ac4
Author: Jonas Ådahl <jadahl gmail com>
Date:   Tue Dec 13 10:53:38 2016 +0800

    monitor-manager: Generate a monitor abstraction from outputs and crtcs
    
    Generate a set of "monitors" abstracting the physical concepts. Each
    monitor is built up of one or more outputs; multiple outputs being
    tiled monitors. Logical monitors will later be built from these.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=777732

 src/Makefile.am                             |    3 +
 src/backends/meta-monitor-manager-private.h |    7 +
 src/backends/meta-monitor-manager.c         |   46 +++++
 src/backends/meta-monitor.c                 |  268 +++++++++++++++++++++++++++
 src/backends/meta-monitor.h                 |   69 +++++++
 5 files changed, 393 insertions(+), 0 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index b2509ad..d5af5b2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -105,6 +105,9 @@ libmutter_la_SOURCES =                              \
        backends/meta-logical-monitor.h         \
        backends/meta-monitor-config.c          \
        backends/meta-monitor-config.h          \
+       backends/meta-monitor.c                 \
+       backends/meta-monitor.h                 \
+       backends/meta-monitor-private.h         \
        backends/meta-monitor-manager.c         \
        meta/meta-monitor-manager.h             \
        backends/meta-monitor-manager-private.h \
diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h
index 53f1e4e..e27107b 100644
--- a/src/backends/meta-monitor-manager-private.h
+++ b/src/backends/meta-monitor-manager-private.h
@@ -50,6 +50,9 @@
 typedef struct _MetaMonitorConfigClass    MetaMonitorConfigClass;
 typedef struct _MetaMonitorConfig         MetaMonitorConfig;
 
+typedef struct _MetaMonitor MetaMonitor;
+typedef struct _MetaMonitorNormal MetaMonitorNormal;
+typedef struct _MetaMonitorTiled MetaMonitorTiled;
 typedef struct _MetaLogicalMonitor MetaLogicalMonitor;
 
 typedef struct _MetaCrtc MetaCrtc;
@@ -266,6 +269,8 @@ struct _MetaMonitorManager
   MetaCrtc *crtcs;
   unsigned int n_crtcs;
 
+  GList *monitors;
+
   GList *logical_monitors;
   MetaLogicalMonitor *primary_logical_monitor;
 
@@ -344,6 +349,8 @@ MetaLogicalMonitor *meta_monitor_manager_get_logical_monitor_neighbor (MetaMonit
                                                                        MetaLogicalMonitor *logical_monitor,
                                                                        MetaScreenDirection direction);
 
+GList *             meta_monitor_manager_get_monitors      (MetaMonitorManager *manager);
+
 MetaOutput         *meta_monitor_manager_get_outputs       (MetaMonitorManager *manager,
                                                            unsigned int       *n_outputs);
 
diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c
index 588c084..14dd503 100644
--- a/src/backends/meta-monitor-manager.c
+++ b/src/backends/meta-monitor-manager.c
@@ -38,6 +38,7 @@
 #include "edid.h"
 #include "meta-monitor-config.h"
 #include "backends/meta-logical-monitor.h"
+#include "backends/meta-monitor.h"
 #include "backends/x11/meta-monitor-manager-xrandr.h"
 #include "meta-backend-private.h"
 
@@ -1446,6 +1447,12 @@ meta_monitor_manager_get_logical_monitor_neighbor (MetaMonitorManager *manager,
   return NULL;
 }
 
+GList *
+meta_monitor_manager_get_monitors (MetaMonitorManager *manager)
+{
+  return manager->monitors;
+}
+
 MetaOutput *
 meta_monitor_manager_get_outputs (MetaMonitorManager *manager,
                                   unsigned int       *n_outputs)
@@ -1498,6 +1505,43 @@ meta_monitor_manager_get_screen_limits (MetaMonitorManager *manager,
   *height = manager->max_screen_height;
 }
 
+static void
+rebuild_monitors (MetaMonitorManager *manager)
+{
+  unsigned int i;
+
+  if (manager->monitors)
+    {
+      g_list_free_full (manager->monitors, g_object_unref);
+      manager->monitors = NULL;
+    }
+
+  for (i = 0; i < manager->n_outputs; i++)
+    {
+      MetaOutput *output = &manager->outputs[i];
+
+      if (output->tile_info.group_id)
+        {
+          if (is_main_tiled_monitor_output (output))
+            {
+              MetaMonitorTiled *monitor_tiled;
+
+              monitor_tiled = meta_monitor_tiled_new (manager, output);
+              manager->monitors = g_list_append (manager->monitors,
+                                                 monitor_tiled);
+            }
+        }
+      else
+        {
+          MetaMonitorNormal *monitor_normal;
+
+          monitor_normal = meta_monitor_normal_new (output);
+          manager->monitors = g_list_append (manager->monitors,
+                                             monitor_normal);
+        }
+    }
+}
+
 void
 meta_monitor_manager_read_current_config (MetaMonitorManager *manager)
 {
@@ -1519,6 +1563,8 @@ meta_monitor_manager_read_current_config (MetaMonitorManager *manager)
   manager->serial++;
   META_MONITOR_MANAGER_GET_CLASS (manager)->read_current (manager);
 
+  rebuild_monitors (manager);
+
   meta_monitor_manager_free_output_array (old_outputs, n_old_outputs);
   meta_monitor_manager_free_mode_array (old_modes, n_old_modes);
   meta_monitor_manager_free_crtc_array (old_crtcs, n_old_crtcs);
diff --git a/src/backends/meta-monitor.c b/src/backends/meta-monitor.c
new file mode 100644
index 0000000..d528686
--- /dev/null
+++ b/src/backends/meta-monitor.c
@@ -0,0 +1,268 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/*
+ * Copyright (C) 2016 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "backends/meta-monitor.h"
+
+#include "backends/meta-monitor-manager-private.h"
+
+typedef struct _MetaMonitorPrivate
+{
+  GList *outputs;
+
+  /*
+   * The primary or first output for this monitor, 0 if we can't figure out.
+   * It can be matched to a winsys_id of a MetaOutput.
+   *
+   * This is used as an opaque token on reconfiguration when switching from
+   * clone to extened, to decide on what output the windows should go next
+   * (it's an attempt to keep windows on the same monitor, and preferably on
+   * the primary one).
+   */
+  long winsys_id;
+} MetaMonitorPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (MetaMonitor, meta_monitor, G_TYPE_OBJECT)
+
+struct _MetaMonitorNormal
+{
+  MetaMonitor parent;
+};
+
+G_DEFINE_TYPE (MetaMonitorNormal, meta_monitor_normal, META_TYPE_MONITOR)
+
+struct _MetaMonitorTiled
+{
+  MetaMonitor parent;
+
+  uint32_t tile_group_id;
+
+  MetaOutput *main_output;
+};
+
+G_DEFINE_TYPE (MetaMonitorTiled, meta_monitor_tiled, META_TYPE_MONITOR)
+
+GList *
+meta_monitor_get_outputs (MetaMonitor *monitor)
+{
+  MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
+
+  return priv->outputs;
+}
+
+static MetaOutput *
+meta_monitor_get_main_output (MetaMonitor *monitor)
+{
+  return META_MONITOR_GET_CLASS (monitor)->get_main_output (monitor);
+}
+
+gboolean
+meta_monitor_is_active (MetaMonitor *monitor)
+{
+  MetaOutput *output;
+
+  output = meta_monitor_get_main_output (monitor);
+
+  return output->crtc && output->crtc->current_mode;
+}
+
+void
+meta_monitor_get_dimensions (MetaMonitor   *monitor,
+                             int           *width,
+                             int           *height)
+{
+  META_MONITOR_GET_CLASS (monitor)->get_dimensions (monitor, width, height);
+}
+
+void
+meta_monitor_get_physical_dimensions (MetaMonitor *monitor,
+                                      int         *width_mm,
+                                      int         *height_mm)
+{
+  MetaOutput *output;
+
+  output = meta_monitor_get_main_output (monitor);
+  *width_mm = output->width_mm;
+  *height_mm = output->height_mm;
+}
+
+static void
+meta_monitor_finalize (GObject *object)
+{
+  MetaMonitor *monitor = META_MONITOR (object);
+  MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
+
+  g_clear_pointer (&priv->outputs, g_list_free);
+}
+
+static void
+meta_monitor_init (MetaMonitor *monitor)
+{
+}
+
+static void
+meta_monitor_class_init (MetaMonitorClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = meta_monitor_finalize;
+}
+
+MetaMonitorNormal *
+meta_monitor_normal_new (MetaOutput *output)
+{
+  MetaMonitorNormal *monitor_normal;
+  MetaMonitorPrivate *monitor_priv;
+
+  monitor_normal = g_object_new (META_TYPE_MONITOR_NORMAL, NULL);
+  monitor_priv =
+    meta_monitor_get_instance_private (META_MONITOR (monitor_normal));
+
+  monitor_priv->outputs = g_list_append (NULL, output);
+  monitor_priv->winsys_id = output->winsys_id;
+
+  return monitor_normal;
+}
+
+static MetaOutput *
+meta_monitor_normal_get_main_output (MetaMonitor *monitor)
+{
+  MetaMonitorPrivate *monitor_priv =
+    meta_monitor_get_instance_private (monitor);
+
+  return monitor_priv->outputs->data;
+}
+
+static void
+meta_monitor_normal_get_dimensions (MetaMonitor   *monitor,
+                                    int           *width,
+                                    int           *height)
+{
+  MetaOutput *output;
+
+  output = meta_monitor_get_main_output (monitor);
+  *width = output->crtc->rect.width;
+  *height = output->crtc->rect.height;
+}
+
+static void
+meta_monitor_normal_init (MetaMonitorNormal *monitor)
+{
+}
+
+static void
+meta_monitor_normal_class_init (MetaMonitorNormalClass *klass)
+{
+  MetaMonitorClass *monitor_class = META_MONITOR_CLASS (klass);
+
+  monitor_class->get_main_output = meta_monitor_normal_get_main_output;
+  monitor_class->get_dimensions = meta_monitor_normal_get_dimensions;
+}
+
+static void
+add_tiled_monitor_outputs (MetaMonitorManager *monitor_manager,
+                           MetaMonitorTiled   *monitor_tiled)
+{
+  MetaMonitorPrivate *monitor_priv =
+    meta_monitor_get_instance_private (META_MONITOR (monitor_tiled));
+  unsigned int i;
+
+  for (i = 0; i < monitor_manager->n_outputs; i++)
+    {
+      MetaOutput *output = &monitor_manager->outputs[i];
+
+      if (output->tile_info.group_id != monitor_tiled->tile_group_id)
+        continue;
+
+      monitor_priv->outputs = g_list_append (monitor_priv->outputs, output);
+    }
+}
+
+MetaMonitorTiled *
+meta_monitor_tiled_new (MetaMonitorManager *monitor_manager,
+                        MetaOutput         *output)
+{
+  MetaMonitorTiled *monitor_tiled;
+  MetaMonitorPrivate *monitor_priv;
+
+  monitor_tiled = g_object_new (META_TYPE_MONITOR_TILED, NULL);
+  monitor_priv =
+    meta_monitor_get_instance_private (META_MONITOR (monitor_tiled));
+
+  monitor_tiled->tile_group_id = output->tile_info.group_id;
+  monitor_priv->winsys_id = output->winsys_id;
+
+  add_tiled_monitor_outputs (monitor_manager, monitor_tiled);
+  monitor_tiled->main_output = output;
+
+  return monitor_tiled;
+}
+
+static MetaOutput *
+meta_monitor_tiled_get_main_output (MetaMonitor *monitor)
+{
+  MetaMonitorTiled *monitor_tiled = META_MONITOR_TILED (monitor);
+
+  return monitor_tiled->main_output;
+}
+
+static void
+meta_monitor_tiled_get_dimensions (MetaMonitor   *monitor,
+                                   int           *out_width,
+                                   int           *out_height)
+{
+  MetaMonitorPrivate *monitor_priv =
+    meta_monitor_get_instance_private (monitor);
+  GList *l;
+  int width;
+  int height;
+
+  width = 0;
+  height = 0;
+  for (l = monitor_priv->outputs; l; l = l->next)
+    {
+      MetaOutput *output = l->data;
+
+      if (output->tile_info.loc_v_tile == 0)
+        width += output->tile_info.tile_w;
+
+      if (output->tile_info.loc_h_tile == 0)
+        height += output->tile_info.tile_h;
+    }
+
+  *out_width = width;
+  *out_height = height;
+}
+
+static void
+meta_monitor_tiled_init (MetaMonitorTiled *monitor)
+{
+}
+
+static void
+meta_monitor_tiled_class_init (MetaMonitorTiledClass *klass)
+{
+  MetaMonitorClass *monitor_class = META_MONITOR_CLASS (klass);
+
+  monitor_class->get_main_output = meta_monitor_tiled_get_main_output;
+  monitor_class->get_dimensions = meta_monitor_tiled_get_dimensions;
+}
diff --git a/src/backends/meta-monitor.h b/src/backends/meta-monitor.h
new file mode 100644
index 0000000..b469e18
--- /dev/null
+++ b/src/backends/meta-monitor.h
@@ -0,0 +1,69 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/*
+ * Copyright (C) 2016 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef META_MONITOR_H
+#define META_MONITOR_H
+
+#include <glib-object.h>
+
+#include "backends/meta-monitor-manager-private.h"
+
+#define META_TYPE_MONITOR (meta_monitor_get_type ())
+G_DECLARE_DERIVABLE_TYPE (MetaMonitor, meta_monitor, META, MONITOR, GObject)
+
+struct _MetaMonitorClass
+{
+  GObjectClass parent_class;
+
+  MetaOutput * (* get_main_output) (MetaMonitor *monitor);
+  void (* get_dimensions) (MetaMonitor   *monitor,
+                           int           *width,
+                           int           *height);
+};
+
+#define META_TYPE_MONITOR_NORMAL (meta_monitor_normal_get_type ())
+G_DECLARE_FINAL_TYPE (MetaMonitorNormal, meta_monitor_normal,
+                      META, MONITOR_NORMAL,
+                      MetaMonitor)
+
+#define META_TYPE_MONITOR_TILED (meta_monitor_tiled_get_type ())
+G_DECLARE_FINAL_TYPE (MetaMonitorTiled, meta_monitor_tiled,
+                      META, MONITOR_TILED,
+                      MetaMonitor)
+
+MetaMonitorTiled * meta_monitor_tiled_new (MetaMonitorManager *monitor_manager,
+                                           MetaOutput         *main_output);
+
+MetaMonitorNormal * meta_monitor_normal_new (MetaOutput *output);
+
+gboolean meta_monitor_is_active (MetaMonitor *monitor);
+
+GList * meta_monitor_get_outputs (MetaMonitor *monitor);
+
+void meta_monitor_get_dimensions (MetaMonitor   *monitor,
+                                  int           *width,
+                                  int           *height);
+
+void meta_monitor_get_physical_dimensions (MetaMonitor *monitor,
+                                           int         *width_mm,
+                                           int         *height_mm);
+
+#endif /* META_MONITOR_H */


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