[Xquartz-changes] xserver: Branch 'server-1.9-apple' - 33 commits

Jeremy Huddleston jeremyhu at freedesktop.org
Thu Aug 12 23:27:30 PDT 2010


Rebased ref, commits from common ancestor:
commit 58b269bf7443cb616ce12f4c193c8f3c5a6591e4
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Fri Feb 12 19:48:52 2010 -0800

    fb: Revert fb changes that broke XQuartz
    
    http://bugs.freedesktop.org/show_bug.cgi?id=26124
    
    Revert "Fix source pictures getting random transforms after 2d6a8f668342a5190cdf43b5."
    Revert "fb: Adjust transform or composite coordinates for pixman operations"
    
    http://bugs.freedesktop.org/26124
    
    This reverts commit a72c65e9176c51de95db2fdbf4c5d946a4911695.
    This reverts commit a6bd5d2e482a5aa84acb3d4932e2a166d8670ef1.
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/fb/fb.h b/fb/fb.h
index a06f98b..3b9efea 100644
--- a/fb/fb.h
+++ b/fb/fb.h
@@ -2080,11 +2080,8 @@ fbFillRegionSolid (DrawablePtr	pDrawable,
 		   FbBits	xor);
 
 extern _X_EXPORT pixman_image_t *
-image_from_pict (PicturePtr	pict,
-		 Bool		has_clip,
-		 int		*xoff,
-		 int		*yoff);
-
+image_from_pict (PicturePtr pict,
+		 Bool       has_clip);
 extern _X_EXPORT void free_pixman_pict (PicturePtr, pixman_image_t *);
 
 #endif /* _FB_H_ */
diff --git a/fb/fbpict.c b/fb/fbpict.c
index f7f1200..5467ee4 100644
--- a/fb/fbpict.c
+++ b/fb/fbpict.c
@@ -156,24 +156,19 @@ fbComposite (CARD8      op,
 	     CARD16     height)
 {
     pixman_image_t *src, *mask, *dest;
-    int src_xoff, src_yoff;
-    int msk_xoff, msk_yoff;
-    int dst_xoff, dst_yoff;
     
     miCompositeSourceValidate (pSrc, xSrc - xDst, ySrc - yDst, width, height);
     if (pMask)
 	miCompositeSourceValidate (pMask, xMask - xDst, yMask - yDst, width, height);
     
-    src = image_from_pict (pSrc, FALSE, &src_xoff, &src_yoff);
-    mask = image_from_pict (pMask, FALSE, &msk_xoff, &msk_yoff);
-    dest = image_from_pict (pDst, TRUE, &dst_xoff, &dst_yoff);
+    src = image_from_pict (pSrc, TRUE);
+    mask = image_from_pict (pMask, TRUE);
+    dest = image_from_pict (pDst, TRUE);
 
     if (src && dest && !(pMask && !mask))
     {
 	pixman_image_composite (op, src, mask, dest,
-				xSrc + src_xoff, ySrc + src_yoff,
-				xMask + msk_xoff, yMask + msk_yoff,
-				xDst + dst_xoff, yDst + dst_yoff,
+				xSrc, ySrc, xMask, yMask, xDst, yDst,
 				width, height);
     }
 
@@ -271,22 +266,22 @@ create_conical_gradient_image (PictGradient *gradient)
 
 static pixman_image_t *
 create_bits_picture (PicturePtr pict,
-		     Bool       has_clip,
-		     int	*xoff,
-		     int	*yoff)
+		     Bool       has_clip)
 {
-    PixmapPtr pixmap;
     FbBits *bits;
     FbStride stride;
-    int bpp;
+    int bpp, xoff, yoff;
     pixman_image_t *image;
     
-    fbGetDrawablePixmap (pict->pDrawable, pixmap, *xoff, *yoff);
-    fbGetPixmapBitsData(pixmap, bits, stride, bpp);
+    fbGetDrawable (pict->pDrawable, bits, stride, bpp, xoff, yoff);
+
+    bits = (FbBits*)((CARD8*)bits +
+		     (pict->pDrawable->y + yoff) * stride * sizeof(FbBits) +
+		     (pict->pDrawable->x + xoff) * (bpp / 8));
 
     image = pixman_image_create_bits (
 	pict->format,
-	pixmap->drawable.width, pixmap->drawable.height,
+	pict->pDrawable->width, pict->pDrawable->height,
 	(uint32_t *)bits, stride * sizeof (FbStride));
     
     
@@ -312,55 +307,33 @@ create_bits_picture (PicturePtr pict,
 	if (pict->clientClipType != CT_NONE)
 	    pixman_image_set_has_client_clip (image, TRUE);
 
-	if (*xoff || *yoff)
-	    pixman_region_translate (pict->pCompositeClip, *xoff, *yoff);
+	pixman_region_translate (pict->pCompositeClip, - pict->pDrawable->x, - pict->pDrawable->y);
 
 	pixman_image_set_clip_region (image, pict->pCompositeClip);
 
-	if (*xoff || *yoff)
-	    pixman_region_translate (pict->pCompositeClip, -*xoff, -*yoff);
+	pixman_region_translate (pict->pCompositeClip, pict->pDrawable->x, pict->pDrawable->y);
     }
     
     /* Indexed table */
     if (pict->pFormat->index.devPrivate)
 	pixman_image_set_indexed (image, pict->pFormat->index.devPrivate);
 
-    /* Add in drawable origin to position within the image */
-    *xoff += pict->pDrawable->x;
-    *yoff += pict->pDrawable->y;
-
     return image;
 }
 
 static pixman_image_t *
-image_from_pict_internal (PicturePtr pict, Bool has_clip, int *xoff, int *yoff, Bool is_alpha_map);
+image_from_pict_internal (PicturePtr pict, Bool has_clip, Bool is_alpha_map);
 
 static void
