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