Blob Blame History Raw
diff -up gnome-desktop-2.21.90/configure.in.add-randr-12 gnome-desktop-2.21.90/configure.in
--- gnome-desktop-2.21.90/configure.in.add-randr-12	2008-01-27 18:48:13.000000000 -0500
+++ gnome-desktop-2.21.90/configure.in	2008-01-31 16:44:28.000000000 -0500
@@ -51,10 +51,10 @@ AC_SUBST(GNOME_MICRO)
 AC_SUBST(GNOME_DISTRIBUTOR)
 AC_SUBST(GNOME_DATE)
 
-GNOME_COMMON_INIT
-GNOME_DEBUG_CHECK
-GNOME_COMPILE_WARNINGS([maximum])
-GNOME_MAINTAINER_MODE_DEFINES
+#GNOME_COMMON_INIT
+#GNOME_DEBUG_CHECK
+#GNOME_COMPILE_WARNINGS([maximum])
+#GNOME_MAINTAINER_MODE_DEFINES
 
 # As a special favour for vuntz, support --disable-deprecations
 
diff -up gnome-desktop-2.21.90/libgnome-desktop/libgnomeui/Makefile.am.add-randr-12 gnome-desktop-2.21.90/libgnome-desktop/libgnomeui/Makefile.am
--- gnome-desktop-2.21.90/libgnome-desktop/libgnomeui/Makefile.am.add-randr-12	2008-01-27 18:44:20.000000000 -0500
+++ gnome-desktop-2.21.90/libgnome-desktop/libgnomeui/Makefile.am	2008-01-31 16:44:28.000000000 -0500
@@ -2,4 +2,5 @@ libgnomeui_desktopdir = $(includedir)/gn
 libgnomeui_desktop_HEADERS = \
 	gnome-ditem-edit.h \
 	gnome-hint.h       \
