dmxwindow.c revision 706f2543
11.6Sdante/* 21.1Sjtc * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina. 31.1Sjtc * 41.1Sjtc * All Rights Reserved. 51.5Sdante * 61.3Scgd * Permission is hereby granted, free of charge, to any person obtaining 71.6Sdante * a copy of this software and associated documentation files (the 81.6Sdante * "Software"), to deal in the Software without restriction, including 91.1Sjtc * without limitation on the rights to use, copy, modify, merge, 101.1Sjtc * publish, distribute, sublicense, and/or sell copies of the Software, 11 * and to permit persons to whom the Software is furnished to do so, 12 * subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial 16 * portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS 22 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 23 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 * SOFTWARE. 26 */ 27 28/* 29 * Authors: 30 * Kevin E. Martin <kem@redhat.com> 31 * 32 */ 33 34/** \file 35 * This file provides support for window-related functions. */ 36 37#ifdef HAVE_DMX_CONFIG_H 38#include <dmx-config.h> 39#endif 40 41#include "dmx.h" 42#include "dmxsync.h" 43#include "dmxwindow.h" 44#include "dmxpixmap.h" 45#include "dmxcmap.h" 46#include "dmxvisual.h" 47#include "dmxinput.h" 48#include "dmxextension.h" 49#include "dmxpict.h" 50 51#include "windowstr.h" 52 53static void dmxDoRestackWindow(WindowPtr pWindow); 54static void dmxDoChangeWindowAttributes(WindowPtr pWindow, 55 unsigned long *mask, 56 XSetWindowAttributes *attribs); 57 58static void dmxDoSetShape(WindowPtr pWindow); 59 60/** Initialize the private area for the window functions. */ 61Bool dmxInitWindow(ScreenPtr pScreen) 62{ 63 if (!dixRegisterPrivateKey(&dmxWinPrivateKeyRec, PRIVATE_WINDOW, sizeof(dmxWinPrivRec))) 64 return FALSE; 65 66 return TRUE; 67} 68 69 70Window dmxCreateRootWindow(WindowPtr pWindow) 71{ 72 ScreenPtr pScreen = pWindow->drawable.pScreen; 73 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 74 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); 75 Window parent; 76 Visual *visual; 77 unsigned long mask; 78 XSetWindowAttributes attribs; 79 ColormapPtr pCmap; 80 dmxColormapPrivPtr pCmapPriv; 81 82 /* Create root window */ 83 84 parent = dmxScreen->scrnWin; /* This is our "Screen" window */ 85 visual = dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual; 86 87 dixLookupResourceByType((pointer*) &pCmap, wColormap(pWindow), 88 RT_COLORMAP, NullClient, DixUnknownAccess); 89 pCmapPriv = DMX_GET_COLORMAP_PRIV(pCmap); 90 91 mask = CWEventMask | CWBackingStore | CWColormap | CWBorderPixel; 92 attribs.event_mask = ExposureMask; 93 attribs.backing_store = NotUseful; 94 attribs.colormap = pCmapPriv->cmap; 95 attribs.border_pixel = 0; 96 97 /* Incorporate new attributes, if needed */ 98 if (pWinPriv->attribMask) { 99 dmxDoChangeWindowAttributes(pWindow, &pWinPriv->attribMask, &attribs); 100 mask |= pWinPriv->attribMask; 101 } 102 103 return XCreateWindow(dmxScreen->beDisplay, 104 parent, 105 pWindow->origin.x - wBorderWidth(pWindow), 106 pWindow->origin.y - wBorderWidth(pWindow), 107 pWindow->drawable.width, 108 pWindow->drawable.height, 109 pWindow->borderWidth, 110 pWindow->drawable.depth, 111 pWindow->drawable.class, 112 visual, 113 mask, 114 &attribs); 115} 116 117/** Change the location and size of the "screen" window. Called from 118 * #dmxConfigureScreenWindow(). */ 119void dmxResizeScreenWindow(ScreenPtr pScreen, 120 int x, int y, int w, int h) 121{ 122 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 123 unsigned int m; 124 XWindowChanges c; 125 126 if (!dmxScreen->beDisplay) 127 return; 128 129 /* Handle resizing on back-end server */ 130 m = CWX | CWY | CWWidth | CWHeight; 131 c.x = x; 132 c.y = y; 133 c.width = w; 134 c.height = h; 135 136 XConfigureWindow(dmxScreen->beDisplay, dmxScreen->scrnWin, m, &c); 137 dmxSync(dmxScreen, False); 138} 139 140/** Change the location and size of the "root" window. Called from 141 * #dmxConfigureRootWindow. */ 142void dmxResizeRootWindow(WindowPtr pRoot, 143 int x, int y, int w, int h) 144{ 145 DMXScreenInfo *dmxScreen = &dmxScreens[pRoot->drawable.pScreen->myNum]; 146 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pRoot); 147 unsigned int m; 148 XWindowChanges c; 149 150 /* Handle resizing on back-end server */ 151 if (dmxScreen->beDisplay) { 152 m = CWX | CWY | CWWidth | CWHeight; 153 c.x = x; 154 c.y = y; 155 c.width = (w > 0) ? w : 1; 156 c.height = (h > 0) ? h : 1; 157 158 XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c); 159 } 160 161 if (w == 0 || h == 0) { 162 if (pWinPriv->mapped) { 163 if (dmxScreen->beDisplay) 164 XUnmapWindow(dmxScreen->beDisplay, pWinPriv->window); 165 pWinPriv->mapped = FALSE; 166 } 167 } else if (!pWinPriv->mapped) { 168 if (dmxScreen->beDisplay) 169 XMapWindow(dmxScreen->beDisplay, pWinPriv->window); 170 pWinPriv->mapped = TRUE; 171 } 172 173 if (dmxScreen->beDisplay) 174 dmxSync(dmxScreen, False); 175} 176 177void dmxGetDefaultWindowAttributes(WindowPtr pWindow, 178 Colormap *cmap, 179 Visual **visual) 180{ 181 ScreenPtr pScreen = pWindow->drawable.pScreen; 182 183 if (pWindow->drawable.class != InputOnly && 184 pWindow->optional && 185 pWindow->optional->visual != wVisual(pWindow->parent)) { 186 187 /* Find the matching visual */ 188 *visual = dmxLookupVisualFromID(pScreen, wVisual(pWindow)); 189 190 /* Handle optional colormaps */ 191 if (pWindow->optional->colormap) { 192 ColormapPtr pCmap; 193 dmxColormapPrivPtr pCmapPriv; 194 195 dixLookupResourceByType((pointer*) &pCmap, wColormap(pWindow), 196 RT_COLORMAP, NullClient, DixUnknownAccess); 197 pCmapPriv = DMX_GET_COLORMAP_PRIV(pCmap); 198 *cmap = pCmapPriv->cmap; 199 } else { 200 *cmap = dmxColormapFromDefaultVisual(pScreen, *visual); 201 } 202 } else { 203 *visual = CopyFromParent; 204 *cmap = (Colormap)0; 205 } 206} 207 208static Window dmxCreateNonRootWindow(WindowPtr pWindow) 209{ 210 ScreenPtr pScreen = pWindow->drawable.pScreen; 211 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 212 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); 213 Window parent; 214 unsigned long mask = 0L; 215 XSetWindowAttributes attribs; 216 dmxWinPrivPtr pParentPriv = DMX_GET_WINDOW_PRIV(pWindow->parent); 217 218 /* Create window on back-end server */ 219 220 parent = pParentPriv->window; 221 222 /* The parent won't exist if this call to CreateNonRootWindow came 223 from ReparentWindow and the grandparent window has not yet been 224 created */ 225 if (!parent) { 226 dmxCreateAndRealizeWindow(pWindow->parent, FALSE); 227 parent = pParentPriv->window; 228 } 229 230 /* Incorporate new attributes, if needed */ 231 if (pWinPriv->attribMask) { 232 dmxDoChangeWindowAttributes(pWindow, &pWinPriv->attribMask, &attribs); 233 mask |= pWinPriv->attribMask; 234 } 235 236 /* Add in default attributes */ 237 if (pWindow->drawable.class != InputOnly) { 238 mask |= CWBackingStore; 239 attribs.backing_store = NotUseful; 240 241 if (!(mask & CWColormap) && pWinPriv->cmap) { 242 mask |= CWColormap; 243 attribs.colormap = pWinPriv->cmap; 244 if (!(mask & CWBorderPixel)) { 245 mask |= CWBorderPixel; 246 attribs.border_pixel = 0; 247 } 248 } 249 } 250 251 /* Handle case where subwindows are being mapped, but created out of 252 order -- if current window has a previous sibling, then it cannot 253 be created on top of the stack, so we must restack the windows */ 254 pWinPriv->restacked = (pWindow->prevSib != NullWindow); 255 256 return XCreateWindow(dmxScreen->beDisplay, 257 parent, 258 pWindow->origin.x - wBorderWidth(pWindow), 259 pWindow->origin.y - wBorderWidth(pWindow), 260 pWindow->drawable.width, 261 pWindow->drawable.height, 262 pWindow->borderWidth, 263 pWindow->drawable.depth, 264 pWindow->drawable.class, 265 pWinPriv->visual, 266 mask, 267 &attribs); 268} 269 270/** This function handles lazy window creation and realization. Window 271 * creation is handled by #dmxCreateNonRootWindow(). It also handles 272 * any stacking changes that have occured since the window was 273 * originally created by calling #dmxDoRestackWindow(). If the window 274 * is shaped, the shape is set on the back-end server by calling 275 * #dmxDoSetShape(), and if the window has pictures (from RENDER) 276 * associated with it, those pictures are created on the back-end 277 * server by calling #dmxCreatePictureList(). If \a doSync is TRUE, 278 * then #dmxSync() is called. */ 279void dmxCreateAndRealizeWindow(WindowPtr pWindow, Bool doSync) 280{ 281 ScreenPtr pScreen = pWindow->drawable.pScreen; 282 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 283 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); 284 285 if (!dmxScreen->beDisplay) return; 286 287 pWinPriv->window = dmxCreateNonRootWindow(pWindow); 288 if (pWinPriv->restacked) dmxDoRestackWindow(pWindow); 289 if (pWinPriv->isShaped) dmxDoSetShape(pWindow); 290 if (pWinPriv->hasPict) dmxCreatePictureList(pWindow); 291 if (pWinPriv->mapped) XMapWindow(dmxScreen->beDisplay, 292 pWinPriv->window); 293 if (doSync) dmxSync(dmxScreen, False); 294} 295 296/** Create \a pWindow on the back-end server. If the lazy window 297 * creation optimization is enabled, then the actual creation and 298 * realization of the window is handled by 299 * #dmxCreateAndRealizeWindow(). */ 300Bool dmxCreateWindow(WindowPtr pWindow) 301{ 302 ScreenPtr pScreen = pWindow->drawable.pScreen; 303 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 304 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); 305 Bool ret = TRUE; 306 307 DMX_UNWRAP(CreateWindow, dmxScreen, pScreen); 308#if 0 309 if (pScreen->CreateWindow) 310 ret = pScreen->CreateWindow(pWindow); 311#endif 312 313 /* Set up the defaults */ 314 pWinPriv->window = (Window)0; 315 pWinPriv->offscreen = TRUE; 316 pWinPriv->mapped = FALSE; 317 pWinPriv->restacked = FALSE; 318 pWinPriv->attribMask = 0; 319 pWinPriv->isShaped = FALSE; 320 pWinPriv->hasPict = FALSE; 321#ifdef GLXEXT 322 pWinPriv->swapGroup = NULL; 323 pWinPriv->barrier = 0; 324#endif 325 326 if (dmxScreen->beDisplay) { 327 /* Only create the root window at this stage -- non-root windows are 328 created when they are mapped and are on-screen */ 329 if (!pWindow->parent) { 330 dmxScreen->rootWin = pWinPriv->window 331 = dmxCreateRootWindow(pWindow); 332 if (dmxScreen->scrnX != dmxScreen->rootX 333 || dmxScreen->scrnY != dmxScreen->rootY 334 || dmxScreen->scrnWidth != dmxScreen->rootWidth 335 || dmxScreen->scrnHeight != dmxScreen->rootHeight) { 336 dmxResizeRootWindow(pWindow, 337 dmxScreen->rootX, 338 dmxScreen->rootY, 339 dmxScreen->rootWidth, 340 dmxScreen->rootHeight); 341 dmxUpdateScreenResources(screenInfo.screens[dmxScreen->index], 342 dmxScreen->rootX, 343 dmxScreen->rootY, 344 dmxScreen->rootWidth, 345 dmxScreen->rootHeight); 346 pWindow->origin.x = dmxScreen->rootX; 347 pWindow->origin.y = dmxScreen->rootY; 348 } 349 } else { 350 dmxGetDefaultWindowAttributes(pWindow, 351 &pWinPriv->cmap, 352 &pWinPriv->visual); 353 354 if (dmxLazyWindowCreation) { 355 /* Save parent's visual for use later */ 356 if (pWinPriv->visual == CopyFromParent) 357 pWinPriv->visual = 358 dmxLookupVisualFromID(pScreen, 359 wVisual(pWindow->parent)); 360 } else { 361 pWinPriv->window = dmxCreateNonRootWindow(pWindow); 362 } 363 } 364 365 dmxSync(dmxScreen, False); 366 } 367 368 DMX_WRAP(CreateWindow, dmxCreateWindow, dmxScreen, pScreen); 369 370 return ret; 371} 372 373/** Destroy \a pWindow on the back-end server. */ 374Bool dmxBEDestroyWindow(WindowPtr pWindow) 375{ 376 ScreenPtr pScreen = pWindow->drawable.pScreen; 377 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 378 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); 379 380 if (pWinPriv->window) { 381 XDestroyWindow(dmxScreen->beDisplay, pWinPriv->window); 382 pWinPriv->window = (Window)0; 383 return TRUE; 384 } 385 386 return FALSE; 387} 388 389/** Destroy \a pWindow on the back-end server. If any RENDER pictures 390 were created, destroy them as well. */ 391Bool dmxDestroyWindow(WindowPtr pWindow) 392{ 393 ScreenPtr pScreen = pWindow->drawable.pScreen; 394 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 395 Bool ret = TRUE; 396 Bool needSync = FALSE; 397#ifdef GLXEXT 398 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); 399#endif 400 401 DMX_UNWRAP(DestroyWindow, dmxScreen, pScreen); 402 403 /* Destroy any picture list associated with this window */ 404 needSync |= dmxDestroyPictureList(pWindow); 405 406 /* Destroy window on back-end server */ 407 needSync |= dmxBEDestroyWindow(pWindow); 408 if (needSync) dmxSync(dmxScreen, FALSE); 409 410#ifdef GLXEXT 411 if (pWinPriv->swapGroup && pWinPriv->windowDestroyed) 412 pWinPriv->windowDestroyed(pWindow); 413#endif 414 415 if (pScreen->DestroyWindow) 416 ret = pScreen->DestroyWindow(pWindow); 417 418 DMX_WRAP(DestroyWindow, dmxDestroyWindow, dmxScreen, pScreen); 419 420 return ret; 421} 422 423/** Change the position of \a pWindow to be \a x, \a y. */ 424Bool dmxPositionWindow(WindowPtr pWindow, int x, int y) 425{ 426 ScreenPtr pScreen = pWindow->drawable.pScreen; 427 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 428 Bool ret = TRUE; 429 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); 430 unsigned int m; 431 XWindowChanges c; 432 433 DMX_UNWRAP(PositionWindow, dmxScreen, pScreen); 434#if 0 435 if (pScreen->PositionWindow) 436 ret = pScreen->PositionWindow(pWindow, x, y); 437#endif 438 439 /* Determine if the window is completely off the visible portion of 440 the screen */ 441 pWinPriv->offscreen = DMX_WINDOW_OFFSCREEN(pWindow); 442 443 /* If the window is now on-screen and it is mapped and it has not 444 been created yet, create it and map it */ 445 if (!pWinPriv->window && pWinPriv->mapped && !pWinPriv->offscreen) { 446 dmxCreateAndRealizeWindow(pWindow, TRUE); 447 } else if (pWinPriv->window) { 448 /* Position window on back-end server */ 449 m = CWX | CWY | CWWidth | CWHeight; 450 c.x = pWindow->origin.x - wBorderWidth(pWindow); 451 c.y = pWindow->origin.y - wBorderWidth(pWindow); 452 c.width = pWindow->drawable.width; 453 c.height = pWindow->drawable.height; 454 if (pWindow->drawable.class != InputOnly) { 455 m |= CWBorderWidth; 456 c.border_width = pWindow->borderWidth; 457 } 458 459 XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c); 460 dmxSync(dmxScreen, False); 461 } 462 463 DMX_WRAP(PositionWindow, dmxPositionWindow, dmxScreen, pScreen); 464 465 return ret; 466} 467 468static void dmxDoChangeWindowAttributes(WindowPtr pWindow, 469 unsigned long *mask, 470 XSetWindowAttributes *attribs) 471{ 472 dmxPixPrivPtr pPixPriv; 473 474 if (*mask & CWBackPixmap) { 475 switch (pWindow->backgroundState) { 476 case None: 477 attribs->background_pixmap = None; 478 break; 479 480 case ParentRelative: 481 attribs->background_pixmap = ParentRelative; 482 break; 483 484 case BackgroundPixmap: 485 pPixPriv = DMX_GET_PIXMAP_PRIV(pWindow->background.pixmap); 486 attribs->background_pixmap = pPixPriv->pixmap; 487 break; 488 489 case BackgroundPixel: 490 *mask &= ~CWBackPixmap; 491 break; 492 } 493 } 494 495 if (*mask & CWBackPixel) { 496 if (pWindow->backgroundState == BackgroundPixel) 497 attribs->background_pixel = pWindow->background.pixel; 498 else 499 *mask &= ~CWBackPixel; 500 } 501 502 if (*mask & CWBorderPixmap) { 503 if (pWindow->borderIsPixel) 504 *mask &= ~CWBorderPixmap; 505 else { 506 pPixPriv = DMX_GET_PIXMAP_PRIV(pWindow->border.pixmap); 507 attribs->border_pixmap = pPixPriv->pixmap; 508 } 509 } 510 511 if (*mask & CWBorderPixel) { 512 if (pWindow->borderIsPixel) 513 attribs->border_pixel = pWindow->border.pixel; 514 else 515 *mask &= ~CWBorderPixel; 516 } 517 518 if (*mask & CWBitGravity) 519 attribs->bit_gravity = pWindow->bitGravity; 520 521 if (*mask & CWWinGravity) 522 *mask &= ~CWWinGravity; /* Handled by dix */ 523 524 if (*mask & CWBackingStore) 525 *mask &= ~CWBackingStore; /* Backing store not supported */ 526 527 if (*mask & CWBackingPlanes) 528 *mask &= ~CWBackingPlanes; /* Backing store not supported */ 529 530 if (*mask & CWBackingPixel) 531 *mask &= ~CWBackingPixel; /* Backing store not supported */ 532 533 if (*mask & CWOverrideRedirect) 534 attribs->override_redirect = pWindow->overrideRedirect; 535 536 if (*mask & CWSaveUnder) 537 *mask &= ~CWSaveUnder; /* Save unders not supported */ 538 539 if (*mask & CWEventMask) 540 *mask &= ~CWEventMask; /* Events are handled by dix */ 541 542 if (*mask & CWDontPropagate) 543 *mask &= ~CWDontPropagate; /* Events are handled by dix */ 544 545 if (*mask & CWColormap) { 546 ColormapPtr pCmap; 547 dmxColormapPrivPtr pCmapPriv; 548 549 dixLookupResourceByType((pointer*) &pCmap, wColormap(pWindow), 550 RT_COLORMAP, NullClient, DixUnknownAccess); 551 pCmapPriv = DMX_GET_COLORMAP_PRIV(pCmap); 552 attribs->colormap = pCmapPriv->cmap; 553 } 554 555 if (*mask & CWCursor) 556 *mask &= ~CWCursor; /* Handled by the cursor code */ 557} 558 559/** Change the window attributes of \a pWindow. */ 560Bool dmxChangeWindowAttributes(WindowPtr pWindow, unsigned long mask) 561{ 562 ScreenPtr pScreen = pWindow->drawable.pScreen; 563 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 564 Bool ret = TRUE; 565 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); 566 XSetWindowAttributes attribs; 567 568 DMX_UNWRAP(ChangeWindowAttributes, dmxScreen, pScreen); 569#if 0 570 if (pScreen->ChangeWindowAttributes) 571 ret = pScreen->ChangeWindowAttributes(pWindow, mask); 572#endif 573 574 /* Change window attribs on back-end server */ 575 dmxDoChangeWindowAttributes(pWindow, &mask, &attribs); 576 577 /* Save mask for lazy window creation optimization */ 578 pWinPriv->attribMask |= mask; 579 580 if (mask && pWinPriv->window) { 581 XChangeWindowAttributes(dmxScreen->beDisplay, pWinPriv->window, 582 mask, &attribs); 583 dmxSync(dmxScreen, False); 584 } 585 586 DMX_WRAP(ChangeWindowAttributes, dmxChangeWindowAttributes, dmxScreen, 587 pScreen); 588 589 return ret; 590} 591 592/** Realize \a pWindow on the back-end server. If the lazy window 593 * creation optimization is enabled, the window is only realized when 594 * it at least partially overlaps the screen. */ 595Bool dmxRealizeWindow(WindowPtr pWindow) 596{ 597 ScreenPtr pScreen = pWindow->drawable.pScreen; 598 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 599 Bool ret = TRUE; 600 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); 601 602 DMX_UNWRAP(RealizeWindow, dmxScreen, pScreen); 603#if 0 604 if (pScreen->RealizeWindow) 605 ret = pScreen->RealizeWindow(pWindow); 606#endif 607 608 /* Determine if the window is completely off the visible portion of 609 the screen */ 610 pWinPriv->offscreen = DMX_WINDOW_OFFSCREEN(pWindow); 611 612 /* If the window hasn't been created and it's not offscreen, then 613 create it */ 614 if (!pWinPriv->window && !pWinPriv->offscreen) { 615 dmxCreateAndRealizeWindow(pWindow, FALSE); 616 } 617 618 if (pWinPriv->window) { 619 /* Realize window on back-end server */ 620 XMapWindow(dmxScreen->beDisplay, pWinPriv->window); 621 dmxSync(dmxScreen, False); 622 } 623 624 /* Let the other functions know that the window is now mapped */ 625 pWinPriv->mapped = TRUE; 626 627 DMX_WRAP(RealizeWindow, dmxRealizeWindow, dmxScreen, pScreen); 628 629 dmxUpdateWindowInfo(DMX_UPDATE_REALIZE, pWindow); 630 return ret; 631} 632 633/** Unrealize \a pWindow on the back-end server. */ 634Bool dmxUnrealizeWindow(WindowPtr pWindow) 635{ 636 ScreenPtr pScreen = pWindow->drawable.pScreen; 637 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 638 Bool ret = TRUE; 639 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); 640 641 DMX_UNWRAP(UnrealizeWindow, dmxScreen, pScreen); 642#if 0 643 if (pScreen->UnrealizeWindow) 644 ret = pScreen->UnrealizeWindow(pWindow); 645#endif 646 647 if (pWinPriv->window) { 648 /* Unrealize window on back-end server */ 649 XUnmapWindow(dmxScreen->beDisplay, pWinPriv->window); 650 dmxSync(dmxScreen, False); 651 } 652 653 /* When unrealized (i.e., unmapped), the window is always considered 654 off of the visible portion of the screen */ 655 pWinPriv->offscreen = TRUE; 656 pWinPriv->mapped = FALSE; 657 658#ifdef GLXEXT 659 if (pWinPriv->swapGroup && pWinPriv->windowUnmapped) 660 pWinPriv->windowUnmapped(pWindow); 661#endif 662 663 DMX_WRAP(UnrealizeWindow, dmxUnrealizeWindow, dmxScreen, pScreen); 664 665 dmxUpdateWindowInfo(DMX_UPDATE_UNREALIZE, pWindow); 666 return ret; 667} 668 669static void dmxDoRestackWindow(WindowPtr pWindow) 670{ 671 ScreenPtr pScreen = pWindow->drawable.pScreen; 672 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 673 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); 674 WindowPtr pNextSib = pWindow->nextSib; 675 unsigned int m; 676 XWindowChanges c; 677 678 if (pNextSib == NullWindow) { 679 /* Window is at the bottom of the stack */ 680 m = CWStackMode; 681 c.sibling = (Window)0; 682 c.stack_mode = Below; 683 XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c); 684 } else { 685 /* Window is not at the bottom of the stack */ 686 dmxWinPrivPtr pNextSibPriv = DMX_GET_WINDOW_PRIV(pNextSib); 687 688 /* Handle case where siblings have not yet been created due to 689 lazy window creation optimization by first finding the next 690 sibling in the sibling list that has been created (if any) 691 and then putting the current window just above that sibling, 692 and if no next siblings have been created yet, then put it at 693 the bottom of the stack (since it might have a previous 694 sibling that should be above it). */ 695 while (!pNextSibPriv->window) { 696 pNextSib = pNextSib->nextSib; 697 if (pNextSib == NullWindow) { 698 /* Window is at the bottom of the stack */ 699 m = CWStackMode; 700 c.sibling = (Window)0; 701 c.stack_mode = Below; 702 XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c); 703 return; 704 } 705 pNextSibPriv = DMX_GET_WINDOW_PRIV(pNextSib); 706 } 707 708 m = CWStackMode | CWSibling; 709 c.sibling = pNextSibPriv->window; 710 c.stack_mode = Above; 711 XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c); 712 } 713} 714 715/** Handle window restacking. The actual restacking occurs in 716 * #dmxDoRestackWindow(). */ 717void dmxRestackWindow(WindowPtr pWindow, WindowPtr pOldNextSib) 718{ 719 ScreenPtr pScreen = pWindow->drawable.pScreen; 720 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 721 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); 722 723 DMX_UNWRAP(RestackWindow, dmxScreen, pScreen); 724#if 0 725 if (pScreen->RestackWindow) 726 pScreen->RestackWindow(pWindow, pOldNextSib); 727#endif 728 729 if (pOldNextSib != pWindow->nextSib) { 730 /* Track restacking for lazy window creation optimization */ 731 pWinPriv->restacked = TRUE; 732 733 /* Restack window on back-end server */ 734 if (pWinPriv->window) { 735 dmxDoRestackWindow(pWindow); 736 dmxSync(dmxScreen, False); 737 } 738 } 739 740 DMX_WRAP(RestackWindow, dmxRestackWindow, dmxScreen, pScreen); 741 dmxUpdateWindowInfo(DMX_UPDATE_RESTACK, pWindow); 742} 743 744static Bool dmxWindowExposurePredicate(Display *dpy, XEvent *ev, XPointer ptr) 745{ 746 return (ev->type == Expose && ev->xexpose.window == *(Window *)ptr); 747} 748 749/** Handle exposures on \a pWindow. Since window exposures are handled 750 * in DMX, the events that are generated by the back-end server are 751 * redundant, so we eat them here. */ 752void dmxWindowExposures(WindowPtr pWindow, RegionPtr prgn, 753 RegionPtr other_exposed) 754{ 755 ScreenPtr pScreen = pWindow->drawable.pScreen; 756 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 757 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); 758 XEvent ev; 759 760 DMX_UNWRAP(WindowExposures, dmxScreen, pScreen); 761 762 dmxSync(dmxScreen, False); 763 764 if (pWinPriv->window) { 765 while (XCheckIfEvent(dmxScreen->beDisplay, &ev, 766 dmxWindowExposurePredicate, 767 (XPointer)&pWinPriv->window)) { 768 /* Handle expose events -- this should not be necessary 769 since the base window in which the root window was 770 created is guaranteed to be on top (override_redirect), 771 so we should just swallow these events. If for some 772 reason the window is not on top, then we'd need to 773 collect these events and send them to the client later 774 (e.g., during the block handler as Xnest does). */ 775 } 776 } 777 778#if 1 779 if (pScreen->WindowExposures) 780 pScreen->WindowExposures(pWindow, prgn, other_exposed); 781#endif 782 DMX_WRAP(WindowExposures, dmxWindowExposures, dmxScreen, pScreen); 783} 784 785/** Move \a pWindow on the back-end server. Determine whether or not it 786 * is on or offscreen, and realize it if it is newly on screen and the 787 * lazy window creation optimization is enabled. */ 788void dmxCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc) 789{ 790 ScreenPtr pScreen = pWindow->drawable.pScreen; 791 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 792 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); 793 unsigned int m; 794 XWindowChanges c; 795 796 DMX_UNWRAP(CopyWindow, dmxScreen, pScreen); 797#if 0 798 if (pScreen->CopyWindow) 799 pScreen->CopyWindow(pWindow, ptOldOrg, prgnSrc); 800#endif 801 802 /* Determine if the window is completely off the visible portion of 803 the screen */ 804 pWinPriv->offscreen = DMX_WINDOW_OFFSCREEN(pWindow); 805 806 /* If the window is now on-screen and it is mapped and it has not 807 been created yet, create it and map it */ 808 if (!pWinPriv->window && pWinPriv->mapped && !pWinPriv->offscreen) { 809 dmxCreateAndRealizeWindow(pWindow, TRUE); 810 } else if (pWinPriv->window) { 811 /* Move window on back-end server */ 812 m = CWX | CWY | CWWidth | CWHeight; 813 c.x = pWindow->origin.x - wBorderWidth(pWindow); 814 c.y = pWindow->origin.y - wBorderWidth(pWindow); 815 c.width = pWindow->drawable.width; 816 c.height = pWindow->drawable.height; 817 818 XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c); 819 dmxSync(dmxScreen, False); 820 } 821 822 DMX_WRAP(CopyWindow, dmxCopyWindow, dmxScreen, pScreen); 823 dmxUpdateWindowInfo(DMX_UPDATE_COPY, pWindow); 824} 825 826/** Resize \a pWindow on the back-end server. Determine whether or not 827 * it is on or offscreen, and realize it if it is newly on screen and 828 * the lazy window creation optimization is enabled. */ 829void dmxResizeWindow(WindowPtr pWindow, int x, int y, 830 unsigned int w, unsigned int h, WindowPtr pSib) 831{ 832 ScreenPtr pScreen = pWindow->drawable.pScreen; 833 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 834 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); 835 dmxWinPrivPtr pSibPriv; 836 unsigned int m; 837 XWindowChanges c; 838 839 if (pSib) 840 pSibPriv = DMX_GET_WINDOW_PRIV(pSib); 841 842 DMX_UNWRAP(ResizeWindow, dmxScreen, pScreen); 843#if 1 844 if (pScreen->ResizeWindow) 845 pScreen->ResizeWindow(pWindow, x, y, w, h, pSib); 846#endif 847 848 /* Determine if the window is completely off the visible portion of 849 the screen */ 850 pWinPriv->offscreen = DMX_WINDOW_OFFSCREEN(pWindow); 851 852 /* If the window is now on-screen and it is mapped and it has not 853 been created yet, create it and map it */ 854 if (!pWinPriv->window && pWinPriv->mapped && !pWinPriv->offscreen) { 855 dmxCreateAndRealizeWindow(pWindow, TRUE); 856 } else if (pWinPriv->window) { 857 /* Handle resizing on back-end server */ 858 m = CWX | CWY | CWWidth | CWHeight; 859 c.x = pWindow->origin.x - wBorderWidth(pWindow); 860 c.y = pWindow->origin.y - wBorderWidth(pWindow); 861 c.width = pWindow->drawable.width; 862 c.height = pWindow->drawable.height; 863 864 XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c); 865 dmxSync(dmxScreen, False); 866 } 867 868 DMX_WRAP(ResizeWindow, dmxResizeWindow, dmxScreen, pScreen); 869 dmxUpdateWindowInfo(DMX_UPDATE_RESIZE, pWindow); 870} 871 872/** Reparent \a pWindow on the back-end server. */ 873void dmxReparentWindow(WindowPtr pWindow, WindowPtr pPriorParent) 874{ 875 ScreenPtr pScreen = pWindow->drawable.pScreen; 876 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 877 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); 878 dmxWinPrivPtr pParentPriv = DMX_GET_WINDOW_PRIV(pWindow->parent); 879 880 DMX_UNWRAP(ReparentWindow, dmxScreen, pScreen); 881#if 0 882 if (pScreen->ReparentWindow) 883 pScreen->ReparentWindow(pWindow, pPriorParent); 884#endif 885 886 if (pWinPriv->window) { 887 if (!pParentPriv->window) { 888 dmxCreateAndRealizeWindow(pWindow->parent, FALSE); 889 } 890 891 /* Handle reparenting on back-end server */ 892 XReparentWindow(dmxScreen->beDisplay, pWinPriv->window, 893 pParentPriv->window, 894 pWindow->origin.x - wBorderWidth(pWindow), 895 pWindow->origin.x - wBorderWidth(pWindow)); 896 dmxSync(dmxScreen, False); 897 } 898 899 DMX_WRAP(ReparentWindow, dmxReparentWindow, dmxScreen, pScreen); 900 dmxUpdateWindowInfo(DMX_UPDATE_REPARENT, pWindow); 901} 902 903/** Change border width for \a pWindow to \a width pixels. */ 904void dmxChangeBorderWidth(WindowPtr pWindow, unsigned int width) 905{ 906 ScreenPtr pScreen = pWindow->drawable.pScreen; 907 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 908 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); 909 unsigned int m; 910 XWindowChanges c; 911 912 DMX_UNWRAP(ChangeBorderWidth, dmxScreen, pScreen); 913#if 1 914 if (pScreen->ChangeBorderWidth) 915 pScreen->ChangeBorderWidth(pWindow, width); 916#endif 917 918 /* NOTE: Do we need to check for on/off screen here? */ 919 920 if (pWinPriv->window) { 921 /* Handle border width change on back-end server */ 922 m = CWBorderWidth; 923 c.border_width = width; 924 925 XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c); 926 dmxSync(dmxScreen, False); 927 } 928 929 DMX_WRAP(ChangeBorderWidth, dmxChangeBorderWidth, dmxScreen, pScreen); 930} 931 932static void dmxDoSetShape(WindowPtr pWindow) 933{ 934 ScreenPtr pScreen = pWindow->drawable.pScreen; 935 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 936 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); 937 int nBox; 938 BoxPtr pBox; 939 int nRect; 940 XRectangle *pRect; 941 XRectangle *pRectFirst; 942 943 /* First, set the bounding shape */ 944 if (wBoundingShape(pWindow)) { 945 pBox = RegionRects(wBoundingShape(pWindow)); 946 nRect = nBox = RegionNumRects(wBoundingShape(pWindow)); 947 pRectFirst = pRect = malloc(nRect * sizeof(*pRect)); 948 while (nBox--) { 949 pRect->x = pBox->x1; 950 pRect->y = pBox->y1; 951 pRect->width = pBox->x2 - pBox->x1; 952 pRect->height = pBox->y2 - pBox->y1; 953 pBox++; 954 pRect++; 955 } 956 XShapeCombineRectangles(dmxScreen->beDisplay, pWinPriv->window, 957 ShapeBounding, 0, 0, 958 pRectFirst, nRect, 959 ShapeSet, YXBanded); 960 free(pRectFirst); 961 } else { 962 XShapeCombineMask(dmxScreen->beDisplay, pWinPriv->window, 963 ShapeBounding, 0, 0, None, ShapeSet); 964 } 965 966 /* Next, set the clip shape */ 967 if (wClipShape(pWindow)) { 968 pBox = RegionRects(wClipShape(pWindow)); 969 nRect = nBox = RegionNumRects(wClipShape(pWindow)); 970 pRectFirst = pRect = malloc(nRect * sizeof(*pRect)); 971 while (nBox--) { 972 pRect->x = pBox->x1; 973 pRect->y = pBox->y1; 974 pRect->width = pBox->x2 - pBox->x1; 975 pRect->height = pBox->y2 - pBox->y1; 976 pBox++; 977 pRect++; 978 } 979 XShapeCombineRectangles(dmxScreen->beDisplay, pWinPriv->window, 980 ShapeClip, 0, 0, 981 pRectFirst, nRect, 982 ShapeSet, YXBanded); 983 free(pRectFirst); 984 } else { 985 XShapeCombineMask(dmxScreen->beDisplay, pWinPriv->window, 986 ShapeClip, 0, 0, None, ShapeSet); 987 } 988 989 if (XShapeInputSelected(dmxScreen->beDisplay, pWinPriv->window)) { 990 ErrorF("Input selected for window %x on Screen %d\n", 991 (unsigned int)pWinPriv->window, pScreen->myNum); 992 } 993} 994 995/** Set shape of \a pWindow on the back-end server. */ 996void dmxSetShape(WindowPtr pWindow, int kind) 997{ 998 ScreenPtr pScreen = pWindow->drawable.pScreen; 999 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 1000 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); 1001 1002 DMX_UNWRAP(SetShape, dmxScreen, pScreen); 1003#if 1 1004 if (pScreen->SetShape) 1005 pScreen->SetShape(pWindow, kind); 1006#endif 1007 1008 if (pWinPriv->window) { 1009 /* Handle setting the current shape on the back-end server */ 1010 dmxDoSetShape(pWindow); 1011 dmxSync(dmxScreen, False); 1012 } else { 1013 pWinPriv->isShaped = TRUE; 1014 } 1015 1016 DMX_WRAP(SetShape, dmxSetShape, dmxScreen, pScreen); 1017} 1018