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