-	gnome-bg.h
+	gnome-bg.h         \
+	randrwrap.h
diff -up /dev/null gnome-desktop-2.21.90/libgnome-desktop/libgnomeui/randrwrap.h
--- /dev/null	2008-01-30 11:34:25.225700292 -0500
+++ gnome-desktop-2.21.90/libgnome-desktop/libgnomeui/randrwrap.h	2008-02-04 08:33:51.000000000 -0500
@@ -0,0 +1,100 @@
+#ifndef I_KNOW_THIS_IS_UNSTABLE_AND_ONLY_IN_FEDORA
+#error This is not yet for general consumption.
+#endif
+
+#ifndef RANDR_WRAP_H
+#define RANDR_WRAP_H
+
+#include <glib.h>
+#include <gdk/gdk.h>
+
+typedef struct RWScreen RWScreen;
+typedef struct RWOutput RWOutput;
+typedef struct RWCrtc RWCrtc;
+typedef struct RWMode RWMode;
+
+typedef void (* RWScreenChanged) (RWScreen *screen, gpointer data);
+
+typedef enum
+{
+    RW_ROTATION_0 =	(1 << 0),
+    RW_ROTATION_90 =	(1 << 1),
+    RW_ROTATION_180 =	(1 << 2),
+    RW_ROTATION_270 =	(1 << 3),
+    RW_REFLECT_X =	(1 << 4),
+    RW_REFLECT_Y =	(1 << 5)
+} RWRotation;
+
+/* RWScreen */
+RWScreen *    rw_screen_new                (GdkScreen       *screen,
+					    RWScreenChanged  callback,
+					    gpointer         data);
+RWOutput **   rw_screen_list_outputs       (RWScreen        *screen);
+RWCrtc **     rw_screen_list_crtcs         (RWScreen        *screen);
+RWMode **     rw_screen_list_modes         (RWScreen        *screen);
+void          rw_screen_set_size           (RWScreen        *screen,
+					    int		     width,
+					    int              height,
+					    int              mm_width,
+					    int              mm_height);
+RWCrtc *      rw_screen_get_crtc_by_id     (RWScreen        *screen,
+					    guint32          id);
+void          rw_screen_refresh            (RWScreen        *screen);
+RWOutput *    rw_screen_get_output_by_id   (RWScreen        *screen,
+					    guint32          id);
+RWOutput *    rw_screen_get_output_by_name (RWScreen        *screen,
+					    const char      *name);
+void	      rw_screen_get_ranges         (RWScreen	    *screen,
+					    int		    *min_width,
+					    int		    *max_width,
+					    int             *min_height,
+					    int		    *max_height);
+
+/* RWOutput */
+guint32       rw_output_get_id             (RWOutput        *output);
+const char *  rw_output_get_name           (RWOutput        *output);
+gboolean      rw_output_is_connected       (RWOutput        *output);
+int           rw_output_get_size_inches    (RWOutput        *output);
+int           rw_output_get_width_mm       (RWOutput        *outout);
+int           rw_output_get_height_mm      (RWOutput        *output);
+const guint8 *rw_output_get_edid_data      (RWOutput        *output);
+RWCrtc **     rw_output_get_possible_crtcs (RWOutput        *output);
+RWMode *      rw_output_get_current_mode   (RWOutput        *output);
+RWCrtc *      rw_output_get_crtc           (RWOutput        *output);
+void          rw_output_get_position       (RWOutput        *output,
+					    int             *x,
+					    int             *y);
+gboolean      rw_output_can_clone          (RWOutput        *output,
+					    RWOutput        *clone);
+RWMode **     rw_output_list_modes         (RWOutput        *output);
+RWMode *      rw_output_get_preferred_mode (RWOutput        *output);
+gboolean      rw_output_supports_mode      (RWOutput        *output,
+					    RWMode          *mode);
+
+/* RWMode */
+guint32	      rw_mode_get_id               (RWMode          *mode);
+guint	      rw_mode_get_width		   (RWMode          *mode);
+guint         rw_mode_get_height           (RWMode          *mode);
+int           rw_mode_get_freq             (RWMode          *mode);
+
+/* RWCrtc */
+guint32       rw_crtc_get_id               (RWCrtc          *crtc);
+gboolean      rw_crtc_set_config	   (RWCrtc          *crtc,
+					    int		     x,
+					    int		     y,
+					    RWMode	    *mode,
+					    RWRotation	     rotation,
+					    RWOutput	   **outputs,
+				  	    int              n_outputs);
+gboolean      rw_crtc_can_drive_output     (RWCrtc          *crtc,
+					    RWOutput        *output);
+RWMode *      rw_crtc_get_current_mode     (RWCrtc          *crtc);
+void          rw_crtc_get_position         (RWCrtc          *crtc,
+					    int             *x,
+					    int             *y);
+RWRotation    rw_crtc_get_current_rotation (RWCrtc          *crtc);
+RWRotation    rw_crtc_get_rotations        (RWCrtc          *crtc);
+gboolean      rw_crtc_supports_rotation    (RWCrtc	    *crtc,
+					    RWRotation	     rotation);
+
+#endif
diff -up /dev/null gnome-desktop-2.21.90/libgnome-desktop/randrwrap.c
--- /dev/null	2008-01-30 11:34:25.225700292 -0500
+++ gnome-desktop-2.21.90/libgnome-desktop/randrwrap.c	2008-02-04 08:33:51.000000000 -0500
@@ -0,0 +1,1042 @@
+#define I_KNOW_THIS_IS_UNSTABLE_AND_ONLY_IN_FEDORA
+#include "libgnomeui/randrwrap.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>
+
+struct RWScreen
+{
+    GdkScreen *		gdk_screen;
+    GdkWindow *		gdk_root;
+    Display *		xdisplay;
+    Screen *		xscreen;
+    Window		xroot;
+
+    int			min_width;
+    int			max_width;
+    int			min_height;
+    int			max_height;
+    
+    RWScreenChanged	callback;
+    gpointer		data;
+
+    XRRScreenResources *resources;
+    
+    RWOutput **		outputs;
+    RWCrtc **		crtcs;
+    RWMode **		modes;
+    
+    int			randr_event_base;
+};
+
+struct RWOutput
+{
+    RWScreen *		screen;
+    RROutput		id;
+    
+    char *		name;
+    RWCrtc *		current_crtc;
+    gboolean		connected;
+    gulong		width_mm;
+    gulong		height_mm;
+    RWCrtc **		possible_crtcs;
+    RWOutput **		clones;
+    RWMode **		modes;
+    int			n_preferred;
+    guint8 *		edid_data;
+};
+
+struct RWCrtc
+{
+    RWScreen *		screen;
+    RRCrtc		id;
+    
+    RWMode *		current_mode;
+    RWOutput **		current_outputs;
+    RWOutput **		possible_outputs;
+    int			x;
+    int			y;
+
+    RWRotation		current_rotation;
+    RWRotation		rotations;
+};
+
+struct RWMode
+{
+    RWScreen *		screen;
+    RRMode		id;
+    char *		name;
+    int			width;
+    int			height;
+    int			freq;		/* in mHz */
+};
+
+/* RWCrtc */
+static RWCrtc *  crtc_new             (RWScreen           *screen,
+				       RRCrtc              id);
+static void      crtc_free            (RWCrtc             *crtc);
+static void      crtc_initialize      (RWCrtc             *crtc,
+				       XRRScreenResources *res);
+
+
+/* RWOutput */
+static RWOutput *output_new           (RWScreen           *screen,
+				       RROutput            id);
+static void      output_initialize    (RWOutput           *output,
+				       XRRScreenResources *res);
+static void      output_free          (RWOutput           *output);
+
+
+/* RWMode */
+static RWMode *  mode_new             (RWScreen           *screen,
+				       RRMode              id);
+static void      mode_initialize      (RWMode             *mode,
+				       XRRModeInfo        *info);
+static void      mode_free            (RWMode             *mode);
+
+
+/* Screen */
+static RWOutput *
+rw_output_by_id (RWScreen *screen, RROutput id)
+{
+    RWOutput **output;
+    
+    for (output = screen->outputs; *output; ++output)
+    {
+	if ((*output)->id == id)
+	    return *output;
+    }
+    
+    return NULL;
+}
+
+static RWCrtc *
+crtc_by_id (RWScreen *screen, RRCrtc id)
+{
+    RWCrtc **crtc;
+    
+    for (crtc = screen->crtcs; *crtc; ++crtc)
+    {
+	if ((*crtc)->id == id)
+	    return *crtc;
+    }
+    
+    return NULL;
+}
+
+static RWMode *
+mode_by_id (RWScreen *screen, RRMode id)
+{
+    RWMode **mode;
+    
+    for (mode = screen->modes; *mode; ++mode)
+    {
+	if ((*mode)->id == id)
+	    return *mode;
+    }
+    
+    return NULL;
+}
+
+static void
+screen_free_resources (RWScreen *screen)
+{
+    RWOutput **output;
+    RWCrtc **crtc;
+    RWMode **mode;
+
+    if (screen->resources)
+    {
+	XRRFreeScreenResources (screen->resources);
+
+	screen->resources = NULL;
+    }
+    
+    if (screen->outputs)
+    {
+	for (output = screen->outputs; *output; ++output)
+	    output_free (*output);
+	g_free (screen->outputs);
+    }
+    
+    if (screen->crtcs)
+    {
+	for (crtc = screen->crtcs; *crtc; ++crtc)
+	    crtc_free (*crtc);
+	g_free (screen->crtcs);
+    }
+    
+    if (screen->modes)
+    {
+	for (mode = screen->modes; *mode; ++mode)
+	    mode_free (*mode);
+	g_free (screen->modes);
+    }
+}
+
+static void
+screen_update (RWScreen *screen,
+	       gboolean  call_callback)
+{
+    XRRScreenResources *resources;
+
+    g_return_if_fail (screen != NULL);
+    
+    XRRGetScreenSizeRange (screen->xdisplay, screen->xroot,
+			   &(screen->min_width),
+			   &(screen->min_height),
+			   &(screen->max_width),
+			   &(screen->max_height));
+
+#if 0
+    g_print ("ranges: %d - %d; %d - %d\n",
+	     screen->min_width, screen->max_width,
+	     screen->min_height, screen->max_height);
+#endif
+    
+    resources = XRRGetScreenResources (screen->xdisplay, screen->xroot);
+    
+    if (resources)
+    {
+	int i;
+	GPtrArray *a;
+	RWCrtc **crtc;
+	RWOutput **output;
+
+	screen_free_resources (screen);
+
+	screen->resources = resources;
+	
+	/* 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)
+	{
+	    RWCrtc *crtc = crtc_new (screen, resources->crtcs[i]);
+	    
+	    g_ptr_array_add (a, crtc);
+	}
+	g_ptr_array_add (a, NULL);
+	screen->crtcs = (RWCrtc **)g_ptr_array_free (a, FALSE);
+	
+	a = g_ptr_array_new ();
+	for (i = 0; i < resources->noutput; ++i)
+	{
+	    RWOutput *output = output_new (screen, resources->outputs[i]);
+	    
+	    g_ptr_array_add (a, output);
+	}
+	g_ptr_array_add (a, NULL);
+	screen->outputs = (RWOutput **)g_ptr_array_free (a, FALSE);
+	
+	a = g_ptr_array_new ();
+	for (i = 0;  i < resources->nmode; ++i)
+	{
+	    RWMode *mode = mode_new (screen, resources->modes[i].id);
+	    
+	    g_ptr_array_add (a, mode);
+	}
+	g_ptr_array_add (a, NULL);
+	screen->modes = (RWMode **)g_ptr_array_free (a, FALSE);
+	
+	/* Initialize */
+	for (crtc = screen->crtcs; *crtc; ++crtc)
+	    crtc_initialize (*crtc, resources);
+	
+	for (output = screen->outputs; *output; ++output)
+	    output_initialize (*output, resources);
+	
+	for (i = 0; i < resources->nmode; ++i)
+	{
+	    RWMode *mode = mode_by_id (screen, resources->modes[i].id);
+	    
+	    mode_initialize (mode, &(resources->modes[i]));
+	}
+    }
+    
+    if (call_callback && screen->callback)
+	screen->callback (screen, screen->data);
+}
+
+static GdkFilterReturn
+screen_on_event (GdkXEvent *xevent,
+		 GdkEvent *event,
+		 gpointer data)
+{
+    RWScreen *screen = data;
+    XEvent *e = xevent;
+    
+    if (e->type - screen->randr_event_base == RRNotify)
+    {
+	/* FIXME: we probably need to be more discriminating in
+	 * what causes 'changed' events
+	 */
+	screen_update (screen, TRUE);
+    }
+    
+    /* Pass the event on to GTK+ */
+    return GDK_FILTER_CONTINUE;
+}
+
+RWScreen *
+rw_screen_new (GdkScreen *gdk_screen,
+	       RWScreenChanged callback,
+	       gpointer data)
+{
+    Display *dpy = GDK_SCREEN_XDISPLAY (gdk_screen);
+    int event_base;
+    int ignore;
+    
+    if (XRRQueryExtension (dpy, &event_base, &ignore))
+    {
+	RWScreen *screen = g_new0 (RWScreen, 1);
+	
+	screen->gdk_screen = gdk_screen;
+	screen->gdk_root = gdk_screen_get_root_window (gdk_screen);
+	screen->xroot = gdk_x11_drawable_get_xid (screen->gdk_root);
+	screen->xdisplay = dpy;
+	screen->xscreen = gdk_x11_screen_get_xscreen (screen->gdk_screen);
+	
+	screen->callback = callback;
+	screen->data = data;
+	
+	screen->randr_event_base = event_base;
+	
+	screen->outputs = NULL;
+	screen->crtcs = NULL;
+	screen->modes = NULL;
+	
+	screen_update (screen, FALSE);
+	
+	XRRSelectInput (screen->xdisplay,
+			screen->xroot,
+			RRScreenChangeNotifyMask	|
+			RRCrtcChangeNotifyMask		|
+			RROutputPropertyNotifyMask);
+	
+	gdk_x11_register_standard_event_type (
+	    gdk_screen_get_display (gdk_screen),
+	    event_base,
+	    RRNotify + 1);
+
+	gdk_window_add_filter (screen->gdk_root, screen_on_event, screen);
+	return screen;
+    }
+    
+    return NULL;
+}
+
+void
+rw_screen_set_size (RWScreen *screen,
+		    int	      width,
+		    int       height,
+		    int       mm_width,
+		    int       mm_height)
+{
+    g_return_if_fail (screen != NULL);
+    
+    XRRSetScreenSize (screen->xdisplay, screen->xroot,
+		      width, height, mm_width, mm_height);
+}
+
+void
+rw_screen_get_ranges (RWScreen	*screen,
+		      int	*min_width,
+		      int	*max_width,
+		      int       *min_height,
+		      int	*max_height)
+{
+    g_return_if_fail (screen != NULL);
+
+    if (min_width)
+	*min_width = screen->min_width;
+
+    if (max_width)
+	*max_width = screen->max_width;
+
+    if (min_height)
+	*min_height = screen->min_height;
+
+    if (max_height)
+	*max_height = screen->max_height;
+}
+
+void
+rw_screen_refresh (RWScreen *screen)
+{
+    screen_update (screen, TRUE);
+}
+
+RWMode **
+rw_screen_list_modes (RWScreen *screen)
+{
+    return screen->modes;
+}
+
+RWCrtc **
+rw_screen_list_crtcs (RWScreen *screen)
+{
+    return screen->crtcs;
+}
+
+RWOutput **
+rw_screen_list_outputs (RWScreen *screen)
+{
+    return screen->outputs;
+}
+
+RWCrtc *
+rw_screen_get_crtc_by_id (RWScreen *screen,
+			  guint32   id)
+{
+    int i;
+
+    for (i = 0; screen->crtcs[i] != NULL; ++i)
+    {
+	if (screen->crtcs[i]->id == id)
+	    return screen->crtcs[i];
+    }
+
+    return NULL;
+}
+
+RWOutput *
+rw_screen_get_output_by_id (RWScreen *screen,
+			    guint32 id)
+{
+    int i;
+
+    for (i = 0; screen->outputs[i] != NULL; ++i)
+    {
+	if (screen->outputs[i]->id == id)
+	    return screen->outputs[i];
+    }
+
+    return NULL;
+}
+
+/* RWOutput */
+static RWOutput *
+output_new (RWScreen *screen, RROutput id)
+{
+    RWOutput *output = g_new0 (RWOutput, 1);
+    
+    output->id = id;
+    output->screen = screen;
+    
+    return output;
+}
+
+static guint8 *
+get_property (Display *dpy,
+	      RROutput output,
+	      Atom atom,
+	      int *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 (RWOutput *output)
+{
+    Atom edid_atom = XInternAtom (output->screen->xdisplay, "EDID_DATA", FALSE);
+    guint8 *result;
+    int len;
+
+    result = get_property (output->screen->xdisplay, output->id, edid_atom, &len);
+
+    if (result)
+    {
+	if (len == 128)
+	    return result;
+	else
+	    g_free (result);
+    }
+
+    return NULL;
+}
+
+static void
+output_initialize (RWOutput *output, XRRScreenResources *res)
+{
+    XRROutputInfo *info = XRRGetOutputInfo (
+	output->screen->xdisplay, res, output->id);
+    GPtrArray *a;
+    int i;
+    
+    if (!info)
+    {
+	/* FIXME */
+	return;
+    }
+    
+    output->name = g_strdup (info->name); /* FIXME: what is nameLen used for? */
+    output->current_crtc = crtc_by_id (output->screen, info->crtc);
+    output->width_mm = info->mm_width;
+    output->height_mm = info->mm_height;
+    output->connected = (info->connection == RR_Connected);
+    
+    /* Possible crtcs */
+    a = g_ptr_array_new ();
+    
+    for (i = 0; i < info->ncrtc; ++i)
+    {
+	RWCrtc *crtc = crtc_by_id (output->screen, info->crtcs[i]);
+	
+	if (crtc)
+	    g_ptr_array_add (a, crtc);
+    }
+    g_ptr_array_add (a, NULL);
+    output->possible_crtcs = (RWCrtc **)g_ptr_array_free (a, FALSE);
+    
+    /* Clones */
+    a = g_ptr_array_new ();
+    for (i = 0; i < info->nclone; ++i)
+    {
+	RWOutput *output = rw_output_by_id (output->screen, info->clones[i]);
+	
+	if (output)
+	    g_ptr_array_add (a, output);
+    }
+    g_ptr_array_add (a, NULL);
+    output->clones = (RWOutput **)g_ptr_array_free (a, FALSE);
+    
+    /* Modes */
+    a = g_ptr_array_new ();
+    for (i = 0; i < info->nmode; ++i)
+    {
+	RWMode *mode = mode_by_id (output->screen, info->modes[i]);
+	
+	if (mode)
+	    g_ptr_array_add (a, mode);
+    }
+    g_ptr_array_add (a, NULL);
+    output->modes = (RWMode **)g_ptr_array_free (a, FALSE);
+
+    output->n_preferred = info->npreferred;
+    
+    /* Edid data */
+    output->edid_data = read_edid_data (output);
+    
+    XRRFreeOutputInfo (info);
+}
+
+static void
+output_free (RWOutput *output)
+{
+    g_free (output);
+}
+
+guint32
+rw_output_get_id (RWOutput *output)
+{
+    return output->id;
+}
+
+const guint8 *
+rw_output_get_edid_data (RWOutput *output)
+{
+    return output->edid_data;
+}
+
+RWOutput *
+rw_screen_get_output_by_name (RWScreen        *screen,
+			      const char      *name)
+{
+    int i;
+
+    for (i = 0; screen->outputs[i] != NULL; ++i)
+    {
+	RWOutput *output = screen->outputs[i];
+
+	if (strcmp (output->name, name) == 0)
+	    return output;
+    }
+
+    return NULL;
+}
+
+RWCrtc *
+rw_output_get_crtc (RWOutput *output)
+{
+    return output->current_crtc;
+}
+
+RWMode *
+rw_output_get_current_mode (RWOutput *output)
+{
+    RWCrtc *crtc;
+
+    g_return_val_if_fail (output != NULL, NULL);
+    
+    if ((crtc = rw_output_get_crtc (output)))
+	return rw_crtc_get_current_mode (crtc);
+
+    return NULL;
+}
+
+void
+rw_output_get_position (RWOutput        *output,
+			int             *x,
+			int             *y)
+{
+    RWCrtc *crtc;
+
+    g_return_if_fail (output != NULL);
+    
+    if ((crtc = rw_output_get_crtc (output)))
+	rw_crtc_get_position (crtc, x, y);
+}
+
+const char *
+rw_output_get_name (RWOutput *output)
+{
+    return output->name;
+}
+
+int
+rw_output_get_width_mm (RWOutput *output)
+{
+    return output->width_mm;
+}
+
+int
+rw_output_get_height_mm (RWOutput *output)
+{
+    return output->height_mm;
+}
+
+RWMode *
+rw_output_get_preferred_mode (RWOutput *output)
+{
+    if (output->n_preferred)
+	return output->modes[0];
+
+    return NULL;
+}
+
+RWMode **
+rw_output_list_modes (RWOutput *output)
+{
+    return output->modes;
+}
+
+gboolean
+rw_output_is_connected (RWOutput *output)
+{
+    return output->connected;
+}
+
+gboolean
+rw_output_supports_mode (RWOutput *output,
+			 RWMode   *mode)
+{
+    int i;
+
+    g_return_val_if_fail (output != NULL, FALSE);
+    g_return_val_if_fail (mode != NULL, FALSE);
+
+    for (i = 0; output->modes[i] != NULL; ++i)
+    {
+	if (output->modes[i] == mode)
+	    return TRUE;
+    }
+
+    return FALSE;
+}
+
+gboolean
+rw_output_can_clone (RWOutput *output,
+		     RWOutput *clone)
+{
+    int i;
+
+    g_return_val_if_fail (output != NULL, FALSE);
+    g_return_val_if_fail (clone != NULL, FALSE);
+
+    for (i = 0; output->clones[i] != NULL; ++i)
+    {
+	if (output->clones[i] == clone)
+	    return TRUE;
+    }
+
+    return FALSE;
+}
+
+/* RWCrtc */
+typedef struct
+{
+    Rotation xrot;
+    RWRotation rot;
+} RotationMap;
+static const RotationMap rotation_map[] =
+{
+    { RR_Rotate_0, RW_ROTATION_0 },
+    { RR_Rotate_90, RW_ROTATION_90 },
+    { RR_Rotate_180, RW_ROTATION_180 },
+    { RR_Rotate_270, RW_ROTATION_270 },
+    { RR_Reflect_X, RW_REFLECT_X },
+    { RR_Reflect_Y, RW_REFLECT_Y },
+};
+
+static RWRotation
+rw_rotation_from_xrotation (Rotation r)
+{
+    int i;
+    RWRotation 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 (RWRotation 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
+rw_crtc_set_config (RWCrtc    *crtc,
+		    int        x,
+		    int        y,
+		    RWMode    *mode,
+		    RWRotation rotation,
+		    RWOutput **outputs,
+		    int        n_outputs)
+{
+    RWScreen *screen;
+    GArray *output_ids;
+    int i;
+
+    g_return_val_if_fail (crtc != NULL, FALSE);
+    g_return_val_if_fail (mode != NULL || outputs == NULL || n_outputs == 0, FALSE);
+
+    screen = crtc->screen;
+
+    if (mode)
+    {
+#if 0
+	g_print ("x: %d mode->width: %d max width: %d\n", x, mode->width, screen->max_width);
+#endif
+	g_return_val_if_fail (x + mode->width <= screen->max_width, FALSE);
+	g_return_val_if_fail (y + mode->height <= screen->max_height, 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);
+    }
+    
+    XRRSetCrtcConfig (screen->xdisplay, screen->resources, crtc->id,
+		      CurrentTime, 
+		      x, y,
+		      mode? mode->id : None,
+		      xrotation_from_rotation (rotation),
+		      (RROutput *)output_ids->data,
+		      output_ids->len);
+
+    g_array_free (output_ids, TRUE);
+    
+    return TRUE;
+}
+
+RWMode *
+rw_crtc_get_current_mode (RWCrtc *crtc)
+{
+    g_return_val_if_fail (crtc != NULL, NULL);
+
+    return crtc->current_mode;
+}
+
+guint32
+rw_crtc_get_id (RWCrtc *crtc)
+{
+    g_return_val_if_fail (crtc != NULL, 0);
+
+    return crtc->id;
+}
+
+gboolean
+rw_crtc_can_drive_output (RWCrtc   *crtc,
+			  RWOutput *output)
+{
+    int i;
+
+    g_return_val_if_fail (crtc != NULL, FALSE);
+    g_return_val_if_fail (output != NULL, FALSE);
+    
+    for (i = 0; crtc->possible_outputs[i] != NULL; ++i)
+    {
+	if (crtc->possible_outputs[i] == output)
+	    return TRUE;
+    }
+
+    return FALSE;
+}
+
+/* FIXME: merge with get_mode()? */
+void
+rw_crtc_get_position (RWCrtc          *crtc,
+		      int             *x,
+		      int             *y)
+{
+    g_return_if_fail (crtc != NULL);
+    
+    if (x)
+	*x = crtc->x;
+
+    if (y)
+	*y = crtc->y;
+}
+
+/* FIXME: merge with get_mode()? */
+RWRotation
+rw_crtc_get_current_rotation (RWCrtc *crtc)
+{
+    return crtc->current_rotation;
+}
+
+RWRotation
+rw_crtc_get_rotations (RWCrtc *crtc)
+{
+    return crtc->rotations;
+}
+
+gboolean
+rw_crtc_supports_rotation (RWCrtc *   crtc,
+			   RWRotation rotation)
+{
+    return (crtc->rotations & rotation);
+}
+
+static RWCrtc *
+crtc_new (RWScreen *screen, RROutput id)
+{
+    RWCrtc *crtc = g_new0 (RWCrtc, 1);
+    
+    crtc->id = id;
+    crtc->screen = screen;
+    
+    return crtc;
+}
+
+static void
+crtc_initialize (RWCrtc *crtc, XRRScreenResources *res)
+{
+    XRRCrtcInfo *info = XRRGetCrtcInfo (crtc->screen->xdisplay, res, crtc->id);
+    GPtrArray *a;
+    int i;
+    
+    if (!info)
+    {
+	/* FIXME: We need to reaquire the screen resources */
+	return;
+    }
+    
+    /* RWMode */
+    crtc->current_mode = mode_by_id (crtc->screen, info->mode);
+    
+    crtc->x = info->x;
+    crtc->y = info->y;
+    
+    /* Current outputs */
+    a = g_ptr_array_new ();
+    for (i = 0; i < info->noutput; ++i)
+    {
+	RWOutput *output = rw_output_by_id (crtc->screen, info->outputs[i]);
+	
+	if (output)
+	    g_ptr_array_add (a, output);
+    }
+    g_ptr_array_add (a, NULL);
+    crtc->current_outputs = (RWOutput **)g_ptr_array_free (a, FALSE);
+    
+    /* Possible outputs */
+    a = g_ptr_array_new ();
+    for (i = 0; i < info->npossible; ++i)
+    {
+	RWOutput *output = rw_output_by_id (crtc->screen, info->possible[i]);
+	
+	if (output)
+	    g_ptr_array_add (a, output);
+    }
+    g_ptr_array_add (a, NULL);
+    crtc->possible_outputs = (RWOutput **)g_ptr_array_free (a, FALSE);
+
+    /* Rotations */
+    crtc->current_rotation = rw_rotation_from_xrotation (info->rotation);
+    crtc->rotations = rw_rotation_from_xrotation (info->rotations);
+
+    XRRFreeCrtcInfo (info);
+}
+
+static void
+crtc_free (RWCrtc *crtc)
+{
+    g_free (crtc->current_outputs);
+    g_free (crtc->possible_outputs);
+    g_free (crtc);
+}
+
+/* RWMode */
+static RWMode *
+mode_new (RWScreen *screen, RRMode id)
+{
+    RWMode *mode = g_new0 (RWMode, 1);
+    
+    mode->id = id;
+    mode->screen = screen;
+    
+    return mode;
+}
+
+guint32
+rw_mode_get_id (RWMode *mode)
+{
+    return mode->id;
+}
+
+guint
+rw_mode_get_width (RWMode *mode)
+{
+    return mode->width;
+}
+
+int
+rw_mode_get_freq (RWMode *mode)
+{
+    return (mode->freq) / 1000;
+}
+
+guint
+rw_mode_get_height (RWMode *mode)
+{
+    return mode->height;
+}
+
+static void
+mode_initialize (RWMode *mode, XRRModeInfo *info)
+{
+    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;
+}
+
+static void
+mode_free (RWMode *mode)
+{
+    g_free (mode->name);
+    g_free (mode);
+}
+
+
+#ifdef INCLUDE_MAIN
+static void
+on_screen_changed (RWScreen *screen, gpointer data)
+{
+    g_print ("Changed\n");
+}
+
+static gboolean
+do_refresh (gpointer data)
+{
+    RWScreen *screen = data;
+
+    rw_screen_refresh (screen);
+
+    return TRUE;
+}
+
+int
+main (int argc, char **argv)
+{
+    int i;
+    
+    gtk_init (&argc, &argv);
+    
+    RWScreen *screen = rw_screen_new (gdk_screen_get_default(),
+				   on_screen_changed,
+				   NULL);
+    
+    for (i = 0; screen->crtcs[i]; ++i)
+    {
+	RWCrtc *crtc = screen->crtcs[i];
+	
+	if (crtc->current_mode)
+	{
+	    g_print ("CRTC %p: (%d %d %d %d)\n",
+		     crtc, crtc->x, crtc->y,
+		     crtc->current_mode->width, crtc->current_mode->height);
+	}
+	else
+	{
+	    g_print ("CRTC %p: turned off\n", crtc);
+	}
+    }
+    
+    for (i = 0; screen->outputs[i]; ++i)
+    {
+	RWOutput *output = screen->outputs[i];
+	
+	g_print ("Output %s currently", output->name);
+	
+	if (!output->current_crtc)
+	    g_print (" turned off\n");
+	else
+	    g_print (" driven by CRTC %p\n", output->current_crtc);
+    }
+
+    g_timeout_add (500, do_refresh, screen);
+    
+    gtk_main ();
+    
+    return 0;
+}
+#endif
diff -up gnome-desktop-2.21.90/libgnome-desktop/Makefile.am.add-randr-12 gnome-desktop-2.21.90/libgnome-desktop/Makefile.am
--- gnome-desktop-2.21.90/libgnome-desktop/Makefile.am.add-randr-12	2008-01-27 18:44:20.000000000 -0500
+++ gnome-desktop-2.21.90/libgnome-desktop/Makefile.am	2008-01-31 16:44:28.000000000 -0500
@@ -20,7 +20,8 @@ libgnome_desktop_2_la_SOURCES = \
 	gnome-desktop-item.c	\
 	gnome-ditem-edit.c	\
 	gnome-hint.c		\
-	gnome-bg.c
+	gnome-bg.c		\
+	randrwrap.c
 
 libgnome_desktop_2_la_LIBADD =	\
 	$(XLIB_LIBS)		\