Window.c (15657B)
1 /* 2 3 Copyright 1993 by Davor Matic 4 5 Permission to use, copy, modify, distribute, and sell this software 6 and its documentation for any purpose is hereby granted without fee, 7 provided that the above copyright notice appear in all copies and that 8 both that copyright notice and this permission notice appear in 9 supporting documentation. Davor Matic makes no representations about 10 the suitability of this software for any purpose. It is provided "as 11 is" without express or implied warranty. 12 13 */ 14 15 #ifdef HAVE_XNEST_CONFIG_H 16 #include <xnest-config.h> 17 #endif 18 19 #include <X11/X.h> 20 #include <X11/Xproto.h> 21 #include "gcstruct.h" 22 #include "window.h" 23 #include "windowstr.h" 24 #include "pixmapstr.h" 25 #include "colormapst.h" 26 #include "scrnintstr.h" 27 #include "region.h" 28 29 #include "mi.h" 30 31 #include "Xnest.h" 32 33 #include "Display.h" 34 #include "Screen.h" 35 #include "XNGC.h" 36 #include "Drawable.h" 37 #include "Color.h" 38 #include "Visual.h" 39 #include "Events.h" 40 #include "Args.h" 41 42 DevPrivateKeyRec xnestWindowPrivateKeyRec; 43 44 static int 45 xnestFindWindowMatch(WindowPtr pWin, void *ptr) 46 { 47 xnestWindowMatch *wm = (xnestWindowMatch *) ptr; 48 49 if (wm->window == xnestWindow(pWin)) { 50 wm->pWin = pWin; 51 return WT_STOPWALKING; 52 } 53 else 54 return WT_WALKCHILDREN; 55 } 56 57 WindowPtr 58 xnestWindowPtr(Window window) 59 { 60 xnestWindowMatch wm; 61 int i; 62 63 wm.pWin = NullWindow; 64 wm.window = window; 65 66 for (i = 0; i < xnestNumScreens; i++) { 67 WalkTree(screenInfo.screens[i], xnestFindWindowMatch, (void *) &wm); 68 if (wm.pWin) 69 break; 70 } 71 72 return wm.pWin; 73 } 74 75 Bool 76 xnestCreateWindow(WindowPtr pWin) 77 { 78 unsigned long mask; 79 XSetWindowAttributes attributes; 80 Visual *visual; 81 ColormapPtr pCmap; 82 83 if (pWin->drawable.class == InputOnly) { 84 mask = 0L; 85 visual = CopyFromParent; 86 } 87 else { 88 mask = CWEventMask | CWBackingStore; 89 attributes.event_mask = ExposureMask; 90 attributes.backing_store = NotUseful; 91 92 if (pWin->parent) { 93 if (pWin->optional && 94 pWin->optional->visual != wVisual(pWin->parent)) { 95 visual = 96 xnestVisualFromID(pWin->drawable.pScreen, wVisual(pWin)); 97 mask |= CWColormap; 98 if (pWin->optional->colormap) { 99 dixLookupResourceByType((void **) &pCmap, wColormap(pWin), 100 RT_COLORMAP, serverClient, 101 DixUseAccess); 102 attributes.colormap = xnestColormap(pCmap); 103 } 104 else 105 attributes.colormap = xnestDefaultVisualColormap(visual); 106 } 107 else 108 visual = CopyFromParent; 109 } 110 else { /* root windows have their own colormaps at creation time */ 111 visual = xnestVisualFromID(pWin->drawable.pScreen, wVisual(pWin)); 112 dixLookupResourceByType((void **) &pCmap, wColormap(pWin), 113 RT_COLORMAP, serverClient, DixUseAccess); 114 mask |= CWColormap; 115 attributes.colormap = xnestColormap(pCmap); 116 } 117 } 118 119 xnestWindowPriv(pWin)->window = XCreateWindow(xnestDisplay, 120 xnestWindowParent(pWin), 121 pWin->origin.x - 122 wBorderWidth(pWin), 123 pWin->origin.y - 124 wBorderWidth(pWin), 125 pWin->drawable.width, 126 pWin->drawable.height, 127 pWin->borderWidth, 128 pWin->drawable.depth, 129 pWin->drawable.class, 130 visual, mask, &attributes); 131 xnestWindowPriv(pWin)->parent = xnestWindowParent(pWin); 132 xnestWindowPriv(pWin)->x = pWin->origin.x - wBorderWidth(pWin); 133 xnestWindowPriv(pWin)->y = pWin->origin.y - wBorderWidth(pWin); 134 xnestWindowPriv(pWin)->width = pWin->drawable.width; 135 xnestWindowPriv(pWin)->height = pWin->drawable.height; 136 xnestWindowPriv(pWin)->border_width = pWin->borderWidth; 137 xnestWindowPriv(pWin)->sibling_above = None; 138 if (pWin->nextSib) 139 xnestWindowPriv(pWin->nextSib)->sibling_above = xnestWindow(pWin); 140 xnestWindowPriv(pWin)->bounding_shape = RegionCreate(NULL, 1); 141 xnestWindowPriv(pWin)->clip_shape = RegionCreate(NULL, 1); 142 143 if (!pWin->parent) /* only the root window will have the right colormap */ 144 xnestSetInstalledColormapWindows(pWin->drawable.pScreen); 145 146 return True; 147 } 148 149 Bool 150 xnestDestroyWindow(WindowPtr pWin) 151 { 152 if (pWin->nextSib) 153 xnestWindowPriv(pWin->nextSib)->sibling_above = 154 xnestWindowPriv(pWin)->sibling_above; 155 RegionDestroy(xnestWindowPriv(pWin)->bounding_shape); 156 RegionDestroy(xnestWindowPriv(pWin)->clip_shape); 157 XDestroyWindow(xnestDisplay, xnestWindow(pWin)); 158 xnestWindowPriv(pWin)->window = None; 159 160 if (pWin->optional && pWin->optional->colormap && pWin->parent) 161 xnestSetInstalledColormapWindows(pWin->drawable.pScreen); 162 163 return True; 164 } 165 166 Bool 167 xnestPositionWindow(WindowPtr pWin, int x, int y) 168 { 169 xnestConfigureWindow(pWin, 170 CWParent | 171 CWX | CWY | CWWidth | CWHeight | CWBorderWidth); 172 173 return True; 174 } 175 176 void 177 xnestConfigureWindow(WindowPtr pWin, unsigned int mask) 178 { 179 unsigned int valuemask; 180 XWindowChanges values; 181 182 if (mask & CWParent && 183 xnestWindowPriv(pWin)->parent != xnestWindowParent(pWin)) { 184 XReparentWindow(xnestDisplay, xnestWindow(pWin), 185 xnestWindowParent(pWin), 186 pWin->origin.x - wBorderWidth(pWin), 187 pWin->origin.y - wBorderWidth(pWin)); 188 xnestWindowPriv(pWin)->parent = xnestWindowParent(pWin); 189 xnestWindowPriv(pWin)->x = pWin->origin.x - wBorderWidth(pWin); 190 xnestWindowPriv(pWin)->y = pWin->origin.y - wBorderWidth(pWin); 191 xnestWindowPriv(pWin)->sibling_above = None; 192 if (pWin->nextSib) 193 xnestWindowPriv(pWin->nextSib)->sibling_above = xnestWindow(pWin); 194 } 195 196 valuemask = 0; 197 198 if (mask & CWX && 199 xnestWindowPriv(pWin)->x != pWin->origin.x - wBorderWidth(pWin)) { 200 valuemask |= CWX; 201 values.x = 202 xnestWindowPriv(pWin)->x = pWin->origin.x - wBorderWidth(pWin); 203 } 204 205 if (mask & CWY && 206 xnestWindowPriv(pWin)->y != pWin->origin.y - wBorderWidth(pWin)) { 207 valuemask |= CWY; 208 values.y = 209 xnestWindowPriv(pWin)->y = pWin->origin.y - wBorderWidth(pWin); 210 } 211 212 if (mask & CWWidth && xnestWindowPriv(pWin)->width != pWin->drawable.width) { 213 valuemask |= CWWidth; 214 values.width = xnestWindowPriv(pWin)->width = pWin->drawable.width; 215 } 216 217 if (mask & CWHeight && 218 xnestWindowPriv(pWin)->height != pWin->drawable.height) { 219 valuemask |= CWHeight; 220 values.height = xnestWindowPriv(pWin)->height = pWin->drawable.height; 221 } 222 223 if (mask & CWBorderWidth && 224 xnestWindowPriv(pWin)->border_width != pWin->borderWidth) { 225 valuemask |= CWBorderWidth; 226 values.border_width = 227 xnestWindowPriv(pWin)->border_width = pWin->borderWidth; 228 } 229 230 if (valuemask) 231 XConfigureWindow(xnestDisplay, xnestWindow(pWin), valuemask, &values); 232 233 if (mask & CWStackingOrder && 234 xnestWindowPriv(pWin)->sibling_above != xnestWindowSiblingAbove(pWin)) { 235 WindowPtr pSib; 236 237 /* find the top sibling */ 238 for (pSib = pWin; pSib->prevSib != NullWindow; pSib = pSib->prevSib); 239 240 /* the top sibling */ 241 valuemask = CWStackMode; 242 values.stack_mode = Above; 243 XConfigureWindow(xnestDisplay, xnestWindow(pSib), valuemask, &values); 244 xnestWindowPriv(pSib)->sibling_above = None; 245 246 /* the rest of siblings */ 247 for (pSib = pSib->nextSib; pSib != NullWindow; pSib = pSib->nextSib) { 248 valuemask = CWSibling | CWStackMode; 249 values.sibling = xnestWindowSiblingAbove(pSib); 250 values.stack_mode = Below; 251 XConfigureWindow(xnestDisplay, xnestWindow(pSib), valuemask, 252 &values); 253 xnestWindowPriv(pSib)->sibling_above = 254 xnestWindowSiblingAbove(pSib); 255 } 256 } 257 } 258 259 Bool 260 xnestChangeWindowAttributes(WindowPtr pWin, unsigned long mask) 261 { 262 XSetWindowAttributes attributes; 263 264 if (mask & CWBackPixmap) 265 switch (pWin->backgroundState) { 266 case None: 267 attributes.background_pixmap = None; 268 break; 269 270 case ParentRelative: 271 attributes.background_pixmap = ParentRelative; 272 break; 273 274 case BackgroundPixmap: 275 attributes.background_pixmap = xnestPixmap(pWin->background.pixmap); 276 break; 277 278 case BackgroundPixel: 279 mask &= ~CWBackPixmap; 280 break; 281 } 282 283 if (mask & CWBackPixel) { 284 if (pWin->backgroundState == BackgroundPixel) 285 attributes.background_pixel = xnestPixel(pWin->background.pixel); 286 else 287 mask &= ~CWBackPixel; 288 } 289 290 if (mask & CWBorderPixmap) { 291 if (pWin->borderIsPixel) 292 mask &= ~CWBorderPixmap; 293 else 294 attributes.border_pixmap = xnestPixmap(pWin->border.pixmap); 295 } 296 297 if (mask & CWBorderPixel) { 298 if (pWin->borderIsPixel) 299 attributes.border_pixel = xnestPixel(pWin->border.pixel); 300 else 301 mask &= ~CWBorderPixel; 302 } 303 304 if (mask & CWBitGravity) 305 attributes.bit_gravity = pWin->bitGravity; 306 307 if (mask & CWWinGravity) /* dix does this for us */ 308 mask &= ~CWWinGravity; 309 310 if (mask & CWBackingStore) /* this is really not useful */ 311 mask &= ~CWBackingStore; 312 313 if (mask & CWBackingPlanes) /* this is really not useful */ 314 mask &= ~CWBackingPlanes; 315 316 if (mask & CWBackingPixel) /* this is really not useful */ 317 mask &= ~CWBackingPixel; 318 319 if (mask & CWOverrideRedirect) 320 attributes.override_redirect = pWin->overrideRedirect; 321 322 if (mask & CWSaveUnder) /* this is really not useful */ 323 mask &= ~CWSaveUnder; 324 325 if (mask & CWEventMask) /* events are handled elsewhere */ 326 mask &= ~CWEventMask; 327 328 if (mask & CWDontPropagate) /* events are handled elsewhere */ 329 mask &= ~CWDontPropagate; 330 331 if (mask & CWColormap) { 332 ColormapPtr pCmap; 333 334 dixLookupResourceByType((void **) &pCmap, wColormap(pWin), 335 RT_COLORMAP, serverClient, DixUseAccess); 336 337 attributes.colormap = xnestColormap(pCmap); 338 339 xnestSetInstalledColormapWindows(pWin->drawable.pScreen); 340 } 341 342 if (mask & CWCursor) /* this is handled in cursor code */ 343 mask &= ~CWCursor; 344 345 if (mask) 346 XChangeWindowAttributes(xnestDisplay, xnestWindow(pWin), 347 mask, &attributes); 348 349 return True; 350 } 351 352 Bool 353 xnestRealizeWindow(WindowPtr pWin) 354 { 355 xnestConfigureWindow(pWin, CWStackingOrder); 356 xnestShapeWindow(pWin); 357 XMapWindow(xnestDisplay, xnestWindow(pWin)); 358 359 return True; 360 } 361 362 Bool 363 xnestUnrealizeWindow(WindowPtr pWin) 364 { 365 XUnmapWindow(xnestDisplay, xnestWindow(pWin)); 366 367 return True; 368 } 369 370 void 371 xnestCopyWindow(WindowPtr pWin, xPoint oldOrigin, RegionPtr oldRegion) 372 { 373 } 374 375 void 376 xnestClipNotify(WindowPtr pWin, int dx, int dy) 377 { 378 xnestConfigureWindow(pWin, CWStackingOrder); 379 xnestShapeWindow(pWin); 380 } 381 382 static Bool 383 xnestWindowExposurePredicate(Display * dpy, XEvent * event, XPointer ptr) 384 { 385 return (event->type == Expose && event->xexpose.window == *(Window *) ptr); 386 } 387 388 void 389 xnestWindowExposures(WindowPtr pWin, RegionPtr pRgn) 390 { 391 XEvent event; 392 Window window; 393 BoxRec Box; 394 395 XSync(xnestDisplay, False); 396 397 window = xnestWindow(pWin); 398 399 while (XCheckIfEvent(xnestDisplay, &event, 400 xnestWindowExposurePredicate, (char *) &window)) { 401 402 Box.x1 = pWin->drawable.x + wBorderWidth(pWin) + event.xexpose.x; 403 Box.y1 = pWin->drawable.y + wBorderWidth(pWin) + event.xexpose.y; 404 Box.x2 = Box.x1 + event.xexpose.width; 405 Box.y2 = Box.y1 + event.xexpose.height; 406 407 event.xexpose.type = ProcessedExpose; 408 409 if (RegionContainsRect(pRgn, &Box) != rgnIN) 410 XPutBackEvent(xnestDisplay, &event); 411 } 412 413 miWindowExposures(pWin, pRgn); 414 } 415 416 void 417 xnestSetShape(WindowPtr pWin, int kind) 418 { 419 xnestShapeWindow(pWin); 420 miSetShape(pWin, kind); 421 } 422 423 static Bool 424 xnestRegionEqual(RegionPtr pReg1, RegionPtr pReg2) 425 { 426 BoxPtr pBox1, pBox2; 427 unsigned int n1, n2; 428 429 if (pReg1 == pReg2) 430 return True; 431 432 if (pReg1 == NullRegion || pReg2 == NullRegion) 433 return False; 434 435 pBox1 = RegionRects(pReg1); 436 n1 = RegionNumRects(pReg1); 437 438 pBox2 = RegionRects(pReg2); 439 n2 = RegionNumRects(pReg2); 440 441 if (n1 != n2) 442 return False; 443 444 if (pBox1 == pBox2) 445 return True; 446 447 if (memcmp(pBox1, pBox2, n1 * sizeof(BoxRec))) 448 return False; 449 450 return True; 451 } 452 453 void 454 xnestShapeWindow(WindowPtr pWin) 455 { 456 Region reg; 457 BoxPtr pBox; 458 XRectangle rect; 459 int i; 460 461 if (!xnestRegionEqual(xnestWindowPriv(pWin)->bounding_shape, 462 wBoundingShape(pWin))) { 463 464 if (wBoundingShape(pWin)) { 465 RegionCopy(xnestWindowPriv(pWin)->bounding_shape, 466 wBoundingShape(pWin)); 467 468 reg = XCreateRegion(); 469 pBox = RegionRects(xnestWindowPriv(pWin)->bounding_shape); 470 for (i = 0; 471 i < RegionNumRects(xnestWindowPriv(pWin)->bounding_shape); 472 i++) { 473 rect.x = pBox[i].x1; 474 rect.y = pBox[i].y1; 475 rect.width = pBox[i].x2 - pBox[i].x1; 476 rect.height = pBox[i].y2 - pBox[i].y1; 477 XUnionRectWithRegion(&rect, reg, reg); 478 } 479 XShapeCombineRegion(xnestDisplay, xnestWindow(pWin), 480 ShapeBounding, 0, 0, reg, ShapeSet); 481 XDestroyRegion(reg); 482 } 483 else { 484 RegionEmpty(xnestWindowPriv(pWin)->bounding_shape); 485 486 XShapeCombineMask(xnestDisplay, xnestWindow(pWin), 487 ShapeBounding, 0, 0, None, ShapeSet); 488 } 489 } 490 491 if (!xnestRegionEqual(xnestWindowPriv(pWin)->clip_shape, wClipShape(pWin))) { 492 493 if (wClipShape(pWin)) { 494 RegionCopy(xnestWindowPriv(pWin)->clip_shape, wClipShape(pWin)); 495 496 reg = XCreateRegion(); 497 pBox = RegionRects(xnestWindowPriv(pWin)->clip_shape); 498 for (i = 0; 499 i < RegionNumRects(xnestWindowPriv(pWin)->clip_shape); i++) { 500 rect.x = pBox[i].x1; 501 rect.y = pBox[i].y1; 502 rect.width = pBox[i].x2 - pBox[i].x1; 503 rect.height = pBox[i].y2 - pBox[i].y1; 504 XUnionRectWithRegion(&rect, reg, reg); 505 } 506 XShapeCombineRegion(xnestDisplay, xnestWindow(pWin), 507 ShapeClip, 0, 0, reg, ShapeSet); 508 XDestroyRegion(reg); 509 } 510 else { 511 RegionEmpty(xnestWindowPriv(pWin)->clip_shape); 512 513 XShapeCombineMask(xnestDisplay, xnestWindow(pWin), 514 ShapeClip, 0, 0, None, ShapeSet); 515 } 516 } 517 }