quartz.c revision c8548ba8
14642e01fSmrg/*
24642e01fSmrg *
34642e01fSmrg * Quartz-specific support for the Darwin X Server
44642e01fSmrg *
535c4bbdfSmrg * Copyright (c) 2002-2012 Apple Inc. All rights reserved.
64642e01fSmrg * Copyright (c) 2001-2004 Greg Parker and Torrey T. Lyons.
74642e01fSmrg *                 All Rights Reserved.
84642e01fSmrg *
94642e01fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
104642e01fSmrg * copy of this software and associated documentation files (the "Software"),
114642e01fSmrg * to deal in the Software without restriction, including without limitation
124642e01fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
134642e01fSmrg * and/or sell copies of the Software, and to permit persons to whom the
144642e01fSmrg * Software is furnished to do so, subject to the following conditions:
154642e01fSmrg *
164642e01fSmrg * The above copyright notice and this permission notice shall be included in
174642e01fSmrg * all copies or substantial portions of the Software.
184642e01fSmrg *
194642e01fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
204642e01fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
214642e01fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
224642e01fSmrg * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
234642e01fSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
244642e01fSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
254642e01fSmrg * DEALINGS IN THE SOFTWARE.
264642e01fSmrg *
274642e01fSmrg * Except as contained in this notice, the name(s) of the above copyright
284642e01fSmrg * holders shall not be used in advertising or otherwise to promote the sale,
294642e01fSmrg * use or other dealings in this Software without prior written authorization.
304642e01fSmrg */
314642e01fSmrg
324642e01fSmrg#include "sanitizedCarbon.h"
334642e01fSmrg
344642e01fSmrg#ifdef HAVE_DIX_CONFIG_H
354642e01fSmrg#include <dix-config.h>
364642e01fSmrg#endif
374642e01fSmrg
386747b715Smrg#include "quartzRandR.h"
394642e01fSmrg#include "inputstr.h"
404642e01fSmrg#include "quartz.h"
414642e01fSmrg#include "darwin.h"
424642e01fSmrg#include "darwinEvents.h"
434642e01fSmrg#include "pseudoramiX.h"
4435c4bbdfSmrg#include "extension.h"
4535c4bbdfSmrg#include "nonsdk_extinit.h"
4635c4bbdfSmrg#include "glx_extinit.h"
474642e01fSmrg#define _APPLEWM_SERVER_
484642e01fSmrg#include "applewmExt.h"
494642e01fSmrg
504642e01fSmrg#include "X11Application.h"
514642e01fSmrg
526747b715Smrg#include <X11/extensions/applewmconst.h>
534642e01fSmrg
544642e01fSmrg// X headers
554642e01fSmrg#include "scrnintstr.h"
564642e01fSmrg#include "windowstr.h"
574642e01fSmrg#include "colormapst.h"
584642e01fSmrg#include "globals.h"
594642e01fSmrg#include "mi.h"
604642e01fSmrg
614642e01fSmrg// System headers
626747b715Smrg#include <stdlib.h>
636747b715Smrg#include <string.h>
644642e01fSmrg#include <sys/types.h>
654642e01fSmrg#include <sys/stat.h>
664642e01fSmrg#include <fcntl.h>
674642e01fSmrg#include <IOKit/pwr_mgt/IOPMLib.h>
6835c4bbdfSmrg#include <libkern/OSAtomic.h>
698223e2f2Smrg#include <signal.h>
704642e01fSmrg
714642e01fSmrg#include <rootlessCommon.h>
724642e01fSmrg#include <Xplugin.h>
734642e01fSmrg
74c8548ba8Smrg// These are vended by the Objective-C runtime, but they are unfortunately
75c8548ba8Smrg// not available as API in the macOS SDK.  We are following suit with swift
76c8548ba8Smrg// and clang in declaring them inline here.  They canot be removed or changed
77c8548ba8Smrg// in the OS without major bincompat ramifications.
78c8548ba8Smrg//
79c8548ba8Smrg// These were added in macOS 10.7.
80c8548ba8Smrgvoid * _Nonnull objc_autoreleasePoolPush(void);
81c8548ba8Smrgvoid objc_autoreleasePoolPop(void * _Nonnull context);
8235c4bbdfSmrg
8335c4bbdfSmrgDevPrivateKeyRec quartzScreenKeyRec;
8435c4bbdfSmrgint aquaMenuBarHeight = 0;
8535c4bbdfSmrgQuartzModeProcsPtr quartzProcs = NULL;
864642e01fSmrgconst char             *quartzOpenGLBundle = NULL;
874642e01fSmrg
886747b715SmrgBool XQuartzFullscreenDisableHotkeys = TRUE;
896747b715SmrgBool XQuartzOptionSendsAlt = FALSE;
906747b715SmrgBool XQuartzEnableKeyEquivalents = TRUE;
916747b715SmrgBool XQuartzFullscreenVisible = FALSE;
926747b715SmrgBool XQuartzRootlessDefault = TRUE;
936747b715SmrgBool XQuartzIsRootless = TRUE;
946747b715SmrgBool XQuartzServerVisible = FALSE;
956747b715SmrgBool XQuartzFullscreenMenu = FALSE;
968223e2f2Smrg
978223e2f2Smrgint32_t XQuartzShieldingWindowLevel = 0;
984642e01fSmrg
994642e01fSmrg/*
10035c4bbdfSmrg   ===========================================================================
1014642e01fSmrg
10235c4bbdfSmrg   Screen functions
1034642e01fSmrg
10435c4bbdfSmrg   ===========================================================================
10535c4bbdfSmrg */
1064642e01fSmrg
1074642e01fSmrg/*
1084642e01fSmrg * QuartzAddScreen
1094642e01fSmrg *  Do mode dependent initialization of each screen for Quartz.
1104642e01fSmrg */
11135c4bbdfSmrgBool
11235c4bbdfSmrgQuartzAddScreen(int index,
11335c4bbdfSmrg                ScreenPtr pScreen)
1144642e01fSmrg{
11535c4bbdfSmrg    // The clang static analyzer thinks we leak displayInfo here
11635c4bbdfSmrg#ifndef __clang_analyzer__
1174642e01fSmrg    // allocate space for private per screen Quartz specific storage
1186747b715Smrg    QuartzScreenPtr displayInfo = calloc(sizeof(QuartzScreenRec), 1);
1194642e01fSmrg
1204642e01fSmrg    // QUARTZ_PRIV(pScreen) = displayInfo;
1214642e01fSmrg    dixSetPrivate(&pScreen->devPrivates, quartzScreenKey, displayInfo);
12235c4bbdfSmrg#endif /* __clang_analyzer__ */
1234642e01fSmrg
1244642e01fSmrg    // do Quartz mode specific initialization
1254642e01fSmrg    return quartzProcs->AddScreen(index, pScreen);
1264642e01fSmrg}
1274642e01fSmrg
1284642e01fSmrg/*
1294642e01fSmrg * QuartzSetupScreen
1304642e01fSmrg *  Finalize mode specific setup of each screen.
1314642e01fSmrg */
13235c4bbdfSmrgBool
13335c4bbdfSmrgQuartzSetupScreen(int index,
13435c4bbdfSmrg                  ScreenPtr pScreen)
1354642e01fSmrg{
1364642e01fSmrg    // do Quartz mode specific setup
13735c4bbdfSmrg    if (!quartzProcs->SetupScreen(index, pScreen))
1384642e01fSmrg        return FALSE;
1394642e01fSmrg
1404642e01fSmrg    // setup cursor support
14135c4bbdfSmrg    if (!quartzProcs->InitCursor(pScreen))
1424642e01fSmrg        return FALSE;
1434642e01fSmrg
1446747b715Smrg#if defined(RANDR)
14535c4bbdfSmrg    if (!QuartzRandRInit(pScreen)) {
1466747b715Smrg        DEBUG_LOG("Failed to init RandR extension.\n");
1476747b715Smrg        return FALSE;
1486747b715Smrg    }
1496747b715Smrg#endif
1506747b715Smrg
1514642e01fSmrg    return TRUE;
1524642e01fSmrg}
1534642e01fSmrg
154c8548ba8Smrg/*
155c8548ba8Smrg * QuartzBlockHandler
156c8548ba8Smrg *  Clean out any autoreleased objects.
157c8548ba8Smrg */
158c8548ba8Smrgstatic void
159c8548ba8SmrgQuartzBlockHandler(void *blockData, void *pTimeout)
160c8548ba8Smrg{
161c8548ba8Smrg    static void *poolToken = NULL;
162c8548ba8Smrg
163c8548ba8Smrg    if (poolToken) {
164c8548ba8Smrg        objc_autoreleasePoolPop(poolToken);
165c8548ba8Smrg    }
166c8548ba8Smrg    poolToken = objc_autoreleasePoolPush();
167c8548ba8Smrg}
168c8548ba8Smrg
169c8548ba8Smrg/*
170c8548ba8Smrg * QuartzWakeupHandler
171c8548ba8Smrg */
172c8548ba8Smrgstatic void
173c8548ba8SmrgQuartzWakeupHandler(void *blockData, int result)
174c8548ba8Smrg{
175c8548ba8Smrg    /* nothing here */
176c8548ba8Smrg}
177c8548ba8Smrg
1784642e01fSmrg/*
1794642e01fSmrg * QuartzInitOutput
1804642e01fSmrg *  Quartz display initialization.
1814642e01fSmrg */
18235c4bbdfSmrgvoid
18335c4bbdfSmrgQuartzInitOutput(int argc,
18435c4bbdfSmrg                 char **argv)
1854642e01fSmrg{
1868223e2f2Smrg    /* For XQuartz, we want to just use the default signal handler to work better with CrashTracer */
1878223e2f2Smrg    signal(SIGSEGV, SIG_DFL);
1881b5d61b8Smrg    signal(SIGABRT, SIG_DFL);
1898223e2f2Smrg    signal(SIGILL, SIG_DFL);
1908223e2f2Smrg#ifdef SIGEMT
1918223e2f2Smrg    signal(SIGEMT, SIG_DFL);
1928223e2f2Smrg#endif
1938223e2f2Smrg    signal(SIGFPE, SIG_DFL);
1948223e2f2Smrg#ifdef SIGBUS
1958223e2f2Smrg    signal(SIGBUS, SIG_DFL);
1968223e2f2Smrg#endif
1978223e2f2Smrg#ifdef SIGSYS
1988223e2f2Smrg    signal(SIGSYS, SIG_DFL);
1998223e2f2Smrg#endif
2008223e2f2Smrg#ifdef SIGXCPU
2018223e2f2Smrg    signal(SIGXCPU, SIG_DFL);
2028223e2f2Smrg#endif
2038223e2f2Smrg#ifdef SIGXFSZ
2048223e2f2Smrg    signal(SIGXFSZ, SIG_DFL);
2058223e2f2Smrg#endif
2068223e2f2Smrg
2074642e01fSmrg    if (!RegisterBlockAndWakeupHandlers(QuartzBlockHandler,
2084642e01fSmrg                                        QuartzWakeupHandler,
20935c4bbdfSmrg                                        NULL)) {
2104642e01fSmrg        FatalError("Could not register block and wakeup handlers.");
2114642e01fSmrg    }
2124642e01fSmrg
2136747b715Smrg    if (!dixRegisterPrivateKey(&quartzScreenKeyRec, PRIVATE_SCREEN, 0))
21435c4bbdfSmrg        FatalError("Failed to alloc quartz screen private.\n");
2156747b715Smrg
2164642e01fSmrg    // Do display mode specific initialization
2174642e01fSmrg    quartzProcs->DisplayInit();
21835c4bbdfSmrg}
2194642e01fSmrg
2204642e01fSmrg/*
2214642e01fSmrg * QuartzInitInput
2224642e01fSmrg *  Inform the main thread the X server is ready to handle events.
2234642e01fSmrg */
22435c4bbdfSmrgvoid
22535c4bbdfSmrgQuartzInitInput(int argc,
22635c4bbdfSmrg                char **argv)
2274642e01fSmrg{
2286747b715Smrg    X11ApplicationSetCanQuit(0);
2294642e01fSmrg    X11ApplicationServerReady();
2304642e01fSmrg    // Do final display mode specific initialization before handling events
2314642e01fSmrg    if (quartzProcs->InitInput)
2324642e01fSmrg        quartzProcs->InitInput(argc, argv);
2334642e01fSmrg}
2344642e01fSmrg
23535c4bbdfSmrgvoid
23635c4bbdfSmrgQuartzUpdateScreens(void)
23735c4bbdfSmrg{
2384642e01fSmrg    ScreenPtr pScreen;
2394642e01fSmrg    WindowPtr pRoot;
2404642e01fSmrg    int x, y, width, height, sx, sy;
2414642e01fSmrg    xEvent e;
2426747b715Smrg    BoxRec bounds;
24335c4bbdfSmrg
24435c4bbdfSmrg    if (noPseudoramiXExtension || screenInfo.numScreens != 1) {
2454642e01fSmrg        /* FIXME: if not using Xinerama, we have multiple screens, and
24635c4bbdfSmrg           to do this properly may need to add or remove screens. Which
24735c4bbdfSmrg           isn't possible. So don't do anything. Another reason why
24835c4bbdfSmrg           we default to running with Xinerama. */
24935c4bbdfSmrg
2504642e01fSmrg        return;
2514642e01fSmrg    }
25235c4bbdfSmrg
2534642e01fSmrg    pScreen = screenInfo.screens[0];
25435c4bbdfSmrg
2554642e01fSmrg    PseudoramiXResetScreens();
2566747b715Smrg    quartzProcs->AddPseudoramiXScreens(&x, &y, &width, &height, pScreen);
25735c4bbdfSmrg
2586747b715Smrg    pScreen->x = x;
2596747b715Smrg    pScreen->y = y;
26035c4bbdfSmrg    pScreen->mmWidth = pScreen->mmWidth * ((double)width / pScreen->width);
26135c4bbdfSmrg    pScreen->mmHeight = pScreen->mmHeight * ((double)height / pScreen->height);
2624642e01fSmrg    pScreen->width = width;
2634642e01fSmrg    pScreen->height = height;
26435c4bbdfSmrg
2654642e01fSmrg    DarwinAdjustScreenOrigins(&screenInfo);
26635c4bbdfSmrg
2676747b715Smrg    /* DarwinAdjustScreenOrigins or UpdateScreen may change pScreen->x/y,
2686747b715Smrg     * so use it rather than x/y
2696747b715Smrg     */
2706747b715Smrg    sx = pScreen->x + darwinMainScreenX;
2716747b715Smrg    sy = pScreen->y + darwinMainScreenY;
27235c4bbdfSmrg
2734642e01fSmrg    /* Adjust the root window. */
2746747b715Smrg    pRoot = pScreen->root;
2754642e01fSmrg    AppleWMSetScreenOrigin(pRoot);
2764642e01fSmrg    pScreen->ResizeWindow(pRoot, x - sx, y - sy, width, height, NULL);
2776747b715Smrg
2786747b715Smrg    /* <rdar://problem/7770779> pointer events are clipped to old display region after display reconfiguration
2796747b715Smrg     * http://xquartz.macosforge.org/trac/ticket/346
2806747b715Smrg     */
2816747b715Smrg    bounds.x1 = 0;
2826747b715Smrg    bounds.x2 = width;
2836747b715Smrg    bounds.y1 = 0;
2846747b715Smrg    bounds.y2 = height;
2856747b715Smrg    pScreen->ConstrainCursor(inputInfo.pointer, pScreen, &bounds);
2866747b715Smrg    inputInfo.pointer->spriteInfo->sprite->physLimits = bounds;
2876747b715Smrg    inputInfo.pointer->spriteInfo->sprite->hotLimits = bounds;
2886747b715Smrg
28935c4bbdfSmrg    DEBUG_LOG(
29035c4bbdfSmrg        "Root Window: %dx%d @ (%d, %d) darwinMainScreen (%d, %d) xy (%d, %d) dixScreenOrigins (%d, %d)\n",
29135c4bbdfSmrg        width, height, x - sx, y - sy, darwinMainScreenX, darwinMainScreenY,
29235c4bbdfSmrg        x, y,
29335c4bbdfSmrg        pScreen->x, pScreen->y);
2944642e01fSmrg
2954642e01fSmrg    /* Send an event for the root reconfigure */
2964642e01fSmrg    e.u.u.type = ConfigureNotify;
2974642e01fSmrg    e.u.configureNotify.window = pRoot->drawable.id;
2984642e01fSmrg    e.u.configureNotify.aboveSibling = None;
2994642e01fSmrg    e.u.configureNotify.x = x - sx;
3004642e01fSmrg    e.u.configureNotify.y = y - sy;
3014642e01fSmrg    e.u.configureNotify.width = width;
3024642e01fSmrg    e.u.configureNotify.height = height;
3034642e01fSmrg    e.u.configureNotify.borderWidth = wBorderWidth(pRoot);
3044642e01fSmrg    e.u.configureNotify.override = pRoot->overrideRedirect;
3054642e01fSmrg    DeliverEvents(pRoot, &e, 1, NullWindow);
3064642e01fSmrg
3076747b715Smrg    quartzProcs->UpdateScreen(pScreen);
3088223e2f2Smrg
30935c4bbdfSmrg    /* PaintWindow needs to be called after RootlessUpdateScreenPixmap (from xprUpdateScreen) */
31035c4bbdfSmrg    pScreen->PaintWindow(pRoot, &pRoot->borderClip, PW_BACKGROUND);
3119ace9065Smrg
3128223e2f2Smrg    /* Tell RandR about the new size, so new connections get the correct info */
3138223e2f2Smrg    RRScreenSizeNotify(pScreen);
3148223e2f2Smrg}
3158223e2f2Smrg
31635c4bbdfSmrgstatic void
31735c4bbdfSmrgpokeActivityCallback(CFRunLoopTimerRef timer, void *info)
31835c4bbdfSmrg{
3198223e2f2Smrg    UpdateSystemActivity(OverallAct);
3208223e2f2Smrg}
3218223e2f2Smrg
32235c4bbdfSmrgstatic void
32335c4bbdfSmrgQuartzScreenSaver(int state)
32435c4bbdfSmrg{
3258223e2f2Smrg    static CFRunLoopTimerRef pokeActivityTimer = NULL;
32635c4bbdfSmrg    static CFRunLoopTimerContext pokeActivityContext =
32735c4bbdfSmrg    { 0, NULL, NULL, NULL, NULL };
32835c4bbdfSmrg    static OSSpinLock pokeActivitySpinLock = OS_SPINLOCK_INIT;
3298223e2f2Smrg
33035c4bbdfSmrg    OSSpinLockLock(&pokeActivitySpinLock);
33135c4bbdfSmrg
33235c4bbdfSmrg    if (state) {
33335c4bbdfSmrg        if (pokeActivityTimer == NULL)
3348223e2f2Smrg            goto QuartzScreenSaverEnd;
3358223e2f2Smrg
3368223e2f2Smrg        CFRunLoopTimerInvalidate(pokeActivityTimer);
3378223e2f2Smrg        CFRelease(pokeActivityTimer);
3388223e2f2Smrg        pokeActivityTimer = NULL;
33935c4bbdfSmrg    }
34035c4bbdfSmrg    else {
34135c4bbdfSmrg        if (pokeActivityTimer != NULL)
3428223e2f2Smrg            goto QuartzScreenSaverEnd;
34335c4bbdfSmrg
34435c4bbdfSmrg        pokeActivityTimer = CFRunLoopTimerCreate(NULL,
34535c4bbdfSmrg                                                 CFAbsoluteTimeGetCurrent(),
34635c4bbdfSmrg                                                 30, 0, 0,
34735c4bbdfSmrg                                                 pokeActivityCallback,
34835c4bbdfSmrg                                                 &pokeActivityContext);
34935c4bbdfSmrg        if (pokeActivityTimer == NULL) {
3508223e2f2Smrg            ErrorF("Unable to create pokeActivityTimer.\n");
3518223e2f2Smrg            goto QuartzScreenSaverEnd;
3528223e2f2Smrg        }
3538223e2f2Smrg
35435c4bbdfSmrg        CFRunLoopAddTimer(
35535c4bbdfSmrg            CFRunLoopGetMain(), pokeActivityTimer, kCFRunLoopCommonModes);
3568223e2f2Smrg    }
3578223e2f2SmrgQuartzScreenSaverEnd:
35835c4bbdfSmrg    OSSpinLockUnlock(&pokeActivitySpinLock);
3594642e01fSmrg}
3604642e01fSmrg
36135c4bbdfSmrgvoid
36235c4bbdfSmrgQuartzShowFullscreen(int state)
36335c4bbdfSmrg{
3646747b715Smrg    int i;
36535c4bbdfSmrg
3666747b715Smrg    DEBUG_LOG("QuartzShowFullscreen: state=%d\n", state);
36735c4bbdfSmrg
36835c4bbdfSmrg    if (XQuartzIsRootless) {
3696747b715Smrg        ErrorF("QuartzShowFullscreen called while in rootless mode.\n");
3706747b715Smrg        return;
3716747b715Smrg    }
37235c4bbdfSmrg
3738223e2f2Smrg    QuartzScreenSaver(!state);
37435c4bbdfSmrg
37535c4bbdfSmrg    if (XQuartzFullscreenVisible == state)
3764642e01fSmrg        return;
37735c4bbdfSmrg
3786747b715Smrg    XQuartzFullscreenVisible = state;
37935c4bbdfSmrg
38035c4bbdfSmrg    xp_disable_update();
38135c4bbdfSmrg
3826747b715Smrg    if (!XQuartzFullscreenVisible)
3834642e01fSmrg        RootlessHideAllWindows();
38435c4bbdfSmrg
3856747b715Smrg    RootlessUpdateRooted(XQuartzFullscreenVisible);
38635c4bbdfSmrg
3876747b715Smrg    if (XQuartzFullscreenVisible) {
38835c4bbdfSmrg        RootlessShowAllWindows();
38935c4bbdfSmrg        for (i = 0; i < screenInfo.numScreens; i++) {
39035c4bbdfSmrg            ScreenPtr pScreen = screenInfo.screens[i];
3916747b715Smrg            RootlessRepositionWindows(pScreen);
3926747b715Smrg            // JH: I don't think this is necessary, but keeping it here as a reminder
3936747b715Smrg            //RootlessUpdateScreenPixmap(pScreen);
3946747b715Smrg        }
3954642e01fSmrg    }
3964642e01fSmrg
3974642e01fSmrg    /* Somehow the menubar manages to interfere with our event stream
39835c4bbdfSmrg     * in fullscreen mode, even though it's not visible.
3994642e01fSmrg     */
4006747b715Smrg    X11ApplicationShowHideMenubar(!XQuartzFullscreenVisible);
40135c4bbdfSmrg
40235c4bbdfSmrg    xp_reenable_update();
40335c4bbdfSmrg
4046747b715Smrg    if (XQuartzFullscreenDisableHotkeys)
4056747b715Smrg        xp_disable_hot_keys(XQuartzFullscreenVisible);
4064642e01fSmrg}
4074642e01fSmrg
40835c4bbdfSmrgvoid
40935c4bbdfSmrgQuartzSetRootless(Bool state)
41035c4bbdfSmrg{
4116747b715Smrg    DEBUG_LOG("QuartzSetRootless state=%d\n", state);
41235c4bbdfSmrg
41335c4bbdfSmrg    if (XQuartzIsRootless == state)
4144642e01fSmrg        return;
41535c4bbdfSmrg
41635c4bbdfSmrg    if (state)
4176747b715Smrg        QuartzShowFullscreen(FALSE);
41835c4bbdfSmrg
4196747b715Smrg    XQuartzIsRootless = state;
4204642e01fSmrg
4214642e01fSmrg    xp_disable_update();
4224642e01fSmrg
42335c4bbdfSmrg    /* When in rootless, the menubar is not part of the screen, so we need to update our screens on toggle */
4244642e01fSmrg    QuartzUpdateScreens();
4254642e01fSmrg
42635c4bbdfSmrg    if (XQuartzIsRootless) {
4274642e01fSmrg        RootlessShowAllWindows();
42835c4bbdfSmrg    }
42935c4bbdfSmrg    else {
4306747b715Smrg        RootlessHideAllWindows();
4314642e01fSmrg    }
4324642e01fSmrg
4336747b715Smrg    X11ApplicationShowHideMenubar(TRUE);
4346747b715Smrg
4354642e01fSmrg    xp_reenable_update();
4366747b715Smrg
4376747b715Smrg    xp_disable_hot_keys(FALSE);
4384642e01fSmrg}
4394642e01fSmrg
4404642e01fSmrg/*
4414642e01fSmrg * QuartzShow
4424642e01fSmrg *  Show the X server on screen. Does nothing if already shown.
4434642e01fSmrg *  Calls mode specific screen resume to restore the X clip regions
4444642e01fSmrg *  (if needed) and the X server cursor state.
4454642e01fSmrg */
44635c4bbdfSmrgvoid
44735c4bbdfSmrgQuartzShow(void)
44835c4bbdfSmrg{
4494642e01fSmrg    int i;
4504642e01fSmrg
4516747b715Smrg    if (XQuartzServerVisible)
4524642e01fSmrg        return;
45335c4bbdfSmrg
4546747b715Smrg    XQuartzServerVisible = TRUE;
4554642e01fSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
4564642e01fSmrg        if (screenInfo.screens[i]) {
4576747b715Smrg            quartzProcs->ResumeScreen(screenInfo.screens[i]);
4584642e01fSmrg        }
4594642e01fSmrg    }
46035c4bbdfSmrg
4616747b715Smrg    if (!XQuartzIsRootless)
4626747b715Smrg        QuartzShowFullscreen(TRUE);
4634642e01fSmrg}
4644642e01fSmrg
4654642e01fSmrg/*
4664642e01fSmrg * QuartzHide
4674642e01fSmrg *  Remove the X server display from the screen. Does nothing if already
4684642e01fSmrg *  hidden. Calls mode specific screen suspend to set X clip regions to
4694642e01fSmrg *  prevent drawing (if needed) and restore the Aqua cursor.
4704642e01fSmrg */
47135c4bbdfSmrgvoid
47235c4bbdfSmrgQuartzHide(void)
4734642e01fSmrg{
4744642e01fSmrg    int i;
4754642e01fSmrg
4766747b715Smrg    if (XQuartzServerVisible) {
4774642e01fSmrg        for (i = 0; i < screenInfo.numScreens; i++) {
4784642e01fSmrg            if (screenInfo.screens[i]) {
4794642e01fSmrg                quartzProcs->SuspendScreen(screenInfo.screens[i]);
4804642e01fSmrg            }
4814642e01fSmrg        }
4824642e01fSmrg    }
4836747b715Smrg
48435c4bbdfSmrg    if (!XQuartzIsRootless)
4856747b715Smrg        QuartzShowFullscreen(FALSE);
4866747b715Smrg    XQuartzServerVisible = FALSE;
4874642e01fSmrg}
4884642e01fSmrg
4894642e01fSmrg/*
4904642e01fSmrg * QuartzSetRootClip
4914642e01fSmrg *  Enable or disable rendering to the X screen.
4924642e01fSmrg */
49335c4bbdfSmrgvoid
49435c4bbdfSmrgQuartzSetRootClip(int mode)
4954642e01fSmrg{
4964642e01fSmrg    int i;
4974642e01fSmrg
4986747b715Smrg    if (!XQuartzServerVisible)
4994642e01fSmrg        return;
5004642e01fSmrg
5014642e01fSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
5024642e01fSmrg        if (screenInfo.screens[i]) {
50335c4bbdfSmrg            SetRootClip(screenInfo.screens[i], mode);
5044642e01fSmrg        }
5054642e01fSmrg    }
5064642e01fSmrg}
5074642e01fSmrg
50835c4bbdfSmrg/*
5094642e01fSmrg * QuartzSpaceChanged
5104642e01fSmrg *  Unmap offscreen windows, map onscreen windows
5114642e01fSmrg */
51235c4bbdfSmrgvoid
51335c4bbdfSmrgQuartzSpaceChanged(uint32_t space_id)
51435c4bbdfSmrg{
5154642e01fSmrg    /* Do something special here, so we don't depend on quartz-wm for spaces to work... */
51635c4bbdfSmrg    DEBUG_LOG("Space Changed (%u) ... do something interesting...\n",
51735c4bbdfSmrg              space_id);
5184642e01fSmrg}
5196747b715Smrg
5206747b715Smrg/*
5216747b715Smrg * QuartzCopyDisplayIDs
5226747b715Smrg *  Associate an X11 screen with one or more CoreGraphics display IDs by copying
5236747b715Smrg *  the list into a private array. Free the previously copied array, if present.
5246747b715Smrg */
52535c4bbdfSmrgvoid
52635c4bbdfSmrgQuartzCopyDisplayIDs(ScreenPtr pScreen,
52735c4bbdfSmrg                     int displayCount, CGDirectDisplayID *displayIDs)
52835c4bbdfSmrg{
5296747b715Smrg    QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
5306747b715Smrg
5316747b715Smrg    free(pQuartzScreen->displayIDs);
53235c4bbdfSmrg    if (displayCount) {
5339ace9065Smrg        size_t size = displayCount * sizeof(CGDirectDisplayID);
5349ace9065Smrg        pQuartzScreen->displayIDs = malloc(size);
5359ace9065Smrg        memcpy(pQuartzScreen->displayIDs, displayIDs, size);
53635c4bbdfSmrg    }
53735c4bbdfSmrg    else {
53835c4bbdfSmrg        pQuartzScreen->displayIDs = NULL;
5399ace9065Smrg    }
5406747b715Smrg    pQuartzScreen->displayCount = displayCount;
5416747b715Smrg}
5428223e2f2Smrg
54335c4bbdfSmrgvoid
54435c4bbdfSmrgNSBeep(void);
54535c4bbdfSmrgvoid
54635c4bbdfSmrgDDXRingBell(int volume,              // volume is % of max
54735c4bbdfSmrg            int pitch,               // pitch is Hz
54835c4bbdfSmrg            int duration)            // duration is milliseconds
5498223e2f2Smrg{
5508223e2f2Smrg    if (volume)
5518223e2f2Smrg        NSBeep();
5528223e2f2Smrg}
553