[mutter/wip/wayland-display: 59/62] MonitorManager: split the XRandR parts in a subclass



commit 35fa4d37ab9212241b36b8523f0f769daf2853d5
Author: Giovanni Campagna <gcampagn redhat com>
Date:   Mon Jul 29 13:00:15 2013 +0200

    MonitorManager: split the XRandR parts in a subclass
    
    Instead of keeping a forest of if backend else ..., use a subclass
    and virtual functions to discriminate between XRandR and the
    dummy backend (which lives in the parent class togheter with the
    common code)

 src/Makefile.am            |    1 +
 src/core/monitor-config.c  |   14 +-
 src/core/monitor-private.h |  112 +++++-
 src/core/monitor-xrandr.c  |  776 +++++++++++++++++++++++++++++++
 src/core/monitor.c         | 1106 ++++++--------------------------------------
 src/core/screen.c          |    2 +-
 src/wayland/meta-wayland.c |    2 +-
 7 files changed, 1028 insertions(+), 985 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index fec0436..9e31b0d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -127,6 +127,7 @@ libmutter_la_SOURCES =                              \
        core/monitor.c                          \
        core/monitor-config.c                   \
        core/monitor-private.h                  \
+       core/monitor-xrandr.c                   \
        core/mutter-Xatomtype.h                 \
        core/place.c                            \
        core/place.h                            \
diff --git a/src/core/monitor-config.c b/src/core/monitor-config.c
index f332274..a0f4394 100644
--- a/src/core/monitor-config.c
+++ b/src/core/monitor-config.c
@@ -40,23 +40,11 @@
 #include <clutter/clutter.h>
 #include <libupower-glib/upower.h>
 
-#ifdef HAVE_RANDR
-#include <X11/extensions/Xrandr.h>
-#include <X11/extensions/dpms.h>
-#endif
-
 #include <meta/main.h>
 #include <meta/errors.h>
 #include "monitor-private.h"
-#ifdef HAVE_WAYLAND
-#include "meta-wayland-private.h"
-#endif
-
-#include "meta-dbus-xrandr.h"
-
-#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
 
-/* These two structures represent the intended/persistent configuration,
+/* These structures represent the intended/persistent configuration,
    as stored in the monitors.xml file.
 */
 
diff --git a/src/core/monitor-private.h b/src/core/monitor-private.h
index e02b3d2..4277910 100644
--- a/src/core/monitor-private.h
+++ b/src/core/monitor-private.h
@@ -47,6 +47,13 @@
 #include <wayland-server.h>
 #endif
 
+#include "meta-dbus-xrandr.h"
+
+typedef struct _MetaMonitorManagerClass    MetaMonitorManagerClass;
+typedef struct _MetaMonitorManager         MetaMonitorManager;
+typedef struct _MetaMonitorConfigClass    MetaMonitorConfigClass;
+typedef struct _MetaMonitorConfig         MetaMonitorConfig;
+
 #ifndef HAVE_WAYLAND
 enum wl_output_transform {
   WL_OUTPUT_TRANSFORM_NORMAL,
@@ -194,6 +201,14 @@ struct _MetaOutputInfo {
   gboolean     is_presentation;
 };
 
+typedef enum {
+  META_POWER_SAVE_UNKNOWN = -1,
+  META_POWER_SAVE_ON = 0,
+  META_POWER_SAVE_STANDBY,
+  META_POWER_SAVE_SUSPEND,
+  META_POWER_SAVE_OFF,
+} MetaPowerSave;
+
 #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))
@@ -201,12 +216,88 @@ struct _MetaOutputInfo {
 #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;
+struct _MetaMonitorManager
+{
+  MetaDBusDisplayConfigSkeleton parent_instance;
+
+  /* XXX: this structure is very badly
+     packed, but I like the logical organization
+     of fields */
+
+  gboolean in_init;
+  unsigned int serial;
+
+  MetaPowerSave power_save_mode;
+
+  int max_screen_width;
+  int max_screen_height;
+  int screen_width;
+  int screen_height;
+
+  /* Outputs refer to physical screens,
+     CRTCs refer to stuff that can drive outputs
+     (like encoders, but less tied to the HW),
+     while monitor_infos refer to logical ones.
+
+     See also the comment in monitor-private.h
+  */
+  MetaOutput *outputs;
+  unsigned int n_outputs;
+
+  MetaMonitorMode *modes;
+  unsigned int n_modes;
+
+  MetaCRTC *crtcs;
+  unsigned int n_crtcs;
+
+  MetaMonitorInfo *monitor_infos;
+  unsigned int n_monitor_infos;
+  int primary_monitor_index;
+
+  int dbus_name_id;
+
+  int persistent_timeout_id;
+  MetaMonitorConfig *config;
+};
+
+struct _MetaMonitorManagerClass
+{
+  MetaDBusDisplayConfigSkeletonClass parent_class;
+
+  void (*read_current) (MetaMonitorManager *);
+  void (*apply_configuration) (MetaMonitorManager  *,
+                               MetaCRTCInfo       **,
+                               unsigned int         ,
+                               MetaOutputInfo     **,
+                               unsigned int);
+
+  void (*set_power_save_mode) (MetaMonitorManager *,
+                               MetaPowerSave);
+
+  void (*change_backlight) (MetaMonitorManager *,
+                            MetaOutput         *,
+                            int);
+
+  void (*get_crtc_gamma) (MetaMonitorManager  *,
+                          MetaCRTC            *,
+                          gsize               *,
+                          unsigned short     **,
+                          unsigned short     **,
+                          unsigned short     **);
+  void (*set_crtc_gamma) (MetaMonitorManager *,
+                          MetaCRTC           *,
+                          gsize               ,
+                          unsigned short     *,
+                          unsigned short     *,
+                          unsigned short     *);
+
+  gboolean (*handle_xevent) (MetaMonitorManager *,
+                             XEvent             *);
+};
 
 GType meta_monitor_manager_get_type (void);
 
-void                meta_monitor_manager_initialize (Display *display);
+void                meta_monitor_manager_initialize (void);
 MetaMonitorManager *meta_monitor_manager_get  (void);
 
 MetaMonitorInfo    *meta_monitor_manager_get_monitor_infos (MetaMonitorManager *manager,
@@ -245,6 +336,18 @@ void                meta_monitor_manager_apply_configuration (MetaMonitorManager
 void                meta_monitor_manager_confirm_configuration (MetaMonitorManager *manager,
                                                                 gboolean            ok);
 
+#define META_TYPE_MONITOR_MANAGER_XRANDR            (meta_monitor_manager_xrandr_get_type ())
+#define META_MONITOR_MANAGER_XRANDR(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandr))
+#define META_MONITOR_MANAGER_XRANDR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  
META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandrClass))
+#define META_IS_MONITOR_MANAGER_XRANDR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
META_TYPE_MONITOR_MANAGER_XRANDR))
+#define META_IS_MONITOR_MANAGER_XRANDR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  
META_TYPE_MONITOR_MANAGER_XRANDR))
+#define META_MONITOR_MANAGER_XRANDR_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  
META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandrClass))
+
+typedef struct _MetaMonitorManagerXrandrClass    MetaMonitorManagerXrandrClass;
+typedef struct _MetaMonitorManagerXrandr         MetaMonitorManagerXrandr;
+
+GType meta_monitor_manager_xrandr_get_type (void);
+
 #define META_TYPE_MONITOR_CONFIG            (meta_monitor_config_get_type ())
 #define META_MONITOR_CONFIG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_CONFIG, 
MetaMonitorConfig))
 #define META_MONITOR_CONFIG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_MONITOR_CONFIG, 
MetaMonitorConfigClass))
@@ -252,9 +355,6 @@ void                meta_monitor_manager_confirm_configuration (MetaMonitorManag
 #define META_IS_MONITOR_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_MONITOR_CONFIG))
 #define META_MONITOR_CONFIG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_MONITOR_CONFIG, 
MetaMonitorConfigClass))
 
-typedef struct _MetaMonitorConfigClass    MetaMonitorConfigClass;
-typedef struct _MetaMonitorConfig         MetaMonitorConfig;
-
 GType meta_monitor_config_get_type (void) G_GNUC_CONST;
 
 MetaMonitorConfig *meta_monitor_config_new (void);
