[gnome-color-manager] Drop GcmXserver, GcmScreen and libgnomedesktop3 and make the X11 code faster and cleaner



commit a5ccf8ad9eadfef61d9f600494faea5fa9dc753c
Author: Richard Hughes <richard hughsie com>
Date:   Fri Jul 23 14:56:51 2010 +0100

    Drop GcmXserver, GcmScreen and libgnomedesktop3 and make the X11 code faster and cleaner

 configure.ac                        |    3 +-
 contrib/gnome-color-manager.spec.in |   10 +-
 docs/api/libcolor-glib-docs.sgml    |    3 +-
 libcolor-glib/Makefile.am           |    7 +-
 libcolor-glib/gcm-x11-output.c      |  705 +++++++++++++++++++++++++++++++
 libcolor-glib/gcm-x11-output.h      |  123 ++++++
 libcolor-glib/gcm-x11-screen.c      |  747 ++++++++++++++++++++++++++++++++
 libcolor-glib/gcm-x11-screen.h      |   97 +++++
 libcolor-glib/gcm-xserver.c         |  794 -----------------------------------
 libcolor-glib/gcm-xserver.h         |  111 -----
 libcolor-glib/libcolor-glib.h       |    3 +-
 src/Makefile.am                     |   12 -
 src/gcm-calibrate-argyll.c          |   10 +-
 src/gcm-client.c                    |   96 +++--
 src/gcm-device-xrandr.c             |  242 +++--------
 src/gcm-device-xrandr.h             |    4 +-
 src/gcm-inspect.c                   |   39 +-
 src/gcm-screen.c                    |  220 ----------
 src/gcm-screen.h                    |   86 ----
 tools/Makefile.am                   |    3 +-
 tools/gcm-dump-edid.c               |   59 ++-
 21 files changed, 1870 insertions(+), 1504 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index d34767d..aa540d6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -136,9 +136,8 @@ dnl ---------------------------------------------------------------------------
 dnl - Check library dependencies
 dnl ---------------------------------------------------------------------------
 PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.14.0 gobject-2.0 gthread-2.0 gio-2.0 >= 2.25.9)
-PKG_CHECK_MODULES(XORG, xxf86vm xrandr)
+PKG_CHECK_MODULES(XORG, xrandr)
 PKG_CHECK_MODULES(GTK, gtk+-3.0 >= 2.90.3)
-PKG_CHECK_MODULES(GNOMEDESKTOP, gnome-desktop-3.0 >= 2.90.0)
 PKG_CHECK_MODULES(GUDEV, gudev-1.0)
 PKG_CHECK_MODULES(LCMS, lcms2)
 PKG_CHECK_MODULES(X11, x11)
diff --git a/contrib/gnome-color-manager.spec.in b/contrib/gnome-color-manager.spec.in
index 21dc3d2..efdf3d4 100644
--- a/contrib/gnome-color-manager.spec.in
+++ b/contrib/gnome-color-manager.spec.in
@@ -29,9 +29,7 @@ BuildRequires: vte-devel
 BuildRequires: gnome-doc-utils
 BuildRequires: intltool
 BuildRequires: libgudev1-devel
-BuildRequires: libXxf86vm-devel
 BuildRequires: libXrandr-devel
-BuildRequires: gnome-desktop3-devel
 BuildRequires: lcms2-devel
 BuildRequires: cups-devel
 BuildRequires: sane-backends-devel
