xserver: Branch 'xgl-0-0-1' - 5 commits

David Reveman davidr at kemper.freedesktop.org
Wed Jan 23 09:37:58 PST 2008


 configure.ac        |    2 
 hw/xgl/glx/xglx.c   |  967 +++++++++++++++++++++++++++++++-------
 hw/xgl/xgl.h        |    7 
 hw/xgl/xglscreen.c  |   56 ++
 randr/Makefile.am   |   20 
 randr/mirandr.c     |  174 ++++--
 randr/randr.c       | 1306 +++++++++-------------------------------------------
 randr/randrstr.h    |  781 +++++++++++++++++++++++++++++--
 randr/rrcrtc.c      |  950 +++++++++++++++++++++++++++++++++++++
 randr/rrdispatch.c  |  213 ++++++++
 randr/rrinfo.c      |  335 +++++++++++++
 randr/rrmode.c      |  397 +++++++++++++++
 randr/rroutput.c    |  534 +++++++++++++++++++++
 randr/rrpointer.c   |  145 +++++
 randr/rrproperty.c  |  692 +++++++++++++++++++++++++++
 randr/rrscreen.c    |  981 +++++++++++++++++++++++++++++++++++++++
 randr/rrsdispatch.c |  305 ++++++++++++
 randr/rrxinerama.c  |  444 +++++++++++++++++
 18 files changed, 6971 insertions(+), 1338 deletions(-)

New commits:
commit 1699869562b443fb32e582deef075f4d6b318ef0
Author: David Reveman <davidr at novell.com>
Date:   Thu Jan 17 20:07:14 2008 -0500

    Avoid unnecessary resizing, use xglScreenSetSize to resize screen
    and make sure hints are set properly in fullscreen mode.

diff --git a/hw/xgl/glx/xglx.c b/hw/xgl/glx/xglx.c
index 0363590..74fc8bd 100644
--- a/hw/xgl/glx/xglx.c
+++ b/hw/xgl/glx/xglx.c
@@ -592,48 +592,23 @@ xglxRRScreenSetSize (ScreenPtr pScreen,
 		     CARD32    mmWidth,
 		     CARD32    mmHeight)
 {
-    PixmapPtr pPixmap;
-
     XGLX_SCREEN_PRIV (pScreen);
 
-    pPixmap = (*pScreen->GetScreenPixmap) (pScreen);
-    if (pPixmap)
-    {
-	XGL_PIXMAP_PRIV (pPixmap);
-
-	if (width    != DisplayWidth (xdisplay, xscreen)   ||
-	    height   != DisplayHeight (xdisplay, xscreen)  ||
-	    mmWidth  != DisplayWidthMM (xdisplay, xscreen) ||
-	    mmHeight != DisplayHeightMM (xdisplay, xscreen))
-	    XRRSetScreenSize (xdisplay, pScreenPriv->root,
-			      width, height, mmWidth, mmHeight);
-
-	xglSetRootClip (pScreen, FALSE);
-
-	XResizeWindow (xdisplay, pScreenPriv->win, width, height);
-
-	glitz_drawable_update_size (pPixmapPriv->drawable, width, height);
-
-	pScreen->width    = width;
-	pScreen->height   = height;
-	pScreen->mmWidth  = mmWidth;
-	pScreen->mmHeight = mmHeight;
-
-	(*pScreen->ModifyPixmapHeader) (pPixmap,
-					pScreen->width,
-					pScreen->height,
-					pPixmap->drawable.depth,
-					pPixmap->drawable.bitsPerPixel,
-					0, 0);
+    if (!xglScreenSetSize (pScreen, width, height, mmWidth, mmHeight))
+	return FALSE;
 
-	xglSetRootClip (pScreen, TRUE);
+    if (width    != DisplayWidth (xdisplay, xscreen)   ||
+	height   != DisplayHeight (xdisplay, xscreen)  ||
+	mmWidth  != DisplayWidthMM (xdisplay, xscreen) ||
+	mmHeight != DisplayHeightMM (xdisplay, xscreen))
+	XRRSetScreenSize (xdisplay, pScreenPriv->root,
+			  width, height, mmWidth, mmHeight);
 
-	RRScreenSizeNotify (pScreen);
+    XResizeWindow (xdisplay, pScreenPriv->win, width, height);
 
-	return TRUE;
-    }
+    RRScreenSizeNotify (pScreen);
 
-    return FALSE;
+    return TRUE;
 }
 
 static Bool
@@ -1047,6 +1022,10 @@ xglxEnqueueEvents (void)
     XEvent X;
     xEvent x;
 
+#if RANDR_12_INTERFACE
+    int oldWidth, oldWidthMM, oldHeight, oldHeightMM;
+#endif
+
     while (XCheckIfEvent (xdisplay, &X, xglxNotExposurePredicate, NULL))
     {
 	switch (X.type) {
@@ -1117,14 +1096,22 @@ xglxEnqueueEvents (void)
 	default:
 
 #if RANDR_12_INTERFACE
+	    oldWidth    = DisplayWidth (xdisplay, xscreen);
+	    oldHeight   = DisplayHeight (xdisplay, xscreen);
+	    oldWidthMM  = DisplayWidthMM (xdisplay, xscreen);
+	    oldHeightMM = DisplayHeightMM (xdisplay, xscreen);
+
 	    XRRUpdateConfiguration (&X);
 
-	    switch (X.type - randrEvent) {
-	    case RRScreenChangeNotify: {
-		int i;
+	    if (!randrExtension)
+		break;
 
-		if (!randrExtension)
-		    break;
+	    if (oldWidth    != DisplayWidth (xdisplay, xscreen)   ||
+		oldHeight   != DisplayHeight (xdisplay, xscreen)  ||
+		oldWidthMM  != DisplayWidthMM (xdisplay, xscreen) ||
+		oldHeightMM != DisplayHeightMM (xdisplay, xscreen))
+	    {
+		int i;
 
 		for (i = 0; i < screenInfo.numScreens; i++)
 		{
@@ -1132,18 +1119,28 @@ xglxEnqueueEvents (void)
 
 		    XGLX_SCREEN_PRIV (pScreen);
 
-		    if (pScreenPriv->root == X.xany.window)
+		    if (pScreenPriv->root != X.xany.window)
+			continue;
+
+		    oldWidth    = pScreen->width;
+		    oldHeight   = pScreen->width;
+		    oldWidthMM  = pScreen->mmWidth;
+		    oldHeightMM = pScreen->mmHeight;
+
+		    if (oldWidth    != DisplayWidth (xdisplay, xscreen)   ||
+			oldHeight   != DisplayHeight (xdisplay, xscreen)  ||
+			oldWidthMM  != DisplayWidthMM (xdisplay, xscreen) ||
+			oldHeightMM != DisplayHeightMM (xdisplay, xscreen))
 			RRScreenSizeSet (pScreen,
 					 DisplayWidth (xdisplay, xscreen),
 					 DisplayHeight (xdisplay, xscreen),
 					 DisplayWidthMM (xdisplay, xscreen),
 					 DisplayHeightMM (xdisplay, xscreen));
 		}
-	    } break;
 	    }
-	    break;
 #endif
 
+	    break;
 	}
     }
 }
@@ -1655,20 +1652,26 @@ xglxScreenInit (int	  index,
     XFree (vinfo);
 
     normalHints = XAllocSizeHints ();
-    normalHints->flags      = PMinSize | PMaxSize | PSize;
-    normalHints->min_width  = xglScreenInfo.width;
-    normalHints->min_height = xglScreenInfo.height;
-    normalHints->max_width  = xglScreenInfo.width;
-    normalHints->max_height = xglScreenInfo.height;
+    normalHints->flags  = PSize;
+    normalHints->width  = xglScreenInfo.width;
+    normalHints->height = xglScreenInfo.height;
 
     if (fullscreen)
     {
+	normalHints->flags |= PPosition;
+
 	normalHints->x = x;
 	normalHints->y = y;
-	normalHints->flags |= PPosition;
     }
     else
     {
+	normalHints->flags |= PMinSize | PMaxSize;
+
+	normalHints->min_width  = xglScreenInfo.width;
+	normalHints->min_height = xglScreenInfo.height;
+	normalHints->max_width  = xglScreenInfo.width;
+	normalHints->max_height = xglScreenInfo.height;
+
 	currentEventWindow = pScreenPriv->win;
     }
 
commit effe1f1c6e54d18f0b083de4b2a1fee2a054f08e
Author: David Reveman <davidr at novell.com>
Date:   Thu Jan 17 20:03:28 2008 -0500

    Add xglScreenSetSize for proper resizing of screen.

diff --git a/hw/xgl/xgl.h b/hw/xgl/xgl.h
index f5c3b85..1292892 100644
--- a/hw/xgl/xgl.h
+++ b/hw/xgl/xgl.h
@@ -598,6 +598,13 @@ Bool
 xglCloseScreen (int	  index,
 		ScreenPtr pScreen);
 
+Bool
+xglScreenSetSize (ScreenPtr pScreen,
+		  int	    width,
+		  int	    height,
+		  int	    mmWidth,
+		  int	    mmHeight);
+
 void
 xglCreateSolidAlphaPicture (ScreenPtr pScreen);
 
diff --git a/hw/xgl/xglscreen.c b/hw/xgl/xglscreen.c
index cd5ad36..e025075 100644
--- a/hw/xgl/xglscreen.c
+++ b/hw/xgl/xglscreen.c
@@ -477,6 +477,62 @@ xglCloseScreen (int	  index,
     return (*pScreen->CloseScreen) (index, pScreen);
 }
 
+Bool
+xglScreenSetSize (ScreenPtr pScreen,
+		  int	    width,
+		  int	    height,
+		  int	    mmWidth,
+		  int	    mmHeight)
+{
+    if (width != pScreen->width || height != pScreen->height)
+    {
+	PixmapPtr	pPixmap = (*pScreen->GetScreenPixmap) (pScreen);
+	glitz_surface_t *surface;
+
+	XGL_SCREEN_PRIV (pScreen);
+
+	surface =
+	    glitz_surface_create (pScreenPriv->drawable,
+				  pScreenPriv->rootVisual->format.surface,
+				  width, height, 0, NULL);
+	if (!surface)
+	    return FALSE;
+
+	xglSetRootClip (pScreen, FALSE);
+
+	pScreen->width    = width;
+	pScreen->height   = height;
+	pScreen->mmWidth  = mmWidth;
+	pScreen->mmHeight = mmHeight;
+
+	if (pScreenPriv->surface)
+	    glitz_surface_destroy (pScreenPriv->surface);
+
+	pScreenPriv->surface = surface;
+
+	glitz_drawable_update_size (pScreenPriv->drawable, width, height);
+
+	glitz_surface_attach (pScreenPriv->surface, pScreenPriv->drawable,
+			      GLITZ_DRAWABLE_BUFFER_FRONT_COLOR);
+
+	(*pScreen->ModifyPixmapHeader) (pPixmap,
+					pScreen->width,
+					pScreen->height,
+					pPixmap->drawable.depth,
+					pPixmap->drawable.bitsPerPixel,
+					0, 0);
+
+	xglSetRootClip (pScreen, TRUE);
+    }
+    else
+    {
+	pScreen->mmWidth  = mmWidth;
+	pScreen->mmHeight = mmHeight;
+    }
+
+    return TRUE;
+}
+
 #ifdef RENDER
 void
 xglCreateSolidAlphaPicture (ScreenPtr pScreen)
commit 23233bd7f4922de0c69b60a68bafbdde58458966
Author: David Reveman <davidr at novell.com>
Date:   Thu Jan 17 13:32:41 2008 -0500

    Make sure no invalid values are passed to XRRConfigureOutputProperty and
    XRRChangeOutputProperty in xglxRROutputSetProperty.

diff --git a/hw/xgl/glx/xglx.c b/hw/xgl/glx/xglx.c
index 1ea3c66..0363590 100644
--- a/hw/xgl/glx/xglx.c
+++ b/hw/xgl/glx/xglx.c
@@ -725,8 +725,8 @@ xglxRROutputSetProperty (ScreenPtr	    pScreen,
 {
     RRPropertyPtr p;
     Atom	  atom, type;
-    char	  *data = NULL;
-    long	  *values = NULL;
+    long	  *values = value->data;
+    long	  *validValues;
     int		  i;
 
     if (xRRPending)
@@ -736,55 +736,87 @@ xglxRROutputSetProperty (ScreenPtr	    pScreen,
     if (!p)
 	return FALSE;
 
-    if (p->num_valid)
-    {
-	values = xalloc (p->num_valid * sizeof (long));
-	if (!values)
-	    return FALSE;
-
-	for (i = 0; i < p->num_valid; i++)
-	    values[i] = p->valid_values[i];
-    }
-
-    if (value->size)
-    {
-	int size = value->size * (value->format / 8);
-
-	data = xalloc (size);
-	if (!data)
-	    return FALSE;
-
-	memcpy (data, value->data, size);
-    }
+    validValues = p->valid_values;
 
     atom = XInternAtom (xdisplay, NameForAtom (property), FALSE);
     type = XInternAtom (xdisplay, NameForAtom (value->type), FALSE);
 
     if (type == XA_ATOM && value->format == 32)
     {
-	int i;
+	Atom *atoms = (Atom *) value->data;
 
 	for (i = 0; i < value->size; i++)
-	    data[i] = XInternAtom (xdisplay, NameForAtom (data[i]), FALSE);
+	    if (!ValidAtom (atoms[i]))
+		return FALSE;
+
+	if (p->num_valid > 0)
+	{
+	    for (i = 0; i < p->num_valid; i++)
+		if (!ValidAtom (p->valid_values[i]))
+		    return FALSE;
+
+	    for (i = 0; i < value->size; i++)
+	    {
+		int j;
+
+		for (j = 0; j < p->num_valid; j++)
+		    if (p->valid_values[j] == atoms[i])
+			break;
+
+		if (j == p->num_valid)
+		    return FALSE;
+	    }
+
+	    validValues = xalloc (p->num_valid * sizeof (long));
+	    if (!validValues)
+		return FALSE;
 
-	if (!p->range && p->num_valid > 0)
 	    for (i = 0; i < p->num_valid; i++)
-		values[i] = XInternAtom (xdisplay, NameForAtom (values[i]),
+		validValues[i] = XInternAtom (xdisplay,
+					      NameForAtom (p->valid_values[i]),
+					      FALSE);
+	}
+
+	if (value->size)
+	{
+	    int size = value->size * (value->format / 8);
+
+	    values = xalloc (size);
+	    if (!values)
+		return FALSE;
+
+	    for (i = 0; i < value->size; i++)
+		values[i] = XInternAtom (xdisplay,
+					 NameForAtom (atoms[i]),
 					 FALSE);
+	}
+    }
+    else
+    {
+	if (p->num_valid > 0)
+	{
+	    validValues = xalloc (p->num_valid * sizeof (long));
+	    if (!validValues)
+		return FALSE;
+
+	    for (i = 0; i < p->num_valid; i++)
+		validValues[i] = p->valid_values[i];
+	}
     }
 
     XRRConfigureOutputProperty (xdisplay, (RROutput) output->devPrivate, atom,
-				p->is_pending, p->range, p->num_valid, values);
+				p->is_pending, p->range, p->num_valid,
+				validValues);
 
     XRRChangeOutputProperty (xdisplay, (RROutput) output->devPrivate,
 			     atom, type, value->format, PropModeReplace,
-			     data, value->size);
+			     (unsigned char *) values, value->size);
 
-    if (values)
-	xfree (values);
+    if (validValues != p->valid_values)
+	xfree (validValues);
 
-    if (data)
-	xfree (data);
+    if (values != value->data)
+	xfree (values);
 
     return TRUE;
 }
commit 3afbef5f93d53a5f4321a741d262c299ad6f45c3
Author: David Reveman <davidr at novell.com>
Date:   Tue Jan 15 19:11:32 2008 -0500

    Add randr 1.2 support to Xgl's GLX backend.

diff --git a/hw/xgl/glx/xglx.c b/hw/xgl/glx/xglx.c
index a568770..1ea3c66 100644
--- a/hw/xgl/glx/xglx.c
+++ b/hw/xgl/glx/xglx.c
@@ -41,6 +41,7 @@
 #include "mipointer.h"
 
 #ifdef RANDR
+#include <X11/Xatom.h>
 #include "randrstr.h"
 #endif
 
@@ -147,6 +148,7 @@ static int	 primaryScreen = 0;
 
 static Bool randrExtension = FALSE;
 static int  randrEvent, randrError;
+static Bool xRRPending = FALSE;
 
 static glitz_drawable_format_t *xglxScreenFormat = 0;
 
@@ -181,211 +183,782 @@ xglxAllocatePrivates (ScreenPtr pScreen)
 
 #ifdef RANDR
 
-#define DEFAULT_REFRESH_RATE 50
+#if RANDR_12_INTERFACE
+static RRModePtr
+xglxRRGetMode (XRRScreenResources *r,
+	       RRMode		  mode)
+{
+    xRRModeInfo modeInfo;
+    int		i;
+
+    for (i = 0; i < r->nmode; i++)
+    {
+	if (r->modes[i].id == mode)
+	{
+	    memset (&modeInfo, '\0', sizeof (modeInfo));
+
+	    modeInfo.width      = r->modes[i].width;
+	    modeInfo.height     = r->modes[i].height;
+	    modeInfo.dotClock   = r->modes[i].dotClock;
+	    modeInfo.hSyncStart = r->modes[i].hSyncStart;
+	    modeInfo.hSyncEnd   = r->modes[i].hSyncEnd;
+	    modeInfo.hTotal     = r->modes[i].hTotal;
+	    modeInfo.hSkew      = r->modes[i].hSkew;
+	    modeInfo.vSyncStart = r->modes[i].vSyncStart;
+	    modeInfo.vSyncEnd   = r->modes[i].vSyncEnd;
+	    modeInfo.vTotal     = r->modes[i].vTotal;
+	    modeInfo.nameLength = strlen (r->modes[i].name);
+	    modeInfo.modeFlags  = r->modes[i].modeFlags;
+
+	    return RRModeGet (&modeInfo, r->modes[i].name);
+	}
+    }
+
+    return NULL;
+}
+
+static RRCrtcPtr
+xglxRRGetCrtc (ScreenPtr pScreen,
+	       RRCrtc	 crtc)
+{
+    int i;
+
+    rrScrPriv (pScreen);
+
+    for (i = 0; i < pScrPriv->numCrtcs; i++)
+	if (pScrPriv->crtcs[i]->devPrivate == (void *) crtc)
+	    return pScrPriv->crtcs[i];
+
+    return NULL;
+}
+
+static RROutputPtr
+xglxRRGetOutput (ScreenPtr pScreen,
+		 RRMode	   output)
+{
+    int i;
+
+    rrScrPriv (pScreen);
+
+    for (i = 0; i < pScrPriv->numOutputs; i++)
+	if (pScrPriv->outputs[i]->devPrivate == (void *) output)
+	    return pScrPriv->outputs[i];
+
+    return NULL;
+}
 
 static Bool
-xglxRandRGetInfo (ScreenPtr pScreen,
-		  Rotation  *rotations)
+xglxRRUpdateCrtc (ScreenPtr	     pScreen,
+		  XRRScreenResources *r,
+		  RRCrtc	     xcrtc)
 {
-    RRScreenSizePtr pSize;
+    XRRCrtcInfo  *c;
+    RRCrtcPtr	 crtc;
+    RRModePtr	 mode = NULL;
+    RROutputPtr	 *outputs = NULL;
+    XRRCrtcGamma *gamma;
+    int		 i;
+
+    c = XRRGetCrtcInfo (xdisplay, r, xcrtc);
+    if (!c)
+	return FALSE;
 
-    *rotations = RR_Rotate_0;
+    crtc = xglxRRGetCrtc (pScreen, xcrtc);
+    if (!crtc)
+	return FALSE;
 
-    if (randrExtension)
+    if (c->noutput)
     {
-	XRRScreenConfiguration *xconfig;
-	XRRScreenSize	       *sizes;
-	int		       nSizes, currentSize = 0;
-	short		       *rates, currentRate;
-	int		       nRates, i, j;
+	outputs = xalloc (sizeof (RROutputPtr) * c->noutput);
+	if (!outputs)
+	    return FALSE;
+    }
 
-	XGLX_SCREEN_PRIV (pScreen);
+    if (c->mode)
+	mode = xglxRRGetMode (r, c->mode);
 
-	xconfig	    = XRRGetScreenInfo (xdisplay, pScreenPriv->root);
-	sizes	    = XRRConfigSizes (xconfig, &nSizes);
-	currentRate = XRRConfigCurrentRate (xconfig);
+    for (i = 0; i < c->noutput; i++)
+    {
+	outputs[i] = xglxRRGetOutput (pScreen, c->outputs[i]);
+	if (!outputs[i])
+	    return FALSE;
+    }
 
-	if (pScreenPriv->fullscreen && nScreenRect == 0)
-	{
-	    Rotation rotation;
+    gamma = XRRGetCrtcGamma (xdisplay, xcrtc);
+    if (!gamma)
+	return FALSE;
 
-	    currentSize = XRRConfigCurrentConfiguration (xconfig, &rotation);
+    RRCrtcGammaSet (crtc, gamma->red, gamma->green, gamma->blue);
 
-	    for (i = 0; i < nSizes; i++)
-	    {
-		pSize = RRRegisterSize (pScreen,
-					sizes[i].width,
-					sizes[i].height,
-					sizes[i].mwidth,
-					sizes[i].mheight);
+    XRRFreeGamma (gamma);
 
-		rates = XRRConfigRates (xconfig, i, &nRates);
+    RRCrtcNotify (crtc, mode, c->x, c->y, c->rotation, c->noutput, outputs);
 
-		for (j = 0; j < nRates; j++)
-		{
-		    RRRegisterRate (pScreen, pSize, rates[j]);
+    if (outputs)
+	xfree (outputs);
 
-		    if (i == currentSize && rates[j] == currentRate)
-			RRSetCurrentConfig (pScreen, RR_Rotate_0, currentRate,
-					    pSize);
-		}
-	    }
-	}
-	else
-	{
-	    pSize = RRRegisterSize (pScreen,
-				    pScreen->width,
-				    pScreen->height,
-				    pScreen->mmWidth,
-				    pScreen->mmHeight);
+    XRRFreeCrtcInfo (c);
 
-	    for (i = 0; i < nSizes; i++)
-	    {
-		rates = XRRConfigRates (xconfig, i, &nRates);
+    return TRUE;
+}
 
-		for (j = 0; j < nRates; j++)
-		{
-		    RRRegisterRate (pScreen, pSize, rates[j]);
+static Bool
+xglxRRUpdateOutput (ScreenPtr	       pScreen,
+		    XRRScreenResources *r,
+		    RROutput	       xoutput)
+{
+    XRROutputInfo *o;
+    RROutputPtr	  output, *clones = NULL;
+    RRModePtr	  *modes = NULL;
+    RRCrtcPtr	  *crtcs = NULL;
+    int		  i;
+
+    o = XRRGetOutputInfo (xdisplay, r, xoutput);
+    if (!o)
+	return FALSE;
 
-		    if (rates[j] == currentRate)
-			RRSetCurrentConfig (pScreen, RR_Rotate_0, currentRate,
-					    pSize);
-		}
-	    }
-	}
+    if (o->nclone)
+    {
+	clones = xalloc (sizeof (RROutputPtr) * o->nclone);
+	if (!clones)
+	    return FALSE;
+    }
 
-	XRRFreeScreenConfigInfo (xconfig);
+    if (o->nmode)
+    {
+	modes = xalloc (sizeof (RRModePtr) * o->nmode);
+	if (!modes)
+	    return FALSE;
     }
-    else
+
+    if (o->ncrtc)
+    {
+	crtcs = xalloc (sizeof (RRCrtcPtr) * o->ncrtc);
+	if (!crtcs)
+	    return FALSE;
+    }
+
+    output = xglxRRGetOutput (pScreen, xoutput);
+    if (!output)
+	return FALSE;
+
+    for (i = 0; i < o->nclone; i++)
     {
-	pSize = RRRegisterSize (pScreen,
-				pScreen->width,
-				pScreen->height,
-				pScreen->mmWidth,
-				pScreen->mmHeight);
-
-	RRRegisterRate (pScreen, pSize, DEFAULT_REFRESH_RATE);
-	RRSetCurrentConfig (pScreen, RR_Rotate_0, DEFAULT_REFRESH_RATE, pSize);
+	clones[i] = xglxRRGetOutput (pScreen, o->clones[i]);
+	if (!clones[i])
+	    return FALSE;
     }
 
+    if (!RROutputSetClones (output, clones, o->nclone))
+	return FALSE;
+
+    for (i = 0; i < o->nmode; i++)
+    {
+	modes[i] = xglxRRGetMode (r, o->modes[i]);
+	if (!modes[i])
+	    return FALSE;
+    }
+
+    if (!RROutputSetModes (output, modes, o->nmode, o->npreferred))
+	return FALSE;
+
+    for (i = 0; i < o->ncrtc; i++)
+    {
+	crtcs[i] = xglxRRGetCrtc (pScreen, o->crtcs[i]);
+	if (!crtcs[i])
+	    return FALSE;
+    }
+
+    if (!RROutputSetCrtcs (output, crtcs, o->ncrtc))
+	return FALSE;
+
+    if (!RROutputSetConnection (output, o->connection))
+	return FALSE;
+
+    if (!RROutputSetSubpixelOrder (output, o->subpixel_order))
+	return FALSE;
+
+    if (!RROutputSetPhysicalSize (output, o->mm_width, o->mm_height))
+	return FALSE;
+
+    if (clones)
+	xfree (clones);
+
+    if (modes)
+	xfree (modes);
+
+    if (crtcs)
+	xfree (crtcs);
+
+    XRRFreeOutputInfo (o);
+
     return TRUE;
 }
 
 static Bool
-xglxRandRSetConfig (ScreenPtr	    pScreen,
-		    Rotation	    rotations,
-		    int		    rate,
-		    RRScreenSizePtr pSize)
+xglxRRUpdateOutputProperty (ScreenPtr	       pScreen,
+			    XRRScreenResources *r,
+			    RROutput	       xoutput,
+			    Atom	       xproperty)
 {
-    if (randrExtension)
+    RROutputPtr     output;
+    XRRPropertyInfo *info;
+    unsigned char   *prop;
+    int		    format, status;
+    unsigned long   nElements, bytesAfter;
+    Atom	    type, atom;
+    char	    *name;
+    INT32           *values = NULL;
+
+    output = xglxRRGetOutput (pScreen, xoutput);
+    if (!output)
+	return FALSE;
+
+    name = XGetAtomName (xdisplay, xproperty);
+    if (!name)
+	return FALSE;
+
+    atom = MakeAtom (name, strlen (name), TRUE);
+
+    XFree (name);
+
+    status = XRRGetOutputProperty (xdisplay, xoutput, xproperty,
+				   0, 8192, FALSE, FALSE,
+				   AnyPropertyType, &type, &format,
+				   &nElements, &bytesAfter, &prop);
+
+    if (status != Success)
+	return FALSE;
+
+    info = XRRQueryOutputProperty (xdisplay, xoutput, xproperty);
+    if (!info)
+	return FALSE;
+
+    if (info->num_values)
     {
-	XRRScreenConfiguration *xconfig;
-	XRRScreenSize	       *sizes;
-	int		       nSizes, currentSize;
-	int		       i, size = -1;
-	int		       status = RRSetConfigFailed;
-	Rotation	       rotation;
+	values = xalloc (info->num_values * sizeof (INT32));
+	if (!values)
+	    return FALSE;
 
-	XGLX_SCREEN_PRIV (pScreen);
+	memcpy (values, info->values, info->num_values * sizeof (INT32));
+    }
 
-	xconfig	    = XRRGetScreenInfo (xdisplay, pScreenPriv->root);
-	sizes	    = XRRConfigSizes (xconfig, &nSizes);
-	currentSize = XRRConfigCurrentConfiguration (xconfig, &rotation);
+    if (type == XA_ATOM && format == 32)
+    {
+	int i;
 
-	for (i = 0; i < nSizes; i++)
+	for (i = 0; i < nElements; i++)
 	{
-	    if (pScreenPriv->fullscreen && nScreenRect == 0)
-	    {
-		if (sizes[i].width   == pSize->width   &&
-		    sizes[i].height  == pSize->height  &&
-		    sizes[i].mwidth  == pSize->mmWidth &&
-		    sizes[i].mheight == pSize->mmHeight)
-		{
-		    size = i;
-		    break;
-		}
-	    }
-	    else
+	    name = XGetAtomName (xdisplay, prop[i]);
+	    if (!name)
+		return FALSE;
+
+	    prop[i] = MakeAtom (name, strlen (name), TRUE);
+
+	    XFree (name);
+	}
+
+	if (!info->range && info->num_values > 0)
+	{
+	    for (i = 0; i < info->num_values; i++)
 	    {
-		short *rates;
-		int   nRates, j;
+		name = XGetAtomName (xdisplay, values[i]);
+		if (!name)
+		    return FALSE;
 
-		rates = XRRConfigRates (xconfig, i, &nRates);
+		values[i] = MakeAtom (name, strlen (name), TRUE);
 
-		for (j = 0; j < nRates; j++)
-		{
-		    if (rates[j] == rate)
-		    {
-			size = i;
-			if (i >= currentSize)
-			    break;
-		    }
-		}
+		XFree (name);
 	    }
 	}
+    }
+
+    RRConfigureOutputProperty (output, atom, FALSE,
+			       info->range, info->immutable, info->num_values,
+			       values);
+
+    RRChangeOutputProperty (output, atom, type, format, PropModeReplace,
+			    nElements, prop, FALSE, TRUE);
+
+    if (values)
+	xfree (values);
 
-	if (size >= 0)
-	    status = XRRSetScreenConfigAndRate (xdisplay,
-						xconfig,
-						pScreenPriv->root,
-						size,
-						RR_Rotate_0,
-						rate,
-						CurrentTime);
+    XFree (info);
+    XFree (prop);
 
-	XRRFreeScreenConfigInfo (xconfig);
+    return TRUE;
+}
+#endif
 
-	if (status == RRSetConfigSuccess)
+static Bool
+xglxRRGetInfo (ScreenPtr pScreen,
+	       Rotation  *rotations)
+{
+    RRScreenSizePtr pSize;
+
+#if RANDR_12_INTERFACE
+    XGLX_SCREEN_PRIV (pScreen);
+
+    if (pScreenPriv->fullscreen)
+    {
+	XRRScreenResources *r;
+	int		   i;
+
+	rrScrPriv (pScreen);
+
+	xRRPending = TRUE;
+
+	r = XRRGetScreenResources (xdisplay, pScreenPriv->root);
+	if (!r)
+	    return (xRRPending = FALSE);
+
+	for (i = 0; i < r->noutput; i++)
 	{
-	    PixmapPtr pPixmap;
+	    Atom *props;
+	    int  nProp, j;
 
-	    pPixmap = (*pScreen->GetScreenPixmap) (pScreen);
+	    if (!xglxRRUpdateOutput (pScreen, r, r->outputs[i]))
+		return (xRRPending = FALSE);
 
-	    if (pScreenPriv->fullscreen)
+	    props = XRRListOutputProperties (xdisplay, r->outputs[i], &nProp);
+	    if (nProp)
 	    {
-		XGL_PIXMAP_PRIV (pPixmap);
+		for (j = 0; j < nProp; j++)
+		    if (!xglxRRUpdateOutputProperty (pScreen, r, r->outputs[i],
+						     props[j]))
+			return (xRRPending = FALSE);
+
+		XFree (props);
+	    }
+	}
 
-		xglSetRootClip (pScreen, FALSE);
+	for (i = 0; i < r->ncrtc; i++)
+	    if (!xglxRRUpdateCrtc (pScreen, r, r->crtcs[i]))
+		return (xRRPending = FALSE);
 
-		XResizeWindow (xdisplay, pScreenPriv->win,
-			       pSize->width, pSize->height);
+	XRRFreeScreenResources (r);
 
-		glitz_drawable_update_size (pPixmapPriv->drawable,
-					    pSize->width, pSize->height);
+	*rotations = RR_Rotate_0;
 
-		pScreen->width    = pSize->width;
-		pScreen->height   = pSize->height;
-		pScreen->mmWidth  = pSize->mmWidth;
-		pScreen->mmHeight = pSize->mmHeight;
+	for (i = 0; i < pScrPriv->numCrtcs; i++)
+	    *rotations |= pScrPriv->crtcs[i]->rotations;
 
-		(*pScreen->ModifyPixmapHeader) (pPixmap,
-						pScreen->width,
-						pScreen->height,
-						pPixmap->drawable.depth,
-						pPixmap->drawable.bitsPerPixel,
-						0, 0);
+	xRRPending = FALSE;
 
-		xglSetRootClip (pScreen, TRUE);
-	    }
+	return TRUE;
+    }
+#endif
 
-	    return TRUE;
+    *rotations = RR_Rotate_0;
+
+    return TRUE;
+}
+
+#if RANDR_12_INTERFACE
+static RRMode
+xglxRRGetXMode (XRRScreenResources *r,
+		RRModePtr	   mode)
+{
+    xRRModeInfo modeInfo = mode->mode;
+    int		i;
+
+    for (i = 0; i < r->nmode; i++)
+    {
+	if (modeInfo.width      == r->modes[i].width	  &&
+	    modeInfo.height     == r->modes[i].height	  &&
+	    modeInfo.dotClock   == r->modes[i].dotClock	  &&
+	    modeInfo.hSyncStart == r->modes[i].hSyncStart &&
+	    modeInfo.hSyncEnd   == r->modes[i].hSyncEnd	  &&
+	    modeInfo.hTotal     == r->modes[i].hTotal	  &&
+	    modeInfo.hSkew      == r->modes[i].hSkew	  &&
+	    modeInfo.vSyncStart == r->modes[i].vSyncStart &&
+	    modeInfo.vSyncEnd   == r->modes[i].vSyncEnd	  &&
+	    modeInfo.vTotal     == r->modes[i].vTotal	  &&
+	    modeInfo.nameLength == r->modes[i].nameLength &&
+	    modeInfo.modeFlags  == r->modes[i].modeFlags)
+	{
+	    if (!memcmp (r->modes[i].name, mode->name, modeInfo.nameLength))
+		return r->modes[i].id;
 	}
     }
 
+    return None;
+}
+
+static Bool
+xglxRRScreenSetSize (ScreenPtr pScreen,
+		     CARD16    width,
+		     CARD16    height,
+		     CARD32    mmWidth,
+		     CARD32    mmHeight)
+{
+    PixmapPtr pPixmap;
+
+    XGLX_SCREEN_PRIV (pScreen);
+
+    pPixmap = (*pScreen->GetScreenPixmap) (pScreen);
+    if (pPixmap)
+    {
+	XGL_PIXMAP_PRIV (pPixmap);
+
+	if (width    != DisplayWidth (xdisplay, xscreen)   ||
+	    height   != DisplayHeight (xdisplay, xscreen)  ||
+	    mmWidth  != DisplayWidthMM (xdisplay, xscreen) ||
+	    mmHeight != DisplayHeightMM (xdisplay, xscreen))
+	    XRRSetScreenSize (xdisplay, pScreenPriv->root,
+			      width, height, mmWidth, mmHeight);
+
+	xglSetRootClip (pScreen, FALSE);
+
+	XResizeWindow (xdisplay, pScreenPriv->win, width, height);
+
+	glitz_drawable_update_size (pPixmapPriv->drawable, width, height);
+
+	pScreen->width    = width;
+	pScreen->height   = height;
+	pScreen->mmWidth  = mmWidth;
+	pScreen->mmHeight = mmHeight;
+
+	(*pScreen->ModifyPixmapHeader) (pPixmap,
+					pScreen->width,
+					pScreen->height,
+					pPixmap->drawable.depth,
+					pPixmap->drawable.bitsPerPixel,
+					0, 0);
+
+	xglSetRootClip (pScreen, TRUE);
+
+	RRScreenSizeNotify (pScreen);
+
+	return TRUE;
+    }
+
     return FALSE;
 }
 
 static Bool
+xglxRRCrtcSet (ScreenPtr   pScreen,
+	       RRCrtcPtr   crtc,
+	       RRModePtr   mode,
+	       int	   x,
+	       int	   y,
+	       Rotation    rotation,
+	       int	   numOutputs,
+	       RROutputPtr *outputs)
+{
+    XRRScreenResources *r;
+    RROutput	       *o = NULL;
+    RRMode	       m = None;
+    int		       i;
+
+    XGLX_SCREEN_PRIV (pScreen);
+
+    if (xRRPending)
+	return RRCrtcNotify (crtc, mode, x, y, rotation, numOutputs, outputs);
+
+    if (numOutputs)
+    {
+	o = xalloc (sizeof (RROutput *) * numOutputs);
+	if (!o)
+	    return FALSE;
+    }
+
+    r = XRRGetScreenResources (xdisplay, pScreenPriv->root);
+    if (!r)
+	return FALSE;
+
+    if (mode)
+    {
+	m = xglxRRGetXMode (r, mode);
+	if (!m)
+	    return FALSE;
+    }
+
+    XRRFreeScreenResources (r);
+
+    for (i = 0; i < numOutputs; i++)
+	o[i] = (RROutput) outputs[i]->devPrivate;
+
+    XRRSetCrtcConfig (xdisplay, r,
+		      (RRCrtc) crtc->devPrivate,
+		      CurrentTime,
+		      x, y,
+		      m,
+		      rotation,
+		      o, numOutputs);
+
+    if (o)
+	free (o);
+
+    return RRCrtcNotify (crtc, mode, x, y, rotation, numOutputs, outputs);
+}
+
+static Bool
+xglxRRCrtcSetGamma (ScreenPtr pScreen,
+		    RRCrtcPtr crtc)
+{
+    XRRCrtcGamma *gamma;
+
+    if (xRRPending)
+	return TRUE;
+
+    gamma = XRRAllocGamma (crtc->gammaSize);
+    if (!gamma)
+	return FALSE;
+
+    memcpy (gamma->red,   crtc->gammaRed,   gamma->size * sizeof (CARD16));
+    memcpy (gamma->green, crtc->gammaGreen, gamma->size * sizeof (CARD16));
+    memcpy (gamma->blue,  crtc->gammaBlue,  gamma->size * sizeof (CARD16));
+
+    XRRSetCrtcGamma (xdisplay, (RRCrtc) crtc->devPrivate, gamma);
+
+    XRRFreeGamma (gamma);
+
+    return TRUE;
+}
+
+static Bool
+xglxRROutputSetProperty (ScreenPtr	    pScreen,
+			 RROutputPtr	    output,
+			 Atom	            property,
+			 RRPropertyValuePtr value)
+{
+    RRPropertyPtr p;
+    Atom	  atom, type;
+    char	  *data = NULL;
+    long	  *values = NULL;
+    int		  i;
+
+    if (xRRPending)
+	return TRUE;
+
+    p = RRQueryOutputProperty (output, property);
+    if (!p)
+	return FALSE;
+
+    if (p->num_valid)
+    {
+	values = xalloc (p->num_valid * sizeof (long));
+	if (!values)
+	    return FALSE;
+
+	for (i = 0; i < p->num_valid; i++)
+	    values[i] = p->valid_values[i];
+    }
+
+    if (value->size)
+    {
+	int size = value->size * (value->format / 8);
+
+	data = xalloc (size);
+	if (!data)
+	    return FALSE;
+
+	memcpy (data, value->data, size);
+    }
+
+    atom = XInternAtom (xdisplay, NameForAtom (property), FALSE);
+    type = XInternAtom (xdisplay, NameForAtom (value->type), FALSE);
+
+    if (type == XA_ATOM && value->format == 32)
+    {
+	int i;
+
+	for (i = 0; i < value->size; i++)
+	    data[i] = XInternAtom (xdisplay, NameForAtom (data[i]), FALSE);
+
+	if (!p->range && p->num_valid > 0)
+	    for (i = 0; i < p->num_valid; i++)
+		values[i] = XInternAtom (xdisplay, NameForAtom (values[i]),
+					 FALSE);
+    }
+
+    XRRConfigureOutputProperty (xdisplay, (RROutput) output->devPrivate, atom,
+				p->is_pending, p->range, p->num_valid, values);
+
+    XRRChangeOutputProperty (xdisplay, (RROutput) output->devPrivate,
+			     atom, type, value->format, PropModeReplace,
+			     data, value->size);
+
+    if (values)
+	xfree (values);
+
+    if (data)
+	xfree (data);
+
+    return TRUE;
+}
+
+static Bool
+xglxRROutputValidateMode (ScreenPtr   pScreen,
+			  RROutputPtr output,
+			  RRModePtr   mode)
+{
+    XRRModeInfo *modeInfo;
+    RRMode	m;
+
+    XGLX_SCREEN_PRIV (pScreen);
+
+    if (xRRPending)
+	return TRUE;
+
+    modeInfo = XRRAllocModeInfo (mode->name, mode->mode.nameLength);
+    if (!modeInfo)
+	return FALSE;
+
+    m = XRRCreateMode (xdisplay, pScreenPriv->root, modeInfo);
+    if (!m)
+	return FALSE;
+
+    XRRFreeModeInfo (modeInfo);
+
+    XRRAddOutputMode (xdisplay, (RROutput) output->devPrivate, m);
+
+    return TRUE;
+}
+
+static void
+xglxRRModeDestroy (ScreenPtr pScreen,
+		   RRModePtr mode)
+{
+    XRRScreenResources *r;
+
+    XGLX_SCREEN_PRIV (pScreen);
+
+    if (xRRPending)
+	return;
+
+    r = XRRGetScreenResources (xdisplay, pScreenPriv->root);
+    if (r)
+    {
+	RRMode m;
+
+	m = xglxRRGetXMode (r, mode);
+	if (m)
+	    XRRDestroyMode (xdisplay, m);
+
+	XRRFreeScreenResources (r);
+    }
+}
+#endif
+
+static Bool
 xglxRandRInit (ScreenPtr pScreen)
 {
     rrScrPrivPtr pScrPriv;
 
+    XGLX_SCREEN_PRIV (pScreen);
+
     if (!RRScreenInit (pScreen))
 	return FALSE;
 
     pScrPriv = rrGetScrPriv (pScreen);
-    pScrPriv->rrGetInfo   = xglxRandRGetInfo;
-    pScrPriv->rrSetConfig = xglxRandRSetConfig;
+    pScrPriv->rrGetInfo	= xglxRRGetInfo;
+
+#if RANDR_12_INTERFACE
+    if (pScreenPriv->fullscreen)
+    {
+	XRRScreenResources *r;
+	int		   i, minWidth, minHeight, maxWidth, maxHeight;
+
+	pScrPriv->rrScreenSetSize      = xglxRRScreenSetSize;
+	pScrPriv->rrCrtcSet	       = xglxRRCrtcSet;
+	pScrPriv->rrCrtcSetGamma       = xglxRRCrtcSetGamma;
+	pScrPriv->rrOutputSetProperty  = xglxRROutputSetProperty;
+	pScrPriv->rrOutputValidateMode = xglxRROutputValidateMode;
+	pScrPriv->rrModeDestroy	       = xglxRRModeDestroy;
+
+	if (!XRRGetScreenSizeRange (xdisplay, pScreenPriv->root,
+				    &minWidth, &minHeight,
+				    &maxWidth, &maxHeight))
+	    return FALSE;
+
+	RRScreenSetSizeRange (pScreen,
+			      minWidth, minHeight, maxWidth, maxHeight);
+
+	r = XRRGetScreenResources (xdisplay, pScreenPriv->root);
+	if (!r)
+	    return FALSE;
+
+	for (i = 0; i < r->ncrtc; i++)
+	{
+	    XRRCrtcInfo *c;
+	    RRCrtcPtr	crtc;
+
+	    crtc = RRCrtcCreate (pScreen, (void *) r->crtcs[i]);
+	    if (!crtc)
+		return FALSE;
+
+	    c = XRRGetCrtcInfo (xdisplay, r, r->crtcs[i]);
+	    if (!c)
+		return FALSE;
+
+	    RRCrtcSetRotations (crtc, c->rotations);
+	    RRCrtcGammaSetSize (crtc, XRRGetCrtcGammaSize (xdisplay,
+							   r->crtcs[i]));
+
+	    XRRFreeCrtcInfo (c);
+	}
+
+	for (i = 0; i < r->noutput; i++)
+	{
+	    XRROutputInfo *o;
+	    RROutputPtr	  output;
+
+	    o = XRRGetOutputInfo (xdisplay, r, r->outputs[i]);
+	    if (!o)
+		return FALSE;
+
+	    if (!RROutputCreate (pScreen, o->name, strlen (o->name),
+				 (void *) r->outputs[i]))
+		return FALSE;
+
+	    XRRFreeOutputInfo (o);
+	}
+
+	XRRFreeScreenResources (r);
+    }
+    else
+    {
+	RRModePtr    mode;
+	RRCrtcPtr    crtc;
+	RROutputPtr  output;
+	xRRModeInfo  modeInfo;
+	char	     name[64];
+
+	RRScreenSetSizeRange (pScreen,
+			      pScreen->width, pScreen->height,
+			      pScreen->width, pScreen->height);
+
+	sprintf (name, "%dx%d", pScreen->width, pScreen->height);
+	memset (&modeInfo, '\0', sizeof (modeInfo));
+	modeInfo.width = pScreen->width;
+	modeInfo.height = pScreen->height;
+	modeInfo.nameLength = strlen (name);
+
+	mode = RRModeGet (&modeInfo, name);
+	if (!mode)
+	    return FALSE;
+
+	crtc = RRCrtcCreate (pScreen, NULL);
+	if (!crtc)
+	    return FALSE;
+
+	output = RROutputCreate (pScreen, "screen", 6, NULL);
+	if (!output)
+	    return FALSE;
+	if (!RROutputSetClones (output, NULL, 0))
+	    return FALSE;
+	if (!RROutputSetModes (output, &mode, 1, 0))
+	    return FALSE;
+	if (!RROutputSetCrtcs (output, &crtc, 1))
+	    return FALSE;
+	if (!RROutputSetConnection (output, RR_Connected))
+	    return FALSE;
+
+	RRCrtcNotify (crtc, mode, 0, 0, RR_Rotate_0, 1, &output);
+    }
+#endif
 
     return TRUE;
 }
@@ -510,7 +1083,35 @@ xglxEnqueueEvents (void)
 	    }
 	    break;
 	default:
