1 2/*********************************************************** 3 4Copyright 1987, 1998 The Open Group 5 6Permission to use, copy, modify, distribute, and sell this software and its 7documentation for any purpose is hereby granted without fee, provided that 8the above copyright notice appear in all copies and that both that 9copyright notice and this permission notice appear in supporting 10documentation. 11 12The above copyright notice and this permission notice shall be included in 13all copies or substantial portions of the Software. 14 15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22Except as contained in this notice, the name of The Open Group shall not be 23used in advertising or otherwise to promote the sale, use or other dealings 24in this Software without prior written authorization from The Open Group. 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 <X11/extensions/shapeconst.h> 53#include "regionstr.h" 54#include "region.h" 55#include "mi.h" 56#include "windowstr.h" 57#include "scrnintstr.h" 58#include "pixmapstr.h" 59#include "mivalidate.h" 60#include "inputstr.h" 61 62void 63miClearToBackground(WindowPtr pWin, 64 int x, int y, int w, int h, Bool generateExposures) 65{ 66 BoxRec box; 67 RegionRec reg; 68 BoxPtr extents; 69 int x1, y1, x2, y2; 70 71 /* compute everything using ints to avoid overflow */ 72 73 x1 = pWin->drawable.x + x; 74 y1 = pWin->drawable.y + y; 75 if (w) 76 x2 = x1 + (int) w; 77 else 78 x2 = x1 + (int) pWin->drawable.width - (int) x; 79 if (h) 80 y2 = y1 + h; 81 else 82 y2 = y1 + (int) pWin->drawable.height - (int) y; 83 84 extents = &pWin->clipList.extents; 85 86 /* clip the resulting rectangle to the window clipList extents. This 87 * makes sure that the result will fit in a box, given that the 88 * screen is < 32768 on a side. 89 */ 90 91 if (x1 < extents->x1) 92 x1 = extents->x1; 93 if (x2 > extents->x2) 94 x2 = extents->x2; 95 if (y1 < extents->y1) 96 y1 = extents->y1; 97 if (y2 > extents->y2) 98 y2 = extents->y2; 99 100 if (x2 <= x1 || y2 <= y1) { 101 x2 = x1 = 0; 102 y2 = y1 = 0; 103 } 104 105 box.x1 = x1; 106 box.x2 = x2; 107 box.y1 = y1; 108 box.y2 = y2; 109 110 RegionInit(®, &box, 1); 111 112 RegionIntersect(®, ®, &pWin->clipList); 113 if (generateExposures) 114 (*pWin->drawable.pScreen->WindowExposures) (pWin, ®); 115 else if (pWin->backgroundState != None) 116 pWin->drawable.pScreen->PaintWindow(pWin, ®, PW_BACKGROUND); 117 RegionUninit(®); 118} 119 120void 121miMarkWindow(WindowPtr pWin) 122{ 123 ValidatePtr val; 124 125 if (pWin->valdata) 126 return; 127 val = (ValidatePtr) xnfalloc(sizeof(ValidateRec)); 128 val->before.oldAbsCorner.x = pWin->drawable.x; 129 val->before.oldAbsCorner.y = pWin->drawable.y; 130 val->before.borderVisible = NullRegion; 131 val->before.resized = FALSE; 132 pWin->valdata = val; 133} 134 135Bool 136miMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst, WindowPtr *ppLayerWin) 137{ 138 BoxPtr box; 139 WindowPtr pChild, pLast; 140 Bool anyMarked = FALSE; 141 MarkWindowProcPtr MarkWindow = pWin->drawable.pScreen->MarkWindow; 142 143 /* single layered systems are easy */ 144 if (ppLayerWin) 145 *ppLayerWin = pWin; 146 147 if (pWin == pFirst) { 148 /* Blindly mark pWin and all of its inferiors. This is a slight 149 * overkill if there are mapped windows that outside pWin's border, 150 * but it's better than wasting time on RectIn checks. 151 */ 152 pChild = pWin; 153 while (1) { 154 if (pChild->viewable) { 155 if (RegionBroken(&pChild->winSize)) 156 SetWinSize(pChild); 157 if (RegionBroken(&pChild->borderSize)) 158 SetBorderSize(pChild); 159 (*MarkWindow) (pChild); 160 if (pChild->firstChild) { 161 pChild = pChild->firstChild; 162 continue; 163 } 164 } 165 while (!pChild->nextSib && (pChild != pWin)) 166 pChild = pChild->parent; 167 if (pChild == pWin) 168 break; 169 pChild = pChild->nextSib; 170 } 171 anyMarked = TRUE; 172 pFirst = pFirst->nextSib; 173 } 174 if ((pChild = pFirst)) { 175 box = RegionExtents(&pWin->borderSize); 176 pLast = pChild->parent->lastChild; 177 while (1) { 178 if (pChild->viewable) { 179 if (RegionBroken(&pChild->winSize)) 180 SetWinSize(pChild); 181 if (RegionBroken(&pChild->borderSize)) 182 SetBorderSize(pChild); 183 if (RegionContainsRect(&pChild->borderSize, box)) { 184 (*MarkWindow) (pChild); 185 anyMarked = TRUE; 186 if (pChild->firstChild) { 187 pChild = pChild->firstChild; 188 continue; 189 } 190 } 191 } 192 while (!pChild->nextSib && (pChild != pLast)) 193 pChild = pChild->parent; 194 if (pChild == pLast) 195 break; 196 pChild = pChild->nextSib; 197 } 198 } 199 if (anyMarked) 200 (*MarkWindow) (pWin->parent); 201 return anyMarked; 202} 203 204/***** 205 * miHandleValidateExposures(pWin) 206 * starting at pWin, draw background in any windows that have exposure 207 * regions, translate the regions, restore any backing store, 208 * and then send any regions still exposed to the client 209 *****/ 210void 211miHandleValidateExposures(WindowPtr pWin) 212{ 213 WindowPtr pChild; 214 ValidatePtr val; 215 WindowExposuresProcPtr WindowExposures; 216 217 pChild = pWin; 218 WindowExposures = pChild->drawable.pScreen->WindowExposures; 219 while (1) { 220 if ((val = pChild->valdata)) { 221 if (RegionNotEmpty(&val->after.borderExposed)) 222 pWin->drawable.pScreen->PaintWindow(pChild, 223 &val->after.borderExposed, 224 PW_BORDER); 225 RegionUninit(&val->after.borderExposed); 226 (*WindowExposures) (pChild, &val->after.exposed); 227 RegionUninit(&val->after.exposed); 228 free(val); 229 pChild->valdata = NULL; 230 if (pChild->firstChild) { 231 pChild = pChild->firstChild; 232 continue; 233 } 234 } 235 while (!pChild->nextSib && (pChild != pWin)) 236 pChild = pChild->parent; 237 if (pChild == pWin) 238 break; 239 pChild = pChild->nextSib; 240 } 241} 242 243void 244miMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pNextSib, VTKind kind) 245{ 246 WindowPtr pParent; 247 Bool WasViewable = (Bool) (pWin->viewable); 248 short bw; 249 RegionPtr oldRegion = NULL; 250 DDXPointRec oldpt; 251 Bool anyMarked = FALSE; 252 ScreenPtr pScreen; 253 WindowPtr windowToValidate; 254 WindowPtr pLayerWin; 255 256 /* if this is a root window, can't be moved */ 257 if (!(pParent = pWin->parent)) 258 return; 259 pScreen = pWin->drawable.pScreen; 260 bw = wBorderWidth(pWin); 261 262 oldpt.x = pWin->drawable.x; 263 oldpt.y = pWin->drawable.y; 264 if (WasViewable) { 265 oldRegion = RegionCreate(NullBox, 1); 266 RegionCopy(oldRegion, &pWin->borderClip); 267 anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pWin, &pLayerWin); 268 } 269 pWin->origin.x = x + (int) bw; 270 pWin->origin.y = y + (int) bw; 271 x = pWin->drawable.x = pParent->drawable.x + x + (int) bw; 272 y = pWin->drawable.y = pParent->drawable.y + y + (int) bw; 273 274 SetWinSize(pWin); 275 SetBorderSize(pWin); 276 277 (*pScreen->PositionWindow) (pWin, x, y); 278 279 windowToValidate = MoveWindowInStack(pWin, pNextSib); 280 281 ResizeChildrenWinSize(pWin, x - oldpt.x, y - oldpt.y, 0, 0); 282 283 if (WasViewable) { 284 if (pLayerWin == pWin) 285 anyMarked |= (*pScreen->MarkOverlappedWindows) 286 (pWin, windowToValidate, NULL); 287 else 288 anyMarked |= (*pScreen->MarkOverlappedWindows) 289 (pWin, pLayerWin, NULL); 290 291 if (anyMarked) { 292 (*pScreen->ValidateTree) (pLayerWin->parent, NullWindow, kind); 293 (*pWin->drawable.pScreen->CopyWindow) (pWin, oldpt, oldRegion); 294 RegionDestroy(oldRegion); 295 /* XXX need to retile border if ParentRelative origin */ 296 (*pScreen->HandleExposures) (pLayerWin->parent); 297 if (pScreen->PostValidateTree) 298 (*pScreen->PostValidateTree) (pLayerWin->parent, NULL, kind); 299 } 300 } 301 if (pWin->realized) 302 WindowsRestructured(); 303} 304 305/* 306 * pValid is a region of the screen which has been 307 * successfully copied -- recomputed exposed regions for affected windows 308 */ 309 310static int 311miRecomputeExposures(WindowPtr pWin, void *value) 312{ /* must conform to VisitWindowProcPtr */ 313 RegionPtr pValid = (RegionPtr) value; 314 315 if (pWin->valdata) { 316#ifdef COMPOSITE 317 /* 318 * Redirected windows are not affected by parent window 319 * gravity manipulations, so don't recompute their 320 * exposed areas here. 321 */ 322 if (pWin->redirectDraw != RedirectDrawNone) 323 return WT_DONTWALKCHILDREN; 324#endif 325 /* 326 * compute exposed regions of this window 327 */ 328 RegionSubtract(&pWin->valdata->after.exposed, &pWin->clipList, pValid); 329 /* 330 * compute exposed regions of the border 331 */ 332 RegionSubtract(&pWin->valdata->after.borderExposed, 333 &pWin->borderClip, &pWin->winSize); 334 RegionSubtract(&pWin->valdata->after.borderExposed, 335 &pWin->valdata->after.borderExposed, pValid); 336 return WT_WALKCHILDREN; 337 } 338 return WT_NOMATCH; 339} 340 341void 342miResizeWindow(WindowPtr pWin, int x, int y, unsigned int w, unsigned int h, 343 WindowPtr pSib) 344{ 345 WindowPtr pParent; 346 Bool WasViewable = (Bool) (pWin->viewable); 347 unsigned short width = pWin->drawable.width, height = pWin->drawable.height; 348 short oldx = pWin->drawable.x, oldy = pWin->drawable.y; 349 int bw = wBorderWidth(pWin); 350 short dw, dh; 351 DDXPointRec oldpt; 352 RegionPtr oldRegion = NULL; 353 Bool anyMarked = FALSE; 354 ScreenPtr pScreen; 355 WindowPtr pFirstChange; 356 WindowPtr pChild; 357 RegionPtr gravitate[StaticGravity + 1]; 358 unsigned g; 359 int nx, ny; /* destination x,y */ 360 int newx, newy; /* new inner window position */ 361 RegionPtr pRegion = NULL; 362 RegionPtr destClip; /* portions of destination already written */ 363 RegionPtr oldWinClip = NULL; /* old clip list for window */ 364 RegionPtr borderVisible = NullRegion; /* visible area of the border */ 365 Bool shrunk = FALSE; /* shrunk in an inner dimension */ 366 Bool moved = FALSE; /* window position changed */ 367 WindowPtr pLayerWin; 368 369 /* if this is a root window, can't be resized */ 370 if (!(pParent = pWin->parent)) 371 return; 372 373 pScreen = pWin->drawable.pScreen; 374 newx = pParent->drawable.x + x + bw; 375 newy = pParent->drawable.y + y + bw; 376 if (WasViewable) { 377 anyMarked = FALSE; 378 /* 379 * save the visible region of the window 380 */ 381 oldRegion = RegionCreate(NullBox, 1); 382 RegionCopy(oldRegion, &pWin->winSize); 383 384 /* 385 * categorize child windows into regions to be moved 386 */ 387 for (g = 0; g <= StaticGravity; g++) 388 gravitate[g] = (RegionPtr) NULL; 389 for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) { 390 g = pChild->winGravity; 391 if (g != UnmapGravity) { 392 if (!gravitate[g]) 393 gravitate[g] = RegionCreate(NullBox, 1); 394 RegionUnion(gravitate[g], gravitate[g], &pChild->borderClip); 395 } 396 else { 397 UnmapWindow(pChild, TRUE); 398 anyMarked = TRUE; 399 } 400 } 401 anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin, pWin, &pLayerWin); 402 403 oldWinClip = NULL; 404 if (pWin->bitGravity != ForgetGravity) { 405 oldWinClip = RegionCreate(NullBox, 1); 406 RegionCopy(oldWinClip, &pWin->clipList); 407 } 408 /* 409 * if the window is changing size, borderExposed 410 * can't be computed correctly without some help. 411 */ 412 if (pWin->drawable.height > h || pWin->drawable.width > w) 413 shrunk = TRUE; 414 415 if (newx != oldx || newy != oldy) 416 moved = TRUE; 417 418 if ((pWin->drawable.height != h || pWin->drawable.width != w) && 419 HasBorder(pWin)) { 420 borderVisible = RegionCreate(NullBox, 1); 421 /* for tiled borders, we punt and draw the whole thing */ 422 if (pWin->borderIsPixel || !moved) { 423 if (shrunk || moved) 424 RegionSubtract(borderVisible, 425 &pWin->borderClip, &pWin->winSize); 426 else 427 RegionCopy(borderVisible, &pWin->borderClip); 428 } 429 } 430 } 431 pWin->origin.x = x + bw; 432 pWin->origin.y = y + bw; 433 pWin->drawable.height = h; 434 pWin->drawable.width = w; 435 436 x = pWin->drawable.x = newx; 437 y = pWin->drawable.y = newy; 438 439 SetWinSize(pWin); 440 SetBorderSize(pWin); 441 442 dw = (int) w - (int) width; 443 dh = (int) h - (int) height; 444 ResizeChildrenWinSize(pWin, x - oldx, y - oldy, dw, dh); 445 446 /* let the hardware adjust background and border pixmaps, if any */ 447 (*pScreen->PositionWindow) (pWin, x, y); 448 449 pFirstChange = MoveWindowInStack(pWin, pSib); 450 451 if (WasViewable) { 452 pRegion = RegionCreate(NullBox, 1); 453 454 if (pLayerWin == pWin) 455 anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin, pFirstChange, 456 NULL); 457 else 458 anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin, pLayerWin, 459 NULL); 460 461 if (pWin->valdata) { 462 pWin->valdata->before.resized = TRUE; 463 pWin->valdata->before.borderVisible = borderVisible; 464 } 465 466 if (anyMarked) 467 (*pScreen->ValidateTree) (pLayerWin->parent, pFirstChange, VTOther); 468 /* 469 * the entire window is trashed unless bitGravity 470 * recovers portions of it 471 */ 472 RegionCopy(&pWin->valdata->after.exposed, &pWin->clipList); 473 } 474 475 GravityTranslate(x, y, oldx, oldy, dw, dh, pWin->bitGravity, &nx, &ny); 476 477 if (WasViewable) { 478 /* avoid the border */ 479 if (HasBorder(pWin)) { 480 int offx, offy, dx, dy; 481 482 /* kruft to avoid double translates for each gravity */ 483 offx = 0; 484 offy = 0; 485 for (g = 0; g <= StaticGravity; g++) { 486 if (!gravitate[g]) 487 continue; 488 489 /* align winSize to gravitate[g]. 490 * winSize is in new coordinates, 491 * gravitate[g] is still in old coordinates */ 492 GravityTranslate(x, y, oldx, oldy, dw, dh, g, &nx, &ny); 493 494 dx = (oldx - nx) - offx; 495 dy = (oldy - ny) - offy; 496 if (dx || dy) { 497 RegionTranslate(&pWin->winSize, dx, dy); 498 offx += dx; 499 offy += dy; 500 } 501 RegionIntersect(gravitate[g], gravitate[g], &pWin->winSize); 502 } 503 /* get winSize back where it belongs */ 504 if (offx || offy) 505 RegionTranslate(&pWin->winSize, -offx, -offy); 506 } 507 /* 508 * add screen bits to the appropriate bucket 509 */ 510 511 if (oldWinClip) { 512 /* 513 * clip to new clipList 514 */ 515 RegionCopy(pRegion, oldWinClip); 516 RegionTranslate(pRegion, nx - oldx, ny - oldy); 517 RegionIntersect(oldWinClip, pRegion, &pWin->clipList); 518 /* 519 * don't step on any gravity bits which will be copied after this 520 * region. Note -- this assumes that the regions will be copied 521 * in gravity order. 522 */ 523 for (g = pWin->bitGravity + 1; g <= StaticGravity; g++) { 524 if (gravitate[g]) 525 RegionSubtract(oldWinClip, oldWinClip, gravitate[g]); 526 } 527 RegionTranslate(oldWinClip, oldx - nx, oldy - ny); 528 g = pWin->bitGravity; 529 if (!gravitate[g]) 530 gravitate[g] = oldWinClip; 531 else { 532 RegionUnion(gravitate[g], gravitate[g], oldWinClip); 533 RegionDestroy(oldWinClip); 534 } 535 } 536 537 /* 538 * move the bits on the screen 539 */ 540 541 destClip = NULL; 542 543 for (g = 0; g <= StaticGravity; g++) { 544 if (!gravitate[g]) 545 continue; 546 547 GravityTranslate(x, y, oldx, oldy, dw, dh, g, &nx, &ny); 548 549 oldpt.x = oldx + (x - nx); 550 oldpt.y = oldy + (y - ny); 551 552 /* Note that gravitate[g] is *translated* by CopyWindow */ 553 554 /* only copy the remaining useful bits */ 555 556 RegionIntersect(gravitate[g], gravitate[g], oldRegion); 557 558 /* clip to not overwrite already copied areas */ 559 560 if (destClip) { 561 RegionTranslate(destClip, oldpt.x - x, oldpt.y - y); 562 RegionSubtract(gravitate[g], gravitate[g], destClip); 563 RegionTranslate(destClip, x - oldpt.x, y - oldpt.y); 564 } 565 566 /* and move those bits */ 567 568 if (oldpt.x != x || oldpt.y != y 569#ifdef COMPOSITE 570 || pWin->redirectDraw 571#endif 572 ) { 573 (*pWin->drawable.pScreen->CopyWindow) (pWin, oldpt, 574 gravitate[g]); 575 } 576 577 /* remove any overwritten bits from the remaining useful bits */ 578 579 RegionSubtract(oldRegion, oldRegion, gravitate[g]); 580 581 /* 582 * recompute exposed regions of child windows 583 */ 584 585 for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) { 586 if (pChild->winGravity != g) 587 continue; 588 RegionIntersect(pRegion, &pChild->borderClip, gravitate[g]); 589 TraverseTree(pChild, miRecomputeExposures, (void *) pRegion); 590 } 591 592 /* 593 * remove the successfully copied regions of the 594 * window from its exposed region 595 */ 596 597 if (g == pWin->bitGravity) 598 RegionSubtract(&pWin->valdata->after.exposed, 599 &pWin->valdata->after.exposed, gravitate[g]); 600 if (!destClip) 601 destClip = gravitate[g]; 602 else { 603 RegionUnion(destClip, destClip, gravitate[g]); 604 RegionDestroy(gravitate[g]); 605 } 606 } 607 608 RegionDestroy(oldRegion); 609 RegionDestroy(pRegion); 610 if (destClip) 611 RegionDestroy(destClip); 612 if (anyMarked) { 613 (*pScreen->HandleExposures) (pLayerWin->parent); 614 if (pScreen->PostValidateTree) 615 (*pScreen->PostValidateTree) (pLayerWin->parent, pFirstChange, 616 VTOther); 617 } 618 } 619 if (pWin->realized) 620 WindowsRestructured(); 621} 622 623WindowPtr 624miGetLayerWindow(WindowPtr pWin) 625{ 626 return pWin->firstChild; 627} 628 629/****** 630 * 631 * miSetShape 632 * The border/window shape has changed. Recompute winSize/borderSize 633 * and send appropriate exposure events 634 */ 635 636void 637miSetShape(WindowPtr pWin, int kind) 638{ 639 Bool WasViewable = (Bool) (pWin->viewable); 640 ScreenPtr pScreen = pWin->drawable.pScreen; 641 Bool anyMarked = FALSE; 642 WindowPtr pLayerWin; 643 644 if (kind != ShapeInput) { 645 if (WasViewable) { 646 anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pWin, 647 &pLayerWin); 648 if (pWin->valdata) { 649 if (HasBorder(pWin)) { 650 RegionPtr borderVisible; 651 652 borderVisible = RegionCreate(NullBox, 1); 653 RegionSubtract(borderVisible, 654 &pWin->borderClip, &pWin->winSize); 655 pWin->valdata->before.borderVisible = borderVisible; 656 } 657 pWin->valdata->before.resized = TRUE; 658 } 659 } 660 661 SetWinSize(pWin); 662 SetBorderSize(pWin); 663 664 ResizeChildrenWinSize(pWin, 0, 0, 0, 0); 665 666 if (WasViewable) { 667 anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin, pWin, NULL); 668 669 if (anyMarked) { 670 (*pScreen->ValidateTree) (pLayerWin->parent, NullWindow, 671 VTOther); 672 (*pScreen->HandleExposures) (pLayerWin->parent); 673 if (pScreen->PostValidateTree) 674 (*pScreen->PostValidateTree) (pLayerWin->parent, NULL, 675 VTOther); 676 } 677 } 678 } 679 if (pWin->realized) 680 WindowsRestructured(); 681 CheckCursorConfinement(pWin); 682} 683 684/* Keeps the same inside(!) origin */ 685 686void 687miChangeBorderWidth(WindowPtr pWin, unsigned int width) 688{ 689 int oldwidth; 690 Bool anyMarked = FALSE; 691 ScreenPtr pScreen; 692 Bool WasViewable = (Bool) (pWin->viewable); 693 Bool HadBorder; 694 WindowPtr pLayerWin; 695 696 oldwidth = wBorderWidth(pWin); 697 if (oldwidth == width) 698 return; 699 HadBorder = HasBorder(pWin); 700 pScreen = pWin->drawable.pScreen; 701 if (WasViewable && width < oldwidth) 702 anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pWin, &pLayerWin); 703 704 pWin->borderWidth = width; 705 SetBorderSize(pWin); 706 707 if (WasViewable) { 708 if (width > oldwidth) { 709 anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pWin, 710 &pLayerWin); 711 /* 712 * save the old border visible region to correctly compute 713 * borderExposed. 714 */ 715 if (pWin->valdata && HadBorder) { 716 RegionPtr borderVisible; 717 718 borderVisible = RegionCreate(NULL, 1); 719 RegionSubtract(borderVisible, 720 &pWin->borderClip, &pWin->winSize); 721 pWin->valdata->before.borderVisible = borderVisible; 722 } 723 } 724 725 if (anyMarked) { 726 (*pScreen->ValidateTree) (pLayerWin->parent, pLayerWin, VTOther); 727 (*pScreen->HandleExposures) (pLayerWin->parent); 728 if (pScreen->PostValidateTree) 729 (*pScreen->PostValidateTree) (pLayerWin->parent, pLayerWin, 730 VTOther); 731 } 732 } 733 if (pWin->realized) 734 WindowsRestructured(); 735} 736 737void 738miMarkUnrealizedWindow(WindowPtr pChild, WindowPtr pWin, Bool fromConfigure) 739{ 740 if ((pChild != pWin) || fromConfigure) { 741 RegionEmpty(&pChild->clipList); 742 if (pChild->drawable.pScreen->ClipNotify) 743 (*pChild->drawable.pScreen->ClipNotify) (pChild, 0, 0); 744 RegionEmpty(&pChild->borderClip); 745 } 746} 747 748WindowPtr 749miSpriteTrace(SpritePtr pSprite, int x, int y) 750{ 751 WindowPtr pWin; 752 BoxRec box; 753 754 pWin = DeepestSpriteWin(pSprite)->firstChild; 755 while (pWin) { 756 if ((pWin->mapped) && 757 (x >= pWin->drawable.x - wBorderWidth(pWin)) && 758 (x < pWin->drawable.x + (int) pWin->drawable.width + 759 wBorderWidth(pWin)) && 760 (y >= pWin->drawable.y - wBorderWidth(pWin)) && 761 (y < pWin->drawable.y + (int) pWin->drawable.height + 762 wBorderWidth(pWin)) 763 /* When a window is shaped, a further check 764 * is made to see if the point is inside 765 * borderSize 766 */ 767 && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y)) 768 && (!wInputShape(pWin) || 769 RegionContainsPoint(wInputShape(pWin), 770 x - pWin->drawable.x, 771 y - pWin->drawable.y, &box)) 772 /* In rootless mode windows may be offscreen, even when 773 * they're in X's stack. (E.g. if the native window system 774 * implements some form of virtual desktop system). 775 */ 776 && !pWin->unhittable) { 777 if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize) { 778 pSprite->spriteTraceSize += 10; 779 pSprite->spriteTrace = reallocarray(pSprite->spriteTrace, 780 pSprite->spriteTraceSize, 781 sizeof(WindowPtr)); 782 } 783 pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin; 784 pWin = pWin->firstChild; 785 } 786 else 787 pWin = pWin->nextSib; 788 } 789 return DeepestSpriteWin(pSprite); 790} 791 792/** 793 * Traversed from the root window to the window at the position x/y. While 794 * traversing, it sets up the traversal history in the spriteTrace array. 795 * After completing, the spriteTrace history is set in the following way: 796 * spriteTrace[0] ... root window 797 * spriteTrace[1] ... top level window that encloses x/y 798 * ... 799 * spriteTrace[spriteTraceGood - 1] ... window at x/y 800 * 801 * @returns the window at the given coordinates. 802 */ 803WindowPtr 804miXYToWindow(ScreenPtr pScreen, SpritePtr pSprite, int x, int y) 805{ 806 pSprite->spriteTraceGood = 1; /* root window still there */ 807 return miSpriteTrace(pSprite, x, y); 808} 809