@@ -64,6 +62,8 @@ done
 
 rm -f $RPM_BUILD_ROOT%{_libdir}/control-center-1/panels/*.a
 rm -f $RPM_BUILD_ROOT%{_libdir}/control-center-1/panels/*.la
+rm -f $RPM_BUILD_ROOT%{_libdir}/*.a
+rm -f $RPM_BUILD_ROOT%{_libdir}/*.la
 
 %find_lang %name --with-gnome
 
@@ -113,6 +113,12 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &> /dev/null || :
 %{_datadir}/GConf/gsettings/org.gnome.color-manager.gschema.migrate
 %{_datadir}/dbus-1/interfaces/org.gnome.ColorManager.xml
 %{_libdir}/control-center-1/panels/*.so
+%{_includedir}/libcolor-glib/*.h
+%{_libdir}/libcolor-glib.so
+%{_libdir}/libcolor-glib.so.1
+%{_libdir}/libcolor-glib.so.1.0.0
+%{_libdir}/pkgconfig/libcolor-glib.pc
+%{_datadir}/gtk-doc/html/libcolor-glib
 
 %changelog
 * #LONGDATE# Richard Hughes <richard hughsie com> #VERSION#-0.#BUILD##ALPHATAG#
diff --git a/docs/api/libcolor-glib-docs.sgml b/docs/api/libcolor-glib-docs.sgml
index 524e05d..ef6ef59 100644
--- a/docs/api/libcolor-glib-docs.sgml
+++ b/docs/api/libcolor-glib-docs.sgml
@@ -36,7 +36,8 @@
     <xi:include href="xml/gcm-client.xml"/>
 -->
     <xi:include href="xml/gcm-sensor-dummy.xml"/>
-    <xi:include href="xml/gcm-xserver.xml"/>
+    <xi:include href="xml/gcm-x11-output.xml"/>
+    <xi:include href="xml/gcm-x11-screen.xml"/>
     <xi:include href="xml/gcm-edid.xml"/>
     <xi:include href="xml/gcm-ddc-control.xml"/>
     <xi:include href="xml/gcm-profile.xml"/>
diff --git a/libcolor-glib/Makefile.am b/libcolor-glib/Makefile.am
index 597b2cb..e032d13 100644
--- a/libcolor-glib/Makefile.am
+++ b/libcolor-glib/Makefile.am
@@ -46,7 +46,6 @@ libcolor_glib_include_HEADERS =					\
 	gcm-image.h						\
 	gcm-profile-store.h					\
 	gcm-dmi.h						\
-	gcm-xserver.h						\
 	gcm-version.h						\
 	$(NULL)
 
@@ -96,8 +95,10 @@ libcolor_glib_la_SOURCES =					\
 	gcm-usb.h						\
 	gcm-profile-store.c					\
 	gcm-profile-store.h					\
-	gcm-xserver.c						\
-	gcm-xserver.h						\
+	gcm-x11-output.c					\
+	gcm-x11-output.h					\
+	gcm-x11-screen.c					\
+	gcm-x11-screen.h					\
 	gcm-version.h						\
 	gcm-brightness.c					\
 	gcm-brightness.h					\
diff --git a/libcolor-glib/gcm-x11-output.c b/libcolor-glib/gcm-x11-output.c
new file mode 100644
index 0000000..24b20e0
--- /dev/null
+++ b/libcolor-glib/gcm-x11-output.c
@@ -0,0 +1,705 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2007-2008 Soren Sandmann <sandmann redhat com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * SECTION:gcm-x11-output
+ * @short_description: Object to interact with the XServer
+ *
+ * This object talks to the currently running X Server.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+#include <X11/extensions/Xrandr.h>
+#include <X11/Xatom.h>
+#include <string.h>
+#include <gdk/gdk.h>
+
+#include "gcm-x11-output.h"
+
+#include "egg-debug.h"
+
+static void     gcm_x11_output_finalize	(GObject     *object);
+
+#define GCM_X11_OUTPUT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GCM_TYPE_X11_OUTPUT, GcmX11OutputPrivate))
+
+/**
+ * GcmX11OutputPrivate:
+ *
+ * Private #GcmX11Output data
+ **/
+struct _GcmX11OutputPrivate
+{
+	gchar				*display_name;
+	Display				*display;
+	gchar				*name;
+	guint				 id;
+	guint				 crtc_id;
+	gboolean			 primary;
+	guint				 gamma_size;
+	gboolean			 connected;
+	guint				 x;
+	guint				 y;
+	guint				 width;
+	guint				 height;
+};
+
+enum {
+	PROP_0,
+	PROP_DISPLAY_NAME,
+	PROP_LAST
+};
+
+G_DEFINE_TYPE (GcmX11Output, gcm_x11_output, G_TYPE_OBJECT)
+
+/**
+ * gcm_x11_output_set_name:
+ **/
+void
+gcm_x11_output_set_display (GcmX11Output *output, gpointer display)
+{
+	g_return_if_fail (GCM_IS_X11_OUTPUT (output));
+	output->priv->display = display;
+}
+
+/**
+ * gcm_x11_output_set_name:
+ **/
+void
+gcm_x11_output_set_name (GcmX11Output *output, const gchar *name)
+{
+	g_return_if_fail (GCM_IS_X11_OUTPUT (output));
+	output->priv->name = g_strdup (name);
+}
+
+/**
+ * gcm_x11_output_get_name:
+ **/
+const gchar *
+gcm_x11_output_get_name (GcmX11Output *output)
+{
+	g_return_val_if_fail (GCM_IS_X11_OUTPUT (output), NULL);
+	return output->priv->name;
+}
+
+/**
+ * gcm_x11_output_set_id:
+ **/
+void
+gcm_x11_output_set_id (GcmX11Output *output, guint id)
+{
+	g_return_if_fail (GCM_IS_X11_OUTPUT (output));
+	output->priv->id = id;
+}
+
+/**
+ * gcm_x11_output_get_id:
+ **/
+guint
+gcm_x11_output_get_id (GcmX11Output *output)
+{
+	g_return_val_if_fail (GCM_IS_X11_OUTPUT (output), 0);
+	return output->priv->id;
+}
+
+/**
+ * gcm_x11_output_set_crtc_id:
+ **/
+void
+gcm_x11_output_set_crtc_id (GcmX11Output *output, guint crtc_id)
+{
+	g_return_if_fail (GCM_IS_X11_OUTPUT (output));
+	output->priv->crtc_id = crtc_id;
+}
+
+/**
+ * gcm_x11_output_get_crtc_id:
+ **/
+guint
+gcm_x11_output_get_crtc_id (GcmX11Output *output)
+{
+	g_return_val_if_fail (GCM_IS_X11_OUTPUT (output), 0);
+	return output->priv->crtc_id;
+}
+
+/**
+ * gcm_x11_output_set_gamma_size:
+ **/
+void
+gcm_x11_output_set_gamma_size (GcmX11Output *output, guint gamma_size)
+{
+	g_return_if_fail (GCM_IS_X11_OUTPUT (output));
+	output->priv->gamma_size = gamma_size;
+}
+
+/**
+ * gcm_x11_output_get_gamma_size:
+ **/
+guint
+gcm_x11_output_get_gamma_size (GcmX11Output *output)
+{
+	g_return_val_if_fail (GCM_IS_X11_OUTPUT (output), 0);
+	return output->priv->gamma_size;
+}
+
+/**
+ * gcm_x11_output_set_primary:
+ **/
+void
+gcm_x11_output_set_primary (GcmX11Output *output, gboolean primary)
+{
+	g_return_if_fail (GCM_IS_X11_OUTPUT (output));
+	output->priv->primary = primary;
+}
+
+/**
+ * gcm_x11_output_get_primary:
+ **/
+gboolean
+gcm_x11_output_get_primary (GcmX11Output *output)
+{
+	g_return_val_if_fail (GCM_IS_X11_OUTPUT (output), FALSE);
+	return output->priv->primary;
+}
+
+/**
+ * gcm_x11_output_set_connected:
+ **/
+void
+gcm_x11_output_set_connected (GcmX11Output *output, gboolean connected)
+{
+	g_return_if_fail (GCM_IS_X11_OUTPUT (output));
+	output->priv->connected = connected;
+}
+
+/**
+ * gcm_x11_output_get_connected:
+ **/
+gboolean
+gcm_x11_output_get_connected (GcmX11Output *output)
+{
+	g_return_val_if_fail (GCM_IS_X11_OUTPUT (output), FALSE);
+	return output->priv->connected;
+}
+
+/**
+ * gcm_x11_output_set_position:
+ **/
+void
+gcm_x11_output_set_position (GcmX11Output *output, guint x, guint y)
+{
+	g_return_if_fail (GCM_IS_X11_OUTPUT (output));
+	output->priv->x = x;
+	output->priv->y = y;
+}
+
+/**
+ * gcm_x11_output_get_position:
+ **/
+void
+gcm_x11_output_get_position (GcmX11Output *output, guint *x, guint *y)
+{
+	g_return_if_fail (GCM_IS_X11_OUTPUT (output));
+	if (x != NULL)
+		*x = output->priv->x;
+	if (y != NULL)
+		*y = output->priv->y;
+}
+
+/**
+ * gcm_x11_output_set_size:
+ **/
+void
+gcm_x11_output_set_size (GcmX11Output *output, guint width, guint height)
+{
+	g_return_if_fail (GCM_IS_X11_OUTPUT (output));
+	output->priv->width = width;
+	output->priv->height = height;
+}
+
+/**
+ * gcm_x11_output_get_size:
+ **/
+void
+gcm_x11_output_get_size (GcmX11Output *output, guint *width, guint *height)
+{
+	g_return_if_fail (GCM_IS_X11_OUTPUT (output));
+	if (width != NULL)
+		*width = output->priv->width;
+	if (height != NULL)
+		*height = output->priv->height;
+}
+
+/**
+ * gcm_x11_output_get_property_atom:
+ **/
+static guint8 *
+gcm_x11_output_get_property_atom (GcmX11Output *output, Atom atom, gint *len)
+{
+	guchar *prop;
+	gint actual_format;
+	unsigned long nitems, bytes_after;
+	Atom actual_type;
+	guint8 *result = NULL;
+
+	/* get a property on the output */
+	gdk_error_trap_push ();
+	XRRGetOutputProperty (output->priv->display, output->priv->id, atom,
+			      0, 100, False, False,
+			      AnyPropertyType,
+			      &actual_type, &actual_format,
+			      &nitems, &bytes_after, &prop);
+	gdk_flush ();
+	if (gdk_error_trap_pop ())
+		goto out;
+	if (actual_type == XA_INTEGER && actual_format == 8) {
+		result = g_memdup (prop, nitems);
+		if (len)
+			*len = nitems;
+	}
+	XFree (prop);
+out:
+	return result;
+}
+
+/**
+ * gcm_x11_output_get_edid_data:
+ **/
+gboolean
+gcm_x11_output_get_edid_data (GcmX11Output *output, guint8 **data, gsize *length, GError **error)
+{
+	Atom edid_atom;
+	guint8 *result;
+	gint len;
+	gboolean ret = FALSE;
+
+	g_return_val_if_fail (GCM_IS_X11_OUTPUT (output), FALSE);
+	g_return_val_if_fail (output->priv->display != NULL, FALSE);
+
+	/* get the new name */
+	edid_atom = XInternAtom (output->priv->display, "EDID", FALSE);
+	result = gcm_x11_output_get_property_atom (output, edid_atom, &len);
+
+	/* try harder */
+	if (result == NULL) {
+		edid_atom = XInternAtom (output->priv->display, "EDID_DATA", FALSE);
+		result = gcm_x11_output_get_property_atom (output, edid_atom, &len);
+	}
+
+	/* failed */
+	if (result == NULL) {
+		g_set_error_literal (error, 1, 0, "no edid data");
+		goto out;
+	}
+
+	/* success */
+	if (data != NULL)
+		*data = result;
+	ret = TRUE;
+out:
+	return ret;
+}
+
+/**
+ * gcm_x11_output_set_gamma:
+ * @output: a valid %GcmX11Output instance
+ * @error: a %GError, or %NULL
+ *
+ * Sets the gamma ramps for the given output.
+ *
+ * Return value: %TRUE for success.
+ **/
+gboolean
+gcm_x11_output_set_gamma (GcmX11Output *output, guint size, guint16 *red, guint16 *green, guint16 *blue, GError **error)
+{
+	guint copy_size;
+	XRRCrtcGamma *gamma;
+
+	g_return_val_if_fail (GCM_IS_X11_OUTPUT (output), FALSE);
+	g_return_val_if_fail (output->priv->display != NULL, FALSE);
+	g_return_val_if_fail (red != NULL, FALSE);
+	g_return_val_if_fail (green != NULL, FALSE);
+	g_return_val_if_fail (blue != NULL, FALSE);
+
+	return TRUE;
+
+	if (size != output->priv->gamma_size)
+		return FALSE;
+
+	gamma = XRRAllocGamma (output->priv->gamma_size);
+	copy_size = output->priv->gamma_size * sizeof (guint16);
+	memcpy (gamma->red, red, copy_size);
+	memcpy (gamma->green, green, copy_size);
+	memcpy (gamma->blue, blue, copy_size);
+
+	gdk_error_trap_push ();
+	XRRSetCrtcGamma (output->priv->display, output->priv->crtc_id, gamma);
+	XRRFreeGamma (gamma);
+	gdk_flush ();
+	if (gdk_error_trap_pop ()) {
+		g_set_error_literal (error,
+				     GCM_X11_OUTPUT_ERROR, GCM_X11_OUTPUT_ERROR_INTERNAL,
+				     "Failed to set gamma");
+		return FALSE;
+	}
+	return TRUE;
+}
+
+/**
+ * gcm_x11_output_get_gamma:
+ **/
+gboolean
+gcm_x11_output_get_gamma (GcmX11Output *output, guint *size, guint16 **red, guint16 **green, guint16 **blue, GError **error)
+{
+	guint copy_size;
+	guint16 *r, *g, *b;
+	XRRCrtcGamma *gamma;
+
+	g_return_val_if_fail (GCM_IS_X11_OUTPUT (output), FALSE);
+	g_return_val_if_fail (output->priv->display != NULL, FALSE);
+
+	gdk_error_trap_push ();
+	gamma = XRRGetCrtcGamma (output->priv->display, output->priv->crtc_id);
+	gdk_flush ();
+	if (gdk_error_trap_pop () || gamma == NULL) {
+		g_set_error_literal (error,
+				     GCM_X11_OUTPUT_ERROR, GCM_X11_OUTPUT_ERROR_INTERNAL,
+				     "Failed to get gamma");
+		return FALSE;
+	}
+
+	copy_size = output->priv->gamma_size * sizeof (guint16);
+	if (red != NULL) {
+		r = g_new0 (guint16, output->priv->gamma_size);
+		memcpy (r, gamma->red, copy_size);
+		*red = r;
+	}
+	if (green != NULL) {
+		g = g_new0 (guint16, output->priv->gamma_size);
+		memcpy (g, gamma->green, copy_size);
+		*green = g;
+	}
+	if (blue != NULL) {
+		b = g_new0 (guint16, output->priv->gamma_size);
+		memcpy (b, gamma->blue, copy_size);
+		*blue = b;
+	}
+	if (size)
+		*size = output->priv->gamma_size;
+	XRRFreeGamma (gamma);
+	return TRUE;
+}
+
+
+/**
+ * gcm_x11_output_get_profile_data:
+ *
+ * @x11: a valid %GcmX11Output instance
+ * @data: the data that is returned from the XServer. Free with g_free()
+ * @length: the size of the returned data, or %NULL if you don't care
+ * @error: a %GError that is set in the result of an error, or %NULL
+ *
+ * Gets the ICC profile data from the specified output.
+ *
+ * Return value: %TRUE for success.
+ *
+ * Since: 0.0.1
+ **/
+gboolean
+gcm_x11_output_get_profile_data (GcmX11Output *output, guint8 **data, gsize *length, GError **error)
+{
+	gboolean ret = FALSE;
+	gchar *data_tmp = NULL;
+	gint format;
+	gint rc = -1;
+	gulong bytes_after;
+	gulong nitems = 0;
+	Atom atom;
+	Atom type;
+	GcmX11OutputPrivate *priv = output->priv;
+
+	g_return_val_if_fail (GCM_IS_X11_OUTPUT (output), FALSE);
+	g_return_val_if_fail (data != NULL, FALSE);
+
+	/* get the value */
+	gdk_error_trap_push ();
+	atom = XInternAtom (priv->display, "_ICC_PROFILE", FALSE);
+	rc = XRRGetOutputProperty (priv->display, priv->id,
+				   atom, 0, ~0, False, False,
+				   AnyPropertyType, &type, &format, &nitems, &bytes_after,
+				   (unsigned char **) &data_tmp);
+	egg_debug ("got %i bytes", (guint) nitems);
+	gdk_error_trap_pop ();
+
+	/* did the call fail */
+	if (rc != Success) {
+		g_set_error (error, 1, 0, "failed to get icc profile atom with rc %i", rc);
+		goto out;
+	}
+
+	/* was nothing found */
+	if (nitems == 0) {
+		g_set_error (error, 1, 0, "icc profile atom has not been set");
+		goto out;
+	}
+
+	/* allocate the data using Glib, rather than asking the user to use XFree */
+	*data = g_new0 (guint8, nitems);
+	memcpy (*data, data_tmp, nitems);
+
+	/* copy the length */
+	if (length != NULL)
+		*length = nitems;
+
+	/* success */
+	ret = TRUE;
+out:
+	if (data_tmp != NULL)
+		XFree (data_tmp);
+	return ret;
+}
+
+/**
+ * gcm_x11_output_set_profile:
+ * @x11: a valid %GcmX11Output instance
+ * @filename: the filename of the ICC profile
+ * @error: a %GError that is set in the result of an error, or %NULL
+ *
+ * Sets the ICC profile data to the specified output.
+ *
+ * Return value: %TRUE for success.
+ *
+ * Since: 0.0.1
+ **/
+gboolean
+gcm_x11_output_set_profile (GcmX11Output *output, const gchar *filename, GError **error)
+{
+	gboolean ret;
+	gchar *data = NULL;
+	gsize length;
+
+	g_return_val_if_fail (GCM_IS_X11_OUTPUT (output), FALSE);
+	g_return_val_if_fail (filename != NULL, FALSE);
+
+	egg_debug ("setting output ICC profile atom from %s", filename);
+
+	/* get contents of file */
+	ret = g_file_get_contents (filename, &data, &length, error);
+	if (!ret)
+		goto out;
+
+	/* send to the XServer */
+	ret = gcm_x11_output_set_profile_data (output, (const guint8 *) data, length, error);
+	if (!ret)
+		goto out;
+out:
+	g_free (data);
+	return ret;
+}
+
+/**
+ * gcm_x11_output_set_profile_data:
+ * @x11: a valid %GcmX11Output instance
+ * @data: the data that is to be set to the XServer
+ * @length: the size of the data
+ * @error: a %GError that is set in the result of an error, or %NULL
+ *
+ * Sets the ICC profile data to the specified output.
+ *
+ * Return value: %TRUE for success.
+ *
+ * Since: 0.0.1
+ **/
+gboolean
+gcm_x11_output_set_profile_data (GcmX11Output *output, const guint8 *data, gsize length, GError **error)
+{
+	gboolean ret = FALSE;
+	gint rc;
+	Atom atom = None;
+	GcmX11OutputPrivate *priv = output->priv;
+
+	g_return_val_if_fail (GCM_IS_X11_OUTPUT (output), FALSE);
+	g_return_val_if_fail (data != NULL, FALSE);
+	g_return_val_if_fail (length != 0, FALSE);
+
+	/* get the value */
+	gdk_error_trap_push ();
+	atom = XInternAtom (priv->display, "_ICC_PROFILE", FALSE);
+	XRRChangeOutputProperty (priv->display, priv->id,
+				 atom, XA_CARDINAL, 8,
+				 PropModeReplace,
+				 (unsigned char*) data, (gint)length);
+	rc = gdk_error_trap_pop ();
+
+	/* did the call fail */
+	if (rc != Success) {
+		g_set_error (error, 1, 0, "failed to set output icc profile atom with rc %i", rc);
+		goto out;
+	}
+
+	/* success */
+	ret = TRUE;
+out:
+	return ret;
+}
+
+/**
+ * gcm_x11_output_remove_profile:
+ * @x11: a valid %GcmX11Output instance
+ * @error: a %GError that is set in the result of an error, or %NULL
+ *
+ * Sets the ICC profile data to the specified output.
+ *
+ * Return value: %TRUE for success.
+ *
+ * Since: 0.0.1
+ **/
+gboolean
+gcm_x11_output_remove_profile (GcmX11Output *output, GError **error)
+{
+	gboolean ret = FALSE;
+	gint rc;
+	Atom atom;
+	GcmX11OutputPrivate *priv = output->priv;
+
+	g_return_val_if_fail (GCM_IS_X11_OUTPUT (output), FALSE);
+
+	/* get the value */
+	gdk_error_trap_push ();
+	atom = XInternAtom (priv->display, "_ICC_PROFILE", FALSE);
+	XRRDeleteOutputProperty (priv->display, priv->id, atom);
+	rc = gdk_error_trap_pop ();
+
+	/* did the call fail */
+	if (rc != Success) {
+		g_set_error (error, 1, 0, "failed to remove output icc profile atom with rc %i", rc);
+		goto out;
+	}
+
+	/* success */
+	ret = TRUE;
+out:
+	return ret;
+}
+
+/**
+ * gcm_x11_output_get_property:
+ **/
+static void
+gcm_x11_output_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+	GcmX11Output *output = GCM_X11_OUTPUT (object);
+	GcmX11OutputPrivate *priv = output->priv;
+
+	switch (prop_id) {
+	case PROP_DISPLAY_NAME:
+		g_value_set_string (value, priv->display_name);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+/**
+ * gcm_x11_output_set_property:
+ **/
+static void
+gcm_x11_output_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+	GcmX11Output *output = GCM_X11_OUTPUT (object);
+	GcmX11OutputPrivate *priv = output->priv;
+
+	switch (prop_id) {
+	case PROP_DISPLAY_NAME:
+		g_free (priv->display_name);
+		priv->display_name = g_strdup (g_value_get_string (value));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+/**
+ * gcm_x11_output_class_init:
+ **/
+static void
+gcm_x11_output_class_init (GcmX11OutputClass *klass)
+{
+	GParamSpec *pspec;
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	object_class->finalize = gcm_x11_output_finalize;
+	object_class->get_property = gcm_x11_output_get_property;
+	object_class->set_property = gcm_x11_output_set_property;
+
+	/**
+	 * GcmX11Output:display-name:
+	 */
+	pspec = g_param_spec_string ("display-name", NULL, NULL,
+				     NULL,
+				     G_PARAM_READWRITE);
+	g_object_class_install_property (object_class, PROP_DISPLAY_NAME, pspec);
+
+	g_type_class_add_private (klass, sizeof (GcmX11OutputPrivate));
+}
+
+/**
+ * gcm_x11_output_init:
+ **/
+static void
+gcm_x11_output_init (GcmX11Output *output)
+{
+	output->priv = GCM_X11_OUTPUT_GET_PRIVATE (output);
+	output->priv->display_name = NULL;
+}
+
+/**
+ * gcm_x11_output_finalize:
+ **/
+static void
+gcm_x11_output_finalize (GObject *object)
+{
+	GcmX11Output *output = GCM_X11_OUTPUT (object);
+	GcmX11OutputPrivate *priv = output->priv;
+
+	g_free (priv->display_name);
+
+	G_OBJECT_CLASS (gcm_x11_output_parent_class)->finalize (object);
+}
+
+/**
+ * gcm_x11_output_new:
+ *
+ * Return value: a new GcmX11Output object.
+ *
+ * Since: 0.0.1
+ **/
+GcmX11Output *
+gcm_x11_output_new (void)
+{
+	GcmX11Output *output;
+	output = g_object_new (GCM_TYPE_X11_OUTPUT, NULL);
+	return GCM_X11_OUTPUT (output);
+}
+
diff --git a/libcolor-glib/gcm-x11-output.h b/libcolor-glib/gcm-x11-output.h
new file mode 100644
index 0000000..dac019a
--- /dev/null
+++ b/libcolor-glib/gcm-x11-output.h
@@ -0,0 +1,123 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined (__LIBCOLOR_GLIB_H_INSIDE__) && !defined (LIBCOLOR_GLIB_COMPILATION)
+#error "Only <libcolor-glib.h> can be included directly."
+#endif
+
+#ifndef __GCM_X11_OUTPUT_H
+#define __GCM_X11_OUTPUT_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GCM_TYPE_X11_OUTPUT		(gcm_x11_output_get_type ())
+#define GCM_X11_OUTPUT(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), GCM_TYPE_X11_OUTPUT, GcmX11Output))
+#define GCM_IS_X11_OUTPUT(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), GCM_TYPE_X11_OUTPUT))
+
+#define GCM_X11_OUTPUT_ERROR		1
+#define GCM_X11_OUTPUT_ERROR_INTERNAL	0
+
+typedef struct _GcmX11OutputPrivate	GcmX11OutputPrivate;
+typedef struct _GcmX11Output		GcmX11Output;
+typedef struct _GcmX11OutputClass	GcmX11OutputClass;
+
+struct _GcmX11Output
+{
+	 GObject		 parent;
+	 GcmX11OutputPrivate	*priv;
+};
+
+struct _GcmX11OutputClass
+{
+	GObjectClass		 parent_class;
+};
+
+GType		 gcm_x11_output_get_type		(void);
+GcmX11Output	*gcm_x11_output_new			(void);
+
+void		 gcm_x11_output_set_display		(GcmX11Output		*output,
+							 gpointer		 display);
+void		 gcm_x11_output_set_name		(GcmX11Output		*output,
+							 const gchar		*name);
+const gchar	*gcm_x11_output_get_name		(GcmX11Output		*output);
+void		 gcm_x11_output_set_id			(GcmX11Output		*output,
+							 guint			 id);
+guint		 gcm_x11_output_get_id			(GcmX11Output		*output);
+void		 gcm_x11_output_set_crtc_id		(GcmX11Output		*output,
+							 guint			 crtc_id);
+guint		 gcm_x11_output_get_crtc_id		(GcmX11Output		*output);
+void		 gcm_x11_output_set_gamma_size		(GcmX11Output		*output,
+							 guint			 gamma_size);
+guint		 gcm_x11_output_get_gamma_size		(GcmX11Output		*output);
+void		 gcm_x11_output_set_position		(GcmX11Output		*output,
+							 guint			 x,
+							 guint			 y);
+void		 gcm_x11_output_get_position		(GcmX11Output		*output,
+							 guint			*x,
+							 guint			*y);
+void		 gcm_x11_output_set_size		(GcmX11Output		*output,
+							 guint			 width,
+							 guint			 height);
+void		 gcm_x11_output_get_size		(GcmX11Output		*output,
+							 guint			*width,
+							 guint			*height);
+void		 gcm_x11_output_set_primary		(GcmX11Output		*output,
+							 gboolean		 primary);
+gboolean	 gcm_x11_output_get_primary		(GcmX11Output		*output);
+void		 gcm_x11_output_set_connected		(GcmX11Output		*output,
+							 gboolean		 connected);
+gboolean	 gcm_x11_output_get_connected		(GcmX11Output		*output);
+gboolean	 gcm_x11_output_get_gamma		(GcmX11Output		*output,
+							 guint			*size,
+							 guint16		**red,
+							 guint16		**green,
+							 guint16		**blue,
+							 GError			**error);
+gboolean	 gcm_x11_output_set_gamma		(GcmX11Output		*output,
+							 guint			 size,
+							 guint16		*red,
+							 guint16		*green,
+							 guint16		*blue,
+							 GError			**error);
+gboolean	 gcm_x11_output_get_edid_data		(GcmX11Output		*output,
+							 guint8			**data,
+							 gsize			*length,
+							 GError			**error);
+gboolean	 gcm_x11_output_get_profile_data	(GcmX11Output		*output,
+							 guint8			**data,
+							 gsize			*length,
+							 GError			**error);
+gboolean	 gcm_x11_output_set_profile_data	(GcmX11Output		*output,
+							 const guint8		*data,
+							 gsize			 length,
+							 GError			**error);
+gboolean	 gcm_x11_output_set_profile		(GcmX11Output		*output,
+							 const gchar		*filename,
+							 GError			**error);
+gboolean	 gcm_x11_output_remove_profile		(GcmX11Output		*output,
+							 GError			**error);
+
+G_END_DECLS
+
+#endif /* __GCM_X11_OUTPUT_H */
+
diff --git a/libcolor-glib/gcm-x11-screen.c b/libcolor-glib/gcm-x11-screen.c
new file mode 100644
index 0000000..811a85f
--- /dev/null
+++ b/libcolor-glib/gcm-x11-screen.c
@@ -0,0 +1,747 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2007-2008 Soren Sandmann <sandmann redhat com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * SECTION:gcm-x11-screen
+ * @short_description: Object to interact with the XServer
+ *
+ * This object talks to the currently running X Server.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+#include <gdk/gdkx.h>
+#include <X11/extensions/Xrandr.h>
+#include <X11/Xatom.h>
+
+#include "gcm-x11-screen.h"
+
+#include "egg-debug.h"
+
+static void     gcm_x11_screen_finalize	(GObject     *object);
+
+#define GCM_X11_SCREEN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GCM_TYPE_X11_SCREEN, GcmX11ScreenPrivate))
+
+/**
+ * GcmX11ScreenPrivate:
+ *
+ * Private #GcmX11Screen data
+ **/
+struct _GcmX11ScreenPrivate
+{
+	GdkScreen			*gdk_screen;
+	GdkWindow			*gdk_root;
+	Display				*xdisplay;
+	Screen				*xscreen;
+	Window				 xroot;
+	guint				 randr_event_base;
+	guint				 rr_major_version;
+	guint				 rr_minor_version;
+	GPtrArray			*outputs;
+};
+
+enum {
+	SIGNAL_CHANGED,
+	SIGNAL_LAST
+};
+
+static guint signals[SIGNAL_LAST] = { 0 };
+static gpointer gcm_x11_screen_object = NULL;
+G_DEFINE_TYPE (GcmX11Screen, gcm_x11_screen, G_TYPE_OBJECT)
+
+/**
+ * gcm_x11_screen_on_event_cb:
+ **/
+static GdkFilterReturn
+gcm_x11_screen_on_event_cb (GdkXEvent *xevent, GdkEvent *event, gpointer data)
+{
+	GcmX11Screen *screen = data;
+	GcmX11ScreenPrivate *priv = screen->priv;
+	XEvent *e = xevent;
+	gint event_num;
+
+	if (e == NULL)
+		return GDK_FILTER_CONTINUE;
+
+	event_num = e->type - priv->randr_event_base;
+
+	if (event_num == RRScreenChangeNotify) {
+		egg_debug ("emit changed");
+		g_signal_emit (screen, signals[SIGNAL_CHANGED], 0);
+	}
+
+	/* Pass the event on to GTK+ */
+	return GDK_FILTER_CONTINUE;
+}
+
+/**
+ * gcm_x11_screen_refresh:
+ **/
+static gboolean
+gcm_x11_screen_refresh (GcmX11Screen *screen, GError **error)
+{
+	gint i;
+	gboolean connected;
+	gboolean ret = FALSE;
+	GcmX11ScreenPrivate *priv = screen->priv;
+	XRRScreenResources *resources;
+	RROutput rr_output;
+	GcmX11Output *output;
+	XRROutputInfo *output_info;
+	XRRCrtcInfo *crtc_info;
+	gint gamma_size;
+
+	/* clear old outputs */
+	g_ptr_array_set_size (priv->outputs, 0);
+
+	/* get new resources */
+	gdk_error_trap_push ();
+	resources = XRRGetScreenResources (priv->xdisplay, priv->xroot);
+	gdk_flush ();
+	if (gdk_error_trap_pop () || resources == NULL) {
+		g_set_error_literal (error,
+				     GCM_X11_SCREEN_ERROR, GCM_X11_SCREEN_ERROR_INTERNAL,
+				     "Failed to get X11 resources");
+		goto out;
+	}
+
+	/* add each output */
+	for (i=0; i < resources->noutput; i++) {
+		rr_output = resources->outputs[i];
+
+		/* get information about the output */
+		gdk_error_trap_push ();
+		output_info = XRRGetOutputInfo (priv->xdisplay, resources, rr_output);
+		gdk_flush ();
+		if (gdk_error_trap_pop ()) {
+			egg_warning ("failed to get output info");
+			continue;
+		}
+
+		connected = (output_info->connection == RR_Connected);
+		if (connected && output_info->crtc != 0) {
+
+			/* get crtc info */
+			gdk_error_trap_push ();
+			crtc_info = XRRGetCrtcInfo (priv->xdisplay, resources, output_info->crtc);
+			gdk_flush ();
+			if (gdk_error_trap_pop () || crtc_info == NULL) {
+				egg_warning ("failed to get crtc info for %s", output_info->name);
+				continue;
+			}
+
+			/* get gamma size */
+			gdk_error_trap_push ();
+			gamma_size = XRRGetCrtcGammaSize (priv->xdisplay, output_info->crtc);
+			gdk_flush ();
+			if (gdk_error_trap_pop ()) {
+				egg_warning ("failed to get gamma size");
+				continue;
+			}
+
+			/* create new object and set properties */
+			output = gcm_x11_output_new ();
+			gcm_x11_output_set_name (output, output_info->name);
+			gcm_x11_output_set_display (output, priv->xdisplay);
+			gcm_x11_output_set_id (output, rr_output);
+			gcm_x11_output_set_crtc_id (output, output_info->crtc);
+			gcm_x11_output_set_primary (output, (crtc_info->x == 0 && crtc_info->y == 0));
+			gcm_x11_output_set_gamma_size (output, gamma_size);
+			gcm_x11_output_set_connected (output, connected);
+			gcm_x11_output_set_position (output, crtc_info->x, crtc_info->y);
+			gcm_x11_output_set_size (output, crtc_info->width, crtc_info->height);
+
+			/* add it to the array */
+			g_ptr_array_add (priv->outputs, output);
+
+			/* free client side X resources */
+			XRRFreeCrtcInfo (crtc_info);
+		}
+		XRRFreeOutputInfo (output_info);
+	}
+
+	/* success */
+	ret = TRUE;
+out:
+	return ret;
+}
+
+/**
+ * gcm_x11_screen_assign:
+ * @screen: a valid %GcmX11Screen instance
+ * @gdk_screen: a #GdkScreen
+ * @error: a %GError or %NULL
+ *
+ * Assigns a #GdkScreen to this instance.
+ *
+ * Return value: %TRUE for success.
+ *
+ * Since: 0.0.1
+ **/
+gboolean
+gcm_x11_screen_assign (GcmX11Screen *screen, GdkScreen *gdk_screen, GError **error)
+{
+	GcmX11ScreenPrivate *priv = screen->priv;
+	Display *dpy;
+	gint event_base;
+	gint ignore;
+	gboolean ret = FALSE;
+
+	g_return_val_if_fail (GCM_IS_X11_SCREEN (screen), FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+	/* NULL means default */
+	if (gdk_screen != NULL) {
+		priv->gdk_screen = gdk_screen;
+	} else {
+		priv->gdk_screen = gdk_screen_get_default ();
+	}
+
+	/* do we even have XRandR? */
+	dpy = GDK_SCREEN_XDISPLAY (priv->gdk_screen);
+	if (!XRRQueryExtension (dpy, &event_base, &ignore)) {
+		g_set_error_literal (error, GCM_X11_SCREEN_ERROR, GCM_X11_SCREEN_ERROR_INTERNAL,
+				     "RANDR extension is not present");
+		goto out;
+	}
+
+	priv->gdk_root = gdk_screen_get_root_window (priv->gdk_screen);
+	priv->xroot = gdk_x11_drawable_get_xid (priv->gdk_root);
+	priv->xdisplay = dpy;
+	priv->xscreen = gdk_x11_screen_get_xscreen (priv->gdk_screen);
+	priv->randr_event_base = event_base;
+
+	/* get version */
+	gdk_error_trap_push ();
+	XRRQueryVersion (dpy, (gint*)&priv->rr_major_version, (gint*)&priv->rr_minor_version);
+	gdk_flush ();
+	if (gdk_error_trap_pop ()) {
+		g_set_error_literal (error, GCM_X11_SCREEN_ERROR, GCM_X11_SCREEN_ERROR_INTERNAL,
+				     "failed to get RANDR extension version");
+		goto out;
+	}
+
+	/* too small */
+	if (priv->rr_major_version > 1 ||
+	    (priv->rr_major_version == 1 && priv->rr_minor_version < 2)) {
+		g_set_error_literal (error, GCM_X11_SCREEN_ERROR, GCM_X11_SCREEN_ERROR_INTERNAL,
+				     "RANDR extension is too old (must be at least 1.2)");
+		goto out;
+	}
+
+	/* add filter */
+	gdk_error_trap_push ();
+	XRRSelectInput (priv->xdisplay,
+			priv->xroot,
+			RRScreenChangeNotifyMask);
+	if (gdk_error_trap_pop ()) {
+		egg_warning ("failed to select input");
+		goto out;
+	}
+
+	gdk_x11_register_standard_event_type (gdk_screen_get_display (priv->gdk_screen),
+					      event_base, RRNotify + 1);
+
+	gdk_window_add_filter (priv->gdk_root, gcm_x11_screen_on_event_cb, screen);
+
+	/* get resources */
+	ret = gcm_x11_screen_refresh (screen, error);
+out:
+	return ret;
+}
+
+/**
+ * gcm_x11_screen_get_outputs:
+ * @screen: a valid %GcmX11Screen instance
+ * @error: a %GError or %NULL
+ *
+ * Gets the list of outputs.
+ *
+ * Return value: A #GPtrArray of #GcmX11Output's. Free with g_ptr_array_unref() when done.
+ *
+ * Since: 0.0.1
+ **/
+GPtrArray *
+gcm_x11_screen_get_outputs (GcmX11Screen *screen, GError **error)
+{
+	GcmX11ScreenPrivate *priv = screen->priv;
+
+	/* not set the display */
+	if (priv->gdk_screen == NULL) {
+		g_set_error_literal (error,
+				     GCM_X11_SCREEN_ERROR, GCM_X11_SCREEN_ERROR_INTERNAL,
+				     "no display set, use gcm_x11_screen_assign()");
+		return NULL;
+	}
+
+	return g_ptr_array_ref (priv->outputs);
+}
+
+/**
+ * gcm_x11_screen_get_output_by_name:
+ * @screen: a valid %GcmX11Screen instance
+ * @name: an output name, e.g. "lvds1"
+ * @error: a %GError or %NULL
+ *
+ * Gets a specified output.
+ *
+ * Return value: A #GcmX11Output, or %NULL if nothing matched.
+ *
+ * Since: 0.0.1
+ **/
+GcmX11Output *
+gcm_x11_screen_get_output_by_name (GcmX11Screen *screen, const gchar *name, GError **error)
+{
+	guint i;
+	GcmX11Output *output;
+	GcmX11ScreenPrivate *priv = screen->priv;
+
+	/* not set the display */
+	if (priv->gdk_screen == NULL) {
+		g_set_error_literal (error,
+				     GCM_X11_SCREEN_ERROR, GCM_X11_SCREEN_ERROR_INTERNAL,
+				     "no display set, use gcm_x11_screen_assign()");
+		return NULL;
+	}
+
+	/* find the output */
+	for (i=0; i<priv->outputs->len; i++) {
+		output = g_ptr_array_index (priv->outputs, i);
+		if (g_strcmp0 (gcm_x11_output_get_name (output), name) == 0)
+			return g_object_ref (output);
+	}
+	g_set_error_literal (error,
+			     GCM_X11_SCREEN_ERROR, GCM_X11_SCREEN_ERROR_INTERNAL,
+			     "no output with that name");
+	return NULL;
+}
+
+/**
+ * gcm_x11_screen_get_profile_data:
+ * @x11: a valid %GcmX11Screen instance
+ * @data: the data that is returned from the XServer. Free with g_free()
+ * @length: the size of the returned data, or %NULL if you don't care
+ * @error: a %GError that is set in the result of an error, or %NULL
+ *
+ * Gets the ICC profile data from the XServer.
+ *
+ * Return value: %TRUE for success.
+ **/
+gboolean
+gcm_x11_screen_get_profile_data (GcmX11Screen *screen, guint8 **data, gsize *length, GError **error)
+{
+	gboolean ret = FALSE;
+	gchar *data_tmp = NULL;
+	gint format;
+	gint rc;
+	gulong bytes_after;
+	gulong nitems;
+	Atom atom = None;
+	Atom type;
+	GcmX11ScreenPrivate *priv = screen->priv;
+
+	g_return_val_if_fail (GCM_IS_X11_SCREEN (screen), FALSE);
+	g_return_val_if_fail (data != NULL, FALSE);
+
+	/* get the value */
+	gdk_error_trap_push ();
+	atom = XInternAtom (priv->xdisplay, "_ICC_PROFILE", FALSE);
+	rc = XGetWindowProperty (priv->xdisplay, priv->xroot, atom, 0, G_MAXLONG, False, XA_CARDINAL,
+				 &type, &format, &nitems, &bytes_after, (void*) &data_tmp);
+	gdk_error_trap_pop ();
+
+	/* did the call fail */
+	if (rc != Success) {
+		g_set_error (error, 1, 0, "failed to get icc profile atom with rc %i", rc);
+		goto out;
+	}
+
+	/* was nothing found */
+	if (nitems == 0) {
+		g_set_error (error, 1, 0, "atom has not been set");
+		goto out;
+	}
+
+	/* allocate the data using Glib, rather than asking the user to use XFree */
+	*data = g_memdup (data_tmp, nitems);
+
+	/* copy the length */
+	if (length != NULL)
+		*length = nitems;
+
+	/* success */
+	ret = TRUE;
+out:
+	if (data_tmp != NULL)
+		XFree (data_tmp);
+	return ret;
+}
+
+/**
+ * gcm_x11_screen_set_profile:
+ * @x11: a valid %GcmX11Screen instance
+ * @filename: the filename of the ICC profile
+ * @error: a %GError that is set in the result of an error, or %NULL
+ *
+ * Sets the ICC profile data to the XServer.
+ *
+ * Return value: %TRUE for success.
+ *
+ * Since: 0.0.1
+ **/
+gboolean
+gcm_x11_screen_set_profile (GcmX11Screen *screen, const gchar *filename, GError **error)
+{
+	gboolean ret;
+	gchar *data = NULL;
+	gsize length;
+
+	g_return_val_if_fail (GCM_IS_X11_SCREEN (screen), FALSE);
+	g_return_val_if_fail (filename != NULL, FALSE);
+
+	egg_debug ("setting root window ICC profile atom from %s", filename);
+
+	/* get contents of file */
+	ret = g_file_get_contents (filename, &data, &length, error);
+	if (!ret)
+		goto out;
+
+	/* send to the XServer */
+	ret = gcm_x11_screen_set_profile_data (screen, (const guint8 *) data, length, error);
+	if (!ret)
+		goto out;
+out:
+	g_free (data);
+	return ret;
+}
+
+/**
+ * gcm_x11_screen_set_profile_data:
+ * @x11: a valid %GcmX11Screen instance
+ * @data: the data that is to be set to the XServer
+ * @length: the size of the data
+ * @error: a %GError that is set in the result of an error, or %NULL
+ *
+ * Sets the ICC profile data to the XServer.
+ *
+ * Return value: %TRUE for success.
+ *
+ * Since: 0.0.1
+ **/
+gboolean
+gcm_x11_screen_set_profile_data (GcmX11Screen *screen, const guint8 *data, gsize length, GError **error)
+{
+	gboolean ret = FALSE;
+	gint rc;
+	Atom atom = None;
+	GcmX11ScreenPrivate *priv = screen->priv;
+
+	g_return_val_if_fail (GCM_IS_X11_SCREEN (screen), FALSE);
+	g_return_val_if_fail (data != NULL, FALSE);
+	g_return_val_if_fail (length != 0, FALSE);
+
+	/* get the value */
+	gdk_error_trap_push ();
+	atom = XInternAtom (priv->xdisplay, "_ICC_PROFILE", FALSE);
+	rc = XChangeProperty (priv->xdisplay, priv->xroot, atom, XA_CARDINAL, 8, PropModeReplace, (unsigned char*) data, length);
+	gdk_error_trap_pop ();
+
+	/* for some reason this fails with BadRequest, but actually sets the value */
+	if (rc == BadRequest)
+		rc = Success;
+
+	/* did the call fail */
+	if (rc != Success) {
+		g_set_error (error, 1, 0, "failed to set icc profile atom with rc %i", rc);
+		goto out;
+	}
+
+	/* success */
+	ret = TRUE;
+out:
+	return ret;
+}
+
+/**
+ * gcm_x11_screen_set_protocol_version:
+ * @x11: a valid %GcmX11Screen instance
+ * @major: the major version
+ * @minor: the minor version
+ * @error: a %GError that is set in the result of an error, or %NULL
+ *
+ * Sets the ICC Profiles in X supported version to the XServer.
+ *
+ * Return value: %TRUE for success.
+ *
+ * Since: 0.0.1
+ **/
+gboolean
+gcm_x11_screen_set_protocol_version (GcmX11Screen *screen, guint major, guint minor, GError **error)
+{
+	gboolean ret = FALSE;
+	gint rc;
+	Atom atom = None;
+	guint data;
+	GcmX11ScreenPrivate *priv = screen->priv;
+
+	g_return_val_if_fail (GCM_IS_X11_SCREEN (screen), FALSE);
+
+	/* get the atom data */
+	data = major * 100 + minor * 1;
+
+	/* get the value */
+	gdk_error_trap_push ();
+	atom = XInternAtom (priv->xdisplay, "_ICC_PROFILE_IN_X_VERSION", FALSE);
+	rc = XChangeProperty (priv->xdisplay, priv->xroot, atom, XA_CARDINAL, 8, PropModeReplace, (unsigned char*) &data, 1);
+	gdk_error_trap_pop ();
+
+	/* for some reason this fails with BadRequest, but actually sets the value */
+	if (rc == BadRequest)
+		rc = Success;
+
+	/* did the call fail */
+	if (rc != Success) {
+		g_set_error (error, 1, 0, "failed to set icc profile atom with rc %i", rc);
+		goto out;
+	}
+
+	/* success */
+	ret = TRUE;
+out:
+	return ret;
+}
+
+/**
+ * gcm_x11_screen_remove_protocol_version:
+ * @x11: a valid %GcmX11Screen instance
+ * @error: a %GError that is set in the result of an error, or %NULL
+ *
+ * Removes the ICC profile version data from the XServer.
+ *
+ * Return value: %TRUE for success.
+ *
+ * Since: 0.0.1
+ **/
+gboolean
+gcm_x11_screen_remove_protocol_version (GcmX11Screen *screen, GError **error)
+{
+	Atom atom = None;
+	gint rc;
+	gboolean ret = TRUE;
+	GcmX11ScreenPrivate *priv = screen->priv;
+
+	g_return_val_if_fail (GCM_IS_X11_SCREEN (screen), FALSE);
+
+	egg_debug ("removing root window ICC profile atom");
+
+	/* get the value */
+	gdk_error_trap_push ();
+	atom = XInternAtom (priv->xdisplay, "_ICC_PROFILE_IN_X_VERSION", FALSE);
+	rc = XDeleteProperty(priv->xdisplay, priv->xroot, atom);
+	gdk_error_trap_pop ();
+
+	/* this fails with BadRequest if the atom was not set */
+	if (rc == BadRequest)
+		rc = Success;
+
+	/* did the call fail */
+	if (rc != Success) {
+		ret = FALSE;
+		g_set_error (error, 1, 0, "failed to delete root window atom with rc %i", rc);
+		goto out;
+	}
+out:
+	return ret;
+}
+
+/**
+ * gcm_x11_screen_get_protocol_version:
+ *
+ * @x11: a valid %GcmX11Screen instance
+ * @major: the major version
+ * @minor: the minor version
+ * @error: a %GError that is set in the result of an error, or %NULL
+ *
+ * Gets the ICC profile data from the XServer.
+ *
+ * Return value: %TRUE for success.
+ *
+ * Since: 0.0.1
+ **/
+gboolean
+gcm_x11_screen_get_protocol_version (GcmX11Screen *screen, guint *major, guint *minor, GError **error)
+{
+	gboolean ret = FALSE;
+	gchar *data_tmp;
+	gint format;
+	gint rc;
+	gulong bytes_after;
+	gulong nitems;
+	Atom atom = None;
+	Atom type;
+	GcmX11ScreenPrivate *priv = screen->priv;
+
+	g_return_val_if_fail (GCM_IS_X11_SCREEN (screen), FALSE);
+	g_return_val_if_fail (major != NULL, FALSE);
+	g_return_val_if_fail (minor != NULL, FALSE);
+
+	/* get the value */
+	gdk_error_trap_push ();
+	atom = XInternAtom (priv->xdisplay, "_ICC_PROFILE_IN_X_VERSION", FALSE);
+	rc = XGetWindowProperty (priv->xdisplay, priv->xroot, atom, 0, G_MAXLONG, False, XA_CARDINAL,
+				 &type, &format, &nitems, &bytes_after, (unsigned char **) &data_tmp);
+	gdk_error_trap_pop ();
+
+	/* did the call fail */
+	if (rc != Success) {
+		g_set_error (error, 1, 0, "failed to get atom with rc %i", rc);
+		goto out;
+	}
+
+	/* was nothing found */
+	if (nitems == 0) {
+		g_set_error (error, 1, 0, "icc profile atom has not been set");
+		goto out;
+	}
+
+	/* set total */
+	*major = (guint) data_tmp[0] / 100;
+	*minor = (guint) data_tmp[0] % 100;
+
+	/* success */
+	ret = TRUE;
+out:
+	if (data_tmp != NULL)
+		XFree (data_tmp);
+	return ret;
+}
+
+/**
+ * gcm_x11_screen_remove_profile:
+ * @x11: a valid %GcmX11Screen instance
+ * @error: a %GError that is set in the result of an error, or %NULL
+ *
+ * Removes the ICC profile data from the XServer.
+ *
+ * Return value: %TRUE for success.
+ *
+ * Since: 0.0.1
+ **/
+gboolean
+gcm_x11_screen_remove_profile (GcmX11Screen *screen, GError **error)
+{
+	Atom atom = None;
+	gint rc;
+	gboolean ret = TRUE;
+	GcmX11ScreenPrivate *priv = screen->priv;
+
+	g_return_val_if_fail (GCM_IS_X11_SCREEN (screen), FALSE);
+
+	egg_debug ("removing root window ICC profile atom");
+
+	/* get the value */
+	gdk_error_trap_push ();
+	atom = XInternAtom (priv->xdisplay, "_ICC_PROFILE", FALSE);
+	rc = XDeleteProperty (priv->xdisplay, priv->xroot, atom);
+	gdk_error_trap_pop ();
+
+	/* this fails with BadRequest if the atom was not set */
+	if (rc == BadRequest)
+		rc = Success;
+
+	/* did the call fail */
+	if (rc != Success) {
+		ret = FALSE;
+		g_set_error (error, 1, 0, "failed to delete root window atom with rc %i", rc);
+		goto out;
+	}
+out:
+	return ret;
+}
+
+/**
+ * gcm_x11_screen_class_init:
+ **/
+static void
+gcm_x11_screen_class_init (GcmX11ScreenClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	object_class->finalize = gcm_x11_screen_finalize;
+
+	/**
+	 * GcmX11Screen::changed:
+	 **/
+	signals[SIGNAL_CHANGED] =
+		g_signal_new ("changed",
+			      G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (GcmX11ScreenClass, changed),
+			      NULL, NULL, g_cclosure_marshal_VOID__VOID,
+			      G_TYPE_NONE, 0);
+
+	g_type_class_add_private (klass, sizeof (GcmX11ScreenPrivate));
+}
+
+/**
+ * gcm_x11_screen_init:
+ **/
+static void
+gcm_x11_screen_init (GcmX11Screen *screen)
+{
+	screen->priv = GCM_X11_SCREEN_GET_PRIVATE (screen);
+	screen->priv->outputs = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+}
+
+/**
+ * gcm_x11_screen_finalize:
+ **/
+static void
+gcm_x11_screen_finalize (GObject *object)
+{
+	GcmX11Screen *screen = GCM_X11_SCREEN (object);
+	GcmX11ScreenPrivate *priv = screen->priv;
+
+	g_ptr_array_unref (screen->priv->outputs);
+	gdk_window_remove_filter (priv->gdk_root, gcm_x11_screen_on_event_cb, screen);
+
+	G_OBJECT_CLASS (gcm_x11_screen_parent_class)->finalize (object);
+}
+
+/**
+ * gcm_x11_screen_new:
+ *
+ * Return value: a new #GcmX11Screen object.
+ *
+ * Since: 0.0.1
+ **/
+GcmX11Screen *
+gcm_x11_screen_new (void)
+{
+	if (gcm_x11_screen_object != NULL) {
+		g_object_ref (gcm_x11_screen_object);
+	} else {
+		gcm_x11_screen_object = g_object_new (GCM_TYPE_X11_SCREEN, NULL);
+		g_object_add_weak_pointer (gcm_x11_screen_object, &gcm_x11_screen_object);
+	}
+	return GCM_X11_SCREEN (gcm_x11_screen_object);
+}
+
diff --git a/libcolor-glib/gcm-x11-screen.h b/libcolor-glib/gcm-x11-screen.h
new file mode 100644
index 0000000..52f7e54
--- /dev/null
+++ b/libcolor-glib/gcm-x11-screen.h
@@ -0,0 +1,97 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#if !defined (__LIBCOLOR_GLIB_H_INSIDE__) && !defined (LIBCOLOR_GLIB_COMPILATION)
+#error "Only <libcolor-glib.h> can be included directly."
+#endif
+
+#ifndef __GCM_X11_SCREEN_H
+#define __GCM_X11_SCREEN_H
+
+#include <glib-object.h>
+#include <gdk/gdk.h>
+
+#include "gcm-x11-output.h"
+
+G_BEGIN_DECLS
+
+#define GCM_TYPE_X11_SCREEN		(gcm_x11_screen_get_type ())
+#define GCM_X11_SCREEN(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), GCM_TYPE_X11_SCREEN, GcmX11Screen))
+#define GCM_IS_X11_SCREEN(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), GCM_TYPE_X11_SCREEN))
+
+#define GCM_X11_SCREEN_ERROR		1
+#define GCM_X11_SCREEN_ERROR_INTERNAL	0
+
+typedef struct _GcmX11ScreenPrivate	GcmX11ScreenPrivate;
+typedef struct _GcmX11Screen		GcmX11Screen;
+typedef struct _GcmX11ScreenClass	GcmX11ScreenClass;
+
+struct _GcmX11Screen
+{
+	 GObject		 parent;
+	 GcmX11ScreenPrivate	*priv;
+};
+
+struct _GcmX11ScreenClass
+{
+	GObjectClass		 parent_class;
+	void			(* changed)		(GcmX11Screen		*screen);
+};
+
+GType		 gcm_x11_screen_get_type		(void);
+GcmX11Screen	*gcm_x11_screen_new			(void);
+
+gboolean	 gcm_x11_screen_assign			(GcmX11Screen		*screen,
+							 GdkScreen		*gdk_screen,
+							 GError			**error);
+GPtrArray	*gcm_x11_screen_get_outputs		(GcmX11Screen		*screen,
+							 GError			**error);
+GcmX11Output	*gcm_x11_screen_get_output_by_name	(GcmX11Screen		*screen,
+							 const gchar		*name,
+							 GError			**error);
+gboolean	 gcm_x11_screen_get_profile_data	(GcmX11Screen		*screen,
+							 guint8			**data,
+							 gsize			*length,
+							 GError			**error);
+gboolean	 gcm_x11_screen_set_profile_data	(GcmX11Screen		*screen,
+							 const guint8		*data,
+							 gsize			 length,
+							 GError			**error);
+gboolean	 gcm_x11_screen_set_profile		(GcmX11Screen		*screen,
+							 const gchar		*filename,
+							 GError			**error);
+gboolean	 gcm_x11_screen_remove_profile		(GcmX11Screen		*screen,
+							 GError			**error);
+gboolean	 gcm_x11_screen_set_protocol_version	(GcmX11Screen		*screen,
+							 guint			 major,
+							 guint			 minor,
+							 GError			**error);
+gboolean	 gcm_x11_screen_remove_protocol_version	(GcmX11Screen		*screen,
+							 GError			**error);
+gboolean	 gcm_x11_screen_get_protocol_version	(GcmX11Screen		*screen,
+							 guint			*major,
+							 guint			*minor,
+							 GError			**error);
+
+G_END_DECLS
+
+#endif /* __GCM_X11_SCREEN_H */
+
diff --git a/libcolor-glib/libcolor-glib.h b/libcolor-glib/libcolor-glib.h
index 8cdeecb..6f66ecb 100644
--- a/libcolor-glib/libcolor-glib.h
+++ b/libcolor-glib/libcolor-glib.h
@@ -43,7 +43,8 @@
 #include <gcm-enum.h>
 #include <gcm-clut.h>
 #include <gcm-dmi.h>
-#include <gcm-xserver.h>
+#include <gcm-x11-screen.h>
+#include <gcm-x11-output.h>
 #include <gcm-brightness.h>
 #include <gcm-profile-store.h>
 #include <gcm-usb.h>
diff --git a/src/Makefile.am b/src/Makefile.am
index 2b5590d..59bff3d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -2,7 +2,6 @@ INCLUDES =						\
 	$(GLIB_CFLAGS)					\
 	$(X11_CFLAGS)					\
 	$(GTK_CFLAGS)					\
-	$(GNOMEDESKTOP_CFLAGS)				\
 	$(VTE_CFLAGS)					\
 	$(XORG_CFLAGS)					\
 	$(CUPS_CFLAGS)					\
@@ -14,7 +13,6 @@ INCLUDES =						\
 	$(CANBERRA_CFLAGS)				\
 	$(CONTROL_CENTER_CFLAGS)			\
 	-DG_UDEV_API_IS_SUBJECT_TO_CHANGE		\
-	-DGNOME_DESKTOP_USE_UNSTABLE_API		\
 	$(GUDEV_CFLAGS)					\
 	-I$(top_srcdir)/libcolor-glib			\
 	-DLIBCOLOR_GLIB_COMPILATION			\
@@ -40,8 +38,6 @@ noinst_LIBRARIES = libgcmshared.a
 libgcmshared_a_SOURCES =				\
 	egg-debug.c					\
 	egg-debug.h					\
-	gcm-screen.c					\
-	gcm-screen.h					\
 	gcm-exif.c					\
 	gcm-exif.h					\
 	gcm-print.c					\
@@ -119,7 +115,6 @@ gcm_inspect_LDADD =					\
 	libgcmshared.a					\
 	$(GLIB_LIBS)					\
 	$(X11_LIBS)					\
-	$(GNOMEDESKTOP_LIBS)				\
 	$(GUDEV_LIBS)					\
 	$(XORG_LIBS)					\
 	$(GTK_LIBS)					\
@@ -138,7 +133,6 @@ gcm_apply_LDADD =					\
 	libgcmshared.a					\
 	$(GLIB_LIBS)					\
 	$(X11_LIBS)					\
-	$(GNOMEDESKTOP_LIBS)				\
 	$(GUDEV_LIBS)					\
 	$(XORG_LIBS)					\
 	$(GTK_LIBS)					\
@@ -157,7 +151,6 @@ gcm_import_LDADD =					\
 	libgcmshared.a					\
 	$(GLIB_LIBS)					\
 	$(X11_LIBS)					\
-	$(GNOMEDESKTOP_LIBS)				\
 	$(GUDEV_LIBS)					\
 	$(XORG_LIBS)					\
 	$(GTK_LIBS)					\
@@ -178,7 +171,6 @@ gcm_viewer_LDADD =					\
 	libgcmshared.a					\
 	$(GLIB_LIBS)					\
 	$(X11_LIBS)					\
-	$(GNOMEDESKTOP_LIBS)				\
 	$(VTE_LIBS)					\
 	$(GUDEV_LIBS)					\
 	$(XORG_LIBS)					\
@@ -200,7 +192,6 @@ gcm_picker_LDADD =					\
 	libgcmshared.a					\
 	$(GLIB_LIBS)					\
 	$(X11_LIBS)					\
-	$(GNOMEDESKTOP_LIBS)				\
 	$(VTE_LIBS)					\
 	$(GUDEV_LIBS)					\
 	$(XORG_LIBS)					\
@@ -223,7 +214,6 @@ gcm_session_LDADD =					\
 	libgcmshared.a					\
 	$(GLIB_LIBS)					\
 	$(X11_LIBS)					\
-	$(GNOMEDESKTOP_LIBS)				\
 	$(GUDEV_LIBS)					\
 	$(XORG_LIBS)					\
 	$(GTK_LIBS)					\
@@ -249,7 +239,6 @@ libcolor_la_SOURCES =					\
 libcolor_la_LIBADD =					\
 	$(GLIB_LIBS)					\
 	$(X11_LIBS)					\
-	$(GNOMEDESKTOP_LIBS)				\
 	$(GUDEV_LIBS)					\
 	$(XORG_LIBS)					\
 	$(GTK_LIBS)					\
@@ -281,7 +270,6 @@ gcm_self_test_LDADD =					\
 	libgcmshared.a					\
 	$(GLIB_LIBS)					\
 	$(X11_LIBS)					\
-	$(GNOMEDESKTOP_LIBS)				\
 	$(GUDEV_LIBS)					\
 	$(XORG_LIBS)					\
 	$(GTK_LIBS)					\
diff --git a/src/gcm-calibrate-argyll.c b/src/gcm-calibrate-argyll.c
index 52b13ea..e0947d4 100644
--- a/src/gcm-calibrate-argyll.c
+++ b/src/gcm-calibrate-argyll.c
@@ -43,7 +43,7 @@
 #include "gcm-calibrate-argyll.h"
 #include "gcm-sensor-client.h"
 #include "gcm-utils.h"
-#include "gcm-screen.h"
+#include "gcm-x11-screen.h"
 #include "gcm-print.h"
 #include "gcm-xyz.h"
 #include "gcm-calibrate-dialog.h"
@@ -79,7 +79,7 @@ struct _GcmCalibrateArgyllPrivate
 	GcmCalibrateDialog		*calibrate_dialog;
 	pid_t				 child_pid;
 	GtkResponseType			 response;
-	GcmScreen			*screen;
+	GcmX11Screen			*screen;
 	glong				 vte_previous_row;
 	glong				 vte_previous_col;
 	gboolean			 already_on_window;
@@ -417,7 +417,7 @@ gcm_calibrate_argyll_display_neutralise (GcmCalibrateArgyll *calibrate_argyll, G
 	gchar kind;
 	gchar *command = NULL;
 	gchar **argv = NULL;
-	GnomeRROutput *output;
+	GcmX11Output *output;
 	GPtrArray *array = NULL;
 	gchar *basename = NULL;
 	gchar *output_name = NULL;
@@ -445,7 +445,7 @@ gcm_calibrate_argyll_display_neutralise (GcmCalibrateArgyll *calibrate_argyll, G
 	}
 
 	/* get the device */
-	output = gcm_screen_get_output_by_name (priv->screen, output_name, error);
+	output = gcm_x11_screen_get_output_by_name (priv->screen, output_name, error);
 	if (output == NULL) {
 		ret = FALSE;
 		goto out;
@@ -2968,7 +2968,7 @@ gcm_calibrate_argyll_init (GcmCalibrateArgyll *calibrate_argyll)
 			  G_CALLBACK (gcm_calibrate_argyll_response_cb), calibrate_argyll);
 
 	/* get screen */
-	calibrate_argyll->priv->screen = gcm_screen_new ();
+	calibrate_argyll->priv->screen = gcm_x11_screen_new ();
 
 	/* add vte widget */
 #ifdef HAVE_VTE
diff --git a/src/gcm-client.c b/src/gcm-client.c
index af9c92b..a0272bf 100644
--- a/src/gcm-client.c
+++ b/src/gcm-client.c
@@ -32,13 +32,13 @@
 #include <glib/gi18n.h>
 #include <glib-object.h>
 #include <gudev/gudev.h>
-#include <libgnomeui/gnome-rr.h>
 #include <cups/cups.h>
 
 #ifdef HAVE_SANE
  #include <sane/sane.h>
 #endif
 
+#include "gcm-x11-screen.h"
 #include "gcm-client.h"
 #include "gcm-device-xrandr.h"
 #include "gcm-device-udev.h"
@@ -47,7 +47,7 @@
  #include "gcm-device-sane.h"
 #endif
 #include "gcm-device-virtual.h"
-#include "gcm-screen.h"
+#include "gcm-x11-screen.h"
 #include "gcm-utils.h"
 
 #include "egg-debug.h"
@@ -56,7 +56,7 @@ static void     gcm_client_finalize	(GObject     *object);
 
 #define GCM_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GCM_TYPE_CLIENT, GcmClientPrivate))
 
-static void gcm_client_xrandr_add (GcmClient *client, GnomeRROutput *output);
+static void gcm_client_xrandr_add (GcmClient *client, GcmX11Output *output);
 
 #ifdef HAVE_SANE
 static gboolean gcm_client_coldplug_devices_sane (GcmClient *client, GError **error);
@@ -74,7 +74,7 @@ struct _GcmClientPrivate
 	GPtrArray			*array;
 	GUdevClient			*gudev_client;
 	GSettings			*settings;
-	GcmScreen			*screen;
+	GcmX11Screen			*screen;
 	http_t				*http;
 	gboolean			 loading;
 	guint				 loading_refcount;
@@ -590,13 +590,12 @@ gcm_client_get_device_by_window (GcmClient *client, GdkWindow *window)
 	gfloat covered_max = 0.0f;
 	gint window_width, window_height;
 	gint window_x, window_y;
-	gint x, y;
+	guint x, y;
 	guint i;
-	guint len = 0;
 	guint width, height;
-	GnomeRRMode *mode;
-	GnomeRROutput *output_best = NULL;
-	GnomeRROutput **outputs;
+	GcmX11Output *output;
+	GcmX11Output *output_best = NULL;
+	GPtrArray *outputs;
 	GcmDevice *device = NULL;
 
 	/* get the window parameters, in root co-ordinates */
@@ -604,27 +603,22 @@ gcm_client_get_device_by_window (GcmClient *client, GdkWindow *window)
 	gdk_drawable_get_size (GDK_DRAWABLE(window), &window_width, &window_height);
 
 	/* get list of updates */
-	outputs = gcm_screen_get_outputs (client->priv->screen, NULL);
+	outputs = gcm_x11_screen_get_outputs (client->priv->screen, NULL);
 	if (outputs == NULL)
 		goto out;
 
-	/* find length */
-	for (i=0; outputs[i] != NULL; i++)
-		len++;
-
 	/* go through each option */
-	for (i=0; i<len; i++) {
+	for (i=0; i<outputs->len; i++) {
 
 		/* not interesting */
-		if (!gnome_rr_output_is_connected (outputs[i]))
+		output = g_ptr_array_index (outputs, i);
+		if (!gcm_x11_output_get_connected (output))
 			continue;
 
 		/* get details about the output */
-		gnome_rr_output_get_position (outputs[i], &x, &y);
-		mode = gnome_rr_output_get_current_mode (outputs[i]);
-		width = gnome_rr_mode_get_width (mode);
-		height = gnome_rr_mode_get_height (mode);
-		egg_debug ("%s: %ix%i -> %ix%i (%ix%i -> %ix%i)", gnome_rr_output_get_name (outputs[i]),
+		gcm_x11_output_get_position (output, &x, &y);
+		gcm_x11_output_get_size (output, &width, &height);
+		egg_debug ("%s: %ix%i -> %ix%i (%ix%i -> %ix%i)", gcm_x11_output_get_name (output),
 			   x, y, x+width, y+height,
 			   window_x, window_y, window_x+window_width, window_y+window_height);
 
@@ -634,7 +628,7 @@ gcm_client_get_device_by_window (GcmClient *client, GdkWindow *window)
 
 		/* keep a running total of which one is best */
 		if (covered > 0.01f && covered > covered_max) {
-			output_best = outputs[i];
+			output_best = output;
 
 			/* optimize */
 			if (covered > 0.99) {
@@ -644,10 +638,12 @@ gcm_client_get_device_by_window (GcmClient *client, GdkWindow *window)
 
 			/* keep looking */
 			covered_max = covered;
-			egg_debug ("personal best of %f for %s", covered, gnome_rr_output_get_name (output_best));
+			egg_debug ("personal best of %f for %s", covered, gcm_x11_output_get_name (output_best));
 		}
 	}
 out:
+	if (outputs != NULL)
+		g_ptr_array_unref (outputs);
 	/* if we found an output, get the device */
 	if (output_best != NULL) {
 		GcmDevice *device_tmp;
@@ -663,16 +659,16 @@ out:
  * gcm_client_xrandr_add:
  **/
 static void
-gcm_client_xrandr_add (GcmClient *client, GnomeRROutput *output)
+gcm_client_xrandr_add (GcmClient *client, GcmX11Output *output)
 {
 	gboolean ret;
 	GError *error = NULL;
 	GcmDevice *device = NULL;
 
 	/* if nothing connected then ignore */
-	ret = gnome_rr_output_is_connected (output);
+	ret = gcm_x11_output_get_connected (output);
 	if (!ret) {
-		egg_debug ("%s is not connected", gnome_rr_output_get_name (output));
+		egg_debug ("%s is not connected", gcm_x11_output_get_name (output));
 		goto out;
 	}
 
@@ -703,20 +699,32 @@ out:
 static gboolean
 gcm_client_coldplug_devices_xrandr (GcmClient *client, GError **error)
 {
-	GnomeRROutput **outputs;
+	GcmX11Output *output;
+	GPtrArray *outputs = NULL;
 	guint i;
+	gboolean ret;
 	GcmClientPrivate *priv = client->priv;
 
-	outputs = gcm_screen_get_outputs (priv->screen, error);
-	if (outputs == NULL)
-		return FALSE;
-	for (i=0; outputs[i] != NULL; i++)
-		gcm_client_xrandr_add (client, outputs[i]);
+	/* use the default screen */
+	ret = gcm_x11_screen_assign (priv->screen, NULL, error);
+	if (!ret)
+		goto out;
+	outputs = gcm_x11_screen_get_outputs (priv->screen, error);
+	if (outputs == NULL) {
+		ret = FALSE;
+		goto out;
+	}
 
-	/* inform the UI */
+	/* add each device */
+	for (i=0; i<outputs->len; i++) {
+		output = g_ptr_array_index (outputs, i);
+		gcm_client_xrandr_add (client, output);
+	}
+out:
+	if (outputs != NULL)
+		g_ptr_array_unref (outputs);
 	gcm_client_done_loading (client);
-
-	return TRUE;
+	return ret;
 }
 
 /**
@@ -1403,17 +1411,21 @@ gcm_client_set_property (GObject *object, guint prop_id, const GValue *value, GP
  * gcm_client_randr_event_cb:
  **/
 static void
-gcm_client_randr_event_cb (GcmScreen *screen, GcmClient *client)
+gcm_client_randr_event_cb (GcmX11Screen *screen, GcmClient *client)
 {
-	GnomeRROutput **outputs;
+	GPtrArray *outputs;
+	GcmX11Output *output;
 	guint i;
 
 	egg_debug ("screens may have changed");
 
 	/* replug devices */
-	outputs = gcm_screen_get_outputs (screen, NULL);
-	for (i=0; outputs[i] != NULL; i++)
-		gcm_client_xrandr_add (client, outputs[i]);
+	outputs = gcm_x11_screen_get_outputs (screen, NULL);
+	for (i=0; i<outputs->len; i++) {
+		output = g_ptr_array_index (outputs, i);
+		gcm_client_xrandr_add (client, output);
+	}
+	g_ptr_array_unref (outputs);
 }
 
 /**
@@ -1501,8 +1513,8 @@ gcm_client_init (GcmClient *client)
 	client->priv->init_sane = FALSE;
 	client->priv->settings = g_settings_new (GCM_SETTINGS_SCHEMA);
 	client->priv->array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
-	client->priv->screen = gcm_screen_new ();
-	g_signal_connect (client->priv->screen, "outputs-changed",
+	client->priv->screen = gcm_x11_screen_new ();
+	g_signal_connect (client->priv->screen, "changed",
 			  G_CALLBACK (gcm_client_randr_event_cb), client);
 
 	/* use GUdev to find devices */
diff --git a/src/gcm-device-xrandr.c b/src/gcm-device-xrandr.c
index b7457df..f87ad73 100644
--- a/src/gcm-device-xrandr.c
+++ b/src/gcm-device-xrandr.c
@@ -24,18 +24,17 @@
 #include <glib-object.h>
 #include <glib/gi18n.h>
 #include <math.h>
-#include <libgnomeui/gnome-rr.h>
 #include <X11/extensions/Xrandr.h>
-#include <X11/extensions/xf86vmode.h>
 #include <gdk/gdkx.h>
 
 #include "gcm-device-xrandr.h"
 #include "gcm-edid.h"
 #include "gcm-dmi.h"
 #include "gcm-utils.h"
-#include "gcm-xserver.h"
-#include "gcm-screen.h"
+#include "gcm-x11-screen.h"
 #include "gcm-clut.h"
+#include "gcm-x11-output.h"
+#include "gcm-x11-screen.h"
 
 #include "egg-debug.h"
 
@@ -57,16 +56,13 @@ struct _GcmDeviceXrandrPrivate
 	GcmEdid				*edid;
 	GcmDmi				*dmi;
 	GSettings			*settings;
-	GcmXserver			*xserver;
-	GcmScreen			*screen;
-	gboolean			 xrandr_fallback;
+	GcmX11Screen			*screen;
 	gboolean			 remove_atom;
 };
 
 enum {
 	PROP_0,
 	PROP_NATIVE_DEVICE,
-	PROP_XRANDR_FALLBACK,
 	PROP_EISA_ID,
 	PROP_EDID_MD5,
 	PROP_LAST
@@ -105,21 +101,12 @@ gcm_device_xrandr_get_edid_md5 (GcmDeviceXrandr *device_xrandr)
 }
 
 /**
- * gcm_device_xrandr_get_fallback:
- **/
-gboolean
-gcm_device_xrandr_get_fallback (GcmDeviceXrandr *device_xrandr)
-{
-	return device_xrandr->priv->xrandr_fallback;
-}
-
-/**
  * gcm_device_xrandr_get_output_name:
  *
  * Return value: the output name, free with g_free().
  **/
 static gchar *
-gcm_device_xrandr_get_output_name (GcmDeviceXrandr *device_xrandr, GnomeRROutput *output)
+gcm_device_xrandr_get_output_name (GcmDeviceXrandr *device_xrandr, GcmX11Output *output)
 {
 	const gchar *output_name;
 	const gchar *name;
@@ -134,12 +121,12 @@ gcm_device_xrandr_get_output_name (GcmDeviceXrandr *device_xrandr, GnomeRROutput
 	string = g_string_new ("");
 
 	/* if nothing connected then fall back to the connector name */
-	ret = gnome_rr_output_is_connected (output);
+	ret = gcm_x11_output_get_connected (output);
 	if (!ret)
 		goto out;
 
 	/* this is an internal panel, use the DMI data */
-	output_name = gnome_rr_output_get_name (output);
+	output_name = gcm_x11_output_get_name (output);
 	ret = gcm_utils_output_is_lcd_internal (output_name);
 	if (ret) {
 		/* find the machine details */
@@ -187,7 +174,7 @@ out:
  * gcm_device_xrandr_get_id_for_xrandr_device:
  **/
 static gchar *
-gcm_device_xrandr_get_id_for_xrandr_device (GcmDeviceXrandr *device_xrandr, GnomeRROutput *output)
+gcm_device_xrandr_get_id_for_xrandr_device (GcmDeviceXrandr *device_xrandr, GcmX11Output *output)
 {
 	const gchar *output_name;
 	const gchar *name;
@@ -202,7 +189,7 @@ gcm_device_xrandr_get_id_for_xrandr_device (GcmDeviceXrandr *device_xrandr, Gnom
 	string = g_string_new ("xrandr");
 
 	/* if nothing connected then fall back to the connector name */
-	ret = gnome_rr_output_is_connected (output);
+	ret = gcm_x11_output_get_connected (output);
 	if (!ret)
 		goto out;
 
@@ -222,11 +209,11 @@ gcm_device_xrandr_get_id_for_xrandr_device (GcmDeviceXrandr *device_xrandr, Gnom
 out:
 	/* fallback to the output name */
 	if (string->len == 6) {
-		output_name = gnome_rr_output_get_name (output);
+		output_name = gcm_x11_output_get_name (output);
 		ret = gcm_utils_output_is_lcd_internal (output_name);
 		if (ret)
 			output_name = "LVDS";
-		g_string_append (string, output_name);
+		g_string_append_printf (string, "_%s", output_name);
 	}
 
 	/* replace unsafe chars */
@@ -238,7 +225,7 @@ out:
  * gcm_device_xrandr_set_from_output:
  **/
 gboolean
-gcm_device_xrandr_set_from_output (GcmDevice *device, GnomeRROutput *output, GError **error)
+gcm_device_xrandr_set_from_output (GcmDevice *device, GcmX11Output *output, GError **error)
 {
 	gchar *title = NULL;
 	gchar *id = NULL;
@@ -248,12 +235,13 @@ gcm_device_xrandr_set_from_output (GcmDevice *device, GnomeRROutput *output, GEr
 	const gchar *serial;
 	const gchar *manufacturer;
 	const gchar *model;
-	const guint8 *data;
+	guint8 *data = NULL;
+	gsize length;
 	GcmDeviceXrandrPrivate *priv = GCM_DEVICE_XRANDR(device)->priv;
 
-	/* parse the EDID to get a crtc-specific name, not an output specific name */
-	data = gnome_rr_output_get_edid_data (output);
-	if (data != NULL) {
+	/* parse the EDID to get a output specific name */
+	ret = gcm_x11_output_get_edid_data (output, &data, &length, NULL);
+	if (ret) {
 		ret = gcm_edid_parse (priv->edid, data, NULL);
 		if (!ret) {
 			g_set_error (error, 1, 0, "failed to parse edid");
@@ -276,7 +264,7 @@ gcm_device_xrandr_set_from_output (GcmDevice *device, GnomeRROutput *output, GEr
 	priv->edid_md5 = g_strdup (gcm_edid_get_checksum (priv->edid));
 
 	/* refine data if it's missing */
-	output_name = gnome_rr_output_get_name (output);
+	output_name = gcm_x11_output_get_name (output);
 	lcd_internal = gcm_utils_output_is_lcd_internal (output_name);
 	if (lcd_internal && model == NULL)
 		model = gcm_dmi_get_version (priv->dmi);
@@ -294,107 +282,29 @@ gcm_device_xrandr_set_from_output (GcmDevice *device, GnomeRROutput *output, GEr
 		      "title", title,
 		      "native-device", output_name,
 		      NULL);
+
+	/* success */
+	ret = TRUE;
 out:
+	g_free (data);
 	g_free (id);
 	g_free (title);
 	return ret;
 }
 
-
-/**
- * gcm_device_xrandr_get_gamma_size_fallback:
- **/
-static guint
-gcm_device_xrandr_get_gamma_size_fallback (void)
-{
-	guint size;
-	Bool rc;
-
-	/* this is per-screen, not per output which is less than ideal */
-	gdk_error_trap_push ();
-	egg_warning ("using PER-SCREEN gamma tables as driver is not XRANDR 1.3 compliant");
-	rc = XF86VidModeGetGammaRampSize (GDK_DISPLAY(), gdk_x11_get_default_screen (), (int*) &size);
-	gdk_error_trap_pop ();
-	if (!rc)
-		size = 0;
-
-	return size;
-}
-
-/**
- * gcm_device_xrandr_get_gamma_size:
- *
- * Return value: the gamma size, or 0 if error;
- **/
-static guint
-gcm_device_xrandr_get_gamma_size (GcmDeviceXrandr *device_xrandr, GnomeRRCrtc *crtc, GError **error)
-{
-	guint id;
-	guint size;
-	GcmDeviceXrandrPrivate *priv = device_xrandr->priv;
-
-	/* use cached value */
-	if (priv->gamma_size > 0)
-		return priv->gamma_size;
-
-	/* get id that X recognizes */
-	id = gnome_rr_crtc_get_id (crtc);
-
-	/* get the value, and catch errors */
-	gdk_error_trap_push ();
-	size = XRRGetCrtcGammaSize (GDK_DISPLAY(), id);
-	if (gdk_error_trap_pop ())
-		size = 0;
-
-	/* some drivers support Xrandr 1.2, not 1.3 */
-	if (size == 0) {
-		priv->xrandr_fallback = TRUE;
-		size = gcm_device_xrandr_get_gamma_size_fallback ();
-	} else {
-		priv->xrandr_fallback = FALSE;
-	}
-
-	/* no size, or X popped an error */
-	if (size == 0) {
-		g_set_error_literal (error, 1, 0, "failed to get gamma size");
-		goto out;
-	}
-
-	/* save value as this will not change */
-	priv->gamma_size = size;
-out:
-	return size;
-}
-
-/**
- * gcm_device_xrandr_apply_fallback:
- **/
-static gboolean
-gcm_device_xrandr_apply_fallback (XRRCrtcGamma *crtc_gamma, guint size)
-{
-	Bool rc;
-
-	/* this is per-screen, not per output which is less than ideal */
-	gdk_error_trap_push ();
-	egg_warning ("using PER-SCREEN gamma tables as driver is not XRANDR 1.3 compliant");
-	rc = XF86VidModeSetGammaRamp (GDK_DISPLAY(), gdk_x11_get_default_screen (), size, crtc_gamma->red, crtc_gamma->green, crtc_gamma->blue);
-	gdk_error_trap_pop ();
-
-	return rc;
-}
-
 /**
- * gcm_device_xrandr_apply_for_crtc:
+ * gcm_device_xrandr_apply_for_output:
  *
  * Return value: %TRUE for success;
  **/
 static gboolean
-gcm_device_xrandr_apply_for_crtc (GcmDeviceXrandr *device_xrandr, GnomeRRCrtc *crtc, GcmClut *clut, GError **error)
+gcm_device_xrandr_apply_for_output (GcmDeviceXrandr *device_xrandr, GcmX11Output *output, GcmClut *clut, GError **error)
 {
-	guint id;
 	gboolean ret = TRUE;
 	GPtrArray *array = NULL;
-	XRRCrtcGamma *crtc_gamma = NULL;
+	guint16 *red = NULL;
+	guint16 *green = NULL;
+	guint16 *blue = NULL;
 	guint i;
 	GcmClutData *data;
 
@@ -414,32 +324,24 @@ gcm_device_xrandr_apply_for_crtc (GcmDeviceXrandr *device_xrandr, GnomeRRCrtc *c
 	}
 
 	/* convert to a type X understands */
-	crtc_gamma = XRRAllocGamma (array->len);
+	red = g_new (guint16, array->len);
+	green = g_new (guint16, array->len);
+	blue = g_new (guint16, array->len);
 	for (i=0; i<array->len; i++) {
 		data = g_ptr_array_index (array, i);
-		crtc_gamma->red[i] = data->red;
-		crtc_gamma->green[i] = data->green;
-		crtc_gamma->blue[i] = data->blue;
+		red[i] = data->red;
+		green[i] = data->green;
+		blue[i] = data->blue;
 	}
 
-	/* get id that X recognizes */
-	id = gnome_rr_crtc_get_id (crtc);
-
-	/* get the value, and catch errors */
-	gdk_error_trap_push ();
-	XRRSetCrtcGamma (GDK_DISPLAY(), id, crtc_gamma);
-	gdk_flush ();
-	if (gdk_error_trap_pop ()) {
-		/* some drivers support Xrandr 1.2, not 1.3 */
-		ret = gcm_device_xrandr_apply_fallback (crtc_gamma, array->len);
-		if (!ret) {
-			g_set_error (error, 1, 0, "failed to set crtc gamma %p (%i) on %i", crtc_gamma, array->len, id);
-			goto out;
-		}
-	}
+	/* send to LUT */
+	ret = gcm_x11_output_set_gamma (output, array->len, red, green, blue, error);
+	if (!ret)
+		goto out;
 out:
-	if (crtc_gamma != NULL)
-		XRRFreeGamma (crtc_gamma);
+	g_free (red);
+	g_free (green);
+	g_free (blue);
 	if (array != NULL)
 		g_ptr_array_unref (array);
 	return ret;
@@ -477,18 +379,18 @@ gcm_device_xrandr_get_config_data (GcmDevice *device)
 gboolean
 gcm_device_xrandr_is_primary (GcmDeviceXrandr *device_xrandr)
 {
-	gint x, y;
+	guint x, y;
 	gboolean ret = FALSE;
-	GnomeRROutput *output;
+	GcmX11Output *output;
 
 	/* check we have an output */
-	output = gcm_screen_get_output_by_name (device_xrandr->priv->screen,
-						device_xrandr->priv->native_device, NULL);
+	output = gcm_x11_screen_get_output_by_name (device_xrandr->priv->screen,
+						    device_xrandr->priv->native_device, NULL);
 	if (output == NULL)
 		goto out;
 
 	/* is the monitor our primary monitor */
-	gnome_rr_output_get_position (output, &x, &y);
+	gcm_x11_output_get_position (output, &x, &y);
 	ret = (x == 0 && y == 0);
 out:
 	return ret;
@@ -505,9 +407,8 @@ gcm_device_xrandr_apply (GcmDevice *device, GError **error)
 	gboolean ret = FALSE;
 	GcmClut *clut = NULL;
 	GcmProfile *profile = NULL;
-	GnomeRRCrtc *crtc;
-	GnomeRROutput *output;
-	gint x, y;
+	GcmX11Output *output;
+	guint x, y;
 	const gchar *filename;
 	gchar *filename_systemwide = NULL;
 	gfloat gamma_adjust;
@@ -560,21 +461,11 @@ gcm_device_xrandr_apply (GcmDevice *device, GError **error)
 	}
 
 	/* check we have an output */
-	output = gcm_screen_get_output_by_name (priv->screen, output_name, error);
+	output = gcm_x11_screen_get_output_by_name (priv->screen, output_name, error);
 	if (output == NULL)
 		goto out;
-
-	/* get crtc size */
-	crtc = gnome_rr_output_get_crtc (output);
-	if (crtc == NULL) {
-		g_set_error (error, 1, 0, "failed to get crtc for device: %s", id);
-		goto out;
-	}
-
-	/* get gamma table size */
-	size = gcm_device_xrandr_get_gamma_size (device_xrandr, crtc, error);
-	if (size == 0)
-		goto out;
+	priv->gamma_size = gcm_x11_output_get_gamma_size (output);
+	size = priv->gamma_size;
 
 	/* only set the CLUT if we're not seting the atom */
 	use_global = g_settings_get_boolean (priv->settings, GCM_SETTINGS_GLOBAL_DISPLAY_CORRECTION);
@@ -602,12 +493,12 @@ gcm_device_xrandr_apply (GcmDevice *device, GError **error)
 	}
 
 	/* actually set the gamma */
-	ret = gcm_device_xrandr_apply_for_crtc (device_xrandr, crtc, clut, error);
+	ret = gcm_device_xrandr_apply_for_output (device_xrandr, output, clut, error);
 	if (!ret)
 		goto out;
 
 	/* is the monitor our primary monitor */
-	gnome_rr_output_get_position (output, &x, &y);
+	gcm_x11_output_get_position (output, &x, &y);
 	leftmost_screen = (x == 0 && y == 0);
 
 	/* either remove the atoms or set them */
@@ -619,32 +510,32 @@ gcm_device_xrandr_apply (GcmDevice *device, GError **error)
 			goto out;
 
 		/* remove the output atom if there's nothing to show */
-		ret = gcm_xserver_remove_output_profile (priv->xserver, output_name, error);
+		ret = gcm_x11_output_remove_profile (output, error);
 		if (!ret)
 			goto out;
 
 		/* primary screen */
 		if (leftmost_screen) {
-			ret = gcm_xserver_remove_root_window_profile (priv->xserver, error);
+			ret = gcm_x11_screen_remove_profile (priv->screen, error);
 			if (!ret)
 				goto out;
-			ret = gcm_xserver_remove_protocol_version (priv->xserver, error);
+			ret = gcm_x11_screen_remove_protocol_version (priv->screen, error);
 			if (!ret)
 				goto out;
 		}
 	} else {
 		/* set the per-output and per screen profile atoms */
 		filename = gcm_profile_get_filename (profile);
-		ret = gcm_xserver_set_output_profile (priv->xserver, output_name, filename, error);
+		ret = gcm_x11_output_set_profile (output, filename, error);
 		if (!ret)
 			goto out;
 
 		/* primary screen */
 		if (leftmost_screen) {
-			ret = gcm_xserver_set_root_window_profile (priv->xserver, filename, error);
+			ret = gcm_x11_screen_set_profile (priv->screen, filename, error);
 			if (!ret)
 				goto out;
-			ret = gcm_xserver_set_protocol_version (priv->xserver,
+			ret = gcm_x11_screen_set_protocol_version (priv->screen,
 								GCM_ICC_PROFILE_IN_X_VERSION_MAJOR,
 								GCM_ICC_PROFILE_IN_X_VERSION_MINOR,
 								error);
@@ -674,9 +565,6 @@ gcm_device_xrandr_get_property (GObject *object, guint prop_id, GValue *value, G
 	case PROP_NATIVE_DEVICE:
 		g_value_set_string (value, priv->native_device);
 		break;
-	case PROP_XRANDR_FALLBACK:
-		g_value_set_boolean (value, priv->xrandr_fallback);
-		break;
 	case PROP_EISA_ID:
 		g_value_set_string (value, priv->eisa_id);
 		break;
@@ -735,14 +623,6 @@ gcm_device_xrandr_class_init (GcmDeviceXrandrClass *klass)
 	g_object_class_install_property (object_class, PROP_NATIVE_DEVICE, pspec);
 
 	/**
-	 * GcmDeviceXrandr:xrandr-fallback:
-	 */
-	pspec = g_param_spec_boolean ("xrandr-fallback", NULL, NULL,
-				      FALSE,
-				      G_PARAM_READABLE);
-	g_object_class_install_property (object_class, PROP_XRANDR_FALLBACK, pspec);
-
-	/**
 	 * GcmDeviceXrandr:eisa-id:
 	 */
 	pspec = g_param_spec_string ("eisa-id", NULL, NULL,
@@ -771,14 +651,12 @@ gcm_device_xrandr_init (GcmDeviceXrandr *device_xrandr)
 	device_xrandr->priv->native_device = NULL;
 	device_xrandr->priv->eisa_id = NULL;
 	device_xrandr->priv->edid_md5 = NULL;
-	device_xrandr->priv->xrandr_fallback = FALSE;
 	device_xrandr->priv->remove_atom = TRUE;
 	device_xrandr->priv->gamma_size = 0;
 	device_xrandr->priv->edid = gcm_edid_new ();
 	device_xrandr->priv->dmi = gcm_dmi_new ();
 	device_xrandr->priv->settings = g_settings_new (GCM_SETTINGS_SCHEMA);
-	device_xrandr->priv->screen = gcm_screen_new ();
-	device_xrandr->priv->xserver = gcm_xserver_new ();
+	device_xrandr->priv->screen = gcm_x11_screen_new ();
 }
 
 /**
@@ -797,7 +675,7 @@ gcm_device_xrandr_finalize (GObject *object)
 	g_object_unref (priv->dmi);
 	g_object_unref (priv->settings);
 	g_object_unref (priv->screen);
-	g_object_unref (priv->xserver);
+	g_object_unref (priv->screen);
 
 	G_OBJECT_CLASS (gcm_device_xrandr_parent_class)->finalize (object);
 }
diff --git a/src/gcm-device-xrandr.h b/src/gcm-device-xrandr.h
index 5d61525..58434be 100644
--- a/src/gcm-device-xrandr.h
+++ b/src/gcm-device-xrandr.h
@@ -23,9 +23,9 @@
 #define __GCM_DEVICE_XRANDR_H
 
 #include <glib-object.h>
-#include <libgnomeui/gnome-rr.h>
 
 #include "gcm-device.h"
+#include "gcm-x11-screen.h"
 
 G_BEGIN_DECLS
 
@@ -51,7 +51,7 @@ struct _GcmDeviceXrandrClass
 GType		 gcm_device_xrandr_get_type		(void);
 GcmDevice	*gcm_device_xrandr_new			(void);
 gboolean	 gcm_device_xrandr_set_from_output	(GcmDevice		*device,
-							 GnomeRROutput		*output,
+							 GcmX11Output		*output,
 							 GError			**error);
 void		 gcm_device_xrandr_set_remove_atom	(GcmDeviceXrandr	*device_xrandr,
 							 gboolean		 remove_atom);
diff --git a/src/gcm-inspect.c b/src/gcm-inspect.c
index 78f72a2..a399ba9 100644
--- a/src/gcm-inspect.c
+++ b/src/gcm-inspect.c
@@ -23,15 +23,14 @@
 
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
-#include <libgnomeui/gnome-rr.h>
 #include <locale.h>
 
 #include "egg-debug.h"
 
 #include "gcm-utils.h"
 #include "gcm-profile.h"
-#include "gcm-xserver.h"
-#include "gcm-screen.h"
+#include "gcm-x11-output.h"
+#include "gcm-x11-screen.h"
 
 /**
  * gcm_inspect_print_data_info:
@@ -76,10 +75,10 @@ gcm_inspect_show_x11_atoms (void)
 	guint8 *data = NULL;
 	guint8 *data_tmp;
 	gsize length;
-	GcmXserver *xserver = NULL;
-	GnomeRROutput **outputs;
+	GPtrArray *outputs;
+	GcmX11Output *output;
+	GcmX11Screen *screen = NULL;
 	guint i;
-	GcmScreen *screen = NULL;
 	const gchar *output_name;
 	gchar *title;
 	GError *error = NULL;
@@ -87,10 +86,16 @@ gcm_inspect_show_x11_atoms (void)
 	guint minor;
 
 	/* setup object to access X */
-	xserver = gcm_xserver_new ();
+	screen = gcm_x11_screen_new ();
+	ret = gcm_x11_screen_assign (screen, NULL, &error);
+	if (!ret) {
+		egg_warning ("failed to get outputs: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
 
 	/* get profile from XServer */
-	ret = gcm_xserver_get_root_window_profile_data (xserver, &data, &length, &error);
+	ret = gcm_x11_screen_get_profile_data (screen, &data, &length, &error);
 	if (!ret) {
 		egg_warning ("failed to get XServer profile data: %s", error->message);
 		g_error_free (error);
@@ -102,7 +107,7 @@ gcm_inspect_show_x11_atoms (void)
 	}
 
 	/* get profile from XServer */
-	ret = gcm_xserver_get_protocol_version (xserver, &major, &minor, &error);
+	ret = gcm_x11_screen_get_protocol_version (screen, &major, &minor, &error);
 	if (!ret) {
 		egg_warning ("failed to get XServer protocol version: %s", error->message);
 		g_error_free (error);
@@ -114,22 +119,22 @@ gcm_inspect_show_x11_atoms (void)
 	}
 
 	/* coldplug devices */
-	screen = gcm_screen_new ();
-	outputs = gcm_screen_get_outputs (screen, &error);
+	outputs = gcm_x11_screen_get_outputs (screen, &error);
 	if (outputs == NULL) {
 		ret = FALSE;
 		egg_warning ("failed to get outputs: %s", error->message);
 		g_error_free (error);
 		goto out;
 	}
-	for (i=0; outputs[i] != NULL; i++) {
+	for (i=0; i<outputs->len; i++) {
 
 		/* get output name */
-		output_name = gnome_rr_output_get_name (outputs[i]);
+		output = g_ptr_array_index (outputs, i);
+		output_name = gcm_x11_output_get_name (output);
 		title = g_strdup_printf (_("Output profile '%s':"), output_name);
 
 		/* get profile from XServer */
-		ret = gcm_xserver_get_output_profile_data (xserver, output_name, &data_tmp, &length, &error);
+		ret = gcm_x11_output_get_profile_data (output, &data_tmp, &length, &error);
 		if (!ret) {
 			egg_warning ("failed to get output profile data: %s", error->message);
 			/* TRANSLATORS: this is when the profile has not been set */
@@ -148,8 +153,6 @@ out:
 	g_free (data);
 	if (screen != NULL)
 		g_object_unref (screen);
-	if (xserver != NULL)
-		g_object_unref (xserver);
 	return ret;
 }
 
@@ -567,9 +570,9 @@ main (int argc, char **argv)
 	GOptionContext *context;
 
 	const GOptionEntry options[] = {
-		{ "x11", 'x', 0, G_OPTION_ARG_NONE, &x11,
+		{ "xserver", 'x', 0, G_OPTION_ARG_NONE, &x11,
 			/* TRANSLATORS: command line option */
-			_("Show X11 properties"), NULL },
+			_("Show xserver properties"), NULL },
 		{ "device", '\0', 0, G_OPTION_ARG_STRING, &device_id,
 			/* TRANSLATORS: command line option */
 			_("Get the profiles for a specific device"), NULL },
diff --git a/tools/Makefile.am b/tools/Makefile.am
index ac3b186..bf961f1 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -25,11 +25,11 @@ INCLUDES =						\
 noinst_PROGRAMS =					\
 	gcm-dump-profile				\
 	gcm-dump-sensor					\
+	gcm-dump-edid					\
 	gcm-fix-profile					\
 	gcm-ddc-util					\
 	gcm-sensor-example
 
-if FALSE
 gcm_dump_edid_SOURCES =					\
 	gcm-dump-edid.c
 
@@ -39,7 +39,6 @@ gcm_dump_edid_LDADD =					\
 
 gcm_dump_edid_CFLAGS =					\
 	$(WARNINGFLAGS_C)
-endif
 
 gcm_dump_profile_SOURCES =				\
 	gcm-dump-profile.c
diff --git a/tools/gcm-dump-edid.c b/tools/gcm-dump-edid.c
index e39e8ef..eaeb778 100644
--- a/tools/gcm-dump-edid.c
+++ b/tools/gcm-dump-edid.c
@@ -23,13 +23,10 @@
 
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
-#include <libgnomeui/gnome-rr.h>
 #include <locale.h>
 
-#include "egg-debug.h"
-
-#include "gcm-screen.h"
 #include "gcm-edid.h"
+#include "gcm-x11-screen.h"
 
 /**
  * gcm_dump_edid_filename:
@@ -84,7 +81,7 @@ gcm_dump_edid_filename (const gchar *filename)
 	width = gcm_edid_get_width (edid);
 	height = gcm_edid_get_height (edid);
 	if (width != 0)
-		g_print ("  Size: %ix%i\n", "", width, height);
+		g_print ("  Size: %ix%i\n", width, height);
 	gamma = gcm_edid_get_gamma (edid);
 	if (gamma > 0.0f)
 		g_print ("  Gamma: %f\n", gamma);
@@ -96,12 +93,30 @@ out:
 }
 
 /**
+ * gcm_dump_edid_alphanum_lcase:
+ **/
+static void
+gcm_dump_edid_alphanum_lcase (gchar *data)
+{
+	guint i;
+
+	g_return_if_fail (data != NULL);
+
+	/* replace unsafe chars, and make lowercase */
+	for (i=0; data[i] != '\0'; i++) {
+		if (!g_ascii_isalnum (data[i]))
+			data[i] = '_';
+		data[i] = g_ascii_tolower (data[i]);
+	}
+}
+
+/**
  * main:
  **/
 int
 main (int argc, char **argv)
 {
-	const guint8 *data;
+	guint8 *data = NULL;
 	gboolean ret;
 	gchar *output_name;
 	gchar *filename;
@@ -109,8 +124,9 @@ main (int argc, char **argv)
 	guint i;
 	guint retval = 0;
 	GError *error = NULL;
-	GnomeRROutput **outputs;
-	GcmScreen *screen = NULL;
+	GPtrArray *outputs;
+	GcmX11Output *output;
+	GcmX11Screen *screen = NULL;
 	GOptionContext *context;
 
 	const GOptionEntry options[] = {
@@ -129,7 +145,6 @@ main (int argc, char **argv)
 
 	context = g_option_context_new ("gnome-color-manager dump edid program");
 	g_option_context_add_main_entries (context, options, NULL);
-	g_option_context_add_group (context, egg_debug_get_option_group ());
 	g_option_context_add_group (context, gtk_get_option_group (TRUE));
 	g_option_context_parse (context, &argc, &argv, NULL);
 	g_option_context_free (context);
@@ -144,28 +159,29 @@ main (int argc, char **argv)
 	}
 
 	/* coldplug devices */
-	screen = gcm_screen_new ();
-	outputs = gcm_screen_get_outputs (screen, &error);
-	if (screen == NULL) {
-		egg_warning ("failed to get outputs: %s", error->message);
+	screen = gcm_x11_screen_new ();
+	outputs = gcm_x11_screen_get_outputs (screen, &error);
+	if (outputs == NULL) {
+		g_print ("Failed to get outputs: %s\n", error->message);
 		retval = 1;
 		goto out;
 	}
-	for (i=0; outputs[i] != NULL; i++) {
+	for (i=0; i<outputs->len; i++) {
 
 		/* only try to get edid if connected */
-		ret = gnome_rr_output_is_connected (outputs[i]);
+		output = g_ptr_array_index (outputs, i);
+		ret = gcm_x11_output_get_connected (output);
 		if (!ret)
 			continue;
 
 		/* get data */
-		data = gnome_rr_output_get_edid_data (outputs[i]);
-		if (data == NULL)
+		ret = gcm_x11_output_get_edid_data (output, &data, NULL, NULL);
+		if (!ret)
 			continue;
 
 		/* get output name */
-		output_name = g_strdup (gnome_rr_output_get_name (outputs[i]));
-		gcm_utils_alphanum_lcase (output_name);
+		output_name = g_strdup (gcm_x11_output_get_name (output));
+		gcm_dump_edid_alphanum_lcase (output_name);
 
 		/* get suitable filename */
 		filename = g_strdup_printf ("./%s.bin", output_name);
@@ -173,16 +189,17 @@ main (int argc, char **argv)
 		/* save to disk */
 		ret = g_file_set_contents (filename, (const gchar *) data, 0x80, &error);
 		if (ret) {
-			g_print "Saved %i bytes to %s", 128, filename);
-			g_print ("\n");
+			g_print ("Saved %i bytes to %s\n", 128, filename);
 			gcm_dump_edid_filename (filename);
 		} else {
 			g_print ("Failed to save EDID to %s: %s\n", filename, error->message);
 			/* non-fatal */
 			g_clear_error (&error);
 		}
+		g_free (data);
 		g_free (filename);
 	}
+	g_ptr_array_unref (outputs);
 out:
 	g_strfreev (files);
 	if (screen != NULL)



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