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
88dc61d50dSmrg/* These are initialized by X11Application with default values set in NSUserDefaults+XQuartzDefaults */
89dc61d50dSmrgBool XQuartzFullscreenDisableHotkeys;
90dc61d50dSmrgBool XQuartzOptionSendsAlt;
91dc61d50dSmrgBool XQuartzEnableKeyEquivalents;
92dc61d50dSmrgBool XQuartzFullscreenMenu;
93dc61d50dSmrgBool XQuartzRootlessDefault;
94dc61d50dSmrg
956747b715SmrgBool XQuartzFullscreenVisible = FALSE;
966747b715SmrgBool XQuartzIsRootless = TRUE;
976747b715SmrgBool XQuartzServerVisible = FALSE;
988223e2f2Smrg
998223e2f2Smrgint32_t XQuartzShieldingWindowLevel = 0;
1004642e01fSmrg
1014642e01fSmrg/*
10235c4bbdfSmrg   ===========================================================================
1034642e01fSmrg
10435c4bbdfSmrg   Screen functions
1054642e01fSmrg
10635c4bbdfSmrg   ===========================================================================
10735c4bbdfSmrg */
1084642e01fSmrg
1094642e01fSmrg/*
1104642e01fSmrg * QuartzAddScreen
1114642e01fSmrg *  Do mode dependent initialization of each screen for Quartz.
1124642e01fSmrg */
11335c4bbdfSmrgBool
11435c4bbdfSmrgQuartzAddScreen(int index,
11535c4bbdfSmrg                ScreenPtr pScreen)
1164642e01fSmrg{
11735c4bbdfSmrg    // The clang static analyzer thinks we leak displayInfo here
11835c4bbdfSmrg#ifndef __clang_analyzer__
1194642e01fSmrg    // allocate space for private per screen Quartz specific storage
1206747b715Smrg    QuartzScreenPtr displayInfo = calloc(sizeof(QuartzScreenRec), 1);
1214642e01fSmrg
1224642e01fSmrg    // QUARTZ_PRIV(pScreen) = displayInfo;
1234642e01fSmrg    dixSetPrivate(&pScreen->devPrivates, quartzScreenKey, displayInfo);
12435c4bbdfSmrg#endif /* __clang_analyzer__ */
1254642e01fSmrg
1264642e01fSmrg    // do Quartz mode specific initialization
1274642e01fSmrg    return quartzProcs->AddScreen(index, pScreen);
1284642e01fSmrg}
1294642e01fSmrg
1304642e01fSmrg/*
1314642e01fSmrg * QuartzSetupScreen
1324642e01fSmrg *  Finalize mode specific setup of each screen.
1334642e01fSmrg */
13435c4bbdfSmrgBool
13535c4bbdfSmrgQuartzSetupScreen(int index,
13635c4bbdfSmrg                  ScreenPtr pScreen)
1374642e01fSmrg{
1384642e01fSmrg    // do Quartz mode specific setup
13935c4bbdfSmrg    if (!quartzProcs->SetupScreen(index, pScreen))
1404642e01fSmrg        return FALSE;
1414642e01fSmrg
1424642e01fSmrg    // setup cursor support
14335c4bbdfSmrg    if (!quartzProcs->InitCursor(pScreen))
1444642e01fSmrg        return FALSE;
1454642e01fSmrg
1466747b715Smrg#if defined(RANDR)
14735c4bbdfSmrg    if (!QuartzRandRInit(pScreen)) {
1486747b715Smrg        DEBUG_LOG("Failed to init RandR extension.\n");
1496747b715Smrg        return FALSE;
1506747b715Smrg    }
1516747b715Smrg#endif
1526747b715Smrg
1534642e01fSmrg    return TRUE;
1544642e01fSmrg}
1554642e01fSmrg
156c8548ba8Smrg/*
157c8548ba8Smrg * QuartzBlockHandler
158c8548ba8Smrg *  Clean out any autoreleased objects.
159c8548ba8Smrg */
160c8548ba8Smrgstatic void
161c8548ba8SmrgQuartzBlockHandler(void *blockData, void *pTimeout)
162c8548ba8Smrg{
163c8548ba8Smrg    static void *poolToken = NULL;
164c8548ba8Smrg
165c8548ba8Smrg    if (poolToken) {
166c8548ba8Smrg        objc_autoreleasePoolPop(poolToken);
167c8548ba8Smrg    }
168c8548ba8Smrg    poolToken = objc_autoreleasePoolPush();
169c8548ba8Smrg}
170c8548ba8Smrg
171c8548ba8Smrg/*
172c8548ba8Smrg * QuartzWakeupHandler
173c8548ba8Smrg */
174c8548ba8Smrgstatic void
175c8548ba8SmrgQuartzWakeupHandler(void *blockData, int result)
176c8548ba8Smrg{
177c8548ba8Smrg    /* nothing here */
178c8548ba8Smrg}
179c8548ba8Smrg
1804642e01fSmrg/*
1814642e01fSmrg * QuartzInitOutput
1824642e01fSmrg *  Quartz display initialization.
1834642e01fSmrg */
18435c4bbdfSmrgvoid
18535c4bbdfSmrgQuartzInitOutput(int argc,
18635c4bbdfSmrg                 char **argv)
1874642e01fSmrg{
1888223e2f2Smrg    /* For XQuartz, we want to just use the default signal handler to work better with CrashTracer */
1898223e2f2Smrg    signal(SIGSEGV, SIG_DFL);
1901b5d61b8Smrg    signal(SIGABRT, SIG_DFL);
1918223e2f2Smrg    signal(SIGILL, SIG_DFL);
1928223e2f2Smrg#ifdef SIGEMT
1938223e2f2Smrg    signal(SIGEMT, SIG_DFL);
1948223e2f2Smrg#endif
1958223e2f2Smrg    signal(SIGFPE, SIG_DFL);
1968223e2f2Smrg#ifdef SIGBUS
1978223e2f2Smrg    signal(SIGBUS, SIG_DFL);
1988223e2f2Smrg#endif
1998223e2f2Smrg#ifdef SIGSYS
2008223e2f2Smrg    signal(SIGSYS, SIG_DFL);
2018223e2f2Smrg#endif
2028223e2f2Smrg#ifdef SIGXCPU
2038223e2f2Smrg    signal(SIGXCPU, SIG_DFL);
2048223e2f2Smrg#endif
2058223e2f2Smrg#ifdef SIGXFSZ
2068223e2f2Smrg    signal(SIGXFSZ, SIG_DFL);
2078223e2f2Smrg#endif
2088223e2f2Smrg
2094642e01fSmrg    if (!RegisterBlockAndWakeupHandlers(QuartzBlockHandler,
2104642e01fSmrg                                        QuartzWakeupHandler,
21135c4bbdfSmrg                                        NULL)) {
2124642e01fSmrg        FatalError("Could not register block and wakeup handlers.");
2134642e01fSmrg    }
2144642e01fSmrg
2156747b715Smrg    if (!dixRegisterPrivateKey(&quartzScreenKeyRec, PRIVATE_SCREEN, 0))
21635c4bbdfSmrg        FatalError("Failed to alloc quartz screen private.\n");
2176747b715Smrg
2184642e01fSmrg    // Do display mode specific initialization
2194642e01fSmrg    quartzProcs->DisplayInit();
22035c4bbdfSmrg}
2214642e01fSmrg
2224642e01fSmrg/*
2234642e01fSmrg * QuartzInitInput
2244642e01fSmrg *  Inform the main thread the X server is ready to handle events.
2254642e01fSmrg */
22635c4bbdfSmrgvoid
22735c4bbdfSmrgQuartzInitInput(int argc,
22835c4bbdfSmrg                char **argv)
2294642e01fSmrg{
2306747b715Smrg    X11ApplicationSetCanQuit(0);
2314642e01fSmrg    X11ApplicationServerReady();
2324642e01fSmrg    // Do final display mode specific initialization before handling events
2334642e01fSmrg    if (quartzProcs->InitInput)
2344642e01fSmrg        quartzProcs->InitInput(argc, argv);
2354642e01fSmrg}
2364642e01fSmrg
23735c4bbdfSmrgvoid
23835c4bbdfSmrgQuartzUpdateScreens(void)
23935c4bbdfSmrg{
2404642e01fSmrg    ScreenPtr pScreen;
2414642e01fSmrg    WindowPtr pRoot;
2424642e01fSmrg    int x, y, width, height, sx, sy;
2434642e01fSmrg    xEvent e;
2446747b715Smrg    BoxRec bounds;
24535c4bbdfSmrg
24635c4bbdfSmrg    if (noPseudoramiXExtension || screenInfo.numScreens != 1) {
2474642e01fSmrg        /* FIXME: if not using Xinerama, we have multiple screens, and
24835c4bbdfSmrg           to do this properly may need to add or remove screens. Which
24935c4bbdfSmrg           isn't possible. So don't do anything. Another reason why
25035c4bbdfSmrg           we default to running with Xinerama. */
25135c4bbdfSmrg
2524642e01fSmrg        return;
2534642e01fSmrg    }
25435c4bbdfSmrg
2554642e01fSmrg    pScreen = screenInfo.screens[0];
25635c4bbdfSmrg
2574642e01fSmrg    PseudoramiXResetScreens();
2586747b715Smrg    quartzProcs->AddPseudoramiXScreens(&x, &y, &width, &height, pScreen);
25935c4bbdfSmrg
2606747b715Smrg    pScreen->x = x;
2616747b715Smrg    pScreen->y = y;
26235c4bbdfSmrg    pScreen->mmWidth = pScreen->mmWidth * ((double)width / pScreen->width);
26335c4bbdfSmrg    pScreen->mmHeight = pScreen->mmHeight * ((double)height / pScreen->height);
2644642e01fSmrg    pScreen->width = width;
2654642e01fSmrg    pScreen->height = height;
26635c4bbdfSmrg
2674642e01fSmrg    DarwinAdjustScreenOrigins(&screenInfo);
26835c4bbdfSmrg
2696747b715Smrg    /* DarwinAdjustScreenOrigins or UpdateScreen may change pScreen->x/y,
2706747b715Smrg     * so use it rather than x/y
2716747b715Smrg     */
2726747b715Smrg    sx = pScreen->x + darwinMainScreenX;
2736747b715Smrg    sy = pScreen->y + darwinMainScreenY;
27435c4bbdfSmrg
2754642e01fSmrg    /* Adjust the root window. */
2766747b715Smrg    pRoot = pScreen->root;
2774642e01fSmrg    AppleWMSetScreenOrigin(pRoot);
2784642e01fSmrg    pScreen->ResizeWindow(pRoot, x - sx, y - sy, width, height, NULL);
2796747b715Smrg
2806747b715Smrg    /* <rdar://problem/7770779> pointer events are clipped to old display region after display reconfiguration
2816747b715Smrg     * http://xquartz.macosforge.org/trac/ticket/346
2826747b715Smrg     */
2836747b715Smrg    bounds.x1 = 0;
2846747b715Smrg    bounds.x2 = width;
2856747b715Smrg    bounds.y1 = 0;
2866747b715Smrg    bounds.y2 = height;
2876747b715Smrg    pScreen->ConstrainCursor(inputInfo.pointer, pScreen, &bounds);
2886747b715Smrg    inputInfo.pointer->spriteInfo->sprite->physLimits = bounds;
2896747b715Smrg    inputInfo.pointer->spriteInfo->sprite->hotLimits = bounds;
2906747b715Smrg
29135c4bbdfSmrg    DEBUG_LOG(
29235c4bbdfSmrg        "Root Window: %dx%d @ (%d, %d) darwinMainScreen (%d, %d) xy (%d, %d) dixScreenOrigins (%d, %d)\n",
29335c4bbdfSmrg        width, height, x - sx, y - sy, darwinMainScreenX, darwinMainScreenY,
29435c4bbdfSmrg        x, y,
29535c4bbdfSmrg        pScreen->x, pScreen->y);
2964642e01fSmrg
2974642e01fSmrg    /* Send an event for the root reconfigure */
2984642e01fSmrg    e.u.u.type = ConfigureNotify;
2994642e01fSmrg    e.u.configureNotify.window = pRoot->drawable.id;
3004642e01fSmrg    e.u.configureNotify.aboveSibling = None;
3014642e01fSmrg    e.u.configureNotify.x = x - sx;
3024642e01fSmrg    e.u.configureNotify.y = y - sy;
3034642e01fSmrg    e.u.configureNotify.width = width;
3044642e01fSmrg    e.u.configureNotify.height = height;
3054642e01fSmrg    e.u.configureNotify.borderWidth = wBorderWidth(pRoot);
3064642e01fSmrg    e.u.configureNotify.override = pRoot->overrideRedirect;
3074642e01fSmrg    DeliverEvents(pRoot, &e, 1, NullWindow);
3084642e01fSmrg
3096747b715Smrg    quartzProcs->UpdateScreen(pScreen);
3108223e2f2Smrg
31135c4bbdfSmrg    /* PaintWindow needs to be called after RootlessUpdateScreenPixmap (from xprUpdateScreen) */
31235c4bbdfSmrg    pScreen->PaintWindow(pRoot, &pRoot->borderClip, PW_BACKGROUND);
3139ace9065Smrg
3148223e2f2Smrg    /* Tell RandR about the new size, so new connections get the correct info */
3158223e2f2Smrg    RRScreenSizeNotify(pScreen);
3168223e2f2Smrg}
3178223e2f2Smrg
31835c4bbdfSmrgstatic void
31935c4bbdfSmrgpokeActivityCallback(CFRunLoopTimerRef timer, void *info)
32035c4bbdfSmrg{
3218223e2f2Smrg    UpdateSystemActivity(OverallAct);
3228223e2f2Smrg}
3238223e2f2Smrg
32435c4bbdfSmrgstatic void
32535c4bbdfSmrgQuartzScreenSaver(int state)
32635c4bbdfSmrg{
3278223e2f2Smrg    static CFRunLoopTimerRef pokeActivityTimer = NULL;
32835c4bbdfSmrg    static CFRunLoopTimerContext pokeActivityContext =
32935c4bbdfSmrg    { 0, NULL, NULL, NULL, NULL };
33035c4bbdfSmrg    static OSSpinLock pokeActivitySpinLock = OS_SPINLOCK_INIT;
3318223e2f2Smrg
33235c4bbdfSmrg    OSSpinLockLock(&pokeActivitySpinLock);
33335c4bbdfSmrg
33435c4bbdfSmrg    if (state) {
33535c4bbdfSmrg        if (pokeActivityTimer == NULL)
3368223e2f2Smrg            goto QuartzScreenSaverEnd;
3378223e2f2Smrg
3388223e2f2Smrg        CFRunLoopTimerInvalidate(pokeActivityTimer);
3398223e2f2Smrg        CFRelease(pokeActivityTimer);
3408223e2f2Smrg        pokeActivityTimer = NULL;
34135c4bbdfSmrg    }
34235c4bbdfSmrg    else {
34335c4bbdfSmrg        if (pokeActivityTimer != NULL)
3448223e2f2Smrg            goto QuartzScreenSaverEnd;
34535c4bbdfSmrg
34635c4bbdfSmrg        pokeActivityTimer = CFRunLoopTimerCreate(NULL,
34735c4bbdfSmrg                                                 CFAbsoluteTimeGetCurrent(),
34835c4bbdfSmrg                                                 30, 0, 0,
34935c4bbdfSmrg                                                 pokeActivityCallback,
35035c4bbdfSmrg                                                 &pokeActivityContext);
35135c4bbdfSmrg        if (pokeActivityTimer == NULL) {
3528223e2f2Smrg            ErrorF("Unable to create pokeActivityTimer.\n");
3538223e2f2Smrg            goto QuartzScreenSaverEnd;
3548223e2f2Smrg        }
3558223e2f2Smrg
35635c4bbdfSmrg        CFRunLoopAddTimer(
35735c4bbdfSmrg            CFRunLoopGetMain(), pokeActivityTimer, kCFRunLoopCommonModes);
3588223e2f2Smrg    }
3598223e2f2SmrgQuartzScreenSaverEnd:
36035c4bbdfSmrg    OSSpinLockUnlock(&pokeActivitySpinLock);
3614642e01fSmrg}
3624642e01fSmrg
36335c4bbdfSmrgvoid
36435c4bbdfSmrgQuartzShowFullscreen(int state)
36535c4bbdfSmrg{
3666747b715Smrg    int i;
36735c4bbdfSmrg
3686747b715Smrg    DEBUG_LOG("QuartzShowFullscreen: state=%d\n", state);
36935c4bbdfSmrg
37035c4bbdfSmrg    if (XQuartzIsRootless) {
3716747b715Smrg        ErrorF("QuartzShowFullscreen called while in rootless mode.\n");
3726747b715Smrg        return;
3736747b715Smrg    }
37435c4bbdfSmrg
3758223e2f2Smrg    QuartzScreenSaver(!state);
37635c4bbdfSmrg
37735c4bbdfSmrg    if (XQuartzFullscreenVisible == state)
3784642e01fSmrg        return;
37935c4bbdfSmrg
3806747b715Smrg    XQuartzFullscreenVisible = state;
38135c4bbdfSmrg
38235c4bbdfSmrg    xp_disable_update();
38335c4bbdfSmrg
3846747b715Smrg    if (!XQuartzFullscreenVisible)
3854642e01fSmrg        RootlessHideAllWindows();
38635c4bbdfSmrg
3876747b715Smrg    RootlessUpdateRooted(XQuartzFullscreenVisible);
38835c4bbdfSmrg
3896747b715Smrg    if (XQuartzFullscreenVisible) {
39035c4bbdfSmrg        RootlessShowAllWindows();
39135c4bbdfSmrg        for (i = 0; i < screenInfo.numScreens; i++) {
39235c4bbdfSmrg            ScreenPtr pScreen = screenInfo.screens[i];
3936747b715Smrg            RootlessRepositionWindows(pScreen);
3946747b715Smrg            // JH: I don't think this is necessary, but keeping it here as a reminder
3956747b715Smrg            //RootlessUpdateScreenPixmap(pScreen);
3966747b715Smrg        }
3974642e01fSmrg    }
3984642e01fSmrg
3994642e01fSmrg    /* Somehow the menubar manages to interfere with our event stream
40035c4bbdfSmrg     * in fullscreen mode, even though it's not visible.
4014642e01fSmrg     */
4026747b715Smrg    X11ApplicationShowHideMenubar(!XQuartzFullscreenVisible);
40335c4bbdfSmrg
40435c4bbdfSmrg    xp_reenable_update();
40535c4bbdfSmrg
4066747b715Smrg    if (XQuartzFullscreenDisableHotkeys)
4076747b715Smrg        xp_disable_hot_keys(XQuartzFullscreenVisible);
4084642e01fSmrg}
4094642e01fSmrg
41035c4bbdfSmrgvoid
41135c4bbdfSmrgQuartzSetRootless(Bool state)
41235c4bbdfSmrg{
4136747b715Smrg    DEBUG_LOG("QuartzSetRootless state=%d\n", state);
41435c4bbdfSmrg
41535c4bbdfSmrg    if (XQuartzIsRootless == state)
4164642e01fSmrg        return;
41735c4bbdfSmrg
41835c4bbdfSmrg    if (state)
4196747b715Smrg        QuartzShowFullscreen(FALSE);
42035c4bbdfSmrg
4216747b715Smrg    XQuartzIsRootless = state;
4224642e01fSmrg
4234642e01fSmrg    xp_disable_update();
4244642e01fSmrg
42535c4bbdfSmrg    /* When in rootless, the menubar is not part of the screen, so we need to update our screens on toggle */
4264642e01fSmrg    QuartzUpdateScreens();
4274642e01fSmrg
42835c4bbdfSmrg    if (XQuartzIsRootless) {
4294642e01fSmrg        RootlessShowAllWindows();
43035c4bbdfSmrg    }
43135c4bbdfSmrg    else {
4326747b715Smrg        RootlessHideAllWindows();
4334642e01fSmrg    }
4344642e01fSmrg
4356747b715Smrg    X11ApplicationShowHideMenubar(TRUE);
4366747b715Smrg
4374642e01fSmrg    xp_reenable_update();
4386747b715Smrg
4396747b715Smrg    xp_disable_hot_keys(FALSE);
4404642e01fSmrg}
4414642e01fSmrg
4424642e01fSmrg/*
4434642e01fSmrg * QuartzShow
4444642e01fSmrg *  Show the X server on screen. Does nothing if already shown.
4454642e01fSmrg *  Calls mode specific screen resume to restore the X clip regions
4464642e01fSmrg *  (if needed) and the X server cursor state.
4474642e01fSmrg */
44835c4bbdfSmrgvoid
44935c4bbdfSmrgQuartzShow(void)
45035c4bbdfSmrg{
4514642e01fSmrg    int i;
4524642e01fSmrg
4536747b715Smrg    if (XQuartzServerVisible)
4544642e01fSmrg        return;
45535c4bbdfSmrg
4566747b715Smrg    XQuartzServerVisible = TRUE;
4574642e01fSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
4584642e01fSmrg        if (screenInfo.screens[i]) {
4596747b715Smrg            quartzProcs->ResumeScreen(screenInfo.screens[i]);
4604642e01fSmrg        }
4614642e01fSmrg    }
46235c4bbdfSmrg
4636747b715Smrg    if (!XQuartzIsRootless)
4646747b715Smrg        QuartzShowFullscreen(TRUE);
4654642e01fSmrg}
4664642e01fSmrg
4674642e01fSmrg/*
4684642e01fSmrg * QuartzHide
4694642e01fSmrg *  Remove the X server display from the screen. Does nothing if already
4704642e01fSmrg *  hidden. Calls mode specific screen suspend to set X clip regions to
4714642e01fSmrg *  prevent drawing (if needed) and restore the Aqua cursor.
4724642e01fSmrg */
47335c4bbdfSmrgvoid
47435c4bbdfSmrgQuartzHide(void)
4754642e01fSmrg{
4764642e01fSmrg    int i;
4774642e01fSmrg
4786747b715Smrg    if (XQuartzServerVisible) {
4794642e01fSmrg        for (i = 0; i < screenInfo.numScreens; i++) {
4804642e01fSmrg            if (screenInfo.screens[i]) {
4814642e01fSmrg                quartzProcs->SuspendScreen(screenInfo.screens[i]);
4824642e01fSmrg            }
4834642e01fSmrg        }
4844642e01fSmrg    }
4856747b715Smrg
48635c4bbdfSmrg    if (!XQuartzIsRootless)
4876747b715Smrg        QuartzShowFullscreen(FALSE);
4886747b715Smrg    XQuartzServerVisible = FALSE;
4894642e01fSmrg}
4904642e01fSmrg
4914642e01fSmrg/*
4924642e01fSmrg * QuartzSetRootClip
4934642e01fSmrg *  Enable or disable rendering to the X screen.
4944642e01fSmrg */
49535c4bbdfSmrgvoid
49635c4bbdfSmrgQuartzSetRootClip(int mode)
4974642e01fSmrg{
4984642e01fSmrg    int i;
4994642e01fSmrg
5006747b715Smrg    if (!XQuartzServerVisible)
5014642e01fSmrg        return;
5024642e01fSmrg
5034642e01fSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
5044642e01fSmrg        if (screenInfo.screens[i]) {
50535c4bbdfSmrg            SetRootClip(screenInfo.screens[i], mode);
5064642e01fSmrg        }
5074642e01fSmrg    }
5084642e01fSmrg}
5094642e01fSmrg
51035c4bbdfSmrg/*
5114642e01fSmrg * QuartzSpaceChanged
5124642e01fSmrg *  Unmap offscreen windows, map onscreen windows
5134642e01fSmrg */
51435c4bbdfSmrgvoid
51535c4bbdfSmrgQuartzSpaceChanged(uint32_t space_id)
51635c4bbdfSmrg{
5174642e01fSmrg    /* Do something special here, so we don't depend on quartz-wm for spaces to work... */
51835c4bbdfSmrg    DEBUG_LOG("Space Changed (%u) ... do something interesting...\n",
51935c4bbdfSmrg              space_id);
5204642e01fSmrg}
5216747b715Smrg
5226747b715Smrg/*
5236747b715Smrg * QuartzCopyDisplayIDs
5246747b715Smrg *  Associate an X11 screen with one or more CoreGraphics display IDs by copying
5256747b715Smrg *  the list into a private array. Free the previously copied array, if present.
5266747b715Smrg */
52735c4bbdfSmrgvoid
52835c4bbdfSmrgQuartzCopyDisplayIDs(ScreenPtr pScreen,
52935c4bbdfSmrg                     int displayCount, CGDirectDisplayID *displayIDs)
53035c4bbdfSmrg{
5316747b715Smrg    QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen);
5326747b715Smrg
5336747b715Smrg    free(pQuartzScreen->displayIDs);
53435c4bbdfSmrg    if (displayCount) {
5359ace9065Smrg        size_t size = displayCount * sizeof(CGDirectDisplayID);
5369ace9065Smrg        pQuartzScreen->displayIDs = malloc(size);
5379ace9065Smrg        memcpy(pQuartzScreen->displayIDs, displayIDs, size);
53835c4bbdfSmrg    }
53935c4bbdfSmrg    else {
54035c4bbdfSmrg        pQuartzScreen->displayIDs = NULL;
5419ace9065Smrg    }
5426747b715Smrg    pQuartzScreen->displayCount = displayCount;
5436747b715Smrg}
5448223e2f2Smrg
54535c4bbdfSmrgvoid
54635c4bbdfSmrgNSBeep(void);
54735c4bbdfSmrgvoid
54835c4bbdfSmrgDDXRingBell(int volume,              // volume is % of max
54935c4bbdfSmrg            int pitch,               // pitch is Hz
55035c4bbdfSmrg            int duration)            // duration is milliseconds
5518223e2f2Smrg{
5528223e2f2Smrg    if (volume)
5538223e2f2Smrg        NSBeep();
5548223e2f2Smrg}
555