2 /***********************************************************
4 Copyright 1987, 1998 The Open Group
6 Permission to use, copy, modify, distribute, and sell this software and its
7 documentation for any purpose is hereby granted without fee, provided that
8 the above copyright notice appear in all copies and that both that
9 copyright notice and this permission notice appear in supporting
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 Except as contained in this notice, the name of The Open Group shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from The Open Group.
26 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
30 Permission to use, copy, modify, and distribute this software and its
31 documentation for any purpose and without fee is hereby granted,
32 provided that the above copyright notice appear in all copies and that
33 both that copyright notice and this permission notice appear in
34 supporting documentation, and that the name of Digital not be
35 used in advertising or publicity pertaining to distribution of the
36 software without specific, written prior permission.
38 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
46 ******************************************************************/
47 #ifdef HAVE_DIX_CONFIG_H
48 #include <dix-config.h>
52 #include <X11/extensions/shapeconst.h>
53 #include "regionstr.h"
56 #include "windowstr.h"
57 #include "scrnintstr.h"
58 #include "pixmapstr.h"
59 #include "mivalidate.h"
62 miClearToBackground(WindowPtr pWin
,
63 int x
, int y
, int w
, int h
, Bool generateExposures
)
70 /* compute everything using ints to avoid overflow */
72 x1
= pWin
->drawable
.x
+ x
;
73 y1
= pWin
->drawable
.y
+ y
;
77 x2
= x1
+ (int) pWin
->drawable
.width
- (int) x
;
81 y2
= y1
+ (int) pWin
->drawable
.height
- (int) y
;
83 extents
= &pWin
->clipList
.extents
;
85 /* clip the resulting rectangle to the window clipList extents. This
86 * makes sure that the result will fit in a box, given that the
87 * screen is < 32768 on a side.
99 if (x2
<= x1
|| y2
<= y1
) {
109 RegionInit(®
, &box
, 1);
111 RegionIntersect(®
, ®
, &pWin
->clipList
);
112 if (generateExposures
)
113 (*pWin
->drawable
.pScreen
->WindowExposures
) (pWin
, ®
, NULL
);
114 else if (pWin
->backgroundState
!= None
)
115 miPaintWindow(pWin
, ®
, PW_BACKGROUND
);
120 miMarkWindow(WindowPtr pWin
)
126 val
= (ValidatePtr
) xnfalloc(sizeof(ValidateRec
));
127 val
->before
.oldAbsCorner
.x
= pWin
->drawable
.x
;
128 val
->before
.oldAbsCorner
.y
= pWin
->drawable
.y
;
129 val
->before
.borderVisible
= NullRegion
;
130 val
->before
.resized
= FALSE
;
135 miMarkOverlappedWindows(WindowPtr pWin
, WindowPtr pFirst
, WindowPtr
*ppLayerWin
)
138 WindowPtr pChild
, pLast
;
139 Bool anyMarked
= FALSE
;
140 MarkWindowProcPtr MarkWindow
= pWin
->drawable
.pScreen
->MarkWindow
;
142 /* single layered systems are easy */
146 if (pWin
== pFirst
) {
147 /* Blindly mark pWin and all of its inferiors. This is a slight
148 * overkill if there are mapped windows that outside pWin's border,
149 * but it's better than wasting time on RectIn checks.
153 if (pChild
->viewable
) {
154 if (RegionBroken(&pChild
->winSize
))
156 if (RegionBroken(&pChild
->borderSize
))
157 SetBorderSize(pChild
);
158 (*MarkWindow
) (pChild
);
159 if (pChild
->firstChild
) {
160 pChild
= pChild
->firstChild
;
164 while (!pChild
->nextSib
&& (pChild
!= pWin
))
165 pChild
= pChild
->parent
;
168 pChild
= pChild
->nextSib
;
171 pFirst
= pFirst
->nextSib
;
173 if ((pChild
= pFirst
)) {
174 box
= RegionExtents(&pWin
->borderSize
);
175 pLast
= pChild
->parent
->lastChild
;
177 if (pChild
->viewable
) {
178 if (RegionBroken(&pChild
->winSize
))
180 if (RegionBroken(&pChild
->borderSize
))
181 SetBorderSize(pChild
);
182 if (RegionContainsRect(&pChild
->borderSize
, box
)) {
183 (*MarkWindow
) (pChild
);
185 if (pChild
->firstChild
) {
186 pChild
= pChild
->firstChild
;
191 while (!pChild
->nextSib
&& (pChild
!= pLast
))
192 pChild
= pChild
->parent
;
195 pChild
= pChild
->nextSib
;
199 (*MarkWindow
) (pWin
->parent
);
204 * miHandleValidateExposures(pWin)
205 * starting at pWin, draw background in any windows that have exposure
206 * regions, translate the regions, restore any backing store,
207 * and then send any regions still exposed to the client
210 miHandleValidateExposures(WindowPtr pWin
)
214 WindowExposuresProcPtr WindowExposures
;
217 WindowExposures
= pChild
->drawable
.pScreen
->WindowExposures
;
219 if ((val
= pChild
->valdata
)) {
220 if (RegionNotEmpty(&val
->after
.borderExposed
))
221 miPaintWindow(pChild
, &val
->after
.borderExposed
, PW_BORDER
);
222 RegionUninit(&val
->after
.borderExposed
);
223 (*WindowExposures
) (pChild
, &val
->after
.exposed
, NullRegion
);
224 RegionUninit(&val
->after
.exposed
);
226 pChild
->valdata
= NULL
;
227 if (pChild
->firstChild
) {
228 pChild
= pChild
->firstChild
;
232 while (!pChild
->nextSib
&& (pChild
!= pWin
))
233 pChild
= pChild
->parent
;
236 pChild
= pChild
->nextSib
;
241 miMoveWindow(WindowPtr pWin
, int x
, int y
, WindowPtr pNextSib
, VTKind kind
)
244 Bool WasViewable
= (Bool
) (pWin
->viewable
);
246 RegionPtr oldRegion
= NULL
;
248 Bool anyMarked
= FALSE
;
250 WindowPtr windowToValidate
;
253 /* if this is a root window, can't be moved */
254 if (!(pParent
= pWin
->parent
))
256 pScreen
= pWin
->drawable
.pScreen
;
257 bw
= wBorderWidth(pWin
);
259 oldpt
.x
= pWin
->drawable
.x
;
260 oldpt
.y
= pWin
->drawable
.y
;
262 oldRegion
= RegionCreate(NullBox
, 1);
263 RegionCopy(oldRegion
, &pWin
->borderClip
);
264 anyMarked
= (*pScreen
->MarkOverlappedWindows
) (pWin
, pWin
, &pLayerWin
);
266 pWin
->origin
.x
= x
+ (int) bw
;
267 pWin
->origin
.y
= y
+ (int) bw
;
268 x
= pWin
->drawable
.x
= pParent
->drawable
.x
+ x
+ (int) bw
;
269 y
= pWin
->drawable
.y
= pParent
->drawable
.y
+ y
+ (int) bw
;
274 (*pScreen
->PositionWindow
) (pWin
, x
, y
);
276 windowToValidate
= MoveWindowInStack(pWin
, pNextSib
);
278 ResizeChildrenWinSize(pWin
, x
- oldpt
.x
, y
- oldpt
.y
, 0, 0);
281 if (pLayerWin
== pWin
)
282 anyMarked
|= (*pScreen
->MarkOverlappedWindows
)
283 (pWin
, windowToValidate
, NULL
);
285 anyMarked
|= (*pScreen
->MarkOverlappedWindows
)
286 (pWin
, pLayerWin
, NULL
);
289 (*pScreen
->ValidateTree
) (pLayerWin
->parent
, NullWindow
, kind
);
290 (*pWin
->drawable
.pScreen
->CopyWindow
) (pWin
, oldpt
, oldRegion
);
291 RegionDestroy(oldRegion
);
292 /* XXX need to retile border if ParentRelative origin */
293 (*pScreen
->HandleExposures
) (pLayerWin
->parent
);
295 if (anyMarked
&& pScreen
->PostValidateTree
)
296 (*pScreen
->PostValidateTree
) (pLayerWin
->parent
, NullWindow
, kind
);
299 WindowsRestructured();
303 * pValid is a region of the screen which has been
304 * successfully copied -- recomputed exposed regions for affected windows
308 miRecomputeExposures(WindowPtr pWin
, pointer value
)
309 { /* must conform to VisitWindowProcPtr */
310 RegionPtr pValid
= (RegionPtr
) value
;
315 * Redirected windows are not affected by parent window
316 * gravity manipulations, so don't recompute their
317 * exposed areas here.
319 if (pWin
->redirectDraw
!= RedirectDrawNone
)
320 return WT_DONTWALKCHILDREN
;
323 * compute exposed regions of this window
325 RegionSubtract(&pWin
->valdata
->after
.exposed
, &pWin
->clipList
, pValid
);
327 * compute exposed regions of the border
329 RegionSubtract(&pWin
->valdata
->after
.borderExposed
,
330 &pWin
->borderClip
, &pWin
->winSize
);
331 RegionSubtract(&pWin
->valdata
->after
.borderExposed
,
332 &pWin
->valdata
->after
.borderExposed
, pValid
);
333 return WT_WALKCHILDREN
;
339 miSlideAndSizeWindow(WindowPtr pWin
,
341 unsigned int w
, unsigned int h
, WindowPtr pSib
)
344 Bool WasViewable
= (Bool
) (pWin
->viewable
);
345 unsigned short width
= pWin
->drawable
.width
, height
= pWin
->drawable
.height
;
346 short oldx
= pWin
->drawable
.x
, oldy
= pWin
->drawable
.y
;
347 int bw
= wBorderWidth(pWin
);
350 RegionPtr oldRegion
= NULL
;
351 Bool anyMarked
= FALSE
;
353 WindowPtr pFirstChange
;
355 RegionPtr gravitate
[StaticGravity
+ 1];
357 int nx
, ny
; /* destination x,y */
358 int newx
, newy
; /* new inner window position */
359 RegionPtr pRegion
= NULL
;
360 RegionPtr destClip
; /* portions of destination already written */
361 RegionPtr oldWinClip
= NULL
; /* old clip list for window */
362 RegionPtr borderVisible
= NullRegion
; /* visible area of the border */
363 Bool shrunk
= FALSE
; /* shrunk in an inner dimension */
364 Bool moved
= FALSE
; /* window position changed */
367 /* if this is a root window, can't be resized */
368 if (!(pParent
= pWin
->parent
))
371 pScreen
= pWin
->drawable
.pScreen
;
372 newx
= pParent
->drawable
.x
+ x
+ bw
;
373 newy
= pParent
->drawable
.y
+ y
+ bw
;
377 * save the visible region of the window
379 oldRegion
= RegionCreate(NullBox
, 1);
380 RegionCopy(oldRegion
, &pWin
->winSize
);
383 * categorize child windows into regions to be moved
385 for (g
= 0; g
<= StaticGravity
; g
++)
386 gravitate
[g
] = (RegionPtr
) NULL
;
387 for (pChild
= pWin
->firstChild
; pChild
; pChild
= pChild
->nextSib
) {
388 g
= pChild
->winGravity
;
389 if (g
!= UnmapGravity
) {
391 gravitate
[g
] = RegionCreate(NullBox
, 1);
392 RegionUnion(gravitate
[g
], gravitate
[g
], &pChild
->borderClip
);
395 UnmapWindow(pChild
, TRUE
);
399 anyMarked
|= (*pScreen
->MarkOverlappedWindows
) (pWin
, pWin
, &pLayerWin
);
402 if (pWin
->bitGravity
!= ForgetGravity
) {
403 oldWinClip
= RegionCreate(NullBox
, 1);
404 RegionCopy(oldWinClip
, &pWin
->clipList
);
407 * if the window is changing size, borderExposed
408 * can't be computed correctly without some help.
410 if (pWin
->drawable
.height
> h
|| pWin
->drawable
.width
> w
)
413 if (newx
!= oldx
|| newy
!= oldy
)
416 if ((pWin
->drawable
.height
!= h
|| pWin
->drawable
.width
!= w
) &&
418 borderVisible
= RegionCreate(NullBox
, 1);
419 /* for tiled borders, we punt and draw the whole thing */
420 if (pWin
->borderIsPixel
|| !moved
) {
422 RegionSubtract(borderVisible
,
423 &pWin
->borderClip
, &pWin
->winSize
);
425 RegionCopy(borderVisible
, &pWin
->borderClip
);
429 pWin
->origin
.x
= x
+ bw
;
430 pWin
->origin
.y
= y
+ bw
;
431 pWin
->drawable
.height
= h
;
432 pWin
->drawable
.width
= w
;
434 x
= pWin
->drawable
.x
= newx
;
435 y
= pWin
->drawable
.y
= newy
;
440 dw
= (int) w
- (int) width
;
441 dh
= (int) h
- (int) height
;
442 ResizeChildrenWinSize(pWin
, x
- oldx
, y
- oldy
, dw
, dh
);
444 /* let the hardware adjust background and border pixmaps, if any */
445 (*pScreen
->PositionWindow
) (pWin
, x
, y
);
447 pFirstChange
= MoveWindowInStack(pWin
, pSib
);
450 pRegion
= RegionCreate(NullBox
, 1);
452 if (pLayerWin
== pWin
)
453 anyMarked
|= (*pScreen
->MarkOverlappedWindows
) (pWin
, pFirstChange
,
456 anyMarked
|= (*pScreen
->MarkOverlappedWindows
) (pWin
, pLayerWin
,
460 pWin
->valdata
->before
.resized
= TRUE
;
461 pWin
->valdata
->before
.borderVisible
= borderVisible
;
465 (*pScreen
->ValidateTree
) (pLayerWin
->parent
, pFirstChange
, VTOther
);
467 * the entire window is trashed unless bitGravity
468 * recovers portions of it
470 RegionCopy(&pWin
->valdata
->after
.exposed
, &pWin
->clipList
);
473 GravityTranslate(x
, y
, oldx
, oldy
, dw
, dh
, pWin
->bitGravity
, &nx
, &ny
);
476 /* avoid the border */
477 if (HasBorder(pWin
)) {
478 int offx
, offy
, dx
, dy
;
480 /* kruft to avoid double translates for each gravity */
483 for (g
= 0; g
<= StaticGravity
; g
++) {
487 /* align winSize to gravitate[g].
488 * winSize is in new coordinates,
489 * gravitate[g] is still in old coordinates */
490 GravityTranslate(x
, y
, oldx
, oldy
, dw
, dh
, g
, &nx
, &ny
);
492 dx
= (oldx
- nx
) - offx
;
493 dy
= (oldy
- ny
) - offy
;
495 RegionTranslate(&pWin
->winSize
, dx
, dy
);
499 RegionIntersect(gravitate
[g
], gravitate
[g
], &pWin
->winSize
);
501 /* get winSize back where it belongs */
503 RegionTranslate(&pWin
->winSize
, -offx
, -offy
);
506 * add screen bits to the appropriate bucket
511 * clip to new clipList
513 RegionCopy(pRegion
, oldWinClip
);
514 RegionTranslate(pRegion
, nx
- oldx
, ny
- oldy
);
515 RegionIntersect(oldWinClip
, pRegion
, &pWin
->clipList
);
517 * don't step on any gravity bits which will be copied after this
518 * region. Note -- this assumes that the regions will be copied
521 for (g
= pWin
->bitGravity
+ 1; g
<= StaticGravity
; g
++) {
523 RegionSubtract(oldWinClip
, oldWinClip
, gravitate
[g
]);
525 RegionTranslate(oldWinClip
, oldx
- nx
, oldy
- ny
);
526 g
= pWin
->bitGravity
;
528 gravitate
[g
] = oldWinClip
;
530 RegionUnion(gravitate
[g
], gravitate
[g
], oldWinClip
);
531 RegionDestroy(oldWinClip
);
536 * move the bits on the screen
541 for (g
= 0; g
<= StaticGravity
; g
++) {
545 GravityTranslate(x
, y
, oldx
, oldy
, dw
, dh
, g
, &nx
, &ny
);
547 oldpt
.x
= oldx
+ (x
- nx
);
548 oldpt
.y
= oldy
+ (y
- ny
);
550 /* Note that gravitate[g] is *translated* by CopyWindow */
552 /* only copy the remaining useful bits */
554 RegionIntersect(gravitate
[g
], gravitate
[g
], oldRegion
);
556 /* clip to not overwrite already copied areas */
559 RegionTranslate(destClip
, oldpt
.x
- x
, oldpt
.y
- y
);
560 RegionSubtract(gravitate
[g
], gravitate
[g
], destClip
);
561 RegionTranslate(destClip
, x
- oldpt
.x
, y
- oldpt
.y
);
564 /* and move those bits */
566 if (oldpt
.x
!= x
|| oldpt
.y
!= y
568 || pWin
->redirectDraw
571 (*pWin
->drawable
.pScreen
->CopyWindow
) (pWin
, oldpt
,
575 /* remove any overwritten bits from the remaining useful bits */
577 RegionSubtract(oldRegion
, oldRegion
, gravitate
[g
]);
580 * recompute exposed regions of child windows
583 for (pChild
= pWin
->firstChild
; pChild
; pChild
= pChild
->nextSib
) {
584 if (pChild
->winGravity
!= g
)
586 RegionIntersect(pRegion
, &pChild
->borderClip
, gravitate
[g
]);
587 TraverseTree(pChild
, miRecomputeExposures
, (pointer
) pRegion
);
591 * remove the successfully copied regions of the
592 * window from its exposed region
595 if (g
== pWin
->bitGravity
)
596 RegionSubtract(&pWin
->valdata
->after
.exposed
,
597 &pWin
->valdata
->after
.exposed
, gravitate
[g
]);
599 destClip
= gravitate
[g
];
601 RegionUnion(destClip
, destClip
, gravitate
[g
]);
602 RegionDestroy(gravitate
[g
]);
606 RegionDestroy(oldRegion
);
607 RegionDestroy(pRegion
);
609 RegionDestroy(destClip
);
611 (*pScreen
->HandleExposures
) (pLayerWin
->parent
);
612 if (anyMarked
&& pScreen
->PostValidateTree
)
613 (*pScreen
->PostValidateTree
) (pLayerWin
->parent
, pFirstChange
,
617 WindowsRestructured();
621 miGetLayerWindow(WindowPtr pWin
)
623 return pWin
->firstChild
;
629 * The border/window shape has changed. Recompute winSize/borderSize
630 * and send appropriate exposure events
634 miSetShape(WindowPtr pWin
, int kind
)
636 Bool WasViewable
= (Bool
) (pWin
->viewable
);
637 ScreenPtr pScreen
= pWin
->drawable
.pScreen
;
638 Bool anyMarked
= FALSE
;
641 if (kind
!= ShapeInput
) {
643 anyMarked
= (*pScreen
->MarkOverlappedWindows
) (pWin
, pWin
,
646 if (HasBorder(pWin
)) {
647 RegionPtr borderVisible
;
649 borderVisible
= RegionCreate(NullBox
, 1);
650 RegionSubtract(borderVisible
,
651 &pWin
->borderClip
, &pWin
->winSize
);
652 pWin
->valdata
->before
.borderVisible
= borderVisible
;
654 pWin
->valdata
->before
.resized
= TRUE
;
661 ResizeChildrenWinSize(pWin
, 0, 0, 0, 0);
664 anyMarked
|= (*pScreen
->MarkOverlappedWindows
) (pWin
, pWin
, NULL
);
667 (*pScreen
->ValidateTree
) (pLayerWin
->parent
, NullWindow
,
673 (*pScreen
->HandleExposures
) (pLayerWin
->parent
);
674 if (anyMarked
&& pScreen
->PostValidateTree
)
675 (*pScreen
->PostValidateTree
) (pLayerWin
->parent
, NullWindow
,
680 WindowsRestructured();
681 CheckCursorConfinement(pWin
);
684 /* Keeps the same inside(!) origin */
687 miChangeBorderWidth(WindowPtr pWin
, unsigned int width
)
690 Bool anyMarked
= FALSE
;
692 Bool WasViewable
= (Bool
) (pWin
->viewable
);
696 oldwidth
= wBorderWidth(pWin
);
697 if (oldwidth
== width
)
699 HadBorder
= HasBorder(pWin
);
700 pScreen
= pWin
->drawable
.pScreen
;
701 if (WasViewable
&& width
< oldwidth
)
702 anyMarked
= (*pScreen
->MarkOverlappedWindows
) (pWin
, pWin
, &pLayerWin
);
704 pWin
->borderWidth
= width
;
708 if (width
> oldwidth
) {
709 anyMarked
= (*pScreen
->MarkOverlappedWindows
) (pWin
, pWin
,
712 * save the old border visible region to correctly compute
715 if (pWin
->valdata
&& HadBorder
) {
716 RegionPtr borderVisible
;
718 borderVisible
= RegionCreate(NULL
, 1);
719 RegionSubtract(borderVisible
,
720 &pWin
->borderClip
, &pWin
->winSize
);
721 pWin
->valdata
->before
.borderVisible
= borderVisible
;
726 (*pScreen
->ValidateTree
) (pLayerWin
->parent
, pLayerWin
, VTOther
);
727 (*pScreen
->HandleExposures
) (pLayerWin
->parent
);
729 if (anyMarked
&& pScreen
->PostValidateTree
)
730 (*pScreen
->PostValidateTree
) (pLayerWin
->parent
, pLayerWin
,
734 WindowsRestructured();
738 miMarkUnrealizedWindow(WindowPtr pChild
, WindowPtr pWin
, Bool fromConfigure
)
740 if ((pChild
!= pWin
) || fromConfigure
) {
741 RegionEmpty(&pChild
->clipList
);
742 if (pChild
->drawable
.pScreen
->ClipNotify
)
743 (*pChild
->drawable
.pScreen
->ClipNotify
) (pChild
, 0, 0);
744 RegionEmpty(&pChild
->borderClip
);
749 miSegregateChildren(WindowPtr pWin
, RegionPtr pReg
, int depth
)
753 for (pChild
= pWin
->firstChild
; pChild
; pChild
= pChild
->nextSib
) {
754 if (pChild
->drawable
.depth
== depth
)
755 RegionUnion(pReg
, pReg
, &pChild
->borderClip
);
757 if (pChild
->firstChild
)
758 miSegregateChildren(pChild
, pReg
, depth
);