[mutter/wip/wayland-display: 14/17] Split monitor handling into an helper object
- From: Giovanni Campagna <gcampagna src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wip/wayland-display: 14/17] Split monitor handling into an helper object
- Date: Fri, 19 Jul 2013 14:07:40 +0000 (UTC)
commit 18abb58a38d56270ccfe07b69cca4faf3aa6bd9c
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.
src/Makefile.am | 2 +
src/core/display.c | 2 +-
src/core/monitor-private.h | 98 ++++++++
src/core/monitor.c | 432 ++++++++++++++++++++++++++++++++++++
src/core/screen-private.h | 38 +---
src/core/screen.c | 289 +++---------------------
src/wayland/meta-wayland-private.h | 4 -
src/wayland/meta-wayland.c | 55 +++---
8 files changed, 595 insertions(+), 325 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 3a4e629..2302c0d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -123,6 +123,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 c651f46..0fd7400 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..850ae30
--- /dev/null
+++ b/src/core/monitor.c
@@ -0,0 +1,432 @@
+/* -*- 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"
+#ifdef HAVE_WAYLAND
+#include "meta-wayland-private.h"
+#endif
+
+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
+
+typedef struct {
+ GArray *monitor_infos;
+ GArray *outputs;
+} ReadMonitorCoglClosure;
+
+static void
+read_monitor_from_cogl_helper (CoglOutput *output,
+ void *user_data)
+{
+ ReadMonitorCoglClosure *closure = user_data;
+ MetaMonitorInfo info;
+ MetaOutput meta_output;
+
+ info.number = closure->monitor_infos->len;
+ info.rect.x = cogl_output_get_x (output);
+ info.rect.y = cogl_output_get_y (output);
+ info.rect.width = cogl_output_get_width (output);
+ info.rect.height = cogl_output_get_height (output);
+ info.refresh_rate = cogl_output_get_refresh_rate (output);
+ info.is_primary = (info.number == 0);
+ info.in_fullscreen = -1;
+ info.output_id = 0; /* unknown */
+
+ g_array_append_val (closure->monitor_infos, info);
+
+ meta_output.monitor = &g_array_index (closure->monitor_infos,
+ MetaMonitorInfo,
+ closure->monitor_infos->len - 1);
+ meta_output.name = NULL;
+ meta_output.width_mm = cogl_output_get_mm_width (output);
+ meta_output.height_mm = cogl_output_get_mm_height (output);
+ meta_output.subpixel_order = cogl_output_get_subpixel_order (output);
+
+ g_array_append_val (closure->outputs, meta_output);
+}
+
+static void
+read_monitor_infos_from_cogl (MetaMonitorManager *manager)
+{
+ ReadMonitorCoglClosure closure;
+ ClutterBackend *backend;
+ CoglContext *cogl_context;
+ CoglRenderer *cogl_renderer;
+
+ backend = clutter_get_default_backend ();
+ cogl_context = clutter_backend_get_cogl_context (backend);
+ cogl_renderer = cogl_display_get_renderer (cogl_context_get_display (cogl_context));
+
+ closure.monitor_infos = g_array_new (FALSE, TRUE, sizeof (MetaMonitorInfo));
+ closure.outputs = g_array_new (FALSE, TRUE, sizeof (MetaOutput));
+
+ cogl_renderer_foreach_output (cogl_renderer,
+ read_monitor_from_cogl_helper, &closure);
+
+ manager->n_monitor_infos = closure.monitor_infos->len;
+ manager->monitor_infos = (void*)g_array_free (closure.monitor_infos, FALSE);
+ manager->n_outputs = closure.outputs->len;
+ manager->outputs = (void*)g_array_free (closure.outputs, FALSE);
+
+ manager->primary_monitor_index = 0;
+}
+
+/*
+ * 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)
+{
+ MetaWaylandCompositor *compositor;
+
+ if (!meta_is_display_server ())
+ return FALSE;
+
+ /* FIXME: actually, even in EGL-KMS mode, Cogl does not
+ expose the outputs through CoglOutput - yet */
+ compositor = meta_wayland_compositor_get_default ();
+ return !meta_wayland_compositor_is_native (compositor);
+}
+
+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
+ if (!meta_is_display_server ())
+ return read_monitor_infos_from_xrandr (manager);
+#endif
+
+ return read_monitor_infos_from_cogl (manager);
+}
+
+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 8ca1d1c..f884148 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 7596600..a3c8c41 100644
--- a/src/core/screen.c
+++ b/src/core/screen.c
@@ -51,10 +51,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>
@@ -79,6 +75,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,
@@ -353,54 +352,6 @@ set_wm_icon_size_hint (MetaScreen *screen)
#undef N_VALS
}
-/*
- * 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)
-{
- MetaWaylandCompositor *compositor;
-
- if (!meta_is_display_server ())
- return FALSE;
-
- /* FIXME: actually, even in EGL-KMS mode, Cogl does not
- expose the outputs through CoglOutput - yet */
- compositor = meta_wayland_compositor_get_default ();
- return !meta_wayland_compositor_is_native (compositor);
-}
-
-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)
{
@@ -461,179 +412,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
-
-typedef struct {
- GArray *monitor_infos;
- GArray *outputs;
-} ReadMonitorCoglClosure;
-
-static void
-read_monitor_from_cogl_helper (CoglOutput *output,
- void *user_data)
-{
- ReadMonitorCoglClosure *closure = user_data;
- MetaMonitorInfo info;
- MetaOutput meta_output;
-
- info.number = closure->monitor_infos->len;
- info.rect.x = cogl_output_get_x (output);
- info.rect.y = cogl_output_get_y (output);
- info.rect.width = cogl_output_get_width (output);
- info.rect.height = cogl_output_get_height (output);
- info.refresh_rate = cogl_output_get_refresh_rate (output);
- info.is_primary = (info.number == 0);
- info.in_fullscreen = -1;
- info.output_id = 0; /* unknown */
-
- g_array_append_val (closure->monitor_infos, info);
-
- meta_output.monitor = &g_array_index (closure->monitor_infos,
- MetaMonitorInfo,
- closure->monitor_infos->len - 1);
- meta_output.name = NULL;
- meta_output.width_mm = cogl_output_get_mm_width (output);
- meta_output.height_mm = cogl_output_get_mm_height (output);
- meta_output.subpixel_order = cogl_output_get_subpixel_order (output);
-
- g_array_append_val (closure->outputs, meta_output);
-}
-
-static void
-read_monitor_infos_from_cogl (MetaScreen *screen)
-{
- ReadMonitorCoglClosure closure;
- ClutterBackend *backend;
- CoglContext *cogl_context;
- CoglRenderer *cogl_renderer;
-
- backend = clutter_get_default_backend ();
- cogl_context = clutter_backend_get_cogl_context (backend);
- cogl_renderer = cogl_display_get_renderer (cogl_context_get_display (cogl_context));
-
- closure.monitor_infos = g_array_new (FALSE, TRUE, sizeof (MetaMonitorInfo));
- closure.outputs = g_array_new (FALSE, TRUE, sizeof (MetaOutput));
-
- cogl_renderer_foreach_output (cogl_renderer,
- read_monitor_from_cogl_helper, &closure);
-
- screen->n_monitor_infos = closure.monitor_infos->len;
- screen->monitor_infos = (void*)g_array_free (closure.monitor_infos, FALSE);
- screen->n_outputs = closure.outputs->len;
- screen->outputs = (void*)g_array_free (closure.outputs, FALSE);
-
- screen->primary_monitor_index = 0;
-}
-
static void
reload_monitor_infos (MetaScreen *screen)
{
GList *tmp;
+ MetaMonitorManager *manager;
tmp = screen->workspaces;
while (tmp != NULL)
@@ -647,23 +430,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);
-
-#ifdef HAVE_RANDR
- if (!meta_is_display_server ())
- return read_monitor_infos_from_xrandr (screen);
-#endif
+ manager = meta_monitor_manager_get ();
- return read_monitor_infos_from_cogl (screen);
+ 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
@@ -941,7 +716,18 @@ meta_screen_new (MetaDisplay *display,
screen->compositor_data = NULL;
screen->guard_window = None;
- reload_monitor_infos (screen);
+ {
+ MetaMonitorManager *manager;
+
+ if (!meta_is_display_server ())
+ 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);
@@ -1027,12 +813,6 @@ meta_screen_new (MetaDisplay *display,
meta_verbose ("Added screen %d ('%s') root 0x%lx\n",
screen->number, screen->screen_name, screen->xroot);
-#ifdef HAVE_WAYLAND
- if (meta_is_display_server ())
- meta_wayland_compositor_init_screen (compositor,
- screen);
-#endif
-
return screen;
}
@@ -3096,18 +2876,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);
@@ -3119,8 +2898,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,
@@ -3130,7 +2909,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);
@@ -3146,16 +2926,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
diff --git a/src/wayland/meta-wayland-private.h b/src/wayland/meta-wayland-private.h
index 334c84e..2ee1fe7 100644
--- a/src/wayland/meta-wayland-private.h
+++ b/src/wayland/meta-wayland-private.h
@@ -129,7 +129,6 @@ typedef struct
struct _MetaWaylandCompositor
{
- MetaScreen *screen;
GList *outputs;
struct wl_display *wayland_display;
@@ -337,9 +336,6 @@ void meta_wayland_finalize (void);
* API after meta_wayland_init() has been called. */
MetaWaylandCompositor *meta_wayland_compositor_get_default (void);
-void meta_wayland_compositor_init_screen (MetaWaylandCompositor *compositor,
- MetaScreen *screen);
-
MetaWaylandSurface *meta_wayland_lookup_surface_for_xid (guint32 xid);
void meta_wayland_compositor_repick (MetaWaylandCompositor *compositor);
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index be0f948..e6c4eda 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -633,21 +633,25 @@ bind_output (struct wl_client *client,
(int)output->monitor->rect.height,
(int)output->monitor->refresh_rate);
- wl_resource_post_event (resource,
- WL_OUTPUT_DONE);
+ if (version >= 2)
+ wl_resource_post_event (resource,
+ WL_OUTPUT_DONE);
}
static void
-meta_wayland_compositor_create_outputs (MetaWaylandCompositor *compositor)
+meta_wayland_compositor_create_outputs (MetaWaylandCompositor *compositor,
+ MetaMonitorManager *monitors)
{
- MetaScreen *screen = compositor->screen;
- int i;
+ MetaOutput *outputs;
+ int i, n_outputs;
+
+ outputs = meta_monitor_manager_get_outputs (monitors, &n_outputs);
- for (i = 0; i < screen->n_outputs; i++)
+ for (i = 0; i < n_outputs; i++)
compositor->outputs = g_list_prepend (compositor->outputs,
wl_global_create (compositor->wayland_display,
&wl_output_interface, 2,
- &screen->outputs[i], bind_output));
+ &outputs[i], bind_output));
}
const static struct wl_compositor_interface meta_wayland_compositor_interface = {
@@ -1908,6 +1912,14 @@ on_evdev_device_open (const char *path,
path, flags, error);
}
+static void
+on_monitors_changed (MetaMonitorManager *monitors,
+ MetaWaylandCompositor *compositor)
+{
+ g_list_free_full (compositor->outputs, (GDestroyNotify) wl_global_destroy);
+ meta_wayland_compositor_create_outputs (compositor, monitors);
+}
+
void
meta_wayland_init (void)
{
@@ -1917,6 +1929,7 @@ meta_wayland_init (void)
CoglContext *cogl_context;
CoglRenderer *cogl_renderer;
int weston_launch_fd;
+ MetaMonitorManager *monitors;
memset (compositor, 0, sizeof (MetaWaylandCompositor));
@@ -1994,12 +2007,20 @@ meta_wayland_init (void)
}
compositor->stage = meta_wayland_stage_new ();
+ /* FIXME */
+ clutter_actor_set_size (CLUTTER_ACTOR (compositor->stage), 1024, 768);
clutter_stage_set_user_resizable (CLUTTER_STAGE (compositor->stage), FALSE);
g_signal_connect_after (compositor->stage, "paint",
G_CALLBACK (paint_finished_cb), compositor);
g_signal_connect (compositor->stage, "destroy",
G_CALLBACK (stage_destroy_cb), NULL);
+ meta_monitor_manager_initialize (NULL);
+ monitors = meta_monitor_manager_get ();
+ g_signal_connect (monitors, "monitors-changed",
+ G_CALLBACK (on_monitors_changed), compositor);
+ meta_wayland_compositor_create_outputs (compositor, monitors);
+
meta_wayland_data_device_manager_init (compositor->wayland_display);
compositor->seat = meta_wayland_seat_new (compositor->wayland_display);
@@ -2081,23 +2102,3 @@ meta_wayland_compositor_is_native (MetaWaylandCompositor *compositor)
{
return compositor->drm_fd >= 0;
}
-
-static void
-on_monitors_changed (MetaScreen *screen,
- MetaWaylandCompositor *compositor)
-{
- g_list_free_full (compositor->outputs, (GDestroyNotify) wl_global_destroy);
- meta_wayland_compositor_create_outputs (compositor);
-}
-
-void
-meta_wayland_compositor_init_screen (MetaWaylandCompositor *compositor,
- MetaScreen *screen)
-{
- compositor->screen = screen;
-
- g_signal_connect (compositor->screen, "monitors-changed",
- G_CALLBACK (on_monitors_changed), compositor);
-
- meta_wayland_compositor_create_outputs (compositor);
-}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]