Add patch that contain Mali fixes.
[deb_xorg-server.git] / mi / mioverlay.c
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, 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 void (*WindowExposures) (WindowPtr, RegionPtr, RegionPtr);
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 miPaintWindow(pTree->pWin, &mival->borderExposed,
848 PW_BORDER);
849 }
850 RegionUninit(&mival->borderExposed);
851
852 (*WindowExposures) (pTree->pWin, &mival->exposed,
853 NullRegion);
854 RegionUninit(&mival->exposed);
855 }
856 free(mival);
857 pTree->valdata = NULL;
858 if (pTree->firstChild) {
859 pTree = pTree->firstChild;
860 continue;
861 }
862 }
863 while (!pTree->nextSib && (pTree->pWin != pChild))
864 pTree = pTree->parent;
865 if (pTree->pWin == pChild)
866 break;
867 pTree = pTree->nextSib;
868 }
869 pPriv->underlayMarked = FALSE;
870 }
871
872 pChild = pWin;
873 while (1) {
874 if ((val = pChild->valdata)) {
875 if (!((*pPriv->InOverlay) (pChild))) {
876 RegionUnion(&val->after.exposed, &val->after.exposed,
877 &val->after.borderExposed);
878
879 if (RegionNotEmpty(&val->after.exposed)) {
880 (*(MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->MakeTransparent))
881 (pScreen, RegionNumRects(&val->after.exposed),
882 RegionRects(&val->after.exposed));
883 }
884 }
885 else {
886 if (RegionNotEmpty(&val->after.borderExposed)) {
887 miPaintWindow(pChild, &val->after.borderExposed, PW_BORDER);
888 }
889 (*WindowExposures) (pChild, &val->after.exposed, NullRegion);
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
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
983 miOverlayWindowExposures(WindowPtr pWin,
984 RegionPtr prgn, RegionPtr other_exposed)
985 {
986 RegionPtr exposures = prgn;
987
988 if ((prgn && !RegionNil(prgn)) ||
989 (exposures && !RegionNil(exposures)) || other_exposed) {
990 RegionRec expRec;
991 int clientInterested;
992
993 clientInterested = (pWin->eventMask | wOtherEventMasks(pWin)) &
994 ExposureMask;
995 if (other_exposed) {
996 if (exposures) {
997 RegionUnion(other_exposed, exposures, other_exposed);
998 if (exposures != prgn)
999 RegionDestroy(exposures);
1000 }
1001 exposures = other_exposed;
1002 }
1003 if (clientInterested && exposures &&
1004 (RegionNumRects(exposures) > RECTLIMIT)) {
1005 ScreenPtr pScreen = pWin->drawable.pScreen;
1006 miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
1007 BoxRec box;
1008
1009 box = *RegionExtents(exposures);
1010 if (exposures == prgn) {
1011 exposures = &expRec;
1012 RegionInit(exposures, &box, 1);
1013 RegionReset(prgn, &box);
1014 }
1015 else {
1016 RegionReset(exposures, &box);
1017 RegionUnion(prgn, prgn, exposures);
1018 }
1019 /* This is the only reason why we are replacing mi's version
1020 of this file */
1021
1022 if (!((*pPriv->InOverlay) (pWin))) {
1023 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1024
1025 RegionIntersect(prgn, prgn, &pTree->clipList);
1026 }
1027 else
1028 RegionIntersect(prgn, prgn, &pWin->clipList);
1029 }
1030 if (prgn && !RegionNil(prgn))
1031 miPaintWindow(pWin, prgn, PW_BACKGROUND);
1032 if (clientInterested && exposures && !RegionNil(exposures))
1033 miSendExposures(pWin, exposures,
1034 pWin->drawable.x, pWin->drawable.y);
1035 if (exposures == &expRec) {
1036 RegionUninit(exposures);
1037 }
1038 else if (exposures && exposures != prgn && exposures != other_exposed)
1039 RegionDestroy(exposures);
1040 if (prgn)
1041 RegionEmpty(prgn);
1042 }
1043 else if (exposures && exposures != prgn)
1044 RegionDestroy(exposures);
1045 }
1046
1047 typedef struct {
1048 RegionPtr over;
1049 RegionPtr under;
1050 } miOverlayTwoRegions;
1051
1052 static int
1053 miOverlayRecomputeExposures(WindowPtr pWin, pointer value)
1054 {
1055 miOverlayTwoRegions *pValid = (miOverlayTwoRegions *) value;
1056 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1057
1058 if (pWin->valdata) {
1059 /*
1060 * compute exposed regions of this window
1061 */
1062 RegionSubtract(&pWin->valdata->after.exposed,
1063 &pWin->clipList, pValid->over);
1064 /*
1065 * compute exposed regions of the border
1066 */
1067 RegionSubtract(&pWin->valdata->after.borderExposed,
1068 &pWin->borderClip, &pWin->winSize);
1069 RegionSubtract(&pWin->valdata->after.borderExposed,
1070 &pWin->valdata->after.borderExposed, pValid->over);
1071 }
1072
1073 if (pTree && pTree->valdata) {
1074 RegionSubtract(&pTree->valdata->exposed,
1075 &pTree->clipList, pValid->under);
1076 RegionSubtract(&pTree->valdata->borderExposed,
1077 &pTree->borderClip, &pWin->winSize);
1078 RegionSubtract(&pTree->valdata->borderExposed,
1079 &pTree->valdata->borderExposed, pValid->under);
1080 }
1081 else if (!pWin->valdata)
1082 return WT_NOMATCH;
1083
1084 return WT_WALKCHILDREN;
1085 }
1086
1087 static void
1088 miOverlayResizeWindow(WindowPtr pWin,
1089 int x, int y,
1090 unsigned int w, unsigned int h, WindowPtr pSib)
1091 {
1092 ScreenPtr pScreen = pWin->drawable.pScreen;
1093 WindowPtr pParent;
1094 miOverlayTreePtr tChild, pTree;
1095 Bool WasViewable = (Bool) (pWin->viewable);
1096 unsigned short width = pWin->drawable.width;
1097 unsigned short height = pWin->drawable.height;
1098 short oldx = pWin->drawable.x;
1099 short oldy = pWin->drawable.y;
1100 int bw = wBorderWidth(pWin);
1101 short dw, dh;
1102 DDXPointRec oldpt;
1103 RegionPtr oldRegion = NULL, oldRegion2 = NULL;
1104 WindowPtr pFirstChange;
1105 WindowPtr pChild;
1106 RegionPtr gravitate[StaticGravity + 1];
1107 RegionPtr gravitate2[StaticGravity + 1];
1108 unsigned g;
1109 int nx, ny; /* destination x,y */
1110 int newx, newy; /* new inner window position */
1111 RegionPtr pRegion = NULL;
1112 RegionPtr destClip, destClip2;
1113 RegionPtr oldWinClip = NULL, oldWinClip2 = NULL;
1114 RegionPtr borderVisible = NullRegion;
1115 RegionPtr borderVisible2 = NullRegion;
1116 Bool shrunk = FALSE; /* shrunk in an inner dimension */
1117 Bool moved = FALSE; /* window position changed */
1118 Bool doUnderlay;
1119
1120 /* if this is a root window, can't be resized */
1121 if (!(pParent = pWin->parent))
1122 return;
1123
1124 pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1125 doUnderlay = ((pTree) || HasUnderlayChildren(pWin));
1126 newx = pParent->drawable.x + x + bw;
1127 newy = pParent->drawable.y + y + bw;
1128 if (WasViewable) {
1129 /*
1130 * save the visible region of the window
1131 */
1132 oldRegion = RegionCreate(NullBox, 1);
1133 RegionCopy(oldRegion, &pWin->winSize);
1134 if (doUnderlay) {
1135 oldRegion2 = RegionCreate(NullBox, 1);
1136 RegionCopy(oldRegion2, &pWin->winSize);
1137 }
1138
1139 /*
1140 * categorize child windows into regions to be moved
1141 */
1142 for (g = 0; g <= StaticGravity; g++)
1143 gravitate[g] = gravitate2[g] = NULL;
1144 for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) {
1145 g = pChild->winGravity;
1146 if (g != UnmapGravity) {
1147 if (!gravitate[g])
1148 gravitate[g] = RegionCreate(NullBox, 1);
1149 RegionUnion(gravitate[g], gravitate[g], &pChild->borderClip);
1150
1151 if (doUnderlay) {
1152 if (!gravitate2[g])
1153 gravitate2[g] = RegionCreate(NullBox, 0);
1154
1155 if ((tChild = MIOVERLAY_GET_WINDOW_TREE(pChild))) {
1156 RegionUnion(gravitate2[g],
1157 gravitate2[g], &tChild->borderClip);
1158 }
1159 else
1160 CollectUnderlayChildrenRegions(pChild, gravitate2[g]);
1161 }
1162 }
1163 else {
1164 UnmapWindow(pChild, TRUE);
1165 }
1166 }
1167 (*pScreen->MarkOverlappedWindows) (pWin, pWin, NULL);
1168
1169 oldWinClip = oldWinClip2 = NULL;
1170 if (pWin->bitGravity != ForgetGravity) {
1171 oldWinClip = RegionCreate(NullBox, 1);
1172 RegionCopy(oldWinClip, &pWin->clipList);
1173 if (pTree) {
1174 oldWinClip2 = RegionCreate(NullBox, 1);
1175 RegionCopy(oldWinClip2, &pTree->clipList);
1176 }
1177 }
1178 /*
1179 * if the window is changing size, borderExposed
1180 * can't be computed correctly without some help.
1181 */
1182 if (pWin->drawable.height > h || pWin->drawable.width > w)
1183 shrunk = TRUE;
1184
1185 if (newx != oldx || newy != oldy)
1186 moved = TRUE;
1187
1188 if ((pWin->drawable.height != h || pWin->drawable.width != w) &&
1189 HasBorder(pWin)) {
1190 borderVisible = RegionCreate(NullBox, 1);
1191 if (pTree)
1192 borderVisible2 = RegionCreate(NullBox, 1);
1193 /* for tiled borders, we punt and draw the whole thing */
1194 if (pWin->borderIsPixel || !moved) {
1195 if (shrunk || moved)
1196 RegionSubtract(borderVisible,
1197 &pWin->borderClip, &pWin->winSize);
1198 else
1199 RegionCopy(borderVisible, &pWin->borderClip);
1200 if (pTree) {
1201 if (shrunk || moved)
1202 RegionSubtract(borderVisible,
1203 &pTree->borderClip, &pWin->winSize);
1204 else
1205 RegionCopy(borderVisible, &pTree->borderClip);
1206 }
1207 }
1208 }
1209 }
1210 pWin->origin.x = x + bw;
1211 pWin->origin.y = y + bw;
1212 pWin->drawable.height = h;
1213 pWin->drawable.width = w;
1214
1215 x = pWin->drawable.x = newx;
1216 y = pWin->drawable.y = newy;
1217
1218 SetWinSize(pWin);
1219 SetBorderSize(pWin);
1220
1221 dw = (int) w - (int) width;
1222 dh = (int) h - (int) height;
1223 ResizeChildrenWinSize(pWin, x - oldx, y - oldy, dw, dh);
1224
1225 /* let the hardware adjust background and border pixmaps, if any */
1226 (*pScreen->PositionWindow) (pWin, x, y);
1227
1228 pFirstChange = MoveWindowInStack(pWin, pSib);
1229
1230 if (WasViewable) {
1231 pRegion = RegionCreate(NullBox, 1);
1232
1233 (*pScreen->MarkOverlappedWindows) (pWin, pFirstChange, NULL);
1234
1235 pWin->valdata->before.resized = TRUE;
1236 pWin->valdata->before.borderVisible = borderVisible;
1237 if (pTree)
1238 pTree->valdata->borderVisible = borderVisible2;
1239
1240 (*pScreen->ValidateTree) (pWin->parent, pFirstChange, VTOther);
1241 /*
1242 * the entire window is trashed unless bitGravity
1243 * recovers portions of it
1244 */
1245 RegionCopy(&pWin->valdata->after.exposed, &pWin->clipList);
1246 if (pTree)
1247 RegionCopy(&pTree->valdata->exposed, &pTree->clipList);
1248 }
1249
1250 GravityTranslate(x, y, oldx, oldy, dw, dh, pWin->bitGravity, &nx, &ny);
1251
1252 if (WasViewable) {
1253 miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
1254 miOverlayTwoRegions TwoRegions;
1255
1256 /* avoid the border */
1257 if (HasBorder(pWin)) {
1258 int offx, offy, dx, dy;
1259
1260 /* kruft to avoid double translates for each gravity */
1261 offx = 0;
1262 offy = 0;
1263 for (g = 0; g <= StaticGravity; g++) {
1264 if (!gravitate[g] && !gravitate2[g])
1265 continue;
1266
1267 /* align winSize to gravitate[g].
1268 * winSize is in new coordinates,
1269 * gravitate[g] is still in old coordinates */
1270 GravityTranslate(x, y, oldx, oldy, dw, dh, g, &nx, &ny);
1271
1272 dx = (oldx - nx) - offx;
1273 dy = (oldy - ny) - offy;
1274 if (dx || dy) {
1275 RegionTranslate(&pWin->winSize, dx, dy);
1276 offx += dx;
1277 offy += dy;
1278 }
1279 if (gravitate[g])
1280 RegionIntersect(gravitate[g], gravitate[g], &pWin->winSize);
1281 if (gravitate2[g])
1282 RegionIntersect(gravitate2[g], gravitate2[g],
1283 &pWin->winSize);
1284 }
1285 /* get winSize back where it belongs */
1286 if (offx || offy)
1287 RegionTranslate(&pWin->winSize, -offx, -offy);
1288 }
1289 /*
1290 * add screen bits to the appropriate bucket
1291 */
1292
1293 if (oldWinClip2) {
1294 RegionCopy(pRegion, oldWinClip2);
1295 RegionTranslate(pRegion, nx - oldx, ny - oldy);
1296 RegionIntersect(oldWinClip2, pRegion, &pTree->clipList);
1297
1298 for (g = pWin->bitGravity + 1; g <= StaticGravity; g++) {
1299 if (gravitate2[g])
1300 RegionSubtract(oldWinClip2, oldWinClip2, gravitate2[g]);
1301 }
1302 RegionTranslate(oldWinClip2, oldx - nx, oldy - ny);
1303 g = pWin->bitGravity;
1304 if (!gravitate2[g])
1305 gravitate2[g] = oldWinClip2;
1306 else {
1307 RegionUnion(gravitate2[g], gravitate2[g], oldWinClip2);
1308 RegionDestroy(oldWinClip2);
1309 }
1310 }
1311
1312 if (oldWinClip) {
1313 /*
1314 * clip to new clipList
1315 */
1316 RegionCopy(pRegion, oldWinClip);
1317 RegionTranslate(pRegion, nx - oldx, ny - oldy);
1318 RegionIntersect(oldWinClip, pRegion, &pWin->clipList);
1319 /*
1320 * don't step on any gravity bits which will be copied after this
1321 * region. Note -- this assumes that the regions will be copied
1322 * in gravity order.
1323 */
1324 for (g = pWin->bitGravity + 1; g <= StaticGravity; g++) {
1325 if (gravitate[g])
1326 RegionSubtract(oldWinClip, oldWinClip, gravitate[g]);
1327 }
1328 RegionTranslate(oldWinClip, oldx - nx, oldy - ny);
1329 g = pWin->bitGravity;
1330 if (!gravitate[g])
1331 gravitate[g] = oldWinClip;
1332 else {
1333 RegionUnion(gravitate[g], gravitate[g], oldWinClip);
1334 RegionDestroy(oldWinClip);
1335 }
1336 }
1337
1338 /*
1339 * move the bits on the screen
1340 */
1341
1342 destClip = destClip2 = NULL;
1343
1344 for (g = 0; g <= StaticGravity; g++) {
1345 if (!gravitate[g] && !gravitate2[g])
1346 continue;
1347
1348 GravityTranslate(x, y, oldx, oldy, dw, dh, g, &nx, &ny);
1349
1350 oldpt.x = oldx + (x - nx);
1351 oldpt.y = oldy + (y - ny);
1352
1353 /* Note that gravitate[g] is *translated* by CopyWindow */
1354
1355 /* only copy the remaining useful bits */
1356
1357 if (gravitate[g])
1358 RegionIntersect(gravitate[g], gravitate[g], oldRegion);
1359 if (gravitate2[g])
1360 RegionIntersect(gravitate2[g], gravitate2[g], oldRegion2);
1361
1362 /* clip to not overwrite already copied areas */
1363
1364 if (destClip && gravitate[g]) {
1365 RegionTranslate(destClip, oldpt.x - x, oldpt.y - y);
1366 RegionSubtract(gravitate[g], gravitate[g], destClip);
1367 RegionTranslate(destClip, x - oldpt.x, y - oldpt.y);
1368 }
1369 if (destClip2 && gravitate2[g]) {
1370 RegionTranslate(destClip2, oldpt.x - x, oldpt.y - y);
1371 RegionSubtract(gravitate2[g], gravitate2[g], destClip2);
1372 RegionTranslate(destClip2, x - oldpt.x, y - oldpt.y);
1373 }
1374
1375 /* and move those bits */
1376
1377 if (oldpt.x != x || oldpt.y != y) {
1378 if (gravitate2[g]) {
1379 pPriv->copyUnderlay = TRUE;
1380 (*pScreen->CopyWindow) (pWin, oldpt, gravitate2[g]);
1381 }
1382 if (gravitate[g]) {
1383 pPriv->copyUnderlay = FALSE;
1384 (*pScreen->CopyWindow) (pWin, oldpt, gravitate[g]);
1385 }
1386 }
1387
1388 /* remove any overwritten bits from the remaining useful bits */
1389
1390 if (gravitate[g])
1391 RegionSubtract(oldRegion, oldRegion, gravitate[g]);
1392 if (gravitate2[g])
1393 RegionSubtract(oldRegion2, oldRegion2, gravitate2[g]);
1394
1395 /*
1396 * recompute exposed regions of child windows
1397 */
1398
1399 for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) {
1400 if (pChild->winGravity != g)
1401 continue;
1402
1403 TwoRegions.over = gravitate[g];
1404 TwoRegions.under = gravitate2[g];
1405
1406 TraverseTree(pChild, miOverlayRecomputeExposures,
1407 (pointer) (&TwoRegions));
1408 }
1409
1410 /*
1411 * remove the successfully copied regions of the
1412 * window from its exposed region
1413 */
1414
1415 if (g == pWin->bitGravity) {
1416 if (gravitate[g])
1417 RegionSubtract(&pWin->valdata->after.exposed,
1418 &pWin->valdata->after.exposed, gravitate[g]);
1419 if (gravitate2[g] && pTree)
1420 RegionSubtract(&pTree->valdata->exposed,
1421 &pTree->valdata->exposed, gravitate2[g]);
1422 }
1423 if (gravitate[g]) {
1424 if (!destClip)
1425 destClip = gravitate[g];
1426 else {
1427 RegionUnion(destClip, destClip, gravitate[g]);
1428 RegionDestroy(gravitate[g]);
1429 }
1430 }
1431 if (gravitate2[g]) {
1432 if (!destClip2)
1433 destClip2 = gravitate2[g];
1434 else {
1435 RegionUnion(destClip2, destClip2, gravitate2[g]);
1436 RegionDestroy(gravitate2[g]);
1437 }
1438 }
1439 }
1440
1441 RegionDestroy(pRegion);
1442 RegionDestroy(oldRegion);
1443 if (doUnderlay)
1444 RegionDestroy(oldRegion2);
1445 if (destClip)
1446 RegionDestroy(destClip);
1447 if (destClip2)
1448 RegionDestroy(destClip2);
1449 (*pScreen->HandleExposures) (pWin->parent);
1450 if (pScreen->PostValidateTree)
1451 (*pScreen->PostValidateTree) (pWin->parent, pFirstChange, VTOther);
1452 }
1453 if (pWin->realized)
1454 WindowsRestructured();
1455 }
1456
1457 static void
1458 miOverlaySetShape(WindowPtr pWin, int kind)
1459 {
1460 Bool WasViewable = (Bool) (pWin->viewable);
1461 ScreenPtr pScreen = pWin->drawable.pScreen;
1462
1463 if (kind != ShapeInput) {
1464 if (WasViewable) {
1465 (*pScreen->MarkOverlappedWindows) (pWin, pWin, NULL);
1466
1467 if (HasBorder(pWin)) {
1468 RegionPtr borderVisible;
1469
1470 borderVisible = RegionCreate(NullBox, 1);
1471 RegionSubtract(borderVisible,
1472 &pWin->borderClip, &pWin->winSize);
1473 pWin->valdata->before.borderVisible = borderVisible;
1474 pWin->valdata->before.resized = TRUE;
1475 if (IN_UNDERLAY(pWin)) {
1476 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1477 RegionPtr borderVisible2;
1478
1479 borderVisible2 = RegionCreate(NULL, 1);
1480 RegionSubtract(borderVisible2,
1481 &pTree->borderClip, &pWin->winSize);
1482 pTree->valdata->borderVisible = borderVisible2;
1483 }
1484 }
1485 }
1486
1487 SetWinSize(pWin);
1488 SetBorderSize(pWin);
1489
1490 ResizeChildrenWinSize(pWin, 0, 0, 0, 0);
1491
1492 if (WasViewable) {
1493 (*pScreen->MarkOverlappedWindows) (pWin, pWin, NULL);
1494
1495 (*pScreen->ValidateTree) (pWin->parent, NullWindow, VTOther);
1496 }
1497
1498 if (WasViewable) {
1499 (*pScreen->HandleExposures) (pWin->parent);
1500 if (pScreen->PostValidateTree)
1501 (*pScreen->PostValidateTree) (pWin->parent, NullWindow,
1502 VTOther);
1503 }
1504 }
1505 if (pWin->realized)
1506 WindowsRestructured();
1507 CheckCursorConfinement(pWin);
1508 }
1509
1510 static void
1511 miOverlayChangeBorderWidth(WindowPtr pWin, unsigned int width)
1512 {
1513 int oldwidth;
1514 ScreenPtr pScreen;
1515 Bool WasViewable = (Bool) (pWin->viewable);
1516 Bool HadBorder;
1517
1518 oldwidth = wBorderWidth(pWin);
1519 if (oldwidth == width)
1520 return;
1521 HadBorder = HasBorder(pWin);
1522 pScreen = pWin->drawable.pScreen;
1523 if (WasViewable && (width < oldwidth))
1524 (*pScreen->MarkOverlappedWindows) (pWin, pWin, NULL);
1525
1526 pWin->borderWidth = width;
1527 SetBorderSize(pWin);
1528
1529 if (WasViewable) {
1530 if (width > oldwidth) {
1531 (*pScreen->MarkOverlappedWindows) (pWin, pWin, NULL);
1532
1533 if (HadBorder) {
1534 RegionPtr borderVisible;
1535
1536 borderVisible = RegionCreate(NULL, 1);
1537 RegionSubtract(borderVisible,
1538 &pWin->borderClip, &pWin->winSize);
1539 pWin->valdata->before.borderVisible = borderVisible;
1540 if (IN_UNDERLAY(pWin)) {
1541 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1542 RegionPtr borderVisible2;
1543
1544 borderVisible2 = RegionCreate(NULL, 1);
1545 RegionSubtract(borderVisible2,
1546 &pTree->borderClip, &pWin->winSize);
1547 pTree->valdata->borderVisible = borderVisible2;
1548 }
1549 }
1550 }
1551 (*pScreen->ValidateTree) (pWin->parent, pWin, VTOther);
1552 (*pScreen->HandleExposures) (pWin->parent);
1553
1554 if (pScreen->PostValidateTree)
1555 (*pScreen->PostValidateTree) (pWin->parent, pWin, VTOther);
1556 }
1557 if (pWin->realized)
1558 WindowsRestructured();
1559 }
1560
1561 /* We need this as an addition since the xf86 common code doesn't
1562 know about the second tree which is static to this file. */
1563
1564 void
1565 miOverlaySetRootClip(ScreenPtr pScreen, Bool enable)
1566 {
1567 WindowPtr pRoot = pScreen->root;
1568 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pRoot);
1569
1570 MARK_UNDERLAY(pRoot);
1571
1572 if (enable) {
1573 BoxRec box;
1574
1575 box.x1 = 0;
1576 box.y1 = 0;
1577 box.x2 = pScreen->width;
1578 box.y2 = pScreen->height;
1579
1580 RegionReset(&pTree->borderClip, &box);
1581 }
1582 else
1583 RegionEmpty(&pTree->borderClip);
1584
1585 RegionBreak(&pTree->clipList);
1586 }
1587
1588 static void
1589 miOverlayClearToBackground(WindowPtr pWin,
1590 int x, int y, int w, int h, Bool generateExposures)
1591 {
1592 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1593 BoxRec box;
1594 RegionRec reg;
1595 RegionPtr pBSReg = NullRegion;
1596 ScreenPtr pScreen = pWin->drawable.pScreen;
1597 miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
1598 RegionPtr clipList;
1599 BoxPtr extents;
1600 int x1, y1, x2, y2;
1601
1602 x1 = pWin->drawable.x + x;
1603 y1 = pWin->drawable.y + y;
1604 if (w)
1605 x2 = x1 + (int) w;
1606 else
1607 x2 = x1 + (int) pWin->drawable.width - (int) x;
1608 if (h)
1609 y2 = y1 + h;
1610 else
1611 y2 = y1 + (int) pWin->drawable.height - (int) y;
1612
1613 clipList = ((*pScreenPriv->InOverlay) (pWin)) ? &pWin->clipList :
1614 &pTree->clipList;
1615
1616 extents = RegionExtents(clipList);
1617
1618 if (x1 < extents->x1)
1619 x1 = extents->x1;
1620 if (x2 > extents->x2)
1621 x2 = extents->x2;
1622 if (y1 < extents->y1)
1623 y1 = extents->y1;
1624 if (y2 > extents->y2)
1625 y2 = extents->y2;
1626
1627 if (x2 <= x1 || y2 <= y1)
1628 x2 = x1 = y2 = y1 = 0;
1629
1630 box.x1 = x1;
1631 box.x2 = x2;
1632 box.y1 = y1;
1633 box.y2 = y2;
1634
1635 RegionInit(&reg, &box, 1);
1636
1637 RegionIntersect(&reg, &reg, clipList);
1638 if (generateExposures)
1639 (*pScreen->WindowExposures) (pWin, &reg, pBSReg);
1640 else if (pWin->backgroundState != None)
1641 miPaintWindow(pWin, &reg, PW_BACKGROUND);
1642 RegionUninit(&reg);
1643 if (pBSReg)
1644 RegionDestroy(pBSReg);
1645 }
1646
1647 /****************************************************************/
1648
1649 /* not used */
1650 Bool
1651 miOverlayGetPrivateClips(WindowPtr pWin,
1652 RegionPtr *borderClip, RegionPtr *clipList)
1653 {
1654 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1655
1656 if (pTree) {
1657 *borderClip = &(pTree->borderClip);
1658 *clipList = &(pTree->clipList);
1659 return TRUE;
1660 }
1661
1662 *borderClip = *clipList = NULL;
1663
1664 return FALSE;
1665 }
1666
1667 void
1668 miOverlaySetTransFunction(ScreenPtr pScreen, miOverlayTransFunc transFunc)
1669 {
1670 MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->MakeTransparent = transFunc;
1671 }
1672
1673 Bool
1674 miOverlayCopyUnderlay(ScreenPtr pScreen)
1675 {
1676 return MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->copyUnderlay;
1677 }
1678
1679 void
1680 miOverlayComputeCompositeClip(GCPtr pGC, WindowPtr pWin)
1681 {
1682 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1683 RegionPtr pregWin;
1684 Bool freeTmpClip, freeCompClip;
1685
1686 if (!pTree) {
1687 miComputeCompositeClip(pGC, &pWin->drawable);
1688 return;
1689 }
1690
1691 if (pGC->subWindowMode == IncludeInferiors) {
1692 pregWin = RegionCreate(NullBox, 1);
1693 freeTmpClip = TRUE;
1694 if (pWin->parent || (screenIsSaved != SCREEN_SAVER_ON) ||
1695 !HasSaverWindow(pGC->pScreen)) {
1696 RegionIntersect(pregWin, &pTree->borderClip, &pWin->winSize);
1697 }
1698 }
1699 else {
1700 pregWin = &pTree->clipList;
1701 freeTmpClip = FALSE;
1702 }
1703 freeCompClip = pGC->freeCompClip;
1704 if (pGC->clientClipType == CT_NONE) {
1705 if (freeCompClip)
1706 RegionDestroy(pGC->pCompositeClip);
1707 pGC->pCompositeClip = pregWin;
1708 pGC->freeCompClip = freeTmpClip;
1709 }
1710 else {
1711 RegionTranslate(pGC->clientClip,
1712 pWin->drawable.x + pGC->clipOrg.x,
1713 pWin->drawable.y + pGC->clipOrg.y);
1714
1715 if (freeCompClip) {
1716 RegionIntersect(pGC->pCompositeClip, pregWin, pGC->clientClip);
1717 if (freeTmpClip)
1718 RegionDestroy(pregWin);
1719 }
1720 else if (freeTmpClip) {
1721 RegionIntersect(pregWin, pregWin, pGC->clientClip);
1722 pGC->pCompositeClip = pregWin;
1723 }
1724 else {
1725 pGC->pCompositeClip = RegionCreate(NullBox, 0);
1726 RegionIntersect(pGC->pCompositeClip, pregWin, pGC->clientClip);
1727 }
1728 pGC->freeCompClip = TRUE;
1729 RegionTranslate(pGC->clientClip,
1730 -(pWin->drawable.x + pGC->clipOrg.x),
1731 -(pWin->drawable.y + pGC->clipOrg.y));
1732 }
1733 }
1734
1735 Bool
1736 miOverlayCollectUnderlayRegions(WindowPtr pWin, RegionPtr *region)
1737 {
1738 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1739
1740 if (pTree) {
1741 *region = &pTree->borderClip;
1742 return FALSE;
1743 }
1744
1745 *region = RegionCreate(NullBox, 0);
1746
1747 CollectUnderlayChildrenRegions(pWin, *region);
1748
1749 return TRUE;
1750 }
1751
1752 static miOverlayTreePtr
1753 DoLeaf(WindowPtr pWin, miOverlayTreePtr parent, miOverlayTreePtr prevSib)
1754 {
1755 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1756
1757 pTree->parent = parent;
1758 pTree->firstChild = NULL;
1759 pTree->lastChild = NULL;
1760 pTree->prevSib = prevSib;
1761 pTree->nextSib = NULL;
1762
1763 if (prevSib)
1764 prevSib->nextSib = pTree;
1765
1766 if (!parent->firstChild)
1767 parent->firstChild = parent->lastChild = pTree;
1768 else if (parent->lastChild == prevSib)
1769 parent->lastChild = pTree;
1770
1771 return pTree;
1772 }
1773
1774 static void
1775 RebuildTree(WindowPtr pWin)
1776 {
1777 miOverlayTreePtr parent, prevSib, tChild;
1778 WindowPtr pChild;
1779
1780 prevSib = tChild = NULL;
1781
1782 pWin = pWin->parent;
1783
1784 while (IN_OVERLAY(pWin))
1785 pWin = pWin->parent;
1786
1787 parent = MIOVERLAY_GET_WINDOW_TREE(pWin);
1788
1789 pChild = pWin->firstChild;
1790 parent->firstChild = parent->lastChild = NULL;
1791
1792 while (1) {
1793 if (IN_UNDERLAY(pChild))
1794 prevSib = tChild = DoLeaf(pChild, parent, prevSib);
1795
1796 if (pChild->firstChild) {
1797 if (IN_UNDERLAY(pChild)) {
1798 parent = tChild;
1799 prevSib = NULL;
1800 }
1801 pChild = pChild->firstChild;
1802 continue;
1803 }
1804
1805 while (!pChild->nextSib) {
1806 pChild = pChild->parent;
1807 if (pChild == pWin)
1808 return;
1809 if (IN_UNDERLAY(pChild)) {
1810 prevSib = tChild = MIOVERLAY_GET_WINDOW_TREE(pChild);
1811 parent = tChild->parent;
1812 }
1813 }
1814
1815 pChild = pChild->nextSib;
1816 }
1817 }
1818
1819 static Bool
1820 HasUnderlayChildren(WindowPtr pWin)
1821 {
1822 WindowPtr pChild;
1823
1824 if (!(pChild = pWin->firstChild))
1825 return FALSE;
1826
1827 while (1) {
1828 if (IN_UNDERLAY(pChild))
1829 return TRUE;
1830
1831 if (pChild->firstChild) {
1832 pChild = pChild->firstChild;
1833 continue;
1834 }
1835
1836 while (!pChild->nextSib && (pWin != pChild))
1837 pChild = pChild->parent;
1838
1839 if (pChild == pWin)
1840 break;
1841
1842 pChild = pChild->nextSib;
1843 }
1844
1845 return FALSE;
1846 }
1847
1848 static Bool
1849 CollectUnderlayChildrenRegions(WindowPtr pWin, RegionPtr pReg)
1850 {
1851 WindowPtr pChild;
1852 miOverlayTreePtr pTree;
1853 Bool hasUnderlay;
1854
1855 if (!(pChild = pWin->firstChild))
1856 return FALSE;
1857
1858 hasUnderlay = FALSE;
1859
1860 while (1) {
1861 if ((pTree = MIOVERLAY_GET_WINDOW_TREE(pChild))) {
1862 RegionAppend(pReg, &pTree->borderClip);
1863 hasUnderlay = TRUE;
1864 }
1865 else if (pChild->firstChild) {
1866 pChild = pChild->firstChild;
1867 continue;
1868 }
1869
1870 while (!pChild->nextSib && (pWin != pChild))
1871 pChild = pChild->parent;
1872
1873 if (pChild == pWin)
1874 break;
1875
1876 pChild = pChild->nextSib;
1877 }
1878
1879 if (hasUnderlay) {
1880 Bool overlap;
1881
1882 RegionValidate(pReg, &overlap);
1883 }
1884
1885 return hasUnderlay;
1886 }
1887
1888 static void
1889 MarkUnderlayWindow(WindowPtr pWin)
1890 {
1891 miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1892
1893 if (pTree->valdata)
1894 return;
1895 pTree->valdata =
1896 (miOverlayValDataPtr) xnfalloc(sizeof(miOverlayValDataRec));
1897 pTree->valdata->oldAbsCorner.x = pWin->drawable.x;
1898 pTree->valdata->oldAbsCorner.y = pWin->drawable.y;
1899 pTree->valdata->borderVisible = NullRegion;
1900 }