+
+#if RANDR_12_INTERFACE
+	    XRRUpdateConfiguration (&X);
+
+	    switch (X.type - randrEvent) {
+	    case RRScreenChangeNotify: {
+		int i;
+
+		if (!randrExtension)
+		    break;
+
+		for (i = 0; i < screenInfo.numScreens; i++)
+		{
+		    ScreenPtr pScreen = screenInfo.screens[i];
+
+		    XGLX_SCREEN_PRIV (pScreen);
+
+		    if (pScreenPriv->root == X.xany.window)
+			RRScreenSizeSet (pScreen,
+					 DisplayWidth (xdisplay, xscreen),
+					 DisplayHeight (xdisplay, xscreen),
+					 DisplayWidthMM (xdisplay, xscreen),
+					 DisplayHeightMM (xdisplay, xscreen));
+		}
+	    } break;
+	    }
 	    break;
+#endif
+
 	}
     }
 }
@@ -954,6 +1555,7 @@ xglxScreenInit (int	  index,
     glitz_drawable_format_t *format;
     glitz_drawable_t	    *drawable;
     int			    x = 0, y = 0;
+    long		    eventMask;
 
     format = xglxScreenFormat;
 
@@ -986,25 +1588,6 @@ xglxScreenInit (int	  index,
 	xglScreenInfo.widthMm  = DisplayWidthMM (xdisplay, xscreen);
 	xglScreenInfo.heightMm = DisplayHeightMM (xdisplay, xscreen);
 
-	if (randrExtension)
-	{
-	    XRRScreenConfiguration *xconfig;
-	    Rotation		   rotation;
-	    XRRScreenSize	   *sizes;
-	    int			   nSizes, currentSize;
-
-	    xconfig	= XRRGetScreenInfo (xdisplay, pScreenPriv->root);
-	    currentSize = XRRConfigCurrentConfiguration (xconfig, &rotation);
-	    sizes	= XRRConfigSizes (xconfig, &nSizes);
-
-	    xglScreenInfo.width    = sizes[currentSize].width;
-	    xglScreenInfo.height   = sizes[currentSize].height;
-	    xglScreenInfo.widthMm  = sizes[currentSize].mwidth;
-	    xglScreenInfo.heightMm = sizes[currentSize].mheight;
-
-	    XRRFreeScreenConfigInfo (xconfig);
-	}
-
 	if (nScreenRect)
 	{
 	    int w, h;
@@ -1082,10 +1665,24 @@ xglxScreenInit (int	  index,
 	return FALSE;
     }
 
-    XSelectInput (xdisplay, pScreenPriv->win,
-		  ButtonPressMask | ButtonReleaseMask |
-		  KeyPressMask | KeyReleaseMask | EnterWindowMask |
-		  PointerMotionMask | ExposureMask);
+    eventMask = ButtonPressMask | ButtonReleaseMask |
+	KeyPressMask | KeyReleaseMask | EnterWindowMask |
+	PointerMotionMask | ExposureMask | StructureNotifyMask;
+
+#ifdef XEVDEV
+    if (useEvdev)
+	eventMask = ExposureMask | StructureNotifyMask;
+#endif
+
+    XSelectInput (xdisplay, pScreenPriv->win, eventMask);
+
+#if RANDR_12_INTERFACE
+    if (fullscreen && randrExtension)
+    {
+	XSelectInput (xdisplay, pScreenPriv->root, StructureNotifyMask);
+	XRRSelectInput (xdisplay, pScreenPriv->root, RRScreenChangeNotifyMask);
+    }
+#endif
 
     XMapWindow (xdisplay, pScreenPriv->win);
 
@@ -1297,9 +1894,6 @@ xglxWakeupHandler (pointer blockData,
 		   int     result,
 		   pointer pReadMask)
 {
-#ifdef XEVDEV
-    if (!useEvdev)
-#endif    	    
     xglxEnqueueEvents ();
 }
 
commit 67157794ae6d7741ade6b14c0ffd3bf0f3989112
Author: David Reveman <davidr at novell.com>
Date:   Tue Jan 15 19:06:51 2008 -0500

    Randr 1.2 from master.

diff --git a/configure.ac b/configure.ac
index 8947c24..3c451c4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -510,7 +510,7 @@ else
 	RENDERPROTO="renderproto"
 fi
 
-REQUIRED_MODULES="randrproto $RENDERPROTO [fixesproto >= 4.0] damageproto xcmiscproto xextproto xproto xtrans xf86miscproto xf86vidmodeproto xf86bigfontproto [scrnsaverproto >= 1.1] bigreqsproto resourceproto fontsproto inputproto xf86dgaproto"
+REQUIRED_MODULES="[randrproto >= 1.2] $RENDERPROTO [fixesproto >= 4.0] damageproto xcmiscproto xextproto xproto xtrans xf86miscproto xf86vidmodeproto xf86bigfontproto [scrnsaverproto >= 1.1] bigreqsproto resourceproto fontsproto inputproto xf86dgaproto"
 REQUIRED_LIBS="xfont xau fontenc"
 
 AM_CONDITIONAL(XV, [test "x$XV" = xyes])
diff --git a/randr/Makefile.am b/randr/Makefile.am
index 753eebb..20b0f72 100644
--- a/randr/Makefile.am
+++ b/randr/Makefile.am
@@ -1,6 +1,8 @@
 noinst_LTLIBRARIES = librandr.la
 
-AM_CFLAGS = $(DIX_CFLAGS) @SERVER_DEFINES@ @LOADER_DEFINES@
+AM_CFLAGS = $(DIX_CFLAGS)
+
+XINERAMA_SRCS = rrxinerama.c
 
 if XORG
 sdk_HEADERS = randrstr.h
@@ -9,4 +11,18 @@ endif
 librandr_la_SOURCES =	\
 	mirandr.c	\
 	randr.c		\
-	randrstr.h
+	randrstr.h	\
+	rrcrtc.c	\
+	rrdispatch.c	\
+	rrinfo.c	\
+	rrmode.c	\
+	rroutput.c	\
+	rrpointer.c	\
+	rrproperty.c	\
+	rrscreen.c	\
+	rrsdispatch.c
+
+if XINERAMA
+librandr_la_SOURCES += ${XINERAMA_SRCS}
+endif
+
diff --git a/randr/mirandr.c b/randr/mirandr.c
index b1e19a7..3c4991e 100644
--- a/randr/mirandr.c
+++ b/randr/mirandr.c
@@ -1,76 +1,42 @@
 /*
- * $XFree86: xc/programs/Xserver/randr/mirandr.c,v 1.5 2001/06/04 09:45:40 keithp Exp $
- *
- * Copyright © 2000, Compaq Computer Corporation, 
- * Copyright © 2002, Hewlett Packard, Inc.
+ * Copyright © 2000 Compaq Computer Corporation
+ * Copyright © 2002 Hewlett-Packard Company
+ * Copyright © 2006 Intel Corporation
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Compaq or HP not be used in advertising
- * or publicity pertaining to distribution of the software without specific,
- * written prior permission.  HP makes no representations about the
- * suitability of this software for any purpose.  It is provided "as is"
- * without express or implied warranty.
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
  *
- * HP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL HP
- * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
  *
- * Author:  Jim Gettys, HP Labs, Hewlett-Packard, Inc.
+ * Author:  Jim Gettys, Hewlett-Packard Company, Inc.
+ *	    Keith Packard, Intel Corporation
  */
 
-
 #ifdef HAVE_DIX_CONFIG_H
 #include <dix-config.h>
 #endif
 
 #include "scrnintstr.h"
 #include "mi.h"
-#include <X11/extensions/randr.h>
 #include "randrstr.h"
 #include <stdio.h>
 
-/*
- * This function assumes that only a single depth can be
- * displayed at a time, but that all visuals of that depth
- * can be displayed simultaneously.  It further assumes that
- * only a single size is available.  Hardware providing
- * additional capabilties should use different code.
- * XXX what to do here....
- */
-
 Bool
 miRRGetInfo (ScreenPtr pScreen, Rotation *rotations)
 {
-    int	i;
-    Bool setConfig = FALSE;
-    
-    *rotations = RR_Rotate_0;
-    for (i = 0; i < pScreen->numDepths; i++)
-    {
-	if (pScreen->allowedDepths[i].numVids)
-	{
-		RRScreenSizePtr		pSize;
-
-		pSize = RRRegisterSize (pScreen,
-					pScreen->width,
-					pScreen->height,
-					pScreen->mmWidth,
-					pScreen->mmHeight);
-		if (!pSize)
-		    return FALSE;
-		if (!setConfig)
-		{
-		    RRSetCurrentConfig (pScreen, RR_Rotate_0, 0, pSize);
-		    setConfig = TRUE;
-		}
-	}
-    }
     return TRUE;
 }
 
@@ -79,24 +45,110 @@ miRRGetInfo (ScreenPtr pScreen, Rotation *rotations)
  * different here
  */
 Bool
-miRRSetConfig (ScreenPtr	pScreen,
-	       Rotation		rotation,
-	       int		rate,
-	       RRScreenSizePtr	pSize)
+miRRCrtcSet (ScreenPtr	pScreen,
+	     RRCrtcPtr	crtc,
+	     RRModePtr	mode,
+	     int	x,
+	     int	y,
+	     Rotation	rotation,
+	     int	numOutput,
+	     RROutputPtr *outputs)
 {
     return TRUE;
 }
 
+static Bool
+miRRCrtcSetGamma (ScreenPtr	pScreen,
+		  RRCrtcPtr	crtc)
+{
+    return TRUE;
+}
+
+Bool
+miRROutputSetProperty (ScreenPtr	    pScreen,
+		       RROutputPtr	    output,
+		       Atom		    property,
+		       RRPropertyValuePtr   value)
+{
+    return TRUE;
+}
+
+Bool
+miRROutputValidateMode (ScreenPtr	    pScreen,
+			RROutputPtr	    output,
+			RRModePtr	    mode)
+{
+    return FALSE;
+}
+
+void
+miRRModeDestroy (ScreenPtr  pScreen,
+		 RRModePtr  mode)
+{
+}
+
+/*
+ * This function assumes that only a single depth can be
+ * displayed at a time, but that all visuals of that depth
+ * can be displayed simultaneously.  It further assumes that
+ * only a single size is available.  Hardware providing
+ * additional capabilties should use different code.
+ * XXX what to do here....
+ */
 
 Bool
 miRandRInit (ScreenPtr pScreen)
 {
-    rrScrPrivPtr    rp;
+    rrScrPrivPtr    pScrPriv;
+#if RANDR_12_INTERFACE
+    RRModePtr	mode;
+    RRCrtcPtr	crtc;
+    RROutputPtr	output;
+    xRRModeInfo modeInfo;
+    char	name[64];
+#endif
     
     if (!RRScreenInit (pScreen))
 	return FALSE;
-    rp = rrGetScrPriv(pScreen);
-    rp->rrGetInfo = miRRGetInfo;
-    rp->rrSetConfig = miRRSetConfig;
+    pScrPriv = rrGetScrPriv(pScreen);
+    pScrPriv->rrGetInfo = miRRGetInfo;
+#if RANDR_12_INTERFACE
+    pScrPriv->rrCrtcSet = miRRCrtcSet;
+    pScrPriv->rrCrtcSetGamma = miRRCrtcSetGamma;
+    pScrPriv->rrOutputSetProperty = miRROutputSetProperty;
+    pScrPriv->rrOutputValidateMode = miRROutputValidateMode;
+    pScrPriv->rrModeDestroy = miRRModeDestroy;
+    
+    RRScreenSetSizeRange (pScreen,
+			  pScreen->width, pScreen->height,
+			  pScreen->width, pScreen->height);
+
+    sprintf (name, "%dx%d", pScreen->width, pScreen->height);
+    memset (&modeInfo, '\0', sizeof (modeInfo));
+    modeInfo.width = pScreen->width;
+    modeInfo.height = pScreen->height;
+    modeInfo.nameLength = strlen (name);
+    
+    mode = RRModeGet (&modeInfo, name);
+    if (!mode)
+	return FALSE;
+    
+    crtc = RRCrtcCreate (pScreen, NULL);
+    if (!crtc)
+	return FALSE;
+    
+    output = RROutputCreate (pScreen, "screen", 6, NULL);
+    if (!output)
+	return FALSE;
+    if (!RROutputSetClones (output, NULL, 0))
+	return FALSE;
+    if (!RROutputSetModes (output, &mode, 1, 0))
+	return FALSE;
+    if (!RROutputSetCrtcs (output, &crtc, 1))
+	return FALSE;
+    if (!RROutputSetConnection (output, RR_Connected))
+	return FALSE;
+    RRCrtcNotify (crtc, mode, 0, 0, RR_Rotate_0, 1, &output);
+#endif
     return TRUE;
 }
diff --git a/randr/randr.c b/randr/randr.c
index bcaa232..958f9c1 100644
--- a/randr/randr.c
+++ b/randr/randr.c
@@ -1,55 +1,37 @@
 /*
- * $XFree86: xc/programs/Xserver/randr/randr.c,v 1.21tsi Exp $
- *
- * Copyright © 2000, Compaq Computer Corporation, 
- * Copyright © 2002, Hewlett Packard, Inc.
+ * Copyright © 2000 Compaq Computer Corporation
+ * Copyright © 2002 Hewlett-Packard Company
+ * Copyright © 2006 Intel Corporation
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Compaq or HP not be used in advertising
- * or publicity pertaining to distribution of the software without specific,
- * written prior permission.  HP makes no representations about the
- * suitability of this software for any purpose.  It is provided "as is"
- * without express or implied warranty.
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
  *
- * HP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL HP
- * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
  *
- * Author:  Jim Gettys, HP Labs, Hewlett-Packard, Inc.
+ * Author:  Jim Gettys, Hewlett-Packard Company, Inc.
+ *	    Keith Packard, Intel Corporation
  */
 
-
 #define NEED_REPLIES
 #define NEED_EVENTS
 #ifdef HAVE_DIX_CONFIG_H
 #include <dix-config.h>
 #endif
 
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include "misc.h"
-#include "os.h"
-#include "dixstruct.h"
-#include "resource.h"
-#include "scrnintstr.h"
-#include "windowstr.h"
-#include "pixmapstr.h"
-#include "extnsionst.h"
-#include "servermd.h"
-#include <X11/extensions/randr.h>
-#include <X11/extensions/randrproto.h>
 #include "randrstr.h"
-#ifdef RENDER
-#include <X11/extensions/render.h> 	/* we share subpixel order information */
-#include "picturestr.h"
-#endif
-#include <X11/Xfuncproto.h>
 
 /* From render.h */
 #ifndef SubPixelUnknown
@@ -57,13 +39,7 @@
 #endif
 
 #define RR_VALIDATE
-int	RRGeneration;
-int	RRNScreens;
-
-static int ProcRRQueryVersion (ClientPtr pClient);
-static int ProcRRDispatch (ClientPtr pClient);
-static int SProcRRDispatch (ClientPtr pClient);
-static int SProcRRQueryVersion (ClientPtr pClient);
+static int	RRNScreens;
 
 #define wrap(priv,real,mem,func) {\
     priv->mem = real->mem; \
@@ -74,57 +50,16 @@ static int SProcRRQueryVersion (ClientPtr pClient);
     real->mem = priv->mem; \
 }
 
-#if 0
-static CARD8	RRReqCode;
-static int	RRErrBase;
-#endif
-static int	RREventBase;
-static RESTYPE ClientType, EventType; /* resource types for event masks */
-static int	RRClientPrivateIndex;
-
-typedef struct _RRTimes {
-    TimeStamp	setTime;
-    TimeStamp	configTime;
-} RRTimesRec, *RRTimesPtr;
-
-typedef struct _RRClient {
-    int		major_version;
-    int		minor_version;
-/*  RRTimesRec	times[0]; */
-} RRClientRec, *RRClientPtr;
-
-/*
- * each window has a list of clients requesting
- * RRNotify events.  Each client has a resource
- * for each window it selects RRNotify input for,
- * this resource is used to delete the RRNotifyRec
- * entry from the per-window queue.
- */
-
-typedef struct _RREvent *RREventPtr;
+static int ProcRRDispatch (ClientPtr pClient);
+static int SProcRRDispatch (ClientPtr pClient);
 
-typedef struct _RREvent {
-    RREventPtr  next;
-    ClientPtr	client;
-    WindowPtr	window;
-    XID		clientResource;
-    int		mask;
-} RREventRec;
+int	RREventBase;
+int	RRErrorBase;
+RESTYPE RRClientType, RREventType; /* resource types for event masks */
+int	RRClientPrivateIndex;
 
 int	rrPrivIndex = -1;
 
-#define GetRRClient(pClient)    ((RRClientPtr) (pClient)->devPrivates[RRClientPrivateIndex].ptr)
-#define rrClientPriv(pClient)	RRClientPtr pRRClient = GetRRClient(pClient)
-
-static Bool
-RRClientKnowsRates (ClientPtr	pClient)
-{
-    rrClientPriv(pClient);
-
-    return (pRRClient->major_version > 1 ||
-	    (pRRClient->major_version == 1 && pRRClient->minor_version >= 1));
-}
-
 static void
 RRClientCallback (CallbackListPtr	*list,
 		  pointer		closure,
@@ -160,10 +95,14 @@ static Bool
 RRCloseScreen (int i, ScreenPtr pScreen)
 {
     rrScrPriv(pScreen);
+    int		    j;
 
     unwrap (pScrPriv, pScreen, CloseScreen);
-    if (pScrPriv->pSizes)
-	xfree (pScrPriv->pSizes);
+    for (j = pScrPriv->numCrtcs - 1; j >= 0; j--)
+	RRCrtcDestroy (pScrPriv->crtcs[j]);
+    for (j = pScrPriv->numOutputs - 1; j >= 0; j--)
+	RROutputDestroy (pScrPriv->outputs[j]);
+    
     xfree (pScrPriv);
     RRNScreens -= 1;	/* ok, one fewer screen with RandR running */
     return (*pScreen->CloseScreen) (i, pScreen);    
@@ -188,18 +127,110 @@ SRRScreenChangeNotifyEvent(xRRScreenChangeNotifyEvent *from,
     cpswaps(from->subpixelOrder, to->subpixelOrder);
 }
 
+static void
+SRRCrtcChangeNotifyEvent(xRRCrtcChangeNotifyEvent *from,
+			 xRRCrtcChangeNotifyEvent *to)
+{
+    to->type = from->type;
+    to->subCode = from->subCode;
+    cpswaps(from->sequenceNumber, to->sequenceNumber);
+    cpswapl(from->timestamp, to->timestamp);
+    cpswapl(from->window, to->window);
+    cpswapl(from->crtc, to->crtc);
+    cpswapl(from->mode, to->mode);
+    cpswapl(from->window, to->window);
+    cpswaps(from->rotation, to->rotation);
+    cpswaps(from->x, to->x);
+    cpswaps(from->y, to->y);
+    cpswaps(from->width, to->width);
+    cpswaps(from->height, to->height);
+}
+
+static void
+SRROutputChangeNotifyEvent(xRROutputChangeNotifyEvent *from,
+			   xRROutputChangeNotifyEvent *to)
+{
+    to->type = from->type;
+    to->subCode = from->subCode;
+    cpswaps(from->sequenceNumber, to->sequenceNumber);
+    cpswapl(from->timestamp, to->timestamp);
+    cpswapl(from->configTimestamp, to->configTimestamp);
+    cpswapl(from->window, to->window);
+    cpswapl(from->output, to->output);
+    cpswapl(from->crtc, to->crtc);
+    cpswapl(from->mode, to->mode);
+    cpswaps(from->rotation, to->rotation);
+}
+
+static void
+SRROutputPropertyNotifyEvent(xRROutputPropertyNotifyEvent *from,
+			     xRROutputPropertyNotifyEvent *to)
+{
+    to->type = from->type;
+    to->subCode = from->subCode;
+    cpswaps(from->sequenceNumber, to->sequenceNumber);
+    cpswapl(from->window, to->window);
+    cpswapl(from->output, to->output);
+    cpswapl(from->atom, to->atom);
+    cpswapl(from->timestamp, to->timestamp);
+}
+
+static void
+SRRNotifyEvent (xEvent *from,
+		xEvent *to)
+{
+    switch (from->u.u.detail) {
+    case RRNotify_CrtcChange:
+	SRRCrtcChangeNotifyEvent ((xRRCrtcChangeNotifyEvent *) from,
+				  (xRRCrtcChangeNotifyEvent *) to);
+	break;
+    case RRNotify_OutputChange:
+	SRROutputChangeNotifyEvent ((xRROutputChangeNotifyEvent *) from,
+				    (xRROutputChangeNotifyEvent *) to);
+	break;
+    case RRNotify_OutputProperty:
+	SRROutputPropertyNotifyEvent ((xRROutputPropertyNotifyEvent *) from,
+				      (xRROutputPropertyNotifyEvent *) to);
+	break;
+    default:
+	break;
+    }
+}
+
+static int RRGeneration;
+
+Bool RRInit (void)
+{
+    if (RRGeneration != serverGeneration)
+    {
+	if (!RRModeInit ())
+	    return FALSE;
+	if (!RRCrtcInit ())
+	    return FALSE;
+	if (!RROutputInit ())
+	    return FALSE;
+	RRGeneration = serverGeneration;
+    }
+    return TRUE;
+}
+
+static int RRScreenGeneration;
+
 Bool RRScreenInit(ScreenPtr pScreen)
 {
     rrScrPrivPtr   pScrPriv;
 
-    if (RRGeneration != serverGeneration)
+    if (!RRInit ())
+	return FALSE;
+
+    if (RRScreenGeneration != serverGeneration)
     {
 	if ((rrPrivIndex = AllocateScreenPrivateIndex()) < 0)
 	    return FALSE;
-	RRGeneration = serverGeneration;
+	RRScreenGeneration = serverGeneration;
     }
 
-    pScrPriv = (rrScrPrivPtr) xalloc (sizeof (rrScrPrivRec));
+    pScrPriv = (rrScrPrivPtr) xcalloc (1, sizeof (rrScrPrivRec));
     if (!pScrPriv)
 	return FALSE;
 
@@ -208,8 +239,31 @@ Bool RRScreenInit(ScreenPtr pScreen)
     /*
      * Calling function best set these function vectors
      */
-    pScrPriv->rrSetConfig = 0;
     pScrPriv->rrGetInfo = 0;
+    pScrPriv->maxWidth = pScrPriv->minWidth = pScreen->width;
+    pScrPriv->maxHeight = pScrPriv->minHeight = pScreen->height;
+    
+    pScrPriv->width = pScreen->width;
+    pScrPriv->height = pScreen->height;
+    pScrPriv->mmWidth = pScreen->mmWidth;
+    pScrPriv->mmHeight = pScreen->mmHeight;
+#if RANDR_12_INTERFACE
+    pScrPriv->rrScreenSetSize = NULL;
+    pScrPriv->rrCrtcSet = NULL;
+    pScrPriv->rrCrtcSetGamma = NULL;
+#endif
+#if RANDR_10_INTERFACE    
+    pScrPriv->rrSetConfig = 0;
+    pScrPriv->rotations = RR_Rotate_0;
+    pScrPriv->reqWidth = pScreen->width;
+    pScrPriv->reqHeight = pScreen->height;
+    pScrPriv->nSizes = 0;
+    pScrPriv->pSizes = NULL;
+    pScrPriv->rotation = RR_Rotate_0;
+    pScrPriv->rate = 0;
+    pScrPriv->size = 0;
+#endif
+    
     /*
      * This value doesn't really matter -- any client must call
      * GetScreenInfo before reading it which will automatically update
@@ -220,14 +274,10 @@ Bool RRScreenInit(ScreenPtr pScreen)
     
     wrap (pScrPriv, pScreen, CloseScreen, RRCloseScreen);
 
-    pScrPriv->rotations = RR_Rotate_0;
-    
-    pScrPriv->nSizes = 0;
-    pScrPriv->nSizesInUse = 0;
-    pScrPriv->pSizes = 0;
-    
-    pScrPriv->rotation = RR_Rotate_0;
-    pScrPriv->size = -1;
+    pScrPriv->numOutputs = 0;
+    pScrPriv->outputs = NULL;
+    pScrPriv->numCrtcs = 0;
+    pScrPriv->crtcs = NULL;
     
     RRNScreens += 1;	/* keep count of screens that implement randr */
     return TRUE;
@@ -243,7 +293,7 @@ RRFreeClient (pointer data, XID id)
 
     pRREvent = (RREventPtr) data;
     pWin = pRREvent->window;
-    pHead = (RREventPtr *) LookupIDByType(pWin->drawable.id, EventType);
+    pHead = (RREventPtr *) LookupIDByType(pWin->drawable.id, RREventType);
     if (pHead) {
 	pPrev = 0;
 	for (pCur = *pHead; pCur && pCur != pRREvent; pCur=pCur->next)
@@ -269,7 +319,7 @@ RRFreeEvents (pointer data, XID id)
     pHead = (RREventPtr *) data;
     for (pCur = *pHead; pCur; pCur = pNext) {
 	pNext = pCur->next;
-	FreeResource (pCur->clientResource, ClientType);
+	FreeResource (pCur->clientResource, RRClientType);
 	xfree ((pointer) pCur);
     }
     xfree ((pointer) pHead);
@@ -291,1037 +341,157 @@ RRExtensionInit (void)
     if (!AddCallback (&ClientStateCallback, RRClientCallback, 0))
 	return;
 
-    ClientType = CreateNewResourceType(RRFreeClient);
-    if (!ClientType)
+    RRClientType = CreateNewResourceType(RRFreeClient);
+    if (!RRClientType)
 	return;
-    EventType = CreateNewResourceType(RRFreeEvents);
-    if (!EventType)
+    RREventType = CreateNewResourceType(RRFreeEvents);
+    if (!RREventType)
 	return;
     extEntry = AddExtension (RANDR_NAME, RRNumberEvents, RRNumberErrors,
 			     ProcRRDispatch, SProcRRDispatch,
 			     RRResetProc, StandardMinorOpcode);
     if (!extEntry)
 	return;
-#if 0
-    RRReqCode = (CARD8) extEntry->base;
-    RRErrBase = extEntry->errorBase;
-#endif
+    RRErrorBase = extEntry->errorBase;
     RREventBase = extEntry->eventBase;
     EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr) 
-      SRRScreenChangeNotifyEvent;
-
-    return;
+	SRRScreenChangeNotifyEvent;
+    EventSwapVector[RREventBase + RRNotify] = (EventSwapPtr)
+	SRRNotifyEvent;
+#ifdef PANORAMIX
+    RRXineramaExtensionInit();
+#endif
 }
-		
+
 static int
 TellChanged (WindowPtr pWin, pointer value)
 {
     RREventPtr			*pHead, pRREvent;
     ClientPtr			client;
-    xRRScreenChangeNotifyEvent	se;
     ScreenPtr			pScreen = pWin->drawable.pScreen;
     rrScrPriv(pScreen);
-    RRScreenSizePtr		pSize;
-    WindowPtr			pRoot = WindowTable[pScreen->myNum];
+    int				i;
 
-    pHead = (RREventPtr *) LookupIDByType (pWin->drawable.id, EventType);
+    pHead = (RREventPtr *) LookupIDByType (pWin->drawable.id, RREventType);
     if (!pHead)
 	return WT_WALKCHILDREN;
 
-    se.type = RRScreenChangeNotify + RREventBase;
-    se.rotation = (CARD8) pScrPriv->rotation;
-    se.timestamp = pScrPriv->lastSetTime.milliseconds;
-    se.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
-    se.root =  pRoot->drawable.id;
-    se.window = pWin->drawable.id;
-#ifdef RENDER
-    se.subpixelOrder = PictureGetSubpixelOrder (pScreen);
-#else
-    se.subpixelOrder = SubPixelUnknown;
-#endif
-    if (pScrPriv->size >= 0)
-    {
-	pSize = &pScrPriv->pSizes[pScrPriv->size];
-	se.sizeID = pSize->id;
-	se.widthInPixels = pSize->width;
-	se.heightInPixels = pSize->height;
-	se.widthInMillimeters = pSize->mmWidth;
-	se.heightInMillimeters = pSize->mmHeight;
-    }
-    else
-    {
-	/*
-	 * This "shouldn't happen", but a broken DDX can
-	 * forget to set the current configuration on GetInfo
-	 */
-	se.sizeID = 0xffff;
-	se.widthInPixels = 0;
-	se.heightInPixels = 0;
-	se.widthInMillimeters = 0;
-	se.heightInMillimeters = 0;
-    }    
     for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) 
     {
 	client = pRREvent->client;
 	if (client == serverClient || client->clientGone)
 	    continue;
-	se.sequenceNumber = client->sequence;
-	if(pRREvent->mask & RRScreenChangeNotifyMask)
-	  WriteEventsToClient (client, 1, (xEvent *) &se);
-    }
-    return WT_WALKCHILDREN;
-}
 
-static Bool
-RRGetInfo (ScreenPtr pScreen)
-{
-    rrScrPriv (pScreen);
-    int		    i, j, k, l;
-    Bool	    changed;
-    Rotation	    rotations;
-    RRScreenSizePtr pSize;
-    RRScreenRatePtr pRate;
-
-    for (i = 0; i < pScrPriv->nSizes; i++)
-    {
-	pSize = &pScrPriv->pSizes[i];
-	pSize->oldReferenced = pSize->referenced;
-	pSize->referenced = FALSE;
-	for (k = 0; k < pSize->nRates; k++)
-	{
-	    pRate = &pSize->pRates[k];
-	    pRate->oldReferenced = pRate->referenced;
-	    pRate->referenced = FALSE;
-	}
-    }
-    if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations))
-	return FALSE;
-
-    changed = FALSE;
-
-    /*
-     * Check whether anything changed and simultaneously generate
-     * the protocol id values for the objects
-     */
-    if (rotations != pScrPriv->rotations)
-    {
-	pScrPriv->rotations = rotations;
-	changed = TRUE;
-    }
-
-    j = 0;
-    for (i = 0; i < pScrPriv->nSizes; i++)
-    {
-	pSize = &pScrPriv->pSizes[i];
-	if (pSize->oldReferenced != pSize->referenced)
-	    changed = TRUE;
-	if (pSize->referenced)
-	    pSize->id = j++;
-	l = 0;
-	for (k = 0; k < pSize->nRates; k++)
-	{
-	    pRate = &pSize->pRates[k];
-	    if (pRate->oldReferenced != pRate->referenced)
-		changed = TRUE;
-	    if (pRate->referenced)
-		l++;
-	}
-	pSize->nRatesInUse = l;
-    }
-    pScrPriv->nSizesInUse = j;
-    if (changed)
-    {
-	UpdateCurrentTime ();
-	pScrPriv->lastConfigTime = currentTime;
-	WalkTree (pScreen, TellChanged, (pointer) pScreen);
-    }
-    return TRUE;
-}
-
-static void
-RRSendConfigNotify (ScreenPtr pScreen)
-{
-    WindowPtr	pWin = WindowTable[pScreen->myNum];
-    xEvent	event;
-
-    event.u.u.type = ConfigureNotify;
-    event.u.configureNotify.window = pWin->drawable.id;
-    event.u.configureNotify.aboveSibling = None;
-    event.u.configureNotify.x = 0;
-    event.u.configureNotify.y = 0;
-
-    /* XXX xinerama stuff ? */
-    
-    event.u.configureNotify.width = pWin->drawable.width;
-    event.u.configureNotify.height = pWin->drawable.height;
-    event.u.configureNotify.borderWidth = wBorderWidth (pWin);
-    event.u.configureNotify.override = pWin->overrideRedirect;
-    DeliverEvents(pWin, &event, 1, NullWindow);
-}
-
-static int
-ProcRRQueryVersion (ClientPtr client)
-{
-    xRRQueryVersionReply rep;
-    register int n;
-    REQUEST(xRRQueryVersionReq);
-    rrClientPriv(client);
-
-    REQUEST_SIZE_MATCH(xRRQueryVersionReq);
-    pRRClient->major_version = stuff->majorVersion;
-    pRRClient->minor_version = stuff->minorVersion;
-    rep.type = X_Reply;
-    rep.length = 0;
-    rep.sequenceNumber = client->sequence;
-    rep.majorVersion = RANDR_MAJOR;
-    rep.minorVersion = RANDR_MINOR;
-    if (client->swapped) {
-    	swaps(&rep.sequenceNumber, n);
-    	swapl(&rep.length, n);
-	swapl(&rep.majorVersion, n);
-	swapl(&rep.minorVersion, n);
-    }
-    WriteToClient(client, sizeof(xRRQueryVersionReply), (char *)&rep);
-    return (client->noClientException);
-}
-
-
-extern char	*ConnectionInfo;
-
-static int padlength[4] = {0, 3, 2, 1};
-
-static void
-RREditConnectionInfo (ScreenPtr pScreen)
-{
-    xConnSetup	    *connSetup;
-    char	    *vendor;
-    xPixmapFormat   *formats;
-    xWindowRoot	    *root;
-    xDepth	    *depth;
-    xVisualType	    *visual;
-    int		    screen = 0;
-    int		    d;
-
-    connSetup = (xConnSetup *) ConnectionInfo;
-    vendor = (char *) connSetup + sizeof (xConnSetup);
-    formats = (xPixmapFormat *) ((char *) vendor +
-				 connSetup->nbytesVendor +
-				 padlength[connSetup->nbytesVendor & 3]);
-    root = (xWindowRoot *) ((char *) formats +
-			    sizeof (xPixmapFormat) * screenInfo.numPixmapFormats);
-    while (screen != pScreen->myNum)
-    {
-	depth = (xDepth *) ((char *) root + 
-			    sizeof (xWindowRoot));
-	for (d = 0; d < root->nDepths; d++)
-	{
-	    visual = (xVisualType *) ((char *) depth +
-				      sizeof (xDepth));
-	    depth = (xDepth *) ((char *) visual +
-				depth->nVisuals * sizeof (xVisualType));
-	}
-	root = (xWindowRoot *) ((char *) depth);
-	screen++;
-    }
-    root->pixWidth = pScreen->width;
-    root->pixHeight = pScreen->height;
-    root->mmWidth = pScreen->mmWidth;
-    root->mmHeight = pScreen->mmHeight;
-}
-
-static int
-ProcRRGetScreenInfo (ClientPtr client)
-{
-    REQUEST(xRRGetScreenInfoReq);
-    xRRGetScreenInfoReply   rep;
-    WindowPtr	    	    pWin;
-    int			    n;
-    ScreenPtr		    pScreen;
-    rrScrPrivPtr	    pScrPriv;
-    CARD8		    *extra;
-    unsigned long	    extraLen;
-
-    REQUEST_SIZE_MATCH(xRRGetScreenInfoReq);
-    pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
-					   SecurityReadAccess);
-
-    if (!pWin)
-	return BadWindow;
-
-    pScreen = pWin->drawable.pScreen;
-    pScrPriv = rrGetScrPriv(pScreen);
-    rep.pad = 0;
-    if (!pScrPriv)
-    {
-	rep.type = X_Reply;
-	rep.setOfRotations = RR_Rotate_0;;
-	rep.sequenceNumber = client->sequence;
-	rep.length = 0;
-	rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
-	rep.timestamp = currentTime.milliseconds;
-	rep.configTimestamp = currentTime.milliseconds;
-	rep.nSizes = 0;
-	rep.sizeID = 0;
-	rep.rotation = RR_Rotate_0;
-	rep.rate = 0;
-	rep.nrateEnts = 0;
-	extra = 0;
-	extraLen = 0;
-    }
-    else
-    {
-	int			i, j;
-	xScreenSizes		*size;
-	CARD16			*rates;
-	CARD8			*data8;
-	Bool			has_rate = RRClientKnowsRates (client);
-    
-	RRGetInfo (pScreen);
-
-	rep.type = X_Reply;
-	rep.setOfRotations = pScrPriv->rotations;
-	rep.sequenceNumber = client->sequence;
-	rep.length = 0;
-	rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
-	rep.timestamp = pScrPriv->lastSetTime.milliseconds;
-	rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
-	rep.rotation = pScrPriv->rotation;
-	rep.nSizes = pScrPriv->nSizesInUse;
-	rep.rate = pScrPriv->rate;
-        rep.nrateEnts = 0;
-	if (has_rate)
+	if (pRREvent->mask & RRScreenChangeNotifyMask)
+	    RRDeliverScreenEvent (client, pWin, pScreen);
+	
+	if (pRREvent->mask & RRCrtcChangeNotifyMask)
 	{
-	    for (i = 0; i < pScrPriv->nSizes; i++)
+	    for (i = 0; i < pScrPriv->numCrtcs; i++)
 	    {
-		RRScreenSizePtr pSize = &pScrPriv->pSizes[i];
-		if (pSize->referenced)
-		{
-		    rep.nrateEnts += (1 + pSize->nRatesInUse);
-		}
+		RRCrtcPtr   crtc = pScrPriv->crtcs[i];
+		if (crtc->changed)
+		    RRDeliverCrtcEvent (client, pWin, crtc);
 	    }
 	}
-
-	if (pScrPriv->size >= 0)
-	    rep.sizeID = pScrPriv->pSizes[pScrPriv->size].id;
-	else
-	    return BadImplementation;
-
-	extraLen = (rep.nSizes * sizeof (xScreenSizes) +
-		    rep.nrateEnts * sizeof (CARD16));
-
-	extra = (CARD8 *) xalloc (extraLen);
-	if (!extra)
-	    return BadAlloc;
-	/*
-	 * First comes the size information
-	 */
-	size = (xScreenSizes *) extra;
-	rates = (CARD16 *) (size + rep.nSizes);
-	for (i = 0; i < pScrPriv->nSizes; i++)
+	
+	if (pRREvent->mask & RROutputChangeNotifyMask)
 	{
-	    RRScreenSizePtr pSize = &pScrPriv->pSizes[i];
-	    if (pSize->referenced)
+	    for (i = 0; i < pScrPriv->numOutputs; i++)
 	    {
-		size->widthInPixels = pSize->width;
-		size->heightInPixels = pSize->height;
-		size->widthInMillimeters = pSize->mmWidth;
-		size->heightInMillimeters = pSize->mmHeight;
-		if (client->swapped)
-		{
-		    swaps (&size->widthInPixels, n);
-		    swaps (&size->heightInPixels, n);
-		    swaps (&size->widthInMillimeters, n);
-		    swaps (&size->heightInMillimeters, n);
-		}
-		size++;
-		if (has_rate)
-		{
-		    *rates = pSize->nRatesInUse;
-		    if (client->swapped)
-		    {
-			swaps (rates, n);
-		    }
-		    rates++;
-		    for (j = 0; j < pSize->nRates; j++)
-		    {
-			RRScreenRatePtr	pRate = &pSize->pRates[j];
-			if (pRate->referenced)
-			{
-			    *rates = pRate->rate;
-			    if (client->swapped)
-			    {
-				swaps (rates, n);
-			    }
-			    rates++;
-			}
-		    }
-		}
+		RROutputPtr   output = pScrPriv->outputs[i];
+		if (output->changed)
+		    RRDeliverOutputEvent (client, pWin, output);
 	    }
 	}
-	data8 = (CARD8 *) rates;
-
-	if (data8 - (CARD8 *) extra != extraLen)
-	    FatalError ("RRGetScreenInfo bad extra len %ld != %ld\n",
-			(unsigned long)(data8 - (CARD8 *) extra), extraLen);
-	rep.length =  (extraLen + 3) >> 2;
-    }
-    if (client->swapped) {
-	swaps(&rep.sequenceNumber, n);
-	swapl(&rep.length, n);
-	swapl(&rep.timestamp, n);
-	swaps(&rep.rotation, n);
-	swaps(&rep.nSizes, n);
-	swaps(&rep.sizeID, n);
-	swaps(&rep.rate, n);
-	swaps(&rep.nrateEnts, n);
-    }
-    WriteToClient(client, sizeof(xRRGetScreenInfoReply), (char *)&rep);
-    if (extraLen)
-    {
-	WriteToClient (client, extraLen, (char *) extra);
-	xfree (extra);
     }
-    return (client->noClientException);
+    return WT_WALKCHILDREN;
 }
 
