xprScreen.c revision 6747b715
1/* 2 * Xplugin rootless implementation screen functions 3 * 4 * Copyright (c) 2002 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 "quartzCommon.h" 37#include "inputstr.h" 38#include "quartz.h" 39#include "quartzRandR.h" 40#include "xpr.h" 41#include "xprEvent.h" 42#include "pseudoramiX.h" 43#include "darwin.h" 44#include "darwinEvents.h" 45#include "rootless.h" 46#include "dri.h" 47#include "globals.h" 48#include <Xplugin.h> 49#include "applewmExt.h" 50#include "micmap.h" 51 52#include "rootlessCommon.h" 53 54#ifdef DAMAGE 55# include "damage.h" 56#endif 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 63static const char *xprOpenGLBundle = "glxCGL.bundle"; 64 65/* 66 * eventHandler 67 * Callback handler for Xplugin events. 68 */ 69static void eventHandler(unsigned int type, const void *arg, 70 unsigned int arg_size, void *data) { 71 72 switch (type) { 73 case XP_EVENT_DISPLAY_CHANGED: 74 DEBUG_LOG("XP_EVENT_DISPLAY_CHANGED\n"); 75 DarwinSendDDXEvent(kXquartzDisplayChanged, 0); 76 break; 77 78 case XP_EVENT_WINDOW_STATE_CHANGED: 79 if (arg_size >= sizeof(xp_window_state_event)) { 80 const xp_window_state_event *ws_arg = arg; 81 82 DEBUG_LOG("XP_EVENT_WINDOW_STATE_CHANGED: id=%d, state=%d\n", ws_arg->id, ws_arg->state); 83 DarwinSendDDXEvent(kXquartzWindowState, 2, 84 ws_arg->id, ws_arg->state); 85 } else { 86 DEBUG_LOG("XP_EVENT_WINDOW_STATE_CHANGED: ignored\n"); 87 } 88 break; 89 90 case XP_EVENT_WINDOW_MOVED: 91 DEBUG_LOG("XP_EVENT_WINDOW_MOVED\n"); 92 if (arg_size == sizeof(xp_window_id)) { 93 xp_window_id id = * (xp_window_id *) arg; 94 DarwinSendDDXEvent(kXquartzWindowMoved, 1, id); 95 } 96 break; 97 98 case XP_EVENT_SURFACE_DESTROYED: 99 DEBUG_LOG("XP_EVENT_SURFACE_DESTROYED\n"); 100 case XP_EVENT_SURFACE_CHANGED: 101 DEBUG_LOG("XP_EVENT_SURFACE_CHANGED\n"); 102 if (arg_size == sizeof(xp_surface_id)) { 103 int kind; 104 105 if (type == XP_EVENT_SURFACE_DESTROYED) 106 kind = AppleDRISurfaceNotifyDestroyed; 107 else 108 kind = AppleDRISurfaceNotifyChanged; 109 110 DRISurfaceNotify(*(xp_surface_id *) arg, kind); 111 } 112 break; 113#ifdef XP_EVENT_SPACE_CHANGED 114 case XP_EVENT_SPACE_CHANGED: 115 DEBUG_LOG("XP_EVENT_SPACE_CHANGED\n"); 116 if(arg_size == sizeof(uint32_t)) { 117 uint32_t space_id = *(uint32_t *)arg; 118 DarwinSendDDXEvent(kXquartzSpaceChanged, 1, space_id); 119 } 120 break; 121#endif 122 default: 123 ErrorF("Unknown XP_EVENT type (%d) in xprScreen:eventHandler\n", type); 124 } 125} 126 127/* 128 * displayAtIndex 129 * Return the display ID for a particular display index. 130 */ 131static CGDirectDisplayID 132displayAtIndex(int index) 133{ 134 CGError err; 135 CGDisplayCount cnt; 136 CGDirectDisplayID dpy[index+1]; 137 138 err = CGGetActiveDisplayList(index + 1, dpy, &cnt); 139 if (err == kCGErrorSuccess && cnt == index + 1) 140 return dpy[index]; 141 else 142 return kCGNullDirectDisplay; 143} 144 145/* 146 * displayScreenBounds 147 * Return the bounds of a particular display. 148 */ 149static CGRect 150displayScreenBounds(CGDirectDisplayID id) 151{ 152 CGRect frame; 153 154 frame = CGDisplayBounds(id); 155 156 DEBUG_LOG(" %dx%d @ (%d,%d).\n", 157 (int)frame.size.width, (int)frame.size.height, 158 (int)frame.origin.x, (int)frame.origin.y); 159 160 /* Remove menubar to help standard X11 window managers. */ 161 if (XQuartzIsRootless && 162 frame.origin.x == 0 && frame.origin.y == 0) { 163 frame.origin.y += aquaMenuBarHeight; 164 frame.size.height -= aquaMenuBarHeight; 165 } 166 167 DEBUG_LOG(" %dx%d @ (%d,%d).\n", 168 (int)frame.size.width, (int)frame.size.height, 169 (int)frame.origin.x, (int)frame.origin.y); 170 171 return frame; 172} 173 174/* 175 * xprAddPseudoramiXScreens 176 * Add a single virtual screen encompassing all the physical screens 177 * with PseudoramiX. 178 */ 179static void 180xprAddPseudoramiXScreens(int *x, int *y, int *width, int *height, ScreenPtr pScreen) 181{ 182 CGDisplayCount i, displayCount; 183 CGDirectDisplayID *displayList = NULL; 184 CGRect unionRect = CGRectNull, frame; 185 186 // Find all the CoreGraphics displays 187 CGGetActiveDisplayList(0, NULL, &displayCount); 188 DEBUG_LOG("displayCount: %d\n", (int)displayCount); 189 190 if(!displayCount) { 191 ErrorF("CoreGraphics has reported no connected displays. Creating a stub 800x600 display.\n"); 192 *x = *y = 0; 193 *width = 800; 194 *height = 600; 195 PseudoramiXAddScreen(*x, *y, *width, *height); 196 return; 197 } 198 199 displayList = malloc(displayCount * sizeof(CGDirectDisplayID)); 200 if(!displayList) 201 FatalError("Unable to allocate memory for list of displays.\n"); 202 CGGetActiveDisplayList(displayCount, displayList, &displayCount); 203 QuartzCopyDisplayIDs(pScreen, displayCount, displayList); 204 205 /* Get the union of all screens */ 206 for (i = 0; i < displayCount; i++) { 207 CGDirectDisplayID dpy = displayList[i]; 208 frame = displayScreenBounds(dpy); 209 unionRect = CGRectUnion(unionRect, frame); 210 } 211 212 /* Use unionRect as the screen size for the X server. */ 213 *x = unionRect.origin.x; 214 *y = unionRect.origin.y; 215 *width = unionRect.size.width; 216 *height = unionRect.size.height; 217 218 DEBUG_LOG(" screen union origin: (%d,%d) size: (%d,%d).\n", 219 *x, *y, *width, *height); 220 221 /* Tell PseudoramiX about the real screens. */ 222 for (i = 0; i < displayCount; i++) 223 { 224 CGDirectDisplayID dpy = displayList[i]; 225 226 frame = displayScreenBounds(dpy); 227 frame.origin.x -= unionRect.origin.x; 228 frame.origin.y -= unionRect.origin.y; 229 230 DEBUG_LOG(" placed at X11 coordinate (%d,%d).\n", 231 (int)frame.origin.x, (int)frame.origin.y); 232 233 PseudoramiXAddScreen(frame.origin.x, frame.origin.y, 234 frame.size.width, frame.size.height); 235 } 236 237 free(displayList); 238} 239 240/* 241 * xprDisplayInit 242 * Find number of CoreGraphics displays and initialize Xplugin. 243 */ 244static void 245xprDisplayInit(void) 246{ 247 CGDisplayCount displayCount; 248 249 DEBUG_LOG(""); 250 251 CGGetActiveDisplayList(0, NULL, &displayCount); 252 253 /* With PseudoramiX, the X server only sees one screen; only PseudoramiX 254 itself knows about all of the screens. */ 255 256 if (noPseudoramiXExtension) 257 darwinScreensFound = displayCount; 258 else 259 darwinScreensFound = 1; 260 261 if (xp_init(XP_BACKGROUND_EVENTS | XP_NO_DEFERRED_UPDATES) != Success) 262 FatalError("Could not initialize the Xplugin library."); 263 264 xp_select_events(XP_EVENT_DISPLAY_CHANGED 265 | XP_EVENT_WINDOW_STATE_CHANGED 266 | XP_EVENT_WINDOW_MOVED 267#ifdef XP_EVENT_SPACE_CHANGED 268 | XP_EVENT_SPACE_CHANGED 269#endif 270 | XP_EVENT_SURFACE_CHANGED 271 | XP_EVENT_SURFACE_DESTROYED, 272 eventHandler, NULL); 273 274 AppleDRIExtensionInit(); 275 xprAppleWMInit(); 276 277 XQuartzIsRootless = XQuartzRootlessDefault; 278 if (!XQuartzIsRootless) 279 RootlessHideAllWindows(); 280} 281 282/* 283 * xprAddScreen 284 * Init the framebuffer and record pixmap parameters for the screen. 285 */ 286static Bool 287xprAddScreen(int index, ScreenPtr pScreen) 288{ 289 DarwinFramebufferPtr dfb = SCREEN_PRIV(pScreen); 290 int depth = darwinDesiredDepth; 291 292 DEBUG_LOG("index=%d depth=%d\n", index, depth); 293 294 if(depth == -1) { 295 depth = CGDisplaySamplesPerPixel(kCGDirectMainDisplay) * CGDisplayBitsPerSample(kCGDirectMainDisplay); 296 } 297 298 switch(depth) { 299 case 8: // pseudo-working 300 dfb->visuals = PseudoColorMask; 301 dfb->preferredCVC = PseudoColor; 302 dfb->depth = 8; 303 dfb->bitsPerRGB = 8; 304 dfb->bitsPerPixel = 8; 305 dfb->redMask = 0; 306 dfb->greenMask = 0; 307 dfb->blueMask = 0; 308 break; 309 case 15: 310 dfb->visuals = TrueColorMask; //LARGE_VISUALS; 311 dfb->preferredCVC = TrueColor; 312 dfb->depth = 15; 313 dfb->bitsPerRGB = 5; 314 dfb->bitsPerPixel = 16; 315 dfb->redMask = RM_ARGB(0,5,5,5); 316 dfb->greenMask = GM_ARGB(0,5,5,5); 317 dfb->blueMask = BM_ARGB(0,5,5,5); 318 break; 319// case 24: 320 default: 321 if(depth != 24) 322 ErrorF("Unsupported color depth requested. Defaulting to 24bit. (depth=%d darwinDesiredDepth=%d CGDisplaySamplesPerPixel=%d CGDisplayBitsPerSample=%d)\n", darwinDesiredDepth, depth, (int)CGDisplaySamplesPerPixel(kCGDirectMainDisplay), (int)CGDisplayBitsPerSample(kCGDirectMainDisplay)); 323 dfb->visuals = TrueColorMask; //LARGE_VISUALS; 324 dfb->preferredCVC = TrueColor; 325 dfb->depth = 24; 326 dfb->bitsPerRGB = 8; 327 dfb->bitsPerPixel = 32; 328 dfb->redMask = RM_ARGB(0,8,8,8); 329 dfb->greenMask = GM_ARGB(0,8,8,8); 330 dfb->blueMask = BM_ARGB(0,8,8,8); 331 break; 332 } 333 334 if (noPseudoramiXExtension) 335 { 336 CGDirectDisplayID dpy; 337 CGRect frame; 338 339 ErrorF("Warning: noPseudoramiXExtension!\n"); 340 341 dpy = displayAtIndex(index); 342 QuartzCopyDisplayIDs(pScreen, 1, &dpy); 343 344 frame = displayScreenBounds(dpy); 345 346 dfb->x = frame.origin.x; 347 dfb->y = frame.origin.y; 348 dfb->width = frame.size.width; 349 dfb->height = frame.size.height; 350 } 351 else 352 { 353 xprAddPseudoramiXScreens(&dfb->x, &dfb->y, &dfb->width, &dfb->height, pScreen); 354 } 355 356 /* Passing zero width (pitch) makes miCreateScreenResources set the 357 screen pixmap to the framebuffer pointer, i.e. NULL. The generic 358 rootless code takes care of making this work. */ 359 dfb->pitch = 0; 360 dfb->framebuffer = NULL; 361 362 DRIScreenInit(pScreen); 363 364 return TRUE; 365} 366 367/* 368 * xprSetupScreen 369 * Setup the screen for rootless access. 370 */ 371static Bool 372xprSetupScreen(int index, ScreenPtr pScreen) 373{ 374 // Initialize accelerated rootless drawing 375 // Note that this must be done before DamageSetup(). 376 377 // These are crashing ugly... better to be stable and not crash for now. 378 //RootlessAccelInit(pScreen); 379 380#ifdef DAMAGE 381 // The Damage extension needs to wrap underneath the 382 // generic rootless layer, so do it now. 383 if (!DamageSetup(pScreen)) 384 return FALSE; 385#endif 386 387 // Initialize generic rootless code 388 if (!xprInit(pScreen)) 389 return FALSE; 390 391 return DRIFinishScreenInit(pScreen); 392} 393 394/* 395 * xprUpdateScreen 396 * Update screen after configuation change. 397 */ 398static void 399xprUpdateScreen(ScreenPtr pScreen) 400{ 401 rootlessGlobalOffsetX = darwinMainScreenX; 402 rootlessGlobalOffsetY = darwinMainScreenY; 403 404 AppleWMSetScreenOrigin(pScreen->root); 405 406 RootlessRepositionWindows(pScreen); 407 RootlessUpdateScreenPixmap(pScreen); 408} 409 410/* 411 * xprInitInput 412 * Finalize xpr specific setup. 413 */ 414static void 415xprInitInput(int argc, char **argv) 416{ 417 int i; 418 419 rootlessGlobalOffsetX = darwinMainScreenX; 420 rootlessGlobalOffsetY = darwinMainScreenY; 421 422 for (i = 0; i < screenInfo.numScreens; i++) 423 AppleWMSetScreenOrigin(screenInfo.screens[i]->root); 424} 425 426/* 427 * Quartz display mode function list. 428 */ 429static QuartzModeProcsRec xprModeProcs = { 430 xprDisplayInit, 431 xprAddScreen, 432 xprSetupScreen, 433 xprInitInput, 434 QuartzInitCursor, 435 QuartzSuspendXCursor, 436 QuartzResumeXCursor, 437 xprAddPseudoramiXScreens, 438 xprUpdateScreen, 439 xprIsX11Window, 440 xprHideWindows, 441 RootlessFrameForWindow, 442 TopLevelParent, 443 DRICreateSurface, 444 DRIDestroySurface 445}; 446 447/* 448 * QuartzModeBundleInit 449 * Initialize the display mode bundle after loading. 450 */ 451Bool 452QuartzModeBundleInit(void) 453{ 454 quartzProcs = &xprModeProcs; 455 quartzOpenGLBundle = xprOpenGLBundle; 456 return TRUE; 457} 458