[Xquartz-dev] XRandR update

Jeremy Huddleston jeremyhu at apple.com
Mon Jul 19 10:37:25 PDT 2010


Hi Jan,

I've had a bit more time to play around with these patches.  This is a *GREAT* first step, but I've made a list of the most obvious places for improvement:

1) multi-monitor configs
Right now, for multi monitor configurations, we just list the first two resolution options for the entire union display.  The ideal fix would be to update pseudoramiX to report multiple OS X displays as multiple X11 displays and have RandR controls for each display.  If I recall, the former is a larger problem than it seems at the onset, but the last time I looked was well over 2 years ago.

For now, I think a good alternative would be having the display modes of the primary monitor listed.  We could then use only the primary monitor in those modes and ignore the secondary display.

2) resized windows in other applications
If we have a maximized Mail.app running and we shrink our X11 using RandR, the height of Mail.app will be shrunk when we restore our default display setting using RandR.  I seem to recall an API to deal with this... something about "Game Mode" or "Grab/Lock/Own Display" or something along those lines.

3) cmd-alt-a
The escape sequence to toggle fullscreen is usable when in one of our RandR chosen modes, but what it does is just toggle fullscreen.  In other words, doing it will show the OS X Desktop.  We should probably force mode '0' when doing that.  This is very important for dealing with situations where the requesting application has crashed and the user needs to restore to something usable.

Let me know if you want to work on any of these issues.  I'll tackle the others.

Thanks,
Jeremy

On Jul 17, 2010, at 09:00, Jan Hauffa wrote:

> Hi,
> 
> I apologize for the lack of communication from my side. The problem of
> enabling/disabling rootless mode when changing the screen resolution
> turned out to be more complicated than expected, and only recently did I
> find the time to investigate further.
> 
> I've attached an updated series of patches: Patches 1 and 3 are
> unchanged from the previous submission. Patch 1 contains the basic
> implementation of RandR mode setting, and patch 3 removes the FAKE_RANDR
> code. Patch 2 makes RandR report a "fake mode" that corresponds to the
> screen resolution at startup of the X server, but excluding the height
> of the menu bar. If a client requests this screen mode, rootless mode is
> enabled, for all other modes it is disabled.
> 
> The problem I was struggling with is that if the screen resolution was
> changed while the root window was visible, the server would crash. When
> the resolution is changed, he event handler in darwinEvents.c calls
> QuartzUpdateScreens, which resizes the root window and fills it with the
> background color. To resize the window, RootlessWindowResize is called,
> which contains a special case for resizing the root window:
> xprResizeFrame is not called for the root window, so the subsequent call
> to xprStartDrawing will return a pointer to a buffer that is smaller
> than expected.
> 
> I have implemented two methods of working around this problem: The first
> patch (0002-<...>.patch) simply makes RootlessWindowResize call
> xprResizeFrame. This is the most straightforward approach, but it adds
> an "ifdef XQUARTZ" block to unrelated code.
> The only alternative, as far as I can see, is to destroy the root window
> before changing the screen resolution, and to ensure that a new root
> window of correct size is created afterwards. As you can see in patch
> "alt-0002-<...>.patch", this makes the logic in
> QuartzRandRSetConfiguration rather complex.
> 
> Perhaps I'm just missing an obvious solution, as I've been staring at
> this code for too long...
> 
> Regards,
>  Jan
> 
>> From 95f6284a2b45253af75fc0dfd58b8e2a8aaca265 Mon Sep 17 00:00:00 2001
> From: Jan Hauffa <hauffa at in.tum.de>
> Date: Fri, 16 Jul 2010 17:18:03 +0200
> Subject: [PATCH 1/3] 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>
> ---
> hw/xquartz/Makefile.am     |    2 +
> hw/xquartz/quartz.c        |  104 +++---------
> hw/xquartz/quartz.h        |    3 +-
> hw/xquartz/quartzCommon.h  |    3 +
> hw/xquartz/quartzRandR.c   |  394 ++++++++++++++++++++++++++++++++++++++++++++
> hw/xquartz/quartzRandR.h   |   37 ++++
> hw/xquartz/xpr/xprScreen.c |    6 +-
> 7 files changed, 469 insertions(+), 80 deletions(-)
> create mode 100644 hw/xquartz/quartzRandR.c
> create mode 100644 hw/xquartz/quartzRandR.h
> 
> 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
> -- 
> 1.6.4.4
> 
>> From 08dafd774ede0f27a8cb31cc48feeb2403b398e8 Mon Sep 17 00:00:00 2001
> From: Jan Hauffa <hauffa at in.tum.de>
> Date: Fri, 16 Jul 2010 17:54:55 +0200
> Subject: [PATCH 2/3] 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>
> ---
> hw/xquartz/quartzCommon.h       |    7 +++
> hw/xquartz/quartzRandR.c        |   93 +++++++++++++++++++++++++++------------
> miext/rootless/rootlessWindow.c |    9 ++++
> 3 files changed, 81 insertions(+), 28 deletions(-)
> 
> 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;
> diff --git a/miext/rootless/rootlessWindow.c b/miext/rootless/rootlessWindow.c
> index 7fe5e1d..8f57bea 100644
> --- a/miext/rootless/rootlessWindow.c
> +++ b/miext/rootless/rootlessWindow.c
> @@ -1315,6 +1315,15 @@ RootlessResizeWindow(WindowPtr pWin, int x, int y,
>         RegionCopy(&pWin->clipList, &pWin->winSize);
>         RegionCopy(&pWin->borderClip, &pWin->winSize);
> 
> +#ifdef XQUARTZ
> +        if (winRec) {
> +            SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen,
> +                                                 x + SCREEN_TO_GLOBAL_X,
> +                                                 y + SCREEN_TO_GLOBAL_Y,
> +                                                 w, h, RL_GRAVITY_NONE);
> +        }
> +#endif
> +
>         miSendExposures(pWin, &pWin->borderClip,
>                         pWin->drawable.x, pWin->drawable.y);        
>     }
> -- 
> 1.6.4.4
> 
>> From 15709adc132603658312c621210135f6a255b33b Mon Sep 17 00:00:00 2001
> From: Jan Hauffa <hauffa at in.tum.de>
> Date: Fri, 16 Jul 2010 17:56:44 +0200
> Subject: [PATCH 3/3] XQuartz: Remove FAKE_RANDR code.
> 
> Signed-off-by: Jan Hauffa <hauffa at in.tum.de>
> ---
> hw/xquartz/quartz.c      |    6 +----
> hw/xquartz/quartzRandR.c |   52 ----------------------------------------------
> hw/xquartz/quartzRandR.h |    5 ----
> 3 files changed, 1 insertions(+), 62 deletions(-)
> 
> 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
> -- 
> 1.6.4.4
> 
>> From 734eab5835e5d81d43cd186f20755aace999d347 Mon Sep 17 00:00:00 2001
> From: Jan Hauffa <hauffa at in.tum.de>
> Date: Sat, 17 Jul 2010 00:52:42 +0200
> Subject: [PATCH] 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>
> ---
> hw/xquartz/quartzCommon.h |    7 +++
> hw/xquartz/quartzRandR.c  |  124 +++++++++++++++++++++++++++++++++------------
> 2 files changed, 98 insertions(+), 33 deletions(-)
> 
> 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..9d26576 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,24 +333,44 @@ 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);
> }
> 
> +static void QuartzRandRSetRootless(Bool rootless) {
> +    if (rootless) {
> +        QuartzSetFullscreen(FALSE);
> +        QuartzSetRootless(TRUE);
> +    }
> +    else {
> +        QuartzSetRootless(FALSE);
> +        QuartzSetFullscreen(TRUE);
> +    }
> +}
> +
> static Bool QuartzRandRSetConfig (ScreenPtr           pScreen,
> 			          Rotation            randr,
> 			          int                 rate,
> @@ -354,6 +378,19 @@ 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;
> +    }
> 
>     if (pQuartzScreen->displayCount == 0)
>         return FALSE;
> @@ -361,30 +398,51 @@ 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));
> +        QuartzRandRSetRootless(rootless);
> +        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. */
> +    /* Switch modes if requested mode is not equal to current mode. */
>     if (!QuartzRandRGetCurrentModeInfo(screenId, &curMode))
>         return FALSE;
> -    if (QuartzRandRModesEqual(&reqMode, &curMode))
> -        return TRUE;
> +    if (!QuartzRandRModesEqual(&reqMode, &curMode)) {
> +        /* Ensure that the current root window is deleted. */
> +        QuartzSetFullscreen(FALSE);
> +
> +        if (!QuartzRandREnumerateModes(pScreen, screenId,
> +                QuartzRandRSetModeCallback, &reqMode))
> +            return FALSE;
> +
> +        /* If the root window is to be restored, make sure that its size is
> +           correct. */
> +        if (!rootless && !quartzEnableRootless)
> +            QuartzUpdateScreens();
> +    }
> 
> -    return QuartzRandREnumerateModes(pScreen, screenId,
> -        QuartzRandRSetModeCallback, &reqMode);
> +    QuartzRandRSetRootless(rootless);
> +    return TRUE;
> }
> 
> 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;
> -- 
> 1.6.4.4
> 
> 
> _______________________________________________
> Xquartz-dev mailing list
> Xquartz-dev at lists.macosforge.org
> http://lists.macosforge.org/mailman/listinfo.cgi/xquartz-dev



More information about the Xquartz-dev mailing list