-set_image_properties (pixman_image_t *image, PicturePtr pict, Bool has_clip, int *xoff, int *yoff, Bool is_alpha_map)
+set_image_properties (pixman_image_t *image, PicturePtr pict, Bool is_alpha_map)
 {
     pixman_repeat_t repeat;
     pixman_filter_t filter;
     
     if (pict->transform)
     {
-	/* For source images, adjust the transform to account
-	 * for the drawable offset within the pixman image,
-	 * then set the offset to 0 as it will be used
-	 * to compute positions within the transformed image.
-	 */
-	if (!has_clip) {
-	    struct pixman_transform	adjusted;
-
-	    adjusted = *pict->transform;
-	    pixman_transform_translate(&adjusted,
-				       NULL,
-				       pixman_int_to_fixed(*xoff),
-				       pixman_int_to_fixed(*yoff));
-	    pixman_image_set_transform (image, &adjusted);
-	    *xoff = 0;
-	    *yoff = 0;
-	} else
-	    pixman_image_set_transform (image, pict->transform);
+	pixman_image_set_transform (
+	    image, (pixman_transform_t *)pict->transform);
     }
     
     switch (pict->repeatType)
@@ -390,8 +363,7 @@ set_image_properties (pixman_image_t *image, PicturePtr pict, Bool has_clip, int
      */
     if (pict->alphaMap && !is_alpha_map)
     {
-	int alpha_xoff, alpha_yoff;
-	pixman_image_t *alpha_map = image_from_pict_internal (pict->alphaMap, FALSE, &alpha_xoff, &alpha_yoff, TRUE);
+	pixman_image_t *alpha_map = image_from_pict_internal (pict->alphaMap, TRUE, TRUE);
 	
 	pixman_image_set_alpha_map (
 	    image, alpha_map, pict->alphaOrigin.x, pict->alphaOrigin.y);
@@ -424,7 +396,8 @@ set_image_properties (pixman_image_t *image, PicturePtr pict, Bool has_clip, int
 }
 
 static pixman_image_t *
-image_from_pict_internal (PicturePtr pict, Bool has_clip, int *xoff, int *yoff, Bool is_alpha_map)
+image_from_pict_internal (PicturePtr pict,
+		 Bool has_clip, Bool is_alpha_map)
 {
     pixman_image_t *image = NULL;
 
@@ -433,7 +406,7 @@ image_from_pict_internal (PicturePtr pict, Bool has_clip, int *xoff, int *yoff,
 
     if (pict->pDrawable)
     {
-	image = create_bits_picture (pict, has_clip, xoff, yoff);
+	image = create_bits_picture (pict, has_clip);
     }
     else if (pict->pSourcePict)
     {
@@ -454,19 +427,18 @@ image_from_pict_internal (PicturePtr pict, Bool has_clip, int *xoff, int *yoff,
 	    else if (sp->type == SourcePictTypeConical)
 		image = create_conical_gradient_image (gradient);
 	}
-	*xoff = *yoff = 0;
     }
     
     if (image)
-	set_image_properties (image, pict, has_clip, xoff, yoff, is_alpha_map);
+	set_image_properties (image, pict, is_alpha_map);
     
     return image;
 }
 
 pixman_image_t *
-image_from_pict (PicturePtr pict, Bool has_clip, int *xoff, int *yoff)
+image_from_pict (PicturePtr pict, Bool has_clip)
 {
-    return image_from_pict_internal (pict, has_clip, xoff, yoff, FALSE);
+    return image_from_pict_internal (pict, has_clip, FALSE);
 }
 
 void
diff --git a/fb/fbtrap.c b/fb/fbtrap.c
index 9f5c39f..9c55236 100644
--- a/fb/fbtrap.c
+++ b/fb/fbtrap.c
@@ -38,8 +38,7 @@ fbAddTraps (PicturePtr	pPicture,
 	    int		ntrap,
 	    xTrap	*traps)
 {
-    int image_xoff, image_yoff;
-    pixman_image_t *image = image_from_pict (pPicture, FALSE, &image_xoff, &image_yoff);
+    pixman_image_t *image = image_from_pict (pPicture, FALSE);
 
     if (!image)
 	return;
@@ -55,8 +54,7 @@ fbRasterizeTrapezoid (PicturePtr    pPicture,
 		      int	    x_off,
 		      int	    y_off)
 {
-    int	mask_xoff, mask_yoff;
-    pixman_image_t *image = image_from_pict (pPicture, FALSE, &mask_xoff, &mask_yoff);
+    pixman_image_t *image = image_from_pict (pPicture, FALSE);
 
     if (!image)
 	return;
commit d29824e984ee4bca5f5761d2ebedb83e048604c3
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Fri Apr 30 13:08:25 2010 -0700

    Workaround the GC clipping problem in miPaintWindow and add some debugging output.
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/mi/miexpose.c b/mi/miexpose.c
index 94258b8..4f25c23 100644
--- a/mi/miexpose.c
+++ b/mi/miexpose.c
@@ -521,6 +521,7 @@ void RootlessSetPixmapOfAncestors(WindowPtr pWin);
 void RootlessStartDrawing(WindowPtr pWin);
 void RootlessDamageRegion(WindowPtr pWin, RegionPtr prgn);
 Bool IsFramedWindow(WindowPtr pWin);
+#include "../fb/fb.h"
 #endif 
 
 void
@@ -548,24 +549,37 @@ miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
     Bool	solid = TRUE;
     DrawablePtr	drawable = &pWin->drawable;
 
+#ifdef XQUARTZ_CLIP_DEBUG
+    ErrorF("START %d BS %d (pR = %ld)\n", what, pWin->backgroundState, ParentRelative);
+    ErrorF("      Rgn: %d %d %d %d\n", prgn->extents.x1, prgn->extents.y1,
+	                               prgn->extents.x2 - prgn->extents.x1,
+	                               prgn->extents.y2 - prgn->extents.y1);
+    ErrorF("      Win: %d %d (%d %d) %d %d\n", pWin->origin.x, pWin->origin.y,
+	                                       pWin->winSize.extents.x1, pWin->winSize.extents.y1,
+	                                       pWin->winSize.extents.x2 - pWin->winSize.extents.x1,
+					       pWin->winSize.extents.y2 - pWin->winSize.extents.y1);
+    ErrorF("     Draw: %d %d %d %d\n", pWin->drawable.x, pWin->drawable.y,
+				       pWin->drawable.width, pWin->drawable.height);
+#endif
+
 #ifdef ROOTLESS
     if(!drawable || drawable->type == UNDRAWABLE_WINDOW)
 	return;
-
-    if(IsFramedWindow(pWin)) {
-        RootlessStartDrawing(pWin);
-        RootlessDamageRegion(pWin, prgn);
-    
-        if(pWin->backgroundState == ParentRelative) {
-            if((what == PW_BACKGROUND) || 
-               (what == PW_BORDER && !pWin->borderIsPixel))
-                RootlessSetPixmapOfAncestors(pWin);
-        }
-    }
 #endif
     
     if (what == PW_BACKGROUND)
     {
+#ifdef ROOTLESS
+	if(IsFramedWindow(pWin)) {
+	    RootlessStartDrawing(pWin);
+	    RootlessDamageRegion(pWin, prgn);
+
+	    if(pWin->backgroundState == ParentRelative) {
+		RootlessSetPixmapOfAncestors(pWin);
+	    }
+	}
+#endif
+
 	while (pWin->backgroundState == ParentRelative)
 	    pWin = pWin->parent;
 
@@ -587,6 +601,18 @@ miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
     {
 	PixmapPtr   pixmap;
 
+#ifdef ROOTLESS
+	if(IsFramedWindow(pWin)) {
+	    RootlessStartDrawing(pWin);
+	    RootlessDamageRegion(pWin, prgn);
+	    
+	    if(!pWin->borderIsPixel &&
+		pWin->backgroundState == ParentRelative) {
+		RootlessSetPixmapOfAncestors(pWin);
+	    }
+	}
+#endif
+
 	tile_x_off = drawable->x;
 	tile_y_off = drawable->y;
 	
@@ -595,6 +621,12 @@ miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
 	    return;
 	pixmap = (*pScreen->GetWindowPixmap) ((WindowPtr) drawable);
 	drawable = &pixmap->drawable;
+
+#ifdef XQUARTZ_CLIP_DEBUG
+	ErrorF("     Draw: %d %d %d %d\n",
+	       drawable->x, drawable->y, drawable->width, drawable->height);    
+#endif
+	
 #ifdef COMPOSITE
 	draw_x_off = pixmap->screen_x;
 	draw_y_off = pixmap->screen_y;
@@ -657,6 +689,57 @@ miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
     ChangeGC (NullClient, pGC, gcmask, gcval);
     ValidateGC (drawable, pGC);
 
+#ifdef XQUARTZ_CLIP_DEBUG
+    ErrorF("       GC: %d %d %d %d\n",
+	   pGC->pCompositeClip->extents.x1, pGC->pCompositeClip->extents.y1,
+	   pGC->pCompositeClip->extents.x2 - pGC->pCompositeClip->extents.x1,
+	   pGC->pCompositeClip->extents.y2 - pGC->pCompositeClip->extents.y1);
+#endif
+    
+#ifdef XQUARTZ
+    /* Looks like our clipping isn't set right for some reason:
+     * http://xquartz.macosforge.org/trac/ticket/290
+     */
+    if(what == PW_BORDER) {
+
+#if 0
+	if(solid) {
+#if 1
+	    fbFillRegionSolid(&pWin->drawable,
+			      prgn,
+			      0,
+			      fbReplicatePixel(fill.pixel,
+					       pWin->drawable.bitsPerPixel));
+#else
+	    fbFillRegionSolid(drawable,
+			      prgn,
+			      0,
+			      fbReplicatePixel(fill.pixel,
+					       drawable->bitsPerPixel));
+#endif
+	    return;
+	}
+#endif
+    
+	pGC->pCompositeClip->extents.x1 += prgn->extents.x1;
+	pGC->pCompositeClip->extents.y1 += prgn->extents.y1;
+	pGC->pCompositeClip->extents.x2 += prgn->extents.x1;
+	pGC->pCompositeClip->extents.y2 += prgn->extents.y1;
+	
+	if(pGC->pCompositeClip->extents.x2 > drawable->pScreen->width)
+	    pGC->pCompositeClip->extents.x2 = drawable->pScreen->width;
+	if(pGC->pCompositeClip->extents.y2 > drawable->pScreen->height)
+	    pGC->pCompositeClip->extents.y2 = drawable->pScreen->height;
+    }
+#endif
+
+#ifdef XQUARTZ_CLIP_DEBUG
+    ErrorF("       GC: %d %d %d %d\n",
+	   pGC->pCompositeClip->extents.x1, pGC->pCompositeClip->extents.y1,
+	   pGC->pCompositeClip->extents.x2 - pGC->pCompositeClip->extents.x1,
+	   pGC->pCompositeClip->extents.y2 - pGC->pCompositeClip->extents.y1);    
+#endif
+
     numRects = RegionNumRects(prgn);
     pbox = RegionRects(prgn);
     for (i= numRects; --i >= 0; pbox++, prect++)
commit 4fa0b305404517854efbc1ed48e8f0b806ad91f8
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Tue Aug 3 12:51:51 2010 -0700

    XQuartz: RandR: Refactor legacy mode-switching to be better integrated with RandR
    
    Adds three new functions
    void QuartzRandRSetFakeRootless (void);
    void QuartzRandRSetFakeFullscreen (void);
    void QuartzRandRToggleFullscreen (void);
    
    The first two are identical to requesting the fake modes from a RandR client
    The third responds to cmd-alt-a to leave fullscreen or RandR.
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/hw/xquartz/X11Application.m b/hw/xquartz/X11Application.m
index 781dccc..8f4f23f 100644
--- a/hw/xquartz/X11Application.m
+++ b/hw/xquartz/X11Application.m
@@ -370,7 +370,7 @@ static void message_kit_thread (SEL selector, NSObject *arg) {
                     break;
                     
                 case 18: /* ApplicationDidReactivate */
-                    if (XQuartzHasRoot) for_appkit = NO;
+                    if (XQuartzFullscreenVisible) for_appkit = NO;
                     break;
                     
                 case NSApplicationDeactivatedEventType:
diff --git a/hw/xquartz/darwinEvents.c b/hw/xquartz/darwinEvents.c
index 4332202..74fadf4 100644
--- a/hw/xquartz/darwinEvents.c
+++ b/hw/xquartz/darwinEvents.c
@@ -241,17 +241,17 @@ static void DarwinEventHandler(int screenNum, InternalEvent *ie, DeviceIntPtr de
             DEBUG_LOG("kXquartzToggleFullscreen\n");
             if(XQuartzIsRootless)
                 ErrorF("Ignoring kXquartzToggleFullscreen because of rootless mode.");
-            else if (XQuartzHasRoot)
-                QuartzHide();
-            else
-                QuartzShow();
+            else 
+                QuartzRandRToggleFullscreen();
             break;
             
         case kXquartzSetRootless:
             DEBUG_LOG("kXquartzSetRootless\n");
-            QuartzSetRootless(e->data[0]);
-            if (!XQuartzIsRootless && !XQuartzHasRoot)
-                QuartzHide();
+            if(e->data[0]) {
+                QuartzRandRSetFakeRootless();
+            } else {
+                QuartzRandRSetFakeFullscreen(FALSE);
+            }
             break;
             
         case kXquartzSetRootClip:
diff --git a/hw/xquartz/quartz.c b/hw/xquartz/quartz.c
index cd90457..e21303c 100644
--- a/hw/xquartz/quartz.c
+++ b/hw/xquartz/quartz.c
@@ -74,7 +74,7 @@ const char             *quartzOpenGLBundle = NULL;
 Bool XQuartzFullscreenDisableHotkeys = TRUE;
 Bool XQuartzOptionSendsAlt = FALSE;
 Bool XQuartzEnableKeyEquivalents = TRUE;
-Bool XQuartzHasRoot = FALSE;
+Bool XQuartzFullscreenVisible = FALSE;
 Bool XQuartzRootlessDefault = TRUE;
 Bool XQuartzIsRootless = TRUE;
 Bool XQuartzServerVisible = FALSE;
@@ -246,44 +246,58 @@ void QuartzUpdateScreens(void) {
     quartzProcs->UpdateScreen(pScreen);
 }
 
-void QuartzSetFullscreen(Bool state) {
+void QuartzShowFullscreen(int state) {
+    int i;
+    
+    DEBUG_LOG("QuartzShowFullscreen: state=%d\n", state);
     
-    DEBUG_LOG("QuartzSetFullscreen: state=%d\n", state);
+    if(XQuartzIsRootless) {
+        ErrorF("QuartzShowFullscreen called while in rootless mode.\n");
+        return;
+    }
     
-    if(XQuartzHasRoot == state)
+    if(XQuartzFullscreenVisible == state)
         return;
     
-    XQuartzHasRoot = state;
+    XQuartzFullscreenVisible = state;
     
     xp_disable_update ();
     
-    if (!XQuartzHasRoot && !XQuartzIsRootless)
+    if (!XQuartzFullscreenVisible)
         RootlessHideAllWindows();
     
-    RootlessUpdateRooted(XQuartzHasRoot);
+    RootlessUpdateRooted(XQuartzFullscreenVisible);
     
-    if (XQuartzHasRoot && !XQuartzIsRootless)
+    if (XQuartzFullscreenVisible) {
         RootlessShowAllWindows ();
-    
-    if (XQuartzHasRoot || XQuartzIsRootless) {
-        RootlessRepositionWindows(screenInfo.screens[0]);
+        for (i=0; i < screenInfo.numScreens; i++) {
+            ScreenPtr pScreen = screenInfo.screens[i];        
+            RootlessRepositionWindows(pScreen);
+            // JH: I don't think this is necessary, but keeping it here as a reminder
+            //RootlessUpdateScreenPixmap(pScreen);
+        }
     }
 
     /* Somehow the menubar manages to interfere with our event stream
      * in fullscreen mode, even though it's not visible. 
      */
-    X11ApplicationShowHideMenubar(!XQuartzHasRoot);
+    X11ApplicationShowHideMenubar(!XQuartzFullscreenVisible);
     
     xp_reenable_update ();
     
     if (XQuartzFullscreenDisableHotkeys)
-        xp_disable_hot_keys(XQuartzHasRoot);
+        xp_disable_hot_keys(XQuartzFullscreenVisible);
 }
 
-void QuartzSetRootless(Bool state) {
+void QuartzSetRootless(Bool state) {    
+    DEBUG_LOG("QuartzSetRootless state=%d\n", state);
+    
     if(XQuartzIsRootless == state)
         return;
     
+    if(state)
+        QuartzShowFullscreen(FALSE);
+    
     XQuartzIsRootless = state;
 
     xp_disable_update();
@@ -291,20 +305,17 @@ void QuartzSetRootless(Bool state) {
     /* When in rootless, the menubar is not part of the screen, so we need to update our screens on toggle */    
     QuartzUpdateScreens();
 
-    if(!XQuartzHasRoot) {
-        if(!XQuartzIsRootless) {
-            RootlessHideAllWindows();
-        } else {
-            RootlessShowAllWindows();
-        }
+    if(XQuartzIsRootless) {
+        RootlessShowAllWindows();
+    } else {
+        RootlessHideAllWindows();
     }
 
-    X11ApplicationShowHideMenubar(!XQuartzHasRoot);
+    X11ApplicationShowHideMenubar(TRUE);
 
     xp_reenable_update();
 
-    if (!XQuartzIsRootless && XQuartzFullscreenDisableHotkeys)
-        xp_disable_hot_keys(XQuartzHasRoot);
+    xp_disable_hot_keys(FALSE);
 }
 
 /*
@@ -327,7 +338,7 @@ void QuartzShow(void) {
     }
     
     if (!XQuartzIsRootless)
-        QuartzSetFullscreen(TRUE);
+        QuartzShowFullscreen(TRUE);
 }
 
 
@@ -348,8 +359,9 @@ void QuartzHide(void)
             }
         }
     }
-    
-    QuartzSetFullscreen(FALSE);
+
+    if(!XQuartzIsRootless)
+        QuartzShowFullscreen(FALSE);
     XQuartzServerVisible = FALSE;
 }
 
diff --git a/hw/xquartz/quartz.h b/hw/xquartz/quartz.h
index a0a17cb..7efb7e0 100644
--- a/hw/xquartz/quartz.h
+++ b/hw/xquartz/quartz.h
@@ -115,12 +115,8 @@ typedef struct _QuartzModeProcs {
 
 extern QuartzModeProcsPtr quartzProcs;
 
-extern Bool XQuartzHasRoot;          /* TODO: These two booleans are very similar and */
-extern Bool XQuartzServerVisible;    /* the code that uses them needs to be refactored
-                                      * XQuartzHasRoot is essentially the "saved" XQuartzServerVisible
-                                      * value from when the server was not in rootless mode.
-                                      */
-
+extern Bool XQuartzFullscreenVisible; /* Are the windows visible (predicated on !rootless) */
+extern Bool XQuartzServerVisible;     /* Is the server visible ... TODO: Refactor to "active" */
 extern Bool XQuartzEnableKeyEquivalents;
 extern Bool XQuartzRootlessDefault;  /* Is our default mode rootless? */
 extern Bool XQuartzIsRootless;       /* Is our current mode rootless (or FS)? */
@@ -144,7 +140,7 @@ void QuartzSetRootClip(BOOL enable);
 void QuartzSpaceChanged(uint32_t space_id);
 
 void QuartzSetRootless(Bool state);
-void QuartzSetFullscreen(Bool state);
+void QuartzShowFullscreen(Bool state);
 
 int server_main(int argc, char **argv, char **envp);
 #endif
diff --git a/hw/xquartz/quartzRandR.c b/hw/xquartz/quartzRandR.c
index 7534267..586d299 100644
--- a/hw/xquartz/quartzRandR.c
+++ b/hw/xquartz/quartzRandR.c
@@ -62,7 +62,7 @@ static Bool ignore_next_fake_mode_update = FALSE;
 #define CALLBACK_ERROR -1
 
 typedef int (*QuartzModeCallback)
-    (ScreenPtr, CGDirectDisplayID, QuartzModeInfoPtr, void *);
+    (ScreenPtr, QuartzModeInfoPtr, void *);
 
 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
 
@@ -98,6 +98,7 @@ static void QuartzRandRGetModeInfo (CFDictionaryRef modeRef,
     if (pMode->refresh == 0)
         pMode->refresh = DEFAULT_REFRESH;
     pMode->ref = NULL;
+    pMode->pSize = NULL;
 }
 
 static Bool QuartzRandRCopyCurrentModeInfo (CGDirectDisplayID screenId,
@@ -112,14 +113,13 @@ static Bool QuartzRandRCopyCurrentModeInfo (CGDirectDisplayID screenId,
     return TRUE;
 }
 
-static Bool QuartzRandRSetMode (CGDirectDisplayID screenId,
+static Bool QuartzRandRSetCGMode (CGDirectDisplayID screenId,
                                 QuartzModeInfoPtr pMode) {
     CFDictionaryRef modeRef = (CFDictionaryRef) pMode->ref;
     return (CGDisplaySwitchToMode(screenId, modeRef) == kCGErrorSuccess);
 }
 
 static Bool QuartzRandREnumerateModes (ScreenPtr pScreen,
-                                       CGDirectDisplayID screenId,
                                        QuartzModeCallback callback,
                                        void *data) {
     CFDictionaryRef curModeRef, modeRef;
@@ -129,8 +129,9 @@ static Bool QuartzRandREnumerateModes (ScreenPtr pScreen,
     int i;
     BOOL retval = FALSE;
     QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
+    CGDirectDisplayID screenId = pQuartzScreen->displayIDs[0];
 
-    switch(callback(pScreen, screenId, &pQuartzScreen->rootlessMode, data)) {
+    switch(callback(pScreen, &pQuartzScreen->rootlessMode, data)) {
         case CALLBACK_SUCCESS:
             return TRUE;
         case CALLBACK_ERROR:
@@ -140,7 +141,7 @@ static Bool QuartzRandREnumerateModes (ScreenPtr pScreen,
             break;
     }
 
-    switch(callback(pScreen, screenId, &pQuartzScreen->fullscreenMode, data)) {
+    switch(callback(pScreen, &pQuartzScreen->fullscreenMode, data)) {
         case CALLBACK_SUCCESS:
             return TRUE;
         case CALLBACK_ERROR:
@@ -172,7 +173,7 @@ static Bool QuartzRandREnumerateModes (ScreenPtr pScreen,
 
         QuartzRandRGetModeInfo(modeRef, &modeInfo);
         modeInfo.ref = modeRef;
-        cb = callback(pScreen, screenId, &modeInfo, data);
+        cb = callback(pScreen, &modeInfo, data);
         if (cb == CALLBACK_SUCCESS)
             break;
         if (cb == CALLBACK_ERROR) {
@@ -193,6 +194,7 @@ static void QuartzRandRGetModeInfo (CGDisplayModeRef modeRef,
     if (pMode->refresh == 0)
         pMode->refresh = DEFAULT_REFRESH;
     pMode->ref = NULL;
+    pMode->pSize = NULL;
 }
 
 static Bool QuartzRandRCopyCurrentModeInfo (CGDirectDisplayID screenId,
@@ -206,7 +208,7 @@ static Bool QuartzRandRCopyCurrentModeInfo (CGDirectDisplayID screenId,
     return TRUE;
 }
 
-static Bool QuartzRandRSetMode (CGDirectDisplayID screenId,
+static Bool QuartzRandRSetCGMode (CGDirectDisplayID screenId,
                                 QuartzModeInfoPtr pMode) {
     CGDisplayModeRef modeRef = (CGDisplayModeRef) pMode->ref;
     if (!modeRef)
@@ -216,7 +218,6 @@ static Bool QuartzRandRSetMode (CGDirectDisplayID screenId,
 }
 
 static Bool QuartzRandREnumerateModes (ScreenPtr pScreen,
-                                       CGDirectDisplayID screenId,
                                        QuartzModeCallback callback,
                                        void *data) {
     CGDisplayModeRef curModeRef, modeRef;
@@ -228,8 +229,9 @@ static Bool QuartzRandREnumerateModes (ScreenPtr pScreen,
     Bool retval = TRUE;
 
     QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
+    CGDirectDisplayID screenId = pQuartzScreen->displayIDs[0];
 
-    switch(callback(pScreen, screenId, &pQuartzScreen->rootlessMode, data)) {
+    switch(callback(pScreen, &pQuartzScreen->rootlessMode, data)) {
         case CALLBACK_SUCCESS:
             return TRUE;
         case CALLBACK_ERROR:
@@ -239,7 +241,7 @@ static Bool QuartzRandREnumerateModes (ScreenPtr pScreen,
             break;
     }
 
-    switch(callback(pScreen, screenId, &pQuartzScreen->fullscreenMode, data)) {
+    switch(callback(pScreen, &pQuartzScreen->fullscreenMode, data)) {
         case CALLBACK_SUCCESS:
             return TRUE;
         case CALLBACK_ERROR:
@@ -277,7 +279,7 @@ static Bool QuartzRandREnumerateModes (ScreenPtr pScreen,
 
         QuartzRandRGetModeInfo(modeRef, &modeInfo);
         modeInfo.ref = modeRef;
-        cb = callback(pScreen, screenId, &modeInfo, data);
+        cb = callback(pScreen, &modeInfo, data);
         if (cb == CALLBACK_SUCCESS)
             break;
 		if (cb == CALLBACK_ERROR) {
@@ -306,14 +308,15 @@ static Bool QuartzRandRRegisterMode (ScreenPtr pScreen,
                                      QuartzModeInfoPtr pMode) {
     QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
     Bool isCurrentMode = QuartzRandRModesEqual(&pQuartzScreen->currentMode, pMode);
-    RRScreenSizePtr pSize = RRRegisterSize(pScreen,
-        pMode->width, pMode->height, pScreen->mmWidth, pScreen->mmHeight);
-    if (pSize) {
+
+    /* TODO: DPI */
+    pMode->pSize = RRRegisterSize(pScreen, pMode->width, pMode->height, pScreen->mmWidth, pScreen->mmHeight);
+    if (pMode->pSize) {
         //DEBUG_LOG("registering: %d x %d @ %d %s\n", (int)pMode->width, (int)pMode->height, (int)pMode->refresh, isCurrentMode ? "*" : "");
-        RRRegisterRate(pScreen, pSize, pMode->refresh);
+        RRRegisterRate(pScreen, pMode->pSize, pMode->refresh);
 
         if (isCurrentMode)
-            RRSetCurrentConfig(pScreen, RR_Rotate_0, pMode->refresh, pSize);
+            RRSetCurrentConfig(pScreen, RR_Rotate_0, pMode->refresh, pMode->pSize);
 
         return TRUE;
     }
@@ -321,7 +324,6 @@ static Bool QuartzRandRRegisterMode (ScreenPtr pScreen,
 }
 
 static int QuartzRandRRegisterModeCallback (ScreenPtr pScreen,
-                                        CGDirectDisplayID screenId,
                                         QuartzModeInfoPtr pMode,
                                         void *data __unused) {
     if(QuartzRandRRegisterMode(pScreen, pMode)) {
@@ -331,40 +333,53 @@ static int QuartzRandRRegisterModeCallback (ScreenPtr pScreen,
     }
 }
 
+static Bool QuartzRandRSetMode(ScreenPtr pScreen, QuartzModeInfoPtr pMode, BOOL doRegister) {
+    QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
+    CGDirectDisplayID screenId = pQuartzScreen->displayIDs[0];
+
+    if (pQuartzScreen->currentMode.ref && CFEqual(pMode->ref, pQuartzScreen->currentMode.ref)) {
+        DEBUG_LOG("Requested RandR resolution matches current CG mode\n");
+    } if (QuartzRandRSetCGMode(screenId, pMode)) {
+        ignore_next_fake_mode_update = TRUE;
+    } else {
+        DEBUG_LOG("Error while requesting CG resolution change.\n");
+        return FALSE;
+    }
+
+    /* If the client requested the fake rootless mode, switch to rootless.
+     * Otherwise, force fullscreen mode.
+     */
+    QuartzSetRootless(pMode->refresh == FAKE_REFRESH_ROOTLESS);
+    if (pMode->refresh != FAKE_REFRESH_ROOTLESS) {
+        QuartzShowFullscreen(TRUE);
+    }
+
+    if(pQuartzScreen->currentMode.ref)
+        CFRelease(pQuartzScreen->currentMode.ref);
+    pQuartzScreen->currentMode = *pMode;
+    CFRetain(pQuartzScreen->currentMode.ref);
+    
+    return TRUE;
+}
+
 static int QuartzRandRSetModeCallback (ScreenPtr pScreen,
-                                       CGDirectDisplayID screenId,
                                        QuartzModeInfoPtr pMode,
                                        void *data) {
     QuartzModeInfoPtr pReqMode = (QuartzModeInfoPtr) data;
-    QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
 	
     if (!QuartzRandRModesEqual(pMode, pReqMode))
         return CALLBACK_CONTINUE;  /* continue enumeration */
 
     DEBUG_LOG("Found a match for requested RandR resolution (%dx%d@%d).\n", (int)pMode->width, (int)pMode->height, (int)pMode->refresh);
 
-    if (pQuartzScreen->currentMode.ref && CFEqual(pMode->ref, pQuartzScreen->currentMode.ref)) {
-        DEBUG_LOG("Requested RandR resolution matches current CG mode\n");
-        return CALLBACK_SUCCESS; /* We don't need to do anything in CG */
-    }
-
-    if (QuartzRandRSetMode(screenId, pMode)) {
-        if(pQuartzScreen->currentMode.ref)
-            CFRelease(pQuartzScreen->currentMode.ref);
-        pQuartzScreen->currentMode = *pMode;
-        CFRetain(pQuartzScreen->currentMode.ref);
-
-        ignore_next_fake_mode_update = TRUE;
+    if(QuartzRandRSetMode(pScreen, pMode, FALSE))
         return CALLBACK_SUCCESS;
-    } else {
-        DEBUG_LOG("Error while requesting CG resolution change.\n");
+    else
         return CALLBACK_ERROR;
-    }
 }
 
 static Bool QuartzRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) {
     QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
-    CGDirectDisplayID screenId;
 
     *rotations = RR_Rotate_0;  /* TODO: support rotation */
 
@@ -381,8 +396,7 @@ static Bool QuartzRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) {
         return TRUE;
     }
 
-    screenId = pQuartzScreen->displayIDs[0];
-    return QuartzRandREnumerateModes(pScreen, screenId, QuartzRandRRegisterModeCallback, NULL);
+    return QuartzRandREnumerateModes(pScreen, QuartzRandRRegisterModeCallback, NULL);
 }
 
 static Bool QuartzRandRSetConfig (ScreenPtr           pScreen,
@@ -390,39 +404,20 @@ static Bool QuartzRandRSetConfig (ScreenPtr           pScreen,
                                   int                 rate,
                                   RRScreenSizePtr     pSize) {
     QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
-    CGDirectDisplayID screenId;
     QuartzModeInfo reqMode;
 
     reqMode.width = pSize->width;
     reqMode.height = pSize->height;
     reqMode.refresh = rate;
 
-    /* If the client requested the fake rootless mode, switch to rootless.
-     * Otherwise, force fullscreen mode.
-     * TODO: Refactor all this fullscreen/rootless crap as it is spaghetti
-     *       has redundancies.
-     */
-    QuartzSetRootless(reqMode.refresh == FAKE_REFRESH_ROOTLESS);
-    QuartzSetFullscreen(reqMode.refresh != FAKE_REFRESH_ROOTLESS);
-    if(reqMode.refresh != FAKE_REFRESH_ROOTLESS &&
-       reqMode.refresh != FAKE_REFRESH_FULLSCREEN)
-        QuartzShow();
-
     if (pQuartzScreen->displayCount == 0)
         return FALSE;
-    if (pQuartzScreen->displayCount > 1) {
-        /* RandR operations are not well-defined for an X11 screen spanning
-           multiple CG displays. Do not accept any configuations that differ
-           from the current configuration. */
-        return TRUE;
-    }
 
     /* Do not switch modes if requested mode is equal to current mode. */
     if (QuartzRandRModesEqual(&reqMode, &pQuartzScreen->currentMode))
         return TRUE;
         
-    screenId = pQuartzScreen->displayIDs[0];
-    if (QuartzRandREnumerateModes(pScreen, screenId, QuartzRandRSetModeCallback, &reqMode)) {
+    if (QuartzRandREnumerateModes(pScreen, QuartzRandRSetModeCallback, &reqMode)) {
         return TRUE;
     }
     
@@ -499,3 +494,57 @@ Bool QuartzRandRInit (ScreenPtr pScreen) {
     pScrPriv->rrSetConfig = QuartzRandRSetConfig;
     return TRUE;
 }
+
+void QuartzRandRSetFakeRootless (void) {
+    int i;
+    
+    DEBUG_LOG("QuartzRandRSetFakeRootless called.\n");
+    
+    for (i=0; i < screenInfo.numScreens; i++) {
+        ScreenPtr pScreen = screenInfo.screens[i];
+        QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
+
+        QuartzRandRSetMode(pScreen, &pQuartzScreen->rootlessMode, TRUE);
+    }
+}
+
+void QuartzRandRSetFakeFullscreen (BOOL state) {
+    int i;
+
+    DEBUG_LOG("QuartzRandRSetFakeFullscreen called.\n");
+    
+    for (i=0; i < screenInfo.numScreens; i++) {
+        ScreenPtr pScreen = screenInfo.screens[i];
+        QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
+
+        QuartzRandRSetMode(pScreen, &pQuartzScreen->fullscreenMode, TRUE);
+    }
+    
+    QuartzShowFullscreen(state);
+}
+
+/* Toggle fullscreen mode.  If "fake" fullscreen is the current mode,
+ * this will just show/hide the X11 windows.  If we are in a RandR fullscreen
+ * mode, this will toggles us to the default fake mode and hide windows if
+ * it is fullscreen
+ */
+void QuartzRandRToggleFullscreen (void) {
+    ScreenPtr pScreen = screenInfo.screens[0];
+    QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
+
+    if (pQuartzScreen->currentMode.ref == NULL) {
+        ErrorF("Ignoring QuartzRandRToggleFullscreen because don't have a current mode set.\n");
+    } else if (pQuartzScreen->currentMode.refresh == FAKE_REFRESH_ROOTLESS) {
+        ErrorF("Ignoring QuartzRandRToggleFullscreen because we are in rootless mode.\n");
+    } else if (pQuartzScreen->currentMode.refresh == FAKE_REFRESH_FULLSCREEN) {
+        /* Legacy fullscreen mode.  Hide/Show */
+        QuartzShowFullscreen(!XQuartzFullscreenVisible);
+    } else {
+        /* RandR fullscreen mode.  Return to default mode and hide if it is fullscreen. */
+        if(XQuartzRootlessDefault) {
+            QuartzRandRSetFakeRootless();
+        } else {
+            QuartzRandRSetFakeFullscreen(FALSE);
+        }
+    }    
+}
diff --git a/hw/xquartz/quartzRandR.h b/hw/xquartz/quartzRandR.h
index b2d4d09..fb0ce0c 100644
--- a/hw/xquartz/quartzRandR.h
+++ b/hw/xquartz/quartzRandR.h
@@ -31,9 +31,12 @@
 #ifndef _QUARTZRANDR_H_
 #define _QUARTZRANDR_H_
 
+#include "randrstr.h"
+
 typedef struct {
     size_t width, height;
     int refresh;
+    RRScreenSizePtr pSize;
     void *ref; /* CGDisplayModeRef or CFDictionaryRef */
 } QuartzModeInfo, *QuartzModeInfoPtr;
 
@@ -57,4 +60,21 @@ void QuartzCopyDisplayIDs(ScreenPtr pScreen,
 Bool QuartzRandRUpdateFakeModes (BOOL force_update);
 Bool QuartzRandRInit (ScreenPtr pScreen);
 
+/* These two functions provide functionality expected by the legacy
+ * mode switching.  They are equivalent to a client requesting one
+ * of the modes corresponding to these "fake" modes.
+ * QuartzRandRSetFakeFullscreen takes an argument which is used to determine
+ * the visibility of the windows after the change.
+ */
+void QuartzRandRSetFakeRootless (void);
+void QuartzRandRSetFakeFullscreen (BOOL state);
+
+
+/* Toggle fullscreen mode.  If "fake" fullscreen is the current mode,
+ * this will just show/hide the X11 windows.  If we are in a RandR fullscreen
+ * mode, this will toggles us to the default fake mode and hide windows if
+ * it is fullscreen
+ */
+void QuartzRandRToggleFullscreen (void);
+
 #endif
commit 0541f9c9b5d232c48454d98f9f21ffd66c09d97e
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Mon Jul 26 23:34:49 2010 -0700

    XQuartz: RandR: Don't change the rootless preference when changing RandR mode
    
    Also renames a bunch of other variables for better consistency.
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/hw/xquartz/X11Application.h b/hw/xquartz/X11Application.h
index ce19e03..4621284 100644
--- a/hw/xquartz/X11Application.h
+++ b/hw/xquartz/X11Application.h
@@ -75,9 +75,6 @@ void X11ApplicationLaunchClient (const char *cmd);
 
 void X11ApplicationMain(int argc, char **argv, char **envp);
 
-extern int X11EnableKeyEquivalents;
-extern int quartzHasRoot, quartzEnableRootless, quartzFullscreenMenu;
-
 #define PREFS_APPSMENU              "apps_menu"
 #define PREFS_FAKEBUTTONS           "enable_fake_buttons"
 #define PREFS_SYSBEEP               "enable_system_beep"
diff --git a/hw/xquartz/X11Application.m b/hw/xquartz/X11Application.m
index 36c39e5..781dccc 100644
--- a/hw/xquartz/X11Application.m
+++ b/hw/xquartz/X11Application.m
@@ -38,6 +38,7 @@
 #import "X11Application.h"
 
 #include "darwin.h"
+#include "quartz.h"
 #include "darwinEvents.h"
 #include "quartzKeyboard.h"
 #include "quartz.h"
@@ -63,9 +64,6 @@ extern int xpbproxy_run (void);
 /* Stuck modifier / button state... force release when we context switch */
 static NSEventType keyState[NUM_KEYCODES];
 
-int X11EnableKeyEquivalents = TRUE, quartzFullscreenMenu = FALSE;
-int quartzHasRoot = FALSE, quartzEnableRootless = TRUE;
-
 extern Bool noTestExtensions;
 
 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
@@ -287,23 +285,23 @@ static void message_kit_thread (SEL selector, NSObject *arg) {
                         do_swallow = YES;
                         for_x = NO;
 #if XPLUGIN_VERSION >= 1
-                    } else if(X11EnableKeyEquivalents &&
+                    } else if(XQuartzEnableKeyEquivalents &&
                              xp_is_symbolic_hotkey_event([e eventRef])) {
                         swallow_keycode = [e keyCode];
                         do_swallow = YES;
                         for_x = NO;
 #endif
-                    } else if(X11EnableKeyEquivalents &&
+                    } else if(XQuartzEnableKeyEquivalents &&
                               [[self mainMenu] performKeyEquivalent:e]) {
                         swallow_keycode = [e keyCode];
                         do_swallow = YES;
                         for_appkit = NO;
                         for_x = NO;
-                    } else if(!quartzEnableRootless
+                    } else if(!XQuartzIsRootless
                               && ([e modifierFlags] & ALL_KEY_MASKS) == (NSCommandKeyMask | NSAlternateKeyMask)
                               && ([e keyCode] == 0 /*a*/ || [e keyCode] == 53 /*Esc*/)) {
                         /* We have this here to force processing fullscreen 
-                         * toggle even if X11EnableKeyEquivalents is disabled */
+                         * toggle even if XQuartzEnableKeyEquivalents is disabled */
                         swallow_keycode = [e keyCode];
                         do_swallow = YES;
                         for_x = NO;
@@ -372,7 +370,7 @@ static void message_kit_thread (SEL selector, NSObject *arg) {
                     break;
                     
                 case 18: /* ApplicationDidReactivate */
-                    if (quartzHasRoot) for_appkit = NO;
+                    if (XQuartzHasRoot) for_appkit = NO;
                     break;
                     
                 case NSApplicationDeactivatedEventType:
@@ -422,7 +420,7 @@ static void message_kit_thread (SEL selector, NSObject *arg) {
     if ([state boolValue])
         SetSystemUIMode(kUIModeNormal, 0); 
     else
-        SetSystemUIMode(kUIModeAllHidden, quartzFullscreenMenu ? kUIOptionAutoShowMenuBar : 0); // kUIModeAllSuppressed or kUIOptionAutoShowMenuBar can be used to allow "mouse-activation"
+        SetSystemUIMode(kUIModeAllHidden, XQuartzFullscreenMenu ? kUIOptionAutoShowMenuBar : 0); // kUIModeAllSuppressed or kUIOptionAutoShowMenuBar can be used to allow "mouse-activation"
 }
 
 - (void) launch_client:(NSString *)cmd {
@@ -720,18 +718,18 @@ static NSMutableArray * cfarray_to_nsarray (CFArrayRef in) {
     NSString *nsstr;
     const char *tem;
 	
-    quartzUseSysBeep = [self prefs_get_boolean:@PREFS_SYSBEEP
-                                       default:quartzUseSysBeep];
-    quartzEnableRootless = [self prefs_get_boolean:@PREFS_ROOTLESS
-                                           default:quartzEnableRootless];
-    quartzFullscreenMenu = [self prefs_get_boolean:@PREFS_FULLSCREEN_MENU
-                                           default:quartzFullscreenMenu];
-    quartzFullscreenDisableHotkeys = ![self prefs_get_boolean:@PREFS_FULLSCREEN_HOTKEYS
-                                                      default:!quartzFullscreenDisableHotkeys];
+    XQuartzUseSysBeep = [self prefs_get_boolean:@PREFS_SYSBEEP
+                                       default:XQuartzUseSysBeep];
+    XQuartzRootlessDefault = [self prefs_get_boolean:@PREFS_ROOTLESS
+                                           default:XQuartzRootlessDefault];
+    XQuartzFullscreenMenu = [self prefs_get_boolean:@PREFS_FULLSCREEN_MENU
+                                           default:XQuartzFullscreenMenu];
+    XQuartzFullscreenDisableHotkeys = ![self prefs_get_boolean:@PREFS_FULLSCREEN_HOTKEYS
+                                                      default:!XQuartzFullscreenDisableHotkeys];
     darwinFakeButtons = [self prefs_get_boolean:@PREFS_FAKEBUTTONS
                                         default:darwinFakeButtons];
-    quartzOptionSendsAlt = [self prefs_get_boolean:@PREFS_OPTION_SENDS_ALT
-                                           default:quartzOptionSendsAlt];
+    XQuartzOptionSendsAlt = [self prefs_get_boolean:@PREFS_OPTION_SENDS_ALT
+                                           default:XQuartzOptionSendsAlt];
 
     if (darwinFakeButtons) {
         const char *fake2, *fake3;
@@ -759,8 +757,8 @@ static NSMutableArray * cfarray_to_nsarray (CFArrayRef in) {
         }
     }
 
-    X11EnableKeyEquivalents = [self prefs_get_boolean:@PREFS_KEYEQUIVS
-                                              default:X11EnableKeyEquivalents];
+    XQuartzEnableKeyEquivalents = [self prefs_get_boolean:@PREFS_KEYEQUIVS
+                                              default:XQuartzEnableKeyEquivalents];
 	
     darwinSyncKeymap = [self prefs_get_boolean:@PREFS_SYNC_KEYMAP
                                        default:darwinSyncKeymap];
@@ -1158,7 +1156,7 @@ static inline int ensure_flag(int flags, int device_independent, int device_depe
                 pDev = darwinTabletCurrent;
             }
 
-            if(!quartzServerVisible && noTestExtensions) {
+            if(!XQuartzServerVisible && noTestExtensions) {
 #if defined(XPLUGIN_VERSION) && XPLUGIN_VERSION > 0
 /* Older libXplugin (Tiger/"Stock" Leopard) aren't thread safe, so we can't call xp_find_window from the Appkit thread */
                 xp_window_id wid = 0;
@@ -1218,7 +1216,7 @@ static inline int ensure_flag(int flags, int device_independent, int device_depe
             /* If we're in the background, we need to send a MotionNotify event
              * first, since we aren't getting them on background mouse motion
              */
-            if(!quartzServerVisible && noTestExtensions) {
+            if(!XQuartzServerVisible && noTestExtensions) {
                 bgMouseLocationUpdated = FALSE;
                 DarwinSendPointerEvents(darwinPointer, MotionNotify, 0, location.x,
                                         location.y, pressure, tilt.x, tilt.y);
diff --git a/hw/xquartz/X11Controller.m b/hw/xquartz/X11Controller.m
index d66d039..13b6366 100644
--- a/hw/xquartz/X11Controller.m
+++ b/hw/xquartz/X11Controller.m
@@ -609,13 +609,13 @@ objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
 }
 
 - (IBAction) enable_fullscreen_changed:sender {
-    int value = ![enable_fullscreen intValue];
+    XQuartzRootlessDefault = ![enable_fullscreen intValue];
 
-    [enable_fullscreen_menu setEnabled:!value];
+    [enable_fullscreen_menu setEnabled:!XQuartzRootlessDefault];
 
-    DarwinSendDDXEvent(kXquartzSetRootless, 1, value);
+    DarwinSendDDXEvent(kXquartzSetRootless, 1, XQuartzRootlessDefault);
 
-    [NSApp prefs_set_boolean:@PREFS_ROOTLESS value:value];
+    [NSApp prefs_set_boolean:@PREFS_ROOTLESS value:XQuartzRootlessDefault];
     [NSApp prefs_synchronize];
 }
 
@@ -638,24 +638,24 @@ objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
         darwinFakeButtons = [fake_buttons intValue];
         [NSApp prefs_set_boolean:@PREFS_FAKEBUTTONS value:darwinFakeButtons];
     } else if(sender == use_sysbeep) {
-        quartzUseSysBeep = [use_sysbeep intValue];
-        [NSApp prefs_set_boolean:@PREFS_SYSBEEP value:quartzUseSysBeep];
+        XQuartzUseSysBeep = [use_sysbeep intValue];
+        [NSApp prefs_set_boolean:@PREFS_SYSBEEP value:XQuartzUseSysBeep];
     } else if(sender == enable_keyequivs) {
-        X11EnableKeyEquivalents =  [enable_keyequivs intValue];
-        [NSApp prefs_set_boolean:@PREFS_KEYEQUIVS value:X11EnableKeyEquivalents];
+        XQuartzEnableKeyEquivalents =  [enable_keyequivs intValue];
+        [NSApp prefs_set_boolean:@PREFS_KEYEQUIVS value:XQuartzEnableKeyEquivalents];
     } else if(sender == sync_keymap) {
         darwinSyncKeymap = [sync_keymap intValue];
         [NSApp prefs_set_boolean:@PREFS_SYNC_KEYMAP value:darwinSyncKeymap];
     } else if(sender == enable_fullscreen_menu) {
-        quartzFullscreenMenu = [enable_fullscreen_menu intValue];
-        [NSApp prefs_set_boolean:@PREFS_FULLSCREEN_MENU value:quartzFullscreenMenu];
+        XQuartzFullscreenMenu = [enable_fullscreen_menu intValue];
+        [NSApp prefs_set_boolean:@PREFS_FULLSCREEN_MENU value:XQuartzFullscreenMenu];
     } else if(sender == option_sends_alt) {
-        BOOL prev_opt_sends_alt = quartzOptionSendsAlt;
+        BOOL prev_opt_sends_alt = XQuartzOptionSendsAlt;
         
-        quartzOptionSendsAlt = [option_sends_alt intValue];
-        [NSApp prefs_set_boolean:@PREFS_OPTION_SENDS_ALT value:quartzOptionSendsAlt];
+        XQuartzOptionSendsAlt = [option_sends_alt intValue];
+        [NSApp prefs_set_boolean:@PREFS_OPTION_SENDS_ALT value:XQuartzOptionSendsAlt];
 
-        if(prev_opt_sends_alt != quartzOptionSendsAlt)
+        if(prev_opt_sends_alt != XQuartzOptionSendsAlt)
             QuartsResyncKeymap(TRUE);
     } else if(sender == click_through) {
         [NSApp prefs_set_boolean:@PREFS_CLICK_THROUGH value:[click_through intValue]];
@@ -701,10 +701,10 @@ objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
     BOOL pbproxy_active = [NSApp prefs_get_boolean:@PREFS_SYNC_PB default:YES];
     
     [fake_buttons setIntValue:darwinFakeButtons];
-    [use_sysbeep setIntValue:quartzUseSysBeep];
-    [enable_keyequivs setIntValue:X11EnableKeyEquivalents];
+    [use_sysbeep setIntValue:XQuartzUseSysBeep];
+    [enable_keyequivs setIntValue:XQuartzEnableKeyEquivalents];
     [sync_keymap setIntValue:darwinSyncKeymap];
-    [option_sends_alt setIntValue:quartzOptionSendsAlt];
+    [option_sends_alt setIntValue:XQuartzOptionSendsAlt];
     [click_through setIntValue:[NSApp prefs_get_boolean:@PREFS_CLICK_THROUGH default:NO]];
     [focus_follows_mouse setIntValue:[NSApp prefs_get_boolean:@PREFS_FFM default:NO]];
     [focus_on_new_window setIntValue:[NSApp prefs_get_boolean:@PREFS_FOCUS_ON_NEW_WINDOW default:YES]];
@@ -729,9 +729,9 @@ objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
     [sync_text1 setTextColor:pbproxy_active ? [NSColor controlTextColor] : [NSColor disabledControlTextColor]];
     [sync_text2 setTextColor:pbproxy_active ? [NSColor controlTextColor] : [NSColor disabledControlTextColor]];
 	
-    [enable_fullscreen setIntValue:!quartzEnableRootless];
-    [enable_fullscreen_menu setEnabled:!quartzEnableRootless];
-    [enable_fullscreen_menu setIntValue:quartzFullscreenMenu];
+    [enable_fullscreen setIntValue:!XQuartzRootlessDefault];
+    [enable_fullscreen_menu setEnabled:!XQuartzRootlessDefault];
+    [enable_fullscreen_menu setIntValue:XQuartzFullscreenMenu];
     
     [prefs_panel makeKeyAndOrderFront:sender];
 }
@@ -752,7 +752,7 @@ objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
   NSMenu *menu = [item menu];
     
   if (item == toggle_fullscreen_item)
-    return !quartzEnableRootless;
+    return !XQuartzIsRootless;
   else if (menu == [X11App windowsMenu] || menu == dock_menu
 	   || (menu == [x11_about_item menu] && [item tag] == 42))
     return (AppleWMSelectedEvents () & AppleWMControllerNotifyMask) != 0;
diff --git a/hw/xquartz/darwinEvents.c b/hw/xquartz/darwinEvents.c
index 7367068..4332202 100644
--- a/hw/xquartz/darwinEvents.c
+++ b/hw/xquartz/darwinEvents.c
@@ -239,9 +239,9 @@ static void DarwinEventHandler(int screenNum, InternalEvent *ie, DeviceIntPtr de
             
         case kXquartzToggleFullscreen:
             DEBUG_LOG("kXquartzToggleFullscreen\n");
-            if(quartzEnableRootless) 
+            if(XQuartzIsRootless)
                 ErrorF("Ignoring kXquartzToggleFullscreen because of rootless mode.");
-            else if (quartzHasRoot)
+            else if (XQuartzHasRoot)
                 QuartzHide();
             else
                 QuartzShow();
@@ -250,7 +250,7 @@ static void DarwinEventHandler(int screenNum, InternalEvent *ie, DeviceIntPtr de
         case kXquartzSetRootless:
             DEBUG_LOG("kXquartzSetRootless\n");
             QuartzSetRootless(e->data[0]);
-            if (!quartzEnableRootless && !quartzHasRoot)
+            if (!XQuartzIsRootless && !XQuartzHasRoot)
                 QuartzHide();
             break;
             
diff --git a/hw/xquartz/quartz.c b/hw/xquartz/quartz.c
index a52cac9..cd90457 100644
--- a/hw/xquartz/quartz.c
+++ b/hw/xquartz/quartz.c
@@ -66,15 +66,20 @@
 #include <rootlessCommon.h>
 #include <Xplugin.h>
 
-// Shared global variables for Quartz modes
-int                     quartzUseSysBeep = 0;
-int                     quartzServerVisible = FALSE;
 DevPrivateKeyRec        quartzScreenKeyRec;
 int                     aquaMenuBarHeight = 0;
 QuartzModeProcsPtr      quartzProcs = NULL;
 const char             *quartzOpenGLBundle = NULL;
-int                     quartzFullscreenDisableHotkeys = TRUE;
-int                     quartzOptionSendsAlt = FALSE;
+
+Bool XQuartzFullscreenDisableHotkeys = TRUE;
+Bool XQuartzOptionSendsAlt = FALSE;
+Bool XQuartzEnableKeyEquivalents = TRUE;
+Bool XQuartzHasRoot = FALSE;
+Bool XQuartzRootlessDefault = TRUE;
+Bool XQuartzIsRootless = TRUE;
+Bool XQuartzServerVisible = FALSE;
+Bool XQuartzFullscreenMenu = FALSE;
+Bool XQuartzUseSysBeep = FALSE;
 
 /*
 ===========================================================================
@@ -245,61 +250,61 @@ void QuartzSetFullscreen(Bool state) {
     
     DEBUG_LOG("QuartzSetFullscreen: state=%d\n", state);
     
-    if(quartzHasRoot == state)
+    if(XQuartzHasRoot == state)
         return;
     
-    quartzHasRoot = state;
+    XQuartzHasRoot = state;
     
     xp_disable_update ();
     
-    if (!quartzHasRoot && !quartzEnableRootless)
+    if (!XQuartzHasRoot && !XQuartzIsRootless)
         RootlessHideAllWindows();
     
-    RootlessUpdateRooted(quartzHasRoot);
+    RootlessUpdateRooted(XQuartzHasRoot);
     
-    if (quartzHasRoot && !quartzEnableRootless)
+    if (XQuartzHasRoot && !XQuartzIsRootless)
         RootlessShowAllWindows ();
     
-    if (quartzHasRoot || quartzEnableRootless) {
+    if (XQuartzHasRoot || XQuartzIsRootless) {
         RootlessRepositionWindows(screenInfo.screens[0]);
     }
 
     /* Somehow the menubar manages to interfere with our event stream
      * in fullscreen mode, even though it's not visible. 
      */
-    X11ApplicationShowHideMenubar(!quartzHasRoot);
+    X11ApplicationShowHideMenubar(!XQuartzHasRoot);
     
     xp_reenable_update ();
     
-    if (quartzFullscreenDisableHotkeys)
-        xp_disable_hot_keys(quartzHasRoot);
+    if (XQuartzFullscreenDisableHotkeys)
+        xp_disable_hot_keys(XQuartzHasRoot);
 }
 
 void QuartzSetRootless(Bool state) {
-    if(quartzEnableRootless == state)
+    if(XQuartzIsRootless == state)
         return;
     
-    quartzEnableRootless = state;
+    XQuartzIsRootless = state;
 
     xp_disable_update();
 
     /* When in rootless, the menubar is not part of the screen, so we need to update our screens on toggle */    
     QuartzUpdateScreens();
 
-    if(!quartzHasRoot) {
-        if(!quartzEnableRootless) {
+    if(!XQuartzHasRoot) {
+        if(!XQuartzIsRootless) {
             RootlessHideAllWindows();
         } else {
             RootlessShowAllWindows();
         }
     }
 
-    X11ApplicationShowHideMenubar(!quartzHasRoot);
+    X11ApplicationShowHideMenubar(!XQuartzHasRoot);
 
     xp_reenable_update();
 
-    if (!quartzEnableRootless && quartzFullscreenDisableHotkeys)
-        xp_disable_hot_keys(quartzHasRoot);
+    if (!XQuartzIsRootless && XQuartzFullscreenDisableHotkeys)
+        xp_disable_hot_keys(XQuartzHasRoot);
 }
 
 /*
@@ -311,17 +316,17 @@ void QuartzSetRootless(Bool state) {
 void QuartzShow(void) {
     int i;
 
-    if (quartzServerVisible)
+    if (XQuartzServerVisible)
         return;
     
-    quartzServerVisible = TRUE;
+    XQuartzServerVisible = TRUE;
     for (i = 0; i < screenInfo.numScreens; i++) {
         if (screenInfo.screens[i]) {
             quartzProcs->ResumeScreen(screenInfo.screens[i]);
         }
     }
     
-    if (!quartzEnableRootless)
+    if (!XQuartzIsRootless)
         QuartzSetFullscreen(TRUE);
 }
 
@@ -336,7 +341,7 @@ void QuartzHide(void)
 {
     int i;
 
-    if (quartzServerVisible) {
+    if (XQuartzServerVisible) {
         for (i = 0; i < screenInfo.numScreens; i++) {
             if (screenInfo.screens[i]) {
                 quartzProcs->SuspendScreen(screenInfo.screens[i]);
@@ -345,7 +350,7 @@ void QuartzHide(void)
     }
     
     QuartzSetFullscreen(FALSE);
-    quartzServerVisible = FALSE;
+    XQuartzServerVisible = FALSE;
 }
 
 
@@ -358,7 +363,7 @@ void QuartzSetRootClip(
 {
     int i;
 
-    if (!quartzServerVisible)
+    if (!XQuartzServerVisible)
         return;
 
     for (i = 0; i < screenInfo.numScreens; i++) {
diff --git a/hw/xquartz/quartz.h b/hw/xquartz/quartz.h
index 1b924e7..a0a17cb 100644
--- a/hw/xquartz/quartz.h
+++ b/hw/xquartz/quartz.h
@@ -35,6 +35,7 @@
 
 #include "screenint.h"
 #include "window.h"
+#include "pixmap.h"
 
 /*------------------------------------------
    Quartz display mode function types
@@ -113,7 +114,20 @@ typedef struct _QuartzModeProcs {
 } QuartzModeProcsRec, *QuartzModeProcsPtr;
 
 extern QuartzModeProcsPtr quartzProcs;
-extern int quartzHasRoot, quartzEnableRootless;
+
+extern Bool XQuartzHasRoot;          /* TODO: These two booleans are very similar and */
+extern Bool XQuartzServerVisible;    /* the code that uses them needs to be refactored
+                                      * XQuartzHasRoot is essentially the "saved" XQuartzServerVisible
+                                      * value from when the server was not in rootless mode.
+                                      */
+
+extern Bool XQuartzEnableKeyEquivalents;
+extern Bool XQuartzRootlessDefault;  /* Is our default mode rootless? */
+extern Bool XQuartzIsRootless;       /* Is our current mode rootless (or FS)? */
+extern Bool XQuartzFullscreenMenu;   /* Show the menu bar (autohide) while in FS */
+extern Bool XQuartzFullscreenDisableHotkeys;
+extern Bool XQuartzOptionSendsAlt;   /* Alt or Mode_switch? */
+extern Bool XQuartzUseSysBeep;       /* Sys beep or our own? */
 
 Bool QuartzAddScreen(int index, ScreenPtr pScreen);
 Bool QuartzSetupScreen(int index, ScreenPtr pScreen);
@@ -129,8 +143,8 @@ void QuartzHide(void);
 void QuartzSetRootClip(BOOL enable);
 void QuartzSpaceChanged(uint32_t space_id);
 
-void QuartzSetFullscreen(Bool state);
 void QuartzSetRootless(Bool state);
+void QuartzSetFullscreen(Bool state);
 
 int server_main(int argc, char **argv, char **envp);
 #endif
diff --git a/hw/xquartz/quartzAudio.c b/hw/xquartz/quartzAudio.c
index 708202b..d0f7c53 100644
--- a/hw/xquartz/quartzAudio.c
+++ b/hw/xquartz/quartzAudio.c
@@ -42,7 +42,7 @@
 #include <dix-config.h>
 #endif
 
-#include "quartzCommon.h"
+#include "quartz.h"
 #include "quartzAudio.h"
 
 #include <CoreAudio/CoreAudio.h>
@@ -220,7 +220,7 @@ void DDXRingBell(
     int pitch,          // pitch is Hz
     int duration )      // duration is milliseconds
 {
-    if (quartzUseSysBeep) {
+    if (XQuartzUseSysBeep) {
         if (volume)
             NSBeep();
         return;
diff --git a/hw/xquartz/quartzCommon.h b/hw/xquartz/quartzCommon.h
index 718df4b..fbfe6f8 100644
--- a/hw/xquartz/quartzCommon.h
+++ b/hw/xquartz/quartzCommon.h
@@ -38,13 +38,7 @@
 #include <X11/Xdefs.h>
 #include "privates.h"
 
-// User preferences used by Quartz modes
-extern int              quartzUseSysBeep;
-extern int              quartzFullscreenDisableHotkeys;
-extern int              quartzOptionSendsAlt;
-
 // Other shared data
-extern int              quartzServerVisible;
 extern DevPrivateKeyRec quartzScreenKeyRec;
 #define quartzScreenKey (&quartzScreenKeyRec)
 extern int              aquaMenuBarHeight;
diff --git a/hw/xquartz/quartzKeyboard.c b/hw/xquartz/quartzKeyboard.c
index 75cf23f..f54c686 100644
--- a/hw/xquartz/quartzKeyboard.c
+++ b/hw/xquartz/quartzKeyboard.c
@@ -48,7 +48,7 @@
 #include <sys/stat.h>
 #include <AvailabilityMacros.h>
 
-#include "quartzCommon.h"
+#include "quartz.h"
 #include "darwin.h"
 #include "darwinEvents.h"
 
@@ -262,7 +262,7 @@ static void DarwinBuildModifierMaps(darwinKeyboardInfo *info) {
             case XK_Alt_L:
                 info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i;
                 info->modMap[MIN_KEYCODE + i] = Mod1Mask;
-                if(!quartzOptionSendsAlt)
+                if(!XQuartzOptionSendsAlt)
                     *k = XK_Mode_switch; // Yes, this is ugly.  This needs to be cleaned up when we integrate quartzKeyboard with this code and refactor.
                 break;
 
@@ -272,7 +272,7 @@ static void DarwinBuildModifierMaps(darwinKeyboardInfo *info) {
 #else
                 info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i;
 #endif
-                if(!quartzOptionSendsAlt)
+                if(!XQuartzOptionSendsAlt)
                     *k = XK_Mode_switch; // Yes, this is ugly.  This needs to be cleaned up when we integrate quartzKeyboard with this code and refactor.
                 info->modMap[MIN_KEYCODE + i] = Mod1Mask;
                 break;
diff --git a/hw/xquartz/quartzRandR.c b/hw/xquartz/quartzRandR.c
index 9b84fa1..7534267 100644
--- a/hw/xquartz/quartzRandR.c
+++ b/hw/xquartz/quartzRandR.c
@@ -140,7 +140,7 @@ static Bool QuartzRandREnumerateModes (ScreenPtr pScreen,
             break;
     }
 
-    switch(callback(pScreen, screenId, &pQuartzScreen->fullScreenMode, data)) {
+    switch(callback(pScreen, screenId, &pQuartzScreen->fullscreenMode, data)) {
         case CALLBACK_SUCCESS:
             return TRUE;
         case CALLBACK_ERROR:
@@ -239,7 +239,7 @@ static Bool QuartzRandREnumerateModes (ScreenPtr pScreen,
             break;
     }
 
-    switch(callback(pScreen, screenId, &pQuartzScreen->fullScreenMode, data)) {
+    switch(callback(pScreen, screenId, &pQuartzScreen->fullscreenMode, data)) {
         case CALLBACK_SUCCESS:
             return TRUE;
         case CALLBACK_ERROR:
@@ -377,7 +377,7 @@ static Bool QuartzRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) {
            resolution including/excluding the menu bar. */
 
         QuartzRandRRegisterMode(pScreen, &pQuartzScreen->rootlessMode);
-        QuartzRandRRegisterMode(pScreen, &pQuartzScreen->fullScreenMode);
+        QuartzRandRRegisterMode(pScreen, &pQuartzScreen->fullscreenMode);
         return TRUE;
     }
 
@@ -434,37 +434,37 @@ static Bool _QuartzRandRUpdateFakeModes (ScreenPtr pScreen) {
     QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
 
     if (pQuartzScreen->displayCount == 1) {
-        if(pQuartzScreen->fullScreenMode.ref)
-            CFRelease(pQuartzScreen->fullScreenMode.ref);
+        if(pQuartzScreen->fullscreenMode.ref)
+            CFRelease(pQuartzScreen->fullscreenMode.ref);
         if(pQuartzScreen->currentMode.ref)
             CFRelease(pQuartzScreen->currentMode.ref);
         
         if (!QuartzRandRCopyCurrentModeInfo(pQuartzScreen->displayIDs[0],
-                                            &pQuartzScreen->fullScreenMode))
+                                            &pQuartzScreen->fullscreenMode))
             return FALSE;
 
-        CFRetain(pQuartzScreen->fullScreenMode.ref);  /* This extra retain is for currentMode's copy */
+        CFRetain(pQuartzScreen->fullscreenMode.ref);  /* This extra retain is for currentMode's copy */
     } else {
-        pQuartzScreen->fullScreenMode.width = pScreen->width;
-        pQuartzScreen->fullScreenMode.height = pScreen->height;
-        if(quartzEnableRootless)
-            pQuartzScreen->fullScreenMode.height += aquaMenuBarHeight;
+        pQuartzScreen->fullscreenMode.width = pScreen->width;
+        pQuartzScreen->fullscreenMode.height = pScreen->height;
+        if(XQuartzIsRootless)
+            pQuartzScreen->fullscreenMode.height += aquaMenuBarHeight;
     }
 
-    pQuartzScreen->fullScreenMode.refresh = FAKE_REFRESH_FULLSCREEN;
+    pQuartzScreen->fullscreenMode.refresh = FAKE_REFRESH_FULLSCREEN;
 
-    pQuartzScreen->rootlessMode = pQuartzScreen->fullScreenMode;
+    pQuartzScreen->rootlessMode = pQuartzScreen->fullscreenMode;
     pQuartzScreen->rootlessMode.refresh = FAKE_REFRESH_ROOTLESS;
     pQuartzScreen->rootlessMode.height -= aquaMenuBarHeight;
 
-    if(quartzEnableRootless) {
+    if(XQuartzIsRootless) {
         pQuartzScreen->currentMode = pQuartzScreen->rootlessMode;
     } else {
-        pQuartzScreen->currentMode = pQuartzScreen->fullScreenMode;
+        pQuartzScreen->currentMode = pQuartzScreen->fullscreenMode;
     }
     
     DEBUG_LOG("rootlessMode: %d x %d\n", (int)pQuartzScreen->rootlessMode.width, (int)pQuartzScreen->rootlessMode.height);
-    DEBUG_LOG("fullScreenMode: %d x %d\n", (int)pQuartzScreen->fullScreenMode.width, (int)pQuartzScreen->fullScreenMode.height);
+    DEBUG_LOG("fullscreenMode: %d x %d\n", (int)pQuartzScreen->fullscreenMode.width, (int)pQuartzScreen->fullscreenMode.height);
     DEBUG_LOG("currentMode: %d x %d\n", (int)pQuartzScreen->currentMode.width, (int)pQuartzScreen->currentMode.height);
     
     return TRUE;
diff --git a/hw/xquartz/quartzRandR.h b/hw/xquartz/quartzRandR.h
index 4a7990e..b2d4d09 100644
--- a/hw/xquartz/quartzRandR.h
+++ b/hw/xquartz/quartzRandR.h
@@ -45,7 +45,7 @@ typedef struct {
     // No CG display will be covered by more than one X11 screen.
     int displayCount;
     CGDirectDisplayID *displayIDs;
-    QuartzModeInfo rootlessMode, fullScreenMode, currentMode;
+    QuartzModeInfo rootlessMode, fullscreenMode, currentMode;
 } QuartzScreenRec, *QuartzScreenPtr;
 
 #define QUARTZ_PRIV(pScreen) \
diff --git a/hw/xquartz/xpr/xprAppleWM.c b/hw/xquartz/xpr/xprAppleWM.c
index 4b31e3a..1a3d427 100644
--- a/hw/xquartz/xpr/xprAppleWM.c
+++ b/hw/xquartz/xpr/xprAppleWM.c
@@ -67,7 +67,7 @@ static int xprSetWindowLevel(
     if(!winRec)
         return BadWindow;
     
-    if(quartzEnableRootless)
+    if(XQuartzIsRootless)
         wc.window_level = normal_window_levels[level];
     else
         wc.window_level = rooted_window_levels[level];
diff --git a/hw/xquartz/xpr/xprCursor.c b/hw/xquartz/xpr/xprCursor.c
index a106e72..216678e 100644
--- a/hw/xquartz/xpr/xprCursor.c
+++ b/hw/xquartz/xpr/xprCursor.c
@@ -35,7 +35,7 @@
 #include <dix-config.h>
 #endif
 
-#include "quartzCommon.h"
+#include "quartz.h"
 #include "xpr.h"
 #include "darwin.h"
 #include "darwinEvents.h"
@@ -226,7 +226,7 @@ QuartzSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, int x,
 {
     QuartzCursorScreenPtr ScreenPriv = CURSOR_PRIV(pScreen);
 
-    if (!quartzServerVisible)
+    if (!XQuartzServerVisible)
         return;
 
     if (pCursor == NULL)
@@ -295,7 +295,7 @@ QuartzCrossScreen(ScreenPtr pScreen, Bool entering)
 static void
 QuartzWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
 {
-    if (quartzServerVisible)
+    if (XQuartzServerVisible)
     {
         int sx, sy;
 
diff --git a/hw/xquartz/xpr/xprFrame.c b/hw/xquartz/xpr/xprFrame.c
index 42f06ef..ede5af5 100644
--- a/hw/xquartz/xpr/xprFrame.c
+++ b/hw/xquartz/xpr/xprFrame.c
@@ -171,7 +171,7 @@ xprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen,
 
     pFrame->level = !IsRoot (pWin) ? AppleWMWindowLevelNormal : AppleWMNumWindowLevels;
 
-    if(quartzEnableRootless)
+    if(XQuartzIsRootless)
         wc.window_level = normal_window_levels[pFrame->level];
     else
         wc.window_level = rooted_window_levels[pFrame->level];
@@ -285,7 +285,7 @@ static void xprRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid) {
         RootlessWindowRec *winRec = x_hash_table_lookup(window_hash, wid, NULL);
 
         if(winRec) {
-            if(quartzEnableRootless)
+            if(XQuartzIsRootless)
                 wc.window_level = normal_window_levels[winRec->level];
             else
                 wc.window_level = rooted_window_levels[winRec->level];
diff --git a/hw/xquartz/xpr/xprScreen.c b/hw/xquartz/xpr/xprScreen.c
index b3ac693..599ef6f 100644
--- a/hw/xquartz/xpr/xprScreen.c
+++ b/hw/xquartz/xpr/xprScreen.c
@@ -158,7 +158,7 @@ displayScreenBounds(CGDirectDisplayID id)
               (int)frame.origin.x, (int)frame.origin.y);
     
     /* Remove menubar to help standard X11 window managers. */
-    if (quartzEnableRootless && 
+    if (XQuartzIsRootless && 
         frame.origin.x == 0 && frame.origin.y == 0) {
         frame.origin.y += aquaMenuBarHeight;
         frame.size.height -= aquaMenuBarHeight;
@@ -274,7 +274,8 @@ xprDisplayInit(void)
     AppleDRIExtensionInit();
     xprAppleWMInit();
 
-    if (!quartzEnableRootless)
+    XQuartzIsRootless = XQuartzRootlessDefault;
+    if (!XQuartzIsRootless)
         RootlessHideAllWindows();
 }
 
commit cdf091632a9803fe225c8f65a1172ebda40e563e
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Mon Jul 26 11:45:59 2010 -0700

    XQuartz: RandR: Better handle switching betwen RandR modes that share CG modes
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/hw/xquartz/quartzRandR.c b/hw/xquartz/quartzRandR.c
index 65dce22..9b84fa1 100644
--- a/hw/xquartz/quartzRandR.c
+++ b/hw/xquartz/quartzRandR.c
@@ -57,9 +57,12 @@ static Bool ignore_next_fake_mode_update = FALSE;
 #define DEFAULT_REFRESH  60
 #define kDisplayModeUsableFlags  (kDisplayModeValidFlag | kDisplayModeSafeFlag)
 
-typedef Bool (*QuartzModeCallback)
-    (ScreenPtr, CGDirectDisplayID, QuartzModeInfoPtr, void *);
+#define CALLBACK_SUCCESS 0
+#define CALLBACK_CONTINUE 1
+#define CALLBACK_ERROR -1
 
+typedef int (*QuartzModeCallback)
+    (ScreenPtr, CGDirectDisplayID, QuartzModeInfoPtr, void *);
 
 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
 
@@ -97,20 +100,22 @@ static void QuartzRandRGetModeInfo (CFDictionaryRef modeRef,
     pMode->ref = NULL;
 }
 
-static Bool QuartzRandRGetCurrentModeInfo (CGDirectDisplayID screenId,
+static Bool QuartzRandRCopyCurrentModeInfo (CGDirectDisplayID screenId,
                                            QuartzModeInfoPtr pMode) {
     CFDictionaryRef curModeRef = CGDisplayCurrentMode(screenId);
     if (!curModeRef)
         return FALSE;
 
     QuartzRandRGetModeInfo(curModeRef, pMode);
+    pMode->ref = curModeRef;
+    CFRetain(pMode->ref);
     return TRUE;
 }
 
 static Bool QuartzRandRSetMode (CGDirectDisplayID screenId,
                                 QuartzModeInfoPtr pMode) {
     CFDictionaryRef modeRef = (CFDictionaryRef) pMode->ref;
-    return (CGDisplaySwitchToMode(screenId, modeRef) != kCGErrorSuccess);
+    return (CGDisplaySwitchToMode(screenId, modeRef) == kCGErrorSuccess);
 }
 
 static Bool QuartzRandREnumerateModes (ScreenPtr pScreen,
@@ -122,6 +127,28 @@ static Bool QuartzRandREnumerateModes (ScreenPtr pScreen,
     CFArrayRef modes;
     QuartzModeInfo modeInfo;
     int i;
+    BOOL retval = FALSE;
+    QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
+
+    switch(callback(pScreen, screenId, &pQuartzScreen->rootlessMode, data)) {
+        case CALLBACK_SUCCESS:
+            return TRUE;
+        case CALLBACK_ERROR:
+            return FALSE;
+        case CALLBACK_CONTINUE:
+        default:
+            break;
+    }
+
+    switch(callback(pScreen, screenId, &pQuartzScreen->fullScreenMode, data)) {
+        case CALLBACK_SUCCESS:
+            return TRUE;
+        case CALLBACK_ERROR:
+            return FALSE;
+        case CALLBACK_CONTINUE:
+        default:
+            break;
+    }
 
     curModeRef = CGDisplayCurrentMode(screenId);
     if (!curModeRef)
@@ -132,6 +159,7 @@ static Bool QuartzRandREnumerateModes (ScreenPtr pScreen,
     if (!modes)
         return FALSE;
     for (i = 0; i < CFArrayGetCount(modes); i++) {
+        int cb;
         modeRef = (CFDictionaryRef) CFArrayGetValueAtIndex(modes, i);
 
         /* Skip modes that are not usable on the current display or have a
@@ -144,10 +172,15 @@ static Bool QuartzRandREnumerateModes (ScreenPtr pScreen,
 
         QuartzRandRGetModeInfo(modeRef, &modeInfo);
         modeInfo.ref = modeRef;
-        if (!callback(pScreen, screenId, &modeInfo, data))
+        cb = callback(pScreen, screenId, &modeInfo, data);
+        if (cb == CALLBACK_SUCCESS)
+            break;
+        if (cb == CALLBACK_ERROR) {
+            retval = FALSE;
             break;
+        }
     }
-    return TRUE;
+    return retval;
 }
 
 #else /* we have the new CG APIs from Snow Leopard */
@@ -162,14 +195,14 @@ static void QuartzRandRGetModeInfo (CGDisplayModeRef modeRef,
     pMode->ref = NULL;
 }
 
-static Bool QuartzRandRGetCurrentModeInfo (CGDirectDisplayID screenId,
-                                           QuartzModeInfoPtr pMode) {
+static Bool QuartzRandRCopyCurrentModeInfo (CGDirectDisplayID screenId,
+                                            QuartzModeInfoPtr pMode) {
     CGDisplayModeRef curModeRef = CGDisplayCopyDisplayMode(screenId);
     if (!curModeRef)
         return FALSE;
 
     QuartzRandRGetModeInfo(curModeRef, pMode);
-    CGDisplayModeRelease(curModeRef);
+    pMode->ref = curModeRef;
     return TRUE;
 }
 
@@ -179,7 +212,7 @@ static Bool QuartzRandRSetMode (CGDirectDisplayID screenId,
     if (!modeRef)
         return FALSE;
 
-    return (CGDisplaySetDisplayMode(screenId, modeRef, NULL) != kCGErrorSuccess);
+    return (CGDisplaySetDisplayMode(screenId, modeRef, NULL) == kCGErrorSuccess);
 }
 
 static Bool QuartzRandREnumerateModes (ScreenPtr pScreen,
@@ -192,6 +225,29 @@ static Bool QuartzRandREnumerateModes (ScreenPtr pScreen,
     CFArrayRef modes;
     QuartzModeInfo modeInfo;
     int i;
+    Bool retval = TRUE;
+
+    QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
+
+    switch(callback(pScreen, screenId, &pQuartzScreen->rootlessMode, data)) {
+        case CALLBACK_SUCCESS:
+            return TRUE;
+        case CALLBACK_ERROR:
+            return FALSE;
+        case CALLBACK_CONTINUE:
+        default:
+            break;
+    }
+
+    switch(callback(pScreen, screenId, &pQuartzScreen->fullScreenMode, data)) {
+        case CALLBACK_SUCCESS:
+            return TRUE;
+        case CALLBACK_ERROR:
+            return FALSE;
+        case CALLBACK_CONTINUE:
+        default:
+            break;
+    }
 
     curModeRef = CGDisplayCopyDisplayMode(screenId);
     if (!curModeRef)
@@ -205,6 +261,7 @@ static Bool QuartzRandREnumerateModes (ScreenPtr pScreen,
         return FALSE;
     }
     for (i = 0; i < CFArrayGetCount(modes); i++) {
+        int cb;
         modeRef = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
 
         /* Skip modes that are not usable on the current display or have a
@@ -220,13 +277,19 @@ static Bool QuartzRandREnumerateModes (ScreenPtr pScreen,
 
         QuartzRandRGetModeInfo(modeRef, &modeInfo);
         modeInfo.ref = modeRef;
-        if (!callback(pScreen, screenId, &modeInfo, data))
+        cb = callback(pScreen, screenId, &modeInfo, data);
+        if (cb == CALLBACK_SUCCESS)
+            break;
+		if (cb == CALLBACK_ERROR) {
+			retval = FALSE;
             break;
+		}
     }
+		
     CFRelease(modes);
 
     CFRelease(curPixelEnc);
-    return TRUE;
+    return retval;
 }
 
 #endif  /* Snow Leopard CoreGraphics APIs */
@@ -246,6 +309,7 @@ static Bool QuartzRandRRegisterMode (ScreenPtr pScreen,
     RRScreenSizePtr pSize = RRRegisterSize(pScreen,
         pMode->width, pMode->height, pScreen->mmWidth, pScreen->mmHeight);
     if (pSize) {
+        //DEBUG_LOG("registering: %d x %d @ %d %s\n", (int)pMode->width, (int)pMode->height, (int)pMode->refresh, isCurrentMode ? "*" : "");
         RRRegisterRate(pScreen, pSize, pMode->refresh);
 
         if (isCurrentMode)
@@ -256,34 +320,46 @@ static Bool QuartzRandRRegisterMode (ScreenPtr pScreen,
     return FALSE;
 }
 
-static Bool QuartzRandRRegisterModeCallback (ScreenPtr pScreen,
+static int QuartzRandRRegisterModeCallback (ScreenPtr pScreen,
                                         CGDirectDisplayID screenId,
                                         QuartzModeInfoPtr pMode,
                                         void *data __unused) {
-    return QuartzRandRRegisterMode(pScreen, pMode);
+    if(QuartzRandRRegisterMode(pScreen, pMode)) {
+        return CALLBACK_CONTINUE;
+    } else {
+        return CALLBACK_ERROR;
+    }
 }
 
-static Bool QuartzRandRSetModeCallback (ScreenPtr pScreen,
-                                        CGDirectDisplayID screenId,
-                                        QuartzModeInfoPtr pMode,
-                                        void *data) {
+static int QuartzRandRSetModeCallback (ScreenPtr pScreen,
+                                       CGDirectDisplayID screenId,
+                                       QuartzModeInfoPtr pMode,
+                                       void *data) {
     QuartzModeInfoPtr pReqMode = (QuartzModeInfoPtr) data;
     QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
-
+	
     if (!QuartzRandRModesEqual(pMode, pReqMode))
-        return TRUE;  /* continue enumeration */
+        return CALLBACK_CONTINUE;  /* continue enumeration */
+
+    DEBUG_LOG("Found a match for requested RandR resolution (%dx%d@%d).\n", (int)pMode->width, (int)pMode->height, (int)pMode->refresh);
 
-    if (pReqMode->ref == pQuartzScreen->currentMode.ref) {
+    if (pQuartzScreen->currentMode.ref && CFEqual(pMode->ref, pQuartzScreen->currentMode.ref)) {
         DEBUG_LOG("Requested RandR resolution matches current CG mode\n");
-        return FALSE; /* We don't need to do anything in CG */
+        return CALLBACK_SUCCESS; /* We don't need to do anything in CG */
     }
 
-    if (QuartzRandRSetMode(screenId, pMode) == FALSE) {
+    if (QuartzRandRSetMode(screenId, pMode)) {
+        if(pQuartzScreen->currentMode.ref)
+            CFRelease(pQuartzScreen->currentMode.ref);
+        pQuartzScreen->currentMode = *pMode;
+        CFRetain(pQuartzScreen->currentMode.ref);
+
         ignore_next_fake_mode_update = TRUE;
-        return FALSE;
+        return CALLBACK_SUCCESS;
     } else {
-        return TRUE;
-    };
+        DEBUG_LOG("Error while requesting CG resolution change.\n");
+        return CALLBACK_ERROR;
+    }
 }
 
 static Bool QuartzRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) {
@@ -295,17 +371,17 @@ static Bool QuartzRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) {
     if (pQuartzScreen->displayCount == 0)
         return FALSE;
 
-    QuartzRandRRegisterMode(pScreen, &pQuartzScreen->rootlessMode);
-    QuartzRandRRegisterMode(pScreen, &pQuartzScreen->fullScreenMode);
-
     if (pQuartzScreen->displayCount > 1) {
         /* RandR operations are not well-defined for an X11 screen spanning
            multiple CG displays. Create two entries for the current virtual
            resolution including/excluding the menu bar. */
+
+        QuartzRandRRegisterMode(pScreen, &pQuartzScreen->rootlessMode);
+        QuartzRandRRegisterMode(pScreen, &pQuartzScreen->fullScreenMode);
         return TRUE;
     }
-    screenId = pQuartzScreen->displayIDs[0];
 
+    screenId = pQuartzScreen->displayIDs[0];
     return QuartzRandREnumerateModes(pScreen, screenId, QuartzRandRRegisterModeCallback, NULL);
 }
 
@@ -323,9 +399,14 @@ static Bool QuartzRandRSetConfig (ScreenPtr           pScreen,
 
     /* If the client requested the fake rootless mode, switch to rootless.
      * Otherwise, force fullscreen mode.
+     * TODO: Refactor all this fullscreen/rootless crap as it is spaghetti
+     *       has redundancies.
      */
-    QuartzSetFullscreen(reqMode.refresh != FAKE_REFRESH_ROOTLESS);
     QuartzSetRootless(reqMode.refresh == FAKE_REFRESH_ROOTLESS);
+    QuartzSetFullscreen(reqMode.refresh != FAKE_REFRESH_ROOTLESS);
+    if(reqMode.refresh != FAKE_REFRESH_ROOTLESS &&
+       reqMode.refresh != FAKE_REFRESH_FULLSCREEN)
+        QuartzShow();
 
     if (pQuartzScreen->displayCount == 0)
         return FALSE;
@@ -342,12 +423,10 @@ static Bool QuartzRandRSetConfig (ScreenPtr           pScreen,
         
     screenId = pQuartzScreen->displayIDs[0];
     if (QuartzRandREnumerateModes(pScreen, screenId, QuartzRandRSetModeCallback, &reqMode)) {
-        pQuartzScreen->currentMode = reqMode;
         return TRUE;
     }
     
     DEBUG_LOG("Unable to find a matching config: %d x %d @ %d\n", (int)reqMode.width, (int)reqMode.height, (int)reqMode.refresh);
-
     return FALSE;
 }
 
@@ -355,9 +434,16 @@ static Bool _QuartzRandRUpdateFakeModes (ScreenPtr pScreen) {
     QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
 
     if (pQuartzScreen->displayCount == 1) {
-        if (!QuartzRandRGetCurrentModeInfo(pQuartzScreen->displayIDs[0],
-                                           &pQuartzScreen->fullScreenMode))
+        if(pQuartzScreen->fullScreenMode.ref)
+            CFRelease(pQuartzScreen->fullScreenMode.ref);
+        if(pQuartzScreen->currentMode.ref)
+            CFRelease(pQuartzScreen->currentMode.ref);
+        
+        if (!QuartzRandRCopyCurrentModeInfo(pQuartzScreen->displayIDs[0],
+                                            &pQuartzScreen->fullScreenMode))
             return FALSE;
+
+        CFRetain(pQuartzScreen->fullScreenMode.ref);  /* This extra retain is for currentMode's copy */
     } else {
         pQuartzScreen->fullScreenMode.width = pScreen->width;
         pQuartzScreen->fullScreenMode.height = pScreen->height;
diff --git a/hw/xquartz/quartzRandR.h b/hw/xquartz/quartzRandR.h
index 8ee2818..4a7990e 100644
--- a/hw/xquartz/quartzRandR.h
+++ b/hw/xquartz/quartzRandR.h
@@ -34,7 +34,7 @@
 typedef struct {
     size_t width, height;
     int refresh;
-    const void *ref;
+    void *ref; /* CGDisplayModeRef or CFDictionaryRef */
 } QuartzModeInfo, *QuartzModeInfoPtr;
 
 // Quartz specific per screen storage structure
commit 42647a084bd4a1913c54521f992a00b59c0a5e68
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Mon Jul 26 01:17:12 2010 -0700

    XQuartz: RandR: Respond better to resolution changes made outside X
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/hw/xquartz/darwinEvents.c b/hw/xquartz/darwinEvents.c
index 7b34b8a..7367068 100644
--- a/hw/xquartz/darwinEvents.c
+++ b/hw/xquartz/darwinEvents.c
@@ -52,6 +52,7 @@ in this Software without prior written authorization from The Open Group.
 #include "darwin.h"
 #include "quartz.h"
 #include "quartzKeyboard.h"
+#include "quartzRandR.h"
 #include "darwinEvents.h"
 
 #include <sys/types.h>
@@ -276,7 +277,12 @@ static void DarwinEventHandler(int screenNum, InternalEvent *ie, DeviceIntPtr de
             break;
             
         case kXquartzDisplayChanged:
+            DEBUG_LOG("kXquartzDisplayChanged\n");
             QuartzUpdateScreens();
+#ifdef RANDR
+            /* Update our RandR info */
+            QuartzRandRUpdateFakeModes(TRUE);
+#endif
             break;
             
         default:
diff --git a/hw/xquartz/quartzCommon.h b/hw/xquartz/quartzCommon.h
index 851e74c..718df4b 100644
--- a/hw/xquartz/quartzCommon.h
+++ b/hw/xquartz/quartzCommon.h
@@ -38,29 +38,6 @@
 #include <X11/Xdefs.h>
 #include "privates.h"
 
-typedef struct {
-    size_t width, height;
-    int refresh;
-    const void *ref;
-} QuartzModeInfo, *QuartzModeInfoPtr;
-
-// Quartz specific per screen storage structure
-typedef struct {
-    // List of CoreGraphics displays that this X11 screen covers.
-    // This is more than one CG display for video mirroring and
-    // rootless PseudoramiX mode.
-    // No CG display will be covered by more than one X11 screen.
-    int displayCount;
-    CGDirectDisplayID *displayIDs;
-    QuartzModeInfo originalMode, fakeMode;
-} QuartzScreenRec, *QuartzScreenPtr;
-
-#define QUARTZ_PRIV(pScreen) \
-    ((QuartzScreenPtr)dixLookupPrivate(&pScreen->devPrivates, quartzScreenKey))
-
-void QuartzCopyDisplayIDs(ScreenPtr pScreen,
-                          int displayCount, CGDirectDisplayID *displayIDs);
-
 // User preferences used by Quartz modes
 extern int              quartzUseSysBeep;
 extern int              quartzFullscreenDisableHotkeys;
diff --git a/hw/xquartz/quartzRandR.c b/hw/xquartz/quartzRandR.c
index e46e904..65dce22 100644
--- a/hw/xquartz/quartzRandR.c
+++ b/hw/xquartz/quartzRandR.c
@@ -38,6 +38,7 @@
 #include "quartzCommon.h"
 #include "quartzRandR.h"
 #include "quartz.h"
+#include "darwin.h"
 
 #include <AvailabilityMacros.h>
 
@@ -45,6 +46,13 @@
 #include <randrstr.h>
 #include <IOKit/graphics/IOGraphicsTypes.h>
 
+/* TODO: UGLY, find a better way!
+ * We want to ignore kXquartzDisplayChanged which are generated by us
+ */
+static Bool ignore_next_fake_mode_update = FALSE;
+
+#define FAKE_REFRESH_ROOTLESS 1
+#define FAKE_REFRESH_FULLSCREEN 2
 
 #define DEFAULT_REFRESH  60
 #define kDisplayModeUsableFlags  (kDisplayModeValidFlag | kDisplayModeSafeFlag)
@@ -171,8 +179,7 @@ static Bool QuartzRandRSetMode (CGDirectDisplayID screenId,
     if (!modeRef)
         return FALSE;
 
-    return (CGDisplaySetDisplayMode(screenId, modeRef, NULL) !=
-            kCGErrorSuccess);
+    return (CGDisplaySetDisplayMode(screenId, modeRef, NULL) != kCGErrorSuccess);
 }
 
 static Bool QuartzRandREnumerateModes (ScreenPtr pScreen,
@@ -227,18 +234,15 @@ static Bool QuartzRandREnumerateModes (ScreenPtr pScreen,
 
 static Bool QuartzRandRModesEqual (QuartzModeInfoPtr pMode1,
                                    QuartzModeInfoPtr pMode2) {
-    if (pMode1->width != pMode2->width)
-        return FALSE;
-    if (pMode1->height != pMode2->height)
-        return FALSE;
-    if (pMode1->refresh != pMode2->refresh)
-        return FALSE;
-    return TRUE;
+    return (pMode1->width == pMode2->width) &&
+           (pMode1->height == pMode2->height) &&
+           (pMode1->refresh == pMode2->refresh);
 }
 
 static Bool QuartzRandRRegisterMode (ScreenPtr pScreen,
-                                     QuartzModeInfoPtr pMode,
-                                     Bool isCurrentMode) {
+                                     QuartzModeInfoPtr pMode) {
+    QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
+    Bool isCurrentMode = QuartzRandRModesEqual(&pQuartzScreen->currentMode, pMode);
     RRScreenSizePtr pSize = RRRegisterSize(pScreen,
         pMode->width, pMode->height, pScreen->mmWidth, pScreen->mmHeight);
     if (pSize) {
@@ -252,14 +256,11 @@ static Bool QuartzRandRRegisterMode (ScreenPtr pScreen,
     return FALSE;
 }
 
-static Bool QuartzRandRGetModeCallback (ScreenPtr pScreen,
+static Bool QuartzRandRRegisterModeCallback (ScreenPtr pScreen,
                                         CGDirectDisplayID screenId,
                                         QuartzModeInfoPtr pMode,
-                                        void *data) {
-    QuartzModeInfoPtr pCurMode = (QuartzModeInfoPtr) data;
-
-    return QuartzRandRRegisterMode(pScreen, pMode,
-        QuartzRandRModesEqual(pMode, pCurMode));
+                                        void *data __unused) {
+    return QuartzRandRRegisterMode(pScreen, pMode);
 }
 
 static Bool QuartzRandRSetModeCallback (ScreenPtr pScreen,
@@ -267,73 +268,64 @@ static Bool QuartzRandRSetModeCallback (ScreenPtr pScreen,
                                         QuartzModeInfoPtr pMode,
                                         void *data) {
     QuartzModeInfoPtr pReqMode = (QuartzModeInfoPtr) data;
+    QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
 
     if (!QuartzRandRModesEqual(pMode, pReqMode))
         return TRUE;  /* continue enumeration */
 
-    return QuartzRandRSetMode(screenId, pMode);
+    if (pReqMode->ref == pQuartzScreen->currentMode.ref) {
+        DEBUG_LOG("Requested RandR resolution matches current CG mode\n");
+        return FALSE; /* We don't need to do anything in CG */
+    }
+
+    if (QuartzRandRSetMode(screenId, pMode) == FALSE) {
+        ignore_next_fake_mode_update = TRUE;
+        return FALSE;
+    } else {
+        return TRUE;
+    };
 }
 
 static Bool QuartzRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) {
     QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
     CGDirectDisplayID screenId;
-    QuartzModeInfo curMode;
 
     *rotations = RR_Rotate_0;  /* TODO: support rotation */
 
     if (pQuartzScreen->displayCount == 0)
         return FALSE;
+
+    QuartzRandRRegisterMode(pScreen, &pQuartzScreen->rootlessMode);
+    QuartzRandRRegisterMode(pScreen, &pQuartzScreen->fullScreenMode);
+
     if (pQuartzScreen->displayCount > 1) {
         /* RandR operations are not well-defined for an X11 screen spanning
            multiple CG displays. Create two entries for the current virtual
            resolution including/excluding the menu bar. */
-        QuartzRandRRegisterMode(pScreen, &pQuartzScreen->fakeMode,
-            !quartzHasRoot);
-        QuartzRandRRegisterMode(pScreen, &pQuartzScreen->originalMode,
-            quartzHasRoot);
         return TRUE;
     }
     screenId = pQuartzScreen->displayIDs[0];
 
-    if (!QuartzRandRGetCurrentModeInfo(screenId, &curMode))
-        return FALSE;
-
-    /* Add a fake mode corresponding to the original resolution excluding the
-       height of the menu bar. */
-    if (!quartzHasRoot &&
-        QuartzRandRModesEqual(&pQuartzScreen->originalMode, &curMode)) {
-        QuartzRandRRegisterMode(pScreen, &pQuartzScreen->fakeMode, TRUE);
-        curMode = pQuartzScreen->fakeMode;
-    }
-    else
-        QuartzRandRRegisterMode(pScreen, &pQuartzScreen->fakeMode, FALSE);
-
-    return QuartzRandREnumerateModes(pScreen, screenId,
-        QuartzRandRGetModeCallback, &curMode);
+    return QuartzRandREnumerateModes(pScreen, screenId, QuartzRandRRegisterModeCallback, NULL);
 }
 
 static Bool QuartzRandRSetConfig (ScreenPtr           pScreen,
-			          Rotation            randr,
-			          int                 rate,
-			          RRScreenSizePtr     pSize) {
+                                  Rotation            randr,
+                                  int                 rate,
+                                  RRScreenSizePtr     pSize) {
     QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
     CGDirectDisplayID screenId;
-    QuartzModeInfo reqMode, curMode;
-    Bool rootless = FALSE;
+    QuartzModeInfo reqMode;
 
     reqMode.width = pSize->width;
     reqMode.height = pSize->height;
     reqMode.refresh = rate;
 
-    /* If the client requested the fake screen mode, switch to rootless mode.
-       Switch to fullscreen mode (root window visible) if a real screen mode was
-       requested. */
-    if (QuartzRandRModesEqual(&reqMode, &pQuartzScreen->fakeMode)) {
-        rootless = TRUE;
-        reqMode = pQuartzScreen->originalMode;
-    }
-    QuartzSetFullscreen(!rootless);
-    QuartzSetRootless(rootless);
+    /* If the client requested the fake rootless mode, switch to rootless.
+     * Otherwise, force fullscreen mode.
+     */
+    QuartzSetFullscreen(reqMode.refresh != FAKE_REFRESH_ROOTLESS);
+    QuartzSetRootless(reqMode.refresh == FAKE_REFRESH_ROOTLESS);
 
     if (pQuartzScreen->displayCount == 0)
         return FALSE;
@@ -341,38 +333,80 @@ static Bool QuartzRandRSetConfig (ScreenPtr           pScreen,
         /* RandR operations are not well-defined for an X11 screen spanning
            multiple CG displays. Do not accept any configuations that differ
            from the current configuration. */
-        return QuartzRandRModesEqual(&reqMode, &pQuartzScreen->originalMode);
+        return TRUE;
     }
-    screenId = pQuartzScreen->displayIDs[0];
 
     /* Do not switch modes if requested mode is equal to current mode. */
-    if (!QuartzRandRGetCurrentModeInfo(screenId, &curMode))
-        return FALSE;
-    if (QuartzRandRModesEqual(&reqMode, &curMode))
+    if (QuartzRandRModesEqual(&reqMode, &pQuartzScreen->currentMode))
         return TRUE;
+        
+    screenId = pQuartzScreen->displayIDs[0];
+    if (QuartzRandREnumerateModes(pScreen, screenId, QuartzRandRSetModeCallback, &reqMode)) {
+        pQuartzScreen->currentMode = reqMode;
+        return TRUE;
+    }
+    
+    DEBUG_LOG("Unable to find a matching config: %d x %d @ %d\n", (int)reqMode.width, (int)reqMode.height, (int)reqMode.refresh);
 
-    return QuartzRandREnumerateModes(pScreen, screenId,
-        QuartzRandRSetModeCallback, &reqMode);
+    return FALSE;
 }
 
-Bool QuartzRandRInit (ScreenPtr pScreen) {
-    rrScrPrivPtr    pScrPriv;
+static Bool _QuartzRandRUpdateFakeModes (ScreenPtr pScreen) {
     QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
-    
-    if (!RRScreenInit (pScreen)) return FALSE;
 
     if (pQuartzScreen->displayCount == 1) {
         if (!QuartzRandRGetCurrentModeInfo(pQuartzScreen->displayIDs[0],
-                                           &pQuartzScreen->originalMode))
+                                           &pQuartzScreen->fullScreenMode))
             return FALSE;
+    } else {
+        pQuartzScreen->fullScreenMode.width = pScreen->width;
+        pQuartzScreen->fullScreenMode.height = pScreen->height;
+        if(quartzEnableRootless)
+            pQuartzScreen->fullScreenMode.height += aquaMenuBarHeight;
     }
-    else {
-        pQuartzScreen->originalMode.width = pScreen->width;
-        pQuartzScreen->originalMode.height = pScreen->height;
-        pQuartzScreen->originalMode.refresh = DEFAULT_REFRESH;
+
+    pQuartzScreen->fullScreenMode.refresh = FAKE_REFRESH_FULLSCREEN;
+
+    pQuartzScreen->rootlessMode = pQuartzScreen->fullScreenMode;
+    pQuartzScreen->rootlessMode.refresh = FAKE_REFRESH_ROOTLESS;
+    pQuartzScreen->rootlessMode.height -= aquaMenuBarHeight;
+
+    if(quartzEnableRootless) {
+        pQuartzScreen->currentMode = pQuartzScreen->rootlessMode;
+    } else {
+        pQuartzScreen->currentMode = pQuartzScreen->fullScreenMode;
     }
-    pQuartzScreen->fakeMode = pQuartzScreen->originalMode;
-    pQuartzScreen->fakeMode.height -= aquaMenuBarHeight;
+    
+    DEBUG_LOG("rootlessMode: %d x %d\n", (int)pQuartzScreen->rootlessMode.width, (int)pQuartzScreen->rootlessMode.height);
+    DEBUG_LOG("fullScreenMode: %d x %d\n", (int)pQuartzScreen->fullScreenMode.width, (int)pQuartzScreen->fullScreenMode.height);
+    DEBUG_LOG("currentMode: %d x %d\n", (int)pQuartzScreen->currentMode.width, (int)pQuartzScreen->currentMode.height);
+    
+    return TRUE;
+}
+
+Bool QuartzRandRUpdateFakeModes (BOOL force_update) {
+    ScreenPtr pScreen = screenInfo.screens[0];
+    
+    if(ignore_next_fake_mode_update) {
+        DEBUG_LOG("Ignoring update request caused by RandR resolution change.\n");
+        ignore_next_fake_mode_update = FALSE;
+        return TRUE;
+    }
+    
+    if(!_QuartzRandRUpdateFakeModes(pScreen))
+        return FALSE;
+    
+    if(force_update)
+        RRGetInfo(pScreen, TRUE);
+
+    return TRUE;
+}
+
+Bool QuartzRandRInit (ScreenPtr pScreen) {
+    rrScrPrivPtr    pScrPriv;
+    
+    if (!RRScreenInit (pScreen)) return FALSE;
+    if (!_QuartzRandRUpdateFakeModes (pScreen)) return FALSE;
 
     pScrPriv = rrGetScrPriv(pScreen);
     pScrPriv->rrGetInfo = QuartzRandRGetInfo;
diff --git a/hw/xquartz/quartzRandR.h b/hw/xquartz/quartzRandR.h
index d57dc3b..8ee2818 100644
--- a/hw/xquartz/quartzRandR.h
+++ b/hw/xquartz/quartzRandR.h
@@ -31,6 +31,30 @@
 #ifndef _QUARTZRANDR_H_
 #define _QUARTZRANDR_H_
 
+typedef struct {
+    size_t width, height;
+    int refresh;
+    const void *ref;
+} QuartzModeInfo, *QuartzModeInfoPtr;
+
+// Quartz specific per screen storage structure
+typedef struct {
+    // List of CoreGraphics displays that this X11 screen covers.
+    // This is more than one CG display for video mirroring and
+    // rootless PseudoramiX mode.
+    // No CG display will be covered by more than one X11 screen.
+    int displayCount;
+    CGDirectDisplayID *displayIDs;
+    QuartzModeInfo rootlessMode, fullScreenMode, currentMode;
+} QuartzScreenRec, *QuartzScreenPtr;
+
+#define QUARTZ_PRIV(pScreen) \
+    ((QuartzScreenPtr)dixLookupPrivate(&pScreen->devPrivates, quartzScreenKey))
+
+void QuartzCopyDisplayIDs(ScreenPtr pScreen,
+                          int displayCount, CGDirectDisplayID *displayIDs);
+
+Bool QuartzRandRUpdateFakeModes (BOOL force_update);
 Bool QuartzRandRInit (ScreenPtr pScreen);
 
 #endif
diff --git a/hw/xquartz/xpr/xprScreen.c b/hw/xquartz/xpr/xprScreen.c
index 0e36ee1..b3ac693 100644
--- a/hw/xquartz/xpr/xprScreen.c
+++ b/hw/xquartz/xpr/xprScreen.c
@@ -36,6 +36,7 @@
 #include "quartzCommon.h"
 #include "inputstr.h"
 #include "quartz.h"
+#include "quartzRandR.h"
 #include "xpr.h"
 #include "xprEvent.h"
 #include "pseudoramiX.h"
commit 16083d38acaea3e9835e1b46eb45e608cc831b32
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Sun Jul 25 22:25:49 2010 -0700

    XQuartz: RandR: Use deprecated CG APIs only on Leopard and earlier
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/hw/xquartz/quartzRandR.c b/hw/xquartz/quartzRandR.c
index b3b315c..e46e904 100644
--- a/hw/xquartz/quartzRandR.c
+++ b/hw/xquartz/quartzRandR.c
@@ -1,9 +1,9 @@
 /*
- *
  * Quartz-specific support for the XRandR extension
  *
  * Copyright (c) 2001-2004 Greg Parker and Torrey T. Lyons,
  *               2010      Jan Hauffa.
+ *               2010      Apple Inc.
  *                 All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -39,6 +39,8 @@
 #include "quartzRandR.h"
 #include "quartz.h"
 
+#include <AvailabilityMacros.h>
+
 #include <X11/extensions/randr.h>
 #include <randrstr.h>
 #include <IOKit/graphics/IOGraphicsTypes.h>
@@ -51,7 +53,7 @@ typedef Bool (*QuartzModeCallback)
     (ScreenPtr, CGDirectDisplayID, QuartzModeInfoPtr, void *);
 
 
-#if defined(USE_DEPRECATED_CG_API)
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
 
 static long getDictLong (CFDictionaryRef dictRef, CFStringRef key) {
     long value;
@@ -140,7 +142,7 @@ static Bool QuartzRandREnumerateModes (ScreenPtr pScreen,
     return TRUE;
 }
 
-#else  /* defined(USE_DEPRECATED_CG_API) */
+#else /* we have the new CG APIs from Snow Leopard */
 
 static void QuartzRandRGetModeInfo (CGDisplayModeRef modeRef,
                                     QuartzModeInfoPtr pMode) {
@@ -220,7 +222,7 @@ static Bool QuartzRandREnumerateModes (ScreenPtr pScreen,
     return TRUE;
 }
 
-#endif  /* defined(USE_DEPRECATED_CG_API) */
+#endif  /* Snow Leopard CoreGraphics APIs */
 
 
 static Bool QuartzRandRModesEqual (QuartzModeInfoPtr pMode1,
diff --git a/hw/xquartz/quartzRandR.h b/hw/xquartz/quartzRandR.h
index 711c3f3..d57dc3b 100644
--- a/hw/xquartz/quartzRandR.h
+++ b/hw/xquartz/quartzRandR.h
@@ -2,6 +2,7 @@
  * quartzRandR.h
  *
  * Copyright (c) 2010 Jan Hauffa.
+ *               2010 Apple Inc.
  *                 All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -27,6 +28,9 @@
  * use or other dealings in this Software without prior written authorization.
  */
 
-#define USE_DEPRECATED_CG_API 1
+#ifndef _QUARTZRANDR_H_
+#define _QUARTZRANDR_H_
 
 Bool QuartzRandRInit (ScreenPtr pScreen);
+
+#endif
commit 50c877be2bf55d90858d3ee5ff2bb297255d2c3c
Author: Jan Hauffa <hauffa at in.tum.de>
Date:   Fri Jul 16 17:56:44 2010 +0200

    XQuartz: RandR: Remove FAKE_RANDR code.
    
    Signed-off-by: Jan Hauffa <hauffa at in.tum.de>
    Reviewed-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/hw/xquartz/quartz.c b/hw/xquartz/quartz.c
index a4d7474..a52cac9 100644
--- a/hw/xquartz/quartz.c
+++ b/hw/xquartz/quartz.c
@@ -119,7 +119,7 @@ Bool QuartzSetupScreen(
     if (! quartzProcs->InitCursor(pScreen))
         return FALSE;
 
-#if defined(RANDR) && !defined(FAKE_RANDR)
+#if defined(RANDR)
     if(!QuartzRandRInit(pScreen)) {
         DEBUG_LOG("Failed to init RandR extension.\n");
         return FALSE;
@@ -239,10 +239,6 @@ void QuartzUpdateScreens(void) {
     DeliverEvents(pRoot, &e, 1, NullWindow);
 
     quartzProcs->UpdateScreen(pScreen);
-    
-#ifdef FAKE_RANDR
-    RREditConnectionInfo(pScreen);
-#endif    
 }
 
 void QuartzSetFullscreen(Bool state) {
diff --git a/hw/xquartz/quartzRandR.c b/hw/xquartz/quartzRandR.c
index f61ff93..b3b315c 100644
--- a/hw/xquartz/quartzRandR.c
+++ b/hw/xquartz/quartzRandR.c
@@ -39,60 +39,10 @@
 #include "quartzRandR.h"
 #include "quartz.h"
 
-#if defined(FAKE_RANDR)
-#include "scrnintstr.h"
-#include "windowstr.h"
-#else
 #include <X11/extensions/randr.h>
 #include <randrstr.h>
 #include <IOKit/graphics/IOGraphicsTypes.h>
-#endif
-
-
-#if defined(FAKE_RANDR)
-
-static const int padlength[4] = {0, 3, 2, 1};
-
-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;
-}
 
-#else  /* defined(FAKE_RANDR) */
 
 #define DEFAULT_REFRESH  60
 #define kDisplayModeUsableFlags  (kDisplayModeValidFlag | kDisplayModeSafeFlag)
@@ -427,5 +377,3 @@ Bool QuartzRandRInit (ScreenPtr pScreen) {
     pScrPriv->rrSetConfig = QuartzRandRSetConfig;
     return TRUE;
 }
-
-#endif  /* defined(FAKE_RANDR) */
diff --git a/hw/xquartz/quartzRandR.h b/hw/xquartz/quartzRandR.h
index a190205..711c3f3 100644
--- a/hw/xquartz/quartzRandR.h
+++ b/hw/xquartz/quartzRandR.h
@@ -27,11 +27,6 @@
  * use or other dealings in this Software without prior written authorization.
  */
 
-/*define FAKE_RANDR 1*/
 #define USE_DEPRECATED_CG_API 1
 
-#if defined(FAKE_RANDR)
-void RREditConnectionInfo (ScreenPtr pScreen);
-#else
 Bool QuartzRandRInit (ScreenPtr pScreen);
-#endif
commit b28e0b0b51801e3c7657f18db683da17256a956d
Author: Jan Hauffa <hauffa at in.tum.de>
Date:   Fri Jul 16 17:54:55 2010 +0200

    XQuartz: RandR: Toggle rootless mode on XRandR mode switch.
    
    Report a fake screen mode that corresponds to the screen mode at startup of the
    server excluding the height of the menu bar. If a client requests this mode,
    rootless mode is enabled. In all other modes, the root window is shown.
    
    Signed-off-by: Jan Hauffa <hauffa at in.tum.de>
    Reviewed-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/hw/xquartz/quartzCommon.h b/hw/xquartz/quartzCommon.h
index d0d358b..851e74c 100644
--- a/hw/xquartz/quartzCommon.h
+++ b/hw/xquartz/quartzCommon.h
@@ -38,6 +38,12 @@
 #include <X11/Xdefs.h>
 #include "privates.h"
 
+typedef struct {
+    size_t width, height;
+    int refresh;
+    const void *ref;
+} QuartzModeInfo, *QuartzModeInfoPtr;
+
 // Quartz specific per screen storage structure
 typedef struct {
     // List of CoreGraphics displays that this X11 screen covers.
@@ -46,6 +52,7 @@ typedef struct {
     // No CG display will be covered by more than one X11 screen.
     int displayCount;
     CGDirectDisplayID *displayIDs;
+    QuartzModeInfo originalMode, fakeMode;
 } QuartzScreenRec, *QuartzScreenPtr;
 
 #define QUARTZ_PRIV(pScreen) \
diff --git a/hw/xquartz/quartzRandR.c b/hw/xquartz/quartzRandR.c
index 6747752..f61ff93 100644
--- a/hw/xquartz/quartzRandR.c
+++ b/hw/xquartz/quartzRandR.c
@@ -37,6 +37,7 @@
 
 #include "quartzCommon.h"
 #include "quartzRandR.h"
+#include "quartz.h"
 
 #if defined(FAKE_RANDR)
 #include "scrnintstr.h"
@@ -96,12 +97,6 @@ RREditConnectionInfo (ScreenPtr pScreen)
 #define DEFAULT_REFRESH  60
 #define kDisplayModeUsableFlags  (kDisplayModeValidFlag | kDisplayModeSafeFlag)
 
-typedef struct {
-    size_t width, height;
-    int refresh;
-    const void *ref;
-} QuartzModeInfo, *QuartzModeInfoPtr;
-
 typedef Bool (*QuartzModeCallback)
     (ScreenPtr, CGDirectDisplayID, QuartzModeInfoPtr, void *);
 
@@ -289,21 +284,30 @@ static Bool QuartzRandRModesEqual (QuartzModeInfoPtr pMode1,
     return TRUE;
 }
 
-static Bool QuartzRandRGetModeCallback (ScreenPtr pScreen,
-                                        CGDirectDisplayID screenId,
-                                        QuartzModeInfoPtr pMode,
-                                        void *data) {
-    QuartzModeInfoPtr pCurMode = (QuartzModeInfoPtr) data;
-
+static Bool QuartzRandRRegisterMode (ScreenPtr pScreen,
+                                     QuartzModeInfoPtr pMode,
+                                     Bool isCurrentMode) {
     RRScreenSizePtr pSize = RRRegisterSize(pScreen,
         pMode->width, pMode->height, pScreen->mmWidth, pScreen->mmHeight);
     if (pSize) {
         RRRegisterRate(pScreen, pSize, pMode->refresh);
 
-        if (QuartzRandRModesEqual(pMode, pCurMode))
+        if (isCurrentMode)
             RRSetCurrentConfig(pScreen, RR_Rotate_0, pMode->refresh, pSize);
+
+        return TRUE;
     }
-    return TRUE;
+    return FALSE;
+}
+
+static Bool QuartzRandRGetModeCallback (ScreenPtr pScreen,
+                                        CGDirectDisplayID screenId,
+                                        QuartzModeInfoPtr pMode,
+                                        void *data) {
+    QuartzModeInfoPtr pCurMode = (QuartzModeInfoPtr) data;
+
+    return QuartzRandRRegisterMode(pScreen, pMode,
+        QuartzRandRModesEqual(pMode, pCurMode));
 }
 
 static Bool QuartzRandRSetModeCallback (ScreenPtr pScreen,
@@ -329,20 +333,29 @@ static Bool QuartzRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) {
         return FALSE;
     if (pQuartzScreen->displayCount > 1) {
         /* RandR operations are not well-defined for an X11 screen spanning
-           multiple CG displays. Create a single entry for the current virtual
-           resolution. */
-        RRScreenSizePtr pSize = RRRegisterSize(pScreen, pScreen->width,
-            pScreen->height, pScreen->mmWidth, pScreen->mmHeight);
-        if (pSize) {
-            RRRegisterRate(pScreen, pSize, DEFAULT_REFRESH);
-            RRSetCurrentConfig(pScreen, RR_Rotate_0, DEFAULT_REFRESH, pSize);
-        }
+           multiple CG displays. Create two entries for the current virtual
+           resolution including/excluding the menu bar. */
+        QuartzRandRRegisterMode(pScreen, &pQuartzScreen->fakeMode,
+            !quartzHasRoot);
+        QuartzRandRRegisterMode(pScreen, &pQuartzScreen->originalMode,
+            quartzHasRoot);
         return TRUE;
     }
     screenId = pQuartzScreen->displayIDs[0];
 
     if (!QuartzRandRGetCurrentModeInfo(screenId, &curMode))
         return FALSE;
+
+    /* Add a fake mode corresponding to the original resolution excluding the
+       height of the menu bar. */
+    if (!quartzHasRoot &&
+        QuartzRandRModesEqual(&pQuartzScreen->originalMode, &curMode)) {
+        QuartzRandRRegisterMode(pScreen, &pQuartzScreen->fakeMode, TRUE);
+        curMode = pQuartzScreen->fakeMode;
+    }
+    else
+        QuartzRandRRegisterMode(pScreen, &pQuartzScreen->fakeMode, FALSE);
+
     return QuartzRandREnumerateModes(pScreen, screenId,
         QuartzRandRGetModeCallback, &curMode);
 }
@@ -354,6 +367,21 @@ static Bool QuartzRandRSetConfig (ScreenPtr           pScreen,
     QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
     CGDirectDisplayID screenId;
     QuartzModeInfo reqMode, curMode;
+    Bool rootless = FALSE;
+
+    reqMode.width = pSize->width;
+    reqMode.height = pSize->height;
+    reqMode.refresh = rate;
+
+    /* If the client requested the fake screen mode, switch to rootless mode.
+       Switch to fullscreen mode (root window visible) if a real screen mode was
+       requested. */
+    if (QuartzRandRModesEqual(&reqMode, &pQuartzScreen->fakeMode)) {
+        rootless = TRUE;
+        reqMode = pQuartzScreen->originalMode;
+    }
+    QuartzSetFullscreen(!rootless);
+    QuartzSetRootless(rootless);
 
     if (pQuartzScreen->displayCount == 0)
         return FALSE;
@@ -361,15 +389,10 @@ static Bool QuartzRandRSetConfig (ScreenPtr           pScreen,
         /* RandR operations are not well-defined for an X11 screen spanning
            multiple CG displays. Do not accept any configuations that differ
            from the current configuration. */
-        return ((pSize->width == pScreen->width) &&
-                (pSize->height == pScreen->height));
+        return QuartzRandRModesEqual(&reqMode, &pQuartzScreen->originalMode);
     }
     screenId = pQuartzScreen->displayIDs[0];
 
-    reqMode.width = pSize->width;
-    reqMode.height = pSize->height;
-    reqMode.refresh = rate;
-
     /* Do not switch modes if requested mode is equal to current mode. */
     if (!QuartzRandRGetCurrentModeInfo(screenId, &curMode))
         return FALSE;
@@ -382,9 +405,23 @@ static Bool QuartzRandRSetConfig (ScreenPtr           pScreen,
 
 Bool QuartzRandRInit (ScreenPtr pScreen) {
     rrScrPrivPtr    pScrPriv;
+    QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
     
     if (!RRScreenInit (pScreen)) return FALSE;
 
+    if (pQuartzScreen->displayCount == 1) {
+        if (!QuartzRandRGetCurrentModeInfo(pQuartzScreen->displayIDs[0],
+                                           &pQuartzScreen->originalMode))
+            return FALSE;
+    }
+    else {
+        pQuartzScreen->originalMode.width = pScreen->width;
+        pQuartzScreen->originalMode.height = pScreen->height;
+        pQuartzScreen->originalMode.refresh = DEFAULT_REFRESH;
+    }
+    pQuartzScreen->fakeMode = pQuartzScreen->originalMode;
+    pQuartzScreen->fakeMode.height -= aquaMenuBarHeight;
+
     pScrPriv = rrGetScrPriv(pScreen);
     pScrPriv->rrGetInfo = QuartzRandRGetInfo;
     pScrPriv->rrSetConfig = QuartzRandRSetConfig;
commit ecac2d4b47d6230cdd1f34d595ca1939a9e3b9c9
Author: Jan Hauffa <hauffa at in.tum.de>
Date:   Fri Jul 16 17:18:03 2010 +0200

    XQuartz: RandR: Implement basic RandR functionality.
    
    Querying and changing of resolution and refresh rate is supported,
    rotation is not implemented yet.
    
    Signed-off-by: Jan Hauffa <hauffa at in.tum.de>
    Reviewed-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/hw/xquartz/Makefile.am b/hw/xquartz/Makefile.am
index 96b139f..721d272 100644
--- a/hw/xquartz/Makefile.am
+++ b/hw/xquartz/Makefile.am
@@ -34,6 +34,7 @@ libXquartz_la_SOURCES = \
 	quartzCocoa.m \
 	quartzKeyboard.c \
 	quartzStartup.c \
+	quartzRandR.c \
 	threadSafety.c
 
 EXTRA_DIST = \
@@ -49,6 +50,7 @@ EXTRA_DIST = \
 	quartzAudio.h \
 	quartzCommon.h \
 	quartzKeyboard.h \
+	quartzRandR.h \
 	sanitizedCarbon.h \
 	sanitizedCocoa.h \
 	threadSafety.h
diff --git a/hw/xquartz/quartz.c b/hw/xquartz/quartz.c
index eee6151..a4d7474 100644
--- a/hw/xquartz/quartz.c
+++ b/hw/xquartz/quartz.c
@@ -35,6 +35,7 @@
 #endif
 
 #include "quartzCommon.h"
+#include "quartzRandR.h"
 #include "inputstr.h"
 #include "quartz.h"
 #include "darwin.h"
@@ -46,7 +47,6 @@
 #include "X11Application.h"
 
 #include <X11/extensions/applewmconst.h>
-#include <X11/extensions/randr.h>
 
 // X headers
 #include "scrnintstr.h"
@@ -56,6 +56,8 @@
 #include "mi.h"
 
 // System headers
+#include <stdlib.h>
+#include <string.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -64,8 +66,6 @@
 #include <rootlessCommon.h>
 #include <Xplugin.h>
 
-#define FAKE_RANDR 1
-
 // Shared global variables for Quartz modes
 int                     quartzUseSysBeep = 0;
 int                     quartzServerVisible = FALSE;
@@ -76,30 +76,6 @@ const char             *quartzOpenGLBundle = NULL;
 int                     quartzFullscreenDisableHotkeys = TRUE;
 int                     quartzOptionSendsAlt = FALSE;
 
-#if defined(RANDR) && !defined(FAKE_RANDR)
-Bool QuartzRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) {
-  return FALSE;
-}
-
-Bool QuartzRandRSetConfig (ScreenPtr           pScreen,
-			       Rotation            randr,
-			       int                 rate,
-			       RRScreenSizePtr     pSize) {
-  return FALSE;
-}
-
-Bool QuartzRandRInit (ScreenPtr pScreen) {
-  rrScrPrivPtr    pScrPriv;
-    
-  if (!RRScreenInit (pScreen)) return FALSE;
-
-  pScrPriv = rrGetScrPriv(pScreen);
-  pScrPriv->rrGetInfo = QuartzRandRGetInfo;
-  pScrPriv->rrSetConfig = QuartzRandRSetConfig;
-  return TRUE;
-}
-#endif
-
 /*
 ===========================================================================
 
@@ -143,6 +119,13 @@ Bool QuartzSetupScreen(
     if (! quartzProcs->InitCursor(pScreen))
         return FALSE;
 
+#if defined(RANDR) && !defined(FAKE_RANDR)
+    if(!QuartzRandRInit(pScreen)) {
+        DEBUG_LOG("Failed to init RandR extension.\n");
+        return FALSE;
+    }
+#endif
+
     return TRUE;
 }
 
@@ -165,11 +148,6 @@ void QuartzInitOutput(
     if (!dixRegisterPrivateKey(&quartzScreenKeyRec, PRIVATE_SCREEN, 0))
 	FatalError("Failed to alloc quartz screen private.\n");
 
-#if defined(RANDR) && !defined(FAKE_RANDR)
-    if(!QuartzRandRInit(pScreen))
-        FatalError("Failed to init RandR extension.\n");
-#endif
-
     // Do display mode specific initialization
     quartzProcs->DisplayInit();
 }
@@ -191,50 +169,6 @@ void QuartzInitInput(
 }
 
 
-#ifdef FAKE_RANDR
-
-static const 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;
-}
-#endif
-
 void QuartzUpdateScreens(void) {
     ScreenPtr pScreen;
     WindowPtr pRoot;
@@ -255,7 +189,7 @@ void QuartzUpdateScreens(void) {
     pScreen = screenInfo.screens[0];
     
     PseudoramiXResetScreens();
-    quartzProcs->AddPseudoramiXScreens(&x, &y, &width, &height);
+    quartzProcs->AddPseudoramiXScreens(&x, &y, &width, &height, pScreen);
     
     pScreen->x = x;
     pScreen->y = y;
@@ -446,3 +380,19 @@ void QuartzSpaceChanged(uint32_t space_id) {
     /* Do something special here, so we don't depend on quartz-wm for spaces to work... */
     DEBUG_LOG("Space Changed (%u) ... do something interesting...\n", space_id);
 }
+
+/*
+ * QuartzCopyDisplayIDs
+ *  Associate an X11 screen with one or more CoreGraphics display IDs by copying
+ *  the list into a private array. Free the previously copied array, if present.
+ */
+void QuartzCopyDisplayIDs(ScreenPtr pScreen,
+                          int displayCount, CGDirectDisplayID *displayIDs) {
+    QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
+    int size = displayCount * sizeof(CGDirectDisplayID);
+
+    free(pQuartzScreen->displayIDs);
+    pQuartzScreen->displayIDs = malloc(size);
+    memcpy(pQuartzScreen->displayIDs, displayIDs, size);
+    pQuartzScreen->displayCount = displayCount;
+}
diff --git a/hw/xquartz/quartz.h b/hw/xquartz/quartz.h
index b1a3f31..1b924e7 100644
--- a/hw/xquartz/quartz.h
+++ b/hw/xquartz/quartz.h
@@ -62,7 +62,8 @@ typedef void (*ResumeScreenProc)(ScreenPtr pScreen);
 /*
  * Screen state change support
  */
-typedef void (*AddPseudoramiXScreensProc)(int *x, int *y, int *width, int *height);
+typedef void (*AddPseudoramiXScreensProc)
+    (int *x, int *y, int *width, int *height, ScreenPtr pScreen);
 typedef void (*UpdateScreenProc)(ScreenPtr pScreen);
 
 /*
diff --git a/hw/xquartz/quartzCommon.h b/hw/xquartz/quartzCommon.h
index eb761ed..d0d358b 100644
--- a/hw/xquartz/quartzCommon.h
+++ b/hw/xquartz/quartzCommon.h
@@ -51,6 +51,9 @@ typedef struct {
 #define QUARTZ_PRIV(pScreen) \
     ((QuartzScreenPtr)dixLookupPrivate(&pScreen->devPrivates, quartzScreenKey))
 
+void QuartzCopyDisplayIDs(ScreenPtr pScreen,
+                          int displayCount, CGDirectDisplayID *displayIDs);
+
 // User preferences used by Quartz modes
 extern int              quartzUseSysBeep;
 extern int              quartzFullscreenDisableHotkeys;
diff --git a/hw/xquartz/quartzRandR.c b/hw/xquartz/quartzRandR.c
new file mode 100644
index 0000000..6747752
--- /dev/null
+++ b/hw/xquartz/quartzRandR.c
@@ -0,0 +1,394 @@
+/*
+ *
+ * Quartz-specific support for the XRandR extension
+ *
+ * Copyright (c) 2001-2004 Greg Parker and Torrey T. Lyons,
+ *               2010      Jan Hauffa.
+ *                 All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+
+#include "sanitizedCarbon.h"
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "quartzCommon.h"
+#include "quartzRandR.h"
+
+#if defined(FAKE_RANDR)
+#include "scrnintstr.h"
+#include "windowstr.h"
+#else
+#include <X11/extensions/randr.h>
+#include <randrstr.h>
+#include <IOKit/graphics/IOGraphicsTypes.h>
+#endif
+
+
+#if defined(FAKE_RANDR)
+
+static const int padlength[4] = {0, 3, 2, 1};
+
+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;
+}
+
+#else  /* defined(FAKE_RANDR) */
+
+#define DEFAULT_REFRESH  60
+#define kDisplayModeUsableFlags  (kDisplayModeValidFlag | kDisplayModeSafeFlag)
+
+typedef struct {
+    size_t width, height;
+    int refresh;
+    const void *ref;
+} QuartzModeInfo, *QuartzModeInfoPtr;
+
+typedef Bool (*QuartzModeCallback)
+    (ScreenPtr, CGDirectDisplayID, QuartzModeInfoPtr, void *);
+
+
+#if defined(USE_DEPRECATED_CG_API)
+
+static long getDictLong (CFDictionaryRef dictRef, CFStringRef key) {
+    long value;
+
+    CFNumberRef numRef = (CFNumberRef) CFDictionaryGetValue(dictRef, key);
+    if (!numRef)
+        return 0;
+
+    if (!CFNumberGetValue(numRef, kCFNumberLongType, &value))
+        return 0;
+    return value;
+}
+
+static double getDictDouble (CFDictionaryRef dictRef, CFStringRef key) {
+    double value;
+
+    CFNumberRef numRef = (CFNumberRef) CFDictionaryGetValue(dictRef, key);
+    if (!numRef)
+        return 0.0;
+
+    if (!CFNumberGetValue(numRef, kCFNumberDoubleType, &value))
+        return 0.0;
+    return value;
+}
+
+static void QuartzRandRGetModeInfo (CFDictionaryRef modeRef,
+                                    QuartzModeInfoPtr pMode) {
+    pMode->width = (size_t) getDictLong(modeRef, kCGDisplayWidth);
+    pMode->height = (size_t) getDictLong(modeRef, kCGDisplayHeight);
+    pMode->refresh = (int)(getDictDouble(modeRef, kCGDisplayRefreshRate) + 0.5);
+    if (pMode->refresh == 0)
+        pMode->refresh = DEFAULT_REFRESH;
+    pMode->ref = NULL;
+}
+
+static Bool QuartzRandRGetCurrentModeInfo (CGDirectDisplayID screenId,
+                                           QuartzModeInfoPtr pMode) {
+    CFDictionaryRef curModeRef = CGDisplayCurrentMode(screenId);
+    if (!curModeRef)
+        return FALSE;
+
+    QuartzRandRGetModeInfo(curModeRef, pMode);
+    return TRUE;
+}
+
+static Bool QuartzRandRSetMode (CGDirectDisplayID screenId,
+                                QuartzModeInfoPtr pMode) {
+    CFDictionaryRef modeRef = (CFDictionaryRef) pMode->ref;
+    return (CGDisplaySwitchToMode(screenId, modeRef) != kCGErrorSuccess);
+}
+
+static Bool QuartzRandREnumerateModes (ScreenPtr pScreen,
+                                       CGDirectDisplayID screenId,
+                                       QuartzModeCallback callback,
+                                       void *data) {
+    CFDictionaryRef curModeRef, modeRef;
+    long curBpp;
+    CFArrayRef modes;
+    QuartzModeInfo modeInfo;
+    int i;
+
+    curModeRef = CGDisplayCurrentMode(screenId);
+    if (!curModeRef)
+        return FALSE;
+    curBpp = getDictLong(curModeRef, kCGDisplayBitsPerPixel);
+
+    modes = CGDisplayAvailableModes(screenId);
+    if (!modes)
+        return FALSE;
+    for (i = 0; i < CFArrayGetCount(modes); i++) {
+        modeRef = (CFDictionaryRef) CFArrayGetValueAtIndex(modes, i);
+
+        /* Skip modes that are not usable on the current display or have a
+           different pixel encoding than the current mode. */
+        if (((unsigned long) getDictLong(modeRef, kCGDisplayIOFlags) &
+             kDisplayModeUsableFlags) != kDisplayModeUsableFlags)
+            continue;
+        if (getDictLong(modeRef, kCGDisplayBitsPerPixel) != curBpp)
+            continue;
+
+        QuartzRandRGetModeInfo(modeRef, &modeInfo);
+        modeInfo.ref = modeRef;
+        if (!callback(pScreen, screenId, &modeInfo, data))
+            break;
+    }
+    return TRUE;
+}
+
+#else  /* defined(USE_DEPRECATED_CG_API) */
+
+static void QuartzRandRGetModeInfo (CGDisplayModeRef modeRef,
+                                    QuartzModeInfoPtr pMode) {
+    pMode->width = CGDisplayModeGetWidth(modeRef);
+    pMode->height = CGDisplayModeGetHeight(modeRef);
+    pMode->refresh = (int) (CGDisplayModeGetRefreshRate(modeRef) + 0.5);
+    if (pMode->refresh == 0)
+        pMode->refresh = DEFAULT_REFRESH;
+    pMode->ref = NULL;
+}
+
+static Bool QuartzRandRGetCurrentModeInfo (CGDirectDisplayID screenId,
+                                           QuartzModeInfoPtr pMode) {
+    CGDisplayModeRef curModeRef = CGDisplayCopyDisplayMode(screenId);
+    if (!curModeRef)
+        return FALSE;
+
+    QuartzRandRGetModeInfo(curModeRef, pMode);
+    CGDisplayModeRelease(curModeRef);
+    return TRUE;
+}
+
+static Bool QuartzRandRSetMode (CGDirectDisplayID screenId,
+                                QuartzModeInfoPtr pMode) {
+    CGDisplayModeRef modeRef = (CGDisplayModeRef) pMode->ref;
+    if (!modeRef)
+        return FALSE;
+
+    return (CGDisplaySetDisplayMode(screenId, modeRef, NULL) !=
+            kCGErrorSuccess);
+}
+
+static Bool QuartzRandREnumerateModes (ScreenPtr pScreen,
+                                       CGDirectDisplayID screenId,
+                                       QuartzModeCallback callback,
+                                       void *data) {
+    CGDisplayModeRef curModeRef, modeRef;
+    CFStringRef curPixelEnc, pixelEnc;
+    CFComparisonResult pixelEncEqual;
+    CFArrayRef modes;
+    QuartzModeInfo modeInfo;
+    int i;
+
+    curModeRef = CGDisplayCopyDisplayMode(screenId);
+    if (!curModeRef)
+        return FALSE;
+    curPixelEnc = CGDisplayModeCopyPixelEncoding(curModeRef);
+    CGDisplayModeRelease(curModeRef);
+
+    modes = CGDisplayCopyAllDisplayModes(screenId, NULL);
+    if (!modes) {
+        CFRelease(curPixelEnc);
+        return FALSE;
+    }
+    for (i = 0; i < CFArrayGetCount(modes); i++) {
+        modeRef = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
+
+        /* Skip modes that are not usable on the current display or have a
+           different pixel encoding than the current mode. */
+        if ((CGDisplayModeGetIOFlags(modeRef) & kDisplayModeUsableFlags) !=
+            kDisplayModeUsableFlags)
+            continue;
+        pixelEnc = CGDisplayModeCopyPixelEncoding(modeRef);
+        pixelEncEqual = CFStringCompare(pixelEnc, curPixelEnc, 0);
+        CFRelease(pixelEnc);
+        if (pixelEncEqual != kCFCompareEqualTo)
+            continue;
+
+        QuartzRandRGetModeInfo(modeRef, &modeInfo);
+        modeInfo.ref = modeRef;
+        if (!callback(pScreen, screenId, &modeInfo, data))
+            break;
+    }
+    CFRelease(modes);
+
+    CFRelease(curPixelEnc);
+    return TRUE;
+}
+
+#endif  /* defined(USE_DEPRECATED_CG_API) */
+
+
+static Bool QuartzRandRModesEqual (QuartzModeInfoPtr pMode1,
+                                   QuartzModeInfoPtr pMode2) {
+    if (pMode1->width != pMode2->width)
+        return FALSE;
+    if (pMode1->height != pMode2->height)
+        return FALSE;
+    if (pMode1->refresh != pMode2->refresh)
+        return FALSE;
+    return TRUE;
+}
+
+static Bool QuartzRandRGetModeCallback (ScreenPtr pScreen,
+                                        CGDirectDisplayID screenId,
+                                        QuartzModeInfoPtr pMode,
+                                        void *data) {
+    QuartzModeInfoPtr pCurMode = (QuartzModeInfoPtr) data;
+
+    RRScreenSizePtr pSize = RRRegisterSize(pScreen,
+        pMode->width, pMode->height, pScreen->mmWidth, pScreen->mmHeight);
+    if (pSize) {
+        RRRegisterRate(pScreen, pSize, pMode->refresh);
+
+        if (QuartzRandRModesEqual(pMode, pCurMode))
+            RRSetCurrentConfig(pScreen, RR_Rotate_0, pMode->refresh, pSize);
+    }
+    return TRUE;
+}
+
+static Bool QuartzRandRSetModeCallback (ScreenPtr pScreen,
+                                        CGDirectDisplayID screenId,
+                                        QuartzModeInfoPtr pMode,
+                                        void *data) {
+    QuartzModeInfoPtr pReqMode = (QuartzModeInfoPtr) data;
+
+    if (!QuartzRandRModesEqual(pMode, pReqMode))
+        return TRUE;  /* continue enumeration */
+
+    return QuartzRandRSetMode(screenId, pMode);
+}
+
+static Bool QuartzRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) {
+    QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
+    CGDirectDisplayID screenId;
+    QuartzModeInfo curMode;
+
+    *rotations = RR_Rotate_0;  /* TODO: support rotation */
+
+    if (pQuartzScreen->displayCount == 0)
+        return FALSE;
+    if (pQuartzScreen->displayCount > 1) {
+        /* RandR operations are not well-defined for an X11 screen spanning
+           multiple CG displays. Create a single entry for the current virtual
+           resolution. */
+        RRScreenSizePtr pSize = RRRegisterSize(pScreen, pScreen->width,
+            pScreen->height, pScreen->mmWidth, pScreen->mmHeight);
+        if (pSize) {
+            RRRegisterRate(pScreen, pSize, DEFAULT_REFRESH);
+            RRSetCurrentConfig(pScreen, RR_Rotate_0, DEFAULT_REFRESH, pSize);
+        }
+        return TRUE;
+    }
+    screenId = pQuartzScreen->displayIDs[0];
+
+    if (!QuartzRandRGetCurrentModeInfo(screenId, &curMode))
+        return FALSE;
+    return QuartzRandREnumerateModes(pScreen, screenId,
+        QuartzRandRGetModeCallback, &curMode);
+}
+
+static Bool QuartzRandRSetConfig (ScreenPtr           pScreen,
+			          Rotation            randr,
+			          int                 rate,
+			          RRScreenSizePtr     pSize) {
+    QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
+    CGDirectDisplayID screenId;
+    QuartzModeInfo reqMode, curMode;
+
+    if (pQuartzScreen->displayCount == 0)
+        return FALSE;
+    if (pQuartzScreen->displayCount > 1) {
+        /* RandR operations are not well-defined for an X11 screen spanning
+           multiple CG displays. Do not accept any configuations that differ
+           from the current configuration. */
+        return ((pSize->width == pScreen->width) &&
+                (pSize->height == pScreen->height));
+    }
+    screenId = pQuartzScreen->displayIDs[0];
+
+    reqMode.width = pSize->width;
+    reqMode.height = pSize->height;
+    reqMode.refresh = rate;
+
+    /* Do not switch modes if requested mode is equal to current mode. */
+    if (!QuartzRandRGetCurrentModeInfo(screenId, &curMode))
+        return FALSE;
+    if (QuartzRandRModesEqual(&reqMode, &curMode))
+        return TRUE;
+
+    return QuartzRandREnumerateModes(pScreen, screenId,
+        QuartzRandRSetModeCallback, &reqMode);
+}
+
+Bool QuartzRandRInit (ScreenPtr pScreen) {
+    rrScrPrivPtr    pScrPriv;
+    
+    if (!RRScreenInit (pScreen)) return FALSE;
+
+    pScrPriv = rrGetScrPriv(pScreen);
+    pScrPriv->rrGetInfo = QuartzRandRGetInfo;
+    pScrPriv->rrSetConfig = QuartzRandRSetConfig;
+    return TRUE;
+}
+
+#endif  /* defined(FAKE_RANDR) */
diff --git a/hw/xquartz/quartzRandR.h b/hw/xquartz/quartzRandR.h
new file mode 100644
index 0000000..a190205
--- /dev/null
+++ b/hw/xquartz/quartzRandR.h
@@ -0,0 +1,37 @@
+/*
+ * quartzRandR.h
+ *
+ * Copyright (c) 2010 Jan Hauffa.
+ *                 All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+
+/*define FAKE_RANDR 1*/
+#define USE_DEPRECATED_CG_API 1
+
+#if defined(FAKE_RANDR)
+void RREditConnectionInfo (ScreenPtr pScreen);
+#else
+Bool QuartzRandRInit (ScreenPtr pScreen);
+#endif
diff --git a/hw/xquartz/xpr/xprScreen.c b/hw/xquartz/xpr/xprScreen.c
index 87e97d4..0e36ee1 100644
--- a/hw/xquartz/xpr/xprScreen.c
+++ b/hw/xquartz/xpr/xprScreen.c
@@ -176,7 +176,7 @@ displayScreenBounds(CGDirectDisplayID id)
  *  with PseudoramiX.
  */
 static void
-xprAddPseudoramiXScreens(int *x, int *y, int *width, int *height)
+xprAddPseudoramiXScreens(int *x, int *y, int *width, int *height, ScreenPtr pScreen)
 {
     CGDisplayCount i, displayCount;
     CGDirectDisplayID *displayList = NULL;
@@ -199,6 +199,7 @@ xprAddPseudoramiXScreens(int *x, int *y, int *width, int *height)
     if(!displayList)
         FatalError("Unable to allocate memory for list of displays.\n");
     CGGetActiveDisplayList(displayCount, displayList, &displayCount);
+    QuartzCopyDisplayIDs(pScreen, displayCount, displayList);
 
     /* Get the union of all screens */
     for (i = 0; i < displayCount; i++) {
@@ -336,6 +337,7 @@ xprAddScreen(int index, ScreenPtr pScreen)
         ErrorF("Warning: noPseudoramiXExtension!\n");
         
         dpy = displayAtIndex(index);
+        QuartzCopyDisplayIDs(pScreen, 1, &dpy);
 
         frame = displayScreenBounds(dpy);
 
@@ -346,7 +348,7 @@ xprAddScreen(int index, ScreenPtr pScreen)
     }
     else
     {
-        xprAddPseudoramiXScreens(&dfb->x, &dfb->y, &dfb->width, &dfb->height);
+        xprAddPseudoramiXScreens(&dfb->x, &dfb->y, &dfb->width, &dfb->height, pScreen);
     }
 
     /* Passing zero width (pitch) makes miCreateScreenResources set the
commit 5d1d9d9ae39fab2ee2ac085f9776f82768828dc8
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Sun Aug 1 11:41:58 2010 -0700

    XQuartz: xpr: Bail on errors during unlock and destroy
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/hw/xquartz/xpr/xprFrame.c b/hw/xquartz/xpr/xprFrame.c
index 9f5d8a6..42f06ef 100644
--- a/hw/xquartz/xpr/xprFrame.c
+++ b/hw/xquartz/xpr/xprFrame.c
@@ -206,13 +206,16 @@ xprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen,
 static void
 xprDestroyFrame(RootlessFrameID wid)
 {
+    xp_error err;
     TA_SERVER();
     
     pthread_mutex_lock(&window_hash_mutex);
     x_hash_table_remove(window_hash, wid);
     pthread_mutex_unlock(&window_hash_mutex);
 
-    xp_destroy_window(x_cvt_vptr_to_uint(wid));
+    err = xp_destroy_window(x_cvt_vptr_to_uint(wid));
+    if (err != Success)
+        FatalError("Could not destroy window %i.", (int)x_cvt_vptr_to_uint(wid));
 }
 
 
@@ -366,9 +369,12 @@ xprStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow)
 static void
 xprStopDrawing(RootlessFrameID wid, Bool flush)
 {
+    xp_error err;
     TA_SERVER();
     
-    xp_unlock_window(x_cvt_vptr_to_uint(wid), flush);
+    err = xp_unlock_window(x_cvt_vptr_to_uint(wid), flush);
+    if(err != Success)
+        FatalError("Could not unlock window %i after drawing.", (int)x_cvt_vptr_to_uint(wid));
 }
 
 
commit ee7fd8fc58d9fadfbb92302ddea224537f068538
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Sun Aug 1 11:39:14 2010 -0700

    XQuartz: UpdateScreen at the end of SetRootless
    
    This will ensure that pRoot is unlocked after the miPaintWindow
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/hw/xquartz/quartz.c b/hw/xquartz/quartz.c
index bdaa262..eee6151 100644
--- a/hw/xquartz/quartz.c
+++ b/hw/xquartz/quartz.c
@@ -265,7 +265,6 @@ void QuartzUpdateScreens(void) {
     pScreen->height = height;
     
     DarwinAdjustScreenOrigins(&screenInfo);
-    quartzProcs->UpdateScreen(pScreen);
     
     /* DarwinAdjustScreenOrigins or UpdateScreen may change pScreen->x/y,
      * so use it rather than x/y
@@ -277,6 +276,7 @@ void QuartzUpdateScreens(void) {
     pRoot = pScreen->root;
     AppleWMSetScreenOrigin(pRoot);
     pScreen->ResizeWindow(pRoot, x - sx, y - sy, width, height, NULL);
+
     miPaintWindow(pRoot, &pRoot->borderClip,  PW_BACKGROUND);
 
     /* <rdar://problem/7770779> pointer events are clipped to old display region after display reconfiguration
@@ -303,6 +303,8 @@ void QuartzUpdateScreens(void) {
     e.u.configureNotify.borderWidth = wBorderWidth(pRoot);
     e.u.configureNotify.override = pRoot->overrideRedirect;
     DeliverEvents(pRoot, &e, 1, NullWindow);
+
+    quartzProcs->UpdateScreen(pScreen);
     
 #ifdef FAKE_RANDR
     RREditConnectionInfo(pScreen);
commit 4fc4cab98d454afbfd0d2f48548b5b481e8e7c82
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Thu Jul 29 14:49:10 2010 -0700

    XQuartz: Make application switching work better for the no-spaces case
    
    We still have the issue with not raising the frontmost window for the case
    when spaces is enabled, and the AppleSpacesSwitchOnActivate preference is
    disabled.
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/hw/xquartz/X11Application.m b/hw/xquartz/X11Application.m
index 805ed99..36c39e5 100644
--- a/hw/xquartz/X11Application.m
+++ b/hw/xquartz/X11Application.m
@@ -337,7 +337,7 @@ static void message_kit_thread (SEL selector, NSObject *arg) {
                 case NSApplicationActivatedEventType:
                     for_x = NO;
                     if ([self modalWindow] == nil) {
-                        BOOL switch_on_activate, ok;
+                        BOOL order_all_windows = YES, workspaces, ok;
                         for_appkit = NO;
                         
                         /* FIXME: hack to avoid having to pass the event to appkit,
@@ -347,13 +347,27 @@ static void message_kit_thread (SEL selector, NSObject *arg) {
                         [self activateX:YES];
                         
                         /* Get the Spaces preference for SwitchOnActivate */
-                        (void)CFPreferencesAppSynchronize(CFSTR(".GlobalPreferences"));
-                        switch_on_activate = CFPreferencesGetAppBooleanValue(CFSTR("AppleSpacesSwitchOnActivate"), CFSTR(".GlobalPreferences"), &ok);
-                        if(!ok)
-                            switch_on_activate = YES;
+                        (void)CFPreferencesAppSynchronize(CFSTR("com.apple.dock"));
+                        workspaces = CFPreferencesGetAppBooleanValue(CFSTR("workspaces"), CFSTR("com.apple.dock"), &ok);
+                        if (!ok)
+                            workspaces = NO;
+
+                        if (workspaces) {
+                            (void)CFPreferencesAppSynchronize(CFSTR(".GlobalPreferences"));
+                            order_all_windows = CFPreferencesGetAppBooleanValue(CFSTR("AppleSpacesSwitchOnActivate"), CFSTR(".GlobalPreferences"), &ok);
+                            if (!ok)
+                                order_all_windows = YES;
+                        }
                         
-                        if ([e data2] & 0x10 && switch_on_activate) // 0x10 is set when we use cmd-tab or the dock icon
-                            DarwinSendDDXEvent(kXquartzBringAllToFront, 0);
+                        /* TODO: In the workspaces && !AppleSpacesSwitchOnActivate case, the windows are ordered
+                         *       correctly, but we need to activate the top window on this space if there is
+                         *       none active.
+                         *
+                         *       If there are no active windows, and there are minimized windows, we should
+                         *       be restoring one of them.
+                         */
+                        if ([e data2] & 0x10) // 0x10 is set when we use cmd-tab or the dock icon
+                            DarwinSendDDXEvent(kXquartzBringAllToFront, 1, order_all_windows);
                     }
                     break;
                     
diff --git a/hw/xquartz/xpr/xprEvent.c b/hw/xquartz/xpr/xprEvent.c
index 6245cce..342b54c 100644
--- a/hw/xquartz/xpr/xprEvent.c
+++ b/hw/xquartz/xpr/xprEvent.c
@@ -73,7 +73,7 @@ Bool QuartzModeEventHandler(int screenNum, XQuartzEvent *e, DeviceIntPtr dev) {
             
         case kXquartzBringAllToFront:
             DEBUG_LOG("kXquartzBringAllToFront\n");
-            RootlessOrderAllWindows();
+            RootlessOrderAllWindows(e->data[0]);
             return TRUE;
         default:
             return FALSE;
diff --git a/miext/rootless/rootless.h b/miext/rootless/rootless.h
index 00eac4e..dc4213f 100644
--- a/miext/rootless/rootless.h
+++ b/miext/rootless/rootless.h
@@ -444,7 +444,7 @@ void RootlessUpdateScreenPixmap(ScreenPtr pScreen);
 void RootlessRepositionWindows(ScreenPtr pScreen);
 
 /*
- * Bring all windows to the front of the Aqua stack
+ * Bring all windows to the front of the native stack
  */
-void RootlessOrderAllWindows (void);
+void RootlessOrderAllWindows (Bool include_unhitable);
 #endif /* _ROOTLESS_H */
diff --git a/miext/rootless/rootlessWindow.c b/miext/rootless/rootlessWindow.c
index bef8a2f..c1c6bdb 100644
--- a/miext/rootless/rootlessWindow.c
+++ b/miext/rootless/rootlessWindow.c
@@ -581,10 +581,15 @@ RootlessReorderWindow(WindowPtr pWin)
 
         RootlessStopDrawing(pWin, FALSE);
 
-        /* Find the next window above this one that has a mapped frame. */
+        /* Find the next window above this one that has a mapped frame. 
+         * Only include cases where the windows are in the same category of
+         * hittability to ensure offscreen windows dont get restacked
+         * relative to onscreen ones (but that the offscreen ones maintain
+         * their stacking order if they are explicitly asked to Reorder
+         */
 
         newPrevW = pWin->prevSib;
-        while (newPrevW && (WINREC(newPrevW) == NULL || !newPrevW->realized))
+        while (newPrevW && (WINREC(newPrevW) == NULL || !newPrevW->realized || newPrevW->rootlessUnhittable != pWin->rootlessUnhittable))
             newPrevW = newPrevW->prevSib;
 
         newPrev = newPrevW != NULL ? WINREC(newPrevW) : NULL;
@@ -1502,7 +1507,7 @@ RootlessChangeBorderWidth(WindowPtr pWin, unsigned int width)
  * (i.e in front of Aqua windows) -- called when X11.app is given focus
  */
 void
-RootlessOrderAllWindows (void)
+RootlessOrderAllWindows (Bool include_unhitable)
 {
     int i;
     WindowPtr pWin;
@@ -1519,6 +1524,7 @@ RootlessOrderAllWindows (void)
       for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) {
 	if (!pWin->realized) continue;
 	if (RootlessEnsureFrame(pWin) == NULL) continue;
+        if (!include_unhitable && pWin->rootlessUnhittable) continue;
 	RootlessReorderWindow (pWin);
       }
     }
commit e5bc62a03289f956c54c4699edf47f7ff237b5be
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Sun Jul 25 22:29:11 2010 -0700

    XQuartz: Ignore kXquartzToggleFullscreen when rootless
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/hw/xquartz/darwinEvents.c b/hw/xquartz/darwinEvents.c
index 147b32a..7b34b8a 100644
--- a/hw/xquartz/darwinEvents.c
+++ b/hw/xquartz/darwinEvents.c
@@ -238,8 +238,8 @@ static void DarwinEventHandler(int screenNum, InternalEvent *ie, DeviceIntPtr de
             
         case kXquartzToggleFullscreen:
             DEBUG_LOG("kXquartzToggleFullscreen\n");
-            if (quartzEnableRootless) 
-                QuartzSetFullscreen(!quartzHasRoot);
+            if(quartzEnableRootless) 
+                ErrorF("Ignoring kXquartzToggleFullscreen because of rootless mode.");
             else if (quartzHasRoot)
                 QuartzHide();
             else
commit 71af1f71c0492c365707c6b3810f94642ff39352
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Aug 12 23:01:59 2010 -0700

    Bump to version 1.8.99.906 (1.9 RC6)
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/configure.ac b/configure.ac
index 23a0f10..1f4eb34 100644
--- a/configure.ac
+++ b/configure.ac
@@ -26,8 +26,8 @@ dnl
 dnl Process this file with autoconf to create configure.
 
 AC_PREREQ(2.57)
-AC_INIT([xorg-server], 1.8.99.905, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server)
-RELEASE_DATE="2010-07-14"
+AC_INIT([xorg-server], 1.8.99.906, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server)
+RELEASE_DATE="2010-08-12"
 AC_CONFIG_SRCDIR([Makefile.am])
 AM_INIT_AUTOMAKE([foreign dist-bzip2])
 AM_MAINTAINER_MODE
commit 0af322858e86665ee43f065741318e69c2755510
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Aug 12 22:56:36 2010 -0700

    Silence GCC warning about uninitialized lastSlave variable
    
    Not an actual bug, but gcc can't tell that this variable cannot be
    used without being initialized
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index 59c7fc5..8c75301 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@ -1358,7 +1358,7 @@ InjectPointerKeyEvents(DeviceIntPtr dev, int type, int button, int flags, int nu
     ScreenPtr           pScreen;
     EventListPtr        events;
     int                 nevents, i;
-    DeviceIntPtr        ptr, mpointer, lastSlave;
+    DeviceIntPtr        ptr, mpointer, lastSlave = NULL;
     Bool                saveWait;
 
     if (IsMaster(dev)) {
commit b5cf9c5090d15a50b105470900823f2d398d4bd2
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Thu Aug 12 00:09:01 2010 -0700

    Stop checking or calling PtrCtrlProcs
    
    None of them do anything useful now that pointer acceleration is
    entirely handled in the server.   (Does not completely nuke yet,
    since that would be an API/ABI break.)
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/dix/devices.c b/dix/devices.c
index ac5806a..2e65a04 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2111,9 +2111,6 @@ ProcChangePointerControl(ClientPtr client)
     REQUEST(xChangePointerControlReq);
     REQUEST_SIZE_MATCH(xChangePointerControlReq);
 
-    if (!mouse->ptrfeed->CtrlProc)
-        return BadDevice;
-
     ctrl = mouse->ptrfeed->ctrl;
     if ((stuff->doAccel != xTrue) && (stuff->doAccel != xFalse)) {
 	client->errorValue = stuff->doAccel;
@@ -2161,7 +2158,7 @@ ProcChangePointerControl(ClientPtr client)
 
     for (dev = inputInfo.devices; dev; dev = dev->next) {
         if ((dev == mouse || (!IsMaster(dev) && dev->u.master == mouse)) &&
-            dev->ptrfeed && dev->ptrfeed->CtrlProc) {
+            dev->ptrfeed) {
 	    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess);
 	    if (rc != Success)
 		return rc;
@@ -2170,9 +2167,8 @@ ProcChangePointerControl(ClientPtr client)
 
     for (dev = inputInfo.devices; dev; dev = dev->next) {
         if ((dev == mouse || (!IsMaster(dev) && dev->u.master == mouse)) &&
-            dev->ptrfeed && dev->ptrfeed->CtrlProc) {
+            dev->ptrfeed) {
             dev->ptrfeed->ctrl = ctrl;
-            (*dev->ptrfeed->CtrlProc)(dev, &mouse->ptrfeed->ctrl);
         }
     }
 
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 76d2d00..bd77fe6 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -264,9 +264,6 @@ ApplyAccelerationSettings(DeviceIntPtr dev){
         if (i >= 0)
             dev->ptrfeed->ctrl.threshold = i;
 
-        /* mostly a no-op anyway */
-        (*dev->ptrfeed->CtrlProc)(dev, &dev->ptrfeed->ctrl);
-
         xf86Msg(X_CONFIG, "%s: (accel) acceleration factor: %.3f\n",
                             local->name, ((float)dev->ptrfeed->ctrl.num)/
                                          ((float)dev->ptrfeed->ctrl.den));
commit bce12f2956f23c0ee53f7f6485dba631293a0931
Author: Jesse Adkins <jesserayadkins at gmail.com>
Date:   Wed Aug 4 23:39:14 2010 -0700

    xfree86: parser: Never use constant strings for driver names (fixes #17438)
    
    When the parser sees the "keyboard" driver, it automatically (and
     silently) replaces it with the constant string "kbd".
    Everybody else uses malloc'd memory for the driver name, so input
     device closure assumes it can use free.
    Free val.str, so this crash doesn't turn into a memory leak. Whew.
    
    Signed-off-by: Jesse Adkins <jesserayadkins at gmail.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xfree86/parser/Input.c b/hw/xfree86/parser/Input.c
index 50869d4..faff0f4 100644
--- a/hw/xfree86/parser/Input.c
+++ b/hw/xfree86/parser/Input.c
@@ -59,6 +59,7 @@
 #include <xorg-config.h>
 #endif
 
+#include "os.h"
 #include "xf86Parser.h"
 #include "xf86tokens.h"
 #include "Configint.h"
@@ -102,8 +103,10 @@ xf86parseInputSection (void)
 		case DRIVER:
 			if (xf86getSubToken (&(ptr->inp_comment)) != STRING)
 				Error (QUOTE_MSG, "Driver");
-                        if (strcmp(val.str, "keyboard") == 0)
-                            ptr->inp_driver = "kbd";
+                        if (strcmp(val.str, "keyboard") == 0) {
+                            ptr->inp_driver = strdup("kbd");
+                            free(val.str);
+                        }
                         else
 			    ptr->inp_driver = val.str;
 			break;
diff --git a/hw/xfree86/parser/InputClass.c b/hw/xfree86/parser/InputClass.c
index ce611d9..9f88e7e 100644
--- a/hw/xfree86/parser/InputClass.c
+++ b/hw/xfree86/parser/InputClass.c
@@ -111,8 +111,10 @@ xf86parseInputClassSection(void)
         case DRIVER:
             if (xf86getSubToken(&(ptr->comment)) != STRING)
                 Error(QUOTE_MSG, "Driver");
-            if (strcmp(val.str, "keyboard") == 0)
-                ptr->driver = "kbd";
+            if (strcmp(val.str, "keyboard") == 0) {
+                ptr->driver = strdup("kbd");
+                free(val.str);
+            }
             else
                 ptr->driver = val.str;
             break;
commit 619ca32202cd22f2a408586cbc906b8bbaeb9358
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Wed Jul 28 15:08:27 2010 +1000

    Xi: reset the unused classes pointer after copying
    
    After copying the unused_classes into the device, reset the original
    pointer. Otherwise we have two pointers pointing to the same field and both
    get freed on device removal.
    
    Some classes already have this behaviour since 51c8fd69.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index e990aeb..e19e207 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -223,6 +223,7 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
         {
             classes = to->unused_classes;
             to->intfeed = classes->intfeed;
+            classes->intfeed = NULL;
         }
 
         i = &to->intfeed;
@@ -258,6 +259,7 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
         {
             classes = to->unused_classes;
             to->stringfeed = classes->stringfeed;
+            classes->stringfeed = NULL;
         }
 
         s = &to->stringfeed;
@@ -293,6 +295,7 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
         {
             classes = to->unused_classes;
             to->bell = classes->bell;
+            classes->bell = NULL;
         }
 
         b = &to->bell;
@@ -329,6 +332,7 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
         {
             classes = to->unused_classes;
             to->leds = classes->leds;
+            classes->leds = NULL;
         }
 
         l = &to->leds;
@@ -379,6 +383,7 @@ DeepCopyKeyboardClasses(DeviceIntPtr from, DeviceIntPtr to)
             to->kbdfeed = classes->kbdfeed;
             if (!to->kbdfeed)
                 InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
+            classes->kbdfeed = NULL;
         }
 
         k = &to->kbdfeed;
@@ -506,6 +511,7 @@ DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
         {
             classes = to->unused_classes;
             to->ptrfeed = classes->ptrfeed;
+            classes->ptrfeed = NULL;
         }
 
         p = &to->ptrfeed;
commit 1a172f3297369a72865232c382abfc14281102a4
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Jul 23 13:24:34 2010 +1000

    xkb: if the button isn't down, don't fake an event.
    
    If the button we're about to fake isn't down (or up), don't fake a release
    (or press) event for it. Behaviour is the same as before, this just saves
    a few cycles.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index c36dba0..59c7fc5 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@ -1410,6 +1410,7 @@ void
 XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button)
 {
     DeviceIntPtr        ptr;
+    int                 down;
 
     /* If dev is a slave device, and the SD is attached, do nothing. If we'd
      * post through the attached master pointer we'd get duplicate events.
@@ -1427,6 +1428,10 @@ XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button)
     else
         return;
 
+    down = button_is_down(ptr, button, BUTTON_PROCESSED);
+    if (press == down)
+        return;
+
     InjectPointerKeyEvents(dev, press ? ButtonPress : ButtonRelease,
                            button, 0, 0, NULL);
 }
commit 651c36e95ec0ac60d3fb98966df4218712ae78c2
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Fri Jul 23 11:46:30 2010 +1000

    xkb: post-fix PointerKeys button events with a DeviceChangedEvent.
    
    commit 14327858391ebe929b806efb53ad79e789361883
        xkb: release XTEST pointer buttons on physical releases. (#28808)
    revealed a bug with the XTEST/PointerKeys interaction.
    
    Events resulting from PointerKeys are injected into the event processing
    stream, not appended to the event queue. The events generated for the fake
    button press include a DeviceChangedEvent (DCE), a raw button event and the
    button event itself. The DCE causes the master to switch classes to the
    attached XTEST pointer device.
    
    Once the fake button is processed, normal event processing continues with
    events in the EQ. The master still contains the XTEST classes, causing some
    events to be dropped if e.g. the number of valuators of the event in the
    queue exceeds the XTEST device's number of valuators.
    
    Example: the EQ contains the following events, processed one-by-one, left to
    right.
    
    [DCE (dev)][Btn down][Btn up][Motion][Motion][...]
                      ^ XkbFakeDeviceButton injects [DCE (XTEST)][Btn up]
    
    Thus the event sequence processed looks like this:
    
    [DCE (dev)][Btn down][Btn up][DCE (XTEST)][Btn up][Motion][Motion][...]
    
    The first DCE causes the master to switch to the device. The button up event
    injects a DCE to the XTEST device, causing the following Motion events to be
    processed with the master still being on XTEST classes.
    
    This patch post-fixes the injected event sequence with a DCE to restore the
    classes of the original slave device, resulting in an event sequence like
    this:
    [DCE (dev)][Btn down][Btn up][DCE (XTEST)][Btn up][DCE (dev)][Motion][Motion]
    
    Note that this is a simplified description. The event sequence injected by
    the PointerKeys code is injected for the master device only and the matching
    slave device that caused the injection has already finished processing on
    the slave. Furthermore, the injection happens as part of the the XKB layer,
    before the unwrapping of the processInputProc takes us into the DIX where
    the DCE is actually handled.
    
    Bug reproducible with a device that reports more than 2 valuators. Simply
    cause button releases on the device and wait for a "too many valuators"
    warning message.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Acked-by: Daniel Stone <daniel at fooishbar.org>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/dix/getevents.c b/dix/getevents.c
index a9b6e82..20bcf7e 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -652,8 +652,8 @@ clipValuators(DeviceIntPtr pDev, int first_valuator, int num_valuators,
  *        events if a DCCE was generated.
  * @return The updated @events pointer.
  */
-static EventListPtr
-updateFromMaster(EventListPtr events, DeviceIntPtr dev, int type, int *num_events)
+EventListPtr
+UpdateFromMaster(EventListPtr events, DeviceIntPtr dev, int type, int *num_events)
 {
     DeviceIntPtr master;
 
@@ -929,7 +929,7 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
 
     num_events = 1;
 
-    events = updateFromMaster(events, pDev, DEVCHANGE_KEYBOARD_EVENT, &num_events);
+    events = UpdateFromMaster(events, pDev, DEVCHANGE_KEYBOARD_EVENT, &num_events);
 
     /* Handle core repeating, via press/release/press/release. */
     if (type == KeyPress && key_is_down(pDev, key_code, KEY_POSTED)) {
@@ -1091,7 +1091,7 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
         (type == MotionNotify && num_valuators <= 0))
         return 0;
 
-    events = updateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
+    events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
 
     raw = (RawDeviceEvent*)events->event;
     events++;
@@ -1206,7 +1206,7 @@ GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type,
         (num_valuators + first_valuator) > pDev->valuator->numAxes)
         return 0;
 
-    events = updateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
+    events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
 
     event = (DeviceEvent *) events->event;
     init_event(pDev, event, GetTimeInMillis());
diff --git a/include/input.h b/include/input.h
index 55b1537..ffb1c33 100644
--- a/include/input.h
+++ b/include/input.h
@@ -439,6 +439,12 @@ extern void CreateClassesChangedEvent(EventListPtr event,
                                       DeviceIntPtr master,
                                       DeviceIntPtr slave,
                                       int type);
+extern EventListPtr UpdateFromMaster(
+    EventListPtr events,
+    DeviceIntPtr pDev,
+    int type,
+    int *num_events);
+
 extern _X_EXPORT int GetPointerEvents(
     EventListPtr events,
     DeviceIntPtr pDev,
diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index eea3d4a..c36dba0 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@ -1332,35 +1332,53 @@ xkbStateNotify	sn;
     return;
 }
 
+/*
+ * The event is injected into the event processing, not the EQ. Thus,
+ * ensure that we restore the master after the event sequence to the
+ * original set of classes. Otherwise, the master remains on the XTEST
+ * classes and drops events that don't fit into the XTEST layout (e.g.
+ * events with more than 2 valuators).
+ *
+ * FIXME: EQ injection in the processing stage is not designed for, so this
+ * is a rather awkward hack. The event list returned by GetPointerEvents()
+ * and friends is always prefixed with a DCE if the last _posted_ device was
+ * different. For normal events, this sequence then resets the master during
+ * the processing stage. Since we inject the PointerKey events in the
+ * processing stage though, we need to manually reset to restore the
+ * previous order, because the events already in the EQ must be sent for the
+ * right device.
+ * So we post-fix the event list we get from GPE with a DCE back to the
+ * previous slave device.
+ *
+ * First one on drinking island wins!
+ */
 static void
-XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y)
+InjectPointerKeyEvents(DeviceIntPtr dev, int type, int button, int flags, int num_valuators, int *valuators)
 {
+    ScreenPtr           pScreen;
     EventListPtr        events;
     int                 nevents, i;
-    DeviceIntPtr        ptr;
-    ScreenPtr           pScreen;
+    DeviceIntPtr        ptr, mpointer, lastSlave;
     Bool                saveWait;
-    int                 gpe_flags = 0;
 
-    if (IsMaster(dev))
-        ptr = GetXTestDevice(GetMaster(dev, MASTER_POINTER));
-    else if (!dev->u.master)
+    if (IsMaster(dev)) {
+        mpointer = GetMaster(dev, MASTER_POINTER);
+        lastSlave = mpointer->u.lastSlave;
+        ptr = GetXTestDevice(mpointer);
+    } else if (!dev->u.master)
         ptr = dev;
     else
         return;
 
-    if (flags & XkbSA_MoveAbsoluteX || flags & XkbSA_MoveAbsoluteY)
-        gpe_flags = POINTER_ABSOLUTE;
-    else
-        gpe_flags = POINTER_RELATIVE;
 
-    events = InitEventList(GetMaximumEventsNum());
+    events = InitEventList(GetMaximumEventsNum() + 1);
     OsBlockSignals();
     pScreen = miPointerGetScreen(ptr);
     saveWait = miPointerSetWaitForUpdate(pScreen, FALSE);
-    nevents = GetPointerEvents(events, ptr,
-                               MotionNotify, 0,
-                               gpe_flags, 0, 2, (int[]){x, y});
+    nevents = GetPointerEvents(events, ptr, type, button, flags, 0,
+                               num_valuators, valuators);
+    if (IsMaster(dev) && (lastSlave && lastSlave != ptr))
+        UpdateFromMaster(&events[nevents], lastSlave, DEVCHANGE_POINTER_EVENT, &nevents);
     miPointerSetWaitForUpdate(pScreen, saveWait);
     OsReleaseSignals();
 
@@ -1368,13 +1386,29 @@ XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y)
         mieqProcessDeviceEvent(ptr, (InternalEvent*)events[i].event, NULL);
 
     FreeEventList(events, GetMaximumEventsNum());
+
+}
+
+static void
+XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y)
+{
+    int                 gpe_flags = 0;
+
+    /* ignore attached SDs */
+    if (!IsMaster(dev) && GetMaster(dev, MASTER_POINTER) != NULL)
+        return;
+
+    if (flags & XkbSA_MoveAbsoluteX || flags & XkbSA_MoveAbsoluteY)
+        gpe_flags = POINTER_ABSOLUTE;
+    else
+        gpe_flags = POINTER_RELATIVE;
+
+    InjectPointerKeyEvents(dev, MotionNotify, 0, gpe_flags, 2, (int[]){x, y});
 }
 
 void
 XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button)
 {
-    EventListPtr        events;
-    int                 nevents, i;
     DeviceIntPtr        ptr;
 
     /* If dev is a slave device, and the SD is attached, do nothing. If we'd
@@ -1385,24 +1419,14 @@ XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button)
      * if dev is a floating slave, post through the device itself.
      */
 
-    if (IsMaster(dev))
-        ptr = GetXTestDevice(GetMaster(dev, MASTER_POINTER));
-    else if (!dev->u.master)
+    if (IsMaster(dev)) {
+        DeviceIntPtr mpointer = GetMaster(dev, MASTER_POINTER);
+        ptr = GetXTestDevice(mpointer);
+    } else if (!dev->u.master)
         ptr = dev;
     else
         return;
 
-    events = InitEventList(GetMaximumEventsNum());
-    OsBlockSignals();
-    nevents = GetPointerEvents(events, ptr,
-                               press ? ButtonPress : ButtonRelease, button,
-                               0 /* flags */, 0 /* first */,
-                               0 /* num_val */, NULL);
-    OsReleaseSignals();
-
-
-    for (i = 0; i < nevents; i++)
-        mieqProcessDeviceEvent(ptr, (InternalEvent*)events[i].event, NULL);
-
-    FreeEventList(events, GetMaximumEventsNum());
+    InjectPointerKeyEvents(dev, press ? ButtonPress : ButtonRelease,
+                           button, 0, 0, NULL);
 }
commit 6dae7f3792611aace1df0cca63bf50c50d93de43
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Aug 10 19:30:20 2010 +0100

    xace: Invalid reference to out-of-scope data.
    
    The callback data passed by reference to the hook was allocated on stack
    within the scope of the case statement. The compiler is free to reuse
    any of that stack space whilst making the function call so we may end up
    passing garbage into the callback.
    
    References:
    
      Bug 18451 - Xorg server 1.5.2 SEGV during XFixesGetCursorImage()
      https://bugs.freedesktop.org/show_bug.cgi?id=18451
    
    v2: Drop the unrelated hunk that snuck in when ammending the commit
    message.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
    Reviewed-by: Alan Coopersmith <alan.coopersmith at oracle.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/Xext/xace.c b/Xext/xace.c
index e10d837..c757cad 100644
--- a/Xext/xace.c
+++ b/Xext/xace.c
@@ -87,7 +87,18 @@ void XaceHookAuditEnd(ClientPtr ptr, int result)
  */
 int XaceHook(int hook, ...)
 {
-    pointer calldata;	/* data passed to callback */
+    union {
+	XaceResourceAccessRec res;
+	XaceDeviceAccessRec dev;
+	XaceSendAccessRec send;
+	XaceReceiveAccessRec recv;
+	XaceClientAccessRec client;
+	XaceExtAccessRec ext;
+	XaceServerAccessRec server;
+	XaceScreenAccessRec screen;
+	XaceAuthAvailRec auth;
+	XaceKeyAvailRec key;
+    } u;
     int *prv = NULL;	/* points to return value from callback */
     va_list ap;		/* argument list */
     va_start(ap, hook);
@@ -99,117 +110,86 @@ int XaceHook(int hook, ...)
      */
     switch (hook)
     {
-	case XACE_RESOURCE_ACCESS: {
-	    XaceResourceAccessRec rec;
-	    rec.client = va_arg(ap, ClientPtr);
-	    rec.id = va_arg(ap, XID);
-	    rec.rtype = va_arg(ap, RESTYPE);
-	    rec.res = va_arg(ap, pointer);
-	    rec.ptype = va_arg(ap, RESTYPE);
-	    rec.parent = va_arg(ap, pointer);
-	    rec.access_mode = va_arg(ap, Mask);
-	    rec.status = Success; /* default allow */
-	    calldata = &rec;
-	    prv = &rec.status;
+	case XACE_RESOURCE_ACCESS:
+	    u.res.client = va_arg(ap, ClientPtr);
+	    u.res.id = va_arg(ap, XID);
+	    u.res.rtype = va_arg(ap, RESTYPE);
+	    u.res.res = va_arg(ap, pointer);
+	    u.res.ptype = va_arg(ap, RESTYPE);
+	    u.res.parent = va_arg(ap, pointer);
+	    u.res.access_mode = va_arg(ap, Mask);
+	    u.res.status = Success; /* default allow */
+	    prv = &u.res.status;
 	    break;
-	}
-	case XACE_DEVICE_ACCESS: {
-	    XaceDeviceAccessRec rec;
-	    rec.client = va_arg(ap, ClientPtr);
-	    rec.dev = va_arg(ap, DeviceIntPtr);
-	    rec.access_mode = va_arg(ap, Mask);
-	    rec.status = Success; /* default allow */
-	    calldata = &rec;
-	    prv = &rec.status;
+	case XACE_DEVICE_ACCESS:
+	    u.dev.client = va_arg(ap, ClientPtr);
+	    u.dev.dev = va_arg(ap, DeviceIntPtr);
+	    u.dev.access_mode = va_arg(ap, Mask);
+	    u.dev.status = Success; /* default allow */
+	    prv = &u.dev.status;
 	    break;
-	}
-	case XACE_SEND_ACCESS: {
-	    XaceSendAccessRec rec;
-	    rec.client = va_arg(ap, ClientPtr);
-	    rec.dev = va_arg(ap, DeviceIntPtr);
-	    rec.pWin = va_arg(ap, WindowPtr);
-	    rec.events = va_arg(ap, xEventPtr);
-	    rec.count = va_arg(ap, int);
-	    rec.status = Success; /* default allow */
-	    calldata = &rec;
-	    prv = &rec.status;
+	case XACE_SEND_ACCESS:
+	    u.send.client = va_arg(ap, ClientPtr);
+	    u.send.dev = va_arg(ap, DeviceIntPtr);
+	    u.send.pWin = va_arg(ap, WindowPtr);
+	    u.send.events = va_arg(ap, xEventPtr);
+	    u.send.count = va_arg(ap, int);
+	    u.send.status = Success; /* default allow */
+	    prv = &u.send.status;
 	    break;
-	}
-	case XACE_RECEIVE_ACCESS: {
-	    XaceReceiveAccessRec rec;
-	    rec.client = va_arg(ap, ClientPtr);
-	    rec.pWin = va_arg(ap, WindowPtr);
-	    rec.events = va_arg(ap, xEventPtr);
-	    rec.count = va_arg(ap, int);
-	    rec.status = Success; /* default allow */
-	    calldata = &rec;
-	    prv = &rec.status;
+	case XACE_RECEIVE_ACCESS:
+	    u.recv.client = va_arg(ap, ClientPtr);
+	    u.recv.pWin = va_arg(ap, WindowPtr);
+	    u.recv.events = va_arg(ap, xEventPtr);
+	    u.recv.count = va_arg(ap, int);
+	    u.recv.status = Success; /* default allow */
+	    prv = &u.recv.status;
 	    break;
-	}
-	case XACE_CLIENT_ACCESS: {
-	    XaceClientAccessRec rec;
-	    rec.client = va_arg(ap, ClientPtr);
-	    rec.target = va_arg(ap, ClientPtr);
-	    rec.access_mode = va_arg(ap, Mask);
-	    rec.status = Success; /* default allow */
-	    calldata = &rec;
-	    prv = &rec.status;
+	case XACE_CLIENT_ACCESS:
+	    u.client.client = va_arg(ap, ClientPtr);
+	    u.client.target = va_arg(ap, ClientPtr);
+	    u.client.access_mode = va_arg(ap, Mask);
+	    u.client.status = Success; /* default allow */
+	    prv = &u.client.status;
 	    break;
-	}
-	case XACE_EXT_ACCESS: {
-	    XaceExtAccessRec rec;
-	    rec.client = va_arg(ap, ClientPtr);
-	    rec.ext = va_arg(ap, ExtensionEntry*);
-	    rec.access_mode = DixGetAttrAccess;
-	    rec.status = Success; /* default allow */
-	    calldata = &rec;
-	    prv = &rec.status;
+	case XACE_EXT_ACCESS:
+	    u.ext.client = va_arg(ap, ClientPtr);
+	    u.ext.ext = va_arg(ap, ExtensionEntry*);
+	    u.ext.access_mode = DixGetAttrAccess;
+	    u.ext.status = Success; /* default allow */
+	    prv = &u.ext.status;
 	    break;
-	}
-	case XACE_SERVER_ACCESS: {
-	    XaceServerAccessRec rec;
-	    rec.client = va_arg(ap, ClientPtr);
-	    rec.access_mode = va_arg(ap, Mask);
-	    rec.status = Success; /* default allow */
-	    calldata = &rec;
-	    prv = &rec.status;
+	case XACE_SERVER_ACCESS:
+	    u.server.client = va_arg(ap, ClientPtr);
+	    u.server.access_mode = va_arg(ap, Mask);
+	    u.server.status = Success; /* default allow */
+	    prv = &u.server.status;
 	    break;
-	}
 	case XACE_SCREEN_ACCESS:
-	case XACE_SCREENSAVER_ACCESS: {
-	    XaceScreenAccessRec rec;
-	    rec.client = va_arg(ap, ClientPtr);
-	    rec.screen = va_arg(ap, ScreenPtr);
-	    rec.access_mode = va_arg(ap, Mask);
-	    rec.status = Success; /* default allow */
-	    calldata = &rec;
-	    prv = &rec.status;
+	case XACE_SCREENSAVER_ACCESS:
+	    u.screen.client = va_arg(ap, ClientPtr);
+	    u.screen.screen = va_arg(ap, ScreenPtr);
+	    u.screen.access_mode = va_arg(ap, Mask);
+	    u.screen.status = Success; /* default allow */
+	    prv = &u.screen.status;
 	    break;
-	}
-	case XACE_AUTH_AVAIL: {
-	    XaceAuthAvailRec rec;
-	    rec.client = va_arg(ap, ClientPtr);
-	    rec.authId = va_arg(ap, XID);
-	    calldata = &rec;
+	case XACE_AUTH_AVAIL:
+	    u.auth.client = va_arg(ap, ClientPtr);
+	    u.auth.authId = va_arg(ap, XID);
 	    break;
-	}
-	case XACE_KEY_AVAIL: {
-	    XaceKeyAvailRec rec;
-	    rec.event = va_arg(ap, xEventPtr);
-	    rec.keybd = va_arg(ap, DeviceIntPtr);
-	    rec.count = va_arg(ap, int);
-	    calldata = &rec;
+	case XACE_KEY_AVAIL:
+	    u.key.event = va_arg(ap, xEventPtr);
+	    u.key.keybd = va_arg(ap, DeviceIntPtr);
+	    u.key.count = va_arg(ap, int);
 	    break;
-	}
-	default: {
+	default:
 	    va_end(ap);
 	    return 0;	/* unimplemented hook number */
-	}
     }
     va_end(ap);
  
     /* call callbacks and return result, if any. */
-    CallCallbacks(&XaceHooks[hook], calldata);
+    CallCallbacks(&XaceHooks[hook], &u);
     return prv ? *prv : Success;
 }
 
commit fbd02046797185715e1a120d52e410ec78fc365f
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Thu Aug 5 15:19:20 2010 +0100

    Cygwin/X: Fix glxWinCreateDrawable() for API change
    
    Commit 9de0e31746d5f0d9d39d11c94ec3cbc04a9935fc changed the signature
    of __GLXScreen's createDrawable method.
    
    Update the glxWinCreateDrawable() function in XWin's GLX provider
    appropriately.
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Tested-by: Colin Harrison <colin.harrison at virgin.net>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xwin/glx/indirect.c b/hw/xwin/glx/indirect.c
index 8ec40da..1cf82a7 100755
--- a/hw/xwin/glx/indirect.c
+++ b/hw/xwin/glx/indirect.c
@@ -375,10 +375,12 @@ static __GLXscreen *glxWinScreenProbe(ScreenPtr pScreen);
 static __GLXcontext *glxWinCreateContext(__GLXscreen *screen,
                                         __GLXconfig *modes,
                                         __GLXcontext *baseShareContext);
-static __GLXdrawable *glxWinCreateDrawable(__GLXscreen *screen,
+static __GLXdrawable *glxWinCreateDrawable(ClientPtr client,
+                                          __GLXscreen *screen,
                                           DrawablePtr pDraw,
-                                          int type,
                                           XID drawId,
+                                          int type,
+                                          XID glxDrawId,
                                           __GLXconfig *conf);
 
 static Bool glxWinRealizeWindow(WindowPtr pWin);
@@ -901,10 +903,12 @@ glxWinDrawableDestroy(__GLXdrawable *base)
 }
 
 static __GLXdrawable *
-glxWinCreateDrawable(__GLXscreen *screen,
+glxWinCreateDrawable(ClientPtr client,
+                    __GLXscreen *screen,
                     DrawablePtr pDraw,
-                    int type,
                     XID drawId,
+                    int type,
+                    XID glxDrawId,
                     __GLXconfig *conf)
 {
   __GLXWinDrawable *glxPriv;
@@ -916,7 +920,7 @@ glxWinCreateDrawable(__GLXscreen *screen,
 
   memset(glxPriv, 0, sizeof *glxPriv);
 
-  if(!__glXDrawableInit(&glxPriv->base, screen, pDraw, type, drawId, conf)) {
+  if(!__glXDrawableInit(&glxPriv->base, screen, pDraw, type, glxDrawId, conf)) {
     free(glxPriv);
     return NULL;
   }
commit ff70848e623920779d20f35d47e9e1f34157de47
Author: Keith Packard <keithp at keithp.com>
Date:   Fri May 21 09:01:43 2010 -0700

    Don't let alpha maps recurse in fb. Bug 23581.
    
    Recursive alpha maps (where one picture's alpha map is set to a
    picture with an external alpha map) would be all fine and dandy,
    except for the case where the client constructs a loop. Detecting this
    case when setting the alpha map values would be difficult as any time
    an alpha map is set, the server would have to check for the looping
    case.
    
    Instead, a far simpler fix is to simply disallow recursive alpha maps
    in the rendering code, the Render spec is ambiguous in this area and
    allows us to to ignore the recursive case.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/fb/fbpict.c b/fb/fbpict.c
index 26cdc0d..f7f1200 100644
--- a/fb/fbpict.c
+++ b/fb/fbpict.c
@@ -332,8 +332,11 @@ create_bits_picture (PicturePtr pict,
     return image;
 }
 
+static pixman_image_t *
+image_from_pict_internal (PicturePtr pict, Bool has_clip, int *xoff, int *yoff, Bool is_alpha_map);
+
 static void
-set_image_properties (pixman_image_t *image, PicturePtr pict, Bool has_clip, int *xoff, int *yoff)
+set_image_properties (pixman_image_t *image, PicturePtr pict, Bool has_clip, int *xoff, int *yoff, Bool is_alpha_map)
 {
     pixman_repeat_t repeat;
     pixman_filter_t filter;
@@ -382,10 +385,13 @@ set_image_properties (pixman_image_t *image, PicturePtr pict, Bool has_clip, int
     
     pixman_image_set_repeat (image, repeat);
     
-    if (pict->alphaMap)
+    /* Fetch alpha map unless 'pict' is being used
+     * as the alpha map for this operation
+     */
+    if (pict->alphaMap && !is_alpha_map)
     {
 	int alpha_xoff, alpha_yoff;
-	pixman_image_t *alpha_map = image_from_pict (pict->alphaMap, FALSE, &alpha_xoff, &alpha_yoff);
+	pixman_image_t *alpha_map = image_from_pict_internal (pict->alphaMap, FALSE, &alpha_xoff, &alpha_yoff, TRUE);
 	
 	pixman_image_set_alpha_map (
 	    image, alpha_map, pict->alphaOrigin.x, pict->alphaOrigin.y);
@@ -417,8 +423,8 @@ set_image_properties (pixman_image_t *image, PicturePtr pict, Bool has_clip, int
     pixman_image_set_source_clipping (image, TRUE);
 }
 
-pixman_image_t *
-image_from_pict (PicturePtr pict, Bool has_clip, int *xoff, int *yoff)
+static pixman_image_t *
+image_from_pict_internal (PicturePtr pict, Bool has_clip, int *xoff, int *yoff, Bool is_alpha_map)
 {
     pixman_image_t *image = NULL;
 
@@ -452,11 +458,17 @@ image_from_pict (PicturePtr pict, Bool has_clip, int *xoff, int *yoff)
     }
     
     if (image)
-	set_image_properties (image, pict, has_clip, xoff, yoff);
+	set_image_properties (image, pict, has_clip, xoff, yoff, is_alpha_map);
     
     return image;
 }
 
+pixman_image_t *
+image_from_pict (PicturePtr pict, Bool has_clip, int *xoff, int *yoff)
+{
+    return image_from_pict_internal (pict, has_clip, xoff, yoff, FALSE);
+}
+
 void
 free_pixman_pict (PicturePtr pict, pixman_image_t *image)
 {
commit 70a94c5b7a42adc0995bf774c44587a0778be0d0
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Tue Aug 3 19:49:10 2010 +0100

    rootless: fix uninitialized private key assert in non-rootless modes in Cygwin/X
    
    IsFramedWindow() is called from miPaintWindow() if the server has
    been built with ROOTLESS defined, irrespective of if RootlessInit()
    has ever been called, or not.
    
    Add a check to IsFramedWindow() to check if rootlessWindowPrivateKey
    has been registered (as a proxy for checking if the rootless extension
    has been initialized) so we don't go on to try to use that key,
    triggering an assert.
    
    This bug exposes what appears to be a difference in opinion about
    the rootless extension between XQuartz and XWin.  XQuartz always
    initializes the rootless extension, whereas XWin offers several modes
    of operation, and the rootless extension is only used for one of them
    
    That probably means that the all code under compile time guard for
    ROOTLESS should be carefully checked that it doesn't also need to be
    under a run-time guard
    
    (I've reviewed the other ROOTLESS blocks in dix/events.c and
    dix/window.c and they look ok -- keithp)
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/miext/rootless/rootlessCommon.c b/miext/rootless/rootlessCommon.c
index 82fe0b9..f91cfb4 100644
--- a/miext/rootless/rootlessCommon.c
+++ b/miext/rootless/rootlessCommon.c
@@ -92,6 +92,9 @@ IsFramedWindow(WindowPtr pWin)
 {
     WindowPtr top;
 
+    if (!dixPrivateKeyRegistered(&rootlessWindowPrivateKeyRec))
+        return FALSE;
+
     if (!pWin->realized)
         return FALSE;
     top = TopLevelParent(pWin);
commit 3ab6cd31cbdf8095b2948034fce5fb645422d8da
Author: Adam Jackson <ajax at redhat.com>
Date:   Mon Aug 9 15:20:20 2010 -0400

    fonts: Fix refcounting for asynchronous font operations (#3040)
    
    When doing Xinerama, we'll dispatch font ops across all backend screens.
    If using a font server (such that some operations can sleep), we'll put
    the client to sleep once for each screen, but only wake up once, because
    we're trying to keep track of the sleep count in _each_ screen's
    closure.
    
    Instead, just ask the core whether the client is already asleep.
    
    Signed-off-by: Adam Jackson <ajax at redhat.com>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/dix/dixfonts.c b/dix/dixfonts.c
index 4a8f113..e22eabe 100644
--- a/dix/dixfonts.c
+++ b/dix/dixfonts.c
@@ -321,10 +321,10 @@ doOpenFont(ClientPtr client, OFclosurePtr c)
 	    continue;
 	}
 	if (err == Suspended) {
-	    if (!c->slept) {
-		c->slept = TRUE;
-		ClientSleep(client, (ClientSleepProcPtr)doOpenFont, (pointer) c);
-	    }
+	    if (!ClientIsAsleep(client))
+		ClientSleep(client, (ClientSleepProcPtr)doOpenFont, c);
+	    else
+		goto xinerama_sleep;
 	    return TRUE;
 	}
 	break;
@@ -373,8 +373,8 @@ bail:
 	SendErrorToClient(c->client, X_OpenFont, 0,
 			  c->fontid, FontToXError(err));
     }
-    if (c->slept)
-	ClientWakeup(c->client);
+    ClientWakeup(c->client);
+xinerama_sleep:
     for (i = 0; i < c->num_fpes; i++) {
 	FreeFPE(c->fpe_list[i]);
     }
@@ -460,7 +460,6 @@ OpenFont(ClientPtr client, XID fid, Mask flags, unsigned lenfname, char *pfontna
     c->current_fpe = 0;
     c->num_fpes = num_fpes;
     c->fnamelen = lenfname;
-    c->slept = FALSE;
     c->flags = flags;
     c->non_cachable_font = cached;
 
@@ -622,12 +621,12 @@ doListFontsAndAliases(ClientPtr client, LFclosurePtr c)
 		 c->names);
 
 	    if (err == Suspended) {
-		if (!c->slept) {
-		    c->slept = TRUE;
+		if (!ClientIsAsleep(client))
 		    ClientSleep(client,
-			(ClientSleepProcPtr)doListFontsAndAliases,
-			(pointer) c);
-		}
+				(ClientSleepProcPtr)doListFontsAndAliases,
+				c);
+		else
+		    goto xinerama_sleep;
 		return TRUE;
 	    }
 
@@ -650,12 +649,12 @@ doListFontsAndAliases(ClientPtr client, LFclosurePtr c)
 		     c->current.patlen, c->current.max_names - c->names->nnames,
 		     &c->current.private);
 		if (err == Suspended) {
-		    if (!c->slept) {
+		    if (!ClientIsAsleep(client))
 			ClientSleep(client,
 				    (ClientSleepProcPtr)doListFontsAndAliases,
-				    (pointer) c);
-			c->slept = TRUE;
-		    }
+				    c);
+		    else
+			goto xinerama_sleep;
 		    return TRUE;
 		}
 		if (err == Successful)
@@ -668,12 +667,12 @@ doListFontsAndAliases(ClientPtr client, LFclosurePtr c)
 		    ((pointer) c->client, fpe, &name, &namelen, &tmpname,
 		     &resolvedlen, c->current.private);
 		if (err == Suspended) {
-		    if (!c->slept) {
+		    if (ClientIsAsleep(client))
 			ClientSleep(client,
 				    (ClientSleepProcPtr)doListFontsAndAliases,
-				    (pointer) c);
-			c->slept = TRUE;
-		    }
+				    c);
+		    else
+			goto xinerama_sleep;
 		    return TRUE;
 		}
 		if (err == FontNameAlias) {
@@ -822,8 +821,8 @@ finish:
     free(bufferStart);
 
 bail:
-    if (c->slept)
-	ClientWakeup(client);
+    ClientWakeup(client);
+xinerama_sleep:
     for (i = 0; i < c->num_fpes; i++)
 	FreeFPE(c->fpe_list[i]);
     free(c->fpe_list);
@@ -881,7 +880,6 @@ ListFonts(ClientPtr client, unsigned char *pattern, unsigned length,
     c->current.list_started = FALSE;
     c->current.private = 0;
     c->haveSaved = FALSE;
-    c->slept = FALSE;
     c->savedName = 0;
     doListFontsAndAliases(client, c);
     return Success;
@@ -928,11 +926,11 @@ doListFontsWithInfo(ClientPtr client, LFWIclosurePtr c)
 		 c->current.max_names, &c->current.private);
 	    if (err == Suspended)
  	    {
-		if (!c->slept)
- 		{
-		    ClientSleep(client, (ClientSleepProcPtr)doListFontsWithInfo, c);
-		    c->slept = TRUE;
-		}
+		if (!ClientIsAsleep(client))
+		    ClientSleep(client,
+				(ClientSleepProcPtr)doListFontsWithInfo, c);
+		else
+		    goto xinerama_sleep;
 		return TRUE;
 	    }
 	    if (err == Successful)
@@ -947,13 +945,11 @@ doListFontsWithInfo(ClientPtr client, LFWIclosurePtr c)
 		 &numFonts, c->current.private);
 	    if (err == Suspended)
  	    {
-		if (!c->slept)
- 		{
+		if (!ClientIsAsleep(client))
 		    ClientSleep(client,
-		    	     (ClientSleepProcPtr)doListFontsWithInfo,
-			     c);
-		    c->slept = TRUE;
-		}
+				(ClientSleepProcPtr)doListFontsWithInfo, c);
+		else
+		    goto xinerama_sleep;
 		return TRUE;
 	    }
 	}
@@ -1098,8 +1094,8 @@ finish:
 		     - sizeof(xGenericReply));
     WriteSwappedDataToClient(client, length, &finalReply);
 bail:
-    if (c->slept)
-	ClientWakeup(client);
+    ClientWakeup(client);
+xinerama_sleep:
     for (i = 0; i < c->num_fpes; i++)
 	FreeFPE(c->fpe_list[i]);
     free(c->reply);
@@ -1154,7 +1150,6 @@ StartListFontsWithInfo(ClientPtr client, int length, unsigned char *pattern,
     c->current.private = 0;
     c->savedNumFonts = 0;
     c->haveSaved = FALSE;
-    c->slept = FALSE;
     c->savedName = 0;
     doListFontsWithInfo(client, c);
     return Success;
@@ -1181,7 +1176,7 @@ doPolyText(ClientPtr client, PTclosurePtr c)
 	fpe = c->pGC->font->fpe;
 	(*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
 
-	if (c->slept)
+	if (ClientIsAsleep(client))
 	{
 	    /* Client has died, but we cannot bail out right now.  We
 	       need to clean up after the work we did when going to
@@ -1198,7 +1193,7 @@ doPolyText(ClientPtr client, PTclosurePtr c)
     }
 
     /* Make sure our drawable hasn't disappeared while we slept. */
-    if (c->slept && c->pDraw)
+    if (ClientIsAsleep(client) && c->pDraw)
     {
 	DrawablePtr pDraw;
 	dixLookupDrawable(&pDraw, c->did, client, 0, DixWriteAccess);
@@ -1212,7 +1207,7 @@ doPolyText(ClientPtr client, PTclosurePtr c)
 	}
     }
 
-    client_state = c->slept ? SLEEPING : NEVER_SLEPT;
+    client_state = ClientIsAsleep(client) ? SLEEPING : NEVER_SLEPT;
 
     while (c->endReq - c->pElt > TextEltHeader)
     {
@@ -1295,7 +1290,7 @@ doPolyText(ClientPtr client, PTclosurePtr c)
 
 	    if (lgerr == Suspended)
 	    {
-		if (!c->slept) {
+		if (!ClientIsAsleep(client)) {
 		    int len;
 		    GC *pGC;
 		    PTclosurePtr new_closure;
@@ -1368,15 +1363,14 @@ doPolyText(ClientPtr client, PTclosurePtr c)
 		    c->pGC = pGC;
 		    ValidateGC(c->pDraw, c->pGC);
 		    
-		    c->slept = TRUE;
-		    ClientSleep(client,
-		    	     (ClientSleepProcPtr)doPolyText,
-			     (pointer) c);
+		    ClientSleep(client, (ClientSleepProcPtr)doPolyText, c);
 
 		    /* Set up to perform steps 3 and 4 */
 		    client_state = START_SLEEP;
 		    continue;	/* on to steps 3 and 4 */
 		}
+		else
+		    goto xinerama_sleep;
 		return TRUE;
 	    }
 	    else if (lgerr != Successful)
@@ -1419,9 +1413,10 @@ bail:
 #endif
 	    SendErrorToClient(c->client, c->reqType, 0, 0, err);
     }
-    if (c->slept)
+    if (ClientIsAsleep(client))
     {
 	ClientWakeup(c->client);
+xinerama_sleep:
 	ChangeGC(NullClient, c->pGC, clearGCmask, clearGC);
 
 	/* Unreference the font from the scratch GC */
@@ -1460,7 +1455,6 @@ PolyText(ClientPtr client, DrawablePtr pDraw, GC *pGC, unsigned char *pElt,
     local_closure.pGC = pGC;
     local_closure.did = did;
     local_closure.err = Success;
-    local_closure.slept = FALSE;
 
     (void) doPolyText(client, &local_closure);
     return Success;
@@ -1485,7 +1479,7 @@ doImageText(ClientPtr client, ITclosurePtr c)
     }
 
     /* Make sure our drawable hasn't disappeared while we slept. */
-    if (c->slept && c->pDraw)
+    if (ClientIsAsleep(client) && c->pDraw)
     {
 	DrawablePtr pDraw;
 	dixLookupDrawable(&pDraw, c->did, client, 0, DixWriteAccess);
@@ -1502,7 +1496,7 @@ doImageText(ClientPtr client, ITclosurePtr c)
     lgerr = LoadGlyphs(client, c->pGC->font, c->nChars, c->itemSize, c->data);
     if (lgerr == Suspended)
     {
-        if (!c->slept) {
+        if (!ClientIsAsleep(client)) {
 	    GC *pGC;
 	    unsigned char *data;
 	    ITclosurePtr new_closure;
@@ -1555,9 +1549,10 @@ doImageText(ClientPtr client, ITclosurePtr c)
 	    c->pGC = pGC;
 	    ValidateGC(c->pDraw, c->pGC);
 
-	    c->slept = TRUE;
-            ClientSleep(client, (ClientSleepProcPtr)doImageText, (pointer) c);
+            ClientSleep(client, (ClientSleepProcPtr)doImageText, c);
         }
+	else
+	    goto xinerama_sleep;
         return TRUE;
     }
     else if (lgerr != Successful)
@@ -1576,9 +1571,10 @@ bail:
     if (err != Success && c->client != serverClient) {
 	SendErrorToClient(c->client, c->reqType, 0, 0, err);
     }
-    if (c->slept)
+    if (ClientIsAsleep(client))
     {
 	ClientWakeup(c->client);
+xinerama_sleep:
 	ChangeGC(NullClient, c->pGC, clearGCmask, clearGC);
 
 	/* Unreference the font from the scratch GC */
@@ -1616,7 +1612,6 @@ ImageText(ClientPtr client, DrawablePtr pDraw, GC *pGC, int nChars,
 	local_closure.itemSize = 2;
     }
     local_closure.did = did;
-    local_closure.slept = FALSE;
 
     (void) doImageText(client, &local_closure);
     return Success;
diff --git a/include/closestr.h b/include/closestr.h
index 2cd67b1..7ca2613 100644
--- a/include/closestr.h
+++ b/include/closestr.h
@@ -46,7 +46,6 @@ typedef struct _OFclosure {
     short       num_fpes;
     FontPathElementPtr *fpe_list;
     Mask        flags;
-    Bool        slept;
 
 /* XXX -- get these from request buffer instead? */
     char       *origFontName;
@@ -79,7 +78,6 @@ typedef struct _LFWIclosure {
     LFWIstateRec	saved;
     int			savedNumFonts;
     Bool		haveSaved;
-    Bool		slept;
     char		*savedName;
 } LFWIclosureRec;
 
@@ -93,7 +91,6 @@ typedef struct _LFclosure {
     LFWIstateRec current;
     LFWIstateRec saved;
     Bool        haveSaved;
-    Bool        slept;
     char	*savedName;
     int		savedNameLen;
 }	LFclosureRec;
@@ -124,7 +121,6 @@ typedef struct _PTclosure {
     int			itemSize;
     XID			did;
     int			err;
-    Bool		slept;
 } PTclosureRec;
 
 /* ImageText */
@@ -151,6 +147,5 @@ typedef struct _ITclosure {
     ImageTextPtr	imageText;
     int			itemSize;
     XID			did;
-    Bool		slept;
 } ITclosureRec;
 #endif				/* CLOSESTR_H */
commit 35c0dbe4b0a6ab790f4271325b8a0b16894daa8b
Author: Gaetan Nadon <memsize at videotron.ca>
Date:   Sun Aug 8 10:03:08 2010 -0400

    doc: add missing .gitignore for Xserver-DTrace
    
    The dtrace doc was recently added in commit
    9c171d4aee695ab66e6db1ab92539557bd368cfa
    
    Reviewed-by: Alan Coopersmith <alan.coopersmith at oracle.com>
    Signed-off-by: Gaetan Nadon <memsize at videotron.ca>

diff --git a/doc/xml/dtrace/.gitignore b/doc/xml/dtrace/.gitignore
new file mode 100644
index 0000000..a43c4e1
--- /dev/null
+++ b/doc/xml/dtrace/.gitignore
@@ -0,0 +1,4 @@
+Xserver-DTrace.html
+Xserver-DTrace.pdf
+Xserver-DTrace.txt
+xorg.css
commit 05c4fe83fdc20b838fd59658478278dc31a55eb9
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Fri Jul 30 17:43:24 2010 -0700

    Check HAVE_XMLTO_TEXT before trying to use xmlto to make text files
    
    Reported-by: Matt Turner <mattst88 at gmail.com>
    Tested-by: Gaetan Nadon <memsize at videotron.ca>
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>

diff --git a/doc/xml/xmlrules.in b/doc/xml/xmlrules.in
index 0d094be..b7fda11 100644
--- a/doc/xml/xmlrules.in
+++ b/doc/xml/xmlrules.in
@@ -48,10 +48,12 @@ xorg.css: $(STYLESHEET_SRCDIR)/xorg.css
 endif
 
 if HAVE_XMLTO
+if HAVE_XMLTO_TEXT
 BUILT_DOC_FILES += $(TXT_FILES)
 .xml.txt:
 	@rm -f $@
 	$(AM_V_GEN)$(XMLTO) $(XMLTO_FLAGS) txt $<
+endif
 
 BUILT_DOC_FILES += $(HTML_FILES)
 .xml.html:
commit a6fb7829ed9bf26c4c2a02c6ed075fb1b17f7b2a
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Mon Jul 26 19:55:27 2010 -0700

    Xserver-spec: Update ChangeGC prototype, add ChangeGCXIDs
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>
    Reviewed-by: Jamey Sharp <jamey at minilop.net>

diff --git a/doc/xml/Xserver-spec.xml b/doc/xml/Xserver-spec.xml
index c5fd191..563705f 100644
--- a/doc/xml/Xserver-spec.xml
+++ b/doc/xml/Xserver-spec.xml
@@ -3760,7 +3760,7 @@ Also included in each GC is support for dynamic devPrivates, which the
 DDX can use for any purpose (see <xref linkend="wrappers_and_privates"/> below).</para>
 <para>
 The DIX routines available for manipulating GCs are
-CreateGC, ChangeGC, CopyGC, SetClipRects, SetDashes, and FreeGC.
+CreateGC, ChangeGC, ChangeGCXIDs, CopyGC, SetClipRects, SetDashes, and FreeGC.
 <blockquote><programlisting>
 
 	GCPtr CreateGC(pDrawable, mask, pval, pStatus)
@@ -3769,10 +3769,17 @@ CreateGC, ChangeGC, CopyGC, SetClipRects, SetDashes, and FreeGC.
 	    XID *pval;
 	    int *pStatus;
 
-	int ChangeGC(pGC, mask, pval)
+	int ChangeGC(client, pGC, mask, pUnion)
+	    ClientPtr client;
 	    GCPtr pGC;
 	    BITS32 mask;
-	    XID *pval;
+	    ChangeGCValPtr pUnion;
+
+	int ChangeGCXIDs(client, pGC, mask, pC32)
+	    ClientPtr client;
+	    GCPtr pGC;
+	    BITS32 mask;
+	    CARD32 *pC32;
 
 	int CopyGC(pgcSrc, pgcDst, mask)
 	    GCPtr pgcSrc;
commit a817271d461e2f95dd7dc62cd1c7d123ce92f555
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Thu Jul 22 23:57:57 2010 -0700

    Update Xserver-spec for new devPrivates API
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>
    Reviewed-by: Patrick E. Kane <pekane52 at gmail.com>

diff --git a/doc/xml/Xserver-spec.xml b/doc/xml/Xserver-spec.xml
index 466b79d..c5fd191 100644
--- a/doc/xml/Xserver-spec.xml
+++ b/doc/xml/Xserver-spec.xml
@@ -92,6 +92,13 @@
 	<authorinitials>efw</authorinitials>
 	<revremark>Revised for devPrivates changes</revremark>
       </revision>
+      <revision>
+	<revnumber>3.5</revnumber>
+	<date>July 2010</date>
+	<authorinitials>ac</authorinitials>
+	<revremark>Revised for Xorg 1.9 devPrivates changes
+	  and 1.8 CreateNewResourceType changes</revremark>
+      </revision>
     </revhistory>
     <legalnotice>
       <para>Copyright &#xA9; 1994 X Consortium, Inc., 2004 X.org Foundation, Inc.</para>
@@ -4808,32 +4815,68 @@ Two new extensibility concepts have been developed for release 4, Wrappers
 and devPrivates.  These replace the R3 GCInterest queues, which were not a
 general enough mechanism for many extensions and only provided hooks into a
 single data structure.  devPrivates have been revised substantially for
-X.org X server relase 1.5.</para>
+X.Org X server release 1.5, and updated again for the 1.9 release.</para>
 <section>
   <title>devPrivates</title>
 <para>
 devPrivates provides a way to attach arbitrary private data to various server structures.
 Any structure which contains a <structfield>devPrivates</structfield> field of
-type <type>PrivateRec</type> supports this mechanism.  Private data can be allocated at
-any time during an object's life cycle and callbacks are available to initialize and clean
-up allocated space.</para>
+type <type>PrivateRec</type> supports this mechanism.  Some structures allow
+allocating space for private data after some objects have been created, others
+require all space allocations be registered before any objects of that type
+are created.  <filename class="headerfile">Xserver/include/privates.h</filename>
+lists which of these cases applies to each structure containing
+<structfield>devPrivates</structfield>.</para>
+
+<para>
+To request private space, use
+<blockquote><programlisting>
+	Bool dixRegisterPrivateKey(DevPrivateKey key, DevPrivateType type, unsigned size);
+</programlisting></blockquote>
+The first argument is a pointer to a <type>DevPrivateKeyRec</type> which
+will serve as the unique identifier for the private data.  Typically this is
+the address of a static <type>DevPrivateKeyRec</type> in your code.
+The second argument is the class of objects for which this key will apply.
+The third argument is the size of the space being requested, or
+<constant>0</constant> to only allocate a pointer that the caller will manage.
+If space is requested, this space will be automatically freed when the object
+is destroyed.  Note that a call to <function>dixSetPrivate</function>
+that changes the pointer value may cause the space to be unreachable by the caller, however it will still be automatically freed.
+The function returns <literal>TRUE</literal> unless memory allocation fails.
+If the function is called more than once on the same key, all calls must use
+the same value for <type>size</type> or the server will abort.</para>
+
+<para>
+To request private space and have the server manage the key, use
+<blockquote><programlisting>
+	DevPrivateKey dixCreatePrivateKey(DevPrivateType type, unsigned size);
+</programlisting></blockquote>
+The <parameter>type</parameter> and <parameter>size</parameter> arguments are
+the same as those to <function>dixRegisterPrivateKey</function> but this
+function allocates a <type>DevPrivateKeyRec</type> and returns a pointer to it
+instead of requiring the caller to pass a pointer to an existing structure.
+The server will free it automatically when the privates system is restarted
+at server reset time.</para>
+
 <para>
 To attach a piece of private data to an object, use:
 <blockquote><programlisting>
-	int dixSetPrivate(PrivateRec **privates, const DevPrivateKey key, pointer val)
+	void dixSetPrivate(PrivateRec **privates, const DevPrivateKey key, pointer val)
 </programlisting></blockquote>
-The first argument is the address of the <structfield>devPrivates</structfield> field
-in the target structure.  This field is managed privately by the DIX layer and
-should not be directly modified.  The second argument is some address value which
-will serve as the unique identifier for the private data.  Typically this is the address
-of some global variable in your code.  Only one piece of data with a given key can be attached to an object.  However, you
-can use the same key to store data in any object that supports the devPrivates mechanism.  The third
-argument is the value to store.</para>
+The first argument is the address of the <structfield>devPrivates</structfield>
+field in the target structure.  This field is managed privately by the DIX
+layer and should not be directly modified.  The second argument is a pointer
+to the <type>DevPrivateKeyRec</type> which you registered with
+<function>dixRegisterPrivateKey</function> or allocated with
+<function>dixCreatePrivateKey</function>.  Only one
+piece of data with a given key can be attached to an object, and in most cases
+each key is specific to the type of object it was registered for.   (An
+exception is the PRIVATE_XSELINUX class which applies to multiple object types.)
+The third argument is the value to store.</para>
 <para>
-If private data with the given key is already associated with the object, <function>dixSetPrivate</function> will
-overwrite the old value with the new one.  Otherwise, new space will be allocated to hold the pointer value.
-The function returns <literal>TRUE</literal> unless memory allocation fails, but note that since memory allocation only
-occurs on the first reference to the private data, all subsequent calls are guaranteed to succeed.</para>
+If private data with the given key is already associated with the object,
+<function>dixSetPrivate</function> will overwrite the old value with the
+new one.</para>
 
 <para>
 To look up a piece of private data, use one of:
@@ -4842,56 +4885,22 @@ To look up a piece of private data, use one of:
 	pointer *dixLookupPrivateAddr(PrivateRec **privates, const DevPrivateKey key)
 </programlisting></blockquote>
 The first argument is the address of the <structfield>devPrivates</structfield> field
-in the target structure.  The second argument is the key to look up.  If private data with the given key is already associated
-with the object, <function>dixLookupPrivate</function> will return the stored pointer value while <function>dixLookupPrivateAddr</function>
-will return the address of the stored pointer.  Otherwise, new space will be first allocated to hold the pointer value
-and it will be initialized to NULL.  Both functions return <literal>NULL</literal> if memory allocation fails, but note that
-since memory allocation only occurs on the first reference to the private data, all subsequent calls are guaranteed to succeed.</para>
-
-<para>
-To request pre-allocated private space, use
-<blockquote><programlisting>
-	int dixRequestPrivate(const DevPrivateKey key, unsigned size)
-</programlisting></blockquote>
-The first argument is the key for which space is being requested.  The second argument is the size of the space being requested.
-After this function has been called,
-future calls to <function>dixLookupPrivate</function> or <function>dixLookupPrivateAddr</function> that cause the private pointer
-to be initially allocated will also allocate <varname>size</varname> bytes of space cleared to zero and initialize the private pointer to point
-to this space instead of <literal>NULL</literal>.  This space will be automatically freed.  Note that a call to <function>dixSetPrivate</function>
-that changes the pointer value may cause the space to be unreachable by the caller, however it will still be automatically freed.
-The function returns <literal>TRUE</literal> unless memory allocation fails.  If the function is called more than once, the largest value
-of <type>size</type> is used.</para>
-
-<para>
-To set callbacks for initializing and cleaning up private space, use
-<blockquote><programlisting>
-	typedef struct {
-		DevPrivateKey key;
-		pointer *value;
-	} PrivateCallbackRec;
-
-	int dixRegisterPrivateInitFunc(const DevPrivateKey key,
-		CallbackProcPtr callback,
-		pointer userdata)
-	int dixRegisterPrivateDeleteFunc(const DevPrivateKey key,
-		CallbackProcPtr callback,
-		pointer userdata)
-</programlisting></blockquote>
-The first argument is the key for which the callbacks are being registered.  The second argument is the callback function.  The third argument
-will be passed as the user data argument to the callback function when it is called.  The call data argument to the callback is a pointer to
-a structure of type <type>PrivateCallbackRec</type>.</para>
-<para>
-The init callback is called immediately after new private space has been allocated for the given key.  The delete callback is called immediately
-before the private space is freed when the object is being destroyed.  The <type>PrivateCallbackRec</type> structure contains the devPrivate key
-and the address of the private pointer.  The init callback may be used to initialize any pre-allocated space requested by
-<function>dixRequestPrivate</function>, while the delete callback may be used to free any data stored there.  However the callbacks are called even
-if no pre-allocated space was requested.</para>
-
-<para>
-When implementing new server resource objects that support devPrivates, there are three steps to perform:
-Declare a field of type <type>PrivateRec *</type> in your structure;
+in the target structure.  The second argument is the key to look up.
+If a non-zero size was given when the key was registered, or if private data
+with the given key is already associated with the object, then
+<function>dixLookupPrivate</function> will return the pointer value
+while <function>dixLookupPrivateAddr</function>
+will return the address of the pointer.</para>
+
+<para>
+When implementing new server resource objects that support devPrivates, there
+are four steps to perform:
+Add a type value to the <type>DevPrivateType</type> enum in
+<filename class="headerfile">Xserver/include/privates.h</filename>,
+declare a field of type <type>PrivateRec *</type> in your structure;
 initialize this field to <literal>NULL</literal> when creating any objects; and
-call the <function>dixFreePrivates</function> function, passing in the field value, when freeing any objects.</para>
+when freeing any objects call the <function>dixFreePrivates</function> or
+<function>dixFreeObjectWithPrivates</function> function.</para>
 </section>
 <section>
   <title>Wrappers</title>
commit 40d598a4f84091db743ceef4d60752bb910c3e56
Author: Alan Coopersmith <alan.coopersmith at oracle.com>
Date:   Thu Jul 22 23:57:02 2010 -0700

    Correct function name in dixRegisterPrivateKey comments
    
    Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>
    Reviewed-by: Patrick E. Kane <pekane52 at gmail.com>

diff --git a/include/privates.h b/include/privates.h
index 5ba9358..d3c0e13 100644
--- a/include/privates.h
+++ b/include/privates.h
@@ -81,10 +81,10 @@ typedef struct _DevPrivateKeyRec {
  * you can get the address of the extra space and store whatever data you like
  * there.
  *
- * You may call dixRegisterPrivate more than once on the same key, but the
+ * You may call dixRegisterPrivateKey more than once on the same key, but the
  * size and type must match or the server will abort.
  *
- * dixRegisterPrivateIndex returns FALSE if it fails to allocate memory
+ * dixRegisterPrivateKey returns FALSE if it fails to allocate memory
  * during its operation.
  */
 extern _X_EXPORT Bool
commit 8d7b7a0d71e0b89321b3341b781bc8845386def6
Author: Kristian Høgsberg <krh at bitplanet.net>
Date:   Thu Jul 29 20:36:25 2010 -0400

    Set DamageSetReportAfterOp to true for the damage extension
    
    Change the damage extension reporter to queue up events after we chain
    to the wrapped functions.  Damage events are typically sent out after
    the rendering happens anyway, since we submit batch buffers from the
    flush callback chain and then flush client io buffers.  Compositing
    managers relie on this order, and there is no way we could reliably
    provide damage events to clients before the rendering happens anyway.
    
    By queueing up the damage events before the rendering happens, there's
    a risk that the client io buffer may overflow and send the damage
    events to the client before the driver has even seen the rendering
    request.  Reporting damage events after the rendering fixes this
    corner case and better corresponds with how we expect this to work.
    
    Signed-off-by: Kristian Høgsberg <krh at bitplanet.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/damageext/damageext.c b/damageext/damageext.c
index f5265dd..b4bb478 100644
--- a/damageext/damageext.c
+++ b/damageext/damageext.c
@@ -217,6 +217,7 @@ ProcDamageCreate (ClientPtr client)
     if (!AddResource (stuff->damage, DamageExtType, (pointer) pDamageExt))
 	return BadAlloc;
 
+    DamageSetReportAfterOp (pDamageExt->pDamage, TRUE);
     DamageRegister (pDamageExt->pDrawable, pDamageExt->pDamage);
 
     if (pDrawable->type == DRAWABLE_WINDOW)
commit c65f610e12f9df168d5639534ed3c2bd40afffc8
Author: Kristian Høgsberg <krh at bitplanet.net>
Date:   Thu Jul 29 18:52:35 2010 -0400

    Always call the flush callback chain when we flush client buffers
    
    We were missing the callback in a couple of places.  Drivers may use
    the flush callback to submit batched up rendering before events (for
    example, damage events) are sent out, to ensure that the rendering
    has been queued when the client receives the event.
    
    Signed-off-by: Kristian Høgsberg <krh at bitplanet.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>

diff --git a/os/connection.c b/os/connection.c
index c143fb6..77910be 100644
--- a/os/connection.c
+++ b/os/connection.c
@@ -1033,6 +1033,9 @@ CloseDownConnection(ClientPtr client)
 {
     OsCommPtr oc = (OsCommPtr)client->osPrivate;
 
+    if (FlushCallback)
+	CallCallbacks(&FlushCallback, NULL);
+
     if (oc->output && oc->output->count)
 	FlushClient(client, oc, (char *)NULL, 0);
 #ifdef XDMCP
diff --git a/os/io.c b/os/io.c
index b5f98b7..e2df2e3 100644
--- a/os/io.c
+++ b/os/io.c
@@ -819,6 +819,10 @@ WriteToClient (ClientPtr who, int count, const void *__buf)
 	  CriticalOutputPending = FALSE;
 	  NewOutputPending = FALSE;
 	}
+
+	if (FlushCallback)
+	    CallCallbacks(&FlushCallback, NULL);
+
 	return FlushClient(who, oc, buf, count);
     }
 


More information about the Xquartz-changes mailing list