[gnome-desktop/wip/wayland-display: 1/2] API: GnomeRR: replace direct XRandR calls with DBus calls to mutter



commit 91e5b6ed6a8e023a0e80035f5a3fed7f16917287
Author: Giovanni Campagna <gcampagn redhat com>
Date:   Fri Jul 26 13:40:41 2013 +0200

    API: GnomeRR: replace direct XRandR calls with DBus calls to mutter
    
    Mutter now provides a DBus API that wraps XRandR and abstracts
    away the detail of running X or wayland.
    
    A number of API changes are needed, as GnomeRR is no longer in
    charge of maintaining the monitors.xml file updated.

 libgnome-desktop/Makefile.am            |   12 +
 libgnome-desktop/gnome-rr-config.c      | 1032 +++------------------
 libgnome-desktop/gnome-rr-config.h      |   33 +-
 libgnome-desktop/gnome-rr-debug.c       |    2 +-
 libgnome-desktop/gnome-rr-output-info.c |   22 +-
 libgnome-desktop/gnome-rr-private.h     |   53 +-
 libgnome-desktop/gnome-rr.c             | 1534 ++++++-------------------------
 libgnome-desktop/gnome-rr.h             |   56 +-
 libgnome-desktop/xrandr.xml             |  241 +++++
 9 files changed, 769 insertions(+), 2216 deletions(-)
---
diff --git a/libgnome-desktop/Makefile.am b/libgnome-desktop/Makefile.am
index 7041be5..c19a3d5 100644
--- a/libgnome-desktop/Makefile.am
+++ b/libgnome-desktop/Makefile.am
@@ -42,6 +42,7 @@ introspection_sources =               \
 
 libgnome_desktop_3_la_SOURCES =        \
        $(introspection_sources)        \
+       $(dbus_xrandr_built_sources)    \
        gnome-datetime-source.h         \
        gnome-datetime-source.c         \
        gnome-rr-private.h              \
@@ -49,6 +50,17 @@ libgnome_desktop_3_la_SOURCES =      \
        edid.h                          \
        locarchive.h
 
+dbus_xrandr_built_sources = meta-dbus-xrandr.c meta-dbus-xrandr.h
+
+$(dbus_xrandr_built_sources) : Makefile.am xrandr.xml
+       $(AM_V_GEN)gdbus-codegen                                                        \
+               --interface-prefix org.gnome.Mutter                                     \
+               --c-namespace MetaDBus                                                  \
+               --generate-c-code meta-dbus-xrandr                                      \
+               xrandr.xml
+
+BUILT_SOURCES = $(dbus_xrandr_built_sources)
+
 libgnome_desktop_3_la_LIBADD = \
        $(XLIB_LIBS)            \
        $(LIBM)                 \
diff --git a/libgnome-desktop/gnome-rr-config.c b/libgnome-desktop/gnome-rr-config.c
index 06ff2e6..2fb1632 100644
--- a/libgnome-desktop/gnome-rr-config.c
+++ b/libgnome-desktop/gnome-rr-config.c
@@ -1,8 +1,8 @@
 /* gnome-rr-config.c
  * -*- c-basic-offset: 4 -*-
  *
- * Copyright 2007, 2008, Red Hat, Inc.
- * Copyright 2010 Giovanni Campagna
+ * Copyright 2007, 2008, 2013 Red Hat, Inc.
+ * Copyright 2010 Giovanni Campagna <scampa giovanni gmail com>
  * 
  * This file is part of the Gnome Library.
  * 
@@ -74,16 +74,10 @@
  *   </monitors>
  */
 
