[mutter/wip/display-no-wayland: 10/33] Split monitor handling into an helper object



commit cb26296b3918e9bb86126f855b9c95dbd180d3b8
Author: Giovanni Campagna <gcampagn redhat com>
Date:   Thu Jul 18 14:45:48 2013 +0200

    Split monitor handling into an helper object
    
    Create a new singleton object, MetaMonitorManager, which deals
    with reading the XRandR configuration and in the future applying
    the new one.
    This is required because xwayland will not bind the xserver interface
    until he has seen the current wl_outputs, so we can't wait
    until MetaScreen is built to expose them.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=705670

 src/Makefile.am            |    2 +
 src/core/display.c         |    2 +-
 src/core/monitor-private.h |   98 ++++++++++++
 src/core/monitor.c         |  356 ++++++++++++++++++++++++++++++++++++++++++++
 src/core/screen-private.h  |   38 +-----
 src/core/screen.c          |  203 ++++---------------------
 6 files changed, 490 insertions(+), 209 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 5a20ef1..f62f3f4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -110,6 +110,8 @@ libmutter_la_SOURCES =                              \
        core/keybindings.c                      \
        core/keybindings-private.h              \
        core/main.c                             \
+       core/monitor.c                          \
+       core/monitor-private.h                  \
        core/mutter-Xatomtype.h                 \
        core/place.c                            \
        core/place.h                            \
diff --git a/src/core/display.c b/src/core/display.c
index e39361e..430829b 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -517,7 +517,7 @@ meta_display_open (void)
 
   if (meta_is_syncing ())
     XSynchronize (xdisplay, True);
-  
+
   g_assert (the_display == NULL);
   the_display = g_object_new (META_TYPE_DISPLAY, NULL);
 
