Hi, the attached patch series contains a basic implementation of XRandR functionality and some related fixes: The first patch removes some dead code I noticed, mainly orphaned forward declarations and unused global variables. The second patch makes Xinerama report the actual screen resolution instead of subtracting the size of the global menu bar. Wine uses Xinerama to determine the current resolution and expects to be able to switch back to that resolution via XRandR. The adjusted resolution is still used by XQuartz internally, and I verified that window placement still works correctly, i.e. it's still impossible to move windows below the menu bar. However, I'm not completely sure my approach here is correct. The third patch contains the routines for enumerating and setting screen modes. By commenting out the definition of "USE_DEPRECATED_API" in quartzRandR.h, you can enable the use of the new CoreGraphics API introduced in MacOS 10.6. I was unsure whether XQuartz is supposed to be compatible with earlier versions of MacOS, so I left both code paths in. The fourth and final patch removes the FAKE_RANDR code to get rid of some preprocessor conditionals. I haven't done any X11 development before, so the patches might not be ready for inclusion yet. Please let me know what needs to be done to make them acceptable. Regards, Jan
From 8e6bf23ec7068524f27f399aa1d9bcc7b5f41abd Mon Sep 17 00:00:00 2001 From: Jan Hauffa <hauffa@in.tum.de> Date: Sun, 13 Jun 2010 18:42:48 +0200 Subject: [PATCH 1/4] XQuartz: Remove some dead code.
Signed-off-by: Jan Hauffa <hauffa@in.tum.de> --- hw/xquartz/quartz.c | 4 ---- hw/xquartz/quartzCocoa.m | 11 ----------- hw/xquartz/quartzCommon.h | 15 --------------- 3 files changed, 0 insertions(+), 30 deletions(-) diff --git a/hw/xquartz/quartz.c b/hw/xquartz/quartz.c index 36d18eb..981a90f 100644 --- a/hw/xquartz/quartz.c +++ b/hw/xquartz/quartz.c @@ -67,12 +67,8 @@ #define FAKE_RANDR 1 // Shared global variables for Quartz modes -int quartzEventWriteFD = -1; int quartzUseSysBeep = 0; -int quartzUseAGL = 1; -int quartzEnableKeyEquivalents = 1; int quartzServerVisible = FALSE; -int quartzServerQuitting = FALSE; static int quartzScreenKeyIndex; DevPrivateKey quartzScreenKey = &quartzScreenKeyIndex; int aquaMenuBarHeight = 0; diff --git a/hw/xquartz/quartzCocoa.m b/hw/xquartz/quartzCocoa.m index 4501472..54c900d 100644 --- a/hw/xquartz/quartzCocoa.m +++ b/hw/xquartz/quartzCocoa.m @@ -44,17 +44,6 @@ #include "darwin.h" /* - * QuartzFSUseQDCursor - * Return whether the screen should use a QuickDraw cursor. - */ -int QuartzFSUseQDCursor( - int depth) // screen depth -{ - return TRUE; -} - - -/* * QuartzBlockHandler * Clean out any autoreleased objects. */ diff --git a/hw/xquartz/quartzCommon.h b/hw/xquartz/quartzCommon.h index 8ab70f2..a80b0b8 100644 --- a/hw/xquartz/quartzCommon.h +++ b/hw/xquartz/quartzCommon.h @@ -51,34 +51,19 @@ typedef struct { #define QUARTZ_PRIV(pScreen) \ ((QuartzScreenPtr)dixLookupPrivate(&pScreen->devPrivates, quartzScreenKey)) -// Data stored at startup for Cocoa front end -extern int quartzEventWriteFD; - // User preferences used by Quartz modes extern int quartzUseSysBeep; -extern int focusOnNewWindow; -extern int quartzUseAGL; -extern int quartzEnableKeyEquivalents; extern int quartzFullscreenDisableHotkeys; extern int quartzOptionSendsAlt; // Other shared data extern int quartzServerVisible; -extern int quartzServerQuitting; extern DevPrivateKey quartzScreenKey; extern int aquaMenuBarHeight; // Name of GLX bundle for native OpenGL extern const char *quartzOpenGLBundle; -void QuartzReadPreferences(void); -void QuartzMessageMainThread(unsigned msg, void *data, unsigned length); -void QuartzMessageServerThread(int type, int argc, ...); -void QuartzSetWindowMenu(int nitems, const char **items, - const char *shortcuts); -void QuartzFSCapture(void); -void QuartzFSRelease(void); -int QuartzFSUseQDCursor(int depth); void QuartzBlockHandler(pointer blockData, OSTimePtr pTimeout, pointer pReadmask); void QuartzWakeupHandler(pointer blockData, int result, pointer pReadmask); -- 1.6.4.4
From 0cc700bd66a81320eb9743fc27d687186435bf75 Mon Sep 17 00:00:00 2001 From: Jan Hauffa <hauffa@in.tum.de> Date: Sun, 13 Jun 2010 18:46:46 +0200 Subject: [PATCH 2/4] XQuartz: Make PseudoramiX report the actual screen resolution.
Before changing the resolution via RandR, Wine queries Xinerama for the current screen size. Without this patch, the size of the top menu bar is subtracted from the reported size, and an attempt to restore the original resolution will fail. This patch makes Xinerama report the actual resolution; the modified size is still used internally. Signed-off-by: Jan Hauffa <hauffa@in.tum.de> --- hw/xquartz/xpr/xprScreen.c | 12 +++++------- 1 files changed, 5 insertions(+), 7 deletions(-) diff --git a/hw/xquartz/xpr/xprScreen.c b/hw/xquartz/xpr/xprScreen.c index d574721..c050969 100644 --- a/hw/xquartz/xpr/xprScreen.c +++ b/hw/xquartz/xpr/xprScreen.c @@ -146,7 +146,7 @@ displayAtIndex(int index) * Return the bounds of a particular display. */ static CGRect -displayScreenBounds(CGDirectDisplayID id) +displayScreenBounds(CGDirectDisplayID id, Bool excludeMenuBar) { CGRect frame; @@ -157,7 +157,7 @@ displayScreenBounds(CGDirectDisplayID id) (int)frame.origin.x, (int)frame.origin.y); /* Remove menubar to help standard X11 window managers. */ - if (quartzEnableRootless && + if (excludeMenuBar && quartzEnableRootless && frame.origin.x == 0 && frame.origin.y == 0) { frame.origin.y += aquaMenuBarHeight; frame.size.height -= aquaMenuBarHeight; @@ -203,7 +203,7 @@ xprAddPseudoramiXScreens(int *x, int *y, int *width, int *height) /* Get the union of all screens */ for (i = 0; i < displayCount; i++) { CGDirectDisplayID dpy = displayList[i]; - frame = displayScreenBounds(dpy); + frame = displayScreenBounds(dpy, TRUE); unionRect = CGRectUnion(unionRect, frame); } @@ -221,9 +221,7 @@ xprAddPseudoramiXScreens(int *x, int *y, int *width, int *height) { CGDirectDisplayID dpy = displayList[i]; - frame = displayScreenBounds(dpy); - frame.origin.x -= unionRect.origin.x; - frame.origin.y -= unionRect.origin.y; + frame = displayScreenBounds(dpy, FALSE); DEBUG_LOG(" placed at X11 coordinate (%d,%d).\n", (int)frame.origin.x, (int)frame.origin.y); @@ -337,7 +335,7 @@ xprAddScreen(int index, ScreenPtr pScreen) dpy = displayAtIndex(index); - frame = displayScreenBounds(dpy); + frame = displayScreenBounds(dpy, TRUE); dfb->x = frame.origin.x; dfb->y = frame.origin.y; -- 1.6.4.4
From 9d48ea7390c42611c9b6c38feaf9e858bc85a9a0 Mon Sep 17 00:00:00 2001 From: Jan Hauffa <hauffa@in.tum.de> Date: Sun, 13 Jun 2010 19:36:57 +0200 Subject: [PATCH 3/4] 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@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 981a90f..eb9d030 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; @@ -77,30 +77,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 - /* =========================================================================== @@ -144,6 +120,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; } @@ -163,11 +146,6 @@ void QuartzInitOutput( FatalError("Could not register block and wakeup handlers."); } -#if defined(RANDR) && !defined(FAKE_RANDR) - if(!QuartzRandRInit(pScreen)) - FatalError("Failed to init RandR extension.\n"); -#endif - // Do display mode specific initialization quartzProcs->DisplayInit(); } @@ -189,50 +167,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; @@ -253,7 +187,7 @@ void QuartzUpdateScreens(void) { pScreen = screenInfo.screens[0]; PseudoramiXResetScreens(); - quartzProcs->AddPseudoramiXScreens(&x, &y, &width, &height); + quartzProcs->AddPseudoramiXScreens(&x, &y, &width, &height, pScreen); dixScreenOrigins[pScreen->myNum].x = x; dixScreenOrigins[pScreen->myNum].y = y; @@ -442,3 +376,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 a80b0b8..aeccf8b 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 c050969..f5a4c7a 100644 --- a/hw/xquartz/xpr/xprScreen.c +++ b/hw/xquartz/xpr/xprScreen.c @@ -176,7 +176,7 @@ displayScreenBounds(CGDirectDisplayID id, Bool excludeMenuBar) * 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++) { @@ -334,6 +335,7 @@ xprAddScreen(int index, ScreenPtr pScreen) ErrorF("Warning: noPseudoramiXExtension!\n"); dpy = displayAtIndex(index); + QuartzCopyDisplayIDs(pScreen, 1, &dpy); frame = displayScreenBounds(dpy, TRUE); @@ -344,7 +346,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 e48172f4101a911b3cbb141aaf5d0f1c30928ffb Mon Sep 17 00:00:00 2001 From: Jan Hauffa <hauffa@in.tum.de> Date: Sun, 13 Jun 2010 19:44:30 +0200 Subject: [PATCH 4/4] XQuartz: Remove FAKE_RANDR code.
Signed-off-by: Jan Hauffa <hauffa@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 eb9d030..749a98b 100644 --- a/hw/xquartz/quartz.c +++ b/hw/xquartz/quartz.c @@ -120,7 +120,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; @@ -235,10 +235,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 6747752..e75bea5 100644 --- a/hw/xquartz/quartzRandR.c +++ b/hw/xquartz/quartzRandR.c @@ -38,60 +38,10 @@ #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) @@ -390,5 +340,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