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

Jeremy Huddleston jeremyhu at freedesktop.org
Sat Jul 17 12:44:28 PDT 2010


Rebased ref, commits from common ancestor:
commit eba8b06f462e53ce02c78fd47d7247e90b1cc848
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 26cdc0d..f2ddb63 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,52 +307,30 @@ 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 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)
 {
     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)
@@ -384,8 +357,7 @@ set_image_properties (pixman_image_t *image, PicturePtr pict, Bool has_clip, int
     
     if (pict->alphaMap)
     {
-	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 (pict->alphaMap, TRUE);
 	
 	pixman_image_set_alpha_map (
 	    image, alpha_map, pict->alphaOrigin.x, pict->alphaOrigin.y);
@@ -418,7 +390,8 @@ set_image_properties (pixman_image_t *image, PicturePtr pict, Bool has_clip, int
 }
 
 pixman_image_t *
-image_from_pict (PicturePtr pict, Bool has_clip, int *xoff, int *yoff)
+image_from_pict (PicturePtr pict,
+		 Bool has_clip)
 {
     pixman_image_t *image = NULL;
 
@@ -427,7 +400,7 @@ image_from_pict (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)
     {
@@ -448,11 +421,10 @@ image_from_pict (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);
+	set_image_properties (image, pict);
     
     return image;
 }
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 d873fe659ea835417ab6678b1a992378b1635595
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 e141325f3495f4a40a25b04871a285a02a1cda61
Author: Jan Hauffa <hauffa at in.tum.de>
Date:   Fri Jul 16 17:56:44 2010 +0200

    XQuartz: 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 3f4e7b8..acc5575 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;
@@ -237,10 +237,6 @@ void QuartzUpdateScreens(void) {
     e.u.configureNotify.borderWidth = wBorderWidth(pRoot);
     e.u.configureNotify.override = pRoot->overrideRedirect;
     DeliverEvents(pRoot, &e, 1, NullWindow);
-    
-#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 a0659689279ae3199e055b30eb794cad033ab33f
Author: Jan Hauffa <hauffa at in.tum.de>
Date:   Fri Jul 16 17:54:55 2010 +0200

    XQuartz: 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 cb48b8c054f57a8a2f673bc2889de755905e9a2a
Author: Jan Hauffa <hauffa at in.tum.de>
Date:   Fri Jul 16 17:18:03 2010 +0200

    XQuartz: 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 bdaa262..3f4e7b8 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;
@@ -444,3 +378,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 1d9c47e93cf105f45bdc1f21fd4c8e2bc3333ca6
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Sat Jul 17 12:18:39 2010 -0700

    rootless: Adjust the frame size of the native root window in RootlessResizeWindow
    
    If the native root window isn't resized as well, we will likely crash the
    next time we draw to the root.  On OS X, this can be seen by:
    
    1) Put the display preferences in the menu bar and set X11's preferences so you
       can access the menu bar in fullscreen mode
    2) Set the resolution of your screen lower than normal.
    3) Start X11 in fullscreen mode.  The root window will cover the screen as
       expected.
    4) Use the menu bar to increase the resolution of the display.  The root
       window will now cover the old area and not the full screen, but
       'xwininfo -root' will report the full width.
    5) Run 'xsetroot -solid red', and we have the crash you mention above.
    
    Leaving/entering fullscreen after #4 will fix the problem.  This is because the
    WINREC is erased when we leave fullscreen mode and it is recreated upon
    re-entry:
    
    RootlessUpdateRooted(FALSE)
        RootlessDisableRoot(screenInfo.screens[0])
            RootlessDestroyFrame (pRoot, winRec);
    RootlessUpdateRooted(TRUE)
        RootlessEnableRoot(screenInfo.screens[0])
            RootlessEnsureFrame(screenInfo.screens[0]->pRoot)
                creates a new WINREC...
    
    Signed-off-by: Jan Hauffa <hauffa at in.tum.de>
    Reviewed-by: Jeremy Huddleston <jeremyhu at apple.com>
    Tested-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/miext/rootless/rootlessWindow.c b/miext/rootless/rootlessWindow.c
index 7fe5e1d..bef8a2f 100644
--- a/miext/rootless/rootlessWindow.c
+++ b/miext/rootless/rootlessWindow.c
@@ -1315,6 +1315,13 @@ RootlessResizeWindow(WindowPtr pWin, int x, int y,
         RegionCopy(&pWin->clipList, &pWin->winSize);
         RegionCopy(&pWin->borderClip, &pWin->winSize);
 
+        if (winRec) {
+            SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen,
+                                                 x + SCREEN_TO_GLOBAL_X,
+                                                 y + SCREEN_TO_GLOBAL_Y,
+                                                 w, h, RL_GRAVITY_NONE);
+        }
+
         miSendExposures(pWin, &pWin->borderClip,
                         pWin->drawable.x, pWin->drawable.y);        
     }


More information about the Xquartz-changes mailing list