diff --git a/src/core/monitor-private.h b/src/core/monitor-private.h
new file mode 100644
index 0000000..0150dc2
--- /dev/null
+++ b/src/core/monitor-private.h
@@ -0,0 +1,98 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/**
+ * \file screen-private.h  Handling of monitor configuration
+ *
+ * Managing multiple monitors
+ * This file contains structures and functions that handle
+ * multiple monitors, including reading the current configuration
+ * and available hardware, and applying it.
+ *
+ * This interface is private to mutter, API users should look
+ * at MetaScreen instead.
+ */
+
+/* 
+ * Copyright (C) 2001 Havoc Pennington
+ * Copyright (C) 2003 Rob Adams
+ * Copyright (C) 2004-2006 Elijah Newren
+ * Copyright (C) 2013 Red Hat Inc.
+ * 
+ * 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_PRIVATE_H
+#define META_MONITOR_PRIVATE_H
+
+#include "display-private.h"
+#include <meta/screen.h>
+#include "stack-tracker.h"
+#include "ui.h"
+
+#include <cogl/cogl.h>
+
+typedef struct _MetaOutput MetaOutput;
+typedef struct _MetaMonitorInfo MetaMonitorInfo;
+
+struct _MetaOutput
+{
+  MetaMonitorInfo *monitor;
+  char *name;
+  int width_mm;
+  int height_mm;
+  CoglSubpixelOrder subpixel_order;
+};
+
+struct _MetaMonitorInfo
+{
+  int number;
+  int xinerama_index;
+  MetaRectangle rect;
+  gboolean is_primary;
+  gboolean in_fullscreen;
+  float refresh_rate;
+
+  /* The primary or first output for this crtc, 0 if we can't figure out.
+     This is a XID when using XRandR, otherwise a KMS id (not implemented) */
+  glong output_id;
+};
+
+#define META_TYPE_MONITOR_MANAGER            (meta_monitor_manager_get_type ())
+#define META_MONITOR_MANAGER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER, 
MetaMonitorManager))
+#define META_MONITOR_MANAGER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_MONITOR_MANAGER, 
MetaMonitorManagerClass))
+#define META_IS_MONITOR_MANAGER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_MANAGER))
+#define META_IS_MONITOR_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_MONITOR_MANAGER))
+#define META_MONITOR_MANAGER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_MONITOR_MANAGER, 
MetaMonitorManagerClass))
+
+typedef struct _MetaMonitorManagerClass    MetaMonitorManagerClass;
+typedef struct _MetaMonitorManager         MetaMonitorManager;
+
+GType meta_monitor_manager_get_type (void);
+
+void                meta_monitor_manager_initialize (Display *display);
+MetaMonitorManager *meta_monitor_manager_get  (void);
+
+MetaMonitorInfo    *meta_monitor_manager_get_monitor_infos (MetaMonitorManager *manager,
+                                                           int                *n_infos);
+
+MetaOutput         *meta_monitor_manager_get_outputs       (MetaMonitorManager *manager,
+                                                           int                *n_outputs);
+
+int                 meta_monitor_manager_get_primary_index (MetaMonitorManager *manager);
+
+void                meta_monitor_manager_invalidate        (MetaMonitorManager *manager);
+
+#endif
diff --git a/src/core/monitor.c b/src/core/monitor.c
new file mode 100644
index 0000000..05d4f2b
--- /dev/null
+++ b/src/core/monitor.c
@@ -0,0 +1,356 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/* 
+ * Copyright (C) 2001, 2002 Havoc Pennington
+ * Copyright (C) 2002, 2003 Red Hat Inc.
+ * Some ICCCM manager selection code derived from fvwm2,
+ * Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team
+ * Copyright (C) 2003 Rob Adams
+ * Copyright (C) 2004-2006 Elijah Newren
+ * Copyright (C) 2013 Red Hat Inc.
+ * 
+ * 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 <clutter/clutter.h>
+
+#ifdef HAVE_RANDR
+#include <X11/extensions/Xrandr.h>
+#endif
+
+#include "monitor-private.h"
+
+struct _MetaMonitorManager
+{
+  GObject parent_instance;
+
+  /* Outputs refers to physical screens,
+     while monitor_infos refer to logical ones (aka CRTC)
+     They can be different if two outputs are
+     in clone mode
+  */
+  MetaOutput *outputs;
+  int primary_monitor_index;
+  int n_outputs;
+
+  MetaMonitorInfo *monitor_infos;
+  int n_monitor_infos;
+
+#ifdef HAVE_RANDR
+  Display *xdisplay;
+#endif
+};
+
+struct _MetaMonitorManagerClass
+{
+  GObjectClass parent_class;
+};
+
+enum {
+  MONITORS_CHANGED,
+  SIGNALS_LAST
+};
+
+static int signals[SIGNALS_LAST];
+
+G_DEFINE_TYPE (MetaMonitorManager, meta_monitor_manager, G_TYPE_OBJECT);
+
+static void
+make_dummy_monitor_config (MetaMonitorManager *manager)
+{
+  manager->monitor_infos = g_new0 (MetaMonitorInfo, 1);
+  manager->n_monitor_infos = 1;
+
+  manager->monitor_infos[0].number = 0;
+  manager->monitor_infos[0].xinerama_index = 0;
+  manager->monitor_infos[0].rect.x = 0;
+  manager->monitor_infos[0].rect.y = 0;
+  if (manager->xdisplay)
+    {
+      Screen *screen = ScreenOfDisplay (manager->xdisplay,
+                                        DefaultScreen (manager->xdisplay));
+
+      manager->monitor_infos[0].rect.width = WidthOfScreen (screen);
+      manager->monitor_infos[0].rect.height = HeightOfScreen (screen);
+    }
+  else
+    {
+      manager->monitor_infos[0].rect.width = 1024;
+      manager->monitor_infos[0].rect.height = 768;
+    }
+  manager->monitor_infos[0].refresh_rate = 60.0f;
+  manager->monitor_infos[0].is_primary = TRUE;
+  manager->monitor_infos[0].in_fullscreen = -1;
+  manager->monitor_infos[0].output_id = 1;
+
+  manager->outputs = g_new0 (MetaOutput, 1);
+  manager->n_outputs = 1;
+
+  manager->outputs[0].monitor = &manager->monitor_infos[0];
+  manager->outputs[0].name = g_strdup ("LVDS");
+  manager->outputs[0].width_mm = 222;
+  manager->outputs[0].height_mm = 125;
+  manager->outputs[0].subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
+}
+
+#ifdef HAVE_RANDR
+
+/* In the case of multiple outputs of a single crtc (mirroring), we consider one of the
+ * outputs the "main". This is the one we consider "owning" the windows, so if
+ * the mirroring is changed to a dual monitor setup then the windows are moved to the
+ * crtc that now has that main output. If one of the outputs is the primary that is
+ * always the main, otherwise we just use the first.
+ */
+static void
+find_main_output_for_crtc (MetaMonitorManager         *manager,
+                           XRRScreenResources *resources,
+                           XRRCrtcInfo        *crtc,
+                           MetaMonitorInfo    *info,
+                           GArray             *outputs)
+{
+  XRROutputInfo *output;
+  RROutput primary_output;
+  int i;
+
+  primary_output = XRRGetOutputPrimary (manager->xdisplay,
+                                        DefaultRootWindow (manager->xdisplay));
+
+  for (i = 0; i < crtc->noutput; i++)
+    {
+      output = XRRGetOutputInfo (manager->xdisplay, resources, crtc->outputs[i]);
+
+      if (output->connection != RR_Disconnected)
+        {
+          MetaOutput meta_output;
+
+          meta_output.name = g_strdup (output->name);
+          meta_output.width_mm = output->mm_width;
+          meta_output.height_mm = output->mm_height;
+          meta_output.subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
+
+          g_array_append_val (outputs, meta_output);
+
+          if (crtc->outputs[i] == primary_output)
+            {
+              info->output_id = crtc->outputs[i];
+              info->is_primary = TRUE;
+              manager->primary_monitor_index = info->number;
+            }
+          else if (info->output_id == 0)
+            {
+              info->output_id = crtc->outputs[i];
+            }
+        }
+
+      XRRFreeOutputInfo (output);
+    }
+}
+
+static void
+read_monitor_infos_from_xrandr (MetaMonitorManager *manager)
+{
+    XRRScreenResources *resources;
+    GArray *outputs;
+    int i, j;
+
+    resources = XRRGetScreenResourcesCurrent (manager->xdisplay,
+                                              DefaultRootWindow (manager->xdisplay));
+    if (!resources)
+      return make_dummy_monitor_config (manager);
+
+    outputs = g_array_new (FALSE, TRUE, sizeof (MetaOutput));
+
+    manager->n_outputs = 0;
+    manager->n_monitor_infos = resources->ncrtc;
+
+    manager->monitor_infos = g_new0 (MetaMonitorInfo, manager->n_monitor_infos);
+
+    for (i = 0; i < resources->ncrtc; i++)
+      {
+        XRRCrtcInfo *crtc;
+        MetaMonitorInfo *info;
+
+        crtc = XRRGetCrtcInfo (manager->xdisplay, resources, resources->crtcs[i]);
+
+        info = &manager->monitor_infos[i];
+
+        info->number = i;
+        info->rect.x = crtc->x;
+        info->rect.y = crtc->y;
+        info->rect.width = crtc->width;
+        info->rect.height = crtc->height;
+        info->in_fullscreen = -1;
+
+        for (j = 0; j < resources->nmode; j++)
+          {
+            if (resources->modes[j].id == crtc->mode)
+              info->refresh_rate = (resources->modes[j].dotClock /
+                                    ((float)resources->modes[j].hTotal *
+                                     resources->modes[j].vTotal));
+          }
+
+        find_main_output_for_crtc (manager, resources, crtc, info, outputs);
+
+        XRRFreeCrtcInfo (crtc);
+      }
+
+    manager->n_outputs = outputs->len;
+    manager->outputs = (void*)g_array_free (outputs, FALSE);
+
+    XRRFreeScreenResources (resources);
+}
+
+#endif
+
+/*
+ * meta_has_dummy_output:
+ *
+ * Returns TRUE if the only available monitor is the dummy one
+ * backing the ClutterStage window.
+ */
+static gboolean
+has_dummy_output (void)
+{
+  return FALSE;
+}
+
+static void
+meta_monitor_manager_init (MetaMonitorManager *manager)
+{
+}
+
+static void
+read_current_config (MetaMonitorManager *manager)
+{
+  if (has_dummy_output ())
+    return make_dummy_monitor_config (manager);
+
+#ifdef HAVE_RANDR
+  return read_monitor_infos_from_xrandr (manager);
+#endif
+}
+
+static MetaMonitorManager *
+meta_monitor_manager_new (Display *display)
+{
+  MetaMonitorManager *manager;
+
+  manager = g_object_new (META_TYPE_MONITOR_MANAGER, NULL);
+
+  manager->xdisplay = display;
+
+  read_current_config (manager);
+  return manager;
+}
+
+static void
+free_output_array (MetaOutput *old_outputs,
+                   int         n_old_outputs)
+{
+  int i;
+
+  for (i = 0; i < n_old_outputs; i++)
+    g_free (old_outputs[i].name);
+  g_free (old_outputs);
+}
+
+static void
+meta_monitor_manager_finalize (GObject *object)
+{
+  MetaMonitorManager *manager = META_MONITOR_MANAGER (object);
+
+  free_output_array (manager->outputs, manager->n_outputs);
+  g_free (manager->monitor_infos);
+
+  G_OBJECT_CLASS (meta_monitor_manager_parent_class)->finalize (object);
+}
+
+static void
+meta_monitor_manager_class_init (MetaMonitorManagerClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = meta_monitor_manager_finalize;
+
+  signals[MONITORS_CHANGED] =
+    g_signal_new ("monitors-changed",
+                 G_TYPE_FROM_CLASS (object_class),
+                 G_SIGNAL_RUN_LAST,
+                 0,
+                  NULL, NULL, NULL,
+                 G_TYPE_NONE, 0);
+}
+
+static MetaMonitorManager *global_manager;
+
+void
+meta_monitor_manager_initialize (Display *display)
+{
+  global_manager = meta_monitor_manager_new (display);
+}
+
+MetaMonitorManager *
+meta_monitor_manager_get (void)
+{
+  g_assert (global_manager != NULL);
+
+  return global_manager;
+}
+
+MetaMonitorInfo *
+meta_monitor_manager_get_monitor_infos (MetaMonitorManager *manager,
+                                        int                *n_infos)
+{
+  *n_infos = manager->n_monitor_infos;
+  return manager->monitor_infos;
+}
+
+MetaOutput *
+meta_monitor_manager_get_outputs (MetaMonitorManager *manager,
+                                  int                *n_outputs)
+{
+  *n_outputs = manager->n_outputs;
+  return manager->outputs;
+}
+
+int
+meta_monitor_manager_get_primary_index (MetaMonitorManager *manager)
+{
+  return manager->primary_monitor_index;
+}
+
+void
+meta_monitor_manager_invalidate (MetaMonitorManager *manager)
+{
+  MetaOutput *old_outputs;
+  MetaMonitorInfo *old_monitor_infos;
+  int n_old_outputs;
+
+  /* Save the old monitor infos, so they stay valid during the update */
+  old_outputs = manager->outputs;
+  n_old_outputs = manager->n_outputs;
+  old_monitor_infos = manager->monitor_infos;
+
+  read_current_config (manager);
+
+  g_signal_emit (manager, signals[MONITORS_CHANGED], 0);
+
+  g_free (old_monitor_infos);
+  free_output_array (old_outputs, n_old_outputs);
+}
+
diff --git a/src/core/screen-private.h b/src/core/screen-private.h
index dfefaa2..894eda5 100644
--- a/src/core/screen-private.h
+++ b/src/core/screen-private.h
@@ -38,34 +38,7 @@
 #include <X11/Xutil.h>
 #include "stack-tracker.h"
 #include "ui.h"
