xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

xprScreen.c (14988B)


      1 /*
      2  * Xplugin rootless implementation screen functions
      3  *
      4  * Copyright (c) 2002-2012 Apple Computer, Inc. All Rights Reserved.
      5  * Copyright (c) 2004 Torrey T. Lyons. All Rights Reserved.
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a
      8  * copy of this software and associated documentation files (the "Software"),
      9  * to deal in the Software without restriction, including without limitation
     10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     11  * and/or sell copies of the Software, and to permit persons to whom the
     12  * Software is furnished to do so, subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice shall be included in
     15  * all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     20  * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     21  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     23  * DEALINGS IN THE SOFTWARE.
     24  *
     25  * Except as contained in this notice, the name(s) of the above copyright
     26  * holders shall not be used in advertising or otherwise to promote the sale,
     27  * use or other dealings in this Software without prior written authorization.
     28  */
     29 
     30 #include "sanitizedCarbon.h"
     31 
     32 #ifdef HAVE_DIX_CONFIG_H
     33 #include <dix-config.h>
     34 #endif
     35 
     36 #include "inputstr.h"
     37 #include "quartz.h"
     38 #include "quartzRandR.h"
     39 #include "xpr.h"
     40 #include "xprEvent.h"
     41 #include "pseudoramiX.h"
     42 #include "darwinEvents.h"
     43 #include "rootless.h"
     44 #include "dri.h"
     45 #include "globals.h"
     46 #include <Xplugin.h>
     47 #include "applewmExt.h"
     48 #include "micmap.h"
     49 
     50 #include "rootlessCommon.h"
     51 
     52 #ifdef DAMAGE
     53 #include "damage.h"
     54 #endif
     55 
     56 #include "nonsdk_extinit.h"
     57 
     58 /* 10.4's deferred update makes X slower.. have to live with the tearing
     59  * for now.. */
     60 #define XP_NO_DEFERRED_UPDATES 8
     61 
     62 // Name of GLX bundle for native OpenGL
     63 static const char *xprOpenGLBundle = "glxCGL.bundle";
     64 
     65 /*
     66  * eventHandler
     67  *  Callback handler for Xplugin events.
     68  */
     69 static void
     70 eventHandler(unsigned int type, const void *arg,
     71              unsigned int arg_size, void *data)
     72 {
     73 
     74     switch (type) {
     75     case XP_EVENT_DISPLAY_CHANGED:
     76         DEBUG_LOG("XP_EVENT_DISPLAY_CHANGED\n");
     77         DarwinSendDDXEvent(kXquartzDisplayChanged, 0);
     78         break;
     79 
     80     case XP_EVENT_WINDOW_STATE_CHANGED:
     81         if (arg_size >= sizeof(xp_window_state_event)) {
     82             const xp_window_state_event *ws_arg = arg;
     83 
     84             DEBUG_LOG("XP_EVENT_WINDOW_STATE_CHANGED: id=%d, state=%d\n",
     85                       ws_arg->id,
     86                       ws_arg->state);
     87             DarwinSendDDXEvent(kXquartzWindowState, 2,
     88                                ws_arg->id, ws_arg->state);
     89         }
     90         else {
     91             DEBUG_LOG("XP_EVENT_WINDOW_STATE_CHANGED: ignored\n");
     92         }
     93         break;
     94 
     95     case XP_EVENT_WINDOW_MOVED:
     96         DEBUG_LOG("XP_EVENT_WINDOW_MOVED\n");
     97         if (arg_size == sizeof(xp_window_id)) {
     98             xp_window_id id = *(xp_window_id *)arg;
     99             DarwinSendDDXEvent(kXquartzWindowMoved, 1, id);
    100         }
    101         break;
    102 
    103     case XP_EVENT_SURFACE_DESTROYED:
    104         DEBUG_LOG("XP_EVENT_SURFACE_DESTROYED\n");
    105 
    106     case XP_EVENT_SURFACE_CHANGED:
    107         DEBUG_LOG("XP_EVENT_SURFACE_CHANGED\n");
    108         if (arg_size == sizeof(xp_surface_id)) {
    109             int kind;
    110 
    111             if (type == XP_EVENT_SURFACE_DESTROYED)
    112                 kind = AppleDRISurfaceNotifyDestroyed;
    113             else
    114                 kind = AppleDRISurfaceNotifyChanged;
    115 
    116             DRISurfaceNotify(*(xp_surface_id *)arg, kind);
    117         }
    118         break;
    119 
    120 #ifdef XP_EVENT_SPACE_CHANGED
    121     case  XP_EVENT_SPACE_CHANGED:
    122         DEBUG_LOG("XP_EVENT_SPACE_CHANGED\n");
    123         if (arg_size == sizeof(uint32_t)) {
    124             uint32_t space_id = *(uint32_t *)arg;
    125             DarwinSendDDXEvent(kXquartzSpaceChanged, 1, space_id);
    126         }
    127         break;
    128 
    129 #endif
    130     default:
    131         ErrorF("Unknown XP_EVENT type (%d) in xprScreen:eventHandler\n", type);
    132     }
    133 }
    134 
    135 /*
    136  * displayAtIndex
    137  *  Return the display ID for a particular display index.
    138  */
    139 static CGDirectDisplayID
    140 displayAtIndex(int index)
    141 {
    142     CGError err;
    143     CGDisplayCount cnt;
    144     CGDirectDisplayID dpy[index + 1];
    145 
    146     err = CGGetActiveDisplayList(index + 1, dpy, &cnt);
    147     if (err == kCGErrorSuccess && cnt == index + 1)
    148         return dpy[index];
    149     else
    150         return kCGNullDirectDisplay;
    151 }
    152 
    153 /*
    154  * displayScreenBounds
    155  *  Return the bounds of a particular display.
    156  */
    157 static CGRect
    158 displayScreenBounds(CGDirectDisplayID id)
    159 {
    160     CGRect frame;
    161 
    162     frame = CGDisplayBounds(id);
    163 
    164     DEBUG_LOG("    %dx%d @ (%d,%d).\n",
    165               (int)frame.size.width, (int)frame.size.height,
    166               (int)frame.origin.x, (int)frame.origin.y);
    167 
    168     Boolean spacePerDisplay = false;
    169     Boolean ok;
    170     (void)CFPreferencesAppSynchronize(CFSTR("com.apple.spaces"));
    171     spacePerDisplay = ! CFPreferencesGetAppBooleanValue(CFSTR("spans-displays"),
    172                                                         CFSTR("com.apple.spaces"),
    173                                                         &ok);
    174     if (!ok)
    175         spacePerDisplay = true;
    176 
    177     /* Remove menubar to help standard X11 window managers.
    178      * On Mavericks and later, the menu bar is on all displays when spans-displays is false or unset.
    179      */
    180     if (XQuartzIsRootless &&
    181         (spacePerDisplay || (frame.origin.x == 0 && frame.origin.y == 0))) {
    182         frame.origin.y += aquaMenuBarHeight;
    183         frame.size.height -= aquaMenuBarHeight;
    184     }
    185 
    186     DEBUG_LOG("    %dx%d @ (%d,%d).\n",
    187               (int)frame.size.width, (int)frame.size.height,
    188               (int)frame.origin.x, (int)frame.origin.y);
    189 
    190     return frame;
    191 }
    192 
    193 /*
    194  * xprAddPseudoramiXScreens
    195  *  Add a single virtual screen encompassing all the physical screens
    196  *  with PseudoramiX.
    197  */
    198 static void
    199 xprAddPseudoramiXScreens(int *x, int *y, int *width, int *height,
    200                          ScreenPtr pScreen)
    201 {
    202     CGDisplayCount i, displayCount;
    203     CGDirectDisplayID *displayList = NULL;
    204     CGRect unionRect = CGRectNull, frame;
    205 
    206     // Find all the CoreGraphics displays
    207     CGGetActiveDisplayList(0, NULL, &displayCount);
    208     DEBUG_LOG("displayCount: %d\n", (int)displayCount);
    209 
    210     if (!displayCount) {
    211         ErrorF(
    212             "CoreGraphics has reported no connected displays.  Creating a stub 800x600 display.\n");
    213         *x = *y = 0;
    214         *width = 800;
    215         *height = 600;
    216         PseudoramiXAddScreen(*x, *y, *width, *height);
    217         QuartzCopyDisplayIDs(pScreen, 0, NULL);
    218         return;
    219     }
    220 
    221     /* If the displays are captured, we are in a RandR game mode
    222      * on the primary display, so we only want to include the first
    223      * display.  The others are covered by the shield window.
    224      */
    225     if (CGDisplayIsCaptured(kCGDirectMainDisplay))
    226         displayCount = 1;
    227 
    228     displayList = malloc(displayCount * sizeof(CGDirectDisplayID));
    229     if (!displayList)
    230         FatalError("Unable to allocate memory for list of displays.\n");
    231     CGGetActiveDisplayList(displayCount, displayList, &displayCount);
    232     QuartzCopyDisplayIDs(pScreen, displayCount, displayList);
    233 
    234     /* Get the union of all screens */
    235     for (i = 0; i < displayCount; i++) {
    236         CGDirectDisplayID dpy = displayList[i];
    237         frame = displayScreenBounds(dpy);
    238         unionRect = CGRectUnion(unionRect, frame);
    239     }
    240 
    241     /* Use unionRect as the screen size for the X server. */
    242     *x = unionRect.origin.x;
    243     *y = unionRect.origin.y;
    244     *width = unionRect.size.width;
    245     *height = unionRect.size.height;
    246 
    247     DEBUG_LOG("  screen union origin: (%d,%d) size: (%d,%d).\n",
    248               *x, *y, *width, *height);
    249 
    250     /* Tell PseudoramiX about the real screens. */
    251     for (i = 0; i < displayCount; i++) {
    252         CGDirectDisplayID dpy = displayList[i];
    253 
    254         frame = displayScreenBounds(dpy);
    255         frame.origin.x -= unionRect.origin.x;
    256         frame.origin.y -= unionRect.origin.y;
    257 
    258         DEBUG_LOG("    placed at X11 coordinate (%d,%d).\n",
    259                   (int)frame.origin.x, (int)frame.origin.y);
    260 
    261         PseudoramiXAddScreen(frame.origin.x, frame.origin.y,
    262                              frame.size.width, frame.size.height);
    263     }
    264 
    265     free(displayList);
    266 }
    267 
    268 /*
    269  * xprDisplayInit
    270  *  Find number of CoreGraphics displays and initialize Xplugin.
    271  */
    272 static void
    273 xprDisplayInit(void)
    274 {
    275     CGDisplayCount displayCount;
    276 
    277     TRACE();
    278 
    279     CGGetActiveDisplayList(0, NULL, &displayCount);
    280 
    281     /* With PseudoramiX, the X server only sees one screen; only PseudoramiX
    282        itself knows about all of the screens. */
    283 
    284     if (noPseudoramiXExtension) {
    285         darwinScreensFound = displayCount;
    286     } else {
    287         PseudoramiXExtensionInit();
    288         darwinScreensFound = 1;
    289     }
    290 
    291     if (xp_init(XP_BACKGROUND_EVENTS | XP_NO_DEFERRED_UPDATES) != Success)
    292         FatalError("Could not initialize the Xplugin library.");
    293 
    294     xp_select_events(XP_EVENT_DISPLAY_CHANGED
    295                      | XP_EVENT_WINDOW_STATE_CHANGED
    296                      | XP_EVENT_WINDOW_MOVED
    297 #ifdef XP_EVENT_SPACE_CHANGED
    298                      | XP_EVENT_SPACE_CHANGED
    299 #endif
    300                      | XP_EVENT_SURFACE_CHANGED
    301                      | XP_EVENT_SURFACE_DESTROYED,
    302                      eventHandler, NULL);
    303 
    304     AppleDRIExtensionInit();
    305     xprAppleWMInit();
    306 
    307     XQuartzIsRootless = XQuartzRootlessDefault;
    308     if (!XQuartzIsRootless)
    309         RootlessHideAllWindows();
    310 }
    311 
    312 /*
    313  * xprAddScreen
    314  *  Init the framebuffer and record pixmap parameters for the screen.
    315  */
    316 static Bool
    317 xprAddScreen(int index, ScreenPtr pScreen)
    318 {
    319     DarwinFramebufferPtr dfb = SCREEN_PRIV(pScreen);
    320     int depth = darwinDesiredDepth;
    321 
    322     DEBUG_LOG("index=%d depth=%d\n", index, depth);
    323 
    324     if (depth == -1) {
    325         CGDisplayModeRef modeRef;
    326         CFStringRef encStrRef;
    327 
    328         modeRef = CGDisplayCopyDisplayMode(kCGDirectMainDisplay);
    329         if (!modeRef)
    330             goto have_depth;
    331 
    332         encStrRef = CGDisplayModeCopyPixelEncoding(modeRef);
    333         CFRelease(modeRef);
    334         if (!encStrRef)
    335             goto have_depth;
    336 
    337         if (CFStringCompare(encStrRef, CFSTR(IO32BitDirectPixels),
    338                             kCFCompareCaseInsensitive) ==
    339             kCFCompareEqualTo) {
    340             depth = 24;
    341         }
    342         else if (CFStringCompare(encStrRef, CFSTR(IO16BitDirectPixels),
    343                                  kCFCompareCaseInsensitive) ==
    344                  kCFCompareEqualTo) {
    345             depth = 15;
    346         }
    347         else if (CFStringCompare(encStrRef, CFSTR(IO8BitIndexedPixels),
    348                                  kCFCompareCaseInsensitive) ==
    349                  kCFCompareEqualTo) {
    350             depth = 8;
    351         }
    352 
    353         CFRelease(encStrRef);
    354     }
    355 
    356 have_depth:
    357     switch (depth) {
    358     case 8:     // pseudo-working
    359         dfb->visuals = PseudoColorMask;
    360         dfb->preferredCVC = PseudoColor;
    361         dfb->depth = 8;
    362         dfb->bitsPerRGB = 8;
    363         dfb->bitsPerPixel = 8;
    364         dfb->redMask = 0;
    365         dfb->greenMask = 0;
    366         dfb->blueMask = 0;
    367         break;
    368 
    369 #if 0
    370     // Removed because Mountain Lion removed support for
    371     // 15bit backing stores.  We can possibly re-add
    372     // this once libXplugin is updated to work around it.
    373     case 15:
    374         dfb->visuals = TrueColorMask;     //LARGE_VISUALS;
    375         dfb->preferredCVC = TrueColor;
    376         dfb->depth = 15;
    377         dfb->bitsPerRGB = 5;
    378         dfb->bitsPerPixel = 16;
    379         dfb->redMask = RM_ARGB(0, 5, 5, 5);
    380         dfb->greenMask = GM_ARGB(0, 5, 5, 5);
    381         dfb->blueMask = BM_ARGB(0, 5, 5, 5);
    382         break;
    383 #endif
    384 
    385     //        case 24:
    386     default:
    387         if (depth != 24)
    388             ErrorF(
    389                 "Unsupported color depth requested.  Defaulting to 24bit. (depth=%d darwinDesiredDepth=%d)\n",
    390                 depth, darwinDesiredDepth);
    391         dfb->visuals = TrueColorMask;     //LARGE_VISUALS;
    392         dfb->preferredCVC = TrueColor;
    393         dfb->depth = 24;
    394         dfb->bitsPerRGB = 8;
    395         dfb->bitsPerPixel = 32;
    396         dfb->redMask = RM_ARGB(0, 8, 8, 8);
    397         dfb->greenMask = GM_ARGB(0, 8, 8, 8);
    398         dfb->blueMask = BM_ARGB(0, 8, 8, 8);
    399         break;
    400     }
    401 
    402     if (noPseudoramiXExtension) {
    403         CGDirectDisplayID dpy;
    404         CGRect frame;
    405 
    406         ErrorF("Warning: noPseudoramiXExtension!\n");
    407 
    408         dpy = displayAtIndex(index);
    409         QuartzCopyDisplayIDs(pScreen, 1, &dpy);
    410 
    411         frame = displayScreenBounds(dpy);
    412 
    413         dfb->x = frame.origin.x;
    414         dfb->y = frame.origin.y;
    415         dfb->width = frame.size.width;
    416         dfb->height = frame.size.height;
    417     }
    418     else {
    419         xprAddPseudoramiXScreens(&dfb->x, &dfb->y, &dfb->width, &dfb->height,
    420                                  pScreen);
    421     }
    422 
    423     /* Passing zero width (pitch) makes miCreateScreenResources set the
    424        screen pixmap to the framebuffer pointer, i.e. NULL. The generic
    425        rootless code takes care of making this work. */
    426     dfb->pitch = 0;
    427     dfb->framebuffer = NULL;
    428 
    429     DRIScreenInit(pScreen);
    430 
    431     return TRUE;
    432 }
    433 
    434 /*
    435  * xprSetupScreen
    436  *  Setup the screen for rootless access.
    437  */
    438 static Bool
    439 xprSetupScreen(int index, ScreenPtr pScreen)
    440 {
    441 #ifdef DAMAGE
    442     // The Damage extension needs to wrap underneath the
    443     // generic rootless layer, so do it now.
    444     if (!DamageSetup(pScreen))
    445         return FALSE;
    446 #endif
    447 
    448     // Initialize generic rootless code
    449     if (!xprInit(pScreen))
    450         return FALSE;
    451 
    452     return DRIFinishScreenInit(pScreen);
    453 }
    454 
    455 /*
    456  * xprUpdateScreen
    457  *  Update screen after configuration change.
    458  */
    459 static void
    460 xprUpdateScreen(ScreenPtr pScreen)
    461 {
    462     rootlessGlobalOffsetX = darwinMainScreenX;
    463     rootlessGlobalOffsetY = darwinMainScreenY;
    464 
    465     AppleWMSetScreenOrigin(pScreen->root);
    466 
    467     RootlessRepositionWindows(pScreen);
    468     RootlessUpdateScreenPixmap(pScreen);
    469 }
    470 
    471 /*
    472  * xprInitInput
    473  *  Finalize xpr specific setup.
    474  */
    475 static void
    476 xprInitInput(int argc, char **argv)
    477 {
    478     int i;
    479 
    480     rootlessGlobalOffsetX = darwinMainScreenX;
    481     rootlessGlobalOffsetY = darwinMainScreenY;
    482 
    483     for (i = 0; i < screenInfo.numScreens; i++)
    484         AppleWMSetScreenOrigin(screenInfo.screens[i]->root);
    485 }
    486 
    487 /*
    488  * Quartz display mode function list.
    489  */
    490 static QuartzModeProcsRec xprModeProcs = {
    491     xprDisplayInit,
    492     xprAddScreen,
    493     xprSetupScreen,
    494     xprInitInput,
    495     QuartzInitCursor,
    496     QuartzSuspendXCursor,
    497     QuartzResumeXCursor,
    498     xprAddPseudoramiXScreens,
    499     xprUpdateScreen,
    500     xprIsX11Window,
    501     xprHideWindows,
    502     RootlessFrameForWindow,
    503     TopLevelParent,
    504     DRICreateSurface,
    505     DRIDestroySurface
    506 };
    507 
    508 /*
    509  * QuartzModeBundleInit
    510  *  Initialize the display mode bundle after loading.
    511  */
    512 Bool
    513 QuartzModeBundleInit(void)
    514 {
    515     quartzProcs = &xprModeProcs;
    516     quartzOpenGLBundle = xprOpenGLBundle;
    517     return TRUE;
    518 }