diff --git a/src/core/monitor-xrandr.c b/src/core/monitor-xrandr.c
new file mode 100644
index 0000000..68ae61f
--- /dev/null
+++ b/src/core/monitor-xrandr.c
@@ -0,0 +1,776 @@
+/* -*- 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 <string.h>
+#include <stdlib.h>
+#include <clutter/clutter.h>
+
+#include <X11/Xatom.h>
+#include <X11/extensions/Xrandr.h>
+#include <X11/extensions/dpms.h>
+
+#include <meta/main.h>
+#include <meta/errors.h>
+#include "monitor-private.h"
+
+#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
+
+struct _MetaMonitorManagerXrandr
+{
+  MetaMonitorManager parent_instance;
+
+  Display *xdisplay;
+  XRRScreenResources *resources;
+  int time;
+  int rr_event_base;
+  int rr_error_base;
+};
+
+struct _MetaMonitorManagerXrandrClass
+{
+  MetaMonitorManagerClass parent_class;
+};
+
+G_DEFINE_TYPE (MetaMonitorManagerXrandr, meta_monitor_manager_xrandr, META_TYPE_MONITOR_MANAGER);
+
+static enum wl_output_transform
+wl_transform_from_xrandr (Rotation rotation)
+{
+  static const enum wl_output_transform y_reflected_map[4] = {
+    WL_OUTPUT_TRANSFORM_FLIPPED_180,
+    WL_OUTPUT_TRANSFORM_FLIPPED_90,
+    WL_OUTPUT_TRANSFORM_FLIPPED,
+    WL_OUTPUT_TRANSFORM_FLIPPED_270
+  };
+  enum wl_output_transform ret;
+
+  switch (rotation & 0x7F)
+    {
+    default:
+    case RR_Rotate_0:
+      ret = WL_OUTPUT_TRANSFORM_NORMAL;
+      break;
+    case RR_Rotate_90:
+      ret = WL_OUTPUT_TRANSFORM_90;
+      break;
+    case RR_Rotate_180:
+      ret = WL_OUTPUT_TRANSFORM_180;
+      break;
+    case RR_Rotate_270:
+      ret = WL_OUTPUT_TRANSFORM_270;
+      break;
+    }
+
+  if (rotation & RR_Reflect_X)
+    return ret + 4;
+  else if (rotation & RR_Reflect_Y)
+    return y_reflected_map[ret];
+  else
+    return ret;
+}
+
+#define ALL_ROTATIONS (RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270)
+
+static unsigned int
+wl_transform_from_xrandr_all (Rotation rotation)
+{
+  unsigned ret;
+
+  /* Handle the common cases first (none or all) */
+  if (rotation == 0 || rotation == RR_Rotate_0)
+    return (1 << WL_OUTPUT_TRANSFORM_NORMAL);
+
+  /* All rotations and one reflection -> all of them by composition */
+  if ((rotation & ALL_ROTATIONS) &&
+      ((rotation & RR_Reflect_X) || (rotation & RR_Reflect_Y)))
+    return ALL_WL_TRANSFORMS;
+
+  ret = 1 << WL_OUTPUT_TRANSFORM_NORMAL;
+  if (rotation & RR_Rotate_90)
+    ret |= 1 << WL_OUTPUT_TRANSFORM_90;
+  if (rotation & RR_Rotate_180)
+    ret |= 1 << WL_OUTPUT_TRANSFORM_180;
+  if (rotation & RR_Rotate_270)
+    ret |= 1 << WL_OUTPUT_TRANSFORM_270;
+  if (rotation & (RR_Rotate_0 | RR_Reflect_X))
+    ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED;
+  if (rotation & (RR_Rotate_90 | RR_Reflect_X))
+    ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_90;
+  if (rotation & (RR_Rotate_180 | RR_Reflect_X))
+    ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_180;
+  if (rotation & (RR_Rotate_270 | RR_Reflect_X))
+    ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_270;
+
+  return ret;
+}
+
+static gboolean
+output_get_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
+                                MetaOutput               *output)
+{
+  MetaDisplay *display = meta_get_display ();
+  gboolean value;
+  Atom actual_type;
+  int actual_format;
+  unsigned long nitems, bytes_after;
+  unsigned char *buffer;
+
+  XRRGetOutputProperty (manager_xrandr->xdisplay,
+                        (XID)output->output_id,
+                        display->atom__MUTTER_PRESENTATION_OUTPUT,
+                        0, G_MAXLONG, False, False, XA_CARDINAL,
+                        &actual_type, &actual_format,
+                        &nitems, &bytes_after, &buffer);
+
+  if (actual_type != XA_CARDINAL || actual_format != 32 ||
+      nitems < 1)
+    return FALSE;
+
+  value = ((int*)buffer)[0];
+
+  XFree (buffer);
+  return value;
+}
+
+static int
+normalize_backlight (MetaOutput *output,
+                     int         hw_value)
+{
+  return round((double)(hw_value - output->backlight_min) /
+               (output->backlight_max - output->backlight_min) * 100.0);
+}
+
+static int
+output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
+                             MetaOutput               *output)
+{
+  MetaDisplay *display = meta_get_display ();
+  gboolean value;
+  Atom actual_type;
+  int actual_format;
+  unsigned long nitems, bytes_after;
+  unsigned char *buffer;
+
+  XRRGetOutputProperty (manager_xrandr->xdisplay,
+                        (XID)output->output_id,
+                        display->atom_BACKLIGHT,
+                        0, G_MAXLONG, False, False, XA_INTEGER,
+                        &actual_type, &actual_format,
+                        &nitems, &bytes_after, &buffer);
+
+  if (actual_type != XA_INTEGER || actual_format != 32 ||
+      nitems < 1)
+    return -1;
+
+  value = ((int*)buffer)[0];
+
+  XFree (buffer);
+  return normalize_backlight (output, value);
+}
+
+static void
+output_get_backlight_limits_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
+                                    MetaOutput               *output)
+{
+  MetaDisplay *display = meta_get_display ();
+  XRRPropertyInfo *info;
+
+  meta_error_trap_push (display);
+  info = XRRQueryOutputProperty (manager_xrandr->xdisplay,
+                                 (XID)output->output_id,
+                                 display->atom_BACKLIGHT);
+  meta_error_trap_pop (display);
+
+  if (info == NULL)
+    {
+      meta_verbose ("could not get output property for %s\n", output->name);
+      return;
+    }
+
+  if (!info->range || info->num_values != 2)
+    {
+      meta_verbose ("backlight %s was not range\n", output->name);
+      goto out;
+    }
+
+  output->backlight_min = info->values[0];
+  output->backlight_max = info->values[1];
+
+out:
+  XFree (info);
+}
+
+static int
+compare_outputs (const void *one,
+                 const void *two)
+{
+  const MetaOutput *o_one = one, *o_two = two;
+
+  return strcmp (o_one->name, o_two->name);
+}
+
+static void
+meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
+{
+  MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
+  XRRScreenResources *resources;
+  RROutput primary_output;
+  unsigned int i, j, k;
+  unsigned int n_actual_outputs;
+  int min_width, min_height;
+  Screen *screen;
+  BOOL dpms_capable, dpms_enabled;
+  CARD16 dpms_state;
+
+  if (manager_xrandr->resources)
+    XRRFreeScreenResources (manager_xrandr->resources);
+  manager_xrandr->resources = NULL;
+
+  meta_error_trap_push (meta_get_display ());
+  dpms_capable = DPMSCapable (manager_xrandr->xdisplay);
+  meta_error_trap_pop (meta_get_display ());
+
+  if (dpms_capable &&
+      DPMSInfo (manager_xrandr->xdisplay, &dpms_state, &dpms_enabled) &&
+      dpms_enabled)
+    {
+      switch (dpms_state)
+       {
+       case DPMSModeOn:
+         manager->power_save_mode = META_POWER_SAVE_ON;
+       case DPMSModeStandby:
+         manager->power_save_mode = META_POWER_SAVE_STANDBY;
+       case DPMSModeSuspend:
+         manager->power_save_mode = META_POWER_SAVE_SUSPEND;
+       case DPMSModeOff:
+         manager->power_save_mode = META_POWER_SAVE_OFF;
+       default:
+         manager->power_save_mode = META_POWER_SAVE_UNKNOWN;
+       }
+    }
+  else
+    {
+      manager->power_save_mode = META_POWER_SAVE_UNKNOWN;
+    }
+
+  XRRGetScreenSizeRange (manager_xrandr->xdisplay, DefaultRootWindow (manager_xrandr->xdisplay),
+                        &min_width,
+                        &min_height,
+                        &manager->max_screen_width,
+                        &manager->max_screen_height);
+
+  screen = ScreenOfDisplay (manager_xrandr->xdisplay,
+                           DefaultScreen (manager_xrandr->xdisplay));
+  /* This is updated because we called RRUpdateConfiguration below */
+  manager->screen_width = WidthOfScreen (screen);
+  manager->screen_height = HeightOfScreen (screen);
+
+  resources = XRRGetScreenResourcesCurrent (manager_xrandr->xdisplay,
+                                           DefaultRootWindow (manager_xrandr->xdisplay));
+  if (!resources)
+    return;
+
+  manager_xrandr->resources = resources;
+  manager_xrandr->time = resources->configTimestamp;
+  manager->n_outputs = resources->noutput;
+  manager->n_crtcs = resources->ncrtc;
+  manager->n_modes = resources->nmode;
+  manager->outputs = g_new0 (MetaOutput, manager->n_outputs);
+  manager->modes = g_new0 (MetaMonitorMode, manager->n_modes);
+  manager->crtcs = g_new0 (MetaCRTC, manager->n_crtcs);
+
+  for (i = 0; i < (unsigned)resources->nmode; i++)
+    {
+      XRRModeInfo *xmode = &resources->modes[i];
+      MetaMonitorMode *mode;
+
+      mode = &manager->modes[i];
+
+      mode->mode_id = xmode->id;
+      mode->width = xmode->width;
+      mode->height = xmode->height;
+      mode->refresh_rate = (xmode->dotClock /
+                           ((float)xmode->hTotal * xmode->vTotal));
+    }
+
+  for (i = 0; i < (unsigned)resources->ncrtc; i++)
+    {
+      XRRCrtcInfo *crtc;
+      MetaCRTC *meta_crtc;
+
+      crtc = XRRGetCrtcInfo (manager_xrandr->xdisplay, resources, resources->crtcs[i]);
+
+      meta_crtc = &manager->crtcs[i];
+
+      meta_crtc->crtc_id = resources->crtcs[i];
+      meta_crtc->rect.x = crtc->x;
+      meta_crtc->rect.y = crtc->y;
+      meta_crtc->rect.width = crtc->width;
+      meta_crtc->rect.height = crtc->height;
+      meta_crtc->dirty = FALSE;
+      meta_crtc->transform = wl_transform_from_xrandr (crtc->rotation);
+      meta_crtc->all_transforms = wl_transform_from_xrandr_all (crtc->rotations);
+
+      for (j = 0; j < (unsigned)resources->nmode; j++)
+       {
+         if (resources->modes[j].id == crtc->mode)
+           {
+             meta_crtc->current_mode = &manager->modes[j];
+             break;
+           }
+       }
+
+      XRRFreeCrtcInfo (crtc);
+    }
+
+  primary_output = XRRGetOutputPrimary (manager_xrandr->xdisplay,
+                                       DefaultRootWindow (manager_xrandr->xdisplay));
+
+  n_actual_outputs = 0;
+  for (i = 0; i < (unsigned)resources->noutput; i++)
+    {
+      XRROutputInfo *output;
+      MetaOutput *meta_output;
+
+      output = XRRGetOutputInfo (manager_xrandr->xdisplay, resources, resources->outputs[i]);
+
+      meta_output = &manager->outputs[n_actual_outputs];
+
+      if (output->connection != RR_Disconnected)
+       {
+         meta_output->output_id = resources->outputs[i];
+         meta_output->name = g_strdup (output->name);
+         meta_output->vendor = g_strdup ("unknown");
+         meta_output->product = g_strdup ("unknown");
+         meta_output->serial = g_strdup ("");
+         meta_output->width_mm = output->mm_width;
+         meta_output->height_mm = output->mm_height;
+         meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
+
+         meta_output->n_modes = output->nmode;
+         meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
+         for (j = 0; j < meta_output->n_modes; j++)
+           {
+             for (k = 0; k < manager->n_modes; k++)
+               {
+                 if (output->modes[j] == (XID)manager->modes[k].mode_id)
+                   {
+                     meta_output->modes[j] = &manager->modes[k];
+                     break;
+                   }
+               }
+           }
+         meta_output->preferred_mode = meta_output->modes[0];
+
+         meta_output->n_possible_crtcs = output->ncrtc;
+         meta_output->possible_crtcs = g_new0 (MetaCRTC *, meta_output->n_possible_crtcs);
+         for (j = 0; j < (unsigned)output->ncrtc; j++)
+           {
+             for (k = 0; k < manager->n_crtcs; k++)
+               {
+                 if ((XID)manager->crtcs[k].crtc_id == output->crtcs[j])
+                   {
+                     meta_output->possible_crtcs[j] = &manager->crtcs[k];
+                     break;
+                   }
+               }
+           }
+
+         meta_output->crtc = NULL;
+         for (j = 0; j < manager->n_crtcs; j++)
+           {
+             if ((XID)manager->crtcs[j].crtc_id == output->crtc)
+               {
+                 meta_output->crtc = &manager->crtcs[j];
+                 break;
+               }
+           }
+
+         meta_output->n_possible_clones = output->nclone;
+         meta_output->possible_clones = g_new0 (MetaOutput *, meta_output->n_possible_clones);
+         /* We can build the list of clones now, because we don't have the list of outputs
+            yet, so temporarily set the pointers to the bare XIDs, and then we'll fix them
+            in a second pass
+         */
+         for (j = 0; j < (unsigned)output->nclone; j++)
+           {
+             meta_output->possible_clones = GINT_TO_POINTER (output->clones[j]);
+           }
+
+         meta_output->is_primary = ((XID)meta_output->output_id == primary_output);
+         meta_output->is_presentation = output_get_presentation_xrandr (manager_xrandr, meta_output);
+         output_get_backlight_limits_xrandr (manager_xrandr, meta_output);
+
+         if (!(meta_output->backlight_min == 0 && meta_output->backlight_max == 0))
+           meta_output->backlight = output_get_backlight_xrandr (manager_xrandr, meta_output);
+         else
+           meta_output->backlight = -1;
+
+         n_actual_outputs++;
+       }
+
+      XRRFreeOutputInfo (output);
+    }
+
+  manager->n_outputs = n_actual_outputs;
+
+  /* Sort the outputs for easier handling in MetaMonitorConfig */
+  qsort (manager->outputs, manager->n_outputs, sizeof (MetaOutput), compare_outputs);
+
+  /* Now fix the clones */
+  for (i = 0; i < manager->n_outputs; i++)
+    {
+      MetaOutput *meta_output;
+
+      meta_output = &manager->outputs[i];
+
+      for (j = 0; j < meta_output->n_possible_clones; j++)
+       {
+         RROutput clone = GPOINTER_TO_INT (meta_output->possible_clones[j]);
+
+         for (k = 0; k < manager->n_outputs; k++)
+           {
+             if (clone == (XID)manager->outputs[k].output_id)
+               {
+                 meta_output->possible_clones[j] = &manager->outputs[k];
+                 break;
+               }
+           }
+       }
+    }
+}
+
+static void
+meta_monitor_manager_xrandr_set_power_save_mode (MetaMonitorManager *manager,
+                                                MetaPowerSave       mode)
+{
+  MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
+  CARD16 state;
+
+  switch (mode) {
+  case META_POWER_SAVE_ON:
+    state = DPMSModeOn;
+    break;
+  case META_POWER_SAVE_STANDBY:
+    state = DPMSModeStandby;
+    break;
+  case META_POWER_SAVE_SUSPEND:
+    state = DPMSModeSuspend;
+    break;
+  case META_POWER_SAVE_OFF:
+    state = DPMSModeOff;
+    break;
+  default:
+    return;
+  }
+
+  meta_error_trap_push (meta_get_display ());
+  DPMSForceLevel (manager_xrandr->xdisplay, state);
+  DPMSSetTimeouts (manager_xrandr->xdisplay, 0, 0, 0);
+  meta_error_trap_pop (meta_get_display ());
+}
+
+static Rotation
+wl_transform_to_xrandr (enum wl_output_transform transform)
+{
+  switch (transform)
+    {
+    case WL_OUTPUT_TRANSFORM_NORMAL:
+      return RR_Rotate_0;
+    case WL_OUTPUT_TRANSFORM_90:
+      return RR_Rotate_90;
+    case WL_OUTPUT_TRANSFORM_180:
+      return RR_Rotate_180;
+    case WL_OUTPUT_TRANSFORM_270:
+      return RR_Rotate_270;
+    case WL_OUTPUT_TRANSFORM_FLIPPED:
+      return RR_Reflect_X | RR_Rotate_0;
+    case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+      return RR_Reflect_X | RR_Rotate_90;
+    case WL_OUTPUT_TRANSFORM_FLIPPED_180:
+      return RR_Reflect_X | RR_Rotate_180;
+    case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+      return RR_Reflect_X | RR_Rotate_270;
+    }
+
+  g_assert_not_reached ();
+}
+
+static void
+output_set_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
+                                MetaOutput               *output,
+                                gboolean                  presentation)
+{
+  MetaDisplay *display = meta_get_display ();
+  int value = presentation;
+
+  XRRChangeOutputProperty (manager_xrandr->xdisplay,
+                           (XID)output->output_id,
+                           display->atom__MUTTER_PRESENTATION_OUTPUT,
+                           XA_CARDINAL, 32, PropModeReplace,
+                           (unsigned char*) &value, 1);
+}
+
+static void
+meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
+                                                MetaCRTCInfo       **crtcs,
+                                                unsigned int         n_crtcs,
+                                                MetaOutputInfo     **outputs,
+                                                unsigned int         n_outputs)
+{
+  MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
+  unsigned i;
+
+  meta_display_grab (meta_get_display ());
+
+  for (i = 0; i < n_crtcs; i++)
+    {
+      MetaCRTCInfo *crtc_info = crtcs[i];
+      MetaCRTC *crtc = crtc_info->crtc;
+      crtc->dirty = TRUE;
+
+      if (crtc_info->mode == NULL)
+        {
+          XRRSetCrtcConfig (manager_xrandr->xdisplay,
+                            manager_xrandr->resources,
+                            (XID)crtc->crtc_id,
+                            manager_xrandr->time,
+                            0, 0,
+                            None,
+                            RR_Rotate_0,
+                            NULL, 0);
+        }
+      else
+        {
+          MetaMonitorMode *mode;
+          XID *outputs;
+          int j, n_outputs;
+          Status ok;
+
+          mode = crtc_info->mode;
+
+          n_outputs = crtc_info->outputs->len;
+          outputs = g_new (XID, n_outputs);
+
+          for (j = 0; j < n_outputs; j++)
+            outputs[j] = ((MetaOutput**)crtc_info->outputs->pdata)[j]->output_id;
+
+          meta_error_trap_push (meta_get_display ());
+          ok = XRRSetCrtcConfig (manager_xrandr->xdisplay,
+                                 manager_xrandr->resources,
+                                 (XID)crtc->crtc_id,
+                                 manager_xrandr->time,
+                                 crtc_info->x, crtc_info->y,
+                                 (XID)mode->mode_id,
+                                 wl_transform_to_xrandr (crtc_info->transform),
+                                 outputs, n_outputs);
+          meta_error_trap_pop (meta_get_display ());
+
+          if (ok != Success)
+            meta_warning ("Configuring CRTC %d with mode %d (%d x %d @ %f) at position %d, %d and transfrom 
%u failed\n",
+                          (unsigned)(crtc - manager->crtcs), (unsigned)(mode - manager->modes),
+                          mode->width, mode->height, (float)mode->refresh_rate,
+                          crtc_info->x, crtc_info->y, crtc_info->transform);
+
+          g_free (outputs);
+        }
+    }
+
+  for (i = 0; i < n_outputs; i++)
+    {
+      MetaOutputInfo *output_info = outputs[i];
+
+      if (output_info->is_primary)
+        {
+          XRRSetOutputPrimary (manager_xrandr->xdisplay,
+                               DefaultRootWindow (manager_xrandr->xdisplay),
+                               (XID)output_info->output->output_id);
+        }
+
+      output_set_presentation_xrandr (manager_xrandr,
+                                      output_info->output,
+                                      output_info->is_presentation);
+    }
+
+  /* Disable CRTCs not mentioned in the list */
+  for (i = 0; i < manager->n_crtcs; i++)
+    {
+      MetaCRTC *crtc = &manager->crtcs[i];
+
+      if (crtc->dirty)
+        {
+          crtc->dirty = FALSE;
+          continue;
+        }
+      if (crtc->current_mode == NULL)
+        continue;
+
+      XRRSetCrtcConfig (manager_xrandr->xdisplay,
+                        manager_xrandr->resources,
+                        (XID)crtc->crtc_id,
+                        manager_xrandr->time,
+                        0, 0,
+                        None,
+                        RR_Rotate_0,
+                        NULL, 0);
+    }
+
+  meta_display_ungrab (meta_get_display ());
+}
+
+static void
+meta_monitor_manager_xrandr_change_backlight (MetaMonitorManager *manager,
+                                             MetaOutput         *output,
+                                             gint                value)
+{
+  MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
+  MetaDisplay *display = meta_get_display ();
+  int hw_value;
+
+  hw_value = round((double)value / 100.0 * output->backlight_max + output->backlight_min);
+
+  meta_error_trap_push (display);
+  XRRChangeOutputProperty (manager_xrandr->xdisplay,
+                           (XID)output->output_id,
+                           display->atom_BACKLIGHT,
+                           XA_INTEGER, 32, PropModeReplace,
+                           (unsigned char *) &hw_value, 1);
+  meta_error_trap_pop (display);
+
+  /* We're not selecting for property notifies, so update the value immediately */
+  output->backlight = normalize_backlight (output, hw_value);
+}
+
+static void
+meta_monitor_manager_xrandr_get_crtc_gamma (MetaMonitorManager  *manager,
+                                           MetaCRTC            *crtc,
+                                           gsize               *size,
+                                           unsigned short     **red,
+                                           unsigned short     **green,
+                                           unsigned short     **blue)
+{
+  MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
+  XRRCrtcGamma *gamma;
+
+  gamma = XRRGetCrtcGamma (manager_xrandr->xdisplay, (XID)crtc->crtc_id);
+
+  *size = gamma->size;
+  *red = g_memdup (gamma->red, sizeof (unsigned short) * gamma->size);
+  *green = g_memdup (gamma->green, sizeof (unsigned short) * gamma->size);
+  *blue = g_memdup (gamma->blue, sizeof (unsigned short) * gamma->size);
+
+  XRRFreeGamma (gamma);
+}
+
+static void
+meta_monitor_manager_xrandr_set_crtc_gamma (MetaMonitorManager *manager,
+                                           MetaCRTC           *crtc,
+                                           gsize               size,
+                                           unsigned short     *red,
+                                           unsigned short     *green,
+                                           unsigned short     *blue)
+{
+  MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
+  XRRCrtcGamma gamma;
+
+  gamma.size = size;
+  gamma.red = red;
+  gamma.green = green;
+  gamma.blue = blue;
+
+  XRRSetCrtcGamma (manager_xrandr->xdisplay, (XID)crtc->crtc_id, &gamma);
+}
+
+static gboolean
+meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManager *manager,
+                                          XEvent             *event)
+{
+  MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
+
+  if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify)
+    return FALSE;
+
+  XRRUpdateConfiguration (event);
+  return TRUE;
+}
+
+static void
+meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr)
+{
+  MetaDisplay *display = meta_get_display ();
+
+  manager_xrandr->xdisplay = display->xdisplay;
+
+  if (!XRRQueryExtension (manager_xrandr->xdisplay,
+                         &manager_xrandr->rr_event_base,
+                         &manager_xrandr->rr_error_base))
+    {
+      return;
+    }
+  else
+    {
+      /* We only use ScreenChangeNotify, but GDK uses the others,
+        and we don't want to step on its toes */
+      XRRSelectInput (manager_xrandr->xdisplay,
+                     DefaultRootWindow (manager_xrandr->xdisplay),
+                     RRScreenChangeNotifyMask
+                     | RRCrtcChangeNotifyMask
+                     | RROutputPropertyNotifyMask);
+    }
+}
+
+static void
+meta_monitor_manager_xrandr_finalize (GObject *object)
+{
+  MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (object);
+
+  if (manager_xrandr->resources)
+    XRRFreeScreenResources (manager_xrandr->resources);
+  manager_xrandr->resources = NULL;
+
+  G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->finalize (object);
+}
+
+static void
+meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass)
+{
+  MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = meta_monitor_manager_xrandr_finalize;
+
+  manager_class->read_current = meta_monitor_manager_xrandr_read_current;
+  manager_class->apply_configuration = meta_monitor_manager_xrandr_apply_configuration;
+  manager_class->set_power_save_mode = meta_monitor_manager_xrandr_set_power_save_mode;
+  manager_class->change_backlight = meta_monitor_manager_xrandr_change_backlight;
+  manager_class->get_crtc_gamma = meta_monitor_manager_xrandr_get_crtc_gamma;
+  manager_class->set_crtc_gamma = meta_monitor_manager_xrandr_set_crtc_gamma;
+  manager_class->handle_xevent = meta_monitor_manager_xrandr_handle_xevent;
+}
+
diff --git a/src/core/monitor.c b/src/core/monitor.c
index b2a9265..07a6b20 100644
--- a/src/core/monitor.c
+++ b/src/core/monitor.c
@@ -31,97 +31,14 @@
 #include <stdlib.h>
 #include <clutter/clutter.h>
 