-
-#include <cogl/cogl.h>
-
-typedef struct _MetaOutput MetaOutput;
-typedef struct _MetaMonitorInfo MetaMonitorInfo;
-
-struct _MetaOutput
-{
-  MetaMonitorInfo *monitor;
-  char *name;
-  int width_mm;
-  int height_mm;
-  CoglSubpixelOrder subpixel_order;
-};
-
-struct _MetaMonitorInfo
-{
-  int number;
-  int xinerama_index;
-  MetaRectangle rect;
-  gboolean is_primary;
-  gboolean in_fullscreen;
-  float refresh_rate;
-
-  /* The primary or first output for this crtc, 0 if we can't figure out.
-     This is a XID when using XRandR, otherwise a KMS id (not implemented) */
-  glong output_id;
-};
+#include "monitor-private.h"
 
 typedef void (* MetaScreenWindowFunc) (MetaScreen *screen, MetaWindow *window,
                                        gpointer user_data);
@@ -118,16 +91,9 @@ struct _MetaScreen
   Atom wm_sn_atom;
   guint32 wm_sn_timestamp;
 
-  /* Outputs refers to physical screens,
-     while monitor_infos refer to logical ones (aka CRTC)
-     They can be different if two outputs are
-     in clone mode
-  */
-  MetaOutput *outputs;
   MetaMonitorInfo *monitor_infos;
