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