1
2 /***********************************************************
3
4 Copyright 1987, 1998 The Open Group
5
6 Permission to use, copy, modify, distribute, and sell this software and its
7 documentation for any purpose is hereby granted without fee, provided that
8 the above copyright notice appear in all copies and that both that
9 copyright notice and this permission notice appear in supporting
10 documentation.
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of The Open Group shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from The Open Group.
25
26 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
27
28 All Rights Reserved
29
30 Permission to use, copy, modify, and distribute this software and its
31 documentation for any purpose and without fee is hereby granted,
32 provided that the above copyright notice appear in all copies and that
33 both that copyright notice and this permission notice appear in
34 supporting documentation, and that the name of Digital not be
35 used in advertising or publicity pertaining to distribution of the
36 software without specific, written prior permission.
37
38 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
44 SOFTWARE.
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
62 void
miClearToBackground(WindowPtr pWin,int x,int y,int w,int h,Bool generateExposures)63 miClearToBackground(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
120 void
miMarkWindow(WindowPtr pWin)121 miMarkWindow(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
135 Bool
miMarkOverlappedWindows(WindowPtr pWin,WindowPtr pFirst,WindowPtr * ppLayerWin)136 miMarkOverlappedWindows(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 *****/
210 void
miHandleValidateExposures(WindowPtr pWin)211 miHandleValidateExposures(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
243 void
miMoveWindow(WindowPtr pWin,int x,int y,WindowPtr pNextSib,VTKind kind)244 miMoveWindow(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
310 static int
miRecomputeExposures(WindowPtr pWin,void * value)311 miRecomputeExposures(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
341 void
miResizeWindow(WindowPtr pWin,int x,int y,unsigned int w,unsigned int h,WindowPtr pSib)342 miResizeWindow(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
623 WindowPtr
miGetLayerWindow(WindowPtr pWin)624 miGetLayerWindow(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
636 void
miSetShape(WindowPtr pWin,int kind)637 miSetShape(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
686 void
miChangeBorderWidth(WindowPtr pWin,unsigned int width)687 miChangeBorderWidth(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
737 void
miMarkUnrealizedWindow(WindowPtr pChild,WindowPtr pWin,Bool fromConfigure)738 miMarkUnrealizedWindow(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
748 WindowPtr
miSpriteTrace(SpritePtr pSprite,int x,int y)749 miSpriteTrace(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 */
803 WindowPtr
miXYToWindow(ScreenPtr pScreen,SpritePtr pSprite,int x,int y)804 miXYToWindow(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