-/* A helper wrapper around the GMarkup parser stuff */
-static gboolean parse_file_gmarkup (const gchar *file,
-                                   const GMarkupParser *parser,
-                                   gpointer data,
-                                   GError **err);
-
 typedef struct CrtcAssignment CrtcAssignment;
 
 static gboolean         crtc_assignment_apply (CrtcAssignment   *assign,
-                                              guint32           timestamp,
+                                              gboolean          persistent,
                                               GError          **error);
 static CrtcAssignment  *crtc_assignment_new   (GnomeRRScreen      *screen,
                                               GnomeRROutputInfo **outputs,
@@ -98,357 +92,6 @@ enum {
 
 G_DEFINE_TYPE (GnomeRRConfig, gnome_rr_config, G_TYPE_OBJECT)
 
-typedef struct Parser Parser;
-
-/* Parser for monitor configurations */
-struct Parser
-{
-    int                        config_file_version;
-    GnomeRROutputInfo *        output;
-    GnomeRRConfig *    configuration;
-    GPtrArray *                outputs;
-    GPtrArray *                configurations;
-    GQueue *           stack;
-};
-
-static int
-parse_int (const char *text)
-{
-    return strtol (text, NULL, 0);
-}
-
-static guint
-parse_uint (const char *text)
-{
-    return strtoul (text, NULL, 0);
-}
-
-static gboolean
-stack_is (Parser *parser,
-         const char *s1,
-         ...)
-{
-    GList *stack = NULL;
-    const char *s;
-    GList *l1, *l2;
-    va_list args;
-    
-    stack = g_list_prepend (stack, (gpointer)s1);
-    
-    va_start (args, s1);
-    
-    s = va_arg (args, const char *);
-    while (s)
-    {
-       stack = g_list_prepend (stack, (gpointer)s);
-       s = va_arg (args, const char *);
-    }
-       
-    l1 = stack;
-    l2 = parser->stack->head;
-    
-    while (l1 && l2)
-    {
-       if (strcmp (l1->data, l2->data) != 0)
-       {
-           g_list_free (stack);
-           return FALSE;
-       }
-       
-       l1 = l1->next;
-       l2 = l2->next;
-    }
-    
-    g_list_free (stack);
-    
-    return (!l1 && !l2);
-}
-
-static void
-handle_start_element (GMarkupParseContext *context,
-                     const gchar         *name,
-                     const gchar        **attr_names,
-                     const gchar        **attr_values,
-                     gpointer             user_data,
-                     GError             **err)
-{
-    Parser *parser = user_data;
-
-    if (strcmp (name, "output") == 0)
-    {
-       int i;
-       g_assert (parser->output == NULL);
-
-       parser->output = g_object_new (GNOME_TYPE_RR_OUTPUT_INFO, NULL);
-       parser->output->priv->rotation = 0;
-       
-       for (i = 0; attr_names[i] != NULL; ++i)
-       {
-           if (strcmp (attr_names[i], "name") == 0)
-           {
-               parser->output->priv->name = g_strdup (attr_values[i]);
-               break;
-           }
-       }
-
-       if (!parser->output->priv->name)
-       {
-           /* This really shouldn't happen, but it's better to make
-            * something up than to crash later.
-            */
-           g_warning ("Malformed monitor configuration file");
-           
-           parser->output->priv->name = g_strdup ("default");
-       }       
-       parser->output->priv->connected = FALSE;
-       parser->output->priv->on = FALSE;
-       parser->output->priv->primary = FALSE;
-    }
-    else if (strcmp (name, "configuration") == 0)
-    {
-       g_assert (parser->configuration == NULL);
-       
-       parser->configuration = g_object_new (GNOME_TYPE_RR_CONFIG, NULL);
-       parser->configuration->priv->clone = FALSE;
-       parser->configuration->priv->outputs = NULL;
-    }
-    else if (strcmp (name, "monitors") == 0)
-    {
-       int i;
-
-       for (i = 0; attr_names[i] != NULL; i++)
-       {
-           if (strcmp (attr_names[i], "version") == 0)
-           {
-               parser->config_file_version = parse_int (attr_values[i]);
-               break;
-           }
-       }
-    }
-
-    g_queue_push_tail (parser->stack, g_strdup (name));
-}
-
-static void
-handle_end_element (GMarkupParseContext *context,
-                   const gchar         *name,
-                   gpointer             user_data,
-                   GError             **err)
-{
-    Parser *parser = user_data;
-    
-    if (strcmp (name, "output") == 0)
-    {
-       /* If no rotation properties were set, just use GNOME_RR_ROTATION_0 */
-       if (parser->output->priv->rotation == 0)
-           parser->output->priv->rotation = GNOME_RR_ROTATION_0;
-       
-       g_ptr_array_add (parser->outputs, parser->output);
-
-       parser->output = NULL;
-    }
-    else if (strcmp (name, "configuration") == 0)
-    {
-       g_ptr_array_add (parser->outputs, NULL);
-       parser->configuration->priv->outputs =
-           (GnomeRROutputInfo **)g_ptr_array_free (parser->outputs, FALSE);
-       parser->outputs = g_ptr_array_new ();
-       g_ptr_array_add (parser->configurations, parser->configuration);
-       parser->configuration = NULL;
-    }
-    
-    g_free (g_queue_pop_tail (parser->stack));
-}
-
-#define TOPLEVEL_ELEMENT (parser->config_file_version > 0 ? "monitors" : NULL)
-
-static void
-handle_text (GMarkupParseContext *context,
-            const gchar         *text,
-            gsize                text_len,
-            gpointer             user_data,
-            GError             **err)
-{
-    Parser *parser = user_data;
-    
-    if (stack_is (parser, "vendor", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
-    {
-       parser->output->priv->connected = TRUE;
-       
-       strncpy ((gchar*) parser->output->priv->vendor, text, 3);
-       parser->output->priv->vendor[3] = 0;
-    }
-    else if (stack_is (parser, "clone", "configuration", TOPLEVEL_ELEMENT, NULL))
-    {
-       if (strcmp (text, "yes") == 0)
-           parser->configuration->priv->clone = TRUE;
-    }
-    else if (stack_is (parser, "product", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
-    {
-       parser->output->priv->connected = TRUE;
-
-       parser->output->priv->product = parse_int (text);
-    }
-    else if (stack_is (parser, "serial", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
-    {
-       parser->output->priv->connected = TRUE;
-
-       parser->output->priv->serial = parse_uint (text);
-    }
-    else if (stack_is (parser, "width", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
-    {
-       parser->output->priv->on = TRUE;
-
-       parser->output->priv->width = parse_int (text);
-    }
-    else if (stack_is (parser, "x", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
-    {
-       parser->output->priv->on = TRUE;
-
-       parser->output->priv->x = parse_int (text);
-    }
-    else if (stack_is (parser, "y", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
-    {
-       parser->output->priv->on = TRUE;
-
-       parser->output->priv->y = parse_int (text);
-    }
-    else if (stack_is (parser, "height", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
-    {
-       parser->output->priv->on = TRUE;
-
-       parser->output->priv->height = parse_int (text);
-    }
-    else if (stack_is (parser, "rate", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
-    {
-       parser->output->priv->on = TRUE;
-
-       parser->output->priv->rate = parse_int (text);
-    }
-    else if (stack_is (parser, "rotation", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
-    {
-       if (strcmp (text, "normal") == 0)
-       {
-           parser->output->priv->rotation |= GNOME_RR_ROTATION_0;
-       }
-       else if (strcmp (text, "left") == 0)
-       {
-           parser->output->priv->rotation |= GNOME_RR_ROTATION_90;
-       }
-       else if (strcmp (text, "upside_down") == 0)
-       {
-           parser->output->priv->rotation |= GNOME_RR_ROTATION_180;
-       }
-       else if (strcmp (text, "right") == 0)
-       {
-           parser->output->priv->rotation |= GNOME_RR_ROTATION_270;
-       }
-    }
-    else if (stack_is (parser, "reflect_x", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
-    {
-       if (strcmp (text, "yes") == 0)
-       {
-           parser->output->priv->rotation |= GNOME_RR_REFLECT_X;
-       }
-    }
-    else if (stack_is (parser, "reflect_y", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
-    {
-       if (strcmp (text, "yes") == 0)
-       {
-           parser->output->priv->rotation |= GNOME_RR_REFLECT_Y;
-       }
-    }
-    else if (stack_is (parser, "primary", "output", "configuration", TOPLEVEL_ELEMENT, NULL))
-    {
-       if (strcmp (text, "yes") == 0)
-       {
-           parser->output->priv->primary = TRUE;
-       }
-    }
-    else
-    {
-       /* Ignore other properties so we can expand the format in the future */
-    }
-}
-
-static void
-parser_free (Parser *parser)
-{
-    int i;
-    GList *list;
-
-    g_assert (parser != NULL);
-
-    if (parser->output)
-       g_object_unref (parser->output);
-
-    if (parser->configuration)
-       g_object_unref (parser->configuration);
-
-    for (i = 0; i < parser->outputs->len; ++i)
-    {
-       GnomeRROutputInfo *output = parser->outputs->pdata[i];
-
-       g_object_unref (output);
-    }
-
-    g_ptr_array_free (parser->outputs, TRUE);
-
-    for (i = 0; i < parser->configurations->len; ++i)
-    {
-       GnomeRRConfig *config = parser->configurations->pdata[i];
-
-       g_object_unref (config);
-    }
-
-    g_ptr_array_free (parser->configurations, TRUE);
-
-    for (list = parser->stack->head; list; list = list->next)
-       g_free (list->data);
-    g_queue_free (parser->stack);
-    
-    g_free (parser);
-}
-
-static GnomeRRConfig **
-configurations_read_from_file (const gchar *filename, GError **error)
-{
-    Parser *parser = g_new0 (Parser, 1);
-    GnomeRRConfig **result;
-    GMarkupParser callbacks = {
-       handle_start_element,
-       handle_end_element,
-       handle_text,
-       NULL, /* passthrough */
-       NULL, /* error */
-    };
-
-    parser->config_file_version = 0;
-    parser->configurations = g_ptr_array_new ();
-    parser->outputs = g_ptr_array_new ();
-    parser->stack = g_queue_new ();
-    
-    if (!parse_file_gmarkup (filename, &callbacks, parser, error))
-    {
-       result = NULL;
-       
-       g_assert (parser->outputs);
-       goto out;
-    }
-
-    g_assert (parser->outputs);
-    
-    g_ptr_array_add (parser->configurations, NULL);
-    result = (GnomeRRConfig **)g_ptr_array_free (parser->configurations, FALSE);
-    parser->configurations = g_ptr_array_new ();
-    
-    g_assert (parser->outputs);
-out:
-    parser_free (parser);
-
-    return result;
-}
-
 static void
 gnome_rr_config_init (GnomeRRConfig *self)
 {
@@ -516,11 +159,10 @@ gnome_rr_config_load_current (GnomeRRConfig *config, GError **error)
        GnomeRROutput *rr_output = rr_outputs[i];
        GnomeRROutputInfo *output = g_object_new (GNOME_TYPE_RR_OUTPUT_INFO, NULL);
        GnomeRRMode *mode = NULL;
-       const guint8 *edid_data = gnome_rr_output_get_edid_data (rr_output, NULL);
        GnomeRRCrtc *crtc;
 
        output->priv->name = g_strdup (gnome_rr_output_get_name (rr_output));
-       output->priv->connected = gnome_rr_output_is_connected (rr_output);
+       output->priv->connected = TRUE;
        output->priv->display_name = g_strdup (gnome_rr_output_get_display_name (rr_output));
 
        if (!output->priv->connected)
@@ -534,35 +176,18 @@ gnome_rr_config_load_current (GnomeRRConfig *config, GError **error)
        }
        else
        {
-           MonitorInfo *info = NULL;
-
-           if (edid_data)
-               info = decode_edid (edid_data);
-
-           if (info)
-           {
-               memcpy (output->priv->vendor, info->manufacturer_code,
-                       sizeof (output->priv->vendor));
-               
-               output->priv->product = info->product_code;
-               output->priv->serial = info->serial_number;
-               output->priv->aspect = info->aspect_ratio;
-           }
-           else
-           {
-               strcpy (output->priv->vendor, "???");
-               output->priv->product = 0;
-               output->priv->serial = 0;
-           }
-           g_free (info);
+           gnome_rr_output_get_ids_from_edid (rr_output,
+                                              &output->priv->vendor,
+                                              &output->priv->product,
+                                              &output->priv->serial);
                
            crtc = gnome_rr_output_get_crtc (rr_output);
-           mode = crtc? gnome_rr_crtc_get_current_mode (crtc) : NULL;
-           
+           mode = crtc ? gnome_rr_crtc_get_current_mode (crtc) : NULL;
+
            if (crtc && mode)
            {
                output->priv->on = TRUE;
-               
+
                gnome_rr_crtc_get_position (crtc, &output->priv->x, &output->priv->y);
                output->priv->width = gnome_rr_mode_get_width (mode);
                output->priv->height = gnome_rr_mode_get_height (mode);
@@ -570,13 +195,13 @@ gnome_rr_config_load_current (GnomeRRConfig *config, GError **error)
                output->priv->rotation = gnome_rr_crtc_get_current_rotation (crtc);
 
                if (output->priv->x == 0 && output->priv->y == 0) {
-                       if (clone_width == -1) {
-                               clone_width = output->priv->width;
-                               clone_height = output->priv->height;
-                       } else if (clone_width == output->priv->width &&
-                                  clone_height == output->priv->height) {
-                               config->priv->clone = TRUE;
-                       }
+                   if (clone_width == -1) {
+                       clone_width = output->priv->width;
+                       clone_height = output->priv->height;
+                   } else if (clone_width == output->priv->width &&
+                              clone_height == output->priv->height) {
+                       config->priv->clone = TRUE;
+                   }
                }
            }
            else
@@ -587,36 +212,8 @@ gnome_rr_config_load_current (GnomeRRConfig *config, GError **error)
 
            /* Get preferred size for the monitor */
            mode = gnome_rr_output_get_preferred_mode (rr_output);
-           
-           if (!mode)
-           {
-               GnomeRRMode **modes = gnome_rr_output_list_modes (rr_output);
-               
-               /* FIXME: we should pick the "best" mode here, where best is
-                * sorted wrt
-                *
-                * - closest aspect ratio
-                * - mode area
-                * - refresh rate
-                * - We may want to extend randrwrap so that get_preferred
-                *   returns that - although that could also depend on
-                *   the crtc.
-                */
-               if (modes[0])
-                   mode = modes[0];
-           }
-           
-           if (mode)
-           {
-               output->priv->pref_width = gnome_rr_mode_get_width (mode);
-               output->priv->pref_height = gnome_rr_mode_get_height (mode);
-           }
-           else
-           {
-               /* Pick some random numbers. This should basically never happen */
-               output->priv->pref_width = 1024;
-               output->priv->pref_height = 768;
-           }
+           output->priv->pref_width = gnome_rr_mode_get_width (mode);
+           output->priv->pref_height = gnome_rr_mode_get_height (mode);
        }
 
         output->priv->primary = gnome_rr_output_get_is_primary (rr_output);
@@ -661,57 +258,6 @@ gnome_rr_config_load_current (GnomeRRConfig *config, GError **error)
     return TRUE;
 }
 
-gboolean
-gnome_rr_config_load_filename (GnomeRRConfig *result, const char *filename, GError **error)
-{
-    GnomeRRConfig *current;
-    GnomeRRConfig **configs;
-    gboolean found = FALSE;
-
-    g_return_val_if_fail (GNOME_IS_RR_CONFIG (result), FALSE);
-    g_return_val_if_fail (filename != NULL, FALSE);
-    g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-    current = gnome_rr_config_new_current (result->priv->screen, error);
-
-    configs = configurations_read_from_file (filename, error);
-
-    if (configs)
-    {
-       int i;
-
-       for (i = 0; configs[i] != NULL; ++i)
-       {
-           if (gnome_rr_config_match (configs[i], current))
-           {
-               int j;
-               GPtrArray *array;
-               result->priv->clone = configs[i]->priv->clone;
-
-               array = g_ptr_array_new ();
-               for (j = 0; configs[i]->priv->outputs[j] != NULL; j++) {
-                    g_object_ref (configs[i]->priv->outputs[j]);
-                   g_ptr_array_add (array, configs[i]->priv->outputs[j]);
-               }
-               g_ptr_array_add (array, NULL);
-               result->priv->outputs = (GnomeRROutputInfo **) g_ptr_array_free (array, FALSE);
-
-               found = TRUE;
-               break;
-           }
-           g_object_unref (configs[i]);
-       }
-       g_free (configs);
-
-       if (!found)
-           g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_NO_MATCHING_CONFIG,
-                        _("none of the saved display configurations matched the active configuration"));
-    }
-
-    g_object_unref (current);
-    return found;
-}
-
 static void
 gnome_rr_config_class_init (GnomeRRConfigClass *klass)
 {
@@ -741,69 +287,6 @@ gnome_rr_config_new_current (GnomeRRScreen *screen, GError **error)
       }
 }
 
-GnomeRRConfig *
-gnome_rr_config_new_stored (GnomeRRScreen *screen, GError **error)
-{
-    GnomeRRConfig *self = g_object_new (GNOME_TYPE_RR_CONFIG, "screen", screen, NULL);
-    char *filename;
-    gboolean success;
-
-    filename = gnome_rr_config_get_intended_filename ();
-
-    success = gnome_rr_config_load_filename (self, filename, error);
-
-    g_free (filename);
-
-    if (success)
-      return self;
-    else
-      {
-       g_object_unref (self);
-       return NULL;
-      }
-}
-
-static gboolean
-parse_file_gmarkup (const gchar          *filename,
-                   const GMarkupParser  *parser,
-                   gpointer             data,
-                   GError              **err)
-{
-    GMarkupParseContext *context = NULL;
-    gchar *contents = NULL;
-    gboolean result = TRUE;
-    gsize len;
-
-    if (!g_file_get_contents (filename, &contents, &len, err))
-    {
-       result = FALSE;
-       goto out;
-    }
-    
-    context = g_markup_parse_context_new (parser, 0, data, NULL);
-
-    if (!g_markup_parse_context_parse (context, contents, len, err))
-    {
-       result = FALSE;
-       goto out;
-    }
-
-    if (!g_markup_parse_context_end_parse (context, err))
-    {
-       result = FALSE;
-       goto out;
-    }
-
-out:
-    if (contents)
-       g_free (contents);
-
-    if (context)
-       g_markup_parse_context_free (context);
-
-    return result;
-}
-
 static gboolean
 output_match (GnomeRROutputInfo *output1, GnomeRROutputInfo *output2)
 {
@@ -816,13 +299,10 @@ output_match (GnomeRROutputInfo *output1, GnomeRROutputInfo *output2)
     if (strcmp (output1->priv->vendor, output2->priv->vendor) != 0)
        return FALSE;
 
-    if (output1->priv->product != output2->priv->product)
-       return FALSE;
-
-    if (output1->priv->serial != output2->priv->serial)
+    if (strcmp (output1->priv->product, output2->priv->product) != 0)
        return FALSE;
 
-    if (output1->priv->connected != output2->priv->connected)
+    if (strcmp (output1->priv->serial, output2->priv->serial) != 0)
        return FALSE;
     
     return TRUE;
@@ -1006,115 +486,6 @@ gnome_rr_config_applicable (GnomeRRConfig  *configuration,
 
 /* Database management */
 
-static void
-ensure_config_directory (void)
-{
-    g_mkdir_with_parents (g_get_user_config_dir (), 0700);
-}
-
-char *
-gnome_rr_config_get_backup_filename (void)
-{
-    ensure_config_directory ();
-    return g_build_filename (g_get_user_config_dir (), CONFIG_BACKUP_BASENAME, NULL);
-}
-
-char *
-gnome_rr_config_get_intended_filename (void)
-{
-    ensure_config_directory ();
-    return g_build_filename (g_get_user_config_dir (), CONFIG_INTENDED_BASENAME, NULL);
-}
-
-static const char *
-get_rotation_name (GnomeRRRotation r)
-{
-    if (r & GNOME_RR_ROTATION_0)
-       return "normal";
-    if (r & GNOME_RR_ROTATION_90)
-       return "left";
-    if (r & GNOME_RR_ROTATION_180)
-       return "upside_down";
-    if (r & GNOME_RR_ROTATION_270)
-       return "right";
-
-    return "normal";
-}
-
-static const char *
-yes_no (int x)
-{
-    return x? "yes" : "no";
-}
-
-static const char *
-get_reflect_x (GnomeRRRotation r)
-{
-    return yes_no (r & GNOME_RR_REFLECT_X);
-}
-
-static const char *
-get_reflect_y (GnomeRRRotation r)
-{
-    return yes_no (r & GNOME_RR_REFLECT_Y);
-}
-
-static void
-emit_configuration (GnomeRRConfig *config,
-                   GString *string)
-{
-    int j;
-
-    g_string_append_printf (string, "  <configuration>\n");
-
-    g_string_append_printf (string, "      <clone>%s</clone>\n", yes_no (config->priv->clone));
-    
-    for (j = 0; config->priv->outputs[j] != NULL; ++j)
-    {
-       GnomeRROutputInfo *output = config->priv->outputs[j];
-       
-       g_string_append_printf (
-           string, "      <output name=\"%s\">\n", output->priv->name);
-       
-       if (output->priv->connected && *output->priv->vendor != '\0')
-       {
-           g_string_append_printf (
-               string, "          <vendor>%s</vendor>\n", output->priv->vendor);
-           g_string_append_printf (
-               string, "          <product>0x%04x</product>\n", output->priv->product);
-           g_string_append_printf (
-               string, "          <serial>0x%08x</serial>\n", output->priv->serial);
-       }
-       
-       /* An unconnected output which is on does not make sense */
-       if (output->priv->connected && output->priv->on)
-       {
-           g_string_append_printf (
-               string, "          <width>%d</width>\n", output->priv->width);
-           g_string_append_printf (
-               string, "          <height>%d</height>\n", output->priv->height);
-           g_string_append_printf (
-               string, "          <rate>%d</rate>\n", output->priv->rate);
-           g_string_append_printf (
-               string, "          <x>%d</x>\n", output->priv->x);
-           g_string_append_printf (
-               string, "          <y>%d</y>\n", output->priv->y);
-           g_string_append_printf (
-               string, "          <rotation>%s</rotation>\n", get_rotation_name (output->priv->rotation));
-           g_string_append_printf (
-               string, "          <reflect_x>%s</reflect_x>\n", get_reflect_x (output->priv->rotation));
-           g_string_append_printf (
-               string, "          <reflect_y>%s</reflect_y>\n", get_reflect_y (output->priv->rotation));
-            g_string_append_printf (
-                string, "          <primary>%s</primary>\n", yes_no (output->priv->primary));
-       }
-       
-       g_string_append_printf (string, "      </output>\n");
-    }
-    
-    g_string_append_printf (string, "  </configuration>\n");
-}
-
 void
 gnome_rr_config_sanitize (GnomeRRConfig *config)
 {
@@ -1224,63 +595,11 @@ gnome_rr_config_ensure_primary (GnomeRRConfig *configuration)
         return !found;
 }
 
-gboolean
-gnome_rr_config_save (GnomeRRConfig *configuration, GError **error)
-{
-    GnomeRRConfig **configurations;
-    GString *output;
-    int i;
-    gchar *intended_filename;
-    gchar *backup_filename;
-    gboolean result;
-
-    g_return_val_if_fail (GNOME_IS_RR_CONFIG (configuration), FALSE);
-    g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-    output = g_string_new ("");
-
-    backup_filename = gnome_rr_config_get_backup_filename ();
-    intended_filename = gnome_rr_config_get_intended_filename ();
-
-    configurations = configurations_read_from_file (intended_filename, NULL); /* NULL-GError */
-    
-    g_string_append_printf (output, "<monitors version=\"1\">\n");
-
-    if (configurations)
-    {
-       for (i = 0; configurations[i] != NULL; ++i)
-       {
-           if (!gnome_rr_config_match (configurations[i], configuration))
-               emit_configuration (configurations[i], output);
-           g_object_unref (configurations[i]);
-       }
-
-       g_free (configurations);
-    }
-
-    emit_configuration (configuration, output);
-
-    g_string_append_printf (output, "</monitors>\n");
-
-    /* backup the file first */
-    rename (intended_filename, backup_filename); /* no error checking because the intended file may not even 
exist */
-
-    result = g_file_set_contents (intended_filename, output->str, -1, error);
-
-    if (!result)
-       rename (backup_filename, intended_filename); /* no error checking because the backup may not even 
exist */
-
-    g_free (backup_filename);
-    g_free (intended_filename);
-
-    return result;
-}
-
-gboolean
-gnome_rr_config_apply_with_time (GnomeRRConfig *config,
-                                GnomeRRScreen *screen,
-                                guint32        timestamp,
-                                GError       **error)
+static gboolean
+gnome_rr_config_apply_helper (GnomeRRConfig *config,
+                             GnomeRRScreen *screen,
+                             gboolean       persistent,
+                             GError       **error)
 {
     CrtcAssignment *assignment;
     GnomeRROutputInfo **outputs;
@@ -1294,76 +613,35 @@ gnome_rr_config_apply_with_time (GnomeRRConfig *config,
 
     assignment = crtc_assignment_new (screen, outputs, error);
 
-    for (i = 0; outputs[i] != NULL; i++)
-       g_object_unref (outputs[i]);
-    g_free (outputs);
-    
     if (assignment)
     {
-       if (crtc_assignment_apply (assignment, timestamp, error))
+       if (crtc_assignment_apply (assignment, persistent, error))
            result = TRUE;
 
        crtc_assignment_free (assignment);
-
-       gdk_flush ();
     }
 
+    for (i = 0; outputs[i] != NULL; i++)
+       g_object_unref (outputs[i]);
+    g_free (outputs);
+
     return result;
 }
 
-/* gnome_rr_config_apply_from_filename_with_time:
- * @screen: A #GnomeRRScreen
- * @filename: Path of the file to look in for stored RANDR configurations.
- * @timestamp: X server timestamp from the event that causes the screen configuration to change (a user's 
button press, for example)
- * @error: Location to store error, or %NULL
- *
- * Loads the file in @filename and looks for suitable matching RANDR
- * configurations in the file; if one is found, that configuration will be
- * applied to the current set of RANDR outputs.
- *
- * Typically, @filename is the result of gnome_rr_config_get_intended_filename() or
- * gnome_rr_config_get_backup_filename().
- *
- * Returns: TRUE if the RANDR configuration was loaded and applied from
- * the specified file, or FALSE otherwise:
- *
- * If the file in question is loaded successfully but the configuration cannot
- * be applied, the @error will have a domain of #GNOME_RR_ERROR.  Note that an
- * error code of #GNOME_RR_ERROR_NO_MATCHING_CONFIG is not a real error; it
- * simply means that there were no stored configurations that match the current
- * set of RANDR outputs.
- *
- * If the file in question cannot be loaded, the @error will have a domain of
- * #G_FILE_ERROR.  Note that an error code of G_FILE_ERROR_NOENT is not really
- * an error, either; it means that there was no stored configuration file and so
- * nothing is changed.
- */
 gboolean
-gnome_rr_config_apply_from_filename_with_time (GnomeRRScreen *screen, const char *filename, guint32 
timestamp, GError **error)
+gnome_rr_config_apply (GnomeRRConfig *config,
+                      GnomeRRScreen *screen,
+                      GError       **error)
 {
-    GnomeRRConfig *stored;
-
-    g_return_val_if_fail (GNOME_IS_RR_SCREEN (screen), FALSE);
-    g_return_val_if_fail (filename != NULL, FALSE);
-    g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-    stored = g_object_new (GNOME_TYPE_RR_CONFIG, "screen", screen, NULL);
-
-    if (gnome_rr_config_load_filename (stored, filename, error))
-    {
-       gboolean result;
-
-        gnome_rr_config_ensure_primary (stored);
-       result = gnome_rr_config_apply_with_time (stored, screen, timestamp, error);
+    return gnome_rr_config_apply_helper (config, screen, FALSE, error);
+}
 
-       g_object_unref (stored);
-       return result;
-    }
-    else
-    {
-       g_object_unref (stored);
-       return FALSE;
-    }
+gboolean
+gnome_rr_config_apply_persistent (GnomeRRConfig *config,
+                                 GnomeRRScreen *screen,
+                                 GError       **error)
+{
+    return gnome_rr_config_apply_helper (config, screen, TRUE, error);
 }
 
 /**
@@ -1418,6 +696,7 @@ struct CrtcInfo
 
 struct CrtcAssignment
 {
+    GnomeRROutputInfo **outputs;
     GnomeRRScreen *screen;
     GHashTable *info;
     GnomeRROutput *primary;
@@ -1479,9 +758,8 @@ crtc_assignment_assign (CrtcAssignment   *assign,
     if (!gnome_rr_crtc_supports_rotation (crtc, rotation))
     {
        g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_CRTC_ASSIGNMENT,
-                    _("CRTC %d does not support rotation=%s"),
-                    crtc_id,
-                    get_rotation_name (rotation));
+                    _("CRTC %d does not support rotation=%d"),
+                    crtc_id, rotation);
        return FALSE;
     }
 
@@ -1496,12 +774,12 @@ crtc_assignment_assign (CrtcAssignment   *assign,
                         _("output %s does not have the same parameters as another cloned output:\n"
                           "existing mode = %d, new mode = %d\n"
                           "existing coordinates = (%d, %d), new coordinates = (%d, %d)\n"
-                          "existing rotation = %s, new rotation = %s"),
+                          "existing rotation = %d, new rotation = %d"),
                         output_name,
                         gnome_rr_mode_get_id (info->mode), gnome_rr_mode_get_id (mode),
                         info->x, info->y,
                         x, y,
-                        get_rotation_name (info->rotation), get_rotation_name (rotation));
+                        info->rotation, rotation);
            return FALSE;
        }
 
@@ -1574,35 +852,6 @@ crtc_assignment_free (CrtcAssignment *assign)
     g_free (assign);
 }
 
-typedef struct {
-    guint32 timestamp;
-    gboolean has_error;
-    GError **error;
-} ConfigureCrtcState;
-
-static void
-configure_crtc (gpointer key,
-               gpointer value,
-               gpointer data)
-{
-    GnomeRRCrtc *crtc = key;
-    CrtcInfo *info = value;
-    ConfigureCrtcState *state = data;
-
-    if (state->has_error)
-       return;
-
-    if (!gnome_rr_crtc_set_config_with_time (crtc,
-                                            state->timestamp,
-                                            info->x, info->y,
-                                            info->mode,
-                                            info->rotation,
-                                            (GnomeRROutput **)info->outputs->pdata,
-                                            info->outputs->len,
-                                            state->error))
-       state->has_error = TRUE;
-}
-
 static gboolean
 mode_is_rotated (CrtcInfo *info)
 {
@@ -1614,20 +863,6 @@ mode_is_rotated (CrtcInfo *info)
     return FALSE;
 }
 
-static gboolean
-crtc_is_rotated (GnomeRRCrtc *crtc)
-{
-    GnomeRRRotation r = gnome_rr_crtc_get_current_rotation (crtc);
-
-    if ((r & GNOME_RR_ROTATION_270)            ||
-       (r & GNOME_RR_ROTATION_90))
-    {
-       return TRUE;
-    }
-
-    return FALSE;
-}
-
 static void
 accumulate_error (GString *accumulated_error, GError *error)
 {
@@ -1806,10 +1041,13 @@ get_required_virtual_size (CrtcAssignment *assign, int *width, int *height)
 }
 
 static CrtcAssignment *
-crtc_assignment_new (GnomeRRScreen *screen, GnomeRROutputInfo **outputs, GError **error)
+crtc_assignment_new (GnomeRRScreen      *screen,
+                    GnomeRROutputInfo **outputs,
+                    GError            **error)
 {
     CrtcAssignment *assignment = g_new0 (CrtcAssignment, 1);
 
+    assignment->outputs = outputs;
     assignment->info = g_hash_table_new_full (
        g_direct_hash, g_direct_equal, NULL, (GFreeFunc)crtc_info_free);
 
@@ -1849,102 +1087,94 @@ fail:
     return NULL;
 }
 
-static gboolean
-crtc_assignment_apply (CrtcAssignment *assign, guint32 timestamp, GError **error)
+static enum wl_output_transform
+rotation_to_transform (GnomeRRRotation rotation)
 {
-    GnomeRRCrtc **all_crtcs = gnome_rr_screen_list_crtcs (assign->screen);
-    int width, height;
-    int i;
-    int min_width, max_width, min_height, max_height;
-    int width_mm, height_mm;
-    gboolean success = TRUE;
-
-    /* Compute size of the screen */
-    get_required_virtual_size (assign, &width, &height);
-
-    gnome_rr_screen_get_ranges (
-       assign->screen, &min_width, &max_width, &min_height, &max_height);
-
-    /* We should never get here if the dimensions don't fit in the virtual size,
-     * but just in case we do, fix it up.
-     */
-    width = MAX (min_width, width);
-    width = MIN (max_width, width);
-    height = MAX (min_height, height);
-    height = MIN (max_height, height);
-
-    /* FMQ: do we need to check the sizes instead of clamping them? */
+  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 GNOME_RR_ROTATION_0:
+      ret = WL_OUTPUT_TRANSFORM_NORMAL;
+      break;
+    case GNOME_RR_ROTATION_90:
+      ret = WL_OUTPUT_TRANSFORM_90;
+      break;
+    case GNOME_RR_ROTATION_180:
+      ret = WL_OUTPUT_TRANSFORM_180;
+      break;
+    case GNOME_RR_ROTATION_270:
+      ret = WL_OUTPUT_TRANSFORM_270;
+      break;
+    }
+
+  if (rotation & GNOME_RR_REFLECT_X)
+    return ret + 4;
+  else if (rotation & GNOME_RR_REFLECT_Y)
+    return y_reflected_map[ret];
+  else
+    return ret;
+}
 
-    /* Grab the server while we fiddle with the CRTCs and the screen, so that
-     * apps that listen for RANDR notifications will only receive the final
-     * status.
-     */
+static gboolean
+crtc_assignment_apply (CrtcAssignment *assign, gboolean persistent, GError **error)
+{
+    GVariantBuilder crtc_builder, output_builder, nested_outputs;
+    GHashTableIter iter;
+    GnomeRRCrtc *crtc;
+    CrtcInfo *info;
+    unsigned i;
 
-    gdk_x11_display_grab (gdk_screen_get_display (assign->screen->priv->gdk_screen));
+    g_variant_builder_init (&crtc_builder, G_VARIANT_TYPE ("a(uiiiuaua{sv})"));
+    g_variant_builder_init (&output_builder, G_VARIANT_TYPE ("a(ua{sv})"));
 
-    /* Turn off all crtcs that are currently displaying outside the new screen,
-     * or are not used in the new setup
-     */
-    for (i = 0; all_crtcs[i] != NULL; ++i)
+    g_hash_table_iter_init (&iter, assign->info);
+    while (g_hash_table_iter_next (&iter, (void*) &crtc, (void*) &info))
     {
-       GnomeRRCrtc *crtc = all_crtcs[i];
-       GnomeRRMode *mode = gnome_rr_crtc_get_current_mode (crtc);
-       int x, y;
-
-       if (mode)
+       g_variant_builder_init (&nested_outputs, G_VARIANT_TYPE ("au"));
+       for (i = 0; i < info->outputs->len; i++)
        {
-           int w, h;
-           gnome_rr_crtc_get_position (crtc, &x, &y);
-
-           w = gnome_rr_mode_get_width (mode);
-           h = gnome_rr_mode_get_height (mode);
+           GnomeRROutput *output = g_ptr_array_index (info->outputs, i);
 
-           if (crtc_is_rotated (crtc))
-           {
-               int tmp = h;
-               h = w;
-               w = tmp;
-           }
-           
-           if (x + w > width || y + h > height || !g_hash_table_lookup (assign->info, crtc))
-           {
-               if (!gnome_rr_crtc_set_config_with_time (crtc, timestamp, 0, 0, NULL, GNOME_RR_ROTATION_0, 
NULL, 0, error))
-               {
-                   success = FALSE;
-                   break;
-               }
-               
-           }
+           g_variant_builder_add (&nested_outputs, "u",
+                                  gnome_rr_output_get_id (output));
        }
-    }
 
-    /* The 'physical size' of an X screen is meaningless if that screen
-     * can consist of many monitors. So just pick a size that make the
-     * dpi 96.
-     *
-     * Firefox and Evince apparently believe what X tells them.
-     */
-    width_mm = (width / DPI_FALLBACK) * 25.4 + 0.5;
-    height_mm = (height / DPI_FALLBACK) * 25.4 + 0.5;
-
-    if (success)
-    {
-       ConfigureCrtcState state;
-
-       gnome_rr_screen_set_size (assign->screen, width, height, width_mm, height_mm);
-
-       state.timestamp = timestamp;
-       state.has_error = FALSE;
-       state.error = error;
-       
-       g_hash_table_foreach (assign->info, configure_crtc, &state);
-
-       success = !state.has_error;
+       g_variant_builder_add (&crtc_builder, "(uiiiuaua{sv})",
+                              gnome_rr_crtc_get_id (crtc),
+                              info->mode ?
+                              gnome_rr_mode_get_id (info->mode) : -1,
+                              info->x,
+                              info->y,
+                              rotation_to_transform (info->rotation),
+                              &nested_outputs,
+                              NULL);
     }
 
-    gnome_rr_screen_set_primary_output (assign->screen, assign->primary);
-
-    gdk_x11_display_ungrab (gdk_screen_get_display (assign->screen->priv->gdk_screen));
-
-    return success;
+    for (i = 0; assign->outputs[i]; i++)
+    {
+       GnomeRROutputInfo *output = assign->outputs[i];
+       GnomeRROutput *gnome_rr_output = gnome_rr_screen_get_output_by_name (assign->screen,
+                                                                            output->priv->name);
+
+       g_variant_builder_add (&output_builder, "(u a{sv})",
+                              gnome_rr_output_get_id (gnome_rr_output),
+                              g_variant_new_parsed ("{ 'primary': <%b>,"
+                                                    "  'presentation': <%b> }",
+                                                    output->priv->primary,
+                                                    FALSE));
+    }
+
+    return _gnome_rr_screen_apply_configuration (assign->screen,
+                                                persistent,
+                                                g_variant_builder_end (&crtc_builder),
+                                                g_variant_builder_end (&output_builder),
+                                                error);
 }
diff --git a/libgnome-desktop/gnome-rr-config.h b/libgnome-desktop/gnome-rr-config.h
index 0a406d1..e7069e0 100644
--- a/libgnome-desktop/gnome-rr-config.h
+++ b/libgnome-desktop/gnome-rr-config.h
@@ -75,9 +75,9 @@ GnomeRRRotation gnome_rr_output_info_get_rotation (GnomeRROutputInfo *self);
 void            gnome_rr_output_info_set_rotation (GnomeRROutputInfo *self, GnomeRRRotation rotation);
 
 gboolean gnome_rr_output_info_is_connected     (GnomeRROutputInfo *self);
-void     gnome_rr_output_info_get_vendor       (GnomeRROutputInfo *self, gchar* vendor);
-guint    gnome_rr_output_info_get_product      (GnomeRROutputInfo *self);
-guint    gnome_rr_output_info_get_serial       (GnomeRROutputInfo *self);
+const char *gnome_rr_output_info_get_vendor    (GnomeRROutputInfo *self);
+const char *gnome_rr_output_info_get_product   (GnomeRROutputInfo *self);
+const char *gnome_rr_output_info_get_serial    (GnomeRROutputInfo *self);
 double   gnome_rr_output_info_get_aspect_ratio (GnomeRROutputInfo *self);
 char    *gnome_rr_output_info_get_display_name (GnomeRROutputInfo *self);
 
@@ -115,31 +115,21 @@ GType               gnome_rr_config_get_type     (void);
 
 GnomeRRConfig      *gnome_rr_config_new_current  (GnomeRRScreen  *screen,
                                                  GError        **error);
-GnomeRRConfig      *gnome_rr_config_new_stored   (GnomeRRScreen  *screen,
+gboolean            gnome_rr_config_load_current (GnomeRRConfig  *self,
                                                  GError        **error);
-gboolean                gnome_rr_config_load_current (GnomeRRConfig  *self,
-                                                     GError        **error);
-gboolean                gnome_rr_config_load_filename (GnomeRRConfig  *self,
-                                                      const gchar    *filename,
-                                                      GError        **error);
 gboolean            gnome_rr_config_match        (GnomeRRConfig  *config1,
                                                  GnomeRRConfig  *config2);
 gboolean            gnome_rr_config_equal       (GnomeRRConfig  *config1,
                                                  GnomeRRConfig  *config2);
-gboolean            gnome_rr_config_save         (GnomeRRConfig  *configuration,
-                                                 GError        **error);
 void                gnome_rr_config_sanitize     (GnomeRRConfig  *configuration);
 gboolean            gnome_rr_config_ensure_primary (GnomeRRConfig  *configuration);
 
-gboolean           gnome_rr_config_apply_with_time (GnomeRRConfig  *configuration,
-                                                    GnomeRRScreen  *screen,
-                                                    guint32         timestamp,
-                                                    GError        **error);
-
-gboolean            gnome_rr_config_apply_from_filename_with_time (GnomeRRScreen  *screen,
-                                                                  const char     *filename,
-                                                                  guint32         timestamp,
-                                                                  GError        **error);
+gboolean           gnome_rr_config_apply  (GnomeRRConfig  *configuration,
+                                           GnomeRRScreen  *screen,
+                                           GError        **error);
+gboolean           gnome_rr_config_apply_persistent  (GnomeRRConfig  *configuration,
+                                                      GnomeRRScreen  *screen,
+                                                      GError        **error);
 
 gboolean            gnome_rr_config_applicable   (GnomeRRConfig  *configuration,
                                                  GnomeRRScreen  *screen,
@@ -149,7 +139,4 @@ gboolean            gnome_rr_config_get_clone    (GnomeRRConfig  *configuration)
 void                gnome_rr_config_set_clone    (GnomeRRConfig  *configuration, gboolean clone);
 GnomeRROutputInfo **gnome_rr_config_get_outputs  (GnomeRRConfig  *configuration);
 
-char *gnome_rr_config_get_backup_filename (void);
-char *gnome_rr_config_get_intended_filename (void);
-
 #endif
diff --git a/libgnome-desktop/gnome-rr-debug.c b/libgnome-desktop/gnome-rr-debug.c
index 20fa090..0395ecc 100644
--- a/libgnome-desktop/gnome-rr-debug.c
+++ b/libgnome-desktop/gnome-rr-debug.c
@@ -83,7 +83,7 @@ main (int argc, char *argv[])
        outputs = gnome_rr_screen_list_outputs (screen);
        for (i = 0; outputs[i] != NULL; i++) {
                g_print ("[%s]\n", gnome_rr_output_get_name (outputs[i]));
-               g_print ("\tconnected: %i\n", gnome_rr_output_is_connected (outputs[i]));
+               g_print ("\tconnected: %i\n", 1);
                g_print ("\tbuilt-in: %i\n", gnome_rr_output_is_builtin_display (outputs[i]));
                g_print ("\tprimary: %i\n", gnome_rr_output_get_is_primary (outputs[i]));
                g_print ("\tid: %i\n", gnome_rr_output_get_id (outputs[i]));
diff --git a/libgnome-desktop/gnome-rr-output-info.c b/libgnome-desktop/gnome-rr-output-info.c
index 43ab0e3..2177692 100644
--- a/libgnome-desktop/gnome-rr-output-info.c
+++ b/libgnome-desktop/gnome-rr-output-info.c
@@ -169,29 +169,27 @@ gboolean gnome_rr_output_info_is_connected (GnomeRROutputInfo *self)
 /**
  * gnome_rr_output_info_get_vendor:
  * @self: a #GnomeRROutputInfo
- * @vendor: (out caller-allocates) (array fixed-size=4):
  */
-void gnome_rr_output_info_get_vendor (GnomeRROutputInfo *self, gchar* vendor)
+const char *
+gnome_rr_output_info_get_vendor (GnomeRROutputInfo *self)
 {
-    g_return_if_fail (GNOME_IS_RR_OUTPUT_INFO (self));
-    g_return_if_fail (vendor != NULL);
+    g_return_val_if_fail (GNOME_IS_RR_OUTPUT_INFO (self), NULL);
 
-    vendor[0] = self->priv->vendor[0];
-    vendor[1] = self->priv->vendor[1];
-    vendor[2] = self->priv->vendor[2];
-    vendor[3] = self->priv->vendor[3];
+    return self->priv->vendor;
 }
 
-guint gnome_rr_output_info_get_product (GnomeRROutputInfo *self)
+const char *
+gnome_rr_output_info_get_product (GnomeRROutputInfo *self)
 {
-    g_return_val_if_fail (GNOME_IS_RR_OUTPUT_INFO (self), 0);
+    g_return_val_if_fail (GNOME_IS_RR_OUTPUT_INFO (self), NULL);
 
     return self->priv->product;
 }
 
-guint gnome_rr_output_info_get_serial (GnomeRROutputInfo *self)
+const char *
+gnome_rr_output_info_get_serial (GnomeRROutputInfo *self)
 {
-    g_return_val_if_fail (GNOME_IS_RR_OUTPUT_INFO (self), 0);
+    g_return_val_if_fail (GNOME_IS_RR_OUTPUT_INFO (self), NULL);
 
     return self->priv->serial;
 }
diff --git a/libgnome-desktop/gnome-rr-private.h b/libgnome-desktop/gnome-rr-private.h
index edadbad..522398a 100644
--- a/libgnome-desktop/gnome-rr-private.h
+++ b/libgnome-desktop/gnome-rr-private.h
@@ -1,9 +1,22 @@
 #ifndef GNOME_RR_PRIVATE_H
 #define GNOME_RR_PRIVATE_H
 
-#include <X11/Xlib.h>
+#ifdef GDK_WINDOWING_WAYLAND
+#include <gdk/gdkwayland.h>
+#else
+enum wl_output_transform {
+  WL_OUTPUT_TRANSFORM_NORMAL,
+  WL_OUTPUT_TRANSFORM_90,
+  WL_OUTPUT_TRANSFORM_180,
+  WL_OUTPUT_TRANSFORM_270,
+  WL_OUTPUT_TRANSFORM_FLIPPED,
+  WL_OUTPUT_TRANSFORM_FLIPPED_90,
+  WL_OUTPUT_TRANSFORM_FLIPPED_180,
+  WL_OUTPUT_TRANSFORM_FLIPPED_270
+};
+#endif
 
-#include <X11/extensions/Xrandr.h>
+#include "meta-dbus-xrandr.h"
 
 typedef struct ScreenInfo ScreenInfo;
 
@@ -14,7 +27,7 @@ struct ScreenInfo
     int                        min_height;
     int                        max_height;
 
-    XRRScreenResources *resources;
+    guint               serial;
     
     GnomeRROutput **   outputs;
     GnomeRRCrtc **     crtcs;
@@ -24,24 +37,16 @@ struct ScreenInfo
 
     GnomeRRMode **     clone_modes;
 
-    RROutput            primary;
+    GnomeRROutput *     primary;
 };
 
 struct GnomeRRScreenPrivate
 {
     GdkScreen *                        gdk_screen;
     GdkWindow *                        gdk_root;
-    Display *                  xdisplay;
-    Screen *                   xscreen;
-    Window                     xroot;
     ScreenInfo *               info;
-    
-    int                                randr_event_base;
-    int                                rr_major_version;
-    int                                rr_minor_version;
-    
-    Atom                        connector_type_atom;
-    gboolean                    dpms_capable;
+
+    MetaDBusDisplayConfig      *proxy;
 };
 
 struct _GnomeRROutputInfoPrivate
@@ -57,9 +62,9 @@ struct _GnomeRROutputInfoPrivate
     GnomeRRRotation    rotation;
 
     gboolean           connected;
-    gchar              vendor[4];
-    guint              product;
-    guint              serial;
+    char *             vendor;
+    char *             product;
+    char *             serial;
     double             aspect;
     int                        pref_width;
     int                        pref_height;
@@ -76,4 +81,18 @@ struct _GnomeRRConfigPrivate
 
 gboolean _gnome_rr_output_name_is_builtin_display (const char *name);
 
+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;
+
+gboolean _gnome_rr_screen_apply_configuration (GnomeRRScreen  *screen,
+                                              gboolean        persistent,
+                                              GVariant       *crtcs,
+                                              GVariant       *outputs,
+                                              GError        **error);
+
 #endif
diff --git a/libgnome-desktop/gnome-rr.c b/libgnome-desktop/gnome-rr.c
index c59d142..5249e17 100644
--- a/libgnome-desktop/gnome-rr.c
+++ b/libgnome-desktop/gnome-rr.c
@@ -1,6 +1,6 @@
 /* gnome-rr.c
  *
- * Copyright 2007, 2008, Red Hat, Inc.
+ * Copyright 2007, 2008, 2013 Red Hat, Inc.
  * 
  * This file is part of the Gnome Library.
  * 
@@ -20,6 +20,7 @@
  * Boston, MA 02110-1301, USA.
  * 
  * Author: Soren Sandmann <sandmann redhat com>
+ *         Giovanni Campagna <gcampagn redhat com>
  */
 
 #define GNOME_DESKTOP_USE_UNSTABLE_API
@@ -27,14 +28,9 @@
 #include <config.h>
 #include <glib/gi18n-lib.h>
 #include <string.h>
-#include <X11/Xlib.h>
-
-#include <X11/extensions/Xrandr.h>
 
 #include <gtk/gtk.h>
 #include <gdk/gdkx.h>
-#include <X11/Xatom.h>
-#include <X11/extensions/dpms.h>
 
 #undef GNOME_DISABLE_DEPRECATED
 #include "gnome-rr.h"
@@ -43,9 +39,6 @@
 #include "edid.h"
 #include "gnome-rr-private.h"
 
-#define DISPLAY(o) ((o)->info->screen->priv->xdisplay)
-
-#define SERVERS_RANDR_IS_AT_LEAST_1_3(priv) (priv->rr_major_version > 1 || (priv->rr_major_version == 1 && 
priv->rr_minor_version >= 3))
 
 enum {
     SCREEN_PROP_0,
@@ -65,34 +58,31 @@ gint screen_signals[SCREEN_SIGNAL_LAST];
 struct GnomeRROutput
 {
     ScreenInfo *       info;
-    RROutput           id;
+    guint              id;
+    glong               winsys_id;
     
     char *             name;
     char *             display_name;
     GnomeRRCrtc *      current_crtc;
-    gboolean           connected;
-    gulong             width_mm;
-    gulong             height_mm;
     GnomeRRCrtc **     possible_crtcs;
     GnomeRROutput **   clones;
     GnomeRRMode **     modes;
-    int                        n_preferred;
-    guint8 *           edid_data;
-    gsize              edid_size;
-    char *              connector_type;
-    gint               backlight_min;
-    gint               backlight_max;
-};
 
-struct GnomeRROutputWrap
-{
-    RROutput           id;
+    char *              vendor;
+    char *              product;
+    char *              serial;
+
+    int                 backlight;
+
+    gboolean            is_primary;
+    gboolean            is_presentation;
 };
 
 struct GnomeRRCrtc
 {
     ScreenInfo *       info;
-    RRCrtc             id;
+    guint              id;
+    glong               winsys_id;
     
     GnomeRRMode *      current_mode;
     GnomeRROutput **   current_outputs;
@@ -100,16 +90,16 @@ struct GnomeRRCrtc
     int                        x;
     int                        y;
     
-    GnomeRRRotation    current_rotation;
-    GnomeRRRotation    rotations;
+    enum wl_output_transform transform;
+    int                 all_transforms;
     int                        gamma_size;
 };
 
 struct GnomeRRMode
 {
     ScreenInfo *       info;
-    RRMode             id;
-    char *             name;
+    guint              id;
+    glong               winsys_id;
     int                        width;
     int                        height;
     int                        freq;           /* in mHz */
@@ -117,31 +107,29 @@ struct GnomeRRMode
 
 /* GnomeRRCrtc */
 static GnomeRRCrtc *  crtc_new          (ScreenInfo         *info,
-                                        RRCrtc              id);
+                                        guint               id);
 static GnomeRRCrtc *  crtc_copy         (const GnomeRRCrtc  *from);
 static void           crtc_free         (GnomeRRCrtc        *crtc);
 
-static gboolean       crtc_initialize   (GnomeRRCrtc        *crtc,
-                                        XRRScreenResources *res,
-                                        GError            **error);
+static void           crtc_initialize   (GnomeRRCrtc        *crtc,
+                                        GVariant           *res);
 
 /* GnomeRROutput */
 static GnomeRROutput *output_new        (ScreenInfo         *info,
-                                        RROutput            id);
+                                        guint               id);
 
-static gboolean       output_initialize (GnomeRROutput      *output,
-                                        XRRScreenResources *res,
-                                        GError            **error);
+static void           output_initialize (GnomeRROutput      *output,
+                                        GVariant           *res);
 
 static GnomeRROutput *output_copy       (const GnomeRROutput *from);
 static void           output_free       (GnomeRROutput      *output);
 
 /* GnomeRRMode */
 static GnomeRRMode *  mode_new          (ScreenInfo         *info,
-                                        RRMode              id);
+                                        guint               id);
 
 static void           mode_initialize   (GnomeRRMode        *mode,
-                                        XRRModeInfo        *info);
+                                        GVariant           *info);
 
 static GnomeRRMode *  mode_copy         (const GnomeRRMode  *from);
 static void           mode_free         (GnomeRRMode        *mode);
@@ -176,7 +164,7 @@ gnome_rr_error_quark (void)
 
 /* Screen */
 static GnomeRROutput *
-gnome_rr_output_by_id (ScreenInfo *info, RROutput id)
+gnome_rr_output_by_id (ScreenInfo *info, guint id)
 {
     GnomeRROutput **output;
     
@@ -192,7 +180,7 @@ gnome_rr_output_by_id (ScreenInfo *info, RROutput id)
 }
 
 static GnomeRRCrtc *
-crtc_by_id (ScreenInfo *info, RRCrtc id)
+crtc_by_id (ScreenInfo *info, guint id)
 {
     GnomeRRCrtc **crtc;
     
@@ -209,7 +197,7 @@ crtc_by_id (ScreenInfo *info, RRCrtc id)
 }
 
 static GnomeRRMode *
-mode_by_id (ScreenInfo *info, RRMode id)
+mode_by_id (ScreenInfo *info, guint id)
 {
     GnomeRRMode **mode;
     
@@ -233,13 +221,6 @@ screen_info_free (ScreenInfo *info)
     
     g_assert (info != NULL);
 
-    if (info->resources)
-    {
-       XRRFreeScreenResources (info->resources);
-       
-       info->resources = NULL;
-    }
-    
     if (info->outputs)
     {
        for (output = info->outputs; *output; ++output)
@@ -305,9 +286,6 @@ gather_clone_modes (ScreenInfo *info)
 
        output1 = info->outputs[i];
        
-       if (!output1->connected)
-           continue;
-       
        for (j = 0; output1->modes[j] != NULL; ++j)
        {
            GnomeRRMode *mode = output1->modes[j];
@@ -319,9 +297,6 @@ gather_clone_modes (ScreenInfo *info)
            {
                output2 = info->outputs[k];
                
-               if (!output2->connected)
-                   continue;
-               
                if (!has_similar_mode (output2, mode))
                {
                    valid = FALSE;
@@ -339,25 +314,44 @@ gather_clone_modes (ScreenInfo *info)
     info->clone_modes = (GnomeRRMode **)g_ptr_array_free (result, FALSE);
 }
 
-static gboolean
+static void
 fill_screen_info_from_resources (ScreenInfo *info,
-                                XRRScreenResources *resources,
-                                GError **error)
+                                guint       serial,
+                                GVariant   *crtcs,
+                                GVariant   *outputs,
+                                GVariant   *modes,
+                                int         max_width,
+                                int         max_height)
 {
     int i;
     GPtrArray *a;
     GnomeRRCrtc **crtc;
     GnomeRROutput **output;
+    GnomeRRMode **mode;
+    guint ncrtc, noutput, nmode;
+    guint id;
 
-    info->resources = resources;
+    info->min_width = 312;
+    info->min_height = 312;
+    info->max_width = max_width;
+    info->max_height = max_height;
+    info->serial = serial;
+
+    ncrtc = g_variant_n_children (crtcs);
+    noutput = g_variant_n_children (outputs);
+    nmode = g_variant_n_children (modes);
 
     /* We create all the structures before initializing them, so
      * that they can refer to each other.
      */
     a = g_ptr_array_new ();
-    for (i = 0; i < resources->ncrtc; ++i)
+    for (i = 0; i < ncrtc; ++i)
     {
-       GnomeRRCrtc *crtc = crtc_new (info, resources->crtcs[i]);
+       GnomeRRCrtc *crtc;
+
+       g_variant_get_child (crtcs, i, "(uxiiiiiuaua{sv})", &id,
+                            NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+       crtc = crtc_new (info, id);
 
        g_ptr_array_add (a, crtc);
     }
@@ -365,9 +359,13 @@ fill_screen_info_from_resources (ScreenInfo *info,
     info->crtcs = (GnomeRRCrtc **)g_ptr_array_free (a, FALSE);
 
     a = g_ptr_array_new ();
-    for (i = 0; i < resources->noutput; ++i)
+    for (i = 0; i < noutput; ++i)
     {
-       GnomeRROutput *output = output_new (info, resources->outputs[i]);
+       GnomeRROutput *output;
+ 
+       g_variant_get_child (outputs, i, "(uxiaussssiauaua{sv})", &id,
+                            NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+       output = output_new (info, id);
 
        g_ptr_array_add (a, output);
     }
@@ -375,9 +373,13 @@ fill_screen_info_from_resources (ScreenInfo *info,
     info->outputs = (GnomeRROutput **)g_ptr_array_free (a, FALSE);
 
     a = g_ptr_array_new ();
-    for (i = 0;  i < resources->nmode; ++i)
+    for (i = 0;  i < nmode; ++i)
     {
-       GnomeRRMode *mode = mode_new (info, resources->modes[i].id);
+       GnomeRRMode *mode;
+
+       g_variant_get_child (modes, i, "(uxuud)", &id,
+                            NULL, NULL, NULL, NULL);
+       mode = mode_new (info, id);
 
        g_ptr_array_add (a, mode);
     }
@@ -385,140 +387,66 @@ fill_screen_info_from_resources (ScreenInfo *info,
     info->modes = (GnomeRRMode **)g_ptr_array_free (a, FALSE);
 
     /* Initialize */
-    for (crtc = info->crtcs; *crtc; ++crtc)
+    for (i = 0, crtc = info->crtcs; *crtc; ++i, ++crtc)
     {
-       if (!crtc_initialize (*crtc, resources, error))
-           return FALSE;
+       crtc_initialize (*crtc, g_variant_get_child_value (crtcs, i));
     }
 
-    for (output = info->outputs; *output; ++output)
+    for (i = 0, output = info->outputs; *output; ++i, ++output)
     {
-       if (!output_initialize (*output, resources, error))
-           return FALSE;
+       output_initialize (*output, g_variant_get_child_value (outputs, i));
     }
 
-    for (i = 0; i < resources->nmode; ++i)
+    for (i = 0, mode = info->modes; *mode; ++i, ++mode)
     {
-       GnomeRRMode *mode = mode_by_id (info, resources->modes[i].id);
-
-       mode_initialize (mode, &(resources->modes[i]));
+       mode_initialize (*mode, g_variant_get_child_value (modes, i));
     }
 
     gather_clone_modes (info);
-
-    return TRUE;
 }
 
 static gboolean
-fill_out_screen_info (Display *xdisplay,
-                     Window xroot,
-                     ScreenInfo *info,
-                     gboolean needs_reprobe,
-                     GError **error)
+fill_out_screen_info (ScreenInfo  *info,
+                     GError     **error)
 {
-    XRRScreenResources *resources;
     GnomeRRScreenPrivate *priv;
-    
-    g_assert (xdisplay != NULL);
+    guint serial;
+    GVariant *crtcs, *outputs, *modes;
+    int max_width, max_height;
+
     g_assert (info != NULL);
 
     priv = info->screen->priv;
 
-    /* First update the screen resources */
-
-    if (needs_reprobe)
-        resources = XRRGetScreenResources (xdisplay, xroot);
-    else
-    {
-       /* XRRGetScreenResourcesCurrent is less expensive than
-        * XRRGetScreenResources, however it is available only
-        * in RandR 1.3 or higher
-        */
-        if (SERVERS_RANDR_IS_AT_LEAST_1_3 (priv))
-            resources = XRRGetScreenResourcesCurrent (xdisplay, xroot);
-        else
-            resources = XRRGetScreenResources (xdisplay, xroot);
-    }
-
-    if (resources)
-    {
-       if (!fill_screen_info_from_resources (info, resources, error))
-           return FALSE;
-    }
-    else
-    {
-       g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_RANDR_ERROR,
-                    /* Translators: a CRTC is a CRT Controller (this is X terminology). */
-                    _("could not get the screen resources (CRTCs, outputs, modes)"));
+    if (!meta_dbus_display_config_call_get_resources_sync (priv->proxy,
+                                                          &serial,
+                                                          &crtcs,
+                                                          &outputs,
+                                                          &modes,
+                                                          &max_width,
+                                                          &max_height,
+                                                          NULL,
+                                                          error))
        return FALSE;
-    }
-
-    /* Then update the screen size range.  We do this after XRRGetScreenResources() so that
-     * the X server will already have an updated view of the outputs.
-     */
-
-    if (needs_reprobe) {
-       gboolean success;
-
-        gdk_error_trap_push ();
-       success = XRRGetScreenSizeRange (xdisplay, xroot,
-                                        &(info->min_width),
-                                        &(info->min_height),
-                                        &(info->max_width),
-                                        &(info->max_height));
-       gdk_flush ();
-       if (gdk_error_trap_pop ()) {
-           g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_UNKNOWN,
-                        _("unhandled X error while getting the range of screen sizes"));
-           return FALSE;
-       }
-
-       if (!success) {
-           g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_RANDR_ERROR,
-                        _("could not get the range of screen sizes"));
-            return FALSE;
-        }
-    }
-    else
-    {
-        gnome_rr_screen_get_ranges (info->screen, 
-                                        &(info->min_width),
-                                        &(info->max_width),
-                                        &(info->min_height),
-                                        &(info->max_height));
-    }
-
-    info->primary = None;
-    if (SERVERS_RANDR_IS_AT_LEAST_1_3 (priv)) {
-        gdk_error_trap_push ();
-        info->primary = XRRGetOutputPrimary (xdisplay, xroot);
-       gdk_error_trap_pop_ignored ();
-    }
-
-    /* can the screen do DPMS? */
-    gdk_error_trap_push ();
-    priv->dpms_capable = DPMSCapable (priv->xdisplay);
-    gdk_error_trap_pop_ignored ();
 
+    fill_screen_info_from_resources (info, serial, crtcs, outputs,
+                                    modes, max_width, max_height);
     return TRUE;
 }
 
 static ScreenInfo *
-screen_info_new (GnomeRRScreen *screen, gboolean needs_reprobe, GError **error)
+screen_info_new (GnomeRRScreen *screen, GError **error)
 {
     ScreenInfo *info = g_new0 (ScreenInfo, 1);
-    GnomeRRScreenPrivate *priv;
 
     g_assert (screen != NULL);
 
-    priv = screen->priv;
-
     info->outputs = NULL;
     info->crtcs = NULL;
     info->modes = NULL;
     info->screen = screen;
     
-    if (fill_out_screen_info (priv->xdisplay, priv->xroot, info, needs_reprobe, error))
+    if (fill_out_screen_info (info, error))
     {
        return info;
     }
@@ -530,13 +458,13 @@ screen_info_new (GnomeRRScreen *screen, gboolean needs_reprobe, GError **error)
 }
 
 static GnomeRROutput *
-find_output_by_id (GnomeRROutput **haystack, guint32 id)
+find_output_by_winsys_id (GnomeRROutput **haystack, glong winsys_id)
 {
     guint i;
 
     for (i = 0; haystack[i] != NULL; i++)
     {
-       if (gnome_rr_output_get_id (haystack[i]) == id)
+       if (haystack[i]->winsys_id == winsys_id)
            return haystack[i];
     }
     return NULL;
@@ -546,76 +474,50 @@ static void
 diff_outputs_and_emit_signals (ScreenInfo *old, ScreenInfo *new)
 {
     guint i;
-    guint32 id_old, id_new;
+    gulong winsys_id_old, winsys_id_new;
     GnomeRROutput *output_old;
     GnomeRROutput *output_new;
 
-    /* have any outputs been removed or disconnected */
+    /* have any outputs been removed/disconnected */
     for (i = 0; old->outputs[i] != NULL; i++)
     {
-        id_old = gnome_rr_output_get_id (old->outputs[i]);
-        output_new = find_output_by_id (new->outputs, id_old);
+        winsys_id_old = old->outputs[i]->winsys_id;
+        output_new = find_output_by_winsys_id (new->outputs, winsys_id_old);
        if (output_new == NULL)
        {
-           /* output removed (and disconnected) */
-           if (gnome_rr_output_is_connected (old->outputs[i]))
-            {
-               g_signal_emit (G_OBJECT (new->screen),
-                              screen_signals[SCREEN_OUTPUT_DISCONNECTED], 0,
-                              old->outputs[i]);
-             }
-           continue;
-       }
-       if (gnome_rr_output_is_connected (old->outputs[i]) &&
-           !gnome_rr_output_is_connected (output_new))
-       {
-           /* output disconnected */
            g_signal_emit (G_OBJECT (new->screen),
                           screen_signals[SCREEN_OUTPUT_DISCONNECTED], 0,
                           old->outputs[i]);
-        }
+       }
     }
 
-    /* have any outputs been created or connected */
+    /* have any outputs been created/connected */
     for (i = 0; new->outputs[i] != NULL; i++)
     {
-        id_new = gnome_rr_output_get_id (new->outputs[i]);
-        output_old = find_output_by_id (old->outputs, id_new);
+        winsys_id_new = new->outputs[i]->winsys_id;
+        output_old = find_output_by_winsys_id (old->outputs, winsys_id_new);
        if (output_old == NULL)
        {
-           /* output created */
-           if (gnome_rr_output_is_connected (new->outputs[i]))
-            {
-               g_signal_emit (G_OBJECT (new->screen),
-                              screen_signals[SCREEN_OUTPUT_CONNECTED], 0,
-                              new->outputs[i]);
-            }
-           continue;
-       }
-       if (!gnome_rr_output_is_connected (output_old) &&
-           gnome_rr_output_is_connected (new->outputs[i]))
-       {
-           /* output connected */
            g_signal_emit (G_OBJECT (new->screen),
                           screen_signals[SCREEN_OUTPUT_CONNECTED], 0,
                           new->outputs[i]);
-         }
+       }
     }
 }
 
 static gboolean
-screen_update (GnomeRRScreen *screen, gboolean force_callback, gboolean needs_reprobe, GError **error)
+screen_update (GnomeRRScreen *screen, gboolean force_callback, GError **error)
 {
     ScreenInfo *info;
     gboolean changed = FALSE;
     
     g_assert (screen != NULL);
 
-    info = screen_info_new (screen, needs_reprobe, error);
+    info = screen_info_new (screen, error);
     if (!info)
            return FALSE;
 
-    if (info->resources->configTimestamp != screen->priv->info->resources->configTimestamp)
+    if (info->serial != screen->priv->info->serial)
            changed = TRUE;
 
     /* work out if any outputs have changed connected state */
@@ -631,98 +533,13 @@ screen_update (GnomeRRScreen *screen, gboolean force_callback, gboolean needs_re
     return changed;
 }
 
-static GdkFilterReturn
-screen_on_event (GdkXEvent *xevent,
-                GdkEvent *event,
-                gpointer data)
+static void
+screen_on_monitors_changed (GdkScreen *gdk_screen,
+                           gpointer data)
 {
     GnomeRRScreen *screen = data;
-    GnomeRRScreenPrivate *priv = screen->priv;
-    XEvent *e = xevent;
-    int event_num;
-
-    if (!e)
-       return GDK_FILTER_CONTINUE;
-
-    event_num = e->type - priv->randr_event_base;
-
-    if (event_num == RRScreenChangeNotify) {
-       /* We don't reprobe the hardware; we just fetch the X server's latest
-        * state.  The server already knows the new state of the outputs; that's
-        * why it sent us an event!
-        */
-        screen_update (screen, TRUE, FALSE, NULL); /* NULL-GError */
-#if 0
-       /* Enable this code to get a dialog showing the RANDR timestamps, for debugging purposes */
-       {
-           GtkWidget *dialog;
-           XRRScreenChangeNotifyEvent *rr_event;
-           static int dialog_num;
-
-           rr_event = (XRRScreenChangeNotifyEvent *) e;
-
-           dialog = gtk_message_dialog_new (NULL,
-                                            0,
-                                            GTK_MESSAGE_INFO,
-                                            GTK_BUTTONS_CLOSE,
-                                            "RRScreenChangeNotify timestamps (%d):\n"
-                                            "event change: %u\n"
-                                            "event config: %u\n"
-                                            "event serial: %lu\n"
-                                            "----------------------"
-                                            "screen change: %u\n"
-                                            "screen config: %u\n",
-                                            dialog_num++,
-                                            (guint32) rr_event->timestamp,
-                                            (guint32) rr_event->config_timestamp,
-                                            rr_event->serial,
-                                            (guint32) priv->info->resources->timestamp,
-                                            (guint32) priv->info->resources->configTimestamp);
-           g_signal_connect (dialog, "response",
-                             G_CALLBACK (gtk_widget_destroy), NULL);
-           gtk_widget_show (dialog);
-       }
-#endif
-    }
-#if 0
-    /* WHY THIS CODE IS DISABLED:
-     *
-     * Note that in gnome_rr_screen_new(), we only select for
-     * RRScreenChangeNotifyMask.  We used to select for other values in
-     * RR*NotifyMask, but we weren't really doing anything useful with those
-     * events.  We only care about "the screens changed in some way or another"
-     * for now.
-     *
-     * If we ever run into a situtation that could benefit from processing more
-     * detailed events, we can enable this code again.
-     *
-     * Note that the X server sends RRScreenChangeNotify in conjunction with the
-     * more detailed events from RANDR 1.2 - see xserver/randr/randr.c:TellChanged().
-     */
-    else if (event_num == RRNotify)
-    {
-       /* Other RandR events */
-
-       XRRNotifyEvent *event = (XRRNotifyEvent *)e;
-
-       /* Here we can distinguish between RRNotify events supported
-        * since RandR 1.2 such as RRNotify_OutputProperty.  For now, we
-        * don't have anything special to do for particular subevent types, so
-        * we leave this as an empty switch().
-        */
-       switch (event->subtype)
-       {
-       default:
-           break;
-       }
-
-       /* No need to reprobe hardware here */
-       screen_update (screen, TRUE, FALSE, NULL); /* NULL-GError */
-    }
-#endif
 
-    /* Pass the event on to GTK+ */
-    return GDK_FILTER_CONTINUE;
+    screen_update (screen, TRUE, NULL);
 }
 
 static gboolean
@@ -730,46 +547,25 @@ gnome_rr_screen_initable_init (GInitable *initable, GCancellable *canc, GError *
 {
     GnomeRRScreen *self = GNOME_RR_SCREEN (initable);
     GnomeRRScreenPrivate *priv = self->priv;
-    Display *dpy = GDK_SCREEN_XDISPLAY (self->priv->gdk_screen);
-    int event_base;
-    int ignore;
-
-    priv->connector_type_atom = XInternAtom (dpy, "ConnectorType", FALSE);
-
-    if (XRRQueryExtension (dpy, &event_base, &ignore))
-    {
-        priv->randr_event_base = event_base;
-
-        XRRQueryVersion (dpy, &priv->rr_major_version, &priv->rr_minor_version);
-        if (priv->rr_major_version < 1 || (priv->rr_major_version == 1 && priv->rr_minor_version < 2)) {
-            g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_NO_RANDR_EXTENSION,
-                    "RANDR extension is too old (must be at least 1.2)");
-            return FALSE;
-        }
-
-        priv->info = screen_info_new (self, TRUE, error);
-
-        if (!priv->info) {
-            return FALSE;
-        }
+    MetaDBusDisplayConfig *proxy;
+
+    proxy = meta_dbus_display_config_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+                                                            G_DBUS_PROXY_FLAGS_NONE,
+                                                            "org.gnome.Mutter.DisplayConfig",
+                                                            "/org/gnome/Mutter/DisplayConfig",
+                                                            NULL, error);
+    if (!proxy)
+       return FALSE;
 
-        XRRSelectInput (priv->xdisplay,
-                priv->xroot,
-                RRScreenChangeNotifyMask);
-        gdk_x11_register_standard_event_type (gdk_screen_get_display (priv->gdk_screen),
-                          event_base,
-                          RRNotify + 1);
-        gdk_window_add_filter (priv->gdk_root, screen_on_event, self);
+    priv->proxy = META_DBUS_DISPLAY_CONFIG (proxy);
 
-        return TRUE;
-    }
-    else
-    {
-      g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_NO_RANDR_EXTENSION,
-                   _("RANDR extension is not present"));
+    priv->info = screen_info_new (self, error);
+    if (!priv->info)
+       return FALSE;
 
-      return FALSE;
-   }
+    g_signal_connect_object (priv->gdk_screen, "monitors-changed",
+                            G_CALLBACK (screen_on_monitors_changed), self, 0);
+    return TRUE;
 }
 
 void
@@ -783,11 +579,11 @@ gnome_rr_screen_finalize (GObject *gobject)
 {
     GnomeRRScreen *screen = GNOME_RR_SCREEN (gobject);
 
-    gdk_window_remove_filter (screen->priv->gdk_root, screen_on_event, screen);
-
     if (screen->priv->info)
       screen_info_free (screen->priv->info);
 
+    g_clear_object (&screen->priv->proxy);
+
     G_OBJECT_CLASS (gnome_rr_screen_parent_class)->finalize (gobject);
 }
 
@@ -801,10 +597,6 @@ gnome_rr_screen_set_property (GObject *gobject, guint property_id, const GValue
     {
     case SCREEN_PROP_GDK_SCREEN:
         priv->gdk_screen = g_value_get_object (value);
-        priv->gdk_root = gdk_screen_get_root_window (priv->gdk_screen);
-        priv->xroot = gdk_x11_window_get_xid (priv->gdk_root);
-        priv->xdisplay = GDK_SCREEN_XDISPLAY (priv->gdk_screen);
-        priv->xscreen = gdk_x11_screen_get_xscreen (priv->gdk_screen);
         return;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, property);
@@ -928,15 +720,6 @@ gnome_rr_screen_init (GnomeRRScreen *self)
 {
     GnomeRRScreenPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GNOME_TYPE_RR_SCREEN, 
GnomeRRScreenPrivate);
     self->priv = priv;
-
-    priv->gdk_screen = NULL;
-    priv->gdk_root = NULL;
-    priv->xdisplay = NULL;
-    priv->xroot = None;
-    priv->xscreen = NULL;
-    priv->info = NULL;
-    priv->rr_major_version = 0;
-    priv->rr_minor_version = 0;
 }
 
 /* Weak reference callback set in gnome_rr_screen_new(); we remove the GObject data from the GdkScreen. */
@@ -982,21 +765,6 @@ gnome_rr_screen_new (GdkScreen *screen,
     return rr_screen;
 }
 
-void
-gnome_rr_screen_set_size (GnomeRRScreen *screen,
-                         int         width,
-                         int       height,
-                         int       mm_width,
-                         int       mm_height)
-{
-    g_return_if_fail (GNOME_IS_RR_SCREEN (screen));
-
-    gdk_error_trap_push ();
-    XRRSetScreenSize (screen->priv->xdisplay, screen->priv->xroot,
-                     width, height, mm_width, mm_height);
-    gdk_error_trap_pop_ignored ();
-}
-
 /**
  * gnome_rr_screen_get_ranges:
  * @screen: a #GnomeRRScreen
@@ -1034,83 +802,6 @@ gnome_rr_screen_get_ranges (GnomeRRScreen *screen,
 }
 
 /**
- * gnome_rr_screen_get_timestamps:
- * @screen: a #GnomeRRScreen
- * @change_timestamp_ret: (out): Location in which to store the timestamp at which the RANDR configuration 
was last changed
- * @config_timestamp_ret: (out): Location in which to store the timestamp at which the RANDR configuration 
was last obtained
- *
- * Queries the two timestamps that the X RANDR extension maintains.  The X
- * server will prevent change requests for stale configurations, those whose
- * timestamp is not equal to that of the latest request for configuration.  The
- * X server will also prevent change requests that have an older timestamp to
- * the latest change request.
- */
-void
-gnome_rr_screen_get_timestamps (GnomeRRScreen *screen,
-                               guint32       *change_timestamp_ret,
-                               guint32       *config_timestamp_ret)
-{
-    GnomeRRScreenPrivate *priv;
-
-    g_return_if_fail (GNOME_IS_RR_SCREEN (screen));
-
-    priv = screen->priv;
-
-    if (change_timestamp_ret)
-       *change_timestamp_ret = priv->info->resources->timestamp;
-
-    if (config_timestamp_ret)
-       *config_timestamp_ret = priv->info->resources->configTimestamp;
-}
-
-static gboolean
-force_timestamp_update (GnomeRRScreen *screen)
-{
-    GnomeRRScreenPrivate *priv = screen->priv;
-    GnomeRRCrtc *crtc;
-    XRRCrtcInfo *current_info;
-    Status status;
-    gboolean timestamp_updated;
-
-    timestamp_updated = FALSE;
-
-    crtc = priv->info->crtcs[0];
-
-    if (crtc == NULL)
-       goto out;
-
-    current_info = XRRGetCrtcInfo (priv->xdisplay,
-                                  priv->info->resources,
-                                  crtc->id);
-
-    if (current_info == NULL)
-       goto out;
-
-    gdk_error_trap_push ();
-    status = XRRSetCrtcConfig (priv->xdisplay,
-                              priv->info->resources,
-                              crtc->id,
-                              current_info->timestamp,
-                              current_info->x,
-                              current_info->y,
-                              current_info->mode,
-                              current_info->rotation,
-                              current_info->outputs,
-                              current_info->noutput);
-
-    XRRFreeCrtcInfo (current_info);
-
-    gdk_flush ();
-    if (gdk_error_trap_pop ())
-       goto out;
-
-    if (status == RRSetConfigSuccess)
-       timestamp_updated = TRUE;
-out:
-    return timestamp_updated;
-}
-
-/**
  * gnome_rr_screen_refresh:
  * @screen: a #GnomeRRScreen
  * @error: location to store error, or %NULL
@@ -1127,18 +818,9 @@ gboolean
 gnome_rr_screen_refresh (GnomeRRScreen *screen,
                         GError       **error)
 {
-    gboolean refreshed;
-
     g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
-    gdk_x11_display_grab (gdk_screen_get_display (screen->priv->gdk_screen));
-
-    refreshed = screen_update (screen, FALSE, TRUE, error);
-    force_timestamp_update (screen); /* this is to keep other clients from thinking that the X server 
re-detected things by itself - bgo#621046 */
-
-    gdk_x11_display_ungrab (gdk_screen_get_display (screen->priv->gdk_screen));
-
-    return refreshed;
+    return screen_update (screen, FALSE, error);
 }
 
 /**
@@ -1146,81 +828,43 @@ gnome_rr_screen_refresh (GnomeRRScreen *screen,
  * @mode: (out): The current #GnomeRRDpmsMode of this screen
  **/
 gboolean
-gnome_rr_screen_get_dpms_mode (GnomeRRScreen *screen,
-                               GnomeRRDpmsMode *mode,
-                               GError **error)
+gnome_rr_screen_get_dpms_mode (GnomeRRScreen    *screen,
+                               GnomeRRDpmsMode  *mode,
+                               GError          **error)
 {
-    BOOL enabled = FALSE;
-    CARD16 state;
-    gboolean ret = FALSE;
+    MetaPowerSave power_save;
 
     g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
     g_return_val_if_fail (mode != NULL, FALSE);
 
-    if (!screen->priv->dpms_capable) {
+    power_save = meta_dbus_display_config_get_power_save_mode (screen->priv->proxy);
+
+    if (power_save == META_POWER_SAVE_UNKNOWN) {
         g_set_error_literal (error,
                              GNOME_RR_ERROR,
                              GNOME_RR_ERROR_NO_DPMS_EXTENSION,
                              "Display is not DPMS capable");
-        goto out;
-    }
-
-    if (!DPMSInfo (screen->priv->xdisplay,
-                   &state,
-                   &enabled)) {
-        g_set_error_literal (error,
-                             GNOME_RR_ERROR,
-                             GNOME_RR_ERROR_UNKNOWN,
-                             "Unable to get DPMS state");
-        goto out;
-    }
-
-    /* DPMS not enabled is a valid mode */
-    if (!enabled) {
-        *mode = GNOME_RR_DPMS_DISABLED;
-        ret = TRUE;
-        goto out;
+       return FALSE;
     }
 
-    switch (state) {
-    case DPMSModeOn:
+    switch (power_save) {
+    case META_POWER_SAVE_ON:
         *mode = GNOME_RR_DPMS_ON;
         break;
-    case DPMSModeStandby:
+    case META_POWER_SAVE_STANDBY:
         *mode = GNOME_RR_DPMS_STANDBY;
         break;
-    case DPMSModeSuspend:
+    case META_POWER_SAVE_SUSPEND:
         *mode = GNOME_RR_DPMS_SUSPEND;
         break;
-    case DPMSModeOff:
+    case META_POWER_SAVE_OFF:
         *mode = GNOME_RR_DPMS_OFF;
         break;
     default:
         g_assert_not_reached ();
         break;
     }
-    ret = TRUE;
-out:
-    return ret;
-}
 
-/**
- * gnome_rr_screen_clear_dpms_timeouts:
- **/
-static gboolean
-gnome_rr_screen_clear_dpms_timeouts (GnomeRRScreen *screen,
-                                     GError **error)
-{
-    gdk_error_trap_push ();
-    /* DPMSSetTimeouts() return value is often a lie, so ignore it */
-    DPMSSetTimeouts (screen->priv->xdisplay, 0, 0, 0);
-    if (gdk_error_trap_pop ()) {
-        g_set_error_literal (error,
-                             GNOME_RR_ERROR,
-                             GNOME_RR_ERROR_UNKNOWN,
-                             "Could not set DPMS timeouts");
-        return FALSE;
-    }
     return TRUE;
 }
 
@@ -1230,11 +874,11 @@ gnome_rr_screen_clear_dpms_timeouts (GnomeRRScreen *screen,
  * This method also disables the DPMS timeouts.
  **/
 gboolean
-gnome_rr_screen_set_dpms_mode (GnomeRRScreen *screen,
-                               GnomeRRDpmsMode mode,
-                               GError **error)
+gnome_rr_screen_set_dpms_mode (GnomeRRScreen    *screen,
+                               GnomeRRDpmsMode   mode,
+                               GError          **error)
 {
-    CARD16 state = 0;
+    MetaPowerSave power_save;
     gboolean ret;
     GnomeRRDpmsMode current_mode;
 
@@ -1243,48 +887,31 @@ gnome_rr_screen_set_dpms_mode (GnomeRRScreen *screen,
     /* set, if the new mode is different */
     ret = gnome_rr_screen_get_dpms_mode (screen, &current_mode, error);
     if (!ret)
-        goto out;
-    if (current_mode == mode) {
-        ret = gnome_rr_screen_clear_dpms_timeouts (screen, error);
-        goto out;
-    }
+       return FALSE;
+    if (current_mode == mode)
+       return TRUE;
 
     switch (mode) {
     case GNOME_RR_DPMS_ON:
-        state = DPMSModeOn;
+        power_save = META_POWER_SAVE_ON;
         break;
     case GNOME_RR_DPMS_STANDBY:
-        state = DPMSModeStandby;
+       power_save = META_POWER_SAVE_STANDBY;
         break;
     case GNOME_RR_DPMS_SUSPEND:
-        state = DPMSModeSuspend;
+       power_save = META_POWER_SAVE_SUSPEND;
         break;
     case GNOME_RR_DPMS_OFF:
-        state = DPMSModeOff;
+       power_save = META_POWER_SAVE_OFF;
         break;
     default:
         g_assert_not_reached ();
         break;
     }
 
-    gdk_error_trap_push ();
-    /* DPMSForceLevel() return value is often a lie, so ignore it */
-    DPMSForceLevel (screen->priv->xdisplay, state);
-    XSync (screen->priv->xdisplay, False);
-    if (gdk_error_trap_pop ()) {
-        ret = FALSE;
-        g_set_error_literal (error,
-                             GNOME_RR_ERROR,
-                             GNOME_RR_ERROR_UNKNOWN,
-                             "Could not change DPMS mode");
-        goto out;
-    }
+    meta_dbus_display_config_set_power_save_mode (screen->priv->proxy, power_save);
 
-    ret = gnome_rr_screen_clear_dpms_timeouts (screen, error);
-    if (!ret)
-        goto out;
-out:
-    return ret;
+    return TRUE;
 }
 
 /**
@@ -1405,7 +1032,7 @@ gnome_rr_screen_get_output_by_id (GnomeRRScreen *screen,
 
 /* GnomeRROutput */
 static GnomeRROutput *
-output_new (ScreenInfo *info, RROutput id)
+output_new (ScreenInfo *info, guint id)
 {
     GnomeRROutput *output = g_slice_new0 (GnomeRROutput);
     
@@ -1415,230 +1042,90 @@ output_new (ScreenInfo *info, RROutput id)
     return output;
 }
 
-static guint8 *
-get_property (Display *dpy,
-             RROutput output,
-             Atom atom,
-             gsize *len)
-{
-    unsigned char *prop;
-    int actual_format;
-    unsigned long nitems, bytes_after;
-    Atom actual_type;
-    guint8 *result;
-    
-    XRRGetOutputProperty (dpy, output, atom,
-                         0, 100, False, False,
-                         AnyPropertyType,
-                         &actual_type, &actual_format,
-                         &nitems, &bytes_after, &prop);
-    
-    if (actual_type == XA_INTEGER && actual_format == 8)
-    {
-       result = g_memdup (prop, nitems);
-       if (len)
-           *len = nitems;
-    }
-    else
-    {
-       result = NULL;
-    }
-    
-    XFree (prop);
-    
-    return result;
-}
-
-static guint8 *
-read_edid_data (GnomeRROutput *output, gsize *len)
+static void
+append_output_array (GnomeRROutput ***array, GnomeRROutput *output)
 {
-    Atom edid_atom;
-    guint8 *result;
+    unsigned i;
 
-    edid_atom = XInternAtom (DISPLAY (output), "EDID", FALSE);
-    result = get_property (DISPLAY (output),
-                          output->id, edid_atom, len);
+    for (i = 0; (*array)[i]; i++);
 
-    if (!result)
-    {
-       edid_atom = XInternAtom (DISPLAY (output), "EDID_DATA", FALSE);
-       result = get_property (DISPLAY (output),
-                              output->id, edid_atom, len);
-    }
-
-    if (!result)
-    {
-       edid_atom = XInternAtom (DISPLAY (output), "XFree86_DDC_EDID1_RAWDATA", FALSE);
-       result = get_property (DISPLAY (output),
-                              output->id, edid_atom, len);
-    }
+    *array = g_renew (GnomeRROutput *, *array, i + 2);
 
-    if (result)
-    {
-       if (*len % 128 == 0)
-           return result;
-       else
-           g_free (result);
-    }
-    
-    return NULL;
-}
-
-static char *
-get_connector_type_string (GnomeRROutput *output)
-{
-    char *result;
-    unsigned char *prop;
-    int actual_format;
-    unsigned long nitems, bytes_after;
-    Atom actual_type;
-    Atom connector_type;
-    char *connector_type_str;
-
-    result = NULL;
-
-    if (XRRGetOutputProperty (DISPLAY (output), output->id, output->info->screen->priv->connector_type_atom,
-                             0, 100, False, False,
-                             AnyPropertyType,
-                             &actual_type, &actual_format,
-                             &nitems, &bytes_after, &prop) != Success)
-       return NULL;
-
-    if (!(actual_type == XA_ATOM && actual_format == 32 && nitems == 1))
-       goto out;
-
-    connector_type = *((Atom *) prop);
-
-    connector_type_str = XGetAtomName (DISPLAY (output), connector_type);
-    if (connector_type_str) {
-       result = g_strdup (connector_type_str); /* so the caller can g_free() it */
-       XFree (connector_type_str);
-    }
-
-out:
-
-    XFree (prop);
-
-    return result;
+    (*array)[i] = output;
+    (*array)[i + 1] = NULL;
 }
 
 static void
-update_brightness_limits (GnomeRROutput *output)
-{
-    gint rc;
-    Atom atom;
-    XRRPropertyInfo *info;
-
-    gdk_error_trap_push ();
-    atom = XInternAtom (DISPLAY (output), "BACKLIGHT", FALSE);
-    info = XRRQueryOutputProperty (DISPLAY (output), output->id, atom);
-    rc = gdk_error_trap_pop ();
-    if (rc != Success)
-    {
-        if (rc != BadName)
-          g_warning ("could not get output property for %s, rc: %i",
-                    output->name, rc);
-        goto out;
-    }
-    if (info == NULL)
-    {
-        g_warning ("could not get output property for %s",
-                  output->name);
-        goto out;
-    }
-    if (!info->range || info->num_values != 2)
-    {
-        g_debug ("backlight %s was not range", output->name);
-        goto out;
-    }
-    output->backlight_min = info->values[0];
-    output->backlight_max = info->values[1];
-out:
-    if (info != NULL)
-    {
-        XFree (info);
-    }
-}
-
-static gboolean
-output_initialize (GnomeRROutput *output, XRRScreenResources *res, GError **error)
+output_initialize (GnomeRROutput *output, GVariant *info)
 {
-    XRROutputInfo *info = XRRGetOutputInfo (
-       DISPLAY (output), res, output->id);
     GPtrArray *a;
-    int i;
-    
-#if 0
-    g_print ("Output %lx Timestamp: %u\n", output->id, (guint32)info->timestamp);
-#endif
-    
-    if (!info || !output->info)
-    {
-       /* FIXME: see the comment in crtc_initialize() */
-       /* Translators: here, an "output" is a video output */
-       g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_RANDR_ERROR,
-                    _("could not get information about output %d"),
-                    (int) output->id);
-       return FALSE;
-    }
-    
-    output->name = g_strdup (info->name); /* FIXME: what is nameLen used for? */
-    output->display_name = NULL; /* set first time the getter is used */
-    output->current_crtc = crtc_by_id (output->info, info->crtc);
-    output->width_mm = info->mm_width;
-    output->height_mm = info->mm_height;
-    output->connected = (info->connection == RR_Connected);
-    output->connector_type = get_connector_type_string (output);
+    GVariantIter *crtcs, *clones, *modes;
+    GVariant *properties;
+    int current_crtc_id;
+    guint id;
+
+    g_variant_get (info, "(uxiaussssiauau a{sv})",
+                  &output->id, &output->winsys_id,
+                  &current_crtc_id, &crtcs,
+                  &output->name, &output->vendor,
+                  &output->product, &output->serial,
+                  &output->backlight,
+                  &modes, &clones, &properties);
 
     /* Possible crtcs */
     a = g_ptr_array_new ();
-    
-    for (i = 0; i < info->ncrtc; ++i)
+    while (g_variant_iter_loop (crtcs, "u", &id))
     {
-       GnomeRRCrtc *crtc = crtc_by_id (output->info, info->crtcs[i]);
+       GnomeRRCrtc *crtc = crtc_by_id (output->info, id);
        
-       if (crtc)
-           g_ptr_array_add (a, crtc);
+       if (!crtc)
+           continue;
+
+       g_ptr_array_add (a, crtc);
+
+       if (crtc->id == current_crtc_id)
+       {
+           output->current_crtc = crtc;
+           append_output_array (&crtc->current_outputs, output);
+       }
+
+       append_output_array (&crtc->possible_outputs, output);
     }
     g_ptr_array_add (a, NULL);
     output->possible_crtcs = (GnomeRRCrtc **)g_ptr_array_free (a, FALSE);
-    
+    g_variant_iter_free (crtcs);
+
     /* Clones */
     a = g_ptr_array_new ();
-    for (i = 0; i < info->nclone; ++i)
+    while (g_variant_iter_loop (clones, "u", &id))
     {
-       GnomeRROutput *gnome_rr_output = gnome_rr_output_by_id (output->info, info->clones[i]);
+       GnomeRROutput *gnome_rr_output = gnome_rr_output_by_id (output->info, id);
        
        if (gnome_rr_output)
            g_ptr_array_add (a, gnome_rr_output);
     }
     g_ptr_array_add (a, NULL);
     output->clones = (GnomeRROutput **)g_ptr_array_free (a, FALSE);
+    g_variant_iter_free (clones);
     
     /* Modes */
     a = g_ptr_array_new ();
-    for (i = 0; i < info->nmode; ++i)
+    while (g_variant_iter_loop (modes, "u", &id))
     {
-       GnomeRRMode *mode = mode_by_id (output->info, info->modes[i]);
+       GnomeRRMode *mode = mode_by_id (output->info, id);
        
        if (mode)
            g_ptr_array_add (a, mode);
     }
     g_ptr_array_add (a, NULL);
     output->modes = (GnomeRRMode **)g_ptr_array_free (a, FALSE);
+    g_variant_iter_free (modes);
     
-    output->n_preferred = info->npreferred;
-    
-    /* Edid data */
-    output->edid_data = read_edid_data (output, &output->edid_size);
+    g_variant_lookup (properties, "primary", "b", &output->is_primary);
+    g_variant_lookup (properties, "presentation", "b", &output->is_presentation);
 
-    /* brightness data */
-    if (output->connected)
-        update_brightness_limits (output);
-
-    XRRFreeOutputInfo (info);
-
-    return TRUE;
+    if (output->is_primary)
+       output->info->primary = output;
 }
 
 static GnomeRROutput*
@@ -1653,14 +1140,14 @@ output_copy (const GnomeRROutput *from)
     output->id = from->id;
     output->info = from->info;
     output->name = g_strdup (from->name);
+    output->vendor = g_strdup (from->vendor);
+    output->product = g_strdup (from->product);
+    output->serial = g_strdup (from->serial);
     output->current_crtc = from->current_crtc;
-    output->width_mm = from->width_mm;
-    output->height_mm = from->height_mm;
-    output->connected = from->connected;
-    output->n_preferred = from->n_preferred;
-    output->connector_type = g_strdup (from->connector_type);
-    output->backlight_min = -1;
-    output->backlight_max = -1;
+    output->backlight = from->backlight;
+
+    output->is_primary = from->is_primary;
+    output->is_presentation = from->is_presentation;
 
     array = g_ptr_array_new ();
     for (p_crtc = from->possible_crtcs; *p_crtc != NULL; p_crtc++)
@@ -1683,9 +1170,6 @@ output_copy (const GnomeRROutput *from)
     }
     output->modes = (GnomeRRMode**) g_ptr_array_free (array, FALSE);
 
-    output->edid_size = from->edid_size;
-    output->edid_data = g_memdup (from->edid_data, from->edid_size);
-
     return output;
 }
 
@@ -1695,10 +1179,11 @@ output_free (GnomeRROutput *output)
     g_free (output->clones);
     g_free (output->modes);
     g_free (output->possible_crtcs);
-    g_free (output->edid_data);
     g_free (output->name);
+    g_free (output->vendor);
+    g_free (output->product);
+    g_free (output->serial);
     g_free (output->display_name);
-    g_free (output->connector_type);
     g_slice_free (GnomeRROutput, output);
 }
 
@@ -1710,15 +1195,6 @@ gnome_rr_output_get_id (GnomeRROutput *output)
     return output->id;
 }
 
-const guint8 *
-gnome_rr_output_get_edid_data (GnomeRROutput *output, gsize *size)
-{
-    g_return_val_if_fail (output != NULL, NULL);
-    if (size)
-        *size = output->edid_size;
-    return output->edid_data;
-}
-
 /**
  * gnome_rr_output_get_ids_from_edid:
  * @output: a #GnomeRROutput
@@ -1726,32 +1202,17 @@ gnome_rr_output_get_edid_data (GnomeRROutput *output, gsize *size)
  * @product: (out) (allow-none):
  * @serial: (out) (allow-none):
  */
-gboolean
+void
 gnome_rr_output_get_ids_from_edid (GnomeRROutput         *output,
                                    char                 **vendor,
-                                   int                   *product,
-                                   int                   *serial)
+                                   char                 **product,
+                                   char                 **serial)
 {
-    MonitorInfo *info;
-
-    g_return_val_if_fail (output != NULL, FALSE);
-
-    if (!output->edid_data)
-        return FALSE;
-    info = decode_edid (output->edid_data);
-    if (!info)
-        return FALSE;
-    if (vendor)
-        *vendor = g_memdup (info->manufacturer_code, 4);
-    if (product)
-        *product = info->product_code;
-    if (serial)
-        *serial = info->serial_number;
-
-    g_free (info);
-
-    return TRUE;
+    g_return_if_fail (output != NULL);
 
+    *vendor = g_strdup (output->vendor);
+    *product = g_strdup (output->product);
+    *serial = g_strdup (output->serial);
 }
 
 static void
@@ -1763,31 +1224,13 @@ ensure_display_name (GnomeRROutput *output)
     if (gnome_rr_output_is_builtin_display (output))
         output->display_name = g_strdup (_("Built-in Display"));
 
-    if (output->display_name == NULL
-        && output->edid_data != NULL) {
-        MonitorInfo *info;
-
-        info = decode_edid (output->edid_data);
-        if (info != NULL)
-            output->display_name = make_display_name (info);
-
-        g_free (info);
-    }
-
-    if (output->display_name == NULL) {
-        char *inches;
-        inches = make_display_size_string (output->width_mm, output->height_mm);
-        if (inches != NULL) {
-            /* Translators: %s is the size of the monitor in inches */
-            output->display_name = g_strdup_printf (_("%s Display"), inches);
-        }
-        g_free (inches);
-    }
+#if 0
+    if (output->display_name == NULL)
+       output->display_name = make_display_name (output);
+#endif
 
-    /* last chance on the stairway */
-    if (output->display_name == NULL) {
+    if (output->display_name == NULL)
       output->display_name = g_strdup (_("Unknown Display"));
-    }
 }
 
 const char *
@@ -1801,136 +1244,33 @@ gnome_rr_output_get_display_name (GnomeRROutput *output)
 }
 
 /**
- * gnome_rr_output_get_backlight_min:
- *
- * Returns: The mimimum backlight value, or -1 if not supported
- */
-gint
-gnome_rr_output_get_backlight_min (GnomeRROutput *output)
-{
-    g_return_val_if_fail (output != NULL, -1);
-    return output->backlight_min;
-}
-
-/**
- * gnome_rr_output_get_backlight_max:
- *
- * Returns: The maximum backlight value, or -1 if not supported
- */
-gint
-gnome_rr_output_get_backlight_max (GnomeRROutput *output)
-{
-    g_return_val_if_fail (output != NULL, -1);
-    return output->backlight_max;
-}
-
-/**
  * gnome_rr_output_get_backlight:
  *
  * Returns: The currently set backlight brightness
  */
-gint
-gnome_rr_output_get_backlight (GnomeRROutput *output, GError **error)
-{
-    guint now = -1;
-    unsigned long nitems;
-    unsigned long bytes_after;
-    guint *prop;
-    Atom atom;
-    Atom actual_type;
-    int actual_format;
-    gint retval;
-
+int
+gnome_rr_output_get_backlight (GnomeRROutput *output)
+{
     g_return_val_if_fail (output != NULL, -1);
 
-    gdk_error_trap_push ();
-    atom = XInternAtom (DISPLAY (output), "BACKLIGHT", FALSE);
-    retval = XRRGetOutputProperty (DISPLAY (output), output->id, atom,
-                                  0, 4, False, False, None,
-                                  &actual_type, &actual_format,
-                                  &nitems, &bytes_after, ((unsigned char **)&prop));
-    gdk_flush ();
-    if (gdk_error_trap_pop ())
-    {
-        g_set_error_literal (error,
-                            GNOME_RR_ERROR,
-                            GNOME_RR_ERROR_UNKNOWN,
-                            "unhandled X error while getting the range of backlight values");
-        goto out;
-    }
-
-    if (retval != Success) {
-        g_set_error_literal (error,
-                            GNOME_RR_ERROR,
-                            GNOME_RR_ERROR_RANDR_ERROR,
-                            "could not get the range of backlight values");
-        goto out;
-    }
-    if (actual_type == XA_INTEGER &&
-        nitems == 1 &&
-        actual_format == 32)
-    {
-        memcpy (&now, prop, sizeof (guint));
-    }
-    else
-    {
-       g_set_error (error,
-                    GNOME_RR_ERROR,
-                    GNOME_RR_ERROR_RANDR_ERROR,
-                    "failed to get correct property type, got %lu,%i",
-                    nitems, actual_format);
-    }
-out:
-    XFree (prop);
-    return now;
+    return output->backlight;
 }
 
 /**
  * gnome_rr_output_set_backlight:
- * @value: the absolute value which is min >= this <= max
+ * @value: the absolute value which is 0 >= this <= 100
  *
  * Returns: %TRUE for success
  */
 gboolean
 gnome_rr_output_set_backlight (GnomeRROutput *output, gint value, GError **error)
 {
-    gboolean ret = FALSE;
-    Atom atom;
-
     g_return_val_if_fail (output != NULL, FALSE);
 
-    /* check this is sane */
-    if (value < output->backlight_min ||
-        value > output->backlight_max)
-    {
-       g_set_error (error,
-                    GNOME_RR_ERROR,
-                    GNOME_RR_ERROR_BOUNDS_ERROR,
-                    "out of brightness range: %i, has to be %i -> %i",
-                    value,
-                    output->backlight_max, output->backlight_min);
-       goto out;
-    }
-
-    /* don't abort on error */
-    gdk_error_trap_push ();
-    atom = XInternAtom (DISPLAY (output), "BACKLIGHT", FALSE);
-    XRRChangeOutputProperty (DISPLAY (output), output->id, atom,
-                            XA_INTEGER, 32, PropModeReplace,
-                            (unsigned char *) &value, 1);
-    if (gdk_error_trap_pop ())
-    {
-        g_set_error_literal (error,
-                            GNOME_RR_ERROR,
-                            GNOME_RR_ERROR_UNKNOWN,
-                            "unhandled X error while setting the backlight values");
-        goto out;
-    }
-
-    /* we assume this succeeded as there's no return value */
-    ret = TRUE;
-out:
-    return ret;
+    return meta_dbus_display_config_call_change_backlight_sync (output->info->screen->priv->proxy,
+                                                               output->info->serial,
+                                                               output->id, value,
+                                                               NULL, error);
 }
 
 /**
@@ -1966,15 +1306,6 @@ gnome_rr_output_get_crtc (GnomeRROutput *output)
     return output->current_crtc;
 }
 
-/* Returns NULL if the ConnectorType property is not available */
-const char *
-gnome_rr_output_get_connector_type (GnomeRROutput *output)
-{
-    g_return_val_if_fail (output != NULL, NULL);
-
-    return output->connector_type;
-}
-
 gboolean
 _gnome_rr_output_name_is_builtin_display (const char *name)
 {
@@ -1997,20 +1328,7 @@ gnome_rr_output_is_builtin_display (GnomeRROutput *output)
 {
     g_return_val_if_fail (output != NULL, FALSE);
 
-    if (!output->connected)
-       return FALSE;
-
-    /* The ConnectorType property is present in RANDR 1.3 and greater */
-    if (g_strcmp0 (output->connector_type, GNOME_RR_CONNECTOR_TYPE_PANEL) == 0)
-       return TRUE;
-
-    /* Older versions of RANDR - this is a best guess, as @#$% RANDR doesn't have standard output names,
-     * so drivers can use whatever they like.
-     */
-    if (_gnome_rr_output_name_is_builtin_display (output->name))
-        return TRUE;
-
-    return FALSE;
+    return _gnome_rr_output_name_is_builtin_display (output->name);
 }
 
 GnomeRRMode *
@@ -2052,28 +1370,11 @@ gnome_rr_output_get_name (GnomeRROutput *output)
     return output->name;
 }
 
-int
-gnome_rr_output_get_width_mm (GnomeRROutput *output)
-{
-    g_assert (output != NULL);
-    return output->width_mm;
-}
-
-int
-gnome_rr_output_get_height_mm (GnomeRROutput *output)
-{
-    g_assert (output != NULL);
-    return output->height_mm;
-}
-
 GnomeRRMode *
 gnome_rr_output_get_preferred_mode (GnomeRROutput *output)
 {
     g_return_val_if_fail (output != NULL, NULL);
-    if (output->n_preferred)
-       return output->modes[0];
-    
-    return NULL;
+    return output->modes[0];
 }
 
 GnomeRRMode **
@@ -2084,13 +1385,6 @@ gnome_rr_output_list_modes (GnomeRROutput *output)
 }
 
 gboolean
-gnome_rr_output_is_connected (GnomeRROutput *output)
-{
-    g_return_val_if_fail (output != NULL, FALSE);
-    return output->connected;
-}
-
-gboolean
 gnome_rr_output_supports_mode (GnomeRROutput *output,
                               GnomeRRMode   *mode)
 {
@@ -2129,150 +1423,26 @@ gnome_rr_output_can_clone (GnomeRROutput *output,
 gboolean
 gnome_rr_output_get_is_primary (GnomeRROutput *output)
 {
-    return output->info->primary == output->id;
-}
-
-void
-gnome_rr_screen_set_primary_output (GnomeRRScreen *screen,
-                                    GnomeRROutput *output)
-{
-    GnomeRRScreenPrivate *priv;
-    RROutput id;
-
-    g_return_if_fail (GNOME_IS_RR_SCREEN (screen));
-
-    priv = screen->priv;
-
-    if (output)
-        id = output->id;
-    else
-        id = None;
-
-    if (SERVERS_RANDR_IS_AT_LEAST_1_3 (priv))
-        XRRSetOutputPrimary (priv->xdisplay, priv->xroot, id);
+    return output->is_primary;
 }
 
 /* GnomeRRCrtc */
-typedef struct
-{
-    Rotation xrot;
-    GnomeRRRotation rot;
-} RotationMap;
-
-static const RotationMap rotation_map[] =
-{
-    { RR_Rotate_0, GNOME_RR_ROTATION_0 },
-    { RR_Rotate_90, GNOME_RR_ROTATION_90 },
-    { RR_Rotate_180, GNOME_RR_ROTATION_180 },
-    { RR_Rotate_270, GNOME_RR_ROTATION_270 },
-    { RR_Reflect_X, GNOME_RR_REFLECT_X },
-    { RR_Reflect_Y, GNOME_RR_REFLECT_Y },
+static const GnomeRRRotation rotation_map[] =
+{
+    GNOME_RR_ROTATION_0,
+    GNOME_RR_ROTATION_90,
+    GNOME_RR_ROTATION_180,
+    GNOME_RR_ROTATION_270,
+    GNOME_RR_REFLECT_X | GNOME_RR_ROTATION_0,
+    GNOME_RR_REFLECT_X | GNOME_RR_ROTATION_90,
+    GNOME_RR_REFLECT_X | GNOME_RR_ROTATION_180,
+    GNOME_RR_REFLECT_X | GNOME_RR_ROTATION_270,
 };
 
 static GnomeRRRotation
-gnome_rr_rotation_from_xrotation (Rotation r)
+gnome_rr_rotation_from_transform (enum wl_output_transform transform)
 {
-    int i;
-    GnomeRRRotation result = 0;
-    
-    for (i = 0; i < G_N_ELEMENTS (rotation_map); ++i)
-    {
-       if (r & rotation_map[i].xrot)
-           result |= rotation_map[i].rot;
-    }
-    
-    return result;
-}
-
-static Rotation
-xrotation_from_rotation (GnomeRRRotation r)
-{
-    int i;
-    Rotation result = 0;
-    
-    for (i = 0; i < G_N_ELEMENTS (rotation_map); ++i)
-    {
-       if (r & rotation_map[i].rot)
-           result |= rotation_map[i].xrot;
-    }
-    
-    return result;
-}
-
-gboolean
-gnome_rr_crtc_set_config_with_time (GnomeRRCrtc      *crtc,
-                                   guint32           timestamp,
-                                   int               x,
-                                   int               y,
-                                   GnomeRRMode      *mode,
-                                   GnomeRRRotation   rotation,
-                                   GnomeRROutput   **outputs,
-                                   int               n_outputs,
-                                   GError          **error)
-{
-    ScreenInfo *info;
-    GArray *output_ids;
-    Status status;
-    gboolean result;
-    int i;
-    
-    g_return_val_if_fail (crtc != NULL, FALSE);
-    g_return_val_if_fail (mode != NULL || outputs == NULL || n_outputs == 0, FALSE);
-    g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-    
-    info = crtc->info;
-    
-    if (mode)
-    {
-       if (x + mode->width > info->max_width
-           || y + mode->height > info->max_height)
-       {
-           g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_BOUNDS_ERROR,
-                        /* Translators: the "position", "size", and "maximum"
-                         * words here are not keywords; please translate them
-                         * as usual.  A CRTC is a CRT Controller (this is X terminology) */
-                        _("requested position/size for CRTC %d is outside the allowed limit: "
-                          "position=(%d, %d), size=(%d, %d), maximum=(%d, %d)"),
-                        (int) crtc->id,
-                        x, y,
-                        mode->width, mode->height,
-                        info->max_width, info->max_height);
-           return FALSE;
-       }
-    }
-    
-    output_ids = g_array_new (FALSE, FALSE, sizeof (RROutput));
-    
-    if (outputs)
-    {
-       for (i = 0; i < n_outputs; ++i)
-           g_array_append_val (output_ids, outputs[i]->id);
-    }
-
-    gdk_error_trap_push ();
-    status = XRRSetCrtcConfig (DISPLAY (crtc), info->resources, crtc->id,
-                              timestamp, 
-                              x, y,
-                              mode ? mode->id : None,
-                              xrotation_from_rotation (rotation),
-                              (RROutput *)output_ids->data,
-                              output_ids->len);
-    
-    g_array_free (output_ids, TRUE);
-
-    if (gdk_error_trap_pop () || status != RRSetConfigSuccess) {
-       /* Translators: CRTC is a CRT Controller (this is X terminology).
-        * It is *very* unlikely that you'll ever get this error, so it is
-        * only listed for completeness. */
-       g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_RANDR_ERROR,
-                    _("could not set the configuration for CRTC %d"),
-                    (int) crtc->id);
-        return FALSE;
-    } else {
-        result = TRUE;
-    }
-    
-    return result;
+    return rotation_map[transform];
 }
 
 GnomeRRMode *
@@ -2309,7 +1479,6 @@ gnome_rr_crtc_can_drive_output (GnomeRRCrtc   *crtc,
     return FALSE;
 }
 
-/* FIXME: merge with get_mode()? */
 /**
  * gnome_rr_crtc_get_position:
  * @crtc: a #GnomeRRCrtc
@@ -2330,19 +1499,32 @@ gnome_rr_crtc_get_position (GnomeRRCrtc *crtc,
        *y = crtc->y;
 }
 
-/* FIXME: merge with get_mode()? */
 GnomeRRRotation
 gnome_rr_crtc_get_current_rotation (GnomeRRCrtc *crtc)
 {
     g_assert(crtc != NULL);
-    return crtc->current_rotation;
+    return gnome_rr_rotation_from_transform (crtc->transform);
+}
+
+static GnomeRRRotation
+gnome_rr_rotation_from_all_transforms (int all_transforms)
+{
+    GnomeRRRotation ret = all_transforms & 0x3;
+
+    if (all_transforms & (1 << WL_OUTPUT_TRANSFORM_FLIPPED))
+       ret |= GNOME_RR_REFLECT_X;
+
+    if (all_transforms & (1 << WL_OUTPUT_TRANSFORM_FLIPPED_180))
+       ret |= GNOME_RR_REFLECT_Y;
+
+    return ret;
 }
 
 GnomeRRRotation
 gnome_rr_crtc_get_rotations (GnomeRRCrtc *crtc)
 {
     g_assert(crtc != NULL);
-    return crtc->rotations;
+    return gnome_rr_rotation_from_all_transforms (crtc->all_transforms);
 }
 
 gboolean
@@ -2350,16 +1532,18 @@ gnome_rr_crtc_supports_rotation (GnomeRRCrtc *   crtc,
                                 GnomeRRRotation rotation)
 {
     g_return_val_if_fail (crtc != NULL, FALSE);
-    return (crtc->rotations & rotation);
+    return (gnome_rr_rotation_from_all_transforms (crtc->all_transforms) & rotation);
 }
 
 static GnomeRRCrtc *
-crtc_new (ScreenInfo *info, RROutput id)
+crtc_new (ScreenInfo *info, guint id)
 {
     GnomeRRCrtc *crtc = g_slice_new0 (GnomeRRCrtc);
     
     crtc->id = id;
     crtc->info = info;
+    crtc->current_outputs = g_new0 (GnomeRROutput *, 1);
+    crtc->possible_outputs = g_new0 (GnomeRROutput *, 1);
     
     return crtc;
 }
@@ -2376,8 +1560,8 @@ crtc_copy (const GnomeRRCrtc *from)
     to->current_mode = from->current_mode;
     to->x = from->x;
     to->y = from->y;
-    to->current_rotation = from->current_rotation;
-    to->rotations = from->rotations;
+    to->transform = from->transform;
+    to->all_transforms = from->all_transforms;
     to->gamma_size = from->gamma_size;
 
     array = g_ptr_array_new ();
@@ -2397,73 +1581,26 @@ crtc_copy (const GnomeRRCrtc *from)
     return to;
 }
 
-static gboolean
-crtc_initialize (GnomeRRCrtc        *crtc,
-                XRRScreenResources *res,
-                GError            **error)
+static void
+crtc_initialize (GnomeRRCrtc *crtc, GVariant *info)
 {
-    XRRCrtcInfo *info = XRRGetCrtcInfo (DISPLAY (crtc), res, crtc->id);
-    GPtrArray *a;
-    int i;
-    
-#if 0
-    g_print ("CRTC %lx Timestamp: %u\n", crtc->id, (guint32)info->timestamp);
-#endif
-    
-    if (!info)
-    {
-       /* FIXME: We need to reaquire the screen resources */
-       /* FIXME: can we actually catch BadRRCrtc, and does it make sense to emit that? */
-
-       /* Translators: CRTC is a CRT Controller (this is X terminology).
-        * It is *very* unlikely that you'll ever get this error, so it is
-        * only listed for completeness. */
-       g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_RANDR_ERROR,
-                    _("could not get information about CRTC %d"),
-                    (int) crtc->id);
-       return FALSE;
-    }
-    
-    /* GnomeRRMode */
-    crtc->current_mode = mode_by_id (crtc->info, info->mode);
-    
-    crtc->x = info->x;
-    crtc->y = info->y;
-    
-    /* Current outputs */
-    a = g_ptr_array_new ();
-    for (i = 0; i < info->noutput; ++i)
-    {
-       GnomeRROutput *output = gnome_rr_output_by_id (crtc->info, info->outputs[i]);
-       
-       if (output)
-           g_ptr_array_add (a, output);
-    }
-    g_ptr_array_add (a, NULL);
-    crtc->current_outputs = (GnomeRROutput **)g_ptr_array_free (a, FALSE);
-    
-    /* Possible outputs */
-    a = g_ptr_array_new ();
-    for (i = 0; i < info->npossible; ++i)
-    {
-       GnomeRROutput *output = gnome_rr_output_by_id (crtc->info, info->possible[i]);
-       
-       if (output)
-           g_ptr_array_add (a, output);
-    }
-    g_ptr_array_add (a, NULL);
-    crtc->possible_outputs = (GnomeRROutput **)g_ptr_array_free (a, FALSE);
-    
-    /* Rotations */
-    crtc->current_rotation = gnome_rr_rotation_from_xrotation (info->rotation);
-    crtc->rotations = gnome_rr_rotation_from_xrotation (info->rotations);
-    
-    XRRFreeCrtcInfo (info);
+    GVariantIter *all_transforms;
+    int current_mode_id;
+    guint transform;
 
-    /* get an store gamma size */
-    crtc->gamma_size = XRRGetCrtcGammaSize (DISPLAY (crtc), crtc->id);
+    g_variant_get (info, "(uxiiiiiuau a{sv})",
+                  &crtc->id, &crtc->winsys_id,
+                  &crtc->x, &crtc->y,
+                  NULL, NULL,
+                  &current_mode_id,
+                  &crtc->transform, &all_transforms,
+                  NULL);
 
-    return TRUE;
+    /* GnomeRRMode */
+    crtc->current_mode = current_mode_id >= 0 ? mode_by_id (crtc->info, current_mode_id) : NULL;
+    
+    while (g_variant_iter_loop (all_transforms, "u", &transform))
+       crtc->all_transforms |= 1 << transform;
 }
 
 static void
@@ -2476,7 +1613,7 @@ crtc_free (GnomeRRCrtc *crtc)
 
 /* GnomeRRMode */
 static GnomeRRMode *
-mode_new (ScreenInfo *info, RRMode id)
+mode_new (ScreenInfo *info, guint id)
 {
     GnomeRRMode *mode = g_slice_new0 (GnomeRRMode);
     
@@ -2515,15 +1652,16 @@ gnome_rr_mode_get_height (GnomeRRMode *mode)
 }
 
 static void
-mode_initialize (GnomeRRMode *mode, XRRModeInfo *info)
+mode_initialize (GnomeRRMode *mode, GVariant *info)
 {
-    g_assert (mode != NULL);
-    g_assert (info != NULL);
+    gdouble frequency;
+
+    g_variant_get (info, "(uxuud)",
+                  &mode->id, &mode->winsys_id,
+                  &mode->width, &mode->height,
+                  &frequency);
     
-    mode->name = g_strdup (info->name);
-    mode->width = info->width;
-    mode->height = info->height;
-    mode->freq = ((info->dotClock / (double)info->hTotal) / info->vTotal + 0.5) * 1000;
+    mode->freq = frequency * 1000;
 }
 
 static GnomeRRMode *
@@ -2533,7 +1671,6 @@ mode_copy (const GnomeRRMode *from)
 
     to->id = from->id;
     to->info = from->info;
-    to->name = g_strdup (from->name);
     to->width = from->width;
     to->height = from->height;
     to->freq = from->freq;
@@ -2544,78 +1681,19 @@ mode_copy (const GnomeRRMode *from)
 static void
 mode_free (GnomeRRMode *mode)
 {
-    g_free (mode->name);
     g_slice_free (GnomeRRMode, mode);
 }
 
-void
-gnome_rr_crtc_set_gamma (GnomeRRCrtc *crtc, int size,
-                        unsigned short *red,
-                        unsigned short *green,
-                        unsigned short *blue)
-{
-    int copy_size;
-    XRRCrtcGamma *gamma;
-
-    g_return_if_fail (crtc != NULL);
-    g_return_if_fail (red != NULL);
-    g_return_if_fail (green != NULL);
-    g_return_if_fail (blue != NULL);
-
-    if (size != crtc->gamma_size)
-       return;
-
-    gamma = XRRAllocGamma (crtc->gamma_size);
-
-    copy_size = crtc->gamma_size * sizeof (unsigned short);
-    memcpy (gamma->red, red, copy_size);
-    memcpy (gamma->green, green, copy_size);
-    memcpy (gamma->blue, blue, copy_size);
-
-    XRRSetCrtcGamma (DISPLAY (crtc), crtc->id, gamma);
-    XRRFreeGamma (gamma);
-}
-
 gboolean
-gnome_rr_crtc_get_gamma (GnomeRRCrtc *crtc, int *size,
-                        unsigned short **red, unsigned short **green,
-                        unsigned short **blue)
-{
-    int copy_size;
-    unsigned short *r, *g, *b;
-    XRRCrtcGamma *gamma;
-
-    g_return_val_if_fail (crtc != NULL, FALSE);
-
-    gamma = XRRGetCrtcGamma (DISPLAY (crtc), crtc->id);
-    if (!gamma)
-       return FALSE;
-
-    copy_size = crtc->gamma_size * sizeof (unsigned short);
-
-    if (red) {
-       r = g_new0 (unsigned short, crtc->gamma_size);
-       memcpy (r, gamma->red, copy_size);
-       *red = r;
-    }
-
-    if (green) {
-       g = g_new0 (unsigned short, crtc->gamma_size);
-       memcpy (g, gamma->green, copy_size);
-       *green = g;
-    }
-
-    if (blue) {
-       b = g_new0 (unsigned short, crtc->gamma_size);
-       memcpy (b, gamma->blue, copy_size);
-       *blue = b;
-    }
-
-    XRRFreeGamma (gamma);
-
-    if (size)
-       *size = crtc->gamma_size;
-
-    return TRUE;
+_gnome_rr_screen_apply_configuration (GnomeRRScreen  *screen,
+                                     gboolean        persistent,
+                                     GVariant       *crtcs,
+                                     GVariant       *outputs,
+                                     GError        **error)
+{
+  return meta_dbus_display_config_call_apply_configuration_sync (screen->priv->proxy,
+                                                                screen->priv->info->serial,
+                                                                persistent,
+                                                                crtcs, outputs,
+                                                                NULL, error);
 }
-
diff --git a/libgnome-desktop/gnome-rr.h b/libgnome-desktop/gnome-rr.h
index 08bceca..316e088 100644
--- a/libgnome-desktop/gnome-rr.h
+++ b/libgnome-desktop/gnome-rr.h
@@ -111,11 +111,6 @@ GnomeRROutput **gnome_rr_screen_list_outputs       (GnomeRRScreen         *scree
 GnomeRRCrtc **  gnome_rr_screen_list_crtcs         (GnomeRRScreen         *screen);
 GnomeRRMode **  gnome_rr_screen_list_modes         (GnomeRRScreen         *screen);
 GnomeRRMode **  gnome_rr_screen_list_clone_modes   (GnomeRRScreen        *screen);
-void            gnome_rr_screen_set_size           (GnomeRRScreen         *screen,
-                                                   int                    width,
-                                                   int                    height,
-                                                   int                    mm_width,
-                                                   int                    mm_height);
 GnomeRRCrtc *   gnome_rr_screen_get_crtc_by_id     (GnomeRRScreen         *screen,
                                                    guint32                id);
 gboolean        gnome_rr_screen_refresh            (GnomeRRScreen         *screen,
@@ -129,12 +124,6 @@ void            gnome_rr_screen_get_ranges         (GnomeRRScreen         *scree
                                                    int                   *max_width,
                                                    int                   *min_height,
                                                    int                   *max_height);
-void            gnome_rr_screen_get_timestamps     (GnomeRRScreen         *screen,
-                                                   guint32               *change_timestamp_ret,
-                                                   guint32               *config_timestamp_ret);
-
-void            gnome_rr_screen_set_primary_output (GnomeRRScreen         *screen,
-                                                    GnomeRROutput         *output);
 
 GnomeRRMode   **gnome_rr_screen_create_clone_modes (GnomeRRScreen *screen);
 
@@ -149,21 +138,12 @@ gboolean        gnome_rr_screen_set_dpms_mode      (GnomeRRScreen         *scree
 guint32         gnome_rr_output_get_id             (GnomeRROutput         *output);
 const char *    gnome_rr_output_get_name           (GnomeRROutput         *output);
 const char *    gnome_rr_output_get_display_name   (GnomeRROutput         *output);
-gboolean        gnome_rr_output_is_connected       (GnomeRROutput         *output);
-int             gnome_rr_output_get_size_inches    (GnomeRROutput         *output);
-int             gnome_rr_output_get_width_mm       (GnomeRROutput         *outout);
-int             gnome_rr_output_get_height_mm      (GnomeRROutput         *output);
-const guint8 *  gnome_rr_output_get_edid_data      (GnomeRROutput         *output,
-                                                    gsize                 *size);
-gboolean        gnome_rr_output_get_ids_from_edid  (GnomeRROutput         *output,
+void            gnome_rr_output_get_ids_from_edid  (GnomeRROutput         *output,
                                                     char                 **vendor,
-                                                    int                   *product,
-                                                    int                   *serial);
+                                                    char                 **product,
+                                                    char                 **serial);
 
-gint            gnome_rr_output_get_backlight_min  (GnomeRROutput         *output);
-gint            gnome_rr_output_get_backlight_max  (GnomeRROutput         *output);
-gint            gnome_rr_output_get_backlight      (GnomeRROutput         *output,
-                                                    GError                **error);
+gint            gnome_rr_output_get_backlight      (GnomeRROutput         *output);
 gboolean        gnome_rr_output_set_backlight      (GnomeRROutput         *output,
                                                     gint                   value,
                                                     GError                **error);
@@ -171,7 +151,6 @@ gboolean        gnome_rr_output_set_backlight      (GnomeRROutput         *outpu
 GnomeRRCrtc **  gnome_rr_output_get_possible_crtcs (GnomeRROutput         *output);
 GnomeRRMode *   gnome_rr_output_get_current_mode   (GnomeRROutput         *output);
 GnomeRRCrtc *   gnome_rr_output_get_crtc           (GnomeRROutput         *output);
-const char *    gnome_rr_output_get_connector_type (GnomeRROutput         *output);
 gboolean        gnome_rr_output_is_builtin_display (GnomeRROutput         *output);
 void            gnome_rr_output_get_position       (GnomeRROutput         *output,
                                                    int                   *x,
@@ -193,15 +172,6 @@ int             gnome_rr_mode_get_freq             (GnomeRRMode           *mode)
 /* GnomeRRCrtc */
 guint32         gnome_rr_crtc_get_id               (GnomeRRCrtc           *crtc);
 
-gboolean        gnome_rr_crtc_set_config_with_time (GnomeRRCrtc           *crtc,
-                                                   guint32                timestamp,
-                                                   int                    x,
-                                                   int                    y,
-                                                   GnomeRRMode           *mode,
-                                                   GnomeRRRotation        rotation,
-                                                   GnomeRROutput        **outputs,
-                                                   int                    n_outputs,
-                                                   GError               **error);
 gboolean        gnome_rr_crtc_can_drive_output     (GnomeRRCrtc           *crtc,
                                                    GnomeRROutput         *output);
 GnomeRRMode *   gnome_rr_crtc_get_current_mode     (GnomeRRCrtc           *crtc);
@@ -213,6 +183,7 @@ GnomeRRRotation gnome_rr_crtc_get_rotations        (GnomeRRCrtc           *crtc)
 gboolean        gnome_rr_crtc_supports_rotation    (GnomeRRCrtc           *crtc,
                                                    GnomeRRRotation        rotation);
 
+#if 0 /* gamma support */
 gboolean        gnome_rr_crtc_get_gamma            (GnomeRRCrtc           *crtc,
                                                    int                   *size,
                                                    unsigned short       **red,
@@ -223,4 +194,21 @@ void            gnome_rr_crtc_set_gamma            (GnomeRRCrtc           *crtc,
                                                    unsigned short        *red,
                                                    unsigned short        *green,
                                                    unsigned short        *blue);
+#endif
+
+#if 0 /* configuration writing */
+void            gnome_rr_screen_set_primary_output (GnomeRRScreen         *screen,
+                                                    GnomeRROutput         *output);
+
+gboolean        gnome_rr_crtc_set_config_with_time (GnomeRRCrtc           *crtc,
+                                                   guint32                timestamp,
+                                                   int                    x,
+                                                   int                    y,
+                                                   GnomeRRMode           *mode,
+                                                   GnomeRRRotation        rotation,
+                                                   GnomeRROutput        **outputs,
+                                                   int                    n_outputs,
+                                                   GError               **error);
+#endif
+
 #endif /* GNOME_RR_H */
diff --git a/libgnome-desktop/xrandr.xml b/libgnome-desktop/xrandr.xml
new file mode 100644
index 0000000..f7abefd
--- /dev/null
+++ b/libgnome-desktop/xrandr.xml
@@ -0,0 +1,241 @@
+<!DOCTYPE node PUBLIC
+'-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'
+'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>
+<node>
+  <!--
+      org.gnome.Mutter.DisplayConfig:
+      @short_description: display configuration interface
+
+      This interface is used by mutter and gnome-settings-daemon
+      to apply multiple monitor configuration.
+  -->
+
+  <interface name="org.gnome.Mutter.DisplayConfig">
+
+    <!--
+        GetResources:
+       @serial: configuration serial
+       @crtcs: available CRTCs
+       @outputs: available outputs
+       @modes: available modes
+       @max_screen_width:
+       @max_screen_height:
+
+        Retrieves the current layout of the hardware.
+
+        @serial is an unique identifier representing the current state
+        of the screen. It must be passed back to ApplyConfiguration()
+       and will be increased for every configuration change (so that
+       mutter can detect that the new configuration is based on old
+       state).
+
+       A CRTC (CRT controller) is a logical monitor, ie a portion
+       of the compositor coordinate space. It might correspond
+       to multiple monitors, when in clone mode, but not that
+       it is possible to implement clone mode also by setting different
+       CRTCs to the same coordinates.
+
+       The number of CRTCs represent the maximum number of monitors
+       that can be set to expand and it is a HW constraint; if more
+       monitors are connected, then necessarily some will clone. This
+       is complementary to the concept of the encoder (not exposed in
+       the API), which groups outputs that necessarily will show the
+       same image (again a HW constraint).
+
+       A CRTC is represented by a DBus structure with the following
+       layout:
+       * u ID: the ID in the API of this CRTC
+       * x winsys_id: the low-level ID of this CRTC (which might
+                      be a XID, a KMS handle or something entirely
+                      different)
+       * i x, y, width, height: the geometry of this CRTC
+                                (might be invalid if the CRTC is not in
+                                use)
+       * i current_mode: the current mode of the CRTC, or -1 if this
+                         CRTC is not used
+                         Note: the size of the mode will always correspond
+                         to the width and height of the CRTC
+       * u current_transform: the current transform (espressed according
+                              to the wayland protocol)
+       * au transforms: all possible transforms
+       * a{sv} properties: other high-level properties that affect this
+                           CRTC; they are not necessarily reflected in
+                           the hardware.
+                           No property is specified in this version of the API.
+        FIXME: gamma?
+
+        Note: all geometry information refers to the untransformed
+       display.
+
+       An output represents a physical screen, connected somewhere to
+       the computer. Floating connectors are not exposed in the API.
+       An output is a DBus struct with the following fields:
+       * u ID: the ID in the API
+       * x winsys_id: the low-level ID of this output (XID or KMS handle)
+       * i current_crtc: the CRTC that is currently driving this output,
+                         or -1 if the output is disabled
+       * au possible_crtcs: all CRTCs that can control this output
+       * s name: the name of the connector to which the output is attached
+                 (like VGA1 or HDMI)
+       * s vendor: the human readable name of the manufacturer
+       * s product: the human readable name of the display model
+       * s serial: the serial number of this particular hardward part
+       * i backlight: the backlight value as a percentage (-1 if not supported)
+       * au modes: valid modes for this output
+       * au clones: valid clones for this output, ie other outputs that
+                    can be assigned the same CRTC as this one; if you
+                    want to mirror two outputs that don't have each other
+                    in the clone list, you must configure two different
+                    CRTCs for the same geometry
+       * a{sv} properties: other high-level properties that affect this
+                           output; they are not necessarily reflected in
+                           the hardware.
+                           Known properties:
+                           - "primary" (b): whether this output is primary
+                                            or not
+                           - "presentation" (b): whether this output is
+                                                 for presentation only
+                           Note: properties might be ignored if not consistenly
+                           applied to all outputs in the same clone group. In
+                           general, it's expected that presentation or primary
+                           outputs will not be cloned.
+
+        A mode represents a set of parameters that are applied to
+       each output, such as resolution and refresh rate. It is a separate
+       object so that it can be referenced by CRTCs and outputs.
+       Multiple outputs in the same CRTCs must all have the same mode.
+       A mode is exposed as:
+       * u ID: the ID in the API
+       * x winsys_id: the low-level ID of this mode
+       * u width, height: the resolution
+       * d frequency: refresh rate
+
+        Output and modes are read-only objects (except for output properties),
+       they can change only in accordance to HW changes (such as hotplugging
+       a monitor), while CRTCs can be changed with ApplyConfiguration().
+
+        XXX: actually, if you insist enough, you can add new modes
+       through xrandr command line or the KMS API, overriding what the
+       kernel driver and the EDID say.
+       Usually, it only matters with old cards with broken drivers, or
+       old monitors with broken EDIDs, but it happens more often with
+       projectors (if for example the kernel driver doesn't add the
+       640x480 - 800x600 - 1024x768 default modes). Probably something
+       that we need to handle in mutter anyway.
+    -->
+    <method name="GetResources">
+      <arg name="serial" direction="out" type="u" />
+      <arg name="crtcs" direction="out" type="a(uxiiiiiuaua{sv})" />
+      <arg name="outputs" direction="out" type="a(uxiaussssiauaua{sv})" />
+      <arg name="modes" direction="out" type="a(uxuud)" />
+      <arg name="max_screen_width" direction="out" type="i" />
+      <arg name="max_screen_height" direction="out" type="i" />
+    </method>
+
+    <!--
+        ApplyConfiguration:
+       @serial: configuration serial
+       @persistent: whether this configuration should be saved on disk
+       @crtcs: new data for CRTCs
+       @outputs: new data for outputs
+
+       Applies the requested configuration changes.
+
+       @serial must match the serial from the last GetResources() call,
+       or org.freedesktop.DBus.AccessDenied will be generated.
+       (XXX: a better error maybe?)
+
+       If @persistent is true, mutter will attempt to replicate this
+       configuration the next time this HW layout appears.
+       (XXX: or is this gnome-settings-daemon role?)
+
+       @crtcs represents the new logical configuration, as a list
+       of structures containing:
+       - u ID: the API ID from the corresponding GetResources() call
+       - i new_mode: the API ID of the new mode to configure the CRTC
+                     with, or -1 if the CRTC should be disabled
+        - i x, y: the new coordinates of the top left corner
+                 the geometry will be completed with the size information
+                 from @new_mode
+        - u transform: the desired transform
+       - au outputs: the API ID of outputs that should be assigned to
+                     this CRTC
+        - a{sv} properties: properties whose value should be changed
+
+       Note: CRTCs not referenced in the array will be disabled.
+
+       @outputs represent the output property changes as:
+       - u ID: the API ID of the output to change
+       - a{sv} properties: properties whose value should be changed
+
+       Note: both for CRTCs and outputs, properties not included in
+       the dictionary will not be changed.
+
+       Note: unrecognized properties will have no effect, but if the
+       configuration change succeeds the property will be reported
+       by the next GetResources() call, and if @persistent is true,
+       it will also be saved to disk.
+
+       If the configuration is invalid according to the previous
+       GetResources() call, for example because a CRTC references
+       an output it cannot drive, or not all outputs support the
+       chosen mode, the error org.freedesktop.DBus.InvalidArgs will
+       be generated.
+
+       If the configuration cannot be applied for any other reason
+       (eg. the screen size would exceed texture limits), the error
+       org.freedesktop.DBus.Error.LimitsExceeded will be generated.
+    -->
+    <method name="ApplyConfiguration">
+      <arg name="serial" direction="in" type="u" />
+      <arg name="persistent" direction="in" type="b" />
+      <arg name="crtcs" direction="in" type="a(uiiiuaua{sv})" />
+      <arg name="outputs" direction="in" type="a(ua{sv})" />
+    </method>
+
+    <!--
+        ChangeBacklight:
+       @serial: configuration serial
+       @output: the API id of the output
+       @value: the new backlight value
+
+       Changes the backlight of @output to @value, which is
+       expressed as a percentage and rounded to the HW limits.
+    -->
+    <method name="ChangeBacklight">
+      <arg name="serial" direction="in" type="u" />
+      <arg name="output" direction="in" type="u" />
+      <arg name="value" direction="in" type="i" />
+    </method>
+
+    <!--
+        PowerSaveMode:
+
+       Contains the current power saving mode for the screen, and
+       allows changing it.
+
+        Possible values:
+       - 0: on
+       - 1: standby
+       - 2: suspend
+       - 3: off
+       - -1: unknown (unsupported)
+
+        A client should not attempt to change the powersave mode
+       from -1 (unknown) to any other value, and viceversa.
+       Note that the actual effects of the different values
+       depend on the hardware and the kernel driver in use, and
+       it's perfectly possible that all values different than on
+       have the same effect.
+       Also, setting the PowerSaveMode to 3 (off) may or may
+       not have the same effect as disabling all outputs by
+       setting no CRTC on them with ApplyConfiguration(), and
+       may or may not cause a configuration change.
+
+        Also note that this property might become out of date
+       if changed through different means (for example using the
+       XRandR interface directly).
+    -->
+    <property name="PowerSaveMode" type="i" access="readwrite" />
+  </interface>
+</node>


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