-static int
-ProcRRSetScreenConfig (ClientPtr client)
+/*
+ * Something changed; send events and adjust pointer position
+ */
+void
+RRTellChanged (ScreenPtr pScreen)
 {
-    REQUEST(xRRSetScreenConfigReq);
-    xRRSetScreenConfigReply rep;
-    DrawablePtr		    pDraw;
-    int			    n;
-    ScreenPtr		    pScreen;
-    rrScrPrivPtr	    pScrPriv;
-    TimeStamp		    configTime;
-    TimeStamp		    time;
-    RRScreenSizePtr	    pSize;
-    int			    i;
-    Rotation		    rotation;
-    int			    rate;
-    short		    oldWidth, oldHeight;
-    Bool		    has_rate;
-
-    UpdateCurrentTime ();
-
-    if (RRClientKnowsRates (client))
-    {
-	REQUEST_SIZE_MATCH (xRRSetScreenConfigReq);
-	has_rate = TRUE;
-    }
-    else
-    {
-	REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq);
-	has_rate = FALSE;
-    }
-    
-    SECURITY_VERIFY_DRAWABLE(pDraw, stuff->drawable, client,
-			     SecurityWriteAccess);
-
-    pScreen = pDraw->pScreen;
-
-    pScrPriv = rrGetScrPriv(pScreen);
-    
-    time = ClientTimeToServerTime(stuff->timestamp);
-    configTime = ClientTimeToServerTime(stuff->configTimestamp);
-    
-    oldWidth = pScreen->width;
-    oldHeight = pScreen->height;
-    
-    if (!pScrPriv)
-    {
-	time = currentTime;
-	rep.status = RRSetConfigFailed;
-	goto sendReply;
-    }
-    if (!RRGetInfo (pScreen))
-	return BadAlloc;
-    
-    /*
-     * if the client's config timestamp is not the same as the last config
-     * timestamp, then the config information isn't up-to-date and
-     * can't even be validated
-     */
-    if (CompareTimeStamps (configTime, pScrPriv->lastConfigTime) != 0)
-    {
-	rep.status = RRSetConfigInvalidConfigTime;
-	goto sendReply;
-    }
-    
-    /*
-     * Search for the requested size
-     */
-    pSize = 0;
-    for (i = 0; i < pScrPriv->nSizes; i++)
-    {
-	pSize = &pScrPriv->pSizes[i];
-	if (pSize->referenced && pSize->id == stuff->sizeID)
-	{
-	    break;
-	}
-    }
-    if (i == pScrPriv->nSizes)
-    {
-	/*
-	 * Invalid size ID
-	 */
-	client->errorValue = stuff->sizeID;
-	return BadValue;
-    }
+    rrScrPriv (pScreen);
+    int i;
     
-    /*
-     * Validate requested rotation
-     */
-    rotation = (Rotation) stuff->rotation;
-
-    /* test the rotation bits only! */
-    switch (rotation & 0xf) {
-    case RR_Rotate_0:
-    case RR_Rotate_90:
-    case RR_Rotate_180:
-    case RR_Rotate_270:
-	break;
-    default:
-	/*
-	 * Invalid rotation
-	 */
-	client->errorValue = stuff->rotation;
-	return BadValue;
-    }
-
-    if ((~pScrPriv->rotations) & rotation)
+    if (pScrPriv->changed)
     {
-	/*
-	 * requested rotation or reflection not supported by screen
-	 */
-	client->errorValue = stuff->rotation;
-	return BadMatch;
-    }
-
-    /*
-     * Validate requested refresh
-     */
-    if (has_rate)
-	rate = (int) stuff->rate;
-    else
-	rate = 0;
-
-    if (rate)
-    {
-	for (i = 0; i < pSize->nRates; i++)
+	UpdateCurrentTime ();
+	if (pScrPriv->configChanged)
 	{
-	    RRScreenRatePtr pRate = &pSize->pRates[i];
-	    if (pRate->referenced && pRate->rate == rate)
-		break;
+	    pScrPriv->lastConfigTime = currentTime;
+	    pScrPriv->configChanged = FALSE;
 	}
-	if (i == pSize->nRates)
+	pScrPriv->changed = FALSE;
+	WalkTree (pScreen, TellChanged, (pointer) pScreen);
+	for (i = 0; i < pScrPriv->numOutputs; i++)
+	    pScrPriv->outputs[i]->changed = FALSE;
+	for (i = 0; i < pScrPriv->numCrtcs; i++)
+	    pScrPriv->crtcs[i]->changed = FALSE;
+	if (pScrPriv->layoutChanged)
 	{
-	    /*
-	     * Invalid rate
-	     */
-	    client->errorValue = rate;
-	    return BadValue;
+	    pScrPriv->layoutChanged = FALSE;
+	    RRPointerScreenConfigured (pScreen);
+	    RRSendConfigNotify (pScreen);
 	}
     }
-    
-    /*
-     * Make sure the requested set-time is not older than
-     * the last set-time
-     */
-    if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0)
-    {
-	rep.status = RRSetConfigInvalidTime;
-	goto sendReply;
-    }
-
-    /*
-     * call out to ddx routine to effect the change
-     */
-    if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate,
-				   pSize))
-    {
-	/*
-	 * unknown DDX failure, report to client
-	 */
-	rep.status = RRSetConfigFailed;
-	goto sendReply;
-    }
-    
-    /*
-     * set current extension configuration pointers
-     */
-    RRSetCurrentConfig (pScreen, rotation, rate, pSize);
-    
-    /*
-     * Deliver ScreenChangeNotify events whenever
-     * the configuration is updated
-     */
-    WalkTree (pScreen, TellChanged, (pointer) pScreen);
-    
-    /*
-     * Deliver ConfigureNotify events when root changes
-     * pixel size
-     */
-    if (oldWidth != pScreen->width || oldHeight != pScreen->height)
-	RRSendConfigNotify (pScreen);
-    RREditConnectionInfo (pScreen);
-    
-    /*
-     * Fix pointer bounds and location
-     */
-    ScreenRestructured (pScreen);
-    pScrPriv->lastSetTime = time;
-    
-    /*
-     * Report Success
-     */
-    rep.status = RRSetConfigSuccess;
-    
-sendReply:
-    
-    rep.type = X_Reply;
-    /* rep.status has already been filled in */
-    rep.length = 0;
-    rep.sequenceNumber = client->sequence;
-
-    rep.newTimestamp = pScrPriv->lastSetTime.milliseconds;
-    rep.newConfigTimestamp = pScrPriv->lastConfigTime.milliseconds;
-    rep.root = WindowTable[pDraw->pScreen->myNum]->drawable.id;
-
-    if (client->swapped) 
-    {
-    	swaps(&rep.sequenceNumber, n);
-    	swapl(&rep.length, n);
-	swapl(&rep.newTimestamp, n);
-	swapl(&rep.newConfigTimestamp, n);
-	swapl(&rep.root, n);
-    }
-    WriteToClient(client, sizeof(xRRSetScreenConfigReply), (char *)&rep);
-
-    return (client->noClientException);
 }
 
-int
-RRSetScreenConfig (ScreenPtr		pScreen,
-		   Rotation		rotation,
-		   int			rate,
-		   RRScreenSizePtr	pSize)
+/*
+ * Return the first output which is connected to an active CRTC
+ * Used in emulating 1.0 behaviour
+ */
+RROutputPtr
+RRFirstOutput (ScreenPtr pScreen)
 {
-    rrScrPrivPtr	    pScrPriv;
-    int			    i;
-    short		    oldWidth, oldHeight;
-
-    pScrPriv = rrGetScrPriv(pScreen);
-    
-    oldWidth = pScreen->width;
-    oldHeight = pScreen->height;
-    
-    if (!RRGetInfo (pScreen))
-	return BadAlloc;
+    rrScrPriv(pScreen);
+    RROutputPtr		    output;
+    int	i, j;
     
-    /*
-     * Validate requested rotation
-     */
-
-    /* test the rotation bits only! */
-    switch (rotation & 0xf) {
-    case RR_Rotate_0:
-    case RR_Rotate_90:
-    case RR_Rotate_180:
-    case RR_Rotate_270:
-	break;
-    default:
-	/*
-	 * Invalid rotation
-	 */
-	return BadValue;
-    }
-
-    if ((~pScrPriv->rotations) & rotation)
-    {
-	/*
-	 * requested rotation or reflection not supported by screen
-	 */
-	return BadMatch;
-    }
-
-    /*
-     * Validate requested refresh
-     */
-    if (rate)
+    for (i = 0; i < pScrPriv->numCrtcs; i++)
     {
-	for (i = 0; i < pSize->nRates; i++)
-	{
-	    RRScreenRatePtr pRate = &pSize->pRates[i];
-	    if (pRate->referenced && pRate->rate == rate)
-		break;
-	}
-	if (i == pSize->nRates)
+	RRCrtcPtr   crtc = pScrPriv->crtcs[i];
+	for (j = 0; j < pScrPriv->numOutputs; j++)
 	{
-	    /*
-	     * Invalid rate
-	     */
-	    return BadValue;
+	    output = pScrPriv->outputs[j];
+	    if (output->crtc == crtc)
+		return output;
 	}
     }
-
-    /*
-     * call out to ddx routine to effect the change
-     */
-    if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate,
-				   pSize))
-    {
-	/*
-	 * unknown DDX failure, report to client
-	 */
-        return BadImplementation;
-    }
-    
-    /*
-     * set current extension configuration pointers
-     */
-    RRSetCurrentConfig (pScreen, rotation, rate, pSize);
-    
-    /*
-     * Deliver ScreenChangeNotify events whenever
-     * the configuration is updated
-     */
-    WalkTree (pScreen, TellChanged, (pointer) pScreen);
-    
-    /*
-     * Deliver ConfigureNotify events when root changes
-     * pixel size
-     */
-    if (oldWidth != pScreen->width || oldHeight != pScreen->height)
-	RRSendConfigNotify (pScreen);
-    RREditConnectionInfo (pScreen);
-    
-    /*
-     * Fix pointer bounds and location
-     */
-    ScreenRestructured (pScreen);
-    
-    return Success;
+    return NULL;
 }
 
-static int
-ProcRRSelectInput (ClientPtr client)
+CARD16
+RRVerticalRefresh (xRRModeInfo *mode)
 {
-    REQUEST(xRRSelectInputReq);
-    rrClientPriv(client);
-    RRTimesPtr	pTimes;
-    WindowPtr	pWin;
-    RREventPtr	pRREvent, pNewRREvent, *pHead;
-    XID		clientResource;
-
-    REQUEST_SIZE_MATCH(xRRSelectInputReq);
-    pWin = SecurityLookupWindow (stuff->window, client, SecurityWriteAccess);
-    if (!pWin)
-	return BadWindow;
-    pHead = (RREventPtr *)SecurityLookupIDByType(client,
-						 pWin->drawable.id, EventType,
-						 SecurityWriteAccess);
-
-    if (stuff->enable & (RRScreenChangeNotifyMask)) 
-    {
-	ScreenPtr	pScreen = pWin->drawable.pScreen;
-	rrScrPriv	(pScreen);
-
-	if (pHead) 
-	{
-	    /* check for existing entry. */
-	    for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
-		if (pRREvent->client == client)
-		    return Success;
-	}
-
-	/* build the entry */
-	pNewRREvent = (RREventPtr) xalloc (sizeof (RREventRec));
-	if (!pNewRREvent)
-	    return BadAlloc;
-	pNewRREvent->next = 0;
-	pNewRREvent->client = client;
-	pNewRREvent->window = pWin;
-	pNewRREvent->mask = stuff->enable;
-	/*
-	 * add a resource that will be deleted when
-	 * the client goes away
-	 */
-	clientResource = FakeClientID (client->index);
-	pNewRREvent->clientResource = clientResource;
-	if (!AddResource (clientResource, ClientType, (pointer)pNewRREvent))
-	    return BadAlloc;
-	/*
-	 * create a resource to contain a pointer to the list
-	 * of clients selecting input.  This must be indirect as
-	 * the list may be arbitrarily rearranged which cannot be
-	 * done through the resource database.
-	 */
-	if (!pHead)
-	{
-	    pHead = (RREventPtr *) xalloc (sizeof (RREventPtr));
-	    if (!pHead ||
-		!AddResource (pWin->drawable.id, EventType, (pointer)pHead))
-	    {
-		FreeResource (clientResource, RT_NONE);
-		return BadAlloc;
-	    }
-	    *pHead = 0;
-	}
-	pNewRREvent->next = *pHead;
-	*pHead = pNewRREvent;
-	/*
-	 * Now see if the client needs an event
-	 */
-	if (pScrPriv)
-	{
-	    pTimes = &((RRTimesPtr) (pRRClient + 1))[pScreen->myNum];
-	    if (CompareTimeStamps (pTimes->setTime, 
-				   pScrPriv->lastSetTime) != 0 ||
-		CompareTimeStamps (pTimes->configTime, 
-				   pScrPriv->lastConfigTime) != 0)
-	    {
-		TellChanged (pWin, (pointer) pScreen);
-	    }
-	}
-    }
-    else if (stuff->enable == xFalse) 
-    {
-	/* delete the interest */
-	if (pHead) {
-	    pNewRREvent = 0;
-	    for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) {
-		if (pRREvent->client == client)
-		    break;
-		pNewRREvent = pRREvent;
-	    }
-	    if (pRREvent) {
-		FreeResource (pRREvent->clientResource, ClientType);
-		if (pNewRREvent)
-		    pNewRREvent->next = pRREvent->next;
-		else
-		    *pHead = pRREvent->next;
-		xfree (pRREvent);
-	    }
-	}
-    }
-    else 
-    {
-	client->errorValue = stuff->enable;
-	return BadValue;
-    }
-    return Success;
+    CARD32  refresh;
+    CARD32  dots = mode->hTotal * mode->vTotal;
+    if (!dots)
+	return 0;
+    refresh = (mode->dotClock + dots/2) / dots;
+    if (refresh > 0xffff)
+	refresh = 0xffff;
+    return (CARD16) refresh;
 }
 
-
 static int
 ProcRRDispatch (ClientPtr client)
 {
     REQUEST(xReq);
-    switch (stuff->data)
-    {
-    case X_RRQueryVersion:
-	return ProcRRQueryVersion(client);
-    case X_RRSetScreenConfig:
-        return ProcRRSetScreenConfig(client);
-    case X_RRSelectInput:
-        return ProcRRSelectInput(client);
-    case X_RRGetScreenInfo:
-        return ProcRRGetScreenInfo(client);
-    default:
+    if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data])
 	return BadRequest;
-    }
-}
-
-static int
-SProcRRQueryVersion (ClientPtr client)
-{
-    register int n;
-    REQUEST(xRRQueryVersionReq);
-
-    swaps(&stuff->length, n);
-    swapl(&stuff->majorVersion, n);
-    swapl(&stuff->minorVersion, n);
-    return ProcRRQueryVersion(client);
+    return (*ProcRandrVector[stuff->data]) (client);
 }
 
 static int
-SProcRRGetScreenInfo (ClientPtr client)
-{
-    register int n;
-    REQUEST(xRRGetScreenInfoReq);
-
-    swaps(&stuff->length, n);
-    swapl(&stuff->window, n);
-    return ProcRRGetScreenInfo(client);
-}
-
-static int
-SProcRRSetScreenConfig (ClientPtr client)
-{
-    register int n;
-    REQUEST(xRRSetScreenConfigReq);
-
-    if (RRClientKnowsRates (client))
-    {
-	REQUEST_SIZE_MATCH (xRRSetScreenConfigReq);
-	swaps (&stuff->rate, n);
-    }
-    else
-    {
-	REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq);
-    }
-    
-    swaps(&stuff->length, n);
-    swapl(&stuff->drawable, n);
-    swapl(&stuff->timestamp, n);
-    swaps(&stuff->sizeID, n);
-    swaps(&stuff->rotation, n);
-    return ProcRRSetScreenConfig(client);
-}
-
-static int
-SProcRRSelectInput (ClientPtr client)
-{
-    register int n;
-    REQUEST(xRRSelectInputReq);
-
-    swaps(&stuff->length, n);
-    swapl(&stuff->window, n);
-    return ProcRRSelectInput(client);
-}
-
-
-static int
 SProcRRDispatch (ClientPtr client)
 {
     REQUEST(xReq);
-    switch (stuff->data)
-    {
-    case X_RRQueryVersion:
-	return SProcRRQueryVersion(client);
-    case X_RRSetScreenConfig:
-        return SProcRRSetScreenConfig(client);
-    case X_RRSelectInput:
-        return SProcRRSelectInput(client);
-    case X_RRGetScreenInfo:
-        return SProcRRGetScreenInfo(client);
-    default:
+    if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data])
 	return BadRequest;
-    }
-}
-
-
-static Bool
-RRScreenSizeMatches (RRScreenSizePtr  a,
-		   RRScreenSizePtr  b)
-{
-    if (a->width != b->width)
-	return FALSE;
-    if (a->height != b->height)
-	return FALSE;
-    if (a->mmWidth != b->mmWidth)
-	return FALSE;
-    if (a->mmHeight != b->mmHeight)
-	return FALSE;
-    return TRUE;
-}
-
-RRScreenSizePtr
-RRRegisterSize (ScreenPtr	    pScreen,
-		short		    width, 
-		short		    height,
-		short		    mmWidth,
-		short		    mmHeight)
-{
-    rrScrPriv (pScreen);
-    int		    i;
-    RRScreenSize    tmp;
-    RRScreenSizePtr pNew;
-
-    if (!pScrPriv)
-	return 0;
-    
-    tmp.width = width;
-    tmp.height= height;
-    tmp.mmWidth = mmWidth;
-    tmp.mmHeight = mmHeight;
-    tmp.pRates = 0;
-    tmp.nRates = 0;
-    tmp.nRatesInUse = 0;
-    tmp.referenced = TRUE;
-    tmp.oldReferenced = FALSE;
-    for (i = 0; i < pScrPriv->nSizes; i++)
-	if (RRScreenSizeMatches (&tmp, &pScrPriv->pSizes[i]))
-	{
-	    pScrPriv->pSizes[i].referenced = TRUE;
-	    return &pScrPriv->pSizes[i];
-	}
-    pNew = xrealloc (pScrPriv->pSizes,
-		     (pScrPriv->nSizes + 1) * sizeof (RRScreenSize));
-    if (!pNew)
-	return 0;
-    pNew[pScrPriv->nSizes++] = tmp;
-    pScrPriv->pSizes = pNew;
-    return &pNew[pScrPriv->nSizes-1];
-}
-
-Bool RRRegisterRate (ScreenPtr		pScreen,
-		     RRScreenSizePtr	pSize,
-		     int		rate)
-{
-    rrScrPriv(pScreen);
-    int		    i;
-    RRScreenRatePtr pNew, pRate;
-
-    if (!pScrPriv)
-	return FALSE;
-    
-    for (i = 0; i < pSize->nRates; i++)
-    {
-	pRate = &pSize->pRates[i];
-	if (pRate->rate == rate)
-	{
-	    pRate->referenced = TRUE;
-	    return TRUE;
-	}
-    }
-
-    pNew = xrealloc (pSize->pRates,
-		     (pSize->nRates + 1) * sizeof (RRScreenRate));
-    if (!pNew)
-	return FALSE;
-    pRate = &pNew[pSize->nRates++];
-    pRate->rate = rate;
-    pRate->referenced = TRUE;
-    pRate->oldReferenced = FALSE;
-    pSize->pRates = pNew;
-    return TRUE;
+    return (*SProcRandrVector[stuff->data]) (client);
 }
 
