1/* 2 * Quartz-specific support for the XRandR extension 3 * 4 * Copyright (c) 2001-2004 Greg Parker and Torrey T. Lyons, 5 * 2010 Jan Hauffa. 6 * 2010-2011 Apple Inc. 7 * All Rights Reserved. 8 * 9 * Permission is hereby granted, free of charge, to any person obtaining a 10 * copy of this software and associated documentation files (the "Software"), 11 * to deal in the Software without restriction, including without limitation 12 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 * and/or sell copies of the Software, and to permit persons to whom the 14 * Software is furnished to do so, subject to the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be included in 17 * all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 * DEALINGS IN THE SOFTWARE. 26 * 27 * Except as contained in this notice, the name(s) of the above copyright 28 * holders shall not be used in advertising or otherwise to promote the sale, 29 * use or other dealings in this Software without prior written authorization. 30 */ 31 32#include "sanitizedCarbon.h" 33 34#ifdef HAVE_DIX_CONFIG_H 35#include <dix-config.h> 36#endif 37 38#include "quartzCommon.h" 39#include "quartzRandR.h" 40#include "quartz.h" 41#include "darwin.h" 42 43#include "X11Application.h" 44 45#include <AvailabilityMacros.h> 46 47#include <X11/extensions/randr.h> 48#include <randrstr.h> 49#include <IOKit/graphics/IOGraphicsTypes.h> 50 51/* TODO: UGLY, find a better way! 52 * We want to ignore kXquartzDisplayChanged which are generated by us 53 */ 54static Bool ignore_next_fake_mode_update = FALSE; 55 56#define FAKE_REFRESH_ROOTLESS 1 57#define FAKE_REFRESH_FULLSCREEN 2 58 59#define DEFAULT_REFRESH 60 60#define kDisplayModeUsableFlags (kDisplayModeValidFlag | kDisplayModeSafeFlag) 61 62#define CALLBACK_SUCCESS 0 63#define CALLBACK_CONTINUE 1 64#define CALLBACK_ERROR -1 65 66typedef int (*QuartzModeCallback) 67 (ScreenPtr, QuartzModeInfoPtr, void *); 68 69#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 70 71static long getDictLong (CFDictionaryRef dictRef, CFStringRef key) { 72 long value; 73 74 CFNumberRef numRef = (CFNumberRef) CFDictionaryGetValue(dictRef, key); 75 if (!numRef) 76 return 0; 77 78 if (!CFNumberGetValue(numRef, kCFNumberLongType, &value)) 79 return 0; 80 return value; 81} 82 83static double getDictDouble (CFDictionaryRef dictRef, CFStringRef key) { 84 double value; 85 86 CFNumberRef numRef = (CFNumberRef) CFDictionaryGetValue(dictRef, key); 87 if (!numRef) 88 return 0.0; 89 90 if (!CFNumberGetValue(numRef, kCFNumberDoubleType, &value)) 91 return 0.0; 92 return value; 93} 94 95static void QuartzRandRGetModeInfo (CFDictionaryRef modeRef, 96 QuartzModeInfoPtr pMode) { 97 pMode->width = (size_t) getDictLong(modeRef, kCGDisplayWidth); 98 pMode->height = (size_t) getDictLong(modeRef, kCGDisplayHeight); 99 pMode->refresh = (int)(getDictDouble(modeRef, kCGDisplayRefreshRate) + 0.5); 100 if (pMode->refresh == 0) 101 pMode->refresh = DEFAULT_REFRESH; 102 pMode->ref = NULL; 103 pMode->pSize = NULL; 104} 105 106static Bool QuartzRandRCopyCurrentModeInfo (CGDirectDisplayID screenId, 107 QuartzModeInfoPtr pMode) { 108 CFDictionaryRef curModeRef = CGDisplayCurrentMode(screenId); 109 if (!curModeRef) 110 return FALSE; 111 112 QuartzRandRGetModeInfo(curModeRef, pMode); 113 pMode->ref = (void *)curModeRef; 114 CFRetain(pMode->ref); 115 return TRUE; 116} 117 118static Bool QuartzRandRSetCGMode (CGDirectDisplayID screenId, 119 QuartzModeInfoPtr pMode) { 120 CFDictionaryRef modeRef = (CFDictionaryRef) pMode->ref; 121 return (CGDisplaySwitchToMode(screenId, modeRef) == kCGErrorSuccess); 122} 123 124static Bool QuartzRandREnumerateModes (ScreenPtr pScreen, 125 QuartzModeCallback callback, 126 void *data) { 127 Bool retval = FALSE; 128 QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); 129 130 /* Just an 800x600 fallback if we have no attached heads */ 131 if(pQuartzScreen->displayIDs) { 132 CFDictionaryRef curModeRef, modeRef; 133 long curBpp; 134 CFArrayRef modes; 135 QuartzModeInfo modeInfo; 136 int i; 137 CGDirectDisplayID screenId = pQuartzScreen->displayIDs[0]; 138 139 curModeRef = CGDisplayCurrentMode(screenId); 140 if (!curModeRef) 141 return FALSE; 142 curBpp = getDictLong(curModeRef, kCGDisplayBitsPerPixel); 143 144 modes = CGDisplayAvailableModes(screenId); 145 if (!modes) 146 return FALSE; 147 for (i = 0; i < CFArrayGetCount(modes); i++) { 148 int cb; 149 modeRef = (CFDictionaryRef) CFArrayGetValueAtIndex(modes, i); 150 151 /* Skip modes that are not usable on the current display or have a 152 different pixel encoding than the current mode. */ 153 if (((unsigned long) getDictLong(modeRef, kCGDisplayIOFlags) & 154 kDisplayModeUsableFlags) != kDisplayModeUsableFlags) 155 continue; 156 if (getDictLong(modeRef, kCGDisplayBitsPerPixel) != curBpp) 157 continue; 158 159 QuartzRandRGetModeInfo(modeRef, &modeInfo); 160 modeInfo.ref = (void *)modeRef; 161 cb = callback(pScreen, &modeInfo, data); 162 if (cb == CALLBACK_CONTINUE) 163 retval = TRUE; 164 else if (cb == CALLBACK_SUCCESS) 165 return TRUE; 166 else if (cb == CALLBACK_ERROR) 167 return FALSE; 168 } 169 } 170 171 switch(callback(pScreen, &pQuartzScreen->rootlessMode, data)) { 172 case CALLBACK_SUCCESS: 173 return TRUE; 174 case CALLBACK_ERROR: 175 return FALSE; 176 case CALLBACK_CONTINUE: 177 retval = TRUE; 178 default: 179 break; 180 } 181 182 switch(callback(pScreen, &pQuartzScreen->fullscreenMode, data)) { 183 case CALLBACK_SUCCESS: 184 return TRUE; 185 case CALLBACK_ERROR: 186 return FALSE; 187 case CALLBACK_CONTINUE: 188 retval = TRUE; 189 default: 190 break; 191 } 192 193 return retval; 194} 195 196#else /* we have the new CG APIs from Snow Leopard */ 197 198static void QuartzRandRGetModeInfo (CGDisplayModeRef modeRef, 199 QuartzModeInfoPtr pMode) { 200 pMode->width = CGDisplayModeGetWidth(modeRef); 201 pMode->height = CGDisplayModeGetHeight(modeRef); 202 pMode->refresh = (int) (CGDisplayModeGetRefreshRate(modeRef) + 0.5); 203 if (pMode->refresh == 0) 204 pMode->refresh = DEFAULT_REFRESH; 205 pMode->ref = NULL; 206 pMode->pSize = NULL; 207} 208 209static Bool QuartzRandRCopyCurrentModeInfo (CGDirectDisplayID screenId, 210 QuartzModeInfoPtr pMode) { 211 CGDisplayModeRef curModeRef = CGDisplayCopyDisplayMode(screenId); 212 if (!curModeRef) 213 return FALSE; 214 215 QuartzRandRGetModeInfo(curModeRef, pMode); 216 pMode->ref = curModeRef; 217 return TRUE; 218} 219 220static Bool QuartzRandRSetCGMode (CGDirectDisplayID screenId, 221 QuartzModeInfoPtr pMode) { 222 CGDisplayModeRef modeRef = (CGDisplayModeRef) pMode->ref; 223 if (!modeRef) 224 return FALSE; 225 226 return (CGDisplaySetDisplayMode(screenId, modeRef, NULL) == kCGErrorSuccess); 227} 228 229static Bool QuartzRandREnumerateModes (ScreenPtr pScreen, 230 QuartzModeCallback callback, 231 void *data) { 232 Bool retval = FALSE; 233 QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); 234 235 /* Just an 800x600 fallback if we have no attached heads */ 236 if(pQuartzScreen->displayIDs) { 237 CGDisplayModeRef curModeRef, modeRef; 238 CFStringRef curPixelEnc, pixelEnc; 239 CFComparisonResult pixelEncEqual; 240 CFArrayRef modes; 241 QuartzModeInfo modeInfo; 242 int i; 243 CGDirectDisplayID screenId = pQuartzScreen->displayIDs[0]; 244 245 curModeRef = CGDisplayCopyDisplayMode(screenId); 246 if (!curModeRef) 247 return FALSE; 248 curPixelEnc = CGDisplayModeCopyPixelEncoding(curModeRef); 249 CGDisplayModeRelease(curModeRef); 250 251 modes = CGDisplayCopyAllDisplayModes(screenId, NULL); 252 if (!modes) { 253 CFRelease(curPixelEnc); 254 return FALSE; 255 } 256 for (i = 0; i < CFArrayGetCount(modes); i++) { 257 int cb; 258 modeRef = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i); 259 260 /* Skip modes that are not usable on the current display or have a 261 different pixel encoding than the current mode. */ 262 if ((CGDisplayModeGetIOFlags(modeRef) & kDisplayModeUsableFlags) != 263 kDisplayModeUsableFlags) 264 continue; 265 pixelEnc = CGDisplayModeCopyPixelEncoding(modeRef); 266 pixelEncEqual = CFStringCompare(pixelEnc, curPixelEnc, 0); 267 CFRelease(pixelEnc); 268 if (pixelEncEqual != kCFCompareEqualTo) 269 continue; 270 271 QuartzRandRGetModeInfo(modeRef, &modeInfo); 272 modeInfo.ref = modeRef; 273 cb = callback(pScreen, &modeInfo, data); 274 if (cb == CALLBACK_CONTINUE) { 275 retval = TRUE; 276 } else if (cb == CALLBACK_SUCCESS) { 277 CFRelease(modes); 278 CFRelease(curPixelEnc); 279 return TRUE; 280 } else if (cb == CALLBACK_ERROR) { 281 CFRelease(modes); 282 CFRelease(curPixelEnc); 283 return FALSE; 284 } 285 } 286 287 CFRelease(modes); 288 CFRelease(curPixelEnc); 289 } 290 291 switch(callback(pScreen, &pQuartzScreen->rootlessMode, data)) { 292 case CALLBACK_SUCCESS: 293 return TRUE; 294 case CALLBACK_ERROR: 295 return FALSE; 296 case CALLBACK_CONTINUE: 297 retval = TRUE; 298 default: 299 break; 300 } 301 302 switch(callback(pScreen, &pQuartzScreen->fullscreenMode, data)) { 303 case CALLBACK_SUCCESS: 304 return TRUE; 305 case CALLBACK_ERROR: 306 return FALSE; 307 case CALLBACK_CONTINUE: 308 retval = TRUE; 309 default: 310 break; 311 } 312 313 return retval; 314} 315 316#endif /* Snow Leopard CoreGraphics APIs */ 317 318 319static Bool QuartzRandRModesEqual (QuartzModeInfoPtr pMode1, 320 QuartzModeInfoPtr pMode2) { 321 return (pMode1->width == pMode2->width) && 322 (pMode1->height == pMode2->height) && 323 (pMode1->refresh == pMode2->refresh); 324} 325 326static Bool QuartzRandRRegisterMode (ScreenPtr pScreen, 327 QuartzModeInfoPtr pMode) { 328 QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); 329 Bool isCurrentMode = QuartzRandRModesEqual(&pQuartzScreen->currentMode, pMode); 330 331 /* TODO: DPI */ 332 pMode->pSize = RRRegisterSize(pScreen, pMode->width, pMode->height, pScreen->mmWidth, pScreen->mmHeight); 333 if (pMode->pSize) { 334 //DEBUG_LOG("registering: %d x %d @ %d %s\n", (int)pMode->width, (int)pMode->height, (int)pMode->refresh, isCurrentMode ? "*" : ""); 335 RRRegisterRate(pScreen, pMode->pSize, pMode->refresh); 336 337 if (isCurrentMode) 338 RRSetCurrentConfig(pScreen, RR_Rotate_0, pMode->refresh, pMode->pSize); 339 340 return TRUE; 341 } 342 return FALSE; 343} 344 345static int QuartzRandRRegisterModeCallback (ScreenPtr pScreen, 346 QuartzModeInfoPtr pMode, 347 void *data __unused) { 348 if(QuartzRandRRegisterMode(pScreen, pMode)) { 349 return CALLBACK_CONTINUE; 350 } else { 351 return CALLBACK_ERROR; 352 } 353} 354 355static Bool QuartzRandRSetMode(ScreenPtr pScreen, QuartzModeInfoPtr pMode, BOOL doRegister) { 356 QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); 357 Bool captureDisplay = (pMode->refresh != FAKE_REFRESH_FULLSCREEN && pMode->refresh != FAKE_REFRESH_ROOTLESS); 358 CGDirectDisplayID screenId; 359 360 if(pQuartzScreen->displayIDs == NULL) 361 return FALSE; 362 363 screenId = pQuartzScreen->displayIDs[0]; 364 if(XQuartzShieldingWindowLevel == 0 && captureDisplay) { 365 if(!X11ApplicationCanEnterRandR()) 366 return FALSE; 367 CGCaptureAllDisplays(); 368 XQuartzShieldingWindowLevel = CGShieldingWindowLevel(); // 2147483630 369 DEBUG_LOG("Display captured. ShieldWindowID: %u, Shield level: %d\n", 370 CGShieldingWindowID(screenId), XQuartzShieldingWindowLevel); 371 } 372 373 if (pQuartzScreen->currentMode.ref && CFEqual(pMode->ref, pQuartzScreen->currentMode.ref)) { 374 DEBUG_LOG("Requested RandR resolution matches current CG mode\n"); 375 } if (QuartzRandRSetCGMode(screenId, pMode)) { 376 ignore_next_fake_mode_update = TRUE; 377 } else { 378 DEBUG_LOG("Error while requesting CG resolution change.\n"); 379 return FALSE; 380 } 381 382 /* If the client requested the fake rootless mode, switch to rootless. 383 * Otherwise, force fullscreen mode. 384 */ 385 QuartzSetRootless(pMode->refresh == FAKE_REFRESH_ROOTLESS); 386 if (pMode->refresh != FAKE_REFRESH_ROOTLESS) { 387 QuartzShowFullscreen(TRUE); 388 } 389 390 if(pQuartzScreen->currentMode.ref) 391 CFRelease(pQuartzScreen->currentMode.ref); 392 pQuartzScreen->currentMode = *pMode; 393 if(pQuartzScreen->currentMode.ref) 394 CFRetain(pQuartzScreen->currentMode.ref); 395 396 if(XQuartzShieldingWindowLevel != 0 && !captureDisplay) { 397 CGReleaseAllDisplays(); 398 XQuartzShieldingWindowLevel = 0; 399 } 400 401 return TRUE; 402} 403 404static int QuartzRandRSetModeCallback (ScreenPtr pScreen, 405 QuartzModeInfoPtr pMode, 406 void *data) { 407 QuartzModeInfoPtr pReqMode = (QuartzModeInfoPtr) data; 408 409 if (!QuartzRandRModesEqual(pMode, pReqMode)) 410 return CALLBACK_CONTINUE; /* continue enumeration */ 411 412 DEBUG_LOG("Found a match for requested RandR resolution (%dx%d@%d).\n", (int)pMode->width, (int)pMode->height, (int)pMode->refresh); 413 414 if(QuartzRandRSetMode(pScreen, pMode, FALSE)) 415 return CALLBACK_SUCCESS; 416 else 417 return CALLBACK_ERROR; 418} 419 420static Bool QuartzRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) { 421 *rotations = RR_Rotate_0; /* TODO: support rotation */ 422 423 return QuartzRandREnumerateModes(pScreen, QuartzRandRRegisterModeCallback, NULL); 424} 425 426static Bool QuartzRandRSetConfig (ScreenPtr pScreen, 427 Rotation randr, 428 int rate, 429 RRScreenSizePtr pSize) { 430 QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); 431 QuartzModeInfo reqMode; 432 433 reqMode.width = pSize->width; 434 reqMode.height = pSize->height; 435 reqMode.refresh = rate; 436 437 /* Do not switch modes if requested mode is equal to current mode. */ 438 if (QuartzRandRModesEqual(&reqMode, &pQuartzScreen->currentMode)) 439 return TRUE; 440 441 if (QuartzRandREnumerateModes(pScreen, QuartzRandRSetModeCallback, &reqMode)) { 442 return TRUE; 443 } 444 445 DEBUG_LOG("Unable to find a matching config: %d x %d @ %d\n", (int)reqMode.width, (int)reqMode.height, (int)reqMode.refresh); 446 return FALSE; 447} 448 449static Bool _QuartzRandRUpdateFakeModes (ScreenPtr pScreen) { 450 QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); 451 QuartzModeInfo activeMode; 452 453 if(pQuartzScreen->displayCount > 0) { 454 if(!QuartzRandRCopyCurrentModeInfo(pQuartzScreen->displayIDs[0], &activeMode)) { 455 ErrorF("Unable to determine current display mode.\n"); 456 return FALSE; 457 } 458 } else { 459 memset(&activeMode, 0, sizeof(activeMode)); 460 activeMode.width = 800; 461 activeMode.height = 600; 462 activeMode.refresh = 60; 463 } 464 465 if(pQuartzScreen->fullscreenMode.ref) 466 CFRelease(pQuartzScreen->fullscreenMode.ref); 467 if(pQuartzScreen->currentMode.ref) 468 CFRelease(pQuartzScreen->currentMode.ref); 469 470 if(pQuartzScreen->displayCount > 1) { 471 activeMode.width = pScreen->width; 472 activeMode.height = pScreen->height; 473 if(XQuartzIsRootless) 474 activeMode.height += aquaMenuBarHeight; 475 } 476 477 pQuartzScreen->fullscreenMode = activeMode; 478 pQuartzScreen->fullscreenMode.refresh = FAKE_REFRESH_FULLSCREEN; 479 480 pQuartzScreen->rootlessMode = activeMode; 481 pQuartzScreen->rootlessMode.refresh = FAKE_REFRESH_ROOTLESS; 482 pQuartzScreen->rootlessMode.height -= aquaMenuBarHeight; 483 484 if(XQuartzIsRootless) { 485 pQuartzScreen->currentMode = pQuartzScreen->rootlessMode; 486 } else { 487 pQuartzScreen->currentMode = pQuartzScreen->fullscreenMode; 488 } 489 490 /* This extra retain is for currentMode's copy. 491 * fullscreen and rootless share a retain. 492 */ 493 if(pQuartzScreen->currentMode.ref) 494 CFRetain(pQuartzScreen->currentMode.ref); 495 496 DEBUG_LOG("rootlessMode: %d x %d\n", (int)pQuartzScreen->rootlessMode.width, (int)pQuartzScreen->rootlessMode.height); 497 DEBUG_LOG("fullscreenMode: %d x %d\n", (int)pQuartzScreen->fullscreenMode.width, (int)pQuartzScreen->fullscreenMode.height); 498 DEBUG_LOG("currentMode: %d x %d\n", (int)pQuartzScreen->currentMode.width, (int)pQuartzScreen->currentMode.height); 499 500 return TRUE; 501} 502 503Bool QuartzRandRUpdateFakeModes (BOOL force_update) { 504 ScreenPtr pScreen = screenInfo.screens[0]; 505 506 if(ignore_next_fake_mode_update) { 507 DEBUG_LOG("Ignoring update request caused by RandR resolution change.\n"); 508 ignore_next_fake_mode_update = FALSE; 509 return TRUE; 510 } 511 512 if(!_QuartzRandRUpdateFakeModes(pScreen)) 513 return FALSE; 514 515 if(force_update) 516 RRGetInfo(pScreen, TRUE); 517 518 return TRUE; 519} 520 521Bool QuartzRandRInit (ScreenPtr pScreen) { 522 rrScrPrivPtr pScrPriv; 523 524 if (!RRScreenInit (pScreen)) return FALSE; 525 if (!_QuartzRandRUpdateFakeModes (pScreen)) return FALSE; 526 527 pScrPriv = rrGetScrPriv(pScreen); 528 pScrPriv->rrGetInfo = QuartzRandRGetInfo; 529 pScrPriv->rrSetConfig = QuartzRandRSetConfig; 530 return TRUE; 531} 532 533void QuartzRandRSetFakeRootless (void) { 534 int i; 535 536 DEBUG_LOG("QuartzRandRSetFakeRootless called.\n"); 537 538 for (i=0; i < screenInfo.numScreens; i++) { 539 ScreenPtr pScreen = screenInfo.screens[i]; 540 QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); 541 542 QuartzRandRSetMode(pScreen, &pQuartzScreen->rootlessMode, TRUE); 543 } 544} 545 546void QuartzRandRSetFakeFullscreen (BOOL state) { 547 int i; 548 549 DEBUG_LOG("QuartzRandRSetFakeFullscreen called.\n"); 550 551 for (i=0; i < screenInfo.numScreens; i++) { 552 ScreenPtr pScreen = screenInfo.screens[i]; 553 QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); 554 555 QuartzRandRSetMode(pScreen, &pQuartzScreen->fullscreenMode, TRUE); 556 } 557 558 QuartzShowFullscreen(state); 559} 560 561/* Toggle fullscreen mode. If "fake" fullscreen is the current mode, 562 * this will just show/hide the X11 windows. If we are in a RandR fullscreen 563 * mode, this will toggles us to the default fake mode and hide windows if 564 * it is fullscreen 565 */ 566void QuartzRandRToggleFullscreen (void) { 567 ScreenPtr pScreen = screenInfo.screens[0]; 568 QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); 569 570 if (pQuartzScreen->currentMode.ref == NULL) { 571 ErrorF("Ignoring QuartzRandRToggleFullscreen because don't have a current mode set.\n"); 572 } else if (pQuartzScreen->currentMode.refresh == FAKE_REFRESH_ROOTLESS) { 573 ErrorF("Ignoring QuartzRandRToggleFullscreen because we are in rootless mode.\n"); 574 } else if (pQuartzScreen->currentMode.refresh == FAKE_REFRESH_FULLSCREEN) { 575 /* Legacy fullscreen mode. Hide/Show */ 576 QuartzShowFullscreen(!XQuartzFullscreenVisible); 577 } else { 578 /* RandR fullscreen mode. Return to default mode and hide if it is fullscreen. */ 579 if(XQuartzRootlessDefault) { 580 QuartzRandRSetFakeRootless(); 581 } else { 582 QuartzRandRSetFakeFullscreen(FALSE); 583 } 584 } 585} 586