-#ifdef HAVE_RANDR
-#include <X11/Xatom.h>
-#include <X11/extensions/Xrandr.h>
-#include <X11/extensions/dpms.h>
-#endif
-
 #include <meta/main.h>
 #include <meta/errors.h>
 #include "monitor-private.h"
-#ifdef HAVE_WAYLAND
-#include "meta-wayland-private.h"
-#endif
 
 #include "meta-dbus-xrandr.h"
 
 #define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
 
-typedef enum {
-  META_POWER_SAVE_UNKNOWN = -1,
-  META_POWER_SAVE_ON = 0,
-  META_POWER_SAVE_STANDBY,
-  META_POWER_SAVE_SUSPEND,
-  META_POWER_SAVE_OFF,
-} MetaPowerSave;
-
-typedef enum {
-  META_BACKEND_UNSPECIFIED,
-  META_BACKEND_DUMMY,
-  META_BACKEND_XRANDR,
-} MetaMonitorBackend;
-
-
-struct _MetaMonitorManager
-{
-  MetaDBusDisplayConfigSkeleton parent_instance;
-
-  MetaMonitorBackend backend;
-
-  /* XXX: this structure is very badly
-     packed, but I like the logical organization
-     of fields */
-
-  gboolean in_init;
-  unsigned int serial;
-
-  MetaPowerSave power_save_mode;
-
-  int max_screen_width;
-  int max_screen_height;
-  int screen_width;
-  int screen_height;
-
-  /* Outputs refer to physical screens,
-     CRTCs refer to stuff that can drive outputs
-     (like encoders, but less tied to the HW),
-     while monitor_infos refer to logical ones.
-
-     See also the comment in monitor-private.h
-  */
-  MetaOutput *outputs;
-  unsigned int n_outputs;
-
-  MetaMonitorMode *modes;
-  unsigned int n_modes;
-
-  MetaCRTC *crtcs;
-  unsigned int n_crtcs;
-
-  MetaMonitorInfo *monitor_infos;
-  unsigned int n_monitor_infos;
-  int primary_monitor_index;
-
-#ifdef HAVE_RANDR
-  Display *xdisplay;
-  XRRScreenResources *resources;
-  int time;
-  int rr_event_base;
-  int rr_error_base;
-#endif
-
-  int dbus_name_id;
-
-  int persistent_timeout_id;
-  MetaMonitorConfig *config;
-};
-
-struct _MetaMonitorManagerClass
-{
-  MetaDBusDisplayConfigSkeletonClass parent_class;
-};
-
 enum {
   MONITORS_CHANGED,
   CONFIRM_DISPLAY_CHANGE,
@@ -144,9 +61,10 @@ G_DEFINE_TYPE_WITH_CODE (MetaMonitorManager, meta_monitor_manager, META_DBUS_TYP
 static void free_output_array (MetaOutput *old_outputs,
                                int         n_old_outputs);
 static void invalidate_logical_config (MetaMonitorManager *manager);
+static void initialize_dbus_interface (MetaMonitorManager *manager);
 
 static void
-make_dummy_monitor_config (MetaMonitorManager *manager)
+read_current_dummy (MetaMonitorManager *manager)
 {
   /* The dummy monitor config has:
      - one enabled output, LVDS, primary, at 0x0 and 1024x768
@@ -159,8 +77,6 @@ make_dummy_monitor_config (MetaMonitorManager *manager)
      mimick what XRandR and KMS do
   */
 
-  manager->backend = META_BACKEND_DUMMY;
-
   manager->max_screen_width = 65535;
   manager->max_screen_height = 65535;
   manager->screen_width = 1024;
@@ -320,440 +236,107 @@ make_dummy_monitor_config (MetaMonitorManager *manager)
   manager->outputs[2].backlight_max = 0;
 }
 
-#ifdef HAVE_RANDR
-static enum wl_output_transform
-wl_transform_from_xrandr (Rotation rotation)
-{
-  static const enum wl_output_transform y_reflected_map[4] = {
-    WL_OUTPUT_TRANSFORM_FLIPPED_180,
-    WL_OUTPUT_TRANSFORM_FLIPPED_90,
-    WL_OUTPUT_TRANSFORM_FLIPPED,
-    WL_OUTPUT_TRANSFORM_FLIPPED_270
-  };
-  enum wl_output_transform ret;
-
-  switch (rotation & 0x7F)
-    {
-    default:
-    case RR_Rotate_0:
-      ret = WL_OUTPUT_TRANSFORM_NORMAL;
-      break;
-    case RR_Rotate_90:
-      ret = WL_OUTPUT_TRANSFORM_90;
-      break;
-    case RR_Rotate_180:
-      ret = WL_OUTPUT_TRANSFORM_180;
-      break;
-    case RR_Rotate_270:
-      ret = WL_OUTPUT_TRANSFORM_270;
-      break;
-    }
-
-  if (rotation & RR_Reflect_X)
-    return ret + 4;
-  else if (rotation & RR_Reflect_Y)
-    return y_reflected_map[ret];
-  else
-    return ret;
-}
-
-#define ALL_ROTATIONS (RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270)
-
-static unsigned int
-wl_transform_from_xrandr_all (Rotation rotation)
-{
-  unsigned ret;
-
-  /* Handle the common cases first (none or all) */
-  if (rotation == 0 || rotation == RR_Rotate_0)
-    return (1 << WL_OUTPUT_TRANSFORM_NORMAL);
-
-  /* All rotations and one reflection -> all of them by composition */
-  if ((rotation & ALL_ROTATIONS) &&
-      ((rotation & RR_Reflect_X) || (rotation & RR_Reflect_Y)))
-    return ALL_WL_TRANSFORMS;
-
-  ret = 1 << WL_OUTPUT_TRANSFORM_NORMAL;
-  if (rotation & RR_Rotate_90)
-    ret |= 1 << WL_OUTPUT_TRANSFORM_90;
-  if (rotation & RR_Rotate_180)
-    ret |= 1 << WL_OUTPUT_TRANSFORM_180;
-  if (rotation & RR_Rotate_270)
-    ret |= 1 << WL_OUTPUT_TRANSFORM_270;
-  if (rotation & (RR_Rotate_0 | RR_Reflect_X))
-    ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED;
-  if (rotation & (RR_Rotate_90 | RR_Reflect_X))
-    ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_90;
-  if (rotation & (RR_Rotate_180 | RR_Reflect_X))
-    ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_180;
-  if (rotation & (RR_Rotate_270 | RR_Reflect_X))
-    ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_270;
-
-  return ret;
-}
-
-static gboolean
-output_get_presentation_xrandr (MetaMonitorManager *manager,
-                                MetaOutput         *output)
+static void
+apply_config_dummy (MetaMonitorManager *manager,
+                    MetaCRTCInfo       **crtcs,
+                    unsigned int         n_crtcs,
+                    MetaOutputInfo     **outputs,
+                    unsigned int         n_outputs)
 {
-  MetaDisplay *display = meta_get_display ();
-  gboolean value;
-  Atom actual_type;
-  int actual_format;
-  unsigned long nitems, bytes_after;
-  unsigned char *buffer;
-
-  XRRGetOutputProperty (manager->xdisplay,
-                        (XID)output->output_id,
-                        display->atom__MUTTER_PRESENTATION_OUTPUT,
-                        0, G_MAXLONG, False, False, XA_CARDINAL,
-                        &actual_type, &actual_format,
-                        &nitems, &bytes_after, &buffer);
-
-  if (actual_type != XA_CARDINAL || actual_format != 32 ||
-      nitems < 1)
-    return FALSE;
+  unsigned i;
+  int screen_width = 0, screen_height = 0;
 
-  value = ((int*)buffer)[0];
+  for (i = 0; i < n_crtcs; i++)
+    {
+      MetaCRTCInfo *crtc_info = crtcs[i];
+      MetaCRTC *crtc = crtc_info->crtc;
+      crtc->dirty = TRUE;
 
-  XFree (buffer);
-  return value;
-}
+      if (crtc_info->mode == NULL)
+        {
+          crtc->rect.x = 0;
+          crtc->rect.y = 0;
+          crtc->rect.width = 0;
+          crtc->rect.height = 0;
+          crtc->current_mode = NULL;
+        }
+      else
+        {
+          MetaMonitorMode *mode;
+          MetaOutput *output;
+          int i, n_outputs;
 
-static int
-normalize_backlight (MetaOutput *output,
-                     int         hw_value)
-{
-  return round((double)(hw_value - output->backlight_min) /
-               (output->backlight_max - output->backlight_min) * 100.0);
-}
+          mode = crtc_info->mode;
 
-static int
-output_get_backlight_xrandr (MetaMonitorManager *manager,
-                             MetaOutput         *output)
-{
-  MetaDisplay *display = meta_get_display ();
-  gboolean value;
-  Atom actual_type;
-  int actual_format;
-  unsigned long nitems, bytes_after;
-  unsigned char *buffer;
-
-  XRRGetOutputProperty (manager->xdisplay,
-                        (XID)output->output_id,
-                        display->atom_BACKLIGHT,
-                        0, G_MAXLONG, False, False, XA_INTEGER,
-                        &actual_type, &actual_format,
-                        &nitems, &bytes_after, &buffer);
-
-  if (actual_type != XA_INTEGER || actual_format != 32 ||
-      nitems < 1)
-    return -1;
-
-  value = ((int*)buffer)[0];
-
-  XFree (buffer);
-  return normalize_backlight (output, value);
-}
+          crtc->rect.x = crtc_info->x;
+          crtc->rect.y = crtc_info->y;
+          crtc->rect.width = mode->width;
+          crtc->rect.height = mode->height;
+          crtc->current_mode = mode;
+          crtc->transform = crtc_info->transform;
 
-static void
-output_get_backlight_limits_xrandr (MetaMonitorManager *manager,
-                                    MetaOutput         *output)
-{
-  MetaDisplay *display = meta_get_display ();
-  XRRPropertyInfo *info;
+          screen_width = MAX (screen_width, crtc_info->x + mode->width);
+          screen_height = MAX (screen_height, crtc_info->y + mode->height);
 
-  meta_error_trap_push (display);
-  info = XRRQueryOutputProperty (manager->xdisplay,
-                                 (XID)output->output_id,
-                                 display->atom_BACKLIGHT);
-  meta_error_trap_pop (display);
+          n_outputs = crtc_info->outputs->len;
+          for (i = 0; i < n_outputs; i++)
+            {
+              output = ((MetaOutput**)crtc_info->outputs->pdata)[i];
 
-  if (info == NULL)
-    {
-      meta_warning ("could not get output property for %s\n", output->name);
-      return;
+              output->dirty = TRUE;
+              output->crtc = crtc;
+            }
+        }
     }
 
-  if (!info->range || info->num_values != 2)
+  for (i = 0; i < n_outputs; i++)
     {
-      meta_verbose ("backlight %s was not range\n", output->name);
-      goto out;
+      MetaOutputInfo *output_info = outputs[i];
+      MetaOutput *output = output_info->output;
+
+      output->is_primary = output_info->is_primary;
+      output->is_presentation = output_info->is_presentation;
     }
 
-  output->backlight_min = info->values[0];
-  output->backlight_max = info->values[1];
+  /* Disable CRTCs not mentioned in the list */
+  for (i = 0; i < manager->n_crtcs; i++)
+    {
+      MetaCRTC *crtc = &manager->crtcs[i];
 
-out:
-  XFree (info);
-}
+      crtc->logical_monitor = NULL;
 
-static int
-compare_outputs (const void *one,
-                 const void *two)
-{
-  const MetaOutput *o_one = one, *o_two = two;
+      if (crtc->dirty)
+        {
+          crtc->dirty = FALSE;
+          continue;
+        }
 
-  return strcmp (o_one->name, o_two->name);
-}
+      crtc->rect.x = 0;
+      crtc->rect.y = 0;
+      crtc->rect.width = 0;
+      crtc->rect.height = 0;
+      crtc->current_mode = NULL;
+    }
 
-static void
-read_monitor_infos_from_xrandr (MetaMonitorManager *manager)
-{
-    XRRScreenResources *resources;
-    RROutput primary_output;
-    unsigned int i, j, k;
-    unsigned int n_actual_outputs;
-    int min_width, min_height;
-    Screen *screen;
-    BOOL dpms_capable, dpms_enabled;
-    CARD16 dpms_state;
-
-    if (manager->resources)
-      XRRFreeScreenResources (manager->resources);
-    manager->resources = NULL;
-
-    meta_error_trap_push (meta_get_display ());
-    dpms_capable = DPMSCapable (manager->xdisplay);
-    meta_error_trap_pop (meta_get_display ());
-
-    if (dpms_capable &&
-        DPMSInfo (manager->xdisplay, &dpms_state, &dpms_enabled) &&
-        dpms_enabled)
-      {
-        switch (dpms_state)
-          {
-          case DPMSModeOn:
-            manager->power_save_mode = META_POWER_SAVE_ON;
-          case DPMSModeStandby:
-            manager->power_save_mode = META_POWER_SAVE_STANDBY;
-          case DPMSModeSuspend:
-            manager->power_save_mode = META_POWER_SAVE_SUSPEND;
-          case DPMSModeOff:
-            manager->power_save_mode = META_POWER_SAVE_OFF;
-          default:
-            manager->power_save_mode = META_POWER_SAVE_UNKNOWN;
-          }
-      }
-    else
-      {
-        manager->power_save_mode = META_POWER_SAVE_UNKNOWN;
-      }
-
-    XRRGetScreenSizeRange (manager->xdisplay, DefaultRootWindow (manager->xdisplay),
-                           &min_width,
-                           &min_height,
-                           &manager->max_screen_width,
-                           &manager->max_screen_height);
-
-    screen = ScreenOfDisplay (manager->xdisplay,
-                              DefaultScreen (manager->xdisplay));
-    /* This is updated because we called RRUpdateConfiguration below */
-    manager->screen_width = WidthOfScreen (screen);
-    manager->screen_height = HeightOfScreen (screen);
-
-    resources = XRRGetScreenResourcesCurrent (manager->xdisplay,
-                                              DefaultRootWindow (manager->xdisplay));
-    if (!resources)
-      return make_dummy_monitor_config (manager);
-
-    manager->resources = resources;
-    manager->time = resources->configTimestamp;
-    manager->n_outputs = resources->noutput;
-    manager->n_crtcs = resources->ncrtc;
-    manager->n_modes = resources->nmode;
-    manager->outputs = g_new0 (MetaOutput, manager->n_outputs);
-    manager->modes = g_new0 (MetaMonitorMode, manager->n_modes);
-    manager->crtcs = g_new0 (MetaCRTC, manager->n_crtcs);
-
-    for (i = 0; i < (unsigned)resources->nmode; i++)
-      {
-        XRRModeInfo *xmode = &resources->modes[i];
-        MetaMonitorMode *mode;
-
-        mode = &manager->modes[i];
-
-        mode->mode_id = xmode->id;
-        mode->width = xmode->width;
-        mode->height = xmode->height;
-        mode->refresh_rate = (xmode->dotClock /
-                              ((float)xmode->hTotal * xmode->vTotal));
-      }
-
-    for (i = 0; i < (unsigned)resources->ncrtc; i++)
-      {
-        XRRCrtcInfo *crtc;
-        MetaCRTC *meta_crtc;
-
-        crtc = XRRGetCrtcInfo (manager->xdisplay, resources, resources->crtcs[i]);
-
-        meta_crtc = &manager->crtcs[i];
-
-        meta_crtc->crtc_id = resources->crtcs[i];
-        meta_crtc->rect.x = crtc->x;
-        meta_crtc->rect.y = crtc->y;
-        meta_crtc->rect.width = crtc->width;
-        meta_crtc->rect.height = crtc->height;
-        meta_crtc->dirty = FALSE;
-        meta_crtc->transform = wl_transform_from_xrandr (crtc->rotation);
-        meta_crtc->all_transforms = wl_transform_from_xrandr_all (crtc->rotations);
-
-        for (j = 0; j < (unsigned)resources->nmode; j++)
-          {
-            if (resources->modes[j].id == crtc->mode)
-              {
-                meta_crtc->current_mode = &manager->modes[j];
-                break;
-              }
-          }
-
-        XRRFreeCrtcInfo (crtc);
-      }
-
-    primary_output = XRRGetOutputPrimary (manager->xdisplay,
-                                          DefaultRootWindow (manager->xdisplay));
-
-    n_actual_outputs = 0;
-    for (i = 0; i < (unsigned)resources->noutput; i++)
-      {
-        XRROutputInfo *output;
-        MetaOutput *meta_output;
-
-        output = XRRGetOutputInfo (manager->xdisplay, resources, resources->outputs[i]);
-
-        meta_output = &manager->outputs[n_actual_outputs];
-
-        if (output->connection != RR_Disconnected)
-          {
-            meta_output->output_id = resources->outputs[i];
-            meta_output->name = g_strdup (output->name);
-            meta_output->vendor = g_strdup ("unknown");
-            meta_output->product = g_strdup ("unknown");
-            meta_output->serial = g_strdup ("");
-            meta_output->width_mm = output->mm_width;
-            meta_output->height_mm = output->mm_height;
-            meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
-
-            meta_output->n_modes = output->nmode;
-            meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
-            for (j = 0; j < meta_output->n_modes; j++)
-              {
-                for (k = 0; k < manager->n_modes; k++)
-                  {
-                    if (output->modes[j] == (XID)manager->modes[k].mode_id)
-                      {
-                        meta_output->modes[j] = &manager->modes[k];
-                        break;
-                      }
-                  }
-              }
-            meta_output->preferred_mode = &meta_output->modes[0];
-
-            if (meta_output->preferred_mode == NULL)
-              meta_output->preferred_mode = meta_output->modes[0];
-
-            meta_output->n_possible_crtcs = output->ncrtc;
-            meta_output->possible_crtcs = g_new0 (MetaCRTC *, meta_output->n_possible_crtcs);
-            for (j = 0; j < (unsigned)output->ncrtc; j++)
-              {
-                for (k = 0; k < manager->n_crtcs; k++)
-                  {
-                    if ((XID)manager->crtcs[k].crtc_id == output->crtcs[j])
-                      {
-                        meta_output->possible_crtcs[j] = &manager->crtcs[k];
-                        break;
-                      }
-                  }
-              }
-
-            meta_output->crtc = NULL;
-            for (j = 0; j < manager->n_crtcs; j++)
-              {
-                if ((XID)manager->crtcs[j].crtc_id == output->crtc)
-                  {
-                    meta_output->crtc = &manager->crtcs[j];
-                    break;
-                  }
-              }
-
-            meta_output->n_possible_clones = output->nclone;
-            meta_output->possible_clones = g_new0 (MetaOutput *, meta_output->n_possible_clones);
-            /* We can build the list of clones now, because we don't have the list of outputs
-               yet, so temporarily set the pointers to the bare XIDs, and then we'll fix them
-               in a second pass
-            */
-            for (j = 0; j < (unsigned)output->nclone; j++)
-              {
-                meta_output->possible_clones = GINT_TO_POINTER (output->clones[j]);
-              }
-
-            meta_output->is_primary = ((XID)meta_output->output_id == primary_output);
-            meta_output->is_presentation = output_get_presentation_xrandr (manager, meta_output);
-            output_get_backlight_limits_xrandr (manager, meta_output);
-
-            if (!(meta_output->backlight_min == 0 && meta_output->backlight_max == 0))
-              meta_output->backlight = output_get_backlight_xrandr (manager, meta_output);
-            else
-              meta_output->backlight = -1;
-
-            n_actual_outputs++;
-          }
-
-        XRRFreeOutputInfo (output);
-      }
-
-    manager->n_outputs = n_actual_outputs;
-
-    /* Sort the outputs for easier handling in MetaMonitorConfig */
-    qsort (manager->outputs, manager->n_outputs, sizeof (MetaOutput), compare_outputs);
-
-    /* Now fix the clones */
-    for (i = 0; i < manager->n_outputs; i++)
-      {
-        MetaOutput *meta_output;
-
-        meta_output = &manager->outputs[i];
-
-        for (j = 0; j < meta_output->n_possible_clones; j++)
-          {
-            RROutput clone = GPOINTER_TO_INT (meta_output->possible_clones[j]);
-
-            for (k = 0; k < manager->n_outputs; k++)
-              {
-                if (clone == (XID)manager->outputs[k].output_id)
-                  {
-                    meta_output->possible_clones[j] = &manager->outputs[k];
-                    break;
-                  }
-              }
-          }
-      }
-}
+  /* Disable outputs not mentioned in the list */
+  for (i = 0; i < manager->n_outputs; i++)
+    {
+      MetaOutput *output = &manager->outputs[i];
 
-#endif
+      if (output->dirty)
+        {
+          output->dirty = FALSE;
+          continue;
+        }
 
-/*
- * 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)
-{
-#ifdef HAVE_WAYLAND
-  MetaWaylandCompositor *compositor;
+      output->crtc = NULL;
+      output->is_primary = FALSE;
+    }
 
-  if (!meta_is_display_server ())
-    return FALSE;
+  manager->screen_width = screen_width;
+  manager->screen_height = screen_height;
 
-  /* 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);
-#else
-  return FALSE;
-#endif
+  invalidate_logical_config (manager);
 }
 
 static void
@@ -761,37 +344,12 @@ meta_monitor_manager_init (MetaMonitorManager *manager)
 {
 }
 
-static MetaMonitorBackend
-make_debug_config (MetaMonitorManager *manager)
-{
-  const char *env;
-
-  env = g_getenv ("META_DEBUG_MULTIMONITOR");
-
-  if (env == NULL)
-    return META_BACKEND_UNSPECIFIED;
-
-#ifdef HAVE_RANDR
-  if (strcmp (env, "xrandr") == 0)
-    return META_BACKEND_XRANDR;
-  else
-#endif
-    return META_BACKEND_DUMMY;
-
-  return TRUE;
-}
-
 static void
 read_current_config (MetaMonitorManager *manager)
 {
   manager->serial++;
 
-#ifdef HAVE_RANDR
-  if (manager->backend == META_BACKEND_XRANDR)
-    return read_monitor_infos_from_xrandr (manager);
-#endif
-
-  return make_dummy_monitor_config (manager);
+  META_MONITOR_MANAGER_GET_CLASS (manager)->read_current (manager);
 }
 
 /*
@@ -890,48 +448,35 @@ make_logical_config (MetaMonitorManager *manager)
 }
 
 static MetaMonitorManager *
-meta_monitor_manager_new (Display *display)
+meta_monitor_manager_new (void)
 {
-  MetaMonitorManager *manager;
-
-  manager = g_object_new (META_TYPE_MONITOR_MANAGER, NULL);
-
-  manager->in_init = TRUE;
-  manager->xdisplay = display;
+  const char *env;
+  GType type;
 
-  manager->backend = make_debug_config (manager);
+  env = g_getenv ("META_DEBUG_MULTIMONITOR");
 
-  if (manager->backend == META_BACKEND_UNSPECIFIED)
+  if (env == NULL)
     {
-#ifdef HAVE_XRANDR
-      if (display)
-        manager->backend = META_BACKEND_XRANDR;
+      if (!meta_is_display_server ())
+        type = META_TYPE_MONITOR_MANAGER_XRANDR;
       else
-#endif
-        if (has_dummy_output ())
-          manager->backend = META_BACKEND_DUMMY;
+        type = META_TYPE_MONITOR_MANAGER;
     }
+  else if (strcmp (env, "xrandr") == 0)
+    type = META_TYPE_MONITOR_MANAGER_XRANDR;
+  else
+    type = META_TYPE_MONITOR_MANAGER;
+
+  return g_object_new (type, NULL);
+}
+
+static void
+meta_monitor_manager_constructed (GObject *object)
+{
+  MetaMonitorManager *manager = META_MONITOR_MANAGER (object);
+
+  manager->in_init = TRUE;
 
-#ifdef HAVE_XRANDR
-  if (manager->backend == META_BACKEND_XRANDR)
-    {
-      if (!XRRQueryExtension (display,
-                              &manager->rr_event_base,
-                              &manager->rr_error_base))
-        {
-          manager->backend = META_BACKEND_DUMMY;
-        }
-      else
-        {
-          /* We only use ScreenChangeNotify, but GDK uses the others,
-             and we don't want to step on its toes */
-          XRRSelectInput (display, DefaultRootWindow (display),
-                          RRScreenChangeNotifyMask
-                          | RRCrtcChangeNotifyMask
-                          | RROutputPropertyNotifyMask);
-        }
-    }
-#endif
   manager->config = meta_monitor_config_new ();
 
   read_current_config (manager);
@@ -946,7 +491,7 @@ meta_monitor_manager_new (Display *display)
      The other backends keep the data structures always updated,
      so this is not needed.
   */
-  if (manager->backend == META_BACKEND_XRANDR)
+  if (META_IS_MONITOR_MANAGER_XRANDR (manager))
     {
       MetaOutput *old_outputs;
       MetaCRTC *old_crtcs;
@@ -966,15 +511,17 @@ meta_monitor_manager_new (Display *display)
     }
 
   make_logical_config (manager);
+  initialize_dbus_interface (manager);
 
   manager->in_init = FALSE;
-  return manager;
 }
 
 static void
 meta_monitor_manager_set_power_save_mode (MetaMonitorManager *manager,
                                           MetaPowerSave       mode)
 {
+  MetaMonitorManagerClass *klass;
+
   if (mode == manager->power_save_mode)
     return;
 
@@ -982,34 +529,9 @@ meta_monitor_manager_set_power_save_mode (MetaMonitorManager *manager,
       mode == META_POWER_SAVE_UNKNOWN)
     return;
 
-#ifdef HAVE_RANDR
-  if (manager->backend == META_BACKEND_XRANDR)
-    {
-      CARD16 state;
-
-      switch (mode) {
-      case META_POWER_SAVE_ON:
-        state = DPMSModeOn;
-        break;
-      case META_POWER_SAVE_STANDBY:
-        state = DPMSModeStandby;
-        break;
-      case META_POWER_SAVE_SUSPEND:
-        state = DPMSModeSuspend;
-        break;
-      case META_POWER_SAVE_OFF:
-        state = DPMSModeOff;
-        break;
-      default:
-        return;
-      }
-
-      meta_error_trap_push (meta_get_display ());
-      DPMSForceLevel (manager->xdisplay, state);
-      DPMSSetTimeouts (manager->xdisplay, 0, 0, 0);
-      meta_error_trap_pop (meta_get_display ());
-    }
-#endif
+  klass = META_MONITOR_MANAGER_GET_CLASS (manager);
+  if (klass->set_power_save_mode)
+    klass->set_power_save_mode (manager, mode);
 
   manager->power_save_mode = mode;
 }
@@ -1104,11 +626,15 @@ meta_monitor_manager_class_init (MetaMonitorManagerClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
+  object_class->constructed = meta_monitor_manager_constructed;
   object_class->get_property = meta_monitor_manager_get_property;
   object_class->set_property = meta_monitor_manager_set_property;
   object_class->dispose = meta_monitor_manager_dispose;
   object_class->finalize = meta_monitor_manager_finalize;
 
+  klass->read_current = read_current_dummy;
+  klass->apply_configuration = apply_config_dummy;
+
   signals[MONITORS_CHANGED] =
     g_signal_new ("monitors-changed",
                  G_TYPE_FROM_CLASS (object_class),
@@ -1268,254 +794,6 @@ output_can_clone (MetaOutput *output,
   return ok;
 }
 
-#ifdef HAVE_RANDR
-static Rotation
-wl_transform_to_xrandr (enum wl_output_transform transform)
-{
-  switch (transform)
-    {
-    case WL_OUTPUT_TRANSFORM_NORMAL:
-      return RR_Rotate_0;
-    case WL_OUTPUT_TRANSFORM_90:
-      return RR_Rotate_90;
-    case WL_OUTPUT_TRANSFORM_180:
-      return RR_Rotate_180;
-    case WL_OUTPUT_TRANSFORM_270:
-      return RR_Rotate_270;
-    case WL_OUTPUT_TRANSFORM_FLIPPED:
-      return RR_Reflect_X | RR_Rotate_0;
-    case WL_OUTPUT_TRANSFORM_FLIPPED_90:
-      return RR_Reflect_X | RR_Rotate_90;
-    case WL_OUTPUT_TRANSFORM_FLIPPED_180:
-      return RR_Reflect_X | RR_Rotate_180;
-    case WL_OUTPUT_TRANSFORM_FLIPPED_270:
-      return RR_Reflect_X | RR_Rotate_270;
-    }
-
-  g_assert_not_reached ();
-}
-
-static void
-output_set_presentation_xrandr (MetaMonitorManager *manager,
-                                MetaOutput         *output,
-                                gboolean            presentation)
-{
-  MetaDisplay *display = meta_get_display ();
-  int value = presentation;
-
-  XRRChangeOutputProperty (manager->xdisplay,
-                           (XID)output->output_id,
-                           display->atom__MUTTER_PRESENTATION_OUTPUT,
-                           XA_CARDINAL, 32, PropModeReplace,
-                           (unsigned char*) &value, 1);
-}
-
-static void
-apply_config_xrandr (MetaMonitorManager *manager,
-                     MetaCRTCInfo       **crtcs,
-                     unsigned int         n_crtcs,
-                     MetaOutputInfo     **outputs,
-                     unsigned int         n_outputs)
-{
-  unsigned i;
-
-  for (i = 0; i < n_crtcs; i++)
-    {
-      MetaCRTCInfo *crtc_info = crtcs[i];
-      MetaCRTC *crtc = crtc_info->crtc;
-      crtc->dirty = TRUE;
-
-      if (crtc_info->mode == NULL)
-        {
-          XRRSetCrtcConfig (manager->xdisplay,
-                            manager->resources,
-                            (XID)crtc->crtc_id,
-                            manager->time,
-                            0, 0,
-                            None,
-                            RR_Rotate_0,
-                            NULL, 0);
-        }
-      else
-        {
-          MetaMonitorMode *mode;
-          XID *outputs;
-          int j, n_outputs;
-          Status ok;
-
-          mode = crtc_info->mode;
-
-          n_outputs = crtc_info->outputs->len;
-          outputs = g_new (XID, n_outputs);
-
-          for (j = 0; j < n_outputs; j++)
-            outputs[i] = ((MetaOutput**)crtc_info->outputs->pdata)[i]->output_id;
-
-          meta_error_trap_push (meta_get_display ());
-          ok = XRRSetCrtcConfig (manager->xdisplay,
-                                 manager->resources,
-                                 (XID)crtc->crtc_id,
-                                 manager->time,
-                                 crtc_info->x, crtc_info->y,
-                                 (XID)mode->mode_id,
-                                 wl_transform_to_xrandr (crtc_info->transform),
-                                 outputs, n_outputs);
-          meta_error_trap_pop (meta_get_display ());
-
-          if (ok != Success)
-            meta_warning ("Configuring CRTC %d with mode %d (%d x %d @ %f) at position %d, %d and transfrom 
%u failed\n",
-                          (unsigned)(crtc - manager->crtcs), (unsigned)(mode - manager->modes),
-                          mode->width, mode->height, (float)mode->refresh_rate,
-                          crtc_info->x, crtc_info->y, crtc_info->transform);
-
-          g_free (outputs);
-        }
-    }
-
-  for (i = 0; i < n_outputs; i++)
-    {
-      MetaOutputInfo *output_info = outputs[i];
-
-      if (output_info->is_primary)
-        {
-          XRRSetOutputPrimary (manager->xdisplay,
-                               DefaultRootWindow (manager->xdisplay),
-                               (XID)output_info->output->output_id);
-        }
-
-      output_set_presentation_xrandr (manager,
-                                      output_info->output,
-                                      output_info->is_presentation);
-    }
-
-  /* Disable CRTCs not mentioned in the list */
-  for (i = 0; i < manager->n_crtcs; i++)
-    {
-      MetaCRTC *crtc = &manager->crtcs[i];
-
-      if (crtc->dirty)
-        {
-          crtc->dirty = FALSE;
-          continue;
-        }
-      if (crtc->current_mode == NULL)
-        continue;
-
-      XRRSetCrtcConfig (manager->xdisplay,
-                        manager->resources,
-                        (XID)crtc->crtc_id,
-                        manager->time,
-                        0, 0,
-                        None,
-                        RR_Rotate_0,
-                        NULL, 0);
-    }
-}
-#endif
-
-static void
-apply_config_dummy (MetaMonitorManager *manager,
-                    MetaCRTCInfo       **crtcs,
-                    unsigned int         n_crtcs,
-                    MetaOutputInfo     **outputs,
-                    unsigned int         n_outputs)
-{
-  unsigned i;
-  int screen_width = 0, screen_height = 0;
-
-  for (i = 0; i < n_crtcs; i++)
-    {
-      MetaCRTCInfo *crtc_info = crtcs[i];
-      MetaCRTC *crtc = crtc_info->crtc;
-      crtc->dirty = TRUE;
-
-      if (crtc_info->mode == NULL)
-        {
-          crtc->rect.x = 0;
-          crtc->rect.y = 0;
-          crtc->rect.width = 0;
-          crtc->rect.height = 0;
-          crtc->current_mode = NULL;
-        }
-      else
-        {
-          MetaMonitorMode *mode;
-          MetaOutput *output;
-          int i, n_outputs;
-
-          mode = crtc_info->mode;
-
-          crtc->rect.x = crtc_info->x;
-          crtc->rect.y = crtc_info->y;
-          crtc->rect.width = mode->width;
-          crtc->rect.height = mode->height;
-          crtc->current_mode = mode;
-          crtc->transform = crtc_info->transform;
-
-          screen_width = MAX (screen_width, crtc_info->x + mode->width);
-          screen_height = MAX (screen_height, crtc_info->y + mode->height);
-
-          n_outputs = crtc_info->outputs->len;
-          for (i = 0; i < n_outputs; i++)
-            {
-              output = ((MetaOutput**)crtc_info->outputs->pdata)[i];
-
-              output->dirty = TRUE;
-              output->crtc = crtc;
-            }
-        }
-    }
-
-  for (i = 0; i < n_outputs; i++)
-    {
-      MetaOutputInfo *output_info = outputs[i];
-      MetaOutput *output = output_info->output;
-
-      output->is_primary = output_info->is_primary;
-      output->is_presentation = output_info->is_presentation;
-    }
-
-  /* Disable CRTCs not mentioned in the list */
-  for (i = 0; i < manager->n_crtcs; i++)
-    {
-      MetaCRTC *crtc = &manager->crtcs[i];
-
-      crtc->logical_monitor = NULL;
-
-      if (crtc->dirty)
-        {
-          crtc->dirty = FALSE;
-          continue;
-        }
-
-      crtc->rect.x = 0;
-      crtc->rect.y = 0;
-      crtc->rect.width = 0;
-      crtc->rect.height = 0;
-      crtc->current_mode = NULL;
-    }
-
-  /* Disable outputs not mentioned in the list */
-  for (i = 0; i < manager->n_outputs; i++)
-    {
-      MetaOutput *output = &manager->outputs[i];
-
-      if (output->dirty)
-        {
-          output->dirty = FALSE;
-          continue;
-        }
-
-      output->crtc = NULL;
-      output->is_primary = FALSE;
-    }
-
-  manager->screen_width = screen_width;
-  manager->screen_height = screen_height;
-
-  invalidate_logical_config (manager);
-}
-
 void
 meta_monitor_manager_apply_configuration (MetaMonitorManager *manager,
                                           MetaCRTCInfo       **crtcs,
@@ -1523,10 +801,9 @@ meta_monitor_manager_apply_configuration (MetaMonitorManager *manager,
                                           MetaOutputInfo     **outputs,
                                           unsigned int         n_outputs)
 {
-  if (manager->backend == META_BACKEND_XRANDR)
-    apply_config_xrandr (manager, crtcs, n_crtcs, outputs, n_outputs);
-  else
-    apply_config_dummy (manager, crtcs, n_crtcs, outputs, n_outputs);
+  META_MONITOR_MANAGER_GET_CLASS (manager)->apply_configuration (manager,
+                                                                 crtcs, n_crtcs,
+                                                                 outputs, n_outputs);
 }
 
 static gboolean
@@ -1778,38 +1055,6 @@ meta_monitor_manager_confirm_configuration (MetaMonitorManager *manager,
     meta_monitor_config_restore_previous (manager->config, manager);
 }
 
-#ifdef HAVE_RANDR
-static void
-handle_change_backlight_xrandr (MetaMonitorManager *manager,
-                                MetaOutput         *output,
-                                gint                value)
-{
-  MetaDisplay *display = meta_get_display ();
-  int hw_value;
-
-  hw_value = round((double)value / 100.0 * output->backlight_max + output->backlight_min);
-
-  meta_error_trap_push (display);
-  XRRChangeOutputProperty (manager->xdisplay,
-                           (XID)output->output_id,
-                           display->atom_BACKLIGHT,
-                           XA_INTEGER, 32, PropModeReplace,
-                           (unsigned char *) &hw_value, 1);
-  meta_error_trap_pop (display);
-
-  /* We're not selecting for property notifies, so update the value immediately */
-  output->backlight = normalize_backlight (output, hw_value);
-}
-#endif
-
-static void
-handle_change_backlight_dummy (MetaMonitorManager *manager,
-                               MetaOutput         *output,
-                               gint                value)
-{
-  g_assert_not_reached ();
-}
-
 static gboolean
 meta_monitor_manager_handle_change_backlight  (MetaDBusDisplayConfig *skeleton,
                                                GDBusMethodInvocation *invocation,
@@ -1854,51 +1099,12 @@ meta_monitor_manager_handle_change_backlight  (MetaDBusDisplayConfig *skeleton,
       return TRUE;
     }
 
-  if (manager->backend == META_BACKEND_XRANDR)
-    handle_change_backlight_xrandr (manager, output, value);
-  else
-    handle_change_backlight_dummy (manager, output, value);
+  META_MONITOR_MANAGER_GET_CLASS (manager)->change_backlight (manager, output, value);
 
   meta_dbus_display_config_complete_change_backlight (skeleton, invocation);
   return TRUE;
 }
 
-#ifdef HAVE_RANDR
-static void
-handle_get_crtc_gamma_xrandr (MetaMonitorManager  *manager,
-                              MetaCRTC            *crtc,
-                              gsize               *size,
-                              unsigned short     **red,
-                              unsigned short     **green,
-                              unsigned short     **blue)
-{
-  XRRCrtcGamma *gamma;
-
-  gamma = XRRGetCrtcGamma (manager->xdisplay, (XID)crtc->crtc_id);
-
-  *size = gamma->size;
-  *red = g_memdup (gamma->red, sizeof (unsigned short) * gamma->size);
-  *green = g_memdup (gamma->green, sizeof (unsigned short) * gamma->size);
-  *blue = g_memdup (gamma->blue, sizeof (unsigned short) * gamma->size);
-
-  XRRFreeGamma (gamma);
-}
-#endif
-
-static void
-handle_get_crtc_gamma_dummy (MetaMonitorManager  *manager,
-                             MetaCRTC            *crtc,
-                             gsize               *size,
-                             unsigned short     **red,
-                             unsigned short     **green,
-                             unsigned short     **blue)
-{
-  *size = 0;
-  *red = g_new0 (unsigned short, 0);
-  *green = g_new0 (unsigned short, 0);
-  *blue = g_new0 (unsigned short, 0);
-}
-
 static gboolean
 meta_monitor_manager_handle_get_crtc_gamma  (MetaDBusDisplayConfig *skeleton,
                                              GDBusMethodInvocation *invocation,
@@ -1906,6 +1112,7 @@ meta_monitor_manager_handle_get_crtc_gamma  (MetaDBusDisplayConfig *skeleton,
                                              guint                  crtc_id)
 {
   MetaMonitorManager *manager = META_MONITOR_MANAGER (skeleton);
+  MetaMonitorManagerClass *klass;
   MetaCRTC *crtc;
   gsize size;
   unsigned short *red;
@@ -1931,10 +1138,14 @@ meta_monitor_manager_handle_get_crtc_gamma  (MetaDBusDisplayConfig *skeleton,
     }
   crtc = &manager->crtcs[crtc_id];
 
-  if (manager->backend == META_BACKEND_XRANDR)
-    handle_get_crtc_gamma_xrandr (manager, crtc, &size, &red, &green, &blue);
+  klass = META_MONITOR_MANAGER_GET_CLASS (manager);
+  if (klass->get_crtc_gamma)
+    klass->get_crtc_gamma (manager, crtc, &size, &red, &green, &blue);
   else
-    handle_get_crtc_gamma_dummy (manager, crtc, &size, &red, &green, &blue);
+    {
+      size = 0;
+      red = green = blue = NULL;
+    }
 
   red_bytes = g_bytes_new_take (red, size * sizeof (unsigned short));
   green_bytes = g_bytes_new_take (green, size * sizeof (unsigned short));
@@ -1954,36 +1165,6 @@ meta_monitor_manager_handle_get_crtc_gamma  (MetaDBusDisplayConfig *skeleton,
   return TRUE;
 }
 
-#ifdef HAVE_RANDR
-static void
-handle_set_crtc_gamma_xrandr (MetaMonitorManager *manager,
-                              MetaCRTC           *crtc,
-                              gsize               size,
-                              unsigned short     *red,
-                              unsigned short     *green,
-                              unsigned short     *blue)
-{
-  XRRCrtcGamma gamma;
-
-  gamma.size = size;
-  gamma.red = red;
-  gamma.green = green;
-  gamma.blue = blue;
-
-  XRRSetCrtcGamma (manager->xdisplay, (XID)crtc->crtc_id, &gamma);
-}
-#endif
-
-static void
-handle_set_crtc_gamma_dummy (MetaMonitorManager *manager,
-                             MetaCRTC           *crtc,
-                             gsize               size,
-                             unsigned short     *red,
-                             unsigned short     *green,
-                             unsigned short     *blue)
-{
-}
-
 static gboolean
 meta_monitor_manager_handle_set_crtc_gamma  (MetaDBusDisplayConfig *skeleton,
                                              GDBusMethodInvocation *invocation,
@@ -1994,6 +1175,7 @@ meta_monitor_manager_handle_set_crtc_gamma  (MetaDBusDisplayConfig *skeleton,
                                              GVariant              *blue_v)
 {
   MetaMonitorManager *manager = META_MONITOR_MANAGER (skeleton);
+  MetaMonitorManagerClass *klass;
   MetaCRTC *crtc;
   gsize size, dummy;
   unsigned short *red;
@@ -2027,10 +1209,9 @@ meta_monitor_manager_handle_set_crtc_gamma  (MetaDBusDisplayConfig *skeleton,
   green = (unsigned short*) g_bytes_get_data (green_bytes, &dummy);
   blue = (unsigned short*) g_bytes_get_data (blue_bytes, &dummy);
 
-  if (manager->backend == META_BACKEND_XRANDR)
-    handle_set_crtc_gamma_xrandr (manager, crtc, size, red, green, blue);
-  else
-    handle_set_crtc_gamma_dummy (manager, crtc, size, red, green, blue);
+  klass = META_MONITOR_MANAGER_GET_CLASS (manager);
+  if (klass->set_crtc_gamma)
+    klass->set_crtc_gamma (manager, crtc, size, red, green, blue);
 
   meta_dbus_display_config_complete_set_crtc_gamma (skeleton, invocation);
 
@@ -2098,11 +1279,9 @@ initialize_dbus_interface (MetaMonitorManager *manager)
 static MetaMonitorManager *global_manager;
 
 void
-meta_monitor_manager_initialize (Display *display)
+meta_monitor_manager_initialize (void)
 {
-  global_manager = meta_monitor_manager_new (display);
-
-  initialize_dbus_interface (global_manager);
+  global_manager = meta_monitor_manager_new ();
 }
 
 MetaMonitorManager *
@@ -2191,20 +1370,22 @@ gboolean
 meta_monitor_manager_handle_xevent (MetaMonitorManager *manager,
                                     XEvent             *event)
 {
+  MetaMonitorManagerClass *klass;
   MetaOutput *old_outputs;
   MetaCRTC *old_crtcs;
   MetaMonitorMode *old_modes;
   int n_old_outputs;
+  gboolean changed;
 
-  if (manager->backend != META_BACKEND_XRANDR)
-    return FALSE;
+  klass = META_MONITOR_MANAGER_GET_CLASS (manager);
+  if (klass->handle_xevent)
+    changed = klass->handle_xevent (manager, event);
+  else
+    changed = FALSE;
 
-#ifdef HAVE_RANDR
-  if ((event->type - manager->rr_event_base) != RRScreenChangeNotify)
+  if (!changed)
     return FALSE;
 
-  XRRUpdateConfiguration (event);
-
   /* Save the old structures, so they stay valid during the update */
   old_outputs = manager->outputs;
   n_old_outputs = manager->n_outputs;
@@ -2236,8 +1417,5 @@ meta_monitor_manager_handle_xevent (MetaMonitorManager *manager,
   g_free (old_crtcs);
 
   return TRUE;
-#else
-  return FALSE;
-#endif
 }
 
diff --git a/src/core/screen.c b/src/core/screen.c
index 7b839c5..6b2feb2 100644
--- a/src/core/screen.c
+++ b/src/core/screen.c
@@ -679,7 +679,7 @@ meta_screen_new (MetaDisplay *display,
 #ifdef HAVE_WAYLAND
   if (!meta_is_display_server ())
 #endif
-    meta_monitor_manager_initialize (screen->display->xdisplay);
+    meta_monitor_manager_initialize ();
 
   manager = meta_monitor_manager_get ();
   g_signal_connect (manager, "monitors-changed",
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index 3212af9..cb23796 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -1977,7 +1977,7 @@ meta_wayland_init (void)
        }
     }
 
-  meta_monitor_manager_initialize (NULL);
+  meta_monitor_manager_initialize ();
   monitors = meta_monitor_manager_get ();
   g_signal_connect (monitors, "monitors-changed",
                    G_CALLBACK (on_monitors_changed), compositor);


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