xserver: Branch 'server-1.2-branch' - 54 commits

Keith Packard keithp at kemper.freedesktop.org
Thu Feb 1 01:39:21 EET 2007


 GL/mesa/X/xf86glx.c           |    4 
 configure.ac                  |    2 
 damageext/damageext.c         |   40 +
 fb/fbpict.h                   |    3 
 hw/xfree86/common/Makefile.am |    2 
 randr/Makefile.am             |   12 
 randr/mirandr.c               |  165 +++--
 randr/randr.c                 | 1302 +++++++-----------------------------------
 randr/randrstr.h              |  764 +++++++++++++++++++++++-
 randr/rrcrtc.c                |  891 ++++++++++++++++++++++++++++
 randr/rrdispatch.c            |  210 ++++++
 randr/rrinfo.c                |  339 ++++++++++
 randr/rrmode.c                |  242 +++++++
 randr/rroutput.c              |  465 +++++++++++++++
 randr/rrpointer.c             |  145 ++++
 randr/rrproperty.c            |  638 ++++++++++++++++++++
 randr/rrscreen.c              |  958 ++++++++++++++++++++++++++++++
 randr/rrsdispatch.c           |  305 +++++++++
 randr/rrxinerama.c            |  433 +++++++++++++
 19 files changed, 5750 insertions(+), 1170 deletions(-)

New commits:
diff-tree 8798c8cfa888521cc47173bf6db00b5724da4a54 (from 895250181b21a76cab815b6ee2862d8a0c3a2fbf)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Tue Jan 30 19:05:20 2007 -0800

    Allow DDX to not supply a property set notification function.
    
    Check rrOutputSetProperty and only call if it isn't NULL.

diff --git a/randr/rrproperty.c b/randr/rrproperty.c
index ed01c88..03a1b5c 100644
--- a/randr/rrproperty.c
+++ b/randr/rrproperty.c
@@ -215,7 +215,7 @@ RRChangeOutputProperty (RROutputPtr outp
 	output->properties = prop;
     }
 
-    if (!prop->is_pending) {
+    if (!prop->is_pending && pScrPriv->rrOutputSetProperty) {
 	/* What should we do in case of failure? */
 	pScrPriv->rrOutputSetProperty(output->pScreen, output,
 				      prop->propertyName, prop_value);
diff-tree 895250181b21a76cab815b6ee2862d8a0c3a2fbf (from f993e142d2b8c7ce27370fb2c18d2eafb6ff40ca)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Tue Jan 30 18:45:44 2007 -0800

    Use old resource API in backported patch.
    
    1.2 branch doesn't have the resource lookup changes, so we need to use the
    old APIs.

diff --git a/damageext/damageext.c b/damageext/damageext.c
index 36d31e8..d13c67b 100755
--- a/damageext/damageext.c
+++ b/damageext/damageext.c
@@ -281,14 +281,10 @@ ProcDamageAdd (ClientPtr client)
     REQUEST(xDamageAddReq);
     DrawablePtr	    pDrawable;
     RegionPtr	    pRegion;
-    int		    rc;
 
     REQUEST_SIZE_MATCH(xDamageAddReq);
-    VERIFY_REGION(pRegion, stuff->region, client, DixWriteAccess);
-    rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
-			   DixReadAccess);
-    if (rc != Success)
-	return rc;
+    VERIFY_REGION(pRegion, stuff->region, client, SecurityWriteAccess);
+    SECURITY_VERIFY_DRAWABLE (pDrawable, stuff->drawable, client, SecurityReadAccess);
 
     /* The region is relative to the drawable origin, so translate it out to
      * screen coordinates like damage expects.
diff-tree f993e142d2b8c7ce27370fb2c18d2eafb6ff40ca (from 72754184f1215acd2b053d476fa46142d97c8ebd)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Mon Jan 29 23:04:17 2007 -0800

    Make Xinearama screen information reflect CRTC rotation.
    
    (cherry picked from commit b6b855932109b4bc3454f07bef8cb079d79ca369)

diff --git a/randr/randrstr.h b/randr/randrstr.h
index 7a34b39..f86f9b5 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -548,6 +548,9 @@ Bool
 RRCrtcGammaSetSize (RRCrtcPtr	crtc,
 		    int		size);
 
+void
+RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height);
+
 /*
  * Destroy a Crtc at shutdown
  */
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 63898f8..1e04290 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -406,6 +406,32 @@ 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
  */
diff --git a/randr/rrpointer.c b/randr/rrpointer.c
index 2a5ae7d..802dcb2 100644
--- a/randr/rrpointer.c
+++ b/randr/rrpointer.c
@@ -22,32 +22,6 @@
 
 #include "randrstr.h"
 
-/**
- * Returns the width/height that the crtc scans out from the framebuffer
- */
-static 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;
-    }
-}
-
 /*
  * 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
diff --git a/randr/rrxinerama.c b/randr/rrxinerama.c
index 771ed09..63a34b5 100644
--- a/randr/rrxinerama.c
+++ b/randr/rrxinerama.c
@@ -287,10 +287,12 @@ ProcRRXineramaQueryScreens(ClientPtr cli
 	    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  = crtc->mode->mode.width;
-		scratch.height = crtc->mode->mode.height;
+		scratch.width  = width;
+		scratch.height = height;
 		if(client->swapped) {
 		    register int n;
 		    swaps(&scratch.x_org, n);
diff-tree 72754184f1215acd2b053d476fa46142d97c8ebd (from 1225a49da28dc04cc8233cfa746e1fae0024bbe1)
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Jan 22 08:41:50 2007 +0800

    Really fix optimized render cases being hit when they shouldn't.
    
    I don't know how this define slipped in there.  Fixes
    6fdfd9dad91d7b7aa292f8c4d268dd27c34de8d3.

diff --git a/fb/fbpict.h b/fb/fbpict.h
index 179a07d..bfcb38e 100644
--- a/fb/fbpict.h
+++ b/fb/fbpict.h
@@ -105,9 +105,6 @@ fbCanGetSolid(PicturePtr pict)
     }
 }
 
-#define fbCanGetSolid(pict) \
-(pict->pDrawable != NULL && pict->pDrawable->width == 1 && pict->pDrawable->height == 1)
-
 #define fbComposeGetSolid(pict, bits, fmt) { \
     FbBits	*__bits__; \
     FbStride	__stride__; \
diff-tree 1225a49da28dc04cc8233cfa746e1fae0024bbe1 (from 364fb547d4d489f623cd633eaaeea00f617fd75e)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 18 14:28:01 2007 -0800

    Account for CRTC rotation in the cursor containment code.

diff --git a/randr/rrpointer.c b/randr/rrpointer.c
index c092e49..2a5ae7d 100644
--- a/randr/rrpointer.c
+++ b/randr/rrpointer.c
@@ -22,6 +22,32 @@
 
 #include "randrstr.h"
 
+/**
+ * Returns the width/height that the crtc scans out from the framebuffer
+ */
+static 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;
+    }
+}
+
 /*
  * 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
@@ -34,11 +60,15 @@ static Bool
 RRCrtcContainsPosition (RRCrtcPtr crtc, int x, int y)
 {
     RRModePtr   mode = crtc->mode;
-    
+    int		scan_width, scan_height;
+
     if (!mode)
 	return FALSE;
-    if (crtc->x <= x && x < crtc->x + mode->mode.width &&
-	crtc->y <= y && y < crtc->y + mode->mode.height)
+
+    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;
 }
@@ -54,28 +84,32 @@ RRPointerToNearestCrtc (ScreenPtr pScree
     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 + mode->mode.width)
-	    dx = x - (crtc->x + mode->mode.width);
+	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 + mode->mode.height)
-	    dy = y - (crtc->y + mode->mode.height);
+	else if (y > crtc->y + scan_height)
+	    dy = y - (crtc->y + scan_height);
 	else
 	    dy = 0;
 	dist = dx + dy;
diff-tree 364fb547d4d489f623cd633eaaeea00f617fd75e (from 11307c4b88244afc8b6a4dac36aa063c083b36d4)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Jan 16 13:01:03 2007 -0800

    When changing a non-pending property, call the screen rrOutputSetProperty hook.

diff --git a/randr/rrproperty.c b/randr/rrproperty.c
index dd1b5e0..ed01c88 100644
--- a/randr/rrproperty.c
+++ b/randr/rrproperty.c
@@ -125,6 +125,7 @@ RRChangeOutputProperty (RROutputPtr outp
 {
     RRPropertyPtr		    prop;
     xRROutputPropertyNotifyEvent    event;
+    rrScrPrivPtr		    pScrPriv = rrGetScrPriv(output->pScreen);
     int				    sizeInBytes;
     int				    totalSize;
     pointer			    data;
@@ -213,6 +214,13 @@ RRChangeOutputProperty (RROutputPtr outp
 	prop->next = output->properties;
 	output->properties = prop;
     }
+
+    if (!prop->is_pending) {
+	/* What should we do in case of failure? */
+	pScrPriv->rrOutputSetProperty(output->pScreen, output,
+				      prop->propertyName, prop_value);
+    }
+
     if (sendevent)
     {
 	event.type = RREventBase + RRNotify;
diff-tree 11307c4b88244afc8b6a4dac36aa063c083b36d4 (from 07e5c928ab9904ef21678d236b8eb5ef6419ed51)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Jan 16 12:59:34 2007 -0800

    Don't forget to add the property we configure to the properties list.

diff --git a/randr/rrproperty.c b/randr/rrproperty.c
index 13e8483..dd1b5e0 100644
--- a/randr/rrproperty.c
+++ b/randr/rrproperty.c
@@ -298,6 +298,12 @@ RRConfigureOutputProperty (RROutputPtr o
     if (prop->valid_values)
 	xfree (prop->valid_values);
     prop->valid_values = new_values;
+
+    if (add) {
+	prop->next = output->properties;
+	output->properties = prop;
+    }
+
     return Success;
 }
 
diff-tree 07e5c928ab9904ef21678d236b8eb5ef6419ed51 (from f1b95fda6ca01ff10a06e8753f66eb123d603eed)
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Jan 9 16:34:40 2007 -0800

    Track rename of DamagePost -> DamageAdd.

diff --git a/damageext/damageext.c b/damageext/damageext.c
index 62525f6..36d31e8 100755
--- a/damageext/damageext.c
+++ b/damageext/damageext.c
@@ -276,14 +276,14 @@ ProcDamageSubtract (ClientPtr client)
 }
 
 static int
-ProcDamagePost (ClientPtr client)
+ProcDamageAdd (ClientPtr client)
 {
-    REQUEST(xDamagePostReq);
+    REQUEST(xDamageAddReq);
     DrawablePtr	    pDrawable;
     RegionPtr	    pRegion;
     int		    rc;
 
-    REQUEST_SIZE_MATCH(xDamagePostReq);
+    REQUEST_SIZE_MATCH(xDamageAddReq);
     VERIFY_REGION(pRegion, stuff->region, client, DixWriteAccess);
     rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
 			   DixReadAccess);
@@ -303,7 +303,7 @@ ProcDamagePost (ClientPtr client)
 /* Major version controls available requests */
 static const int version_requests[] = {
     X_DamageQueryVersion,	/* before client sends QueryVersion */
-    X_DamagePost,		/* Version 1 */
+    X_DamageAdd,		/* Version 1 */
 };
 
 #define NUM_VERSION_REQUESTS	(sizeof (version_requests) / sizeof (version_requests[0]))
@@ -315,7 +315,7 @@ int	(*ProcDamageVector[XDamageNumberRequ
     ProcDamageDestroy,
     ProcDamageSubtract,
 /*************** Version 1.1 ****************/
-    ProcDamagePost,
+    ProcDamageAdd,
 };
 
 
@@ -385,10 +385,10 @@ SProcDamageSubtract (ClientPtr client)
 }
 
 static int
-SProcDamagePost (ClientPtr client)
+SProcDamageAdd (ClientPtr client)
 {
     register int n;
-    REQUEST(xDamagePostReq);
+    REQUEST(xDamageAddReq);
 
     swaps (&stuff->length, n);
     REQUEST_SIZE_MATCH(xDamageSubtractReq);
@@ -404,7 +404,7 @@ int	(*SProcDamageVector[XDamageNumberReq
     SProcDamageDestroy,
     SProcDamageSubtract,
 /*************** Version 1.1 ****************/
-    SProcDamagePost,
+    SProcDamageAdd,
 };
 
 static int
diff-tree f1b95fda6ca01ff10a06e8753f66eb123d603eed (from cd5fe7890d9b940b9d3e00043a6c81a10ae3db69)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Mon Jan 29 23:01:37 2007 -0800

    Add support for the DamagePost (XDamage 1.1) request.
    
    This makes damageproto >= 1.1 a requirement to build.
    (cherry picked from 0b73a7eb17fd848c6bdc6a65ba835aa2cbfc3cfd)

diff --git a/configure.ac b/configure.ac
index 6c0aa3a..a939687 100644
--- a/configure.ac
+++ b/configure.ac
@@ -514,7 +514,7 @@ XEXT_LIB='$(top_builddir)/Xext/libXext.l
 XEXTXORG_LIB='$(top_builddir)/Xext/libXextbuiltin.la'
 
 dnl Core modules for most extensions, et al.
-REQUIRED_MODULES="randrproto renderproto [fixesproto >= 4.0] damageproto xcmiscproto xextproto xproto xtrans xf86miscproto xf86vidmodeproto xf86bigfontproto [scrnsaverproto >= 1.1] bigreqsproto resourceproto fontsproto inputproto xf86dgaproto [kbproto >= 1.0.3]"
+REQUIRED_MODULES="[randrproto >= 1.2] renderproto [fixesproto >= 4.0] [damageproto >= 1.1] xcmiscproto xextproto xproto xtrans xf86miscproto xf86vidmodeproto xf86bigfontproto [scrnsaverproto >= 1.1] bigreqsproto resourceproto fontsproto inputproto xf86dgaproto [kbproto >= 1.0.3]"
 REQUIRED_LIBS="xfont xau fontenc"
 
 AM_CONDITIONAL(XV, [test "x$XV" = xyes])
diff --git a/damageext/damageext.c b/damageext/damageext.c
index 225f9ec..62525f6 100755
--- a/damageext/damageext.c
+++ b/damageext/damageext.c
@@ -275,10 +275,35 @@ ProcDamageSubtract (ClientPtr client)
     return (client->noClientException);
 }
 
+static int
+ProcDamagePost (ClientPtr client)
+{
+    REQUEST(xDamagePostReq);
+    DrawablePtr	    pDrawable;
+    RegionPtr	    pRegion;
+    int		    rc;
+
+    REQUEST_SIZE_MATCH(xDamagePostReq);
+    VERIFY_REGION(pRegion, stuff->region, client, DixWriteAccess);
+    rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
+			   DixReadAccess);
+    if (rc != Success)
+	return rc;
+
+    /* The region is relative to the drawable origin, so translate it out to
+     * screen coordinates like damage expects.
+     */
+    REGION_TRANSLATE(pScreen, pRegion, pDrawable->x, pDrawable->y);
+    DamageDamageRegion(pDrawable, pRegion);
+    REGION_TRANSLATE(pScreen, pRegion, -pDrawable->x, -pDrawable->y);
+
+    return (client->noClientException);
+}
+
 /* Major version controls available requests */
 static const int version_requests[] = {
     X_DamageQueryVersion,	/* before client sends QueryVersion */
-    X_DamageSubtract,		/* Version 1 */
+    X_DamagePost,		/* Version 1 */
 };
 
 #define NUM_VERSION_REQUESTS	(sizeof (version_requests) / sizeof (version_requests[0]))
@@ -289,6 +314,8 @@ int	(*ProcDamageVector[XDamageNumberRequ
     ProcDamageCreate,
     ProcDamageDestroy,
     ProcDamageSubtract,
+/*************** Version 1.1 ****************/
+    ProcDamagePost,
 };
 
 
@@ -357,12 +384,27 @@ SProcDamageSubtract (ClientPtr client)
     return (*ProcDamageVector[stuff->damageReqType]) (client);
 }
 
+static int
+SProcDamagePost (ClientPtr client)
+{
+    register int n;
+    REQUEST(xDamagePostReq);
+
+    swaps (&stuff->length, n);
+    REQUEST_SIZE_MATCH(xDamageSubtractReq);
+    swapl (&stuff->drawable, n);
+    swapl (&stuff->region, n);
+    return (*ProcDamageVector[stuff->damageReqType]) (client);
+}
+
 int	(*SProcDamageVector[XDamageNumberRequests])(ClientPtr) = {
 /*************** Version 1 ******************/
     SProcDamageQueryVersion,
     SProcDamageCreate,
     SProcDamageDestroy,
     SProcDamageSubtract,
+/*************** Version 1.1 ****************/
+    SProcDamagePost,
 };
 
 static int
diff-tree cd5fe7890d9b940b9d3e00043a6c81a10ae3db69 (from 1a34f1966c23fbc291a56e9e747aec8eaf9ca2a4)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 4 12:24:48 2007 -0800

    Keep track of how many visuals we set up for GLcore, to avoid an invalid free.
    
    The proper fix would involve actually setting up the ARGB visual for GLcore,
    but I just want the server to not crash at exit.

diff --git a/GL/mesa/X/xf86glx.c b/GL/mesa/X/xf86glx.c
index 94959d6..47c87f6 100644
--- a/GL/mesa/X/xf86glx.c
+++ b/GL/mesa/X/xf86glx.c
@@ -78,6 +78,7 @@ typedef struct __GLXMESAdrawable __GLXME
 struct __GLXMESAscreen {
     __GLXscreen   base;
     int           index;
+    int		  num_vis;
     XMesaVisual  *xm_vis;
 };
 
@@ -280,7 +281,7 @@ __glXMesaScreenDestroy(__GLXscreen *scre
     __GLXMESAscreen *mesaScreen = (__GLXMESAscreen *) screen;
     int i;
 
-    for (i = 0; i < screen->numVisuals; i++) {
+    for (i = 0; i < mesaScreen->num_vis; i++) {
 	if (mesaScreen->xm_vis[i])
 	    XMesaDestroyVisual(mesaScreen->xm_vis[i]);
     }
@@ -389,6 +390,7 @@ static void init_screen_visuals(__GLXMES
 
     xfree(used);
 
+    screen->num_vis = pScreen->numVisuals;
     screen->xm_vis = pXMesaVisual;
 }
 
diff-tree 1a34f1966c23fbc291a56e9e747aec8eaf9ca2a4 (from ceca97cb84385da8b3178671f811af9bc61558f7)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Mon Jan 29 22:04:07 2007 -0800

    Export API for setting allowed CRTC rotations

diff --git a/randr/randrstr.h b/randr/randrstr.h
index 136a47e..7a34b39 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -480,6 +480,12 @@ RRCrtcPtr
 RRCrtcCreate (void	*devPrivate);
 
 /*
+ * Set the allowed rotations on a CRTC
+ */
+void
+RRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations);
+
+/*
  * Attach a CRTC to a screen. Once done, this cannot be
  * undone without destroying the CRTC; it is separate from Create
  * only to allow an xf86-based driver to create objects in preinit
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 93854d5..63898f8 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -81,6 +81,15 @@ RRCrtcCreate (void	*devPrivate)
 }
 
 /*
+ * Set the allowed rotations on a CRTC
+ */
+void
+RRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations)
+{
+    crtc->rotations = rotations;
+}
+
+/*
  * Attach a Crtc to a screen. This is done as a separate step
  * so that an xf86-based driver can create CRTCs in PreInit
  * before the Screen has been created
diff-tree ceca97cb84385da8b3178671f811af9bc61558f7 (from parents)
Merge: f05dd384d38c76dd9662933a03625dfef5b1c81f b9dc0aeea817f4056837465b51fccf60173e4e62
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Mon Jan 29 22:03:19 2007 -0800

    Merge branch 'server-1.2' into randr-1.2-for-server-1.2

diff-tree f05dd384d38c76dd9662933a03625dfef5b1c81f (from 06a4be5e7a5371881106b6f51368330a33b26401)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sat Dec 30 21:52:22 2006 -0800

    Use RRScreenSetSizeRange in 1.0 compat. Check RRGetInfo for error.
    
    The RRScreenSizeSetRange function is used externally for 1.2 API drivers,
    but can also be used in the 1.0 compatibility code. This also ensures that
    the right changed bits are set so that clients are correctly notified when
    the range changes.
    
    RRGetInfo can return an error, use that to return BadAlloc to clients
    instead of blindly going on with various requests.

diff --git a/randr/rrinfo.c b/randr/rrinfo.c
index 85426f6..797cdb1 100644
--- a/randr/rrinfo.c
+++ b/randr/rrinfo.c
@@ -169,18 +169,7 @@ RRScanOldConfig (ScreenPtr pScreen, Rota
 	if (height > maxHeight) maxHeight = height;
     }
 
-    if (minWidth != pScrPriv->minWidth) {
-	pScrPriv->minWidth = minWidth; pScrPriv->changed = TRUE;
-    }
-    if (maxWidth != pScrPriv->maxWidth) {
-	pScrPriv->maxWidth = maxWidth; pScrPriv->changed = TRUE;
-    }
-    if (minHeight != pScrPriv->minHeight) {
-	pScrPriv->minHeight = minHeight; pScrPriv->changed = TRUE;
-    }
-    if (maxHeight != pScrPriv->maxHeight) {
-	pScrPriv->maxHeight = maxHeight; pScrPriv->changed = TRUE;
-    }
+    RRScreenSetSizeRange (pScreen, minWidth, minHeight, maxWidth, maxHeight);
 
     /* notice current mode */
     if (newMode)
@@ -219,7 +208,6 @@ RRGetInfo (ScreenPtr pScreen)
     return TRUE;
 }
 
-#if RANDR_12_INTERFACE
 /*
  * Register the range of sizes for the screen
  */
@@ -234,12 +222,19 @@ RRScreenSetSizeRange (ScreenPtr	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;
 }
-#endif
 
 #ifdef RANDR_10_INTERFACE
 static Bool
diff --git a/randr/rrscreen.c b/randr/rrscreen.c
index 8ee126a..7b0fbb8 100644
--- a/randr/rrscreen.c
+++ b/randr/rrscreen.c
@@ -239,7 +239,8 @@ ProcRRGetScreenSizeRange (ClientPtr clie
     
     if (pScrPriv) 
     {
-	RRGetInfo (pScreen);
+	if (!RRGetInfo (pScreen))
+	    return BadAlloc;
 	rep.minWidth  = pScrPriv->minWidth;
 	rep.minHeight = pScrPriv->minHeight;
 	rep.maxWidth  = pScrPriv->maxWidth;
@@ -359,7 +360,8 @@ ProcRRGetScreenResources (ClientPtr clie
     rep.pad = 0;
     
     if (pScrPriv)
-	RRGetInfo (pScreen);
+	if (!RRGetInfo (pScreen))
+	    return BadAlloc;
 
     if (!pScrPriv)
     {
@@ -603,7 +605,8 @@ ProcRRGetScreenInfo (ClientPtr client)
     rep.pad = 0;
     
     if (pScrPriv)
-	RRGetInfo (pScreen);
+	if (!RRGetInfo (pScreen))
+	    return BadAlloc;
 
     output = RRFirstOutput (pScreen);
     
diff-tree 06a4be5e7a5371881106b6f51368330a33b26401 (from parents)
Merge: f42e3cea236fa0091ed398a818fc8e17b0e1b3df f4ef99e8168fd2931961aa0d42f0547c89d21c1f
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Thu Dec 21 23:52:24 2006 -0800

    Merge branch 'server-1.2-branch' into randr-1.2-for-server-1.2

diff-tree f42e3cea236fa0091ed398a818fc8e17b0e1b3df (from 91396f14307537557ecd6eacf778fa091dd410c6)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Thu Dec 21 23:50:39 2006 -0800

    Track physical screen size and send out updates when that changes.
    
    Events and internal data structures need to be updated whenever the physical
    or pixel size of the screen changes. The code was ignoring the physical
    size, so changing only that would not be registered anywhere.

diff --git a/randr/randr.c b/randr/randr.c
index 1470035..5fa9baf 100644
--- a/randr/randr.c
+++ b/randr/randr.c
@@ -243,6 +243,10 @@ Bool RRScreenInit(ScreenPtr pScreen)
     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;
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 88f7588..136a47e 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -224,6 +224,7 @@ typedef struct _rrScrPriv {
     CARD16		    minWidth, minHeight;
     CARD16		    maxWidth, maxHeight;
     CARD16		    width, height;	/* last known screen size */
+    CARD16		    mmWidth, mmHeight;	/* last known screen size */
 
     int			    numOutputs;
     RROutputPtr		    *outputs;
diff --git a/randr/rrscreen.c b/randr/rrscreen.c
index 51957bf..8ee126a 100644
--- a/randr/rrscreen.c
+++ b/randr/rrscreen.c
@@ -158,11 +158,15 @@ RRScreenSizeNotify (ScreenPtr	pScreen)
      * pixel size
      */
     if (pScrPriv->width == pScreen->width &&
-	pScrPriv->height == pScreen->height)
+	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; */
 
diff-tree 91396f14307537557ecd6eacf778fa091dd410c6 (from parents)
Merge: 612a8e61803da8db0e305cbb093696b8e4284572 6dc711833d7387372012fdff1ce1df3aefa2d234
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Wed Dec 13 01:21:53 2006 -0800

    Merge branch 'randr-1.2-for-server-1.2-origin' into randr-1.2-for-server-1.2

diff-tree 612a8e61803da8db0e305cbb093696b8e4284572 (from 66b6358a393972946f16394918db2401c51dc5ed)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Wed Dec 13 01:21:32 2006 -0800

    RandR 1.2 rotation code must adjust width/height.
    
    Mode lines reflect the monitor mode, not the projected size into the frame
    buffer. Flip width/height around so that the dimensions are oriented
    correctly.

diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index e8a7b79..7409e96 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -698,7 +698,15 @@ ProcRRSetCrtcConfig (ClientPtr client)
 	 */
 	if (pScrPriv->rrScreenSetSize)
 	{
-	    if (stuff->x + mode->mode.width > pScreen->width)
+	    int source_width = mode->mode.width;
+	    int	source_height = mode->mode.height;
+
+	    if (rotation == RR_Rotate_90 || rotation == 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)
@@ -706,7 +714,7 @@ ProcRRSetCrtcConfig (ClientPtr client)
 		return BadValue;
 	    }
 	    
-	    if (stuff->y + mode->mode.height > pScreen->height)
+	    if (stuff->y + source_height > pScreen->height)
 	    {
 		client->errorValue = stuff->y;
 		if (outputs)
diff --git a/randr/rrscreen.c b/randr/rrscreen.c
index 76c16b0..38dbaed 100644
--- a/randr/rrscreen.c
+++ b/randr/rrscreen.c
@@ -268,7 +268,6 @@ ProcRRSetScreenSize (ClientPtr client)
     WindowPtr		pWin;
     ScreenPtr		pScreen;
     rrScrPrivPtr	pScrPriv;
-    RRCrtcPtr		crtc;
     int			i;
     
     REQUEST_SIZE_MATCH(xRRSetScreenSizeReq);
@@ -291,12 +290,26 @@ ProcRRSetScreenSize (ClientPtr client)
 	client->errorValue = stuff->height;
 	return BadValue;
     }
-    for (i = 0; i < pScrPriv->numCrtcs; i++) {
-	crtc = pScrPriv->crtcs[i];
-	if (crtc->mode &&
-	    (crtc->x + crtc->mode->mode.width > stuff->width ||
-	     crtc->y + crtc->mode->mode.height > stuff->height))
+    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)
     {
diff-tree 6dc711833d7387372012fdff1ce1df3aefa2d234 (from 98d18a6578130adb411ca4bcc776fcb7e07f189f)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Wed Dec 13 00:58:54 2006 -0800

    RandR 1.0 refresh rates unscrambled. SetScreenConfig uses RRCrtcSet right.
    
    RandR 1.0 refresh rates were scrambled when working with a 1.2 driver that
    returned sizes in a mixed order. SetScreenConfig was treating RRCrtcSet as
    returning an RandR status instead of a Bool.

diff --git a/randr/rrscreen.c b/randr/rrscreen.c
index 76c16b0..0028748 100644
--- a/randr/rrscreen.c
+++ b/randr/rrscreen.c
@@ -481,62 +481,81 @@ RR10GetData (ScreenPtr pScreen, RROutput
     RR10DataPtr	    data;
     RRScreenSizePtr size;
     int		    nmode = output->numModes;
-    int		    i, j, k;
+    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 (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;
-    for (i = 0; i < output->numModes; i++)
+    
+    /*
+     * find modes not yet listed
+     */
+    for (o = 0; o < output->numModes; o++)
     {
-	mode = output->modes[i];
-	for (j = 0; j < data->nsize; j++)
-	    if (mode->mode.width == size[j].width &&
-		mode->mode.height == size[j].height)
-		break;
-	if (j == data->nsize)
-	{
-	    size[j].id = j;
-	    size[j].width = mode->mode.width;
-	    size[j].height = mode->mode.height;
-	    if (output->mmWidth && output->mmHeight) {
-		size[j].mmWidth = output->mmWidth;
-		size[j].mmHeight = output->mmHeight;
-	    } else {
-		size[j].mmWidth = pScreen->mmWidth;
-		size[j].mmHeight = pScreen->mmHeight;
-	    }
-	    size[j].nRates = 0;
-	    size[j].pRates = &refresh[data->nrefresh];
-	    data->nsize++;
-	}
-	vRefresh = RRVerticalRefresh (&mode->mode);
-	for (k = 0; k < size[j].nRates; k++)
-	    if (vRefresh == size[j].pRates[k].rate)
-		break;
-	if (k == size[j].nRates)
-	{
-	    size[j].pRates[k].rate = vRefresh;
-	    size[j].pRates[k].mode = mode;
-	    size[j].nRates++;
-	    data->nrefresh++;
+	if (used[o]) continue;
+	
+	mode = output->modes[o];
+	
+	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;
 	}
-	if (mode == output->crtc->mode)
+	size[l].nRates = 0;
+	size[l].pRates = &refresh[data->nrefresh];
+	data->nsize++;
+	
+	/*
+	 * Find all modes with matching size
+	 */
+	for (os = o; os < output->numModes; os++)
 	{
-	    data->size = j;
-	    data->refresh = vRefresh;
+	    mode = output->modes[os];
+	    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;
@@ -864,22 +883,28 @@ ProcRRSetScreenConfig (ClientPtr client)
 
 	for (c = 0; c < pScrPriv->numCrtcs; c++)
 	{
-	    rep.status = RRCrtcSet (pScrPriv->crtcs[c], NULL, 0, 0, RR_Rotate_0,
-				    0, NULL);
-	    if (rep.status != Success)
+	    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, mode->mode.width, mode->mode.height,
 			      pScreen->mmWidth, pScreen->mmHeight))
 	{
 	    rep.status = RRSetConfigFailed;
+	    /* XXX recover from failure */
 	    goto sendReply;
 	}
     }
-    
-    rep.status = RRCrtcSet (output->crtc, mode, 0, 0, stuff->rotation,
-			    1, &output);
-    
+
+    if (!RRCrtcSet (output->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
      */
diff-tree 98d18a6578130adb411ca4bcc776fcb7e07f189f (from 78689d0d6630afcbcd3ce5394d12c2564a489f45)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Tue Dec 12 22:59:03 2006 -0800

    RandR: config time updates when hardware config changes.
    
    The config time in the RandR protocol reflects when the hardware state has
    changed. It was getting changed anytime the driver changed the usage
    of the hardware as well.

diff --git a/randr/randr.c b/randr/randr.c
index 147df8c..1470035 100644
--- a/randr/randr.c
+++ b/randr/randr.c
@@ -415,7 +415,11 @@ RRTellChanged (ScreenPtr pScreen)
     if (pScrPriv->changed)
     {
 	UpdateCurrentTime ();
-	pScrPriv->lastConfigTime = currentTime;
+	if (pScrPriv->configChanged)
+	{
+	    pScrPriv->lastConfigTime = currentTime;
+	    pScrPriv->configChanged = FALSE;
+	}
 	pScrPriv->changed = FALSE;
 	WalkTree (pScreen, TellChanged, (pointer) pScreen);
 	for (i = 0; i < pScrPriv->numOutputs; i++)
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 27ede92..88f7588 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -216,11 +216,14 @@ typedef struct _rrScrPriv {
     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 */
-    Bool		    layoutChanged;	/* screen layout changed */
 
     int			    numOutputs;
     RROutputPtr		    *outputs;
@@ -619,10 +622,13 @@ ProcRRDeleteOutputMode (ClientPtr client
 /* rroutput.c */
 
 /*
- * Notify the output of some change
+ * 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);
+RROutputChanged (RROutputPtr output, Bool configChanged);
 
 /*
  * Create an output
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index e8a7b79..5100bda 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -136,7 +136,7 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
 		break;
 	if (j == crtc->numOutputs)
 	{
-	    RROutputChanged (outputs[i]);
+	    RROutputChanged (outputs[i], FALSE);
 	    RRCrtcChanged (crtc, FALSE);
 	}
     }
@@ -151,7 +151,7 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
 		break;
 	if (i == numOutputs)
 	{
-	    RROutputChanged (crtc->outputs[j]);
+	    RROutputChanged (crtc->outputs[j], FALSE);
 	    RRCrtcChanged (crtc, FALSE);
 	}
     }
diff --git a/randr/rrinfo.c b/randr/rrinfo.c
index 244b089..85426f6 100644
--- a/randr/rrinfo.c
+++ b/randr/rrinfo.c
@@ -69,6 +69,7 @@ RROldModeAdd (RROutputPtr output, RRScre
     output->modes = modes;
     output->changed = TRUE;
     pScrPriv->changed = TRUE;
+    pScrPriv->configChanged = TRUE;
     return mode;
 }
 
@@ -205,6 +206,7 @@ RRGetInfo (ScreenPtr pScreen)
     
     rotations = 0;
     pScrPriv->changed = FALSE;
+    pScrPriv->configChanged = FALSE;
     
     if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations))
 	return FALSE;
diff --git a/randr/rroutput.c b/randr/rroutput.c
index 430f8bd..8007a8a 100644
--- a/randr/rroutput.c
+++ b/randr/rroutput.c
@@ -28,7 +28,7 @@ RESTYPE	RROutputType;
  * Notify the output of some change
  */
 void
-RROutputChanged (RROutputPtr output)
+RROutputChanged (RROutputPtr output, Bool configChanged)
 {
     ScreenPtr	pScreen = output->pScreen;
     
@@ -37,6 +37,8 @@ RROutputChanged (RROutputPtr output)
     {
 	rrScrPriv (pScreen);
 	pScrPriv->changed = TRUE;
+	if (configChanged)
+	    pScrPriv->configChanged = TRUE;
     }
 }
 
@@ -106,7 +108,7 @@ RROutputAttachScreen (RROutputPtr output
     output->pScreen = pScreen;
     pScrPriv->outputs = outputs;
     pScrPriv->outputs[pScrPriv->numOutputs++] = output;
-    RROutputChanged (output);
+    RROutputChanged (output, FALSE);
     return TRUE;
 }
 		      
@@ -142,7 +144,7 @@ RROutputSetClones (RROutputPtr  output,
     memcpy (newClones, clones, numClones * sizeof (RROutputPtr));
     output->clones = newClones;
     output->numClones = numClones;
-    RROutputChanged (output);
+    RROutputChanged (output, TRUE);
     return TRUE;
 }
 
@@ -186,7 +188,7 @@ RROutputSetModes (RROutputPtr	output,
     output->modes = newModes;
     output->numModes = numModes;
     output->numPreferred = numPreferred;
-    RROutputChanged (output);
+    RROutputChanged (output, TRUE);
     return TRUE;
 }
 
@@ -219,7 +221,7 @@ RROutputSetCrtcs (RROutputPtr	output,
     memcpy (newCrtcs, crtcs, numCrtcs * sizeof (RRCrtcPtr));
     output->crtcs = newCrtcs;
     output->numCrtcs = numCrtcs;
-    RROutputChanged (output);
+    RROutputChanged (output, TRUE);
     return TRUE;
 }
 
@@ -229,7 +231,7 @@ RROutputSetCrtc (RROutputPtr output, RRC
     if (output->crtc == crtc)
 	return;
     output->crtc = crtc;
-    RROutputChanged (output);
+    RROutputChanged (output, FALSE);
 }
 
 Bool
@@ -239,7 +241,7 @@ RROutputSetConnection (RROutputPtr  outp
     if (output->connection == connection)
 	return TRUE;
     output->connection = connection;
-    RROutputChanged (output);
+    RROutputChanged (output, TRUE);
     return TRUE;
 }
 
@@ -251,7 +253,7 @@ RROutputSetSubpixelOrder (RROutputPtr ou
 	return TRUE;
 
     output->subpixelOrder = subpixelOrder;
-    RROutputChanged (output);
+    RROutputChanged (output, FALSE);
     return TRUE;
 }
 
@@ -264,7 +266,7 @@ RROutputSetPhysicalSize (RROutputPtr	out
 	return TRUE;
     output->mmWidth = mmWidth;
     output->mmHeight = mmHeight;
-    RROutputChanged (output);
+    RROutputChanged (output, FALSE);
     return TRUE;
 }
 
diff-tree 78689d0d6630afcbcd3ce5394d12c2564a489f45 (from 12c9714ba7dc01bb845b299ec9213e8c2e98e3e6)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Tue Dec 12 20:16:49 2006 -0800

    RandR mode list needs both output and crtc modes.
    
    When an output no longer reports the current mode, it must still be included
    in the list advertised by the X server. Walk the crtcs to ensure it is
    included.

diff --git a/randr/rrmode.c b/randr/rrmode.c
index a0696e1..261e1b7 100644
--- a/randr/rrmode.c
+++ b/randr/rrmode.c
@@ -108,12 +108,15 @@ RRModePtr *
 RRModesForScreen (ScreenPtr pScreen, int *num_ret)
 {
     rrScrPriv(pScreen);
-    int	o;
+    int	o, c;
     RRModePtr	*screen_modes;
     int		num_screen_modes = 0;
 
     screen_modes = xalloc ((num_modes ? num_modes : 1) * sizeof (RRModePtr));
     
+    /*
+     * Add modes from all outputs
+     */
     for (o = 0; o < pScrPriv->numOutputs; o++)
     {
 	RROutputPtr	output = pScrPriv->outputs[o];
@@ -129,6 +132,24 @@ RRModesForScreen (ScreenPtr pScreen, int
 		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;
+    }
     *num_ret = num_screen_modes;
     return screen_modes;
 }
diff-tree 12c9714ba7dc01bb845b299ec9213e8c2e98e3e6 (from parents)
Merge: 66b6358a393972946f16394918db2401c51dc5ed 8049eeea994ad88273b3e62199237f41b22b48df
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Tue Dec 12 09:22:14 2006 -0800

    Merge branch 'server-1.2-branch' into randr-1.2-for-server-1.2

diff-tree 66b6358a393972946f16394918db2401c51dc5ed (from b5e373143695ab46605bae479c37a2106e947212)
Author: Keith Packard <keithp at ukulele.keithp.com>
Date:   Thu Nov 30 23:16:42 2006 -0800

    RandR ListOutputProperties has nAtoms element, not nProperties
    
    Earlier RandR 1.2 encoding revisions used 8-bit nProperties field.
    Final RandR 1.2 spec uses 16-bit nAtoms field instead.

diff --git a/randr/rrproperty.c b/randr/rrproperty.c
index a47f306..13e8483 100644
--- a/randr/rrproperty.c
+++ b/randr/rrproperty.c
@@ -325,9 +325,9 @@ ProcRRListOutputProperties (ClientPtr cl
             return(BadAlloc);
 
     rep.type = X_Reply;
-    rep.nProperties = numProps;
     rep.length = (numProps * sizeof(Atom)) >> 2;
     rep.sequenceNumber = client->sequence;
+    rep.nAtoms = numProps;
     if (client->swapped) 
     {
 	int n;
diff-tree b5e373143695ab46605bae479c37a2106e947212 (from parents)
Merge: 4202b23ed86405a4cebfdcf239df1b023c1d10ca 7c639791bea07340182de5e43db9526f8baee65a
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Nov 30 17:40:12 2006 -0800

    Merge branch 'server-1.2' into randr-1.2-for-server-1.2

diff-tree 4202b23ed86405a4cebfdcf239df1b023c1d10ca (from ec83d674167e7045d5317b179c9998e3172a26dc)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Mon Nov 27 21:40:24 2006 -0800

    Destroying RandR crtc or output overwrites memory.
    
    RRCrtcDestroyResource and RROutputDestroyResource had matching
    bugs that would overwrite memory past the end of the storage
    of the crtc or output arrays. Oops.

diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 212352c..e8a7b79 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -344,7 +344,7 @@ RRCrtcDestroyResource (pointer value, XI
 	    if (pScrPriv->crtcs[i] == crtc)
 	    {
 		memmove (pScrPriv->crtcs + i, pScrPriv->crtcs + i + 1,
-			 (pScrPriv->numCrtcs - (i - 1)) * sizeof (RRCrtcPtr));
+			 (pScrPriv->numCrtcs - (i + 1)) * sizeof (RRCrtcPtr));
 		--pScrPriv->numCrtcs;
 		break;
 	    }
diff --git a/randr/rroutput.c b/randr/rroutput.c
index f38f582..430f8bd 100644
--- a/randr/rroutput.c
+++ b/randr/rroutput.c
@@ -327,7 +327,7 @@ RROutputDestroyResource (pointer value, 
 	    if (pScrPriv->outputs[i] == output)
 	    {
 		memmove (pScrPriv->outputs + i, pScrPriv->outputs + i + 1,
-			 (pScrPriv->numOutputs - (i - 1)) * sizeof (RROutputPtr));
+			 (pScrPriv->numOutputs - (i + 1)) * sizeof (RROutputPtr));
 		--pScrPriv->numOutputs;
 		break;
 	    }
diff-tree ec83d674167e7045d5317b179c9998e3172a26dc (from 0626eb8e5c9fa05de6bdc9aa0c654f5148bf7cff)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sun Nov 26 19:31:48 2006 -0800

    Ensure RandR resource types are registered before resources are created.
    
    Now that resources can be created during server initialization, make sure
    the crtc, output and mode resource types are created before attempting to
    create associated resources.

diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index b81c390..212352c 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -55,6 +55,8 @@ RRCrtcCreate (void	*devPrivate)
 {
     RRCrtcPtr	crtc;
     
+    if (!RRInit())
+	return NULL;
     crtc = xalloc (sizeof (RRCrtcRec));
     if (!crtc)
 	return NULL;
diff --git a/randr/rrmode.c b/randr/rrmode.c
index 3cd9ef2..a0696e1 100644
--- a/randr/rrmode.c
+++ b/randr/rrmode.c
@@ -67,6 +67,9 @@ RRModeGet (xRRModeInfo	*modeInfo,
 	}
     }
 
+    if (!RRInit ())
+	return NULL;
+
     mode = xalloc (sizeof (RRModeRec) + modeInfo->nameLength + 1);
     if (!mode)
 	return NULL;
diff --git a/randr/rroutput.c b/randr/rroutput.c
index 8b760ec..f38f582 100644
--- a/randr/rroutput.c
+++ b/randr/rroutput.c
@@ -51,6 +51,8 @@ RROutputCreate (const char  *name,
 {
     RROutputPtr	output;
 
+    if (!RRInit())
+	return NULL;
     output = xalloc (sizeof (RROutputRec) + nameLength + 1);
     if (!output)
 	return NULL;
diff-tree 0626eb8e5c9fa05de6bdc9aa0c654f5148bf7cff (from af55c65bea40669fdc038aa34c6a1ec9ecb33e87)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Tue Nov 21 16:52:28 2006 -0800

    Allocate correct size for RRPropertyRec (oops).
    
    Neglected to change the allocation size from sizeof (PropertyRec) to
    sizeof (RRPropertyRec). Lots of fun crashes this way.

diff --git a/randr/rrproperty.c b/randr/rrproperty.c
index 5d4c865..a47f306 100644
--- a/randr/rrproperty.c
+++ b/randr/rrproperty.c
@@ -68,9 +68,10 @@ RRCreateOutputProperty (Atom property)
 {
     RRPropertyPtr   prop;
     
-    prop = (RRPropertyPtr)xalloc(sizeof(PropertyRec));
+    prop = (RRPropertyPtr)xalloc(sizeof(RRPropertyRec));
     if (!prop)
 	return NULL;
+    prop->next = NULL;
     prop->propertyName = property;
     prop->is_pending = FALSE;
     prop->range = FALSE;
diff-tree af55c65bea40669fdc038aa34c6a1ec9ecb33e87 (from 2953ef0c049faa55e44d741f30ff0ee5510bb7be)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Tue Nov 21 01:15:26 2006 -0800

    Change RandR property datatype to include pending/valid values.
    
    This patch tracks the protocol changes which introduce more complex
    semantics for RandR output properties including pending and valid value
    information.

diff --git a/randr/mirandr.c b/randr/mirandr.c
index 3a99bf9..0b763e1 100644
--- a/randr/mirandr.c
+++ b/randr/mirandr.c
@@ -64,10 +64,11 @@ miRRCrtcSetGamma (ScreenPtr	pScreen,
     return TRUE;
 }
 
-static Bool
-miRROutputSetProperty (ScreenPtr	pScreen,
-		       RROutputPtr	output,
-		       Atom	property)
+Bool
+miRROutputSetProperty (ScreenPtr	    pScreen,
+		       RROutputPtr	    output,
+		       Atom		    property,
+		       RRPropertyValuePtr   value)
 {
     return TRUE;
 }
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 19af9b9..27ede92 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -69,9 +69,11 @@ extern int (*SProcRandrVector[RRNumberRe
  */
 
 #define RRModeName(pMode) ((char *) (pMode + 1))
-typedef struct _rrMode	    RRModeRec, *RRModePtr;
-typedef struct _rrCrtc	    RRCrtcRec, *RRCrtcPtr;
-typedef struct _rrOutput    RROutputRec, *RROutputPtr;
+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;
@@ -81,6 +83,24 @@ struct _rrMode {
     Bool	    userDefined;
 };
 
+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;
@@ -116,7 +136,7 @@ struct _rrOutput {
     int		    numPreferred;
     RRModePtr	    *modes;
     Bool	    changed;
-    PropertyPtr	    properties;
+    RRPropertyPtr   properties;
     void	    *devPrivate;
 };
 
@@ -139,9 +159,10 @@ typedef Bool (*RRCrtcSetProcPtr) (Screen
 typedef Bool (*RRCrtcSetGammaProcPtr) (ScreenPtr	pScreen,
 				       RRCrtcPtr	crtc);
 
-typedef Bool (*RROutputSetPropertyProcPtr) (ScreenPtr	pScreen,
-					    RROutputPtr	output,
-					    Atom	property);
+typedef Bool (*RROutputSetPropertyProcPtr) (ScreenPtr		pScreen,
+					    RROutputPtr		output,
+					    Atom		property,
+					    RRPropertyValuePtr	value);
 
 #endif
 
@@ -363,6 +384,12 @@ miRRCrtcSet (ScreenPtr	pScreen,
 	     int	numOutput,
 	     RROutputPtr *outputs);
 
+Bool
+miRROutputSetProperty (ScreenPtr	    pScreen,
+		       RROutputPtr	    output,
+		       Atom		    property,
+		       RRPropertyValuePtr   value);
+
 /* randr.c */
 /*
  * Send all pending events
@@ -676,6 +703,12 @@ RRPointerScreenConfigured (ScreenPtr pSc
 void
 RRDeleteAllOutputProperties (RROutputPtr output);
 
+RRPropertyValuePtr
+RRGetOutputProperty (RROutputPtr output, Atom property, Bool pending);
+
+RRPropertyPtr
+RRQueryOutputProperty (RROutputPtr output, Atom property);
+		       
 void
 RRDeleteOutputProperty (RROutputPtr output, Atom property);
 
@@ -685,6 +718,10 @@ RRChangeOutputProperty (RROutputPtr outp
 			pointer value, Bool sendevent);
 
 int
+RRConfigureOutputProperty (RROutputPtr output, Atom property,
+			   Bool pending, Bool range, Bool immutable,
+			   int num_values, INT32 *values);
+int
 ProcRRChangeOutputProperty (ClientPtr client);
 
 int
@@ -694,6 +731,12 @@ int
 ProcRRListOutputProperties (ClientPtr client);
 
 int
+ProcRRQueryOutputProperty (ClientPtr client);
+
+int
+ProcRRConfigureOutputProperty (ClientPtr client);
+
+int
 ProcRRDeleteOutputProperty (ClientPtr client);
 
 /* rrxinerama.c */
diff --git a/randr/rrdispatch.c b/randr/rrdispatch.c
index 49ba10b..6b61b9c 100644
--- a/randr/rrdispatch.c
+++ b/randr/rrdispatch.c
@@ -192,17 +192,19 @@ int (*ProcRandrVector[RRNumberRequests])
     ProcRRGetScreenResources,	/* 8 */
     ProcRRGetOutputInfo,	/* 9 */
     ProcRRListOutputProperties,	/* 10 */
-    ProcRRChangeOutputProperty,	/* 11 */
-    ProcRRDeleteOutputProperty,	/* 12 */
-    ProcRRGetOutputProperty,	/* 13 */
-    ProcRRCreateMode,		/* 14 */
-    ProcRRDestroyMode,		/* 15 */
-    ProcRRAddOutputMode,	/* 16 */
-    ProcRRDeleteOutputMode,	/* 17 */
-    ProcRRGetCrtcInfo,		/* 18 */
-    ProcRRSetCrtcConfig,	/* 19 */
-    ProcRRGetCrtcGammaSize,	/* 20 */
-    ProcRRGetCrtcGamma,		/* 21 */
-    ProcRRSetCrtcGamma,		/* 22 */
+    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/rrproperty.c b/randr/rrproperty.c
index 44f1f0a..5d4c865 100644
--- a/randr/rrproperty.c
+++ b/randr/rrproperty.c
@@ -33,7 +33,7 @@ RRDeliverEvent (ScreenPtr pScreen, xEven
 void
 RRDeleteAllOutputProperties (RROutputPtr output)
 {
-    PropertyPtr prop, next;
+    RRPropertyPtr prop, next;
     xRROutputPropertyNotifyEvent    event;
 
     for (prop = output->properties; prop; prop = next)
@@ -46,15 +46,58 @@ RRDeleteAllOutputProperties (RROutputPtr
 	event.atom = prop->propertyName;
 	event.timestamp = currentTime.milliseconds;
 	RRDeliverEvent (output->pScreen, (xEvent *) &event, RROutputPropertyNotifyMask);
-        xfree(prop->data);
+	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(PropertyRec));
+    if (!prop)
+	return 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)
 {
-    PropertyPtr	prop, *prev;
+    RRPropertyPtr	prop, *prev;
     xRROutputPropertyNotifyEvent    event;
 
     for (prev = &output->properties; (prop = *prev); prev = &(prop->next))
@@ -70,8 +113,7 @@ RRDeleteOutputProperty (RROutputPtr outp
 	event.atom = prop->propertyName;
 	event.timestamp = currentTime.milliseconds;
 	RRDeliverEvent (output->pScreen, (xEvent *) &event, RROutputPropertyNotifyMask);
-        xfree(prop->data);
-        xfree(prop);
+	RRDestroyOutputProperty (prop);
     }
 }
 
@@ -80,96 +122,95 @@ RRChangeOutputProperty (RROutputPtr outp
 			int format, int mode, unsigned long len,
 			pointer value, Bool sendevent)
 {
-    PropertyPtr			    prop;
+    RRPropertyPtr		    prop;
     xRROutputPropertyNotifyEvent    event;
     int				    sizeInBytes;
     int				    totalSize;
     pointer			    data;
+    RRPropertyValuePtr		    prop_value;
+    Bool			    add = FALSE;
 
     sizeInBytes = format >> 3;
     totalSize = len * sizeInBytes;
 
     /* first see if property already exists */
-
-    for (prop = output->properties; prop; prop = prop->next)
-	if (prop->propertyName == property)
-	    break;
-    
+    prop = RRQueryOutputProperty (output, property);
     if (!prop)   /* just add to list */
     {
-        prop = (PropertyPtr)xalloc(sizeof(PropertyRec));
+        prop = RRCreateOutputProperty (property);
 	if (!prop)
 	    return(BadAlloc);
-        data = (pointer)xalloc(totalSize);
-	if (!data && len)
-	{
-	    xfree(prop);
-	    return(BadAlloc);
-	}
-        prop->propertyName = property;
-        prop->type = type;
-        prop->format = format;
-        prop->data = data;
-	if (len)
-	    memmove((char *)data, (char *)value, totalSize);
-	prop->size = len;
-        prop->next = output->properties;
-        output->properties = prop;
+	add = TRUE;
+	mode = PropModeReplace;
     }
+    if (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);
+    if (mode == PropModeReplace)
     {
-	/* 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->format) && (mode != PropModeReplace))
-	    return(BadMatch);
-        if ((prop->type != type) && (mode != PropModeReplace))
-            return(BadMatch);
-        if (mode == PropModeReplace)
-        {
-	    if (totalSize != prop->size * (prop->format >> 3))
-	    {
-	    	data = (pointer)xrealloc(prop->data, totalSize);
-	    	if (!data && len)
-		    return(BadAlloc);
-            	prop->data = data;
-	    }
-	    if (len)
-		memmove((char *)prop->data, (char *)value, totalSize);
-	    prop->size = len;
-    	    prop->type = type;
-	    prop->format = format;
-	}
-	else if (len == 0)
+	if (totalSize != prop_value->size * (prop_value->format >> 3))
 	{
-	    /* do nothing */
-	}
-        else if (mode == PropModeAppend)
-        {
-	    data = (pointer)xrealloc(prop->data,
-				     sizeInBytes * (len + prop->size));
-	    if (!data)
-		return(BadAlloc);
-            prop->data = data;
-	    memmove(&((char *)data)[prop->size * sizeInBytes], 
-		    (char *)value,
-		  totalSize);
-            prop->size += len;
-	}
-        else if (mode == PropModePrepend)
-        {
-            data = (pointer)xalloc(sizeInBytes * (len + prop->size));
-	    if (!data)
+	    if (prop_value->data)
+		data = (pointer)xrealloc(prop_value->data, totalSize);
+	    else
+		data = (pointer)xalloc (totalSize);
+	    if (!data && len)
+	    {
+		if (add)
+		    RRDestroyOutputProperty (prop);
 		return(BadAlloc);
-	    memmove(&((char *)data)[totalSize], (char *)prop->data, 
-		  (int)(prop->size * sizeInBytes));
-            memmove((char *)data, (char *)value, totalSize);
-	    xfree(prop->data);
-            prop->data = data;
-            prop->size += len;
+	    }
+	    prop_value->data = data;
 	}
+	if (len)
+	    memmove((char *)prop_value->data, (char *)value, totalSize);
+	prop_value->size = len;
+	prop_value->type = type;
+	prop_value->format = format;
+    }
+    else if (len == 0)
+    {
+	/* do nothing */
+    }
+    else if (mode == PropModeAppend)
+    {
+	data = (pointer)xrealloc(prop_value->data,
+				 sizeInBytes * (len + prop_value->size));
+	if (!data)
+	    return(BadAlloc);
+	prop_value->data = data;
+	memmove(&((char *)data)[prop_value->size * sizeInBytes], 
+		(char *)value,
+	      totalSize);
+	prop_value->size += len;
+    }
+    else if (mode == PropModePrepend)
+    {
+	data = (pointer)xalloc(sizeInBytes * (len + prop_value->size));
+	if (!data)
+	    return(BadAlloc);
+	memmove(&((char *)data)[totalSize], (char *)prop_value->data, 
+	      (int)(prop_value->size * sizeInBytes));
+	memmove((char *)data, (char *)value, totalSize);
+	xfree(prop_value->data);
+	prop_value->data = data;
+	prop_value->size += len;
+    }
+    if (add)
+    {
+	prop->next = output->properties;
+	output->properties = prop;
     }
     if (sendevent)
     {
@@ -184,6 +225,81 @@ RRChangeOutputProperty (RROutputPtr outp
     return(Success);
 }
 
+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;
+    return Success;
+}
+
 int
 ProcRRListOutputProperties (ClientPtr client)
 {
@@ -192,7 +308,7 @@ ProcRRListOutputProperties (ClientPtr cl
     xRRListOutputPropertiesReply    rep;
     int				    numProps = 0;
     RROutputPtr			    output;
-    PropertyPtr			    prop;
+    RRPropertyPtr			    prop;
     
     REQUEST_SIZE_MATCH(xRRListOutputPropertiesReq);
 
@@ -211,6 +327,12 @@ ProcRRListOutputProperties (ClientPtr cl
     rep.nProperties = numProps;
     rep.length = (numProps * sizeof(Atom)) >> 2;
     rep.sequenceNumber = client->sequence;
+    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;
@@ -226,6 +348,68 @@ ProcRRListOutputProperties (ClientPtr cl
 }
 
 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_SIZE_MATCH(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);
@@ -309,7 +493,8 @@ int
 ProcRRGetOutputProperty (ClientPtr client)
 {
     REQUEST(xRRGetOutputPropertyReq);
-    PropertyPtr			prop, *prev;
+    RRPropertyPtr			prop, *prev;
+    RRPropertyValuePtr			prop_value;
     unsigned long		n, len, ind;
     RROutputPtr			output;
     xRRGetOutputPropertyReply	reply;
@@ -356,18 +541,26 @@ ProcRRGetOutputProperty (ClientPtr clien
 	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->type) &&
+    if (((stuff->type != prop_value->type) &&
 	 (stuff->type != AnyPropertyType))
        )
     {
-	reply.bytesAfter = prop->size;
-	reply.format = prop->format;
+	reply.bytesAfter = prop_value->size;
+	reply.format = prop_value->format;
 	reply.length = 0;
 	reply.nItems = 0;
-	reply.propertyType = prop->type;
+	reply.propertyType = prop_value->type;
 	WriteReplyToClient(client, sizeof(xRRGetOutputPropertyReply), &reply);
 	return(client->noClientException);
     }
@@ -375,7 +568,7 @@ ProcRRGetOutputProperty (ClientPtr clien
 /*
  *  Return type, format, value to client
  */
-    n = (prop->format/8) * prop->size; /* size (bytes) of prop */
+    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
@@ -390,10 +583,10 @@ ProcRRGetOutputProperty (ClientPtr clien
     len = min(n - ind, 4 * stuff->longLength);
 
     reply.bytesAfter = n - (ind + len);
-    reply.format = prop->format;
+    reply.format = prop_value->format;
     reply.length = (len + 3) >> 2;
-    reply.nItems = len / (prop->format / 8 );
-    reply.propertyType = prop->type;
+    reply.nItems = len / (prop_value->format / 8 );
+    reply.propertyType = prop_value->type;
 
     if (stuff->delete && (reply.bytesAfter == 0))
     {
@@ -417,14 +610,13 @@ ProcRRGetOutputProperty (ClientPtr clien
 	default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break;
 	}
 	WriteSwappedDataToClient(client, len,
-				 (char *)prop->data + ind);
+				 (char *)prop_value->data + ind);
     }
 
     if (stuff->delete && (reply.bytesAfter == 0))
     { /* delete the Property */
 	*prev = prop->next;
-	xfree(prop->data);
-	xfree(prop);
+	RRDestroyOutputProperty (prop);
     }
     return(client->noClientException);
 }
diff --git a/randr/rrsdispatch.c b/randr/rrsdispatch.c
index 67af753..4a6a6e4 100644
--- a/randr/rrsdispatch.c
+++ b/randr/rrsdispatch.c
@@ -132,6 +132,26 @@ SProcRRListOutputProperties (ClientPtr c
 }
 
 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);
@@ -267,17 +287,19 @@ int (*SProcRandrVector[RRNumberRequests]
     SProcRRGetScreenResources,	/* 8 */
     SProcRRGetOutputInfo,	/* 9 */
     SProcRRListOutputProperties,/* 10 */
-    SProcRRChangeOutputProperty,/* 11 */
-    SProcRRDeleteOutputProperty,/* 12 */
-    SProcRRGetOutputProperty,	/* 13 */
-    SProcRRCreateMode,		/* 14 */
-    SProcRRDestroyMode,		/* 15 */
-    SProcRRAddOutputMode,	/* 16 */
-    SProcRRDeleteOutputMode,	/* 17 */
-    SProcRRGetCrtcInfo,		/* 18 */
-    SProcRRSetCrtcConfig,	/* 19 */
-    SProcRRGetCrtcGammaSize,	/* 20 */
-    SProcRRGetCrtcGamma,	/* 21 */
-    SProcRRSetCrtcGamma,	/* 22 */
+    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-tree 2953ef0c049faa55e44d741f30ff0ee5510bb7be (from b5aa9eb8e6eda36856a075f4b008c33f6c706bad)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Fri Nov 17 09:47:58 2006 -0800

    Add mipmap.c to GL/mesa/main/Makefile to build with mesa master

diff --git a/GL/mesa/main/Makefile.am b/GL/mesa/main/Makefile.am
index 4d5b0cd..64b383d 100644
--- a/GL/mesa/main/Makefile.am
+++ b/GL/mesa/main/Makefile.am
@@ -60,6 +60,7 @@ nodist_libmain_la_SOURCES = accum.c \
                     light.c \
                     lines.c \
                     matrix.c \
+                    mipmap.c \
                     mm.c \
                     occlude.c \
                     pixel.c \
diff-tree b5aa9eb8e6eda36856a075f4b008c33f6c706bad (from 8b2a7e94a1dc2776ab2cfaaebb309be02502602a)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Nov 16 13:50:48 2006 -0800

    Reduce calls to RRGetInfo.
    
    RRGetInfo can be expensive. Don't invoke it when quering Xinerama
    information or setting a new CRTC configuration.

diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index c945468..b81c390 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -632,13 +632,6 @@ ProcRRSetCrtcConfig (ClientPtr client)
     pScreen = crtc->pScreen;
     pScrPriv = rrGetScrPriv(pScreen);
     
-    if (!RRGetInfo (pScreen))
-    {
-	if (outputs)
-	    xfree (outputs);
-	return BadAlloc;
-    }
-    
     time = ClientTimeToServerTime(stuff->timestamp);
     configTime = ClientTimeToServerTime(stuff->configTimestamp);
     
diff --git a/randr/rrxinerama.c b/randr/rrxinerama.c
index a8e4b39..771ed09 100644
--- a/randr/rrxinerama.c
+++ b/randr/rrxinerama.c
@@ -260,7 +260,11 @@ ProcRRXineramaQueryScreens(ClientPtr cli
     REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
 
     if (RRXineramaScreenActive (pScreen))
-	RRGetInfo (pScreen);
+    {
+	rrScrPriv(pScreen);
+	if (pScrPriv->numCrtcs == 0 || pScrPriv->numOutputs == 0)
+	    RRGetInfo (pScreen);
+    }
     
     rep.type = X_Reply;
     rep.sequenceNumber = client->sequence;
diff-tree 8b2a7e94a1dc2776ab2cfaaebb309be02502602a (from ae9375ed6ba7d1c0353e4767bdfeda8dcdc8d5f6)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Nov 16 09:48:33 2006 -0800

    Remove RandR output options.
    
    RandR output options are now expected to be handled by properties instead.

diff --git a/randr/mirandr.c b/randr/mirandr.c
index 3f56fe4..3a99bf9 100644
--- a/randr/mirandr.c
+++ b/randr/mirandr.c
@@ -52,7 +52,7 @@ miRRCrtcSet (ScreenPtr	pScreen,
 	     int	y,
 	     Rotation	rotation,
 	     int	numOutput,
-	     RROutputConfigPtr    outputs)
+	     RROutputPtr *outputs)
 {
     return TRUE;
 }
@@ -137,10 +137,6 @@ miRandRInit (ScreenPtr pScreen)
 	return FALSE;
     if (!RROutputSetCrtcs (output, &crtc, 1))
 	return FALSE;
-    if (!RROutputSetPossibleOptions (output, 0))
-	return FALSE;
-    if (!RROutputSetCurrentOptions (output, 0))
-	return FALSE;
     if (!RROutputSetConnection (output, RR_Connected))
 	return FALSE;
     RRCrtcNotify (crtc, mode, 0, 0, RR_Rotate_0, 1, &output);
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 2c3e0e7..19af9b9 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -72,7 +72,6 @@ extern int (*SProcRandrVector[RRNumberRe
 typedef struct _rrMode	    RRModeRec, *RRModePtr;
 typedef struct _rrCrtc	    RRCrtcRec, *RRCrtcPtr;
 typedef struct _rrOutput    RROutputRec, *RROutputPtr;
-typedef struct _rrOutputConfig	RROutputConfigRec, *RROutputConfigPtr;
 
 struct _rrMode {
     int		    refcnt;
@@ -109,8 +108,6 @@ struct _rrOutput {
     int		    mmWidth;
     int		    mmHeight;
     RRCrtcPtr	    crtc;
-    CARD32	    currentOptions;
-    CARD32	    possibleOptions;
     int		    numCrtcs;
     RRCrtcPtr	    *crtcs;
     int		    numClones;
@@ -123,11 +120,6 @@ struct _rrOutput {
     void	    *devPrivate;
 };
 
-struct _rrOutputConfig {
-    RROutputPtr	    output;
-    CARD32	    options;
-};
-
 #if RANDR_12_INTERFACE
 typedef Bool (*RRScreenSetSizeProcPtr) (ScreenPtr	pScreen,
 					CARD16		width,
@@ -142,7 +134,7 @@ typedef Bool (*RRCrtcSetProcPtr) (Screen
 				  int			y,
 				  Rotation		rotation,
 				  int			numOutputs,
-				  RROutputConfigPtr	outputs);
+				  RROutputPtr		*outputs);
 
 typedef Bool (*RRCrtcSetGammaProcPtr) (ScreenPtr	pScreen,
 				       RRCrtcPtr	crtc);
@@ -369,7 +361,7 @@ miRRCrtcSet (ScreenPtr	pScreen,
 	     int	y,
 	     Rotation	rotation,
 	     int	numOutput,
-	     RROutputConfigPtr    outputs);
+	     RROutputPtr *outputs);
 
 /* randr.c */
 /*
@@ -490,7 +482,7 @@ RRCrtcSet (RRCrtcPtr    crtc,
 	   int		y,
 	   Rotation	rotation,
 	   int		numOutput,
-	   RROutputConfigPtr  outputs);
+	   RROutputPtr  *outputs);
 
 /*
  * Request that the Crtc gamma be changed
@@ -641,10 +633,6 @@ RROutputSetCrtcs (RROutputPtr	output,
 		  RRCrtcPtr	*crtcs,
 		  int		numCrtcs);
 
-Bool
-RROutputSetPossibleOptions (RROutputPtr	output,
-			    CARD32	possibleOptions);
-
 void
 RROutputSetCrtc (RROutputPtr output, RRCrtcPtr crtc);
     
@@ -657,10 +645,6 @@ RROutputSetSubpixelOrder (RROutputPtr ou
 			  int	      subpixelOrder);
 
 Bool
-RROutputSetCurrentOptions (RROutputPtr output,
-			   CARD32      currentOptions);
-
-Bool
 RROutputSetPhysicalSize (RROutputPtr	output,
 			 int		mmWidth,
 			 int		mmHeight);
@@ -739,8 +723,6 @@ Query state:
 		RRScreenSetSizeRange
 		RROutputSetCrtcs
 		RROutputSetCrtc
-		RROutputSetPossibleOptions
-		RRSetCurrentOptions
 		RRModeGet
 		RROutputSetModes
 		RROutputSetConnection
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 9f7177a..c945468 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -257,7 +257,7 @@ RRCrtcSet (RRCrtcPtr    crtc,
 	   int		y,
 	   Rotation	rotation,
 	   int		numOutputs,
-	   RROutputConfigPtr  outputs)
+	   RROutputPtr  *outputs)
 {
     ScreenPtr	pScreen = crtc->pScreen;
 
@@ -290,10 +290,10 @@ RRCrtcSet (RRCrtcPtr    crtc,
 
 	    size.width = mode->mode.width;
 	    size.height = mode->mode.height;
-	    if (outputs[0].output->mmWidth && outputs[0].output->mmHeight)
+	    if (outputs[0]->mmWidth && outputs[0]->mmHeight)
 	    {
-		size.mmWidth = outputs[0].output->mmWidth;
-		size.mmHeight = outputs[0].output->mmHeight;
+		size.mmWidth = outputs[0]->mmWidth;
+		size.mmHeight = outputs[0]->mmHeight;
 	    }
 	    else
 	    {
@@ -308,7 +308,7 @@ RRCrtcSet (RRCrtcPtr    crtc,
 	     * Old 1.0 interface tied screen size to mode size
 	     */
 	    if (ret)
-		RRCrtcNotify (crtc, mode, x, y, rotation, 1, &outputs[0].output);
+		RRCrtcNotify (crtc, mode, x, y, rotation, 1, outputs);
 	    return ret;
 	}
 #endif
@@ -554,15 +554,15 @@ ProcRRSetCrtcConfig (ClientPtr client)
     RRCrtcPtr		    crtc;
     RRModePtr		    mode;
     int			    numOutputs;
-    RROutputConfigPtr	    outputs = NULL;
-    xRROutputConfig 	    *outputConfigs;
+    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)) >> 1;
+    numOutputs = (stuff->length - (SIZEOF (xRRSetCrtcConfigReq) >> 2));
     
     crtc = LookupIDByType (stuff->crtc, RRCrtcType);
     if (!crtc)
@@ -589,47 +589,39 @@ ProcRRSetCrtcConfig (ClientPtr client)
     }
     if (numOutputs)
     {
-	outputs = xalloc (numOutputs * sizeof (RROutputConfigRec));
+	outputs = xalloc (numOutputs * sizeof (RROutputPtr));
 	if (!outputs)
 	    return BadAlloc;
     }
     else
 	outputs = NULL;
     
-    outputConfigs = (xRROutputConfig *) (stuff + 1);
+    outputIds = (RROutput *) (stuff + 1);
     for (i = 0; i < numOutputs; i++)
     {
-	outputs[i].output = LookupIDByType (outputConfigs[i].output, RROutputType);
-	if (!outputs[i].output)
+	outputs[i] = (RROutputPtr) LookupIDByType (outputIds[i], RROutputType);
+	if (!outputs[i])
 	{
-	    client->errorValue = outputConfigs[i].output;
+	    client->errorValue = outputIds[i];
 	    if (outputs)
 		xfree (outputs);
 	    return RRErrorBase + BadRROutput;
 	}
-	outputs[i].options = outputConfigs[i].options;
-	if (outputs[i].options & ~outputs[i].output->possibleOptions)
-	{
-	    client->errorValue = outputConfigs[i].options;
-	    if (outputs)
-		xfree (outputs);
-	    return BadMatch;
-	}
 	/* validate crtc for this output */
-	for (j = 0; j < outputs[i].output->numCrtcs; j++)
-	    if (outputs[i].output->crtcs[j] == crtc)
+	for (j = 0; j < outputs[i]->numCrtcs; j++)
+	    if (outputs[i]->crtcs[j] == crtc)
 		break;
-	if (j == outputs[i].output->numCrtcs)
+	if (j == outputs[i]->numCrtcs)
 	{
 	    if (outputs)
 		xfree (outputs);
 	    return BadMatch;
 	}
 	/* validate mode for this output */
-	for (j = 0; j < outputs[i].output->numModes; j++)
-	    if (outputs[i].output->modes[j] == mode)
+	for (j = 0; j < outputs[i]->numModes; j++)
+	    if (outputs[i]->modes[j] == mode)
 		break;
-	if (j == outputs[i].output->numModes)
+	if (j == outputs[i]->numModes)
 	{
 	    if (outputs)
 		xfree (outputs);
diff --git a/randr/rroutput.c b/randr/rroutput.c
index 102587b..8b760ec 100644
--- a/randr/rroutput.c
+++ b/randr/rroutput.c
@@ -65,8 +65,6 @@ RROutputCreate (const char  *name,
     output->mmWidth = 0;
     output->mmHeight = 0;
     output->crtc = NULL;
-    output->currentOptions = 0;
-    output->possibleOptions = 0;
     output->numCrtcs = 0;
     output->crtcs = NULL;
     output->numClones = 0;
@@ -223,17 +221,6 @@ RROutputSetCrtcs (RROutputPtr	output,
     return TRUE;
 }
 
-Bool
-RROutputSetPossibleOptions (RROutputPtr	output,
-			    CARD32	possibleOptions)
-{
-    if (output->possibleOptions == possibleOptions)
-	return TRUE;
-    output->possibleOptions = possibleOptions;
-    RROutputChanged (output);
-    return TRUE;
-}
-
 void
 RROutputSetCrtc (RROutputPtr output, RRCrtcPtr crtc)
 {
@@ -267,17 +254,6 @@ RROutputSetSubpixelOrder (RROutputPtr ou
 }
 
 Bool
-RROutputSetCurrentOptions (RROutputPtr output,
-			   CARD32      currentOptions)
-{
-    if (output->currentOptions == currentOptions)
-	return TRUE;
-    output->currentOptions = currentOptions;
-    RROutputChanged (output);
-    return TRUE;
-}
-
-Bool
 RROutputSetPhysicalSize (RROutputPtr	output,
 			 int		mmWidth,
 			 int		mmHeight)
@@ -413,7 +389,6 @@ ProcRRGetOutputInfo (ClientPtr client)
     rep.length = OutputInfoExtra >> 2;
     rep.timestamp = pScrPriv->lastSetTime.milliseconds;
     rep.crtc = output->crtc ? output->crtc->id : None;
-    rep.currentOptions = output->currentOptions;
     rep.mmWidth = output->mmWidth;
     rep.mmHeight = output->mmHeight;
     rep.connection = output->connection;
@@ -423,7 +398,6 @@ ProcRRGetOutputInfo (ClientPtr client)
     rep.nPreferred = output->numPreferred;
     rep.nClones = output->numClones;
     rep.nameLength = output->nameLength;
-    rep.possibleOptions = output->possibleOptions;
     
     extraLen = ((output->numCrtcs + 
 		 output->numModes + 
@@ -469,15 +443,12 @@ ProcRRGetOutputInfo (ClientPtr client)
 	swapl(&rep.length, n);
 	swapl(&rep.timestamp, n);
 	swapl(&rep.crtc, n);
-	swapl(&rep.currentOptions, n);
 	swapl(&rep.mmWidth, n);
 	swapl(&rep.mmHeight, n);
 	swaps(&rep.nCrtcs, n);
 	swaps(&rep.nModes, n);
 	swaps(&rep.nClones, n);
-	swapl(&rep.possibleOptions, n);
 	swaps(&rep.nameLength, n);
-	swapl(&rep.possibleOptions, n);
     }
     WriteToClient(client, sizeof(xRRGetOutputInfoReply), (char *)&rep);
     if (extraLen)
diff --git a/randr/rrscreen.c b/randr/rrscreen.c
index d47e9d6..76c16b0 100644
--- a/randr/rrscreen.c
+++ b/randr/rrscreen.c
@@ -712,7 +712,7 @@ ProcRRSetScreenConfig (ClientPtr client)
     Rotation		    rotation;
     int			    rate;
     Bool		    has_rate;
-    RROutputConfigRec	    output;
+    RROutputPtr		    output;
     RRModePtr		    mode;
     RR10DataPtr		    pData = NULL;
     RRScreenSizePtr    	    pSize;
@@ -749,14 +749,13 @@ ProcRRSetScreenConfig (ClientPtr client)
     if (!RRGetInfo (pScreen))
 	return BadAlloc;
     
-    output.output = RRFirstOutput (pScreen);
-    if (!output.output)
+    output = RRFirstOutput (pScreen);
+    if (!output)
     {
 	time = currentTime;
 	rep.status = RRSetConfigFailed;
 	goto sendReply;
     }
-    output.options = output.output->currentOptions;
     
     /*
      * if the client's config timestamp is not the same as the last config
@@ -769,7 +768,7 @@ ProcRRSetScreenConfig (ClientPtr client)
 	goto sendReply;
     }
     
-    pData = RR10GetData (pScreen, output.output);
+    pData = RR10GetData (pScreen, output);
     if (!pData)
 	return BadAlloc;
     
@@ -805,7 +804,7 @@ ProcRRSetScreenConfig (ClientPtr client)
 	return BadValue;
     }
 
-    if ((~output.output->crtc->rotations) & rotation)
+    if ((~output->crtc->rotations) & rotation)
     {
 	/*
 	 * requested rotation or reflection not supported by screen
@@ -878,7 +877,7 @@ ProcRRSetScreenConfig (ClientPtr client)
 	}
     }
     
-    rep.status = RRCrtcSet (output.output->crtc, mode, 0, 0, stuff->rotation,
+    rep.status = RRCrtcSet (output->crtc, mode, 0, 0, stuff->rotation,
 			    1, &output);
     
     /*
diff-tree ae9375ed6ba7d1c0353e4767bdfeda8dcdc8d5f6 (from 8d0ac835bca282283dd6394fda7416e62a1934c7)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Wed Nov 8 23:17:55 2006 -0800

    Add RRInit function to create resource types for RR objects.
    
    To allow RandR objects to be created before the screen object exists,
    the resource types must be registered with the resource database.
    A driver wishing to create RandR objects must call RRInit before doing so.
    
    Also, fix a segfault when setting Output data before it is associated with a
    screen.

diff --git a/randr/randr.c b/randr/randr.c
index 4426c47..147df8c 100644
--- a/randr/randr.c
+++ b/randr/randr.c
@@ -39,8 +39,7 @@
 #endif
 
 #define RR_VALIDATE
-int	RRGeneration;
-int	RRNScreens;
+static int	RRNScreens;
 
 #define wrap(priv,real,mem,func) {\
     priv->mem = real->mem; \
@@ -198,10 +197,10 @@ SRRNotifyEvent (xEvent *from,
     }
 }
 
-Bool RRScreenInit(ScreenPtr pScreen)
-{
-    rrScrPrivPtr   pScrPriv;
+static int RRGeneration;
 
+Bool RRInit (void)
+{
     if (RRGeneration != serverGeneration)
     {
 	if (!RRModeInit ())
@@ -210,9 +209,25 @@ Bool RRScreenInit(ScreenPtr pScreen)
 	    return FALSE;
 	if (!RROutputInit ())
 	    return FALSE;
+	RRGeneration = serverGeneration;
+    }
+    return TRUE;
+}
+
+static int RRScreenGeneration;
+
+Bool RRScreenInit(ScreenPtr pScreen)
+{
+    rrScrPrivPtr   pScrPriv;
+
+    if (!RRInit ())
+	return FALSE;
+
+    if (RRScreenGeneration != serverGeneration)
+    {
 	if ((rrPrivIndex = AllocateScreenPrivateIndex()) < 0)
 	    return FALSE;
-	RRGeneration = serverGeneration;
+	RRScreenGeneration = serverGeneration;
     }
 
     pScrPriv = (rrScrPrivPtr) xalloc (sizeof (rrScrPrivRec));
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 345418b..2c3e0e7 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -384,6 +384,8 @@ RRTellChanged (ScreenPtr pScreen);
 Bool
 RRGetInfo (ScreenPtr pScreen);
 
+Bool RRInit (void);
+
 Bool RRScreenInit(ScreenPtr pScreen);
 
 RROutputPtr
diff --git a/randr/rroutput.c b/randr/rroutput.c
index 1b0ecab..102587b 100644
--- a/randr/rroutput.c
+++ b/randr/rroutput.c
@@ -31,10 +31,13 @@ void
 RROutputChanged (RROutputPtr output)
 {
     ScreenPtr	pScreen = output->pScreen;
-    rrScrPriv (pScreen);
-
+    
     output->changed = TRUE;
-    pScrPriv->changed = TRUE;
+    if (pScreen)
+    {
+	rrScrPriv (pScreen);
+	pScrPriv->changed = TRUE;
+    }
 }
 
 /*
@@ -335,17 +338,21 @@ RROutputDestroyResource (pointer value, 
 {
     RROutputPtr	output = (RROutputPtr) value;
     ScreenPtr	pScreen = output->pScreen;
-    rrScrPriv(pScreen);
-    int		i;
 
-    for (i = 0; i < pScrPriv->numOutputs; i++)
+    if (pScreen)
     {
-	if (pScrPriv->outputs[i] == output)
+	rrScrPriv(pScreen);
+	int		i;
+    
+	for (i = 0; i < pScrPriv->numOutputs; i++)
 	{
-	    memmove (pScrPriv->outputs + i, pScrPriv->outputs + i + 1,
-		     (pScrPriv->numOutputs - (i - 1)) * sizeof (RROutputPtr));
-	    --pScrPriv->numOutputs;
-	    break;
+	    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)
@@ -481,4 +488,3 @@ ProcRRGetOutputInfo (ClientPtr client)
     
     return client->noClientException;
 }
-
diff-tree 8d0ac835bca282283dd6394fda7416e62a1934c7 (from 45621bd215ad905e39559154d1d3dfada92e1798)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Wed Nov 8 21:36:35 2006 -0800

    Allow RandR objects to be created before the associated ScreenRec.
    
    xf86 drivers need to create RandR object in the PreInit stage,
    before the ScreenRec is allocated. Changing the RandR DIX code
    to permit this required the addition of functions that later associate the
    objects with the related screen.
    
    An additional change is that modes are now global, and no longer associated
    with a specific screen. This change actually makes mode management cleaner
    as there is no more per-screen list of modes to deal with.
    
    This changes the RandR 1.2 ABI/API for drivers.

diff --git a/hw/xfree86/common/Makefile.am b/hw/xfree86/common/Makefile.am
index d983ee9..2274527 100644
--- a/hw/xfree86/common/Makefile.am
+++ b/hw/xfree86/common/Makefile.am
@@ -54,7 +54,7 @@ sdk_HEADERS = compiler.h fourcc.h xf86.h
               xf86PciInfo.h xf86Priv.h xf86Privstr.h xf86Resources.h \
               xf86cmap.h xf86fbman.h xf86str.h $(XISDKINCS) \
               $(XVSDKINCS) atKeynames.h xf86Version.h xorgVersion.h \
-              xf86sbusBus.h xf86xv.h xf86xvmc.h xf86xvpriv.h
+              xf86sbusBus.h xf86xv.h xf86xvmc.h xf86xvpriv.h xf86Keymap.h
 
 DISTCLEANFILES = xf86Build.h
 CLEANFILES = $(BUILT_SOURCES)
diff --git a/randr/mirandr.c b/randr/mirandr.c
index 11c2991..3f56fe4 100644
--- a/randr/mirandr.c
+++ b/randr/mirandr.c
@@ -113,17 +113,24 @@ miRandRInit (ScreenPtr pScreen)
     modeInfo.height = pScreen->height;
     modeInfo.nameLength = strlen (name);
     
-    mode = RRModeGet (pScreen, &modeInfo, name);
+    mode = RRModeGet (&modeInfo, name);
     if (!mode)
 	return FALSE;
     
-    crtc = RRCrtcCreate (pScreen, NULL);
+    crtc = RRCrtcCreate (NULL);
     if (!crtc)
 	return FALSE;
+    if (!RRCrtcAttachScreen (crtc, pScreen))
+    {
+	RRCrtcDestroy (crtc);
+	return FALSE;
+    }
     
-    output = RROutputCreate (pScreen, "screen", 6, NULL);
+    output = RROutputCreate ("screen", 6, NULL);
     if (!output)
 	return FALSE;
+    if (!RROutputAttachScreen (output, pScreen))
+	return FALSE;
     if (!RROutputSetClones (output, NULL, 0))
 	return FALSE;
     if (!RROutputSetModes (output, &mode, 1, 0))
diff --git a/randr/randr.c b/randr/randr.c
index 7b39e80..4426c47 100644
--- a/randr/randr.c
+++ b/randr/randr.c
@@ -103,8 +103,6 @@ RRCloseScreen (int i, ScreenPtr pScreen)
 	RRCrtcDestroy (pScrPriv->crtcs[j]);
     for (j = pScrPriv->numOutputs - 1; j >= 0; j--)
 	RROutputDestroy (pScrPriv->outputs[j]);
-    for (j = pScrPriv->numModes - 1; j >= 0; j--)
-	RRModeDestroy (pScrPriv->modes[j]);
     
     xfree (pScrPriv);
     RRNScreens -= 1;	/* ok, one fewer screen with RandR running */
@@ -257,8 +255,6 @@ Bool RRScreenInit(ScreenPtr pScreen)
     
     wrap (pScrPriv, pScreen, CloseScreen, RRCloseScreen);
 
-    pScrPriv->numModes = 0;
-    pScrPriv->modes = NULL;
     pScrPriv->numOutputs = 0;
     pScrPriv->outputs = NULL;
     pScrPriv->numCrtcs = 0;
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 60877a3..345418b 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -79,7 +79,6 @@ struct _rrMode {
     xRRModeInfo	    mode;
     char	    *name;
     void	    *devPrivate;
-    ScreenPtr	    screen;
     Bool	    userDefined;
 };
 
@@ -210,10 +209,6 @@ typedef struct _rrScrPriv {
     CARD16		    width, height;	/* last known screen size */
     Bool		    layoutChanged;	/* screen layout changed */
 
-    /* modes, outputs and crtcs */
-    int			    numModes;
-    RRModePtr		    *modes;
-
     int			    numOutputs;
     RROutputPtr		    *outputs;
 
@@ -457,10 +452,17 @@ RRCrtcChanged (RRCrtcPtr crtc, Bool layo
  * Create a CRTC
  */
 RRCrtcPtr
-RRCrtcCreate (ScreenPtr	pScreen,
-	      void	*devPrivate);
+RRCrtcCreate (void	*devPrivate);
 
 /*
+ * Attach a CRTC to a screen. Once done, this cannot be
+ * undone without destroying the CRTC; it is separate from Create
+ * only to allow an xf86-based driver to create objects in preinit
+ */
+Bool
+RRCrtcAttachScreen (RRCrtcPtr crtc, ScreenPtr pScreen);
+    
+/*
  * Notify the extension that the Crtc has been reconfigured,
  * the driver calls this whenever it has updated the mode
  */
@@ -556,8 +558,7 @@ RRClientKnowsRates (ClientPtr	pClient);
  */
 
 RRModePtr
-RRModeGet (ScreenPtr	pScreen,
-	   xRRModeInfo	*modeInfo,
+RRModeGet (xRRModeInfo	*modeInfo,
 	   const char	*name);
 
 void
@@ -571,6 +572,12 @@ 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
@@ -601,12 +608,19 @@ RROutputChanged (RROutputPtr output);
  */
 
 RROutputPtr
-RROutputCreate (ScreenPtr   pScreen,
-		const char  *name,
+RROutputCreate (const char  *name,
 		int	    nameLength,
 		void	    *devPrivate);
 
 /*
+ * Attach an output to a screen, again split from creation so
+ * xf86 DDXen can create randr resources before the ScreenRec
+ * exists
+ */
+Bool
+RROutputAttachScreen (RROutputPtr output, ScreenPtr pScreen);
+
+/*
  * Notify extension that output parameters have been changed
  */
 Bool
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 76d0b6b..9f7177a 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -32,43 +32,34 @@ void
 RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged)
 {
     ScreenPtr	pScreen = crtc->pScreen;
-    rrScrPriv(pScreen);
 
     crtc->changed = TRUE;
-    pScrPriv->changed = TRUE;
-    /*
-     * Send ConfigureNotify on any layout change
-     */
-    if (layoutChanged)
-	pScrPriv->layoutChanged = 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)
+RRCrtcCreate (void	*devPrivate)
 {
-    rrScrPriv (pScreen);
     RRCrtcPtr	crtc;
-    RRCrtcPtr	*crtcs;
     
     crtc = xalloc (sizeof (RRCrtcRec));
     if (!crtc)
 	return NULL;
-    if (pScrPriv->numCrtcs)
-	crtcs = xrealloc (pScrPriv->crtcs, 
-			  (pScrPriv->numCrtcs + 1) * sizeof (RRCrtcPtr));
-    else
-	crtcs = xalloc (sizeof (RRCrtcPtr));
-    if (!crtcs)
-    {
-	xfree (crtc);
-	return NULL;
-    }
     crtc->id = FakeClientID (0);
-    crtc->pScreen = pScreen;
+    crtc->pScreen = NULL;
     crtc->mode = NULL;
     crtc->x = 0;
     crtc->y = 0;
@@ -84,11 +75,37 @@ RRCrtcCreate (ScreenPtr	pScreen,
     if (!AddResource (crtc->id, RRCrtcType, (pointer) crtc))
 	return NULL;
 
+    return crtc;
+}
+
+/*
+ * Attach a Crtc to a screen. This is done as a separate step
+ * so that an xf86-based driver can create CRTCs in PreInit
+ * before the Screen has been created
+ */
+
+Bool
+RRCrtcAttachScreen (RRCrtcPtr crtc, ScreenPtr pScreen)
+{
+    rrScrPriv (pScreen);
+    RRCrtcPtr	*crtcs;
+
+    /* 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;
+    
+    /* attach the screen and crtc together */
+    crtc->pScreen = pScreen;
     pScrPriv->crtcs = crtcs;
     pScrPriv->crtcs[pScrPriv->numCrtcs++] = crtc;
 
     RRCrtcChanged (crtc, TRUE);
-    return crtc;
+    return TRUE;
 }
 
 /*
@@ -243,7 +260,6 @@ RRCrtcSet (RRCrtcPtr    crtc,
 	   RROutputConfigPtr  outputs)
 {
     ScreenPtr	pScreen = crtc->pScreen;
-    rrScrPriv(pScreen);
 
     /* See if nothing changed */
     if (crtc->mode == mode &&
@@ -255,45 +271,49 @@ RRCrtcSet (RRCrtcPtr    crtc,
     {
 	return TRUE;
     }
-#if RANDR_12_INTERFACE
-    if (pScrPriv->rrCrtcSet)
+    if (pScreen)
     {
-	return (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y, 
-				       rotation, numOutputs, outputs);
-    }
-#endif
-#if RANDR_10_INTERFACE
-    if (pScrPriv->rrSetConfig)
-    {
-	RRScreenSize	    size;
-	RRScreenRate	    rate;
-	Bool		    ret;
-
-	size.width = mode->mode.width;
-	size.height = mode->mode.height;
-	if (outputs[0].output->mmWidth && outputs[0].output->mmHeight)
+#if RANDR_12_INTERFACE
+	rrScrPriv(pScreen);
+	if (pScrPriv->rrCrtcSet)
 	{
-	    size.mmWidth = outputs[0].output->mmWidth;
-	    size.mmHeight = outputs[0].output->mmHeight;
+	    return (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y, 
+					   rotation, numOutputs, outputs);
 	}
-	else
+#endif
+#if RANDR_10_INTERFACE
+	if (pScrPriv->rrSetConfig)
 	{
-	    size.mmWidth = pScreen->mmWidth;
-	    size.mmHeight = pScreen->mmHeight;
+	    RRScreenSize	    size;
+	    RRScreenRate	    rate;
+	    Bool		    ret;
+
+	    size.width = mode->mode.width;
+	    size.height = mode->mode.height;
+	    if (outputs[0].output->mmWidth && outputs[0].output->mmHeight)
+	    {
+		size.mmWidth = outputs[0].output->mmWidth;
+		size.mmHeight = outputs[0].output->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[0].output);
+	    return ret;
 	}
-	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[0].output);
-	return ret;
-    }
 #endif
-    RRTellChanged (pScreen);
+	RRTellChanged (pScreen);
+    }
     return FALSE;
 }
 
@@ -311,22 +331,26 @@ RRCrtcDestroyResource (pointer value, XI
 {
     RRCrtcPtr	crtc = (RRCrtcPtr) value;
     ScreenPtr	pScreen = crtc->pScreen;
-    rrScrPriv(pScreen);
-    int		i;
 
-    for (i = 0; i < pScrPriv->numCrtcs; i++)
+    if (pScreen)
     {
-	if (pScrPriv->crtcs[i] == crtc)
+	rrScrPriv(pScreen);
+	int		i;
+    
+	for (i = 0; i < pScrPriv->numCrtcs; i++)
 	{
-	    memmove (pScrPriv->crtcs + i, pScrPriv->crtcs + i + 1,
-		     (pScrPriv->numCrtcs - (i - 1)) * sizeof (RRCrtcPtr));
-	    --pScrPriv->numCrtcs;
-	    break;
+	    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);
-    xfree (value);
+    xfree (crtc);
     return 1;
 }
 
@@ -343,15 +367,18 @@ RRCrtcGammaSet (RRCrtcPtr   crtc,
     Bool	ret = TRUE;
 #if RANDR_12_INTERFACE
     ScreenPtr	pScreen = crtc->pScreen;
-    rrScrPriv(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 (pScrPriv->rrCrtcSetGamma)
-	ret = (*pScrPriv->rrCrtcSetGamma) (pScreen, crtc);
+    if (pScreen)
+    {
+	rrScrPriv(pScreen);
+	if (pScrPriv->rrCrtcSetGamma)
+	    ret = (*pScrPriv->rrCrtcSetGamma) (pScreen, crtc);
+    }
 #endif
     return ret;
 }
@@ -433,6 +460,9 @@ ProcRRGetCrtcInfo (ClientPtr client)
     if (!crtc)
 	return RRErrorBase + BadRRCrtc;
 
+    /* All crtcs must be associated with screens before client
+     * requests are processed
+     */
     pScreen = crtc->pScreen;
     pScrPriv = rrGetScrPriv(pScreen);
 
@@ -589,7 +619,7 @@ ProcRRSetCrtcConfig (ClientPtr client)
 	for (j = 0; j < outputs[i].output->numCrtcs; j++)
 	    if (outputs[i].output->crtcs[j] == crtc)
 		break;
-	if (j == outputs[j].output->numCrtcs)
+	if (j == outputs[i].output->numCrtcs)
 	{
 	    if (outputs)
 		xfree (outputs);
diff --git a/randr/rrinfo.c b/randr/rrinfo.c
index e92caad..244b089 100644
--- a/randr/rrinfo.c
+++ b/randr/rrinfo.c
@@ -44,7 +44,7 @@ RROldModeAdd (RROutputPtr output, RRScre
     modeInfo.dotClock = ((CARD32) size->width * (CARD32) size->height *
 			 (CARD32) refresh);
     modeInfo.nameLength = strlen (name);
-    mode = RRModeGet (pScreen, &modeInfo, name);
+    mode = RRModeGet (&modeInfo, name);
     if (!mode)
 	return NULL;
     for (i = 0; i < output->numModes; i++)
@@ -90,12 +90,19 @@ RRScanOldConfig (ScreenPtr pScreen, Rota
     if (pScrPriv->numOutputs == 0 &&
 	pScrPriv->numCrtcs == 0)
     {
-	crtc = RRCrtcCreate (pScreen, NULL);
+	crtc = RRCrtcCreate (NULL);
 	if (!crtc)
 	    return;
-	output = RROutputCreate (pScreen, "default", 7, NULL);
+	if (!RRCrtcAttachScreen (crtc, pScreen))
+	{
+	    RRCrtcDestroy (crtc);
+	    return;
+	}
+	output = RROutputCreate ("default", 7, NULL);
 	if (!output)
 	    return;
+	if (!RROutputAttachScreen (output, pScreen))
+	    return;
 	RROutputSetCrtcs (output, &crtc, 1);
 	RROutputSetCrtc (output, crtc);
 	RROutputSetConnection (output, RR_Connected);
@@ -206,7 +213,6 @@ RRGetInfo (ScreenPtr pScreen)
     if (pScrPriv->nSizes)
 	RRScanOldConfig (pScreen, rotations);
 #endif
-    RRModePruneUnused (pScreen);
     RRTellChanged (pScreen);
     return TRUE;
 }
diff --git a/randr/rrmode.c b/randr/rrmode.c
index fb4b5eb..3cd9ef2 100644
--- a/randr/rrmode.c
+++ b/randr/rrmode.c
@@ -42,19 +42,23 @@ RRModeEqual (xRRModeInfo *a, xRRModeInfo
     return TRUE;
 }
 
+/*
+ * Keep a list so it's easy to find modes in the resource database.
+ */
+static int	    num_modes;
+static RRModePtr    *modes;
+
 RRModePtr
-RRModeGet (ScreenPtr	pScreen,
-	   xRRModeInfo	*modeInfo,
+RRModeGet (xRRModeInfo	*modeInfo,
 	   const char	*name)
 {
-    rrScrPriv (pScreen);
     int	i;
     RRModePtr	mode;
-    RRModePtr	*modes;
+    RRModePtr	*newModes;
 
-    for (i = 0; i < pScrPriv->numModes; i++)
+    for (i = 0; i < num_modes; i++)
     {
-	mode = pScrPriv->modes[i];
+	mode = modes[i];
 	if (RRModeEqual (&mode->mode, modeInfo) &&
 	    !memcmp (name, mode->name, modeInfo->nameLength))
 	{
@@ -71,16 +75,14 @@ RRModeGet (ScreenPtr	pScreen,
     mode->name = (char *) (mode + 1);
     memcpy (mode->name, name, modeInfo->nameLength);
     mode->name[modeInfo->nameLength] = '\0';
-    mode->screen = pScreen;
     mode->userDefined = FALSE;
 
-    if (pScrPriv->numModes)
-	modes = xrealloc (pScrPriv->modes,
-			  (pScrPriv->numModes + 1) * sizeof (RRModePtr));
+    if (num_modes)
+	newModes = xrealloc (modes, (num_modes + 1) * sizeof (RRModePtr));
     else
-	modes = xalloc (sizeof (RRModePtr));
+	newModes = xalloc (sizeof (RRModePtr));
 
-    if (!modes)
+    if (!newModes)
     {
 	xfree (mode);
 	return NULL;
@@ -89,37 +91,64 @@ RRModeGet (ScreenPtr	pScreen,
     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;
-    pScrPriv->modes = modes;
-    pScrPriv->modes[pScrPriv->numModes++] = mode;
-    pScrPriv->changed = TRUE;
     return mode;
 }
 
+RRModePtr *
+RRModesForScreen (ScreenPtr pScreen, int *num_ret)
+{
+    rrScrPriv(pScreen);
+    int	o;
+    RRModePtr	*screen_modes;
+    int		num_screen_modes = 0;
+
+    screen_modes = xalloc ((num_modes ? num_modes : 1) * sizeof (RRModePtr));
+    
+    for (o = 0; o < pScrPriv->numOutputs; o++)
+    {
+	RROutputPtr	output = pScrPriv->outputs[o];
+	int		m, n;
+
+	for (m = 0; m < output->numModes; m++)
+	{
+	    RRModePtr	mode = output->modes[m];
+	    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)
 {
-    ScreenPtr	    pScreen;
-    rrScrPrivPtr    pScrPriv;
     int	m;
     
     if (--mode->refcnt > 0)
 	return;
-    pScreen = mode->screen;
-    pScrPriv = rrGetScrPriv (pScreen);
-    for (m = 0; m < pScrPriv->numModes; m++)
+    for (m = 0; m < num_modes; m++)
     {
-	if (pScrPriv->modes[m] == mode)
+	if (modes[m] == mode)
 	{
-	    memmove (pScrPriv->modes + m, pScrPriv->modes + m + 1,
-		     (pScrPriv->numModes - m - 1) * sizeof (RRModePtr));
-	    pScrPriv->numModes--;
-	    if (!pScrPriv->numModes)
+	    memmove (modes + m, modes + m + 1,
+		     (num_modes - m - 1) * sizeof (RRModePtr));
+	    num_modes--;
+	    if (!num_modes)
 	    {
-		xfree (pScrPriv->modes);
-		pScrPriv->modes = NULL;
+		xfree (modes);
+		modes = NULL;
 	    }
-	    pScrPriv->changed = TRUE;
 	    break;
 	}
     }
@@ -137,6 +166,8 @@ RRModeDestroyResource (pointer value, XI
 Bool
 RRModeInit (void)
 {
+    assert (num_modes == 0);
+    assert (modes == NULL);
     RRModeType = CreateNewResourceType (RRModeDestroyResource);
     if (!RRModeType)
 	return FALSE;
@@ -146,26 +177,6 @@ RRModeInit (void)
     return TRUE;
 }
 
-void
-RRModePruneUnused (ScreenPtr pScreen)
-{
-    rrScrPriv (pScreen);
-    RRModePtr	*unused, mode;
-    int		m;
-    int		num = pScrPriv->numModes;
-
-    unused = xalloc (num * sizeof (RRModePtr));
-    if (!unused)
-	return;
-    memcpy (unused, pScrPriv->modes, num * sizeof (RRModePtr));
-    for (m = 0; m < num; m++) {
-	mode = unused[m];
-	if (mode->refcnt == 1 && !mode->userDefined)
-	    FreeResource (mode->mode.id, 0);
-    }
-    xfree (unused);
-}
-
 int
 ProcRRCreateMode (ClientPtr client)
 {
@@ -205,4 +216,3 @@ ProcRRDeleteOutputMode (ClientPtr client
     (void) stuff;
     return BadImplementation; 
 }
-
diff --git a/randr/rroutput.c b/randr/rroutput.c
index 1f6f330..1b0ecab 100644
--- a/randr/rroutput.c
+++ b/randr/rroutput.c
@@ -42,30 +42,17 @@ RROutputChanged (RROutputPtr output)
  */
 
 RROutputPtr
-RROutputCreate (ScreenPtr   pScreen,
-		const char  *name,
+RROutputCreate (const char  *name,
 		int	    nameLength,
 		void	    *devPrivate)
 {
-    rrScrPriv (pScreen);
     RROutputPtr	output;
-    RROutputPtr	*outputs;
 
     output = xalloc (sizeof (RROutputRec) + nameLength + 1);
     if (!output)
 	return NULL;
-    if (pScrPriv->numOutputs)
-	outputs = xrealloc (pScrPriv->outputs, 
-			    (pScrPriv->numOutputs + 1) * sizeof (RROutputPtr));
-    else
-	outputs = xalloc (sizeof (RROutputPtr));
-    if (!outputs)
-    {
-	xfree (output);
-	return NULL;
-    }
     output->id = FakeClientID (0);
-    output->pScreen = pScreen;
+    output->pScreen = NULL;
     output->name = (char *) (output + 1);
     output->nameLength = nameLength;
     memcpy (output->name, name, nameLength);
@@ -91,12 +78,35 @@ RROutputCreate (ScreenPtr   pScreen,
     if (!AddResource (output->id, RROutputType, (pointer) output))
 	return NULL;
 
+    return output;
+}
+
+/*
+ * Attach an Output to a screen. This is done as a separate step
+ * so that an xf86-based driver can create Outputs in PreInit
+ * before the Screen has been created
+ */
+
+Bool
+RROutputAttachScreen (RROutputPtr output, ScreenPtr pScreen)
+{
+    rrScrPriv (pScreen);
+    RROutputPtr	*outputs;
+    
+    if (pScrPriv->numOutputs)
+	outputs = xrealloc (pScrPriv->outputs, 
+			    (pScrPriv->numOutputs + 1) * sizeof (RROutputPtr));
+    else
+	outputs = xalloc (sizeof (RROutputPtr));
+    if (!outputs)
+	return FALSE;
+    output->pScreen = pScreen;
     pScrPriv->outputs = outputs;
     pScrPriv->outputs[pScrPriv->numOutputs++] = output;
     RROutputChanged (output);
-    return output;
+    return TRUE;
 }
-
+		      
 /*
  * Notify extension that output parameters have been changed
  */
diff --git a/randr/rrscreen.c b/randr/rrscreen.c
index 705e7d7..d47e9d6 100644
--- a/randr/rrscreen.c
+++ b/randr/rrscreen.c
@@ -360,6 +360,13 @@ ProcRRGetScreenResources (ClientPtr clie
     }
     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;
@@ -367,15 +374,15 @@ ProcRRGetScreenResources (ClientPtr clie
 	rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
 	rep.nCrtcs = pScrPriv->numCrtcs;
 	rep.nOutputs = pScrPriv->numOutputs;
-	rep.nModes = pScrPriv->numModes;;
+	rep.nModes = num_modes;
 	rep.nbytesNames = 0;
 
-	for (i = 0; i < pScrPriv->numModes; i++)
-	    rep.nbytesNames += pScrPriv->modes[i]->mode.nameLength;
+	for (i = 0; i < num_modes; i++)
+	    rep.nbytesNames += modes[i]->mode.nameLength;
 
 	rep.length = (pScrPriv->numCrtcs + 
 		      pScrPriv->numOutputs + 
-		      pScrPriv->numModes * (SIZEOF(xRRModeInfo) >> 2) +
+		      num_modes * (SIZEOF(xRRModeInfo) >> 2) +
 		      ((rep.nbytesNames + 3) >> 2));
 	
 	extraLen = rep.length << 2;
@@ -383,7 +390,10 @@ ProcRRGetScreenResources (ClientPtr clie
 	{
 	    extra = xalloc (extraLen);
 	    if (!extra)
+	    {
+		xfree (modes);
 		return BadAlloc;
+	    }
 	}
 	else
 	    extra = NULL;
@@ -391,7 +401,7 @@ ProcRRGetScreenResources (ClientPtr clie
 	crtcs = (RRCrtc *) extra;
 	outputs = (RROutput *) (crtcs + pScrPriv->numCrtcs);
 	modeinfos = (xRRModeInfo *) (outputs + pScrPriv->numOutputs);
-	names = (CARD8 *) (modeinfos + pScrPriv->numModes);
+	names = (CARD8 *) (modeinfos + num_modes);
 	
 	for (i = 0; i < pScrPriv->numCrtcs; i++)
 	{
@@ -407,9 +417,10 @@ ProcRRGetScreenResources (ClientPtr clie
 		swapl (&outputs[i], n);
 	}
 	
-	for (i = 0; i < pScrPriv->numModes; i++)
+	for (i = 0; i < num_modes; i++)
 	{
-	    modeinfos[i] = pScrPriv->modes[i]->mode;
+	    RRModePtr	mode = modes[i];
+	    modeinfos[i] = mode->mode;
 	    if (client->swapped)
 	    {
 		swapl (&modeinfos[i].id, n);
@@ -426,10 +437,11 @@ ProcRRGetScreenResources (ClientPtr clie
 		swaps (&modeinfos[i].nameLength, n);
 		swapl (&modeinfos[i].modeFlags, n);
 	    }
-	    memcpy (names, pScrPriv->modes[i]->name, 
-		    pScrPriv->modes[i]->mode.nameLength);
-	    names += pScrPriv->modes[i]->mode.nameLength;
+	    memcpy (names, mode->name, 
+		    mode->mode.nameLength);
+	    names += mode->mode.nameLength;
 	}
+    	xfree (modes);
 	assert (((((char *) names - (char *) extra) + 3) >> 2) == rep.length);
     }
     
diff-tree 45621bd215ad905e39559154d1d3dfada92e1798 (from 354603f509ae5db9301bfeec40bed1dda8c3bc09)
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Nov 3 16:36:34 2006 -0800

    Don't bump the refcnt if the new mode is NULL.

diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index c40dac1..76d0b6b 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -174,7 +174,8 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
 	if (crtc->mode)
 	    RRModeDestroy (crtc->mode);
 	crtc->mode = mode;
-	mode->refcnt++;
+	if (mode != NULL)
+	    mode->refcnt++;
 	RRCrtcChanged (crtc, TRUE);
     }
     if (x != crtc->x)
diff-tree 354603f509ae5db9301bfeec40bed1dda8c3bc09 (from 368cf03d33b3d99a0b704e38d144c322cf5d791e)
Author: Keith Packard <keithp at mandolin.keithp.com>
Date:   Wed Nov 1 00:29:46 2006 -0800

    Move physical size from mode to output.
    
    Modes can be shared across different sized monitors this way.
    
    Also caught some missing byteswapping and an incorrect return type.

diff --git a/randr/mirandr.c b/randr/mirandr.c
index 8d79e8a..11c2991 100644
--- a/randr/mirandr.c
+++ b/randr/mirandr.c
@@ -111,8 +111,6 @@ miRandRInit (ScreenPtr pScreen)
     memset (&modeInfo, '\0', sizeof (modeInfo));
     modeInfo.width = pScreen->width;
     modeInfo.height = pScreen->height;
-    modeInfo.mmWidth = pScreen->mmWidth;
-    modeInfo.mmHeight = pScreen->mmHeight;
     modeInfo.nameLength = strlen (name);
     
     mode = RRModeGet (pScreen, &modeInfo, name);
diff --git a/randr/randrstr.h b/randr/randrstr.h
index a8a9950..60877a3 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -107,6 +107,8 @@ struct _rrOutput {
     int		    nameLength;
     CARD8	    connection;
     CARD8	    subpixelOrder;
+    int		    mmWidth;
+    int		    mmHeight;
     RRCrtcPtr	    crtc;
     CARD32	    currentOptions;
     CARD32	    possibleOptions;
@@ -642,6 +644,11 @@ Bool
 RROutputSetCurrentOptions (RROutputPtr output,
 			   CARD32      currentOptions);
 
+Bool
+RROutputSetPhysicalSize (RROutputPtr	output,
+			 int		mmWidth,
+			 int		mmHeight);
+
 void
 RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output);
 
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index ee51cc2..c40dac1 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -270,8 +270,16 @@ RRCrtcSet (RRCrtcPtr    crtc,
 
 	size.width = mode->mode.width;
 	size.height = mode->mode.height;
-	size.mmWidth = mode->mode.mmWidth;
-	size.mmHeight = mode->mode.mmHeight;
+	if (outputs[0].output->mmWidth && outputs[0].output->mmHeight)
+	{
+	    size.mmWidth = outputs[0].output->mmWidth;
+	    size.mmHeight = outputs[0].output->mmHeight;
+	}
+	else
+	{
+	    size.mmWidth = pScreen->mmWidth;
+	    size.mmHeight = pScreen->mmHeight;
+	}
 	size.nRates = 1;
 	rate.rate = RRVerticalRefresh (&mode->mode);
 	size.pRates = &rate;
diff --git a/randr/rrinfo.c b/randr/rrinfo.c
index 6fd4ee5..e92caad 100644
--- a/randr/rrinfo.c
+++ b/randr/rrinfo.c
@@ -39,8 +39,6 @@ RROldModeAdd (RROutputPtr output, RRScre
     
     modeInfo.width = size->width;
     modeInfo.height = size->height;
-    modeInfo.mmWidth = size->mmWidth;
-    modeInfo.mmHeight = size->mmHeight;
     modeInfo.hTotal = size->width;
     modeInfo.vTotal = size->height;
     modeInfo.dotClock = ((CARD32) size->width * (CARD32) size->height *
diff --git a/randr/rrmode.c b/randr/rrmode.c
index 07cd0c1..fb4b5eb 100644
--- a/randr/rrmode.c
+++ b/randr/rrmode.c
@@ -29,8 +29,6 @@ RRModeEqual (xRRModeInfo *a, xRRModeInfo
 {
     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;
     if (a->dotClock != b->dotClock) return FALSE;
     if (a->hSyncStart != b->hSyncStart) return FALSE;
     if (a->hSyncEnd != b->hSyncEnd) return FALSE;
diff --git a/randr/rroutput.c b/randr/rroutput.c
index fc84ec1..1f6f330 100644
--- a/randr/rroutput.c
+++ b/randr/rroutput.c
@@ -72,6 +72,8 @@ RROutputCreate (ScreenPtr   pScreen,
     output->name[nameLength] = '\0';
     output->connection = RR_UnknownConnection;
     output->subpixelOrder = SubPixelUnknown;
+    output->mmWidth = 0;
+    output->mmHeight = 0;
     output->crtc = NULL;
     output->currentOptions = 0;
     output->possibleOptions = 0;
@@ -262,6 +264,20 @@ RROutputSetCurrentOptions (RROutputPtr o
     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);
+    return TRUE;
+}
+
+
 void
 RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output)
 {
@@ -381,6 +397,8 @@ ProcRRGetOutputInfo (ClientPtr client)
     rep.timestamp = pScrPriv->lastSetTime.milliseconds;
     rep.crtc = output->crtc ? output->crtc->id : None;
     rep.currentOptions = output->currentOptions;
+    rep.mmWidth = output->mmWidth;
+    rep.mmHeight = output->mmHeight;
     rep.connection = output->connection;
     rep.subpixelOrder = output->subpixelOrder;
     rep.nCrtcs = output->numCrtcs;
@@ -434,10 +452,15 @@ ProcRRGetOutputInfo (ClientPtr client)
 	swapl(&rep.length, n);
 	swapl(&rep.timestamp, n);
 	swapl(&rep.crtc, n);
+	swapl(&rep.currentOptions, n);
+	swapl(&rep.mmWidth, n);
+	swapl(&rep.mmHeight, n);
 	swaps(&rep.nCrtcs, n);
 	swaps(&rep.nModes, n);
 	swaps(&rep.nClones, n);
+	swapl(&rep.possibleOptions, n);
 	swaps(&rep.nameLength, n);
+	swapl(&rep.possibleOptions, n);
     }
     WriteToClient(client, sizeof(xRRGetOutputInfoReply), (char *)&rep);
     if (extraLen)
diff --git a/randr/rrpointer.c b/randr/rrpointer.c
index 7ba0460..c092e49 100644
--- a/randr/rrpointer.c
+++ b/randr/rrpointer.c
@@ -131,7 +131,7 @@ RRPointerScreenConfigured (ScreenPtr pSc
     int		x, y;
 
     if (pScreen != pCurrentScreen)
-	return FALSE;
+	return;
     GetSpritePosition (&x, &y);
     RRPointerToNearestCrtc (pScreen, x, y, NULL);
 }
diff --git a/randr/rrscreen.c b/randr/rrscreen.c
index b4d3618..705e7d7 100644
--- a/randr/rrscreen.c
+++ b/randr/rrscreen.c
@@ -126,8 +126,8 @@ RRDeliverScreenEvent (ClientPtr client, 
 	    }
 	se.widthInPixels = mode->mode.width;
 	se.heightInPixels = mode->mode.height;
-	se.widthInMillimeters = mode->mode.mmWidth;
-	se.heightInMillimeters = mode->mode.mmHeight;
+	se.widthInMillimeters = pScreen->mmWidth;
+	se.heightInMillimeters = pScreen->mmHeight;
     }
     else
     {
@@ -415,8 +415,6 @@ ProcRRGetScreenResources (ClientPtr clie
 		swapl (&modeinfos[i].id, n);
 		swaps (&modeinfos[i].width, n);
 		swaps (&modeinfos[i].height, n);
-		swapl (&modeinfos[i].mmWidth, n);
-		swapl (&modeinfos[i].mmHeight, n);
 		swapl (&modeinfos[i].dotClock, n);
 		swaps (&modeinfos[i].hSyncStart, n);
 		swaps (&modeinfos[i].hSyncEnd, n);
@@ -501,8 +499,13 @@ RR10GetData (ScreenPtr pScreen, RROutput
 	    size[j].id = j;
 	    size[j].width = mode->mode.width;
 	    size[j].height = mode->mode.height;
-	    size[j].mmWidth = mode->mode.mmWidth;
-	    size[j].mmHeight = mode->mode.mmHeight;
+	    if (output->mmWidth && output->mmHeight) {
+		size[j].mmWidth = output->mmWidth;
+		size[j].mmHeight = output->mmHeight;
+	    } else {
+		size[j].mmWidth = pScreen->mmWidth;
+		size[j].mmHeight = pScreen->mmHeight;
+	    }
 	    size[j].nRates = 0;
 	    size[j].pRates = &refresh[data->nrefresh];
 	    data->nsize++;
diff-tree 368cf03d33b3d99a0b704e38d144c322cf5d791e (from a153871447393018b96c362282018a3e73fa84e4)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Wed Oct 25 09:48:23 2006 -0700

    Merge master back in and clean up some unfinished code (closes 8745)

diff --git a/randr/mirandr.c b/randr/mirandr.c
index fab0fd1..8d79e8a 100644
--- a/randr/mirandr.c
+++ b/randr/mirandr.c
@@ -57,6 +57,21 @@ miRRCrtcSet (ScreenPtr	pScreen,
     return TRUE;
 }
 
+static Bool
+miRRCrtcSetGamma (ScreenPtr	pScreen,
+		  RRCrtcPtr	crtc)
+{
+    return TRUE;
+}
+
+static Bool
+miRROutputSetProperty (ScreenPtr	pScreen,
+		       RROutputPtr	output,
+		       Atom	property)
+{
+    return TRUE;
+}
+
 /*
  * This function assumes that only a single depth can be
  * displayed at a time, but that all visuals of that depth
@@ -85,7 +100,7 @@ miRandRInit (ScreenPtr pScreen)
 #if RANDR_12_INTERFACE
     pScrPriv->rrCrtcSet = miRRCrtcSet;
     pScrPriv->rrCrtcSetGamma = miRRCrtcSetGamma;
-    pScrPriv->rrOutputSetProperty = miRROutput
+    pScrPriv->rrOutputSetProperty = miRROutputSetProperty;
     
     
     RRScreenSetSizeRange (pScreen,
diff --git a/randr/randr.c b/randr/randr.c
index b422efe..7b39e80 100644
--- a/randr/randr.c
+++ b/randr/randr.c
@@ -42,9 +42,6 @@
 int	RRGeneration;
 int	RRNScreens;
 
-static int ProcRRDispatch (ClientPtr pClient);
-static int SProcRRDispatch (ClientPtr pClient);
-
 #define wrap(priv,real,mem,func) {\
     priv->mem = real->mem; \
     real->mem = func; \
@@ -54,6 +51,9 @@ static int SProcRRDispatch (ClientPtr pC
     real->mem = priv->mem; \
 }
 
+static int ProcRRDispatch (ClientPtr pClient);
+static int SProcRRDispatch (ClientPtr pClient);
+
 int	RREventBase;
 int	RRErrorBase;
 RESTYPE RRClientType, RREventType; /* resource types for event masks */
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index c662899..ee51cc2 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -280,7 +280,7 @@ RRCrtcSet (RRCrtcPtr    crtc,
 	 * Old 1.0 interface tied screen size to mode size
 	 */
 	if (ret)
-	    RRCrtcNotify (crtc, mode, x, y, rotation, 
+	    RRCrtcNotify (crtc, mode, x, y, rotation, 1, &outputs[0].output);
 	return ret;
     }
 #endif
diff --git a/randr/rrscreen.c b/randr/rrscreen.c
index 6d38e96..b4d3618 100644
--- a/randr/rrscreen.c
+++ b/randr/rrscreen.c
@@ -164,7 +164,7 @@ RRScreenSizeNotify (ScreenPtr	pScreen)
     pScrPriv->width = pScreen->width;
     pScrPriv->height = pScreen->height;
     pScrPriv->changed = TRUE;
-    pScrPriv->sizeChanged = TRUE;
+/*    pScrPriv->sizeChanged = TRUE; */
 
     RRTellChanged (pScreen);
     RRSendConfigNotify (pScreen);
@@ -850,7 +850,7 @@ ProcRRSetScreenConfig (ClientPtr client)
 
 	for (c = 0; c < pScrPriv->numCrtcs; c++)
 	{
-	    rep.status = RRCrtcSet (pScrPriv->->crtc, NULL, 0, 0, RR_Rotate_0,
+	    rep.status = RRCrtcSet (pScrPriv->crtcs[c], NULL, 0, 0, RR_Rotate_0,
 				    0, NULL);
 	    if (rep.status != Success)
 		goto sendReply;
@@ -858,7 +858,7 @@ ProcRRSetScreenConfig (ClientPtr client)
 	if (!RRScreenSizeSet (pScreen, mode->mode.width, mode->mode.height,
 			      pScreen->mmWidth, pScreen->mmHeight))
 	{
-	    rep.status  RRSetConfigFailed;
+	    rep.status = RRSetConfigFailed;
 	    goto sendReply;
 	}
     }
diff --git a/randr/rrxinerama.c b/randr/rrxinerama.c
index 31f60cc..a8e4b39 100644
--- a/randr/rrxinerama.c
+++ b/randr/rrxinerama.c
@@ -259,6 +259,9 @@ ProcRRXineramaQueryScreens(ClientPtr cli
 
     REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
 
+    if (RRXineramaScreenActive (pScreen))
+	RRGetInfo (pScreen);
+    
     rep.type = X_Reply;
     rep.sequenceNumber = client->sequence;
     rep.number = RRXineramaScreenCount (pScreen);
diff-tree a153871447393018b96c362282018a3e73fa84e4 (from 39ecb2b10906779edee378ebf834cf84fb282885)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Tue Oct 24 17:23:02 2006 -0700

    Byte swap RRSelectInput enable flags.

diff --git a/randr/rrsdispatch.c b/randr/rrsdispatch.c
index bf81f8b..67af753 100644
--- a/randr/rrsdispatch.c
+++ b/randr/rrsdispatch.c
@@ -77,6 +77,7 @@ SProcRRSelectInput (ClientPtr client)
 
     swaps(&stuff->length, n);
     swapl(&stuff->window, n);
+    swaps(&stuff->enable, n);
     return (*ProcRandrVector[stuff->randrReqType]) (client);
 }
 
diff-tree 39ecb2b10906779edee378ebf834cf84fb282885 (from a9fb37ffde70b8d78bba6f76882ad3b6515320ce)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Fri Oct 13 17:34:53 2006 -0700

    Limit pointer to valid crtc areas. Add event swapping. Fix change tracking.
    
    Add function to keep pointer within valid crtc areas.
    Finish event delivery and swapping code.
    Separate configuration from layout changes to send correct events.

diff --git a/randr/Makefile.am b/randr/Makefile.am
index 91c4bc6..9bf0e65 100644
--- a/randr/Makefile.am
+++ b/randr/Makefile.am
@@ -15,6 +15,7 @@ librandr_la_SOURCES =	\
 	rrinfo.c	\
 	rrmode.c	\
 	rroutput.c	\
+	rrpointer.c	\
 	rrproperty.c	\
 	rrscreen.c	\
 	rrsdispatch.c	\
diff --git a/randr/mirandr.c b/randr/mirandr.c
index 918e55d..fab0fd1 100644
--- a/randr/mirandr.c
+++ b/randr/mirandr.c
@@ -84,6 +84,9 @@ miRandRInit (ScreenPtr pScreen)
     pScrPriv->rrGetInfo = miRRGetInfo;
 #if RANDR_12_INTERFACE
     pScrPriv->rrCrtcSet = miRRCrtcSet;
+    pScrPriv->rrCrtcSetGamma = miRRCrtcSetGamma;
+    pScrPriv->rrOutputSetProperty = miRROutput
+    
     
     RRScreenSetSizeRange (pScreen,
 			  pScreen->width, pScreen->height,
diff --git a/randr/randr.c b/randr/randr.c
index 35f9a4c..b422efe 100644
--- a/randr/randr.c
+++ b/randr/randr.c
@@ -130,38 +130,71 @@ SRRScreenChangeNotifyEvent(xRRScreenChan
     cpswaps(from->subpixelOrder, to->subpixelOrder);
 }
 
-#if 0
 static void
-SRRMonitorChangeNotifyEvent(xRRMonitorChangeNotifyEvent *from,
-			    xRRMonitorChangeNotifyEvent *to)
+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->configTimestamp, to->configTimestamp);
-    cpswapl(from->root, to->root);
     cpswapl(from->window, to->window);
-    cpswaps(from->monitor, to->monitor);
-    cpswaps(from->modeID, to->modeID);
+    cpswapl(from->crtc, to->crtc);
+    cpswapl(from->mode, to->mode);
+    cpswapl(from->window, to->window);
     cpswaps(from->rotation, to->rotation);
-    cpswaps(from->subpixelOrder, to->subpixelOrder);
     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);
 }
-#endif
 
 static void
 SRRNotifyEvent (xEvent *from,
 		xEvent *to)
 {
     switch (from->u.u.detail) {
-#if 0
-    case RRNotify_MonitorChange:
-	SRRMonitorChangeNotifyEvent ((xRRMonitorChangeNotifyEvent *) from,
-				     (xRRMonitorChangeNotifyEvent *) to);
+    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;
-#endif
     default:
 	break;
     }
@@ -359,6 +392,9 @@ TellChanged (WindowPtr pWin, pointer val
     return WT_WALKCHILDREN;
 }
 
+/*
+ * Something changed; send events and adjust pointer position
+ */
 void
 RRTellChanged (ScreenPtr pScreen)
 {
@@ -369,12 +405,18 @@ RRTellChanged (ScreenPtr pScreen)
     {
 	UpdateCurrentTime ();
 	pScrPriv->lastConfigTime = currentTime;
-	WalkTree (pScreen, TellChanged, (pointer) pScreen);
 	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)
+	{
+	    pScrPriv->layoutChanged = FALSE;
+	    RRPointerScreenConfigured (pScreen);
+	    RRSendConfigNotify (pScreen);
+	}
     }
 }
 
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 6690556..a8a9950 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -202,10 +202,11 @@ typedef struct _rrScrPriv {
     TimeStamp		    lastSetTime;	/* last changed by client */
     TimeStamp		    lastConfigTime;	/* possible configs changed */
     RRCloseScreenProcPtr    CloseScreen;
-    Bool		    changed;
+    Bool		    changed;		/* some config changed */
     CARD16		    minWidth, minHeight;
     CARD16		    maxWidth, maxHeight;
     CARD16		    width, height;	/* last known screen size */
+    Bool		    layoutChanged;	/* screen layout changed */
 
     /* modes, outputs and crtcs */
     int			    numModes;
@@ -217,6 +218,9 @@ typedef struct _rrScrPriv {
     int			    numCrtcs;
     RRCrtcPtr		    *crtcs;
 
+    /* Last known pointer position */
+    RRCrtcPtr		    pointerCrtc;
+
 #ifdef RANDR_10_INTERFACE
     /*
      * Configuration information
@@ -439,6 +443,14 @@ RRSetScreenConfig (ScreenPtr		pScreen,
 #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
  */
@@ -575,6 +587,13 @@ int
 ProcRRDeleteOutputMode (ClientPtr client);
 
 /* rroutput.c */
+
+/*
+ * Notify the output of some change
+ */
+void
+RROutputChanged (RROutputPtr output);
+
 /*
  * Create an output
  */
@@ -638,6 +657,13 @@ ProcRRGetOutputInfo (ClientPtr client);
 Bool
 RROutputInit (void);
     
+/* rrpointer.c */
+void
+RRPointerMoved (ScreenPtr pScreen, int x, int y);
+
+void
+RRPointerScreenConfigured (ScreenPtr pScreen);
+
 /* rrproperty.c */
 
 void
@@ -668,3 +694,79 @@ 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
+		RROutputSetCrtc
+		RROutputSetPossibleOptions
+		RRSetCurrentOptions
+		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
+		RROutputSetCrtc
+		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
index baefd3a..c662899 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -26,6 +26,24 @@
 RESTYPE	RRCrtcType;
 
 /*
+ * Notify the CRTC of some change
+ */
+void
+RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged)
+{
+    ScreenPtr	pScreen = crtc->pScreen;
+    rrScrPriv(pScreen);
+
+    crtc->changed = TRUE;
+    pScrPriv->changed = TRUE;
+    /*
+     * Send ConfigureNotify on any layout change
+     */
+    if (layoutChanged)
+	pScrPriv->layoutChanged = TRUE;
+}
+
+/*
  * Create a CRTC
  */
 RRCrtcPtr
@@ -60,7 +78,7 @@ RRCrtcCreate (ScreenPtr	pScreen,
     crtc->numOutputs = 0;
     crtc->gammaSize = 0;
     crtc->gammaRed = crtc->gammaBlue = crtc->gammaGreen = NULL;
-    crtc->changed = TRUE;
+    crtc->changed = FALSE;
     crtc->devPrivate = devPrivate;
 
     if (!AddResource (crtc->id, RRCrtcType, (pointer) crtc))
@@ -68,7 +86,8 @@ RRCrtcCreate (ScreenPtr	pScreen,
 
     pScrPriv->crtcs = crtcs;
     pScrPriv->crtcs[pScrPriv->numCrtcs++] = crtc;
-    pScrPriv->changed = TRUE;
+
+    RRCrtcChanged (crtc, TRUE);
     return crtc;
 }
 
@@ -85,8 +104,6 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
 	      int	    numOutputs,
 	      RROutputPtr   *outputs)
 {
-    ScreenPtr	pScreen = crtc->pScreen;
-    rrScrPriv(pScreen);
     int	    i, j;
     
     /*
@@ -100,8 +117,8 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
 		break;
 	if (j == crtc->numOutputs)
 	{
-	    outputs[i]->changed = TRUE;
-	    crtc->changed = TRUE;
+	    RROutputChanged (outputs[i]);
+	    RRCrtcChanged (crtc, FALSE);
 	}
     }
     /*
@@ -115,8 +132,8 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
 		break;
 	if (i == numOutputs)
 	{
-	    crtc->outputs[j]->changed = TRUE;
-	    crtc->changed = TRUE;
+	    RROutputChanged (crtc->outputs[j]);
+	    RRCrtcChanged (crtc, FALSE);
 	}
     }
     /*
@@ -158,31 +175,22 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
 	    RRModeDestroy (crtc->mode);
 	crtc->mode = mode;
 	mode->refcnt++;
-	crtc->changed = TRUE;
+	RRCrtcChanged (crtc, TRUE);
     }
     if (x != crtc->x)
     {
 	crtc->x = x;
-	crtc->changed = TRUE;
+	RRCrtcChanged (crtc, TRUE);
     }
     if (y != crtc->y)
     {
 	crtc->y = y;
-	crtc->changed = TRUE;
+	RRCrtcChanged (crtc, TRUE);
     }
     if (rotation != crtc->rotation)
     {
 	crtc->rotation = rotation;
-	crtc->changed = TRUE;
-    }
-    /*
-     * Send events if anything changed
-     */
-    if (crtc->changed)
-    {
-	if (!pScrPriv->changed)
-	    RRSendConfigNotify (pScreen);
-	pScrPriv->changed = TRUE;
+	RRCrtcChanged (crtc, TRUE);
     }
     return TRUE;
 }
@@ -272,10 +280,11 @@ RRCrtcSet (RRCrtcPtr    crtc,
 	 * Old 1.0 interface tied screen size to mode size
 	 */
 	if (ret)
-	    RRScreenSizeNotify (pScreen);
+	    RRCrtcNotify (crtc, mode, x, y, rotation, 
 	return ret;
     }
 #endif
+    RRTellChanged (pScreen);
     return FALSE;
 }
 
diff --git a/randr/rroutput.c b/randr/rroutput.c
index 618ef1f..fc84ec1 100644
--- a/randr/rroutput.c
+++ b/randr/rroutput.c
@@ -25,6 +25,19 @@
 RESTYPE	RROutputType;
 
 /*
+ * Notify the output of some change
+ */
+void
+RROutputChanged (RROutputPtr output)
+{
+    ScreenPtr	pScreen = output->pScreen;
+    rrScrPriv (pScreen);
+
+    output->changed = TRUE;
+    pScrPriv->changed = TRUE;
+}
+
+/*
  * Create an output
  */
 
@@ -70,7 +83,7 @@ RROutputCreate (ScreenPtr   pScreen,
     output->numPreferred = 0;
     output->modes = NULL;
     output->properties = NULL;
-    output->changed = TRUE;
+    output->changed = FALSE;
     output->devPrivate = devPrivate;
     
     if (!AddResource (output->id, RROutputType, (pointer) output))
@@ -78,7 +91,7 @@ RROutputCreate (ScreenPtr   pScreen,
 
     pScrPriv->outputs = outputs;
     pScrPriv->outputs[pScrPriv->numOutputs++] = output;
-    pScrPriv->changed = TRUE;
+    RROutputChanged (output);
     return output;
 }
 
@@ -114,7 +127,7 @@ RROutputSetClones (RROutputPtr  output,
     memcpy (newClones, clones, numClones * sizeof (RROutputPtr));
     output->clones = newClones;
     output->numClones = numClones;
-    output->changed = TRUE;
+    RROutputChanged (output);
     return TRUE;
 }
 
@@ -158,7 +171,7 @@ RROutputSetModes (RROutputPtr	output,
     output->modes = newModes;
     output->numModes = numModes;
     output->numPreferred = numPreferred;
-    output->changed = TRUE;
+    RROutputChanged (output);
     return TRUE;
 }
 
@@ -191,7 +204,7 @@ RROutputSetCrtcs (RROutputPtr	output,
     memcpy (newCrtcs, crtcs, numCrtcs * sizeof (RRCrtcPtr));
     output->crtcs = newCrtcs;
     output->numCrtcs = numCrtcs;
-    output->changed = TRUE;
+    RROutputChanged (output);
     return TRUE;
 }
 
@@ -202,7 +215,7 @@ RROutputSetPossibleOptions (RROutputPtr	
     if (output->possibleOptions == possibleOptions)
 	return TRUE;
     output->possibleOptions = possibleOptions;
-    output->changed = TRUE;
+    RROutputChanged (output);
     return TRUE;
 }
 
@@ -212,7 +225,7 @@ RROutputSetCrtc (RROutputPtr output, RRC
     if (output->crtc == crtc)
 	return;
     output->crtc = crtc;
-    output->changed = TRUE;
+    RROutputChanged (output);
 }
 
 Bool
@@ -222,7 +235,7 @@ RROutputSetConnection (RROutputPtr  outp
     if (output->connection == connection)
 	return TRUE;
     output->connection = connection;
-    output->changed = TRUE;
+    RROutputChanged (output);
     return TRUE;
 }
 
@@ -234,7 +247,7 @@ RROutputSetSubpixelOrder (RROutputPtr ou
 	return TRUE;
 
     output->subpixelOrder = subpixelOrder;
-    output->changed = TRUE;
+    RROutputChanged (output);
     return TRUE;
 }
 
@@ -245,13 +258,41 @@ RROutputSetCurrentOptions (RROutputPtr o
     if (output->currentOptions == currentOptions)
 	return TRUE;
     output->currentOptions = currentOptions;
-    output->changed = TRUE;
+    RROutputChanged (output);
     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);
 }
 
 /*
diff --git a/randr/rrpointer.c b/randr/rrpointer.c
new file mode 100644
index 0000000..7ba0460
--- /dev/null
+++ b/randr/rrpointer.c
@@ -0,0 +1,137 @@
+/*
+ * 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;
+    
+    if (!mode)
+	return FALSE;
+    if (crtc->x <= x && x < crtc->x + mode->mode.width &&
+	crtc->y <= y && y < crtc->y + mode->mode.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;
+
+	if (!mode)
+	    continue;
+	if (crtc == skip)
+	    continue;
+	if (x < crtc->x)
+	    dx = crtc->x - x;
+	else if (x > crtc->x + mode->mode.width)
+	    dx = x - (crtc->x + mode->mode.width);
+	else
+	    dx = 0;
+	if (y < crtc->y)
+	    dy = crtc->y - x;
+	else if (y > crtc->y + mode->mode.height)
+	    dy = y - (crtc->y + mode->mode.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 FALSE;
+    GetSpritePosition (&x, &y);
+    RRPointerToNearestCrtc (pScreen, x, y, NULL);
+}
diff --git a/randr/rrproperty.c b/randr/rrproperty.c
index cdafb5c..44f1f0a 100644
--- a/randr/rrproperty.c
+++ b/randr/rrproperty.c
@@ -27,6 +27,7 @@
 static void
 RRDeliverEvent (ScreenPtr pScreen, xEvent *event, CARD32 mask)
 {
+    
 }
 
 void
diff --git a/randr/rrscreen.c b/randr/rrscreen.c
index 7b53f04..6d38e96 100644
--- a/randr/rrscreen.c
+++ b/randr/rrscreen.c
@@ -164,10 +164,13 @@ RRScreenSizeNotify (ScreenPtr	pScreen)
     pScrPriv->width = pScreen->width;
     pScrPriv->height = pScreen->height;
     pScrPriv->changed = TRUE;
+    pScrPriv->sizeChanged = TRUE;
 
+    RRTellChanged (pScreen);
     RRSendConfigNotify (pScreen);
     RREditConnectionInfo (pScreen);
     
+    RRPointerScreenConfigured (pScreen);
     /*
      * Fix pointer bounds and location
      */
@@ -836,9 +839,37 @@ ProcRRSetScreenConfig (ClientPtr client)
 	goto sendReply;
     }
 
+    /*
+     * If the screen size is changing, adjust all of the other outputs
+     * to fit the new size, mirroring as much as possible
+     */
+    if (mode->mode.width != pScreen->width || 
+	mode->mode.height != pScreen->height)
+    {
+	int	c;
+
+	for (c = 0; c < pScrPriv->numCrtcs; c++)
+	{
+	    rep.status = RRCrtcSet (pScrPriv->->crtc, NULL, 0, 0, RR_Rotate_0,
+				    0, NULL);
+	    if (rep.status != Success)
+		goto sendReply;
+	}
+	if (!RRScreenSizeSet (pScreen, mode->mode.width, mode->mode.height,
+			      pScreen->mmWidth, pScreen->mmHeight))
+	{
+	    rep.status  RRSetConfigFailed;
+	    goto sendReply;
+	}
+    }
+    
     rep.status = RRCrtcSet (output.output->crtc, mode, 0, 0, stuff->rotation,
 			    1, &output);
     
+    /*
+     * XXX Configure other crtcs to mirror as much as possible
+     */
+    
 sendReply:
     
     if (pData)
diff-tree a9fb37ffde70b8d78bba6f76882ad3b6515320ce (from 0f37ee35a8edb8de442e4de050607f041f39d7a5)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Thu Oct 5 22:31:35 2006 -0700

    Add preferred modes for each output. Round vrefresh. Deliver crtc events.

diff --git a/randr/mirandr.c b/randr/mirandr.c
index 7300cfe..918e55d 100644
--- a/randr/mirandr.c
+++ b/randr/mirandr.c
@@ -110,7 +110,7 @@ miRandRInit (ScreenPtr pScreen)
 	return FALSE;
     if (!RROutputSetClones (output, NULL, 0))
 	return FALSE;
-    if (!RROutputSetModes (output, &mode, 1))
+    if (!RROutputSetModes (output, &mode, 1, 0))
 	return FALSE;
     if (!RROutputSetCrtcs (output, &crtc, 1))
 	return FALSE;
diff --git a/randr/randr.c b/randr/randr.c
index 4ea72e5..35f9a4c 100644
--- a/randr/randr.c
+++ b/randr/randr.c
@@ -406,9 +406,10 @@ CARD16
 RRVerticalRefresh (xRRModeInfo *mode)
 {
     CARD32  refresh;
-    if (!mode->hTotal || !mode->vTotal)
+    CARD32  dots = mode->hTotal * mode->vTotal;
+    if (!dots)
 	return 0;
-    refresh = mode->dotClock / (mode->hTotal * mode->vTotal);
+    refresh = (mode->dotClock + dots/2) / dots;
     if (refresh > 0xffff)
 	refresh = 0xffff;
     return (CARD16) refresh;
diff --git a/randr/randrstr.h b/randr/randrstr.h
index a4e5589..6690556 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -80,6 +80,7 @@ struct _rrMode {
     char	    *name;
     void	    *devPrivate;
     ScreenPtr	    screen;
+    Bool	    userDefined;
 };
 
 struct _rrCrtc {
@@ -114,6 +115,7 @@ struct _rrOutput {
     int		    numClones;
     RROutputPtr	    *clones;
     int		    numModes;
+    int		    numPreferred;
     RRModePtr	    *modes;
     Bool	    changed;
     PropertyPtr	    properties;
@@ -144,6 +146,10 @@ typedef Bool (*RRCrtcSetProcPtr) (Screen
 typedef Bool (*RRCrtcSetGammaProcPtr) (ScreenPtr	pScreen,
 				       RRCrtcPtr	crtc);
 
+typedef Bool (*RROutputSetPropertyProcPtr) (ScreenPtr	pScreen,
+					    RROutputPtr	output,
+					    Atom	property);
+
 #endif
 
 typedef Bool (*RRGetInfoProcPtr) (ScreenPtr pScreen, Rotation *rotations);
@@ -187,6 +193,7 @@ typedef struct _rrScrPriv {
     RRScreenSetSizeProcPtr  rrScreenSetSize;
     RRCrtcSetProcPtr	    rrCrtcSet;
     RRCrtcSetGammaProcPtr   rrCrtcSetGamma;
+    RROutputSetPropertyProcPtr	rrOutputSetProperty;
 #endif
     
     /*
@@ -589,7 +596,8 @@ RROutputSetClones (RROutputPtr  output,
 Bool
 RROutputSetModes (RROutputPtr	output,
 		  RRModePtr	*modes,
-		  int		numModes);
+		  int		numModes,
+		  int		numPreferred);
 
 Bool
 RROutputSetCrtcs (RROutputPtr	output,
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 3108f14..baefd3a 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -88,9 +88,41 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
     ScreenPtr	pScreen = crtc->pScreen;
     rrScrPriv(pScreen);
     int	    i, j;
-    int	    prevNumOutputs = crtc->numOutputs;
     
-    if (numOutputs != prevNumOutputs)
+    /*
+     * 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]->changed = TRUE;
+	    crtc->changed = TRUE;
+	}
+    }
+    /*
+     * 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)
+	{
+	    crtc->outputs[j]->changed = TRUE;
+	    crtc->changed = TRUE;
+	}
+    }
+    /*
+     * Reallocate the crtc output array if necessary
+     */
+    if (numOutputs != crtc->numOutputs)
     {
 	RROutputPtr *newoutputs;
 	
@@ -113,28 +145,13 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
 	crtc->outputs = newoutputs;
 	crtc->numOutputs = numOutputs;
     }
-    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]->changed = TRUE;
-	    crtc->changed = TRUE;
-	}
-    }
-    for (j = 0; j < crtc->numOutputs; j++)
-    {
-	for (i = 0; i < numOutputs; i++)
-	    if (outputs[i] == crtc->outputs[j])
-		break;
-	if (i != numOutputs)
-	{
-	    crtc->outputs[j]->changed = TRUE;
-	    crtc->changed = TRUE;
-	}
-    }
+    /*
+     * 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)
@@ -158,6 +175,9 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
 	crtc->rotation = rotation;
 	crtc->changed = TRUE;
     }
+    /*
+     * Send events if anything changed
+     */
     if (crtc->changed)
     {
 	if (!pScrPriv->changed)
@@ -170,7 +190,35 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
 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);
 }
 
 /*
@@ -381,7 +429,7 @@ ProcRRGetCrtcInfo (ClientPtr client)
     rep.y = crtc->y;
     rep.width = mode ? mode->mode.width : 0;
     rep.height = mode ? mode->mode.height : 0;
-    rep.mode = mode->mode.id;
+    rep.mode = mode ? mode->mode.id : 0;
     rep.rotation = crtc->rotation;
     rep.rotations = crtc->rotations;
     rep.nOutput = crtc->numOutputs;
@@ -572,30 +620,30 @@ ProcRRSetCrtcConfig (ClientPtr client)
 	goto sendReply;
     }
     
-    if (mode)
-    {
+    /*
+     * 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:
 	/*
-	 * Validate requested rotation
+	 * Invalid 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;
-	}
-    
+	client->errorValue = stuff->rotation;
+	if (outputs)
+	    xfree (outputs);
+	return BadValue;
+    }
+
+    if (mode)
+    {
 	if ((~crtc->rotations) & rotation)
 	{
 	    /*
diff --git a/randr/rrmode.c b/randr/rrmode.c
index 3a67486..07cd0c1 100644
--- a/randr/rrmode.c
+++ b/randr/rrmode.c
@@ -41,7 +41,6 @@ RRModeEqual (xRRModeInfo *a, xRRModeInfo
     if (a->vTotal != b->vTotal) return FALSE;
     if (a->nameLength != b->nameLength) return FALSE;
     if (a->modeFlags != b->modeFlags) return FALSE;
-    if (a->origin != b->origin) return FALSE;
     return TRUE;
 }
 
@@ -75,6 +74,7 @@ RRModeGet (ScreenPtr	pScreen,
     memcpy (mode->name, name, modeInfo->nameLength);
     mode->name[modeInfo->nameLength] = '\0';
     mode->screen = pScreen;
+    mode->userDefined = FALSE;
 
     if (pScrPriv->numModes)
 	modes = xrealloc (pScrPriv->modes,
@@ -162,7 +162,7 @@ RRModePruneUnused (ScreenPtr pScreen)
     memcpy (unused, pScrPriv->modes, num * sizeof (RRModePtr));
     for (m = 0; m < num; m++) {
 	mode = unused[m];
-	if (mode->refcnt == 1 && mode->mode.origin != RRModeOriginUser)
+	if (mode->refcnt == 1 && !mode->userDefined)
 	    FreeResource (mode->mode.id, 0);
     }
     xfree (unused);
diff --git a/randr/rroutput.c b/randr/rroutput.c
index b252d7d..618ef1f 100644
--- a/randr/rroutput.c
+++ b/randr/rroutput.c
@@ -67,6 +67,7 @@ RROutputCreate (ScreenPtr   pScreen,
     output->numClones = 0;
     output->clones = NULL;
     output->numModes = 0;
+    output->numPreferred = 0;
     output->modes = NULL;
     output->properties = NULL;
     output->changed = TRUE;
@@ -120,12 +121,13 @@ RROutputSetClones (RROutputPtr  output,
 Bool
 RROutputSetModes (RROutputPtr	output,
 		  RRModePtr	*modes,
-		  int		numModes)
+		  int		numModes,
+		  int		numPreferred)
 {
     RRModePtr	*newModes;
     int		i;
 
-    if (numModes == output->numModes)
+    if (numModes == output->numModes && numPreferred == output->numPreferred)
     {
 	for (i = 0; i < numModes; i++)
 	    if (output->modes[i] != modes[i])
@@ -155,6 +157,7 @@ RROutputSetModes (RROutputPtr	output,
     memcpy (newModes, modes, numModes * sizeof (RRModePtr));
     output->modes = newModes;
     output->numModes = numModes;
+    output->numPreferred = numPreferred;
     output->changed = TRUE;
     return TRUE;
 }
@@ -341,10 +344,10 @@ ProcRRGetOutputInfo (ClientPtr client)
     rep.subpixelOrder = output->subpixelOrder;
     rep.nCrtcs = output->numCrtcs;
     rep.nModes = output->numModes;
+    rep.nPreferred = output->numPreferred;
     rep.nClones = output->numClones;
     rep.nameLength = output->nameLength;
     rep.possibleOptions = output->possibleOptions;
-    rep.pad1 = 42;
     
     extraLen = ((output->numCrtcs + 
 		 output->numModes + 
diff-tree 0f37ee35a8edb8de442e4de050607f041f39d7a5 (from f7dcf3a6d482d4934ff7ba33826adf725103470b)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Tue Oct 3 21:06:11 2006 -0700

    Add mode origins and output options. Fix memmoves in resource free funcs.
    
    Output options and mode origins both affected driver ABI.  memmove mistakes
    were causing 'Freeing resource which isn't there' messages.
    
    Prune unused non-user defined modes from available list now.

diff --git a/randr/mirandr.c b/randr/mirandr.c
index bcc8e0f..7300cfe 100644
--- a/randr/mirandr.c
+++ b/randr/mirandr.c
@@ -52,7 +52,7 @@ miRRCrtcSet (ScreenPtr	pScreen,
 	     int	y,
 	     Rotation	rotation,
 	     int	numOutput,
-	     RROutputPtr    *outputs)
+	     RROutputConfigPtr    outputs)
 {
     return TRUE;
 }
@@ -114,6 +114,10 @@ miRandRInit (ScreenPtr pScreen)
 	return FALSE;
     if (!RROutputSetCrtcs (output, &crtc, 1))
 	return FALSE;
+    if (!RROutputSetPossibleOptions (output, 0))
+	return FALSE;
+    if (!RROutputSetCurrentOptions (output, 0))
+	return FALSE;
     if (!RROutputSetConnection (output, RR_Connected))
 	return FALSE;
     RRCrtcNotify (crtc, mode, 0, 0, RR_Rotate_0, 1, &output);
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 0b8c61e..a4e5589 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -72,12 +72,14 @@ extern int (*SProcRandrVector[RRNumberRe
 typedef struct _rrMode	    RRModeRec, *RRModePtr;
 typedef struct _rrCrtc	    RRCrtcRec, *RRCrtcPtr;
 typedef struct _rrOutput    RROutputRec, *RROutputPtr;
+typedef struct _rrOutputConfig	RROutputConfigRec, *RROutputConfigPtr;
 
 struct _rrMode {
     int		    refcnt;
     xRRModeInfo	    mode;
     char	    *name;
     void	    *devPrivate;
+    ScreenPtr	    screen;
 };
 
 struct _rrCrtc {
@@ -105,6 +107,8 @@ struct _rrOutput {
     CARD8	    connection;
     CARD8	    subpixelOrder;
     RRCrtcPtr	    crtc;
+    CARD32	    currentOptions;
+    CARD32	    possibleOptions;
     int		    numCrtcs;
     RRCrtcPtr	    *crtcs;
     int		    numClones;
@@ -116,6 +120,11 @@ struct _rrOutput {
     void	    *devPrivate;
 };
 
+struct _rrOutputConfig {
+    RROutputPtr	    output;
+    CARD32	    options;
+};
+
 #if RANDR_12_INTERFACE
 typedef Bool (*RRScreenSetSizeProcPtr) (ScreenPtr	pScreen,
 					CARD16		width,
@@ -130,7 +139,7 @@ typedef Bool (*RRCrtcSetProcPtr) (Screen
 				  int			y,
 				  Rotation		rotation,
 				  int			numOutputs,
-				  RROutputPtr		*outputs);
+				  RROutputConfigPtr	outputs);
 
 typedef Bool (*RRCrtcSetGammaProcPtr) (ScreenPtr	pScreen,
 				       RRCrtcPtr	crtc);
@@ -352,7 +361,7 @@ miRRCrtcSet (ScreenPtr	pScreen,
 	     int	y,
 	     Rotation	rotation,
 	     int	numOutput,
-	     RROutputPtr    *outputs);
+	     RROutputConfigPtr    outputs);
 
 /* randr.c */
 /*
@@ -440,7 +449,7 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
 	      int	    x,
 	      int	    y,
 	      Rotation	    rotation,
-	      int	    numOutput,
+	      int	    numOutputs,
 	      RROutputPtr   *outputs);
 
 void
@@ -456,7 +465,7 @@ RRCrtcSet (RRCrtcPtr    crtc,
 	   int		y,
 	   Rotation	rotation,
 	   int		numOutput,
-	   RROutputPtr  *outputs);
+	   RROutputConfigPtr  outputs);
 
 /*
  * Request that the Crtc gamma be changed
@@ -530,6 +539,9 @@ RRModeGet (ScreenPtr	pScreen,
 	   xRRModeInfo	*modeInfo,
 	   const char	*name);
 
+void
+RRModePruneUnused (ScreenPtr pScreen);
+
 /*
  * Destroy a mode.
  */
@@ -584,6 +596,10 @@ RROutputSetCrtcs (RROutputPtr	output,
 		  RRCrtcPtr	*crtcs,
 		  int		numCrtcs);
 
+Bool
+RROutputSetPossibleOptions (RROutputPtr	output,
+			    CARD32	possibleOptions);
+
 void
 RROutputSetCrtc (RROutputPtr output, RRCrtcPtr crtc);
     
@@ -595,6 +611,10 @@ Bool
 RROutputSetSubpixelOrder (RROutputPtr output,
 			  int	      subpixelOrder);
 
+Bool
+RROutputSetCurrentOptions (RROutputPtr output,
+			   CARD32      currentOptions);
+
 void
 RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output);
 
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 77cba29..3108f14 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -92,25 +92,25 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
     
     if (numOutputs != prevNumOutputs)
     {
-	RROutputPtr *outputs;
+	RROutputPtr *newoutputs;
 	
 	if (numOutputs)
 	{
 	    if (crtc->numOutputs)
-		outputs = xrealloc (crtc->outputs,
+		newoutputs = xrealloc (crtc->outputs,
 				    numOutputs * sizeof (RROutputPtr));
 	    else
-		outputs = xalloc (numOutputs * sizeof (RROutputPtr));
-	    if (!outputs)
+		newoutputs = xalloc (numOutputs * sizeof (RROutputPtr));
+	    if (!newoutputs)
 		return FALSE;
 	}
 	else
 	{
 	    if (crtc->outputs)
 		xfree (crtc->outputs);
-	    outputs = NULL;
+	    newoutputs = NULL;
 	}
-	crtc->outputs = outputs;
+	crtc->outputs = newoutputs;
 	crtc->numOutputs = numOutputs;
     }
     for (i = 0; i < numOutputs; i++)
@@ -183,7 +183,7 @@ RRCrtcSet (RRCrtcPtr    crtc,
 	   int		y,
 	   Rotation	rotation,
 	   int		numOutputs,
-	   RROutputPtr  *outputs)
+	   RROutputConfigPtr  outputs)
 {
     ScreenPtr	pScreen = crtc->pScreen;
     rrScrPriv(pScreen);
@@ -252,7 +252,7 @@ RRCrtcDestroyResource (pointer value, XI
     {
 	if (pScrPriv->crtcs[i] == crtc)
 	{
-	    memmove (pScrPriv->crtcs, pScrPriv->crtcs + 1,
+	    memmove (pScrPriv->crtcs + i, pScrPriv->crtcs + i + 1,
 		     (pScrPriv->numCrtcs - (i - 1)) * sizeof (RRCrtcPtr));
 	    --pScrPriv->numCrtcs;
 	    break;
@@ -458,15 +458,15 @@ ProcRRSetCrtcConfig (ClientPtr client)
     RRCrtcPtr		    crtc;
     RRModePtr		    mode;
     int			    numOutputs;
-    RROutputPtr		    *outputs = NULL;
-    RROutput		    *outputIds;
+    RROutputConfigPtr	    outputs = NULL;
+    xRROutputConfig 	    *outputConfigs;
     TimeStamp		    configTime;
     TimeStamp		    time;
     Rotation		    rotation;
     int			    i, j;
     
     REQUEST_AT_LEAST_SIZE(xRRSetCrtcConfigReq);
-    numOutputs = stuff->length - (SIZEOF (xRRSetCrtcConfigReq) >> 2);
+    numOutputs = (stuff->length - (SIZEOF (xRRSetCrtcConfigReq) >> 2)) >> 1;
     
     crtc = LookupIDByType (stuff->crtc, RRCrtcType);
     if (!crtc)
@@ -493,39 +493,47 @@ ProcRRSetCrtcConfig (ClientPtr client)
     }
     if (numOutputs)
     {
-	outputs = xalloc (numOutputs * sizeof (RROutputPtr));
+	outputs = xalloc (numOutputs * sizeof (RROutputConfigRec));
 	if (!outputs)
 	    return BadAlloc;
     }
     else
 	outputs = NULL;
     
-    outputIds = (RROutput *) (stuff + 1);
+    outputConfigs = (xRROutputConfig *) (stuff + 1);
     for (i = 0; i < numOutputs; i++)
     {
-	outputs[i] = LookupIDByType (outputIds[i], RROutputType);
-	if (!outputs[i])
+	outputs[i].output = LookupIDByType (outputConfigs[i].output, RROutputType);
+	if (!outputs[i].output)
 	{
-	    client->errorValue = outputIds[i];
+	    client->errorValue = outputConfigs[i].output;
 	    if (outputs)
 		xfree (outputs);
 	    return RRErrorBase + BadRROutput;
 	}
+	outputs[i].options = outputConfigs[i].options;
+	if (outputs[i].options & ~outputs[i].output->possibleOptions)
+	{
+	    client->errorValue = outputConfigs[i].options;
+	    if (outputs)
+		xfree (outputs);
+	    return BadMatch;
+	}
 	/* validate crtc for this output */
-	for (j = 0; j < outputs[i]->numCrtcs; j++)
-	    if (outputs[i]->crtcs[j] == crtc)
+	for (j = 0; j < outputs[i].output->numCrtcs; j++)
+	    if (outputs[i].output->crtcs[j] == crtc)
 		break;
-	if (j == outputs[j]->numCrtcs)
+	if (j == outputs[j].output->numCrtcs)
 	{
 	    if (outputs)
 		xfree (outputs);
 	    return BadMatch;
 	}
 	/* validate mode for this output */
-	for (j = 0; j < outputs[i]->numModes; j++)
-	    if (outputs[i]->modes[j] == mode)
+	for (j = 0; j < outputs[i].output->numModes; j++)
+	    if (outputs[i].output->modes[j] == mode)
 		break;
-	if (j == outputs[i]->numModes)
+	if (j == outputs[i].output->numModes)
 	{
 	    if (outputs)
 		xfree (outputs);
diff --git a/randr/rrinfo.c b/randr/rrinfo.c
index 491ac21..6fd4ee5 100644
--- a/randr/rrinfo.c
+++ b/randr/rrinfo.c
@@ -208,6 +208,7 @@ RRGetInfo (ScreenPtr pScreen)
     if (pScrPriv->nSizes)
 	RRScanOldConfig (pScreen, rotations);
 #endif
+    RRModePruneUnused (pScreen);
     RRTellChanged (pScreen);
     return TRUE;
 }
diff --git a/randr/rrmode.c b/randr/rrmode.c
index 23ac530..3a67486 100644
--- a/randr/rrmode.c
+++ b/randr/rrmode.c
@@ -24,6 +24,27 @@
 
 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->mmWidth != b->mmWidth) return FALSE;
+    if (a->mmHeight != b->mmHeight) 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;
+    if (a->origin != b->origin) return FALSE;
+    return TRUE;
+}
+
 RRModePtr
 RRModeGet (ScreenPtr	pScreen,
 	   xRRModeInfo	*modeInfo,
@@ -37,8 +58,7 @@ RRModeGet (ScreenPtr	pScreen,
     for (i = 0; i < pScrPriv->numModes; i++)
     {
 	mode = pScrPriv->modes[i];
-	modeInfo->id = mode->mode.id;
-	if (!memcmp (modeInfo, &mode->mode, sizeof (xRRModeInfo)) &&
+	if (RRModeEqual (&mode->mode, modeInfo) &&
 	    !memcmp (name, mode->name, modeInfo->nameLength))
 	{
 	    ++mode->refcnt;
@@ -54,6 +74,7 @@ RRModeGet (ScreenPtr	pScreen,
     mode->name = (char *) (mode + 1);
     memcpy (mode->name, name, modeInfo->nameLength);
     mode->name[modeInfo->nameLength] = '\0';
+    mode->screen = pScreen;
 
     if (pScrPriv->numModes)
 	modes = xrealloc (pScrPriv->modes,
@@ -80,8 +101,31 @@ RRModeGet (ScreenPtr	pScreen,
 void
 RRModeDestroy (RRModePtr mode)
 {
+    ScreenPtr	    pScreen;
+    rrScrPrivPtr    pScrPriv;
+    int	m;
+    
     if (--mode->refcnt > 0)
 	return;
+    pScreen = mode->screen;
+    pScrPriv = rrGetScrPriv (pScreen);
+    for (m = 0; m < pScrPriv->numModes; m++)
+    {
+	if (pScrPriv->modes[m] == mode)
+	{
+	    memmove (pScrPriv->modes + m, pScrPriv->modes + m + 1,
+		     (pScrPriv->numModes - m - 1) * sizeof (RRModePtr));
+	    pScrPriv->numModes--;
+	    if (!pScrPriv->numModes)
+	    {
+		xfree (pScrPriv->modes);
+		pScrPriv->modes = NULL;
+	    }
+	    pScrPriv->changed = TRUE;
+	    break;
+	}
+    }
+    
     xfree (mode);
 }
 
@@ -104,6 +148,26 @@ RRModeInit (void)
     return TRUE;
 }
 
+void
+RRModePruneUnused (ScreenPtr pScreen)
+{
+    rrScrPriv (pScreen);
+    RRModePtr	*unused, mode;
+    int		m;
+    int		num = pScrPriv->numModes;
+
+    unused = xalloc (num * sizeof (RRModePtr));
+    if (!unused)
+	return;
+    memcpy (unused, pScrPriv->modes, num * sizeof (RRModePtr));
+    for (m = 0; m < num; m++) {
+	mode = unused[m];
+	if (mode->refcnt == 1 && mode->mode.origin != RRModeOriginUser)
+	    FreeResource (mode->mode.id, 0);
+    }
+    xfree (unused);
+}
+
 int
 ProcRRCreateMode (ClientPtr client)
 {
diff --git a/randr/rroutput.c b/randr/rroutput.c
index 90b2b98..b252d7d 100644
--- a/randr/rroutput.c
+++ b/randr/rroutput.c
@@ -60,6 +60,8 @@ RROutputCreate (ScreenPtr   pScreen,
     output->connection = RR_UnknownConnection;
     output->subpixelOrder = SubPixelUnknown;
     output->crtc = NULL;
+    output->currentOptions = 0;
+    output->possibleOptions = 0;
     output->numCrtcs = 0;
     output->crtcs = NULL;
     output->numClones = 0;
@@ -190,6 +192,17 @@ RROutputSetCrtcs (RROutputPtr	output,
     return TRUE;
 }
 
+Bool
+RROutputSetPossibleOptions (RROutputPtr	output,
+			    CARD32	possibleOptions)
+{
+    if (output->possibleOptions == possibleOptions)
+	return TRUE;
+    output->possibleOptions = possibleOptions;
+    output->changed = TRUE;
+    return TRUE;
+}
+
 void
 RROutputSetCrtc (RROutputPtr output, RRCrtcPtr crtc)
 {
@@ -222,6 +235,17 @@ RROutputSetSubpixelOrder (RROutputPtr ou
     return TRUE;
 }
 
+Bool
+RROutputSetCurrentOptions (RROutputPtr output,
+			   CARD32      currentOptions)
+{
+    if (output->currentOptions == currentOptions)
+	return TRUE;
+    output->currentOptions = currentOptions;
+    output->changed = TRUE;
+    return TRUE;
+}
+
 void
 RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output)
 {
@@ -248,7 +272,7 @@ RROutputDestroyResource (pointer value, 
     {
 	if (pScrPriv->outputs[i] == output)
 	{
-	    memmove (pScrPriv->outputs, pScrPriv->outputs + 1,
+	    memmove (pScrPriv->outputs + i, pScrPriv->outputs + i + 1,
 		     (pScrPriv->numOutputs - (i - 1)) * sizeof (RROutputPtr));
 	    --pScrPriv->numOutputs;
 	    break;
@@ -280,6 +304,8 @@ RROutputInit (void)
     return TRUE;
 }
 
+#define OutputInfoExtra	(SIZEOF(xRRGetOutputInfoReply) - 32)
+				
 int
 ProcRRGetOutputInfo (ClientPtr client)
 {
@@ -307,24 +333,27 @@ ProcRRGetOutputInfo (ClientPtr client)
 
     rep.type = X_Reply;
     rep.sequenceNumber = client->sequence;
-    rep.length = 0;
+    rep.length = OutputInfoExtra >> 2;
     rep.timestamp = pScrPriv->lastSetTime.milliseconds;
     rep.crtc = output->crtc ? output->crtc->id : None;
+    rep.currentOptions = output->currentOptions;
     rep.connection = output->connection;
     rep.subpixelOrder = output->subpixelOrder;
     rep.nCrtcs = output->numCrtcs;
     rep.nModes = output->numModes;
     rep.nClones = output->numClones;
     rep.nameLength = output->nameLength;
+    rep.possibleOptions = output->possibleOptions;
+    rep.pad1 = 42;
     
-    rep.length = (output->numCrtcs + 
-		  output->numModes + 
-		  output->numClones +
-		  ((rep.nameLength + 3) >> 2));
+    extraLen = ((output->numCrtcs + 
+		 output->numModes + 
+		 output->numClones +
+		 ((rep.nameLength + 3) >> 2)) << 2);
 
-    extraLen = rep.length << 2;
     if (extraLen)
     {
+	rep.length += extraLen >> 2;
 	extra = xalloc (extraLen);
 	if (!extra)
 	    return BadAlloc;
diff --git a/randr/rrscreen.c b/randr/rrscreen.c
index e382540..7b53f04 100644
--- a/randr/rrscreen.c
+++ b/randr/rrscreen.c
@@ -372,7 +372,7 @@ ProcRRGetScreenResources (ClientPtr clie
 
 	rep.length = (pScrPriv->numCrtcs + 
 		      pScrPriv->numOutputs + 
-		      pScrPriv->numModes * 10 +
+		      pScrPriv->numModes * (SIZEOF(xRRModeInfo) >> 2) +
 		      ((rep.nbytesNames + 3) >> 2));
 	
 	extraLen = rep.length << 2;
@@ -429,7 +429,7 @@ ProcRRGetScreenResources (ClientPtr clie
 		    pScrPriv->modes[i]->mode.nameLength);
 	    names += pScrPriv->modes[i]->mode.nameLength;
 	}
-	assert ((names + 3 >> 3) == rep.length);
+	assert (((((char *) names - (char *) extra) + 3) >> 2) == rep.length);
     }
     
     if (client->swapped) {
@@ -694,7 +694,7 @@ ProcRRSetScreenConfig (ClientPtr client)
     Rotation		    rotation;
     int			    rate;
     Bool		    has_rate;
-    RROutputPtr		    output;
+    RROutputConfigRec	    output;
     RRModePtr		    mode;
     RR10DataPtr		    pData = NULL;
     RRScreenSizePtr    	    pSize;
@@ -731,13 +731,14 @@ ProcRRSetScreenConfig (ClientPtr client)
     if (!RRGetInfo (pScreen))
 	return BadAlloc;
     
-    output = RRFirstOutput (pScreen);
-    if (!output)
+    output.output = RRFirstOutput (pScreen);
+    if (!output.output)
     {
 	time = currentTime;
 	rep.status = RRSetConfigFailed;
 	goto sendReply;
     }
+    output.options = output.output->currentOptions;
     
     /*
      * if the client's config timestamp is not the same as the last config
@@ -750,7 +751,7 @@ ProcRRSetScreenConfig (ClientPtr client)
 	goto sendReply;
     }
     
-    pData = RR10GetData (pScreen, output);
+    pData = RR10GetData (pScreen, output.output);
     if (!pData)
 	return BadAlloc;
     
@@ -786,7 +787,7 @@ ProcRRSetScreenConfig (ClientPtr client)
 	return BadValue;
     }
 
-    if ((~output->crtc->rotations) & rotation)
+    if ((~output.output->crtc->rotations) & rotation)
     {
 	/*
 	 * requested rotation or reflection not supported by screen
@@ -835,7 +836,7 @@ ProcRRSetScreenConfig (ClientPtr client)
 	goto sendReply;
     }
 
-    rep.status = RRCrtcSet (output->crtc, mode, 0, 0, stuff->rotation,
+    rep.status = RRCrtcSet (output.output->crtc, mode, 0, 0, stuff->rotation,
 			    1, &output);
     
 sendReply:
diff-tree f7dcf3a6d482d4934ff7ba33826adf725103470b (from 817a82faaf61c481eb0874475a2e05f339c7fed1)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Thu Sep 21 09:52:04 2006 -0700

    When no mode is specified, don't validate mode-specific parameters.

diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index ebb2540..77cba29 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -564,64 +564,67 @@ ProcRRSetCrtcConfig (ClientPtr client)
 	goto sendReply;
     }
     
-    /*
-     * 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 ((~crtc->rotations) & rotation)
+    if (mode)
     {
 	/*
-	 * requested rotation or reflection not supported by screen
+	 * Validate requested rotation
 	 */
-	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)
-    {
-	if (stuff->x + mode->mode.width > pScreen->width)
-	{
-	    client->errorValue = stuff->x;
+	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 (stuff->y + mode->mode.height > pScreen->height)
+    
+	if ((~crtc->rotations) & rotation)
 	{
-	    client->errorValue = stuff->y;
+	    /*
+	     * requested rotation or reflection not supported by screen
+	     */
+	    client->errorValue = stuff->rotation;
 	    if (outputs)
 		xfree (outputs);
-	    return BadValue;
+	    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)
+	{
+	    if (stuff->x + mode->mode.width > pScreen->width)
+	    {
+		client->errorValue = stuff->x;
+		if (outputs)
+		    xfree (outputs);
+		return BadValue;
+	    }
+	    
+	    if (stuff->y + mode->mode.height > pScreen->height)
+	    {
+		client->errorValue = stuff->y;
+		if (outputs)
+		    xfree (outputs);
+		return BadValue;
+	    }
 	}
-    }
 #endif
+    }
     
     /*
      * Make sure the requested set-time is not older than
diff-tree 817a82faaf61c481eb0874475a2e05f339c7fed1 (from 3516e85b45441715bacda81fcae3b8a786d75f06)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Wed Sep 20 22:43:05 2006 -0700

    Steal Xinerama code from SiS driver. Add missing files.
    
    Provide a Xinerama implementation when DIX version isn't enabled. This
    version exposes each crtc as a separate 'screen' and reports the size of
    that patch. The extension also sends ConfigureNotify events to the root
    window whenever crtcs change so that applications will re-fetch xinerama
    information. This actually works for metacity.

diff --git a/randr/Makefile.am b/randr/Makefile.am
index a28ead0..91c4bc6 100644
--- a/randr/Makefile.am
+++ b/randr/Makefile.am
@@ -17,4 +17,5 @@ librandr_la_SOURCES =	\
 	rroutput.c	\
 	rrproperty.c	\
 	rrscreen.c	\
-	rrsdispatch.c
+	rrsdispatch.c	\
+	rrxinerama.c
diff --git a/randr/randr.c b/randr/randr.c
index 5f54dea..4ea72e5 100644
--- a/randr/randr.c
+++ b/randr/randr.c
@@ -311,7 +311,7 @@ RRExtensionInit (void)
     EventSwapVector[RREventBase + RRNotify] = (EventSwapPtr)
 	SRRNotifyEvent;
 
-    return;
+    RRXineramaExtensionInit();
 }
 
 static int
diff --git a/randr/randrstr.h b/randr/randrstr.h
index e459452..0b8c61e 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -305,6 +305,12 @@ RRScreenSizeSet (ScreenPtr  pScreen,
 		 CARD32	    mmHeight);
 
 /*
+ * Send ConfigureNotify event to root window when 'something' happens
+ */
+void
+RRSendConfigNotify (ScreenPtr pScreen);
+    
+/*
  * screen dispatch
  */
 int 
@@ -629,4 +635,8 @@ ProcRRListOutputProperties (ClientPtr cl
 int
 ProcRRDeleteOutputProperty (ClientPtr client);
 
+/* rrxinerama.c */
+void
+RRXineramaExtensionInit(void);
+
 #endif /* _RANDRSTR_H_ */
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index dfa9ca6..ebb2540 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -111,6 +111,7 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
 	    outputs = NULL;
 	}
 	crtc->outputs = outputs;
+	crtc->numOutputs = numOutputs;
     }
     for (i = 0; i < numOutputs; i++)
     {
@@ -158,7 +159,11 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
 	crtc->changed = TRUE;
     }
     if (crtc->changed)
+    {
+	if (!pScrPriv->changed)
+	    RRSendConfigNotify (pScreen);
 	pScrPriv->changed = TRUE;
+    }
     return TRUE;
 }
 
diff --git a/randr/rrinfo.c b/randr/rrinfo.c
new file mode 100644
index 0000000..491ac21
--- /dev/null
+++ b/randr/rrinfo.c
@@ -0,0 +1,337 @@
+/*
+ * 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.mmWidth = size->mmWidth;
+    modeInfo.mmHeight = size->mmHeight;
+    modeInfo.hTotal = size->width;
+    modeInfo.vTotal = size->height;
+    modeInfo.dotClock = ((CARD32) size->width * (CARD32) size->height *
+			 (CARD32) refresh);
+    modeInfo.nameLength = strlen (name);
+    mode = RRModeGet (pScreen, &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;
+    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);
+	RROutputSetCrtc (output, crtc);
+	RROutputSetConnection (output, RR_Connected);
+#ifdef RENDER
+	RROutputSetSubpixelOrder (output, PictureGetSubpixelOrder (pScreen));
+#endif
+    }
+
+    output = RRFirstOutput (pScreen);
+    if (!output)
+	return;
+    crtc = output->crtc;
+
+    /* 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; i++) 
+    {
+	RRModePtr   mode = output->modes[i];
+        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;
+    }
+
+    if (minWidth != pScrPriv->minWidth) {
+	pScrPriv->minWidth = minWidth; pScrPriv->changed = TRUE;
+    }
+    if (maxWidth != pScrPriv->maxWidth) {
+	pScrPriv->maxWidth = maxWidth; pScrPriv->changed = TRUE;
+    }
+    if (minHeight != pScrPriv->minHeight) {
+	pScrPriv->minHeight = minHeight; pScrPriv->changed = TRUE;
+    }
+    if (maxHeight != pScrPriv->maxHeight) {
+	pScrPriv->maxHeight = maxHeight; pScrPriv->changed = TRUE;
+    }
+
+    /* notice current mode */
+    if (newMode)
+	RRCrtcNotify (output->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;
+    
+    if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations))
+	return FALSE;
+
+#if RANDR_10_INTERFACE
+    if (pScrPriv->nSizes)
+	RRScanOldConfig (pScreen, rotations);
+#endif
+    RRTellChanged (pScreen);
+    return TRUE;
+}
+
+#if RANDR_12_INTERFACE
+/*
+ * 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;
+    pScrPriv->minWidth  = minWidth;
+    pScrPriv->minHeight = minHeight;
+    pScrPriv->maxWidth  = maxWidth;
+    pScrPriv->maxHeight = maxHeight;
+}
+#endif
+
+#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/rrproperty.c b/randr/rrproperty.c
new file mode 100644
index 0000000..cdafb5c
--- /dev/null
+++ b/randr/rrproperty.c
@@ -0,0 +1,430 @@
+/*
+ * 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)
+{
+    PropertyPtr 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);
+        xfree(prop->data);
+        xfree(prop);
+    }
+}
+
+void
+RRDeleteOutputProperty (RROutputPtr output, Atom property)
+{
+    PropertyPtr	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);
+        xfree(prop->data);
+        xfree(prop);
+    }
+}
+
+int
+RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
+			int format, int mode, unsigned long len,
+			pointer value, Bool sendevent)
+{
+    PropertyPtr			    prop;
+    xRROutputPropertyNotifyEvent    event;
+    int				    sizeInBytes;
+    int				    totalSize;
+    pointer			    data;
+
+    sizeInBytes = format >> 3;
+    totalSize = len * sizeInBytes;
+
+    /* first see if property already exists */
+
+    for (prop = output->properties; prop; prop = prop->next)
+	if (prop->propertyName == property)
+	    break;
+    
+    if (!prop)   /* just add to list */
+    {
+        prop = (PropertyPtr)xalloc(sizeof(PropertyRec));
+	if (!prop)
+	    return(BadAlloc);
+        data = (pointer)xalloc(totalSize);
+	if (!data && len)
+	{
+	    xfree(prop);
+	    return(BadAlloc);
+	}
+        prop->propertyName = property;
+        prop->type = type;
+        prop->format = format;
+        prop->data = data;
+	if (len)
+	    memmove((char *)data, (char *)value, totalSize);
+	prop->size = len;
+        prop->next = output->properties;
+        output->properties = prop;
+    }
+    else
+    {
+	/* 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->format) && (mode != PropModeReplace))
+	    return(BadMatch);
+        if ((prop->type != type) && (mode != PropModeReplace))
+            return(BadMatch);
+        if (mode == PropModeReplace)
+        {
+	    if (totalSize != prop->size * (prop->format >> 3))
+	    {
+	    	data = (pointer)xrealloc(prop->data, totalSize);
+	    	if (!data && len)
+		    return(BadAlloc);
+            	prop->data = data;
+	    }
+	    if (len)
+		memmove((char *)prop->data, (char *)value, totalSize);
+	    prop->size = len;
+    	    prop->type = type;
+	    prop->format = format;
+	}
+	else if (len == 0)
+	{
+	    /* do nothing */
+	}
+        else if (mode == PropModeAppend)
+        {
+	    data = (pointer)xrealloc(prop->data,
+				     sizeInBytes * (len + prop->size));
+	    if (!data)
+		return(BadAlloc);
+            prop->data = data;
+	    memmove(&((char *)data)[prop->size * sizeInBytes], 
+		    (char *)value,
+		  totalSize);
+            prop->size += len;
+	}
+        else if (mode == PropModePrepend)
+        {
+            data = (pointer)xalloc(sizeInBytes * (len + prop->size));
+	    if (!data)
+		return(BadAlloc);
+	    memmove(&((char *)data)[totalSize], (char *)prop->data, 
+		  (int)(prop->size * sizeInBytes));
+            memmove((char *)data, (char *)value, totalSize);
+	    xfree(prop->data);
+            prop->data = data;
+            prop->size += len;
+	}
+    }
+    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);
+}
+
+int
+ProcRRListOutputProperties (ClientPtr client)
+{
+    REQUEST(xRRListOutputPropertiesReq);
+    Atom			    *pAtoms = NULL, *temppAtoms;
+    xRRListOutputPropertiesReply    rep;
+    int				    numProps = 0;
+    RROutputPtr			    output;
+    PropertyPtr			    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 *)ALLOCATE_LOCAL(numProps * sizeof(Atom))))
+            return(BadAlloc);
+
+    rep.type = X_Reply;
+    rep.nProperties = numProps;
+    rep.length = (numProps * sizeof(Atom)) >> 2;
+    rep.sequenceNumber = client->sequence;
+    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);
+        DEALLOCATE_LOCAL(pAtoms);
+    }
+    return(client->noClientException);
+}
+
+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);
+    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);
+    PropertyPtr			prop, *prev;
+    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 the request type and actual type don't match. Return the
+    property information, but not the data. */
+
+    if (((stuff->type != prop->type) &&
+	 (stuff->type != AnyPropertyType))
+       )
+    {
+	reply.bytesAfter = prop->size;
+	reply.format = prop->format;
+	reply.length = 0;
+	reply.nItems = 0;
+	reply.propertyType = prop->type;
+	WriteReplyToClient(client, sizeof(xRRGetOutputPropertyReply), &reply);
+	return(client->noClientException);
+    }
+
+/*
+ *  Return type, format, value to client
+ */
+    n = (prop->format/8) * prop->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->format;
+    reply.length = (len + 3) >> 2;
+    reply.nItems = len / (prop->format / 8 );
+    reply.propertyType = prop->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->data + ind);
+    }
+
+    if (stuff->delete && (reply.bytesAfter == 0))
+    { /* delete the Property */
+	*prev = prop->next;
+	xfree(prop->data);
+	xfree(prop);
+    }
+    return(client->noClientException);
+}
+
diff --git a/randr/rrscreen.c b/randr/rrscreen.c
index e59947b..e382540 100644
--- a/randr/rrscreen.c
+++ b/randr/rrscreen.c
@@ -69,7 +69,7 @@ RREditConnectionInfo (ScreenPtr pScreen)
     root->mmHeight = pScreen->mmHeight;
 }
 
-static void
+void
 RRSendConfigNotify (ScreenPtr pScreen)
 {
     WindowPtr	pWin = WindowTable[pScreen->myNum];
diff --git a/randr/rrxinerama.c b/randr/rrxinerama.c
new file mode 100644
index 0000000..31f60cc
--- /dev/null
+++ b/randr/rrxinerama.c
@@ -0,0 +1,424 @@
+/*
+ * 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 = LookupWindow(stuff->window, client);
+    if(!pWin) return BadWindow;
+
+    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
+RRXineramaScreenActive (ScreenPtr pScreen)
+{
+    return rrGetScrPriv(pScreen) != NULL;
+}
+
+static Bool
+RRXineramaCrtcActive (RRCrtcPtr crtc)
+{
+    return crtc->mode != NULL && crtc->numOutputs > 0;
+}
+
+static int
+RRXineramaScreenCount (ScreenPtr pScreen)
+{
+    int	i, n;
+    
+    n = 0;
+    if (RRXineramaScreenActive (pScreen))
+    {
+	rrScrPriv(pScreen);
+	for (i = 0; i < pScrPriv->numCrtcs; i++)
+	    if (RRXineramaCrtcActive (pScrPriv->crtcs[i]))
+		n++;
+    }
+    return n;
+}
+
+int
+ProcRRXineramaGetScreenCount(ClientPtr client)
+{
+    REQUEST(xPanoramiXGetScreenCountReq);
+    WindowPtr				pWin;
+    xPanoramiXGetScreenCountReply	rep;
+    register int			n;
+
+    REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
+    pWin = LookupWindow(stuff->window, client);
+    if(!pWin) return BadWindow;
+    
+    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 = LookupWindow (stuff->window, client);
+    if(!pWin)  return BadWindow;
+
+    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);
+
+    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))
+	    {
+		scratch.x_org  = crtc->x;
+		scratch.y_org  = crtc->y;
+		scratch.width  = crtc->mode->mode.width;
+		scratch.height = crtc->mode->mode.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
+
+    (void) AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0,
+			ProcRRXineramaDispatch,
+			SProcRRXineramaDispatch,
+			RRXineramaResetProc,
+			StandardMinorOpcode);
+}
diff-tree 3516e85b45441715bacda81fcae3b8a786d75f06 (from a0f59b53794bd0d655fc2042c6196b27a033f85a)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Wed Sep 20 19:42:34 2006 -0700

    RRSetCrtcConfig status fix. RRGetScreenResources timestamp fix.
    
    RRSetCrtcConfig was returning the wrong status values.
    RRGetScreenResources was always returning currentTime.

diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 90d609e..dfa9ca6 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -628,8 +628,13 @@ ProcRRSetCrtcConfig (ClientPtr client)
 	goto sendReply;
     }
 
-    rep.status = RRCrtcSet (crtc, mode, stuff->x, stuff->y,
-			    rotation, numOutputs, outputs);
+    if (!RRCrtcSet (crtc, mode, stuff->x, stuff->y,
+		   rotation, numOutputs, outputs))
+    {
+	rep.status = RRSetConfigFailed;
+	goto sendReply;
+    }
+    rep.status = RRSetConfigSuccess;
     
 sendReply:
     if (outputs)
diff --git a/randr/rrscreen.c b/randr/rrscreen.c
index 617ae41..e59947b 100644
--- a/randr/rrscreen.c
+++ b/randr/rrscreen.c
@@ -360,8 +360,8 @@ ProcRRGetScreenResources (ClientPtr clie
 	rep.type = X_Reply;
 	rep.sequenceNumber = client->sequence;
 	rep.length = 0;
-	rep.timestamp = currentTime.milliseconds;
-	rep.configTimestamp = currentTime.milliseconds;
+	rep.timestamp = pScrPriv->lastSetTime.milliseconds;
+	rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
 	rep.nCrtcs = pScrPriv->numCrtcs;
 	rep.nOutputs = pScrPriv->numOutputs;
 	rep.nModes = pScrPriv->numModes;;
diff-tree a0f59b53794bd0d655fc2042c6196b27a033f85a (from b851c3e35e407d966c10572f7594c0cb4a106d8e)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Wed Sep 20 13:15:20 2006 -0700

    typo

diff --git a/randr/rroutput.c b/randr/rroutput.c
index a4f5a66..90b2b98 100644
--- a/randr/rroutput.c
+++ b/randr/rroutput.c
@@ -194,7 +194,7 @@ void
 RROutputSetCrtc (RROutputPtr output, RRCrtcPtr crtc)
 {
     if (output->crtc == crtc)
-	return TRUE;
+	return;
     output->crtc = crtc;
     output->changed = TRUE;
 }
diff-tree b851c3e35e407d966c10572f7594c0cb4a106d8e (from f133e72d82e625683c96200ffde890cdbb5d4b10)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Wed Sep 20 13:14:53 2006 -0700

    When setting output state, leave output unchanged when setting to current.

diff --git a/randr/randrstr.h b/randr/randrstr.h
index 8027262..e459452 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -77,6 +77,7 @@ struct _rrMode {
     int		    refcnt;
     xRRModeInfo	    mode;
     char	    *name;
+    void	    *devPrivate;
 };
 
 struct _rrCrtc {
diff --git a/randr/rroutput.c b/randr/rroutput.c
index 3d4c163..a4f5a66 100644
--- a/randr/rroutput.c
+++ b/randr/rroutput.c
@@ -88,7 +88,16 @@ RROutputSetClones (RROutputPtr  output,
 		   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));
@@ -112,6 +121,20 @@ RROutputSetModes (RROutputPtr	output,
 		  int		numModes)
 {
     RRModePtr	*newModes;
+    int		i;
+
+    if (numModes == output->numModes)
+    {
+	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)
     {
@@ -122,7 +145,11 @@ RROutputSetModes (RROutputPtr	output,
     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;
@@ -136,7 +163,16 @@ RROutputSetCrtcs (RROutputPtr	output,
 		  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));
@@ -157,6 +193,8 @@ RROutputSetCrtcs (RROutputPtr	output,
 void
 RROutputSetCrtc (RROutputPtr output, RRCrtcPtr crtc)
 {
+    if (output->crtc == crtc)
+	return TRUE;
     output->crtc = crtc;
     output->changed = TRUE;
 }
@@ -165,6 +203,8 @@ Bool
 RROutputSetConnection (RROutputPtr  output,
 		       CARD8	    connection)
 {
+    if (output->connection == connection)
+	return TRUE;
     output->connection = connection;
     output->changed = TRUE;
     return TRUE;
@@ -174,6 +214,9 @@ Bool
 RROutputSetSubpixelOrder (RROutputPtr output,
 			  int	      subpixelOrder)
 {
+    if (output->subpixelOrder == subpixelOrder)
+	return TRUE;
+
     output->subpixelOrder = subpixelOrder;
     output->changed = TRUE;
     return TRUE;
diff-tree f133e72d82e625683c96200ffde890cdbb5d4b10 (from cd63e82aa51d941564012a8d8242ebe29b087373)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Wed Sep 20 12:05:52 2006 -0700

    Avoid calling xalloc(0). Change rrScreenSizeSet to rrScreenSetSize.

diff --git a/randr/randr.c b/randr/randr.c
index 5f6ef62..5f54dea 100644
--- a/randr/randr.c
+++ b/randr/randr.c
@@ -198,7 +198,7 @@ Bool RRScreenInit(ScreenPtr pScreen)
     pScrPriv->maxHeight = pScrPriv->minHeight = pScreen->height;
     
 #if RANDR_12_INTERFACE
-    pScrPriv->rrScreenSizeSet = NULL;
+    pScrPriv->rrScreenSetSize = NULL;
     pScrPriv->rrCrtcSet = NULL;
     pScrPriv->rrCrtcSetGamma = NULL;
 #endif
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 26c1806..8027262 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -174,7 +174,7 @@ typedef struct _rrScrPriv {
 #endif
     RRGetInfoProcPtr	    rrGetInfo;
 #if RANDR_12_INTERFACE
-    RRScreenSetSizeProcPtr  rrScreenSizeSet;
+    RRScreenSetSizeProcPtr  rrScreenSetSize;
     RRCrtcSetProcPtr	    rrCrtcSet;
     RRCrtcSetGammaProcPtr   rrCrtcSetGamma;
 #endif
@@ -521,7 +521,7 @@ RRClientKnowsRates (ClientPtr	pClient);
 RRModePtr
 RRModeGet (ScreenPtr	pScreen,
 	   xRRModeInfo	*modeInfo,
-	   char		*name);
+	   const char	*name);
 
 /*
  * Destroy a mode.
@@ -555,7 +555,7 @@ ProcRRDeleteOutputMode (ClientPtr client
 
 RROutputPtr
 RROutputCreate (ScreenPtr   pScreen,
-		char	    *name,
+		const char  *name,
 		int	    nameLength,
 		void	    *devPrivate);
 
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index c55e088..90d609e 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -94,13 +94,22 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
     {
 	RROutputPtr *outputs;
 	
-	if (crtc->numOutputs)
-	    outputs = xrealloc (crtc->outputs,
-				numOutputs * sizeof (RROutputPtr));
+	if (numOutputs)
+	{
+	    if (crtc->numOutputs)
+		outputs = xrealloc (crtc->outputs,
+				    numOutputs * sizeof (RROutputPtr));
+	    else
+		outputs = xalloc (numOutputs * sizeof (RROutputPtr));
+	    if (!outputs)
+		return FALSE;
+	}
 	else
-	    outputs = xalloc (numOutputs * sizeof (RROutputPtr));
-	if (!outputs)
-	    return FALSE;
+	{
+	    if (crtc->outputs)
+		xfree (crtc->outputs);
+	    outputs = NULL;
+	}
 	crtc->outputs = outputs;
     }
     for (i = 0; i < numOutputs; i++)
@@ -300,9 +309,14 @@ RRCrtcGammaSetSize (RRCrtcPtr	crtc,
 
     if (size == crtc->gammaSize)
 	return TRUE;
-    gamma = xalloc (size * 3 * sizeof (CARD16));
-    if (!gamma)
-	return FALSE;
+    if (size)
+    {
+	gamma = xalloc (size * 3 * sizeof (CARD16));
+	if (!gamma)
+	    return FALSE;
+    }
+    else
+	gamma = NULL;
     if (crtc->gammaRed)
 	xfree (crtc->gammaRed);
     crtc->gammaRed = gamma;
@@ -376,9 +390,14 @@ ProcRRGetCrtcInfo (ClientPtr client)
     rep.length = rep.nOutput + rep.nPossibleOutput;
 
     extraLen = rep.length << 2;
-    extra = xalloc (extraLen);
-    if (!extra)
-	return BadAlloc;
+    if (extraLen)
+    {
+	extra = xalloc (extraLen);
+	if (!extra)
+	    return BadAlloc;
+    }
+    else
+	extra = NULL;
 
     outputs = (RROutput *) extra;
     possible = (RROutput *) (outputs + rep.nOutput);
@@ -467,9 +486,14 @@ ProcRRSetCrtcConfig (ClientPtr client)
 	if (numOutputs == 0)
 	    return BadMatch;
     }
-    outputs = xalloc (numOutputs * sizeof (RROutputPtr));
-    if (!outputs)
-	return BadAlloc;
+    if (numOutputs)
+    {
+	outputs = xalloc (numOutputs * sizeof (RROutputPtr));
+	if (!outputs)
+	    return BadAlloc;
+    }
+    else
+	outputs = NULL;
     
     outputIds = (RROutput *) (stuff + 1);
     for (i = 0; i < numOutputs; i++)
@@ -574,7 +598,7 @@ ProcRRSetCrtcConfig (ClientPtr client)
      * for setting screen size. Else, assume the CrtcSet sets
      * the size along with the mode
      */
-    if (pScrPriv->rrScreenSizeSet)
+    if (pScrPriv->rrScreenSetSize)
     {
 	if (stuff->x + mode->mode.width > pScreen->width)
 	{
diff --git a/randr/rrmode.c b/randr/rrmode.c
index ab0ea18..23ac530 100644
--- a/randr/rrmode.c
+++ b/randr/rrmode.c
@@ -27,7 +27,7 @@ RESTYPE	RRModeType;
 RRModePtr
 RRModeGet (ScreenPtr	pScreen,
 	   xRRModeInfo	*modeInfo,
-	   char		*name)
+	   const char	*name)
 {
     rrScrPriv (pScreen);
     int	i;
diff --git a/randr/rroutput.c b/randr/rroutput.c
index 07dabad..3d4c163 100644
--- a/randr/rroutput.c
+++ b/randr/rroutput.c
@@ -30,7 +30,7 @@ RESTYPE	RROutputType;
 
 RROutputPtr
 RROutputCreate (ScreenPtr   pScreen,
-		char	    *name,
+		const char  *name,
 		int	    nameLength,
 		void	    *devPrivate)
 {
@@ -89,9 +89,14 @@ RROutputSetClones (RROutputPtr  output,
 {
     RROutputPtr	*newClones;
 
-    newClones = xalloc (numClones * sizeof (RROutputPtr));
-    if (!newClones)
-	return FALSE;
+    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));
@@ -108,9 +113,14 @@ RROutputSetModes (RROutputPtr	output,
 {
     RRModePtr	*newModes;
 
-    newModes = xalloc (numModes * sizeof (RRModePtr));
-    if (!newModes)
-	return FALSE;
+    if (numModes)
+    {
+	newModes = xalloc (numModes * sizeof (RRModePtr));
+	if (!newModes)
+	    return FALSE;
+    }
+    else
+	newModes = NULL;
     if (output->modes)
 	xfree (output->modes);
     memcpy (newModes, modes, numModes * sizeof (RRModePtr));
@@ -127,9 +137,14 @@ RROutputSetCrtcs (RROutputPtr	output,
 {
     RRCrtcPtr	*newCrtcs;
 
-    newCrtcs = xalloc (numCrtcs * sizeof (RRCrtcPtr));
-    if (!newCrtcs)
-	return FALSE;
+    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));
@@ -265,9 +280,14 @@ ProcRRGetOutputInfo (ClientPtr client)
 		  ((rep.nameLength + 3) >> 2));
 
     extraLen = rep.length << 2;
-    extra = xalloc (extraLen);
-    if (!extra)
-	return BadAlloc;
+    if (extraLen)
+    {
+	extra = xalloc (extraLen);
+	if (!extra)
+	    return BadAlloc;
+    }
+    else
+	extra = NULL;
 
     crtcs = (RRCrtc *) extra;
     modes = (RRMode *) (crtcs + output->numCrtcs);
diff --git a/randr/rrscreen.c b/randr/rrscreen.c
index 58d5152..617ae41 100644
--- a/randr/rrscreen.c
+++ b/randr/rrscreen.c
@@ -187,9 +187,9 @@ RRScreenSizeSet (ScreenPtr  pScreen,
     rrScrPriv(pScreen);
 
 #if RANDR_12_INTERFACE
-    if (pScrPriv->rrScreenSizeSet)
+    if (pScrPriv->rrScreenSetSize)
     {
-	return (*pScrPriv->rrScreenSizeSet) (pScreen,
+	return (*pScrPriv->rrScreenSetSize) (pScreen,
 					     width, height,
 					     mmWidth, mmHeight);
     }
@@ -376,9 +376,14 @@ ProcRRGetScreenResources (ClientPtr clie
 		      ((rep.nbytesNames + 3) >> 2));
 	
 	extraLen = rep.length << 2;
-	extra = xalloc (extraLen);
-	if (!extra)
-	    return BadAlloc;
+	if (extraLen)
+	{
+	    extra = xalloc (extraLen);
+	    if (!extra)
+		return BadAlloc;
+	}
+	else
+	    extra = NULL;
 
 	crtcs = (RRCrtc *) extra;
 	outputs = (RROutput *) (crtcs + pScrPriv->numCrtcs);
@@ -595,12 +600,18 @@ ProcRRGetScreenInfo (ClientPtr client)
 	extraLen = (rep.nSizes * sizeof (xScreenSizes) +
 		    rep.nrateEnts * sizeof (CARD16));
 
-	extra = (CARD8 *) xalloc (extraLen);
-	if (!extra)
+	if (extraLen)
 	{
-	    xfree (pData);
-	    return BadAlloc;
+	    extra = (CARD8 *) xalloc (extraLen);
+	    if (!extra)
+	    {
+		xfree (pData);
+		return BadAlloc;
+	    }
 	}
+	else
+	    extra = NULL;
+
 	/*
 	 * First comes the size information
 	 */
diff-tree cd63e82aa51d941564012a8d8242ebe29b087373 (from 7f9b59d80deb08b8427fdd1b6346390387725137)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Tue Sep 19 22:48:54 2006 -0700

    Split out 1.0-style info and new property routines to their own files.

diff --git a/randr/Makefile.am b/randr/Makefile.am
index 0a73557..a28ead0 100644
--- a/randr/Makefile.am
+++ b/randr/Makefile.am
@@ -12,7 +12,9 @@ librandr_la_SOURCES =	\
 	randrstr.h	\
 	rrcrtc.c	\
 	rrdispatch.c	\
+	rrinfo.c	\
 	rrmode.c	\
 	rroutput.c	\
+	rrproperty.c	\
 	rrscreen.c	\
 	rrsdispatch.c
diff --git a/randr/mirandr.c b/randr/mirandr.c
index a57a157..bcc8e0f 100644
--- a/randr/mirandr.c
+++ b/randr/mirandr.c
@@ -108,11 +108,13 @@ miRandRInit (ScreenPtr pScreen)
     output = RROutputCreate (pScreen, "screen", 6, NULL);
     if (!output)
 	return FALSE;
-    if (!RROutputSet (output, 
-		      NULL, 0,  /* clones */
-		      &mode, 1, /* modes */
-		      &crtc, 1, /* crtcs */
-		      RR_Connected))
+    if (!RROutputSetClones (output, NULL, 0))
+	return FALSE;
+    if (!RROutputSetModes (output, &mode, 1))
+	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
diff --git a/randr/randr.c b/randr/randr.c
index beddb50..5f6ef62 100644
--- a/randr/randr.c
+++ b/randr/randr.c
@@ -198,7 +198,9 @@ Bool RRScreenInit(ScreenPtr pScreen)
     pScrPriv->maxHeight = pScrPriv->minHeight = pScreen->height;
     
 #if RANDR_12_INTERFACE
-    pScrPriv->rrCrtcSet = 0;
+    pScrPriv->rrScreenSizeSet = NULL;
+    pScrPriv->rrCrtcSet = NULL;
+    pScrPriv->rrCrtcSetGamma = NULL;
 #endif
 #if RANDR_10_INTERFACE    
     pScrPriv->rrSetConfig = 0;
@@ -400,196 +402,6 @@ RRFirstOutput (ScreenPtr pScreen)
     return NULL;
 }
 
-#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.mmWidth = size->mmWidth;
-    modeInfo.mmHeight = size->mmHeight;
-    modeInfo.hTotal = size->width;
-    modeInfo.vTotal = size->height;
-    modeInfo.dotClock = ((CARD32) size->width * (CARD32) size->width *
-			 (CARD32) refresh);
-    modeInfo.nameLength = strlen (name);
-    mode = RRModeGet (pScreen, &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;
-    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);
-	RROutputSetCrtc (output, crtc);
-	RROutputSetConnection (output, RR_Connected);
-#ifdef RENDER
-	RROutputSetSubpixelOrder (output, PictureGetSubpixelOrder (pScreen));
-#endif
-    }
-
-    output = RRFirstOutput (pScreen);
-    if (!output)
-	return;
-    crtc = output->crtc;
-
-    /* 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; i++) 
-    {
-	RRModePtr   mode = output->modes[i];
-        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;
-    }
-
-    if (minWidth != pScrPriv->minWidth) {
-	pScrPriv->minWidth = minWidth; pScrPriv->changed = TRUE;
-    }
-    if (maxWidth != pScrPriv->maxWidth) {
-	pScrPriv->maxWidth = maxWidth; pScrPriv->changed = TRUE;
-    }
-    if (minHeight != pScrPriv->minHeight) {
-	pScrPriv->minHeight = minHeight; pScrPriv->changed = TRUE;
-    }
-    if (maxHeight != pScrPriv->maxHeight) {
-	pScrPriv->maxHeight = maxHeight; pScrPriv->changed = TRUE;
-    }
-
-    /* notice current mode */
-    if (newMode)
-	RRCrtcNotify (output->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;
-    
-    if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations))
-	return FALSE;
-
-#if RANDR_10_INTERFACE
-    if (pScrPriv->nSizes)
-	RRScanOldConfig (pScreen, rotations);
-#endif
-    RRTellChanged (pScreen);
-    return TRUE;
-}
-
 CARD16
 RRVerticalRefresh (xRRModeInfo *mode)
 {
@@ -602,83 +414,6 @@ RRVerticalRefresh (xRRModeInfo *mode)
     return (CARD16) refresh;
 }
 
-#if 0
-int
-RRSetScreenConfig (ScreenPtr		pScreen,
-		   Rotation		rotation,
-		   int			rate,
-		   RRScreenSizePtr	pSize)
-{
-    rrScrPrivPtr	    pScrPriv;
-    RRMonitorPtr	    pMonitor;
-    short		    oldWidth, oldHeight;
-    RRModePtr		    pMode;
-    int			    status;
-
-    pScrPriv = rrGetScrPriv(pScreen);
-    
-    if (!pScrPriv)
-	return BadImplementation;
-    
-    pMonitor = pScrPriv->pMonitors;
-    if (!pMonitor)
-	return BadImplementation;
-
-    oldWidth = pScreen->width;
-    oldHeight = pScreen->height;
-    
-    if (!RRGetInfo (pScreen))
-	return BadAlloc;
-    
-    /*
-     * 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;
-    }
-
-    for (pMode = pMonitor->pModes; pMode; pMode = pMode->next)
-    {
-	if (pMode->mode.width == pSize->width &&
-	    pMode->mode.height == pSize->height &&
-	    pMode->mode.widthInMillimeters == pSize->mmWidth &&
-	    pMode->mode.heightInMillimeters == pSize->mmHeight &&
-	    (RRVerticalRefresh (&pMode->mode) == rate || rate == 0))
-	{
-	    break;
-	}
-    }
-    if (!pMode)
-	return BadValue;
-    
-    status = RRMonitorSetMode (pScreen, pMonitor, pMode, 0, 0, 
-			       rotation, currentTime);
-    
-    if (status != RRSetConfigSuccess)
-	return BadImplementation;
-    return Success;
-}
-#endif
-
 static int
 ProcRRDispatch (ClientPtr client)
 {
@@ -697,126 +432,3 @@ SProcRRDispatch (ClientPtr client)
     return (*SProcRandrVector[stuff->data]) (client);
 }
 
-#if RANDR_12_INTERFACE
-/*
- * 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;
-    pScrPriv->minWidth  = minWidth;
-    pScrPriv->minHeight = minHeight;
-    pScrPriv->maxWidth  = maxWidth;
-    pScrPriv->maxHeight = maxHeight;
-}
-#endif
-
-#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/randrstr.h b/randr/randrstr.h
index 682ebbf..26c1806 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -53,7 +53,7 @@
 
 /* required for ABI compatibility for now */
 #define RANDR_10_INTERFACE 1
-/* #define RANDR_12_INTERFACE 1 */
+#define RANDR_12_INTERFACE 1
 
 typedef XID	RRMode;
 typedef XID	RROutput;
@@ -89,6 +89,10 @@ struct _rrCrtc {
     Bool	    changed;
     int		    numOutputs;
     RROutputPtr	    *outputs;
+    int		    gammaSize;
+    CARD16	    *gammaRed;
+    CARD16	    *gammaBlue;
+    CARD16	    *gammaGreen;
     void	    *devPrivate;
 };
 
@@ -107,11 +111,12 @@ struct _rrOutput {
     int		    numModes;
     RRModePtr	    *modes;
     Bool	    changed;
+    PropertyPtr	    properties;
     void	    *devPrivate;
 };
 
 #if RANDR_12_INTERFACE
-typedef Bool (*RRScreentSizeSetProcPtr) (ScreenPtr	pScreen,
+typedef Bool (*RRScreenSetSizeProcPtr) (ScreenPtr	pScreen,
 					CARD16		width,
 					CARD16		height,
 					CARD32		mmWidth,
@@ -125,6 +130,10 @@ typedef Bool (*RRCrtcSetProcPtr) (Screen
 				  Rotation		rotation,
 				  int			numOutputs,
 				  RROutputPtr		*outputs);
+
+typedef Bool (*RRCrtcSetGammaProcPtr) (ScreenPtr	pScreen,
+				       RRCrtcPtr	crtc);
+
 #endif
 
 typedef Bool (*RRGetInfoProcPtr) (ScreenPtr pScreen, Rotation *rotations);
@@ -167,6 +176,7 @@ typedef struct _rrScrPriv {
 #if RANDR_12_INTERFACE
     RRScreenSetSizeProcPtr  rrScreenSizeSet;
     RRCrtcSetProcPtr	    rrCrtcSet;
+    RRCrtcSetGammaProcPtr   rrCrtcSetGamma;
 #endif
     
     /*
@@ -245,6 +255,16 @@ extern RESTYPE	RRClientType, RREventType
 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)
 
@@ -284,6 +304,24 @@ RRScreenSizeSet (ScreenPtr  pScreen,
 		 CARD32	    mmHeight);
 
 /*
+ * 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
@@ -414,6 +452,33 @@ RRCrtcSet (RRCrtcPtr    crtc,
 	   RROutputPtr  *outputs);
 
 /*
+ * Request that the Crtc gamma be changed
+ */
+
+Bool
+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
+RRCrtcGammaNotify (RRCrtcPtr	crtc);
+
+/*
+ * Set the size of the gamma table at server startup time
+ */
+
+Bool
+RRCrtcGammaSetSize (RRCrtcPtr	crtc,
+		    int		size);
+
+/*
  * Destroy a Crtc at shutdown
  */
 void
@@ -425,6 +490,25 @@ RRCrtcDestroy (RRCrtcPtr crtc);
 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);
@@ -452,6 +536,18 @@ RRModeDestroy (RRModePtr mode);
 Bool
 RRModeInit (void);
     
+int
+ProcRRCreateMode (ClientPtr client);
+
+int
+ProcRRDestroyMode (ClientPtr client);
+
+int
+ProcRRAddOutputMode (ClientPtr client);
+
+int
+ProcRRDeleteOutputMode (ClientPtr client);
+
 /* rroutput.c */
 /*
  * Create an output
@@ -498,10 +594,38 @@ RRDeliverOutputEvent(ClientPtr client, W
 void
 RROutputDestroy (RROutputPtr	output);
 
+int
+ProcRRGetOutputInfo (ClientPtr client);
+
 /*
  * Initialize output type
  */
 Bool
 RROutputInit (void);
     
+/* rrproperty.c */
+
+void
+RRDeleteAllOutputProperties (RROutputPtr output);
+
+void
+RRDeleteOutputProperty (RROutputPtr output, Atom property);
+
+int
+RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
+			int format, int mode, unsigned long len,
+			pointer value, Bool sendevent);
+
+int
+ProcRRChangeOutputProperty (ClientPtr client);
+
+int
+ProcRRGetOutputProperty (ClientPtr client);
+
+int
+ProcRRListOutputProperties (ClientPtr client);
+
+int
+ProcRRDeleteOutputProperty (ClientPtr client);
+
 #endif /* _RANDRSTR_H_ */
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index d1328e7..c55e088 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -21,6 +21,7 @@
  */
 
 #include "randrstr.h"
+#include "swaprep.h"
 
 RESTYPE	RRCrtcType;
 
@@ -57,6 +58,8 @@ RRCrtcCreate (ScreenPtr	pScreen,
     crtc->rotations = RR_Rotate_0;
     crtc->outputs = NULL;
     crtc->numOutputs = 0;
+    crtc->gammaSize = 0;
+    crtc->gammaRed = crtc->gammaBlue = crtc->gammaGreen = NULL;
     crtc->changed = TRUE;
     crtc->devPrivate = devPrivate;
 
@@ -241,11 +244,75 @@ RRCrtcDestroyResource (pointer value, XI
 	    break;
 	}
     }
-    free (value);
+    if (crtc->gammaRed)
+	xfree (crtc->gammaRed);
+    xfree (value);
     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;
+    rrScrPriv(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 (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 */
+}
+
+/*
+ * 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;
+    gamma = xalloc (size * 3 * sizeof (CARD16));
+    if (!gamma)
+	return FALSE;
+    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
@@ -259,3 +326,395 @@ RRCrtcInit (void)
 #endif
     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;
+    
+    REQUEST_SIZE_MATCH(xRRGetCrtcInfoReq);
+    crtc = LookupCrtc(client, stuff->crtc, SecurityReadAccess);
+
+    if (!crtc)
+	return RRErrorBase + BadRRCrtc;
+
+    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;
+    rep.width = mode ? mode->mode.width : 0;
+    rep.height = mode ? mode->mode.height : 0;
+    rep.mode = mode->mode.id;
+    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;
+    extra = xalloc (extraLen);
+    if (!extra)
+	return BadAlloc;
+
+    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;
+    }
+    outputs = xalloc (numOutputs * sizeof (RROutputPtr));
+    if (!outputs)
+	return BadAlloc;
+    
+    outputIds = (RROutput *) (stuff + 1);
+    for (i = 0; i < numOutputs; i++)
+    {
+	outputs[i] = 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[j]->numCrtcs)
+	{
+	    if (outputs)
+		xfree (outputs);
+	    return BadMatch;
+	}
+	/* validate mode for this output */
+	for (j = 0; j < outputs[i]->numModes; j++)
+	    if (outputs[i]->modes[j] == mode)
+		break;
+	if (j == outputs[i]->numModes)
+	{
+	    if (outputs)
+		xfree (outputs);
+	    return BadMatch;
+	}
+    }
+
+    pScreen = crtc->pScreen;
+    pScrPriv = rrGetScrPriv(pScreen);
+    
+    if (!RRGetInfo (pScreen))
+    {
+	if (outputs)
+	    xfree (outputs);
+	return BadAlloc;
+    }
+    
+    time = ClientTimeToServerTime(stuff->timestamp);
+    configTime = ClientTimeToServerTime(stuff->configTimestamp);
+    
+    if (!pScrPriv)
+    {
+	time = currentTime;
+	rep.status = RRSetConfigFailed;
+	goto sendReply;
+    }
+    
+    /*
+     * 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;
+    }
+    
+    /*
+     * 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 ((~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->rrScreenSizeSet)
+    {
+	if (stuff->x + mode->mode.width > pScreen->width)
+	{
+	    client->errorValue = stuff->x;
+	    if (outputs)
+		xfree (outputs);
+	    return BadValue;
+	}
+	
+	if (stuff->y + mode->mode.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;
+    }
+
+    rep.status = RRCrtcSet (crtc, mode, stuff->x, stuff->y,
+			    rotation, numOutputs, outputs);
+    
+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_SIZE_MATCH(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
index aca0e54..49ba10b 100644
--- a/randr/rrdispatch.c
+++ b/randr/rrdispatch.c
@@ -31,79 +31,6 @@ RRClientKnowsRates (ClientPtr	pClient)
 	    (pRRClient->major_version == 1 && pRRClient->minor_version >= 1));
 }
 
-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;
-    int		    i, j, k;
-    RRScreenRatePtr refresh;
-    CARD16	    vRefresh;
-    RRModePtr	    mode;
-
-    /* Make sure there is plenty of space for any combination */
-    data = malloc (sizeof (RR10DataRec) + 
-		   sizeof (RRScreenSize) * nmode + 
-		   sizeof (RRScreenRate) * nmode);
-    if (!data)
-	return NULL;
-    size = (RRScreenSizePtr) (data + 1);
-    refresh = (RRScreenRatePtr) (size + nmode);
-    data->sizes = size;
-    data->nsize = 0;
-    data->nrefresh = 0;
-    data->size = 0;
-    data->refresh = 0;
-    for (i = 0; i < output->numModes; i++)
-    {
-	mode = output->modes[i];
-	for (j = 0; j < data->nsize; j++)
-	    if (mode->mode.width == size[j].width &&
-		mode->mode.height == size[j].height)
-		break;
-	if (j == data->nsize)
-	{
-	    size[j].id = j;
-	    size[j].width = mode->mode.width;
-	    size[j].height = mode->mode.height;
-	    size[j].mmWidth = mode->mode.mmWidth;
-	    size[j].mmHeight = mode->mode.mmHeight;
-	    size[j].nRates = 0;
-	    size[j].pRates = &refresh[data->nrefresh];
-	    data->nsize++;
-	}
-	vRefresh = RRVerticalRefresh (&mode->mode);
-	for (k = 0; k < size[j].nRates; k++)
-	    if (vRefresh == size[j].pRates[k].rate)
-		break;
-	if (k == size[j].nRates)
-	{
-	    size[j].pRates[k].rate = vRefresh;
-	    size[j].pRates[k].mode = mode;
-	    size[j].nRates++;
-	    data->nrefresh++;
-	}
-	if (mode == output->crtc->mode)
-	{
-	    data->size = j;
-	    data->refresh = vRefresh;
-	}
-    }
-    return data;
-}
-
 static int
 ProcRRQueryVersion (ClientPtr client)
 {
@@ -135,341 +62,6 @@ ProcRRQueryVersion (ClientPtr client)
 }
 
 static 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 = (WindowPtr)SecurityLookupWindow(stuff->window, client,
-					   SecurityReadAccess);
-
-    if (!pWin)
-	return BadWindow;
-
-    pScreen = pWin->drawable.pScreen;
-    pScrPriv = rrGetScrPriv(pScreen);
-    rep.pad = 0;
-    
-    if (pScrPriv)
-	RRGetInfo (pScreen);
-
-    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));
-
-	extra = (CARD8 *) xalloc (extraLen);
-	if (!extra)
-	{
-	    xfree (pData);
-	    return BadAlloc;
-	}
-	/*
-	 * 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);
-}
-
-static int
-ProcRRSetScreenConfig (ClientPtr client)
-{
-    REQUEST(xRRSetScreenConfigReq);
-    xRRSetScreenConfigReply rep;
-    DrawablePtr		    pDraw;
-    int			    n;
-    ScreenPtr		    pScreen;
-    rrScrPrivPtr	    pScrPriv;
-    TimeStamp		    configTime;
-    TimeStamp		    time;
-    int			    i;
-    Rotation		    rotation;
-    int			    rate;
-    Bool		    has_rate;
-    RROutputPtr		    output;
-    RRModePtr		    mode;
-    RR10DataPtr		    pData = NULL;
-    RRScreenSizePtr    	    pSize;
-    
-    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);
-    
-    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;
-    }
-    
-    /*
-     * 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;
-    }
-    
-    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 ((~output->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;
-    }
-
-    rep.status = RRCrtcSet (output->crtc, mode, 0, 0, stuff->rotation,
-			    1, &output);
-    
-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 int
 ProcRRSelectInput (ClientPtr client)
 {
     REQUEST(xRRSelectInputReq);
@@ -584,633 +176,6 @@ ProcRRSelectInput (ClientPtr client)
     return Success;
 }
 
-/*
- * Retrieve valid screen size range
- */
-static int 
-ProcRRGetScreenSizeRange (ClientPtr client)
-{
-    REQUEST(xRRGetScreenSizeRangeReq);
-    xRRGetScreenSizeRangeReply	rep;
-    WindowPtr			pWin;
-    ScreenPtr			pScreen;
-    rrScrPrivPtr		pScrPriv;
-    
-    REQUEST_SIZE_MATCH(xRRGetScreenInfoReq);
-    pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
-					   SecurityReadAccess);
-
-    if (!pWin)
-	return BadWindow;
-
-    pScreen = pWin->drawable.pScreen;
-    pScrPriv = rrGetScrPriv(pScreen);
-    
-    rep.type = X_Reply;
-    rep.pad = 0;
-    rep.sequenceNumber = client->sequence;
-    rep.length = 0;
-    
-    if (pScrPriv) 
-    {
-	RRGetInfo (pScreen);
-	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);
-}
-
-static int ProcRRSetScreenSize (ClientPtr client)
-{
-    REQUEST(xRRSetScreenSizeReq);
-    WindowPtr		pWin;
-    ScreenPtr		pScreen;
-    rrScrPrivPtr	pScrPriv;
-    RRCrtcPtr		crtc;
-    int			i;
-    
-    REQUEST_SIZE_MATCH(xRRSetScreenSizeReq);
-    pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
-					   SecurityReadAccess);
-
-    if (!pWin)
-	return BadWindow;
-
-    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++) {
-	crtc = pScrPriv->crtcs[i];
-	if (crtc->mode &&
-	    (crtc->x + crtc->mode->mode.width > stuff->width ||
-	     crtc->y + crtc->mode->mode.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;
-}
-
-static int
-ProcRRGetScreenResources (ClientPtr client)
-{
-    REQUEST(xRRGetScreenResourcesReq);
-    xRRGetScreenResourcesReply  rep;
-    WindowPtr			pWin;
-    ScreenPtr			pScreen;
-    rrScrPrivPtr		pScrPriv;
-    CARD8			*extra;
-    unsigned long		extraLen;
-    int				i;
-    RRCrtc			*crtcs;
-    RROutput			*outputs;
-    xRRModeInfo			*modeinfos;
-    CARD8			*names;
-    int				n;
-    
-    REQUEST_SIZE_MATCH(xRRGetScreenResourcesReq);
-    pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
-					   SecurityReadAccess);
-
-    if (!pWin)
-	return BadWindow;
-    
-    pScreen = pWin->drawable.pScreen;
-    pScrPriv = rrGetScrPriv(pScreen);
-    rep.pad = 0;
-    
-    if (pScrPriv)
-	RRGetInfo (pScreen);
-
-    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
-    {
-	rep.type = X_Reply;
-	rep.sequenceNumber = client->sequence;
-	rep.length = 0;
-	rep.timestamp = currentTime.milliseconds;
-	rep.configTimestamp = currentTime.milliseconds;
-	rep.nCrtcs = pScrPriv->numCrtcs;
-	rep.nOutputs = pScrPriv->numOutputs;
-	rep.nModes = pScrPriv->numModes;;
-	rep.nbytesNames = 0;
-
-	for (i = 0; i < pScrPriv->numModes; i++)
-	    rep.nbytesNames += pScrPriv->modes[i]->mode.nameLength;
-
-	rep.length = (pScrPriv->numCrtcs + 
-		      pScrPriv->numOutputs + 
-		      pScrPriv->numModes * 10 +
-		      ((rep.nbytesNames + 3) >> 2));
-	
-	extraLen = rep.length << 2;
-	extra = xalloc (extraLen);
-	if (!extra)
-	    return BadAlloc;
-
-	crtcs = (RRCrtc *) extra;
-	outputs = (RROutput *) (crtcs + pScrPriv->numCrtcs);
-	modeinfos = (xRRModeInfo *) (outputs + pScrPriv->numOutputs);
-	names = (CARD8 *) (modeinfos + pScrPriv->numModes);
-	
-	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 < pScrPriv->numModes; i++)
-	{
-	    modeinfos[i] = pScrPriv->modes[i]->mode;
-	    if (client->swapped)
-	    {
-		swapl (&modeinfos[i].id, n);
-		swaps (&modeinfos[i].width, n);
-		swaps (&modeinfos[i].height, n);
-		swapl (&modeinfos[i].mmWidth, n);
-		swapl (&modeinfos[i].mmHeight, 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, pScrPriv->modes[i]->name, 
-		    pScrPriv->modes[i]->mode.nameLength);
-	    names += pScrPriv->modes[i]->mode.nameLength;
-	}
-	assert ((names + 3 >> 3) == 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;
-}
-
-static 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 = (RROutputPtr)SecurityLookupIDByType(client, stuff->output, 
-						 RROutputType, 
-						 SecurityReadAccess);
-
-    if (!output)
-	return RRErrorBase + BadRROutput;
-
-    pScreen = output->pScreen;
-    pScrPriv = rrGetScrPriv(pScreen);
-
-    rep.type = X_Reply;
-    rep.sequenceNumber = client->sequence;
-    rep.length = 0;
-    rep.timestamp = pScrPriv->lastSetTime.milliseconds;
-    rep.crtc = output->crtc ? output->crtc->id : None;
-    rep.connection = output->connection;
-    rep.subpixelOrder = output->subpixelOrder;
-    rep.nCrtcs = output->numCrtcs;
-    rep.nModes = output->numModes;
-    rep.nClones = output->numClones;
-    rep.nameLength = output->nameLength;
-    
-    rep.length = (output->numCrtcs + 
-		  output->numModes + 
-		  output->numClones +
-		  ((rep.nameLength + 3) >> 2));
-
-    extraLen = rep.length << 2;
-    extra = xalloc (extraLen);
-    if (!extra)
-	return BadAlloc;
-
-    crtcs = (RRCrtc *) extra;
-    modes = (RRMode *) (crtcs + output->numCrtcs);
-    clones = (RROutput *) (modes + output->numModes);
-    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; i++)
-    {
-	modes[i] = output->modes[i]->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);
-	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;
-}
-
-static int
-ProcRRListOutputProperties (ClientPtr client)
-{
-    REQUEST(xRRListOutputPropertiesReq);
-    
-    REQUEST_SIZE_MATCH(xRRListOutputPropertiesReq);
-    (void) stuff;
-    return BadImplementation; 
-}
-
-static int
-ProcRRChangeOutputProperty (ClientPtr client)
-{
-    REQUEST(xRRChangeOutputPropertyReq);
-    
-    REQUEST_SIZE_MATCH(xRRChangeOutputPropertyReq);
-    (void) stuff;
-    return BadImplementation; 
-}
-
-static int
-ProcRRDeleteOutputProperty (ClientPtr client)
-{
-    REQUEST(xRRDeleteOutputPropertyReq);
-    
-    REQUEST_SIZE_MATCH(xRRDeleteOutputPropertyReq);
-    (void) stuff;
-    return BadImplementation; 
-}
-
-static int
-ProcRRGetOutputProperty (ClientPtr client)
-{
-    REQUEST(xRRGetOutputPropertyReq);
-    
-    REQUEST_SIZE_MATCH(xRRGetOutputPropertyReq);
-    (void) stuff;
-    return BadImplementation; 
-}
-
-static int
-ProcRRCreateMode (ClientPtr client)
-{
-    REQUEST(xRRCreateModeReq);
-    
-    REQUEST_SIZE_MATCH(xRRCreateModeReq);
-    (void) stuff;
-    return BadImplementation; 
-}
-
-static int
-ProcRRDestroyMode (ClientPtr client)
-{
-    REQUEST(xRRDestroyModeReq);
-    
-    REQUEST_SIZE_MATCH(xRRDestroyModeReq);
-    (void) stuff;
-    return BadImplementation; 
-}
-
-static int
-ProcRRAddOutputMode (ClientPtr client)
-{
-    REQUEST(xRRAddOutputModeReq);
-    
-    REQUEST_SIZE_MATCH(xRRAddOutputModeReq);
-    (void) stuff;
-    return BadImplementation; 
-}
-
-static int
-ProcRRDeleteOutputMode (ClientPtr client)
-{
-    REQUEST(xRRDeleteOutputModeReq);
-    
-    REQUEST_SIZE_MATCH(xRRDeleteOutputModeReq);
-    (void) stuff;
-    return BadImplementation; 
-}
-
-static int
-ProcRRGetCrtcInfo (ClientPtr client)
-{
-    REQUEST(xRRGetCrtcInfoReq);
-    
-    REQUEST_SIZE_MATCH(xRRGetCrtcInfoReq);
-    (void) stuff;
-    return BadImplementation; 
-}
-
-static 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;
-    }
-    outputs = xalloc (numOutputs * sizeof (RROutputPtr));
-    if (!outputs)
-	return BadAlloc;
-    
-    outputIds = (RROutput *) (stuff + 1);
-    for (i = 0; i < numOutputs; i++)
-    {
-	outputs[i] = LookupIDByType (outputIds[i], RROutputType);
-	if (!outputs[i])
-	{
-	    client->errorValue = outputIds[i];
-	    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[j]->numCrtcs)
-	    return BadMatch;
-	/* validate mode for this output */
-	for (j = 0; j < outputs[i]->numModes; j++)
-	    if (outputs[i]->modes[j] == mode)
-		break;
-	if (j == outputs[j]->numModes)
-	    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 (!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;
-    }
-    
-    /*
-     * 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 ((~crtc->rotations) & rotation)
-    {
-	/*
-	 * requested rotation or reflection not supported by screen
-	 */
-	client->errorValue = stuff->rotation;
-	return BadMatch;
-    }
-
-    if (stuff->x + mode->mode.width > pScreen->width)
-    {
-	client->errorValue = stuff->x;
-	return BadValue;
-    }
-    
-    if (stuff->y + mode->mode.height > pScreen->height)
-    {
-	client->errorValue = stuff->y;
-	return BadValue;
-    }
-    
-    /*
-     * 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;
-    }
-
-    rep.status = RRCrtcSet (crtc, mode, stuff->x, stuff->y,
-			    rotation, numOutputs, outputs);
-    
-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;
-}
-
-static int
-ProcRRGetCrtcGammaSize (ClientPtr client)
-{
-    REQUEST(xRRGetCrtcGammaSizeReq);
-    
-    REQUEST_SIZE_MATCH(xRRGetCrtcGammaSizeReq);
-    (void) stuff;
-    return BadImplementation; 
-}
-
-static int
-ProcRRGetCrtcGamma (ClientPtr client)
-{
-    REQUEST(xRRGetCrtcGammaReq);
-    
-    REQUEST_SIZE_MATCH(xRRGetCrtcGammaReq);
-    (void) stuff;
-    return BadImplementation; 
-}
-
-static int
-ProcRRSetCrtcGamma (ClientPtr client)
-{
-    REQUEST(xRRSetCrtcGammaReq);
-    
-    REQUEST_SIZE_MATCH(xRRSetCrtcGammaReq);
-    (void) stuff;
-    return BadImplementation; 
-}
-
 int (*ProcRandrVector[RRNumberRequests])(ClientPtr) = {
     ProcRRQueryVersion,	/* 0 */
 /* we skip 1 to make old clients fail pretty immediately */
diff --git a/randr/rrmode.c b/randr/rrmode.c
index 4e44e7d..ab0ea18 100644
--- a/randr/rrmode.c
+++ b/randr/rrmode.c
@@ -103,3 +103,44 @@ RRModeInit (void)
 #endif
     return TRUE;
 }
+
+int
+ProcRRCreateMode (ClientPtr client)
+{
+    REQUEST(xRRCreateModeReq);
+    
+    REQUEST_SIZE_MATCH(xRRCreateModeReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+int
+ProcRRDestroyMode (ClientPtr client)
+{
+    REQUEST(xRRDestroyModeReq);
+    
+    REQUEST_SIZE_MATCH(xRRDestroyModeReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+int
+ProcRRAddOutputMode (ClientPtr client)
+{
+    REQUEST(xRRAddOutputModeReq);
+    
+    REQUEST_SIZE_MATCH(xRRAddOutputModeReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+int
+ProcRRDeleteOutputMode (ClientPtr client)
+{
+    REQUEST(xRRDeleteOutputModeReq);
+    
+    REQUEST_SIZE_MATCH(xRRDeleteOutputModeReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
diff --git a/randr/rroutput.c b/randr/rroutput.c
index 4780023..07dabad 100644
--- a/randr/rroutput.c
+++ b/randr/rroutput.c
@@ -66,6 +66,7 @@ RROutputCreate (ScreenPtr   pScreen,
     output->clones = NULL;
     output->numModes = 0;
     output->modes = NULL;
+    output->properties = NULL;
     output->changed = TRUE;
     output->devPrivate = devPrivate;
     
@@ -201,12 +202,13 @@ RROutputDestroyResource (pointer value, 
 	xfree (output->crtcs);
     if (output->clones)
 	xfree (output->clones);
+    RRDeleteAllOutputProperties (output);
     xfree (output);
     return 1;
 }
 
 /*
- * Initialize crtc type
+ * Initialize output type
  */
 Bool
 RROutputInit (void)
@@ -219,3 +221,95 @@ RROutputInit (void)
 #endif
     return TRUE;
 }
+
+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)
+	return RRErrorBase + BadRROutput;
+
+    pScreen = output->pScreen;
+    pScrPriv = rrGetScrPriv(pScreen);
+
+    rep.type = X_Reply;
+    rep.sequenceNumber = client->sequence;
+    rep.length = 0;
+    rep.timestamp = pScrPriv->lastSetTime.milliseconds;
+    rep.crtc = output->crtc ? output->crtc->id : None;
+    rep.connection = output->connection;
+    rep.subpixelOrder = output->subpixelOrder;
+    rep.nCrtcs = output->numCrtcs;
+    rep.nModes = output->numModes;
+    rep.nClones = output->numClones;
+    rep.nameLength = output->nameLength;
+    
+    rep.length = (output->numCrtcs + 
+		  output->numModes + 
+		  output->numClones +
+		  ((rep.nameLength + 3) >> 2));
+
+    extraLen = rep.length << 2;
+    extra = xalloc (extraLen);
+    if (!extra)
+	return BadAlloc;
+
+    crtcs = (RRCrtc *) extra;
+    modes = (RRMode *) (crtcs + output->numCrtcs);
+    clones = (RROutput *) (modes + output->numModes);
+    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; i++)
+    {
+	modes[i] = output->modes[i]->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);
+	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/rrscreen.c b/randr/rrscreen.c
index 47ba12d..58d5152 100644
--- a/randr/rrscreen.c
+++ b/randr/rrscreen.c
@@ -203,3 +203,654 @@ RRScreenSizeSet (ScreenPtr  pScreen,
     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 = (WindowPtr)SecurityLookupWindow(stuff->window, client,
+					   SecurityReadAccess);
+
+    if (!pWin)
+	return BadWindow;
+
+    pScreen = pWin->drawable.pScreen;
+    pScrPriv = rrGetScrPriv(pScreen);
+    
+    rep.type = X_Reply;
+    rep.pad = 0;
+    rep.sequenceNumber = client->sequence;
+    rep.length = 0;
+    
+    if (pScrPriv) 
+    {
+	RRGetInfo (pScreen);
+	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;
+    RRCrtcPtr		crtc;
+    int			i;
+    
+    REQUEST_SIZE_MATCH(xRRSetScreenSizeReq);
+    pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
+					   SecurityReadAccess);
+
+    if (!pWin)
+	return BadWindow;
+
+    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++) {
+	crtc = pScrPriv->crtcs[i];
+	if (crtc->mode &&
+	    (crtc->x + crtc->mode->mode.width > stuff->width ||
+	     crtc->y + crtc->mode->mode.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;
+    RRCrtc			*crtcs;
+    RROutput			*outputs;
+    xRRModeInfo			*modeinfos;
+    CARD8			*names;
+    int				n;
+    
+    REQUEST_SIZE_MATCH(xRRGetScreenResourcesReq);
+    pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
+					   SecurityReadAccess);
+
+    if (!pWin)
+	return BadWindow;
+    
+    pScreen = pWin->drawable.pScreen;
+    pScrPriv = rrGetScrPriv(pScreen);
+    rep.pad = 0;
+    
+    if (pScrPriv)
+	RRGetInfo (pScreen);
+
+    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
+    {
+	rep.type = X_Reply;
+	rep.sequenceNumber = client->sequence;
+	rep.length = 0;
+	rep.timestamp = currentTime.milliseconds;
+	rep.configTimestamp = currentTime.milliseconds;
+	rep.nCrtcs = pScrPriv->numCrtcs;
+	rep.nOutputs = pScrPriv->numOutputs;
+	rep.nModes = pScrPriv->numModes;;
+	rep.nbytesNames = 0;
+
+	for (i = 0; i < pScrPriv->numModes; i++)
+	    rep.nbytesNames += pScrPriv->modes[i]->mode.nameLength;
+
+	rep.length = (pScrPriv->numCrtcs + 
+		      pScrPriv->numOutputs + 
+		      pScrPriv->numModes * 10 +
+		      ((rep.nbytesNames + 3) >> 2));
+	
+	extraLen = rep.length << 2;
+	extra = xalloc (extraLen);
+	if (!extra)
+	    return BadAlloc;
+
+	crtcs = (RRCrtc *) extra;
+	outputs = (RROutput *) (crtcs + pScrPriv->numCrtcs);
+	modeinfos = (xRRModeInfo *) (outputs + pScrPriv->numOutputs);
+	names = (CARD8 *) (modeinfos + pScrPriv->numModes);
+	
+	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 < pScrPriv->numModes; i++)
+	{
+	    modeinfos[i] = pScrPriv->modes[i]->mode;
+	    if (client->swapped)
+	    {
+		swapl (&modeinfos[i].id, n);
+		swaps (&modeinfos[i].width, n);
+		swaps (&modeinfos[i].height, n);
+		swapl (&modeinfos[i].mmWidth, n);
+		swapl (&modeinfos[i].mmHeight, 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, pScrPriv->modes[i]->name, 
+		    pScrPriv->modes[i]->mode.nameLength);
+	    names += pScrPriv->modes[i]->mode.nameLength;
+	}
+	assert ((names + 3 >> 3) == 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;
+    int		    i, j, k;
+    RRScreenRatePtr refresh;
+    CARD16	    vRefresh;
+    RRModePtr	    mode;
+
+    /* Make sure there is plenty of space for any combination */
+    data = malloc (sizeof (RR10DataRec) + 
+		   sizeof (RRScreenSize) * nmode + 
+		   sizeof (RRScreenRate) * nmode);
+    if (!data)
+	return NULL;
+    size = (RRScreenSizePtr) (data + 1);
+    refresh = (RRScreenRatePtr) (size + nmode);
+    data->sizes = size;
+    data->nsize = 0;
+    data->nrefresh = 0;
+    data->size = 0;
+    data->refresh = 0;
+    for (i = 0; i < output->numModes; i++)
+    {
+	mode = output->modes[i];
+	for (j = 0; j < data->nsize; j++)
+	    if (mode->mode.width == size[j].width &&
+		mode->mode.height == size[j].height)
+		break;
+	if (j == data->nsize)
+	{
+	    size[j].id = j;
+	    size[j].width = mode->mode.width;
+	    size[j].height = mode->mode.height;
+	    size[j].mmWidth = mode->mode.mmWidth;
+	    size[j].mmHeight = mode->mode.mmHeight;
+	    size[j].nRates = 0;
+	    size[j].pRates = &refresh[data->nrefresh];
+	    data->nsize++;
+	}
+	vRefresh = RRVerticalRefresh (&mode->mode);
+	for (k = 0; k < size[j].nRates; k++)
+	    if (vRefresh == size[j].pRates[k].rate)
+		break;
+	if (k == size[j].nRates)
+	{
+	    size[j].pRates[k].rate = vRefresh;
+	    size[j].pRates[k].mode = mode;
+	    size[j].nRates++;
+	    data->nrefresh++;
+	}
+	if (mode == output->crtc->mode)
+	{
+	    data->size = j;
+	    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 = (WindowPtr)SecurityLookupWindow(stuff->window, client,
+					   SecurityReadAccess);
+
+    if (!pWin)
+	return BadWindow;
+
+    pScreen = pWin->drawable.pScreen;
+    pScrPriv = rrGetScrPriv(pScreen);
+    rep.pad = 0;
+    
+    if (pScrPriv)
+	RRGetInfo (pScreen);
+
+    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));
+
+	extra = (CARD8 *) xalloc (extraLen);
+	if (!extra)
+	{
+	    xfree (pData);
+	    return BadAlloc;
+	}
+	/*
+	 * 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;
+    ScreenPtr		    pScreen;
+    rrScrPrivPtr	    pScrPriv;
+    TimeStamp		    configTime;
+    TimeStamp		    time;
+    int			    i;
+    Rotation		    rotation;
+    int			    rate;
+    Bool		    has_rate;
+    RROutputPtr		    output;
+    RRModePtr		    mode;
+    RR10DataPtr		    pData = NULL;
+    RRScreenSizePtr    	    pSize;
+    
+    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);
+    
+    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;
+    }
+    
+    /*
+     * 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;
+    }
+    
+    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 ((~output->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;
+    }
+
+    rep.status = RRCrtcSet (output->crtc, mode, 0, 0, stuff->rotation,
+			    1, &output);
+    
+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);
+}
+
diff-tree 7f9b59d80deb08b8427fdd1b6346390387725137 (from 0b22ab2f492c3a4a2ebab99f0da25f92e06117c3)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Tue Sep 19 00:46:27 2006 -0700

    RRGetScreenResources and RRGetOutputInfo are working now.
    
    Removed separate id field in RRModeRec.
    Pull screen subpixel order from Render extension.
    Implement RGetScreenResources and RRGetOutputInfo

diff --git a/randr/randr.c b/randr/randr.c
index 926e32f..beddb50 100644
--- a/randr/randr.c
+++ b/randr/randr.c
@@ -442,7 +442,7 @@ RROldModeAdd (RROutputPtr output, RRScre
     if (!modes)
     {
 	RRModeDestroy (mode);
-	FreeResource (mode->id, 0);
+	FreeResource (mode->mode.id, 0);
 	return NULL;
     }
     modes[output->numModes++] = mode;
@@ -479,6 +479,9 @@ RRScanOldConfig (ScreenPtr pScreen, Rota
 	RROutputSetCrtcs (output, &crtc, 1);
 	RROutputSetCrtc (output, crtc);
 	RROutputSetConnection (output, RR_Connected);
+#ifdef RENDER
+	RROutputSetSubpixelOrder (output, PictureGetSubpixelOrder (pScreen));
+#endif
     }
 
     output = RRFirstOutput (pScreen);
diff --git a/randr/randrstr.h b/randr/randrstr.h
index a7f91b7..682ebbf 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -74,7 +74,6 @@ typedef struct _rrCrtc	    RRCrtcRec, *R
 typedef struct _rrOutput    RROutputRec, *RROutputPtr;
 
 struct _rrMode {
-    RRMode	    id;
     int		    refcnt;
     xRRModeInfo	    mode;
     char	    *name;
@@ -489,6 +488,10 @@ Bool
 RROutputSetConnection (RROutputPtr  output,
 		       CARD8	    connection);
 
+Bool
+RROutputSetSubpixelOrder (RROutputPtr output,
+			  int	      subpixelOrder);
+
 void
 RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output);
 
diff --git a/randr/rrdispatch.c b/randr/rrdispatch.c
index 279acfd..aca0e54 100644
--- a/randr/rrdispatch.c
+++ b/randr/rrdispatch.c
@@ -694,20 +694,229 @@ static int
 ProcRRGetScreenResources (ClientPtr client)
 {
     REQUEST(xRRGetScreenResourcesReq);
+    xRRGetScreenResourcesReply  rep;
+    WindowPtr			pWin;
+    ScreenPtr			pScreen;
+    rrScrPrivPtr		pScrPriv;
+    CARD8			*extra;
+    unsigned long		extraLen;
+    int				i;
+    RRCrtc			*crtcs;
+    RROutput			*outputs;
+    xRRModeInfo			*modeinfos;
+    CARD8			*names;
+    int				n;
     
     REQUEST_SIZE_MATCH(xRRGetScreenResourcesReq);
-    (void) stuff;
-    return BadImplementation; 
+    pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
+					   SecurityReadAccess);
+
+    if (!pWin)
+	return BadWindow;
+    
+    pScreen = pWin->drawable.pScreen;
+    pScrPriv = rrGetScrPriv(pScreen);
+    rep.pad = 0;
+    
+    if (pScrPriv)
+	RRGetInfo (pScreen);
+
+    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
+    {
+	rep.type = X_Reply;
+	rep.sequenceNumber = client->sequence;
+	rep.length = 0;
+	rep.timestamp = currentTime.milliseconds;
+	rep.configTimestamp = currentTime.milliseconds;
+	rep.nCrtcs = pScrPriv->numCrtcs;
+	rep.nOutputs = pScrPriv->numOutputs;
+	rep.nModes = pScrPriv->numModes;;
+	rep.nbytesNames = 0;
+
+	for (i = 0; i < pScrPriv->numModes; i++)
+	    rep.nbytesNames += pScrPriv->modes[i]->mode.nameLength;
+
+	rep.length = (pScrPriv->numCrtcs + 
+		      pScrPriv->numOutputs + 
+		      pScrPriv->numModes * 10 +
+		      ((rep.nbytesNames + 3) >> 2));
+	
+	extraLen = rep.length << 2;
+	extra = xalloc (extraLen);
+	if (!extra)
+	    return BadAlloc;
+
+	crtcs = (RRCrtc *) extra;
+	outputs = (RROutput *) (crtcs + pScrPriv->numCrtcs);
+	modeinfos = (xRRModeInfo *) (outputs + pScrPriv->numOutputs);
+	names = (CARD8 *) (modeinfos + pScrPriv->numModes);
+	
+	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 < pScrPriv->numModes; i++)
+	{
+	    modeinfos[i] = pScrPriv->modes[i]->mode;
+	    if (client->swapped)
+	    {
+		swapl (&modeinfos[i].id, n);
+		swaps (&modeinfos[i].width, n);
+		swaps (&modeinfos[i].height, n);
+		swapl (&modeinfos[i].mmWidth, n);
+		swapl (&modeinfos[i].mmHeight, 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, pScrPriv->modes[i]->name, 
+		    pScrPriv->modes[i]->mode.nameLength);
+	    names += pScrPriv->modes[i]->mode.nameLength;
+	}
+	assert ((names + 3 >> 3) == 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;
 }
 
 static 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);
-    (void) stuff;
-    return BadImplementation; 
+    output = (RROutputPtr)SecurityLookupIDByType(client, stuff->output, 
+						 RROutputType, 
+						 SecurityReadAccess);
+
+    if (!output)
+	return RRErrorBase + BadRROutput;
+
+    pScreen = output->pScreen;
+    pScrPriv = rrGetScrPriv(pScreen);
+
+    rep.type = X_Reply;
+    rep.sequenceNumber = client->sequence;
+    rep.length = 0;
+    rep.timestamp = pScrPriv->lastSetTime.milliseconds;
+    rep.crtc = output->crtc ? output->crtc->id : None;
+    rep.connection = output->connection;
+    rep.subpixelOrder = output->subpixelOrder;
+    rep.nCrtcs = output->numCrtcs;
+    rep.nModes = output->numModes;
+    rep.nClones = output->numClones;
+    rep.nameLength = output->nameLength;
+    
+    rep.length = (output->numCrtcs + 
+		  output->numModes + 
+		  output->numClones +
+		  ((rep.nameLength + 3) >> 2));
+
+    extraLen = rep.length << 2;
+    extra = xalloc (extraLen);
+    if (!extra)
+	return BadAlloc;
+
+    crtcs = (RRCrtc *) extra;
+    modes = (RRMode *) (crtcs + output->numCrtcs);
+    clones = (RROutput *) (modes + output->numModes);
+    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; i++)
+    {
+	modes[i] = output->modes[i]->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);
+	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;
 }
 
 static int
diff --git a/randr/rrmode.c b/randr/rrmode.c
index 52585d9..4e44e7d 100644
--- a/randr/rrmode.c
+++ b/randr/rrmode.c
@@ -37,6 +37,7 @@ RRModeGet (ScreenPtr	pScreen,
     for (i = 0; i < pScrPriv->numModes; i++)
     {
 	mode = pScrPriv->modes[i];
+	modeInfo->id = mode->mode.id;
 	if (!memcmp (modeInfo, &mode->mode, sizeof (xRRModeInfo)) &&
 	    !memcmp (name, mode->name, modeInfo->nameLength))
 	{
@@ -66,8 +67,8 @@ RRModeGet (ScreenPtr	pScreen,
 	return NULL;
     }
 
-    mode->id = FakeClientID(0);
-    if (!AddResource (mode->id, RRModeType, (pointer) mode))
+    mode->mode.id = FakeClientID(0);
+    if (!AddResource (mode->mode.id, RRModeType, (pointer) mode))
 	return NULL;
     ++mode->refcnt;
     pScrPriv->modes = modes;
diff --git a/randr/rroutput.c b/randr/rroutput.c
index ba5bcb4..4780023 100644
--- a/randr/rroutput.c
+++ b/randr/rroutput.c
@@ -154,6 +154,15 @@ RROutputSetConnection (RROutputPtr  outp
     return TRUE;
 }
 
+Bool
+RROutputSetSubpixelOrder (RROutputPtr output,
+			  int	      subpixelOrder)
+{
+    output->subpixelOrder = subpixelOrder;
+    output->changed = TRUE;
+    return TRUE;
+}
+
 void
 RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output)
 {
diff-tree 0b22ab2f492c3a4a2ebab99f0da25f92e06117c3 (from db4576798e0012f0558f3faac10cbb26a2fbec34)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Mon Sep 18 12:18:22 2006 -0700

    RandR working with old clients and old API.

diff --git a/randr/randr.c b/randr/randr.c
index 63d471c..926e32f 100644
--- a/randr/randr.c
+++ b/randr/randr.c
@@ -477,6 +477,7 @@ RRScanOldConfig (ScreenPtr pScreen, Rota
 	if (!output)
 	    return;
 	RROutputSetCrtcs (output, &crtc, 1);
+	RROutputSetCrtc (output, crtc);
 	RROutputSetConnection (output, RR_Connected);
     }
 
@@ -552,8 +553,8 @@ RRScanOldConfig (ScreenPtr pScreen, Rota
 
     /* notice current mode */
     if (newMode)
-	RRCrtcSet (output->crtc, newMode, 0, 0, pScrPriv->rotation,
-		   1, &output);
+	RRCrtcNotify (output->crtc, newMode, 0, 0, pScrPriv->rotation,
+		      1, &output);
 }
 #endif
 
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 3346157..a7f91b7 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -482,6 +482,9 @@ RROutputSetCrtcs (RROutputPtr	output,
 		  RRCrtcPtr	*crtcs,
 		  int		numCrtcs);
 
+void
+RROutputSetCrtc (RROutputPtr output, RRCrtcPtr crtc);
+    
 Bool
 RROutputSetConnection (RROutputPtr  output,
 		       CARD8	    connection);
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index d343c3a..d1328e7 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -59,7 +59,13 @@ RRCrtcCreate (ScreenPtr	pScreen,
     crtc->numOutputs = 0;
     crtc->changed = TRUE;
     crtc->devPrivate = devPrivate;
+
+    if (!AddResource (crtc->id, RRCrtcType, (pointer) crtc))
+	return NULL;
+
+    pScrPriv->crtcs = crtcs;
     pScrPriv->crtcs[pScrPriv->numCrtcs++] = crtc;
+    pScrPriv->changed = TRUE;
     return crtc;
 }
 
@@ -165,6 +171,16 @@ RRCrtcSet (RRCrtcPtr    crtc,
     ScreenPtr	pScreen = crtc->pScreen;
     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)))
+    {
+	return TRUE;
+    }
 #if RANDR_12_INTERFACE
     if (pScrPriv->rrCrtcSet)
     {
diff --git a/randr/rrdispatch.c b/randr/rrdispatch.c
index acf6298..279acfd 100644
--- a/randr/rrdispatch.c
+++ b/randr/rrdispatch.c
@@ -824,7 +824,7 @@ ProcRRSetCrtcConfig (ClientPtr client)
     if (!crtc)
     {
 	client->errorValue = stuff->crtc;
-	return RRErrorBase + BadCrtc;
+	return RRErrorBase + BadRRCrtc;
     }
     if (stuff->mode == None)
     {
@@ -838,7 +838,7 @@ ProcRRSetCrtcConfig (ClientPtr client)
 	if (!mode)
 	{
 	    client->errorValue = stuff->mode;
-	    return RRErrorBase + BadMode;
+	    return RRErrorBase + BadRRMode;
 	}
 	if (numOutputs == 0)
 	    return BadMatch;
@@ -854,7 +854,7 @@ ProcRRSetCrtcConfig (ClientPtr client)
 	if (!outputs[i])
 	{
 	    client->errorValue = outputIds[i];
-	    return RRErrorBase + BadOutput;
+	    return RRErrorBase + BadRROutput;
 	}
 	/* validate crtc for this output */
 	for (j = 0; j < outputs[i]->numCrtcs; j++)
diff --git a/randr/rrmode.c b/randr/rrmode.c
index 3a9d556..52585d9 100644
--- a/randr/rrmode.c
+++ b/randr/rrmode.c
@@ -32,6 +32,7 @@ RRModeGet (ScreenPtr	pScreen,
     rrScrPriv (pScreen);
     int	i;
     RRModePtr	mode;
+    RRModePtr	*modes;
 
     for (i = 0; i < pScrPriv->numModes; i++)
     {
@@ -43,16 +44,34 @@ RRModeGet (ScreenPtr	pScreen,
 	    return mode;
 	}
     }
+
     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';
+
+    if (pScrPriv->numModes)
+	modes = xrealloc (pScrPriv->modes,
+			  (pScrPriv->numModes + 1) * sizeof (RRModePtr));
+    else
+	modes = xalloc (sizeof (RRModePtr));
+
+    if (!modes)
+    {
+	xfree (mode);
+	return NULL;
+    }
+
     mode->id = FakeClientID(0);
     if (!AddResource (mode->id, RRModeType, (pointer) mode))
 	return NULL;
     ++mode->refcnt;
+    pScrPriv->modes = modes;
+    pScrPriv->modes[pScrPriv->numModes++] = mode;
     pScrPriv->changed = TRUE;
     return mode;
 }
diff --git a/randr/rroutput.c b/randr/rroutput.c
index 6b67f19..ba5bcb4 100644
--- a/randr/rroutput.c
+++ b/randr/rroutput.c
@@ -56,6 +56,7 @@ RROutputCreate (ScreenPtr   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->crtc = NULL;
@@ -67,7 +68,13 @@ RROutputCreate (ScreenPtr   pScreen,
     output->modes = NULL;
     output->changed = TRUE;
     output->devPrivate = devPrivate;
+    
+    if (!AddResource (output->id, RROutputType, (pointer) output))
+	return NULL;
+
+    pScrPriv->outputs = outputs;
     pScrPriv->outputs[pScrPriv->numOutputs++] = output;
+    pScrPriv->changed = TRUE;
     return output;
 }
 
@@ -89,6 +96,7 @@ RROutputSetClones (RROutputPtr  output,
     memcpy (newClones, clones, numClones * sizeof (RROutputPtr));
     output->clones = newClones;
     output->numClones = numClones;
+    output->changed = TRUE;
     return TRUE;
 }
 
@@ -107,6 +115,7 @@ RROutputSetModes (RROutputPtr	output,
     memcpy (newModes, modes, numModes * sizeof (RRModePtr));
     output->modes = newModes;
     output->numModes = numModes;
+    output->changed = TRUE;
     return TRUE;
 }
 
@@ -125,14 +134,23 @@ RROutputSetCrtcs (RROutputPtr	output,
     memcpy (newCrtcs, crtcs, numCrtcs * sizeof (RRCrtcPtr));
     output->crtcs = newCrtcs;
     output->numCrtcs = numCrtcs;
+    output->changed = TRUE;
     return TRUE;
 }
 
+void
+RROutputSetCrtc (RROutputPtr output, RRCrtcPtr crtc)
+{
+    output->crtc = crtc;
+    output->changed = TRUE;
+}
+
 Bool
 RROutputSetConnection (RROutputPtr  output,
 		       CARD8	    connection)
 {
     output->connection = connection;
+    output->changed = TRUE;
     return TRUE;
 }
 
diff-tree db4576798e0012f0558f3faac10cbb26a2fbec34 (from cbb587582e7669dfa18fdf3bba476bf8f07b4543)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sun Sep 17 23:03:23 2006 -0700

    Split out RandR dispatch code from randr.c to rr*dispatch.c.
    
    More disassembly to ease ongoing development.

diff --git a/randr/Makefile.am b/randr/Makefile.am
index 868786e..0a73557 100644
--- a/randr/Makefile.am
+++ b/randr/Makefile.am
@@ -11,6 +11,8 @@ librandr_la_SOURCES =	\
 	randr.c		\
 	randrstr.h	\
 	rrcrtc.c	\
+	rrdispatch.c	\
 	rrmode.c	\
 	rroutput.c	\
-	rrscreen.c
+	rrscreen.c	\
+	rrsdispatch.c
diff --git a/randr/randr.c b/randr/randr.c
index 2305b60..63d471c 100644
--- a/randr/randr.c
+++ b/randr/randr.c
@@ -42,10 +42,8 @@
 int	RRGeneration;
 int	RRNScreens;
 
-static int ProcRRQueryVersion (ClientPtr pClient);
 static int ProcRRDispatch (ClientPtr pClient);
 static int SProcRRDispatch (ClientPtr pClient);
-static int SProcRRQueryVersion (ClientPtr pClient);
 
 #define wrap(priv,real,mem,func) {\
     priv->mem = real->mem; \
@@ -56,57 +54,13 @@ static int SProcRRQueryVersion (ClientPt
     real->mem = priv->mem; \
 }
 
-#if 0
-static CARD8	RRReqCode;
-static int	RRErrBase;
-#endif
 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;
-
-typedef struct _RREvent {
-    RREventPtr  next;
-    ClientPtr	client;
-    WindowPtr	window;
-    XID		clientResource;
-    int		mask;
-} RREventRec;
+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,
@@ -289,7 +243,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)
@@ -315,7 +269,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);
@@ -337,38 +291,26 @@ 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;
+	SRRScreenChangeNotifyEvent;
     EventSwapVector[RREventBase + RRNotify] = (EventSwapPtr)
 	SRRNotifyEvent;
 
     return;
 }
-static void
-DeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc)
-{
-}
-
-static void
-DeliverOutputEvent (ClientPtr client, WindowPtr pWin, RROutputPtr output)
-{
-}
 
 static int
 TellChanged (WindowPtr pWin, pointer value)
@@ -379,7 +321,7 @@ TellChanged (WindowPtr pWin, pointer val
     rrScrPriv(pScreen);
     int				i;
 
-    pHead = (RREventPtr *) LookupIDByType (pWin->drawable.id, EventType);
+    pHead = (RREventPtr *) LookupIDByType (pWin->drawable.id, RREventType);
     if (!pHead)
 	return WT_WALKCHILDREN;
 
@@ -398,7 +340,7 @@ TellChanged (WindowPtr pWin, pointer val
 	    {
 		RRCrtcPtr   crtc = pScrPriv->crtcs[i];
 		if (crtc->changed)
-		    DeliverCrtcEvent (client, pWin, crtc);
+		    RRDeliverCrtcEvent (client, pWin, crtc);
 	    }
 	}
 	
@@ -408,7 +350,7 @@ TellChanged (WindowPtr pWin, pointer val
 	    {
 		RROutputPtr   output = pScrPriv->outputs[i];
 		if (output->changed)
-		    DeliverOutputEvent (client, pWin, output);
+		    RRDeliverOutputEvent (client, pWin, output);
 	    }
 	}
     }
@@ -438,7 +380,7 @@ RRTellChanged (ScreenPtr pScreen)
  * Return the first output which is connected to an active CRTC
  * Used in emulating 1.0 behaviour
  */
-static RROutputPtr
+RROutputPtr
 RRFirstOutput (ScreenPtr pScreen)
 {
     rrScrPriv(pScreen);
@@ -459,7 +401,6 @@ RRFirstOutput (ScreenPtr pScreen)
 }
 
 #ifdef RANDR_10_INTERFACE
-
 static RRModePtr
 RROldModeAdd (RROutputPtr output, RRScreenSizePtr size, int refresh)
 {
@@ -515,13 +456,31 @@ static void
 RRScanOldConfig (ScreenPtr pScreen, Rotation rotations)
 {
     rrScrPriv(pScreen);
-    RROutputPtr	output = RRFirstOutput (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);
+    }
+
+    output = RRFirstOutput (pScreen);
     if (!output)
 	return;
     crtc = output->crtc;
@@ -601,7 +560,7 @@ RRScanOldConfig (ScreenPtr pScreen, Rota
 /*
  * Poll the driver for changed information
  */
-static Bool
+Bool
 RRGetInfo (ScreenPtr pScreen)
 {
     rrScrPriv (pScreen);
@@ -627,44 +586,6 @@ RRGetInfo (ScreenPtr pScreen)
     return TRUE;
 }
 
-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 = 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);
-}
-
-typedef struct _RR10Data {
-    RRScreenSizePtr sizes;
-    int		    nsize;
-    int		    nrefresh;
-    int		    size;
-    CARD16	    refresh;
-} RR10DataRec, *RR10DataPtr;
-
 CARD16
 RRVerticalRefresh (xRRModeInfo *mode)
 {
@@ -677,411 +598,6 @@ RRVerticalRefresh (xRRModeInfo *mode)
     return (CARD16) refresh;
 }
 
-/*
- * 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;
-    int		    i, j, k;
-    RRScreenRatePtr refresh;
-    CARD16	    vRefresh;
-    RRModePtr	    mode;
-
-    /* Make sure there is plenty of space for any combination */
-    data = malloc (sizeof (RR10DataRec) + 
-		   sizeof (RRScreenSize) * nmode + 
-		   sizeof (RRScreenRate) * nmode);
-    if (!data)
-	return NULL;
-    size = (RRScreenSizePtr) (data + 1);
-    refresh = (RRScreenRatePtr) (size + nmode);
-    data->sizes = size;
-    data->nsize = 0;
-    data->nrefresh = 0;
-    data->size = 0;
-    data->refresh = 0;
-    for (i = 0; i < output->numModes; i++)
-    {
-	mode = output->modes[i];
-	for (j = 0; j < data->nsize; j++)
-	    if (mode->mode.width == size[j].width &&
-		mode->mode.height == size[j].height)
-		break;
-	if (j == data->nsize)
-	{
-	    size[j].id = j;
-	    size[j].width = mode->mode.width;
-	    size[j].height = mode->mode.height;
-	    size[j].mmWidth = mode->mode.mmWidth;
-	    size[j].mmHeight = mode->mode.mmHeight;
-	    size[j].nRates = 0;
-	    size[j].pRates = &refresh[data->nrefresh];
-	    data->nsize++;
-	}
-	vRefresh = RRVerticalRefresh (&mode->mode);
-	for (k = 0; k < size[j].nRates; k++)
-	    if (vRefresh == size[j].pRates[k].rate)
-		break;
-	if (k == size[j].nRates)
-	{
-	    size[j].pRates[k].rate = vRefresh;
-	    size[j].pRates[k].mode = mode;
-	    size[j].nRates++;
-	    data->nrefresh++;
-	}
-	if (mode == output->crtc->mode)
-	{
-	    data->size = j;
-	    data->refresh = vRefresh;
-	}
-    }
-    return data;
-}
-
-static 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 = (WindowPtr)SecurityLookupWindow(stuff->window, client,
-					   SecurityReadAccess);
-
-    if (!pWin)
-	return BadWindow;
-
-    pScreen = pWin->drawable.pScreen;
-    pScrPriv = rrGetScrPriv(pScreen);
-    rep.pad = 0;
-    
-    if (pScrPriv)
-	RRGetInfo (pScreen);
-
-    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));
-
-	extra = (CARD8 *) xalloc (extraLen);
-	if (!extra)
-	{
-	    xfree (pData);
-	    return BadAlloc;
-	}
-	/*
-	 * 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);
-}
-
-#if 0
-    return RRSetConfigSuccess;
-}
-#endif
-
-static int
-ProcRRSetScreenConfig (ClientPtr client)
-{
-    REQUEST(xRRSetScreenConfigReq);
-    xRRSetScreenConfigReply rep;
-    DrawablePtr		    pDraw;
-    int			    n;
-    ScreenPtr		    pScreen;
-    rrScrPrivPtr	    pScrPriv;
-    TimeStamp		    configTime;
-    TimeStamp		    time;
-    int			    i;
-    Rotation		    rotation;
-    int			    rate;
-    Bool		    has_rate;
-    RROutputPtr		    output;
-    RRModePtr		    mode;
-    RR10DataPtr		    pData = NULL;
-    RRScreenSizePtr    	    pSize;
-    
-    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);
-    
-    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;
-    }
-    
-    /*
-     * 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;
-    }
-    
-    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 ((~output->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;
-    }
-
-    rep.status = RRCrtcSet (output->crtc, mode, 0, 0, stuff->rotation,
-			    1, &output);
-    
-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);
-}
-
 #if 0
 int
 RRSetScreenConfig (ScreenPtr		pScreen,
@@ -1160,478 +676,6 @@ RRSetScreenConfig (ScreenPtr		pScreen,
 #endif
 
 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 BadWindow;
-    pHead = (RREventPtr *)SecurityLookupIDByType(client,
-						 pWin->drawable.id, EventType,
-						 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, ClientType, (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, EventType, (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, ClientType);
-		if (pNewRREvent)
-		    pNewRREvent->next = pRREvent->next;
-		else
-		    *pHead = pRREvent->next;
-		xfree (pRREvent);
-	    }
-	}
-    }
-    else 
-    {
-	client->errorValue = stuff->enable;
-	return BadValue;
-    }
-    return Success;
-}
-
-/*
- * Retrieve valid screen size range
- */
-static int ProcRRGetScreenSizeRange (ClientPtr client)
-{
-    REQUEST(xRRGetScreenSizeRangeReq);
-    xRRGetScreenSizeRangeReply	rep;
-    WindowPtr			pWin;
-    ScreenPtr			pScreen;
-    rrScrPrivPtr		pScrPriv;
-    
-    REQUEST_SIZE_MATCH(xRRGetScreenInfoReq);
-    pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
-					   SecurityReadAccess);
-
-    if (!pWin)
-	return BadWindow;
-
-    pScreen = pWin->drawable.pScreen;
-    pScrPriv = rrGetScrPriv(pScreen);
-    
-    rep.type = X_Reply;
-    rep.pad = 0;
-    rep.sequenceNumber = client->sequence;
-    rep.length = 0;
-    
-    if (pScrPriv) 
-    {
-	RRGetInfo (pScreen);
-	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);
-}
-
-static int ProcRRSetScreenSize (ClientPtr client)
-{
-    REQUEST(xRRSetScreenSizeReq);
-    WindowPtr		pWin;
-    ScreenPtr		pScreen;
-    rrScrPrivPtr	pScrPriv;
-    RRCrtcPtr		crtc;
-    int			i;
-    
-    REQUEST_SIZE_MATCH(xRRSetScreenSizeReq);
-    pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
-					   SecurityReadAccess);
-
-    if (!pWin)
-	return BadWindow;
-
-    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++) {
-	crtc = pScrPriv->crtcs[i];
-	if (crtc->mode &&
-	    (crtc->x + crtc->mode->mode.width > stuff->width ||
-	     crtc->y + crtc->mode->mode.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;
-}
-
-#if 0
-static int ProcRRGetMonitorInfo (ClientPtr client)
-{
-    REQUEST(xRRGetMonitorInfoReq);
-    xRRGetMonitorInfoReply	rep;
-    WindowPtr			pWin;
-    ScreenPtr			pScreen;
-    rrScrPrivPtr		pScrPriv;
-    RRMonitorPtr		pMonitor;
-    RRModePtr			pMode;
-    int				extraLen;
-    CARD8			*extra;
-    xRRMonitorInfo		*monitor;
-    xRRMonitorMode		*mode;
-    CARD8			*names;
-    
-    REQUEST_SIZE_MATCH(xRRGetScreenInfoReq);
-    pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
-					   SecurityReadAccess);
-
-    if (!pWin)
-	return BadWindow;
-
-    pScreen = pWin->drawable.pScreen;
-    pScrPriv = rrGetScrPriv(pScreen);
-    rep.type = X_Reply;
-    rep.pad = 0;
-    rep.sequenceNumber = client->sequence;
-    rep.numMonitors = 0;
-    rep.numModes = 0;
-    rep.sizeNames = 0;
-    if (!pScrPriv)
-    {
-	extraLen = 0;
-	extra = NULL;
-    }
-    else
-    {
-	int i, m, b;
-	for (pMonitor = pScrPriv->pMonitors; pMonitor; pMonitor = pMonitor->next)
-	{
-	    rep.numMonitors++;
-	    for (pMode = pMonitor->pModes; pMode; pMode = pMode->next)
-	    {
-		rep.numModes++;
-		rep.sizeNames += (1 + pMode->mode.nameLength);
-	    }
-	}
-	extraLen = (rep.numMonitors * sizeof (xRRMonitorInfo) +
-		    rep.numModes * sizeof (xRRMonitorMode) +
-		    rep.sizeNames + 3) & ~3;
-	extra = (CARD8 *) xalloc (extraLen);
-	if (!extra)
-	    return BadAlloc;
-	monitor = (xRRMonitorInfo *) extra;
-	mode = (xRRMonitorMode *) (monitor + rep.numMonitors);
-	names = (CARD8 *) (mode + rep.numModes);
-	i = 0;
-	m = 0;
-	b = 0;
-	for (pMonitor = pScrPriv->pMonitors; pMonitor; pMonitor = pMonitor->next)
-	{
-	    monitor[i].timestamp = pScrPriv->lastSetTime;
-	    monitor[i].configTimestamp = pScrPriv->lastConfigTime;
-	    monitor[i].x = pMonitor->x;
-	    monitor[i].y = pMonitor->y;
-	    monitor[i].rotation = pMonitor->rotation;
-	    monitor[i].mode = pMonitor->pMode->id;
-	    monitor[i].defaultMode = 0;	/* XXX */
-	    monitor[i].rotations = pMonitor->rotations;
-	    monitor[i].firstMode = m;
-	    monitor[i].numModes = 0;
-	    for (pMode = pMonitor->pModes; pMode; pMode = pMode->next)
-	    {
-		monitor[i].numModes++;
-		mode[m] = pMode->mode;
-		names[b] = pMode->mode.nameLength;
-		b++;
-		memcpy (names + b, (char *) (pMode + 1), 
-			pMode->mode.nameLength);
-		b += pMode->mode.nameLength;
-		m++;
-	    }
-	    i++;
-	}
-	if ((char *) (names + ((b + 3) & ~3)) != (char *) extra + extraLen)
-	    FatalError ("RRGetMonitorInfo length mismatch\n");
-    }
-    rep.length = extraLen >> 2;
-    
-    WriteToClient(client, sizeof(xRRGetMonitorInfoReply), (char *)&rep);
-    if (extraLen)
-    {
-	WriteToClient (client, extraLen, (char *) extra);
-	xfree (extra);
-    }
-    
-    if (extra)
-	xfree (extra);
-    return (client->noClientException);
-}
-
-static int ProcRRAddMonitorMode (ClientPtr client)
-{
-    return BadImplementation;
-}
-
-static int ProcRRDeleteMonitorMode (ClientPtr client)
-{
-    return BadImplementation;
-}
-
-static int ProcRRSetMonitorConfig (ClientPtr client)
-{
-    REQUEST(xRRSetMonitorConfigReq);
-    xRRSetMonitorConfigReply	rep;
-    WindowPtr			pWin;
-    ScreenPtr			pScreen;
-    rrScrPrivPtr		pScrPriv;
-    RRMonitorPtr		pMonitor;
-    RRModePtr			pMode;
-    TimeStamp		    configTime;
-    TimeStamp		    time;
-    Rotation		    rotation;
-    
-    REQUEST_SIZE_MATCH(xRRSetScreenConfigReq);
-    pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
-					   SecurityReadAccess);
-
-    if (!pWin)
-	return BadWindow;
-
-    pScreen = pWin->drawable.pScreen;
-    pScrPriv = rrGetScrPriv(pScreen);
-    
-    time = ClientTimeToServerTime(stuff->timestamp);
-    configTime = ClientTimeToServerTime(stuff->configTimestamp);
-    
-    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;
-    }
-    
-    for (pMonitor = pScrPriv->pMonitors; pMonitor; pMonitor = pMonitor->next)
-    {
-	if (pMonitor->id == stuff->monitorIndex)
-	    break;
-    }
-    if (!pMonitor)
-    {
-	client->errorValue = stuff->monitorIndex;
-	return BadValue;
-    }
-    
-    for (pMode = pMonitor->pModes; pMode; pMode = pMode->next)
-    {
-	if (pMode->id == stuff->modeIndex)
-	    break;
-    }
-    if (!pMode)
-    {
-	client->errorValue = stuff->modeIndex;
-	return BadValue;
-    }
-    
-    /*
-     * 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 ((~pMonitor->rotations) & rotation)
-    {
-	/*
-	 * requested rotation or reflection not supported by screen
-	 */
-	client->errorValue = stuff->rotation;
-	return BadMatch;
-    }
-
-    if (stuff->x + pMode->mode.width > pScreen->width)
-    {
-	client->errorValue = stufff
-	stuff->y + pMode->mode.height > 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;
-    }
-
-    rep.status = RRMonitorSetMode (pScreen, pMonitor, 
-				   pMode, stuff->x, stuff->y, rotation, time);
-    
-    return client->noClientException;
-}
-#endif
-
-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 */
-#if 0
-    ProcRRGetScreenSizeRange,	/* 6 */
-    ProcRRSetScreenSize,	/* 7 */
-    ProcRRGetMonitorInfo,	/* 8 */
-    ProcRRAddMonitorMode,	/* 9 */
-    ProcRRDeleteMonitorMode,	/* 10 */
-    ProcRRSetMonitorConfig,	/* 11 */
-#endif
-};
-
-
-static int
 ProcRRDispatch (ClientPtr client)
 {
     REQUEST(xReq);
@@ -1641,81 +685,12 @@ ProcRRDispatch (ClientPtr client)
 }
 
 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);
-}
-
-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;
-    }
+    return (*SProcRandrVector[stuff->data]) (client);
 }
 
 #if RANDR_12_INTERFACE
@@ -1741,7 +716,6 @@ RRScreenSetSizeRange (ScreenPtr	pScreen,
 #endif
 
 #ifdef RANDR_10_INTERFACE
-
 static Bool
 RRScreenSizeMatches (RRScreenSizePtr  a,
 		   RRScreenSizePtr  b)
diff --git a/randr/randrstr.h b/randr/randrstr.h
index f323660..3346157 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -59,8 +59,11 @@ typedef XID	RRMode;
 typedef XID	RROutput;
 typedef XID	RRCrtc;
 
-extern int	RREventBase;
+extern int	RREventBase, RRErrorBase;
 
+extern int (*ProcRandrVector[RRNumberRequests])(ClientPtr);
+extern int (*SProcRandrVector[RRNumberRequests])(ClientPtr);
+    
 /*
  * Modeline for a monitor. Name follows directly after this struct
  */
@@ -101,7 +104,7 @@ struct _rrOutput {
     int		    numCrtcs;
     RRCrtcPtr	    *crtcs;
     int		    numClones;
-    RROutputPtr	    *outputs;
+    RROutputPtr	    *clones;
     int		    numModes;
     RRModePtr	    *modes;
     Bool	    changed;
@@ -210,6 +213,42 @@ 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 GetRRClient(pClient)    ((RRClientPtr) (pClient)->devPrivates[RRClientPrivateIndex].ptr)
+#define rrClientPriv(pClient)	RRClientPtr pRRClient = GetRRClient(pClient)
+
 /* Initialize the extension */
 void
 RRExtensionInit (void);
@@ -278,8 +317,17 @@ miRRCrtcSet (ScreenPtr	pScreen,
 void
 RRTellChanged (ScreenPtr pScreen);
 
+/*
+ * Poll the driver for changed information
+ */
+Bool
+RRGetInfo (ScreenPtr pScreen);
+
 Bool RRScreenInit(ScreenPtr pScreen);
 
+RROutputPtr
+RRFirstOutput (ScreenPtr pScreen);
+
 Rotation
 RRGetRotation (ScreenPtr pScreen);
 
@@ -338,13 +386,6 @@ RRCrtcPtr
 RRCrtcCreate (ScreenPtr	pScreen,
 	      void	*devPrivate);
 
-
-/*
- * Use this value for any num parameter to indicate that
- * the related data are unchanged
- */
-#define RR_NUM_UNCHANGED    -1
-
 /*
  * Notify the extension that the Crtc has been reconfigured,
  * the driver calls this whenever it has updated the mode
@@ -358,6 +399,9 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
 	      int	    numOutput,
 	      RROutputPtr   *outputs);
 
+void
+RRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc);
+    
 /*
  * Request that the Crtc be reconfigured
  */
@@ -382,6 +426,10 @@ RRCrtcDestroy (RRCrtcPtr crtc);
 Bool
 RRCrtcInit (void);
 
+/* rrdispatch.c */
+Bool
+RRClientKnowsRates (ClientPtr	pClient);
+
 /* rrmode.c */
 /*
  * Find, and if necessary, create a mode
@@ -439,6 +487,9 @@ RROutputSetConnection (RROutputPtr  outp
 		       CARD8	    connection);
 
 void
+RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output);
+
+void
 RROutputDestroy (RROutputPtr	output);
 
 /*
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index cc5b24d..d343c3a 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -22,7 +22,7 @@
 
 #include "randrstr.h"
 
-static RESTYPE	CrtcType;
+RESTYPE	RRCrtcType;
 
 /*
  * Create a CRTC
@@ -144,6 +144,12 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
     return TRUE;
 }
 
+void
+RRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc)
+{
+    
+}
+
 /*
  * Request that the Crtc be reconfigured
  */
@@ -216,6 +222,7 @@ RRCrtcDestroyResource (pointer value, XI
 	    memmove (pScrPriv->crtcs, pScrPriv->crtcs + 1,
 		     (pScrPriv->numCrtcs - (i - 1)) * sizeof (RRCrtcPtr));
 	    --pScrPriv->numCrtcs;
+	    break;
 	}
     }
     free (value);
@@ -228,11 +235,11 @@ RRCrtcDestroyResource (pointer value, XI
 Bool
 RRCrtcInit (void)
 {
-    CrtcType = CreateNewResourceType (RRCrtcDestroyResource);
-    if (!CrtcType)
+    RRCrtcType = CreateNewResourceType (RRCrtcDestroyResource);
+    if (!RRCrtcType)
 	return FALSE;
 #ifdef XResExtension
-	RegisterResourceName (CrtcType, "CRTC");
+	RegisterResourceName (RRCrtcType, "CRTC");
 #endif
     return TRUE;
 }
diff --git a/randr/rrdispatch.c b/randr/rrdispatch.c
new file mode 100644
index 0000000..acf6298
--- /dev/null
+++ b/randr/rrdispatch.c
@@ -0,0 +1,1034 @@
+/*
+ * 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"
+
+Bool
+RRClientKnowsRates (ClientPtr	pClient)
+{
+    rrClientPriv(pClient);
+
+    return (pRRClient->major_version > 1 ||
+	    (pRRClient->major_version == 1 && pRRClient->minor_version >= 1));
+}
+
+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;
+    int		    i, j, k;
+    RRScreenRatePtr refresh;
+    CARD16	    vRefresh;
+    RRModePtr	    mode;
+
+    /* Make sure there is plenty of space for any combination */
+    data = malloc (sizeof (RR10DataRec) + 
+		   sizeof (RRScreenSize) * nmode + 
+		   sizeof (RRScreenRate) * nmode);
+    if (!data)
+	return NULL;
+    size = (RRScreenSizePtr) (data + 1);
+    refresh = (RRScreenRatePtr) (size + nmode);
+    data->sizes = size;
+    data->nsize = 0;
+    data->nrefresh = 0;
+    data->size = 0;
+    data->refresh = 0;
+    for (i = 0; i < output->numModes; i++)
+    {
+	mode = output->modes[i];
+	for (j = 0; j < data->nsize; j++)
+	    if (mode->mode.width == size[j].width &&
+		mode->mode.height == size[j].height)
+		break;
+	if (j == data->nsize)
+	{
+	    size[j].id = j;
+	    size[j].width = mode->mode.width;
+	    size[j].height = mode->mode.height;
+	    size[j].mmWidth = mode->mode.mmWidth;
+	    size[j].mmHeight = mode->mode.mmHeight;
+	    size[j].nRates = 0;
+	    size[j].pRates = &refresh[data->nrefresh];
+	    data->nsize++;
+	}
+	vRefresh = RRVerticalRefresh (&mode->mode);
+	for (k = 0; k < size[j].nRates; k++)
+	    if (vRefresh == size[j].pRates[k].rate)
+		break;
+	if (k == size[j].nRates)
+	{
+	    size[j].pRates[k].rate = vRefresh;
+	    size[j].pRates[k].mode = mode;
+	    size[j].nRates++;
+	    data->nrefresh++;
+	}
+	if (mode == output->crtc->mode)
+	{
+	    data->size = j;
+	    data->refresh = vRefresh;
+	}
+    }
+    return data;
+}
+
+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 = 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);
+}
+
+static 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 = (WindowPtr)SecurityLookupWindow(stuff->window, client,
+					   SecurityReadAccess);
+
+    if (!pWin)
+	return BadWindow;
+
+    pScreen = pWin->drawable.pScreen;
+    pScrPriv = rrGetScrPriv(pScreen);
+    rep.pad = 0;
+    
+    if (pScrPriv)
+	RRGetInfo (pScreen);
+
+    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));
+
+	extra = (CARD8 *) xalloc (extraLen);
+	if (!extra)
+	{
+	    xfree (pData);
+	    return BadAlloc;
+	}
+	/*
+	 * 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);
+}
+
+static int
+ProcRRSetScreenConfig (ClientPtr client)
+{
+    REQUEST(xRRSetScreenConfigReq);
+    xRRSetScreenConfigReply rep;
+    DrawablePtr		    pDraw;
+    int			    n;
+    ScreenPtr		    pScreen;
+    rrScrPrivPtr	    pScrPriv;
+    TimeStamp		    configTime;
+    TimeStamp		    time;
+    int			    i;
+    Rotation		    rotation;
+    int			    rate;
+    Bool		    has_rate;
+    RROutputPtr		    output;
+    RRModePtr		    mode;
+    RR10DataPtr		    pData = NULL;
+    RRScreenSizePtr    	    pSize;
+    
+    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);
+    
+    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;
+    }
+    
+    /*
+     * 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;
+    }
+    
+    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 ((~output->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;
+    }
+
+    rep.status = RRCrtcSet (output->crtc, mode, 0, 0, stuff->rotation,
+			    1, &output);
+    
+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 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 BadWindow;
+    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;
+}
+
+/*
+ * Retrieve valid screen size range
+ */
+static int 
+ProcRRGetScreenSizeRange (ClientPtr client)
+{
+    REQUEST(xRRGetScreenSizeRangeReq);
+    xRRGetScreenSizeRangeReply	rep;
+    WindowPtr			pWin;
+    ScreenPtr			pScreen;
+    rrScrPrivPtr		pScrPriv;
+    
+    REQUEST_SIZE_MATCH(xRRGetScreenInfoReq);
+    pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
+					   SecurityReadAccess);
+
+    if (!pWin)
+	return BadWindow;
+
+    pScreen = pWin->drawable.pScreen;
+    pScrPriv = rrGetScrPriv(pScreen);
+    
+    rep.type = X_Reply;
+    rep.pad = 0;
+    rep.sequenceNumber = client->sequence;
+    rep.length = 0;
+    
+    if (pScrPriv) 
+    {
+	RRGetInfo (pScreen);
+	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);
+}
+
+static int ProcRRSetScreenSize (ClientPtr client)
+{
+    REQUEST(xRRSetScreenSizeReq);
+    WindowPtr		pWin;
+    ScreenPtr		pScreen;
+    rrScrPrivPtr	pScrPriv;
+    RRCrtcPtr		crtc;
+    int			i;
+    
+    REQUEST_SIZE_MATCH(xRRSetScreenSizeReq);
+    pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
+					   SecurityReadAccess);
+
+    if (!pWin)
+	return BadWindow;
+
+    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++) {
+	crtc = pScrPriv->crtcs[i];
+	if (crtc->mode &&
+	    (crtc->x + crtc->mode->mode.width > stuff->width ||
+	     crtc->y + crtc->mode->mode.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;
+}
+
+static int
+ProcRRGetScreenResources (ClientPtr client)
+{
+    REQUEST(xRRGetScreenResourcesReq);
+    
+    REQUEST_SIZE_MATCH(xRRGetScreenResourcesReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+ProcRRGetOutputInfo (ClientPtr client)
+{
+    REQUEST(xRRGetOutputInfoReq);;
+    
+    REQUEST_SIZE_MATCH(xRRGetOutputInfoReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+ProcRRListOutputProperties (ClientPtr client)
+{
+    REQUEST(xRRListOutputPropertiesReq);
+    
+    REQUEST_SIZE_MATCH(xRRListOutputPropertiesReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+ProcRRChangeOutputProperty (ClientPtr client)
+{
+    REQUEST(xRRChangeOutputPropertyReq);
+    
+    REQUEST_SIZE_MATCH(xRRChangeOutputPropertyReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+ProcRRDeleteOutputProperty (ClientPtr client)
+{
+    REQUEST(xRRDeleteOutputPropertyReq);
+    
+    REQUEST_SIZE_MATCH(xRRDeleteOutputPropertyReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+ProcRRGetOutputProperty (ClientPtr client)
+{
+    REQUEST(xRRGetOutputPropertyReq);
+    
+    REQUEST_SIZE_MATCH(xRRGetOutputPropertyReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+ProcRRCreateMode (ClientPtr client)
+{
+    REQUEST(xRRCreateModeReq);
+    
+    REQUEST_SIZE_MATCH(xRRCreateModeReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+ProcRRDestroyMode (ClientPtr client)
+{
+    REQUEST(xRRDestroyModeReq);
+    
+    REQUEST_SIZE_MATCH(xRRDestroyModeReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+ProcRRAddOutputMode (ClientPtr client)
+{
+    REQUEST(xRRAddOutputModeReq);
+    
+    REQUEST_SIZE_MATCH(xRRAddOutputModeReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+ProcRRDeleteOutputMode (ClientPtr client)
+{
+    REQUEST(xRRDeleteOutputModeReq);
+    
+    REQUEST_SIZE_MATCH(xRRDeleteOutputModeReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+ProcRRGetCrtcInfo (ClientPtr client)
+{
+    REQUEST(xRRGetCrtcInfoReq);
+    
+    REQUEST_SIZE_MATCH(xRRGetCrtcInfoReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static 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 + BadCrtc;
+    }
+    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 + BadMode;
+	}
+	if (numOutputs == 0)
+	    return BadMatch;
+    }
+    outputs = xalloc (numOutputs * sizeof (RROutputPtr));
+    if (!outputs)
+	return BadAlloc;
+    
+    outputIds = (RROutput *) (stuff + 1);
+    for (i = 0; i < numOutputs; i++)
+    {
+	outputs[i] = LookupIDByType (outputIds[i], RROutputType);
+	if (!outputs[i])
+	{
+	    client->errorValue = outputIds[i];
+	    return RRErrorBase + BadOutput;
+	}
+	/* validate crtc for this output */
+	for (j = 0; j < outputs[i]->numCrtcs; j++)
+	    if (outputs[i]->crtcs[j] == crtc)
+		break;
+	if (j == outputs[j]->numCrtcs)
+	    return BadMatch;
+	/* validate mode for this output */
+	for (j = 0; j < outputs[i]->numModes; j++)
+	    if (outputs[i]->modes[j] == mode)
+		break;
+	if (j == outputs[j]->numModes)
+	    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 (!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;
+    }
+    
+    /*
+     * 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 ((~crtc->rotations) & rotation)
+    {
+	/*
+	 * requested rotation or reflection not supported by screen
+	 */
+	client->errorValue = stuff->rotation;
+	return BadMatch;
+    }
+
+    if (stuff->x + mode->mode.width > pScreen->width)
+    {
+	client->errorValue = stuff->x;
+	return BadValue;
+    }
+    
+    if (stuff->y + mode->mode.height > pScreen->height)
+    {
+	client->errorValue = stuff->y;
+	return BadValue;
+    }
+    
+    /*
+     * 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;
+    }
+
+    rep.status = RRCrtcSet (crtc, mode, stuff->x, stuff->y,
+			    rotation, numOutputs, outputs);
+    
+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;
+}
+
+static int
+ProcRRGetCrtcGammaSize (ClientPtr client)
+{
+    REQUEST(xRRGetCrtcGammaSizeReq);
+    
+    REQUEST_SIZE_MATCH(xRRGetCrtcGammaSizeReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+ProcRRGetCrtcGamma (ClientPtr client)
+{
+    REQUEST(xRRGetCrtcGammaReq);
+    
+    REQUEST_SIZE_MATCH(xRRGetCrtcGammaReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+ProcRRSetCrtcGamma (ClientPtr client)
+{
+    REQUEST(xRRSetCrtcGammaReq);
+    
+    REQUEST_SIZE_MATCH(xRRSetCrtcGammaReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+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 */
+    ProcRRChangeOutputProperty,	/* 11 */
+    ProcRRDeleteOutputProperty,	/* 12 */
+    ProcRRGetOutputProperty,	/* 13 */
+    ProcRRCreateMode,		/* 14 */
+    ProcRRDestroyMode,		/* 15 */
+    ProcRRAddOutputMode,	/* 16 */
+    ProcRRDeleteOutputMode,	/* 17 */
+    ProcRRGetCrtcInfo,		/* 18 */
+    ProcRRSetCrtcConfig,	/* 19 */
+    ProcRRGetCrtcGammaSize,	/* 20 */
+    ProcRRGetCrtcGamma,		/* 21 */
+    ProcRRSetCrtcGamma,		/* 22 */
+};
+
diff --git a/randr/rrmode.c b/randr/rrmode.c
index 1eb53c3..3a9d556 100644
--- a/randr/rrmode.c
+++ b/randr/rrmode.c
@@ -22,7 +22,7 @@
 
 #include "randrstr.h"
 
-static RESTYPE	ModeType;
+RESTYPE	RRModeType;
 
 RRModePtr
 RRModeGet (ScreenPtr	pScreen,
@@ -50,7 +50,7 @@ RRModeGet (ScreenPtr	pScreen,
     memcpy (mode->name, name, modeInfo->nameLength);
     mode->name[modeInfo->nameLength] = '\0';
     mode->id = FakeClientID(0);
-    if (!AddResource (mode->id, ModeType, (pointer) mode))
+    if (!AddResource (mode->id, RRModeType, (pointer) mode))
 	return NULL;
     ++mode->refcnt;
     pScrPriv->changed = TRUE;
@@ -75,11 +75,11 @@ RRModeDestroyResource (pointer value, XI
 Bool
 RRModeInit (void)
 {
-    ModeType = CreateNewResourceType (RRModeDestroyResource);
-    if (!ModeType)
+    RRModeType = CreateNewResourceType (RRModeDestroyResource);
+    if (!RRModeType)
 	return FALSE;
 #ifdef XResExtension
-    RegisterResourceName (ModeType, "MODE");
+    RegisterResourceName (RRModeType, "MODE");
 #endif
     return TRUE;
 }
diff --git a/randr/rroutput.c b/randr/rroutput.c
index c7e7995..6b67f19 100644
--- a/randr/rroutput.c
+++ b/randr/rroutput.c
@@ -22,7 +22,124 @@
 
 #include "randrstr.h"
 
-static RESTYPE	OutputType;
+RESTYPE	RROutputType;
+
+/*
+ * Create an output
+ */
+
+RROutputPtr
+RROutputCreate (ScreenPtr   pScreen,
+		char	    *name,
+		int	    nameLength,
+		void	    *devPrivate)
+{
+    rrScrPriv (pScreen);
+    RROutputPtr	output;
+    RROutputPtr	*outputs;
+
+    output = xalloc (sizeof (RROutputRec) + nameLength + 1);
+    if (!output)
+	return NULL;
+    if (pScrPriv->numOutputs)
+	outputs = xrealloc (pScrPriv->outputs, 
+			    (pScrPriv->numOutputs + 1) * sizeof (RROutputPtr));
+    else
+	outputs = xalloc (sizeof (RROutputPtr));
+    if (!outputs)
+    {
+	xfree (output);
+	return NULL;
+    }
+    output->id = FakeClientID (0);
+    output->pScreen = pScreen;
+    output->name = (char *) (output + 1);
+    output->nameLength = nameLength;
+    memcpy (output->name, name, nameLength);
+    output->connection = RR_UnknownConnection;
+    output->subpixelOrder = SubPixelUnknown;
+    output->crtc = NULL;
+    output->numCrtcs = 0;
+    output->crtcs = NULL;
+    output->numClones = 0;
+    output->clones = NULL;
+    output->numModes = 0;
+    output->modes = NULL;
+    output->changed = TRUE;
+    output->devPrivate = devPrivate;
+    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;
+
+    newClones = xalloc (numClones * sizeof (RROutputPtr));
+    if (!newClones)
+	return FALSE;
+    if (output->clones)
+	xfree (output->clones);
+    memcpy (newClones, clones, numClones * sizeof (RROutputPtr));
+    output->clones = newClones;
+    output->numClones = numClones;
+    return TRUE;
+}
+
+Bool
+RROutputSetModes (RROutputPtr	output,
+		  RRModePtr	*modes,
+		  int		numModes)
+{
+    RRModePtr	*newModes;
+
+    newModes = xalloc (numModes * sizeof (RRModePtr));
+    if (!newModes)
+	return FALSE;
+    if (output->modes)
+	xfree (output->modes);
+    memcpy (newModes, modes, numModes * sizeof (RRModePtr));
+    output->modes = newModes;
+    output->numModes = numModes;
+    return TRUE;
+}
+
+Bool
+RROutputSetCrtcs (RROutputPtr	output,
+		  RRCrtcPtr	*crtcs,
+		  int		numCrtcs)
+{
+    RRCrtcPtr	*newCrtcs;
+
+    newCrtcs = xalloc (numCrtcs * sizeof (RRCrtcPtr));
+    if (!newCrtcs)
+	return FALSE;
+    if (output->crtcs)
+	xfree (output->crtcs);
+    memcpy (newCrtcs, crtcs, numCrtcs * sizeof (RRCrtcPtr));
+    output->crtcs = newCrtcs;
+    output->numCrtcs = numCrtcs;
+    return TRUE;
+}
+
+Bool
+RROutputSetConnection (RROutputPtr  output,
+		       CARD8	    connection)
+{
+    output->connection = connection;
+    return TRUE;
+}
+
+void
+RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output)
+{
+}
 
 /*
  * Destroy a Output at shutdown
@@ -36,7 +153,28 @@ RROutputDestroy (RROutputPtr crtc)
 static int
 RROutputDestroyResource (pointer value, XID pid)
 {
-    free (value);
+    RROutputPtr	output = (RROutputPtr) value;
+    ScreenPtr	pScreen = output->pScreen;
+    rrScrPriv(pScreen);
+    int		i;
+
+    for (i = 0; i < pScrPriv->numOutputs; i++)
+    {
+	if (pScrPriv->outputs[i] == output)
+	{
+	    memmove (pScrPriv->outputs, pScrPriv->outputs + 1,
+		     (pScrPriv->numOutputs - (i - 1)) * sizeof (RROutputPtr));
+	    --pScrPriv->numOutputs;
+	    break;
+	}
+    }
+    if (output->modes)
+	xfree (output->modes);
+    if (output->crtcs)
+	xfree (output->crtcs);
+    if (output->clones)
+	xfree (output->clones);
+    xfree (output);
     return 1;
 }
 
@@ -46,11 +184,11 @@ RROutputDestroyResource (pointer value, 
 Bool
 RROutputInit (void)
 {
-    OutputType = CreateNewResourceType (RROutputDestroyResource);
-    if (!OutputType)
+    RROutputType = CreateNewResourceType (RROutputDestroyResource);
+    if (!RROutputType)
 	return FALSE;
 #ifdef XResExtension
-	RegisterResourceName (OutputType, "OUTPUT");
+	RegisterResourceName (RROutputType, "OUTPUT");
 #endif
     return TRUE;
 }
diff --git a/randr/rrsdispatch.c b/randr/rrsdispatch.c
new file mode 100644
index 0000000..bf81f8b
--- /dev/null
+++ b/randr/rrsdispatch.c
@@ -0,0 +1,282 @@
+/*
+ * 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);
+    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
+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 */
+    SProcRRChangeOutputProperty,/* 11 */
+    SProcRRDeleteOutputProperty,/* 12 */
+    SProcRRGetOutputProperty,	/* 13 */
+    SProcRRCreateMode,		/* 14 */
+    SProcRRDestroyMode,		/* 15 */
+    SProcRRAddOutputMode,	/* 16 */
+    SProcRRDeleteOutputMode,	/* 17 */
+    SProcRRGetCrtcInfo,		/* 18 */
+    SProcRRSetCrtcConfig,	/* 19 */
+    SProcRRGetCrtcGammaSize,	/* 20 */
+    SProcRRGetCrtcGamma,	/* 21 */
+    SProcRRSetCrtcGamma,	/* 22 */
+};
+
diff-tree cbb587582e7669dfa18fdf3bba476bf8f07b4543 (from d7f1f286b7b034827956c857f8f2effbc161e5b2)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sat Sep 16 23:21:37 2006 -0700

    Split RandR implementation into separate files.
    
    RandR is getting too big to live in one file; split into one file per object
    type (crtc, mode, screen), leaving the rest of the code in randr.c.
    
    Code is slowly approaching the point where it will drop-in as a replacement
    for the old 1.0 implementation.

diff --git a/randr/Makefile.am b/randr/Makefile.am
index bd30aed..868786e 100644
--- a/randr/Makefile.am
+++ b/randr/Makefile.am
@@ -9,4 +9,8 @@ endif
 librandr_la_SOURCES =	\
 	mirandr.c	\
 	randr.c		\
-	randrstr.h
+	randrstr.h	\
+	rrcrtc.c	\
+	rrmode.c	\
+	rroutput.c	\
+	rrscreen.c
diff --git a/randr/mirandr.c b/randr/mirandr.c
index 5aea38d..a57a157 100644
--- a/randr/mirandr.c
+++ b/randr/mirandr.c
@@ -70,16 +70,19 @@ Bool
 miRandRInit (ScreenPtr pScreen)
 {
     rrScrPrivPtr    pScrPriv;
+#if RANDR_12_INTERFACE
     RRModePtr	mode;
     RRCrtcPtr	crtc;
     RROutputPtr	output;
     xRRModeInfo modeInfo;
     char	name[64];
+#endif
     
     if (!RRScreenInit (pScreen))
 	return FALSE;
     pScrPriv = rrGetScrPriv(pScreen);
     pScrPriv->rrGetInfo = miRRGetInfo;
+#if RANDR_12_INTERFACE
     pScrPriv->rrCrtcSet = miRRCrtcSet;
     
     RRScreenSetSizeRange (pScreen,
@@ -111,7 +114,7 @@ miRandRInit (ScreenPtr pScreen)
 		      &crtc, 1, /* crtcs */
 		      RR_Connected))
 	return FALSE;
-    if (!RRCrtcSet (crtc, mode, 0, 0, RR_Rotate_0, 1, &output))
-	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 e34b82c..2305b60 100644
--- a/randr/randr.c
+++ b/randr/randr.c
@@ -31,25 +31,7 @@
 #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
@@ -60,8 +42,6 @@
 int	RRGeneration;
 int	RRNScreens;
 
-static RESTYPE	    ModeType, CrtcType, OutputType;
-
 static int ProcRRQueryVersion (ClientPtr pClient);
 static int ProcRRDispatch (ClientPtr pClient);
 static int SProcRRDispatch (ClientPtr pClient);
@@ -80,7 +60,7 @@ static int SProcRRQueryVersion (ClientPt
 static CARD8	RRReqCode;
 static int	RRErrBase;
 #endif
-static int	RREventBase;
+int	RREventBase;
 static RESTYPE ClientType, EventType; /* resource types for event masks */
 static int	RRClientPrivateIndex;
 
@@ -233,50 +213,21 @@ SRRNotifyEvent (xEvent *from,
     }
 }
 
-static int
-RRModeDestroyResource (pointer value, XID pid)
-{
-    RRModeDestroy ((RRModePtr) value);
-    return 1;
-}
-
-static int
-RRCrtcDestroyResource (pointer value, XID pid)
-{
-    RRCrtcDestroy ((RRCrtcPtr) value);
-    return 1;
-}
-
-static int
-RROutputDestroyResource (pointer value, XID pid)
-{
-    RROutputDestroy ((RROutputPtr) value);
-    return 1;
-}
-
 Bool RRScreenInit(ScreenPtr pScreen)
 {
     rrScrPrivPtr   pScrPriv;
 
     if (RRGeneration != serverGeneration)
     {
-	ModeType = CreateNewResourceType (RRModeDestroyResource);
-	if (!ModeType)
+	if (!RRModeInit ())
 	    return FALSE;
-	CrtcType = CreateNewResourceType (RRCrtcDestroyResource);
-	if (!ModeType)
+	if (!RRCrtcInit ())
 	    return FALSE;
-	OutputType = CreateNewResourceType (RROutputDestroyResource);
-	if (!ModeType)
+	if (!RROutputInit ())
 	    return FALSE;
 	if ((rrPrivIndex = AllocateScreenPrivateIndex()) < 0)
 	    return FALSE;
 	RRGeneration = serverGeneration;
-#ifdef XResExtension
-	RegisterResourceName (ModeType, "MODE");
-	RegisterResourceName (CrtcType, "CRTC");
-	RegisterResourceName (OutputType, "OUTPUT");
-#endif
     }
 
     pScrPriv = (rrScrPrivPtr) xalloc (sizeof (rrScrPrivRec));
@@ -288,14 +239,23 @@ Bool RRScreenInit(ScreenPtr pScreen)
     /*
      * Calling function best set these function vectors
      */
-    pScrPriv->rrCrtcSet = 0;
     pScrPriv->rrGetInfo = 0;
     pScrPriv->maxWidth = pScrPriv->minWidth = pScreen->width;
     pScrPriv->maxHeight = pScrPriv->minHeight = pScreen->height;
-#ifdef RANDR_SCREEN_INTERFACE    
+    
+#if RANDR_12_INTERFACE
+    pScrPriv->rrCrtcSet = 0;
+#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
     
     /*
@@ -400,61 +360,6 @@ RRExtensionInit (void)
 
     return;
 }
-		
-static void
-DeliverScreenEvent (ClientPtr client, WindowPtr pWin, ScreenPtr pScreen)
-{
-    rrScrPriv (pScreen);
-    xRRScreenChangeNotifyEvent	se;
-    RRCrtcPtr	crtc = pScrPriv->numCrtcs ? pScrPriv->crtcs[0] : NULL;
-    RROutputPtr	output = pScrPriv->numOutputs ? pScrPriv->outputs[0] : NULL;
-    RRModePtr	mode = crtc ? crtc->mode : NULL;
-    WindowPtr	pRoot = WindowTable[pScreen->myNum];
-    int		i;
-    
-    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;
-    if (mode) 
-    {
-	se.sizeID = -1;
-	for (i = 0; i < output->numModes; i++)
-	    if (mode == output->modes[i])
-	    {
-		se.sizeID = i;
-		break;
-	    }
-	se.widthInPixels = mode->mode.width;
-	se.heightInPixels = mode->mode.height;
-	se.widthInMillimeters = mode->mode.mmWidth;
-	se.heightInMillimeters = mode->mode.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;
-    }    
-    WriteEventsToClient (client, 1, (xEvent *) &se);
-}
-
 static void
 DeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc)
 {
@@ -485,7 +390,7 @@ TellChanged (WindowPtr pWin, pointer val
 	    continue;
 
 	if (pRREvent->mask & RRScreenChangeNotifyMask)
-	    DeliverScreenEvent (client, pWin, pScreen);
+	    RRDeliverScreenEvent (client, pWin, pScreen);
 	
 	if (pRREvent->mask & RRCrtcChangeNotifyMask)
 	{
@@ -529,47 +434,6 @@ RRTellChanged (ScreenPtr pScreen)
     }
 }
 
-RRModePtr
-RRModeGet (ScreenPtr	pScreen,
-	   xRRModeInfo	*modeInfo,
-	   char		*name)
-{
-    rrScrPriv (pScreen);
-    int	i;
-    RRModePtr	mode;
-
-    for (i = 0; i < pScrPriv->numModes; i++)
-    {
-	mode = pScrPriv->modes[i];
-	if (!memcmp (modeInfo, &mode->mode, sizeof (xRRModeInfo)) &&
-	    !memcmp (name, mode->name, modeInfo->nameLength))
-	{
-	    ++mode->refcnt;
-	    return mode;
-	}
-    }
-    mode = xalloc (sizeof (RRModeRec) + modeInfo->nameLength + 1);
-    mode->refcnt = 1;
-    mode->mode = *modeInfo;
-    mode->name = (char *) (mode + 1);
-    memcpy (mode->name, name, modeInfo->nameLength);
-    mode->name[modeInfo->nameLength] = '\0';
-    mode->id = FakeClientID(0);
-    if (!AddResource (mode->id, ModeType, (pointer) mode))
-	return NULL;
-    ++mode->refcnt;
-    pScrPriv->changed = TRUE;
-    return mode;
-}
-
-void
-RRModeDestroy (RRModePtr mode)
-{
-    if (--mode->refcnt > 0)
-	return;
-    xfree (mode);
-}
-
 /*
  * Return the first output which is connected to an active CRTC
  * Used in emulating 1.0 behaviour
@@ -594,11 +458,13 @@ RRFirstOutput (ScreenPtr pScreen)
     return NULL;
 }
 
-#ifdef RANDR_SCREEN_INTERFACE
+#ifdef RANDR_10_INTERFACE
 
-static Bool
+static RRModePtr
 RROldModeAdd (RROutputPtr output, RRScreenSizePtr size, int refresh)
 {
+    ScreenPtr	pScreen = output->pScreen;
+    rrScrPriv(pScreen);
     xRRModeInfo	modeInfo;
     char	name[100];
     RRModePtr	mode;
@@ -617,12 +483,15 @@ RROldModeAdd (RROutputPtr output, RRScre
     modeInfo.dotClock = ((CARD32) size->width * (CARD32) size->width *
 			 (CARD32) refresh);
     modeInfo.nameLength = strlen (name);
-    mode = RRModeGet (output->pScreen, &modeInfo, name);
+    mode = RRModeGet (pScreen, &modeInfo, name);
     if (!mode)
-	return FALSE;
+	return NULL;
     for (i = 0; i < output->numModes; i++)
 	if (output->modes[i] == mode)
-	    return TRUE;
+	{
+	    RRModeDestroy (mode);
+	    return mode;
+	}
     
     if (output->numModes)
 	modes = xrealloc (output->modes, 
@@ -630,11 +499,16 @@ RROldModeAdd (RROutputPtr output, RRScre
     else
 	modes = xalloc (sizeof (RRModePtr));
     if (!modes)
-	return FALSE;
+    {
+	RRModeDestroy (mode);
+	FreeResource (mode->id, 0);
+	return NULL;
+    }
     modes[output->numModes++] = mode;
     output->modes = modes;
     output->changed = TRUE;
-    return TRUE;
+    pScrPriv->changed = TRUE;
+    return mode;
 }
 
 static void
@@ -643,6 +517,7 @@ RRScanOldConfig (ScreenPtr pScreen, Rota
     rrScrPriv(pScreen);
     RROutputPtr	output = RRFirstOutput (pScreen);
     RRCrtcPtr	crtc;
+    RRModePtr	mode, newMode = NULL;
     int		i;
     CARD16	minWidth = MAXSHORT, minHeight = MAXSHORT;
     CARD16	maxWidth = 0, maxHeight = 0;
@@ -666,11 +541,29 @@ RRScanOldConfig (ScreenPtr pScreen, Rota
 	int		r;
 
 	if (size->nRates)
+	{
 	    for (r = 0; r < size->nRates; r++)
-		RROldModeAdd (output, size, size->pRates[r].rate);
+	    {
+		mode = RROldModeAdd (output, size, size->pRates[r].rate);
+		if (i == pScrPriv->size && 
+		    size->pRates[r].rate == pScrPriv->rate)
+		{
+		    newMode = mode;
+		}
+	    }
+	    xfree (size->pRates);
+	}
 	else
-	    RROldModeAdd (output, size, 0);
+	{
+	    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; i++) 
@@ -697,9 +590,17 @@ RRScanOldConfig (ScreenPtr pScreen, Rota
     if (maxHeight != pScrPriv->maxHeight) {
 	pScrPriv->maxHeight = maxHeight; pScrPriv->changed = TRUE;
     }
+
+    /* notice current mode */
+    if (newMode)
+	RRCrtcSet (output->crtc, newMode, 0, 0, pScrPriv->rotation,
+		   1, &output);
 }
 #endif
 
+/*
+ * Poll the driver for changed information
+ */
 static Bool
 RRGetInfo (ScreenPtr pScreen)
 {
@@ -718,7 +619,7 @@ RRGetInfo (ScreenPtr pScreen)
     if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations))
 	return FALSE;
 
-#if RANDR_SCREEN_INTERFACE
+#if RANDR_10_INTERFACE
     if (pScrPriv->nSizes)
 	RRScanOldConfig (pScreen, rotations);
 #endif
@@ -726,27 +627,6 @@ RRGetInfo (ScreenPtr 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)
 {
@@ -777,50 +657,6 @@ ProcRRQueryVersion (ClientPtr client)
     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;
-}
-
 typedef struct _RR10Data {
     RRScreenSizePtr sizes;
     int		    nsize;
@@ -829,7 +665,7 @@ typedef struct _RR10Data {
     CARD16	    refresh;
 } RR10DataRec, *RR10DataPtr;
 
-static CARD16
+CARD16
 RRVerticalRefresh (xRRModeInfo *mode)
 {
     CARD32  refresh;
@@ -1056,94 +892,6 @@ ProcRRGetScreenInfo (ClientPtr client)
 }
 
 #if 0
-static int
-RRMonitorSetMode (ScreenPtr pScreen, RRMonitorPtr pMonitor, 
-		  RRModePtr pMode, int x, int y, Rotation rotation,
-		  TimeStamp time)
-{
-    rrScrPriv(pScreen);
-    short   oldWidth, oldHeight;
-    
-    oldWidth = pScreen->width;
-    oldHeight = pScreen->height;
-    
-    /*
-     * call out to ddx routine to effect the change
-     */
-    if (pScrPriv->rrSetScreenSize && pScrPriv->rrSetMode)
-    {
-	xScreenSizes	oldSize;
-	if (!(*pScrPriv->rrSetMode) (pScreen, 0, NULL, 0, 0, RR_Rotate_0))
-	    return RRSetConfigFailed;
-	oldSize.widthInPixels = pScreen->width;
-	oldSize.heightInPixels = pScreen->width;
-	oldSize.widthInMillimeters = pScreen->mmWidth;
-	oldSize.heightInMillimeters = pScreen->mmHeight;
-	if (!(*pScrPriv->rrSetScreenSize) (pScreen,
-					   pMode->mode.width,
-					   pMode->mode.height,
-					   pMode->mode.widthInMillimeters,
-					   pMode->mode.heightInMillimeters))
-	{
-	    (void) (*pScrPriv->rrSetMode) (pScreen, 0, pMonitor->pMode,
-					   pMonitor->x, pMonitor->y,
-					   pMonitor->rotation);
-	    return RRSetConfigFailed;
-	}
-	if (!(*pScrPriv->rrSetMode) (pScreen, 0, pMode, 0, 0, rotation))
-	{
-	    (void) (*pScrPriv->rrSetScreenSize) (pScreen,
-						 oldSize.widthInPixels,
-						 oldSize.heightInPixels,
-						 oldSize.widthInMillimeters,
-						 oldSize.heightInMillimeters);
-	    (void) (*pScrPriv->rrSetMode) (pScreen, 0, pMonitor->pMode,
-					   pMonitor->x, pMonitor->y,
-					   pMonitor->rotation);
-	    return RRSetConfigFailed;
-	}
-    }
-#ifdef RANDR_SCREEN_INTERFACE
-    else if (pScrPriv->rrSetConfig)
-    {
-	int rate = RRVerticalRefresh (&pMode->mode);
-	RRScreenSizeRec	size;
-
-	size.width = pMode->mode.width;
-	size.height = pMode->mode.height;
-	size.mmWidth = pMode->mode.widthInMillimeters;
-	size.mmHeight = pMode->mode.heightInMillimeters;
-	if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate, &size))
-	    return RRSetConfigFailed;
-    }
-#endif
-    else
-	return RRSetConfigFailed;
-    
-    /*
-     * set current extension configuration pointers
-     */
-    RRSetCurrentMode (pMonitor, pMode, 0, 0, rotation);
-    
-    /*
-     * 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;
     return RRSetConfigSuccess;
 }
 #endif
@@ -1411,36 +1159,6 @@ RRSetScreenConfig (ScreenPtr		pScreen,
 }
 #endif
 
-static Bool
-RRSetScreenSize (ScreenPtr pScreen,
-		 CARD16 width, CARD16 height,
-		 CARD16 widthInMillimeters, CARD16 heightInMillimeters)
-{
-    rrScrPriv(pScreen);
-    
-    if (pScrPriv->rrScreenSetSize) 
-    {
-	return (*pScrPriv->rrScreenSetSize) (pScreen, width, height,
-					     widthInMillimeters,
-					     heightInMillimeters);
-    }
-#ifdef RANDR_SCREEN_INTERFACE
-    else
-    {
-	/* Pend the size change until we get the set mode request.
-	 * Yes, this is 'illegal', but the best we can do until
-	 * drivers are updated
-	 */
-	pScrPriv->reqWidth = width;
-	pScrPriv->reqHeight = height;
-	pScreen->mmWidth = widthInMillimeters;
-	pScreen->mmHeight = heightInMillimeters;
-	return TRUE;
-    }
-#endif
-    return FALSE;
-}
-
 static int
 ProcRRSelectInput (ClientPtr client)
 {
@@ -1524,7 +1242,7 @@ ProcRRSelectInput (ClientPtr client)
 		CompareTimeStamps (pTimes->configTime, 
 				   pScrPriv->lastConfigTime) != 0)
 	    {
-		DeliverScreenEvent (client, pWin, pScreen);
+		RRDeliverScreenEvent (client, pWin, pScreen);
 	    }
 	}
     }
@@ -1651,7 +1369,7 @@ static int ProcRRSetScreenSize (ClientPt
 	client->errorValue = 0;
 	return BadValue;
     }
-    if (!RRSetScreenSize (pScreen, 
+    if (!RRScreenSizeSet (pScreen, 
 			  stuff->width, stuff->height,
 			  stuff->widthInMillimeters,
 			  stuff->heightInMillimeters))
@@ -2000,6 +1718,7 @@ SProcRRDispatch (ClientPtr client)
     }
 }
 
+#if RANDR_12_INTERFACE
 /*
  * Register the range of sizes for the screen
  */
@@ -2019,8 +1738,9 @@ RRScreenSetSizeRange (ScreenPtr	pScreen,
     pScrPriv->maxWidth  = maxWidth;
     pScrPriv->maxHeight = maxHeight;
 }
+#endif
 
-#ifdef RANDR_SCREEN_INTERFACE
+#ifdef RANDR_10_INTERFACE
 
 static Bool
 RRScreenSizeMatches (RRScreenSizePtr  a,
@@ -2052,6 +1772,7 @@ RRRegisterSize (ScreenPtr	    pScreen,
     if (!pScrPriv)
 	return 0;
     
+    tmp.id = 0;
     tmp.width = width;
     tmp.height= height;
     tmp.mmWidth = mmWidth;
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 1694523..f323660 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -32,15 +32,35 @@
 #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_SCREEN_INTERFACE 1
+#define RANDR_10_INTERFACE 1
+/* #define RANDR_12_INTERFACE 1 */
 
 typedef XID	RRMode;
 typedef XID	RROutput;
 typedef XID	RRCrtc;
 
+extern int	RREventBase;
+
 /*
  * Modeline for a monitor. Name follows directly after this struct
  */
@@ -64,9 +84,9 @@ struct _rrCrtc {
     int		    x, y;
     Rotation	    rotation;
     Rotation	    rotations;
-    int		    numPossibleOutputs;
-    RROutputPtr	    *possibleOutputs;
     Bool	    changed;
+    int		    numOutputs;
+    RROutputPtr	    *outputs;
     void	    *devPrivate;
 };
 
@@ -88,11 +108,12 @@ struct _rrOutput {
     void	    *devPrivate;
 };
 
-typedef Bool (*RRScreenSetSizeProcPtr) (ScreenPtr	pScreen,
+#if RANDR_12_INTERFACE
+typedef Bool (*RRScreentSizeSetProcPtr) (ScreenPtr	pScreen,
 					CARD16		width,
 					CARD16		height,
-					CARD32		widthInMM,
-					CARD32		heightInMM);
+					CARD32		mmWidth,
+					CARD32		mmHeight);
 					
 typedef Bool (*RRCrtcSetProcPtr) (ScreenPtr		pScreen,
 				  RRCrtcPtr		crtc,
@@ -100,8 +121,9 @@ typedef Bool (*RRCrtcSetProcPtr) (Screen
 				  int			x,
 				  int			y,
 				  Rotation		rotation,
-				  int			numOutput,
+				  int			numOutputs,
 				  RROutputPtr		*outputs);
+#endif
 
 typedef Bool (*RRGetInfoProcPtr) (ScreenPtr pScreen, Rotation *rotations);
 typedef Bool (*RRCloseScreenProcPtr) ( int i, ScreenPtr pscreen);
@@ -121,7 +143,7 @@ typedef struct _rrScreenSize {
     RRScreenRatePtr pRates;
 } RRScreenSize, *RRScreenSizePtr;
 
-#ifdef RANDR_SCREEN_INTERFACE
+#ifdef RANDR_10_INTERFACE
 
 typedef Bool (*RRSetConfigProcPtr) (ScreenPtr		pScreen,
 				    Rotation		rotation,
@@ -136,12 +158,14 @@ typedef struct _rrScrPriv {
      * 'public' part of the structure; DDXen fill this in
      * as they initialize
      */
-#ifdef RANDR_SCREEN_INTERFACE
+#if RANDR_10_INTERFACE
     RRSetConfigProcPtr	    rrSetConfig;
 #endif
     RRGetInfoProcPtr	    rrGetInfo;
-    RRScreenSetSizeProcPtr  rrScreenSetSize;
+#if RANDR_12_INTERFACE
+    RRScreenSetSizeProcPtr  rrScreenSizeSet;
     RRCrtcSetProcPtr	    rrCrtcSet;
+#endif
     
     /*
      * Private part of the structure; not considered part of the ABI
@@ -152,6 +176,7 @@ typedef struct _rrScrPriv {
     Bool		    changed;
     CARD16		    minWidth, minHeight;
     CARD16		    maxWidth, maxHeight;
+    CARD16		    width, height;	/* last known screen size */
 
     /* modes, outputs and crtcs */
     int			    numModes;
@@ -163,7 +188,7 @@ typedef struct _rrScrPriv {
     int			    numCrtcs;
     RRCrtcPtr		    *crtcs;
 
-#ifdef RANDR_SCREEN_INTERFACE
+#ifdef RANDR_10_INTERFACE
     /*
      * Configuration information
      */
@@ -173,7 +198,6 @@ typedef struct _rrScrPriv {
     int			    nSizes;
     RRScreenSizePtr	    pSizes;
     
-    RRScreenSizePtr	    pSize;
     Rotation		    rotation;
     int			    rate;
     int			    size;
@@ -190,6 +214,7 @@ extern int rrPrivIndex;
 void
 RRExtensionInit (void);
 
+#ifdef RANDR_12_INTERFACE
 /*
  * Set the range of sizes for the screen
  */
@@ -199,89 +224,34 @@ RRScreenSetSizeRange (ScreenPtr	pScreen,
 		      CARD16	minHeight,
 		      CARD16	maxWidth,
 		      CARD16	maxHeight);
+#endif
 
+/* rrscreen.c */
 /*
- * Create a CRTC
- */
-RRCrtcPtr
-RRCrtcCreate (ScreenPtr	pScreen,
-	      void	*devPrivate);
-
-
-/*
- * Use this value for any num parameter to indicate that
- * the related data are unchanged
- */
-#define RR_NUM_UNCHANGED    -1
-
-/*
- * Notify the extension that the Crtc has been reconfigured
- */
-Bool
-RRCrtcSet (RRCrtcPtr	crtc,
-	   RRModePtr	mode,
-	   int		x,
-	   int		y,
-	   Rotation	rotation,
-	   int		numOutput,
-	   RROutputPtr	*outputs);
-
-/*
- * Destroy a Crtc at shutdown
- */
-void
-RRCrtcDestroy (RRCrtcPtr crtc);
-
-/*
- * Find, and if necessary, create a mode
- */
-
-RRModePtr
-RRModeGet (ScreenPtr	pScreen,
-	   xRRModeInfo	*modeInfo,
-	   char		*name);
-
-/*
- * Destroy a mode.
+ * 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
-RRModeDestroy (RRModePtr mode);
+RRScreenSizeNotify (ScreenPtr	pScreen);
 
 /*
- * Create an output
+ * Request that the screen be resized
  */
-
-RROutputPtr
-RROutputCreate (ScreenPtr   pScreen,
-		char	    *name,
-		int	    nameLength,
-		void	    *devPrivate);
+Bool
+RRScreenSizeSet (ScreenPtr  pScreen,
+		 CARD16	    width,
+		 CARD16	    height,
+		 CARD32	    mmWidth,
+		 CARD32	    mmHeight);
 
 /*
- * Notify extension that output parameters have been changed
+ * Deliver a ScreenNotify event
  */
-Bool
-RROutputSet (RROutputPtr    output,
-	     RROutputPtr    *clones,
-	     int	    numClones,
-	     RRModePtr	    *modes,
-	     int	    numModes,
-	     RRCrtcPtr	    *crtcs,
-	     int	    numCrtcs,
-	     CARD8	    connection);
-
 void
-RROutputDestroy (RROutputPtr	output);
-
-void
-RRTellChanged (ScreenPtr pScreen);
-
-Bool RRScreenInit(ScreenPtr pScreen);
-
-Rotation
-RRGetRotation (ScreenPtr pScreen);
-
+RRDeliverScreenEvent (ClientPtr client, WindowPtr pWin, ScreenPtr pScreen);
+    
+/* mirandr.c */
 Bool
 miRandRInit (ScreenPtr pScreen);
 
@@ -301,7 +271,22 @@ miRRCrtcSet (ScreenPtr	pScreen,
 	     int	numOutput,
 	     RROutputPtr    *outputs);
 
-#ifdef RANDR_SCREEN_INTERFACE					
+/* randr.c */
+/*
+ * Send all pending events
+ */
+void
+RRTellChanged (ScreenPtr pScreen);
+
+Bool RRScreenInit(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
@@ -344,4 +329,122 @@ RRSetScreenConfig (ScreenPtr		pScreen,
 		   RRScreenSizePtr	pSize);
 
 #endif					
+
+/* rrcrtc.c */
+/*
+ * Create a CRTC
+ */
+RRCrtcPtr
+RRCrtcCreate (ScreenPtr	pScreen,
+	      void	*devPrivate);
+
+
+/*
+ * Use this value for any num parameter to indicate that
+ * the related data are unchanged
+ */
+#define RR_NUM_UNCHANGED    -1
+
+/*
+ * 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	    numOutput,
+	      RROutputPtr   *outputs);
+
+/*
+ * Request that the Crtc be reconfigured
+ */
+Bool
+RRCrtcSet (RRCrtcPtr    crtc,
+	   RRModePtr	mode,
+	   int		x,
+	   int		y,
+	   Rotation	rotation,
+	   int		numOutput,
+	   RROutputPtr  *outputs);
+
+/*
+ * Destroy a Crtc at shutdown
+ */
+void
+RRCrtcDestroy (RRCrtcPtr crtc);
+
+/*
+ * Initialize crtc type
+ */
+Bool
+RRCrtcInit (void);
+
+/* rrmode.c */
+/*
+ * Find, and if necessary, create a mode
+ */
+
+RRModePtr
+RRModeGet (ScreenPtr	pScreen,
+	   xRRModeInfo	*modeInfo,
+	   char		*name);
+
+/*
+ * Destroy a mode.
+ */
+
+void
+RRModeDestroy (RRModePtr mode);
+
+/*
+ * Initialize mode type
+ */
+Bool
+RRModeInit (void);
+    
+/* rroutput.c */
+/*
+ * Create an output
+ */
+
+RROutputPtr
+RROutputCreate (ScreenPtr   pScreen,
+		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);
+
+Bool
+RROutputSetCrtcs (RROutputPtr	output,
+		  RRCrtcPtr	*crtcs,
+		  int		numCrtcs);
+
+Bool
+RROutputSetConnection (RROutputPtr  output,
+		       CARD8	    connection);
+
+void
+RROutputDestroy (RROutputPtr	output);
+
+/*
+ * Initialize output type
+ */
+Bool
+RROutputInit (void);
+    
 #endif /* _RANDRSTR_H_ */
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
new file mode 100644
index 0000000..cc5b24d
--- /dev/null
+++ b/randr/rrcrtc.c
@@ -0,0 +1,238 @@
+/*
+ * 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 RESTYPE	CrtcType;
+
+/*
+ * Create a CRTC
+ */
+RRCrtcPtr
+RRCrtcCreate (ScreenPtr	pScreen,
+	      void	*devPrivate)
+{
+    rrScrPriv (pScreen);
+    RRCrtcPtr	crtc;
+    RRCrtcPtr	*crtcs;
+    
+    crtc = xalloc (sizeof (RRCrtcRec));
+    if (!crtc)
+	return NULL;
+    if (pScrPriv->numCrtcs)
+	crtcs = xrealloc (pScrPriv->crtcs, 
+			  (pScrPriv->numCrtcs + 1) * sizeof (RRCrtcPtr));
+    else
+	crtcs = xalloc (sizeof (RRCrtcPtr));
+    if (!crtcs)
+    {
+	xfree (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->changed = TRUE;
+    crtc->devPrivate = devPrivate;
+    pScrPriv->crtcs[pScrPriv->numCrtcs++] = crtc;
+    return crtc;
+}
+
+/*
+ * 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)
+{
+    ScreenPtr	pScreen = crtc->pScreen;
+    rrScrPriv(pScreen);
+    int	    i, j;
+    int	    prevNumOutputs = crtc->numOutputs;
+    
+    if (numOutputs != prevNumOutputs)
+    {
+	RROutputPtr *outputs;
+	
+	if (crtc->numOutputs)
+	    outputs = xrealloc (crtc->outputs,
+				numOutputs * sizeof (RROutputPtr));
+	else
+	    outputs = xalloc (numOutputs * sizeof (RROutputPtr));
+	if (!outputs)
+	    return FALSE;
+	crtc->outputs = outputs;
+    }
+    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]->changed = TRUE;
+	    crtc->changed = TRUE;
+	}
+    }
+    for (j = 0; j < crtc->numOutputs; j++)
+    {
+	for (i = 0; i < numOutputs; i++)
+	    if (outputs[i] == crtc->outputs[j])
+		break;
+	if (i != numOutputs)
+	{
+	    crtc->outputs[j]->changed = TRUE;
+	    crtc->changed = TRUE;
+	}
+    }
+    if (mode != crtc->mode)
+    {
+	if (crtc->mode)
+	    RRModeDestroy (crtc->mode);
+	crtc->mode = mode;
+	mode->refcnt++;
+	crtc->changed = TRUE;
+    }
+    if (x != crtc->x)
+    {
+	crtc->x = x;
+	crtc->changed = TRUE;
+    }
+    if (y != crtc->y)
+    {
+	crtc->y = y;
+	crtc->changed = TRUE;
+    }
+    if (rotation != crtc->rotation)
+    {
+	crtc->rotation = rotation;
+	crtc->changed = TRUE;
+    }
+    if (crtc->changed)
+	pScrPriv->changed = TRUE;
+    return TRUE;
+}
+
+/*
+ * 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;
+    rrScrPriv(pScreen);
+
+#if RANDR_12_INTERFACE
+    if (pScrPriv->rrCrtcSet)
+    {
+	return (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y, 
+				       rotation, numOutputs, outputs);
+    }
+#endif
+#if RANDR_10_INTERFACE
+    if (pScrPriv->rrSetConfig)
+    {
+	RRScreenSize	    size;
+	RRScreenRate	    rate;
+	Bool		    ret;
+
+	size.width = mode->mode.width;
+	size.height = mode->mode.height;
+	size.mmWidth = mode->mode.mmWidth;
+	size.mmHeight = mode->mode.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)
+	    RRScreenSizeNotify (pScreen);
+	return ret;
+    }
+#endif
+    return FALSE;
+}
+
+/*
+ * 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;
+    rrScrPriv(pScreen);
+    int		i;
+
+    for (i = 0; i < pScrPriv->numCrtcs; i++)
+    {
+	if (pScrPriv->crtcs[i] == crtc)
+	{
+	    memmove (pScrPriv->crtcs, pScrPriv->crtcs + 1,
+		     (pScrPriv->numCrtcs - (i - 1)) * sizeof (RRCrtcPtr));
+	    --pScrPriv->numCrtcs;
+	}
+    }
+    free (value);
+    return 1;
+}
+
+/*
+ * Initialize crtc type
+ */
+Bool
+RRCrtcInit (void)
+{
+    CrtcType = CreateNewResourceType (RRCrtcDestroyResource);
+    if (!CrtcType)
+	return FALSE;
+#ifdef XResExtension
+	RegisterResourceName (CrtcType, "CRTC");
+#endif
+    return TRUE;
+}
diff --git a/randr/rrmode.c b/randr/rrmode.c
new file mode 100644
index 0000000..1eb53c3
--- /dev/null
+++ b/randr/rrmode.c
@@ -0,0 +1,85 @@
+/*
+ * 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 RESTYPE	ModeType;
+
+RRModePtr
+RRModeGet (ScreenPtr	pScreen,
+	   xRRModeInfo	*modeInfo,
+	   char		*name)
+{
+    rrScrPriv (pScreen);
+    int	i;
+    RRModePtr	mode;
+
+    for (i = 0; i < pScrPriv->numModes; i++)
+    {
+	mode = pScrPriv->modes[i];
+	if (!memcmp (modeInfo, &mode->mode, sizeof (xRRModeInfo)) &&
+	    !memcmp (name, mode->name, modeInfo->nameLength))
+	{
+	    ++mode->refcnt;
+	    return mode;
+	}
+    }
+    mode = xalloc (sizeof (RRModeRec) + modeInfo->nameLength + 1);
+    mode->refcnt = 1;
+    mode->mode = *modeInfo;
+    mode->name = (char *) (mode + 1);
+    memcpy (mode->name, name, modeInfo->nameLength);
+    mode->name[modeInfo->nameLength] = '\0';
+    mode->id = FakeClientID(0);
+    if (!AddResource (mode->id, ModeType, (pointer) mode))
+	return NULL;
+    ++mode->refcnt;
+    pScrPriv->changed = TRUE;
+    return mode;
+}
+
+void
+RRModeDestroy (RRModePtr mode)
+{
+    if (--mode->refcnt > 0)
+	return;
+    xfree (mode);
+}
+
+static int
+RRModeDestroyResource (pointer value, XID pid)
+{
+    RRModeDestroy ((RRModePtr) value);
+    return 1;
+}
+
+Bool
+RRModeInit (void)
+{
+    ModeType = CreateNewResourceType (RRModeDestroyResource);
+    if (!ModeType)
+	return FALSE;
+#ifdef XResExtension
+    RegisterResourceName (ModeType, "MODE");
+#endif
+    return TRUE;
+}
diff --git a/randr/rroutput.c b/randr/rroutput.c
new file mode 100644
index 0000000..c7e7995
--- /dev/null
+++ b/randr/rroutput.c
@@ -0,0 +1,56 @@
+/*
+ * 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 RESTYPE	OutputType;
+
+/*
+ * Destroy a Output at shutdown
+ */
+void
+RROutputDestroy (RROutputPtr crtc)
+{
+    FreeResource (crtc->id, 0);
+}
+
+static int
+RROutputDestroyResource (pointer value, XID pid)
+{
+    free (value);
+    return 1;
+}
+
+/*
+ * Initialize crtc type
+ */
+Bool
+RROutputInit (void)
+{
+    OutputType = CreateNewResourceType (RROutputDestroyResource);
+    if (!OutputType)
+	return FALSE;
+#ifdef XResExtension
+	RegisterResourceName (OutputType, "OUTPUT");
+#endif
+    return TRUE;
+}
diff --git a/randr/rrscreen.c b/randr/rrscreen.c
new file mode 100644
index 0000000..47ba12d
--- /dev/null
+++ b/randr/rrscreen.c
@@ -0,0 +1,205 @@
+/*
+ * 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};
+
+/*
+ * 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;
+}
+
+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);
+}
+
+void
+RRDeliverScreenEvent (ClientPtr client, WindowPtr pWin, ScreenPtr pScreen)
+{
+    rrScrPriv (pScreen);
+    xRRScreenChangeNotifyEvent	se;
+    RRCrtcPtr	crtc = pScrPriv->numCrtcs ? pScrPriv->crtcs[0] : NULL;
+    RROutputPtr	output = pScrPriv->numOutputs ? pScrPriv->outputs[0] : NULL;
+    RRModePtr	mode = crtc ? crtc->mode : NULL;
+    WindowPtr	pRoot = WindowTable[pScreen->myNum];
+    int		i;
+    
+    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;
+    if (mode) 
+    {
+	se.sizeID = -1;
+	for (i = 0; i < output->numModes; i++)
+	    if (mode == output->modes[i])
+	    {
+		se.sizeID = i;
+		break;
+	    }
+	se.widthInPixels = mode->mode.width;
+	se.heightInPixels = mode->mode.height;
+	se.widthInMillimeters = mode->mode.mmWidth;
+	se.heightInMillimeters = mode->mode.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;
+    }    
+    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)
+	return;
+    
+    pScrPriv->width = pScreen->width;
+    pScrPriv->height = pScreen->height;
+    pScrPriv->changed = TRUE;
+
+    RRSendConfigNotify (pScreen);
+    RREditConnectionInfo (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->rrScreenSizeSet)
+    {
+	return (*pScrPriv->rrScreenSizeSet) (pScreen,
+					     width, height,
+					     mmWidth, mmHeight);
+    }
+#endif
+#if RANDR_10_INTERFACE
+    if (pScrPriv->rrSetConfig)
+    {
+	return TRUE;	/* can't set size separately */
+    }
+#endif
+    return FALSE;
+}
+
diff-tree d7f1f286b7b034827956c857f8f2effbc161e5b2 (from fbaeb0b2a1e0ad29b8d284045a9a60cd873f2edb)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sat Sep 16 21:44:42 2006 -0700

    Start moving to new randr 1.2 definition

diff --git a/randr/mirandr.c b/randr/mirandr.c
index e152133..5aea38d 100644
--- a/randr/mirandr.c
+++ b/randr/mirandr.c
@@ -34,51 +34,9 @@
 #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;
-    RRMonitorPtr pMonitor;
-    
-    pMonitor = RRRegisterMonitor (pScreen, NULL, RR_Rotate_0);
-    for (i = 0; i < pScreen->numDepths; i++)
-    {
-	if (pScreen->allowedDepths[i].numVids)
-	{
-	    xRRMonitorMode		rrMode;
-	    RRModePtr			pMode;
-	    char			name[64];
-
-	    sprintf (name, "%dx%d", pScreen->width, pScreen->height);
-	    memset (&rrMode, '\0', sizeof (rrMode));
-	    rrMode.width = pScreen->width;
-	    rrMode.height = pScreen->height;
-	    rrMode.widthInMillimeters = pScreen->mmWidth;
-	    rrMode.heightInMillimeters = pScreen->mmHeight;
-	    rrMode.nameLength = strlen (name);
-	    pMonitor = RRRegisterMonitor (pScreen, NULL, RR_Rotate_0);
-	    pMode = RRRegisterMode (pMonitor,
-				    &rrMode,
-				    name);
-	    if (!pMode)
-		return FALSE;
-	    if (!setConfig)
-	    {
-		RRSetCurrentMode (pMonitor, pMode, 0, 0, RR_Rotate_0);
-		setConfig = TRUE;
-	    }
-	}
-    }
     return TRUE;
 }
 
@@ -87,26 +45,73 @@ miRRGetInfo (ScreenPtr pScreen, Rotation
  * different here
  */
 Bool
-miRRSetMode (ScreenPtr	pScreen,
-	     int	monitor,
-	     RRModePtr	pMode,
+miRRCrtcSet (ScreenPtr	pScreen,
+	     RRCrtcPtr	crtc,
+	     RRModePtr	mode,
 	     int	x,
 	     int	y,
-	     Rotation	rotation)
+	     Rotation	rotation,
+	     int	numOutput,
+	     RROutputPtr    *outputs)
 {
     return TRUE;
 }
 
+/*
+ * 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;
+    RRModePtr	mode;
+    RRCrtcPtr	crtc;
+    RROutputPtr	output;
+    xRRModeInfo modeInfo;
+    char	name[64];
     
     if (!RRScreenInit (pScreen))
 	return FALSE;
-    rp = rrGetScrPriv(pScreen);
-    rp->rrGetInfo = miRRGetInfo;
-    rp->rrSetMode = miRRSetMode;
+    pScrPriv = rrGetScrPriv(pScreen);
+    pScrPriv->rrGetInfo = miRRGetInfo;
+    pScrPriv->rrCrtcSet = miRRCrtcSet;
+    
+    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.mmWidth = pScreen->mmWidth;
+    modeInfo.mmHeight = pScreen->mmHeight;
+    modeInfo.nameLength = strlen (name);
+    
+    mode = RRModeGet (pScreen, &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 (!RROutputSet (output, 
+		      NULL, 0,  /* clones */
+		      &mode, 1, /* modes */
+		      &crtc, 1, /* crtcs */
+		      RR_Connected))
+	return FALSE;
+    if (!RRCrtcSet (crtc, mode, 0, 0, RR_Rotate_0, 1, &output))
+	return FALSE;
     return TRUE;
 }
diff --git a/randr/randr.c b/randr/randr.c
index 58d8f17..e34b82c 100644
--- a/randr/randr.c
+++ b/randr/randr.c
@@ -60,6 +60,8 @@
 int	RRGeneration;
 int	RRNScreens;
 
+static RESTYPE	    ModeType, CrtcType, OutputType;
+
 static int ProcRRQueryVersion (ClientPtr pClient);
 static int ProcRRDispatch (ClientPtr pClient);
 static int SProcRRDispatch (ClientPtr pClient);
@@ -160,21 +162,16 @@ static Bool
 RRCloseScreen (int i, ScreenPtr pScreen)
 {
     rrScrPriv(pScreen);
-    RRMonitorPtr    pMonitor;
+    int		    j;
 
     unwrap (pScrPriv, pScreen, CloseScreen);
-    while ((pMonitor = pScrPriv->pMonitors))
-    {
-	RRModePtr   pMode;
-	
-	pScrPriv->pMonitors = pMonitor->next;
-	while ((pMode = pMonitor->pModes))
-	{
-	    pMonitor->pModes = pMode->next;
-	    xfree (pMode);
-	}
-	xfree (pMonitor);
-    }
+    for (j = pScrPriv->numCrtcs - 1; j >= 0; j--)
+	RRCrtcDestroy (pScrPriv->crtcs[j]);
+    for (j = pScrPriv->numOutputs - 1; j >= 0; j--)
+	RROutputDestroy (pScrPriv->outputs[j]);
+    for (j = pScrPriv->numModes - 1; j >= 0; j--)
+	RRModeDestroy (pScrPriv->modes[j]);
+    
     xfree (pScrPriv);
     RRNScreens -= 1;	/* ok, one fewer screen with RandR running */
     return (*pScreen->CloseScreen) (i, pScreen);    
@@ -199,6 +196,7 @@ SRRScreenChangeNotifyEvent(xRRScreenChan
     cpswaps(from->subpixelOrder, to->subpixelOrder);
 }
 
+#if 0
 static void
 SRRMonitorChangeNotifyEvent(xRRMonitorChangeNotifyEvent *from,
 			    xRRMonitorChangeNotifyEvent *to)
@@ -217,30 +215,68 @@ SRRMonitorChangeNotifyEvent(xRRMonitorCh
     cpswaps(from->x, to->x);
     cpswaps(from->y, to->y);
 }
+#endif
 
 static void
 SRRNotifyEvent (xEvent *from,
 		xEvent *to)
 {
     switch (from->u.u.detail) {
+#if 0
     case RRNotify_MonitorChange:
 	SRRMonitorChangeNotifyEvent ((xRRMonitorChangeNotifyEvent *) from,
 				     (xRRMonitorChangeNotifyEvent *) to);
 	break;
+#endif
     default:
 	break;
     }
 }
 
+static int
+RRModeDestroyResource (pointer value, XID pid)
+{
+    RRModeDestroy ((RRModePtr) value);
+    return 1;
+}
+
+static int
+RRCrtcDestroyResource (pointer value, XID pid)
+{
+    RRCrtcDestroy ((RRCrtcPtr) value);
+    return 1;
+}
+
+static int
+RROutputDestroyResource (pointer value, XID pid)
+{
+    RROutputDestroy ((RROutputPtr) value);
+    return 1;
+}
+
 Bool RRScreenInit(ScreenPtr pScreen)
 {
     rrScrPrivPtr   pScrPriv;
 
     if (RRGeneration != serverGeneration)
     {
+	ModeType = CreateNewResourceType (RRModeDestroyResource);
+	if (!ModeType)
+	    return FALSE;
+	CrtcType = CreateNewResourceType (RRCrtcDestroyResource);
+	if (!ModeType)
+	    return FALSE;
+	OutputType = CreateNewResourceType (RROutputDestroyResource);
+	if (!ModeType)
+	    return FALSE;
 	if ((rrPrivIndex = AllocateScreenPrivateIndex()) < 0)
 	    return FALSE;
 	RRGeneration = serverGeneration;
+#ifdef XResExtension
+	RegisterResourceName (ModeType, "MODE");
+	RegisterResourceName (CrtcType, "CRTC");
+	RegisterResourceName (OutputType, "OUTPUT");
+#endif
     }
 
     pScrPriv = (rrScrPrivPtr) xalloc (sizeof (rrScrPrivRec));
@@ -252,10 +288,14 @@ Bool RRScreenInit(ScreenPtr pScreen)
     /*
      * Calling function best set these function vectors
      */
-    pScrPriv->rrSetMode = 0;
+    pScrPriv->rrCrtcSet = 0;
     pScrPriv->rrGetInfo = 0;
+    pScrPriv->maxWidth = pScrPriv->minWidth = pScreen->width;
+    pScrPriv->maxHeight = pScrPriv->minHeight = pScreen->height;
 #ifdef RANDR_SCREEN_INTERFACE    
     pScrPriv->rrSetConfig = 0;
+    pScrPriv->reqWidth = pScreen->width;
+    pScrPriv->reqHeight = pScreen->height;
 #endif
     
     /*
@@ -268,7 +308,12 @@ Bool RRScreenInit(ScreenPtr pScreen)
     
     wrap (pScrPriv, pScreen, CloseScreen, RRCloseScreen);
 
-    pScrPriv->pMonitors = NULL;
+    pScrPriv->numModes = 0;
+    pScrPriv->modes = NULL;
+    pScrPriv->numOutputs = 0;
+    pScrPriv->outputs = NULL;
+    pScrPriv->numCrtcs = 0;
+    pScrPriv->crtcs = NULL;
     
     RRNScreens += 1;	/* keep count of screens that implement randr */
     return TRUE;
@@ -356,18 +401,77 @@ RRExtensionInit (void)
     return;
 }
 		
+static void
+DeliverScreenEvent (ClientPtr client, WindowPtr pWin, ScreenPtr pScreen)
+{
+    rrScrPriv (pScreen);
+    xRRScreenChangeNotifyEvent	se;
+    RRCrtcPtr	crtc = pScrPriv->numCrtcs ? pScrPriv->crtcs[0] : NULL;
+    RROutputPtr	output = pScrPriv->numOutputs ? pScrPriv->outputs[0] : NULL;
+    RRModePtr	mode = crtc ? crtc->mode : NULL;
+    WindowPtr	pRoot = WindowTable[pScreen->myNum];
+    int		i;
+    
+    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;
+    if (mode) 
+    {
+	se.sizeID = -1;
+	for (i = 0; i < output->numModes; i++)
+	    if (mode == output->modes[i])
+	    {
+		se.sizeID = i;
+		break;
+	    }
+	se.widthInPixels = mode->mode.width;
+	se.heightInPixels = mode->mode.height;
+	se.widthInMillimeters = mode->mode.mmWidth;
+	se.heightInMillimeters = mode->mode.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;
+    }    
+    WriteEventsToClient (client, 1, (xEvent *) &se);
+}
+
+static void
+DeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc)
+{
+}
+
+static void
+DeliverOutputEvent (ClientPtr client, WindowPtr pWin, RROutputPtr output)
+{
+}
+
 static int
 TellChanged (WindowPtr pWin, pointer value)
 {
     RREventPtr			*pHead, pRREvent;
     ClientPtr			client;
-    xRRScreenChangeNotifyEvent	se;
-    xRRMonitorChangeNotifyEvent	me;
     ScreenPtr			pScreen = pWin->drawable.pScreen;
     rrScrPriv(pScreen);
-    RRModePtr			pMode;
-    RRMonitorPtr		pMonitor;
-    WindowPtr			pRoot = WindowTable[pScreen->myNum];
     int				i;
 
     pHead = (RREventPtr *) LookupIDByType (pWin->drawable.id, EventType);
@@ -380,192 +484,245 @@ TellChanged (WindowPtr pWin, pointer val
 	if (client == serverClient || client->clientGone)
 	    continue;
 
-	if (pRREvent->mask & RRMonitorChangeNotifyMask)
+	if (pRREvent->mask & RRScreenChangeNotifyMask)
+	    DeliverScreenEvent (client, pWin, pScreen);
+	
+	if (pRREvent->mask & RRCrtcChangeNotifyMask)
 	{
-	    me.type = RRNotify + RREventBase;
-	    me.subCode = RRNotify_MonitorChange;
-	    me.timestamp = pScrPriv->lastSetTime.milliseconds;
-	    me.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
-	    me.root =  pRoot->drawable.id;
-	    me.window = pWin->drawable.id;
-#ifdef RENDER
-	    me.subpixelOrder = PictureGetSubpixelOrder (pScreen);
-#else
-	    me.subpixelOrder = SubPixelUnknown;
-#endif
-	    for (pMonitor = pScrPriv->pMonitors, i = 0; 
-		 pMonitor; 
-		 pMonitor = pMonitor->next, i++)
+	    for (i = 0; i < pScrPriv->numCrtcs; i++)
 	    {
-		me.monitor = i;
-		if (pMonitor->pMode) {
-		    me.modeID = pMonitor->pMode->id;
-		    me.rotation = pMonitor->rotation;
-		    me.x = pMonitor->x;
-		    me.y = pMonitor->y;
-		} else {
-		    me.modeID = 0xffff;
-		    me.rotation = RR_Rotate_0;
-		    me.x = 0;
-		    me.y = 0;
-		}
-		WriteEventsToClient (client, 1, (xEvent *) &me);
+		RRCrtcPtr   crtc = pScrPriv->crtcs[i];
+		if (crtc->changed)
+		    DeliverCrtcEvent (client, pWin, crtc);
 	    }
 	}
-	if ((pRREvent->mask & RRScreenChangeNotifyMask) &&
-	    (pMonitor = pScrPriv->pMonitors))
+	
+	if (pRREvent->mask & RROutputChangeNotifyMask)
 	{
-	    se.type = RRScreenChangeNotify + RREventBase;
-	    se.rotation = (CARD8) pMonitor->rotation;
-	    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
-
-	    pMonitor = &pScrPriv->pMonitors[0];
-	    se.sequenceNumber = client->sequence;
-	    if (pMonitor->pMode) 
+	    for (i = 0; i < pScrPriv->numOutputs; i++)
 	    {
-		pMode = pMonitor->pMode;
-		se.sizeID = pMode->id;
-		se.widthInPixels = pMode->mode.width;
-		se.heightInPixels = pMode->mode.height;
-		se.widthInMillimeters = pMode->mode.widthInMillimeters;
-		se.heightInMillimeters = pMode->mode.heightInMillimeters;
+		RROutputPtr   output = pScrPriv->outputs[i];
+		if (output->changed)
+		    DeliverOutputEvent (client, pWin, output);
 	    }
-	    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;
-	    }    
-	    WriteEventsToClient (client, 1, (xEvent *) &se);
 	}
     }
     return WT_WALKCHILDREN;
 }
 
-static void
-RRFreeMode (RRModePtr pMode)
+void
+RRTellChanged (ScreenPtr pScreen)
 {
-    xfree (pMode);
+    rrScrPriv (pScreen);
+    int i;
+    
+    if (pScrPriv->changed)
+    {
+	UpdateCurrentTime ();
+	pScrPriv->lastConfigTime = currentTime;
+	WalkTree (pScreen, TellChanged, (pointer) pScreen);
+	pScrPriv->changed = FALSE;
+	for (i = 0; i < pScrPriv->numOutputs; i++)
+	    pScrPriv->outputs[i]->changed = FALSE;
+	for (i = 0; i < pScrPriv->numCrtcs; i++)
+	    pScrPriv->crtcs[i]->changed = FALSE;
+    }
 }
 
-static void
-RRFreeModes (RRModePtr pHead)
+RRModePtr
+RRModeGet (ScreenPtr	pScreen,
+	   xRRModeInfo	*modeInfo,
+	   char		*name)
 {
-    RRModePtr	pMode;
-    while ((pMode = pHead)) 
+    rrScrPriv (pScreen);
+    int	i;
+    RRModePtr	mode;
+
+    for (i = 0; i < pScrPriv->numModes; i++)
     {
-	pHead = pMode->next;
-	RRFreeMode (pMode);
-    }
+	mode = pScrPriv->modes[i];
+	if (!memcmp (modeInfo, &mode->mode, sizeof (xRRModeInfo)) &&
+	    !memcmp (name, mode->name, modeInfo->nameLength))
+	{
+	    ++mode->refcnt;
+	    return mode;
+	}
+    }
+    mode = xalloc (sizeof (RRModeRec) + modeInfo->nameLength + 1);
+    mode->refcnt = 1;
+    mode->mode = *modeInfo;
+    mode->name = (char *) (mode + 1);
+    memcpy (mode->name, name, modeInfo->nameLength);
+    mode->name[modeInfo->nameLength] = '\0';
+    mode->id = FakeClientID(0);
+    if (!AddResource (mode->id, ModeType, (pointer) mode))
+	return NULL;
+    ++mode->refcnt;
+    pScrPriv->changed = TRUE;
+    return mode;
 }
 
-static void
-RRFreeMonitor (RRMonitorPtr pMonitor)
+void
+RRModeDestroy (RRModePtr mode)
 {
-    RRFreeModes (pMonitor->pModes);
-    xfree (pMonitor);
+    if (--mode->refcnt > 0)
+	return;
+    xfree (mode);
 }
 
-
-static Bool
-RRGetInfo (ScreenPtr pScreen)
+/*
+ * Return the first output which is connected to an active CRTC
+ * Used in emulating 1.0 behaviour
+ */
+static RROutputPtr
+RRFirstOutput (ScreenPtr pScreen)
 {
-    rrScrPriv (pScreen);
-    Bool	    changed;
-    Rotation	    rotations;
-    RRMonitorPtr    pMonitor, *pPrevMon;
-    RRModePtr	    pMode, *pPrevMode;
-    int		    monitorid;
-
-    for (pMonitor = pScrPriv->pMonitors; pMonitor; pMonitor = pMonitor->next)
+    rrScrPriv(pScreen);
+    RROutputPtr		    output;
+    int	i, j;
+    
+    for (i = 0; i < pScrPriv->numCrtcs; i++)
     {
-	pMonitor->oldReferenced = TRUE;
-	pMonitor->referenced = FALSE;
-	pMonitor->pMode = NULL;
-	for (pMode = pMonitor->pModes; pMode; pMode = pMode->next)
+	RRCrtcPtr   crtc = pScrPriv->crtcs[i];
+	for (j = 0; j < pScrPriv->numOutputs; j++)
 	{
-	    pMode->oldReferenced = TRUE;
-	    pMode->referenced = FALSE;
+	    output = pScrPriv->outputs[j];
+	    if (output->crtc == crtc)
+		return output;
 	}
     }
-    rotations = 0;
-    if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations))
+    return NULL;
+}
+
+#ifdef RANDR_SCREEN_INTERFACE
+
+static Bool
+RROldModeAdd (RROutputPtr output, RRScreenSizePtr size, int refresh)
+{
+    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.mmWidth = size->mmWidth;
+    modeInfo.mmHeight = size->mmHeight;
+    modeInfo.hTotal = size->width;
+    modeInfo.vTotal = size->height;
+    modeInfo.dotClock = ((CARD32) size->width * (CARD32) size->width *
+			 (CARD32) refresh);
+    modeInfo.nameLength = strlen (name);
+    mode = RRModeGet (output->pScreen, &modeInfo, name);
+    if (!mode)
 	return FALSE;
+    for (i = 0; i < output->numModes; i++)
+	if (output->modes[i] == mode)
+	    return TRUE;
+    
+    if (output->numModes)
+	modes = xrealloc (output->modes, 
+			  (output->numModes + 1) * sizeof (RRModePtr));
+    else
+	modes = xalloc (sizeof (RRModePtr));
+    if (!modes)
+	return FALSE;
+    modes[output->numModes++] = mode;
+    output->modes = modes;
+    output->changed = TRUE;
+    return TRUE;
+}
 
-    changed = FALSE;
+static void
+RRScanOldConfig (ScreenPtr pScreen, Rotation rotations)
+{
+    rrScrPriv(pScreen);
+    RROutputPtr	output = RRFirstOutput (pScreen);
+    RRCrtcPtr	crtc;
+    int		i;
+    CARD16	minWidth = MAXSHORT, minHeight = MAXSHORT;
+    CARD16	maxWidth = 0, maxHeight = 0;
     
-    /* Old GetInfo clients return rotations here */
-    if (rotations && pScrPriv->pMonitors) {
-	/*
-	 * Check whether anything changed and simultaneously generate
-	 * the protocol id values for the objects
-	 */
-	if (rotations != pScrPriv->pMonitors->rotations)
-	{
-	    pScrPriv->pMonitors->rotations = rotations;
-	    changed = TRUE;
-	}
+    if (!output)
+	return;
+    crtc = output->crtc;
+
+    /* check rotations */
+    if (rotations != crtc->rotations)
+    {
+        crtc->rotations = rotations;
+	crtc->changed = TRUE;
+	pScrPriv->changed = TRUE;
     }
 	
-    /*
-     * Walk monitor and mode lists looking for updates
-     */
-    monitorid = 0;
-    for (pPrevMon = &pScrPriv->pMonitors; (pMonitor = *pPrevMon);)
+    /* regenerate mode list */
+    for (i = 0; i < pScrPriv->nSizes; i++)
     {
-	int modeid = 0;
-	
-	if (pMonitor->referenced)
-	{
-	    pMonitor->id = monitorid++;
-	    if (!pMonitor->oldReferenced)
-		changed = TRUE;
-	    for (pPrevMode = &pMonitor->pModes; (pMode = *pPrevMode);)
-	    {
-		if (pMode->referenced)
-		{
-		    pMode->id = modeid++;
-		    if (!pMode->oldReferenced)
-			changed = TRUE;
-		    pPrevMode = &pMode->next;
-		}
-		else
-		{
-		    *pPrevMode = pMode->next;
-		    changed = TRUE;
-		    RRFreeMode (pMode);
-		}
-	    }
-	    pPrevMon = &pMonitor->next;
-	}
+	RRScreenSizePtr	size = &pScrPriv->pSizes[i];
+	int		r;
+
+	if (size->nRates)
+	    for (r = 0; r < size->nRates; r++)
+		RROldModeAdd (output, size, size->pRates[r].rate);
 	else
-	{
-	    *pPrevMon = pMonitor->next;
-	    changed = TRUE;
-	    RRFreeMonitor (pMonitor);
-	}
+	    RROldModeAdd (output, size, 0);
     }
-    if (changed)
-    {
-	UpdateCurrentTime ();
-	pScrPriv->lastConfigTime = currentTime;
-	WalkTree (pScreen, TellChanged, (pointer) pScreen);
+	    
+    /* find size bounds */
+    for (i = 0; i < output->numModes; i++) 
+    {
+	RRModePtr   mode = output->modes[i];
+        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;
+    }
+
+    if (minWidth != pScrPriv->minWidth) {
+	pScrPriv->minWidth = minWidth; pScrPriv->changed = TRUE;
     }
+    if (maxWidth != pScrPriv->maxWidth) {
+	pScrPriv->maxWidth = maxWidth; pScrPriv->changed = TRUE;
+    }
+    if (minHeight != pScrPriv->minHeight) {
+	pScrPriv->minHeight = minHeight; pScrPriv->changed = TRUE;
+    }
+    if (maxHeight != pScrPriv->maxHeight) {
+	pScrPriv->maxHeight = maxHeight; pScrPriv->changed = TRUE;
+    }
+}
+#endif
+
+static 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;
+    
+    if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations))
+	return FALSE;
+
+#if RANDR_SCREEN_INTERFACE
+    if (pScrPriv->nSizes)
+	RRScanOldConfig (pScreen, rotations);
+#endif
+    RRTellChanged (pScreen);
     return TRUE;
 }
 
@@ -664,17 +821,6 @@ RREditConnectionInfo (ScreenPtr pScreen)
     root->mmHeight = pScreen->mmHeight;
 }
 
-static int
-RRNumModes (RRMonitorPtr pMonitor)
-{
-    int	n = 0;
-    RRModePtr	pMode;
-
-    for (pMode = pMonitor->pModes; pMode; pMode = pMode->next)
-	n++;
-    return n;
-}
-
 typedef struct _RR10Data {
     RRScreenSizePtr sizes;
     int		    nsize;
@@ -684,7 +830,7 @@ typedef struct _RR10Data {
 } RR10DataRec, *RR10DataPtr;
 
 static CARD16
-RRVerticalRefresh (xRRMonitorMode *mode)
+RRVerticalRefresh (xRRModeInfo *mode)
 {
     CARD32  refresh;
     if (!mode->hTotal || !mode->vTotal)
@@ -699,61 +845,61 @@ RRVerticalRefresh (xRRMonitorMode *mode)
  * Convert 1.2 monitor data into 1.0 screen data
  */
 static RR10DataPtr
-RR10GetData (ScreenPtr pScreen, RRMonitorPtr pMonitor)
+RR10GetData (ScreenPtr pScreen, RROutputPtr output)
 {
     RR10DataPtr	    data;
     RRScreenSizePtr size;
-    int		    nmode = RRNumModes (pMonitor);
-    int		    i;
-    int		    j;
-    RRRefreshPtr    refresh;
+    int		    nmode = output->numModes;
+    int		    i, j, k;
+    RRScreenRatePtr refresh;
     CARD16	    vRefresh;
-    RRModePtr	    pMode;
+    RRModePtr	    mode;
 
     /* Make sure there is plenty of space for any combination */
     data = malloc (sizeof (RR10DataRec) + 
-		   sizeof (RRScreenSizeRec) * nmode + 
-		   sizeof (RRRefreshRec) * nmode);
+		   sizeof (RRScreenSize) * nmode + 
+		   sizeof (RRScreenRate) * nmode);
     if (!data)
 	return NULL;
     size = (RRScreenSizePtr) (data + 1);
-    refresh = (RRRefreshPtr) (size + nmode);
+    refresh = (RRScreenRatePtr) (size + nmode);
     data->sizes = size;
     data->nsize = 0;
     data->nrefresh = 0;
     data->size = 0;
     data->refresh = 0;
-    for (pMode = pMonitor->pModes; pMode; pMode = pMode->next)
+    for (i = 0; i < output->numModes; i++)
     {
-	for (i = 0; i < data->nsize; i++)
-	    if (pMode->mode.width == size[i].width &&
-		pMode->mode.height == size[i].height)
+	mode = output->modes[i];
+	for (j = 0; j < data->nsize; j++)
+	    if (mode->mode.width == size[j].width &&
+		mode->mode.height == size[j].height)
 		break;
-	if (i == data->nsize)
+	if (j == data->nsize)
 	{
-	    size[i].id = i;
-	    size[i].width = pMode->mode.width;
-	    size[i].height = pMode->mode.height;
-	    size[i].mmWidth = pMode->mode.widthInMillimeters;
-	    size[i].mmHeight = pMode->mode.heightInMillimeters;
-	    size[i].nrefresh = 0;
-	    size[i].refresh = &refresh[data->nrefresh];
+	    size[j].id = j;
+	    size[j].width = mode->mode.width;
+	    size[j].height = mode->mode.height;
+	    size[j].mmWidth = mode->mode.mmWidth;
+	    size[j].mmHeight = mode->mode.mmHeight;
+	    size[j].nRates = 0;
+	    size[j].pRates = &refresh[data->nrefresh];
 	    data->nsize++;
 	}
-	vRefresh = RRVerticalRefresh (&pMode->mode);
-	for (j = 0; j < size[i].nrefresh; j++)
-	    if (vRefresh == size[i].refresh[j].refresh)
+	vRefresh = RRVerticalRefresh (&mode->mode);
+	for (k = 0; k < size[j].nRates; k++)
+	    if (vRefresh == size[j].pRates[k].rate)
 		break;
-	if (j == size[i].nrefresh)
+	if (k == size[j].nRates)
 	{
-	    size[i].refresh[j].refresh = vRefresh;
-	    size[i].refresh[j].pMode = pMode;
-	    size[i].nrefresh++;
+	    size[j].pRates[k].rate = vRefresh;
+	    size[j].pRates[k].mode = mode;
+	    size[j].nRates++;
 	    data->nrefresh++;
 	}
-	if (pMode == pMonitor->pMode)
+	if (mode == output->crtc->mode)
 	{
-	    data->size = i;
+	    data->size = j;
 	    data->refresh = vRefresh;
 	}
     }
@@ -771,6 +917,7 @@ ProcRRGetScreenInfo (ClientPtr client)
     rrScrPrivPtr	    pScrPriv;
     CARD8		    *extra;
     unsigned long	    extraLen;
+    RROutputPtr		    output;
 
     REQUEST_SIZE_MATCH(xRRGetScreenInfoReq);
     pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
@@ -786,7 +933,9 @@ ProcRRGetScreenInfo (ClientPtr client)
     if (pScrPriv)
 	RRGetInfo (pScreen);
 
-    if (!pScrPriv && !pScrPriv->pMonitors)
+    output = RRFirstOutput (pScreen);
+    
+    if (!pScrPriv || !output)
     {
 	rep.type = X_Reply;
 	rep.setOfRotations = RR_Rotate_0;;
@@ -805,7 +954,6 @@ ProcRRGetScreenInfo (ClientPtr client)
     }
     else
     {
-	RRMonitorPtr		pMonitor = pScrPriv->pMonitors;
 	int			i, j;
 	xScreenSizes		*size;
 	CARD16			*rates;
@@ -814,18 +962,18 @@ ProcRRGetScreenInfo (ClientPtr client)
 	RR10DataPtr		pData;
 	RRScreenSizePtr		pSize;
     
-	pData = RR10GetData (pScreen, pMonitor);
+	pData = RR10GetData (pScreen, output);
 	if (!pData)
 	    return BadAlloc;
 	
 	rep.type = X_Reply;
-	rep.setOfRotations = pMonitor->rotations;
+	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 = pMonitor->rotation;
+	rep.rotation = output->crtc->rotation;
 	rep.nSizes = pData->nsize;
         rep.nrateEnts = pData->nrefresh + pData->nsize;
 	rep.sizeID = pData->size;
@@ -862,15 +1010,15 @@ ProcRRGetScreenInfo (ClientPtr client)
 	    size++;
 	    if (has_rate)
 	    {
-		*rates = pSize->nrefresh;
+		*rates = pSize->nRates;
 		if (client->swapped)
 		{
 		    swaps (rates, n);
 		}
 		rates++;
-		for (j = 0; j < pSize->nrefresh; j++)
+		for (j = 0; j < pSize->nRates; j++)
 		{
-		    *rates = pSize->refresh[j].refresh;
+		    *rates = pSize->pRates[j].rate;
 		    if (client->swapped)
 		    {
 			swaps (rates, n);
@@ -907,6 +1055,7 @@ ProcRRGetScreenInfo (ClientPtr client)
     return (client->noClientException);
 }
 
+#if 0
 static int
 RRMonitorSetMode (ScreenPtr pScreen, RRMonitorPtr pMonitor, 
 		  RRModePtr pMode, int x, int y, Rotation rotation,
@@ -997,6 +1146,7 @@ RRMonitorSetMode (ScreenPtr pScreen, RRM
     pScrPriv->lastSetTime = time;
     return RRSetConfigSuccess;
 }
+#endif
 
 static int
 ProcRRSetScreenConfig (ClientPtr client)
@@ -1013,8 +1163,8 @@ ProcRRSetScreenConfig (ClientPtr client)
     Rotation		    rotation;
     int			    rate;
     Bool		    has_rate;
-    RRMonitorPtr	    pMonitor;
-    RRModePtr		    pMode;
+    RROutputPtr		    output;
+    RRModePtr		    mode;
     RR10DataPtr		    pData = NULL;
     RRScreenSizePtr    	    pSize;
     
@@ -1050,8 +1200,8 @@ ProcRRSetScreenConfig (ClientPtr client)
     if (!RRGetInfo (pScreen))
 	return BadAlloc;
     
-    pMonitor = pScrPriv->pMonitors;
-    if (!pMonitor)
+    output = RRFirstOutput (pScreen);
+    if (!output)
     {
 	time = currentTime;
 	rep.status = RRSetConfigFailed;
@@ -1069,7 +1219,7 @@ ProcRRSetScreenConfig (ClientPtr client)
 	goto sendReply;
     }
     
-    pData = RR10GetData (pScreen, pMonitor);
+    pData = RR10GetData (pScreen, output);
     if (!pData)
 	return BadAlloc;
     
@@ -1105,7 +1255,7 @@ ProcRRSetScreenConfig (ClientPtr client)
 	return BadValue;
     }
 
-    if ((~pMonitor->rotations) & rotation)
+    if ((~output->crtc->rotations) & rotation)
     {
 	/*
 	 * requested rotation or reflection not supported by screen
@@ -1125,12 +1275,12 @@ ProcRRSetScreenConfig (ClientPtr client)
 
     if (rate)
     {
-	for (i = 0; i < pSize->nrefresh; i++)
+	for (i = 0; i < pSize->nRates; i++)
 	{
-	    if (pSize->refresh[i].refresh == rate)
+	    if (pSize->pRates[i].rate == rate)
 		break;
 	}
-	if (i == pSize->nrefresh)
+	if (i == pSize->nRates)
 	{
 	    /*
 	     * Invalid rate
@@ -1139,10 +1289,10 @@ ProcRRSetScreenConfig (ClientPtr client)
 	    xfree (pData);
 	    return BadValue;
 	}
-	pMode = pSize->refresh[i].pMode;
+	mode = pSize->pRates[i].mode;
     }
     else
-	pMode = pSize->refresh[0].pMode;
+	mode = pSize->pRates[0].mode;
     
     /*
      * Make sure the requested set-time is not older than
@@ -1154,7 +1304,8 @@ ProcRRSetScreenConfig (ClientPtr client)
 	goto sendReply;
     }
 
-    rep.status = RRMonitorSetMode (pScreen, pMonitor, pMode, 0, 0, rotation, time);
+    rep.status = RRCrtcSet (output->crtc, mode, 0, 0, stuff->rotation,
+			    1, &output);
     
 sendReply:
     
@@ -1183,6 +1334,7 @@ sendReply:
     return (client->noClientException);
 }
 
+#if 0
 int
 RRSetScreenConfig (ScreenPtr		pScreen,
 		   Rotation		rotation,
@@ -1252,10 +1404,42 @@ RRSetScreenConfig (ScreenPtr		pScreen,
     
     status = RRMonitorSetMode (pScreen, pMonitor, pMode, 0, 0, 
 			       rotation, currentTime);
+    
     if (status != RRSetConfigSuccess)
 	return BadImplementation;
     return Success;
 }
+#endif
+
+static Bool
+RRSetScreenSize (ScreenPtr pScreen,
+		 CARD16 width, CARD16 height,
+		 CARD16 widthInMillimeters, CARD16 heightInMillimeters)
+{
+    rrScrPriv(pScreen);
+    
+    if (pScrPriv->rrScreenSetSize) 
+    {
+	return (*pScrPriv->rrScreenSetSize) (pScreen, width, height,
+					     widthInMillimeters,
+					     heightInMillimeters);
+    }
+#ifdef RANDR_SCREEN_INTERFACE
+    else
+    {
+	/* Pend the size change until we get the set mode request.
+	 * Yes, this is 'illegal', but the best we can do until
+	 * drivers are updated
+	 */
+	pScrPriv->reqWidth = width;
+	pScrPriv->reqHeight = height;
+	pScreen->mmWidth = widthInMillimeters;
+	pScreen->mmHeight = heightInMillimeters;
+	return TRUE;
+    }
+#endif
+    return FALSE;
+}
 
 static int
 ProcRRSelectInput (ClientPtr client)
@@ -1264,7 +1448,7 @@ ProcRRSelectInput (ClientPtr client)
     rrClientPriv(client);
     RRTimesPtr	pTimes;
     WindowPtr	pWin;
-    RREventPtr	pRREvent, pNewRREvent, *pHead;
+    RREventPtr	pRREvent, *pHead;
     XID		clientResource;
 
     REQUEST_SIZE_MATCH(xRRSelectInputReq);
@@ -1275,58 +1459,64 @@ ProcRRSelectInput (ClientPtr client)
 						 pWin->drawable.id, EventType,
 						 SecurityWriteAccess);
 
-    if (stuff->enable & (RRScreenChangeNotifyMask)) 
+    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)
-		    return Success;
+		    break;
 	}
 
-	/* 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)
+	if (!pRREvent)
 	{
-	    pHead = (RREventPtr *) xalloc (sizeof (RREventPtr));
-	    if (!pHead ||
-		!AddResource (pWin->drawable.id, EventType, (pointer)pHead))
-	    {
-		FreeResource (clientResource, RT_NONE);
+	    /* 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, ClientType, (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, EventType, (pointer)pHead))
+		{
+		    FreeResource (clientResource, RT_NONE);
+		    return BadAlloc;
+		}
+		*pHead = 0;
 	    }
-	    *pHead = 0;
+	    pRREvent->next = *pHead;
+	    *pHead = pRREvent;
 	}
-	pNewRREvent->next = *pHead;
-	*pHead = pNewRREvent;
 	/*
 	 * Now see if the client needs an event
 	 */
-	if (pScrPriv)
+	if (pScrPriv && (pRREvent->mask & RRScreenChangeNotifyMask))
 	{
 	    pTimes = &((RRTimesPtr) (pRRClient + 1))[pScreen->myNum];
 	    if (CompareTimeStamps (pTimes->setTime, 
@@ -1334,15 +1524,15 @@ ProcRRSelectInput (ClientPtr client)
 		CompareTimeStamps (pTimes->configTime, 
 				   pScrPriv->lastConfigTime) != 0)
 	    {
-		TellChanged (pWin, (pointer) pScreen);
+		DeliverScreenEvent (client, pWin, pScreen);
 	    }
 	}
     }
-    else if (stuff->enable == xFalse) 
+    else if (stuff->enable == 0) 
     {
 	/* delete the interest */
 	if (pHead) {
-	    pNewRREvent = 0;
+	    RREventPtr pNewRREvent = 0;
 	    for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) {
 		if (pRREvent->client == client)
 		    break;
@@ -1366,36 +1556,340 @@ ProcRRSelectInput (ClientPtr client)
     return Success;
 }
 
-
-static int ProcRRGetScreenSizeRange (ClientPtr pClient)
+/*
+ * Retrieve valid screen size range
+ */
+static int ProcRRGetScreenSizeRange (ClientPtr client)
 {
-    return BadImplementation;
+    REQUEST(xRRGetScreenSizeRangeReq);
+    xRRGetScreenSizeRangeReply	rep;
+    WindowPtr			pWin;
+    ScreenPtr			pScreen;
+    rrScrPrivPtr		pScrPriv;
+    
+    REQUEST_SIZE_MATCH(xRRGetScreenInfoReq);
+    pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
+					   SecurityReadAccess);
+
+    if (!pWin)
+	return BadWindow;
+
+    pScreen = pWin->drawable.pScreen;
+    pScrPriv = rrGetScrPriv(pScreen);
+    
+    rep.type = X_Reply;
+    rep.pad = 0;
+    rep.sequenceNumber = client->sequence;
+    rep.length = 0;
+    
+    if (pScrPriv) 
+    {
+	RRGetInfo (pScreen);
+	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);
 }
 
-static int ProcRRSetScreenSize (ClientPtr pClient)
+static int ProcRRSetScreenSize (ClientPtr client)
 {
-    return BadImplementation;
+    REQUEST(xRRSetScreenSizeReq);
+    WindowPtr		pWin;
+    ScreenPtr		pScreen;
+    rrScrPrivPtr	pScrPriv;
+    RRCrtcPtr		crtc;
+    int			i;
+    
+    REQUEST_SIZE_MATCH(xRRSetScreenSizeReq);
+    pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
+					   SecurityReadAccess);
+
+    if (!pWin)
+	return BadWindow;
+
+    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++) {
+	crtc = pScrPriv->crtcs[i];
+	if (crtc->mode &&
+	    (crtc->x + crtc->mode->mode.width > stuff->width ||
+	     crtc->y + crtc->mode->mode.height > stuff->height))
+	    return BadMatch;
+    }
+    if (stuff->widthInMillimeters == 0 || stuff->heightInMillimeters == 0)
+    {
+	client->errorValue = 0;
+	return BadValue;
+    }
+    if (!RRSetScreenSize (pScreen, 
+			  stuff->width, stuff->height,
+			  stuff->widthInMillimeters,
+			  stuff->heightInMillimeters))
+    {
+	return BadMatch;
+    }
+    return Success;
 }
 
-static int ProcRRGetMonitorInfo (ClientPtr pClient)
+#if 0
+static int ProcRRGetMonitorInfo (ClientPtr client)
 {
-    return BadImplementation;
+    REQUEST(xRRGetMonitorInfoReq);
+    xRRGetMonitorInfoReply	rep;
+    WindowPtr			pWin;
+    ScreenPtr			pScreen;
+    rrScrPrivPtr		pScrPriv;
+    RRMonitorPtr		pMonitor;
+    RRModePtr			pMode;
+    int				extraLen;
+    CARD8			*extra;
+    xRRMonitorInfo		*monitor;
+    xRRMonitorMode		*mode;
+    CARD8			*names;
+    
+    REQUEST_SIZE_MATCH(xRRGetScreenInfoReq);
+    pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
+					   SecurityReadAccess);
+
+    if (!pWin)
+	return BadWindow;
+
+    pScreen = pWin->drawable.pScreen;
+    pScrPriv = rrGetScrPriv(pScreen);
+    rep.type = X_Reply;
+    rep.pad = 0;
+    rep.sequenceNumber = client->sequence;
+    rep.numMonitors = 0;
+    rep.numModes = 0;
+    rep.sizeNames = 0;
+    if (!pScrPriv)
+    {
+	extraLen = 0;
+	extra = NULL;
+    }
+    else
+    {
+	int i, m, b;
+	for (pMonitor = pScrPriv->pMonitors; pMonitor; pMonitor = pMonitor->next)
+	{
+	    rep.numMonitors++;
+	    for (pMode = pMonitor->pModes; pMode; pMode = pMode->next)
+	    {
+		rep.numModes++;
+		rep.sizeNames += (1 + pMode->mode.nameLength);
+	    }
+	}
+	extraLen = (rep.numMonitors * sizeof (xRRMonitorInfo) +
+		    rep.numModes * sizeof (xRRMonitorMode) +
+		    rep.sizeNames + 3) & ~3;
+	extra = (CARD8 *) xalloc (extraLen);
+	if (!extra)
+	    return BadAlloc;
+	monitor = (xRRMonitorInfo *) extra;
+	mode = (xRRMonitorMode *) (monitor + rep.numMonitors);
+	names = (CARD8 *) (mode + rep.numModes);
+	i = 0;
+	m = 0;
+	b = 0;
+	for (pMonitor = pScrPriv->pMonitors; pMonitor; pMonitor = pMonitor->next)
+	{
+	    monitor[i].timestamp = pScrPriv->lastSetTime;
+	    monitor[i].configTimestamp = pScrPriv->lastConfigTime;
+	    monitor[i].x = pMonitor->x;
+	    monitor[i].y = pMonitor->y;
+	    monitor[i].rotation = pMonitor->rotation;
+	    monitor[i].mode = pMonitor->pMode->id;
+	    monitor[i].defaultMode = 0;	/* XXX */
+	    monitor[i].rotations = pMonitor->rotations;
+	    monitor[i].firstMode = m;
+	    monitor[i].numModes = 0;
+	    for (pMode = pMonitor->pModes; pMode; pMode = pMode->next)
+	    {
+		monitor[i].numModes++;
+		mode[m] = pMode->mode;
+		names[b] = pMode->mode.nameLength;
+		b++;
+		memcpy (names + b, (char *) (pMode + 1), 
+			pMode->mode.nameLength);
+		b += pMode->mode.nameLength;
+		m++;
+	    }
+	    i++;
+	}
+	if ((char *) (names + ((b + 3) & ~3)) != (char *) extra + extraLen)
+	    FatalError ("RRGetMonitorInfo length mismatch\n");
+    }
+    rep.length = extraLen >> 2;
+    
+    WriteToClient(client, sizeof(xRRGetMonitorInfoReply), (char *)&rep);
+    if (extraLen)
+    {
+	WriteToClient (client, extraLen, (char *) extra);
+	xfree (extra);
+    }
+    
+    if (extra)
+	xfree (extra);
+    return (client->noClientException);
 }
 
-static int ProcRRAddMonitorMode (ClientPtr pClient)
+static int ProcRRAddMonitorMode (ClientPtr client)
 {
     return BadImplementation;
 }
 
-static int ProcRRDeleteMonitorMode (ClientPtr pClient)
+static int ProcRRDeleteMonitorMode (ClientPtr client)
 {
     return BadImplementation;
 }
 
-static int ProcRRSetMonitorConfig (ClientPtr pClient)
+static int ProcRRSetMonitorConfig (ClientPtr client)
 {
-    return BadImplementation;
+    REQUEST(xRRSetMonitorConfigReq);
+    xRRSetMonitorConfigReply	rep;
+    WindowPtr			pWin;
+    ScreenPtr			pScreen;
+    rrScrPrivPtr		pScrPriv;
+    RRMonitorPtr		pMonitor;
+    RRModePtr			pMode;
+    TimeStamp		    configTime;
+    TimeStamp		    time;
+    Rotation		    rotation;
+    
+    REQUEST_SIZE_MATCH(xRRSetScreenConfigReq);
+    pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
+					   SecurityReadAccess);
+
+    if (!pWin)
+	return BadWindow;
+
+    pScreen = pWin->drawable.pScreen;
+    pScrPriv = rrGetScrPriv(pScreen);
+    
+    time = ClientTimeToServerTime(stuff->timestamp);
+    configTime = ClientTimeToServerTime(stuff->configTimestamp);
+    
+    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;
+    }
+    
+    for (pMonitor = pScrPriv->pMonitors; pMonitor; pMonitor = pMonitor->next)
+    {
+	if (pMonitor->id == stuff->monitorIndex)
+	    break;
+    }
+    if (!pMonitor)
+    {
+	client->errorValue = stuff->monitorIndex;
+	return BadValue;
+    }
+    
+    for (pMode = pMonitor->pModes; pMode; pMode = pMode->next)
+    {
+	if (pMode->id == stuff->modeIndex)
+	    break;
+    }
+    if (!pMode)
+    {
+	client->errorValue = stuff->modeIndex;
+	return BadValue;
+    }
+    
+    /*
+     * 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 ((~pMonitor->rotations) & rotation)
+    {
+	/*
+	 * requested rotation or reflection not supported by screen
+	 */
+	client->errorValue = stuff->rotation;
+	return BadMatch;
+    }
+
+    if (stuff->x + pMode->mode.width > pScreen->width)
+    {
+	client->errorValue = stufff
+	stuff->y + pMode->mode.height > 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;
+    }
+
+    rep.status = RRMonitorSetMode (pScreen, pMonitor, 
+				   pMode, stuff->x, stuff->y, rotation, time);
+    
+    return client->noClientException;
 }
+#endif
 
 int (*ProcRandrVector[RRNumberRequests])(ClientPtr) = {
     ProcRRQueryVersion,	/* 0 */
@@ -1408,12 +1902,14 @@ int (*ProcRandrVector[RRNumberRequests])
     ProcRRSelectInput,		/* 4 */
     ProcRRGetScreenInfo,    	/* 5 */
 /* V1.2 additions */
+#if 0
     ProcRRGetScreenSizeRange,	/* 6 */
     ProcRRSetScreenSize,	/* 7 */
     ProcRRGetMonitorInfo,	/* 8 */
     ProcRRAddMonitorMode,	/* 9 */
     ProcRRDeleteMonitorMode,	/* 10 */
     ProcRRSetMonitorConfig,	/* 11 */
+#endif
 };
 
 
@@ -1505,113 +2001,42 @@ SProcRRDispatch (ClientPtr client)
 }
 
 /*
- * Register a monitor for a screen. identifier is a unique identifier
- * for the monitors of a particular screen.
+ * Register the range of sizes for the screen
  */
-RRMonitorPtr
-RRRegisterMonitor (ScreenPtr		pScreen,
-		   void			*identifier,
-		   Rotation		rotations)
+void
+RRScreenSetSizeRange (ScreenPtr	pScreen,
+		      CARD16	minWidth,
+		      CARD16	minHeight,
+		      CARD16	maxWidth,
+		      CARD16	maxHeight)
 {
     rrScrPriv (pScreen);
-    RRMonitorPtr    pMonitor, *pPrev, *pInsert;
 
-    pInsert = NULL;
-    for (pPrev = &pScrPriv->pMonitors; (pMonitor = *pPrev); 
-	 pPrev = &(pMonitor)->next)
-    {
-	if (pMonitor->identifier == identifier) 
-	{
-	    pMonitor->referenced = TRUE;
-	    return pMonitor;
-	}
-	if (!pMonitor->referenced)
-	    pInsert = pPrev;
-    }
-    if (!pInsert)
-	pInsert = pPrev;
-    
-    /*
-     * New monitor, add before the first unreferenced monitor
-     */
-    pMonitor = xalloc (sizeof (RRMonitor));
-    if (!pMonitor)
-	return NULL;
-    pMonitor->pScreen = pScreen;
-    pMonitor->pModes = NULL;
-    pMonitor->identifier = identifier;
-    pMonitor->referenced = TRUE;
-    pMonitor->oldReferenced = FALSE;
-    pMonitor->rotations = RR_Rotate_0;
-    
-    pMonitor->pMode = NULL;
-    pMonitor->x = 0;
-    pMonitor->y = 0;
-    pMonitor->rotation = RR_Rotate_0;
-    pMonitor->next = *pInsert;
-    *pInsert = pMonitor;
-    return pMonitor;
+    if (!pScrPriv)
+	return;
+    pScrPriv->minWidth  = minWidth;
+    pScrPriv->minHeight = minHeight;
+    pScrPriv->maxWidth  = maxWidth;
+    pScrPriv->maxHeight = maxHeight;
 }
 
-/*
- * Register a mode for a monitor
- */
+#ifdef RANDR_SCREEN_INTERFACE
 
-RRModePtr
-RRRegisterMode (RRMonitorPtr	pMonitor,
-		xRRMonitorMode	*pModeline,
-		char		*name)
+static Bool
+RRScreenSizeMatches (RRScreenSizePtr  a,
+		   RRScreenSizePtr  b)
 {
-    RRModePtr	pMode, *pPrev, *pInsert = NULL;
-
-    /*
-     * Find existing mode with same modeline and name
-     */
-    for (pPrev = &pMonitor->pModes; (pMode = *pPrev); pPrev = &(pMode->next))
-    {
-	if (!memcmp (&pMode->mode, pModeline, sizeof (xRRMonitorMode)) &&
-	    pMode->mode.nameLength == pModeline->nameLength &&
-	    !memcmp (RRModeName(pMode), name, pModeline->nameLength))
-	{
-	    pMode->referenced = TRUE;
-	    return pMode;
-	}
-	if (!pMode->referenced)
-	    pInsert = pPrev;
-    }
-
-    if (!pInsert)
-	pInsert = pPrev;
-    
-    /*
-     * Create a new mode, inserting before the first unreferenced mode
-     */
-    pMode = xalloc (sizeof (RRMode) + pModeline->nameLength + 1);
-    pMode->referenced = TRUE;
-    pMode->oldReferenced = FALSE;
-    pMode->mode = *pModeline;
-    memcpy (RRModeName (pMode), name, pModeline->nameLength);
-    RRModeName(pMode)[pModeline->nameLength] = '\0';
-    pMode->next = *pInsert;
-    *pInsert = pMode;
-    return pMode;
-}
-
-void
-RRSetCurrentMode (RRMonitorPtr	pMonitor,
-		  RRModePtr	pMode,
-		  int		x,
-		  int		y,
-		  Rotation	rotation)
-{
-    pMonitor->pMode = pMode;
-    pMonitor->x = x;
-    pMonitor->y = y;
-    pMonitor->rotation = rotation;
+    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;
 }
 
-#ifdef RANDR_SCREEN_INTERFACE
-
 RRScreenSizePtr
 RRRegisterSize (ScreenPtr	    pScreen,
 		short		    width, 
@@ -1620,50 +2045,29 @@ RRRegisterSize (ScreenPtr	    pScreen,
 		short		    mmHeight)
 {
     rrScrPriv (pScreen);
-    xRRMonitorMode  tmp;
-    RRMonitorPtr    pMonitor;
-    RRModePtr	    pMode, *pPrev;
-    char	    name[100];
+    int		    i;
+    RRScreenSize    tmp;
+    RRScreenSizePtr pNew;
 
     if (!pScrPriv)
-	return NULL;
-    pMonitor = pScrPriv->pMonitors;
-    if (!pMonitor)
-    {
-	pMonitor = RRRegisterMonitor (pScreen, NULL, RR_Rotate_0);
-	if (!pMonitor)
-	    return NULL;
-    }
-    pMonitor->referenced = TRUE;
-    
-    for (pPrev = &pMonitor->pModes; (pMode = *pPrev); pPrev = &(pMode->next))
-	if (pMode->mode.width == width &&
-	    pMode->mode.height == height &&
-	    pMode->mode.widthInMillimeters == mmWidth &&
-	    pMode->mode.heightInMillimeters == mmHeight)
-	{
-	    pMode->referenced =TRUE;
-	    return (void *) pMode;
-	}
-    memset (&tmp, '\0', sizeof (xRRMonitorMode));
-    memset (name, '\0', sizeof (name));
-    sprintf (name, "%dx%d", width, height);
+	return 0;
+    
     tmp.width = width;
     tmp.height= height;
-    tmp.widthInMillimeters = mmWidth;
-    tmp.heightInMillimeters = mmHeight;
-    tmp.nameLength = strlen (name) + 10;    /* leave space for refresh */
-    pMode = RRRegisterMode (pMonitor, &tmp, name);
-    return (void *) pMode;
-}
-
-static Bool
-RRModesMatchSize (RRModePtr a, RRModePtr b)
-{
-    return (a->mode.width == a->mode.width &&
-	    a->mode.height == b->mode.height &&
-	    a->mode.widthInMillimeters == b->mode.widthInMillimeters &&
-	    a->mode.heightInMillimeters == b->mode.heightInMillimeters);
+    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,
@@ -1671,77 +2075,35 @@ Bool RRRegisterRate (ScreenPtr		pScreen,
 		     int		rate)
 {
     rrScrPriv(pScreen);
-    RRMonitorPtr    pMonitor;
-    RRModePtr	    pSizeMode = (RRModePtr) pSize;
-    RRModePtr	    pMode, *pPrev;
-    CARD16	    width = pSizeMode->mode.width;
-    CARD16	    height = pSizeMode->mode.height;
-    char	    name[100];
-    xRRMonitorMode  modeLine;
+    int		    i;
+    RRScreenRatePtr pNew, pRate;
 
     if (!pScrPriv)
 	return FALSE;
     
-    pMonitor = pScrPriv->pMonitors;
-    if (!pMonitor)
-	return FALSE;
-
-    for (pPrev = &pMonitor->pModes; (pMode = *pPrev); pPrev = &pMode->next)
-    {
-	if (RRModesMatchSize (pMode, pSizeMode))
-	{
-	    if (pMode->mode.dotClock == 0)
-	    {
-		/*
-		 * First refresh for this size; reprogram this mode
-		 * with the right refresh.
-		 */
-		pMode->mode.hSyncStart = width;
-		pMode->mode.hSyncEnd = width;
-		pMode->mode.hTotal = width;
-		pMode->mode.hSkew = 0;
-		pMode->mode.vSyncStart = height;
-		pMode->mode.vSyncEnd = height;
-		pMode->mode.vTotal = height;
-		pMode->mode.dotClock = width * height * rate;
-		sprintf ((char *) (pMode + 1), "%dx%d@%d", width, height, rate);
-		pMode->mode.modeFlags = 0;
-		pMode->mode.nameLength = strlen ((char *) (pMode + 1));
-		pMode->referenced = TRUE;
-		return TRUE;
-	    }
-	    else if (rate == RRVerticalRefresh (&pMode->mode))
-	    {
-		pMode->referenced = TRUE;
-		return TRUE;
-	    }
-	}
-    }
-    
-    sprintf (name, "%dx%d@%d", pSizeMode->mode.width, pSizeMode->mode.height,
-	     rate);
-    modeLine = pSizeMode->mode;
-    modeLine.dotClock = rate * modeLine.vTotal * modeLine.hTotal;
-    modeLine.nameLength = strlen (name);
-    pMode = RRRegisterMode (pMonitor, &modeLine, name);
-    if (!pMode)
+    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)
 {
-    rrScrPriv (pScreen);
-    RRMonitorPtr    pMonitor;
+    RROutputPtr	output = RRFirstOutput (pScreen);
 
-    if (!pScrPriv)
+    if (!output)
 	return RR_Rotate_0;
 
-    pMonitor = pScrPriv->pMonitors;
-    if (!pMonitor)
-	return RR_Rotate_0;
-    return pMonitor->rotation;
+    return output->crtc->rotation;
 }
 
 void
@@ -1751,25 +2113,11 @@ RRSetCurrentConfig (ScreenPtr		pScreen,
 		    RRScreenSizePtr	pSize)
 {
     rrScrPriv (pScreen);
-    RRMonitorPtr    pMonitor;
-    RRModePtr	    pMode;
-    RRModePtr	    pSizeMode = (RRModePtr) pSize;
 
     if (!pScrPriv)
 	return;
-    pMonitor = pScrPriv->pMonitors;
-    if (!pMonitor)
-	return;
-
-    for (pMode = pMonitor->pModes; pMode; pMode = pMode->next)
-    {
-	if (RRModesMatchSize (pMode, pSizeMode) && 
-	    RRVerticalRefresh (&pMode->mode) == rate)
-	    break;
-    }
-    if (!pMode)
-	return;
-    
-    RRSetCurrentMode (pMonitor, pMode, 0, 0, rotation);
+    pScrPriv->size = pSize - pScrPriv->pSizes;
+    pScrPriv->rotation = rotation;
+    pScrPriv->rate = rate;
 }
 #endif
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 3610274..1694523 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -34,71 +34,94 @@
 
 #include <X11/extensions/randrproto.h>
 
+/* required for ABI compatibility for now */
 #define RANDR_SCREEN_INTERFACE 1
 
+typedef XID	RRMode;
+typedef XID	RROutput;
+typedef XID	RRCrtc;
+
 /*
  * Modeline for a monitor. Name follows directly after this struct
  */
 
 #define RRModeName(pMode) ((char *) (pMode + 1))
+typedef struct _rrMode	    RRModeRec, *RRModePtr;
+typedef struct _rrCrtc	    RRCrtcRec, *RRCrtcPtr;
+typedef struct _rrOutput    RROutputRec, *RROutputPtr;
+
+struct _rrMode {
+    RRMode	    id;
+    int		    refcnt;
+    xRRModeInfo	    mode;
+    char	    *name;
+};
 
-typedef struct _rrMode {
-    struct _rrMode  *next;
-    Bool	    referenced;
-    Bool	    oldReferenced;
-    int		    id;
-    xRRMonitorMode  mode;
-} RRMode, *RRModePtr;
-
-typedef struct _rrMonitor {
-    struct _rrMonitor	*next;
+struct _rrCrtc {
+    RRCrtc	    id;
     ScreenPtr	    pScreen;
-    RRModePtr	    pModes;
-    void	    *identifier;    /* made unique by DDX */
-    int		    id;		    /* index in list of monitors */
-    Bool	    referenced;
-    Bool	    oldReferenced;
-    Rotation	    rotations;
-    
-    /*
-     * Current state
-     */
-    RRModePtr	    pMode;
+    RRModePtr	    mode;
     int		    x, y;
     Rotation	    rotation;
-} RRMonitor, *RRMonitorPtr;
+    Rotation	    rotations;
+    int		    numPossibleOutputs;
+    RROutputPtr	    *possibleOutputs;
+    Bool	    changed;
+    void	    *devPrivate;
+};
+
+struct _rrOutput {
+    RROutput	    id;
+    ScreenPtr	    pScreen;
+    char	    *name;
+    int		    nameLength;
+    CARD8	    connection;
+    CARD8	    subpixelOrder;
+    RRCrtcPtr	    crtc;
+    int		    numCrtcs;
+    RRCrtcPtr	    *crtcs;
+    int		    numClones;
+    RROutputPtr	    *outputs;
+    int		    numModes;
+    RRModePtr	    *modes;
+    Bool	    changed;
+    void	    *devPrivate;
+};
 
-typedef Bool (*RRSetScreenSizeProcPtr) (ScreenPtr	pScreen,
+typedef Bool (*RRScreenSetSizeProcPtr) (ScreenPtr	pScreen,
 					CARD16		width,
 					CARD16		height,
 					CARD32		widthInMM,
 					CARD32		heightInMM);
 					
-typedef Bool (*RRSetModeProcPtr) (ScreenPtr		pScreen,
-				  int			monitor,
-				  RRModePtr		pMode,
+typedef Bool (*RRCrtcSetProcPtr) (ScreenPtr		pScreen,
+				  RRCrtcPtr		crtc,
+				  RRModePtr		mode,
 				  int			x,
 				  int			y,
-				  Rotation		rotation);
+				  Rotation		rotation,
+				  int			numOutput,
+				  RROutputPtr		*outputs);
 
 typedef Bool (*RRGetInfoProcPtr) (ScreenPtr pScreen, Rotation *rotations);
 typedef Bool (*RRCloseScreenProcPtr) ( int i, ScreenPtr pscreen);
 
-
-#ifdef RANDR_SCREEN_INTERFACE
-
+/* These are for 1.0 compatibility */
+ 
 typedef struct _rrRefresh {
-    CARD16	    refresh;
-    RRModePtr	    pMode;
-} RRRefreshRec, *RRRefreshPtr;
+    CARD16	    rate;
+    RRModePtr	    mode;
+} RRScreenRate, *RRScreenRatePtr;
 
 typedef struct _rrScreenSize {
     int		    id;
     short	    width, height;
     short	    mmWidth, mmHeight;
-    int		    nrefresh;
-    RRRefreshPtr    refresh;
-} RRScreenSizeRec, *RRScreenSizePtr;
+    int		    nRates;
+    RRScreenRatePtr pRates;
+} RRScreenSize, *RRScreenSizePtr;
+
+#ifdef RANDR_SCREEN_INTERFACE
 
 typedef Bool (*RRSetConfigProcPtr) (ScreenPtr		pScreen,
 				    Rotation		rotation,
@@ -117,8 +140,8 @@ typedef struct _rrScrPriv {
     RRSetConfigProcPtr	    rrSetConfig;
 #endif
     RRGetInfoProcPtr	    rrGetInfo;
-    RRSetScreenSizeProcPtr  rrSetScreenSize;
-    RRSetModeProcPtr	    rrSetMode;
+    RRScreenSetSizeProcPtr  rrScreenSetSize;
+    RRCrtcSetProcPtr	    rrCrtcSet;
     
     /*
      * Private part of the structure; not considered part of the ABI
@@ -126,20 +149,34 @@ typedef struct _rrScrPriv {
     TimeStamp		    lastSetTime;	/* last changed by client */
     TimeStamp		    lastConfigTime;	/* possible configs changed */
     RRCloseScreenProcPtr    CloseScreen;
+    Bool		    changed;
+    CARD16		    minWidth, minHeight;
+    CARD16		    maxWidth, maxHeight;
+
+    /* modes, outputs and crtcs */
+    int			    numModes;
+    RRModePtr		    *modes;
 
-    /*
-     * monitor data
-     */
-    RRMonitorPtr	    pMonitors;
+    int			    numOutputs;
+    RROutputPtr		    *outputs;
+
+    int			    numCrtcs;
+    RRCrtcPtr		    *crtcs;
 
 #ifdef RANDR_SCREEN_INTERFACE
     /*
      * Configuration information
      */
     Rotation		    rotations;
+    CARD16		    reqWidth, reqHeight;
     
-
+    int			    nSizes;
+    RRScreenSizePtr	    pSizes;
+    
+    RRScreenSizePtr	    pSize;
     Rotation		    rotation;
+    int			    rate;
+    int			    size;
 #endif
 } rrScrPrivRec, *rrScrPrivPtr;
 
@@ -154,33 +191,91 @@ void
 RRExtensionInit (void);
 
 /*
- * Then, register a monitor with the screen
+ * Set the range of sizes for the screen
+ */
+void
+RRScreenSetSizeRange (ScreenPtr	pScreen,
+		      CARD16	minWidth,
+		      CARD16	minHeight,
+		      CARD16	maxWidth,
+		      CARD16	maxHeight);
+
+/*
+ * Create a CRTC
+ */
+RRCrtcPtr
+RRCrtcCreate (ScreenPtr	pScreen,
+	      void	*devPrivate);
+
+
+/*
+ * Use this value for any num parameter to indicate that
+ * the related data are unchanged
  */
+#define RR_NUM_UNCHANGED    -1
 
-RRMonitorPtr
-RRRegisterMonitor (ScreenPtr		pScreen,
-		   void			*identifier,
-		   Rotation		rotations);
+/*
+ * Notify the extension that the Crtc has been reconfigured
+ */
+Bool
+RRCrtcSet (RRCrtcPtr	crtc,
+	   RRModePtr	mode,
+	   int		x,
+	   int		y,
+	   Rotation	rotation,
+	   int		numOutput,
+	   RROutputPtr	*outputs);
+
+/*
+ * Destroy a Crtc at shutdown
+ */
+void
+RRCrtcDestroy (RRCrtcPtr crtc);
 
 /*
- * Next, register the list of modes with the monitor
+ * Find, and if necessary, create a mode
  */
 
 RRModePtr
-RRRegisterMode (RRMonitorPtr	pMonitor,
-		xRRMonitorMode	*pMode,
-		char		*name);
+RRModeGet (ScreenPtr	pScreen,
+	   xRRModeInfo	*modeInfo,
+	   char		*name);
 
 /*
- * Finally, set the current configuration of each monitor
+ * Destroy a mode.
  */
 
 void
-RRSetCurrentMode (RRMonitorPtr	pMonitor,
-		  RRModePtr	pMode,
-		  int		x,
-		  int		y,
-		  Rotation	rotation);
+RRModeDestroy (RRModePtr mode);
+
+/*
+ * Create an output
+ */
+
+RROutputPtr
+RROutputCreate (ScreenPtr   pScreen,
+		char	    *name,
+		int	    nameLength,
+		void	    *devPrivate);
+
+/*
+ * Notify extension that output parameters have been changed
+ */
+Bool
+RROutputSet (RROutputPtr    output,
+	     RROutputPtr    *clones,
+	     int	    numClones,
+	     RRModePtr	    *modes,
+	     int	    numModes,
+	     RRCrtcPtr	    *crtcs,
+	     int	    numCrtcs,
+	     CARD8	    connection);
+
+void
+RROutputDestroy (RROutputPtr	output);
+
+void
+RRTellChanged (ScreenPtr pScreen);
 
 Bool RRScreenInit(ScreenPtr pScreen);
 
@@ -197,12 +292,14 @@ Bool
 miRRGetScreenInfo (ScreenPtr pScreen);
 
 Bool
-miRRSetMode (ScreenPtr	pScreen,
-	     int	monitor,
-	     RRModePtr	pMode,
+miRRCrtcSet (ScreenPtr	pScreen,
+	     RRCrtcPtr	crtc,
+	     RRModePtr	mode,
 	     int	x,
 	     int	y,
-	     Rotation	rotation);
+	     Rotation	rotation,
+	     int	numOutput,
+	     RROutputPtr    *outputs);
 
 #ifdef RANDR_SCREEN_INTERFACE					
 /*
@@ -225,9 +322,6 @@ Bool RRRegisterRate (ScreenPtr		pScreen,
 		     RRScreenSizePtr	pSize,
 		     int		rate);
 
-Bool RRRegisterRotation (ScreenPtr	pScreen,
-			 Rotation	rotation);
-
 /*
  * Finally, set the current configuration of the screen
  */
@@ -238,17 +332,16 @@ RRSetCurrentConfig (ScreenPtr		pScreen,
 		    int			rate,
 		    RRScreenSizePtr	pSize);
 
+Bool RRScreenInit (ScreenPtr pScreen);
+
+Rotation
+RRGetRotation (ScreenPtr pScreen);
+
 int
 RRSetScreenConfig (ScreenPtr		pScreen,
 		   Rotation		rotation,
 		   int			rate,
 		   RRScreenSizePtr	pSize);
 
-Bool
-miRRSetConfig (ScreenPtr	pScreen,
-	       Rotation		rotation,
-	       int		rate,
-	       RRScreenSizePtr	size);
-
 #endif					
 #endif /* _RANDRSTR_H_ */
diff-tree fbaeb0b2a1e0ad29b8d284045a9a60cd873f2edb (from 10b0c7d5e49329b59b1fe66bbeb12fa4371dbaab)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Mon Jul 17 14:43:07 2006 -0400

    Successful legacy RandR API/Protocol emulation for query.
    
    These changes clean up minor errors to make it possible to list the
    available modes for a monitor using legacy APIs in both the X server DDX and
    RandR protocol. Setting modes is untested, so it probably doesn't work.

diff --git a/randr/randr.c b/randr/randr.c
index 4a5cd4e..58d8f17 100644
--- a/randr/randr.c
+++ b/randr/randr.c
@@ -542,6 +542,7 @@ RRGetInfo (ScreenPtr pScreen)
 		    pMode->id = modeid++;
 		    if (!pMode->oldReferenced)
 			changed = TRUE;
+		    pPrevMode = &pMode->next;
 		}
 		else
 		{
@@ -550,6 +551,7 @@ RRGetInfo (ScreenPtr pScreen)
 		    RRFreeMode (pMode);
 		}
 	    }
+	    pPrevMon = &pMonitor->next;
 	}
 	else
 	{
@@ -716,6 +718,7 @@ RR10GetData (ScreenPtr pScreen, RRMonito
 	return NULL;
     size = (RRScreenSizePtr) (data + 1);
     refresh = (RRRefreshPtr) (size + nmode);
+    data->sizes = size;
     data->nsize = 0;
     data->nrefresh = 0;
     data->size = 0;
@@ -728,6 +731,7 @@ RR10GetData (ScreenPtr pScreen, RRMonito
 		break;
 	if (i == data->nsize)
 	{
+	    size[i].id = i;
 	    size[i].width = pMode->mode.width;
 	    size[i].height = pMode->mode.height;
 	    size[i].mmWidth = pMode->mode.widthInMillimeters;
@@ -823,7 +827,7 @@ ProcRRGetScreenInfo (ClientPtr client)
 	rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
 	rep.rotation = pMonitor->rotation;
 	rep.nSizes = pData->nsize;
-        rep.nrateEnts = pData->nrefresh;
+        rep.nrateEnts = pData->nrefresh + pData->nsize;
 	rep.sizeID = pData->size;
 	rep.rate = pData->refresh;
 
@@ -904,6 +908,97 @@ ProcRRGetScreenInfo (ClientPtr client)
 }
 
 static int
+RRMonitorSetMode (ScreenPtr pScreen, RRMonitorPtr pMonitor, 
+		  RRModePtr pMode, int x, int y, Rotation rotation,
+		  TimeStamp time)
+{
+    rrScrPriv(pScreen);
+    short   oldWidth, oldHeight;
+    
+    oldWidth = pScreen->width;
+    oldHeight = pScreen->height;
+    
+    /*
+     * call out to ddx routine to effect the change
+     */
+    if (pScrPriv->rrSetScreenSize && pScrPriv->rrSetMode)
+    {
+	xScreenSizes	oldSize;
+	if (!(*pScrPriv->rrSetMode) (pScreen, 0, NULL, 0, 0, RR_Rotate_0))
+	    return RRSetConfigFailed;
+	oldSize.widthInPixels = pScreen->width;
+	oldSize.heightInPixels = pScreen->width;
+	oldSize.widthInMillimeters = pScreen->mmWidth;
+	oldSize.heightInMillimeters = pScreen->mmHeight;
+	if (!(*pScrPriv->rrSetScreenSize) (pScreen,
+					   pMode->mode.width,
+					   pMode->mode.height,
+					   pMode->mode.widthInMillimeters,
+					   pMode->mode.heightInMillimeters))
+	{
+	    (void) (*pScrPriv->rrSetMode) (pScreen, 0, pMonitor->pMode,
+					   pMonitor->x, pMonitor->y,
+					   pMonitor->rotation);
+	    return RRSetConfigFailed;
+	}
+	if (!(*pScrPriv->rrSetMode) (pScreen, 0, pMode, 0, 0, rotation))
+	{
+	    (void) (*pScrPriv->rrSetScreenSize) (pScreen,
+						 oldSize.widthInPixels,
+						 oldSize.heightInPixels,
+						 oldSize.widthInMillimeters,
+						 oldSize.heightInMillimeters);
+	    (void) (*pScrPriv->rrSetMode) (pScreen, 0, pMonitor->pMode,
+					   pMonitor->x, pMonitor->y,
+					   pMonitor->rotation);
+	    return RRSetConfigFailed;
+	}
+    }
+#ifdef RANDR_SCREEN_INTERFACE
+    else if (pScrPriv->rrSetConfig)
+    {
+	int rate = RRVerticalRefresh (&pMode->mode);
+	RRScreenSizeRec	size;
+
+	size.width = pMode->mode.width;
+	size.height = pMode->mode.height;
+	size.mmWidth = pMode->mode.widthInMillimeters;
+	size.mmHeight = pMode->mode.heightInMillimeters;
+	if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate, &size))
+	    return RRSetConfigFailed;
+    }
+#endif
+    else
+	return RRSetConfigFailed;
+    
+    /*
+     * set current extension configuration pointers
+     */
+    RRSetCurrentMode (pMonitor, pMode, 0, 0, rotation);
+    
+    /*
+     * 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;
+    return RRSetConfigSuccess;
+}
+
+static int
 ProcRRSetScreenConfig (ClientPtr client)
 {
     REQUEST(xRRSetScreenConfigReq);
@@ -917,7 +1012,6 @@ ProcRRSetScreenConfig (ClientPtr client)
     int			    i;
     Rotation		    rotation;
     int			    rate;
-    short		    oldWidth, oldHeight;
     Bool		    has_rate;
     RRMonitorPtr	    pMonitor;
     RRModePtr		    pMode;
@@ -947,9 +1041,6 @@ ProcRRSetScreenConfig (ClientPtr client)
     time = ClientTimeToServerTime(stuff->timestamp);
     configTime = ClientTimeToServerTime(stuff->configTimestamp);
     
-    oldWidth = pScreen->width;
-    oldHeight = pScreen->height;
-    
     if (!pScrPriv)
     {
 	time = currentTime;
@@ -1063,90 +1154,7 @@ ProcRRSetScreenConfig (ClientPtr client)
 	goto sendReply;
     }
 
-    /*
-     * call out to ddx routine to effect the change
-     */
-    if (pScrPriv->rrSetScreenSize && pScrPriv->rrSetMode)
-    {
-	xScreenSizes	oldSize;
-	if (!(*pScrPriv->rrSetMode) (pScreen, 0, NULL, 0, 0, RR_Rotate_0))
-	    goto fail;
-	oldSize.widthInPixels = pScreen->width;
-	oldSize.heightInPixels = pScreen->width;
-	oldSize.widthInMillimeters = pScreen->mmWidth;
-	oldSize.heightInMillimeters = pScreen->mmHeight;
-	if (!(*pScrPriv->rrSetScreenSize) (pScreen,
-					   pMode->mode.width,
-					   pMode->mode.height,
-					   pMode->mode.widthInMillimeters,
-					   pMode->mode.heightInMillimeters))
-	{
-	    (void) (*pScrPriv->rrSetMode) (pScreen, 0, pMonitor->pMode,
-					   pMonitor->x, pMonitor->y,
-					   pMonitor->rotation);
-	    goto fail;
-	}
-	if (!(*pScrPriv->rrSetMode) (pScreen, 0, pMode, 0, 0, rotation))
-	{
-	    (void) (*pScrPriv->rrSetScreenSize) (pScreen,
-						 oldSize.widthInPixels,
-						 oldSize.heightInPixels,
-						 oldSize.widthInMillimeters,
-						 oldSize.heightInMillimeters);
-	    (void) (*pScrPriv->rrSetMode) (pScreen, 0, pMonitor->pMode,
-					   pMonitor->x, pMonitor->y,
-					   pMonitor->rotation);
-	    goto fail;
-	}
-    }
-#ifdef RANDR_SCREEN_INTERFACE
-    else if (pScrPriv->rrSetConfig)
-    {
-	if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate, pSize))
-	{
-	    goto fail;
-	}
-    }
-#endif
-    else
-    {
-fail:	;
-	/*
-	 * unknown DDX failure, report to client
-	 */
-	rep.status = RRSetConfigFailed;
-	goto sendReply;
-    }
-    
-    /*
-     * set current extension configuration pointers
-     */
-    RRSetCurrentMode (pMonitor, pMode, 0, 0, rotation);
-    
-    /*
-     * 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;
+    rep.status = RRMonitorSetMode (pScreen, pMonitor, pMode, 0, 0, rotation, time);
     
 sendReply:
     
@@ -1182,11 +1190,20 @@ RRSetScreenConfig (ScreenPtr		pScreen,
 		   RRScreenSizePtr	pSize)
 {
     rrScrPrivPtr	    pScrPriv;
-    int			    i;
+    RRMonitorPtr	    pMonitor;
     short		    oldWidth, oldHeight;
+    RRModePtr		    pMode;
+    int			    status;
 
     pScrPriv = rrGetScrPriv(pScreen);
     
+    if (!pScrPriv)
+	return BadImplementation;
+    
+    pMonitor = pScrPriv->pMonitors;
+    if (!pMonitor)
+	return BadImplementation;
+
     oldWidth = pScreen->width;
     oldHeight = pScreen->height;
     
@@ -1219,61 +1236,24 @@ RRSetScreenConfig (ScreenPtr		pScreen,
 	return BadMatch;
     }
 
-    /*
-     * Validate requested refresh
-     */
-    if (rate)
+    for (pMode = pMonitor->pModes; pMode; pMode = pMode->next)
     {
-	for (i = 0; i < pSize->nRates; i++)
-	{
-	    RRScreenRatePtr pRate = &pSize->pRates[i];
-	    if (pRate->referenced && pRate->rate == rate)
-		break;
-	}
-	if (i == pSize->nRates)
+	if (pMode->mode.width == pSize->width &&
+	    pMode->mode.height == pSize->height &&
+	    pMode->mode.widthInMillimeters == pSize->mmWidth &&
+	    pMode->mode.heightInMillimeters == pSize->mmHeight &&
+	    (RRVerticalRefresh (&pMode->mode) == rate || rate == 0))
 	{
-	    /*
-	     * Invalid rate
-	     */
-	    return BadValue;
+	    break;
 	}
     }
-
-    /*
-     * 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
-     */
-    RRSetCurrentMode (pMonitor, pMode, 0, 0, rotation);
-    
-    /*
-     * 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);
+    if (!pMode)
+	return BadValue;
     
-    /*
-     * Fix pointer bounds and location
-     */
-    ScreenRestructured (pScreen);
+    status = RRMonitorSetMode (pScreen, pMonitor, pMode, 0, 0, 
+			       rotation, currentTime);
+    if (status != RRSetConfigSuccess)
+	return BadImplementation;
     return Success;
 }
 
@@ -1387,23 +1367,63 @@ ProcRRSelectInput (ClientPtr client)
 }
 
 
+static int ProcRRGetScreenSizeRange (ClientPtr pClient)
+{
+    return BadImplementation;
+}
+
+static int ProcRRSetScreenSize (ClientPtr pClient)
+{
+    return BadImplementation;
+}
+
+static int ProcRRGetMonitorInfo (ClientPtr pClient)
+{
+    return BadImplementation;
+}
+
+static int ProcRRAddMonitorMode (ClientPtr pClient)
+{
+    return BadImplementation;
+}
+
+static int ProcRRDeleteMonitorMode (ClientPtr pClient)
+{
+    return BadImplementation;
+}
+
+static int ProcRRSetMonitorConfig (ClientPtr pClient)
+{
+    return BadImplementation;
+}
+
+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 */
+    ProcRRGetMonitorInfo,	/* 8 */
+    ProcRRAddMonitorMode,	/* 9 */
+    ProcRRDeleteMonitorMode,	/* 10 */
+    ProcRRSetMonitorConfig,	/* 11 */
+};
+
+
 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;
-    }
+    return (*ProcRandrVector[stuff->data]) (client);
 }
 
 static int
@@ -1609,7 +1629,12 @@ RRRegisterSize (ScreenPtr	    pScreen,
 	return NULL;
     pMonitor = pScrPriv->pMonitors;
     if (!pMonitor)
-	return NULL;
+    {
+	pMonitor = RRRegisterMonitor (pScreen, NULL, RR_Rotate_0);
+	if (!pMonitor)
+	    return NULL;
+    }
+    pMonitor->referenced = TRUE;
     
     for (pPrev = &pMonitor->pModes; (pMode = *pPrev); pPrev = &(pMode->next))
 	if (pMode->mode.width == width &&
diff-tree 10b0c7d5e49329b59b1fe66bbeb12fa4371dbaab (from dc89ecf5b51ecd2bf5ab61b8e6a28b1fff3bc38b)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Mon Jul 17 01:21:11 2006 -0400

    RandR: New data structure, old API. At least it compiles now

diff --git a/randr/mirandr.c b/randr/mirandr.c
index 7bef02d..e152133 100644
--- a/randr/mirandr.c
+++ b/randr/mirandr.c
@@ -65,11 +65,11 @@ miRRGetInfo (ScreenPtr pScreen, Rotation
 	    rrMode.height = pScreen->height;
 	    rrMode.widthInMillimeters = pScreen->mmWidth;
 	    rrMode.heightInMillimeters = pScreen->mmHeight;
-	    pMonitor = RRRegisterMonitor (pScreen, RR_Rotate_0);
+	    rrMode.nameLength = strlen (name);
+	    pMonitor = RRRegisterMonitor (pScreen, NULL, RR_Rotate_0);
 	    pMode = RRRegisterMode (pMonitor,
 				    &rrMode,
-				    name,
-				    strlen (name));
+				    name);
 	    if (!pMode)
 		return FALSE;
 	    if (!setConfig)
@@ -90,6 +90,8 @@ Bool
 miRRSetMode (ScreenPtr	pScreen,
 	     int	monitor,
 	     RRModePtr	pMode,
+	     int	x,
+	     int	y,
 	     Rotation	rotation)
 {
     return TRUE;
diff --git a/randr/randr.c b/randr/randr.c
index 1a9624a..4a5cd4e 100644
--- a/randr/randr.c
+++ b/randr/randr.c
@@ -163,12 +163,12 @@ RRCloseScreen (int i, ScreenPtr pScreen)
     RRMonitorPtr    pMonitor;
 
     unwrap (pScrPriv, pScreen, CloseScreen);
-    while (pMonitor = pScrPriv->pMonitors) 
+    while ((pMonitor = pScrPriv->pMonitors))
     {
 	RRModePtr   pMode;
 	
 	pScrPriv->pMonitors = pMonitor->next;
-	while (pMode = pMonitor->pModes) 
+	while ((pMode = pMonitor->pModes))
 	{
 	    pMonitor->pModes = pMode->next;
 	    xfree (pMode);
@@ -218,6 +218,20 @@ SRRMonitorChangeNotifyEvent(xRRMonitorCh
     cpswaps(from->y, to->y);
 }
 
+static void
+SRRNotifyEvent (xEvent *from,
+		xEvent *to)
+{
+    switch (from->u.u.detail) {
+    case RRNotify_MonitorChange:
+	SRRMonitorChangeNotifyEvent ((xRRMonitorChangeNotifyEvent *) from,
+				     (xRRMonitorChangeNotifyEvent *) to);
+	break;
+    default:
+	break;
+    }
+}
+
 Bool RRScreenInit(ScreenPtr pScreen)
 {
     rrScrPrivPtr   pScrPriv;
@@ -336,6 +350,8 @@ RRExtensionInit (void)
     RREventBase = extEntry->eventBase;
     EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr) 
       SRRScreenChangeNotifyEvent;
+    EventSwapVector[RREventBase + RRNotify] = (EventSwapPtr)
+	SRRNotifyEvent;
 
     return;
 }
@@ -349,8 +365,8 @@ TellChanged (WindowPtr pWin, pointer val
     xRRMonitorChangeNotifyEvent	me;
     ScreenPtr			pScreen = pWin->drawable.pScreen;
     rrScrPriv(pScreen);
-    RRMonitorPtr		pMonitor = pScrPriv->pMonitors;
     RRModePtr			pMode;
+    RRMonitorPtr		pMonitor;
     WindowPtr			pRoot = WindowTable[pScreen->myNum];
     int				i;
 
@@ -364,7 +380,7 @@ TellChanged (WindowPtr pWin, pointer val
 	if (client == serverClient || client->clientGone)
 	    continue;
 
-	if (pRREvent->mask & RRMonitorChangeNotifyMask)) 
+	if (pRREvent->mask & RRMonitorChangeNotifyMask)
 	{
 	    me.type = RRNotify + RREventBase;
 	    me.subCode = RRNotify_MonitorChange;
@@ -377,12 +393,13 @@ TellChanged (WindowPtr pWin, pointer val
 #else
 	    me.subpixelOrder = SubPixelUnknown;
 #endif
-	    for (i = 0; i < pScrPriv->nMonitors; i++) 
+	    for (pMonitor = pScrPriv->pMonitors, i = 0; 
+		 pMonitor; 
+		 pMonitor = pMonitor->next, i++)
 	    {
-		pMonitor = &pScrPriv->pMonitors[i];
 		me.monitor = i;
-		if (pMonitor->mode >= 0) {
-		    me.modeID = pMonitor->pMode[pMonitor->mode].id;
+		if (pMonitor->pMode) {
+		    me.modeID = pMonitor->pMode->id;
 		    me.rotation = pMonitor->rotation;
 		    me.x = pMonitor->x;
 		    me.y = pMonitor->y;
@@ -396,10 +413,10 @@ TellChanged (WindowPtr pWin, pointer val
 	    }
 	}
 	if ((pRREvent->mask & RRScreenChangeNotifyMask) &&
-	    pScrPriv->nMonitors > 0)
+	    (pMonitor = pScrPriv->pMonitors))
 	{
 	    se.type = RRScreenChangeNotify + RREventBase;
-	    se.rotation = (CARD8) pScrPriv->rotation;
+	    se.rotation = (CARD8) pMonitor->rotation;
 	    se.timestamp = pScrPriv->lastSetTime.milliseconds;
 	    se.sequenceNumber = client->sequence;
 	    se.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
@@ -413,14 +430,14 @@ TellChanged (WindowPtr pWin, pointer val
 
 	    pMonitor = &pScrPriv->pMonitors[0];
 	    se.sequenceNumber = client->sequence;
-	    if (pMonitor->mode >= 0) 
+	    if (pMonitor->pMode) 
 	    {
-		pMode = &pMonitor->pModes[pMonitor->mode];
+		pMode = pMonitor->pMode;
 		se.sizeID = pMode->id;
-		se.widthInPixels = pMode->width;
-		se.heightInPixels = pMode->height;
-		se.widthInMillimeters = pMode->mmWidth;
-		se.heightInMillimeters = pMode->mmHeight;
+		se.widthInPixels = pMode->mode.width;
+		se.heightInPixels = pMode->mode.height;
+		se.widthInMillimeters = pMode->mode.widthInMillimeters;
+		se.heightInMillimeters = pMode->mode.heightInMillimeters;
 	    }
 	    else
 	    {
@@ -440,70 +457,107 @@ TellChanged (WindowPtr pWin, pointer val
     return WT_WALKCHILDREN;
 }
 
+static void
+RRFreeMode (RRModePtr pMode)
+{
+    xfree (pMode);
+}
+
+static void
+RRFreeModes (RRModePtr pHead)
+{
+    RRModePtr	pMode;
+    while ((pMode = pHead)) 
+    {
+	pHead = pMode->next;
+	RRFreeMode (pMode);
+    }
+}
+
+static void
+RRFreeMonitor (RRMonitorPtr pMonitor)
+{
+    RRFreeModes (pMonitor->pModes);
+    xfree (pMonitor);
+}
+
+
 static Bool
 RRGetInfo (ScreenPtr pScreen)
 {
     rrScrPriv (pScreen);
-    int		    m, s, n;
     Bool	    changed;
     Rotation	    rotations;
-    RRMonitorPtr    pMonitor;
-    RRModePtr	    pMode;
+    RRMonitorPtr    pMonitor, *pPrevMon;
+    RRModePtr	    pMode, *pPrevMode;
+    int		    monitorid;
 
-    for (m = 0; m < pScrPriv->nMonitors; m++)
+    for (pMonitor = pScrPriv->pMonitors; pMonitor; pMonitor = pMonitor->next)
     {
-	pMonitor = &pScrPriv->pMonitors[m];
-	pMonitor->oldReferenced = pMonitor->referenced;
+	pMonitor->oldReferenced = TRUE;
 	pMonitor->referenced = FALSE;
-	for (s = 0; s < pMonitor->nModes; s++)
+	pMonitor->pMode = NULL;
+	for (pMode = pMonitor->pModes; pMode; pMode = pMode->next)
 	{
-	    pMode = &pSize->pModes[s];
-	    pMode->oldReferenced = pMode->referenced;
+	    pMode->oldReferenced = TRUE;
 	    pMode->referenced = FALSE;
 	}
     }
-    changed = FALSE;
-
     rotations = 0;
     if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations))
 	return FALSE;
+
+    changed = FALSE;
     
     /* Old GetInfo clients return rotations here */
-    if (rotations && pScrPriv->nMonitors) {
+    if (rotations && pScrPriv->pMonitors) {
 	/*
 	 * Check whether anything changed and simultaneously generate
 	 * the protocol id values for the objects
 	 */
-	if (rotations != pScrPriv->pMonitors[i].rotations)
+	if (rotations != pScrPriv->pMonitors->rotations)
 	{
-	    pScrPriv->pMonitors[i].rotations = rotations;
+	    pScrPriv->pMonitors->rotations = rotations;
 	    changed = TRUE;
 	}
     }
 	
-    n = 0;
-    for (m = 0; m < pScrPriv->nMonitors; m++)
+    /*
+     * Walk monitor and mode lists looking for updates
+     */
+    monitorid = 0;
+    for (pPrevMon = &pScrPriv->pMonitors; (pMonitor = *pPrevMon);)
     {
 	int modeid = 0;
 	
-	pMonitor = &pScrPriv->pMonitors[m];
-	if (pMonitor->oldReferenced != pMonitor->referenced)
-	    changed = TRUE;
 	if (pMonitor->referenced)
 	{
-	    for (s = 0; s < pMonitor->nModes; s++)
+	    pMonitor->id = monitorid++;
+	    if (!pMonitor->oldReferenced)
+		changed = TRUE;
+	    for (pPrevMode = &pMonitor->pModes; (pMode = *pPrevMode);)
 	    {
-		pMode = &pMonitor->pModes[s];
-		if (pMode->oldReferenced != pMode->referenced)
-		    changed = TRUE;
 		if (pMode->referenced)
+		{
 		    pMode->id = modeid++;
+		    if (!pMode->oldReferenced)
+			changed = TRUE;
+		}
+		else
+		{
+		    *pPrevMode = pMode->next;
+		    changed = TRUE;
+		    RRFreeMode (pMode);
+		}
 	    }
-	    n++;
 	}
-	pMonitor->nModesInUse = modeid;
+	else
+	{
+	    *pPrevMon = pMonitor->next;
+	    changed = TRUE;
+	    RRFreeMonitor (pMonitor);
+	}
     }
-    pScrPriv->nMonitorsInUse = n;
     if (changed)
     {
 	UpdateCurrentTime ();
@@ -548,6 +602,10 @@ ProcRRQueryVersion (ClientPtr client)
     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 = RANDR_MAJOR;
     rep.minorVersion = RANDR_MINOR;
     if (client->swapped) {
@@ -605,6 +663,100 @@ RREditConnectionInfo (ScreenPtr pScreen)
 }
 
 static int
+RRNumModes (RRMonitorPtr pMonitor)
+{
+    int	n = 0;
+    RRModePtr	pMode;
+
+    for (pMode = pMonitor->pModes; pMode; pMode = pMode->next)
+	n++;
+    return n;
+}
+
+typedef struct _RR10Data {
+    RRScreenSizePtr sizes;
+    int		    nsize;
+    int		    nrefresh;
+    int		    size;
+    CARD16	    refresh;
+} RR10DataRec, *RR10DataPtr;
+
+static CARD16
+RRVerticalRefresh (xRRMonitorMode *mode)
+{
+    CARD32  refresh;
+    if (!mode->hTotal || !mode->vTotal)
+	return 0;
+    refresh = mode->dotClock / (mode->hTotal * mode->vTotal);
+    if (refresh > 0xffff)
+	refresh = 0xffff;
+    return (CARD16) refresh;
+}
+
+/*
+ * Convert 1.2 monitor data into 1.0 screen data
+ */
+static RR10DataPtr
+RR10GetData (ScreenPtr pScreen, RRMonitorPtr pMonitor)
+{
+    RR10DataPtr	    data;
+    RRScreenSizePtr size;
+    int		    nmode = RRNumModes (pMonitor);
+    int		    i;
+    int		    j;
+    RRRefreshPtr    refresh;
+    CARD16	    vRefresh;
+    RRModePtr	    pMode;
+
+    /* Make sure there is plenty of space for any combination */
+    data = malloc (sizeof (RR10DataRec) + 
+		   sizeof (RRScreenSizeRec) * nmode + 
+		   sizeof (RRRefreshRec) * nmode);
+    if (!data)
+	return NULL;
+    size = (RRScreenSizePtr) (data + 1);
+    refresh = (RRRefreshPtr) (size + nmode);
+    data->nsize = 0;
+    data->nrefresh = 0;
+    data->size = 0;
+    data->refresh = 0;
+    for (pMode = pMonitor->pModes; pMode; pMode = pMode->next)
+    {
+	for (i = 0; i < data->nsize; i++)
+	    if (pMode->mode.width == size[i].width &&
+		pMode->mode.height == size[i].height)
+		break;
+	if (i == data->nsize)
+	{
+	    size[i].width = pMode->mode.width;
+	    size[i].height = pMode->mode.height;
+	    size[i].mmWidth = pMode->mode.widthInMillimeters;
+	    size[i].mmHeight = pMode->mode.heightInMillimeters;
+	    size[i].nrefresh = 0;
+	    size[i].refresh = &refresh[data->nrefresh];
+	    data->nsize++;
+	}
+	vRefresh = RRVerticalRefresh (&pMode->mode);
+	for (j = 0; j < size[i].nrefresh; j++)
+	    if (vRefresh == size[i].refresh[j].refresh)
+		break;
+	if (j == size[i].nrefresh)
+	{
+	    size[i].refresh[j].refresh = vRefresh;
+	    size[i].refresh[j].pMode = pMode;
+	    size[i].nrefresh++;
+	    data->nrefresh++;
+	}
+	if (pMode == pMonitor->pMode)
+	{
+	    data->size = i;
+	    data->refresh = vRefresh;
+	}
+    }
+    return data;
+}
+
+static int
 ProcRRGetScreenInfo (ClientPtr client)
 {
     REQUEST(xRRGetScreenInfoReq);
@@ -626,7 +778,11 @@ ProcRRGetScreenInfo (ClientPtr client)
     pScreen = pWin->drawable.pScreen;
     pScrPriv = rrGetScrPriv(pScreen);
     rep.pad = 0;
-    if (!pScrPriv)
+    
+    if (pScrPriv)
+	RRGetInfo (pScreen);
+
+    if (!pScrPriv && !pScrPriv->pMonitors)
     {
 	rep.type = X_Reply;
 	rep.setOfRotations = RR_Rotate_0;;
@@ -645,94 +801,82 @@ ProcRRGetScreenInfo (ClientPtr client)
     }
     else
     {
+	RRMonitorPtr		pMonitor = pScrPriv->pMonitors;
 	int			i, j;
 	xScreenSizes		*size;
 	CARD16			*rates;
 	CARD8			*data8;
 	Bool			has_rate = RRClientKnowsRates (client);
+	RR10DataPtr		pData;
+	RRScreenSizePtr		pSize;
     
-	RRGetInfo (pScreen);
-
+	pData = RR10GetData (pScreen, pMonitor);
+	if (!pData)
+	    return BadAlloc;
+	
 	rep.type = X_Reply;
-	rep.setOfRotations = pScrPriv->rotations;
+	rep.setOfRotations = pMonitor->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)
-	{
-	    for (i = 0; i < pScrPriv->nSizes; i++)
-	    {
-		RRScreenSizePtr pSize = &pScrPriv->pSizes[i];
-		if (pSize->referenced)
-		{
-		    rep.nrateEnts += (1 + pSize->nRatesInUse);
-		}
-	    }
-	}
-
-	if (pScrPriv->size >= 0)
-	    rep.sizeID = pScrPriv->pSizes[pScrPriv->size].id;
-	else
-	    return BadImplementation;
+	rep.rotation = pMonitor->rotation;
+	rep.nSizes = pData->nsize;
+        rep.nrateEnts = pData->nrefresh;
+	rep.sizeID = pData->size;
+	rep.rate = pData->refresh;
 
 	extraLen = (rep.nSizes * sizeof (xScreenSizes) +
 		    rep.nrateEnts * sizeof (CARD16));
 
 	extra = (CARD8 *) xalloc (extraLen);
 	if (!extra)
+	{
+	    xfree (pData);
 	    return BadAlloc;
+	}
 	/*
 	 * First comes the size information
 	 */
 	size = (xScreenSizes *) extra;
 	rates = (CARD16 *) (size + rep.nSizes);
-	for (i = 0; i < pScrPriv->nSizes; i++)
+	for (i = 0; i < pData->nsize; i++)
 	{
-	    RRScreenSizePtr pSize = &pScrPriv->pSizes[i];
-	    if (pSize->referenced)
+	    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)
 	    {
-		size->widthInPixels = pSize->width;
-		size->heightInPixels = pSize->height;
-		size->widthInMillimeters = pSize->mmWidth;
-		size->heightInMillimeters = pSize->mmHeight;
+		*rates = pSize->nrefresh;
 		if (client->swapped)
 		{
-		    swaps (&size->widthInPixels, n);
-		    swaps (&size->heightInPixels, n);
-		    swaps (&size->widthInMillimeters, n);
-		    swaps (&size->heightInMillimeters, n);
+		    swaps (rates, n);
 		}
-		size++;
-		if (has_rate)
+		rates++;
+		for (j = 0; j < pSize->nrefresh; j++)
 		{
-		    *rates = pSize->nRatesInUse;
+		    *rates = pSize->refresh[j].refresh;
 		    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++;
-			}
-		    }
 		}
 	    }
 	}
+        xfree (pData);
+	
 	data8 = (CARD8 *) rates;
 
 	if (data8 - (CARD8 *) extra != extraLen)
@@ -770,13 +914,16 @@ ProcRRSetScreenConfig (ClientPtr client)
     rrScrPrivPtr	    pScrPriv;
     TimeStamp		    configTime;
     TimeStamp		    time;
-    RRScreenSizePtr	    pSize;
     int			    i;
     Rotation		    rotation;
     int			    rate;
     short		    oldWidth, oldHeight;
     Bool		    has_rate;
-
+    RRMonitorPtr	    pMonitor;
+    RRModePtr		    pMode;
+    RR10DataPtr		    pData = NULL;
+    RRScreenSizePtr    	    pSize;
+    
     UpdateCurrentTime ();
 
     if (RRClientKnowsRates (client))
@@ -812,6 +959,14 @@ ProcRRSetScreenConfig (ClientPtr client)
     if (!RRGetInfo (pScreen))
 	return BadAlloc;
     
+    pMonitor = pScrPriv->pMonitors;
+    if (!pMonitor)
+    {
+	time = currentTime;
+	rep.status = RRSetConfigFailed;
+	goto sendReply;
+    }
+    
     /*
      * 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
@@ -823,26 +978,20 @@ ProcRRSetScreenConfig (ClientPtr client)
 	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)
+    pData = RR10GetData (pScreen, pMonitor);
+    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
@@ -861,15 +1010,17 @@ ProcRRSetScreenConfig (ClientPtr client)
 	 * Invalid rotation
 	 */
 	client->errorValue = stuff->rotation;
+	xfree (pData);
 	return BadValue;
     }
 
-    if ((~pScrPriv->rotations) & rotation)
+    if ((~pMonitor->rotations) & rotation)
     {
 	/*
 	 * requested rotation or reflection not supported by screen
 	 */
 	client->errorValue = stuff->rotation;
+	xfree (pData);
 	return BadMatch;
     }
 
@@ -883,21 +1034,24 @@ ProcRRSetScreenConfig (ClientPtr client)
 
     if (rate)
     {
-	for (i = 0; i < pSize->nRates; i++)
+	for (i = 0; i < pSize->nrefresh; i++)
 	{
-	    RRScreenRatePtr pRate = &pSize->pRates[i];
-	    if (pRate->referenced && pRate->rate == rate)
+	    if (pSize->refresh[i].refresh == rate)
 		break;
 	}
-	if (i == pSize->nRates)
+	if (i == pSize->nrefresh)
 	{
 	    /*
 	     * Invalid rate
 	     */
 	    client->errorValue = rate;
+	    xfree (pData);
 	    return BadValue;
 	}
+	pMode = pSize->refresh[i].pMode;
     }
+    else
+	pMode = pSize->refresh[0].pMode;
     
     /*
      * Make sure the requested set-time is not older than
@@ -912,9 +1066,51 @@ ProcRRSetScreenConfig (ClientPtr client)
     /*
      * call out to ddx routine to effect the change
      */
-    if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate,
-				   pSize))
+    if (pScrPriv->rrSetScreenSize && pScrPriv->rrSetMode)
+    {
+	xScreenSizes	oldSize;
+	if (!(*pScrPriv->rrSetMode) (pScreen, 0, NULL, 0, 0, RR_Rotate_0))
+	    goto fail;
+	oldSize.widthInPixels = pScreen->width;
+	oldSize.heightInPixels = pScreen->width;
+	oldSize.widthInMillimeters = pScreen->mmWidth;
+	oldSize.heightInMillimeters = pScreen->mmHeight;
+	if (!(*pScrPriv->rrSetScreenSize) (pScreen,
+					   pMode->mode.width,
+					   pMode->mode.height,
+					   pMode->mode.widthInMillimeters,
+					   pMode->mode.heightInMillimeters))
+	{
+	    (void) (*pScrPriv->rrSetMode) (pScreen, 0, pMonitor->pMode,
+					   pMonitor->x, pMonitor->y,
+					   pMonitor->rotation);
+	    goto fail;
+	}
+	if (!(*pScrPriv->rrSetMode) (pScreen, 0, pMode, 0, 0, rotation))
+	{
+	    (void) (*pScrPriv->rrSetScreenSize) (pScreen,
+						 oldSize.widthInPixels,
+						 oldSize.heightInPixels,
+						 oldSize.widthInMillimeters,
+						 oldSize.heightInMillimeters);
+	    (void) (*pScrPriv->rrSetMode) (pScreen, 0, pMonitor->pMode,
+					   pMonitor->x, pMonitor->y,
+					   pMonitor->rotation);
+	    goto fail;
+	}
+    }
+#ifdef RANDR_SCREEN_INTERFACE
+    else if (pScrPriv->rrSetConfig)
     {
+	if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate, pSize))
+	{
+	    goto fail;
+	}
+    }
+#endif
+    else
+    {
+fail:	;
 	/*
 	 * unknown DDX failure, report to client
 	 */
@@ -925,7 +1121,7 @@ ProcRRSetScreenConfig (ClientPtr client)
     /*
      * set current extension configuration pointers
      */
-    RRSetCurrentConfig (pScreen, rotation, rate, pSize);
+    RRSetCurrentMode (pMonitor, pMode, 0, 0, rotation);
     
     /*
      * Deliver ScreenChangeNotify events whenever
@@ -954,6 +1150,9 @@ ProcRRSetScreenConfig (ClientPtr client)
     
 sendReply:
     
+    if (pData)
+	xfree (pData);
+
     rep.type = X_Reply;
     /* rep.status has already been filled in */
     rep.length = 0;
@@ -1055,7 +1254,7 @@ RRSetScreenConfig (ScreenPtr		pScreen,
     /*
      * set current extension configuration pointers
      */
-    RRSetCurrentConfig (pScreen, rotation, rate, pSize);
+    RRSetCurrentMode (pMonitor, pMode, 0, 0, rotation);
     
     /*
      * Deliver ScreenChangeNotify events whenever
@@ -1075,7 +1274,6 @@ RRSetScreenConfig (ScreenPtr		pScreen,
      * Fix pointer bounds and location
      */
     ScreenRestructured (pScreen);
-    
     return Success;
 }
 
@@ -1286,22 +1484,114 @@ SProcRRDispatch (ClientPtr client)
     }
 }
 
+/*
+ * Register a monitor for a screen. identifier is a unique identifier
+ * for the monitors of a particular screen.
+ */
+RRMonitorPtr
+RRRegisterMonitor (ScreenPtr		pScreen,
+		   void			*identifier,
+		   Rotation		rotations)
+{
+    rrScrPriv (pScreen);
+    RRMonitorPtr    pMonitor, *pPrev, *pInsert;
 
-static Bool
-RRScreenSizeMatches (RRScreenSizePtr  a,
-		   RRScreenSizePtr  b)
+    pInsert = NULL;
+    for (pPrev = &pScrPriv->pMonitors; (pMonitor = *pPrev); 
+	 pPrev = &(pMonitor)->next)
+    {
+	if (pMonitor->identifier == identifier) 
+	{
+	    pMonitor->referenced = TRUE;
+	    return pMonitor;
+	}
+	if (!pMonitor->referenced)
+	    pInsert = pPrev;
+    }
+    if (!pInsert)
+	pInsert = pPrev;
+    
+    /*
+     * New monitor, add before the first unreferenced monitor
+     */
+    pMonitor = xalloc (sizeof (RRMonitor));
+    if (!pMonitor)
+	return NULL;
+    pMonitor->pScreen = pScreen;
+    pMonitor->pModes = NULL;
+    pMonitor->identifier = identifier;
+    pMonitor->referenced = TRUE;
+    pMonitor->oldReferenced = FALSE;
+    pMonitor->rotations = RR_Rotate_0;
+    
+    pMonitor->pMode = NULL;
+    pMonitor->x = 0;
+    pMonitor->y = 0;
+    pMonitor->rotation = RR_Rotate_0;
+    pMonitor->next = *pInsert;
+    *pInsert = pMonitor;
+    return pMonitor;
+}
+
+/*
+ * Register a mode for a monitor
+ */
+
+RRModePtr
+RRRegisterMode (RRMonitorPtr	pMonitor,
+		xRRMonitorMode	*pModeline,
+		char		*name)
 {
-    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;
+    RRModePtr	pMode, *pPrev, *pInsert = NULL;
+
+    /*
+     * Find existing mode with same modeline and name
+     */
+    for (pPrev = &pMonitor->pModes; (pMode = *pPrev); pPrev = &(pMode->next))
+    {
+	if (!memcmp (&pMode->mode, pModeline, sizeof (xRRMonitorMode)) &&
+	    pMode->mode.nameLength == pModeline->nameLength &&
+	    !memcmp (RRModeName(pMode), name, pModeline->nameLength))
+	{
+	    pMode->referenced = TRUE;
+	    return pMode;
+	}
+	if (!pMode->referenced)
+	    pInsert = pPrev;
+    }
+
+    if (!pInsert)
+	pInsert = pPrev;
+    
+    /*
+     * Create a new mode, inserting before the first unreferenced mode
+     */
+    pMode = xalloc (sizeof (RRMode) + pModeline->nameLength + 1);
+    pMode->referenced = TRUE;
+    pMode->oldReferenced = FALSE;
+    pMode->mode = *pModeline;
+    memcpy (RRModeName (pMode), name, pModeline->nameLength);
+    RRModeName(pMode)[pModeline->nameLength] = '\0';
+    pMode->next = *pInsert;
+    *pInsert = pMode;
+    return pMode;
+}
+
+void
+RRSetCurrentMode (RRMonitorPtr	pMonitor,
+		  RRModePtr	pMode,
+		  int		x,
+		  int		y,
+		  Rotation	rotation)
+{
+    pMonitor->pMode = pMode;
+    pMonitor->x = x;
+    pMonitor->y = y;
+    pMonitor->rotation = rotation;
 }
 
+#ifdef RANDR_SCREEN_INTERFACE
+
 RRScreenSizePtr
 RRRegisterSize (ScreenPtr	    pScreen,
 		short		    width, 
@@ -1310,36 +1600,45 @@ RRRegisterSize (ScreenPtr	    pScreen,
 		short		    mmHeight)
 {
     rrScrPriv (pScreen);
-    int		    i;
-    RRScreenSize    tmp;
-    RRScreenSizePtr pNew;
+    xRRMonitorMode  tmp;
+    RRMonitorPtr    pMonitor;
+    RRModePtr	    pMode, *pPrev;
+    char	    name[100];
 
     if (!pScrPriv)
-	return 0;
-    
-    tmp.id = -1;
+	return NULL;
+    pMonitor = pScrPriv->pMonitors;
+    if (!pMonitor)
+	return NULL;
+    
+    for (pPrev = &pMonitor->pModes; (pMode = *pPrev); pPrev = &(pMode->next))
+	if (pMode->mode.width == width &&
+	    pMode->mode.height == height &&
+	    pMode->mode.widthInMillimeters == mmWidth &&
+	    pMode->mode.heightInMillimeters == mmHeight)
+	{
+	    pMode->referenced =TRUE;
+	    return (void *) pMode;
+	}
+    memset (&tmp, '\0', sizeof (xRRMonitorMode));
+    memset (name, '\0', sizeof (name));
+    sprintf (name, "%dx%d", width, height);
     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];
+    tmp.widthInMillimeters = mmWidth;
+    tmp.heightInMillimeters = mmHeight;
+    tmp.nameLength = strlen (name) + 10;    /* leave space for refresh */
+    pMode = RRRegisterMode (pMonitor, &tmp, name);
+    return (void *) pMode;
+}
+
+static Bool
+RRModesMatchSize (RRModePtr a, RRModePtr b)
+{
+    return (a->mode.width == a->mode.width &&
+	    a->mode.height == b->mode.height &&
+	    a->mode.widthInMillimeters == b->mode.widthInMillimeters &&
+	    a->mode.heightInMillimeters == b->mode.heightInMillimeters);
 }
 
 Bool RRRegisterRate (ScreenPtr		pScreen,
@@ -1347,31 +1646,61 @@ Bool RRRegisterRate (ScreenPtr		pScreen,
 		     int		rate)
 {
     rrScrPriv(pScreen);
-    int		    i;
-    RRScreenRatePtr pNew, pRate;
+    RRMonitorPtr    pMonitor;
+    RRModePtr	    pSizeMode = (RRModePtr) pSize;
+    RRModePtr	    pMode, *pPrev;
+    CARD16	    width = pSizeMode->mode.width;
+    CARD16	    height = pSizeMode->mode.height;
+    char	    name[100];
+    xRRMonitorMode  modeLine;
 
     if (!pScrPriv)
 	return FALSE;
     
-    for (i = 0; i < pSize->nRates; i++)
+    pMonitor = pScrPriv->pMonitors;
+    if (!pMonitor)
+	return FALSE;
+
+    for (pPrev = &pMonitor->pModes; (pMode = *pPrev); pPrev = &pMode->next)
     {
-	pRate = &pSize->pRates[i];
-	if (pRate->rate == rate)
+	if (RRModesMatchSize (pMode, pSizeMode))
 	{
-	    pRate->referenced = TRUE;
-	    return TRUE;
+	    if (pMode->mode.dotClock == 0)
+	    {
+		/*
+		 * First refresh for this size; reprogram this mode
+		 * with the right refresh.
+		 */
+		pMode->mode.hSyncStart = width;
+		pMode->mode.hSyncEnd = width;
+		pMode->mode.hTotal = width;
+		pMode->mode.hSkew = 0;
+		pMode->mode.vSyncStart = height;
+		pMode->mode.vSyncEnd = height;
+		pMode->mode.vTotal = height;
+		pMode->mode.dotClock = width * height * rate;
+		sprintf ((char *) (pMode + 1), "%dx%d@%d", width, height, rate);
+		pMode->mode.modeFlags = 0;
+		pMode->mode.nameLength = strlen ((char *) (pMode + 1));
+		pMode->referenced = TRUE;
+		return TRUE;
+	    }
+	    else if (rate == RRVerticalRefresh (&pMode->mode))
+	    {
+		pMode->referenced = TRUE;
+		return TRUE;
+	    }
 	}
     }
-
-    pNew = xrealloc (pSize->pRates,
-		     (pSize->nRates + 1) * sizeof (RRScreenRate));
-    if (!pNew)
+    
+    sprintf (name, "%dx%d@%d", pSizeMode->mode.width, pSizeMode->mode.height,
+	     rate);
+    modeLine = pSizeMode->mode;
+    modeLine.dotClock = rate * modeLine.vTotal * modeLine.hTotal;
+    modeLine.nameLength = strlen (name);
+    pMode = RRRegisterMode (pMonitor, &modeLine, name);
+    if (!pMode)
 	return FALSE;
-    pRate = &pNew[pSize->nRates++];
-    pRate->rate = rate;
-    pRate->referenced = TRUE;
-    pRate->oldReferenced = FALSE;
-    pSize->pRates = pNew;
     return TRUE;
 }
 
@@ -1379,11 +1708,15 @@ Rotation
 RRGetRotation(ScreenPtr pScreen)
 {
     rrScrPriv (pScreen);
+    RRMonitorPtr    pMonitor;
 
     if (!pScrPriv)
 	return RR_Rotate_0;
 
-    return pScrPriv->rotation;
+    pMonitor = pScrPriv->pMonitors;
+    if (!pMonitor)
+	return RR_Rotate_0;
+    return pMonitor->rotation;
 }
 
 void
@@ -1393,11 +1726,25 @@ RRSetCurrentConfig (ScreenPtr		pScreen,
 		    RRScreenSizePtr	pSize)
 {
     rrScrPriv (pScreen);
+    RRMonitorPtr    pMonitor;
+    RRModePtr	    pMode;
+    RRModePtr	    pSizeMode = (RRModePtr) pSize;
 
     if (!pScrPriv)
 	return;
+    pMonitor = pScrPriv->pMonitors;
+    if (!pMonitor)
+	return;
 
-    pScrPriv->rotation = rotation;
-    pScrPriv->size = pSize - pScrPriv->pSizes;
-    pScrPriv->rate = rate;
+    for (pMode = pMonitor->pModes; pMode; pMode = pMode->next)
+    {
+	if (RRModesMatchSize (pMode, pSizeMode) && 
+	    RRVerticalRefresh (&pMode->mode) == rate)
+	    break;
+    }
+    if (!pMode)
+	return;
+    
+    RRSetCurrentMode (pMonitor, pMode, 0, 0, rotation);
 }
+#endif
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 07c6c37..3610274 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -34,11 +34,19 @@
 
 #include <X11/extensions/randrproto.h>
 
+#define RANDR_SCREEN_INTERFACE 1
+
+/*
+ * Modeline for a monitor. Name follows directly after this struct
+ */
+
+#define RRModeName(pMode) ((char *) (pMode + 1))
+
 typedef struct _rrMode {
     struct _rrMode  *next;
-    int		    id;
     Bool	    referenced;
     Bool	    oldReferenced;
+    int		    id;
     xRRMonitorMode  mode;
 } RRMode, *RRModePtr;
 
@@ -47,12 +55,15 @@ typedef struct _rrMonitor {
     ScreenPtr	    pScreen;
     RRModePtr	    pModes;
     void	    *identifier;    /* made unique by DDX */
+    int		    id;		    /* index in list of monitors */
     Bool	    referenced;
+    Bool	    oldReferenced;
+    Rotation	    rotations;
     
     /*
      * Current state
      */
-    int		    mode;
+    RRModePtr	    pMode;
     int		    x, y;
     Rotation	    rotation;
 } RRMonitor, *RRMonitorPtr;
@@ -76,7 +87,18 @@ typedef Bool (*RRCloseScreenProcPtr) ( i
 
 #ifdef RANDR_SCREEN_INTERFACE
 
-typedef void *RRScreenSizePtr;
+typedef struct _rrRefresh {
+    CARD16	    refresh;
+    RRModePtr	    pMode;
+} RRRefreshRec, *RRRefreshPtr;
+
+typedef struct _rrScreenSize {
+    int		    id;
+    short	    width, height;
+    short	    mmWidth, mmHeight;
+    int		    nrefresh;
+    RRRefreshPtr    refresh;
+} RRScreenSizeRec, *RRScreenSizePtr;
 
 typedef Bool (*RRSetConfigProcPtr) (ScreenPtr		pScreen,
 				    Rotation		rotation,
@@ -87,12 +109,23 @@ typedef Bool (*RRSetConfigProcPtr) (Scre
 	
 
 typedef struct _rrScrPriv {
-    RRSetModeProcPtr	    rrSetMode;
+    /*
+     * 'public' part of the structure; DDXen fill this in
+     * as they initialize
+     */
+#ifdef RANDR_SCREEN_INTERFACE
+    RRSetConfigProcPtr	    rrSetConfig;
+#endif
     RRGetInfoProcPtr	    rrGetInfo;
-    RRCloseScreenProcPtr    CloseScreen;
+    RRSetScreenSizeProcPtr  rrSetScreenSize;
+    RRSetModeProcPtr	    rrSetMode;
     
+    /*
+     * Private part of the structure; not considered part of the ABI
+     */
     TimeStamp		    lastSetTime;	/* last changed by client */
     TimeStamp		    lastConfigTime;	/* possible configs changed */
+    RRCloseScreenProcPtr    CloseScreen;
 
     /*
      * monitor data
@@ -105,7 +138,6 @@ typedef struct _rrScrPriv {
      */
     Rotation		    rotations;
     
-    RRSetConfigProcPtr	    rrSetConfig;
 
     Rotation		    rotation;
 #endif
@@ -137,8 +169,7 @@ RRRegisterMonitor (ScreenPtr		pScreen,
 RRModePtr
 RRRegisterMode (RRMonitorPtr	pMonitor,
 		xRRMonitorMode	*pMode,
-		char		*name,
-		int		nameLength);
+		char		*name);
 
 /*
  * Finally, set the current configuration of each monitor
@@ -147,6 +178,8 @@ RRRegisterMode (RRMonitorPtr	pMonitor,
 void
 RRSetCurrentMode (RRMonitorPtr	pMonitor,
 		  RRModePtr	pMode,
+		  int		x,
+		  int		y,
 		  Rotation	rotation);
 
 Bool RRScreenInit(ScreenPtr pScreen);
@@ -167,6 +200,8 @@ Bool
 miRRSetMode (ScreenPtr	pScreen,
 	     int	monitor,
 	     RRModePtr	pMode,
+	     int	x,
+	     int	y,
 	     Rotation	rotation);
 
 #ifdef RANDR_SCREEN_INTERFACE					
diff-tree dc89ecf5b51ecd2bf5ab61b8e6a28b1fff3bc38b (from d17becf0242c0e5ef0f10c0718e21f773fa5069f)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Sat Jul 1 19:46:38 2006 -0700

    Preliminary RandR 1.2 work

diff --git a/randr/mirandr.c b/randr/mirandr.c
index 0954028..7bef02d 100644
--- a/randr/mirandr.c
+++ b/randr/mirandr.c
@@ -1,36 +1,36 @@
 /*
- *
- * 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>
 
@@ -48,26 +48,35 @@ miRRGetInfo (ScreenPtr pScreen, Rotation
 {
     int	i;
     Bool setConfig = FALSE;
+    RRMonitorPtr pMonitor;
     
-    *rotations = RR_Rotate_0;
+    pMonitor = RRRegisterMonitor (pScreen, NULL, 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;
-		}
+	    xRRMonitorMode		rrMode;
+	    RRModePtr			pMode;
+	    char			name[64];
+
+	    sprintf (name, "%dx%d", pScreen->width, pScreen->height);
+	    memset (&rrMode, '\0', sizeof (rrMode));
+	    rrMode.width = pScreen->width;
+	    rrMode.height = pScreen->height;
+	    rrMode.widthInMillimeters = pScreen->mmWidth;
+	    rrMode.heightInMillimeters = pScreen->mmHeight;
+	    pMonitor = RRRegisterMonitor (pScreen, RR_Rotate_0);
+	    pMode = RRRegisterMode (pMonitor,
+				    &rrMode,
+				    name,
+				    strlen (name));
+	    if (!pMode)
+		return FALSE;
+	    if (!setConfig)
+	    {
+		RRSetCurrentMode (pMonitor, pMode, 0, 0, RR_Rotate_0);
+		setConfig = TRUE;
+	    }
 	}
     }
     return TRUE;
@@ -78,10 +87,10 @@ miRRGetInfo (ScreenPtr pScreen, Rotation
  * different here
  */
 Bool
-miRRSetConfig (ScreenPtr	pScreen,
-	       Rotation		rotation,
-	       int		rate,
-	       RRScreenSizePtr	pSize)
+miRRSetMode (ScreenPtr	pScreen,
+	     int	monitor,
+	     RRModePtr	pMode,
+	     Rotation	rotation)
 {
     return TRUE;
 }
@@ -96,6 +105,6 @@ miRandRInit (ScreenPtr pScreen)
 	return FALSE;
     rp = rrGetScrPriv(pScreen);
     rp->rrGetInfo = miRRGetInfo;
-    rp->rrSetConfig = miRRSetConfig;
+    rp->rrSetMode = miRRSetMode;
     return TRUE;
 }
diff --git a/randr/randr.c b/randr/randr.c
index 946aad3..1a9624a 100644
--- a/randr/randr.c
+++ b/randr/randr.c
@@ -1,29 +1,30 @@
 /*
- *
- * 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
@@ -159,10 +160,21 @@ static Bool
 RRCloseScreen (int i, ScreenPtr pScreen)
 {
     rrScrPriv(pScreen);
+    RRMonitorPtr    pMonitor;
 
     unwrap (pScrPriv, pScreen, CloseScreen);
-    if (pScrPriv->pSizes)
-	xfree (pScrPriv->pSizes);
+    while (pMonitor = pScrPriv->pMonitors) 
+    {
+	RRModePtr   pMode;
+	
+	pScrPriv->pMonitors = pMonitor->next;
+	while (pMode = pMonitor->pModes) 
+	{
+	    pMonitor->pModes = pMode->next;
+	    xfree (pMode);
+	}
+	xfree (pMonitor);
+    }
     xfree (pScrPriv);
     RRNScreens -= 1;	/* ok, one fewer screen with RandR running */
     return (*pScreen->CloseScreen) (i, pScreen);    
@@ -187,6 +199,25 @@ SRRScreenChangeNotifyEvent(xRRScreenChan
     cpswaps(from->subpixelOrder, to->subpixelOrder);
 }
 
+static void
+SRRMonitorChangeNotifyEvent(xRRMonitorChangeNotifyEvent *from,
+			    xRRMonitorChangeNotifyEvent *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->root, to->root);
+    cpswapl(from->window, to->window);
+    cpswaps(from->monitor, to->monitor);
+    cpswaps(from->modeID, to->modeID);
+    cpswaps(from->rotation, to->rotation);
+    cpswaps(from->subpixelOrder, to->subpixelOrder);
+    cpswaps(from->x, to->x);
+    cpswaps(from->y, to->y);
+}
+
 Bool RRScreenInit(ScreenPtr pScreen)
 {
     rrScrPrivPtr   pScrPriv;
@@ -207,8 +238,12 @@ Bool RRScreenInit(ScreenPtr pScreen)
     /*
      * Calling function best set these function vectors
      */
-    pScrPriv->rrSetConfig = 0;
+    pScrPriv->rrSetMode = 0;
     pScrPriv->rrGetInfo = 0;
+#ifdef RANDR_SCREEN_INTERFACE    
+    pScrPriv->rrSetConfig = 0;
+#endif
+    
     /*
      * This value doesn't really matter -- any client must call
      * GetScreenInfo before reading it which will automatically update
@@ -219,14 +254,7 @@ 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->pMonitors = NULL;
     
     RRNScreens += 1;	/* keep count of screens that implement randr */
     return TRUE;
@@ -318,55 +346,96 @@ TellChanged (WindowPtr pWin, pointer val
     RREventPtr			*pHead, pRREvent;
     ClientPtr			client;
     xRRScreenChangeNotifyEvent	se;
+    xRRMonitorChangeNotifyEvent	me;
     ScreenPtr			pScreen = pWin->drawable.pScreen;
     rrScrPriv(pScreen);
-    RRScreenSizePtr		pSize;
+    RRMonitorPtr		pMonitor = pScrPriv->pMonitors;
+    RRModePtr			pMode;
     WindowPtr			pRoot = WindowTable[pScreen->myNum];
+    int				i;
 
     pHead = (RREventPtr *) LookupIDByType (pWin->drawable.id, EventType);
     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);
+
+	if (pRREvent->mask & RRMonitorChangeNotifyMask)) 
+	{
+	    me.type = RRNotify + RREventBase;
+	    me.subCode = RRNotify_MonitorChange;
+	    me.timestamp = pScrPriv->lastSetTime.milliseconds;
+	    me.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
+	    me.root =  pRoot->drawable.id;
+	    me.window = pWin->drawable.id;
+#ifdef RENDER
+	    me.subpixelOrder = PictureGetSubpixelOrder (pScreen);
+#else
+	    me.subpixelOrder = SubPixelUnknown;
+#endif
+	    for (i = 0; i < pScrPriv->nMonitors; i++) 
+	    {
+		pMonitor = &pScrPriv->pMonitors[i];
+		me.monitor = i;
+		if (pMonitor->mode >= 0) {
+		    me.modeID = pMonitor->pMode[pMonitor->mode].id;
+		    me.rotation = pMonitor->rotation;
+		    me.x = pMonitor->x;
+		    me.y = pMonitor->y;
+		} else {
+		    me.modeID = 0xffff;
+		    me.rotation = RR_Rotate_0;
+		    me.x = 0;
+		    me.y = 0;
+		}
+		WriteEventsToClient (client, 1, (xEvent *) &me);
+	    }
+	}
+	if ((pRREvent->mask & RRScreenChangeNotifyMask) &&
+	    pScrPriv->nMonitors > 0)
+	{
+	    se.type = RRScreenChangeNotify + RREventBase;
+	    se.rotation = (CARD8) pScrPriv->rotation;
+	    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
+
+	    pMonitor = &pScrPriv->pMonitors[0];
+	    se.sequenceNumber = client->sequence;
+	    if (pMonitor->mode >= 0) 
+	    {
+		pMode = &pMonitor->pModes[pMonitor->mode];
+		se.sizeID = pMode->id;
+		se.widthInPixels = pMode->width;
+		se.heightInPixels = pMode->height;
+		se.widthInMillimeters = pMode->mmWidth;
+		se.heightInMillimeters = pMode->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;
+	    }    
+	    WriteEventsToClient (client, 1, (xEvent *) &se);
+	}
     }
     return WT_WALKCHILDREN;
 }
@@ -375,59 +444,66 @@ static Bool
 RRGetInfo (ScreenPtr pScreen)
 {
     rrScrPriv (pScreen);
-    int		    i, j, k, l;
+    int		    m, s, n;
     Bool	    changed;
     Rotation	    rotations;
-    RRScreenSizePtr pSize;
-    RRScreenRatePtr pRate;
+    RRMonitorPtr    pMonitor;
+    RRModePtr	    pMode;
 
-    for (i = 0; i < pScrPriv->nSizes; i++)
+    for (m = 0; m < pScrPriv->nMonitors; m++)
     {
-	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;
+	pMonitor = &pScrPriv->pMonitors[m];
+	pMonitor->oldReferenced = pMonitor->referenced;
+	pMonitor->referenced = FALSE;
+	for (s = 0; s < pMonitor->nModes; s++)
+	{
+	    pMode = &pSize->pModes[s];
+	    pMode->oldReferenced = pMode->referenced;
+	    pMode->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;
+    rotations = 0;
+    if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations))
+	return FALSE;
+    
+    /* Old GetInfo clients return rotations here */
+    if (rotations && pScrPriv->nMonitors) {
+	/*
+	 * Check whether anything changed and simultaneously generate
+	 * the protocol id values for the objects
+	 */
+	if (rotations != pScrPriv->pMonitors[i].rotations)
+	{
+	    pScrPriv->pMonitors[i].rotations = rotations;
+	    changed = TRUE;
+	}
     }
-
-    j = 0;
-    for (i = 0; i < pScrPriv->nSizes; i++)
-    {
-	pSize = &pScrPriv->pSizes[i];
-	if (pSize->oldReferenced != pSize->referenced)
+	
+    n = 0;
+    for (m = 0; m < pScrPriv->nMonitors; m++)
+    {
+	int modeid = 0;
+	
+	pMonitor = &pScrPriv->pMonitors[m];
+	if (pMonitor->oldReferenced != pMonitor->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++;
+	if (pMonitor->referenced)
+	{
+	    for (s = 0; s < pMonitor->nModes; s++)
+	    {
+		pMode = &pMonitor->pModes[s];
+		if (pMode->oldReferenced != pMode->referenced)
+		    changed = TRUE;
+		if (pMode->referenced)
+		    pMode->id = modeid++;
+	    }
+	    n++;
 	}
-	pSize->nRatesInUse = l;
+	pMonitor->nModesInUse = modeid;
     }
-    pScrPriv->nSizesInUse = j;
+    pScrPriv->nMonitorsInUse = n;
     if (changed)
     {
 	UpdateCurrentTime ();
@@ -1241,6 +1317,7 @@ RRRegisterSize (ScreenPtr	    pScreen,
     if (!pScrPriv)
 	return 0;
     
+    tmp.id = -1;
     tmp.width = width;
     tmp.height= height;
     tmp.mmWidth = mmWidth;
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 27ab61a..07c6c37 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -1,24 +1,28 @@
 /*
- *
  * 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
@@ -28,56 +32,83 @@
 #ifndef _RANDRSTR_H_
 #define _RANDRSTR_H_
 
-#include <X11/extensions/randr.h>
+#include <X11/extensions/randrproto.h>
 
-typedef struct _rrScreenRate {
-    int		    rate;
+typedef struct _rrMode {
+    struct _rrMode  *next;
+    int		    id;
     Bool	    referenced;
     Bool	    oldReferenced;
-} RRScreenRate, *RRScreenRatePtr;
+    xRRMonitorMode  mode;
+} RRMode, *RRModePtr;
 
-typedef struct _rrScreenSize {
-    int		    id;
-    short	    width, height;
-    short	    mmWidth, mmHeight;
-    RRScreenRatePtr pRates;
-    int		    nRates;
-    int		    nRatesInUse;
+typedef struct _rrMonitor {
+    struct _rrMonitor	*next;
+    ScreenPtr	    pScreen;
+    RRModePtr	    pModes;
+    void	    *identifier;    /* made unique by DDX */
     Bool	    referenced;
-    Bool	    oldReferenced;
-} RRScreenSize, *RRScreenSizePtr;
+    
+    /*
+     * Current state
+     */
+    int		    mode;
+    int		    x, y;
+    Rotation	    rotation;
+} RRMonitor, *RRMonitorPtr;
+
+typedef Bool (*RRSetScreenSizeProcPtr) (ScreenPtr	pScreen,
+					CARD16		width,
+					CARD16		height,
+					CARD32		widthInMM,
+					CARD32		heightInMM);
+					
+typedef Bool (*RRSetModeProcPtr) (ScreenPtr		pScreen,
+				  int			monitor,
+				  RRModePtr		pMode,
+				  int			x,
+				  int			y,
+				  Rotation		rotation);
+
+typedef Bool (*RRGetInfoProcPtr) (ScreenPtr pScreen, Rotation *rotations);
+typedef Bool (*RRCloseScreenProcPtr) ( int i, ScreenPtr pscreen);
+
+
+#ifdef RANDR_SCREEN_INTERFACE
+
+typedef void *RRScreenSizePtr;
 
 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 {
-    RRSetConfigProcPtr	    rrSetConfig;
+    RRSetModeProcPtr	    rrSetMode;
     RRGetInfoProcPtr	    rrGetInfo;
+    RRCloseScreenProcPtr    CloseScreen;
     
     TimeStamp		    lastSetTime;	/* last changed by client */
     TimeStamp		    lastConfigTime;	/* possible configs changed */
-    RRCloseScreenProcPtr    CloseScreen;
 
     /*
+     * monitor data
+     */
+    RRMonitorPtr	    pMonitors;
+
+#ifdef RANDR_SCREEN_INTERFACE
+    /*
      * Configuration information
      */
     Rotation		    rotations;
     
-    int			    nSizes;
-    int			    nSizesInUse;
-    RRScreenSizePtr	    pSizes;
+    RRSetConfigProcPtr	    rrSetConfig;
 
-    /*
-     * Current state
-     */
     Rotation		    rotation;
-    int			    size;
-    int			    rate;
+#endif
 } rrScrPrivRec, *rrScrPrivPtr;
 
 extern int rrPrivIndex;
@@ -91,6 +122,60 @@ void
 RRExtensionInit (void);
 
 /*
+ * Then, register a monitor with the screen
+ */
+
+RRMonitorPtr
+RRRegisterMonitor (ScreenPtr		pScreen,
+		   void			*identifier,
+		   Rotation		rotations);
+
+/*
+ * Next, register the list of modes with the monitor
+ */
+
+RRModePtr
+RRRegisterMode (RRMonitorPtr	pMonitor,
+		xRRMonitorMode	*pMode,
+		char		*name,
+		int		nameLength);
+
+/*
+ * Finally, set the current configuration of each monitor
+ */
+
+void
+RRSetCurrentMode (RRMonitorPtr	pMonitor,
+		  RRModePtr	pMode,
+		  Rotation	rotation);
+
+Bool RRScreenInit(ScreenPtr pScreen);
+
+Rotation
+RRGetRotation (ScreenPtr pScreen);
+
+Bool
+miRandRInit (ScreenPtr pScreen);
+
+Bool
+miRRGetInfo (ScreenPtr pScreen, Rotation *rotations);
+
+Bool
+miRRGetScreenInfo (ScreenPtr pScreen);
+
+Bool
+miRRSetMode (ScreenPtr	pScreen,
+	     int	monitor,
+	     RRModePtr	pMode,
+	     Rotation	rotation);
+
+#ifdef RANDR_SCREEN_INTERFACE					
+/*
+ * This is the old interface, deprecated but left
+ * around for compatibility
+ */
+
+/*
  * Then, register the specific size with the screen
  */
 
@@ -105,6 +190,9 @@ Bool RRRegisterRate (ScreenPtr		pScreen,
 		     RRScreenSizePtr	pSize,
 		     int		rate);
 
+Bool RRRegisterRotation (ScreenPtr	pScreen,
+			 Rotation	rotation);
+
 /*
  * Finally, set the current configuration of the screen
  */
@@ -115,11 +203,6 @@ RRSetCurrentConfig (ScreenPtr		pScreen,
 		    int			rate,
 		    RRScreenSizePtr	pSize);
 
-Bool RRScreenInit(ScreenPtr pScreen);
-
-Rotation
-RRGetRotation (ScreenPtr pScreen);
-
 int
 RRSetScreenConfig (ScreenPtr		pScreen,
 		   Rotation		rotation,
@@ -127,18 +210,10 @@ RRSetScreenConfig (ScreenPtr		pScreen,
 		   RRScreenSizePtr	pSize);
 
 Bool
-miRandRInit (ScreenPtr pScreen);
-
-Bool
-miRRGetInfo (ScreenPtr pScreen, Rotation *rotations);
-
-Bool
 miRRSetConfig (ScreenPtr	pScreen,
 	       Rotation		rotation,
 	       int		rate,
 	       RRScreenSizePtr	size);
 
-Bool
-miRRGetScreenInfo (ScreenPtr pScreen);
-
+#endif					
 #endif /* _RANDRSTR_H_ */



More information about the xorg-commit mailing list