-Rotation
-RRGetRotation(ScreenPtr pScreen)
-{
-    rrScrPriv (pScreen);
-
-    if (!pScrPriv)
-	return RR_Rotate_0;
-
-    return pScrPriv->rotation;
-}
-
-void
-RRSetCurrentConfig (ScreenPtr		pScreen,
-		    Rotation		rotation,
-		    int			rate,
-		    RRScreenSizePtr	pSize)
-{
-    rrScrPriv (pScreen);
-
-    if (!pScrPriv)
-	return;
-
-    pScrPriv->rotation = rotation;
-    pScrPriv->size = pSize - pScrPriv->pSizes;
-    pScrPriv->rate = rate;
-}
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 9dfc71e..bd19fe9 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -1,25 +1,28 @@
 /*
- * $XFree86: xc/programs/Xserver/randr/randrstr.h,v 1.5 2002/09/29 23:39:45 keithp Exp $
- *
  * Copyright © 2000 Compaq Computer Corporation
+ * Copyright © 2002 Hewlett-Packard Company
+ * Copyright © 2006 Intel Corporation
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Compaq not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission.  Compaq makes no
- * representations about the suitability of this software for any purpose.  It
- * is provided "as is" without express or implied warranty.
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
  *
- * COMPAQ DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL COMPAQ BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ *
+ * Author:  Jim Gettys, Hewlett-Packard Company, Inc.
+ *	    Keith Packard, Intel Corporation
  */
 
 #ifdef HAVE_DIX_CONFIG_H
@@ -29,56 +32,234 @@
 #ifndef _RANDRSTR_H_
 #define _RANDRSTR_H_
 
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "os.h"
+#include "dixstruct.h"
+#include "resource.h"
+#include "scrnintstr.h"
+#include "windowstr.h"
+#include "pixmapstr.h"
+#include "extnsionst.h"
+#include "servermd.h"
 #include <X11/extensions/randr.h>
+#include <X11/extensions/randrproto.h>
+#ifdef RENDER
+#include <X11/extensions/render.h> 	/* we share subpixel order information */
+#include "picturestr.h"
+#endif
+#include <X11/Xfuncproto.h>
+
+/* required for ABI compatibility for now */
+#define RANDR_10_INTERFACE 1
+#define RANDR_12_INTERFACE 1
+
+typedef XID	RRMode;
+typedef XID	RROutput;
+typedef XID	RRCrtc;
+
+extern int	RREventBase, RRErrorBase;
+
+extern int (*ProcRandrVector[RRNumberRequests])(ClientPtr);
+extern int (*SProcRandrVector[RRNumberRequests])(ClientPtr);
+    
+/*
+ * Modeline for a monitor. Name follows directly after this struct
+ */
+
+#define RRModeName(pMode) ((char *) (pMode + 1))
+typedef struct _rrMode		RRModeRec, *RRModePtr;
+typedef struct _rrPropertyValue	RRPropertyValueRec, *RRPropertyValuePtr;
+typedef struct _rrProperty	RRPropertyRec, *RRPropertyPtr;
+typedef struct _rrCrtc		RRCrtcRec, *RRCrtcPtr;
+typedef struct _rrOutput	RROutputRec, *RROutputPtr;
+
+struct _rrMode {
+    int		    refcnt;
+    xRRModeInfo	    mode;
+    char	    *name;
+    ScreenPtr	    userScreen;
+};
+
+struct _rrPropertyValue {
+    Atom	    type;       /* ignored by server */
+    short	    format;     /* format of data for swapping - 8,16,32 */
+    long	    size;	/* size of data in (format/8) bytes */
+    pointer         data;	/* private to client */
+};
+
+struct _rrProperty {
+    RRPropertyPtr   next;
+    ATOM 	    propertyName;
+    Bool	    is_pending;
+    Bool	    range;
+    Bool	    immutable;
+    int		    num_valid;
+    INT32	    *valid_values;
+    RRPropertyValueRec	current, pending;
+};
+
+struct _rrCrtc {
+    RRCrtc	    id;
+    ScreenPtr	    pScreen;
+    RRModePtr	    mode;
+    int		    x, y;
+    Rotation	    rotation;
+    Rotation	    rotations;
+    Bool	    changed;
+    int		    numOutputs;
+    RROutputPtr	    *outputs;
+    int		    gammaSize;
+    CARD16	    *gammaRed;
+    CARD16	    *gammaBlue;
+    CARD16	    *gammaGreen;
+    void	    *devPrivate;
+};
+
+struct _rrOutput {
+    RROutput	    id;
+    ScreenPtr	    pScreen;
+    char	    *name;
+    int		    nameLength;
+    CARD8	    connection;
+    CARD8	    subpixelOrder;
+    int		    mmWidth;
+    int		    mmHeight;
+    RRCrtcPtr	    crtc;
+    int		    numCrtcs;
+    RRCrtcPtr	    *crtcs;
+    int		    numClones;
+    RROutputPtr	    *clones;
+    int		    numModes;
+    int		    numPreferred;
+    RRModePtr	    *modes;
+    int		    numUserModes;
+    RRModePtr	    *userModes;
+    Bool	    changed;
+    RRPropertyPtr   properties;
+    Bool	    pendingProperties;
+    void	    *devPrivate;
+};
+
+#if RANDR_12_INTERFACE
+typedef Bool (*RRScreenSetSizeProcPtr) (ScreenPtr	pScreen,
+					CARD16		width,
+					CARD16		height,
+					CARD32		mmWidth,
+					CARD32		mmHeight);
+					
+typedef Bool (*RRCrtcSetProcPtr) (ScreenPtr		pScreen,
+				  RRCrtcPtr		crtc,
+				  RRModePtr		mode,
+				  int			x,
+				  int			y,
+				  Rotation		rotation,
+				  int			numOutputs,
+				  RROutputPtr		*outputs);
+
+typedef Bool (*RRCrtcSetGammaProcPtr) (ScreenPtr	pScreen,
+				       RRCrtcPtr	crtc);
+
+typedef Bool (*RROutputSetPropertyProcPtr) (ScreenPtr		pScreen,
+					    RROutputPtr		output,
+					    Atom		property,
+					    RRPropertyValuePtr	value);
 
-typedef struct _rrScreenRate {
-    int		    rate;
-    Bool	    referenced;
-    Bool	    oldReferenced;
+typedef Bool (*RROutputValidateModeProcPtr) (ScreenPtr		pScreen,
+					     RROutputPtr	output,
+					     RRModePtr		mode);
+
+typedef void (*RRModeDestroyProcPtr) (ScreenPtr	    pScreen,
+				      RRModePtr	    mode);
+
+#endif
+
+typedef Bool (*RRGetInfoProcPtr) (ScreenPtr pScreen, Rotation *rotations);
+typedef Bool (*RRCloseScreenProcPtr) ( int i, ScreenPtr pscreen);
+
+/* These are for 1.0 compatibility */
+ 
+typedef struct _rrRefresh {
+    CARD16	    rate;
+    RRModePtr	    mode;
 } RRScreenRate, *RRScreenRatePtr;
 
 typedef struct _rrScreenSize {
     int		    id;
     short	    width, height;
     short	    mmWidth, mmHeight;
-    RRScreenRatePtr pRates;
     int		    nRates;
-    int		    nRatesInUse;
-    Bool	    referenced;
-    Bool	    oldReferenced;
+    RRScreenRatePtr pRates;
 } RRScreenSize, *RRScreenSizePtr;
 
+#ifdef RANDR_10_INTERFACE
+
 typedef Bool (*RRSetConfigProcPtr) (ScreenPtr		pScreen,
 				    Rotation		rotation,
 				    int			rate,
 				    RRScreenSizePtr	pSize);
 
-typedef Bool (*RRGetInfoProcPtr) (ScreenPtr pScreen, Rotation *rotations);
-typedef Bool (*RRCloseScreenProcPtr) ( int i, ScreenPtr pscreen);
+#endif
 	
+
 typedef struct _rrScrPriv {
+    /*
+     * 'public' part of the structure; DDXen fill this in
+     * as they initialize
+     */
+#if RANDR_10_INTERFACE
     RRSetConfigProcPtr	    rrSetConfig;
+#endif
     RRGetInfoProcPtr	    rrGetInfo;
+#if RANDR_12_INTERFACE
+    RRScreenSetSizeProcPtr  rrScreenSetSize;
+    RRCrtcSetProcPtr	    rrCrtcSet;
+    RRCrtcSetGammaProcPtr   rrCrtcSetGamma;
+    RROutputSetPropertyProcPtr	rrOutputSetProperty;
+    RROutputValidateModeProcPtr	rrOutputValidateMode;
+    RRModeDestroyProcPtr	rrModeDestroy;
+#endif
     
+    /*
+     * Private part of the structure; not considered part of the ABI
+     */
     TimeStamp		    lastSetTime;	/* last changed by client */
     TimeStamp		    lastConfigTime;	/* possible configs changed */
     RRCloseScreenProcPtr    CloseScreen;
 
+    Bool		    changed;		/* some config changed */
+    Bool		    configChanged;	/* configuration changed */
+    Bool		    layoutChanged;	/* screen layout changed */
+
+    CARD16		    minWidth, minHeight;
+    CARD16		    maxWidth, maxHeight;
+    CARD16		    width, height;	/* last known screen size */
+    CARD16		    mmWidth, mmHeight;	/* last known screen size */
+
+    int			    numOutputs;
+    RROutputPtr		    *outputs;
+
+    int			    numCrtcs;
+    RRCrtcPtr		    *crtcs;
+
+    /* Last known pointer position */
+    RRCrtcPtr		    pointerCrtc;
+
+#ifdef RANDR_10_INTERFACE
     /*
      * Configuration information
      */
     Rotation		    rotations;
+    CARD16		    reqWidth, reqHeight;
     
     int			    nSizes;
-    int			    nSizesInUse;
     RRScreenSizePtr	    pSizes;
-
-    /*
-     * Current state
-     */
+    
     Rotation		    rotation;
-    int			    size;
     int			    rate;
+    int			    size;
+#endif
 } rrScrPrivRec, *rrScrPrivPtr;
 
 extern int rrPrivIndex;
@@ -87,10 +268,184 @@ extern int rrPrivIndex;
 #define rrScrPriv(pScr)	rrScrPrivPtr    pScrPriv = rrGetScrPriv(pScr)
 #define SetRRScreen(s,p) ((s)->devPrivates[rrPrivIndex].ptr = (pointer) (p))
 
+/*
+ * each window has a list of clients requesting
+ * RRNotify events.  Each client has a resource
+ * for each window it selects RRNotify input for,
+ * this resource is used to delete the RRNotifyRec
+ * entry from the per-window queue.
+ */
+
+typedef struct _RREvent *RREventPtr;
+
+typedef struct _RREvent {
+    RREventPtr  next;
+    ClientPtr	client;
+    WindowPtr	window;
+    XID		clientResource;
+    int		mask;
+} RREventRec;
+
+typedef struct _RRTimes {
+    TimeStamp	setTime;
+    TimeStamp	configTime;
+} RRTimesRec, *RRTimesPtr;
+
+typedef struct _RRClient {
+    int		major_version;
+    int		minor_version;
+/*  RRTimesRec	times[0]; */
+} RRClientRec, *RRClientPtr;
+
+extern RESTYPE	RRClientType, RREventType; /* resource types for event masks */
+extern int	RRClientPrivateIndex;
+extern RESTYPE	RRCrtcType, RRModeType, RROutputType;
+
+#define LookupOutput(client,id,a) ((RROutputPtr) \
+				   (SecurityLookupIDByType (client, id, \
+							    RROutputType, a)))
+#define LookupCrtc(client,id,a) ((RRCrtcPtr) \
+				 (SecurityLookupIDByType (client, id, \
+							  RRCrtcType, a)))
+#define LookupMode(client,id,a) ((RRModePtr) \
+				 (SecurityLookupIDByType (client, id, \
+							  RRModeType, a)))
+
+#define GetRRClient(pClient)    ((RRClientPtr) (pClient)->devPrivates[RRClientPrivateIndex].ptr)
+#define rrClientPriv(pClient)	RRClientPtr pRRClient = GetRRClient(pClient)
+
 /* Initialize the extension */
 void
 RRExtensionInit (void);
 
+#ifdef RANDR_12_INTERFACE
+/*
+ * Set the range of sizes for the screen
+ */
+void
+RRScreenSetSizeRange (ScreenPtr	pScreen,
+		      CARD16	minWidth,
+		      CARD16	minHeight,
+		      CARD16	maxWidth,
+		      CARD16	maxHeight);
+#endif
+
+/* rrscreen.c */
+/*
+ * Notify the extension that the screen size has been changed.
+ * The driver is responsible for calling this whenever it has changed
+ * the size of the screen
+ */
+void
+RRScreenSizeNotify (ScreenPtr	pScreen);
+
+/*
+ * Request that the screen be resized
+ */
+Bool
+RRScreenSizeSet (ScreenPtr  pScreen,
+		 CARD16	    width,
+		 CARD16	    height,
+		 CARD32	    mmWidth,
+		 CARD32	    mmHeight);
+
+/*
+ * Send ConfigureNotify event to root window when 'something' happens
+ */
+void
+RRSendConfigNotify (ScreenPtr pScreen);
+    
+/*
+ * screen dispatch
+ */
+int 
+ProcRRGetScreenSizeRange (ClientPtr client);
+
+int
+ProcRRSetScreenSize (ClientPtr client);
+
+int
+ProcRRGetScreenResources (ClientPtr client);
+
+int
+ProcRRSetScreenConfig (ClientPtr client);
+
+int
+ProcRRGetScreenInfo (ClientPtr client);
+
+/*
+ * Deliver a ScreenNotify event
+ */
+void
+RRDeliverScreenEvent (ClientPtr client, WindowPtr pWin, ScreenPtr pScreen);
+    
+/* mirandr.c */
+Bool
+miRandRInit (ScreenPtr pScreen);
+
+Bool
+miRRGetInfo (ScreenPtr pScreen, Rotation *rotations);
+
+Bool
+miRRGetScreenInfo (ScreenPtr pScreen);
+
+Bool
+miRRCrtcSet (ScreenPtr	pScreen,
+	     RRCrtcPtr	crtc,
+	     RRModePtr	mode,
+	     int	x,
+	     int	y,
+	     Rotation	rotation,
+	     int	numOutput,
+	     RROutputPtr *outputs);
+
+Bool
+miRROutputSetProperty (ScreenPtr	    pScreen,
+		       RROutputPtr	    output,
+		       Atom		    property,
+		       RRPropertyValuePtr   value);
+
+Bool
+miRROutputValidateMode (ScreenPtr	    pScreen,
+			RROutputPtr	    output,
+			RRModePtr	    mode);
+
+void
+miRRModeDestroy (ScreenPtr  pScreen,
+		 RRModePtr  mode);
+
+/* randr.c */
+/*
+ * Send all pending events
+ */
+void
+RRTellChanged (ScreenPtr pScreen);
+
+/*
+ * Poll the driver for changed information
+ */
+Bool
+RRGetInfo (ScreenPtr pScreen);
+
+Bool RRInit (void);
+
+Bool RRScreenInit(ScreenPtr pScreen);
+
+RROutputPtr
+RRFirstOutput (ScreenPtr pScreen);
+
+Rotation
+RRGetRotation (ScreenPtr pScreen);
+
+CARD16
+RRVerticalRefresh (xRRModeInfo *mode);
+
+#ifdef RANDR_10_INTERFACE					
+/*
+ * This is the old interface, deprecated but left
+ * around for compatibility
+ */
+
 /*
  * Then, register the specific size with the screen
  */
@@ -116,7 +471,7 @@ RRSetCurrentConfig (ScreenPtr		pScreen,
 		    int			rate,
 		    RRScreenSizePtr	pSize);
 
-Bool RRScreenInit(ScreenPtr pScreen);
+Bool RRScreenInit (ScreenPtr pScreen);
 
 Rotation
 RRGetRotation (ScreenPtr pScreen);
@@ -127,19 +482,371 @@ RRSetScreenConfig (ScreenPtr		pScreen,
 		   int			rate,
 		   RRScreenSizePtr	pSize);
 
+#endif					
+
+/* rrcrtc.c */
+
+/*
+ * Notify the CRTC of some change; layoutChanged indicates that
+ * some position or size element changed
+ */
+void
+RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged);
+
+/*
+ * Create a CRTC
+ */
+RRCrtcPtr
+RRCrtcCreate (ScreenPtr pScreen, void	*devPrivate);
+
+/*
+ * Set the allowed rotations on a CRTC
+ */
+void
+RRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations);
+
+/*
+ * Notify the extension that the Crtc has been reconfigured,
+ * the driver calls this whenever it has updated the mode
+ */
+Bool
+RRCrtcNotify (RRCrtcPtr	    crtc,
+	      RRModePtr	    mode,
+	      int	    x,
+	      int	    y,
+	      Rotation	    rotation,
+	      int	    numOutputs,
+	      RROutputPtr   *outputs);
+
+void
+RRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc);
+    
+/*
+ * Request that the Crtc be reconfigured
+ */
 Bool
-miRandRInit (ScreenPtr pScreen);
+RRCrtcSet (RRCrtcPtr    crtc,
+	   RRModePtr	mode,
+	   int		x,
+	   int		y,
+	   Rotation	rotation,
+	   int		numOutput,
+	   RROutputPtr  *outputs);
+
+/*
+ * Request that the Crtc gamma be changed
+ */
 
 Bool
-miRRGetInfo (ScreenPtr pScreen, Rotation *rotations);
+RRCrtcGammaSet (RRCrtcPtr   crtc,
+		CARD16	    *red,
+		CARD16	    *green,
+		CARD16	    *blue);
+
+/*
+ * Notify the extension that the Crtc gamma has been changed
+ * The driver calls this whenever it has changed the gamma values
+ * in the RRCrtcRec
+ */
 
 Bool
-miRRSetConfig (ScreenPtr	pScreen,
-	       Rotation		rotation,
-	       int		rate,
-	       RRScreenSizePtr	size);
+RRCrtcGammaNotify (RRCrtcPtr	crtc);
+
+/*
+ * Set the size of the gamma table at server startup time
+ */
 
 Bool
-miRRGetScreenInfo (ScreenPtr pScreen);
+RRCrtcGammaSetSize (RRCrtcPtr	crtc,
+		    int		size);
+
+/*
+ * Return the area of the frame buffer scanned out by the crtc,
+ * taking into account the current mode and rotation
+ */
+
+void
+RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height);
+
+/*
+ * Destroy a Crtc at shutdown
+ */
+void
+RRCrtcDestroy (RRCrtcPtr crtc);
+
+/*
+ * Initialize crtc type
+ */
+Bool
+RRCrtcInit (void);
+
+/*
+ * Crtc dispatch
+ */
+
+int
+ProcRRGetCrtcInfo (ClientPtr client);
+
+int
+ProcRRSetCrtcConfig (ClientPtr client);
+
+int
+ProcRRGetCrtcGammaSize (ClientPtr client);
+
+int
+ProcRRGetCrtcGamma (ClientPtr client);
+
+int
+ProcRRSetCrtcGamma (ClientPtr client);
+
+/* rrdispatch.c */
+Bool
+RRClientKnowsRates (ClientPtr	pClient);
+
+/* rrmode.c */
+/*
+ * Find, and if necessary, create a mode
+ */
+
+RRModePtr
+RRModeGet (xRRModeInfo	*modeInfo,
+	   const char	*name);
+
+void
+RRModePruneUnused (ScreenPtr pScreen);
+
+/*
+ * Destroy a mode.
+ */
+
+void
+RRModeDestroy (RRModePtr mode);
+
+/*
+ * Return a list of modes that are valid for some output in pScreen
+ */
+RRModePtr *
+RRModesForScreen (ScreenPtr pScreen, int *num_ret);
+    
+/*
+ * Initialize mode type
+ */
+Bool
+RRModeInit (void);
+    
+int
+ProcRRCreateMode (ClientPtr client);
+
+int
+ProcRRDestroyMode (ClientPtr client);
+
+int
+ProcRRAddOutputMode (ClientPtr client);
+
+int
+ProcRRDeleteOutputMode (ClientPtr client);
+
+/* rroutput.c */
+
+/*
+ * Notify the output of some change. configChanged indicates whether
+ * any external configuration (mode list, clones, connected status)
+ * has changed, or whether the change was strictly internal
+ * (which crtc is in use)
+ */
+void
+RROutputChanged (RROutputPtr output, Bool configChanged);
+
+/*
+ * Create an output
+ */
+
+RROutputPtr
+RROutputCreate (ScreenPtr   pScreen,
+		const char  *name,
+		int	    nameLength,
+		void	    *devPrivate);
+
+/*
+ * Notify extension that output parameters have been changed
+ */
+Bool
+RROutputSetClones (RROutputPtr  output,
+		   RROutputPtr  *clones,
+		   int		numClones);
+
+Bool
+RROutputSetModes (RROutputPtr	output,
+		  RRModePtr	*modes,
+		  int		numModes,
+		  int		numPreferred);
+
+int
+RROutputAddUserMode (RROutputPtr    output,
+		     RRModePtr	    mode);
+
+int
+RROutputDeleteUserMode (RROutputPtr output,
+			RRModePtr   mode);
+
+Bool
+RROutputSetCrtcs (RROutputPtr	output,
+		  RRCrtcPtr	*crtcs,
+		  int		numCrtcs);
+
+Bool
+RROutputSetConnection (RROutputPtr  output,
+		       CARD8	    connection);
+
+Bool
+RROutputSetSubpixelOrder (RROutputPtr output,
+			  int	      subpixelOrder);
+
+Bool
+RROutputSetPhysicalSize (RROutputPtr	output,
+			 int		mmWidth,
+			 int		mmHeight);
+
+void
+RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output);
+
+void
+RROutputDestroy (RROutputPtr	output);
+
+int
+ProcRRGetOutputInfo (ClientPtr client);
+
+/*
+ * Initialize output type
+ */
+Bool
+RROutputInit (void);
+    
+/* rrpointer.c */
+void
+RRPointerMoved (ScreenPtr pScreen, int x, int y);
+
+void
+RRPointerScreenConfigured (ScreenPtr pScreen);
+
+/* rrproperty.c */
+
+void
+RRDeleteAllOutputProperties (RROutputPtr output);
+
+RRPropertyValuePtr
+RRGetOutputProperty (RROutputPtr output, Atom property, Bool pending);
+
+RRPropertyPtr
+RRQueryOutputProperty (RROutputPtr output, Atom property);
+		       
+void
+RRDeleteOutputProperty (RROutputPtr output, Atom property);
+
+Bool
+RRPostPendingProperties (RROutputPtr output);
+    
+int
+RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
+			int format, int mode, unsigned long len,
+			pointer value, Bool sendevent, Bool pending);
+
+int
+RRConfigureOutputProperty (RROutputPtr output, Atom property,
+			   Bool pending, Bool range, Bool immutable,
+			   int num_values, INT32 *values);
+int
+ProcRRChangeOutputProperty (ClientPtr client);
+
+int
+ProcRRGetOutputProperty (ClientPtr client);
+
+int
+ProcRRListOutputProperties (ClientPtr client);
+
+int
+ProcRRQueryOutputProperty (ClientPtr client);
+
+int
+ProcRRConfigureOutputProperty (ClientPtr client);
+
+int
+ProcRRDeleteOutputProperty (ClientPtr client);
+
+/* rrxinerama.c */
+void
+RRXineramaExtensionInit(void);
 
 #endif /* _RANDRSTR_H_ */
