1
2 #ifdef HAVE_DIX_CONFIG_H
3 #include <dix-config.h>
4 #endif
5
6 #include <X11/X.h>
7 #include "scrnintstr.h"
8 #include <X11/extensions/shapeproto.h>
9 #include "validate.h"
10 #include "windowstr.h"
11 #include "mi.h"
12 #include "gcstruct.h"
13 #include "regionstr.h"
14 #include "privates.h"
15 #include "mivalidate.h"
16 #include "mioverlay.h"
17 #include "migc.h"
18
19 #include "globals.h"
20
21 typedef struct {
22 RegionRec exposed;
23 RegionRec borderExposed;
24 RegionPtr borderVisible;
25 DDXPointRec oldAbsCorner;
26 } miOverlayValDataRec, *miOverlayValDataPtr;
27
28 typedef struct _TreeRec {
29 WindowPtr pWin;
30 struct _TreeRec *parent;
31 struct _TreeRec *firstChild;
32 struct _TreeRec *lastChild;
33 struct _TreeRec *prevSib;
34 struct _TreeRec *nextSib;
35 RegionRec borderClip;
36 RegionRec clipList;
37 unsigned visibility;
38 miOverlayValDataPtr valdata;
39 } miOverlayTreeRec, *miOverlayTreePtr;
40
41 typedef struct {
42 miOverlayTreePtr tree;
43 } miOverlayWindowRec, *miOverlayWindowPtr;
44
45 typedef struct {
46 CloseScreenProcPtr CloseScreen;
47 CreateWindowProcPtr CreateWindow;
48 DestroyWindowProcPtr DestroyWindow;
49 UnrealizeWindowProcPtr UnrealizeWindow;
50 RealizeWindowProcPtr RealizeWindow;
51 miOverlayTransFunc MakeTransparent;
52 miOverlayInOverlayFunc InOverlay;
53 Bool underlayMarked;
54 Bool copyUnderlay;
55 } miOverlayScreenRec, *miOverlayScreenPtr;
56
57 static DevPrivateKeyRec miOverlayWindowKeyRec;
58
59 #define miOverlayWindowKey (&miOverlayWindowKeyRec)
60 static DevPrivateKeyRec miOverlayScreenKeyRec;
61
62 #define miOverlayScreenKey (&miOverlayScreenKeyRec)
63
64 static void RebuildTree(WindowPtr);
65 static Bool HasUnderlayChildren(WindowPtr);
66 static void MarkUnderlayWindow(WindowPtr);
67 static Bool CollectUnderlayChildrenRegions(WindowPtr, RegionPtr);
68
69 static Bool miOverlayCloseScreen(ScreenPtr);
70 static Bool miOverlayCreateWindow(WindowPtr);
71 static Bool miOverlayDestroyWindow(WindowPtr);
72 static Bool miOverlayUnrealizeWindow(WindowPtr);
73 static Bool miOverlayRealizeWindow(WindowPtr);
74 static void miOverlayMarkWindow(WindowPtr);
75 static void miOverlayReparentWindow(WindowPtr, WindowPtr);
76 static void miOverlayRestackWindow(WindowPtr, WindowPtr);
77 static Bool miOverlayMarkOverlappedWindows(WindowPtr, WindowPtr, WindowPtr *);
78 static void miOverlayMarkUnrealizedWindow(WindowPtr, WindowPtr, Bool);
79 static int miOverlayValidateTree(WindowPtr, WindowPtr, VTKind);
80 static void miOverlayHandleExposures(WindowPtr);
81 static void miOverlayMoveWindow(WindowPtr, int, int, WindowPtr, VTKind);
82 static void miOverlayWindowExposures(WindowPtr, RegionPtr);
83 static void miOverlayResizeWindow(WindowPtr, int, int, unsigned int,
84 unsigned int, WindowPtr);
85 static void miOverlayClearToBackground(WindowPtr, int, int, int, int, Bool);
86
87 static void miOverlaySetShape(WindowPtr, int);
88 static void miOverlayChangeBorderWidth(WindowPtr, unsigned int);
89
90 #define MIOVERLAY_GET_SCREEN_PRIVATE(pScreen) ((miOverlayScreenPtr) \
91 dixLookupPrivate(&(pScreen)->devPrivates, miOverlayScreenKey))
92 #define MIOVERLAY_GET_WINDOW_PRIVATE(pWin) ((miOverlayWindowPtr) \
93 dixLookupPrivate(&(pWin)->devPrivates, miOverlayWindowKey))
94 #define MIOVERLAY_GET_WINDOW_TREE(pWin) \
95 (MIOVERLAY_GET_WINDOW_PRIVATE(pWin)->tree)
96
97 #define IN_UNDERLAY(w) MIOVERLAY_GET_WINDOW_TREE(w)
98 #define IN_OVERLAY(w) !MIOVERLAY_GET_WINDOW_TREE(w)
99
100 #define MARK_OVERLAY(w) miMarkWindow(w)
101 #define MARK_UNDERLAY(w) MarkUnderlayWindow(w)
102
103 #define HasParentRelativeBorder(w) (!(w)->borderIsPixel && \
104 HasBorder(w) && \
105 (w)->backgroundState == ParentRelative)
106
107 Bool
miInitOverlay(ScreenPtr pScreen,miOverlayInOverlayFunc inOverlayFunc,miOverlayTransFunc transFunc)108 miInitOverlay(ScreenPtr pScreen,
109 miOverlayInOverlayFunc inOverlayFunc,
110 miOverlayTransFunc transFunc)
111 {
112 miOverlayScreenPtr pScreenPriv;
113
114 if (!inOverlayFunc || !transFunc)
115 return FALSE;
116
117 if (!dixRegisterPrivateKey
118 (&miOverlayWindowKeyRec, PRIVATE_WINDOW, sizeof(miOverlayWindowRec)))
119 return FALSE;
120
121 if (!dixRegisterPrivateKey(&miOverlayScreenKeyRec, PRIVATE_SCREEN, 0))
122 return FALSE;
123
124 if (!(pScreenPriv = malloc(sizeof(miOverlayScreenRec))))
125 return FALSE;
126
127 dixSetPrivate(&pScreen->devPrivates, miOverlayScreenKey, pScreenPriv);
128
129 pScreenPriv->InOverlay = inOverlayFunc;
130 pScreenPriv->MakeTransparent = transFunc;
131 pScreenPriv->underlayMarked = FALSE;
132
133 pScreenPriv->CloseScreen = pScreen->CloseScreen;
134 pScreenPriv->CreateWindow = pScreen->CreateWindow;
135 pScreenPriv->DestroyWindow = pScreen->DestroyWindow;
136 pScreenPriv->UnrealizeWindow = pScreen->UnrealizeWindow;
137 pScreenPriv->RealizeWindow = pScreen->RealizeWindow;
138
139 pScreen->CloseScreen = miOverlayCloseScreen;
140 pScreen->CreateWindow = miOverlayCreateWindow;
141 pScreen->DestroyWindow = miOverlayDestroyWindow;
142 pScreen->UnrealizeWindow = miOverlayUnrealizeWindow;
143 pScreen->RealizeWindow = miOverlayRealizeWindow;
144
145 pScreen->ReparentWindow = miOverlayReparentWindow;
146 pScreen->RestackWindow = miOverlayRestackWindow;
147 pScreen->MarkOverlappedWindows = miOverlayMarkOverlappedWindows;
148 pScreen->MarkUnrealizedWindow = miOverlayMarkUnrealizedWindow;
149 pScreen->ValidateTree = miOverlayValidateTree;
150 pScreen->HandleExposures = miOverlayHandleExposures;
151 pScreen->MoveWindow = miOverlayMoveWindow;
152 pScreen->WindowExposures = miOverlayWindowExposures;
153 pScreen->ResizeWindow = miOverlayResizeWindow;
154 pScreen->MarkWindow = miOverlayMarkWindow;
155 pScreen->ClearToBackground = miOverlayClearToBackground;
156 pScreen->SetShape = miOverlaySetShape;
157 pScreen->ChangeBorderWidth = miOverlayChangeBorderWidth;
158
159 return TRUE;
160 }
161
162 static Bool
miOverlayCloseScreen(ScreenPtr pScreen)163 miOverlayCloseScreen(ScreenPtr pScreen)
164 {
165 miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
166
167 pScreen->CloseScreen = pScreenPriv->CloseScreen;
168 pScreen->CreateWindow = pScreenPriv->CreateWindow;
169 pScreen->DestroyWindow = pScreenPriv->DestroyWindow;
170 pScreen->UnrealizeWindow = pScreenPriv->UnrealizeWindow;
171 pScreen->RealizeWindow = pScreenPriv->RealizeWindow;
172
173 free(pScreenPriv);
174
175 return (*pScreen->CloseScreen) (pScreen);
176 }
177
178 static Bool
miOverlayCreateWindow(WindowPtr pWin)179 miOverlayCreateWindow(WindowPtr pWin)
180 {
181 ScreenPtr pScreen = pWin->drawable.pScreen;
182 miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
183 miOverlayWindowPtr pWinPriv = MIOVERLAY_GET_WINDOW_PRIVATE(pWin);
184 miOverlayTreePtr pTree = NULL;
185 Bool result = TRUE;
186
187 pWinPriv->tree = NULL;
188
189 if (!pWin->parent || !((*pScreenPriv->InOverlay) (pWin))) {
190 if (!(pTree = (miOverlayTreePtr) calloc(1, sizeof(miOverlayTreeRec))))
191 return FALSE;
192 }
193
194 if (pScreenPriv->CreateWindow) {
195 pScreen->CreateWindow = pScreenPriv->CreateWindow;
196 result = (*pScreen->CreateWindow) (pWin);
197 pScreen->CreateWindow = miOverlayCreateWindow;
198 }
199
200 if (pTree) {
201 if (result) {
202 pTree->pWin = pWin;
203 pTree->visibility = VisibilityNotViewable;
204 pWinPriv->tree = pTree;
205 if (pWin->parent) {
206 RegionNull(&(pTree->borderClip));
207 RegionNull(&(pTree->clipList));
208 RebuildTree(pWin);
209 }
210 else {
211 BoxRec fullBox;
212
213 fullBox.x1 = 0;
214 fullBox.y1 = 0;
215 fullBox.x2 = pScreen->width;
216 fullBox.y2 = pScreen->height;
217 RegionInit(&(pTree->borderClip), &fullBox, 1);
218 RegionInit(&(pTree->clipList), &fullBox, 1);
219 }
220 }
221 else
222 free(pTree);
223 }
224
225 return TRUE;
226 }
227
228 static Bool
miOverlayDestroyWindow(WindowPtr pWin)229 miOverlayDestroyWindow(WindowPtr pWin)
230 {
231 ScreenPtr pScreen = pWin->drawable.pScreen;
232 miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
233 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
234 Bool result = TRUE;
235
236 if (pTree) {
237 if (pTree->prevSib)
238 pTree->prevSib->nextSib = pTree->nextSib;
239 else if (pTree->parent)
240 pTree->parent->firstChild = pTree->nextSib;
241
242 if (pTree->nextSib)
243 pTree->nextSib->prevSib = pTree->prevSib;
244 else if (pTree->parent)
245 pTree->parent->lastChild = pTree->prevSib;
246
247 RegionUninit(&(pTree->borderClip));
248 RegionUninit(&(pTree->clipList));
249 free(pTree);
250 }
251
252 if (pScreenPriv->DestroyWindow) {
253 pScreen->DestroyWindow = pScreenPriv->DestroyWindow;
254 result = (*pScreen->DestroyWindow) (pWin);
255 pScreen->DestroyWindow = miOverlayDestroyWindow;
256 }
257
258 return result;
259 }
260
261 static Bool
miOverlayUnrealizeWindow(WindowPtr pWin)262 miOverlayUnrealizeWindow(WindowPtr pWin)
263 {
264 ScreenPtr pScreen = pWin->drawable.pScreen;
265 miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
266 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
267 Bool result = TRUE;
268
269 if (pTree)
270 pTree->visibility = VisibilityNotViewable;
271
272 if (pScreenPriv->UnrealizeWindow) {
273 pScreen->UnrealizeWindow = pScreenPriv->UnrealizeWindow;
274 result = (*pScreen->UnrealizeWindow) (pWin);
275 pScreen->UnrealizeWindow = miOverlayUnrealizeWindow;
276 }
277
278 return result;
279 }
280
281 static Bool
miOverlayRealizeWindow(WindowPtr pWin)282 miOverlayRealizeWindow(WindowPtr pWin)
283 {
284 ScreenPtr pScreen = pWin->drawable.pScreen;
285 miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
286 Bool result = TRUE;
287
288 if (pScreenPriv->RealizeWindow) {
289 pScreen->RealizeWindow = pScreenPriv->RealizeWindow;
290 result = (*pScreen->RealizeWindow) (pWin);
291 pScreen->RealizeWindow = miOverlayRealizeWindow;
292 }
293
294 /* we only need to catch the root window realization */
295
296 if (result && !pWin->parent && !((*pScreenPriv->InOverlay) (pWin))) {
297 BoxRec box;
298
299 box.x1 = box.y1 = 0;
300 box.x2 = pWin->drawable.width;
301 box.y2 = pWin->drawable.height;
302 (*pScreenPriv->MakeTransparent) (pScreen, 1, &box);
303 }
304
305 return result;
306 }
307
308 static void
miOverlayReparentWindow(WindowPtr pWin,WindowPtr pPriorParent)309 miOverlayReparentWindow(WindowPtr pWin, WindowPtr pPriorParent)
310 {
311 if (IN_UNDERLAY(pWin) || HasUnderlayChildren(pWin)) {
312 /* This could probably be more optimal */
313 RebuildTree(pWin->drawable.pScreen->root->firstChild);
314 }
315 }
316
317 static void
miOverlayRestackWindow(WindowPtr pWin,WindowPtr oldNextSib)318 miOverlayRestackWindow(WindowPtr pWin, WindowPtr oldNextSib)
319 {
320 if (IN_UNDERLAY(pWin) || HasUnderlayChildren(pWin)) {
321 /* This could probably be more optimal */
322 RebuildTree(pWin);
323 }
324 }
325
326 static Bool
miOverlayMarkOverlappedWindows(WindowPtr pWin,WindowPtr pFirst,WindowPtr * pLayerWin)327 miOverlayMarkOverlappedWindows(WindowPtr pWin,
328 WindowPtr pFirst, WindowPtr *pLayerWin)
329 {
330 WindowPtr pChild, pLast;
331 Bool overMarked, underMarked, doUnderlay, markAll;
332 miOverlayTreePtr pTree = NULL, tLast, tChild;
333 BoxPtr box;
334
335 overMarked = underMarked = markAll = FALSE;
336
337 if (pLayerWin)
338 *pLayerWin = pWin; /* hah! */
339
340 doUnderlay = (IN_UNDERLAY(pWin) || HasUnderlayChildren(pWin));
341
342 box = RegionExtents(&pWin->borderSize);
343
344 if ((pChild = pFirst)) {
345 pLast = pChild->parent->lastChild;
346 while (1) {
347 if (pChild == pWin)
348 markAll = TRUE;
349
350 if (doUnderlay && IN_UNDERLAY(pChild))
351 pTree = MIOVERLAY_GET_WINDOW_TREE(pChild);
352
353 if (pChild->viewable) {
354 if (RegionBroken(&pChild->winSize))
355 SetWinSize(pChild);
356 if (RegionBroken(&pChild->borderSize))
357 SetBorderSize(pChild);
358
359 if (markAll || RegionContainsRect(&pChild->borderSize, box)) {
360 MARK_OVERLAY(pChild);
361 overMarked = TRUE;
362 if (doUnderlay && IN_UNDERLAY(pChild)) {
363 MARK_UNDERLAY(pChild);
364 underMarked = TRUE;
365 }
366 if (pChild->firstChild) {
367 pChild = pChild->firstChild;
368 continue;
369 }
370 }
371 }
372 while (!pChild->nextSib && (pChild != pLast)) {
373 pChild = pChild->parent;
374 if (doUnderlay && IN_UNDERLAY(pChild))
375 pTree = MIOVERLAY_GET_WINDOW_TREE(pChild);
376 }
377
378 if (pChild == pWin)
379 markAll = FALSE;
380
381 if (pChild == pLast)
382 break;
383
384 pChild = pChild->nextSib;
385 }
386 if (overMarked)
387 MARK_OVERLAY(pWin->parent);
388 }
389
390 if (doUnderlay && !pTree) {
391 if (!(pTree = MIOVERLAY_GET_WINDOW_TREE(pWin))) {
392 pChild = pWin->lastChild;
393 while (1) {
394 if ((pTree = MIOVERLAY_GET_WINDOW_TREE(pChild)))
395 break;
396
397 if (pChild->lastChild) {
398 pChild = pChild->lastChild;
399 continue;
400 }
401
402 while (!pChild->prevSib)
403 pChild = pChild->parent;
404
405 pChild = pChild->prevSib;
406 }
407 }
408 }
409
410 if (pTree && pTree->nextSib) {
411 tChild = pTree->parent->lastChild;
412 tLast = pTree->nextSib;
413
414 while (1) {
415 if (tChild->pWin->viewable) {
416 if (RegionBroken(&tChild->pWin->winSize))
417 SetWinSize(tChild->pWin);
418 if (RegionBroken(&tChild->pWin->borderSize))
419 SetBorderSize(tChild->pWin);
420
421 if (RegionContainsRect(&(tChild->pWin->borderSize), box)) {
422 MARK_UNDERLAY(tChild->pWin);
423 underMarked = TRUE;
424 }
425 }
426
427 if (tChild->lastChild) {
428 tChild = tChild->lastChild;
429 continue;
430 }
431
432 while (!tChild->prevSib && (tChild != tLast))
433 tChild = tChild->parent;
434
435 if (tChild == tLast)
436 break;
437
438 tChild = tChild->prevSib;
439 }
440 }
441
442 if (underMarked) {
443 ScreenPtr pScreen = pWin->drawable.pScreen;
444
445 MARK_UNDERLAY(pTree->parent->pWin);
446 MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->underlayMarked = TRUE;
447 }
448
449 return underMarked || overMarked;
450 }
451
452 static void
miOverlayComputeClips(WindowPtr pParent,RegionPtr universe,VTKind kind,RegionPtr exposed)453 miOverlayComputeClips(WindowPtr pParent,
454 RegionPtr universe, VTKind kind, RegionPtr exposed)
455 {
456 ScreenPtr pScreen = pParent->drawable.pScreen;
457 int oldVis, newVis, dx, dy;
458 BoxRec borderSize;
459 RegionPtr borderVisible;
460 RegionRec childUniverse, childUnion;
461 miOverlayTreePtr tParent = MIOVERLAY_GET_WINDOW_TREE(pParent);
462 miOverlayTreePtr tChild;
463 Bool overlap;
464
465 borderSize.x1 = pParent->drawable.x - wBorderWidth(pParent);
466 borderSize.y1 = pParent->drawable.y - wBorderWidth(pParent);
467 dx = (int) pParent->drawable.x + (int) pParent->drawable.width +
468 wBorderWidth(pParent);
469 if (dx > 32767)
470 dx = 32767;
471 borderSize.x2 = dx;
472 dy = (int) pParent->drawable.y + (int) pParent->drawable.height +
473 wBorderWidth(pParent);
474 if (dy > 32767)
475 dy = 32767;
476 borderSize.y2 = dy;
477
478 oldVis = tParent->visibility;
479 switch (RegionContainsRect(universe, &borderSize)) {
480 case rgnIN:
481 newVis = VisibilityUnobscured;
482 break;
483 case rgnPART:
484 newVis = VisibilityPartiallyObscured;
485 {
486 RegionPtr pBounding;
487
488 if ((pBounding = wBoundingShape(pParent))) {
489 switch (miShapedWindowIn(universe, pBounding,
490 &borderSize,
491 pParent->drawable.x,
492 pParent->drawable.y)) {
493 case rgnIN:
494 newVis = VisibilityUnobscured;
495 break;
496 case rgnOUT:
497 newVis = VisibilityFullyObscured;
498 break;
499 }
500 }
501 }
502 break;
503 default:
504 newVis = VisibilityFullyObscured;
505 break;
506 }
507 tParent->visibility = newVis;
508
509 dx = pParent->drawable.x - tParent->valdata->oldAbsCorner.x;
510 dy = pParent->drawable.y - tParent->valdata->oldAbsCorner.y;
511
512 switch (kind) {
513 case VTMap:
514 case VTStack:
515 case VTUnmap:
516 break;
517 case VTMove:
518 if ((oldVis == newVis) &&
519 ((oldVis == VisibilityFullyObscured) ||
520 (oldVis == VisibilityUnobscured))) {
521 tChild = tParent;
522 while (1) {
523 if (tChild->pWin->viewable) {
524 if (tChild->visibility != VisibilityFullyObscured) {
525 RegionTranslate(&tChild->borderClip, dx, dy);
526 RegionTranslate(&tChild->clipList, dx, dy);
527
528 tChild->pWin->drawable.serialNumber =
529 NEXT_SERIAL_NUMBER;
530 if (pScreen->ClipNotify)
531 (*pScreen->ClipNotify) (tChild->pWin, dx, dy);
532 }
533 if (tChild->valdata) {
534 RegionNull(&tChild->valdata->borderExposed);
535 if (HasParentRelativeBorder(tChild->pWin)) {
536 RegionSubtract(&tChild->valdata->borderExposed,
537 &tChild->borderClip,
538 &tChild->pWin->winSize);
539 }
540 RegionNull(&tChild->valdata->exposed);
541 }
542 if (tChild->firstChild) {
543 tChild = tChild->firstChild;
544 continue;
545 }
546 }
547 while (!tChild->nextSib && (tChild != tParent))
548 tChild = tChild->parent;
549 if (tChild == tParent)
550 break;
551 tChild = tChild->nextSib;
552 }
553 return;
554 }
555 /* fall through */
556 default:
557 if (dx || dy) {
558 RegionTranslate(&tParent->borderClip, dx, dy);
559 RegionTranslate(&tParent->clipList, dx, dy);
560 }
561 break;
562 case VTBroken:
563 RegionEmpty(&tParent->borderClip);
564 RegionEmpty(&tParent->clipList);
565 break;
566 }
567
568 borderVisible = tParent->valdata->borderVisible;
569 RegionNull(&tParent->valdata->borderExposed);
570 RegionNull(&tParent->valdata->exposed);
571
572 if (HasBorder(pParent)) {
573 if (borderVisible) {
574 RegionSubtract(exposed, universe, borderVisible);
575 RegionDestroy(borderVisible);
576 }
577 else
578 RegionSubtract(exposed, universe, &tParent->borderClip);
579
580 if (HasParentRelativeBorder(pParent) && (dx || dy))
581 RegionSubtract(&tParent->valdata->borderExposed,
582 universe, &pParent->winSize);
583 else
584 RegionSubtract(&tParent->valdata->borderExposed,
585 exposed, &pParent->winSize);
586
587 RegionCopy(&tParent->borderClip, universe);
588 RegionIntersect(universe, universe, &pParent->winSize);
589 }
590 else
591 RegionCopy(&tParent->borderClip, universe);
592
593 if ((tChild = tParent->firstChild) && pParent->mapped) {
594 RegionNull(&childUniverse);
595 RegionNull(&childUnion);
596
597 for (; tChild; tChild = tChild->nextSib) {
598 if (tChild->pWin->viewable)
599 RegionAppend(&childUnion, &tChild->pWin->borderSize);
600 }
601
602 RegionValidate(&childUnion, &overlap);
603
604 for (tChild = tParent->firstChild; tChild; tChild = tChild->nextSib) {
605 if (tChild->pWin->viewable) {
606 if (tChild->valdata) {
607 RegionIntersect(&childUniverse, universe,
608 &tChild->pWin->borderSize);
609 miOverlayComputeClips(tChild->pWin, &childUniverse,
610 kind, exposed);
611 }
612 if (overlap)
613 RegionSubtract(universe, universe,
614 &tChild->pWin->borderSize);
615 }
616 }
617 if (!overlap)
618 RegionSubtract(universe, universe, &childUnion);
619 RegionUninit(&childUnion);
620 RegionUninit(&childUniverse);
621 }
622
623 if (oldVis == VisibilityFullyObscured || oldVis == VisibilityNotViewable) {
624 RegionCopy(&tParent->valdata->exposed, universe);
625 }
626 else if (newVis != VisibilityFullyObscured &&
627 newVis != VisibilityNotViewable) {
628 RegionSubtract(&tParent->valdata->exposed,
629 universe, &tParent->clipList);
630 }
631
632 /* HACK ALERT - copying contents of regions, instead of regions */
633 {
634 RegionRec tmp;
635
636 tmp = tParent->clipList;
637 tParent->clipList = *universe;
638 *universe = tmp;
639 }
640
641 pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
642
643 if (pScreen->ClipNotify)
644 (*pScreen->ClipNotify) (pParent, dx, dy);
645 }
646
647 static void
miOverlayMarkWindow(WindowPtr pWin)648 miOverlayMarkWindow(WindowPtr pWin)
649 {
650 miOverlayTreePtr pTree = NULL;
651 WindowPtr pChild, pGrandChild;
652
653 miMarkWindow(pWin);
654
655 /* look for UnmapValdata among immediate children */
656
657 if (!(pChild = pWin->firstChild))
658 return;
659
660 for (; pChild; pChild = pChild->nextSib) {
661 if (pChild->valdata == UnmapValData) {
662 if (IN_UNDERLAY(pChild)) {
663 pTree = MIOVERLAY_GET_WINDOW_TREE(pChild);
664 pTree->valdata = (miOverlayValDataPtr) UnmapValData;
665 continue;
666 }
667 else {
668 if (!(pGrandChild = pChild->firstChild))
669 continue;
670
671 while (1) {
672 if (IN_UNDERLAY(pGrandChild)) {
673 pTree = MIOVERLAY_GET_WINDOW_TREE(pGrandChild);
674 pTree->valdata = (miOverlayValDataPtr) UnmapValData;
675 }
676 else if (pGrandChild->firstChild) {
677 pGrandChild = pGrandChild->firstChild;
678 continue;
679 }
680
681 while (!pGrandChild->nextSib && (pGrandChild != pChild))
682 pGrandChild = pGrandChild->parent;
683
684 if (pChild == pGrandChild)
685 break;
686
687 pGrandChild = pGrandChild->nextSib;
688 }
689 }
690 }
691 }
692
693 if (pTree) {
694 MARK_UNDERLAY(pTree->parent->pWin);
695 MIOVERLAY_GET_SCREEN_PRIVATE(pWin->drawable.pScreen)->underlayMarked =
696 TRUE;
697 }
698 }
699
700 static void
miOverlayMarkUnrealizedWindow(WindowPtr pChild,WindowPtr pWin,Bool fromConfigure)701 miOverlayMarkUnrealizedWindow(WindowPtr pChild,
702 WindowPtr pWin, Bool fromConfigure)
703 {
704 if ((pChild != pWin) || fromConfigure) {
705 miOverlayTreePtr pTree;
706
707 RegionEmpty(&pChild->clipList);
708 if (pChild->drawable.pScreen->ClipNotify)
709 (*pChild->drawable.pScreen->ClipNotify) (pChild, 0, 0);
710 RegionEmpty(&pChild->borderClip);
711 if ((pTree = MIOVERLAY_GET_WINDOW_TREE(pChild))) {
712 if (pTree->valdata != (miOverlayValDataPtr) UnmapValData) {
713 RegionEmpty(&pTree->clipList);
714 RegionEmpty(&pTree->borderClip);
715 }
716 }
717 }
718 }
719
720 static int
miOverlayValidateTree(WindowPtr pParent,WindowPtr pChild,VTKind kind)721 miOverlayValidateTree(WindowPtr pParent, WindowPtr pChild, /* first child effected */
722 VTKind kind)
723 {
724 ScreenPtr pScreen = pParent->drawable.pScreen;
725 miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
726 RegionRec totalClip, childClip, exposed;
727 miOverlayTreePtr tParent, tChild, tWin;
728 Bool overlap;
729 WindowPtr newParent;
730
731 if (!pPriv->underlayMarked)
732 goto SKIP_UNDERLAY;
733
734 if (!pChild)
735 pChild = pParent->firstChild;
736
737 RegionNull(&totalClip);
738 RegionNull(&childClip);
739 RegionNull(&exposed);
740
741 newParent = pParent;
742
743 while (IN_OVERLAY(newParent))
744 newParent = newParent->parent;
745
746 tParent = MIOVERLAY_GET_WINDOW_TREE(newParent);
747
748 if (IN_UNDERLAY(pChild))
749 tChild = MIOVERLAY_GET_WINDOW_TREE(pChild);
750 else
751 tChild = tParent->firstChild;
752
753 if (RegionBroken(&tParent->clipList) && !RegionBroken(&tParent->borderClip)) {
754 kind = VTBroken;
755 RegionCopy(&totalClip, &tParent->borderClip);
756 RegionIntersect(&totalClip, &totalClip, &tParent->pWin->winSize);
757
758 for (tWin = tParent->firstChild; tWin != tChild; tWin = tWin->nextSib) {
759 if (tWin->pWin->viewable)
760 RegionSubtract(&totalClip, &totalClip, &tWin->pWin->borderSize);
761 }
762 RegionEmpty(&tParent->clipList);
763 }
764 else {
765 for (tWin = tChild; tWin; tWin = tWin->nextSib) {
766 if (tWin->valdata)
767 RegionAppend(&totalClip, &tWin->borderClip);
768 }
769 RegionValidate(&totalClip, &overlap);
770 }
771
772 if (kind != VTStack)
773 RegionUnion(&totalClip, &totalClip, &tParent->clipList);
774
775 for (tWin = tChild; tWin; tWin = tWin->nextSib) {
776 if (tWin->valdata) {
777 if (tWin->pWin->viewable) {
778 RegionIntersect(&childClip, &totalClip,
779 &tWin->pWin->borderSize);
780 miOverlayComputeClips(tWin->pWin, &childClip, kind, &exposed);
781 RegionSubtract(&totalClip, &totalClip, &tWin->pWin->borderSize);
782 }
783 else { /* Means we are unmapping */
784 RegionEmpty(&tWin->clipList);
785 RegionEmpty(&tWin->borderClip);
786 tWin->valdata = NULL;
787 }
788 }
789 }
790
791 RegionUninit(&childClip);
792
793 if (!((*pPriv->InOverlay) (newParent))) {
794 RegionNull(&tParent->valdata->exposed);
795 RegionNull(&tParent->valdata->borderExposed);
796 }
797
798 switch (kind) {
799 case VTStack:
800 break;
801 default:
802 if (!((*pPriv->InOverlay) (newParent)))
803 RegionSubtract(&tParent->valdata->exposed, &totalClip,
804 &tParent->clipList);
805 /* fall through */
806 case VTMap:
807 RegionCopy(&tParent->clipList, &totalClip);
808 if (!((*pPriv->InOverlay) (newParent)))
809 newParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
810 break;
811 }
812
813 RegionUninit(&totalClip);
814 RegionUninit(&exposed);
815
816 SKIP_UNDERLAY:
817
818 miValidateTree(pParent, pChild, kind);
819
820 return 1;
821 }
822
823 static void
miOverlayHandleExposures(WindowPtr pWin)824 miOverlayHandleExposures(WindowPtr pWin)
825 {
826 ScreenPtr pScreen = pWin->drawable.pScreen;
827 miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
828 WindowPtr pChild;
829 ValidatePtr val;
830 WindowExposuresProcPtr WindowExposures;
831
832 WindowExposures = pWin->drawable.pScreen->WindowExposures;
833 if (pPriv->underlayMarked) {
834 miOverlayTreePtr pTree;
835 miOverlayValDataPtr mival;
836
837 pChild = pWin;
838 while (IN_OVERLAY(pChild))
839 pChild = pChild->parent;
840
841 pTree = MIOVERLAY_GET_WINDOW_TREE(pChild);
842
843 while (1) {
844 if ((mival = pTree->valdata)) {
845 if (!((*pPriv->InOverlay) (pTree->pWin))) {
846 if (RegionNotEmpty(&mival->borderExposed)) {
847 pScreen->PaintWindow(pTree->pWin, &mival->borderExposed,
848 PW_BORDER);
849 }
850 RegionUninit(&mival->borderExposed);
851
852 (*WindowExposures) (pTree->pWin, &mival->exposed);
853 RegionUninit(&mival->exposed);
854 }
855 free(mival);
856 pTree->valdata = NULL;
857 if (pTree->firstChild) {
858 pTree = pTree->firstChild;
859 continue;
860 }
861 }
862 while (!pTree->nextSib && (pTree->pWin != pChild))
863 pTree = pTree->parent;
864 if (pTree->pWin == pChild)
865 break;
866 pTree = pTree->nextSib;
867 }
868 pPriv->underlayMarked = FALSE;
869 }
870
871 pChild = pWin;
872 while (1) {
873 if ((val = pChild->valdata)) {
874 if (!((*pPriv->InOverlay) (pChild))) {
875 RegionUnion(&val->after.exposed, &val->after.exposed,
876 &val->after.borderExposed);
877
878 if (RegionNotEmpty(&val->after.exposed)) {
879 (*(MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->MakeTransparent))
880 (pScreen, RegionNumRects(&val->after.exposed),
881 RegionRects(&val->after.exposed));
882 }
883 }
884 else {
885 if (RegionNotEmpty(&val->after.borderExposed)) {
886 pScreen->PaintWindow(pChild, &val->after.borderExposed,
887 PW_BORDER);
888 }
889 (*WindowExposures) (pChild, &val->after.exposed);
890 }
891 RegionUninit(&val->after.borderExposed);
892 RegionUninit(&val->after.exposed);
893 free(val);
894 pChild->valdata = NULL;
895 if (pChild->firstChild) {
896 pChild = pChild->firstChild;
897 continue;
898 }
899 }
900 while (!pChild->nextSib && (pChild != pWin))
901 pChild = pChild->parent;
902 if (pChild == pWin)
903 break;
904 pChild = pChild->nextSib;
905 }
906 }
907
908 static void
miOverlayMoveWindow(WindowPtr pWin,int x,int y,WindowPtr pNextSib,VTKind kind)909 miOverlayMoveWindow(WindowPtr pWin,
910 int x, int y, WindowPtr pNextSib, VTKind kind)
911 {
912 ScreenPtr pScreen = pWin->drawable.pScreen;
913 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
914 WindowPtr pParent, windowToValidate;
915 Bool WasViewable = (Bool) (pWin->viewable);
916 short bw;
917 RegionRec overReg, underReg;
918 DDXPointRec oldpt;
919
920 if (!(pParent = pWin->parent))
921 return;
922 bw = wBorderWidth(pWin);
923
924 oldpt.x = pWin->drawable.x;
925 oldpt.y = pWin->drawable.y;
926 if (WasViewable) {
927 RegionNull(&overReg);
928 RegionNull(&underReg);
929 if (pTree) {
930 RegionCopy(&overReg, &pWin->borderClip);
931 RegionCopy(&underReg, &pTree->borderClip);
932 }
933 else {
934 RegionCopy(&overReg, &pWin->borderClip);
935 CollectUnderlayChildrenRegions(pWin, &underReg);
936 }
937 (*pScreen->MarkOverlappedWindows) (pWin, pWin, NULL);
938 }
939 pWin->origin.x = x + (int) bw;
940 pWin->origin.y = y + (int) bw;
941 x = pWin->drawable.x = pParent->drawable.x + x + (int) bw;
942 y = pWin->drawable.y = pParent->drawable.y + y + (int) bw;
943
944 SetWinSize(pWin);
945 SetBorderSize(pWin);
946
947 (*pScreen->PositionWindow) (pWin, x, y);
948
949 windowToValidate = MoveWindowInStack(pWin, pNextSib);
950
951 ResizeChildrenWinSize(pWin, x - oldpt.x, y - oldpt.y, 0, 0);
952
953 if (WasViewable) {
954 miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
955
956 (*pScreen->MarkOverlappedWindows) (pWin, windowToValidate, NULL);
957
958 (*pScreen->ValidateTree) (pWin->parent, NullWindow, kind);
959 if (RegionNotEmpty(&underReg)) {
960 pPriv->copyUnderlay = TRUE;
961 (*pWin->drawable.pScreen->CopyWindow) (pWin, oldpt, &underReg);
962 }
963 RegionUninit(&underReg);
964 if (RegionNotEmpty(&overReg)) {
965 pPriv->copyUnderlay = FALSE;
966 (*pWin->drawable.pScreen->CopyWindow) (pWin, oldpt, &overReg);
967 }
968 RegionUninit(&overReg);
969 (*pScreen->HandleExposures) (pWin->parent);
970
971 if (pScreen->PostValidateTree)
972 (*pScreen->PostValidateTree) (pWin->parent, NullWindow, kind);
973 }
974 if (pWin->realized)
975 WindowsRestructured();
976 }
977
978 #ifndef RECTLIMIT
979 #define RECTLIMIT 25
980 #endif
981
982 static void
miOverlayWindowExposures(WindowPtr pWin,RegionPtr prgn)983 miOverlayWindowExposures(WindowPtr pWin, RegionPtr prgn)
984 {
985 RegionPtr exposures = prgn;
986 ScreenPtr pScreen = pWin->drawable.pScreen;
987
988 if (prgn && !RegionNil(prgn)) {
989 RegionRec expRec;
990 int clientInterested =
991 (pWin->eventMask | wOtherEventMasks(pWin)) & ExposureMask;
992 if (clientInterested && (RegionNumRects(prgn) > RECTLIMIT)) {
993 miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
994 BoxRec box;
995
996 box = *RegionExtents(prgn);
997 exposures = &expRec;
998 RegionInit(exposures, &box, 1);
999 RegionReset(prgn, &box);
1000 /* This is the only reason why we are replacing mi's version
1001 of this file */
1002
1003 if (!((*pPriv->InOverlay) (pWin))) {
1004 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1005
1006 RegionIntersect(prgn, prgn, &pTree->clipList);
1007 }
1008 else
1009 RegionIntersect(prgn, prgn, &pWin->clipList);
1010 }
1011 pScreen->PaintWindow(pWin, prgn, PW_BACKGROUND);
1012 if (clientInterested)
1013 miSendExposures(pWin, exposures,
1014 pWin->drawable.x, pWin->drawable.y);
1015 if (exposures == &expRec)
1016 RegionUninit(exposures);
1017 RegionEmpty(prgn);
1018 }
1019 }
1020
1021 typedef struct {
1022 RegionPtr over;
1023 RegionPtr under;
1024 } miOverlayTwoRegions;
1025
1026 static int
miOverlayRecomputeExposures(WindowPtr pWin,void * value)1027 miOverlayRecomputeExposures(WindowPtr pWin, void *value)
1028 {
1029 miOverlayTwoRegions *pValid = (miOverlayTwoRegions *) value;
1030 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1031
1032 if (pWin->valdata) {
1033 /*
1034 * compute exposed regions of this window
1035 */
1036 RegionSubtract(&pWin->valdata->after.exposed,
1037 &pWin->clipList, pValid->over);
1038 /*
1039 * compute exposed regions of the border
1040 */
1041 RegionSubtract(&pWin->valdata->after.borderExposed,
1042 &pWin->borderClip, &pWin->winSize);
1043 RegionSubtract(&pWin->valdata->after.borderExposed,
1044 &pWin->valdata->after.borderExposed, pValid->over);
1045 }
1046
1047 if (pTree && pTree->valdata) {
1048 RegionSubtract(&pTree->valdata->exposed,
1049 &pTree->clipList, pValid->under);
1050 RegionSubtract(&pTree->valdata->borderExposed,
1051 &pTree->borderClip, &pWin->winSize);
1052 RegionSubtract(&pTree->valdata->borderExposed,
1053 &pTree->valdata->borderExposed, pValid->under);
1054 }
1055 else if (!pWin->valdata)
1056 return WT_NOMATCH;
1057
1058 return WT_WALKCHILDREN;
1059 }
1060
1061 static void
miOverlayResizeWindow(WindowPtr pWin,int x,int y,unsigned int w,unsigned int h,WindowPtr pSib)1062 miOverlayResizeWindow(WindowPtr pWin,
1063 int x, int y,
1064 unsigned int w, unsigned int h, WindowPtr pSib)
1065 {
1066 ScreenPtr pScreen = pWin->drawable.pScreen;
1067 WindowPtr pParent;
1068 miOverlayTreePtr tChild, pTree;
1069 Bool WasViewable = (Bool) (pWin->viewable);
1070 unsigned short width = pWin->drawable.width;
1071 unsigned short height = pWin->drawable.height;
1072 short oldx = pWin->drawable.x;
1073 short oldy = pWin->drawable.y;
1074 int bw = wBorderWidth(pWin);
1075 short dw, dh;
1076 DDXPointRec oldpt;
1077 RegionPtr oldRegion = NULL, oldRegion2 = NULL;
1078 WindowPtr pFirstChange;
1079 WindowPtr pChild;
1080 RegionPtr gravitate[StaticGravity + 1];
1081 RegionPtr gravitate2[StaticGravity + 1];
1082 unsigned g;
1083 int nx, ny; /* destination x,y */
1084 int newx, newy; /* new inner window position */
1085 RegionPtr pRegion = NULL;
1086 RegionPtr destClip, destClip2;
1087 RegionPtr oldWinClip = NULL, oldWinClip2 = NULL;
1088 RegionPtr borderVisible = NullRegion;
1089 RegionPtr borderVisible2 = NullRegion;
1090 Bool shrunk = FALSE; /* shrunk in an inner dimension */
1091 Bool moved = FALSE; /* window position changed */
1092 Bool doUnderlay;
1093
1094 /* if this is a root window, can't be resized */
1095 if (!(pParent = pWin->parent))
1096 return;
1097
1098 pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1099 doUnderlay = ((pTree) || HasUnderlayChildren(pWin));
1100 newx = pParent->drawable.x + x + bw;
1101 newy = pParent->drawable.y + y + bw;
1102 if (WasViewable) {
1103 /*
1104 * save the visible region of the window
1105 */
1106 oldRegion = RegionCreate(NullBox, 1);
1107 RegionCopy(oldRegion, &pWin->winSize);
1108 if (doUnderlay) {
1109 oldRegion2 = RegionCreate(NullBox, 1);
1110 RegionCopy(oldRegion2, &pWin->winSize);
1111 }
1112
1113 /*
1114 * categorize child windows into regions to be moved
1115 */
1116 for (g = 0; g <= StaticGravity; g++)
1117 gravitate[g] = gravitate2[g] = NULL;
1118 for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) {
1119 g = pChild->winGravity;
1120 if (g != UnmapGravity) {
1121 if (!gravitate[g])
1122 gravitate[g] = RegionCreate(NullBox, 1);
1123 RegionUnion(gravitate[g], gravitate[g], &pChild->borderClip);
1124
1125 if (doUnderlay) {
1126 if (!gravitate2[g])
1127 gravitate2[g] = RegionCreate(NullBox, 0);
1128
1129 if ((tChild = MIOVERLAY_GET_WINDOW_TREE(pChild))) {
1130 RegionUnion(gravitate2[g],
1131 gravitate2[g], &tChild->borderClip);
1132 }
1133 else
1134 CollectUnderlayChildrenRegions(pChild, gravitate2[g]);
1135 }
1136 }
1137 else {
1138 UnmapWindow(pChild, TRUE);
1139 }
1140 }
1141 (*pScreen->MarkOverlappedWindows) (pWin, pWin, NULL);
1142
1143 oldWinClip = oldWinClip2 = NULL;
1144 if (pWin->bitGravity != ForgetGravity) {
1145 oldWinClip = RegionCreate(NullBox, 1);
1146 RegionCopy(oldWinClip, &pWin->clipList);
1147 if (pTree) {
1148 oldWinClip2 = RegionCreate(NullBox, 1);
1149 RegionCopy(oldWinClip2, &pTree->clipList);
1150 }
1151 }
1152 /*
1153 * if the window is changing size, borderExposed
1154 * can't be computed correctly without some help.
1155 */
1156 if (pWin->drawable.height > h || pWin->drawable.width > w)
1157 shrunk = TRUE;
1158
1159 if (newx != oldx || newy != oldy)
1160 moved = TRUE;
1161
1162 if ((pWin->drawable.height != h || pWin->drawable.width != w) &&
1163 HasBorder(pWin)) {
1164 borderVisible = RegionCreate(NullBox, 1);
1165 if (pTree)
1166 borderVisible2 = RegionCreate(NullBox, 1);
1167 /* for tiled borders, we punt and draw the whole thing */
1168 if (pWin->borderIsPixel || !moved) {
1169 if (shrunk || moved)
1170 RegionSubtract(borderVisible,
1171 &pWin->borderClip, &pWin->winSize);
1172 else
1173 RegionCopy(borderVisible, &pWin->borderClip);
1174 if (pTree) {
1175 if (shrunk || moved)
1176 RegionSubtract(borderVisible,
1177 &pTree->borderClip, &pWin->winSize);
1178 else
1179 RegionCopy(borderVisible, &pTree->borderClip);
1180 }
1181 }
1182 }
1183 }
1184 pWin->origin.x = x + bw;
1185 pWin->origin.y = y + bw;
1186 pWin->drawable.height = h;
1187 pWin->drawable.width = w;
1188
1189 x = pWin->drawable.x = newx;
1190 y = pWin->drawable.y = newy;
1191
1192 SetWinSize(pWin);
1193 SetBorderSize(pWin);
1194
1195 dw = (int) w - (int) width;
1196 dh = (int) h - (int) height;
1197 ResizeChildrenWinSize(pWin, x - oldx, y - oldy, dw, dh);
1198
1199 /* let the hardware adjust background and border pixmaps, if any */
1200 (*pScreen->PositionWindow) (pWin, x, y);
1201
1202 pFirstChange = MoveWindowInStack(pWin, pSib);
1203
1204 if (WasViewable) {
1205 pRegion = RegionCreate(NullBox, 1);
1206
1207 (*pScreen->MarkOverlappedWindows) (pWin, pFirstChange, NULL);
1208
1209 pWin->valdata->before.resized = TRUE;
1210 pWin->valdata->before.borderVisible = borderVisible;
1211 if (pTree)
1212 pTree->valdata->borderVisible = borderVisible2;
1213
1214 (*pScreen->ValidateTree) (pWin->parent, pFirstChange, VTOther);
1215 /*
1216 * the entire window is trashed unless bitGravity
1217 * recovers portions of it
1218 */
1219 RegionCopy(&pWin->valdata->after.exposed, &pWin->clipList);
1220 if (pTree)
1221 RegionCopy(&pTree->valdata->exposed, &pTree->clipList);
1222 }
1223
1224 GravityTranslate(x, y, oldx, oldy, dw, dh, pWin->bitGravity, &nx, &ny);
1225
1226 if (WasViewable) {
1227 miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
1228 miOverlayTwoRegions TwoRegions;
1229
1230 /* avoid the border */
1231 if (HasBorder(pWin)) {
1232 int offx, offy, dx, dy;
1233
1234 /* kruft to avoid double translates for each gravity */
1235 offx = 0;
1236 offy = 0;
1237 for (g = 0; g <= StaticGravity; g++) {
1238 if (!gravitate[g] && !gravitate2[g])
1239 continue;
1240
1241 /* align winSize to gravitate[g].
1242 * winSize is in new coordinates,
1243 * gravitate[g] is still in old coordinates */
1244 GravityTranslate(x, y, oldx, oldy, dw, dh, g, &nx, &ny);
1245
1246 dx = (oldx - nx) - offx;
1247 dy = (oldy - ny) - offy;
1248 if (dx || dy) {
1249 RegionTranslate(&pWin->winSize, dx, dy);
1250 offx += dx;
1251 offy += dy;
1252 }
1253 if (gravitate[g])
1254 RegionIntersect(gravitate[g], gravitate[g], &pWin->winSize);
1255 if (gravitate2[g])
1256 RegionIntersect(gravitate2[g], gravitate2[g],
1257 &pWin->winSize);
1258 }
1259 /* get winSize back where it belongs */
1260 if (offx || offy)
1261 RegionTranslate(&pWin->winSize, -offx, -offy);
1262 }
1263 /*
1264 * add screen bits to the appropriate bucket
1265 */
1266
1267 if (oldWinClip2) {
1268 RegionCopy(pRegion, oldWinClip2);
1269 RegionTranslate(pRegion, nx - oldx, ny - oldy);
1270 RegionIntersect(oldWinClip2, pRegion, &pTree->clipList);
1271
1272 for (g = pWin->bitGravity + 1; g <= StaticGravity; g++) {
1273 if (gravitate2[g])
1274 RegionSubtract(oldWinClip2, oldWinClip2, gravitate2[g]);
1275 }
1276 RegionTranslate(oldWinClip2, oldx - nx, oldy - ny);
1277 g = pWin->bitGravity;
1278 if (!gravitate2[g])
1279 gravitate2[g] = oldWinClip2;
1280 else {
1281 RegionUnion(gravitate2[g], gravitate2[g], oldWinClip2);
1282 RegionDestroy(oldWinClip2);
1283 }
1284 }
1285
1286 if (oldWinClip) {
1287 /*
1288 * clip to new clipList
1289 */
1290 RegionCopy(pRegion, oldWinClip);
1291 RegionTranslate(pRegion, nx - oldx, ny - oldy);
1292 RegionIntersect(oldWinClip, pRegion, &pWin->clipList);
1293 /*
1294 * don't step on any gravity bits which will be copied after this
1295 * region. Note -- this assumes that the regions will be copied
1296 * in gravity order.
1297 */
1298 for (g = pWin->bitGravity + 1; g <= StaticGravity; g++) {
1299 if (gravitate[g])
1300 RegionSubtract(oldWinClip, oldWinClip, gravitate[g]);
1301 }
1302 RegionTranslate(oldWinClip, oldx - nx, oldy - ny);
1303 g = pWin->bitGravity;
1304 if (!gravitate[g])
1305 gravitate[g] = oldWinClip;
1306 else {
1307 RegionUnion(gravitate[g], gravitate[g], oldWinClip);
1308 RegionDestroy(oldWinClip);
1309 }
1310 }
1311
1312 /*
1313 * move the bits on the screen
1314 */
1315
1316 destClip = destClip2 = NULL;
1317
1318 for (g = 0; g <= StaticGravity; g++) {
1319 if (!gravitate[g] && !gravitate2[g])
1320 continue;
1321
1322 GravityTranslate(x, y, oldx, oldy, dw, dh, g, &nx, &ny);
1323
1324 oldpt.x = oldx + (x - nx);
1325 oldpt.y = oldy + (y - ny);
1326
1327 /* Note that gravitate[g] is *translated* by CopyWindow */
1328
1329 /* only copy the remaining useful bits */
1330
1331 if (gravitate[g])
1332 RegionIntersect(gravitate[g], gravitate[g], oldRegion);
1333 if (gravitate2[g])
1334 RegionIntersect(gravitate2[g], gravitate2[g], oldRegion2);
1335
1336 /* clip to not overwrite already copied areas */
1337
1338 if (destClip && gravitate[g]) {
1339 RegionTranslate(destClip, oldpt.x - x, oldpt.y - y);
1340 RegionSubtract(gravitate[g], gravitate[g], destClip);
1341 RegionTranslate(destClip, x - oldpt.x, y - oldpt.y);
1342 }
1343 if (destClip2 && gravitate2[g]) {
1344 RegionTranslate(destClip2, oldpt.x - x, oldpt.y - y);
1345 RegionSubtract(gravitate2[g], gravitate2[g], destClip2);
1346 RegionTranslate(destClip2, x - oldpt.x, y - oldpt.y);
1347 }
1348
1349 /* and move those bits */
1350
1351 if (oldpt.x != x || oldpt.y != y) {
1352 if (gravitate2[g]) {
1353 pPriv->copyUnderlay = TRUE;
1354 (*pScreen->CopyWindow) (pWin, oldpt, gravitate2[g]);
1355 }
1356 if (gravitate[g]) {
1357 pPriv->copyUnderlay = FALSE;
1358 (*pScreen->CopyWindow) (pWin, oldpt, gravitate[g]);
1359 }
1360 }
1361
1362 /* remove any overwritten bits from the remaining useful bits */
1363
1364 if (gravitate[g])
1365 RegionSubtract(oldRegion, oldRegion, gravitate[g]);
1366 if (gravitate2[g])
1367 RegionSubtract(oldRegion2, oldRegion2, gravitate2[g]);
1368
1369 /*
1370 * recompute exposed regions of child windows
1371 */
1372
1373 for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) {
1374 if (pChild->winGravity != g)
1375 continue;
1376
1377 TwoRegions.over = gravitate[g];
1378 TwoRegions.under = gravitate2[g];
1379
1380 TraverseTree(pChild, miOverlayRecomputeExposures,
1381 (void *) (&TwoRegions));
1382 }
1383
1384 /*
1385 * remove the successfully copied regions of the
1386 * window from its exposed region
1387 */
1388
1389 if (g == pWin->bitGravity) {
1390 if (gravitate[g])
1391 RegionSubtract(&pWin->valdata->after.exposed,
1392 &pWin->valdata->after.exposed, gravitate[g]);
1393 if (gravitate2[g] && pTree)
1394 RegionSubtract(&pTree->valdata->exposed,
1395 &pTree->valdata->exposed, gravitate2[g]);
1396 }
1397 if (gravitate[g]) {
1398 if (!destClip)
1399 destClip = gravitate[g];
1400 else {
1401 RegionUnion(destClip, destClip, gravitate[g]);
1402 RegionDestroy(gravitate[g]);
1403 }
1404 }
1405 if (gravitate2[g]) {
1406 if (!destClip2)
1407 destClip2 = gravitate2[g];
1408 else {
1409 RegionUnion(destClip2, destClip2, gravitate2[g]);
1410 RegionDestroy(gravitate2[g]);
1411 }
1412 }
1413 }
1414
1415 RegionDestroy(pRegion);
1416 RegionDestroy(oldRegion);
1417 if (doUnderlay)
1418 RegionDestroy(oldRegion2);
1419 if (destClip)
1420 RegionDestroy(destClip);
1421 if (destClip2)
1422 RegionDestroy(destClip2);
1423 (*pScreen->HandleExposures) (pWin->parent);
1424 if (pScreen->PostValidateTree)
1425 (*pScreen->PostValidateTree) (pWin->parent, pFirstChange, VTOther);
1426 }
1427 if (pWin->realized)
1428 WindowsRestructured();
1429 }
1430
1431 static void
miOverlaySetShape(WindowPtr pWin,int kind)1432 miOverlaySetShape(WindowPtr pWin, int kind)
1433 {
1434 Bool WasViewable = (Bool) (pWin->viewable);
1435 ScreenPtr pScreen = pWin->drawable.pScreen;
1436
1437 if (kind != ShapeInput) {
1438 if (WasViewable) {
1439 (*pScreen->MarkOverlappedWindows) (pWin, pWin, NULL);
1440
1441 if (HasBorder(pWin)) {
1442 RegionPtr borderVisible;
1443
1444 borderVisible = RegionCreate(NullBox, 1);
1445 RegionSubtract(borderVisible,
1446 &pWin->borderClip, &pWin->winSize);
1447 pWin->valdata->before.borderVisible = borderVisible;
1448 pWin->valdata->before.resized = TRUE;
1449 if (IN_UNDERLAY(pWin)) {
1450 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1451 RegionPtr borderVisible2;
1452
1453 borderVisible2 = RegionCreate(NULL, 1);
1454 RegionSubtract(borderVisible2,
1455 &pTree->borderClip, &pWin->winSize);
1456 pTree->valdata->borderVisible = borderVisible2;
1457 }
1458 }
1459 }
1460
1461 SetWinSize(pWin);
1462 SetBorderSize(pWin);
1463
1464 ResizeChildrenWinSize(pWin, 0, 0, 0, 0);
1465
1466 if (WasViewable) {
1467 (*pScreen->MarkOverlappedWindows) (pWin, pWin, NULL);
1468 (*pScreen->ValidateTree) (pWin->parent, NullWindow, VTOther);
1469 (*pScreen->HandleExposures) (pWin->parent);
1470 if (pScreen->PostValidateTree)
1471 (*pScreen->PostValidateTree) (pWin->parent, NullWindow,
1472 VTOther);
1473 }
1474 }
1475 if (pWin->realized)
1476 WindowsRestructured();
1477 CheckCursorConfinement(pWin);
1478 }
1479
1480 static void
miOverlayChangeBorderWidth(WindowPtr pWin,unsigned int width)1481 miOverlayChangeBorderWidth(WindowPtr pWin, unsigned int width)
1482 {
1483 int oldwidth;
1484 ScreenPtr pScreen;
1485 Bool WasViewable = (Bool) (pWin->viewable);
1486 Bool HadBorder;
1487
1488 oldwidth = wBorderWidth(pWin);
1489 if (oldwidth == width)
1490 return;
1491 HadBorder = HasBorder(pWin);
1492 pScreen = pWin->drawable.pScreen;
1493 if (WasViewable && (width < oldwidth))
1494 (*pScreen->MarkOverlappedWindows) (pWin, pWin, NULL);
1495
1496 pWin->borderWidth = width;
1497 SetBorderSize(pWin);
1498
1499 if (WasViewable) {
1500 if (width > oldwidth) {
1501 (*pScreen->MarkOverlappedWindows) (pWin, pWin, NULL);
1502
1503 if (HadBorder) {
1504 RegionPtr borderVisible;
1505
1506 borderVisible = RegionCreate(NULL, 1);
1507 RegionSubtract(borderVisible,
1508 &pWin->borderClip, &pWin->winSize);
1509 pWin->valdata->before.borderVisible = borderVisible;
1510 if (IN_UNDERLAY(pWin)) {
1511 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1512 RegionPtr borderVisible2;
1513
1514 borderVisible2 = RegionCreate(NULL, 1);
1515 RegionSubtract(borderVisible2,
1516 &pTree->borderClip, &pWin->winSize);
1517 pTree->valdata->borderVisible = borderVisible2;
1518 }
1519 }
1520 }
1521 (*pScreen->ValidateTree) (pWin->parent, pWin, VTOther);
1522 (*pScreen->HandleExposures) (pWin->parent);
1523
1524 if (pScreen->PostValidateTree)
1525 (*pScreen->PostValidateTree) (pWin->parent, pWin, VTOther);
1526 }
1527 if (pWin->realized)
1528 WindowsRestructured();
1529 }
1530
1531 /* We need this as an addition since the xf86 common code doesn't
1532 know about the second tree which is static to this file. */
1533
1534 void
miOverlaySetRootClip(ScreenPtr pScreen,Bool enable)1535 miOverlaySetRootClip(ScreenPtr pScreen, Bool enable)
1536 {
1537 WindowPtr pRoot = pScreen->root;
1538 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pRoot);
1539
1540 MARK_UNDERLAY(pRoot);
1541
1542 if (enable) {
1543 BoxRec box;
1544
1545 box.x1 = 0;
1546 box.y1 = 0;
1547 box.x2 = pScreen->width;
1548 box.y2 = pScreen->height;
1549
1550 RegionReset(&pTree->borderClip, &box);
1551 }
1552 else
1553 RegionEmpty(&pTree->borderClip);
1554
1555 RegionBreak(&pTree->clipList);
1556 }
1557
1558 static void
miOverlayClearToBackground(WindowPtr pWin,int x,int y,int w,int h,Bool generateExposures)1559 miOverlayClearToBackground(WindowPtr pWin,
1560 int x, int y, int w, int h, Bool generateExposures)
1561 {
1562 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1563 BoxRec box;
1564 RegionRec reg;
1565 ScreenPtr pScreen = pWin->drawable.pScreen;
1566 miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
1567 RegionPtr clipList;
1568 BoxPtr extents;
1569 int x1, y1, x2, y2;
1570
1571 x1 = pWin->drawable.x + x;
1572 y1 = pWin->drawable.y + y;
1573 if (w)
1574 x2 = x1 + (int) w;
1575 else
1576 x2 = x1 + (int) pWin->drawable.width - (int) x;
1577 if (h)
1578 y2 = y1 + h;
1579 else
1580 y2 = y1 + (int) pWin->drawable.height - (int) y;
1581
1582 clipList = ((*pScreenPriv->InOverlay) (pWin)) ? &pWin->clipList :
1583 &pTree->clipList;
1584
1585 extents = RegionExtents(clipList);
1586
1587 if (x1 < extents->x1)
1588 x1 = extents->x1;
1589 if (x2 > extents->x2)
1590 x2 = extents->x2;
1591 if (y1 < extents->y1)
1592 y1 = extents->y1;
1593 if (y2 > extents->y2)
1594 y2 = extents->y2;
1595
1596 if (x2 <= x1 || y2 <= y1)
1597 x2 = x1 = y2 = y1 = 0;
1598
1599 box.x1 = x1;
1600 box.x2 = x2;
1601 box.y1 = y1;
1602 box.y2 = y2;
1603
1604 RegionInit(®, &box, 1);
1605
1606 RegionIntersect(®, ®, clipList);
1607 if (generateExposures)
1608 (*pScreen->WindowExposures) (pWin, ®);
1609 else if (pWin->backgroundState != None)
1610 pScreen->PaintWindow(pWin, ®, PW_BACKGROUND);
1611 RegionUninit(®);
1612 }
1613
1614 /****************************************************************/
1615
1616 /* not used */
1617 Bool
miOverlayGetPrivateClips(WindowPtr pWin,RegionPtr * borderClip,RegionPtr * clipList)1618 miOverlayGetPrivateClips(WindowPtr pWin,
1619 RegionPtr *borderClip, RegionPtr *clipList)
1620 {
1621 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1622
1623 if (pTree) {
1624 *borderClip = &(pTree->borderClip);
1625 *clipList = &(pTree->clipList);
1626 return TRUE;
1627 }
1628
1629 *borderClip = *clipList = NULL;
1630
1631 return FALSE;
1632 }
1633
1634 void
miOverlaySetTransFunction(ScreenPtr pScreen,miOverlayTransFunc transFunc)1635 miOverlaySetTransFunction(ScreenPtr pScreen, miOverlayTransFunc transFunc)
1636 {
1637 MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->MakeTransparent = transFunc;
1638 }
1639
1640 Bool
miOverlayCopyUnderlay(ScreenPtr pScreen)1641 miOverlayCopyUnderlay(ScreenPtr pScreen)
1642 {
1643 return MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->copyUnderlay;
1644 }
1645
1646 void
miOverlayComputeCompositeClip(GCPtr pGC,WindowPtr pWin)1647 miOverlayComputeCompositeClip(GCPtr pGC, WindowPtr pWin)
1648 {
1649 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1650 RegionPtr pregWin;
1651 Bool freeTmpClip, freeCompClip;
1652
1653 if (!pTree) {
1654 miComputeCompositeClip(pGC, &pWin->drawable);
1655 return;
1656 }
1657
1658 if (pGC->subWindowMode == IncludeInferiors) {
1659 pregWin = RegionCreate(NullBox, 1);
1660 freeTmpClip = TRUE;
1661 if (pWin->parent || (screenIsSaved != SCREEN_SAVER_ON) ||
1662 !HasSaverWindow(pGC->pScreen)) {
1663 RegionIntersect(pregWin, &pTree->borderClip, &pWin->winSize);
1664 }
1665 }
1666 else {
1667 pregWin = &pTree->clipList;
1668 freeTmpClip = FALSE;
1669 }
1670 freeCompClip = pGC->freeCompClip;
1671 if (!pGC->clientClip) {
1672 if (freeCompClip)
1673 RegionDestroy(pGC->pCompositeClip);
1674 pGC->pCompositeClip = pregWin;
1675 pGC->freeCompClip = freeTmpClip;
1676 }
1677 else {
1678 RegionTranslate(pGC->clientClip,
1679 pWin->drawable.x + pGC->clipOrg.x,
1680 pWin->drawable.y + pGC->clipOrg.y);
1681
1682 if (freeCompClip) {
1683 RegionIntersect(pGC->pCompositeClip, pregWin, pGC->clientClip);
1684 if (freeTmpClip)
1685 RegionDestroy(pregWin);
1686 }
1687 else if (freeTmpClip) {
1688 RegionIntersect(pregWin, pregWin, pGC->clientClip);
1689 pGC->pCompositeClip = pregWin;
1690 }
1691 else {
1692 pGC->pCompositeClip = RegionCreate(NullBox, 0);
1693 RegionIntersect(pGC->pCompositeClip, pregWin, pGC->clientClip);
1694 }
1695 pGC->freeCompClip = TRUE;
1696 RegionTranslate(pGC->clientClip,
1697 -(pWin->drawable.x + pGC->clipOrg.x),
1698 -(pWin->drawable.y + pGC->clipOrg.y));
1699 }
1700 }
1701
1702 Bool
miOverlayCollectUnderlayRegions(WindowPtr pWin,RegionPtr * region)1703 miOverlayCollectUnderlayRegions(WindowPtr pWin, RegionPtr *region)
1704 {
1705 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1706
1707 if (pTree) {
1708 *region = &pTree->borderClip;
1709 return FALSE;
1710 }
1711
1712 *region = RegionCreate(NullBox, 0);
1713
1714 CollectUnderlayChildrenRegions(pWin, *region);
1715
1716 return TRUE;
1717 }
1718
1719 static miOverlayTreePtr
DoLeaf(WindowPtr pWin,miOverlayTreePtr parent,miOverlayTreePtr prevSib)1720 DoLeaf(WindowPtr pWin, miOverlayTreePtr parent, miOverlayTreePtr prevSib)
1721 {
1722 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1723
1724 pTree->parent = parent;
1725 pTree->firstChild = NULL;
1726 pTree->lastChild = NULL;
1727 pTree->prevSib = prevSib;
1728 pTree->nextSib = NULL;
1729
1730 if (prevSib)
1731 prevSib->nextSib = pTree;
1732
1733 if (!parent->firstChild)
1734 parent->firstChild = parent->lastChild = pTree;
1735 else if (parent->lastChild == prevSib)
1736 parent->lastChild = pTree;
1737
1738 return pTree;
1739 }
1740
1741 static void
RebuildTree(WindowPtr pWin)1742 RebuildTree(WindowPtr pWin)
1743 {
1744 miOverlayTreePtr parent, prevSib, tChild;
1745 WindowPtr pChild;
1746
1747 prevSib = tChild = NULL;
1748
1749 pWin = pWin->parent;
1750
1751 while (IN_OVERLAY(pWin))
1752 pWin = pWin->parent;
1753
1754 parent = MIOVERLAY_GET_WINDOW_TREE(pWin);
1755
1756 pChild = pWin->firstChild;
1757 parent->firstChild = parent->lastChild = NULL;
1758
1759 while (1) {
1760 if (IN_UNDERLAY(pChild))
1761 prevSib = tChild = DoLeaf(pChild, parent, prevSib);
1762
1763 if (pChild->firstChild) {
1764 if (IN_UNDERLAY(pChild)) {
1765 parent = tChild;
1766 prevSib = NULL;
1767 }
1768 pChild = pChild->firstChild;
1769 continue;
1770 }
1771
1772 while (!pChild->nextSib) {
1773 pChild = pChild->parent;
1774 if (pChild == pWin)
1775 return;
1776 if (IN_UNDERLAY(pChild)) {
1777 prevSib = tChild = MIOVERLAY_GET_WINDOW_TREE(pChild);
1778 parent = tChild->parent;
1779 }
1780 }
1781
1782 pChild = pChild->nextSib;
1783 }
1784 }
1785
1786 static Bool
HasUnderlayChildren(WindowPtr pWin)1787 HasUnderlayChildren(WindowPtr pWin)
1788 {
1789 WindowPtr pChild;
1790
1791 if (!(pChild = pWin->firstChild))
1792 return FALSE;
1793
1794 while (1) {
1795 if (IN_UNDERLAY(pChild))
1796 return TRUE;
1797
1798 if (pChild->firstChild) {
1799 pChild = pChild->firstChild;
1800 continue;
1801 }
1802
1803 while (!pChild->nextSib && (pWin != pChild))
1804 pChild = pChild->parent;
1805
1806 if (pChild == pWin)
1807 break;
1808
1809 pChild = pChild->nextSib;
1810 }
1811
1812 return FALSE;
1813 }
1814
1815 static Bool
CollectUnderlayChildrenRegions(WindowPtr pWin,RegionPtr pReg)1816 CollectUnderlayChildrenRegions(WindowPtr pWin, RegionPtr pReg)
1817 {
1818 WindowPtr pChild;
1819 miOverlayTreePtr pTree;
1820 Bool hasUnderlay;
1821
1822 if (!(pChild = pWin->firstChild))
1823 return FALSE;
1824
1825 hasUnderlay = FALSE;
1826
1827 while (1) {
1828 if ((pTree = MIOVERLAY_GET_WINDOW_TREE(pChild))) {
1829 RegionAppend(pReg, &pTree->borderClip);
1830 hasUnderlay = TRUE;
1831 }
1832 else if (pChild->firstChild) {
1833 pChild = pChild->firstChild;
1834 continue;
1835 }
1836
1837 while (!pChild->nextSib && (pWin != pChild))
1838 pChild = pChild->parent;
1839
1840 if (pChild == pWin)
1841 break;
1842
1843 pChild = pChild->nextSib;
1844 }
1845
1846 if (hasUnderlay) {
1847 Bool overlap;
1848
1849 RegionValidate(pReg, &overlap);
1850 }
1851
1852 return hasUnderlay;
1853 }
1854
1855 static void
MarkUnderlayWindow(WindowPtr pWin)1856 MarkUnderlayWindow(WindowPtr pWin)
1857 {
1858 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1859
1860 if (pTree->valdata)
1861 return;
1862 pTree->valdata =
1863 (miOverlayValDataPtr) xnfalloc(sizeof(miOverlayValDataRec));
1864 pTree->valdata->oldAbsCorner.x = pWin->drawable.x;
1865 pTree->valdata->oldAbsCorner.y = pWin->drawable.y;
1866 pTree->valdata->borderVisible = NullRegion;
1867 }
1868