quartz.c revision 8223e2f2
14642e01fSmrg/* 24642e01fSmrg * 34642e01fSmrg * Quartz-specific support for the Darwin X Server 44642e01fSmrg * 54642e01fSmrg * Copyright (c) 2001-2004 Greg Parker and Torrey T. Lyons. 64642e01fSmrg * All Rights Reserved. 74642e01fSmrg * 84642e01fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 94642e01fSmrg * copy of this software and associated documentation files (the "Software"), 104642e01fSmrg * to deal in the Software without restriction, including without limitation 114642e01fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 124642e01fSmrg * and/or sell copies of the Software, and to permit persons to whom the 134642e01fSmrg * Software is furnished to do so, subject to the following conditions: 144642e01fSmrg * 154642e01fSmrg * The above copyright notice and this permission notice shall be included in 164642e01fSmrg * all copies or substantial portions of the Software. 174642e01fSmrg * 184642e01fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 194642e01fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 204642e01fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 214642e01fSmrg * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 224642e01fSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 234642e01fSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 244642e01fSmrg * DEALINGS IN THE SOFTWARE. 254642e01fSmrg * 264642e01fSmrg * Except as contained in this notice, the name(s) of the above copyright 274642e01fSmrg * holders shall not be used in advertising or otherwise to promote the sale, 284642e01fSmrg * use or other dealings in this Software without prior written authorization. 294642e01fSmrg */ 304642e01fSmrg 314642e01fSmrg#include "sanitizedCarbon.h" 324642e01fSmrg 334642e01fSmrg#ifdef HAVE_DIX_CONFIG_H 344642e01fSmrg#include <dix-config.h> 354642e01fSmrg#endif 364642e01fSmrg 374642e01fSmrg#include "quartzCommon.h" 386747b715Smrg#include "quartzRandR.h" 394642e01fSmrg#include "inputstr.h" 404642e01fSmrg#include "quartz.h" 414642e01fSmrg#include "darwin.h" 424642e01fSmrg#include "darwinEvents.h" 434642e01fSmrg#include "pseudoramiX.h" 444642e01fSmrg#define _APPLEWM_SERVER_ 454642e01fSmrg#include "applewmExt.h" 464642e01fSmrg 474642e01fSmrg#include "X11Application.h" 484642e01fSmrg 496747b715Smrg#include <X11/extensions/applewmconst.h> 504642e01fSmrg 514642e01fSmrg// X headers 524642e01fSmrg#include "scrnintstr.h" 534642e01fSmrg#include "windowstr.h" 544642e01fSmrg#include "colormapst.h" 554642e01fSmrg#include "globals.h" 564642e01fSmrg#include "mi.h" 574642e01fSmrg 584642e01fSmrg// System headers 596747b715Smrg#include <stdlib.h> 606747b715Smrg#include <string.h> 614642e01fSmrg#include <sys/types.h> 624642e01fSmrg#include <sys/stat.h> 634642e01fSmrg#include <fcntl.h> 644642e01fSmrg#include <IOKit/pwr_mgt/IOPMLib.h> 658223e2f2Smrg#include <pthread.h> 668223e2f2Smrg#include <signal.h> 674642e01fSmrg 684642e01fSmrg#include <rootlessCommon.h> 694642e01fSmrg#include <Xplugin.h> 704642e01fSmrg 716747b715SmrgDevPrivateKeyRec quartzScreenKeyRec; 724642e01fSmrgint aquaMenuBarHeight = 0; 734642e01fSmrgQuartzModeProcsPtr quartzProcs = NULL; 744642e01fSmrgconst char *quartzOpenGLBundle = NULL; 754642e01fSmrg 766747b715SmrgBool XQuartzFullscreenDisableHotkeys = TRUE; 776747b715SmrgBool XQuartzOptionSendsAlt = FALSE; 786747b715SmrgBool XQuartzEnableKeyEquivalents = TRUE; 796747b715SmrgBool XQuartzFullscreenVisible = FALSE; 806747b715SmrgBool XQuartzRootlessDefault = TRUE; 816747b715SmrgBool XQuartzIsRootless = TRUE; 826747b715SmrgBool XQuartzServerVisible = FALSE; 836747b715SmrgBool XQuartzFullscreenMenu = FALSE; 848223e2f2Smrg 858223e2f2Smrgint32_t XQuartzShieldingWindowLevel = 0; 864642e01fSmrg 874642e01fSmrg/* 884642e01fSmrg=========================================================================== 894642e01fSmrg 904642e01fSmrg Screen functions 914642e01fSmrg 924642e01fSmrg=========================================================================== 934642e01fSmrg*/ 944642e01fSmrg 954642e01fSmrg/* 964642e01fSmrg * QuartzAddScreen 974642e01fSmrg * Do mode dependent initialization of each screen for Quartz. 984642e01fSmrg */ 994642e01fSmrgBool QuartzAddScreen( 1004642e01fSmrg int index, 1014642e01fSmrg ScreenPtr pScreen) 1024642e01fSmrg{ 1034642e01fSmrg // allocate space for private per screen Quartz specific storage 1046747b715Smrg QuartzScreenPtr displayInfo = calloc(sizeof(QuartzScreenRec), 1); 1054642e01fSmrg 1064642e01fSmrg // QUARTZ_PRIV(pScreen) = displayInfo; 1074642e01fSmrg dixSetPrivate(&pScreen->devPrivates, quartzScreenKey, displayInfo); 1084642e01fSmrg 1094642e01fSmrg // do Quartz mode specific initialization 1104642e01fSmrg return quartzProcs->AddScreen(index, pScreen); 1114642e01fSmrg} 1124642e01fSmrg 1134642e01fSmrg 1144642e01fSmrg/* 1154642e01fSmrg * QuartzSetupScreen 1164642e01fSmrg * Finalize mode specific setup of each screen. 1174642e01fSmrg */ 1184642e01fSmrgBool QuartzSetupScreen( 1194642e01fSmrg int index, 1204642e01fSmrg ScreenPtr pScreen) 1214642e01fSmrg{ 1224642e01fSmrg // do Quartz mode specific setup 1234642e01fSmrg if (! quartzProcs->SetupScreen(index, pScreen)) 1244642e01fSmrg return FALSE; 1254642e01fSmrg 1264642e01fSmrg // setup cursor support 1274642e01fSmrg if (! quartzProcs->InitCursor(pScreen)) 1284642e01fSmrg return FALSE; 1294642e01fSmrg 1306747b715Smrg#if defined(RANDR) 1316747b715Smrg if(!QuartzRandRInit(pScreen)) { 1326747b715Smrg DEBUG_LOG("Failed to init RandR extension.\n"); 1336747b715Smrg return FALSE; 1346747b715Smrg } 1356747b715Smrg#endif 1366747b715Smrg 1374642e01fSmrg return TRUE; 1384642e01fSmrg} 1394642e01fSmrg 1404642e01fSmrg 1414642e01fSmrg/* 1424642e01fSmrg * QuartzInitOutput 1434642e01fSmrg * Quartz display initialization. 1444642e01fSmrg */ 1454642e01fSmrgvoid QuartzInitOutput( 1464642e01fSmrg int argc, 1474642e01fSmrg char **argv ) 1484642e01fSmrg{ 1498223e2f2Smrg /* For XQuartz, we want to just use the default signal handler to work better with CrashTracer */ 1508223e2f2Smrg signal(SIGSEGV, SIG_DFL); 1518223e2f2Smrg signal(SIGILL, SIG_DFL); 1528223e2f2Smrg#ifdef SIGEMT 1538223e2f2Smrg signal(SIGEMT, SIG_DFL); 1548223e2f2Smrg#endif 1558223e2f2Smrg signal(SIGFPE, SIG_DFL); 1568223e2f2Smrg#ifdef SIGBUS 1578223e2f2Smrg signal(SIGBUS, SIG_DFL); 1588223e2f2Smrg#endif 1598223e2f2Smrg#ifdef SIGSYS 1608223e2f2Smrg signal(SIGSYS, SIG_DFL); 1618223e2f2Smrg#endif 1628223e2f2Smrg#ifdef SIGXCPU 1638223e2f2Smrg signal(SIGXCPU, SIG_DFL); 1648223e2f2Smrg#endif 1658223e2f2Smrg#ifdef SIGXFSZ 1668223e2f2Smrg signal(SIGXFSZ, SIG_DFL); 1678223e2f2Smrg#endif 1688223e2f2Smrg 1694642e01fSmrg if (!RegisterBlockAndWakeupHandlers(QuartzBlockHandler, 1704642e01fSmrg QuartzWakeupHandler, 1714642e01fSmrg NULL)) 1724642e01fSmrg { 1734642e01fSmrg FatalError("Could not register block and wakeup handlers."); 1744642e01fSmrg } 1754642e01fSmrg 1766747b715Smrg if (!dixRegisterPrivateKey(&quartzScreenKeyRec, PRIVATE_SCREEN, 0)) 1776747b715Smrg FatalError("Failed to alloc quartz screen private.\n"); 1786747b715Smrg 1794642e01fSmrg // Do display mode specific initialization 1804642e01fSmrg quartzProcs->DisplayInit(); 1814642e01fSmrg} 1824642e01fSmrg 1834642e01fSmrg 1844642e01fSmrg/* 1854642e01fSmrg * QuartzInitInput 1864642e01fSmrg * Inform the main thread the X server is ready to handle events. 1874642e01fSmrg */ 1884642e01fSmrgvoid QuartzInitInput( 1894642e01fSmrg int argc, 1904642e01fSmrg char **argv ) 1914642e01fSmrg{ 1926747b715Smrg X11ApplicationSetCanQuit(0); 1934642e01fSmrg X11ApplicationServerReady(); 1944642e01fSmrg // Do final display mode specific initialization before handling events 1954642e01fSmrg if (quartzProcs->InitInput) 1964642e01fSmrg quartzProcs->InitInput(argc, argv); 1974642e01fSmrg} 1984642e01fSmrg 1994642e01fSmrg 2006747b715Smrgvoid QuartzUpdateScreens(void) { 2014642e01fSmrg ScreenPtr pScreen; 2024642e01fSmrg WindowPtr pRoot; 2034642e01fSmrg int x, y, width, height, sx, sy; 2044642e01fSmrg xEvent e; 2056747b715Smrg BoxRec bounds; 2064642e01fSmrg 2074642e01fSmrg if (noPseudoramiXExtension || screenInfo.numScreens != 1) 2084642e01fSmrg { 2094642e01fSmrg /* FIXME: if not using Xinerama, we have multiple screens, and 2104642e01fSmrg to do this properly may need to add or remove screens. Which 2114642e01fSmrg isn't possible. So don't do anything. Another reason why 2124642e01fSmrg we default to running with Xinerama. */ 2134642e01fSmrg 2144642e01fSmrg return; 2154642e01fSmrg } 2164642e01fSmrg 2174642e01fSmrg pScreen = screenInfo.screens[0]; 2184642e01fSmrg 2194642e01fSmrg PseudoramiXResetScreens(); 2206747b715Smrg quartzProcs->AddPseudoramiXScreens(&x, &y, &width, &height, pScreen); 2214642e01fSmrg 2226747b715Smrg pScreen->x = x; 2236747b715Smrg pScreen->y = y; 2244642e01fSmrg pScreen->mmWidth = pScreen->mmWidth * ((double) width / pScreen->width); 2254642e01fSmrg pScreen->mmHeight = pScreen->mmHeight * ((double) height / pScreen->height); 2264642e01fSmrg pScreen->width = width; 2274642e01fSmrg pScreen->height = height; 2284642e01fSmrg 2294642e01fSmrg DarwinAdjustScreenOrigins(&screenInfo); 2304642e01fSmrg 2316747b715Smrg /* DarwinAdjustScreenOrigins or UpdateScreen may change pScreen->x/y, 2326747b715Smrg * so use it rather than x/y 2336747b715Smrg */ 2346747b715Smrg sx = pScreen->x + darwinMainScreenX; 2356747b715Smrg sy = pScreen->y + darwinMainScreenY; 2364642e01fSmrg 2374642e01fSmrg /* Adjust the root window. */ 2386747b715Smrg pRoot = pScreen->root; 2394642e01fSmrg AppleWMSetScreenOrigin(pRoot); 2404642e01fSmrg pScreen->ResizeWindow(pRoot, x - sx, y - sy, width, height, NULL); 2416747b715Smrg 2424642e01fSmrg miPaintWindow(pRoot, &pRoot->borderClip, PW_BACKGROUND); 2434642e01fSmrg 2446747b715Smrg /* <rdar://problem/7770779> pointer events are clipped to old display region after display reconfiguration 2456747b715Smrg * http://xquartz.macosforge.org/trac/ticket/346 2466747b715Smrg */ 2476747b715Smrg bounds.x1 = 0; 2486747b715Smrg bounds.x2 = width; 2496747b715Smrg bounds.y1 = 0; 2506747b715Smrg bounds.y2 = height; 2516747b715Smrg pScreen->ConstrainCursor(inputInfo.pointer, pScreen, &bounds); 2526747b715Smrg inputInfo.pointer->spriteInfo->sprite->physLimits = bounds; 2536747b715Smrg inputInfo.pointer->spriteInfo->sprite->hotLimits = bounds; 2546747b715Smrg 2556747b715Smrg DEBUG_LOG("Root Window: %dx%d @ (%d, %d) darwinMainScreen (%d, %d) xy (%d, %d) dixScreenOrigins (%d, %d)\n", width, height, x - sx, y - sy, darwinMainScreenX, darwinMainScreenY, x, y, pScreen->x, pScreen->y); 2564642e01fSmrg 2574642e01fSmrg /* Send an event for the root reconfigure */ 2584642e01fSmrg e.u.u.type = ConfigureNotify; 2594642e01fSmrg e.u.configureNotify.window = pRoot->drawable.id; 2604642e01fSmrg e.u.configureNotify.aboveSibling = None; 2614642e01fSmrg e.u.configureNotify.x = x - sx; 2624642e01fSmrg e.u.configureNotify.y = y - sy; 2634642e01fSmrg e.u.configureNotify.width = width; 2644642e01fSmrg e.u.configureNotify.height = height; 2654642e01fSmrg e.u.configureNotify.borderWidth = wBorderWidth(pRoot); 2664642e01fSmrg e.u.configureNotify.override = pRoot->overrideRedirect; 2674642e01fSmrg DeliverEvents(pRoot, &e, 1, NullWindow); 2684642e01fSmrg 2696747b715Smrg quartzProcs->UpdateScreen(pScreen); 2708223e2f2Smrg 2718223e2f2Smrg /* Tell RandR about the new size, so new connections get the correct info */ 2728223e2f2Smrg RRScreenSizeNotify(pScreen); 2738223e2f2Smrg} 2748223e2f2Smrg 2758223e2f2Smrgstatic void pokeActivityCallback(CFRunLoopTimerRef timer, void *info) { 2768223e2f2Smrg UpdateSystemActivity(OverallAct); 2778223e2f2Smrg} 2788223e2f2Smrg 2798223e2f2Smrgstatic void QuartzScreenSaver(int state) { 2808223e2f2Smrg static CFRunLoopTimerRef pokeActivityTimer = NULL; 2818223e2f2Smrg static CFRunLoopTimerContext pokeActivityContext = { 0, NULL, NULL, NULL, NULL }; 2828223e2f2Smrg static pthread_mutex_t pokeActivityMutex = PTHREAD_MUTEX_INITIALIZER; 2838223e2f2Smrg 2848223e2f2Smrg pthread_mutex_lock(&pokeActivityMutex); 2858223e2f2Smrg 2868223e2f2Smrg if(state) { 2878223e2f2Smrg if(pokeActivityTimer == NULL) 2888223e2f2Smrg goto QuartzScreenSaverEnd; 2898223e2f2Smrg 2908223e2f2Smrg CFRunLoopTimerInvalidate(pokeActivityTimer); 2918223e2f2Smrg CFRelease(pokeActivityTimer); 2928223e2f2Smrg pokeActivityTimer = NULL; 2938223e2f2Smrg } else { 2948223e2f2Smrg if(pokeActivityTimer != NULL) 2958223e2f2Smrg goto QuartzScreenSaverEnd; 2968223e2f2Smrg 2978223e2f2Smrg pokeActivityTimer = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent(), 30, 0, 0, pokeActivityCallback, &pokeActivityContext); 2988223e2f2Smrg if(pokeActivityTimer == NULL) { 2998223e2f2Smrg ErrorF("Unable to create pokeActivityTimer.\n"); 3008223e2f2Smrg goto QuartzScreenSaverEnd; 3018223e2f2Smrg } 3028223e2f2Smrg 3038223e2f2Smrg CFRunLoopAddTimer(CFRunLoopGetMain(), pokeActivityTimer, kCFRunLoopCommonModes); 3048223e2f2Smrg } 3058223e2f2SmrgQuartzScreenSaverEnd: 3068223e2f2Smrg pthread_mutex_unlock(&pokeActivityMutex); 3074642e01fSmrg} 3084642e01fSmrg 3096747b715Smrgvoid QuartzShowFullscreen(int state) { 3106747b715Smrg int i; 3116747b715Smrg 3126747b715Smrg DEBUG_LOG("QuartzShowFullscreen: state=%d\n", state); 3134642e01fSmrg 3146747b715Smrg if(XQuartzIsRootless) { 3156747b715Smrg ErrorF("QuartzShowFullscreen called while in rootless mode.\n"); 3166747b715Smrg return; 3176747b715Smrg } 3184642e01fSmrg 3198223e2f2Smrg QuartzScreenSaver(!state); 3208223e2f2Smrg 3216747b715Smrg if(XQuartzFullscreenVisible == state) 3224642e01fSmrg return; 3234642e01fSmrg 3246747b715Smrg XQuartzFullscreenVisible = state; 3254642e01fSmrg 3264642e01fSmrg xp_disable_update (); 3274642e01fSmrg 3286747b715Smrg if (!XQuartzFullscreenVisible) 3294642e01fSmrg RootlessHideAllWindows(); 3304642e01fSmrg 3316747b715Smrg RootlessUpdateRooted(XQuartzFullscreenVisible); 3324642e01fSmrg 3336747b715Smrg if (XQuartzFullscreenVisible) { 3344642e01fSmrg RootlessShowAllWindows (); 3356747b715Smrg for (i=0; i < screenInfo.numScreens; i++) { 3366747b715Smrg ScreenPtr pScreen = screenInfo.screens[i]; 3376747b715Smrg RootlessRepositionWindows(pScreen); 3386747b715Smrg // JH: I don't think this is necessary, but keeping it here as a reminder 3396747b715Smrg //RootlessUpdateScreenPixmap(pScreen); 3406747b715Smrg } 3414642e01fSmrg } 3424642e01fSmrg 3434642e01fSmrg /* Somehow the menubar manages to interfere with our event stream 3444642e01fSmrg * in fullscreen mode, even though it's not visible. 3454642e01fSmrg */ 3466747b715Smrg X11ApplicationShowHideMenubar(!XQuartzFullscreenVisible); 3474642e01fSmrg 3484642e01fSmrg xp_reenable_update (); 3494642e01fSmrg 3506747b715Smrg if (XQuartzFullscreenDisableHotkeys) 3516747b715Smrg xp_disable_hot_keys(XQuartzFullscreenVisible); 3524642e01fSmrg} 3534642e01fSmrg 3546747b715Smrgvoid QuartzSetRootless(Bool state) { 3556747b715Smrg DEBUG_LOG("QuartzSetRootless state=%d\n", state); 3566747b715Smrg 3576747b715Smrg if(XQuartzIsRootless == state) 3584642e01fSmrg return; 3594642e01fSmrg 3606747b715Smrg if(state) 3616747b715Smrg QuartzShowFullscreen(FALSE); 3626747b715Smrg 3636747b715Smrg XQuartzIsRootless = state; 3644642e01fSmrg 3654642e01fSmrg xp_disable_update(); 3664642e01fSmrg 3674642e01fSmrg /* When in rootless, the menubar is not part of the screen, so we need to update our screens on toggle */ 3684642e01fSmrg QuartzUpdateScreens(); 3694642e01fSmrg 3706747b715Smrg if(XQuartzIsRootless) { 3714642e01fSmrg RootlessShowAllWindows(); 3726747b715Smrg } else { 3736747b715Smrg RootlessHideAllWindows(); 3744642e01fSmrg } 3754642e01fSmrg 3766747b715Smrg X11ApplicationShowHideMenubar(TRUE); 3776747b715Smrg 3784642e01fSmrg xp_reenable_update(); 3796747b715Smrg 3806747b715Smrg xp_disable_hot_keys(FALSE); 3814642e01fSmrg} 3824642e01fSmrg 3834642e01fSmrg/* 3844642e01fSmrg * QuartzShow 3854642e01fSmrg * Show the X server on screen. Does nothing if already shown. 3864642e01fSmrg * Calls mode specific screen resume to restore the X clip regions 3874642e01fSmrg * (if needed) and the X server cursor state. 3884642e01fSmrg */ 3896747b715Smrgvoid QuartzShow(void) { 3904642e01fSmrg int i; 3914642e01fSmrg 3926747b715Smrg if (XQuartzServerVisible) 3934642e01fSmrg return; 3944642e01fSmrg 3956747b715Smrg XQuartzServerVisible = TRUE; 3964642e01fSmrg for (i = 0; i < screenInfo.numScreens; i++) { 3974642e01fSmrg if (screenInfo.screens[i]) { 3986747b715Smrg quartzProcs->ResumeScreen(screenInfo.screens[i]); 3994642e01fSmrg } 4004642e01fSmrg } 4014642e01fSmrg 4026747b715Smrg if (!XQuartzIsRootless) 4036747b715Smrg QuartzShowFullscreen(TRUE); 4044642e01fSmrg} 4054642e01fSmrg 4064642e01fSmrg 4074642e01fSmrg/* 4084642e01fSmrg * QuartzHide 4094642e01fSmrg * Remove the X server display from the screen. Does nothing if already 4104642e01fSmrg * hidden. Calls mode specific screen suspend to set X clip regions to 4114642e01fSmrg * prevent drawing (if needed) and restore the Aqua cursor. 4124642e01fSmrg */ 4134642e01fSmrgvoid QuartzHide(void) 4144642e01fSmrg{ 4154642e01fSmrg int i; 4164642e01fSmrg 4176747b715Smrg if (XQuartzServerVisible) { 4184642e01fSmrg for (i = 0; i < screenInfo.numScreens; i++) { 4194642e01fSmrg if (screenInfo.screens[i]) { 4204642e01fSmrg quartzProcs->SuspendScreen(screenInfo.screens[i]); 4214642e01fSmrg } 4224642e01fSmrg } 4234642e01fSmrg } 4246747b715Smrg 4256747b715Smrg if(!XQuartzIsRootless) 4266747b715Smrg QuartzShowFullscreen(FALSE); 4276747b715Smrg XQuartzServerVisible = FALSE; 4284642e01fSmrg} 4294642e01fSmrg 4304642e01fSmrg 4314642e01fSmrg/* 4324642e01fSmrg * QuartzSetRootClip 4334642e01fSmrg * Enable or disable rendering to the X screen. 4344642e01fSmrg */ 4354642e01fSmrgvoid QuartzSetRootClip( 4364642e01fSmrg BOOL enable) 4374642e01fSmrg{ 4384642e01fSmrg int i; 4394642e01fSmrg 4406747b715Smrg if (!XQuartzServerVisible) 4414642e01fSmrg return; 4424642e01fSmrg 4434642e01fSmrg for (i = 0; i < screenInfo.numScreens; i++) { 4444642e01fSmrg if (screenInfo.screens[i]) { 4454642e01fSmrg xf86SetRootClip(screenInfo.screens[i], enable); 4464642e01fSmrg } 4474642e01fSmrg } 4484642e01fSmrg} 4494642e01fSmrg 4504642e01fSmrg/* 4514642e01fSmrg * QuartzSpaceChanged 4524642e01fSmrg * Unmap offscreen windows, map onscreen windows 4534642e01fSmrg */ 4544642e01fSmrgvoid QuartzSpaceChanged(uint32_t space_id) { 4554642e01fSmrg /* Do something special here, so we don't depend on quartz-wm for spaces to work... */ 4564642e01fSmrg DEBUG_LOG("Space Changed (%u) ... do something interesting...\n", space_id); 4574642e01fSmrg} 4586747b715Smrg 4596747b715Smrg/* 4606747b715Smrg * QuartzCopyDisplayIDs 4616747b715Smrg * Associate an X11 screen with one or more CoreGraphics display IDs by copying 4626747b715Smrg * the list into a private array. Free the previously copied array, if present. 4636747b715Smrg */ 4646747b715Smrgvoid QuartzCopyDisplayIDs(ScreenPtr pScreen, 4656747b715Smrg int displayCount, CGDirectDisplayID *displayIDs) { 4666747b715Smrg QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); 4676747b715Smrg int size = displayCount * sizeof(CGDirectDisplayID); 4686747b715Smrg 4696747b715Smrg free(pQuartzScreen->displayIDs); 4706747b715Smrg pQuartzScreen->displayIDs = malloc(size); 4716747b715Smrg memcpy(pQuartzScreen->displayIDs, displayIDs, size); 4726747b715Smrg pQuartzScreen->displayCount = displayCount; 4736747b715Smrg} 4748223e2f2Smrg 4758223e2f2Smrgvoid NSBeep(void); 4768223e2f2Smrgvoid DDXRingBell( 4778223e2f2Smrg int volume, // volume is % of max 4788223e2f2Smrg int pitch, // pitch is Hz 4798223e2f2Smrg int duration) // duration is milliseconds 4808223e2f2Smrg{ 4818223e2f2Smrg if (volume) 4828223e2f2Smrg NSBeep(); 4838223e2f2Smrg} 484