Commit | Line | Data |
---|---|---|
a09e091a JB |
1 | |
2 | /*********************************************************** | |
3 | ||
4 | Copyright 1987, 1998 The Open Group | |
5 | ||
6 | Permission to use, copy, modify, distribute, and sell this software and its | |
7 | documentation for any purpose is hereby granted without fee, provided that | |
8 | the above copyright notice appear in all copies and that both that | |
9 | copyright notice and this permission notice appear in supporting | |
10 | documentation. | |
11 | ||
12 | The above copyright notice and this permission notice shall be included in | |
13 | all copies or substantial portions of the Software. | |
14 | ||
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
18 | OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | |
19 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
21 | ||
22 | Except as contained in this notice, the name of The Open Group shall not be | |
23 | used in advertising or otherwise to promote the sale, use or other dealings | |
24 | in this Software without prior written authorization from The Open Group. | |
25 | ||
26 | Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. | |
27 | ||
28 | All Rights Reserved | |
29 | ||
30 | Permission to use, copy, modify, and distribute this software and its | |
31 | documentation for any purpose and without fee is hereby granted, | |
32 | provided that the above copyright notice appear in all copies and that | |
33 | both that copyright notice and this permission notice appear in | |
34 | supporting documentation, and that the name of Digital not be | |
35 | used in advertising or publicity pertaining to distribution of the | |
36 | software without specific, written prior permission. | |
37 | ||
38 | DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING | |
39 | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL | |
40 | DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR | |
41 | ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | |
42 | WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | |
43 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS | |
44 | SOFTWARE. | |
45 | ||
46 | ******************************************************************/ | |
47 | #ifdef HAVE_DIX_CONFIG_H | |
48 | #include <dix-config.h> | |
49 | #endif | |
50 | ||
51 | #include <X11/X.h> | |
52 | #include <X11/extensions/shapeconst.h> | |
53 | #include "regionstr.h" | |
54 | #include "region.h" | |
55 | #include "mi.h" | |
56 | #include "windowstr.h" | |
57 | #include "scrnintstr.h" | |
58 | #include "pixmapstr.h" | |
59 | #include "mivalidate.h" | |
60 | ||
61 | void | |
62 | miClearToBackground(WindowPtr pWin, | |
63 | int x, int y, int w, int h, Bool generateExposures) | |
64 | { | |
65 | BoxRec box; | |
66 | RegionRec reg; | |
67 | BoxPtr extents; | |
68 | int x1, y1, x2, y2; | |
69 | ||
70 | /* compute everything using ints to avoid overflow */ | |
71 | ||
72 | x1 = pWin->drawable.x + x; | |
73 | y1 = pWin->drawable.y + y; | |
74 | if (w) | |
75 | x2 = x1 + (int) w; | |
76 | else | |
77 | x2 = x1 + (int) pWin->drawable.width - (int) x; | |
78 | if (h) | |
79 | y2 = y1 + h; | |
80 | else | |
81 | y2 = y1 + (int) pWin->drawable.height - (int) y; | |
82 | ||
83 | extents = &pWin->clipList.extents; | |
84 | ||
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. | |
88 | */ | |
89 | ||
90 | if (x1 < extents->x1) | |
91 | x1 = extents->x1; | |
92 | if (x2 > extents->x2) | |
93 | x2 = extents->x2; | |
94 | if (y1 < extents->y1) | |
95 | y1 = extents->y1; | |
96 | if (y2 > extents->y2) | |
97 | y2 = extents->y2; | |
98 | ||
99 | if (x2 <= x1 || y2 <= y1) { | |
100 | x2 = x1 = 0; | |
101 | y2 = y1 = 0; | |
102 | } | |
103 | ||
104 | box.x1 = x1; | |
105 | box.x2 = x2; | |
106 | box.y1 = y1; | |
107 | box.y2 = y2; | |
108 | ||
109 | RegionInit(®, &box, 1); | |
110 | ||
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); | |
116 | RegionUninit(®); | |
117 | } | |
118 | ||
119 | void | |
120 | miMarkWindow(WindowPtr pWin) | |
121 | { | |
122 | ValidatePtr val; | |
123 | ||
124 | if (pWin->valdata) | |
125 | return; | |
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; | |
131 | pWin->valdata = val; | |
132 | } | |
133 | ||
134 | Bool | |
135 | miMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst, WindowPtr *ppLayerWin) | |
136 | { | |
137 | BoxPtr box; | |
138 | WindowPtr pChild, pLast; | |
139 | Bool anyMarked = FALSE; | |
140 | MarkWindowProcPtr MarkWindow = pWin->drawable.pScreen->MarkWindow; | |
141 | ||
142 | /* single layered systems are easy */ | |
143 | if (ppLayerWin) | |
144 | *ppLayerWin = pWin; | |
145 | ||
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. | |
150 | */ | |
151 | pChild = pWin; | |
152 | while (1) { | |
153 | if (pChild->viewable) { | |
154 | if (RegionBroken(&pChild->winSize)) | |
155 | SetWinSize(pChild); | |
156 | if (RegionBroken(&pChild->borderSize)) | |
157 | SetBorderSize(pChild); | |
158 | (*MarkWindow) (pChild); | |
159 | if (pChild->firstChild) { | |
160 | pChild = pChild->firstChild; | |
161 | continue; | |
162 | } | |
163 | } | |
164 | while (!pChild->nextSib && (pChild != pWin)) | |
165 | pChild = pChild->parent; | |
166 | if (pChild == pWin) | |
167 | break; | |
168 | pChild = pChild->nextSib; | |
169 | } | |
170 | anyMarked = TRUE; | |
171 | pFirst = pFirst->nextSib; | |
172 | } | |
173 | if ((pChild = pFirst)) { | |
174 | box = RegionExtents(&pWin->borderSize); | |
175 | pLast = pChild->parent->lastChild; | |
176 | while (1) { | |
177 | if (pChild->viewable) { | |
178 | if (RegionBroken(&pChild->winSize)) | |
179 | SetWinSize(pChild); | |
180 | if (RegionBroken(&pChild->borderSize)) | |
181 | SetBorderSize(pChild); | |
182 | if (RegionContainsRect(&pChild->borderSize, box)) { | |
183 | (*MarkWindow) (pChild); | |
184 | anyMarked = TRUE; | |
185 | if (pChild->firstChild) { | |
186 | pChild = pChild->firstChild; | |
187 | continue; | |
188 | } | |
189 | } | |
190 | } | |
191 | while (!pChild->nextSib && (pChild != pLast)) | |
192 | pChild = pChild->parent; | |
193 | if (pChild == pLast) | |
194 | break; | |
195 | pChild = pChild->nextSib; | |
196 | } | |
197 | } | |
198 | if (anyMarked) | |
199 | (*MarkWindow) (pWin->parent); | |
200 | return anyMarked; | |
201 | } | |
202 | ||
203 | /***** | |
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 | |
208 | *****/ | |
209 | void | |
210 | miHandleValidateExposures(WindowPtr pWin) | |
211 | { | |
212 | WindowPtr pChild; | |
213 | ValidatePtr val; | |
214 | WindowExposuresProcPtr WindowExposures; | |
215 | ||
216 | pChild = pWin; | |
217 | WindowExposures = pChild->drawable.pScreen->WindowExposures; | |
218 | while (1) { | |
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); | |
225 | free(val); | |
226 | pChild->valdata = NULL; | |
227 | if (pChild->firstChild) { | |
228 | pChild = pChild->firstChild; | |
229 | continue; | |
230 | } | |
231 | } | |
232 | while (!pChild->nextSib && (pChild != pWin)) | |
233 | pChild = pChild->parent; | |
234 | if (pChild == pWin) | |
235 | break; | |
236 | pChild = pChild->nextSib; | |
237 | } | |
238 | } | |
239 | ||
240 | void | |
241 | miMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pNextSib, VTKind kind) | |
242 | { | |
243 | WindowPtr pParent; | |
244 | Bool WasViewable = (Bool) (pWin->viewable); | |
245 | short bw; | |
246 | RegionPtr oldRegion = NULL; | |
247 | DDXPointRec oldpt; | |
248 | Bool anyMarked = FALSE; | |
249 | ScreenPtr pScreen; | |
250 | WindowPtr windowToValidate; | |
251 | WindowPtr pLayerWin; | |
252 | ||
253 | /* if this is a root window, can't be moved */ | |
254 | if (!(pParent = pWin->parent)) | |
255 | return; | |
256 | pScreen = pWin->drawable.pScreen; | |
257 | bw = wBorderWidth(pWin); | |
258 | ||
259 | oldpt.x = pWin->drawable.x; | |
260 | oldpt.y = pWin->drawable.y; | |
261 | if (WasViewable) { | |
262 | oldRegion = RegionCreate(NullBox, 1); | |
263 | RegionCopy(oldRegion, &pWin->borderClip); | |
264 | anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pWin, &pLayerWin); | |
265 | } | |
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; | |
270 | ||
271 | SetWinSize(pWin); | |
272 | SetBorderSize(pWin); | |
273 | ||
274 | (*pScreen->PositionWindow) (pWin, x, y); | |
275 | ||
276 | windowToValidate = MoveWindowInStack(pWin, pNextSib); | |
277 | ||
278 | ResizeChildrenWinSize(pWin, x - oldpt.x, y - oldpt.y, 0, 0); | |
279 | ||
280 | if (WasViewable) { | |
281 | if (pLayerWin == pWin) | |
282 | anyMarked |= (*pScreen->MarkOverlappedWindows) | |
283 | (pWin, windowToValidate, NULL); | |
284 | else | |
285 | anyMarked |= (*pScreen->MarkOverlappedWindows) | |
286 | (pWin, pLayerWin, NULL); | |
287 | ||
288 | if (anyMarked) { | |
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); | |
294 | } | |
295 | if (anyMarked && pScreen->PostValidateTree) | |
296 | (*pScreen->PostValidateTree) (pLayerWin->parent, NullWindow, kind); | |
297 | } | |
298 | if (pWin->realized) | |
299 | WindowsRestructured(); | |
300 | } | |
301 | ||
302 | /* | |
303 | * pValid is a region of the screen which has been | |
304 | * successfully copied -- recomputed exposed regions for affected windows | |
305 | */ | |
306 | ||
307 | static int | |
308 | miRecomputeExposures(WindowPtr pWin, pointer value) | |
309 | { /* must conform to VisitWindowProcPtr */ | |
310 | RegionPtr pValid = (RegionPtr) value; | |
311 | ||
312 | if (pWin->valdata) { | |
313 | #ifdef COMPOSITE | |
314 | /* | |
315 | * Redirected windows are not affected by parent window | |
316 | * gravity manipulations, so don't recompute their | |
317 | * exposed areas here. | |
318 | */ | |
319 | if (pWin->redirectDraw != RedirectDrawNone) | |
320 | return WT_DONTWALKCHILDREN; | |
321 | #endif | |
322 | /* | |
323 | * compute exposed regions of this window | |
324 | */ | |
325 | RegionSubtract(&pWin->valdata->after.exposed, &pWin->clipList, pValid); | |
326 | /* | |
327 | * compute exposed regions of the border | |
328 | */ | |
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; | |
334 | } | |
335 | return WT_NOMATCH; | |
336 | } | |
337 | ||
338 | void | |
339 | miSlideAndSizeWindow(WindowPtr pWin, | |
340 | int x, int y, | |
341 | unsigned int w, unsigned int h, WindowPtr pSib) | |
342 | { | |
343 | WindowPtr pParent; | |
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); | |
348 | short dw, dh; | |
349 | DDXPointRec oldpt; | |
350 | RegionPtr oldRegion = NULL; | |
351 | Bool anyMarked = FALSE; | |
352 | ScreenPtr pScreen; | |
353 | WindowPtr pFirstChange; | |
354 | WindowPtr pChild; | |
355 | RegionPtr gravitate[StaticGravity + 1]; | |
356 | unsigned g; | |
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 */ | |
365 | WindowPtr pLayerWin; | |
366 | ||
367 | /* if this is a root window, can't be resized */ | |
368 | if (!(pParent = pWin->parent)) | |
369 | return; | |
370 | ||
371 | pScreen = pWin->drawable.pScreen; | |
372 | newx = pParent->drawable.x + x + bw; | |
373 | newy = pParent->drawable.y + y + bw; | |
374 | if (WasViewable) { | |
375 | anyMarked = FALSE; | |
376 | /* | |
377 | * save the visible region of the window | |
378 | */ | |
379 | oldRegion = RegionCreate(NullBox, 1); | |
380 | RegionCopy(oldRegion, &pWin->winSize); | |
381 | ||
382 | /* | |
383 | * categorize child windows into regions to be moved | |
384 | */ | |
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) { | |
390 | if (!gravitate[g]) | |
391 | gravitate[g] = RegionCreate(NullBox, 1); | |
392 | RegionUnion(gravitate[g], gravitate[g], &pChild->borderClip); | |
393 | } | |
394 | else { | |
395 | UnmapWindow(pChild, TRUE); | |
396 | anyMarked = TRUE; | |
397 | } | |
398 | } | |
399 | anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin, pWin, &pLayerWin); | |
400 | ||
401 | oldWinClip = NULL; | |
402 | if (pWin->bitGravity != ForgetGravity) { | |
403 | oldWinClip = RegionCreate(NullBox, 1); | |
404 | RegionCopy(oldWinClip, &pWin->clipList); | |
405 | } | |
406 | /* | |
407 | * if the window is changing size, borderExposed | |
408 | * can't be computed correctly without some help. | |
409 | */ | |
410 | if (pWin->drawable.height > h || pWin->drawable.width > w) | |
411 | shrunk = TRUE; | |
412 | ||
413 | if (newx != oldx || newy != oldy) | |
414 | moved = TRUE; | |
415 | ||
416 | if ((pWin->drawable.height != h || pWin->drawable.width != w) && | |
417 | HasBorder(pWin)) { | |
418 | borderVisible = RegionCreate(NullBox, 1); | |
419 | /* for tiled borders, we punt and draw the whole thing */ | |
420 | if (pWin->borderIsPixel || !moved) { | |
421 | if (shrunk || moved) | |
422 | RegionSubtract(borderVisible, | |
423 | &pWin->borderClip, &pWin->winSize); | |
424 | else | |
425 | RegionCopy(borderVisible, &pWin->borderClip); | |
426 | } | |
427 | } | |
428 | } | |
429 | pWin->origin.x = x + bw; | |
430 | pWin->origin.y = y + bw; | |
431 | pWin->drawable.height = h; | |
432 | pWin->drawable.width = w; | |
433 | ||
434 | x = pWin->drawable.x = newx; | |
435 | y = pWin->drawable.y = newy; | |
436 | ||
437 | SetWinSize(pWin); | |
438 | SetBorderSize(pWin); | |
439 | ||
440 | dw = (int) w - (int) width; | |
441 | dh = (int) h - (int) height; | |
442 | ResizeChildrenWinSize(pWin, x - oldx, y - oldy, dw, dh); | |
443 | ||
444 | /* let the hardware adjust background and border pixmaps, if any */ | |
445 | (*pScreen->PositionWindow) (pWin, x, y); | |
446 | ||
447 | pFirstChange = MoveWindowInStack(pWin, pSib); | |
448 | ||
449 | if (WasViewable) { | |
450 | pRegion = RegionCreate(NullBox, 1); | |
451 | ||
452 | if (pLayerWin == pWin) | |
453 | anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin, pFirstChange, | |
454 | NULL); | |
455 | else | |
456 | anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin, pLayerWin, | |
457 | NULL); | |
458 | ||
459 | if (pWin->valdata) { | |
460 | pWin->valdata->before.resized = TRUE; | |
461 | pWin->valdata->before.borderVisible = borderVisible; | |
462 | } | |
463 | ||
464 | if (anyMarked) | |
465 | (*pScreen->ValidateTree) (pLayerWin->parent, pFirstChange, VTOther); | |
466 | /* | |
467 | * the entire window is trashed unless bitGravity | |
468 | * recovers portions of it | |
469 | */ | |
470 | RegionCopy(&pWin->valdata->after.exposed, &pWin->clipList); | |
471 | } | |
472 | ||
473 | GravityTranslate(x, y, oldx, oldy, dw, dh, pWin->bitGravity, &nx, &ny); | |
474 | ||
475 | if (WasViewable) { | |
476 | /* avoid the border */ | |
477 | if (HasBorder(pWin)) { | |
478 | int offx, offy, dx, dy; | |
479 | ||
480 | /* kruft to avoid double translates for each gravity */ | |
481 | offx = 0; | |
482 | offy = 0; | |
483 | for (g = 0; g <= StaticGravity; g++) { | |
484 | if (!gravitate[g]) | |
485 | continue; | |
486 | ||
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); | |
491 | ||
492 | dx = (oldx - nx) - offx; | |
493 | dy = (oldy - ny) - offy; | |
494 | if (dx || dy) { | |
495 | RegionTranslate(&pWin->winSize, dx, dy); | |
496 | offx += dx; | |
497 | offy += dy; | |
498 | } | |
499 | RegionIntersect(gravitate[g], gravitate[g], &pWin->winSize); | |
500 | } | |
501 | /* get winSize back where it belongs */ | |
502 | if (offx || offy) | |
503 | RegionTranslate(&pWin->winSize, -offx, -offy); | |
504 | } | |
505 | /* | |
506 | * add screen bits to the appropriate bucket | |
507 | */ | |
508 | ||
509 | if (oldWinClip) { | |
510 | /* | |
511 | * clip to new clipList | |
512 | */ | |
513 | RegionCopy(pRegion, oldWinClip); | |
514 | RegionTranslate(pRegion, nx - oldx, ny - oldy); | |
515 | RegionIntersect(oldWinClip, pRegion, &pWin->clipList); | |
516 | /* | |
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 | |
519 | * in gravity order. | |
520 | */ | |
521 | for (g = pWin->bitGravity + 1; g <= StaticGravity; g++) { | |
522 | if (gravitate[g]) | |
523 | RegionSubtract(oldWinClip, oldWinClip, gravitate[g]); | |
524 | } | |
525 | RegionTranslate(oldWinClip, oldx - nx, oldy - ny); | |
526 | g = pWin->bitGravity; | |
527 | if (!gravitate[g]) | |
528 | gravitate[g] = oldWinClip; | |
529 | else { | |
530 | RegionUnion(gravitate[g], gravitate[g], oldWinClip); | |
531 | RegionDestroy(oldWinClip); | |
532 | } | |
533 | } | |
534 | ||
535 | /* | |
536 | * move the bits on the screen | |
537 | */ | |
538 | ||
539 | destClip = NULL; | |
540 | ||
541 | for (g = 0; g <= StaticGravity; g++) { | |
542 | if (!gravitate[g]) | |
543 | continue; | |
544 | ||
545 | GravityTranslate(x, y, oldx, oldy, dw, dh, g, &nx, &ny); | |
546 | ||
547 | oldpt.x = oldx + (x - nx); | |
548 | oldpt.y = oldy + (y - ny); | |
549 | ||
550 | /* Note that gravitate[g] is *translated* by CopyWindow */ | |
551 | ||
552 | /* only copy the remaining useful bits */ | |
553 | ||
554 | RegionIntersect(gravitate[g], gravitate[g], oldRegion); | |
555 | ||
556 | /* clip to not overwrite already copied areas */ | |
557 | ||
558 | if (destClip) { | |
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); | |
562 | } | |
563 | ||
564 | /* and move those bits */ | |
565 | ||
566 | if (oldpt.x != x || oldpt.y != y | |
567 | #ifdef COMPOSITE | |
568 | || pWin->redirectDraw | |
569 | #endif | |
570 | ) { | |
571 | (*pWin->drawable.pScreen->CopyWindow) (pWin, oldpt, | |
572 | gravitate[g]); | |
573 | } | |
574 | ||
575 | /* remove any overwritten bits from the remaining useful bits */ | |
576 | ||
577 | RegionSubtract(oldRegion, oldRegion, gravitate[g]); | |
578 | ||
579 | /* | |
580 | * recompute exposed regions of child windows | |
581 | */ | |
582 | ||
583 | for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) { | |
584 | if (pChild->winGravity != g) | |
585 | continue; | |
586 | RegionIntersect(pRegion, &pChild->borderClip, gravitate[g]); | |
587 | TraverseTree(pChild, miRecomputeExposures, (pointer) pRegion); | |
588 | } | |
589 | ||
590 | /* | |
591 | * remove the successfully copied regions of the | |
592 | * window from its exposed region | |
593 | */ | |
594 | ||
595 | if (g == pWin->bitGravity) | |
596 | RegionSubtract(&pWin->valdata->after.exposed, | |
597 | &pWin->valdata->after.exposed, gravitate[g]); | |
598 | if (!destClip) | |
599 | destClip = gravitate[g]; | |
600 | else { | |
601 | RegionUnion(destClip, destClip, gravitate[g]); | |
602 | RegionDestroy(gravitate[g]); | |
603 | } | |
604 | } | |
605 | ||
606 | RegionDestroy(oldRegion); | |
607 | RegionDestroy(pRegion); | |
608 | if (destClip) | |
609 | RegionDestroy(destClip); | |
610 | if (anyMarked) | |
611 | (*pScreen->HandleExposures) (pLayerWin->parent); | |
612 | if (anyMarked && pScreen->PostValidateTree) | |
613 | (*pScreen->PostValidateTree) (pLayerWin->parent, pFirstChange, | |
614 | VTOther); | |
615 | } | |
616 | if (pWin->realized) | |
617 | WindowsRestructured(); | |
618 | } | |
619 | ||
620 | WindowPtr | |
621 | miGetLayerWindow(WindowPtr pWin) | |
622 | { | |
623 | return pWin->firstChild; | |
624 | } | |
625 | ||
626 | /****** | |
627 | * | |
628 | * miSetShape | |
629 | * The border/window shape has changed. Recompute winSize/borderSize | |
630 | * and send appropriate exposure events | |
631 | */ | |
632 | ||
633 | void | |
634 | miSetShape(WindowPtr pWin, int kind) | |
635 | { | |
636 | Bool WasViewable = (Bool) (pWin->viewable); | |
637 | ScreenPtr pScreen = pWin->drawable.pScreen; | |
638 | Bool anyMarked = FALSE; | |
639 | WindowPtr pLayerWin; | |
640 | ||
641 | if (kind != ShapeInput) { | |
642 | if (WasViewable) { | |
643 | anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pWin, | |
644 | &pLayerWin); | |
645 | if (pWin->valdata) { | |
646 | if (HasBorder(pWin)) { | |
647 | RegionPtr borderVisible; | |
648 | ||
649 | borderVisible = RegionCreate(NullBox, 1); | |
650 | RegionSubtract(borderVisible, | |
651 | &pWin->borderClip, &pWin->winSize); | |
652 | pWin->valdata->before.borderVisible = borderVisible; | |
653 | } | |
654 | pWin->valdata->before.resized = TRUE; | |
655 | } | |
656 | } | |
657 | ||
658 | SetWinSize(pWin); | |
659 | SetBorderSize(pWin); | |
660 | ||
661 | ResizeChildrenWinSize(pWin, 0, 0, 0, 0); | |
662 | ||
663 | if (WasViewable) { | |
664 | anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin, pWin, NULL); | |
665 | ||
666 | if (anyMarked) | |
667 | (*pScreen->ValidateTree) (pLayerWin->parent, NullWindow, | |
668 | VTOther); | |
669 | } | |
670 | ||
671 | if (WasViewable) { | |
672 | if (anyMarked) | |
673 | (*pScreen->HandleExposures) (pLayerWin->parent); | |
674 | if (anyMarked && pScreen->PostValidateTree) | |
675 | (*pScreen->PostValidateTree) (pLayerWin->parent, NullWindow, | |
676 | VTOther); | |
677 | } | |
678 | } | |
679 | if (pWin->realized) | |
680 | WindowsRestructured(); | |
681 | CheckCursorConfinement(pWin); | |
682 | } | |
683 | ||
684 | /* Keeps the same inside(!) origin */ | |
685 | ||
686 | void | |
687 | miChangeBorderWidth(WindowPtr pWin, unsigned int width) | |
688 | { | |
689 | int oldwidth; | |
690 | Bool anyMarked = FALSE; | |
691 | ScreenPtr pScreen; | |
692 | Bool WasViewable = (Bool) (pWin->viewable); | |
693 | Bool HadBorder; | |
694 | WindowPtr pLayerWin; | |
695 | ||
696 | oldwidth = wBorderWidth(pWin); | |
697 | if (oldwidth == width) | |
698 | return; | |
699 | HadBorder = HasBorder(pWin); | |
700 | pScreen = pWin->drawable.pScreen; | |
701 | if (WasViewable && width < oldwidth) | |
702 | anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pWin, &pLayerWin); | |
703 | ||
704 | pWin->borderWidth = width; | |
705 | SetBorderSize(pWin); | |
706 | ||
707 | if (WasViewable) { | |
708 | if (width > oldwidth) { | |
709 | anyMarked = (*pScreen->MarkOverlappedWindows) (pWin, pWin, | |
710 | &pLayerWin); | |
711 | /* | |
712 | * save the old border visible region to correctly compute | |
713 | * borderExposed. | |
714 | */ | |
715 | if (pWin->valdata && HadBorder) { | |
716 | RegionPtr borderVisible; | |
717 | ||
718 | borderVisible = RegionCreate(NULL, 1); | |
719 | RegionSubtract(borderVisible, | |
720 | &pWin->borderClip, &pWin->winSize); | |
721 | pWin->valdata->before.borderVisible = borderVisible; | |
722 | } | |
723 | } | |
724 | ||
725 | if (anyMarked) { | |
726 | (*pScreen->ValidateTree) (pLayerWin->parent, pLayerWin, VTOther); | |
727 | (*pScreen->HandleExposures) (pLayerWin->parent); | |
728 | } | |
729 | if (anyMarked && pScreen->PostValidateTree) | |
730 | (*pScreen->PostValidateTree) (pLayerWin->parent, pLayerWin, | |
731 | VTOther); | |
732 | } | |
733 | if (pWin->realized) | |
734 | WindowsRestructured(); | |
735 | } | |
736 | ||
737 | void | |
738 | miMarkUnrealizedWindow(WindowPtr pChild, WindowPtr pWin, Bool fromConfigure) | |
739 | { | |
740 | if ((pChild != pWin) || fromConfigure) { | |
741 | RegionEmpty(&pChild->clipList); | |
742 | if (pChild->drawable.pScreen->ClipNotify) | |
743 | (*pChild->drawable.pScreen->ClipNotify) (pChild, 0, 0); | |
744 | RegionEmpty(&pChild->borderClip); | |
745 | } | |
746 | } | |
747 | ||
748 | void | |
749 | miSegregateChildren(WindowPtr pWin, RegionPtr pReg, int depth) | |
750 | { | |
751 | WindowPtr pChild; | |
752 | ||
753 | for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) { | |
754 | if (pChild->drawable.depth == depth) | |
755 | RegionUnion(pReg, pReg, &pChild->borderClip); | |
756 | ||
757 | if (pChild->firstChild) | |
758 | miSegregateChildren(pChild, pReg, depth); | |
759 | } | |
760 | } |