+
+/*
+ 
+randr extension implementation structure
+
+Query state:
+    ProcRRGetScreenInfo/ProcRRGetScreenResources
+	RRGetInfo
+ 
+	    • Request configuration from driver, either 1.0 or 1.2 style
+	    • These functions only record state changes, all
+	      other actions are pended until RRTellChanged is called
+ 
+	    ->rrGetInfo
+	    1.0:
+		RRRegisterSize
+		RRRegisterRate
+		RRSetCurrentConfig
+	    1.2:
+		RRScreenSetSizeRange
+		RROutputSetCrtcs
+		RRModeGet
+		RROutputSetModes
+		RROutputSetConnection
+		RROutputSetSubpixelOrder
+		RROutputSetClones
+		RRCrtcNotify
+ 
+	• Must delay scanning configuration until after ->rrGetInfo returns
+	  because some drivers will call SetCurrentConfig in the middle
+	  of the ->rrGetInfo operation.
+ 
+	1.0:
+
+	    • Scan old configuration, mirror to new structures
+ 
+	    RRScanOldConfig
+		RRCrtcCreate
+		RROutputCreate
+		RROutputSetCrtcs
+		RROutputSetConnection
+		RROutputSetSubpixelOrder
+		RROldModeAdd	• This adds modes one-at-a-time
+		    RRModeGet
+		RRCrtcNotify
+ 
+	• send events, reset pointer if necessary
+ 
+	RRTellChanged
+	    WalkTree (sending events)
+ 
+	    • when layout has changed:
+		RRPointerScreenConfigured
+		RRSendConfigNotify
+ 
+Asynchronous state setting (1.2 only)
+    When setting state asynchronously, the driver invokes the
+    ->rrGetInfo function and then calls RRTellChanged to flush
+    the changes to the clients and reset pointer if necessary
+
+Set state
+
+    ProcRRSetScreenConfig
+	RRCrtcSet
+	    1.2:
+		->rrCrtcSet
+		    RRCrtcNotify
+	    1.0:
+		->rrSetConfig
+		RRCrtcNotify
+	    RRTellChanged
+ */
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
new file mode 100644
index 0000000..774a5f5
--- /dev/null
+++ b/randr/rrcrtc.c
@@ -0,0 +1,950 @@
+/*
+ * Copyright © 2006 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "randrstr.h"
+#include "swaprep.h"
+
+RESTYPE	RRCrtcType;
+
+/*
+ * Notify the CRTC of some change
+ */
+void
+RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged)
+{
+    ScreenPtr	pScreen = crtc->pScreen;
+
+    crtc->changed = TRUE;
+    if (pScreen)
+    {
+	rrScrPriv(pScreen);
+    
+	pScrPriv->changed = TRUE;
+	/*
+	 * Send ConfigureNotify on any layout change
+	 */
+	if (layoutChanged)
+	    pScrPriv->layoutChanged = TRUE;
+    }
+}
+
+/*
+ * Create a CRTC
+ */
+RRCrtcPtr
+RRCrtcCreate (ScreenPtr pScreen, void *devPrivate)
+{
+    RRCrtcPtr	    crtc;
+    RRCrtcPtr	    *crtcs;
+    rrScrPrivPtr    pScrPriv;
+
+    if (!RRInit())
+	return NULL;
+    
+    pScrPriv = rrGetScrPriv(pScreen);
+
+    /* make space for the crtc pointer */
+    if (pScrPriv->numCrtcs)
+	crtcs = xrealloc (pScrPriv->crtcs, 
+			  (pScrPriv->numCrtcs + 1) * sizeof (RRCrtcPtr));
+    else
+	crtcs = xalloc (sizeof (RRCrtcPtr));
+    if (!crtcs)
+	return FALSE;
+    pScrPriv->crtcs = crtcs;
+    
+    crtc = xcalloc (1, sizeof (RRCrtcRec));
+    if (!crtc)
+	return NULL;
+    crtc->id = FakeClientID (0);
+    crtc->pScreen = pScreen;
+    crtc->mode = NULL;
+    crtc->x = 0;
+    crtc->y = 0;
+    crtc->rotation = RR_Rotate_0;
+    crtc->rotations = RR_Rotate_0;
+    crtc->outputs = NULL;
+    crtc->numOutputs = 0;
+    crtc->gammaSize = 0;
+    crtc->gammaRed = crtc->gammaBlue = crtc->gammaGreen = NULL;
+    crtc->changed = FALSE;
+    crtc->devPrivate = devPrivate;
+
+    if (!AddResource (crtc->id, RRCrtcType, (pointer) crtc))
+	return NULL;
+
+    /* attach the screen and crtc together */
+    crtc->pScreen = pScreen;
+    pScrPriv->crtcs[pScrPriv->numCrtcs++] = crtc;
+    
+    return crtc;
+}
+
+/*
+ * Set the allowed rotations on a CRTC
+ */
+void
+RRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations)
+{
+    crtc->rotations = rotations;
+}
+
+/*
+ * Notify the extension that the Crtc has been reconfigured,
+ * the driver calls this whenever it has updated the mode
+ */
+Bool
+RRCrtcNotify (RRCrtcPtr	    crtc,
+	      RRModePtr	    mode,
+	      int	    x,
+	      int	    y,
+	      Rotation	    rotation,
+	      int	    numOutputs,
+	      RROutputPtr   *outputs)
+{
+    int	    i, j;
+    
+    /*
+     * Check to see if any of the new outputs were
+     * not in the old list and mark them as changed
+     */
+    for (i = 0; i < numOutputs; i++)
+    {
+	for (j = 0; j < crtc->numOutputs; j++)
+	    if (outputs[i] == crtc->outputs[j])
+		break;
+	if (j == crtc->numOutputs)
+	{
+	    outputs[i]->crtc = crtc;
+	    RROutputChanged (outputs[i], FALSE);
+	    RRCrtcChanged (crtc, FALSE);
+	}
+    }
+    /*
+     * Check to see if any of the old outputs are
+     * not in the new list and mark them as changed
+     */
+    for (j = 0; j < crtc->numOutputs; j++)
+    {
+	for (i = 0; i < numOutputs; i++)
+	    if (outputs[i] == crtc->outputs[j])
+		break;
+	if (i == numOutputs)
+	{
+	    if (crtc->outputs[j]->crtc == crtc)
+		crtc->outputs[j]->crtc = NULL;
+	    RROutputChanged (crtc->outputs[j], FALSE);
+	    RRCrtcChanged (crtc, FALSE);
+	}
+    }
+    /*
+     * Reallocate the crtc output array if necessary
+     */
+    if (numOutputs != crtc->numOutputs)
+    {
+	RROutputPtr *newoutputs;
+	
+	if (numOutputs)
+	{
+	    if (crtc->numOutputs)
+		newoutputs = xrealloc (crtc->outputs,
+				    numOutputs * sizeof (RROutputPtr));
+	    else
+		newoutputs = xalloc (numOutputs * sizeof (RROutputPtr));
+	    if (!newoutputs)
+		return FALSE;
+	}
+	else
+	{
+	    if (crtc->outputs)
+		xfree (crtc->outputs);
+	    newoutputs = NULL;
+	}
+	crtc->outputs = newoutputs;
+	crtc->numOutputs = numOutputs;
+    }
+    /*
+     * Copy the new list of outputs into the crtc
+     */
+    memcpy (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr));
+    /*
+     * Update remaining crtc fields
+     */
+    if (mode != crtc->mode)
+    {
+	if (crtc->mode)
+	    RRModeDestroy (crtc->mode);
+	crtc->mode = mode;
+	if (mode != NULL)
+	    mode->refcnt++;
+	RRCrtcChanged (crtc, TRUE);
+    }
+    if (x != crtc->x)
+    {
+	crtc->x = x;
+	RRCrtcChanged (crtc, TRUE);
+    }
+    if (y != crtc->y)
+    {
+	crtc->y = y;
+	RRCrtcChanged (crtc, TRUE);
+    }
+    if (rotation != crtc->rotation)
+    {
+	crtc->rotation = rotation;
+	RRCrtcChanged (crtc, TRUE);
+    }
+    return TRUE;
+}
+
+void
+RRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc)
+{
+    ScreenPtr pScreen = pWin->drawable.pScreen;
+    rrScrPriv (pScreen);
+    xRRCrtcChangeNotifyEvent	ce;
+    RRModePtr	mode = crtc->mode;
+    
+    ce.type = RRNotify + RREventBase;
+    ce.subCode = RRNotify_CrtcChange;
+    ce.sequenceNumber = client->sequence;
+    ce.timestamp = pScrPriv->lastSetTime.milliseconds;
+    ce.window = pWin->drawable.id;
+    ce.crtc = crtc->id;
+    ce.rotation = crtc->rotation;
+    if (mode)
+    {
+	ce.mode = mode->mode.id;
+	ce.x = crtc->x;
+	ce.y = crtc->y;
+	ce.width = mode->mode.width;
+	ce.height = mode->mode.height;
+    }
+    else
+    {
+	ce.mode = None;
+	ce.x = 0;
+	ce.y = 0;
+	ce.width = 0;
+	ce.height = 0;
+    }
+    WriteEventsToClient (client, 1, (xEvent *) &ce);
+}
+
+static Bool
+RRCrtcPendingProperties (RRCrtcPtr crtc)
+{
+    ScreenPtr	pScreen = crtc->pScreen;
+    rrScrPriv(pScreen);
+    int		o;
+
+    for (o = 0; o < pScrPriv->numOutputs; o++)
+    {
+	RROutputPtr output = pScrPriv->outputs[o];
+	if (output->crtc == crtc && output->pendingProperties)
+	    return TRUE;
+    }
+    return FALSE;
+}
+
+/*
+ * Request that the Crtc be reconfigured
+ */
+Bool
+RRCrtcSet (RRCrtcPtr    crtc,
+	   RRModePtr	mode,
+	   int		x,
+	   int		y,
+	   Rotation	rotation,
+	   int		numOutputs,
+	   RROutputPtr  *outputs)
+{
+    ScreenPtr	pScreen = crtc->pScreen;
+    Bool	ret = FALSE;
+    rrScrPriv(pScreen);
+
+    /* See if nothing changed */
+    if (crtc->mode == mode &&
+	crtc->x == x &&
+	crtc->y == y &&
+	crtc->rotation == rotation &&
+	crtc->numOutputs == numOutputs &&
+	!memcmp (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr)) &&
+	!RRCrtcPendingProperties (crtc))
+    {
+	ret = TRUE;
+    }
+    else
+    {
+#if RANDR_12_INTERFACE
+	if (pScrPriv->rrCrtcSet)
+	{
+	    ret = (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y, 
+					  rotation, numOutputs, outputs);
+	}
+	else
+#endif
+	{
+#if RANDR_10_INTERFACE
+	    if (pScrPriv->rrSetConfig)
+	    {
+		RRScreenSize	    size;
+		RRScreenRate	    rate;
+
+		if (!mode)
+		{
+		    RRCrtcNotify (crtc, NULL, x, y, rotation, 0, NULL);
+		    ret = TRUE;
+		}
+		else
+		{
+		    size.width = mode->mode.width;
+		    size.height = mode->mode.height;
+		    if (outputs[0]->mmWidth && outputs[0]->mmHeight)
+		    {
+			size.mmWidth = outputs[0]->mmWidth;
+			size.mmHeight = outputs[0]->mmHeight;
+		    }
+		    else
+		    {
+			size.mmWidth = pScreen->mmWidth;
+			size.mmHeight = pScreen->mmHeight;
+		    }
+		    size.nRates = 1;
+		    rate.rate = RRVerticalRefresh (&mode->mode);
+		    size.pRates = &rate;
+		    ret = (*pScrPriv->rrSetConfig) (pScreen, rotation, rate.rate, &size);
+		    /*
+		     * Old 1.0 interface tied screen size to mode size
+		     */
+		    if (ret)
+		    {
+			RRCrtcNotify (crtc, mode, x, y, rotation, 1, outputs);
+			RRScreenSizeNotify (pScreen);
+		    }
+		}
+	    }
+#endif
+	}
+	if (ret)
+	{
+	    int	o;
+	    RRTellChanged (pScreen);
+
+	    for (o = 0; o < numOutputs; o++)
+		RRPostPendingProperties (outputs[o]);
+	}
+    }
+    return ret;
+}
+
+/*
+ * Destroy a Crtc at shutdown
+ */
+void
+RRCrtcDestroy (RRCrtcPtr crtc)
+{
+    FreeResource (crtc->id, 0);
+}
+
+static int
+RRCrtcDestroyResource (pointer value, XID pid)
+{
+    RRCrtcPtr	crtc = (RRCrtcPtr) value;
+    ScreenPtr	pScreen = crtc->pScreen;
+
+    if (pScreen)
+    {
+	rrScrPriv(pScreen);
+	int		i;
+    
+	for (i = 0; i < pScrPriv->numCrtcs; i++)
+	{
+	    if (pScrPriv->crtcs[i] == crtc)
+	    {
+		memmove (pScrPriv->crtcs + i, pScrPriv->crtcs + i + 1,
+			 (pScrPriv->numCrtcs - (i + 1)) * sizeof (RRCrtcPtr));
+		--pScrPriv->numCrtcs;
+		break;
+	    }
+	}
+    }
+    if (crtc->gammaRed)
+	xfree (crtc->gammaRed);
+    if (crtc->mode)
+	RRModeDestroy (crtc->mode);
+    xfree (crtc);
+    return 1;
+}
+
+/*
+ * Request that the Crtc gamma be changed
+ */
+
+Bool
+RRCrtcGammaSet (RRCrtcPtr   crtc,
+		CARD16	    *red,
+		CARD16	    *green,
+		CARD16	    *blue)
+{
+    Bool	ret = TRUE;
+#if RANDR_12_INTERFACE
+    ScreenPtr	pScreen = crtc->pScreen;
+#endif
+    
+    memcpy (crtc->gammaRed, red, crtc->gammaSize * sizeof (CARD16));
+    memcpy (crtc->gammaGreen, green, crtc->gammaSize * sizeof (CARD16));
+    memcpy (crtc->gammaBlue, blue, crtc->gammaSize * sizeof (CARD16));
+#if RANDR_12_INTERFACE
+    if (pScreen)
+    {
+	rrScrPriv(pScreen);
+	if (pScrPriv->rrCrtcSetGamma)
+	    ret = (*pScrPriv->rrCrtcSetGamma) (pScreen, crtc);
+    }
+#endif
+    return ret;
+}
+
+/*
+ * Notify the extension that the Crtc gamma has been changed
+ * The driver calls this whenever it has changed the gamma values
+ * in the RRCrtcRec
+ */
+
+Bool
+RRCrtcGammaNotify (RRCrtcPtr	crtc)
+{
+    return TRUE;    /* not much going on here */
+}
+
+/**
+ * Returns the width/height that the crtc scans out from the framebuffer
+ */
+void
+RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height)
+{
+    if (crtc->mode == NULL) {
+	*width = 0;
+	*height = 0;
+	return;
+    }
+
+    switch (crtc->rotation & 0xf) {
+    case RR_Rotate_0:
+    case RR_Rotate_180:
+	*width = crtc->mode->mode.width;
+	*height = crtc->mode->mode.height;
+	break;
+    case RR_Rotate_90:
+    case RR_Rotate_270:
+	*width = crtc->mode->mode.height;
+	*height = crtc->mode->mode.width;
+	break;
+    }
+}
+
+/*
+ * Set the size of the gamma table at server startup time
+ */
+
+Bool
+RRCrtcGammaSetSize (RRCrtcPtr	crtc,
+		    int		size)
+{
+    CARD16  *gamma;
+
+    if (size == crtc->gammaSize)
+	return TRUE;
+    if (size)
+    {
+	gamma = xalloc (size * 3 * sizeof (CARD16));
+	if (!gamma)
+	    return FALSE;
+    }
+    else
+	gamma = NULL;
+    if (crtc->gammaRed)
+	xfree (crtc->gammaRed);
+    crtc->gammaRed = gamma;
+    crtc->gammaGreen = gamma + size;
+    crtc->gammaBlue = gamma + size*2;
+    crtc->gammaSize = size;
+    return TRUE;
+}
+
+/*
+ * Initialize crtc type
+ */
+Bool
+RRCrtcInit (void)
+{
+    RRCrtcType = CreateNewResourceType (RRCrtcDestroyResource);
+    if (!RRCrtcType)
+	return FALSE;
+    RegisterResourceName (RRCrtcType, "CRTC");
+    return TRUE;
+}
+
+int
+ProcRRGetCrtcInfo (ClientPtr client)
+{
+    REQUEST(xRRGetCrtcInfoReq);
+    xRRGetCrtcInfoReply	rep;
+    RRCrtcPtr			crtc;
+    CARD8			*extra;
+    unsigned long		extraLen;
+    ScreenPtr			pScreen;
+    rrScrPrivPtr		pScrPriv;
+    RRModePtr			mode;
+    RROutput			*outputs;
+    RROutput			*possible;
+    int				i, j, k, n;
+    int				width, height;
+    
+    REQUEST_SIZE_MATCH(xRRGetCrtcInfoReq);
+    crtc = LookupCrtc(client, stuff->crtc, SecurityReadAccess);
+
+    if (!crtc)
+	return RRErrorBase + BadRRCrtc;
+
+    /* All crtcs must be associated with screens before client
+     * requests are processed
+     */
+    pScreen = crtc->pScreen;
+    pScrPriv = rrGetScrPriv(pScreen);
+
+    mode = crtc->mode;
+    
+    rep.type = X_Reply;
+    rep.status = RRSetConfigSuccess;
+    rep.sequenceNumber = client->sequence;
+    rep.length = 0;
+    rep.timestamp = pScrPriv->lastSetTime.milliseconds;
+    rep.x = crtc->x;
+    rep.y = crtc->y;
+    RRCrtcGetScanoutSize (crtc, &width, &height);
+    rep.width = width;
+    rep.height = height;
+    rep.mode = mode ? mode->mode.id : 0;
+    rep.rotation = crtc->rotation;
+    rep.rotations = crtc->rotations;
+    rep.nOutput = crtc->numOutputs;
+    k = 0;
+    for (i = 0; i < pScrPriv->numOutputs; i++)
+	for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++)
+	    if (pScrPriv->outputs[i]->crtcs[j] == crtc)
+		k++;
+    rep.nPossibleOutput = k;
+    
+    rep.length = rep.nOutput + rep.nPossibleOutput;
+
+    extraLen = rep.length << 2;
+    if (extraLen)
+    {
+	extra = xalloc (extraLen);
+	if (!extra)
+	    return BadAlloc;
+    }
+    else
+	extra = NULL;
+
+    outputs = (RROutput *) extra;
+    possible = (RROutput *) (outputs + rep.nOutput);
+    
+    for (i = 0; i < crtc->numOutputs; i++)
+    {
+	outputs[i] = crtc->outputs[i]->id;
+	if (client->swapped)
+	    swapl (&outputs[i], n);
+    }
+    k = 0;
+    for (i = 0; i < pScrPriv->numOutputs; i++)
+	for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++)
+	    if (pScrPriv->outputs[i]->crtcs[j] == crtc)
+	    {
+		possible[k] = pScrPriv->outputs[i]->id;
+		if (client->swapped)
+		    swapl (&possible[k], n);
+		k++;
+	    }
+    
+    if (client->swapped) {
+	swaps(&rep.sequenceNumber, n);
+	swapl(&rep.length, n);
+	swapl(&rep.timestamp, n);
+	swaps(&rep.x, n);
+	swaps(&rep.y, n);
+	swaps(&rep.width, n);
+	swaps(&rep.height, n);
+	swapl(&rep.mode, n);
+	swaps(&rep.rotation, n);
+	swaps(&rep.rotations, n);
+	swaps(&rep.nOutput, n);
+	swaps(&rep.nPossibleOutput, n);
+    }
+    WriteToClient(client, sizeof(xRRGetCrtcInfoReply), (char *)&rep);
+    if (extraLen)
+    {
+	WriteToClient (client, extraLen, (char *) extra);
+	xfree (extra);
+    }
+    
+    return client->noClientException;
+}
+
+int
+ProcRRSetCrtcConfig (ClientPtr client)
+{
+    REQUEST(xRRSetCrtcConfigReq);
+    xRRSetCrtcConfigReply   rep;
+    ScreenPtr		    pScreen;
+    rrScrPrivPtr	    pScrPriv;
+    RRCrtcPtr		    crtc;
+    RRModePtr		    mode;
+    int			    numOutputs;
+    RROutputPtr		    *outputs = NULL;
+    RROutput		    *outputIds;
+    TimeStamp		    configTime;
+    TimeStamp		    time;
+    Rotation		    rotation;
+    int			    i, j;
+    
+    REQUEST_AT_LEAST_SIZE(xRRSetCrtcConfigReq);
+    numOutputs = (stuff->length - (SIZEOF (xRRSetCrtcConfigReq) >> 2));
+    
+    crtc = LookupIDByType (stuff->crtc, RRCrtcType);
+    if (!crtc)
+    {
+	client->errorValue = stuff->crtc;
+	return RRErrorBase + BadRRCrtc;
+    }
+    if (stuff->mode == None)
+    {
+	mode = NULL;
+	if (numOutputs > 0)
+	    return BadMatch;
+    }
+    else
+    {
+	mode = LookupIDByType (stuff->mode, RRModeType);
+	if (!mode)
+	{
+	    client->errorValue = stuff->mode;
+	    return RRErrorBase + BadRRMode;
+	}
+	if (numOutputs == 0)
+	    return BadMatch;
+    }
+    if (numOutputs)
+    {
+	outputs = xalloc (numOutputs * sizeof (RROutputPtr));
+	if (!outputs)
+	    return BadAlloc;
+    }
+    else
+	outputs = NULL;
+    
+    outputIds = (RROutput *) (stuff + 1);
+    for (i = 0; i < numOutputs; i++)
+    {
+	outputs[i] = (RROutputPtr) LookupIDByType (outputIds[i], RROutputType);
+	if (!outputs[i])
+	{
+	    client->errorValue = outputIds[i];
+	    if (outputs)
+		xfree (outputs);
+	    return RRErrorBase + BadRROutput;
+	}
+	/* validate crtc for this output */
+	for (j = 0; j < outputs[i]->numCrtcs; j++)
+	    if (outputs[i]->crtcs[j] == crtc)
+		break;
+	if (j == outputs[i]->numCrtcs)
+	{
+	    if (outputs)
+		xfree (outputs);
+	    return BadMatch;
+	}
+	/* validate mode for this output */
+	for (j = 0; j < outputs[i]->numModes + outputs[i]->numUserModes; j++)
+	{
+	    RRModePtr	m = (j < outputs[i]->numModes ? 
+			     outputs[i]->modes[j] :
+			     outputs[i]->userModes[j - outputs[i]->numModes]);
+	    if (m == mode)
+		break;
+	}
+	if (j == outputs[i]->numModes + outputs[i]->numUserModes)
+	{
+	    if (outputs)
+		xfree (outputs);
+	    return BadMatch;
+	}
+    }
+    /* validate clones */
+    for (i = 0; i < numOutputs; i++)
+    {
+	for (j = 0; j < numOutputs; j++)
+	{
+	    int k;
+	    if (i == j)
+		continue;
+	    for (k = 0; k < outputs[i]->numClones; k++)
+	    {
+		if (outputs[i]->clones[k] == outputs[j])
+		    break;
+	    }
+	    if (k == outputs[i]->numClones)
+	    {
+		if (outputs)
+		    xfree (outputs);
+		return BadMatch;
+	    }
+	}
+    }
+
+    pScreen = crtc->pScreen;
+    pScrPriv = rrGetScrPriv(pScreen);
+    
+    time = ClientTimeToServerTime(stuff->timestamp);
+    configTime = ClientTimeToServerTime(stuff->configTimestamp);
+    
+    if (!pScrPriv)
+    {
+	time = currentTime;
+	rep.status = RRSetConfigFailed;
+	goto sendReply;
+    }
+    
+#if 0
+    /*
+     * if the client's config timestamp is not the same as the last config
+     * timestamp, then the config information isn't up-to-date and
+     * can't even be validated
+     */
+    if (CompareTimeStamps (configTime, pScrPriv->lastConfigTime) != 0)
+    {
+	rep.status = RRSetConfigInvalidConfigTime;
+	goto sendReply;
+    }
+#endif
+    
+    /*
+     * Validate requested rotation
+     */
+    rotation = (Rotation) stuff->rotation;
+
+    /* test the rotation bits only! */
+    switch (rotation & 0xf) {
+    case RR_Rotate_0:
+    case RR_Rotate_90:
+    case RR_Rotate_180:
+    case RR_Rotate_270:
+	break;
+    default:
+	/*
+	 * Invalid rotation
+	 */
+	client->errorValue = stuff->rotation;
+	if (outputs)
+	    xfree (outputs);
+	return BadValue;
+    }
+
+    if (mode)
+    {
+	if ((~crtc->rotations) & rotation)
+	{
+	    /*
+	     * requested rotation or reflection not supported by screen
+	     */
+	    client->errorValue = stuff->rotation;
+	    if (outputs)
+		xfree (outputs);
+	    return BadMatch;
+	}
+    
+#ifdef RANDR_12_INTERFACE
+	/*
+	 * Check screen size bounds if the DDX provides a 1.2 interface
+	 * for setting screen size. Else, assume the CrtcSet sets
+	 * the size along with the mode
+	 */
+	if (pScrPriv->rrScreenSetSize)
+	{
+	    int source_width = mode->mode.width;
+	    int	source_height = mode->mode.height;
+
+	    if ((rotation & 0xf) == RR_Rotate_90 || (rotation & 0xf) == RR_Rotate_270)
+	    {
+		source_width = mode->mode.height;
+		source_height = mode->mode.width;
+	    }
+	    if (stuff->x + source_width > pScreen->width)
+	    {
+		client->errorValue = stuff->x;
+		if (outputs)
+		    xfree (outputs);
+		return BadValue;
+	    }
+	    
+	    if (stuff->y + source_height > pScreen->height)
+	    {
+		client->errorValue = stuff->y;
+		if (outputs)
+		    xfree (outputs);
+		return BadValue;
+	    }
+	}
+#endif
+    }
+    
+    /*
+     * Make sure the requested set-time is not older than
+     * the last set-time
+     */
+    if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0)
+    {
+	rep.status = RRSetConfigInvalidTime;
+	goto sendReply;
+    }
+
+    if (!RRCrtcSet (crtc, mode, stuff->x, stuff->y,
+		   rotation, numOutputs, outputs))
+    {
+	rep.status = RRSetConfigFailed;
+	goto sendReply;
+    }
+    rep.status = RRSetConfigSuccess;
+    
+sendReply:
+    if (outputs)
+	xfree (outputs);
+    
+    rep.type = X_Reply;
+    /* rep.status has already been filled in */
+    rep.length = 0;
+    rep.sequenceNumber = client->sequence;
+    rep.newTimestamp = pScrPriv->lastConfigTime.milliseconds;
+
+    if (client->swapped) 
+    {
+	int n;
+    	swaps(&rep.sequenceNumber, n);
+    	swapl(&rep.length, n);
+	swapl(&rep.newTimestamp, n);
+    }
+    WriteToClient(client, sizeof(xRRSetCrtcConfigReply), (char *)&rep);
+    
+    return client->noClientException;
+}
+
+int
+ProcRRGetCrtcGammaSize (ClientPtr client)
+{
+    REQUEST(xRRGetCrtcGammaSizeReq);
+    xRRGetCrtcGammaSizeReply	reply;
+    RRCrtcPtr			crtc;
+    int				n;
+
+    REQUEST_SIZE_MATCH(xRRGetCrtcGammaSizeReq);
+    crtc = LookupCrtc (client, stuff->crtc, SecurityReadAccess);
+    if (!crtc)
+	return RRErrorBase + BadRRCrtc;
+    
+    reply.type = X_Reply;
+    reply.sequenceNumber = client->sequence;
+    reply.length = 0;
+    reply.size = crtc->gammaSize;
+    if (client->swapped) {
+	swaps (&reply.sequenceNumber, n);
+	swapl (&reply.length, n);
+	swaps (&reply.size, n);
+    }
+    WriteToClient (client, sizeof (xRRGetCrtcGammaSizeReply), (char *) &reply);
+    return client->noClientException;
+}
+
+int
+ProcRRGetCrtcGamma (ClientPtr client)
+{
+    REQUEST(xRRGetCrtcGammaReq);
+    xRRGetCrtcGammaReply	reply;
+    RRCrtcPtr			crtc;
+    int				n;
+    unsigned long		len;
+    
+    REQUEST_SIZE_MATCH(xRRGetCrtcGammaReq);
+    crtc = LookupCrtc (client, stuff->crtc, SecurityReadAccess);
+    if (!crtc)
+	return RRErrorBase + BadRRCrtc;
+    
+    len = crtc->gammaSize * 3 * 2;
+    
+    reply.type = X_Reply;
+    reply.sequenceNumber = client->sequence;
+    reply.length = (len + 3) >> 2;
+    reply.size = crtc->gammaSize;
+    if (client->swapped) {
+	swaps (&reply.sequenceNumber, n);
+	swapl (&reply.length, n);
+	swaps (&reply.size, n);
+    }
+    WriteToClient (client, sizeof (xRRGetCrtcGammaReply), (char *) &reply);
+    if (crtc->gammaSize)
+    {
+	client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write;
+	WriteSwappedDataToClient (client, len, (char *) crtc->gammaRed);
+    }
+    return client->noClientException;
+}
+
+int
+ProcRRSetCrtcGamma (ClientPtr client)
+{
+    REQUEST(xRRSetCrtcGammaReq);
+    RRCrtcPtr			crtc;
+    unsigned long		len;
+    CARD16			*red, *green, *blue;
+    
+    REQUEST_AT_LEAST_SIZE(xRRSetCrtcGammaReq);
+    crtc = LookupCrtc (client, stuff->crtc, SecurityWriteAccess);
+    if (!crtc)
+	return RRErrorBase + BadRRCrtc;
+    
+    len = client->req_len - (sizeof (xRRSetCrtcGammaReq) >> 2);
+    if (len < (stuff->size * 3 + 1) >> 1)
+	return BadLength;
+
+    if (stuff->size != crtc->gammaSize)
+	return BadMatch;
+    
+    red = (CARD16 *) (stuff + 1);
+    green = red + crtc->gammaSize;
+    blue = green + crtc->gammaSize;
+    
+    RRCrtcGammaSet (crtc, red, green, blue);
+
+    return Success;
+}
+
diff --git a/randr/rrdispatch.c b/randr/rrdispatch.c
new file mode 100644
index 0000000..9efb5b7
--- /dev/null
+++ b/randr/rrdispatch.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright © 2006 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "randrstr.h"
+
+#define SERVER_RANDR_MAJOR	1
+#define SERVER_RANDR_MINOR	2
+
+Bool
+RRClientKnowsRates (ClientPtr	pClient)
+{
+    rrClientPriv(pClient);
+
+    return (pRRClient->major_version > 1 ||
+	    (pRRClient->major_version == 1 && pRRClient->minor_version >= 1));
+}
+
+static int
+ProcRRQueryVersion (ClientPtr client)
+{
+    xRRQueryVersionReply rep;
+    register int n;
+    REQUEST(xRRQueryVersionReq);
+    rrClientPriv(client);
+
+    REQUEST_SIZE_MATCH(xRRQueryVersionReq);
+    pRRClient->major_version = stuff->majorVersion;
+    pRRClient->minor_version = stuff->minorVersion;
+    rep.type = X_Reply;
+    rep.length = 0;
+    rep.sequenceNumber = client->sequence;
+    /*
+     * Report the current version; the current
+     * spec says they're all compatible after 1.0
+     */
+    rep.majorVersion = SERVER_RANDR_MAJOR;
+    rep.minorVersion = SERVER_RANDR_MINOR;
+    if (client->swapped) {
+    	swaps(&rep.sequenceNumber, n);
+    	swapl(&rep.length, n);
+	swapl(&rep.majorVersion, n);
+	swapl(&rep.minorVersion, n);
+    }
+    WriteToClient(client, sizeof(xRRQueryVersionReply), (char *)&rep);
+    return (client->noClientException);
+}
+
+static int
+ProcRRSelectInput (ClientPtr client)
+{
+    REQUEST(xRRSelectInputReq);
+    rrClientPriv(client);
+    RRTimesPtr	pTimes;
+    WindowPtr	pWin;
+    RREventPtr	pRREvent, *pHead;
+    XID		clientResource;
+
+    REQUEST_SIZE_MATCH(xRRSelectInputReq);
+    pWin = SecurityLookupWindow(stuff->window, client, SecurityWriteAccess);
+    if (!pWin)
+	return BadAccess;
+    pHead = (RREventPtr *)SecurityLookupIDByType(client,
+						 pWin->drawable.id, RREventType,
+						 SecurityWriteAccess);
+
+    if (stuff->enable & (RRScreenChangeNotifyMask|
+			 RRCrtcChangeNotifyMask|
+			 RROutputChangeNotifyMask)) 
+    {
+	ScreenPtr	pScreen = pWin->drawable.pScreen;
+	rrScrPriv	(pScreen);
+
+	pRREvent = NULL;
+	if (pHead) 
+	{
+	    /* check for existing entry. */
+	    for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
+		if (pRREvent->client == client)
+		    break;
+	}
+
+	if (!pRREvent)
+	{
+	    /* build the entry */
+	    pRREvent = (RREventPtr) xalloc (sizeof (RREventRec));
+	    if (!pRREvent)
+		return BadAlloc;
+	    pRREvent->next = 0;
+	    pRREvent->client = client;
+	    pRREvent->window = pWin;
+	    pRREvent->mask = stuff->enable;
+	    /*
+	     * add a resource that will be deleted when
+	     * the client goes away
+	     */
+	    clientResource = FakeClientID (client->index);
+	    pRREvent->clientResource = clientResource;
+	    if (!AddResource (clientResource, RRClientType, (pointer)pRREvent))
+		return BadAlloc;
+	    /*
+	     * create a resource to contain a pointer to the list
+	     * of clients selecting input.  This must be indirect as
+	     * the list may be arbitrarily rearranged which cannot be
+	     * done through the resource database.
+	     */
+	    if (!pHead)
+	    {
+		pHead = (RREventPtr *) xalloc (sizeof (RREventPtr));
+		if (!pHead ||
+		    !AddResource (pWin->drawable.id, RREventType, (pointer)pHead))
+		{
+		    FreeResource (clientResource, RT_NONE);
+		    return BadAlloc;
+		}
+		*pHead = 0;
+	    }
+	    pRREvent->next = *pHead;
+	    *pHead = pRREvent;
+	}
+	/*
+	 * Now see if the client needs an event
+	 */
+	if (pScrPriv && (pRREvent->mask & RRScreenChangeNotifyMask))
+	{
+	    pTimes = &((RRTimesPtr) (pRRClient + 1))[pScreen->myNum];
+	    if (CompareTimeStamps (pTimes->setTime, 
+				   pScrPriv->lastSetTime) != 0 ||
+		CompareTimeStamps (pTimes->configTime, 
+				   pScrPriv->lastConfigTime) != 0)
+	    {
+		RRDeliverScreenEvent (client, pWin, pScreen);
+	    }
+	}
+    }
+    else if (stuff->enable == 0) 
+    {
+	/* delete the interest */
+	if (pHead) {
+	    RREventPtr pNewRREvent = 0;
+	    for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) {
+		if (pRREvent->client == client)
+		    break;
+		pNewRREvent = pRREvent;
+	    }
+	    if (pRREvent) {
+		FreeResource (pRREvent->clientResource, RRClientType);
+		if (pNewRREvent)
+		    pNewRREvent->next = pRREvent->next;
+		else
+		    *pHead = pRREvent->next;
+		xfree (pRREvent);
+	    }
+	}
+    }
+    else 
+    {
+	client->errorValue = stuff->enable;
+	return BadValue;
+    }
+    return Success;
+}
+
+int (*ProcRandrVector[RRNumberRequests])(ClientPtr) = {
+    ProcRRQueryVersion,	/* 0 */
+/* we skip 1 to make old clients fail pretty immediately */
+    NULL,			/* 1 ProcRandrOldGetScreenInfo */
+/* V1.0 apps share the same set screen config request id */
+    ProcRRSetScreenConfig,	/* 2 */
+    NULL,			/* 3 ProcRandrOldScreenChangeSelectInput */
+/* 3 used to be ScreenChangeSelectInput; deprecated */
+    ProcRRSelectInput,		/* 4 */
+    ProcRRGetScreenInfo,    	/* 5 */
+/* V1.2 additions */
+    ProcRRGetScreenSizeRange,	/* 6 */
+    ProcRRSetScreenSize,	/* 7 */
+    ProcRRGetScreenResources,	/* 8 */
+    ProcRRGetOutputInfo,	/* 9 */
+    ProcRRListOutputProperties,	/* 10 */
+    ProcRRQueryOutputProperty,	/* 11 */
+    ProcRRConfigureOutputProperty,  /* 12 */
+    ProcRRChangeOutputProperty,	/* 13 */
+    ProcRRDeleteOutputProperty,	/* 14 */
+    ProcRRGetOutputProperty,	/* 15 */
+    ProcRRCreateMode,		/* 16 */
+    ProcRRDestroyMode,		/* 17 */
+    ProcRRAddOutputMode,	/* 18 */
+    ProcRRDeleteOutputMode,	/* 19 */
+    ProcRRGetCrtcInfo,		/* 20 */
+    ProcRRSetCrtcConfig,	/* 21 */
+    ProcRRGetCrtcGammaSize,	/* 22 */
+    ProcRRGetCrtcGamma,		/* 23 */
+    ProcRRSetCrtcGamma,		/* 24 */
+};
+
diff --git a/randr/rrinfo.c b/randr/rrinfo.c
new file mode 100644
index 0000000..7e77d39
--- /dev/null
+++ b/randr/rrinfo.c
@@ -0,0 +1,335 @@
+/*
+ * Copyright © 2006 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "randrstr.h"
+
+#ifdef RANDR_10_INTERFACE
+static RRModePtr
+RROldModeAdd (RROutputPtr output, RRScreenSizePtr size, int refresh)
+{
+    ScreenPtr	pScreen = output->pScreen;
+    rrScrPriv(pScreen);
+    xRRModeInfo	modeInfo;
+    char	name[100];
+    RRModePtr	mode;
+    int		i;
+    RRModePtr   *modes;
+    
+    memset (&modeInfo, '\0', sizeof (modeInfo));
+    sprintf (name, "%dx%d", size->width, size->height);
+    
+    modeInfo.width = size->width;
+    modeInfo.height = size->height;
+    modeInfo.hTotal = size->width;
+    modeInfo.vTotal = size->height;
+    modeInfo.dotClock = ((CARD32) size->width * (CARD32) size->height *
+			 (CARD32) refresh);
+    modeInfo.nameLength = strlen (name);
+    mode = RRModeGet (&modeInfo, name);
+    if (!mode)
+	return NULL;
+    for (i = 0; i < output->numModes; i++)
+	if (output->modes[i] == mode)
+	{
+	    RRModeDestroy (mode);
+	    return mode;
+	}
+    
+    if (output->numModes)
+	modes = xrealloc (output->modes, 
+			  (output->numModes + 1) * sizeof (RRModePtr));
+    else
+	modes = xalloc (sizeof (RRModePtr));
+    if (!modes)
+    {
+	RRModeDestroy (mode);
+	FreeResource (mode->mode.id, 0);
+	return NULL;
+    }
+    modes[output->numModes++] = mode;
+    output->modes = modes;
+    output->changed = TRUE;
+    pScrPriv->changed = TRUE;
+    pScrPriv->configChanged = TRUE;
+    return mode;
+}
+
+static void
+RRScanOldConfig (ScreenPtr pScreen, Rotation rotations)
+{
+    rrScrPriv(pScreen);
+    RROutputPtr	output;
+    RRCrtcPtr	crtc;
+    RRModePtr	mode, newMode = NULL;
+    int		i;
+    CARD16	minWidth = MAXSHORT, minHeight = MAXSHORT;
+    CARD16	maxWidth = 0, maxHeight = 0;
+    
+    /*
+     * First time through, create a crtc and output and hook
+     * them together
+     */
+    if (pScrPriv->numOutputs == 0 &&
+	pScrPriv->numCrtcs == 0)
+    {
+	crtc = RRCrtcCreate (pScreen, NULL);
+	if (!crtc)
+	    return;
+	output = RROutputCreate (pScreen, "default", 7, NULL);
+	if (!output)
+	    return;
+	RROutputSetCrtcs (output, &crtc, 1);
+	RROutputSetConnection (output, RR_Connected);
+#ifdef RENDER
+	RROutputSetSubpixelOrder (output, PictureGetSubpixelOrder (pScreen));
+#endif
+    }
+
+    output = pScrPriv->outputs[0];
+    if (!output)
+	return;
+    crtc = pScrPriv->crtcs[0];
+    if (!crtc)
+	return;
+
+    /* check rotations */
+    if (rotations != crtc->rotations)
+    {
+        crtc->rotations = rotations;
+	crtc->changed = TRUE;
+	pScrPriv->changed = TRUE;
+    }
+	
+    /* regenerate mode list */
+    for (i = 0; i < pScrPriv->nSizes; i++)
+    {
+	RRScreenSizePtr	size = &pScrPriv->pSizes[i];
+	int		r;
+
+	if (size->nRates)
+	{
+	    for (r = 0; r < size->nRates; r++)
+	    {
+		mode = RROldModeAdd (output, size, size->pRates[r].rate);
+		if (i == pScrPriv->size && 
+		    size->pRates[r].rate == pScrPriv->rate)
+		{
+		    newMode = mode;
+		}
+	    }
+	    xfree (size->pRates);
+	}
+	else
+	{
+	    mode = RROldModeAdd (output, size, 0);
+	    if (i == pScrPriv->size)
+		newMode = mode;
+	}
+    }
+    if (pScrPriv->nSizes)
+	xfree (pScrPriv->pSizes);
+    pScrPriv->pSizes = NULL;
+    pScrPriv->nSizes = 0;
+	    
+    /* find size bounds */
+    for (i = 0; i < output->numModes + output->numUserModes; i++) 
+    {
+	RRModePtr   mode = (i < output->numModes ? 
+			    output->modes[i] : 
+			    output->userModes[i-output->numModes]);
+        CARD16	    width = mode->mode.width;
+        CARD16	    height = mode->mode.height;
+	
+	if (width < minWidth) minWidth = width;
+	if (width > maxWidth) maxWidth = width;
+	if (height < minHeight) minHeight = height;
+	if (height > maxHeight) maxHeight = height;
+    }
+
+    RRScreenSetSizeRange (pScreen, minWidth, minHeight, maxWidth, maxHeight);
+
+    /* notice current mode */
+    if (newMode)
+	RRCrtcNotify (crtc, newMode, 0, 0, pScrPriv->rotation,
+		      1, &output);
+}
+#endif
+
+/*
+ * Poll the driver for changed information
+ */
+Bool
+RRGetInfo (ScreenPtr pScreen)
+{
+    rrScrPriv (pScreen);
+    Rotation	    rotations;
+    int		    i;
+
+    for (i = 0; i < pScrPriv->numOutputs; i++)
+	pScrPriv->outputs[i]->changed = FALSE;
+    for (i = 0; i < pScrPriv->numCrtcs; i++)
+	pScrPriv->crtcs[i]->changed = FALSE;
+    
+    rotations = 0;
+    pScrPriv->changed = FALSE;
+    pScrPriv->configChanged = FALSE;
+    
+    if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations))
+	return FALSE;
+
+#if RANDR_10_INTERFACE
+    if (pScrPriv->nSizes)
+	RRScanOldConfig (pScreen, rotations);
+#endif
+    RRTellChanged (pScreen);
+    return TRUE;
+}
+
+/*
+ * Register the range of sizes for the screen
+ */
+void
+RRScreenSetSizeRange (ScreenPtr	pScreen,
+		      CARD16	minWidth,
+		      CARD16	minHeight,
+		      CARD16	maxWidth,
+		      CARD16	maxHeight)
+{
+    rrScrPriv (pScreen);
+
+    if (!pScrPriv)
+	return;
+    if (pScrPriv->minWidth == minWidth && pScrPriv->minHeight == minHeight &&
+	pScrPriv->maxWidth == maxWidth && pScrPriv->maxHeight == maxHeight)
+    {
+	return;
+    }
+	
+    pScrPriv->minWidth  = minWidth;
+    pScrPriv->minHeight = minHeight;
+    pScrPriv->maxWidth  = maxWidth;
+    pScrPriv->maxHeight = maxHeight;
+    pScrPriv->changed = TRUE;
+    pScrPriv->configChanged = TRUE;
+}
+
+#ifdef RANDR_10_INTERFACE
+static Bool
+RRScreenSizeMatches (RRScreenSizePtr  a,
+		   RRScreenSizePtr  b)
+{
+    if (a->width != b->width)
+	return FALSE;
+    if (a->height != b->height)
+	return FALSE;
+    if (a->mmWidth != b->mmWidth)
+	return FALSE;
+    if (a->mmHeight != b->mmHeight)
+	return FALSE;
+    return TRUE;
+}
+
+RRScreenSizePtr
+RRRegisterSize (ScreenPtr	    pScreen,
+		short		    width, 
+		short		    height,
+		short		    mmWidth,
+		short		    mmHeight)
+{
+    rrScrPriv (pScreen);
+    int		    i;
+    RRScreenSize    tmp;
+    RRScreenSizePtr pNew;
+
+    if (!pScrPriv)
+	return 0;
+    
+    tmp.id = 0;
+    tmp.width = width;
+    tmp.height= height;
+    tmp.mmWidth = mmWidth;
+    tmp.mmHeight = mmHeight;
+    tmp.pRates = 0;
+    tmp.nRates = 0;
+    for (i = 0; i < pScrPriv->nSizes; i++)
+	if (RRScreenSizeMatches (&tmp, &pScrPriv->pSizes[i]))
+	    return &pScrPriv->pSizes[i];
+    pNew = xrealloc (pScrPriv->pSizes,
+		     (pScrPriv->nSizes + 1) * sizeof (RRScreenSize));
+    if (!pNew)
+	return 0;
+    pNew[pScrPriv->nSizes++] = tmp;
+    pScrPriv->pSizes = pNew;
+    return &pNew[pScrPriv->nSizes-1];
+}
+
+Bool RRRegisterRate (ScreenPtr		pScreen,
+		     RRScreenSizePtr	pSize,
+		     int		rate)
+{
+    rrScrPriv(pScreen);
+    int		    i;
+    RRScreenRatePtr pNew, pRate;
+
+    if (!pScrPriv)
+	return FALSE;
+    
+    for (i = 0; i < pSize->nRates; i++)
+	if (pSize->pRates[i].rate == rate)
+	    return TRUE;
+
+    pNew = xrealloc (pSize->pRates,
+		     (pSize->nRates + 1) * sizeof (RRScreenRate));
+    if (!pNew)
+	return FALSE;
+    pRate = &pNew[pSize->nRates++];
+    pRate->rate = rate;
+    pSize->pRates = pNew;
+    return TRUE;
+}
+
+Rotation
+RRGetRotation(ScreenPtr pScreen)
+{
+    RROutputPtr	output = RRFirstOutput (pScreen);
+
+    if (!output)
+	return RR_Rotate_0;
+
+    return output->crtc->rotation;
+}
+
+void
+RRSetCurrentConfig (ScreenPtr		pScreen,
+		    Rotation		rotation,
+		    int			rate,
+		    RRScreenSizePtr	pSize)
+{
+    rrScrPriv (pScreen);
+
+    if (!pScrPriv)
+	return;
+    pScrPriv->size = pSize - pScrPriv->pSizes;
+    pScrPriv->rotation = rotation;
+    pScrPriv->rate = rate;
+}
+#endif
diff --git a/randr/rrmode.c b/randr/rrmode.c
new file mode 100644
index 0000000..a8baa6c
--- /dev/null
+++ b/randr/rrmode.c
@@ -0,0 +1,397 @@
+/*
+ * Copyright © 2006 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "randrstr.h"
+
+RESTYPE	RRModeType;
+
+static Bool
+RRModeEqual (xRRModeInfo *a, xRRModeInfo *b)
+{
+    if (a->width != b->width) return FALSE;
+    if (a->height != b->height) return FALSE;
+    if (a->dotClock != b->dotClock) return FALSE;
+    if (a->hSyncStart != b->hSyncStart) return FALSE;
+    if (a->hSyncEnd != b->hSyncEnd) return FALSE;
+    if (a->hTotal != b->hTotal) return FALSE;
+    if (a->hSkew != b->hSkew) return FALSE;
+    if (a->vSyncStart != b->vSyncStart) return FALSE;
+    if (a->vSyncEnd != b->vSyncEnd) return FALSE;
+    if (a->vTotal != b->vTotal) return FALSE;
+    if (a->nameLength != b->nameLength) return FALSE;
+    if (a->modeFlags != b->modeFlags) return FALSE;
+    return TRUE;
+}
+
+/*
+ * Keep a list so it's easy to find modes in the resource database.
+ */
+static int	    num_modes;
+static RRModePtr    *modes;
+
+static RRModePtr
+RRModeCreate (xRRModeInfo   *modeInfo,
+	      const char    *name,
+	      ScreenPtr	    userScreen)
+{
+    RRModePtr	mode, *newModes;
+    
+    if (!RRInit ())
+	return NULL;
+
+    mode = xalloc (sizeof (RRModeRec) + modeInfo->nameLength + 1);
+    if (!mode)
+	return NULL;
+    mode->refcnt = 1;
+    mode->mode = *modeInfo;
+    mode->name = (char *) (mode + 1);
+    memcpy (mode->name, name, modeInfo->nameLength);
+    mode->name[modeInfo->nameLength] = '\0';
+    mode->userScreen = userScreen;
+
+    if (num_modes)
+	newModes = xrealloc (modes, (num_modes + 1) * sizeof (RRModePtr));
+    else
+	newModes = xalloc (sizeof (RRModePtr));
+
+    if (!newModes)
+    {
+	xfree (mode);
+	return NULL;
+    }
+
+    mode->mode.id = FakeClientID(0);
+    if (!AddResource (mode->mode.id, RRModeType, (pointer) mode))
+	return NULL;
+    modes = newModes;
+    modes[num_modes++] = mode;
+    
+    /*
+     * give the caller a reference to this mode
+     */
+    ++mode->refcnt;
+    return mode;
+}
+
+static RRModePtr
+RRModeFindByName (const char	*name,
+		  CARD16    	nameLength)
+{
+    int		i;
+    RRModePtr	mode;
+
+    for (i = 0; i < num_modes; i++)
+    {
+	mode = modes[i];
+	if (mode->mode.nameLength == nameLength &&
+	    !memcmp (name, mode->name, nameLength))
+	{
+	    return mode;
+	}
+    }
+    return NULL;
+}
+
+RRModePtr
+RRModeGet (xRRModeInfo	*modeInfo,
+	   const char	*name)
+{
+    int	i;
+
+    for (i = 0; i < num_modes; i++)
+    {
+	RRModePtr   mode = modes[i];
+	if (RRModeEqual (&mode->mode, modeInfo) &&
+	    !memcmp (name, mode->name, modeInfo->nameLength))
+	{
+	    ++mode->refcnt;
+	    return mode;
+	}
+    }
+
+    return RRModeCreate (modeInfo, name, NULL);
+}
+
+static RRModePtr
+RRModeCreateUser (ScreenPtr	pScreen,
+		  xRRModeInfo	*modeInfo,
+		  const char	*name,
+		  int		*error)
+{
+    RRModePtr	mode;
+
+    mode = RRModeFindByName (name, modeInfo->nameLength);
+    if (mode)
+    {
+	*error = BadName;
+	return NULL;
+    }
+    
+    mode = RRModeCreate (modeInfo, name, pScreen);
+    if (!mode)
+    {
+	*error = BadAlloc;
+	return NULL;
+    }
+    *error = Success;
+    return mode;
+}
+
+RRModePtr *
+RRModesForScreen (ScreenPtr pScreen, int *num_ret)
+{
+    rrScrPriv(pScreen);
+    int		o, c, m;
+    RRModePtr	*screen_modes;
+    int		num_screen_modes = 0;
+
+    screen_modes = xalloc ((num_modes ? num_modes : 1) * sizeof (RRModePtr));
+    if (!screen_modes)
+	return NULL;
+    
+    /*
+     * Add modes from all outputs
+     */
+    for (o = 0; o < pScrPriv->numOutputs; o++)
+    {
+	RROutputPtr	output = pScrPriv->outputs[o];
+	int		m, n;
+
+	for (m = 0; m < output->numModes + output->numUserModes; m++)
+	{
+	    RRModePtr   mode = (m < output->numModes ? 
+				output->modes[m] : 
+				output->userModes[m-output->numModes]);
+	    for (n = 0; n < num_screen_modes; n++)
+		if (screen_modes[n] == mode)
+		    break;
+	    if (n == num_screen_modes)
+		screen_modes[num_screen_modes++] = mode;
+	}
+    }
+    /*
+     * Add modes from all crtcs. The goal is to
+     * make sure all available and active modes
+     * are visible to the client
+     */
+    for (c = 0; c < pScrPriv->numCrtcs; c++)
+    {
+	RRCrtcPtr	crtc = pScrPriv->crtcs[c];
+	RRModePtr	mode = crtc->mode;
+	int		n;
+
+	if (!mode) continue;
+	for (n = 0; n < num_screen_modes; n++)
+	    if (screen_modes[n] == mode)
+		break;
+	if (n == num_screen_modes)
+	    screen_modes[num_screen_modes++] = mode;
+    }
+    /*
+     * Add all user modes for this screen
+     */
+    for (m = 0; m < num_modes; m++)
+    {
+	RRModePtr	mode = modes[m];
+	int		n;
+
+	if (mode->userScreen != pScreen)
+	    continue;
+	for (n = 0; n < num_screen_modes; n++)
+	    if (screen_modes[n] == mode)
+		break;
+	if (n == num_screen_modes)
+	    screen_modes[num_screen_modes++] = mode;
+    }
+    
+    *num_ret = num_screen_modes;
+    return screen_modes;
+}
+
+void
+RRModeDestroy (RRModePtr mode)
+{
+    int	m;
+    
+    if (--mode->refcnt > 0)
+	return;
+    for (m = 0; m < num_modes; m++)
+    {
+	if (modes[m] == mode)
+	{
+	    memmove (modes + m, modes + m + 1,
+		     (num_modes - m - 1) * sizeof (RRModePtr));
+	    num_modes--;
+	    if (!num_modes)
+	    {
+		xfree (modes);
+		modes = NULL;
+	    }
+	    break;
+	}
+    }
+    
+    xfree (mode);
+}
+
+static int
+RRModeDestroyResource (pointer value, XID pid)
+{
+    RRModeDestroy ((RRModePtr) value);
+    return 1;
+}
+
+Bool
+RRModeInit (void)
+{
+    assert (num_modes == 0);
+    assert (modes == NULL);
+    RRModeType = CreateNewResourceType (RRModeDestroyResource);
+    if (!RRModeType)
+	return FALSE;
+    RegisterResourceName (RRModeType, "MODE");
+    return TRUE;
+}
+
+int
+ProcRRCreateMode (ClientPtr client)
+{
+    REQUEST(xRRCreateModeReq);
+    xRRCreateModeReply	rep;
+    WindowPtr		pWin;
+    ScreenPtr		pScreen;
+    rrScrPrivPtr	pScrPriv;
+    xRRModeInfo		*modeInfo;
+    long		units_after;
+    char		*name;
+    int			error;
+    RRModePtr		mode;
+    
+    REQUEST_AT_LEAST_SIZE (xRRCreateModeReq);
+    pWin = SecurityLookupWindow(stuff->window, client, SecurityReadAccess);
+    if (!pWin)
+	return BadAccess;
+
+    pScreen = pWin->drawable.pScreen;
+    pScrPriv = rrGetScrPriv(pScreen);
+    
+    modeInfo = &stuff->modeInfo;
+    name = (char *) (stuff + 1);
+    units_after = (stuff->length - (sizeof (xRRCreateModeReq) >> 2));
+
+    /* check to make sure requested name fits within the data provided */
+    if ((int) (modeInfo->nameLength + 3) >> 2 > units_after)
+	return BadLength;
+
+    mode = RRModeCreateUser (pScreen, modeInfo, name, &error);
+    if (!mode)
+	return error;
+
+    rep.type = X_Reply;
+    rep.pad0 = 0;
+    rep.sequenceNumber = client->sequence;
+    rep.length = 0;
+    rep.mode = mode->mode.id;
+    if (client->swapped)
+    {
+	int n;
+    	swaps(&rep.sequenceNumber, n);
+    	swapl(&rep.length, n);
+	swapl(&rep.mode, n);
+    }
+    WriteToClient(client, sizeof(xRRCreateModeReply), (char *)&rep);
+    
+    return client->noClientException;
+}
+
+int
+ProcRRDestroyMode (ClientPtr client)
+{
+    REQUEST(xRRDestroyModeReq);
+    RRModePtr	mode;
+    
+    REQUEST_SIZE_MATCH(xRRDestroyModeReq);
+    mode = LookupIDByType (stuff->mode, RRModeType);
+    if (!mode)
+    {
+	client->errorValue = stuff->mode;
+	return RRErrorBase + BadRRMode;
+    }
+    if (!mode->userScreen)
+	return BadMatch;
+    if (mode->refcnt > 1)
+	return BadAccess;
+    FreeResource (stuff->mode, 0);
+    return Success;
+}
+
+int
+ProcRRAddOutputMode (ClientPtr client)
+{
+    REQUEST(xRRAddOutputModeReq);
+    RRModePtr	mode;
+    RROutputPtr	output;
+    
+    REQUEST_SIZE_MATCH(xRRAddOutputModeReq);
+    output = LookupOutput(client, stuff->output, SecurityReadAccess);
+
+    if (!output)
+    {
+	client->errorValue = stuff->output;
+	return RRErrorBase + BadRROutput;
+    }
+    
+    mode = LookupIDByType (stuff->mode, RRModeType);
+    if (!mode)
+    {
+	client->errorValue = stuff->mode;
+	return RRErrorBase + BadRRMode;
+    }
+    
+    return RROutputAddUserMode (output, mode);
+}
+
+int
+ProcRRDeleteOutputMode (ClientPtr client)
+{
+    REQUEST(xRRDeleteOutputModeReq);
+    RRModePtr	mode;
+    RROutputPtr	output;
+    
+    REQUEST_SIZE_MATCH(xRRDeleteOutputModeReq);
+    output = LookupOutput(client, stuff->output, SecurityReadAccess);
+
+    if (!output)
+    {
+	client->errorValue = stuff->output;
+	return RRErrorBase + BadRROutput;
+    }
+    
+    mode = LookupIDByType (stuff->mode, RRModeType);
+    if (!mode)
+    {
+	client->errorValue = stuff->mode;
+	return RRErrorBase + BadRRMode;
+    }
+    
+    return RROutputDeleteUserMode (output, mode);
+}
diff --git a/randr/rroutput.c b/randr/rroutput.c
new file mode 100644
index 0000000..973599d
--- /dev/null
+++ b/randr/rroutput.c
@@ -0,0 +1,534 @@
+/*
+ * Copyright © 2006 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "randrstr.h"
+
+RESTYPE	RROutputType;
+
+/*
+ * Notify the output of some change
+ */
+void
+RROutputChanged (RROutputPtr output, Bool configChanged)
+{
+    ScreenPtr	pScreen = output->pScreen;
+    
+    output->changed = TRUE;
+    if (pScreen)
+    {
+	rrScrPriv (pScreen);
+	pScrPriv->changed = TRUE;
+	if (configChanged)
+	    pScrPriv->configChanged = TRUE;
+    }
+}
+
+/*
+ * Create an output
+ */
+
+RROutputPtr
+RROutputCreate (ScreenPtr   pScreen,
+		const char  *name,
+		int	    nameLength,
+		void	    *devPrivate)
+{
+    RROutputPtr	    output;
+    RROutputPtr	    *outputs;
+    rrScrPrivPtr    pScrPriv;
+
+    if (!RRInit())
+	return NULL;
+    
+    pScrPriv = rrGetScrPriv(pScreen);
+
+    if (pScrPriv->numOutputs)
+	outputs = xrealloc (pScrPriv->outputs, 
+			    (pScrPriv->numOutputs + 1) * sizeof (RROutputPtr));
+    else
+	outputs = xalloc (sizeof (RROutputPtr));
+    if (!outputs)
+	return FALSE;
+
+    pScrPriv->outputs = outputs;
+    
+    output = xalloc (sizeof (RROutputRec) + nameLength + 1);
+    if (!output)
+	return NULL;
+    output->id = FakeClientID (0);
+    output->pScreen = pScreen;
+    output->name = (char *) (output + 1);
+    output->nameLength = nameLength;
+    memcpy (output->name, name, nameLength);
+    output->name[nameLength] = '\0';
+    output->connection = RR_UnknownConnection;
+    output->subpixelOrder = SubPixelUnknown;
+    output->mmWidth = 0;
+    output->mmHeight = 0;
+    output->crtc = NULL;
+    output->numCrtcs = 0;
+    output->crtcs = NULL;
+    output->numClones = 0;
+    output->clones = NULL;
+    output->numModes = 0;
+    output->numPreferred = 0;
+    output->modes = NULL;
+    output->numUserModes = 0;
+    output->userModes = NULL;
+    output->properties = NULL;
+    output->pendingProperties = FALSE;
+    output->changed = FALSE;
+    output->devPrivate = devPrivate;
+    
+    if (!AddResource (output->id, RROutputType, (pointer) output))
+	return NULL;
+
+    pScrPriv->outputs[pScrPriv->numOutputs++] = output;
+    return output;
+}
+
+/*
+ * Notify extension that output parameters have been changed
+ */
+Bool
+RROutputSetClones (RROutputPtr  output,
+		   RROutputPtr  *clones,
+		   int		numClones)
+{
+    RROutputPtr	*newClones;
+    int		i;
+
+    if (numClones == output->numClones)
+    {
+	for (i = 0; i < numClones; i++)
+	    if (output->clones[i] != clones[i])
+		break;
+	if (i == numClones)
+	    return TRUE;
+    }
+    if (numClones)
+    {
+	newClones = xalloc (numClones * sizeof (RROutputPtr));
+	if (!newClones)
+	    return FALSE;
+    }
+    else
+	newClones = NULL;
+    if (output->clones)
+	xfree (output->clones);
+    memcpy (newClones, clones, numClones * sizeof (RROutputPtr));
+    output->clones = newClones;
+    output->numClones = numClones;
+    RROutputChanged (output, TRUE);
+    return TRUE;
+}
+
+Bool
+RROutputSetModes (RROutputPtr	output,
+		  RRModePtr	*modes,
+		  int		numModes,
+		  int		numPreferred)
+{
+    RRModePtr	*newModes;
+    int		i;
+
+    if (numModes == output->numModes && numPreferred == output->numPreferred)
+    {
+	for (i = 0; i < numModes; i++)
+	    if (output->modes[i] != modes[i])
+		break;
+	if (i == numModes)
+	{
+	    for (i = 0; i < numModes; i++)
+		RRModeDestroy (modes[i]);
+	    return TRUE;
+	}
+    }
+
+    if (numModes)
+    {
+	newModes = xalloc (numModes * sizeof (RRModePtr));
+	if (!newModes)
+	    return FALSE;
+    }
+    else
+	newModes = NULL;
+    if (output->modes)
+    {
+	for (i = 0; i < output->numModes; i++)
+	    RRModeDestroy (output->modes[i]);
+	xfree (output->modes);
+    }
+    memcpy (newModes, modes, numModes * sizeof (RRModePtr));
+    output->modes = newModes;
+    output->numModes = numModes;
+    output->numPreferred = numPreferred;
+    RROutputChanged (output, TRUE);
+    return TRUE;
+}
+
+int
+RROutputAddUserMode (RROutputPtr    output,
+		     RRModePtr	    mode)
+{
+    int		m;
+    ScreenPtr	pScreen = output->pScreen;
+    rrScrPriv(pScreen);
+    RRModePtr	*newModes;
+
+    /* Check to see if this mode is already listed for this output */
+    for (m = 0; m < output->numModes + output->numUserModes; m++)
+    {
+	RRModePtr   e = (m < output->numModes ?
+			 output->modes[m] :
+			 output->userModes[m - output->numModes]);
+	if (mode == e)
+	    return Success;
+    }
+
+    /* Check with the DDX to see if this mode is OK */
+    if (pScrPriv->rrOutputValidateMode)
+	if (!pScrPriv->rrOutputValidateMode (pScreen, output, mode))
+	    return BadMatch;
+
+    if (output->userModes)
+	newModes = xrealloc (output->userModes,
+			     (output->numUserModes + 1) * sizeof (RRModePtr));
+    else
+	newModes = xalloc (sizeof (RRModePtr));
+    if (!newModes)
+	return BadAlloc;
+
+    output->userModes = newModes;
+    output->userModes[output->numUserModes++] = mode;
+    ++mode->refcnt;
+    RROutputChanged (output, TRUE);
+    RRTellChanged (pScreen);
+    return Success;
+}
+
+int
+RROutputDeleteUserMode (RROutputPtr output,
+			RRModePtr   mode)
+{
+    int		m;
+    
+    /* Find this mode in the user mode list */
+    for (m = 0; m < output->numUserModes; m++)
+    {
+	RRModePtr   e = output->userModes[m];
+
+	if (mode == e)
+	    break;
+    }
+    /* Not there, access error */
+    if (m == output->numUserModes)
+	return BadAccess;
+
+    /* make sure the mode isn't active for this output */
+    if (output->crtc && output->crtc->mode == mode)
+	return BadMatch;
+
+    memmove (output->userModes + m, output->userModes + m + 1,
+	     (output->numUserModes - m - 1) * sizeof (RRModePtr));
+    output->numUserModes--;
+    RRModeDestroy (mode);
+    return Success;
+}
+
+Bool
+RROutputSetCrtcs (RROutputPtr	output,
+		  RRCrtcPtr	*crtcs,
+		  int		numCrtcs)
+{
+    RRCrtcPtr	*newCrtcs;
+    int		i;
+
+    if (numCrtcs == output->numCrtcs)
+    {
+	for (i = 0; i < numCrtcs; i++)
+	    if (output->crtcs[i] != crtcs[i])
+		break;
+	if (i == numCrtcs)
+	    return TRUE;
+    }
+    if (numCrtcs)
+    {
+	newCrtcs = xalloc (numCrtcs * sizeof (RRCrtcPtr));
+	if (!newCrtcs)
+	    return FALSE;
+    }
+    else
+	newCrtcs = NULL;
+    if (output->crtcs)
+	xfree (output->crtcs);
+    memcpy (newCrtcs, crtcs, numCrtcs * sizeof (RRCrtcPtr));
+    output->crtcs = newCrtcs;
+    output->numCrtcs = numCrtcs;
+    RROutputChanged (output, TRUE);
+    return TRUE;
+}
+
+Bool
+RROutputSetConnection (RROutputPtr  output,
+		       CARD8	    connection)
+{
+    if (output->connection == connection)
+	return TRUE;
+    output->connection = connection;
+    RROutputChanged (output, TRUE);
+    return TRUE;
+}
+
+Bool
+RROutputSetSubpixelOrder (RROutputPtr output,
+			  int	      subpixelOrder)
+{
+    if (output->subpixelOrder == subpixelOrder)
+	return TRUE;
+
+    output->subpixelOrder = subpixelOrder;
+    RROutputChanged (output, FALSE);
+    return TRUE;
+}
+
+Bool
+RROutputSetPhysicalSize (RROutputPtr	output,
+			 int		mmWidth,
+			 int		mmHeight)
+{
+    if (output->mmWidth == mmWidth && output->mmHeight == mmHeight)
+	return TRUE;
+    output->mmWidth = mmWidth;
+    output->mmHeight = mmHeight;
+    RROutputChanged (output, FALSE);
+    return TRUE;
+}
+
+
+void
+RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output)
+{
+    ScreenPtr pScreen = pWin->drawable.pScreen;
+    rrScrPriv (pScreen);
+    xRROutputChangeNotifyEvent	oe;
+    RRCrtcPtr	crtc = output->crtc;
+    RRModePtr	mode = crtc ? crtc->mode : 0;
+    
+    oe.type = RRNotify + RREventBase;
+    oe.subCode = RRNotify_OutputChange;
+    oe.sequenceNumber = client->sequence;
+    oe.timestamp = pScrPriv->lastSetTime.milliseconds;
+    oe.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
+    oe.window = pWin->drawable.id;
+    oe.output = output->id;
+    if (crtc)
+    {
+	oe.crtc = crtc->id;
+	oe.mode = mode ? mode->mode.id : None;
+	oe.rotation = crtc->rotation;
+    }
+    else
+    {
+	oe.crtc = None;
+	oe.mode = None;
+	oe.rotation = RR_Rotate_0;
+    }
+    oe.connection = output->connection;
+    oe.subpixelOrder = output->subpixelOrder;
+    WriteEventsToClient (client, 1, (xEvent *) &oe);
+}
+
+/*
+ * Destroy a Output at shutdown
+ */
+void
+RROutputDestroy (RROutputPtr output)
+{
+    FreeResource (output->id, 0);
+}
+
+static int
+RROutputDestroyResource (pointer value, XID pid)
+{
+    RROutputPtr	output = (RROutputPtr) value;
+    ScreenPtr	pScreen = output->pScreen;
+    int		m;
+
+    if (pScreen)
+    {
+	rrScrPriv(pScreen);
+	int		i;
+    
+	for (i = 0; i < pScrPriv->numOutputs; i++)
+	{
+	    if (pScrPriv->outputs[i] == output)
+	    {
+		memmove (pScrPriv->outputs + i, pScrPriv->outputs + i + 1,
+			 (pScrPriv->numOutputs - (i + 1)) * sizeof (RROutputPtr));
+		--pScrPriv->numOutputs;
+		break;
+	    }
+	}
+    }
+    if (output->modes)
+    {
+	for (m = 0; m < output->numModes; m++)
+	    RRModeDestroy (output->modes[m]);
+	xfree (output->modes);
+    }
+    
+    for (m = 0; m < output->numUserModes; m++)
+	RRModeDestroy (output->userModes[m]);
+    if (output->userModes)
+	xfree (output->userModes);
+
+    if (output->crtcs)
+	xfree (output->crtcs);
+    if (output->clones)
+	xfree (output->clones);
+    RRDeleteAllOutputProperties (output);
+    xfree (output);
+    return 1;
+}
+
+/*
+ * Initialize output type
+ */
+Bool
+RROutputInit (void)
+{
+    RROutputType = CreateNewResourceType (RROutputDestroyResource);
+    if (!RROutputType)
+	return FALSE;
+    RegisterResourceName (RROutputType, "OUTPUT");
+    return TRUE;
+}
+
+#define OutputInfoExtra	(SIZEOF(xRRGetOutputInfoReply) - 32)
+				
+int
+ProcRRGetOutputInfo (ClientPtr client)
+{
+    REQUEST(xRRGetOutputInfoReq);
+    xRRGetOutputInfoReply	rep;
+    RROutputPtr			output;
+    CARD8			*extra;
+    unsigned long		extraLen;
+    ScreenPtr			pScreen;
+    rrScrPrivPtr		pScrPriv;
+    RRCrtc			*crtcs;
+    RRMode			*modes;
+    RROutput			*clones;
+    char			*name;
+    int				i, n;
+    
+    REQUEST_SIZE_MATCH(xRRGetOutputInfoReq);
+    output = LookupOutput(client, stuff->output, SecurityReadAccess);
+
+    if (!output)
+    {
+	client->errorValue = stuff->output;
+	return RRErrorBase + BadRROutput;
+    }
+
+    pScreen = output->pScreen;
+    pScrPriv = rrGetScrPriv(pScreen);
+
+    rep.type = X_Reply;
+    rep.sequenceNumber = client->sequence;
+    rep.length = OutputInfoExtra >> 2;
+    rep.timestamp = pScrPriv->lastSetTime.milliseconds;
+    rep.crtc = output->crtc ? output->crtc->id : None;
+    rep.mmWidth = output->mmWidth;
+    rep.mmHeight = output->mmHeight;
+    rep.connection = output->connection;
+    rep.subpixelOrder = output->subpixelOrder;
+    rep.nCrtcs = output->numCrtcs;
+    rep.nModes = output->numModes + output->numUserModes;
+    rep.nPreferred = output->numPreferred;
+    rep.nClones = output->numClones;
+    rep.nameLength = output->nameLength;
+    
+    extraLen = ((output->numCrtcs + 
+		 output->numModes + output->numUserModes +
+		 output->numClones +
+		 ((rep.nameLength + 3) >> 2)) << 2);
+
+    if (extraLen)
+    {
+	rep.length += extraLen >> 2;
+	extra = xalloc (extraLen);
+	if (!extra)
+	    return BadAlloc;
+    }
+    else
+	extra = NULL;
+
+    crtcs = (RRCrtc *) extra;
+    modes = (RRMode *) (crtcs + output->numCrtcs);
+    clones = (RROutput *) (modes + output->numModes + output->numUserModes);
+    name = (char *) (clones + output->numClones);
+    
+    for (i = 0; i < output->numCrtcs; i++)
+    {
+	crtcs[i] = output->crtcs[i]->id;
+	if (client->swapped)
+	    swapl (&crtcs[i], n);
+    }
+    for (i = 0; i < output->numModes + output->numUserModes; i++)
+    {
+	if (i < output->numModes)
+	    modes[i] = output->modes[i]->mode.id;
+	else
+	    modes[i] = output->userModes[i - output->numModes]->mode.id;
+	if (client->swapped)
+	    swapl (&modes[i], n);
+    }
+    for (i = 0; i < output->numClones; i++)
+    {
+	clones[i] = output->clones[i]->id;
+	if (client->swapped)
+	    swapl (&clones[i], n);
+    }
+    memcpy (name, output->name, output->nameLength);
+    if (client->swapped) {
+	swaps(&rep.sequenceNumber, n);
+	swapl(&rep.length, n);
+	swapl(&rep.timestamp, n);
+	swapl(&rep.crtc, n);
+	swapl(&rep.mmWidth, n);
+	swapl(&rep.mmHeight, n);
+	swaps(&rep.nCrtcs, n);
+	swaps(&rep.nModes, n);
+	swaps(&rep.nClones, n);
+	swaps(&rep.nameLength, n);
+    }
+    WriteToClient(client, sizeof(xRRGetOutputInfoReply), (char *)&rep);
+    if (extraLen)
+    {
+	WriteToClient (client, extraLen, (char *) extra);
+	xfree (extra);
+    }
+    
+    return client->noClientException;
+}
diff --git a/randr/rrpointer.c b/randr/rrpointer.c
new file mode 100644
index 0000000..c88a0f8
--- /dev/null
+++ b/randr/rrpointer.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright © 2006 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "randrstr.h"
+
+/*
+ * When the pointer moves, check to see if the specified position is outside
+ * any of theavailable CRTCs and move it to a 'sensible' place if so, where
+ * sensible is the closest monitor to the departing edge.
+ *
+ * Returns whether the position was adjusted
+ */
+
+static Bool
+RRCrtcContainsPosition (RRCrtcPtr crtc, int x, int y)
+{
+    RRModePtr   mode = crtc->mode;
+    int		scan_width, scan_height;
+
+    if (!mode)
+	return FALSE;
+
+    RRCrtcGetScanoutSize (crtc, &scan_width, &scan_height);
+
+    if (crtc->x <= x && x < crtc->x + scan_width &&
+	crtc->y <= y && y < crtc->y + scan_height)
+	return TRUE;
+    return FALSE;
+}
+
+/*
+ * Find the CRTC nearest the specified position, ignoring 'skip'
+ */
+static void
+RRPointerToNearestCrtc (ScreenPtr pScreen, int x, int y, RRCrtcPtr skip)
+{
+    rrScrPriv (pScreen);
+    int		c;
+    RRCrtcPtr	nearest = NULL;
+    int		best = 0;
+    int		best_dx = 0, best_dy = 0;
+
+    for (c = 0; c < pScrPriv->numCrtcs; c++)
+    {
+	RRCrtcPtr   crtc = pScrPriv->crtcs[c];
+	RRModePtr   mode = crtc->mode;
+	int	    dx, dy;
+	int	    dist;
+	int	    scan_width, scan_height;
+
+	if (!mode)
+	    continue;
+	if (crtc == skip)
+	    continue;
+
+	RRCrtcGetScanoutSize (crtc, &scan_width, &scan_height);
+
+	if (x < crtc->x)
+	    dx = crtc->x - x;
+	else if (x > crtc->x + scan_width)
+	    dx = x - (crtc->x + scan_width);
+	else
+	    dx = 0;
+	if (y < crtc->y)
+	    dy = crtc->y - x;
+	else if (y > crtc->y + scan_height)
+	    dy = y - (crtc->y + scan_height);
+	else
+	    dy = 0;
+	dist = dx + dy;
+	if (!nearest || dist < best)
+	{
+	    nearest = crtc;
+	    best_dx = dx;
+	    best_dy = dy;
+	}
+    }
+    if (best_dx || best_dy)
+	(*pScreen->SetCursorPosition) (pScreen, x + best_dx, y + best_dy, TRUE);
+    pScrPriv->pointerCrtc = nearest;
+}
+
+void
+RRPointerMoved (ScreenPtr pScreen, int x, int y)
+{
+    rrScrPriv (pScreen);
+    RRCrtcPtr	pointerCrtc = pScrPriv->pointerCrtc;
+    int	c;
+
+    /* Check last known CRTC */
+    if (pointerCrtc && RRCrtcContainsPosition (pointerCrtc, x, y))
+	return;
+    
+    /* Check all CRTCs */
+    for (c = 0; c < pScrPriv->numCrtcs; c++)
+    {
+	RRCrtcPtr   crtc = pScrPriv->crtcs[c];
+	
+	if (RRCrtcContainsPosition (crtc, x, y))
+	{
+	    /* Remember containing CRTC */
+	    pScrPriv->pointerCrtc = crtc;
+	    return;
+	}
+    }
+
+    /* None contain pointer, find nearest */
+    RRPointerToNearestCrtc (pScreen, x, y, pointerCrtc);
+}
+
+/*
+ * When the screen is reconfigured, move the pointer to the nearest
+ * CRTC
+ */
+void
+RRPointerScreenConfigured (ScreenPtr pScreen)
+{
+    WindowPtr	pRoot = GetCurrentRootWindow ();
+    ScreenPtr	pCurrentScreen = pRoot ? pRoot->drawable.pScreen : NULL;
+    int		x, y;
+
+    if (pScreen != pCurrentScreen)
+	return;
+    GetSpritePosition (&x, &y);
+    RRPointerToNearestCrtc (pScreen, x, y, NULL);
+}
diff --git a/randr/rrproperty.c b/randr/rrproperty.c
new file mode 100644
index 0000000..436fc32
--- /dev/null
+++ b/randr/rrproperty.c
@@ -0,0 +1,692 @@
+/*
+ * Copyright © 2006 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "randrstr.h"
+#include "propertyst.h"
+#include "swaprep.h"
+
+static void
+RRDeliverEvent (ScreenPtr pScreen, xEvent *event, CARD32 mask)
+{
+
+}
+
+void
+RRDeleteAllOutputProperties (RROutputPtr output)
+{
+    RRPropertyPtr prop, next;
+    xRROutputPropertyNotifyEvent    event;
+
+    for (prop = output->properties; prop; prop = next)
+    {
+	next = prop->next;
+	event.type = RREventBase + RRNotify;
+	event.subCode = RRNotify_OutputProperty;
+	event.output = output->id;
+	event.state = PropertyDelete;
+	event.atom = prop->propertyName;
+	event.timestamp = currentTime.milliseconds;
+	RRDeliverEvent (output->pScreen, (xEvent *) &event, RROutputPropertyNotifyMask);
+	if (prop->current.data)
+	    xfree(prop->current.data);
+	if (prop->pending.data)
+	    xfree(prop->pending.data);
+	xfree(prop);
+    }
+}
+
+static void
+RRInitOutputPropertyValue (RRPropertyValuePtr property_value)
+{
+    property_value->type = None;
+    property_value->format = 0;
+    property_value->size = 0;
+    property_value->data = NULL;
+}
+
+static RRPropertyPtr
+RRCreateOutputProperty (Atom property)
+{
+    RRPropertyPtr   prop;
+
+    prop = (RRPropertyPtr)xalloc(sizeof(RRPropertyRec));
+    if (!prop)
+	return NULL;
+    prop->next = NULL;
+    prop->propertyName = property;
+    prop->is_pending = FALSE;
+    prop->range = FALSE;
+    prop->immutable = FALSE;
+    prop->num_valid = 0;
+    prop->valid_values = NULL;
+    RRInitOutputPropertyValue (&prop->current);
+    RRInitOutputPropertyValue (&prop->pending);
+    return prop;
+}
+
+static void
+RRDestroyOutputProperty (RRPropertyPtr prop)
+{
+    if (prop->valid_values)
+	xfree (prop->valid_values);
+    if (prop->current.data)
+	xfree(prop->current.data);
+    if (prop->pending.data)
+	xfree(prop->pending.data);
+    xfree(prop);
+}
+
+void
+RRDeleteOutputProperty (RROutputPtr output, Atom property)
+{
+    RRPropertyPtr	prop, *prev;
+    xRROutputPropertyNotifyEvent    event;
+
+    for (prev = &output->properties; (prop = *prev); prev = &(prop->next))
+	if (prop->propertyName == property)
+	    break;
+    if (prop)
+    {
+	*prev = prop->next;
+	event.type = RREventBase + RRNotify;
+	event.subCode = RRNotify_OutputProperty;
+	event.output = output->id;
+	event.state = PropertyDelete;
+	event.atom = prop->propertyName;
+	event.timestamp = currentTime.milliseconds;
+	RRDeliverEvent (output->pScreen, (xEvent *) &event, RROutputPropertyNotifyMask);
+	RRDestroyOutputProperty (prop);
+    }
+}
+
+int
+RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
+			int format, int mode, unsigned long len,
+			pointer value, Bool sendevent, Bool pending)
+{
+    RRPropertyPtr		    prop;
+    xRROutputPropertyNotifyEvent    event;
+    rrScrPrivPtr		    pScrPriv = rrGetScrPriv(output->pScreen);
+    int				    size_in_bytes;
+    int				    total_size;
+    unsigned long		    total_len;
+    RRPropertyValuePtr		    prop_value;
+    RRPropertyValueRec		    new_value;
+    Bool			    add = FALSE;
+
+    size_in_bytes = format >> 3;
+
+    /* first see if property already exists */
+    prop = RRQueryOutputProperty (output, property);
+    if (!prop)   /* just add to list */
+    {
+	prop = RRCreateOutputProperty (property);
+	if (!prop)
+	    return(BadAlloc);
+	add = TRUE;
+	mode = PropModeReplace;
+    }
+    if (pending && prop->is_pending)
+	prop_value = &prop->pending;
+    else
+	prop_value = &prop->current;
+
+    /* To append or prepend to a property the request format and type
+     must match those of the already defined property.  The
+     existing format and type are irrelevant when using the mode
+     "PropModeReplace" since they will be written over. */
+
+    if ((format != prop_value->format) && (mode != PropModeReplace))
+	return(BadMatch);
+    if ((prop_value->type != type) && (mode != PropModeReplace))
+	return(BadMatch);
+    new_value = *prop_value;
+    if (mode == PropModeReplace)
+	total_len = len;
+    else
+	total_len = prop_value->size + len;
+
+    if (mode == PropModeReplace || len > 0)
+    {
+	pointer	    new_data = NULL, old_data = NULL;
+
+	total_size = total_len * size_in_bytes;
+	new_value.data = (pointer)xalloc (total_size);
+	if (!new_value.data && total_size)
+	{
+	    if (add)
+		RRDestroyOutputProperty (prop);
+	    return BadAlloc;
+	}
+	new_value.size = len;
+	new_value.type = type;
+	new_value.format = format;
+
+	switch (mode) {
+	case PropModeReplace:
+	    new_data = new_value.data;
+	    old_data = NULL;
+	    break;
+	case PropModeAppend:
+	    new_data = (pointer) (((char *) new_value.data) + 
+				  (prop_value->size * size_in_bytes));
+	    old_data = new_value.data;
+	    break;
+	case PropModePrepend:
+	    new_data = new_value.data;
+	    old_data = (pointer) (((char *) new_value.data) + 
+				  (prop_value->size * size_in_bytes));
+	    break;
+	}
+	if (new_data)
+	    memcpy ((char *) new_data, (char *) value, len * size_in_bytes);
+	if (old_data)
+	    memcpy ((char *) old_data, (char *) prop_value->data, 
+		    prop_value->size * size_in_bytes);
+
+	if (pending && pScrPriv->rrOutputSetProperty &&
+	    !pScrPriv->rrOutputSetProperty(output->pScreen, output,
+					   prop->propertyName, &new_value))
+	{
+	    if (new_value.data)
+		xfree (new_value.data);
+	    return (BadValue);
+	}
+	if (prop_value->data)
+	    xfree (prop_value->data);
+	*prop_value = new_value;
+    }
+
+    else if (len == 0)
+    {
+	/* do nothing */
+    }
+
+    if (add)
+    {
+	prop->next = output->properties;
+	output->properties = prop;
+    }
+
+    if (pending && prop->is_pending)
+	output->pendingProperties = TRUE;
+
+    if (sendevent)
+    {
+	event.type = RREventBase + RRNotify;
+	event.subCode = RRNotify_OutputProperty;
+	event.output = output->id;
+	event.state = PropertyNewValue;
+	event.atom = prop->propertyName;
+	event.timestamp = currentTime.milliseconds;
+	RRDeliverEvent (output->pScreen, (xEvent *) &event, RROutputPropertyNotifyMask);
+    }
+    return(Success);
+}
+
+Bool
+RRPostPendingProperties (RROutputPtr output)
+{
+    RRPropertyValuePtr	pending_value;
+    RRPropertyValuePtr	current_value;
+    RRPropertyPtr	property;
+    Bool		ret = TRUE;
+
+    if (!output->pendingProperties)
+	return TRUE;
+    
+    output->pendingProperties = FALSE;
+    for (property = output->properties; property; property = property->next)
+    {
+	/* Skip non-pending properties */
+	if (!property->is_pending)
+	    continue;
+	
+	pending_value = &property->pending;
+	current_value = &property->current;
+
+	/*
+	 * If the pending and current values are equal, don't mark it
+	 * as changed (which would deliver an event)
+	 */
+	if (pending_value->type == current_value->type &&
+	    pending_value->format == current_value->format &&
+	    pending_value->size == current_value->size &&
+	    !memcmp (pending_value->data, current_value->data,
+		     pending_value->size))
+	    continue;
+
+	if (RRChangeOutputProperty (output, property->propertyName,
+				    pending_value->type, pending_value->format,
+				    PropModeReplace, pending_value->size,
+				    pending_value->data, TRUE,
+				    FALSE) != Success)
+	    ret = FALSE;
+    }
+    return ret;
+}
+
+RRPropertyPtr
+RRQueryOutputProperty (RROutputPtr output, Atom property)
+{
+    RRPropertyPtr   prop;
+    
+    for (prop = output->properties; prop; prop = prop->next)
+	if (prop->propertyName == property)
+	    return prop;
+    return NULL;
+}
+		       
+RRPropertyValuePtr
+RRGetOutputProperty (RROutputPtr output, Atom property, Bool pending)
+{
+    RRPropertyPtr   prop = RRQueryOutputProperty (output, property);
+
+    if (!prop)
+	return NULL;
+    if (pending && prop->is_pending)
+	return &prop->pending;
+    else
+	return &prop->current;
+}
+
+int
+RRConfigureOutputProperty (RROutputPtr output, Atom property,
+			   Bool pending, Bool range, Bool immutable,
+			   int num_values, INT32 *values)
+{
+    RRPropertyPtr   prop = RRQueryOutputProperty (output, property);
+    Bool	    add = FALSE;
+    INT32	    *new_values;
+
+    if (!prop)
+    {
+        prop = RRCreateOutputProperty (property);
+	if (!prop)
+	    return(BadAlloc);
+	add = TRUE;
+    } else if (prop->immutable && !immutable)
+	return(BadAccess);
+    
+    /*
+     * ranges must have even number of values
+     */
+    if (range && (num_values & 1))
+	return BadMatch;
+
+    new_values = xalloc (num_values * sizeof (INT32));
+    if (!new_values && num_values)
+	return BadAlloc;
+    if (num_values)
+	memcpy (new_values, values, num_values * sizeof (INT32));
+    
+    /*
+     * Property moving from pending to non-pending
+     * loses any pending values
+     */
+    if (prop->is_pending && !pending)
+    {
+	if (prop->pending.data)
+	    xfree (prop->pending.data);
+	RRInitOutputPropertyValue (&prop->pending);
+    }
+
+    prop->is_pending = pending;
+    prop->range = range;
+    prop->immutable = immutable;
+    prop->num_valid = num_values;
+    if (prop->valid_values)
+	xfree (prop->valid_values);
+    prop->valid_values = new_values;
+
+    if (add) {
+	prop->next = output->properties;
+	output->properties = prop;
+    }
+
+    return Success;
+}
+
+int
+ProcRRListOutputProperties (ClientPtr client)
+{
+    REQUEST(xRRListOutputPropertiesReq);
+    Atom			    *pAtoms = NULL, *temppAtoms;
+    xRRListOutputPropertiesReply    rep;
+    int				    numProps = 0;
+    RROutputPtr			    output;
+    RRPropertyPtr			    prop;
+    
+    REQUEST_SIZE_MATCH(xRRListOutputPropertiesReq);
+
+    output = LookupOutput (client, stuff->output, SecurityReadAccess);
+    
+    if (!output)
+        return RRErrorBase + BadRROutput;
+
+    for (prop = output->properties; prop; prop = prop->next)
+	numProps++;
+    if (numProps)
+        if(!(pAtoms = (Atom *)xalloc(numProps * sizeof(Atom))))
+            return(BadAlloc);
+
+    rep.type = X_Reply;
+    rep.length = (numProps * sizeof(Atom)) >> 2;
+    rep.sequenceNumber = client->sequence;
+    rep.nAtoms = numProps;
+    if (client->swapped) 
+    {
+	int n;
+	swaps (&rep.sequenceNumber, n);
+	swapl (&rep.length, n);
+    }
+    temppAtoms = pAtoms;
+    for (prop = output->properties; prop; prop = prop->next)
+	*temppAtoms++ = prop->propertyName;
+
+    WriteReplyToClient(client, sizeof(xRRListOutputPropertiesReply), &rep);
+    if (numProps)
+    {
+        client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write;
+        WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms);
+        xfree(pAtoms);
+    }
+    return(client->noClientException);
+}
+
+int
+ProcRRQueryOutputProperty (ClientPtr client)
+{
+    REQUEST(xRRQueryOutputPropertyReq);
+    xRRQueryOutputPropertyReply	    rep;
+    RROutputPtr			    output;
+    RRPropertyPtr		    prop;
+    
+    REQUEST_SIZE_MATCH(xRRQueryOutputPropertyReq);
+
+    output = LookupOutput (client, stuff->output, SecurityReadAccess);
+    
+    if (!output)
+        return RRErrorBase + BadRROutput;
+    
+    prop = RRQueryOutputProperty (output, stuff->property);
+    if (!prop)
+	return BadName;
+    
+    rep.type = X_Reply;
+    rep.length = prop->num_valid;
+    rep.sequenceNumber = client->sequence;
+    rep.pending = prop->is_pending;
+    rep.range = prop->range;
+    rep.immutable = prop->immutable;
+    if (client->swapped) 
+    {
+	int n;
+	swaps (&rep.sequenceNumber, n);
+	swapl (&rep.length, n);
+    }
+    WriteReplyToClient (client, sizeof (xRRQueryOutputPropertyReply), &rep);
+    if (prop->num_valid)
+    {
+        client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write;
+        WriteSwappedDataToClient(client, prop->num_valid * sizeof(INT32),
+				 prop->valid_values);
+    }
+    return(client->noClientException);
+}
+
+int
+ProcRRConfigureOutputProperty (ClientPtr client)
+{
+    REQUEST(xRRConfigureOutputPropertyReq);
+    RROutputPtr				output;
+    int					num_valid;
+    
+    REQUEST_AT_LEAST_SIZE(xRRConfigureOutputPropertyReq);
+
+    output = LookupOutput (client, stuff->output, SecurityReadAccess);
+    
+    if (!output)
+        return RRErrorBase + BadRROutput;
+    
+    num_valid = stuff->length - (sizeof (xRRConfigureOutputPropertyReq) >> 2);
+    return RRConfigureOutputProperty (output, stuff->property,
+				      stuff->pending, stuff->range,
+				      FALSE, num_valid, 
+				      (INT32 *) (stuff + 1));
+}
+
+int
+ProcRRChangeOutputProperty (ClientPtr client)
+{
+    REQUEST(xRRChangeOutputPropertyReq);
+    RROutputPtr	    output;
+    char	    format, mode;
+    unsigned long   len;
+    int		    sizeInBytes;
+    int		    totalSize;
+    int		    err;
+
+    REQUEST_AT_LEAST_SIZE(xRRChangeOutputPropertyReq);
+    UpdateCurrentTime();
+    format = stuff->format;
+    mode = stuff->mode;
+    if ((mode != PropModeReplace) && (mode != PropModeAppend) &&
+	(mode != PropModePrepend))
+    {
+	client->errorValue = mode;
+	return BadValue;
+    }
+    if ((format != 8) && (format != 16) && (format != 32))
+    {
+	client->errorValue = format;
+        return BadValue;
+    }
+    len = stuff->nUnits;
+    if (len > ((0xffffffff - sizeof(xChangePropertyReq)) >> 2))
+	return BadLength;
+    sizeInBytes = format>>3;
+    totalSize = len * sizeInBytes;
+    REQUEST_FIXED_SIZE(xRRChangeOutputPropertyReq, totalSize);
+
+    output = LookupOutput (client, stuff->output, SecurityWriteAccess);
+    if (!output)
+	return RRErrorBase + BadRROutput;
+    
+    if (!ValidAtom(stuff->property))
+    {
+	client->errorValue = stuff->property;
+	return(BadAtom);
+    }
+    if (!ValidAtom(stuff->type))
+    {
+	client->errorValue = stuff->type;
+	return(BadAtom);
+    }
+
+    err = RRChangeOutputProperty(output, stuff->property,
+				 stuff->type, (int)format,
+				 (int)mode, len, (pointer)&stuff[1], TRUE, TRUE);
+    if (err != Success)
+	return err;
+    else
+	return client->noClientException;
+}
+
+int
+ProcRRDeleteOutputProperty (ClientPtr client)
+{
+    REQUEST(xRRDeleteOutputPropertyReq);
+    RROutputPtr	output;
+              
+    REQUEST_SIZE_MATCH(xRRDeleteOutputPropertyReq);
+    UpdateCurrentTime();
+    output = LookupOutput (client, stuff->output, SecurityWriteAccess);
+    if (!output)
+        return RRErrorBase + BadRROutput;
+    
+    if (!ValidAtom(stuff->property))
+    {
+	client->errorValue = stuff->property;
+	return (BadAtom);
+    }
+
+
+    RRDeleteOutputProperty(output, stuff->property);
+    return client->noClientException;
+}
+
+int
+ProcRRGetOutputProperty (ClientPtr client)
+{
+    REQUEST(xRRGetOutputPropertyReq);
+    RRPropertyPtr		prop, *prev;
+    RRPropertyValuePtr		prop_value;
+    unsigned long		n, len, ind;
+    RROutputPtr			output;
+    xRRGetOutputPropertyReply	reply;
+
+    REQUEST_SIZE_MATCH(xRRGetOutputPropertyReq);
+    if (stuff->delete)
+	UpdateCurrentTime();
+    output = LookupOutput (client, stuff->output, 
+			   stuff->delete ? SecurityWriteAccess :
+			   SecurityReadAccess);
+    if (!output)
+	return RRErrorBase + BadRROutput;
+
+    if (!ValidAtom(stuff->property))
+    {
+	client->errorValue = stuff->property;
+	return(BadAtom);
+    }
+    if ((stuff->delete != xTrue) && (stuff->delete != xFalse))
+    {
+	client->errorValue = stuff->delete;
+	return(BadValue);
+    }
+    if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type))
+    {
+	client->errorValue = stuff->type;
+	return(BadAtom);
+    }
+
+    for (prev = &output->properties; (prop = *prev); prev = &prop->next)
+	if (prop->propertyName == stuff->property) 
+	    break;
+
+    reply.type = X_Reply;
+    reply.sequenceNumber = client->sequence;
+    if (!prop) 
+    {
+	reply.nItems = 0;
+	reply.length = 0;
+	reply.bytesAfter = 0;
+	reply.propertyType = None;
+	reply.format = 0;
+	WriteReplyToClient(client, sizeof(xRRGetOutputPropertyReply), &reply);
+	return(client->noClientException);
+    }
+
+    if (prop->immutable && stuff->delete)
+	return BadAccess;
+
+    if (stuff->pending && prop->is_pending)
+	prop_value = &prop->pending;
+    else
+	prop_value = &prop->current;
+    
+    /* If the request type and actual type don't match. Return the
+    property information, but not the data. */
+
+    if (((stuff->type != prop_value->type) &&
+	 (stuff->type != AnyPropertyType))
+       )
+    {
+	reply.bytesAfter = prop_value->size;
+	reply.format = prop_value->format;
+	reply.length = 0;
+	reply.nItems = 0;
+	reply.propertyType = prop_value->type;
+	WriteReplyToClient(client, sizeof(xRRGetOutputPropertyReply), &reply);
+	return(client->noClientException);
+    }
+
+/*
+ *  Return type, format, value to client
+ */
+    n = (prop_value->format/8) * prop_value->size; /* size (bytes) of prop */
+    ind = stuff->longOffset << 2;        
+
+   /* If longOffset is invalid such that it causes "len" to
+	    be negative, it's a value error. */
+
+    if (n < ind)
+    {
+	client->errorValue = stuff->longOffset;
+	return BadValue;
+    }
+
+    len = min(n - ind, 4 * stuff->longLength);
+
+    reply.bytesAfter = n - (ind + len);
+    reply.format = prop_value->format;
+    reply.length = (len + 3) >> 2;
+    if (prop_value->format)
+	reply.nItems = len / (prop_value->format / 8);
+    else
+	reply.nItems = 0;
+    reply.propertyType = prop_value->type;
+
+    if (stuff->delete && (reply.bytesAfter == 0))
+    {
+	xRROutputPropertyNotifyEvent    event;
+
+	event.type = RREventBase + RRNotify;
+	event.subCode = RRNotify_OutputProperty;
+	event.output = output->id;
+	event.state = PropertyDelete;
+	event.atom = prop->propertyName;
+	event.timestamp = currentTime.milliseconds;
+	RRDeliverEvent (output->pScreen, (xEvent *) &event, RROutputPropertyNotifyMask);
+    }
+
+    WriteReplyToClient(client, sizeof(xGenericReply), &reply);
+    if (len)
+    {
+	switch (reply.format) {
+	case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break;
+	case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break;
+	default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break;
+	}
+	WriteSwappedDataToClient(client, len,
+				 (char *)prop_value->data + ind);
+    }
+
+    if (stuff->delete && (reply.bytesAfter == 0))
+    { /* delete the Property */
+	*prev = prop->next;
+	RRDestroyOutputProperty (prop);
+    }
+    return(client->noClientException);
+}
+
diff --git a/randr/rrscreen.c b/randr/rrscreen.c
new file mode 100644
index 0000000..dbef2ba
--- /dev/null
+++ b/randr/rrscreen.c
@@ -0,0 +1,981 @@
+/*
+ * Copyright © 2006 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "randrstr.h"
+
+extern char	*ConnectionInfo;
+
+static int padlength[4] = {0, 3, 2, 1};
+
+static CARD16
+RR10CurrentSizeID (ScreenPtr pScreen);
+
+/*
+ * Edit connection information block so that new clients
+ * see the current screen size on connect
+ */
+static void
+RREditConnectionInfo (ScreenPtr pScreen)
+{
+    xConnSetup	    *connSetup;
+    char	    *vendor;
+    xPixmapFormat   *formats;
+    xWindowRoot	    *root;
+    xDepth	    *depth;
+    xVisualType	    *visual;
+    int		    screen = 0;
+    int		    d;
+
+    connSetup = (xConnSetup *) ConnectionInfo;
+    vendor = (char *) connSetup + sizeof (xConnSetup);
+    formats = (xPixmapFormat *) ((char *) vendor +
+				 connSetup->nbytesVendor +
+				 padlength[connSetup->nbytesVendor & 3]);
+    root = (xWindowRoot *) ((char *) formats +
+			    sizeof (xPixmapFormat) * screenInfo.numPixmapFormats);
+    while (screen != pScreen->myNum)
+    {
+	depth = (xDepth *) ((char *) root + 
+			    sizeof (xWindowRoot));
+	for (d = 0; d < root->nDepths; d++)
+	{
+	    visual = (xVisualType *) ((char *) depth +
+				      sizeof (xDepth));
+	    depth = (xDepth *) ((char *) visual +
+				depth->nVisuals * sizeof (xVisualType));
+	}
+	root = (xWindowRoot *) ((char *) depth);
+	screen++;
+    }
+    root->pixWidth = pScreen->width;
+    root->pixHeight = pScreen->height;
+    root->mmWidth = pScreen->mmWidth;
+    root->mmHeight = pScreen->mmHeight;
+}
+
+void
+RRSendConfigNotify (ScreenPtr pScreen)
+{
+    WindowPtr	pWin = WindowTable[pScreen->myNum];
+    xEvent	event;
+
+    event.u.u.type = ConfigureNotify;
+    event.u.configureNotify.window = pWin->drawable.id;
+    event.u.configureNotify.aboveSibling = None;
+    event.u.configureNotify.x = 0;
+    event.u.configureNotify.y = 0;
+
+    /* XXX xinerama stuff ? */
+    
+    event.u.configureNotify.width = pWin->drawable.width;
+    event.u.configureNotify.height = pWin->drawable.height;
+    event.u.configureNotify.borderWidth = wBorderWidth (pWin);
+    event.u.configureNotify.override = pWin->overrideRedirect;
+    DeliverEvents(pWin, &event, 1, NullWindow);
+}
+
+void
+RRDeliverScreenEvent (ClientPtr client, WindowPtr pWin, ScreenPtr pScreen)
+{
+    rrScrPriv (pScreen);
+    xRRScreenChangeNotifyEvent	se;
+    RRCrtcPtr	crtc = pScrPriv->numCrtcs ? pScrPriv->crtcs[0] : NULL;
+    WindowPtr	pRoot = WindowTable[pScreen->myNum];
+    
+    se.type = RRScreenChangeNotify + RREventBase;
+    se.rotation = (CARD8) (crtc ? crtc->rotation : RR_Rotate_0);
+    se.timestamp = pScrPriv->lastSetTime.milliseconds;
+    se.sequenceNumber = client->sequence;
+    se.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
+    se.root =  pRoot->drawable.id;
+    se.window = pWin->drawable.id;
+#ifdef RENDER
+    se.subpixelOrder = PictureGetSubpixelOrder (pScreen);
+#else
+    se.subpixelOrder = SubPixelUnknown;
+#endif
+
+    se.sequenceNumber = client->sequence;
+    se.sizeID = RR10CurrentSizeID (pScreen);
+
+    if (se.rotation & (RR_Rotate_90 | RR_Rotate_270)) {
+	se.widthInPixels = pScreen->height;
+	se.heightInPixels = pScreen->width;
+	se.widthInMillimeters = pScreen->mmHeight;
+	se.heightInMillimeters = pScreen->mmWidth;
+    } else {
+	se.widthInPixels = pScreen->width;
+	se.heightInPixels = pScreen->height;
+	se.widthInMillimeters = pScreen->mmWidth;
+	se.heightInMillimeters = pScreen->mmHeight;
+    }
+
+    WriteEventsToClient (client, 1, (xEvent *) &se);
+}
+
+/*
+ * Notify the extension that the screen size has been changed.
+ * The driver is responsible for calling this whenever it has changed
+ * the size of the screen
+ */
+void
+RRScreenSizeNotify (ScreenPtr	pScreen)
+{
+    rrScrPriv(pScreen);
+    /*
+     * Deliver ConfigureNotify events when root changes
+     * pixel size
+     */
+    if (pScrPriv->width == pScreen->width &&
+	pScrPriv->height == pScreen->height &&
+	pScrPriv->mmWidth == pScreen->mmWidth &&
+	pScrPriv->mmHeight == pScreen->mmHeight)
+	return;
+    
+    pScrPriv->width = pScreen->width;
+    pScrPriv->height = pScreen->height;
+    pScrPriv->mmWidth = pScreen->mmWidth;
+    pScrPriv->mmHeight = pScreen->mmHeight;
+    pScrPriv->changed = TRUE;
+/*    pScrPriv->sizeChanged = TRUE; */
+
+    RRTellChanged (pScreen);
+    RRSendConfigNotify (pScreen);
+    RREditConnectionInfo (pScreen);
+    
+    RRPointerScreenConfigured (pScreen);
+    /*
+     * Fix pointer bounds and location
+     */
+    ScreenRestructured (pScreen);
+}
+
+/*
+ * Request that the screen be resized
+ */
+Bool
+RRScreenSizeSet (ScreenPtr  pScreen,
+		 CARD16	    width,
+		 CARD16	    height,
+		 CARD32	    mmWidth,
+		 CARD32	    mmHeight)
+{
+    rrScrPriv(pScreen);
+
+#if RANDR_12_INTERFACE
+    if (pScrPriv->rrScreenSetSize)
+    {
+	return (*pScrPriv->rrScreenSetSize) (pScreen,
+					     width, height,
+					     mmWidth, mmHeight);
+    }
+#endif
+#if RANDR_10_INTERFACE
+    if (pScrPriv->rrSetConfig)
+    {
+	return TRUE;	/* can't set size separately */
+    }
+#endif
+    return FALSE;
+}
+
+/*
+ * Retrieve valid screen size range
+ */
+int 
+ProcRRGetScreenSizeRange (ClientPtr client)
+{
+    REQUEST(xRRGetScreenSizeRangeReq);
+    xRRGetScreenSizeRangeReply	rep;
+    WindowPtr			pWin;
+    ScreenPtr			pScreen;
+    rrScrPrivPtr		pScrPriv;
+    
+    REQUEST_SIZE_MATCH(xRRGetScreenInfoReq);
+    pWin = SecurityLookupWindow(stuff->window, client, SecurityReadAccess);
+    if (!pWin)
+	return BadAccess;
+
+    pScreen = pWin->drawable.pScreen;
+    pScrPriv = rrGetScrPriv(pScreen);
+    
+    rep.type = X_Reply;
+    rep.pad = 0;
+    rep.sequenceNumber = client->sequence;
+    rep.length = 0;
+    
+    if (pScrPriv) 
+    {
+	if (!RRGetInfo (pScreen))
+	    return BadAlloc;
+	rep.minWidth  = pScrPriv->minWidth;
+	rep.minHeight = pScrPriv->minHeight;
+	rep.maxWidth  = pScrPriv->maxWidth;
+	rep.maxHeight = pScrPriv->maxHeight;
+    }
+    else
+    {
+	rep.maxWidth  = rep.minWidth  = pScreen->width;
+	rep.maxHeight = rep.minHeight = pScreen->height;
+    }
+    if (client->swapped) 
+    {
+	int n;
+	
+    	swaps(&rep.sequenceNumber, n);
+    	swapl(&rep.length, n);
+	swaps(&rep.minWidth, n);
+	swaps(&rep.minHeight, n);
+	swaps(&rep.maxWidth, n);
+	swaps(&rep.maxHeight, n);
+    }
+    WriteToClient(client, sizeof(xRRGetScreenSizeRangeReply), (char *)&rep);
+    return (client->noClientException);
+}
+
+int
+ProcRRSetScreenSize (ClientPtr client)
+{
+    REQUEST(xRRSetScreenSizeReq);
+    WindowPtr		pWin;
+    ScreenPtr		pScreen;
+    rrScrPrivPtr	pScrPriv;
+    int			i, rc;
+    
+    REQUEST_SIZE_MATCH(xRRSetScreenSizeReq);
+    pWin = SecurityLookupWindow(stuff->window, client, SecurityReadAccess);
+    if (!pWin)
+	return BadAccess;
+
+    pScreen = pWin->drawable.pScreen;
+    pScrPriv = rrGetScrPriv(pScreen);
+    if (stuff->width < pScrPriv->minWidth || pScrPriv->maxWidth < stuff->width)
+    {
+	client->errorValue = stuff->width;
+	return BadValue;
+    }
+    if (stuff->height < pScrPriv->minHeight || 
+	pScrPriv->maxHeight < stuff->height)
+    {
+	client->errorValue = stuff->height;
+	return BadValue;
+    }
+    for (i = 0; i < pScrPriv->numCrtcs; i++) 
+    {
+	RRCrtcPtr   crtc = pScrPriv->crtcs[i];
+	RRModePtr   mode = crtc->mode;
+	if (mode)
+	{
+	    int		source_width = mode->mode.width;
+	    int		source_height = mode->mode.height;
+	    Rotation	rotation = crtc->rotation;
+
+	    if (rotation == RR_Rotate_90 || rotation == RR_Rotate_270)
+	    {
+		source_width = mode->mode.height;
+		source_height = mode->mode.width;
+	    }
+	    
+	    if (crtc->x + source_width > stuff->width ||
+		crtc->y + source_height > stuff->height)
+	    return BadMatch;
+	}
+    }
+    if (stuff->widthInMillimeters == 0 || stuff->heightInMillimeters == 0)
+    {
+	client->errorValue = 0;
+	return BadValue;
+    }
+    if (!RRScreenSizeSet (pScreen, 
+			  stuff->width, stuff->height,
+			  stuff->widthInMillimeters,
+			  stuff->heightInMillimeters))
+    {
+	return BadMatch;
+    }
+    return Success;
+}
+
+int
+ProcRRGetScreenResources (ClientPtr client)
+{
+    REQUEST(xRRGetScreenResourcesReq);
+    xRRGetScreenResourcesReply  rep;
+    WindowPtr			pWin;
+    ScreenPtr			pScreen;
+    rrScrPrivPtr		pScrPriv;
+    CARD8			*extra;
+    unsigned long		extraLen;
+    int				i, n, rc;
+    RRCrtc			*crtcs;
+    RROutput			*outputs;
+    xRRModeInfo			*modeinfos;
+    CARD8			*names;
+    
+    REQUEST_SIZE_MATCH(xRRGetScreenResourcesReq);
+    pWin = SecurityLookupWindow(stuff->window, client, SecurityReadAccess);
+    if (!pWin)
+	return BadAccess;
+    
+    pScreen = pWin->drawable.pScreen;
+    pScrPriv = rrGetScrPriv(pScreen);
+    rep.pad = 0;
+    
+    if (pScrPriv)
+	if (!RRGetInfo (pScreen))
+	    return BadAlloc;
+
+    if (!pScrPriv)
+    {
+	rep.type = X_Reply;
+	rep.sequenceNumber = client->sequence;
+	rep.length = 0;
+	rep.timestamp = currentTime.milliseconds;
+	rep.configTimestamp = currentTime.milliseconds;
+	rep.nCrtcs = 0;
+	rep.nOutputs = 0;
+	rep.nModes = 0;
+	rep.nbytesNames = 0;
+	extra = NULL;
+	extraLen = 0;
+    }
+    else
+    {
+	RRModePtr   *modes;
+	int	    num_modes;
+
+	modes = RRModesForScreen (pScreen, &num_modes);
+	if (!modes)
+	    return BadAlloc;
+	
+	rep.type = X_Reply;
+	rep.sequenceNumber = client->sequence;
+	rep.length = 0;
+	rep.timestamp = pScrPriv->lastSetTime.milliseconds;
+	rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
+	rep.nCrtcs = pScrPriv->numCrtcs;
+	rep.nOutputs = pScrPriv->numOutputs;
+	rep.nModes = num_modes;
+	rep.nbytesNames = 0;
+
+	for (i = 0; i < num_modes; i++)
+	    rep.nbytesNames += modes[i]->mode.nameLength;
+
+	rep.length = (pScrPriv->numCrtcs + 
+		      pScrPriv->numOutputs + 
+		      num_modes * (SIZEOF(xRRModeInfo) >> 2) +
+		      ((rep.nbytesNames + 3) >> 2));
+	
+	extraLen = rep.length << 2;
+	if (extraLen)
+	{
+	    extra = xalloc (extraLen);
+	    if (!extra)
+	    {
+		xfree (modes);
+		return BadAlloc;
+	    }
+	}
+	else
+	    extra = NULL;
+
+	crtcs = (RRCrtc *) extra;
+	outputs = (RROutput *) (crtcs + pScrPriv->numCrtcs);
+	modeinfos = (xRRModeInfo *) (outputs + pScrPriv->numOutputs);
+	names = (CARD8 *) (modeinfos + num_modes);
+	
+	for (i = 0; i < pScrPriv->numCrtcs; i++)
+	{
+	    crtcs[i] = pScrPriv->crtcs[i]->id;
+	    if (client->swapped)
+		swapl (&crtcs[i], n);
+	}
+	
+	for (i = 0; i < pScrPriv->numOutputs; i++)
+	{
+	    outputs[i] = pScrPriv->outputs[i]->id;
+	    if (client->swapped)
+		swapl (&outputs[i], n);
+	}
+	
+	for (i = 0; i < num_modes; i++)
+	{
+	    RRModePtr	mode = modes[i];
+	    modeinfos[i] = mode->mode;
+	    if (client->swapped)
+	    {
+		swapl (&modeinfos[i].id, n);
+		swaps (&modeinfos[i].width, n);
+		swaps (&modeinfos[i].height, n);
+		swapl (&modeinfos[i].dotClock, n);
+		swaps (&modeinfos[i].hSyncStart, n);
+		swaps (&modeinfos[i].hSyncEnd, n);
+		swaps (&modeinfos[i].hTotal, n);
+		swaps (&modeinfos[i].hSkew, n);
+		swaps (&modeinfos[i].vSyncStart, n);
+		swaps (&modeinfos[i].vSyncEnd, n);
+		swaps (&modeinfos[i].vTotal, n);
+		swaps (&modeinfos[i].nameLength, n);
+		swapl (&modeinfos[i].modeFlags, n);
+	    }
+	    memcpy (names, mode->name, 
+		    mode->mode.nameLength);
+	    names += mode->mode.nameLength;
+	}
+    	xfree (modes);
+	assert (((((char *) names - (char *) extra) + 3) >> 2) == rep.length);
+    }
+    
+    if (client->swapped) {
+	swaps(&rep.sequenceNumber, n);
+	swapl(&rep.length, n);
+	swapl(&rep.timestamp, n);
+	swapl(&rep.configTimestamp, n);
+	swaps(&rep.nCrtcs, n);
+	swaps(&rep.nOutputs, n);
+	swaps(&rep.nModes, n);
+	swaps(&rep.nbytesNames, n);
+    }
+    WriteToClient(client, sizeof(xRRGetScreenResourcesReply), (char *)&rep);
+    if (extraLen)
+    {
+	WriteToClient (client, extraLen, (char *) extra);
+	xfree (extra);
+    }
+    return client->noClientException;
+}
+
+typedef struct _RR10Data {
+    RRScreenSizePtr sizes;
+    int		    nsize;
+    int		    nrefresh;
+    int		    size;
+    CARD16	    refresh;
+} RR10DataRec, *RR10DataPtr;
+
+/*
+ * Convert 1.2 monitor data into 1.0 screen data
+ */
+static RR10DataPtr
+RR10GetData (ScreenPtr pScreen, RROutputPtr output)
+{
+    RR10DataPtr	    data;
+    RRScreenSizePtr size;
+    int		    nmode = output->numModes + output->numUserModes;
+    int		    o, os, l, r;
+    RRScreenRatePtr refresh;
+    CARD16	    vRefresh;
+    RRModePtr	    mode;
+    Bool	    *used;
+
+    /* Make sure there is plenty of space for any combination */
+    data = malloc (sizeof (RR10DataRec) + 
+		   sizeof (RRScreenSize) * nmode + 
+		   sizeof (RRScreenRate) * nmode +
+		   sizeof (Bool) * nmode);
+    if (!data)
+	return NULL;
+    size = (RRScreenSizePtr) (data + 1);
+    refresh = (RRScreenRatePtr) (size + nmode);
+    used = (Bool *) (refresh + nmode);
+    memset (used, '\0', sizeof (Bool) * nmode);
+    data->sizes = size;
+    data->nsize = 0;
+    data->nrefresh = 0;
+    data->size = 0;
+    data->refresh = 0;
+    
+    /*
+     * find modes not yet listed
+     */
+    for (o = 0; o < output->numModes + output->numUserModes; o++)
+    {
+	if (used[o]) continue;
+	
+	if (o < output->numModes)
+	    mode = output->modes[o];
+	else
+	    mode = output->userModes[o - output->numModes];
+	
+	l = data->nsize;
+	size[l].id = data->nsize;
+	size[l].width = mode->mode.width;
+	size[l].height = mode->mode.height;
+	if (output->mmWidth && output->mmHeight) {
+	    size[l].mmWidth = output->mmWidth;
+	    size[l].mmHeight = output->mmHeight;
+	} else {
+	    size[l].mmWidth = pScreen->mmWidth;
+	    size[l].mmHeight = pScreen->mmHeight;
+	}
+	size[l].nRates = 0;
+	size[l].pRates = &refresh[data->nrefresh];
+	data->nsize++;
+	
+	/*
+	 * Find all modes with matching size
+	 */
+	for (os = o; os < output->numModes + output->numUserModes; os++)
+	{
+	    if (os < output->numModes)
+		mode = output->modes[os];
+	    else
+		mode = output->userModes[os - output->numModes];
+	    if (mode->mode.width == size[l].width &&
+		mode->mode.height == size[l].height)
+	    {
+		vRefresh = RRVerticalRefresh (&mode->mode);
+		used[os] = TRUE;
+		
+		for (r = 0; r < size[l].nRates; r++)
+		    if (vRefresh == size[l].pRates[r].rate)
+			break;
+		if (r == size[l].nRates)
+		{
+		    size[l].pRates[r].rate = vRefresh;
+		    size[l].pRates[r].mode = mode;
+		    size[l].nRates++;
+		    data->nrefresh++;
+		}
+		if (mode == output->crtc->mode)
+		{
+		    data->size = l;
+		    data->refresh = vRefresh;
+		}
+	    }
+	}
+    }
+    return data;
+}
+
+int
+ProcRRGetScreenInfo (ClientPtr client)
+{
+    REQUEST(xRRGetScreenInfoReq);
+    xRRGetScreenInfoReply   rep;
+    WindowPtr	    	    pWin;
+    int			    n;
+    ScreenPtr		    pScreen;
+    rrScrPrivPtr	    pScrPriv;
+    CARD8		    *extra;
+    unsigned long	    extraLen;
+    RROutputPtr		    output;
+
+    REQUEST_SIZE_MATCH(xRRGetScreenInfoReq);
+    pWin = SecurityLookupWindow(stuff->window, client, SecurityReadAccess);
+    if (!pWin)
+	return BadAccess;
+
+    pScreen = pWin->drawable.pScreen;
+    pScrPriv = rrGetScrPriv(pScreen);
+    rep.pad = 0;
+    
+    if (pScrPriv)
+	if (!RRGetInfo (pScreen))
+	    return BadAlloc;
+
+    output = RRFirstOutput (pScreen);
+    
+    if (!pScrPriv || !output)
+    {
+	rep.type = X_Reply;
+	rep.setOfRotations = RR_Rotate_0;;
+	rep.sequenceNumber = client->sequence;
+	rep.length = 0;
+	rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
+	rep.timestamp = currentTime.milliseconds;
+	rep.configTimestamp = currentTime.milliseconds;
+	rep.nSizes = 0;
+	rep.sizeID = 0;
+	rep.rotation = RR_Rotate_0;
+	rep.rate = 0;
+	rep.nrateEnts = 0;
+	extra = 0;
+	extraLen = 0;
+    }
+    else
+    {
+	int			i, j;
+	xScreenSizes		*size;
+	CARD16			*rates;
+	CARD8			*data8;
+	Bool			has_rate = RRClientKnowsRates (client);
+	RR10DataPtr		pData;
+	RRScreenSizePtr		pSize;
+    
+	pData = RR10GetData (pScreen, output);
+	if (!pData)
+	    return BadAlloc;
+	
+	rep.type = X_Reply;
+	rep.setOfRotations = output->crtc->rotations;
+	rep.sequenceNumber = client->sequence;
+	rep.length = 0;
+	rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
+	rep.timestamp = pScrPriv->lastSetTime.milliseconds;
+	rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
+	rep.rotation = output->crtc->rotation;
+	rep.nSizes = pData->nsize;
+        rep.nrateEnts = pData->nrefresh + pData->nsize;
+	rep.sizeID = pData->size;
+	rep.rate = pData->refresh;
+
+	extraLen = (rep.nSizes * sizeof (xScreenSizes) +
+		    rep.nrateEnts * sizeof (CARD16));
+
+	if (extraLen)
+	{
+	    extra = (CARD8 *) xalloc (extraLen);
+	    if (!extra)
+	    {
+		xfree (pData);
+		return BadAlloc;
+	    }
+	}
+	else
+	    extra = NULL;
+
+	/*
+	 * First comes the size information
+	 */
+	size = (xScreenSizes *) extra;
+	rates = (CARD16 *) (size + rep.nSizes);
+	for (i = 0; i < pData->nsize; i++)
+	{
+	    pSize = &pData->sizes[i];
+	    size->widthInPixels = pSize->width;
+	    size->heightInPixels = pSize->height;
+	    size->widthInMillimeters = pSize->mmWidth;
+	    size->heightInMillimeters = pSize->mmHeight;
+	    if (client->swapped)
+	    {
+	        swaps (&size->widthInPixels, n);
+	        swaps (&size->heightInPixels, n);
+	        swaps (&size->widthInMillimeters, n);
+	        swaps (&size->heightInMillimeters, n);
+	    }
+	    size++;
+	    if (has_rate)
+	    {
+		*rates = pSize->nRates;
+		if (client->swapped)
+		{
+		    swaps (rates, n);
+		}
+		rates++;
+		for (j = 0; j < pSize->nRates; j++)
+		{
+		    *rates = pSize->pRates[j].rate;
+		    if (client->swapped)
+		    {
+			swaps (rates, n);
+		    }
+		    rates++;
+		}
+	    }
+	}
+        xfree (pData);
+	
+	data8 = (CARD8 *) rates;
+
+	if (data8 - (CARD8 *) extra != extraLen)
+	    FatalError ("RRGetScreenInfo bad extra len %ld != %ld\n",
+			(unsigned long)(data8 - (CARD8 *) extra), extraLen);
+	rep.length =  (extraLen + 3) >> 2;
+    }
+    if (client->swapped) {
+	swaps(&rep.sequenceNumber, n);
+	swapl(&rep.length, n);
+	swapl(&rep.timestamp, n);
+	swaps(&rep.rotation, n);
+	swaps(&rep.nSizes, n);
+	swaps(&rep.sizeID, n);
+	swaps(&rep.rate, n);
+	swaps(&rep.nrateEnts, n);
+    }
+    WriteToClient(client, sizeof(xRRGetScreenInfoReply), (char *)&rep);
+    if (extraLen)
+    {
+	WriteToClient (client, extraLen, (char *) extra);
+	xfree (extra);
+    }
+    return (client->noClientException);
+}
+
+int
+ProcRRSetScreenConfig (ClientPtr client)
+{
+    REQUEST(xRRSetScreenConfigReq);
+    xRRSetScreenConfigReply rep;
+    DrawablePtr		    pDraw;
+    int			    n, rc;
+    ScreenPtr		    pScreen;
+    rrScrPrivPtr	    pScrPriv;
+    TimeStamp		    configTime;
+    TimeStamp		    time;
+    int			    i;
+    Rotation		    rotation;
+    int			    rate;
+    Bool		    has_rate;
+    RROutputPtr		    output;
+    RRCrtcPtr		    crtc;
+    RRModePtr		    mode;
+    RR10DataPtr		    pData = NULL;
+    RRScreenSizePtr    	    pSize;
+    int			    width, height;
+    
+    UpdateCurrentTime ();
+
+    if (RRClientKnowsRates (client))
+    {
+	REQUEST_SIZE_MATCH (xRRSetScreenConfigReq);
+	has_rate = TRUE;
+    }
+    else
+    {
+	REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq);
+	has_rate = FALSE;
+    }
+    
+    pDraw = SecurityLookupDrawable(stuff->drawable, client, SecurityWriteAccess);
+    if (!pDraw)
+	return BadAccess;
+
+    pScreen = pDraw->pScreen;
+
+    pScrPriv = rrGetScrPriv(pScreen);
+    
+    time = ClientTimeToServerTime(stuff->timestamp);
+    
+    if (!pScrPriv)
+    {
+	time = currentTime;
+	rep.status = RRSetConfigFailed;
+	goto sendReply;
+    }
+    if (!RRGetInfo (pScreen))
+	return BadAlloc;
+    
+    output = RRFirstOutput (pScreen);
+    if (!output)
+    {
+	time = currentTime;
+	rep.status = RRSetConfigFailed;
+	goto sendReply;
+    }
+
+    crtc = output->crtc;
+
+    /*
+     * If the client's config timestamp is not the same as the last config
+     * timestamp, then the config information isn't up-to-date and
+     * can't even be validated.
+     *
+     * Note that the client only knows about the milliseconds part of the
+     * timestamp, so using CompareTimeStamps here would cause randr to suddenly
+     * stop working after several hours have passed (freedesktop bug #6502).
+     */
+    if (stuff->configTimestamp != pScrPriv->lastConfigTime.milliseconds)
+    {
+	rep.status = RRSetConfigInvalidConfigTime;
+	goto sendReply;
+    }
+    
+    pData = RR10GetData (pScreen, output);
+    if (!pData)
+	return BadAlloc;
+    
+    if (stuff->sizeID >= pData->nsize)
+    {
+	/*
+	 * Invalid size ID
+	 */
+	client->errorValue = stuff->sizeID;
+	xfree (pData);
+	return BadValue;
+    }
+    pSize = &pData->sizes[stuff->sizeID];
+    
+    /*
+     * Validate requested rotation
+     */
+    rotation = (Rotation) stuff->rotation;
+
+    /* test the rotation bits only! */
+    switch (rotation & 0xf) {
+    case RR_Rotate_0:
+    case RR_Rotate_90:
+    case RR_Rotate_180:
+    case RR_Rotate_270:
+	break;
+    default:
+	/*
+	 * Invalid rotation
+	 */
+	client->errorValue = stuff->rotation;
+	xfree (pData);
+	return BadValue;
+    }
+
+    if ((~crtc->rotations) & rotation)
+    {
+	/*
+	 * requested rotation or reflection not supported by screen
+	 */
+	client->errorValue = stuff->rotation;
+	xfree (pData);
+	return BadMatch;
+    }
+
+    /*
+     * Validate requested refresh
+     */
+    if (has_rate)
+	rate = (int) stuff->rate;
+    else
+	rate = 0;
+
+    if (rate)
+    {
+	for (i = 0; i < pSize->nRates; i++)
+	{
+	    if (pSize->pRates[i].rate == rate)
+		break;
+	}
+	if (i == pSize->nRates)
+	{
+	    /*
+	     * Invalid rate
+	     */
+	    client->errorValue = rate;
+	    xfree (pData);
+	    return BadValue;
+	}
+	mode = pSize->pRates[i].mode;
+    }
+    else
+	mode = pSize->pRates[0].mode;
+    
+    /*
+     * Make sure the requested set-time is not older than
+     * the last set-time
+     */
+    if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0)
+    {
+	rep.status = RRSetConfigInvalidTime;
+	goto sendReply;
+    }
+
+    /*
+     * If the screen size is changing, adjust all of the other outputs
+     * to fit the new size, mirroring as much as possible
+     */
+    width = mode->mode.width;
+    height = mode->mode.height;
+    if (rotation & (RR_Rotate_90|RR_Rotate_270))
+    {
+	width = mode->mode.height;
+	height = mode->mode.width;
+    }
+    if (width != pScreen->width || height != pScreen->height)
+    {
+	int	c;
+
+	for (c = 0; c < pScrPriv->numCrtcs; c++)
+	{
+	    if (!RRCrtcSet (pScrPriv->crtcs[c], NULL, 0, 0, RR_Rotate_0,
+			    0, NULL))
+	    {
+		rep.status = RRSetConfigFailed;
+		/* XXX recover from failure */
+		goto sendReply;
+	    }
+	}
+	if (!RRScreenSizeSet (pScreen, width, height,
+			      pScreen->mmWidth, pScreen->mmHeight))
+	{
+	    rep.status = RRSetConfigFailed;
+	    /* XXX recover from failure */
+	    goto sendReply;
+	}
+    }
+
+    if (!RRCrtcSet (crtc, mode, 0, 0, stuff->rotation, 1, &output))
+	rep.status = RRSetConfigFailed;
+    else
+	rep.status = RRSetConfigSuccess;
+
+    /*
+     * XXX Configure other crtcs to mirror as much as possible
+     */
+    
+sendReply:
+    
+    if (pData)
+	xfree (pData);
+
+    rep.type = X_Reply;
+    /* rep.status has already been filled in */
+    rep.length = 0;
+    rep.sequenceNumber = client->sequence;
+
+    rep.newTimestamp = pScrPriv->lastSetTime.milliseconds;
+    rep.newConfigTimestamp = pScrPriv->lastConfigTime.milliseconds;
+    rep.root = WindowTable[pDraw->pScreen->myNum]->drawable.id;
+
+    if (client->swapped) 
+    {
+    	swaps(&rep.sequenceNumber, n);
+    	swapl(&rep.length, n);
+	swapl(&rep.newTimestamp, n);
+	swapl(&rep.newConfigTimestamp, n);
+	swapl(&rep.root, n);
+    }
+    WriteToClient(client, sizeof(xRRSetScreenConfigReply), (char *)&rep);
+
+    return (client->noClientException);
+}
+
+static CARD16
+RR10CurrentSizeID (ScreenPtr pScreen)
+{
+    CARD16	sizeID = 0xffff;
+    RROutputPtr output = RRFirstOutput (pScreen);
+    
+    if (output)
+    {
+	RR10DataPtr data = RR10GetData (pScreen, output);
+	if (data)
+	{
+	    int i;
+	    for (i = 0; i < data->nsize; i++)
+		if (data->sizes[i].width == pScreen->width &&
+		    data->sizes[i].height == pScreen->height)
+		{
+		    sizeID = (CARD16) i;
+		    break;
+		}
+	    xfree (data);
+	}
+    }
+    return sizeID;
+}
diff --git a/randr/rrsdispatch.c b/randr/rrsdispatch.c
new file mode 100644
index 0000000..4a6a6e4
--- /dev/null
+++ b/randr/rrsdispatch.c
@@ -0,0 +1,305 @@
+/*
+ * Copyright © 2006 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "randrstr.h"
+
+static int
+SProcRRQueryVersion (ClientPtr client)
+{
+    register int n;
+    REQUEST(xRRQueryVersionReq);
+
+    swaps(&stuff->length, n);
+    swapl(&stuff->majorVersion, n);
+    swapl(&stuff->minorVersion, n);
+    return (*ProcRandrVector[stuff->randrReqType]) (client);
+}
+
+static int
+SProcRRGetScreenInfo (ClientPtr client)
+{
+    register int n;
+    REQUEST(xRRGetScreenInfoReq);
+
+    swaps(&stuff->length, n);
+    swapl(&stuff->window, n);
+    return (*ProcRandrVector[stuff->randrReqType]) (client);
+}
+
+static int
+SProcRRSetScreenConfig (ClientPtr client)
+{
+    register int n;
+    REQUEST(xRRSetScreenConfigReq);
+
+    if (RRClientKnowsRates (client))
+    {
+	REQUEST_SIZE_MATCH (xRRSetScreenConfigReq);
+	swaps (&stuff->rate, n);
+    }
+    else
+    {
+	REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq);
+    }
+    
+    swaps(&stuff->length, n);
+    swapl(&stuff->drawable, n);
+    swapl(&stuff->timestamp, n);
+    swaps(&stuff->sizeID, n);
+    swaps(&stuff->rotation, n);
+    return (*ProcRandrVector[stuff->randrReqType]) (client);
+}
+
+static int
+SProcRRSelectInput (ClientPtr client)
+{
+    register int n;
+    REQUEST(xRRSelectInputReq);
+
+    swaps(&stuff->length, n);
+    swapl(&stuff->window, n);
+    swaps(&stuff->enable, n);
+    return (*ProcRandrVector[stuff->randrReqType]) (client);
+}
+
+static int
+SProcRRGetScreenSizeRange (ClientPtr client)
+{
+    REQUEST(xRRGetScreenSizeRangeReq);
+    
+    REQUEST_SIZE_MATCH(xRRGetScreenSizeRangeReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+SProcRRSetScreenSize (ClientPtr client)
+{
+    REQUEST(xRRSetScreenSizeReq);
+    
+    REQUEST_SIZE_MATCH(xRRSetScreenSizeReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+SProcRRGetScreenResources (ClientPtr client)
+{
+    REQUEST(xRRGetScreenResourcesReq);
+    
+    REQUEST_SIZE_MATCH(xRRGetScreenResourcesReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+SProcRRGetOutputInfo (ClientPtr client)
+{
+    REQUEST(xRRGetOutputInfoReq);;
+    
+    REQUEST_SIZE_MATCH(xRRGetOutputInfoReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+SProcRRListOutputProperties (ClientPtr client)
+{
+    REQUEST(xRRListOutputPropertiesReq);
+    
+    REQUEST_SIZE_MATCH(xRRListOutputPropertiesReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+SProcRRQueryOutputProperty (ClientPtr client)
+{
+    REQUEST(xRRQueryOutputPropertyReq);
+    
+    REQUEST_SIZE_MATCH(xRRQueryOutputPropertyReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+SProcRRConfigureOutputProperty (ClientPtr client)
+{
+    REQUEST(xRRConfigureOutputPropertyReq);
+    
+    REQUEST_SIZE_MATCH(xRRConfigureOutputPropertyReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+SProcRRChangeOutputProperty (ClientPtr client)
+{
+    REQUEST(xRRChangeOutputPropertyReq);
+    
+    REQUEST_SIZE_MATCH(xRRChangeOutputPropertyReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+SProcRRDeleteOutputProperty (ClientPtr client)
+{
+    REQUEST(xRRDeleteOutputPropertyReq);
+    
+    REQUEST_SIZE_MATCH(xRRDeleteOutputPropertyReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+SProcRRGetOutputProperty (ClientPtr client)
+{
+    REQUEST(xRRGetOutputPropertyReq);
+    
+    REQUEST_SIZE_MATCH(xRRGetOutputPropertyReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+SProcRRCreateMode (ClientPtr client)
+{
+    REQUEST(xRRCreateModeReq);
+    
+    REQUEST_SIZE_MATCH(xRRCreateModeReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+SProcRRDestroyMode (ClientPtr client)
+{
+    REQUEST(xRRDestroyModeReq);
+    
+    REQUEST_SIZE_MATCH(xRRDestroyModeReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+SProcRRAddOutputMode (ClientPtr client)
+{
+    REQUEST(xRRAddOutputModeReq);
+    
+    REQUEST_SIZE_MATCH(xRRAddOutputModeReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+SProcRRDeleteOutputMode (ClientPtr client)
+{
+    REQUEST(xRRDeleteOutputModeReq);
+    
+    REQUEST_SIZE_MATCH(xRRDeleteOutputModeReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+SProcRRGetCrtcInfo (ClientPtr client)
+{
+    REQUEST(xRRGetCrtcInfoReq);
+    
+    REQUEST_SIZE_MATCH(xRRGetCrtcInfoReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+SProcRRSetCrtcConfig (ClientPtr client)
+{
+    REQUEST(xRRSetCrtcConfigReq);
+    
+    REQUEST_SIZE_MATCH(xRRSetCrtcConfigReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+SProcRRGetCrtcGammaSize (ClientPtr client)
+{
+    REQUEST(xRRGetCrtcGammaSizeReq);
+    
+    REQUEST_SIZE_MATCH(xRRGetCrtcGammaSizeReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+SProcRRGetCrtcGamma (ClientPtr client)
+{
+    REQUEST(xRRGetCrtcGammaReq);
+    
+    REQUEST_SIZE_MATCH(xRRGetCrtcGammaReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+SProcRRSetCrtcGamma (ClientPtr client)
+{
+    REQUEST(xRRSetCrtcGammaReq);
+    
+    REQUEST_SIZE_MATCH(xRRSetCrtcGammaReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+int (*SProcRandrVector[RRNumberRequests])(ClientPtr) = {
+    SProcRRQueryVersion,	/* 0 */
+/* we skip 1 to make old clients fail pretty immediately */
+    NULL,			/* 1 SProcRandrOldGetScreenInfo */
+/* V1.0 apps share the same set screen config request id */
+    SProcRRSetScreenConfig,	/* 2 */
+    NULL,			/* 3 SProcRandrOldScreenChangeSelectInput */
+/* 3 used to be ScreenChangeSelectInput; deprecated */
+    SProcRRSelectInput,		/* 4 */
+    SProcRRGetScreenInfo,    	/* 5 */
+/* V1.2 additions */
+    SProcRRGetScreenSizeRange,	/* 6 */
+    SProcRRSetScreenSize,	/* 7 */
+    SProcRRGetScreenResources,	/* 8 */
+    SProcRRGetOutputInfo,	/* 9 */
+    SProcRRListOutputProperties,/* 10 */
+    SProcRRQueryOutputProperty,	/* 11 */
+    SProcRRConfigureOutputProperty,  /* 12 */
+    SProcRRChangeOutputProperty,/* 13 */
+    SProcRRDeleteOutputProperty,/* 14 */
+    SProcRRGetOutputProperty,	/* 15 */
+    SProcRRCreateMode,		/* 16 */
+    SProcRRDestroyMode,		/* 17 */
+    SProcRRAddOutputMode,	/* 18 */
+    SProcRRDeleteOutputMode,	/* 19 */
+    SProcRRGetCrtcInfo,		/* 20 */
+    SProcRRSetCrtcConfig,	/* 21 */
+    SProcRRGetCrtcGammaSize,	/* 22 */
+    SProcRRGetCrtcGamma,	/* 23 */
+    SProcRRSetCrtcGamma,	/* 24 */
+};
+
diff --git a/randr/rrxinerama.c b/randr/rrxinerama.c
new file mode 100644
index 0000000..9f5eb2d
--- /dev/null
+++ b/randr/rrxinerama.c
@@ -0,0 +1,444 @@
+/*
+ * Copyright © 2006 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+/*
+ * This Xinerama implementation comes from the SiS driver which has
+ * the following notice:
+ */
+/* 
+ * SiS driver main code
+ *
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1) Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2) Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3) The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Thomas Winischhofer <thomas at winischhofer.net>
+ *	- driver entirely rewritten since 2001, only basic structure taken from
+ *	  old code (except sis_dri.c, sis_shadow.c, sis_accel.c and parts of
+ *	  sis_dga.c; these were mostly taken over; sis_dri.c was changed for
+ *	  new versions of the DRI layer)
+ *
+ * This notice covers the entire driver code unless indicated otherwise.
+ *
+ * Formerly based on code which was
+ * 	     Copyright (C) 1998, 1999 by Alan Hourihane, Wigan, England.
+ * 	     Written by:
+ *           Alan Hourihane <alanh at fairlite.demon.co.uk>,
+ *           Mike Chapman <mike at paranoia.com>,
+ *           Juanjo Santamarta <santamarta at ctv.es>,
+ *           Mitani Hiroshi <hmitani at drl.mei.co.jp>,
+ *           David Thomas <davtom at dream.org.uk>.
+ */
+
+#include "randrstr.h"
+#include "swaprep.h"
+#include <X11/extensions/panoramiXproto.h>
+
+#define RR_XINERAMA_MAJOR_VERSION   1
+#define RR_XINERAMA_MINOR_VERSION   1
+
+/* Xinerama is not multi-screen capable; just report about screen 0 */
+#define RR_XINERAMA_SCREEN  0
+
+static int ProcRRXineramaQueryVersion(ClientPtr client);
+static int ProcRRXineramaGetState(ClientPtr client);
+static int ProcRRXineramaGetScreenCount(ClientPtr client);
+static int ProcRRXineramaGetScreenSize(ClientPtr client);
+static int ProcRRXineramaIsActive(ClientPtr client);
+static int ProcRRXineramaQueryScreens(ClientPtr client);
+static int SProcRRXineramaDispatch(ClientPtr client);
+
+/* Proc */
+
+int
+ProcRRXineramaQueryVersion(ClientPtr client)
+{
+    xPanoramiXQueryVersionReply	  rep;
+    register int		  n;
+
+    REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq);
+    rep.type = X_Reply;
+    rep.length = 0;
+    rep.sequenceNumber = client->sequence;
+    rep.majorVersion = RR_XINERAMA_MAJOR_VERSION;
+    rep.minorVersion = RR_XINERAMA_MINOR_VERSION;
+    if(client->swapped) {
+        swaps(&rep.sequenceNumber, n);
+        swapl(&rep.length, n);
+        swaps(&rep.majorVersion, n);
+        swaps(&rep.minorVersion, n);
+    }
+    WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), (char *)&rep);
+    return (client->noClientException);
+}
+
+int
+ProcRRXineramaGetState(ClientPtr client)
+{
+    REQUEST(xPanoramiXGetStateReq);
+    WindowPtr			pWin;
+    xPanoramiXGetStateReply	rep;
+    register int		n;
+    ScreenPtr			pScreen;
+    rrScrPrivPtr		pScrPriv;
+    Bool			active = FALSE;
+
+    REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
+    pWin = SecurityLookupWindow(stuff->window, client, SecurityUnknownAccess);
+    if (!pWin)
+	return BadAccess;
+
+    pScreen = pWin->drawable.pScreen;
+    pScrPriv = rrGetScrPriv(pScreen);
+    if (pScrPriv)
+    {
+	/* XXX do we need more than this? */
+	active = TRUE;
+    }
+
+    rep.type = X_Reply;
+    rep.length = 0;
+    rep.sequenceNumber = client->sequence;
+    rep.state = active;
+    if(client->swapped) {
+       swaps (&rep.sequenceNumber, n);
+       swapl (&rep.length, n);
+       swaps (&rep.state, n);
+    }
+    WriteToClient(client, sizeof(xPanoramiXGetStateReply), (char *)&rep);
+    return client->noClientException;
+}
+
+static Bool
+RRXineramaCrtcActive (RRCrtcPtr crtc)
+{
+    return crtc->mode != NULL && crtc->numOutputs > 0;
+}
+
+static int
+RRXineramaScreenCount (ScreenPtr pScreen)
+{
+    int	i, n;
+    
+    n = 0;
+    if (rrGetScrPriv (pScreen))
+    {
+	rrScrPriv(pScreen);
+	for (i = 0; i < pScrPriv->numCrtcs; i++)
+	    if (RRXineramaCrtcActive (pScrPriv->crtcs[i]))
+		n++;
+    }
+    return n;
+}
+
+static Bool
+RRXineramaScreenActive (ScreenPtr pScreen)
+{
+    return RRXineramaScreenCount (pScreen) > 0;
+}
+
+int
+ProcRRXineramaGetScreenCount(ClientPtr client)
+{
+    REQUEST(xPanoramiXGetScreenCountReq);
+    WindowPtr				pWin;
+    xPanoramiXGetScreenCountReply	rep;
+    register int			n, rc;
+
+    REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
+    pWin = SecurityLookupWindow(stuff->window, client, SecurityUnknownAccess);
+    if (!pWin)
+	return BadAccess;
+    
+    rep.type = X_Reply;
+    rep.length = 0;
+    rep.sequenceNumber = client->sequence;
+    rep.ScreenCount = RRXineramaScreenCount (pWin->drawable.pScreen);
+    if(client->swapped) {
+       swaps(&rep.sequenceNumber, n);
+       swapl(&rep.length, n);
+       swaps(&rep.ScreenCount, n);
+    }
+    WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply), (char *)&rep);
+    return client->noClientException;
+}
+
+int
+ProcRRXineramaGetScreenSize(ClientPtr client)
+{
+    REQUEST(xPanoramiXGetScreenSizeReq);
+    WindowPtr				pWin, pRoot;
+    ScreenPtr				pScreen;
+    xPanoramiXGetScreenSizeReply	rep;
+    register int			n;
+
+    REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
+    pWin = SecurityLookupWindow(stuff->window, client, SecurityUnknownAccess);
+    if (!pWin)
+	return BadAccess;
+
+    pScreen = pWin->drawable.pScreen;
+    pRoot = WindowTable[pScreen->myNum];
+    
+    rep.type = X_Reply;
+    rep.length = 0;
+    rep.sequenceNumber = client->sequence;
+    rep.width  = pRoot->drawable.width;
+    rep.height = pRoot->drawable.height;
+    if(client->swapped) {
+       swaps(&rep.sequenceNumber, n);
+       swapl(&rep.length, n);
+       swaps(&rep.width, n);
+       swaps(&rep.height, n);
+    }
+    WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply), (char *)&rep);
+    return client->noClientException;
+}
+
+int
+ProcRRXineramaIsActive(ClientPtr client)
+{
+    xXineramaIsActiveReply	rep;
+
+    REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
+	
+    rep.type = X_Reply;
+    rep.length = 0;
+    rep.sequenceNumber = client->sequence;
+    rep.state = RRXineramaScreenActive (screenInfo.screens[RR_XINERAMA_SCREEN]);
+    if(client->swapped) {
+	register int n;
+	swaps(&rep.sequenceNumber, n);
+	swapl(&rep.length, n);
+	swapl(&rep.state, n);
+    }
+    WriteToClient(client, sizeof(xXineramaIsActiveReply), (char *) &rep);
+    return client->noClientException;
+}
+
+int
+ProcRRXineramaQueryScreens(ClientPtr client)
+{
+    xXineramaQueryScreensReply	rep;
+    ScreenPtr	pScreen = screenInfo.screens[RR_XINERAMA_SCREEN];
+
+    REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
+
+    if (RRXineramaScreenActive (pScreen))
+    {
+	rrScrPriv(pScreen);
+	if (pScrPriv->numCrtcs == 0 || pScrPriv->numOutputs == 0)
+	    RRGetInfo (pScreen);
+    }
+    
+    rep.type = X_Reply;
+    rep.sequenceNumber = client->sequence;
+    rep.number = RRXineramaScreenCount (pScreen);
+    rep.length = rep.number * sz_XineramaScreenInfo >> 2;
+    if(client->swapped) {
+	register int n;
+	swaps(&rep.sequenceNumber, n);
+	swapl(&rep.length, n);
+	swapl(&rep.number, n);
+    }
+    WriteToClient(client, sizeof(xXineramaQueryScreensReply), (char *)&rep);
+
+    if(rep.number) {
+	rrScrPriv(pScreen);
+	xXineramaScreenInfo scratch;
+	int i;
+
+	for(i = 0; i < pScrPriv->numCrtcs; i++) {
+	    RRCrtcPtr	crtc = pScrPriv->crtcs[i];
+	    if (RRXineramaCrtcActive (crtc))
+	    {
+	        int width, height;
+		RRCrtcGetScanoutSize (crtc, &width, &height);
+		scratch.x_org  = crtc->x;
+		scratch.y_org  = crtc->y;
+		scratch.width  = width;
+		scratch.height = height;
+		if(client->swapped) {
+		    register int n;
+		    swaps(&scratch.x_org, n);
+		    swaps(&scratch.y_org, n);
+		    swaps(&scratch.width, n);
+		    swaps(&scratch.height, n);
+		}
+		WriteToClient(client, sz_XineramaScreenInfo, (char *)&scratch);
+	    }
+	}
+    }
+
+    return client->noClientException;
+}
+
+static int
+ProcRRXineramaDispatch(ClientPtr client)
+{
+    REQUEST(xReq);
+    switch (stuff->data) {
+	case X_PanoramiXQueryVersion:
+	     return ProcRRXineramaQueryVersion(client);
+	case X_PanoramiXGetState:
+	     return ProcRRXineramaGetState(client);
+	case X_PanoramiXGetScreenCount:
+	     return ProcRRXineramaGetScreenCount(client);
+	case X_PanoramiXGetScreenSize:
+	     return ProcRRXineramaGetScreenSize(client);
+	case X_XineramaIsActive:
+	     return ProcRRXineramaIsActive(client);
+	case X_XineramaQueryScreens:
+	     return ProcRRXineramaQueryScreens(client);
+    }
+    return BadRequest;
+}
+
+/* SProc */
+
+static int
+SProcRRXineramaQueryVersion (ClientPtr client)
+{
+    REQUEST(xPanoramiXQueryVersionReq);
+    register int n;
+    swaps(&stuff->length,n);
+    REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq);
+    return ProcRRXineramaQueryVersion(client);
+}
+
+static int
+SProcRRXineramaGetState(ClientPtr client)
+{
+    REQUEST(xPanoramiXGetStateReq);
+    register int n;
+    swaps (&stuff->length, n);
+    REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
+    return ProcRRXineramaGetState(client);
+}
+
+static int
+SProcRRXineramaGetScreenCount(ClientPtr client)
+{
+    REQUEST(xPanoramiXGetScreenCountReq);
+    register int n;
+    swaps (&stuff->length, n);
+    REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
+    return ProcRRXineramaGetScreenCount(client);
+}
+
+static int
+SProcRRXineramaGetScreenSize(ClientPtr client)
+{
+    REQUEST(xPanoramiXGetScreenSizeReq);
+    register int n;
+    swaps (&stuff->length, n);
+    REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
+    return ProcRRXineramaGetScreenSize(client);
+}
+
+static int
+SProcRRXineramaIsActive(ClientPtr client)
+{
+    REQUEST(xXineramaIsActiveReq);
+    register int n;
+    swaps (&stuff->length, n);
+    REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
+    return ProcRRXineramaIsActive(client);
+}
+
+static int
+SProcRRXineramaQueryScreens(ClientPtr client)
+{
+    REQUEST(xXineramaQueryScreensReq);
+    register int n;
+    swaps (&stuff->length, n);
+    REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
+    return ProcRRXineramaQueryScreens(client);
+}
+
+int
+SProcRRXineramaDispatch(ClientPtr client)
+{
+    REQUEST(xReq);
+    switch (stuff->data) {
+	case X_PanoramiXQueryVersion:
+	     return SProcRRXineramaQueryVersion(client);
+	case X_PanoramiXGetState:
+	     return SProcRRXineramaGetState(client);
+	case X_PanoramiXGetScreenCount:
+	     return SProcRRXineramaGetScreenCount(client);
+	case X_PanoramiXGetScreenSize:
+	     return SProcRRXineramaGetScreenSize(client);
+	case X_XineramaIsActive:
+	     return SProcRRXineramaIsActive(client);
+	case X_XineramaQueryScreens:
+	     return SProcRRXineramaQueryScreens(client);
+    }
+    return BadRequest;
+}
+
+static void
+RRXineramaResetProc(ExtensionEntry* extEntry)
+{
+}
+
+void
+RRXineramaExtensionInit(void)
+{
+#ifdef PANORAMIX
+    if(!noPanoramiXExtension)
+	return;
+#endif
+
+    /*
+     * Xinerama isn't capable enough to have multiple protocol screens each
+     * with their own output geometry.  So if there's more than one protocol
+     * screen, just don't even try.
+     */
+    if (screenInfo.numScreens > 1)
+	return;
+
+    (void) AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0,
+			ProcRRXineramaDispatch,
+			SProcRRXineramaDispatch,
+			RRXineramaResetProc,
+			StandardMinorOpcode);
+}


More information about the xorg-commit mailing list