-  int primary_monitor_index;
-  int n_outputs;
   int n_monitor_infos;
+  int primary_monitor_index;
   gboolean has_xinerama_indices;
 
   /* Cache the current monitor */
diff --git a/src/core/screen.c b/src/core/screen.c
index 94b2f19..cb02f20 100644
--- a/src/core/screen.c
+++ b/src/core/screen.c
@@ -48,10 +48,6 @@
 
 #include <X11/extensions/Xinerama.h>
 
-#ifdef HAVE_RANDR
-#include <X11/extensions/Xrandr.h>
-#endif
-
 #include <X11/Xatom.h>
 #include <locale.h>
 #include <string.h>
@@ -76,6 +72,9 @@ static void meta_screen_sn_event   (SnMonitorEvent *event,
                                     void           *user_data);
 #endif
 
+static void on_monitors_changed (MetaMonitorManager *manager,
+                                 MetaScreen         *screen);
+
 enum
 {
   PROP_N_WORKSPACES = 1,
@@ -350,40 +349,6 @@ set_wm_icon_size_hint (MetaScreen *screen)
 #undef N_VALS
 }
 
-static gboolean
-has_dummy_output (void)
-{
-  return FALSE;
-}
-
-static void
-make_dummy_monitor_config (MetaScreen *screen)
-{
-  screen->outputs = g_new0 (MetaOutput, 1);
-  screen->n_outputs = 1;
-
-  screen->outputs[0].name = g_strdup ("LVDS");
-  screen->outputs[0].width_mm = 222;
-  screen->outputs[0].height_mm = 125;
-  screen->outputs[0].subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
-
-  screen->monitor_infos = g_new0 (MetaMonitorInfo, 1);
-  screen->n_monitor_infos = 1;
-
-  screen->monitor_infos[0].number = 0;
-  screen->monitor_infos[0].xinerama_index = 0;
-  screen->monitor_infos[0].rect.x = 0;
-  screen->monitor_infos[0].rect.y = 0;
-  screen->monitor_infos[0].rect.width = screen->rect.width;
-  screen->monitor_infos[0].rect.height = screen->rect.height;
-  screen->monitor_infos[0].refresh_rate = 60.0f;
-  screen->monitor_infos[0].is_primary = TRUE;
-  screen->monitor_infos[0].in_fullscreen = -1;
-  screen->monitor_infos[0].output_id = 1;
-
-  screen->has_xinerama_indices = TRUE;
-}
-
 static void
 meta_screen_ensure_xinerama_indices (MetaScreen *screen)
 {
@@ -444,117 +409,11 @@ meta_screen_xinerama_index_to_monitor_index (MetaScreen *screen,
   return -1;
 }
 
-#ifdef HAVE_RANDR
-
-/* In the case of multiple outputs of a single crtc (mirroring), we consider one of the
- * outputs the "main". This is the one we consider "owning" the windows, so if
- * the mirroring is changed to a dual monitor setup then the windows are moved to the
- * crtc that now has that main output. If one of the outputs is the primary that is
- * always the main, otherwise we just use the first.
- */
-static void
-find_main_output_for_crtc (MetaScreen         *screen,
-                           XRRScreenResources *resources,
-                           XRRCrtcInfo        *crtc,
-                           MetaMonitorInfo    *info,
-                           GArray             *outputs)
-{
-  XRROutputInfo *output;
-  RROutput primary_output;
-  int i;
-
-  primary_output = XRRGetOutputPrimary (screen->display->xdisplay, screen->xroot);
-
-  for (i = 0; i < crtc->noutput; i++)
-    {
-      output = XRRGetOutputInfo (screen->display->xdisplay, resources, crtc->outputs[i]);
-
-      if (output->connection != RR_Disconnected)
-        {
-          MetaOutput meta_output;
-
-          meta_output.name = g_strdup (output->name);
-          meta_output.width_mm = output->mm_width;
-          meta_output.height_mm = output->mm_height;
-          meta_output.subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
-
-          g_array_append_val (outputs, meta_output);
-
-          if (crtc->outputs[i] == primary_output)
-            {
-              info->output_id = crtc->outputs[i];
-              info->is_primary = TRUE;
-              screen->primary_monitor_index = info->number;
-            }
-          else if (info->output_id == 0)
-            {
-              info->output_id = crtc->outputs[i];
-            }
-        }
-
-      XRRFreeOutputInfo (output);
-    }
-}
-
-static void
-read_monitor_infos_from_xrandr (MetaScreen *screen)
-{
-    XRRScreenResources *resources;
-    GArray *outputs;
-    int i, j;
-
-    resources = XRRGetScreenResourcesCurrent (screen->display->xdisplay, screen->xroot);
-    if (!resources)
-      return make_dummy_monitor_config (screen);
-
-    outputs = g_array_new (FALSE, TRUE, sizeof (MetaOutput));
-
-    screen->n_outputs = 0;
-    screen->n_monitor_infos = resources->ncrtc;
-
-    screen->monitor_infos = g_new0 (MetaMonitorInfo, screen->n_monitor_infos);
-
-    for (i = 0; i < resources->ncrtc; i++)
-      {
-        XRRCrtcInfo *crtc;
-        MetaMonitorInfo *info;
-
-        crtc = XRRGetCrtcInfo (screen->display->xdisplay, resources, resources->crtcs[i]);
-
-        info = &screen->monitor_infos[i];
-
-        info->number = i;
-        info->rect.x = crtc->x;
-        info->rect.y = crtc->y;
-        info->rect.width = crtc->width;
-        info->rect.height = crtc->height;
-        info->in_fullscreen = -1;
-
-        for (j = 0; j < resources->nmode; j++)
-          {
-            if (resources->modes[j].id == crtc->mode)
-              info->refresh_rate = (resources->modes[j].dotClock /
-                                    ((float)resources->modes[j].hTotal *
-                                     resources->modes[j].vTotal));
-          }
-
-        find_main_output_for_crtc (screen, resources, crtc, info, outputs);
-
-        XRRFreeCrtcInfo (crtc);
-      }
-
-    screen->n_outputs = outputs->len;
-    screen->outputs = (void*)g_array_free (outputs, FALSE);
-
-    XRRFreeScreenResources (resources);
-}
-
-#endif
-
 static void
 reload_monitor_infos (MetaScreen *screen)
 {
   GList *tmp;
+  MetaMonitorManager *manager;
 
   tmp = screen->workspaces;
   while (tmp != NULL)
@@ -568,20 +427,15 @@ reload_monitor_infos (MetaScreen *screen)
 
   /* Any previous screen->monitor_infos or screen->outputs is freed by the caller */
 
-  screen->outputs = NULL;
-  screen->n_outputs = 0;
-  screen->monitor_infos = NULL;
-  screen->n_monitor_infos = 0;
   screen->last_monitor_index = 0;
   screen->has_xinerama_indices = FALSE;
   screen->display->monitor_cache_invalidated = TRUE;
 
-  if (has_dummy_output ())
-    return make_dummy_monitor_config (screen);
+  manager = meta_monitor_manager_get ();
 
-#ifdef HAVE_RANDR
-  return read_monitor_infos_from_xrandr (screen);
-#endif
+  screen->monitor_infos = meta_monitor_manager_get_monitor_infos (manager,
+                                                                  &screen->n_monitor_infos);
+  screen->primary_monitor_index = meta_monitor_manager_get_primary_index (manager);
 }
 
 /* The guard window allows us to leave minimized windows mapped so
@@ -840,7 +694,17 @@ meta_screen_new (MetaDisplay *display,
   screen->compositor_data = NULL;
   screen->guard_window = None;
 
-  reload_monitor_infos (screen);
+  {
+    MetaMonitorManager *manager;
+
+    meta_monitor_manager_initialize (screen->display->xdisplay);
+
+    reload_monitor_infos (screen);
+
+    manager = meta_monitor_manager_get ();
+    g_signal_connect (manager, "monitors-changed",
+                      G_CALLBACK (on_monitors_changed), screen);
+  }
   
   meta_screen_set_cursor (screen, META_CURSOR_DEFAULT);
 
@@ -2986,18 +2850,17 @@ meta_screen_resize (MetaScreen *screen,
                     int         width,
                     int         height)
 {
-  GSList *windows, *tmp;
-  MetaOutput *old_outputs;
-  MetaMonitorInfo *old_monitor_infos;
-  int n_old_outputs, i;
-
   screen->rect.width = width;
   screen->rect.height = height;
 
-  /* Save the old monitor infos, so they stay valid during the update */
-  old_outputs = screen->outputs;
-  n_old_outputs = screen->n_outputs;
-  old_monitor_infos = screen->monitor_infos;
+  meta_monitor_manager_invalidate (meta_monitor_manager_get ());
+}
+
+static void
+on_monitors_changed (MetaMonitorManager *manager,
+                     MetaScreen         *screen)
+{
+  GSList *tmp, *windows;
 
   reload_monitor_infos (screen);
   set_desktop_geometry_hint (screen);
@@ -3009,8 +2872,8 @@ meta_screen_resize (MetaScreen *screen,
 
       changes.x = 0;
       changes.y = 0;
-      changes.width = width;
-      changes.height = height;
+      changes.width = screen->rect.width;
+      changes.height = screen->rect.height;
 
       XConfigureWindow(screen->display->xdisplay,
                        screen->guard_window,
@@ -3020,7 +2883,8 @@ meta_screen_resize (MetaScreen *screen,
 
   if (screen->display->compositor)
     meta_compositor_sync_screen_size (screen->display->compositor,
-                                     screen, width, height);
+                                     screen,
+                                      screen->rect.width, screen->rect.height);
 
   /* Queue a resize on all the windows */
   meta_screen_foreach_window (screen, meta_screen_resize_func, 0);
@@ -3036,16 +2900,11 @@ meta_screen_resize (MetaScreen *screen,
         meta_window_update_for_monitors_changed (window);
     }
 
-  g_free (old_monitor_infos);
   g_slist_free (windows);
 
   meta_screen_queue_check_fullscreen (screen);
 
   g_signal_emit (screen, screen_signals[MONITORS_CHANGED], 0);
-
-  for (i = 0; i < n_old_outputs; i++)
-    g_free (old_outputs[i].name);
-  g_free (old_outputs);
 }
 
 void


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