quartz.c revision 6747b715
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> 654642e01fSmrg 664642e01fSmrg#include <rootlessCommon.h> 674642e01fSmrg#include <Xplugin.h> 684642e01fSmrg 696747b715SmrgDevPrivateKeyRec quartzScreenKeyRec; 704642e01fSmrgint aquaMenuBarHeight = 0; 714642e01fSmrgQuartzModeProcsPtr quartzProcs = NULL; 724642e01fSmrgconst char *quartzOpenGLBundle = NULL; 734642e01fSmrg 746747b715SmrgBool XQuartzFullscreenDisableHotkeys = TRUE; 756747b715SmrgBool XQuartzOptionSendsAlt = FALSE; 766747b715SmrgBool XQuartzEnableKeyEquivalents = TRUE; 776747b715SmrgBool XQuartzFullscreenVisible = FALSE; 786747b715SmrgBool XQuartzRootlessDefault = TRUE; 796747b715SmrgBool XQuartzIsRootless = TRUE; 806747b715SmrgBool XQuartzServerVisible = FALSE; 816747b715SmrgBool XQuartzFullscreenMenu = FALSE; 826747b715SmrgBool XQuartzUseSysBeep = FALSE; 834642e01fSmrg 844642e01fSmrg/* 854642e01fSmrg=========================================================================== 864642e01fSmrg 874642e01fSmrg Screen functions 884642e01fSmrg 894642e01fSmrg=========================================================================== 904642e01fSmrg*/ 914642e01fSmrg 924642e01fSmrg/* 934642e01fSmrg * QuartzAddScreen 944642e01fSmrg * Do mode dependent initialization of each screen for Quartz. 954642e01fSmrg */ 964642e01fSmrgBool QuartzAddScreen( 974642e01fSmrg int index, 984642e01fSmrg ScreenPtr pScreen) 994642e01fSmrg{ 1004642e01fSmrg // allocate space for private per screen Quartz specific storage 1016747b715Smrg QuartzScreenPtr displayInfo = calloc(sizeof(QuartzScreenRec), 1); 1024642e01fSmrg 1034642e01fSmrg // QUARTZ_PRIV(pScreen) = displayInfo; 1044642e01fSmrg dixSetPrivate(&pScreen->devPrivates, quartzScreenKey, displayInfo); 1054642e01fSmrg 1064642e01fSmrg // do Quartz mode specific initialization 1074642e01fSmrg return quartzProcs->AddScreen(index, pScreen); 1084642e01fSmrg} 1094642e01fSmrg 1104642e01fSmrg 1114642e01fSmrg/* 1124642e01fSmrg * QuartzSetupScreen 1134642e01fSmrg * Finalize mode specific setup of each screen. 1144642e01fSmrg */ 1154642e01fSmrgBool QuartzSetupScreen( 1164642e01fSmrg int index, 1174642e01fSmrg ScreenPtr pScreen) 1184642e01fSmrg{ 1194642e01fSmrg // do Quartz mode specific setup 1204642e01fSmrg if (! quartzProcs->SetupScreen(index, pScreen)) 1214642e01fSmrg return FALSE; 1224642e01fSmrg 1234642e01fSmrg // setup cursor support 1244642e01fSmrg if (! quartzProcs->InitCursor(pScreen)) 1254642e01fSmrg return FALSE; 1264642e01fSmrg 1276747b715Smrg#if defined(RANDR) 1286747b715Smrg if(!QuartzRandRInit(pScreen)) { 1296747b715Smrg DEBUG_LOG("Failed to init RandR extension.\n"); 1306747b715Smrg return FALSE; 1316747b715Smrg } 1326747b715Smrg#endif 1336747b715Smrg 1344642e01fSmrg return TRUE; 1354642e01fSmrg} 1364642e01fSmrg 1374642e01fSmrg 1384642e01fSmrg/* 1394642e01fSmrg * QuartzInitOutput 1404642e01fSmrg * Quartz display initialization. 1414642e01fSmrg */ 1424642e01fSmrgvoid QuartzInitOutput( 1434642e01fSmrg int argc, 1444642e01fSmrg char **argv ) 1454642e01fSmrg{ 1464642e01fSmrg if (!RegisterBlockAndWakeupHandlers(QuartzBlockHandler, 1474642e01fSmrg QuartzWakeupHandler, 1484642e01fSmrg NULL)) 1494642e01fSmrg { 1504642e01fSmrg FatalError("Could not register block and wakeup handlers."); 1514642e01fSmrg } 1524642e01fSmrg 1536747b715Smrg if (!dixRegisterPrivateKey(&quartzScreenKeyRec, PRIVATE_SCREEN, 0)) 1546747b715Smrg FatalError("Failed to alloc quartz screen private.\n"); 1556747b715Smrg 1564642e01fSmrg // Do display mode specific initialization 1574642e01fSmrg quartzProcs->DisplayInit(); 1584642e01fSmrg} 1594642e01fSmrg 1604642e01fSmrg 1614642e01fSmrg/* 1624642e01fSmrg * QuartzInitInput 1634642e01fSmrg * Inform the main thread the X server is ready to handle events. 1644642e01fSmrg */ 1654642e01fSmrgvoid QuartzInitInput( 1664642e01fSmrg int argc, 1674642e01fSmrg char **argv ) 1684642e01fSmrg{ 1696747b715Smrg X11ApplicationSetCanQuit(0); 1704642e01fSmrg X11ApplicationServerReady(); 1714642e01fSmrg // Do final display mode specific initialization before handling events 1724642e01fSmrg if (quartzProcs->InitInput) 1734642e01fSmrg quartzProcs->InitInput(argc, argv); 1744642e01fSmrg} 1754642e01fSmrg 1764642e01fSmrg 1776747b715Smrgvoid QuartzUpdateScreens(void) { 1784642e01fSmrg ScreenPtr pScreen; 1794642e01fSmrg WindowPtr pRoot; 1804642e01fSmrg int x, y, width, height, sx, sy; 1814642e01fSmrg xEvent e; 1826747b715Smrg BoxRec bounds; 1834642e01fSmrg 1844642e01fSmrg if (noPseudoramiXExtension || screenInfo.numScreens != 1) 1854642e01fSmrg { 1864642e01fSmrg /* FIXME: if not using Xinerama, we have multiple screens, and 1874642e01fSmrg to do this properly may need to add or remove screens. Which 1884642e01fSmrg isn't possible. So don't do anything. Another reason why 1894642e01fSmrg we default to running with Xinerama. */ 1904642e01fSmrg 1914642e01fSmrg return; 1924642e01fSmrg } 1934642e01fSmrg 1944642e01fSmrg pScreen = screenInfo.screens[0]; 1954642e01fSmrg 1964642e01fSmrg PseudoramiXResetScreens(); 1976747b715Smrg quartzProcs->AddPseudoramiXScreens(&x, &y, &width, &height, pScreen); 1984642e01fSmrg 1996747b715Smrg pScreen->x = x; 2006747b715Smrg pScreen->y = y; 2014642e01fSmrg pScreen->mmWidth = pScreen->mmWidth * ((double) width / pScreen->width); 2024642e01fSmrg pScreen->mmHeight = pScreen->mmHeight * ((double) height / pScreen->height); 2034642e01fSmrg pScreen->width = width; 2044642e01fSmrg pScreen->height = height; 2054642e01fSmrg 2064642e01fSmrg DarwinAdjustScreenOrigins(&screenInfo); 2074642e01fSmrg 2086747b715Smrg /* DarwinAdjustScreenOrigins or UpdateScreen may change pScreen->x/y, 2096747b715Smrg * so use it rather than x/y 2106747b715Smrg */ 2116747b715Smrg sx = pScreen->x + darwinMainScreenX; 2126747b715Smrg sy = pScreen->y + darwinMainScreenY; 2134642e01fSmrg 2144642e01fSmrg /* Adjust the root window. */ 2156747b715Smrg pRoot = pScreen->root; 2164642e01fSmrg AppleWMSetScreenOrigin(pRoot); 2174642e01fSmrg pScreen->ResizeWindow(pRoot, x - sx, y - sy, width, height, NULL); 2186747b715Smrg 2194642e01fSmrg miPaintWindow(pRoot, &pRoot->borderClip, PW_BACKGROUND); 2204642e01fSmrg 2216747b715Smrg /* <rdar://problem/7770779> pointer events are clipped to old display region after display reconfiguration 2226747b715Smrg * http://xquartz.macosforge.org/trac/ticket/346 2236747b715Smrg */ 2246747b715Smrg bounds.x1 = 0; 2256747b715Smrg bounds.x2 = width; 2266747b715Smrg bounds.y1 = 0; 2276747b715Smrg bounds.y2 = height; 2286747b715Smrg pScreen->ConstrainCursor(inputInfo.pointer, pScreen, &bounds); 2296747b715Smrg inputInfo.pointer->spriteInfo->sprite->physLimits = bounds; 2306747b715Smrg inputInfo.pointer->spriteInfo->sprite->hotLimits = bounds; 2316747b715Smrg 2326747b715Smrg 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); 2334642e01fSmrg 2344642e01fSmrg /* Send an event for the root reconfigure */ 2354642e01fSmrg e.u.u.type = ConfigureNotify; 2364642e01fSmrg e.u.configureNotify.window = pRoot->drawable.id; 2374642e01fSmrg e.u.configureNotify.aboveSibling = None; 2384642e01fSmrg e.u.configureNotify.x = x - sx; 2394642e01fSmrg e.u.configureNotify.y = y - sy; 2404642e01fSmrg e.u.configureNotify.width = width; 2414642e01fSmrg e.u.configureNotify.height = height; 2424642e01fSmrg e.u.configureNotify.borderWidth = wBorderWidth(pRoot); 2434642e01fSmrg e.u.configureNotify.override = pRoot->overrideRedirect; 2444642e01fSmrg DeliverEvents(pRoot, &e, 1, NullWindow); 2454642e01fSmrg 2466747b715Smrg quartzProcs->UpdateScreen(pScreen); 2474642e01fSmrg} 2484642e01fSmrg 2496747b715Smrgvoid QuartzShowFullscreen(int state) { 2506747b715Smrg int i; 2516747b715Smrg 2526747b715Smrg DEBUG_LOG("QuartzShowFullscreen: state=%d\n", state); 2534642e01fSmrg 2546747b715Smrg if(XQuartzIsRootless) { 2556747b715Smrg ErrorF("QuartzShowFullscreen called while in rootless mode.\n"); 2566747b715Smrg return; 2576747b715Smrg } 2584642e01fSmrg 2596747b715Smrg if(XQuartzFullscreenVisible == state) 2604642e01fSmrg return; 2614642e01fSmrg 2626747b715Smrg XQuartzFullscreenVisible = state; 2634642e01fSmrg 2644642e01fSmrg xp_disable_update (); 2654642e01fSmrg 2666747b715Smrg if (!XQuartzFullscreenVisible) 2674642e01fSmrg RootlessHideAllWindows(); 2684642e01fSmrg 2696747b715Smrg RootlessUpdateRooted(XQuartzFullscreenVisible); 2704642e01fSmrg 2716747b715Smrg if (XQuartzFullscreenVisible) { 2724642e01fSmrg RootlessShowAllWindows (); 2736747b715Smrg for (i=0; i < screenInfo.numScreens; i++) { 2746747b715Smrg ScreenPtr pScreen = screenInfo.screens[i]; 2756747b715Smrg RootlessRepositionWindows(pScreen); 2766747b715Smrg // JH: I don't think this is necessary, but keeping it here as a reminder 2776747b715Smrg //RootlessUpdateScreenPixmap(pScreen); 2786747b715Smrg } 2794642e01fSmrg } 2804642e01fSmrg 2814642e01fSmrg /* Somehow the menubar manages to interfere with our event stream 2824642e01fSmrg * in fullscreen mode, even though it's not visible. 2834642e01fSmrg */ 2846747b715Smrg X11ApplicationShowHideMenubar(!XQuartzFullscreenVisible); 2854642e01fSmrg 2864642e01fSmrg xp_reenable_update (); 2874642e01fSmrg 2886747b715Smrg if (XQuartzFullscreenDisableHotkeys) 2896747b715Smrg xp_disable_hot_keys(XQuartzFullscreenVisible); 2904642e01fSmrg} 2914642e01fSmrg 2926747b715Smrgvoid QuartzSetRootless(Bool state) { 2936747b715Smrg DEBUG_LOG("QuartzSetRootless state=%d\n", state); 2946747b715Smrg 2956747b715Smrg if(XQuartzIsRootless == state) 2964642e01fSmrg return; 2974642e01fSmrg 2986747b715Smrg if(state) 2996747b715Smrg QuartzShowFullscreen(FALSE); 3006747b715Smrg 3016747b715Smrg XQuartzIsRootless = state; 3024642e01fSmrg 3034642e01fSmrg xp_disable_update(); 3044642e01fSmrg 3054642e01fSmrg /* When in rootless, the menubar is not part of the screen, so we need to update our screens on toggle */ 3064642e01fSmrg QuartzUpdateScreens(); 3074642e01fSmrg 3086747b715Smrg if(XQuartzIsRootless) { 3094642e01fSmrg RootlessShowAllWindows(); 3106747b715Smrg } else { 3116747b715Smrg RootlessHideAllWindows(); 3124642e01fSmrg } 3134642e01fSmrg 3146747b715Smrg X11ApplicationShowHideMenubar(TRUE); 3156747b715Smrg 3164642e01fSmrg xp_reenable_update(); 3176747b715Smrg 3186747b715Smrg xp_disable_hot_keys(FALSE); 3194642e01fSmrg} 3204642e01fSmrg 3214642e01fSmrg/* 3224642e01fSmrg * QuartzShow 3234642e01fSmrg * Show the X server on screen. Does nothing if already shown. 3244642e01fSmrg * Calls mode specific screen resume to restore the X clip regions 3254642e01fSmrg * (if needed) and the X server cursor state. 3264642e01fSmrg */ 3276747b715Smrgvoid QuartzShow(void) { 3284642e01fSmrg int i; 3294642e01fSmrg 3306747b715Smrg if (XQuartzServerVisible) 3314642e01fSmrg return; 3324642e01fSmrg 3336747b715Smrg XQuartzServerVisible = TRUE; 3344642e01fSmrg for (i = 0; i < screenInfo.numScreens; i++) { 3354642e01fSmrg if (screenInfo.screens[i]) { 3366747b715Smrg quartzProcs->ResumeScreen(screenInfo.screens[i]); 3374642e01fSmrg } 3384642e01fSmrg } 3394642e01fSmrg 3406747b715Smrg if (!XQuartzIsRootless) 3416747b715Smrg QuartzShowFullscreen(TRUE); 3424642e01fSmrg} 3434642e01fSmrg 3444642e01fSmrg 3454642e01fSmrg/* 3464642e01fSmrg * QuartzHide 3474642e01fSmrg * Remove the X server display from the screen. Does nothing if already 3484642e01fSmrg * hidden. Calls mode specific screen suspend to set X clip regions to 3494642e01fSmrg * prevent drawing (if needed) and restore the Aqua cursor. 3504642e01fSmrg */ 3514642e01fSmrgvoid QuartzHide(void) 3524642e01fSmrg{ 3534642e01fSmrg int i; 3544642e01fSmrg 3556747b715Smrg if (XQuartzServerVisible) { 3564642e01fSmrg for (i = 0; i < screenInfo.numScreens; i++) { 3574642e01fSmrg if (screenInfo.screens[i]) { 3584642e01fSmrg quartzProcs->SuspendScreen(screenInfo.screens[i]); 3594642e01fSmrg } 3604642e01fSmrg } 3614642e01fSmrg } 3626747b715Smrg 3636747b715Smrg if(!XQuartzIsRootless) 3646747b715Smrg QuartzShowFullscreen(FALSE); 3656747b715Smrg XQuartzServerVisible = FALSE; 3664642e01fSmrg} 3674642e01fSmrg 3684642e01fSmrg 3694642e01fSmrg/* 3704642e01fSmrg * QuartzSetRootClip 3714642e01fSmrg * Enable or disable rendering to the X screen. 3724642e01fSmrg */ 3734642e01fSmrgvoid QuartzSetRootClip( 3744642e01fSmrg BOOL enable) 3754642e01fSmrg{ 3764642e01fSmrg int i; 3774642e01fSmrg 3786747b715Smrg if (!XQuartzServerVisible) 3794642e01fSmrg return; 3804642e01fSmrg 3814642e01fSmrg for (i = 0; i < screenInfo.numScreens; i++) { 3824642e01fSmrg if (screenInfo.screens[i]) { 3834642e01fSmrg xf86SetRootClip(screenInfo.screens[i], enable); 3844642e01fSmrg } 3854642e01fSmrg } 3864642e01fSmrg} 3874642e01fSmrg 3884642e01fSmrg/* 3894642e01fSmrg * QuartzSpaceChanged 3904642e01fSmrg * Unmap offscreen windows, map onscreen windows 3914642e01fSmrg */ 3924642e01fSmrgvoid QuartzSpaceChanged(uint32_t space_id) { 3934642e01fSmrg /* Do something special here, so we don't depend on quartz-wm for spaces to work... */ 3944642e01fSmrg DEBUG_LOG("Space Changed (%u) ... do something interesting...\n", space_id); 3954642e01fSmrg} 3966747b715Smrg 3976747b715Smrg/* 3986747b715Smrg * QuartzCopyDisplayIDs 3996747b715Smrg * Associate an X11 screen with one or more CoreGraphics display IDs by copying 4006747b715Smrg * the list into a private array. Free the previously copied array, if present. 4016747b715Smrg */ 4026747b715Smrgvoid QuartzCopyDisplayIDs(ScreenPtr pScreen, 4036747b715Smrg int displayCount, CGDirectDisplayID *displayIDs) { 4046747b715Smrg QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); 4056747b715Smrg int size = displayCount * sizeof(CGDirectDisplayID); 4066747b715Smrg 4076747b715Smrg free(pQuartzScreen->displayIDs); 4086747b715Smrg pQuartzScreen->displayIDs = malloc(size); 4096747b715Smrg memcpy(pQuartzScreen->displayIDs, displayIDs, size); 4106747b715Smrg pQuartzScreen->displayCount = displayCount; 4116747b715Smrg} 412