miwindow.c revision 05b261ec
1/*********************************************************** 2 3Copyright 1987, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included in 12all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21Except as contained in this notice, the name of The Open Group shall not be 22used in advertising or otherwise to promote the sale, use or other dealings 23in this Software without prior written authorization from The Open Group. 24 25 26Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. 27 28 All Rights Reserved 29 30Permission to use, copy, modify, and distribute this software and its 31documentation for any purpose and without fee is hereby granted, 32provided that the above copyright notice appear in all copies and that 33both that copyright notice and this permission notice appear in 34supporting documentation, and that the name of Digital not be 35used in advertising or publicity pertaining to distribution of the 36software without specific, written prior permission. 37 38DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 39ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 40DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 41ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 42WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 43ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 44SOFTWARE. 45 46******************************************************************/ 47#ifdef HAVE_DIX_CONFIG_H 48#include <dix-config.h> 49#endif 50 51#include <X11/X.h> 52#include "regionstr.h" 53#include "region.h" 54#include "mi.h" 55#include "windowstr.h" 56#include "scrnintstr.h" 57#include "pixmapstr.h" 58#include "mivalidate.h" 59 60_X_EXPORT void 61miClearToBackground(pWin, x, y, w, h, generateExposures) 62 WindowPtr pWin; 63 int x,y; 64 int w,h; 65 Bool generateExposures; 66{ 67 BoxRec box; 68 RegionRec reg; 69 RegionPtr pBSReg = NullRegion; 70 ScreenPtr pScreen; 71 BoxPtr extents; 72 int x1, y1, x2, y2; 73 74 /* compute everything using ints to avoid overflow */ 75 76 x1 = pWin->drawable.x + x; 77 y1 = pWin->drawable.y + y; 78 if (w) 79 x2 = x1 + (int) w; 80 else 81 x2 = x1 + (int) pWin->drawable.width - (int) x; 82 if (h) 83 y2 = y1 + h; 84 else 85 y2 = y1 + (int) pWin->drawable.height - (int) y; 86 87 extents = &pWin->clipList.extents; 88 89 /* clip the resulting rectangle to the window clipList extents. This 90 * makes sure that the result will fit in a box, given that the 91 * screen is < 32768 on a side. 92 */ 93 94 if (x1 < extents->x1) 95 x1 = extents->x1; 96 if (x2 > extents->x2) 97 x2 = extents->x2; 98 if (y1 < extents->y1) 99 y1 = extents->y1; 100 if (y2 > extents->y2) 101 y2 = extents->y2; 102 103 if (x2 <= x1 || y2 <= y1) 104 { 105 x2 = x1 = 0; 106 y2 = y1 = 0; 107 } 108 109 box.x1 = x1; 110 box.x2 = x2; 111 box.y1 = y1; 112 box.y2 = y2; 113 114 pScreen = pWin->drawable.pScreen; 115 REGION_INIT(pScreen, ®, &box, 1); 116 if (pWin->backStorage) 117 { 118 /* 119 * If the window has backing-store on, call through the 120 * ClearToBackground vector to handle the special semantics 121 * (i.e. things backing store is to be cleared out and 122 * an Expose event is to be generated for those areas in backing 123 * store if generateExposures is TRUE). 124 */ 125 pBSReg = (* pScreen->ClearBackingStore)(pWin, x, y, w, h, 126 generateExposures); 127 } 128 129 REGION_INTERSECT(pScreen, ®, ®, &pWin->clipList); 130 if (generateExposures) 131 (*pScreen->WindowExposures)(pWin, ®, pBSReg); 132 else if (pWin->backgroundState != None) 133 (*pScreen->PaintWindowBackground)(pWin, ®, PW_BACKGROUND); 134 REGION_UNINIT(pScreen, ®); 135 if (pBSReg) 136 REGION_DESTROY(pScreen, pBSReg); 137} 138 139/* 140 * For SaveUnders using backing-store. The idea is that when a window is mapped 141 * with saveUnder set TRUE, any windows it obscures will have its backing 142 * store turned on setting the DIXsaveUnder bit, 143 * The backing-store code must be written to allow for this 144 */ 145 146/*- 147 *----------------------------------------------------------------------- 148 * miCheckSubSaveUnder -- 149 * Check all the inferiors of a window for coverage by saveUnder 150 * windows. Called from ChangeSaveUnder and CheckSaveUnder. 151 * This code is very inefficient. 152 * 153 * Results: 154 * TRUE if any windows need to have backing-store removed. 155 * 156 * Side Effects: 157 * Windows may have backing-store turned on or off. 158 * 159 *----------------------------------------------------------------------- 160 */ 161static Bool 162miCheckSubSaveUnder( 163 WindowPtr pParent, /* Parent to check */ 164 WindowPtr pFirst, /* first reconfigured window */ 165 RegionPtr pRegion) /* Initial area obscured by saveUnder */ 166{ 167 WindowPtr pChild; /* Current child */ 168 ScreenPtr pScreen; /* Screen to use */ 169 RegionRec SubRegion; /* Area of children obscured */ 170 Bool res = FALSE; /* result */ 171 Bool subInited=FALSE;/* SubRegion initialized */ 172 173 pScreen = pParent->drawable.pScreen; 174 if ( (pChild = pParent->firstChild) ) 175 { 176 /* 177 * build region above first changed window 178 */ 179 180 for (; pChild != pFirst; pChild = pChild->nextSib) 181 if (pChild->viewable && pChild->saveUnder) 182 REGION_UNION(pScreen, pRegion, pRegion, &pChild->borderSize); 183 184 /* 185 * check region below and including first changed window 186 */ 187 188 for (; pChild; pChild = pChild->nextSib) 189 { 190 if (pChild->viewable) 191 { 192 /* 193 * don't save under nephew/niece windows; 194 * use a separate region 195 */ 196 197 if (pChild->firstChild) 198 { 199 if (!subInited) 200 { 201 REGION_NULL(pScreen, &SubRegion); 202 subInited = TRUE; 203 } 204 REGION_COPY(pScreen, &SubRegion, pRegion); 205 res |= miCheckSubSaveUnder(pChild, pChild->firstChild, 206 &SubRegion); 207 } 208 else 209 { 210 res |= miCheckSubSaveUnder(pChild, pChild->firstChild, 211 pRegion); 212 } 213 214 if (pChild->saveUnder) 215 REGION_UNION(pScreen, pRegion, pRegion, &pChild->borderSize); 216 } 217 } 218 219 if (subInited) 220 REGION_UNINIT(pScreen, &SubRegion); 221 } 222 223 /* 224 * Check the state of this window. DIX save unders are 225 * enabled for viewable windows with some client expressing 226 * exposure interest and which intersect the save under region 227 */ 228 229 if (pParent->viewable && 230 ((pParent->eventMask | wOtherEventMasks(pParent)) & ExposureMask) && 231 REGION_NOTEMPTY(pScreen, &pParent->borderSize) && 232 RECT_IN_REGION(pScreen, pRegion, REGION_EXTENTS(pScreen, 233 &pParent->borderSize)) != rgnOUT) 234 { 235 if (!pParent->DIXsaveUnder) 236 { 237 pParent->DIXsaveUnder = TRUE; 238 (*pScreen->ChangeWindowAttributes) (pParent, CWBackingStore); 239 } 240 } 241 else 242 { 243 if (pParent->DIXsaveUnder) 244 { 245 res = TRUE; 246 pParent->DIXsaveUnder = FALSE; 247 } 248 } 249 return res; 250} 251 252 253/*- 254 *----------------------------------------------------------------------- 255 * miChangeSaveUnder -- 256 * Change the save-under state of a tree of windows. Called when 257 * a window with saveUnder TRUE is mapped/unmapped/reconfigured. 258 * 259 * Results: 260 * TRUE if any windows need to have backing-store removed (which 261 * means that PostChangeSaveUnder needs to be called later to 262 * finish the job). 263 * 264 * Side Effects: 265 * Windows may have backing-store turned on or off. 266 * 267 *----------------------------------------------------------------------- 268 */ 269Bool 270miChangeSaveUnder(pWin, first) 271 WindowPtr pWin; 272 WindowPtr first; /* First window to check. 273 * Used when pWin was restacked */ 274{ 275 RegionRec rgn; /* Area obscured by saveUnder windows */ 276 ScreenPtr pScreen; 277 Bool res; 278 279 if (!deltaSaveUndersViewable && !numSaveUndersViewable) 280 return FALSE; 281 numSaveUndersViewable += deltaSaveUndersViewable; 282 deltaSaveUndersViewable = 0; 283 pScreen = pWin->drawable.pScreen; 284 REGION_NULL(pScreen, &rgn); 285 res = miCheckSubSaveUnder (pWin->parent, 286 pWin->saveUnder ? first : pWin->nextSib, 287 &rgn); 288 REGION_UNINIT(pScreen, &rgn); 289 return res; 290} 291 292/*- 293 *----------------------------------------------------------------------- 294 * miPostChangeSaveUnder -- 295 * Actually turn backing-store off for those windows that no longer 296 * need to have it on. 297 * 298 * Results: 299 * None. 300 * 301 * Side Effects: 302 * Backing-store and SAVE_UNDER_CHANGE_BIT are turned off for those 303 * windows affected. 304 * 305 *----------------------------------------------------------------------- 306 */ 307void 308miPostChangeSaveUnder(pWin, pFirst) 309 WindowPtr pWin; 310 WindowPtr pFirst; 311{ 312 WindowPtr pParent, pChild; 313 ChangeWindowAttributesProcPtr ChangeWindowAttributes; 314 315 if (!(pParent = pWin->parent)) 316 return; 317 ChangeWindowAttributes = pParent->drawable.pScreen->ChangeWindowAttributes; 318 if (!pParent->DIXsaveUnder && 319 (pParent->backingStore == NotUseful) && pParent->backStorage) 320 (*ChangeWindowAttributes)(pParent, CWBackingStore); 321 if (!(pChild = pFirst)) 322 return; 323 while (1) 324 { 325 if (!pChild->DIXsaveUnder && 326 (pChild->backingStore == NotUseful) && pChild->backStorage) 327 (*ChangeWindowAttributes)(pChild, CWBackingStore); 328 if (pChild->firstChild) 329 { 330 pChild = pChild->firstChild; 331 continue; 332 } 333 while (!pChild->nextSib) 334 { 335 pChild = pChild->parent; 336 if (pChild == pParent) 337 return; 338 } 339 pChild = pChild->nextSib; 340 } 341} 342 343void 344miMarkWindow(pWin) 345 WindowPtr pWin; 346{ 347 ValidatePtr val; 348 349 if (pWin->valdata) 350 return; 351 val = (ValidatePtr)xnfalloc(sizeof(ValidateRec)); 352 val->before.oldAbsCorner.x = pWin->drawable.x; 353 val->before.oldAbsCorner.y = pWin->drawable.y; 354 val->before.borderVisible = NullRegion; 355 val->before.resized = FALSE; 356 pWin->valdata = val; 357} 358 359Bool 360miMarkOverlappedWindows(pWin, pFirst, ppLayerWin) 361 WindowPtr pWin; 362 WindowPtr pFirst; 363 WindowPtr *ppLayerWin; 364{ 365 BoxPtr box; 366 WindowPtr pChild, pLast; 367 Bool anyMarked = FALSE; 368 MarkWindowProcPtr MarkWindow = pWin->drawable.pScreen->MarkWindow; 369 ScreenPtr pScreen; 370 371 pScreen = pWin->drawable.pScreen; 372 373 /* single layered systems are easy */ 374 if (ppLayerWin) *ppLayerWin = pWin; 375 376 if (pWin == pFirst) 377 { 378 /* Blindly mark pWin and all of its inferiors. This is a slight 379 * overkill if there are mapped windows that outside pWin's border, 380 * but it's better than wasting time on RectIn checks. 381 */ 382 pChild = pWin; 383 while (1) 384 { 385 if (pChild->viewable) 386 { 387 if (REGION_BROKEN (pScreen, &pChild->winSize)) 388 SetWinSize (pChild); 389 if (REGION_BROKEN (pScreen, &pChild->borderSize)) 390 SetBorderSize (pChild); 391 (* MarkWindow)(pChild); 392 if (pChild->firstChild) 393 { 394 pChild = pChild->firstChild; 395 continue; 396 } 397 } 398 while (!pChild->nextSib && (pChild != pWin)) 399 pChild = pChild->parent; 400 if (pChild == pWin) 401 break; 402 pChild = pChild->nextSib; 403 } 404 anyMarked = TRUE; 405 pFirst = pFirst->nextSib; 406 } 407 if ( (pChild = pFirst) ) 408 { 409 box = REGION_EXTENTS(pChild->drawable.pScreen, &pWin->borderSize); 410 pLast = pChild->parent->lastChild; 411 while (1) 412 { 413 if (pChild->viewable) 414 { 415 if (REGION_BROKEN (pScreen, &pChild->winSize)) 416 SetWinSize (pChild); 417 if (REGION_BROKEN (pScreen, &pChild->borderSize)) 418 SetBorderSize (pChild); 419 if (RECT_IN_REGION(pScreen, &pChild->borderSize, box)) 420 { 421 (* MarkWindow)(pChild); 422 anyMarked = TRUE; 423 if (pChild->firstChild) 424 { 425 pChild = pChild->firstChild; 426 continue; 427 } 428 } 429 } 430 while (!pChild->nextSib && (pChild != pLast)) 431 pChild = pChild->parent; 432 if (pChild == pLast) 433 break; 434 pChild = pChild->nextSib; 435 } 436 } 437 if (anyMarked) 438 (* MarkWindow)(pWin->parent); 439 return anyMarked; 440} 441 442/***** 443 * miHandleValidateExposures(pWin) 444 * starting at pWin, draw background in any windows that have exposure 445 * regions, translate the regions, restore any backing store, 446 * and then send any regions still exposed to the client 447 *****/ 448_X_EXPORT void 449miHandleValidateExposures(pWin) 450 WindowPtr pWin; 451{ 452 WindowPtr pChild; 453 ValidatePtr val; 454 ScreenPtr pScreen; 455 WindowExposuresProcPtr WindowExposures; 456 457 pScreen = pWin->drawable.pScreen; 458 459 pChild = pWin; 460 WindowExposures = pChild->drawable.pScreen->WindowExposures; 461 while (1) 462 { 463 if ( (val = pChild->valdata) ) 464 { 465 if (REGION_NOTEMPTY(pScreen, &val->after.borderExposed)) 466 (*pChild->drawable.pScreen->PaintWindowBorder)(pChild, 467 &val->after.borderExposed, 468 PW_BORDER); 469 REGION_UNINIT(pScreen, &val->after.borderExposed); 470 (*WindowExposures)(pChild, &val->after.exposed, NullRegion); 471 REGION_UNINIT(pScreen, &val->after.exposed); 472 xfree(val); 473 pChild->valdata = (ValidatePtr)NULL; 474 if (pChild->firstChild) 475 { 476 pChild = pChild->firstChild; 477 continue; 478 } 479 } 480 while (!pChild->nextSib && (pChild != pWin)) 481 pChild = pChild->parent; 482 if (pChild == pWin) 483 break; 484 pChild = pChild->nextSib; 485 } 486} 487 488void 489miMoveWindow(pWin, x, y, pNextSib, kind) 490 WindowPtr pWin; 491 int x,y; 492 WindowPtr pNextSib; 493 VTKind kind; 494{ 495 WindowPtr pParent; 496 Bool WasViewable = (Bool)(pWin->viewable); 497 short bw; 498 RegionPtr oldRegion = NULL; 499 DDXPointRec oldpt; 500 Bool anyMarked = FALSE; 501 ScreenPtr pScreen; 502 WindowPtr windowToValidate; 503#ifdef DO_SAVE_UNDERS 504 Bool dosave = FALSE; 505#endif 506 WindowPtr pLayerWin; 507 508 /* if this is a root window, can't be moved */ 509 if (!(pParent = pWin->parent)) 510 return ; 511 pScreen = pWin->drawable.pScreen; 512 bw = wBorderWidth (pWin); 513 514 oldpt.x = pWin->drawable.x; 515 oldpt.y = pWin->drawable.y; 516 if (WasViewable) 517 { 518 oldRegion = REGION_CREATE(pScreen, NullBox, 1); 519 REGION_COPY(pScreen, oldRegion, &pWin->borderClip); 520 anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin); 521 } 522 pWin->origin.x = x + (int)bw; 523 pWin->origin.y = y + (int)bw; 524 x = pWin->drawable.x = pParent->drawable.x + x + (int)bw; 525 y = pWin->drawable.y = pParent->drawable.y + y + (int)bw; 526 527 SetWinSize (pWin); 528 SetBorderSize (pWin); 529 530 (*pScreen->PositionWindow)(pWin, x, y); 531 532 windowToValidate = MoveWindowInStack(pWin, pNextSib); 533 534 ResizeChildrenWinSize(pWin, x - oldpt.x, y - oldpt.y, 0, 0); 535 536 if (WasViewable) 537 { 538 if (pLayerWin == pWin) 539 anyMarked |= (*pScreen->MarkOverlappedWindows) 540 (pWin, windowToValidate, (WindowPtr *)NULL); 541 else 542 anyMarked |= (*pScreen->MarkOverlappedWindows) 543 (pWin, pLayerWin, (WindowPtr *)NULL); 544 545#ifdef DO_SAVE_UNDERS 546 if (DO_SAVE_UNDERS(pWin)) 547 { 548 dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, windowToValidate); 549 } 550#endif /* DO_SAVE_UNDERS */ 551 552 if (anyMarked) 553 { 554 (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow, kind); 555 (* pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, oldRegion); 556 REGION_DESTROY(pScreen, oldRegion); 557 /* XXX need to retile border if ParentRelative origin */ 558 (*pScreen->HandleExposures)(pLayerWin->parent); 559 } 560#ifdef DO_SAVE_UNDERS 561 if (dosave) 562 (*pScreen->PostChangeSaveUnder)(pLayerWin, windowToValidate); 563#endif /* DO_SAVE_UNDERS */ 564 if (anyMarked && pScreen->PostValidateTree) 565 (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow, kind); 566 } 567 if (pWin->realized) 568 WindowsRestructured (); 569} 570 571 572/* 573 * pValid is a region of the screen which has been 574 * successfully copied -- recomputed exposed regions for affected windows 575 */ 576 577static int 578miRecomputeExposures ( 579 WindowPtr pWin, 580 pointer value) /* must conform to VisitWindowProcPtr */ 581{ 582 ScreenPtr pScreen; 583 RegionPtr pValid = (RegionPtr)value; 584 585 if (pWin->valdata) 586 { 587 pScreen = pWin->drawable.pScreen; 588 /* 589 * compute exposed regions of this window 590 */ 591 REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed, 592 &pWin->clipList, pValid); 593 /* 594 * compute exposed regions of the border 595 */ 596 REGION_SUBTRACT(pScreen, &pWin->valdata->after.borderExposed, 597 &pWin->borderClip, &pWin->winSize); 598 REGION_SUBTRACT(pScreen, &pWin->valdata->after.borderExposed, 599 &pWin->valdata->after.borderExposed, pValid); 600 return WT_WALKCHILDREN; 601 } 602 return WT_NOMATCH; 603} 604 605void 606miSlideAndSizeWindow(pWin, x, y, w, h, pSib) 607 WindowPtr pWin; 608 int x,y; 609 unsigned int w, h; 610 WindowPtr pSib; 611{ 612 WindowPtr pParent; 613 Bool WasViewable = (Bool)(pWin->viewable); 614 unsigned short width = pWin->drawable.width, 615 height = pWin->drawable.height; 616 short oldx = pWin->drawable.x, 617 oldy = pWin->drawable.y; 618 int bw = wBorderWidth (pWin); 619 short dw, dh; 620 DDXPointRec oldpt; 621 RegionPtr oldRegion = NULL; 622 Bool anyMarked = FALSE; 623 ScreenPtr pScreen; 624 WindowPtr pFirstChange; 625 WindowPtr pChild; 626 RegionPtr gravitate[StaticGravity + 1]; 627 unsigned g; 628 int nx, ny; /* destination x,y */ 629 int newx, newy; /* new inner window position */ 630 RegionPtr pRegion = NULL; 631 RegionPtr destClip; /* portions of destination already written */ 632 RegionPtr oldWinClip = NULL; /* old clip list for window */ 633 RegionPtr borderVisible = NullRegion; /* visible area of the border */ 634 RegionPtr bsExposed = NullRegion; /* backing store exposures */ 635 Bool shrunk = FALSE; /* shrunk in an inner dimension */ 636 Bool moved = FALSE; /* window position changed */ 637#ifdef DO_SAVE_UNDERS 638 Bool dosave = FALSE; 639#endif 640 WindowPtr pLayerWin; 641 642 /* if this is a root window, can't be resized */ 643 if (!(pParent = pWin->parent)) 644 return ; 645 646 pScreen = pWin->drawable.pScreen; 647 newx = pParent->drawable.x + x + bw; 648 newy = pParent->drawable.y + y + bw; 649 if (WasViewable) 650 { 651 anyMarked = FALSE; 652 /* 653 * save the visible region of the window 654 */ 655 oldRegion = REGION_CREATE(pScreen, NullBox, 1); 656 REGION_COPY(pScreen, oldRegion, &pWin->winSize); 657 658 /* 659 * categorize child windows into regions to be moved 660 */ 661 for (g = 0; g <= StaticGravity; g++) 662 gravitate[g] = (RegionPtr) NULL; 663 for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) 664 { 665 g = pChild->winGravity; 666 if (g != UnmapGravity) 667 { 668 if (!gravitate[g]) 669 gravitate[g] = REGION_CREATE(pScreen, NullBox, 1); 670 REGION_UNION(pScreen, gravitate[g], 671 gravitate[g], &pChild->borderClip); 672 } 673 else 674 { 675 UnmapWindow(pChild, TRUE); 676 anyMarked = TRUE; 677 } 678 } 679 anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin, 680 &pLayerWin); 681 682 oldWinClip = NULL; 683 if (pWin->bitGravity != ForgetGravity) 684 { 685 oldWinClip = REGION_CREATE(pScreen, NullBox, 1); 686 REGION_COPY(pScreen, oldWinClip, &pWin->clipList); 687 } 688 /* 689 * if the window is changing size, borderExposed 690 * can't be computed correctly without some help. 691 */ 692 if (pWin->drawable.height > h || pWin->drawable.width > w) 693 shrunk = TRUE; 694 695 if (newx != oldx || newy != oldy) 696 moved = TRUE; 697 698 if ((pWin->drawable.height != h || pWin->drawable.width != w) && 699 HasBorder (pWin)) 700 { 701 borderVisible = REGION_CREATE(pScreen, NullBox, 1); 702 /* for tiled borders, we punt and draw the whole thing */ 703 if (pWin->borderIsPixel || !moved) 704 { 705 if (shrunk || moved) 706 REGION_SUBTRACT(pScreen, borderVisible, 707 &pWin->borderClip, 708 &pWin->winSize); 709 else 710 REGION_COPY(pScreen, borderVisible, 711 &pWin->borderClip); 712 } 713 } 714 } 715 pWin->origin.x = x + bw; 716 pWin->origin.y = y + bw; 717 pWin->drawable.height = h; 718 pWin->drawable.width = w; 719 720 x = pWin->drawable.x = newx; 721 y = pWin->drawable.y = newy; 722 723 SetWinSize (pWin); 724 SetBorderSize (pWin); 725 726 dw = (int)w - (int)width; 727 dh = (int)h - (int)height; 728 ResizeChildrenWinSize(pWin, x - oldx, y - oldy, dw, dh); 729 730 /* let the hardware adjust background and border pixmaps, if any */ 731 (*pScreen->PositionWindow)(pWin, x, y); 732 733 pFirstChange = MoveWindowInStack(pWin, pSib); 734 735 if (WasViewable) 736 { 737 pRegion = REGION_CREATE(pScreen, NullBox, 1); 738 if (pWin->backStorage) 739 REGION_COPY(pScreen, pRegion, &pWin->clipList); 740 741 if (pLayerWin == pWin) 742 anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange, 743 (WindowPtr *)NULL); 744 else 745 anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pLayerWin, 746 (WindowPtr *)NULL); 747 748 if (pWin->valdata) 749 { 750 pWin->valdata->before.resized = TRUE; 751 pWin->valdata->before.borderVisible = borderVisible; 752 } 753 754#ifdef DO_SAVE_UNDERS 755 if (DO_SAVE_UNDERS(pWin)) 756 { 757 dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pFirstChange); 758 } 759#endif /* DO_SAVE_UNDERS */ 760 761 if (anyMarked) 762 (*pScreen->ValidateTree)(pLayerWin->parent, pFirstChange, VTOther); 763 /* 764 * the entire window is trashed unless bitGravity 765 * recovers portions of it 766 */ 767 REGION_COPY(pScreen, &pWin->valdata->after.exposed, &pWin->clipList); 768 } 769 770 GravityTranslate (x, y, oldx, oldy, dw, dh, pWin->bitGravity, &nx, &ny); 771 772 if (pWin->backStorage && 773 ((pWin->backingStore == Always) || WasViewable)) 774 { 775 if (!WasViewable) 776 pRegion = &pWin->clipList; /* a convenient empty region */ 777 if (pWin->bitGravity == ForgetGravity) 778 bsExposed = (*pScreen->TranslateBackingStore) 779 (pWin, 0, 0, NullRegion, oldx, oldy); 780 else 781 { 782 bsExposed = (*pScreen->TranslateBackingStore) 783 (pWin, nx - x, ny - y, pRegion, oldx, oldy); 784 } 785 } 786 787 if (WasViewable) 788 { 789 /* avoid the border */ 790 if (HasBorder (pWin)) 791 { 792 int offx, offy, dx, dy; 793 794 /* kruft to avoid double translates for each gravity */ 795 offx = 0; 796 offy = 0; 797 for (g = 0; g <= StaticGravity; g++) 798 { 799 if (!gravitate[g]) 800 continue; 801 802 /* align winSize to gravitate[g]. 803 * winSize is in new coordinates, 804 * gravitate[g] is still in old coordinates */ 805 GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny); 806 807 dx = (oldx - nx) - offx; 808 dy = (oldy - ny) - offy; 809 if (dx || dy) 810 { 811 REGION_TRANSLATE(pScreen, &pWin->winSize, dx, dy); 812 offx += dx; 813 offy += dy; 814 } 815 REGION_INTERSECT(pScreen, gravitate[g], gravitate[g], 816 &pWin->winSize); 817 } 818 /* get winSize back where it belongs */ 819 if (offx || offy) 820 REGION_TRANSLATE(pScreen, &pWin->winSize, -offx, -offy); 821 } 822 /* 823 * add screen bits to the appropriate bucket 824 */ 825 826 if (oldWinClip) 827 { 828 /* 829 * clip to new clipList 830 */ 831 REGION_COPY(pScreen, pRegion, oldWinClip); 832 REGION_TRANSLATE(pScreen, pRegion, nx - oldx, ny - oldy); 833 REGION_INTERSECT(pScreen, oldWinClip, pRegion, &pWin->clipList); 834 /* 835 * don't step on any gravity bits which will be copied after this 836 * region. Note -- this assumes that the regions will be copied 837 * in gravity order. 838 */ 839 for (g = pWin->bitGravity + 1; g <= StaticGravity; g++) 840 { 841 if (gravitate[g]) 842 REGION_SUBTRACT(pScreen, oldWinClip, oldWinClip, 843 gravitate[g]); 844 } 845 REGION_TRANSLATE(pScreen, oldWinClip, oldx - nx, oldy - ny); 846 g = pWin->bitGravity; 847 if (!gravitate[g]) 848 gravitate[g] = oldWinClip; 849 else 850 { 851 REGION_UNION(pScreen, gravitate[g], gravitate[g], oldWinClip); 852 REGION_DESTROY(pScreen, oldWinClip); 853 } 854 } 855 856 /* 857 * move the bits on the screen 858 */ 859 860 destClip = NULL; 861 862 for (g = 0; g <= StaticGravity; g++) 863 { 864 if (!gravitate[g]) 865 continue; 866 867 GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny); 868 869 oldpt.x = oldx + (x - nx); 870 oldpt.y = oldy + (y - ny); 871 872 /* Note that gravitate[g] is *translated* by CopyWindow */ 873 874 /* only copy the remaining useful bits */ 875 876 REGION_INTERSECT(pScreen, gravitate[g], gravitate[g], oldRegion); 877 878 /* clip to not overwrite already copied areas */ 879 880 if (destClip) { 881 REGION_TRANSLATE(pScreen, destClip, oldpt.x - x, oldpt.y - y); 882 REGION_SUBTRACT(pScreen, gravitate[g], gravitate[g], destClip); 883 REGION_TRANSLATE(pScreen, destClip, x - oldpt.x, y - oldpt.y); 884 } 885 886 /* and move those bits */ 887 888 if (oldpt.x != x || oldpt.y != y 889#ifdef COMPOSITE 890 || pWin->redirectDraw 891#endif 892 ) 893 { 894 (*pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, gravitate[g]); 895 } 896 897 /* remove any overwritten bits from the remaining useful bits */ 898 899 REGION_SUBTRACT(pScreen, oldRegion, oldRegion, gravitate[g]); 900 901 /* 902 * recompute exposed regions of child windows 903 */ 904 905 for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) 906 { 907 if (pChild->winGravity != g) 908 continue; 909 REGION_INTERSECT(pScreen, pRegion, 910 &pChild->borderClip, gravitate[g]); 911 TraverseTree (pChild, miRecomputeExposures, (pointer)pRegion); 912 } 913 914 /* 915 * remove the successfully copied regions of the 916 * window from its exposed region 917 */ 918 919 if (g == pWin->bitGravity) 920 REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed, 921 &pWin->valdata->after.exposed, gravitate[g]); 922 if (!destClip) 923 destClip = gravitate[g]; 924 else 925 { 926 REGION_UNION(pScreen, destClip, destClip, gravitate[g]); 927 REGION_DESTROY(pScreen, gravitate[g]); 928 } 929 } 930 931 REGION_DESTROY(pScreen, oldRegion); 932 REGION_DESTROY(pScreen, pRegion); 933 if (destClip) 934 REGION_DESTROY(pScreen, destClip); 935 if (bsExposed) 936 { 937 RegionPtr valExposed = NullRegion; 938 939 if (pWin->valdata) 940 valExposed = &pWin->valdata->after.exposed; 941 (*pScreen->WindowExposures) (pWin, valExposed, bsExposed); 942 if (valExposed) 943 REGION_EMPTY(pScreen, valExposed); 944 REGION_DESTROY(pScreen, bsExposed); 945 } 946 if (anyMarked) 947 (*pScreen->HandleExposures)(pLayerWin->parent); 948#ifdef DO_SAVE_UNDERS 949 if (dosave) 950 { 951 (*pScreen->PostChangeSaveUnder)(pLayerWin, pFirstChange); 952 } 953#endif /* DO_SAVE_UNDERS */ 954 if (anyMarked && pScreen->PostValidateTree) 955 (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstChange, 956 VTOther); 957 } 958 else if (bsExposed) 959 { 960 (*pScreen->WindowExposures) (pWin, NullRegion, bsExposed); 961 REGION_DESTROY(pScreen, bsExposed); 962 } 963 if (pWin->realized) 964 WindowsRestructured (); 965} 966 967WindowPtr 968miGetLayerWindow(pWin) 969 WindowPtr pWin; 970{ 971 return pWin->firstChild; 972} 973 974#ifdef SHAPE 975/****** 976 * 977 * miSetShape 978 * The border/window shape has changed. Recompute winSize/borderSize 979 * and send appropriate exposure events 980 */ 981 982_X_EXPORT void 983miSetShape(pWin) 984 WindowPtr pWin; 985{ 986 Bool WasViewable = (Bool)(pWin->viewable); 987 ScreenPtr pScreen = pWin->drawable.pScreen; 988 Bool anyMarked = FALSE; 989 RegionPtr pOldClip = NULL, bsExposed; 990#ifdef DO_SAVE_UNDERS 991 Bool dosave = FALSE; 992#endif 993 WindowPtr pLayerWin; 994 995 if (WasViewable) 996 { 997 anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, 998 &pLayerWin); 999 if (pWin->valdata) 1000 { 1001 if (HasBorder (pWin)) 1002 { 1003 RegionPtr borderVisible; 1004 1005 borderVisible = REGION_CREATE(pScreen, NullBox, 1); 1006 REGION_SUBTRACT(pScreen, borderVisible, 1007 &pWin->borderClip, &pWin->winSize); 1008 pWin->valdata->before.borderVisible = borderVisible; 1009 } 1010 pWin->valdata->before.resized = TRUE; 1011 } 1012 } 1013 1014 SetWinSize (pWin); 1015 SetBorderSize (pWin); 1016 1017 ResizeChildrenWinSize(pWin, 0, 0, 0, 0); 1018 1019 if (WasViewable) 1020 { 1021 if (pWin->backStorage) 1022 { 1023 pOldClip = REGION_CREATE(pScreen, NullBox, 1); 1024 REGION_COPY(pScreen, pOldClip, &pWin->clipList); 1025 } 1026 1027 anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin, 1028 (WindowPtr *)NULL); 1029 1030#ifdef DO_SAVE_UNDERS 1031 if (DO_SAVE_UNDERS(pWin)) 1032 { 1033 dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin); 1034 } 1035#endif /* DO_SAVE_UNDERS */ 1036 1037 if (anyMarked) 1038 (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow, VTOther); 1039 } 1040 1041 if (pWin->backStorage && 1042 ((pWin->backingStore == Always) || WasViewable)) 1043 { 1044 if (!WasViewable) 1045 pOldClip = &pWin->clipList; /* a convenient empty region */ 1046 bsExposed = (*pScreen->TranslateBackingStore) 1047 (pWin, 0, 0, pOldClip, 1048 pWin->drawable.x, pWin->drawable.y); 1049 if (WasViewable) 1050 REGION_DESTROY(pScreen, pOldClip); 1051 if (bsExposed) 1052 { 1053 RegionPtr valExposed = NullRegion; 1054 1055 if (pWin->valdata) 1056 valExposed = &pWin->valdata->after.exposed; 1057 (*pScreen->WindowExposures) (pWin, valExposed, bsExposed); 1058 if (valExposed) 1059 REGION_EMPTY(pScreen, valExposed); 1060 REGION_DESTROY(pScreen, bsExposed); 1061 } 1062 } 1063 if (WasViewable) 1064 { 1065 if (anyMarked) 1066 (*pScreen->HandleExposures)(pLayerWin->parent); 1067#ifdef DO_SAVE_UNDERS 1068 if (dosave) 1069 (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin); 1070#endif /* DO_SAVE_UNDERS */ 1071 if (anyMarked && pScreen->PostValidateTree) 1072 (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow, VTOther); 1073 } 1074 if (pWin->realized) 1075 WindowsRestructured (); 1076 CheckCursorConfinement(pWin); 1077} 1078#endif 1079 1080/* Keeps the same inside(!) origin */ 1081 1082_X_EXPORT void 1083miChangeBorderWidth(pWin, width) 1084 WindowPtr pWin; 1085 unsigned int width; 1086{ 1087 int oldwidth; 1088 Bool anyMarked = FALSE; 1089 ScreenPtr pScreen; 1090 Bool WasViewable = (Bool)(pWin->viewable); 1091 Bool HadBorder; 1092#ifdef DO_SAVE_UNDERS 1093 Bool dosave = FALSE; 1094#endif 1095 WindowPtr pLayerWin; 1096 1097 oldwidth = wBorderWidth (pWin); 1098 if (oldwidth == width) 1099 return; 1100 HadBorder = HasBorder(pWin); 1101 pScreen = pWin->drawable.pScreen; 1102 if (WasViewable && width < oldwidth) 1103 anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin); 1104 1105 pWin->borderWidth = width; 1106 SetBorderSize (pWin); 1107 1108 if (WasViewable) 1109 { 1110 if (width > oldwidth) 1111 { 1112 anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, 1113 &pLayerWin); 1114 /* 1115 * save the old border visible region to correctly compute 1116 * borderExposed. 1117 */ 1118 if (pWin->valdata && HadBorder) 1119 { 1120 RegionPtr borderVisible; 1121 borderVisible = REGION_CREATE(pScreen, NULL, 1); 1122 REGION_SUBTRACT(pScreen, borderVisible, 1123 &pWin->borderClip, &pWin->winSize); 1124 pWin->valdata->before.borderVisible = borderVisible; 1125 } 1126 } 1127#ifdef DO_SAVE_UNDERS 1128 if (DO_SAVE_UNDERS(pWin)) 1129 { 1130 dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib); 1131 } 1132#endif /* DO_SAVE_UNDERS */ 1133 1134 if (anyMarked) 1135 { 1136 (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTOther); 1137 (*pScreen->HandleExposures)(pLayerWin->parent); 1138 } 1139#ifdef DO_SAVE_UNDERS 1140 if (dosave) 1141 (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib); 1142#endif /* DO_SAVE_UNDERS */ 1143 if (anyMarked && pScreen->PostValidateTree) 1144 (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin, 1145 VTOther); 1146 } 1147 if (pWin->realized) 1148 WindowsRestructured (); 1149} 1150 1151void 1152miMarkUnrealizedWindow(pChild, pWin, fromConfigure) 1153 WindowPtr pChild; 1154 WindowPtr pWin; 1155 Bool fromConfigure; 1156{ 1157 if ((pChild != pWin) || fromConfigure) 1158 { 1159 REGION_EMPTY(pChild->drawable.pScreen, &pChild->clipList); 1160 if (pChild->drawable.pScreen->ClipNotify) 1161 (* pChild->drawable.pScreen->ClipNotify)(pChild, 0, 0); 1162 REGION_EMPTY(pChild->drawable.pScreen, &pChild->borderClip); 1163 } 1164} 1165 1166_X_EXPORT void 1167miSegregateChildren(WindowPtr pWin, RegionPtr pReg, int depth) 1168{ 1169 ScreenPtr pScreen; 1170 WindowPtr pChild; 1171 1172 pScreen = pWin->drawable.pScreen; 1173 1174 for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) 1175 { 1176 if (pChild->drawable.depth == depth) 1177 REGION_UNION(pScreen, pReg, pReg, &pChild->borderClip); 1178 1179 if (pChild->firstChild) 1180 miSegregateChildren(pChild, pReg, depth); 1181 } 1182} 1183