diff options
Diffstat (limited to 'xorg-server/hw/xquartz')
-rw-r--r-- | xorg-server/hw/xquartz/X11Application.h | 3 | ||||
-rw-r--r-- | xorg-server/hw/xquartz/X11Application.m | 29 | ||||
-rw-r--r-- | xorg-server/hw/xquartz/bundle/Resources/English.lproj/Localizable.strings | bin | 2698 -> 4410 bytes | |||
-rw-r--r-- | xorg-server/hw/xquartz/pbproxy/x-selection.h | 2 | ||||
-rw-r--r-- | xorg-server/hw/xquartz/quartz.c | 2 | ||||
-rw-r--r-- | xorg-server/hw/xquartz/quartz.h | 2 | ||||
-rw-r--r-- | xorg-server/hw/xquartz/quartzRandR.c | 1133 | ||||
-rw-r--r-- | xorg-server/hw/xquartz/xpr/xprAppleWM.c | 322 | ||||
-rw-r--r-- | xorg-server/hw/xquartz/xpr/xprFrame.c | 1288 | ||||
-rw-r--r-- | xorg-server/hw/xquartz/xpr/xprScreen.c | 934 |
10 files changed, 1899 insertions, 1816 deletions
diff --git a/xorg-server/hw/xquartz/X11Application.h b/xorg-server/hw/xquartz/X11Application.h index b3ad19b53..256ff187a 100644 --- a/xorg-server/hw/xquartz/X11Application.h +++ b/xorg-server/hw/xquartz/X11Application.h @@ -73,6 +73,8 @@ void X11ApplicationServerReady (void); void X11ApplicationShowHideMenubar (int state); void X11ApplicationLaunchClient (const char *cmd); +Bool X11ApplicationCanEnterRandR (void); + void X11ApplicationMain(int argc, char **argv, char **envp); #define PREFS_APPSMENU "apps_menu" @@ -86,6 +88,7 @@ void X11ApplicationMain(int argc, char **argv, char **envp); #define PREFS_NO_TCP "nolisten_tcp" #define PREFS_DONE_XINIT_CHECK "done_xinit_check" #define PREFS_NO_QUIT_ALERT "no_quit_alert" +#define PREFS_NO_RANDR_ALERT "no_randr_alert" #define PREFS_OPTION_SENDS_ALT "option_sends_alt" #define PREFS_FAKE_BUTTON2 "fake_button2" #define PREFS_FAKE_BUTTON3 "fake_button3" diff --git a/xorg-server/hw/xquartz/X11Application.m b/xorg-server/hw/xquartz/X11Application.m index b855c8358..3521517a2 100644 --- a/xorg-server/hw/xquartz/X11Application.m +++ b/xorg-server/hw/xquartz/X11Application.m @@ -883,6 +883,35 @@ void X11ApplicationLaunchClient (const char *cmd) { [string release]; } +/* This is a special function in that it is run from the *SERVER* thread and + * not the AppKit thread. We want to block entering a screen-capturing RandR + * mode until we notify the user about how to get out if the X11 client crashes. + */ +Bool X11ApplicationCanEnterRandR(void) { + NSString *title, *msg; + + if([X11App prefs_get_boolean:@PREFS_NO_RANDR_ALERT default:NO] || XQuartzShieldingWindowLevel != 0) + return TRUE; + + title = NSLocalizedString(@"Enter RandR mode?", @"Dialog title when switching to RandR"); + msg = NSLocalizedString(@"An application has requested X11 to change the resolution of your display. X11 will restore the display to its previous state when the requesting application requests to return to the previous state. Alternatively, you can use the ⌥⌘A key sequence to force X11 to return to the previous state.", + @"Dialog when switching to RandR"); + + if(!XQuartzIsRootless) + QuartzShowFullscreen(FALSE); + + switch(NSRunAlertPanel(title, msg, NSLocalizedString(@"Allow", @""), NSLocalizedString (@"Cancel", @""), NSLocalizedString (@"Always Allow", @""))) { + case NSAlertOtherReturn: + [X11App prefs_set_boolean:@PREFS_NO_RANDR_ALERT value:YES]; + [X11App prefs_synchronize]; + case NSAlertDefaultReturn: + return YES; + + default: + return NO; + } +} + static void check_xinitrc (void) { char *tem, buf[1024]; NSString *msg; diff --git a/xorg-server/hw/xquartz/bundle/Resources/English.lproj/Localizable.strings b/xorg-server/hw/xquartz/bundle/Resources/English.lproj/Localizable.strings Binary files differindex 03415026e..bf2089ca1 100644 --- a/xorg-server/hw/xquartz/bundle/Resources/English.lproj/Localizable.strings +++ b/xorg-server/hw/xquartz/bundle/Resources/English.lproj/Localizable.strings diff --git a/xorg-server/hw/xquartz/pbproxy/x-selection.h b/xorg-server/hw/xquartz/pbproxy/x-selection.h index 614c8b091..d4a39e58f 100644 --- a/xorg-server/hw/xquartz/pbproxy/x-selection.h +++ b/xorg-server/hw/xquartz/pbproxy/x-selection.h @@ -33,7 +33,9 @@ #include "pbproxy.h" +#define Cursor X_Cursor #include <X11/extensions/Xfixes.h> +#undef Cursor #include <AppKit/NSPasteboard.h> diff --git a/xorg-server/hw/xquartz/quartz.c b/xorg-server/hw/xquartz/quartz.c index 222a5eab0..11e5a74d7 100644 --- a/xorg-server/hw/xquartz/quartz.c +++ b/xorg-server/hw/xquartz/quartz.c @@ -82,6 +82,8 @@ Bool XQuartzIsRootless = TRUE; Bool XQuartzServerVisible = FALSE; Bool XQuartzFullscreenMenu = FALSE; +int32_t XQuartzShieldingWindowLevel = 0; + /* =========================================================================== diff --git a/xorg-server/hw/xquartz/quartz.h b/xorg-server/hw/xquartz/quartz.h index b83391db9..67a7919b2 100644 --- a/xorg-server/hw/xquartz/quartz.h +++ b/xorg-server/hw/xquartz/quartz.h @@ -124,6 +124,8 @@ extern Bool XQuartzFullscreenMenu; /* Show the menu bar (autohide) while in FS extern Bool XQuartzFullscreenDisableHotkeys; extern Bool XQuartzOptionSendsAlt; /* Alt or Mode_switch? */ +extern int32_t XQuartzShieldingWindowLevel; /* CGShieldingWindowLevel() or 0 */ + Bool QuartzAddScreen(int index, ScreenPtr pScreen); Bool QuartzSetupScreen(int index, ScreenPtr pScreen); void QuartzInitOutput(int argc,char **argv); diff --git a/xorg-server/hw/xquartz/quartzRandR.c b/xorg-server/hw/xquartz/quartzRandR.c index 64ad72d84..05641a65d 100644 --- a/xorg-server/hw/xquartz/quartzRandR.c +++ b/xorg-server/hw/xquartz/quartzRandR.c @@ -1,563 +1,570 @@ -/*
- * Quartz-specific support for the XRandR extension
- *
- * Copyright (c) 2001-2004 Greg Parker and Torrey T. Lyons,
- * 2010 Jan Hauffa.
- * 2010 Apple Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * 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"
-#include "quartz.h"
-#include "darwin.h"
-
-#include <AvailabilityMacros.h>
-
-#include <X11/extensions/randr.h>
-#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)
-
-#define CALLBACK_SUCCESS 0
-#define CALLBACK_CONTINUE 1
-#define CALLBACK_ERROR -1
-
-typedef int (*QuartzModeCallback)
- (ScreenPtr, QuartzModeInfoPtr, void *);
-
-#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
-
-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;
- pMode->pSize = NULL;
-}
-
-static Bool QuartzRandRCopyCurrentModeInfo (CGDirectDisplayID screenId,
- QuartzModeInfoPtr pMode) {
- CFDictionaryRef curModeRef = CGDisplayCurrentMode(screenId);
- if (!curModeRef)
- return FALSE;
-
- QuartzRandRGetModeInfo(curModeRef, pMode);
- pMode->ref = (void *)curModeRef;
- CFRetain(pMode->ref);
- return TRUE;
-}
-
-static Bool QuartzRandRSetCGMode (CGDirectDisplayID screenId,
- QuartzModeInfoPtr pMode) {
- CFDictionaryRef modeRef = (CFDictionaryRef) pMode->ref;
- return (CGDisplaySwitchToMode(screenId, modeRef) == kCGErrorSuccess);
-}
-
-static Bool QuartzRandREnumerateModes (ScreenPtr pScreen,
- QuartzModeCallback callback,
- void *data) {
- CFDictionaryRef curModeRef, modeRef;
- long curBpp;
- CFArrayRef modes;
- QuartzModeInfo modeInfo;
- int i;
- BOOL retval = FALSE;
- QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
- CGDirectDisplayID screenId = pQuartzScreen->displayIDs[0];
-
- 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++) {
- int cb;
- 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 = (void *)modeRef;
- cb = callback(pScreen, &modeInfo, data);
- if (cb == CALLBACK_CONTINUE)
- retval = TRUE;
- else if (cb == CALLBACK_SUCCESS)
- return TRUE;
- else if (cb == CALLBACK_ERROR)
- return FALSE;
- }
-
- switch(callback(pScreen, &pQuartzScreen->rootlessMode, data)) {
- case CALLBACK_SUCCESS:
- return TRUE;
- case CALLBACK_ERROR:
- return FALSE;
- case CALLBACK_CONTINUE:
- retval = TRUE;
- default:
- break;
- }
-
- switch(callback(pScreen, &pQuartzScreen->fullscreenMode, data)) {
- case CALLBACK_SUCCESS:
- return TRUE;
- case CALLBACK_ERROR:
- return FALSE;
- case CALLBACK_CONTINUE:
- retval = TRUE;
- default:
- break;
- }
-
- return retval;
-}
-
-#else /* we have the new CG APIs from Snow Leopard */
-
-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;
- pMode->pSize = NULL;
-}
-
-static Bool QuartzRandRCopyCurrentModeInfo (CGDirectDisplayID screenId,
- QuartzModeInfoPtr pMode) {
- CGDisplayModeRef curModeRef = CGDisplayCopyDisplayMode(screenId);
- if (!curModeRef)
- return FALSE;
-
- QuartzRandRGetModeInfo(curModeRef, pMode);
- pMode->ref = curModeRef;
- return TRUE;
-}
-
-static Bool QuartzRandRSetCGMode (CGDirectDisplayID screenId,
- QuartzModeInfoPtr pMode) {
- CGDisplayModeRef modeRef = (CGDisplayModeRef) pMode->ref;
- if (!modeRef)
- return FALSE;
-
- return (CGDisplaySetDisplayMode(screenId, modeRef, NULL) == kCGErrorSuccess);
-}
-
-static Bool QuartzRandREnumerateModes (ScreenPtr pScreen,
- QuartzModeCallback callback,
- void *data) {
- CGDisplayModeRef curModeRef, modeRef;
- CFStringRef curPixelEnc, pixelEnc;
- CFComparisonResult pixelEncEqual;
- CFArrayRef modes;
- QuartzModeInfo modeInfo;
- int i;
- Bool retval = FALSE;
-
- QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
- CGDirectDisplayID screenId = pQuartzScreen->displayIDs[0];
-
- 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++) {
- int cb;
- 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;
- cb = callback(pScreen, &modeInfo, data);
- if (cb == CALLBACK_CONTINUE) {
- retval = TRUE;
- } else if (cb == CALLBACK_SUCCESS) {
- CFRelease(modes);
- CFRelease(curPixelEnc);
- return TRUE;
- } else if (cb == CALLBACK_ERROR) {
- CFRelease(modes);
- CFRelease(curPixelEnc);
- return FALSE;
- }
- }
-
- CFRelease(modes);
- CFRelease(curPixelEnc);
-
- switch(callback(pScreen, &pQuartzScreen->rootlessMode, data)) {
- case CALLBACK_SUCCESS:
- return TRUE;
- case CALLBACK_ERROR:
- return FALSE;
- case CALLBACK_CONTINUE:
- retval = TRUE;
- default:
- break;
- }
-
- switch(callback(pScreen, &pQuartzScreen->fullscreenMode, data)) {
- case CALLBACK_SUCCESS:
- return TRUE;
- case CALLBACK_ERROR:
- return FALSE;
- case CALLBACK_CONTINUE:
- retval = TRUE;
- default:
- break;
- }
-
- return retval;
-}
-
-#endif /* Snow Leopard CoreGraphics APIs */
-
-
-static Bool QuartzRandRModesEqual (QuartzModeInfoPtr pMode1,
- QuartzModeInfoPtr pMode2) {
- return (pMode1->width == pMode2->width) &&
- (pMode1->height == pMode2->height) &&
- (pMode1->refresh == pMode2->refresh);
-}
-
-static Bool QuartzRandRRegisterMode (ScreenPtr pScreen,
- QuartzModeInfoPtr pMode) {
- QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
- Bool isCurrentMode = QuartzRandRModesEqual(&pQuartzScreen->currentMode, pMode);
-
- /* TODO: DPI */
- pMode->pSize = RRRegisterSize(pScreen, pMode->width, pMode->height, pScreen->mmWidth, pScreen->mmHeight);
- if (pMode->pSize) {
- //DEBUG_LOG("registering: %d x %d @ %d %s\n", (int)pMode->width, (int)pMode->height, (int)pMode->refresh, isCurrentMode ? "*" : "");
- RRRegisterRate(pScreen, pMode->pSize, pMode->refresh);
-
- if (isCurrentMode)
- RRSetCurrentConfig(pScreen, RR_Rotate_0, pMode->refresh, pMode->pSize);
-
- return TRUE;
- }
- return FALSE;
-}
-
-static int QuartzRandRRegisterModeCallback (ScreenPtr pScreen,
- QuartzModeInfoPtr pMode,
- void *data __unused) {
- if(QuartzRandRRegisterMode(pScreen, pMode)) {
- return CALLBACK_CONTINUE;
- } else {
- return CALLBACK_ERROR;
- }
-}
-
-static Bool QuartzRandRSetMode(ScreenPtr pScreen, QuartzModeInfoPtr pMode, BOOL doRegister) {
- QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
- CGDirectDisplayID screenId = pQuartzScreen->displayIDs[0];
-
- if (pQuartzScreen->currentMode.ref && CFEqual(pMode->ref, pQuartzScreen->currentMode.ref)) {
- DEBUG_LOG("Requested RandR resolution matches current CG mode\n");
- } if (QuartzRandRSetCGMode(screenId, pMode)) {
- ignore_next_fake_mode_update = TRUE;
- } else {
- DEBUG_LOG("Error while requesting CG resolution change.\n");
- return FALSE;
- }
-
- /* If the client requested the fake rootless mode, switch to rootless.
- * Otherwise, force fullscreen mode.
- */
- QuartzSetRootless(pMode->refresh == FAKE_REFRESH_ROOTLESS);
- if (pMode->refresh != FAKE_REFRESH_ROOTLESS) {
- QuartzShowFullscreen(TRUE);
- }
-
- if(pQuartzScreen->currentMode.ref)
- CFRelease(pQuartzScreen->currentMode.ref);
- pQuartzScreen->currentMode = *pMode;
- CFRetain(pQuartzScreen->currentMode.ref);
-
- return TRUE;
-}
-
-static int QuartzRandRSetModeCallback (ScreenPtr pScreen,
- QuartzModeInfoPtr pMode,
- void *data) {
- QuartzModeInfoPtr pReqMode = (QuartzModeInfoPtr) data;
-
- if (!QuartzRandRModesEqual(pMode, pReqMode))
- return CALLBACK_CONTINUE; /* continue enumeration */
-
- DEBUG_LOG("Found a match for requested RandR resolution (%dx%d@%d).\n", (int)pMode->width, (int)pMode->height, (int)pMode->refresh);
-
- if(QuartzRandRSetMode(pScreen, pMode, FALSE))
- return CALLBACK_SUCCESS;
- else
- return CALLBACK_ERROR;
-}
-
-static Bool QuartzRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) {
- QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
-
- *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 two entries for the current virtual
- resolution including/excluding the menu bar. */
-
- QuartzRandRRegisterMode(pScreen, &pQuartzScreen->rootlessMode);
- QuartzRandRRegisterMode(pScreen, &pQuartzScreen->fullscreenMode);
- return TRUE;
- }
-
- return QuartzRandREnumerateModes(pScreen, QuartzRandRRegisterModeCallback, NULL);
-}
-
-static Bool QuartzRandRSetConfig (ScreenPtr pScreen,
- Rotation randr,
- int rate,
- RRScreenSizePtr pSize) {
- QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
- QuartzModeInfo reqMode;
-
- reqMode.width = pSize->width;
- reqMode.height = pSize->height;
- reqMode.refresh = rate;
-
- if (pQuartzScreen->displayCount == 0)
- return FALSE;
-
- /* Do not switch modes if requested mode is equal to current mode. */
- if (QuartzRandRModesEqual(&reqMode, &pQuartzScreen->currentMode))
- return TRUE;
-
- if (QuartzRandREnumerateModes(pScreen, QuartzRandRSetModeCallback, &reqMode)) {
- return TRUE;
- }
-
- DEBUG_LOG("Unable to find a matching config: %d x %d @ %d\n", (int)reqMode.width, (int)reqMode.height, (int)reqMode.refresh);
- return FALSE;
-}
-
-static Bool _QuartzRandRUpdateFakeModes (ScreenPtr pScreen) {
- QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
-
- if(pQuartzScreen->fullscreenMode.ref)
- CFRelease(pQuartzScreen->fullscreenMode.ref);
- if(pQuartzScreen->currentMode.ref)
- CFRelease(pQuartzScreen->currentMode.ref);
-
- if (!QuartzRandRCopyCurrentModeInfo(pQuartzScreen->displayIDs[0],
- &pQuartzScreen->fullscreenMode))
- return FALSE;
-
- if (pQuartzScreen->displayCount > 1) {
- pQuartzScreen->fullscreenMode.width = pScreen->width;
- pQuartzScreen->fullscreenMode.height = pScreen->height;
- if(XQuartzIsRootless)
- pQuartzScreen->fullscreenMode.height += aquaMenuBarHeight;
- }
-
- pQuartzScreen->fullscreenMode.refresh = FAKE_REFRESH_FULLSCREEN;
-
- pQuartzScreen->rootlessMode = pQuartzScreen->fullscreenMode;
- pQuartzScreen->rootlessMode.refresh = FAKE_REFRESH_ROOTLESS;
- pQuartzScreen->rootlessMode.height -= aquaMenuBarHeight;
-
- if(XQuartzIsRootless) {
- pQuartzScreen->currentMode = pQuartzScreen->rootlessMode;
- } else {
- pQuartzScreen->currentMode = pQuartzScreen->fullscreenMode;
- }
-
- /* This extra retain is for currentMode's copy.
- * fullscreen and rootless share a retain.
- */
- CFRetain(pQuartzScreen->currentMode.ref);
-
- 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;
- pScrPriv->rrSetConfig = QuartzRandRSetConfig;
- return TRUE;
-}
-
-void QuartzRandRSetFakeRootless (void) {
- int i;
-
- DEBUG_LOG("QuartzRandRSetFakeRootless called.\n");
-
- for (i=0; i < screenInfo.numScreens; i++) {
- ScreenPtr pScreen = screenInfo.screens[i];
- QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
-
- QuartzRandRSetMode(pScreen, &pQuartzScreen->rootlessMode, TRUE);
- }
-}
-
-void QuartzRandRSetFakeFullscreen (BOOL state) {
- int i;
-
- DEBUG_LOG("QuartzRandRSetFakeFullscreen called.\n");
-
- for (i=0; i < screenInfo.numScreens; i++) {
- ScreenPtr pScreen = screenInfo.screens[i];
- QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
-
- QuartzRandRSetMode(pScreen, &pQuartzScreen->fullscreenMode, TRUE);
- }
-
- QuartzShowFullscreen(state);
-}
-
-/* Toggle fullscreen mode. If "fake" fullscreen is the current mode,
- * this will just show/hide the X11 windows. If we are in a RandR fullscreen
- * mode, this will toggles us to the default fake mode and hide windows if
- * it is fullscreen
- */
-void QuartzRandRToggleFullscreen (void) {
- ScreenPtr pScreen = screenInfo.screens[0];
- QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
-
- if (pQuartzScreen->currentMode.ref == NULL) {
- ErrorF("Ignoring QuartzRandRToggleFullscreen because don't have a current mode set.\n");
- } else if (pQuartzScreen->currentMode.refresh == FAKE_REFRESH_ROOTLESS) {
- ErrorF("Ignoring QuartzRandRToggleFullscreen because we are in rootless mode.\n");
- } else if (pQuartzScreen->currentMode.refresh == FAKE_REFRESH_FULLSCREEN) {
- /* Legacy fullscreen mode. Hide/Show */
- QuartzShowFullscreen(!XQuartzFullscreenVisible);
- } else {
- /* RandR fullscreen mode. Return to default mode and hide if it is fullscreen. */
- if(XQuartzRootlessDefault) {
- QuartzRandRSetFakeRootless();
- } else {
- QuartzRandRSetFakeFullscreen(FALSE);
- }
- }
-}
+/* + * Quartz-specific support for the XRandR extension + * + * Copyright (c) 2001-2004 Greg Parker and Torrey T. Lyons, + * 2010 Jan Hauffa. + * 2010 Apple Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * 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" +#include "quartz.h" +#include "darwin.h" + +#include "X11Application.h" + +#include <AvailabilityMacros.h> + +#include <X11/extensions/randr.h> +#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) + +#define CALLBACK_SUCCESS 0 +#define CALLBACK_CONTINUE 1 +#define CALLBACK_ERROR -1 + +typedef int (*QuartzModeCallback) + (ScreenPtr, QuartzModeInfoPtr, void *); + +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 + +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; + pMode->pSize = NULL; +} + +static Bool QuartzRandRCopyCurrentModeInfo (CGDirectDisplayID screenId, + QuartzModeInfoPtr pMode) { + CFDictionaryRef curModeRef = CGDisplayCurrentMode(screenId); + if (!curModeRef) + return FALSE; + + QuartzRandRGetModeInfo(curModeRef, pMode); + pMode->ref = (void *)curModeRef; + CFRetain(pMode->ref); + return TRUE; +} + +static Bool QuartzRandRSetCGMode (CGDirectDisplayID screenId, + QuartzModeInfoPtr pMode) { + CFDictionaryRef modeRef = (CFDictionaryRef) pMode->ref; + return (CGDisplaySwitchToMode(screenId, modeRef) == kCGErrorSuccess); +} + +static Bool QuartzRandREnumerateModes (ScreenPtr pScreen, + QuartzModeCallback callback, + void *data) { + CFDictionaryRef curModeRef, modeRef; + long curBpp; + CFArrayRef modes; + QuartzModeInfo modeInfo; + int i; + BOOL retval = FALSE; + QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); + CGDirectDisplayID screenId = pQuartzScreen->displayIDs[0]; + + 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++) { + int cb; + 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 = (void *)modeRef; + cb = callback(pScreen, &modeInfo, data); + if (cb == CALLBACK_CONTINUE) + retval = TRUE; + else if (cb == CALLBACK_SUCCESS) + return TRUE; + else if (cb == CALLBACK_ERROR) + return FALSE; + } + + switch(callback(pScreen, &pQuartzScreen->rootlessMode, data)) { + case CALLBACK_SUCCESS: + return TRUE; + case CALLBACK_ERROR: + return FALSE; + case CALLBACK_CONTINUE: + retval = TRUE; + default: + break; + } + + switch(callback(pScreen, &pQuartzScreen->fullscreenMode, data)) { + case CALLBACK_SUCCESS: + return TRUE; + case CALLBACK_ERROR: + return FALSE; + case CALLBACK_CONTINUE: + retval = TRUE; + default: + break; + } + + return retval; +} + +#else /* we have the new CG APIs from Snow Leopard */ + +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; + pMode->pSize = NULL; +} + +static Bool QuartzRandRCopyCurrentModeInfo (CGDirectDisplayID screenId, + QuartzModeInfoPtr pMode) { + CGDisplayModeRef curModeRef = CGDisplayCopyDisplayMode(screenId); + if (!curModeRef) + return FALSE; + + QuartzRandRGetModeInfo(curModeRef, pMode); + pMode->ref = curModeRef; + return TRUE; +} + +static Bool QuartzRandRSetCGMode (CGDirectDisplayID screenId, + QuartzModeInfoPtr pMode) { + CGDisplayModeRef modeRef = (CGDisplayModeRef) pMode->ref; + if (!modeRef) + return FALSE; + + return (CGDisplaySetDisplayMode(screenId, modeRef, NULL) == kCGErrorSuccess); +} + +static Bool QuartzRandREnumerateModes (ScreenPtr pScreen, + QuartzModeCallback callback, + void *data) { + CGDisplayModeRef curModeRef, modeRef; + CFStringRef curPixelEnc, pixelEnc; + CFComparisonResult pixelEncEqual; + CFArrayRef modes; + QuartzModeInfo modeInfo; + int i; + Bool retval = FALSE; + + QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); + CGDirectDisplayID screenId = pQuartzScreen->displayIDs[0]; + + 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++) { + int cb; + 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; + cb = callback(pScreen, &modeInfo, data); + if (cb == CALLBACK_CONTINUE) { + retval = TRUE; + } else if (cb == CALLBACK_SUCCESS) { + CFRelease(modes); + CFRelease(curPixelEnc); + return TRUE; + } else if (cb == CALLBACK_ERROR) { + CFRelease(modes); + CFRelease(curPixelEnc); + return FALSE; + } + } + + CFRelease(modes); + CFRelease(curPixelEnc); + + switch(callback(pScreen, &pQuartzScreen->rootlessMode, data)) { + case CALLBACK_SUCCESS: + return TRUE; + case CALLBACK_ERROR: + return FALSE; + case CALLBACK_CONTINUE: + retval = TRUE; + default: + break; + } + + switch(callback(pScreen, &pQuartzScreen->fullscreenMode, data)) { + case CALLBACK_SUCCESS: + return TRUE; + case CALLBACK_ERROR: + return FALSE; + case CALLBACK_CONTINUE: + retval = TRUE; + default: + break; + } + + return retval; +} + +#endif /* Snow Leopard CoreGraphics APIs */ + + +static Bool QuartzRandRModesEqual (QuartzModeInfoPtr pMode1, + QuartzModeInfoPtr pMode2) { + return (pMode1->width == pMode2->width) && + (pMode1->height == pMode2->height) && + (pMode1->refresh == pMode2->refresh); +} + +static Bool QuartzRandRRegisterMode (ScreenPtr pScreen, + QuartzModeInfoPtr pMode) { + QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); + Bool isCurrentMode = QuartzRandRModesEqual(&pQuartzScreen->currentMode, pMode); + + /* TODO: DPI */ + pMode->pSize = RRRegisterSize(pScreen, pMode->width, pMode->height, pScreen->mmWidth, pScreen->mmHeight); + if (pMode->pSize) { + //DEBUG_LOG("registering: %d x %d @ %d %s\n", (int)pMode->width, (int)pMode->height, (int)pMode->refresh, isCurrentMode ? "*" : ""); + RRRegisterRate(pScreen, pMode->pSize, pMode->refresh); + + if (isCurrentMode) + RRSetCurrentConfig(pScreen, RR_Rotate_0, pMode->refresh, pMode->pSize); + + return TRUE; + } + return FALSE; +} + +static int QuartzRandRRegisterModeCallback (ScreenPtr pScreen, + QuartzModeInfoPtr pMode, + void *data __unused) { + if(QuartzRandRRegisterMode(pScreen, pMode)) { + return CALLBACK_CONTINUE; + } else { + return CALLBACK_ERROR; + } +} + +static Bool QuartzRandRSetMode(ScreenPtr pScreen, QuartzModeInfoPtr pMode, BOOL doRegister) { + QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); + CGDirectDisplayID screenId = pQuartzScreen->displayIDs[0]; + Bool captureDisplay = (pMode->refresh != FAKE_REFRESH_FULLSCREEN && pMode->refresh != FAKE_REFRESH_ROOTLESS); + + if(XQuartzShieldingWindowLevel == 0 && captureDisplay) { + if(!X11ApplicationCanEnterRandR()) + return FALSE; + CGCaptureAllDisplays(); + XQuartzShieldingWindowLevel = CGShieldingWindowLevel(); // 2147483630 + DEBUG_LOG("Display captured. ShieldWindowID: %u, Shield level: %d\n", + CGShieldingWindowID(screenId), XQuartzShieldingWindowLevel); + } + + if (pQuartzScreen->currentMode.ref && CFEqual(pMode->ref, pQuartzScreen->currentMode.ref)) { + DEBUG_LOG("Requested RandR resolution matches current CG mode\n"); + } if (QuartzRandRSetCGMode(screenId, pMode)) { + ignore_next_fake_mode_update = TRUE; + } else { + DEBUG_LOG("Error while requesting CG resolution change.\n"); + return FALSE; + } + + /* If the client requested the fake rootless mode, switch to rootless. + * Otherwise, force fullscreen mode. + */ + QuartzSetRootless(pMode->refresh == FAKE_REFRESH_ROOTLESS); + if (pMode->refresh != FAKE_REFRESH_ROOTLESS) { + QuartzShowFullscreen(TRUE); + } + + if(pQuartzScreen->currentMode.ref) + CFRelease(pQuartzScreen->currentMode.ref); + pQuartzScreen->currentMode = *pMode; + CFRetain(pQuartzScreen->currentMode.ref); + + if(XQuartzShieldingWindowLevel != 0 && !captureDisplay) { + CGReleaseAllDisplays(); + XQuartzShieldingWindowLevel = 0; + } + + return TRUE; +} + +static int QuartzRandRSetModeCallback (ScreenPtr pScreen, + QuartzModeInfoPtr pMode, + void *data) { + QuartzModeInfoPtr pReqMode = (QuartzModeInfoPtr) data; + + if (!QuartzRandRModesEqual(pMode, pReqMode)) + return CALLBACK_CONTINUE; /* continue enumeration */ + + DEBUG_LOG("Found a match for requested RandR resolution (%dx%d@%d).\n", (int)pMode->width, (int)pMode->height, (int)pMode->refresh); + + if(QuartzRandRSetMode(pScreen, pMode, FALSE)) + return CALLBACK_SUCCESS; + else + return CALLBACK_ERROR; +} + +static Bool QuartzRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) { + QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); + + *rotations = RR_Rotate_0; /* TODO: support rotation */ + + if (pQuartzScreen->displayCount == 0) + return FALSE; + + return QuartzRandREnumerateModes(pScreen, QuartzRandRRegisterModeCallback, NULL); +} + +static Bool QuartzRandRSetConfig (ScreenPtr pScreen, + Rotation randr, + int rate, + RRScreenSizePtr pSize) { + QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); + QuartzModeInfo reqMode; + + reqMode.width = pSize->width; + reqMode.height = pSize->height; + reqMode.refresh = rate; + + if (pQuartzScreen->displayCount == 0) + return FALSE; + + /* Do not switch modes if requested mode is equal to current mode. */ + if (QuartzRandRModesEqual(&reqMode, &pQuartzScreen->currentMode)) + return TRUE; + + if (QuartzRandREnumerateModes(pScreen, QuartzRandRSetModeCallback, &reqMode)) { + return TRUE; + } + + DEBUG_LOG("Unable to find a matching config: %d x %d @ %d\n", (int)reqMode.width, (int)reqMode.height, (int)reqMode.refresh); + return FALSE; +} + +static Bool _QuartzRandRUpdateFakeModes (ScreenPtr pScreen) { + QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); + + if(pQuartzScreen->fullscreenMode.ref) + CFRelease(pQuartzScreen->fullscreenMode.ref); + if(pQuartzScreen->currentMode.ref) + CFRelease(pQuartzScreen->currentMode.ref); + + if (!QuartzRandRCopyCurrentModeInfo(pQuartzScreen->displayIDs[0], + &pQuartzScreen->fullscreenMode)) + return FALSE; + + if (pQuartzScreen->displayCount > 1) { + pQuartzScreen->fullscreenMode.width = pScreen->width; + pQuartzScreen->fullscreenMode.height = pScreen->height; + if(XQuartzIsRootless) + pQuartzScreen->fullscreenMode.height += aquaMenuBarHeight; + } + + pQuartzScreen->fullscreenMode.refresh = FAKE_REFRESH_FULLSCREEN; + + pQuartzScreen->rootlessMode = pQuartzScreen->fullscreenMode; + pQuartzScreen->rootlessMode.refresh = FAKE_REFRESH_ROOTLESS; + pQuartzScreen->rootlessMode.height -= aquaMenuBarHeight; + + if(XQuartzIsRootless) { + pQuartzScreen->currentMode = pQuartzScreen->rootlessMode; + } else { + pQuartzScreen->currentMode = pQuartzScreen->fullscreenMode; + } + + /* This extra retain is for currentMode's copy. + * fullscreen and rootless share a retain. + */ + CFRetain(pQuartzScreen->currentMode.ref); + + 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; + pScrPriv->rrSetConfig = QuartzRandRSetConfig; + return TRUE; +} + +void QuartzRandRSetFakeRootless (void) { + int i; + + DEBUG_LOG("QuartzRandRSetFakeRootless called.\n"); + + for (i=0; i < screenInfo.numScreens; i++) { + ScreenPtr pScreen = screenInfo.screens[i]; + QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); + + QuartzRandRSetMode(pScreen, &pQuartzScreen->rootlessMode, TRUE); + } +} + +void QuartzRandRSetFakeFullscreen (BOOL state) { + int i; + + DEBUG_LOG("QuartzRandRSetFakeFullscreen called.\n"); + + for (i=0; i < screenInfo.numScreens; i++) { + ScreenPtr pScreen = screenInfo.screens[i]; + QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); + + QuartzRandRSetMode(pScreen, &pQuartzScreen->fullscreenMode, TRUE); + } + + QuartzShowFullscreen(state); +} + +/* Toggle fullscreen mode. If "fake" fullscreen is the current mode, + * this will just show/hide the X11 windows. If we are in a RandR fullscreen + * mode, this will toggles us to the default fake mode and hide windows if + * it is fullscreen + */ +void QuartzRandRToggleFullscreen (void) { + ScreenPtr pScreen = screenInfo.screens[0]; + QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); + + if (pQuartzScreen->currentMode.ref == NULL) { + ErrorF("Ignoring QuartzRandRToggleFullscreen because don't have a current mode set.\n"); + } else if (pQuartzScreen->currentMode.refresh == FAKE_REFRESH_ROOTLESS) { + ErrorF("Ignoring QuartzRandRToggleFullscreen because we are in rootless mode.\n"); + } else if (pQuartzScreen->currentMode.refresh == FAKE_REFRESH_FULLSCREEN) { + /* Legacy fullscreen mode. Hide/Show */ + QuartzShowFullscreen(!XQuartzFullscreenVisible); + } else { + /* RandR fullscreen mode. Return to default mode and hide if it is fullscreen. */ + if(XQuartzRootlessDefault) { + QuartzRandRSetFakeRootless(); + } else { + QuartzRandRSetFakeFullscreen(FALSE); + } + } +} diff --git a/xorg-server/hw/xquartz/xpr/xprAppleWM.c b/xorg-server/hw/xquartz/xpr/xprAppleWM.c index 59ce6375e..21e6f98fa 100644 --- a/xorg-server/hw/xquartz/xpr/xprAppleWM.c +++ b/xorg-server/hw/xquartz/xpr/xprAppleWM.c @@ -1,160 +1,162 @@ -/*
- * Xplugin rootless implementation functions for AppleWM extension
- *
- * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
- * Copyright (c) 2003 Torrey T. Lyons. 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.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "xpr.h"
-
-#include <X11/extensions/applewmproto.h>
-
-#include "applewmExt.h"
-#include "rootless.h"
-#include "rootlessCommon.h"
-#include <Xplugin.h>
-#include <X11/X.h>
-#include "quartz.h"
-#include "x-hash.h"
-
-static int xprSetWindowLevel(
- WindowPtr pWin,
- int level)
-{
- xp_window_id wid;
- xp_window_changes wc;
- RootlessWindowRec *winRec;
-
- // AppleWMNumWindowLevels is allowed, but is only set by the server
- // for the root window.
- if (level < 0 || level >= AppleWMNumWindowLevels) {
- return BadValue;
- }
-
- wid = x_cvt_vptr_to_uint(RootlessFrameForWindow (pWin, TRUE));
- if (wid == 0)
- return BadWindow;
-
- RootlessStopDrawing (pWin, FALSE);
- winRec = WINREC(pWin);
-
- if(!winRec)
- return BadWindow;
-
- if(XQuartzIsRootless)
- wc.window_level = normal_window_levels[level];
- else
- wc.window_level = rooted_window_levels[level];
-
- if (xp_configure_window (wid, XP_WINDOW_LEVEL, &wc) != Success) {
- return BadValue;
- }
-
- winRec->level = level;
-
- return Success;
-}
-
-#if defined(XPLUGIN_VERSION) && XPLUGIN_VERSION >= 3
-static int xprAttachTransient(WindowPtr pWinChild, WindowPtr pWinParent) {
- xp_window_id child_wid, parent_wid;
- xp_window_changes wc;
-
- child_wid = x_cvt_vptr_to_uint(RootlessFrameForWindow(pWinChild, TRUE));
- if (child_wid == 0)
- return BadWindow;
-
- if(pWinParent) {
- parent_wid = x_cvt_vptr_to_uint(RootlessFrameForWindow(pWinParent, TRUE));
- if (parent_wid == 0)
- return BadWindow;
- } else {
- parent_wid = 0;
- }
-
- wc.transient_for = parent_wid;
-
- RootlessStopDrawing (pWinChild, FALSE);
-
- if (xp_configure_window(child_wid, XP_ATTACH_TRANSIENT, &wc) != Success) {
- return BadValue;
- }
-
- return Success;
-}
-#endif
-
-static int xprFrameDraw(
- WindowPtr pWin,
- int class,
- unsigned int attr,
- const BoxRec *outer,
- const BoxRec *inner,
- unsigned int title_len,
- const unsigned char *title_bytes)
-{
- xp_window_id wid;
-
- wid = x_cvt_vptr_to_uint(RootlessFrameForWindow (pWin, FALSE));
- if (wid == 0)
- return BadWindow;
-
- if (xp_frame_draw (wid, class, attr, outer, inner,
- title_len, title_bytes) != Success)
- {
- return BadValue;
- }
-
- return Success;
-}
-
-static AppleWMProcsRec xprAppleWMProcs = {
- xp_disable_update,
- xp_reenable_update,
- xprSetWindowLevel,
- xp_frame_get_rect,
- xp_frame_hit_test,
- xprFrameDraw,
-#if defined(XPLUGIN_VERSION) && XPLUGIN_VERSION >= 3
- xp_set_dock_proxy,
- xprAttachTransient
-#elif defined(XPLUGIN_VERSION) && XPLUGIN_VERSION >= 2
- xp_set_dock_proxy,
- NULL
-#else
- NULL,
- NULL
-#endif
-};
-
-
-void xprAppleWMInit(void)
-{
- AppleWMExtensionInit(&xprAppleWMProcs);
-}
+/* + * Xplugin rootless implementation functions for AppleWM extension + * + * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2003 Torrey T. Lyons. 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. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "xpr.h" + +#include <X11/extensions/applewmproto.h> + +#include "applewmExt.h" +#include "rootless.h" +#include "rootlessCommon.h" +#include <Xplugin.h> +#include <X11/X.h> +#include "quartz.h" +#include "x-hash.h" + +static int xprSetWindowLevel( + WindowPtr pWin, + int level) +{ + xp_window_id wid; + xp_window_changes wc; + RootlessWindowRec *winRec; + + // AppleWMNumWindowLevels is allowed, but is only set by the server + // for the root window. + if (level < 0 || level >= AppleWMNumWindowLevels) { + return BadValue; + } + + wid = x_cvt_vptr_to_uint(RootlessFrameForWindow (pWin, TRUE)); + if (wid == 0) + return BadWindow; + + RootlessStopDrawing (pWin, FALSE); + winRec = WINREC(pWin); + + if(!winRec) + return BadWindow; + + if(XQuartzIsRootless) + wc.window_level = normal_window_levels[level]; + else if(XQuartzShieldingWindowLevel) + wc.window_level = XQuartzShieldingWindowLevel + 1; + else + wc.window_level = rooted_window_levels[level]; + + if (xp_configure_window (wid, XP_WINDOW_LEVEL, &wc) != Success) { + return BadValue; + } + + winRec->level = level; + + return Success; +} + +#if defined(XPLUGIN_VERSION) && XPLUGIN_VERSION >= 3 +static int xprAttachTransient(WindowPtr pWinChild, WindowPtr pWinParent) { + xp_window_id child_wid, parent_wid; + xp_window_changes wc; + + child_wid = x_cvt_vptr_to_uint(RootlessFrameForWindow(pWinChild, TRUE)); + if (child_wid == 0) + return BadWindow; + + if(pWinParent) { + parent_wid = x_cvt_vptr_to_uint(RootlessFrameForWindow(pWinParent, TRUE)); + if (parent_wid == 0) + return BadWindow; + } else { + parent_wid = 0; + } + + wc.transient_for = parent_wid; + + RootlessStopDrawing (pWinChild, FALSE); + + if (xp_configure_window(child_wid, XP_ATTACH_TRANSIENT, &wc) != Success) { + return BadValue; + } + + return Success; +} +#endif + +static int xprFrameDraw( + WindowPtr pWin, + int class, + unsigned int attr, + const BoxRec *outer, + const BoxRec *inner, + unsigned int title_len, + const unsigned char *title_bytes) +{ + xp_window_id wid; + + wid = x_cvt_vptr_to_uint(RootlessFrameForWindow (pWin, FALSE)); + if (wid == 0) + return BadWindow; + + if (xp_frame_draw (wid, class, attr, outer, inner, + title_len, title_bytes) != Success) + { + return BadValue; + } + + return Success; +} + +static AppleWMProcsRec xprAppleWMProcs = { + xp_disable_update, + xp_reenable_update, + xprSetWindowLevel, + xp_frame_get_rect, + xp_frame_hit_test, + xprFrameDraw, +#if defined(XPLUGIN_VERSION) && XPLUGIN_VERSION >= 3 + xp_set_dock_proxy, + xprAttachTransient +#elif defined(XPLUGIN_VERSION) && XPLUGIN_VERSION >= 2 + xp_set_dock_proxy, + NULL +#else + NULL, + NULL +#endif +}; + + +void xprAppleWMInit(void) +{ + AppleWMExtensionInit(&xprAppleWMProcs); +} diff --git a/xorg-server/hw/xquartz/xpr/xprFrame.c b/xorg-server/hw/xquartz/xpr/xprFrame.c index fecae5a1b..15598e942 100644 --- a/xorg-server/hw/xquartz/xpr/xprFrame.c +++ b/xorg-server/hw/xquartz/xpr/xprFrame.c @@ -1,642 +1,646 @@ -/*
- * Xplugin rootless implementation frame functions
- *
- * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
- * Copyright (c) 2003 Torrey T. Lyons. 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.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "xpr.h"
-#include "rootlessCommon.h"
-#include <Xplugin.h>
-#include "x-hash.h"
-#include "x-list.h"
-#include "applewmExt.h"
-
-#include "propertyst.h"
-#include "dix.h"
-#include <X11/Xatom.h>
-#include "windowstr.h"
-#include "quartz.h"
-
-#include "threadSafety.h"
-
-#include <pthread.h>
-
-#define DEFINE_ATOM_HELPER(func,atom_name) \
-static Atom func (void) { \
- static int generation; \
- static Atom atom; \
- if (generation != serverGeneration) { \
- generation = serverGeneration; \
- atom = MakeAtom (atom_name, strlen (atom_name), TRUE); \
- } \
- return atom; \
-}
-
-DEFINE_ATOM_HELPER(xa_native_window_id, "_NATIVE_WINDOW_ID")
-
-/* Maps xp_window_id -> RootlessWindowRec */
-static x_hash_table *window_hash;
-static pthread_mutex_t window_hash_mutex;
-
-/* Prototypes for static functions */
-static Bool xprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen,
- int newX, int newY, RegionPtr pShape);
-static void xprDestroyFrame(RootlessFrameID wid);
-static void xprMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY);
-static void xprResizeFrame(RootlessFrameID wid, ScreenPtr pScreen,
- int newX, int newY, unsigned int newW, unsigned int newH,
- unsigned int gravity);
-static void xprRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid);
-static void xprReshapeFrame(RootlessFrameID wid, RegionPtr pShape);
-static void xprUnmapFrame(RootlessFrameID wid);
-static void xprStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow);
-static void xprStopDrawing(RootlessFrameID wid, Bool flush);
-static void xprUpdateRegion(RootlessFrameID wid, RegionPtr pDamage);
-static void xprDamageRects(RootlessFrameID wid, int nrects, const BoxRec *rects,
- int shift_x, int shift_y);
-static void xprSwitchWindow(RootlessWindowPtr pFrame, WindowPtr oldWin);
-static Bool xprDoReorderWindow(RootlessWindowPtr pFrame);
-static void xprHideWindow(RootlessFrameID wid);
-static void xprUpdateColormap(RootlessFrameID wid, ScreenPtr pScreen);
-static void xprCopyWindow(RootlessFrameID wid, int dstNrects, const BoxRec *dstRects,
- int dx, int dy);
-
-
-static inline xp_error
-xprConfigureWindow(xp_window_id id, unsigned int mask,
- const xp_window_changes *values)
-{
- TA_SERVER();
-
- return xp_configure_window(id, mask, values);
-}
-
-
-static void
-xprSetNativeProperty(RootlessWindowPtr pFrame)
-{
- xp_error err;
- unsigned int native_id;
- long data;
-
- TA_SERVER();
-
- err = xp_get_native_window(x_cvt_vptr_to_uint(pFrame->wid), &native_id);
- if (err == Success)
- {
- /* FIXME: move this to AppleWM extension */
-
- data = native_id;
- dixChangeWindowProperty(serverClient, pFrame->win, xa_native_window_id(),
- XA_INTEGER, 32, PropModeReplace, 1, &data, TRUE);
- }
-}
-
-static xp_error
-xprColormapCallback(void *data, int first_color, int n_colors, uint32_t *colors)
-{
- return (RootlessResolveColormap (data, first_color, n_colors, colors) ? XP_Success : XP_BadMatch);
-}
-
-/*
- * Create and display a new frame.
- */
-static Bool
-xprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen,
- int newX, int newY, RegionPtr pShape)
-{
- WindowPtr pWin = pFrame->win;
- xp_window_changes wc;
- unsigned int mask = 0;
- xp_error err;
-
- TA_SERVER();
-
- wc.x = newX;
- wc.y = newY;
- wc.width = pFrame->width;
- wc.height = pFrame->height;
- wc.bit_gravity = XP_GRAVITY_NONE;
- mask |= XP_BOUNDS;
-
- if (pWin->drawable.depth == 8)
- {
- wc.depth = XP_DEPTH_INDEX8;
- wc.colormap = xprColormapCallback;
- wc.colormap_data = pScreen;
- mask |= XP_COLORMAP;
- }
- else if (pWin->drawable.depth == 15)
- wc.depth = XP_DEPTH_RGB555;
- else if (pWin->drawable.depth == 24)
- wc.depth = XP_DEPTH_ARGB8888;
- else
- wc.depth = XP_DEPTH_NIL;
- mask |= XP_DEPTH;
-
- if (pShape != NULL)
- {
- wc.shape_nrects = RegionNumRects(pShape);
- wc.shape_rects = RegionRects(pShape);
- wc.shape_tx = wc.shape_ty = 0;
- mask |= XP_SHAPE;
- }
-
- pFrame->level = !IsRoot (pWin) ? AppleWMWindowLevelNormal : AppleWMNumWindowLevels;
-
- if(XQuartzIsRootless)
- wc.window_level = normal_window_levels[pFrame->level];
- else
- wc.window_level = rooted_window_levels[pFrame->level];
- mask |= XP_WINDOW_LEVEL;
-
- err = xp_create_window(mask, &wc, (xp_window_id *) &pFrame->wid);
-
- if (err != Success)
- {
- return FALSE;
- }
-
- if (window_hash == NULL)
- {
- window_hash = x_hash_table_new(NULL, NULL, NULL, NULL);
- pthread_mutex_init(&window_hash_mutex, NULL);
- }
-
- pthread_mutex_lock(&window_hash_mutex);
- x_hash_table_insert(window_hash, pFrame->wid, pFrame);
- pthread_mutex_unlock(&window_hash_mutex);
-
- xprSetNativeProperty(pFrame);
-
- return TRUE;
-}
-
-
-/*
- * Destroy a frame.
- */
-static void
-xprDestroyFrame(RootlessFrameID wid)
-{
- xp_error err;
- TA_SERVER();
-
- pthread_mutex_lock(&window_hash_mutex);
- x_hash_table_remove(window_hash, wid);
- pthread_mutex_unlock(&window_hash_mutex);
-
- err = xp_destroy_window(x_cvt_vptr_to_uint(wid));
- if (err != Success)
- FatalError("Could not destroy window %i.", (int)x_cvt_vptr_to_uint(wid));
-}
-
-
-/*
- * Move a frame on screen.
- */
-static void
-xprMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY)
-{
- xp_window_changes wc;
-
- TA_SERVER();
-
- wc.x = newX;
- wc.y = newY;
- // ErrorF("xprMoveFrame(%d, %p, %d, %d)\n", wid, pScreen, newX, newY);
- xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_ORIGIN, &wc);
-}
-
-
-/*
- * Resize and move a frame.
- */
-static void
-xprResizeFrame(RootlessFrameID wid, ScreenPtr pScreen,
- int newX, int newY, unsigned int newW, unsigned int newH,
- unsigned int gravity)
-{
- xp_window_changes wc;
-
- TA_SERVER();
-
- wc.x = newX;
- wc.y = newY;
- wc.width = newW;
- wc.height = newH;
- wc.bit_gravity = gravity;
-
- /* It's unlikely that being async will save us anything here.
- But it can't hurt. */
-
- xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_BOUNDS, &wc);
-}
-
-
-/*
- * Change frame stacking.
- */
-static void xprRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid) {
- xp_window_changes wc;
- unsigned int mask = XP_STACKING;
-
- TA_SERVER();
-
- /* Stack frame below nextWid it if it exists, or raise
- frame above everything otherwise. */
-
- if(nextWid == NULL) {
- wc.stack_mode = XP_MAPPED_ABOVE;
- wc.sibling = 0;
- } else {
- wc.stack_mode = XP_MAPPED_BELOW;
- wc.sibling = x_cvt_vptr_to_uint(nextWid);
- }
-
- if(window_hash) {
- RootlessWindowRec *winRec = x_hash_table_lookup(window_hash, wid, NULL);
-
- if(winRec) {
- if(XQuartzIsRootless)
- wc.window_level = normal_window_levels[winRec->level];
- else
- wc.window_level = rooted_window_levels[winRec->level];
- mask |= XP_WINDOW_LEVEL;
- }
- }
-
- xprConfigureWindow(x_cvt_vptr_to_uint(wid), mask, &wc);
-}
-
-
-/*
- * Change the frame's shape.
- */
-static void
-xprReshapeFrame(RootlessFrameID wid, RegionPtr pShape)
-{
- xp_window_changes wc;
-
- TA_SERVER();
-
- if (pShape != NULL)
- {
- wc.shape_nrects = RegionNumRects(pShape);
- wc.shape_rects = RegionRects(pShape);
- }
- else
- {
- wc.shape_nrects = -1;
- wc.shape_rects = NULL;
- }
-
- wc.shape_tx = wc.shape_ty = 0;
-
- xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_SHAPE, &wc);
-}
-
-
-/*
- * Unmap a frame.
- */
-static void
-xprUnmapFrame(RootlessFrameID wid)
-{
- xp_window_changes wc;
-
- TA_SERVER();
-
- wc.stack_mode = XP_UNMAPPED;
- wc.sibling = 0;
-
- xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_STACKING, &wc);
-}
-
-
-/*
- * Start drawing to a frame.
- * Prepare for direct access to its backing buffer.
- */
-static void
-xprStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow)
-{
- void *data[2];
- unsigned int rowbytes[2];
- xp_error err;
-
- TA_SERVER();
-
- err = xp_lock_window(x_cvt_vptr_to_uint(wid), NULL, NULL, data, rowbytes, NULL);
- if (err != Success)
- FatalError("Could not lock window %i for drawing.", (int)x_cvt_vptr_to_uint(wid));
-
- *pixelData = data[0];
- *bytesPerRow = rowbytes[0];
-}
-
-
-/*
- * Stop drawing to a frame.
- */
-static void
-xprStopDrawing(RootlessFrameID wid, Bool flush)
-{
- xp_error err;
- TA_SERVER();
-
- err = xp_unlock_window(x_cvt_vptr_to_uint(wid), flush);
- if(err != Success)
- FatalError("Could not unlock window %i after drawing.", (int)x_cvt_vptr_to_uint(wid));
-}
-
-
-/*
- * Flush drawing updates to the screen.
- */
-static void
-xprUpdateRegion(RootlessFrameID wid, RegionPtr pDamage)
-{
- TA_SERVER();
-
- xp_flush_window(x_cvt_vptr_to_uint(wid));
-}
-
-
-/*
- * Mark damaged rectangles as requiring redisplay to screen.
- */
-static void
-xprDamageRects(RootlessFrameID wid, int nrects, const BoxRec *rects,
- int shift_x, int shift_y)
-{
- TA_SERVER();
-
- xp_mark_window(x_cvt_vptr_to_uint(wid), nrects, rects, shift_x, shift_y);
-}
-
-
-/*
- * Called after the window associated with a frame has been switched
- * to a new top-level parent.
- */
-static void
-xprSwitchWindow(RootlessWindowPtr pFrame, WindowPtr oldWin)
-{
- DeleteProperty(serverClient, oldWin, xa_native_window_id());
-
- TA_SERVER();
-
- xprSetNativeProperty(pFrame);
-}
-
-
-/*
- * Called to check if the frame should be reordered when it is restacked.
- */
-static Bool xprDoReorderWindow(RootlessWindowPtr pFrame)
-{
- WindowPtr pWin = pFrame->win;
-
- TA_SERVER();
-
- return AppleWMDoReorderWindow(pWin);
-}
-
-
-/*
- * Copy area in frame to another part of frame.
- * Used to accelerate scrolling.
- */
-static void
-xprCopyWindow(RootlessFrameID wid, int dstNrects, const BoxRec *dstRects,
- int dx, int dy)
-{
- TA_SERVER();
-
- xp_copy_window(x_cvt_vptr_to_uint(wid), x_cvt_vptr_to_uint(wid),
- dstNrects, dstRects, dx, dy);
-}
-
-
-static RootlessFrameProcsRec xprRootlessProcs = {
- xprCreateFrame,
- xprDestroyFrame,
- xprMoveFrame,
- xprResizeFrame,
- xprRestackFrame,
- xprReshapeFrame,
- xprUnmapFrame,
- xprStartDrawing,
- xprStopDrawing,
- xprUpdateRegion,
- xprDamageRects,
- xprSwitchWindow,
- xprDoReorderWindow,
- xprHideWindow,
- xprUpdateColormap,
- xp_copy_bytes,
- xprCopyWindow
-};
-
-
-/*
- * Initialize XPR implementation
- */
-Bool
-xprInit(ScreenPtr pScreen)
-{
- RootlessInit(pScreen, &xprRootlessProcs);
-
- TA_SERVER();
-
- rootless_CopyBytes_threshold = xp_copy_bytes_threshold;
- rootless_CopyWindow_threshold = xp_scroll_area_threshold;
-
- return TRUE;
-}
-
-
-/*
- * Given the id of a physical window, try to find the top-level (or root)
- * X window that it represents.
- */
-WindowPtr
-xprGetXWindow(xp_window_id wid)
-{
- RootlessWindowRec *winRec;
-
- if (window_hash == NULL)
- return NULL;
-
- winRec = x_hash_table_lookup(window_hash, x_cvt_uint_to_vptr(wid), NULL);
-
- return winRec != NULL ? winRec->win : NULL;
-}
-
-#ifdef UNUSED_CODE
-/*
- * Given the id of a physical window, try to find the top-level (or root)
- * X window that it represents.
- */
-WindowPtr
-xprGetXWindowFromAppKit(int windowNumber)
-{
- RootlessWindowRec *winRec;
- Bool ret;
- xp_window_id wid;
-
- if (window_hash == NULL)
- return FALSE;
-
- /* need to lock, since this function can be called by any thread */
-
- pthread_mutex_lock(&window_hash_mutex);
-
- if (xp_lookup_native_window(windowNumber, &wid))
- ret = xprGetXWindow(wid) != NULL;
- else
- ret = FALSE;
-
- pthread_mutex_unlock(&window_hash_mutex);
-
- if (!ret) return NULL;
- winRec = x_hash_table_lookup(window_hash, x_cvt_uint_to_vptr(wid), NULL);
-
- return winRec != NULL ? winRec->win : NULL;
-}
-#endif
-
-/*
- * The windowNumber is an AppKit window number. Returns TRUE if xpr is
- * displaying a window with that number.
- */
-Bool
-xprIsX11Window(void *nsWindow, int windowNumber)
-{
- Bool ret;
- xp_window_id wid;
-
- if (window_hash == NULL)
- return FALSE;
-
- /* need to lock, since this function can be called by any thread */
-
- pthread_mutex_lock(&window_hash_mutex);
-
- if (xp_lookup_native_window(windowNumber, &wid))
- ret = xprGetXWindow(wid) != NULL;
- else
- ret = FALSE;
-
- pthread_mutex_unlock(&window_hash_mutex);
-
- return ret;
-}
-
-
-/*
- * xprHideWindows
- * Hide or unhide all top level windows. This is called for application hide/
- * unhide events if the window manager is not Apple-WM aware. Xplugin windows
- * do not hide or unhide themselves.
- */
-void
-xprHideWindows(Bool hide)
-{
- int screen;
- WindowPtr pRoot, pWin;
-
- TA_SERVER();
-
- for (screen = 0; screen < screenInfo.numScreens; screen++) {
- RootlessFrameID prevWid = NULL;
- pRoot = screenInfo.screens[screen]->root;
-
- for (pWin = pRoot->firstChild; pWin; pWin = pWin->nextSib) {
- RootlessWindowRec *winRec = WINREC(pWin);
-
- if (winRec != NULL) {
- if (hide) {
- xprUnmapFrame(winRec->wid);
- } else {
- BoxRec box;
-
- xprRestackFrame(winRec->wid, prevWid);
- prevWid = winRec->wid;
-
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = winRec->width;
- box.y2 = winRec->height;
-
- xprDamageRects(winRec->wid, 1, &box, 0, 0);
- RootlessQueueRedisplay(screenInfo.screens[screen]);
- }
- }
- }
- }
-}
-
-// XXX: identical to x_cvt_vptr_to_uint ?
-#define MAKE_WINDOW_ID(x) ((xp_window_id)((size_t)(x)))
-
-Bool no_configure_window;
-
-static inline int
-configure_window (xp_window_id id, unsigned int mask,
- const xp_window_changes *values)
-{
- if (!no_configure_window)
- return xp_configure_window (id, mask, values);
- else
- return XP_Success;
-}
-
-
-static
-void xprUpdateColormap(RootlessFrameID wid, ScreenPtr pScreen)
-{
- /* This is how we tell xp that the colormap may have changed. */
- xp_window_changes wc;
- wc.colormap = xprColormapCallback;
- wc.colormap_data = pScreen;
-
- configure_window(MAKE_WINDOW_ID(wid), XP_COLORMAP, &wc);
-}
-
-static
-void xprHideWindow(RootlessFrameID wid)
-{
- xp_window_changes wc;
- wc.stack_mode = XP_UNMAPPED;
- wc.sibling = 0;
- configure_window(MAKE_WINDOW_ID(wid), XP_STACKING, &wc);
-}
+/* + * Xplugin rootless implementation frame functions + * + * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2003 Torrey T. Lyons. 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. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "xpr.h" +#include "rootlessCommon.h" +#include <Xplugin.h> +#include "x-hash.h" +#include "x-list.h" +#include "applewmExt.h" + +#include "propertyst.h" +#include "dix.h" +#include <X11/Xatom.h> +#include "windowstr.h" +#include "quartz.h" + +#include "threadSafety.h" + +#include <pthread.h> + +#define DEFINE_ATOM_HELPER(func,atom_name) \ +static Atom func (void) { \ + static int generation; \ + static Atom atom; \ + if (generation != serverGeneration) { \ + generation = serverGeneration; \ + atom = MakeAtom (atom_name, strlen (atom_name), TRUE); \ + } \ + return atom; \ +} + +DEFINE_ATOM_HELPER(xa_native_window_id, "_NATIVE_WINDOW_ID") + +/* Maps xp_window_id -> RootlessWindowRec */ +static x_hash_table *window_hash; +static pthread_mutex_t window_hash_mutex; + +/* Prototypes for static functions */ +static Bool xprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen, + int newX, int newY, RegionPtr pShape); +static void xprDestroyFrame(RootlessFrameID wid); +static void xprMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY); +static void xprResizeFrame(RootlessFrameID wid, ScreenPtr pScreen, + int newX, int newY, unsigned int newW, unsigned int newH, + unsigned int gravity); +static void xprRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid); +static void xprReshapeFrame(RootlessFrameID wid, RegionPtr pShape); +static void xprUnmapFrame(RootlessFrameID wid); +static void xprStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow); +static void xprStopDrawing(RootlessFrameID wid, Bool flush); +static void xprUpdateRegion(RootlessFrameID wid, RegionPtr pDamage); +static void xprDamageRects(RootlessFrameID wid, int nrects, const BoxRec *rects, + int shift_x, int shift_y); +static void xprSwitchWindow(RootlessWindowPtr pFrame, WindowPtr oldWin); +static Bool xprDoReorderWindow(RootlessWindowPtr pFrame); +static void xprHideWindow(RootlessFrameID wid); +static void xprUpdateColormap(RootlessFrameID wid, ScreenPtr pScreen); +static void xprCopyWindow(RootlessFrameID wid, int dstNrects, const BoxRec *dstRects, + int dx, int dy); + + +static inline xp_error +xprConfigureWindow(xp_window_id id, unsigned int mask, + const xp_window_changes *values) +{ + TA_SERVER(); + + return xp_configure_window(id, mask, values); +} + + +static void +xprSetNativeProperty(RootlessWindowPtr pFrame) +{ + xp_error err; + unsigned int native_id; + long data; + + TA_SERVER(); + + err = xp_get_native_window(x_cvt_vptr_to_uint(pFrame->wid), &native_id); + if (err == Success) + { + /* FIXME: move this to AppleWM extension */ + + data = native_id; + dixChangeWindowProperty(serverClient, pFrame->win, xa_native_window_id(), + XA_INTEGER, 32, PropModeReplace, 1, &data, TRUE); + } +} + +static xp_error +xprColormapCallback(void *data, int first_color, int n_colors, uint32_t *colors) +{ + return (RootlessResolveColormap (data, first_color, n_colors, colors) ? XP_Success : XP_BadMatch); +} + +/* + * Create and display a new frame. + */ +static Bool +xprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen, + int newX, int newY, RegionPtr pShape) +{ + WindowPtr pWin = pFrame->win; + xp_window_changes wc; + unsigned int mask = 0; + xp_error err; + + TA_SERVER(); + + wc.x = newX; + wc.y = newY; + wc.width = pFrame->width; + wc.height = pFrame->height; + wc.bit_gravity = XP_GRAVITY_NONE; + mask |= XP_BOUNDS; + + if (pWin->drawable.depth == 8) + { + wc.depth = XP_DEPTH_INDEX8; + wc.colormap = xprColormapCallback; + wc.colormap_data = pScreen; + mask |= XP_COLORMAP; + } + else if (pWin->drawable.depth == 15) + wc.depth = XP_DEPTH_RGB555; + else if (pWin->drawable.depth == 24) + wc.depth = XP_DEPTH_ARGB8888; + else + wc.depth = XP_DEPTH_NIL; + mask |= XP_DEPTH; + + if (pShape != NULL) + { + wc.shape_nrects = RegionNumRects(pShape); + wc.shape_rects = RegionRects(pShape); + wc.shape_tx = wc.shape_ty = 0; + mask |= XP_SHAPE; + } + + pFrame->level = !IsRoot (pWin) ? AppleWMWindowLevelNormal : AppleWMNumWindowLevels; + + if(XQuartzIsRootless) + wc.window_level = normal_window_levels[pFrame->level]; + else if(XQuartzShieldingWindowLevel) + wc.window_level = XQuartzShieldingWindowLevel + 1; + else + wc.window_level = rooted_window_levels[pFrame->level]; + mask |= XP_WINDOW_LEVEL; + + err = xp_create_window(mask, &wc, (xp_window_id *) &pFrame->wid); + + if (err != Success) + { + return FALSE; + } + + if (window_hash == NULL) + { + window_hash = x_hash_table_new(NULL, NULL, NULL, NULL); + pthread_mutex_init(&window_hash_mutex, NULL); + } + + pthread_mutex_lock(&window_hash_mutex); + x_hash_table_insert(window_hash, pFrame->wid, pFrame); + pthread_mutex_unlock(&window_hash_mutex); + + xprSetNativeProperty(pFrame); + + return TRUE; +} + + +/* + * Destroy a frame. + */ +static void +xprDestroyFrame(RootlessFrameID wid) +{ + xp_error err; + TA_SERVER(); + + pthread_mutex_lock(&window_hash_mutex); + x_hash_table_remove(window_hash, wid); + pthread_mutex_unlock(&window_hash_mutex); + + err = xp_destroy_window(x_cvt_vptr_to_uint(wid)); + if (err != Success) + FatalError("Could not destroy window %i.", (int)x_cvt_vptr_to_uint(wid)); +} + + +/* + * Move a frame on screen. + */ +static void +xprMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY) +{ + xp_window_changes wc; + + TA_SERVER(); + + wc.x = newX; + wc.y = newY; + // ErrorF("xprMoveFrame(%d, %p, %d, %d)\n", wid, pScreen, newX, newY); + xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_ORIGIN, &wc); +} + + +/* + * Resize and move a frame. + */ +static void +xprResizeFrame(RootlessFrameID wid, ScreenPtr pScreen, + int newX, int newY, unsigned int newW, unsigned int newH, + unsigned int gravity) +{ + xp_window_changes wc; + + TA_SERVER(); + + wc.x = newX; + wc.y = newY; + wc.width = newW; + wc.height = newH; + wc.bit_gravity = gravity; + + /* It's unlikely that being async will save us anything here. + But it can't hurt. */ + + xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_BOUNDS, &wc); +} + + +/* + * Change frame stacking. + */ +static void xprRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid) { + xp_window_changes wc; + unsigned int mask = XP_STACKING; + + TA_SERVER(); + + /* Stack frame below nextWid it if it exists, or raise + frame above everything otherwise. */ + + if(nextWid == NULL) { + wc.stack_mode = XP_MAPPED_ABOVE; + wc.sibling = 0; + } else { + wc.stack_mode = XP_MAPPED_BELOW; + wc.sibling = x_cvt_vptr_to_uint(nextWid); + } + + if(window_hash) { + RootlessWindowRec *winRec = x_hash_table_lookup(window_hash, wid, NULL); + + if(winRec) { + if(XQuartzIsRootless) + wc.window_level = normal_window_levels[winRec->level]; + else if(XQuartzShieldingWindowLevel) + wc.window_level = XQuartzShieldingWindowLevel + 1; + else + wc.window_level = rooted_window_levels[winRec->level]; + mask |= XP_WINDOW_LEVEL; + } + } + + xprConfigureWindow(x_cvt_vptr_to_uint(wid), mask, &wc); +} + + +/* + * Change the frame's shape. + */ +static void +xprReshapeFrame(RootlessFrameID wid, RegionPtr pShape) +{ + xp_window_changes wc; + + TA_SERVER(); + + if (pShape != NULL) + { + wc.shape_nrects = RegionNumRects(pShape); + wc.shape_rects = RegionRects(pShape); + } + else + { + wc.shape_nrects = -1; + wc.shape_rects = NULL; + } + + wc.shape_tx = wc.shape_ty = 0; + + xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_SHAPE, &wc); +} + + +/* + * Unmap a frame. + */ +static void +xprUnmapFrame(RootlessFrameID wid) +{ + xp_window_changes wc; + + TA_SERVER(); + + wc.stack_mode = XP_UNMAPPED; + wc.sibling = 0; + + xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_STACKING, &wc); +} + + +/* + * Start drawing to a frame. + * Prepare for direct access to its backing buffer. + */ +static void +xprStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow) +{ + void *data[2]; + unsigned int rowbytes[2]; + xp_error err; + + TA_SERVER(); + + err = xp_lock_window(x_cvt_vptr_to_uint(wid), NULL, NULL, data, rowbytes, NULL); + if (err != Success) + FatalError("Could not lock window %i for drawing.", (int)x_cvt_vptr_to_uint(wid)); + + *pixelData = data[0]; + *bytesPerRow = rowbytes[0]; +} + + +/* + * Stop drawing to a frame. + */ +static void +xprStopDrawing(RootlessFrameID wid, Bool flush) +{ + xp_error err; + TA_SERVER(); + + err = xp_unlock_window(x_cvt_vptr_to_uint(wid), flush); + if(err != Success) + FatalError("Could not unlock window %i after drawing.", (int)x_cvt_vptr_to_uint(wid)); +} + + +/* + * Flush drawing updates to the screen. + */ +static void +xprUpdateRegion(RootlessFrameID wid, RegionPtr pDamage) +{ + TA_SERVER(); + + xp_flush_window(x_cvt_vptr_to_uint(wid)); +} + + +/* + * Mark damaged rectangles as requiring redisplay to screen. + */ +static void +xprDamageRects(RootlessFrameID wid, int nrects, const BoxRec *rects, + int shift_x, int shift_y) +{ + TA_SERVER(); + + xp_mark_window(x_cvt_vptr_to_uint(wid), nrects, rects, shift_x, shift_y); +} + + +/* + * Called after the window associated with a frame has been switched + * to a new top-level parent. + */ +static void +xprSwitchWindow(RootlessWindowPtr pFrame, WindowPtr oldWin) +{ + DeleteProperty(serverClient, oldWin, xa_native_window_id()); + + TA_SERVER(); + + xprSetNativeProperty(pFrame); +} + + +/* + * Called to check if the frame should be reordered when it is restacked. + */ +static Bool xprDoReorderWindow(RootlessWindowPtr pFrame) +{ + WindowPtr pWin = pFrame->win; + + TA_SERVER(); + + return AppleWMDoReorderWindow(pWin); +} + + +/* + * Copy area in frame to another part of frame. + * Used to accelerate scrolling. + */ +static void +xprCopyWindow(RootlessFrameID wid, int dstNrects, const BoxRec *dstRects, + int dx, int dy) +{ + TA_SERVER(); + + xp_copy_window(x_cvt_vptr_to_uint(wid), x_cvt_vptr_to_uint(wid), + dstNrects, dstRects, dx, dy); +} + + +static RootlessFrameProcsRec xprRootlessProcs = { + xprCreateFrame, + xprDestroyFrame, + xprMoveFrame, + xprResizeFrame, + xprRestackFrame, + xprReshapeFrame, + xprUnmapFrame, + xprStartDrawing, + xprStopDrawing, + xprUpdateRegion, + xprDamageRects, + xprSwitchWindow, + xprDoReorderWindow, + xprHideWindow, + xprUpdateColormap, + xp_copy_bytes, + xprCopyWindow +}; + + +/* + * Initialize XPR implementation + */ +Bool +xprInit(ScreenPtr pScreen) +{ + RootlessInit(pScreen, &xprRootlessProcs); + + TA_SERVER(); + + rootless_CopyBytes_threshold = xp_copy_bytes_threshold; + rootless_CopyWindow_threshold = xp_scroll_area_threshold; + + return TRUE; +} + + +/* + * Given the id of a physical window, try to find the top-level (or root) + * X window that it represents. + */ +WindowPtr +xprGetXWindow(xp_window_id wid) +{ + RootlessWindowRec *winRec; + + if (window_hash == NULL) + return NULL; + + winRec = x_hash_table_lookup(window_hash, x_cvt_uint_to_vptr(wid), NULL); + + return winRec != NULL ? winRec->win : NULL; +} + +#ifdef UNUSED_CODE +/* + * Given the id of a physical window, try to find the top-level (or root) + * X window that it represents. + */ +WindowPtr +xprGetXWindowFromAppKit(int windowNumber) +{ + RootlessWindowRec *winRec; + Bool ret; + xp_window_id wid; + + if (window_hash == NULL) + return FALSE; + + /* need to lock, since this function can be called by any thread */ + + pthread_mutex_lock(&window_hash_mutex); + + if (xp_lookup_native_window(windowNumber, &wid)) + ret = xprGetXWindow(wid) != NULL; + else + ret = FALSE; + + pthread_mutex_unlock(&window_hash_mutex); + + if (!ret) return NULL; + winRec = x_hash_table_lookup(window_hash, x_cvt_uint_to_vptr(wid), NULL); + + return winRec != NULL ? winRec->win : NULL; +} +#endif + +/* + * The windowNumber is an AppKit window number. Returns TRUE if xpr is + * displaying a window with that number. + */ +Bool +xprIsX11Window(void *nsWindow, int windowNumber) +{ + Bool ret; + xp_window_id wid; + + if (window_hash == NULL) + return FALSE; + + /* need to lock, since this function can be called by any thread */ + + pthread_mutex_lock(&window_hash_mutex); + + if (xp_lookup_native_window(windowNumber, &wid)) + ret = xprGetXWindow(wid) != NULL; + else + ret = FALSE; + + pthread_mutex_unlock(&window_hash_mutex); + + return ret; +} + + +/* + * xprHideWindows + * Hide or unhide all top level windows. This is called for application hide/ + * unhide events if the window manager is not Apple-WM aware. Xplugin windows + * do not hide or unhide themselves. + */ +void +xprHideWindows(Bool hide) +{ + int screen; + WindowPtr pRoot, pWin; + + TA_SERVER(); + + for (screen = 0; screen < screenInfo.numScreens; screen++) { + RootlessFrameID prevWid = NULL; + pRoot = screenInfo.screens[screen]->root; + + for (pWin = pRoot->firstChild; pWin; pWin = pWin->nextSib) { + RootlessWindowRec *winRec = WINREC(pWin); + + if (winRec != NULL) { + if (hide) { + xprUnmapFrame(winRec->wid); + } else { + BoxRec box; + + xprRestackFrame(winRec->wid, prevWid); + prevWid = winRec->wid; + + box.x1 = 0; + box.y1 = 0; + box.x2 = winRec->width; + box.y2 = winRec->height; + + xprDamageRects(winRec->wid, 1, &box, 0, 0); + RootlessQueueRedisplay(screenInfo.screens[screen]); + } + } + } + } +} + +// XXX: identical to x_cvt_vptr_to_uint ? +#define MAKE_WINDOW_ID(x) ((xp_window_id)((size_t)(x))) + +Bool no_configure_window; + +static inline int +configure_window (xp_window_id id, unsigned int mask, + const xp_window_changes *values) +{ + if (!no_configure_window) + return xp_configure_window (id, mask, values); + else + return XP_Success; +} + + +static +void xprUpdateColormap(RootlessFrameID wid, ScreenPtr pScreen) +{ + /* This is how we tell xp that the colormap may have changed. */ + xp_window_changes wc; + wc.colormap = xprColormapCallback; + wc.colormap_data = pScreen; + + configure_window(MAKE_WINDOW_ID(wid), XP_COLORMAP, &wc); +} + +static +void xprHideWindow(RootlessFrameID wid) +{ + xp_window_changes wc; + wc.stack_mode = XP_UNMAPPED; + wc.sibling = 0; + configure_window(MAKE_WINDOW_ID(wid), XP_STACKING, &wc); +} diff --git a/xorg-server/hw/xquartz/xpr/xprScreen.c b/xorg-server/hw/xquartz/xpr/xprScreen.c index bd877d97c..972278b75 100644 --- a/xorg-server/hw/xquartz/xpr/xprScreen.c +++ b/xorg-server/hw/xquartz/xpr/xprScreen.c @@ -1,451 +1,483 @@ -/*
- * Xplugin rootless implementation screen functions
- *
- * Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved.
- * Copyright (c) 2004 Torrey T. Lyons. 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 "inputstr.h"
-#include "quartz.h"
-#include "quartzRandR.h"
-#include "xpr.h"
-#include "xprEvent.h"
-#include "pseudoramiX.h"
-#include "darwin.h"
-#include "darwinEvents.h"
-#include "rootless.h"
-#include "dri.h"
-#include "globals.h"
-#include <Xplugin.h>
-#include "applewmExt.h"
-#include "micmap.h"
-
-#include "rootlessCommon.h"
-
-#ifdef DAMAGE
-# include "damage.h"
-#endif
-
-/* 10.4's deferred update makes X slower.. have to live with the tearing
- for now.. */
-#define XP_NO_DEFERRED_UPDATES 8
-
-// Name of GLX bundle for native OpenGL
-static const char *xprOpenGLBundle = "glxCGL.bundle";
-
-/*
- * eventHandler
- * Callback handler for Xplugin events.
- */
-static void eventHandler(unsigned int type, const void *arg,
- unsigned int arg_size, void *data) {
-
- switch (type) {
- case XP_EVENT_DISPLAY_CHANGED:
- DEBUG_LOG("XP_EVENT_DISPLAY_CHANGED\n");
- DarwinSendDDXEvent(kXquartzDisplayChanged, 0);
- break;
-
- case XP_EVENT_WINDOW_STATE_CHANGED:
- if (arg_size >= sizeof(xp_window_state_event)) {
- const xp_window_state_event *ws_arg = arg;
-
- DEBUG_LOG("XP_EVENT_WINDOW_STATE_CHANGED: id=%d, state=%d\n", ws_arg->id, ws_arg->state);
- DarwinSendDDXEvent(kXquartzWindowState, 2,
- ws_arg->id, ws_arg->state);
- } else {
- DEBUG_LOG("XP_EVENT_WINDOW_STATE_CHANGED: ignored\n");
- }
- break;
-
- case XP_EVENT_WINDOW_MOVED:
- DEBUG_LOG("XP_EVENT_WINDOW_MOVED\n");
- if (arg_size == sizeof(xp_window_id)) {
- xp_window_id id = * (xp_window_id *) arg;
- DarwinSendDDXEvent(kXquartzWindowMoved, 1, id);
- }
- break;
-
- case XP_EVENT_SURFACE_DESTROYED:
- DEBUG_LOG("XP_EVENT_SURFACE_DESTROYED\n");
- case XP_EVENT_SURFACE_CHANGED:
- DEBUG_LOG("XP_EVENT_SURFACE_CHANGED\n");
- if (arg_size == sizeof(xp_surface_id)) {
- int kind;
-
- if (type == XP_EVENT_SURFACE_DESTROYED)
- kind = AppleDRISurfaceNotifyDestroyed;
- else
- kind = AppleDRISurfaceNotifyChanged;
-
- DRISurfaceNotify(*(xp_surface_id *) arg, kind);
- }
- break;
-#ifdef XP_EVENT_SPACE_CHANGED
- case XP_EVENT_SPACE_CHANGED:
- DEBUG_LOG("XP_EVENT_SPACE_CHANGED\n");
- if(arg_size == sizeof(uint32_t)) {
- uint32_t space_id = *(uint32_t *)arg;
- DarwinSendDDXEvent(kXquartzSpaceChanged, 1, space_id);
- }
- break;
-#endif
- default:
- ErrorF("Unknown XP_EVENT type (%d) in xprScreen:eventHandler\n", type);
- }
-}
-
-/*
- * displayAtIndex
- * Return the display ID for a particular display index.
- */
-static CGDirectDisplayID
-displayAtIndex(int index)
-{
- CGError err;
- CGDisplayCount cnt;
- CGDirectDisplayID dpy[index+1];
-
- err = CGGetActiveDisplayList(index + 1, dpy, &cnt);
- if (err == kCGErrorSuccess && cnt == index + 1)
- return dpy[index];
- else
- return kCGNullDirectDisplay;
-}
-
-/*
- * displayScreenBounds
- * Return the bounds of a particular display.
- */
-static CGRect
-displayScreenBounds(CGDirectDisplayID id)
-{
- CGRect frame;
-
- frame = CGDisplayBounds(id);
-
- DEBUG_LOG(" %dx%d @ (%d,%d).\n",
- (int)frame.size.width, (int)frame.size.height,
- (int)frame.origin.x, (int)frame.origin.y);
-
- /* Remove menubar to help standard X11 window managers. */
- if (XQuartzIsRootless &&
- frame.origin.x == 0 && frame.origin.y == 0) {
- frame.origin.y += aquaMenuBarHeight;
- frame.size.height -= aquaMenuBarHeight;
- }
-
- DEBUG_LOG(" %dx%d @ (%d,%d).\n",
- (int)frame.size.width, (int)frame.size.height,
- (int)frame.origin.x, (int)frame.origin.y);
-
- return frame;
-}
-
-/*
- * xprAddPseudoramiXScreens
- * Add a single virtual screen encompassing all the physical screens
- * with PseudoramiX.
- */
-static void
-xprAddPseudoramiXScreens(int *x, int *y, int *width, int *height, ScreenPtr pScreen)
-{
- CGDisplayCount i, displayCount;
- CGDirectDisplayID *displayList = NULL;
- CGRect unionRect = CGRectNull, frame;
-
- // Find all the CoreGraphics displays
- CGGetActiveDisplayList(0, NULL, &displayCount);
- DEBUG_LOG("displayCount: %d\n", (int)displayCount);
-
- if(!displayCount) {
- ErrorF("CoreGraphics has reported no connected displays. Creating a stub 800x600 display.\n");
- *x = *y = 0;
- *width = 800;
- *height = 600;
- PseudoramiXAddScreen(*x, *y, *width, *height);
- return;
- }
-
- displayList = malloc(displayCount * sizeof(CGDirectDisplayID));
- 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++) {
- CGDirectDisplayID dpy = displayList[i];
- frame = displayScreenBounds(dpy);
- unionRect = CGRectUnion(unionRect, frame);
- }
-
- /* Use unionRect as the screen size for the X server. */
- *x = unionRect.origin.x;
- *y = unionRect.origin.y;
- *width = unionRect.size.width;
- *height = unionRect.size.height;
-
- DEBUG_LOG(" screen union origin: (%d,%d) size: (%d,%d).\n",
- *x, *y, *width, *height);
-
- /* Tell PseudoramiX about the real screens. */
- for (i = 0; i < displayCount; i++)
- {
- CGDirectDisplayID dpy = displayList[i];
-
- frame = displayScreenBounds(dpy);
- frame.origin.x -= unionRect.origin.x;
- frame.origin.y -= unionRect.origin.y;
-
- DEBUG_LOG(" placed at X11 coordinate (%d,%d).\n",
- (int)frame.origin.x, (int)frame.origin.y);
-
- PseudoramiXAddScreen(frame.origin.x, frame.origin.y,
- frame.size.width, frame.size.height);
- }
-
- free(displayList);
-}
-
-/*
- * xprDisplayInit
- * Find number of CoreGraphics displays and initialize Xplugin.
- */
-static void
-xprDisplayInit(void)
-{
- CGDisplayCount displayCount;
-
- DEBUG_LOG("");
-
- CGGetActiveDisplayList(0, NULL, &displayCount);
-
- /* With PseudoramiX, the X server only sees one screen; only PseudoramiX
- itself knows about all of the screens. */
-
- if (noPseudoramiXExtension)
- darwinScreensFound = displayCount;
- else
- darwinScreensFound = 1;
-
- if (xp_init(XP_BACKGROUND_EVENTS | XP_NO_DEFERRED_UPDATES) != Success)
- FatalError("Could not initialize the Xplugin library.");
-
- xp_select_events(XP_EVENT_DISPLAY_CHANGED
- | XP_EVENT_WINDOW_STATE_CHANGED
- | XP_EVENT_WINDOW_MOVED
-#ifdef XP_EVENT_SPACE_CHANGED
- | XP_EVENT_SPACE_CHANGED
-#endif
- | XP_EVENT_SURFACE_CHANGED
- | XP_EVENT_SURFACE_DESTROYED,
- eventHandler, NULL);
-
- AppleDRIExtensionInit();
- xprAppleWMInit();
-
- XQuartzIsRootless = XQuartzRootlessDefault;
- if (!XQuartzIsRootless)
- RootlessHideAllWindows();
-}
-
-/*
- * xprAddScreen
- * Init the framebuffer and record pixmap parameters for the screen.
- */
-static Bool
-xprAddScreen(int index, ScreenPtr pScreen)
-{
- DarwinFramebufferPtr dfb = SCREEN_PRIV(pScreen);
- int depth = darwinDesiredDepth;
-
- DEBUG_LOG("index=%d depth=%d\n", index, depth);
-
- if(depth == -1) {
- depth = CGDisplaySamplesPerPixel(kCGDirectMainDisplay) * CGDisplayBitsPerSample(kCGDirectMainDisplay);
- }
-
- switch(depth) {
- case 8: // pseudo-working
- dfb->visuals = PseudoColorMask;
- dfb->preferredCVC = PseudoColor;
- dfb->depth = 8;
- dfb->bitsPerRGB = 8;
- dfb->bitsPerPixel = 8;
- dfb->redMask = 0;
- dfb->greenMask = 0;
- dfb->blueMask = 0;
- break;
- case 15:
- dfb->visuals = TrueColorMask; //LARGE_VISUALS;
- dfb->preferredCVC = TrueColor;
- dfb->depth = 15;
- dfb->bitsPerRGB = 5;
- dfb->bitsPerPixel = 16;
- dfb->redMask = RM_ARGB(0,5,5,5);
- dfb->greenMask = GM_ARGB(0,5,5,5);
- dfb->blueMask = BM_ARGB(0,5,5,5);
- break;
-// case 24:
- default:
- if(depth != 24)
- ErrorF("Unsupported color depth requested. Defaulting to 24bit. (depth=%d darwinDesiredDepth=%d CGDisplaySamplesPerPixel=%d CGDisplayBitsPerSample=%d)\n", darwinDesiredDepth, depth, (int)CGDisplaySamplesPerPixel(kCGDirectMainDisplay), (int)CGDisplayBitsPerSample(kCGDirectMainDisplay));
- dfb->visuals = TrueColorMask; //LARGE_VISUALS;
- dfb->preferredCVC = TrueColor;
- dfb->depth = 24;
- dfb->bitsPerRGB = 8;
- dfb->bitsPerPixel = 32;
- dfb->redMask = RM_ARGB(0,8,8,8);
- dfb->greenMask = GM_ARGB(0,8,8,8);
- dfb->blueMask = BM_ARGB(0,8,8,8);
- break;
- }
-
- if (noPseudoramiXExtension)
- {
- CGDirectDisplayID dpy;
- CGRect frame;
-
- ErrorF("Warning: noPseudoramiXExtension!\n");
-
- dpy = displayAtIndex(index);
- QuartzCopyDisplayIDs(pScreen, 1, &dpy);
-
- frame = displayScreenBounds(dpy);
-
- dfb->x = frame.origin.x;
- dfb->y = frame.origin.y;
- dfb->width = frame.size.width;
- dfb->height = frame.size.height;
- }
- else
- {
- xprAddPseudoramiXScreens(&dfb->x, &dfb->y, &dfb->width, &dfb->height, pScreen);
- }
-
- /* Passing zero width (pitch) makes miCreateScreenResources set the
- screen pixmap to the framebuffer pointer, i.e. NULL. The generic
- rootless code takes care of making this work. */
- dfb->pitch = 0;
- dfb->framebuffer = NULL;
-
- DRIScreenInit(pScreen);
-
- return TRUE;
-}
-
-/*
- * xprSetupScreen
- * Setup the screen for rootless access.
- */
-static Bool
-xprSetupScreen(int index, ScreenPtr pScreen)
-{
-#ifdef DAMAGE
- // The Damage extension needs to wrap underneath the
- // generic rootless layer, so do it now.
- if (!DamageSetup(pScreen))
- return FALSE;
-#endif
-
- // Initialize generic rootless code
- if (!xprInit(pScreen))
- return FALSE;
-
- return DRIFinishScreenInit(pScreen);
-}
-
-/*
- * xprUpdateScreen
- * Update screen after configuation change.
- */
-static void
-xprUpdateScreen(ScreenPtr pScreen)
-{
- rootlessGlobalOffsetX = darwinMainScreenX;
- rootlessGlobalOffsetY = darwinMainScreenY;
-
- AppleWMSetScreenOrigin(pScreen->root);
-
- RootlessRepositionWindows(pScreen);
- RootlessUpdateScreenPixmap(pScreen);
-}
-
-/*
- * xprInitInput
- * Finalize xpr specific setup.
- */
-static void
-xprInitInput(int argc, char **argv)
-{
- int i;
-
- rootlessGlobalOffsetX = darwinMainScreenX;
- rootlessGlobalOffsetY = darwinMainScreenY;
-
- for (i = 0; i < screenInfo.numScreens; i++)
- AppleWMSetScreenOrigin(screenInfo.screens[i]->root);
-}
-
-/*
- * Quartz display mode function list.
- */
-static QuartzModeProcsRec xprModeProcs = {
- xprDisplayInit,
- xprAddScreen,
- xprSetupScreen,
- xprInitInput,
- QuartzInitCursor,
- QuartzSuspendXCursor,
- QuartzResumeXCursor,
- xprAddPseudoramiXScreens,
- xprUpdateScreen,
- xprIsX11Window,
- xprHideWindows,
- RootlessFrameForWindow,
- TopLevelParent,
- DRICreateSurface,
- DRIDestroySurface
-};
-
-/*
- * QuartzModeBundleInit
- * Initialize the display mode bundle after loading.
- */
-Bool
-QuartzModeBundleInit(void)
-{
- quartzProcs = &xprModeProcs;
- quartzOpenGLBundle = xprOpenGLBundle;
- return TRUE;
-}
+/* + * Xplugin rootless implementation screen functions + * + * Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2004 Torrey T. Lyons. 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 "inputstr.h" +#include "quartz.h" +#include "quartzRandR.h" +#include "xpr.h" +#include "xprEvent.h" +#include "pseudoramiX.h" +#include "darwin.h" +#include "darwinEvents.h" +#include "rootless.h" +#include "dri.h" +#include "globals.h" +#include <Xplugin.h> +#include "applewmExt.h" +#include "micmap.h" + +#include "rootlessCommon.h" + +#ifdef DAMAGE +# include "damage.h" +#endif + +/* 10.4's deferred update makes X slower.. have to live with the tearing + for now.. */ +#define XP_NO_DEFERRED_UPDATES 8 + +// Name of GLX bundle for native OpenGL +static const char *xprOpenGLBundle = "glxCGL.bundle"; + +/* + * eventHandler + * Callback handler for Xplugin events. + */ +static void eventHandler(unsigned int type, const void *arg, + unsigned int arg_size, void *data) { + + switch (type) { + case XP_EVENT_DISPLAY_CHANGED: + DEBUG_LOG("XP_EVENT_DISPLAY_CHANGED\n"); + DarwinSendDDXEvent(kXquartzDisplayChanged, 0); + break; + + case XP_EVENT_WINDOW_STATE_CHANGED: + if (arg_size >= sizeof(xp_window_state_event)) { + const xp_window_state_event *ws_arg = arg; + + DEBUG_LOG("XP_EVENT_WINDOW_STATE_CHANGED: id=%d, state=%d\n", ws_arg->id, ws_arg->state); + DarwinSendDDXEvent(kXquartzWindowState, 2, + ws_arg->id, ws_arg->state); + } else { + DEBUG_LOG("XP_EVENT_WINDOW_STATE_CHANGED: ignored\n"); + } + break; + + case XP_EVENT_WINDOW_MOVED: + DEBUG_LOG("XP_EVENT_WINDOW_MOVED\n"); + if (arg_size == sizeof(xp_window_id)) { + xp_window_id id = * (xp_window_id *) arg; + DarwinSendDDXEvent(kXquartzWindowMoved, 1, id); + } + break; + + case XP_EVENT_SURFACE_DESTROYED: + DEBUG_LOG("XP_EVENT_SURFACE_DESTROYED\n"); + case XP_EVENT_SURFACE_CHANGED: + DEBUG_LOG("XP_EVENT_SURFACE_CHANGED\n"); + if (arg_size == sizeof(xp_surface_id)) { + int kind; + + if (type == XP_EVENT_SURFACE_DESTROYED) + kind = AppleDRISurfaceNotifyDestroyed; + else + kind = AppleDRISurfaceNotifyChanged; + + DRISurfaceNotify(*(xp_surface_id *) arg, kind); + } + break; +#ifdef XP_EVENT_SPACE_CHANGED + case XP_EVENT_SPACE_CHANGED: + DEBUG_LOG("XP_EVENT_SPACE_CHANGED\n"); + if(arg_size == sizeof(uint32_t)) { + uint32_t space_id = *(uint32_t *)arg; + DarwinSendDDXEvent(kXquartzSpaceChanged, 1, space_id); + } + break; +#endif + default: + ErrorF("Unknown XP_EVENT type (%d) in xprScreen:eventHandler\n", type); + } +} + +/* + * displayAtIndex + * Return the display ID for a particular display index. + */ +static CGDirectDisplayID +displayAtIndex(int index) +{ + CGError err; + CGDisplayCount cnt; + CGDirectDisplayID dpy[index+1]; + + err = CGGetActiveDisplayList(index + 1, dpy, &cnt); + if (err == kCGErrorSuccess && cnt == index + 1) + return dpy[index]; + else + return kCGNullDirectDisplay; +} + +/* + * displayScreenBounds + * Return the bounds of a particular display. + */ +static CGRect +displayScreenBounds(CGDirectDisplayID id) +{ + CGRect frame; + + frame = CGDisplayBounds(id); + + DEBUG_LOG(" %dx%d @ (%d,%d).\n", + (int)frame.size.width, (int)frame.size.height, + (int)frame.origin.x, (int)frame.origin.y); + + /* Remove menubar to help standard X11 window managers. */ + if (XQuartzIsRootless && + frame.origin.x == 0 && frame.origin.y == 0) { + frame.origin.y += aquaMenuBarHeight; + frame.size.height -= aquaMenuBarHeight; + } + + DEBUG_LOG(" %dx%d @ (%d,%d).\n", + (int)frame.size.width, (int)frame.size.height, + (int)frame.origin.x, (int)frame.origin.y); + + return frame; +} + +/* + * xprAddPseudoramiXScreens + * Add a single virtual screen encompassing all the physical screens + * with PseudoramiX. + */ +static void +xprAddPseudoramiXScreens(int *x, int *y, int *width, int *height, ScreenPtr pScreen) +{ + CGDisplayCount i, displayCount; + CGDirectDisplayID *displayList = NULL; + CGRect unionRect = CGRectNull, frame; + + // Find all the CoreGraphics displays + CGGetActiveDisplayList(0, NULL, &displayCount); + DEBUG_LOG("displayCount: %d\n", (int)displayCount); + + if(!displayCount) { + ErrorF("CoreGraphics has reported no connected displays. Creating a stub 800x600 display.\n"); + *x = *y = 0; + *width = 800; + *height = 600; + PseudoramiXAddScreen(*x, *y, *width, *height); + return; + } + + /* If the displays are captured, we are in a RandR game mode + * on the primary display, so we only want to include the first + * display. The others are covered by the shield window. + */ + if (CGDisplayIsCaptured(kCGDirectMainDisplay)) + displayCount = 1; + + displayList = malloc(displayCount * sizeof(CGDirectDisplayID)); + 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++) { + CGDirectDisplayID dpy = displayList[i]; + frame = displayScreenBounds(dpy); + unionRect = CGRectUnion(unionRect, frame); + } + + /* Use unionRect as the screen size for the X server. */ + *x = unionRect.origin.x; + *y = unionRect.origin.y; + *width = unionRect.size.width; + *height = unionRect.size.height; + + DEBUG_LOG(" screen union origin: (%d,%d) size: (%d,%d).\n", + *x, *y, *width, *height); + + /* Tell PseudoramiX about the real screens. */ + for (i = 0; i < displayCount; i++) + { + CGDirectDisplayID dpy = displayList[i]; + + frame = displayScreenBounds(dpy); + frame.origin.x -= unionRect.origin.x; + frame.origin.y -= unionRect.origin.y; + + DEBUG_LOG(" placed at X11 coordinate (%d,%d).\n", + (int)frame.origin.x, (int)frame.origin.y); + + PseudoramiXAddScreen(frame.origin.x, frame.origin.y, + frame.size.width, frame.size.height); + } + + free(displayList); +} + +/* + * xprDisplayInit + * Find number of CoreGraphics displays and initialize Xplugin. + */ +static void +xprDisplayInit(void) +{ + CGDisplayCount displayCount; + + DEBUG_LOG(""); + + CGGetActiveDisplayList(0, NULL, &displayCount); + + /* With PseudoramiX, the X server only sees one screen; only PseudoramiX + itself knows about all of the screens. */ + + if (noPseudoramiXExtension) + darwinScreensFound = displayCount; + else + darwinScreensFound = 1; + + if (xp_init(XP_BACKGROUND_EVENTS | XP_NO_DEFERRED_UPDATES) != Success) + FatalError("Could not initialize the Xplugin library."); + + xp_select_events(XP_EVENT_DISPLAY_CHANGED + | XP_EVENT_WINDOW_STATE_CHANGED + | XP_EVENT_WINDOW_MOVED +#ifdef XP_EVENT_SPACE_CHANGED + | XP_EVENT_SPACE_CHANGED +#endif + | XP_EVENT_SURFACE_CHANGED + | XP_EVENT_SURFACE_DESTROYED, + eventHandler, NULL); + + AppleDRIExtensionInit(); + xprAppleWMInit(); + + XQuartzIsRootless = XQuartzRootlessDefault; + if (!XQuartzIsRootless) + RootlessHideAllWindows(); +} + +/* + * xprAddScreen + * Init the framebuffer and record pixmap parameters for the screen. + */ +static Bool +xprAddScreen(int index, ScreenPtr pScreen) +{ + DarwinFramebufferPtr dfb = SCREEN_PRIV(pScreen); + int depth = darwinDesiredDepth; + + DEBUG_LOG("index=%d depth=%d\n", index, depth); + + if(depth == -1) { +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 + depth = CGDisplaySamplesPerPixel(kCGDirectMainDisplay) * CGDisplayBitsPerSample(kCGDirectMainDisplay); +#else + CGDisplayModeRef modeRef; + CFStringRef encStrRef; + + modeRef = CGDisplayCopyDisplayMode(kCGDirectMainDisplay); + if(!modeRef) + goto have_depth; + + encStrRef = CGDisplayModeCopyPixelEncoding(modeRef); + CFRelease(modeRef); + if(!encStrRef) + goto have_depth; + + if(CFStringCompare(encStrRef, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) { + depth = 24; + } else if(CFStringCompare(encStrRef, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) { + depth = 15; + } else if(CFStringCompare(encStrRef, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) { + depth = 8; + } + + CFRelease(encStrRef); +#endif + } + +have_depth: + switch(depth) { + case 8: // pseudo-working + dfb->visuals = PseudoColorMask; + dfb->preferredCVC = PseudoColor; + dfb->depth = 8; + dfb->bitsPerRGB = 8; + dfb->bitsPerPixel = 8; + dfb->redMask = 0; + dfb->greenMask = 0; + dfb->blueMask = 0; + break; + case 15: + dfb->visuals = TrueColorMask; //LARGE_VISUALS; + dfb->preferredCVC = TrueColor; + dfb->depth = 15; + dfb->bitsPerRGB = 5; + dfb->bitsPerPixel = 16; + dfb->redMask = RM_ARGB(0,5,5,5); + dfb->greenMask = GM_ARGB(0,5,5,5); + dfb->blueMask = BM_ARGB(0,5,5,5); + break; +// case 24: + default: + if(depth != 24) + ErrorF("Unsupported color depth requested. Defaulting to 24bit. (depth=%d darwinDesiredDepth=%d)\n", depth, darwinDesiredDepth); + dfb->visuals = TrueColorMask; //LARGE_VISUALS; + dfb->preferredCVC = TrueColor; + dfb->depth = 24; + dfb->bitsPerRGB = 8; + dfb->bitsPerPixel = 32; + dfb->redMask = RM_ARGB(0,8,8,8); + dfb->greenMask = GM_ARGB(0,8,8,8); + dfb->blueMask = BM_ARGB(0,8,8,8); + break; + } + + if (noPseudoramiXExtension) + { + CGDirectDisplayID dpy; + CGRect frame; + + ErrorF("Warning: noPseudoramiXExtension!\n"); + + dpy = displayAtIndex(index); + QuartzCopyDisplayIDs(pScreen, 1, &dpy); + + frame = displayScreenBounds(dpy); + + dfb->x = frame.origin.x; + dfb->y = frame.origin.y; + dfb->width = frame.size.width; + dfb->height = frame.size.height; + } + else + { + xprAddPseudoramiXScreens(&dfb->x, &dfb->y, &dfb->width, &dfb->height, pScreen); + } + + /* Passing zero width (pitch) makes miCreateScreenResources set the + screen pixmap to the framebuffer pointer, i.e. NULL. The generic + rootless code takes care of making this work. */ + dfb->pitch = 0; + dfb->framebuffer = NULL; + + DRIScreenInit(pScreen); + + return TRUE; +} + +/* + * xprSetupScreen + * Setup the screen for rootless access. + */ +static Bool +xprSetupScreen(int index, ScreenPtr pScreen) +{ +#ifdef DAMAGE + // The Damage extension needs to wrap underneath the + // generic rootless layer, so do it now. + if (!DamageSetup(pScreen)) + return FALSE; +#endif + + // Initialize generic rootless code + if (!xprInit(pScreen)) + return FALSE; + + return DRIFinishScreenInit(pScreen); +} + +/* + * xprUpdateScreen + * Update screen after configuation change. + */ +static void +xprUpdateScreen(ScreenPtr pScreen) +{ + rootlessGlobalOffsetX = darwinMainScreenX; + rootlessGlobalOffsetY = darwinMainScreenY; + + AppleWMSetScreenOrigin(pScreen->root); + + RootlessRepositionWindows(pScreen); + RootlessUpdateScreenPixmap(pScreen); +} + +/* + * xprInitInput + * Finalize xpr specific setup. + */ +static void +xprInitInput(int argc, char **argv) +{ + int i; + + rootlessGlobalOffsetX = darwinMainScreenX; + rootlessGlobalOffsetY = darwinMainScreenY; + + for (i = 0; i < screenInfo.numScreens; i++) + AppleWMSetScreenOrigin(screenInfo.screens[i]->root); +} + +/* + * Quartz display mode function list. + */ +static QuartzModeProcsRec xprModeProcs = { + xprDisplayInit, + xprAddScreen, + xprSetupScreen, + xprInitInput, + QuartzInitCursor, + QuartzSuspendXCursor, + QuartzResumeXCursor, + xprAddPseudoramiXScreens, + xprUpdateScreen, + xprIsX11Window, + xprHideWindows, + RootlessFrameForWindow, + TopLevelParent, + DRICreateSurface, + DRIDestroySurface +}; + +/* + * QuartzModeBundleInit + * Initialize the display mode bundle after loading. + */ +Bool +QuartzModeBundleInit(void) +{ + quartzProcs = &xprModeProcs; + quartzOpenGLBundle = xprOpenGLBundle; + return TRUE; +} |