Add patch that contain Mali fixes.
[deb_xorg-server.git] / composite / compwindow.c
CommitLineData
a09e091a
JB
1/*
2 * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * 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
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Copyright © 2003 Keith Packard
24 *
25 * Permission to use, copy, modify, distribute, and sell this software and its
26 * documentation for any purpose is hereby granted without fee, provided that
27 * the above copyright notice appear in all copies and that both that
28 * copyright notice and this permission notice appear in supporting
29 * documentation, and that the name of Keith Packard not be used in
30 * advertising or publicity pertaining to distribution of the software without
31 * specific, written prior permission. Keith Packard makes no
32 * representations about the suitability of this software for any purpose. It
33 * is provided "as is" without express or implied warranty.
34 *
35 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
36 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
37 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
38 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
39 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
40 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
41 * PERFORMANCE OF THIS SOFTWARE.
42 */
43
44#ifdef HAVE_DIX_CONFIG_H
45#include <dix-config.h>
46#endif
47
48#include "compint.h"
49
50#ifdef PANORAMIX
51#include "panoramiXsrv.h"
52#endif
53
54#ifdef COMPOSITE_DEBUG
55static int
56compCheckWindow(WindowPtr pWin, pointer data)
57{
58 ScreenPtr pScreen = pWin->drawable.pScreen;
59 PixmapPtr pWinPixmap = (*pScreen->GetWindowPixmap) (pWin);
60 PixmapPtr pParentPixmap =
61 pWin->parent ? (*pScreen->GetWindowPixmap) (pWin->parent) : 0;
62 PixmapPtr pScreenPixmap = (*pScreen->GetScreenPixmap) (pScreen);
63
64 if (!pWin->parent) {
65 assert(pWin->redirectDraw == RedirectDrawNone);
66 assert(pWinPixmap == pScreenPixmap);
67 }
68 else if (pWin->redirectDraw != RedirectDrawNone) {
69 assert(pWinPixmap != pParentPixmap);
70 assert(pWinPixmap != pScreenPixmap);
71 }
72 else {
73 assert(pWinPixmap == pParentPixmap);
74 }
75 assert(0 < pWinPixmap->refcnt && pWinPixmap->refcnt < 3);
76 assert(0 < pScreenPixmap->refcnt && pScreenPixmap->refcnt < 3);
77 if (pParentPixmap)
78 assert(0 <= pParentPixmap->refcnt && pParentPixmap->refcnt < 3);
79 return WT_WALKCHILDREN;
80}
81
82void
83compCheckTree(ScreenPtr pScreen)
84{
85 WalkTree(pScreen, compCheckWindow, 0);
86}
87#endif
88
89typedef struct _compPixmapVisit {
90 WindowPtr pWindow;
91 PixmapPtr pPixmap;
92} CompPixmapVisitRec, *CompPixmapVisitPtr;
93
94static Bool
95compRepaintBorder(ClientPtr pClient, pointer closure)
96{
97 WindowPtr pWindow;
98 int rc =
99 dixLookupWindow(&pWindow, (XID) (intptr_t) closure, pClient,
100 DixWriteAccess);
101
102 if (rc == Success) {
103 RegionRec exposed;
104
105 RegionNull(&exposed);
106 RegionSubtract(&exposed, &pWindow->borderClip, &pWindow->winSize);
107 miPaintWindow(pWindow, &exposed, PW_BORDER);
108 RegionUninit(&exposed);
109 }
110 return TRUE;
111}
112
113static int
114compSetPixmapVisitWindow(WindowPtr pWindow, pointer data)
115{
116 CompPixmapVisitPtr pVisit = (CompPixmapVisitPtr) data;
117 ScreenPtr pScreen = pWindow->drawable.pScreen;
118
119 if (pWindow != pVisit->pWindow && pWindow->redirectDraw != RedirectDrawNone)
120 return WT_DONTWALKCHILDREN;
121 (*pScreen->SetWindowPixmap) (pWindow, pVisit->pPixmap);
122 /*
123 * Recompute winSize and borderSize. This is duplicate effort
124 * when resizing pixmaps, but necessary when changing redirection.
125 * Might be nice to fix this.
126 */
127 SetWinSize(pWindow);
128 SetBorderSize(pWindow);
129 if (HasBorder(pWindow))
130 QueueWorkProc(compRepaintBorder, serverClient,
131 (pointer) (intptr_t) pWindow->drawable.id);
132 return WT_WALKCHILDREN;
133}
134
135void
136compSetPixmap(WindowPtr pWindow, PixmapPtr pPixmap)
137{
138 CompPixmapVisitRec visitRec;
139
140 visitRec.pWindow = pWindow;
141 visitRec.pPixmap = pPixmap;
142 TraverseTree(pWindow, compSetPixmapVisitWindow, (pointer) &visitRec);
143 compCheckTree(pWindow->drawable.pScreen);
144}
145
146Bool
147compCheckRedirect(WindowPtr pWin)
148{
149 CompWindowPtr cw = GetCompWindow(pWin);
150 CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen);
151 Bool should;
152
153 should = pWin->realized && (pWin->drawable.class != InputOnly) &&
154 (cw != NULL) && (pWin->parent != NULL);
155
156 /* Never redirect the overlay window */
157 if (cs->pOverlayWin != NULL) {
158 if (pWin == cs->pOverlayWin) {
159 should = FALSE;
160 }
161 }
162
163 if (should != (pWin->redirectDraw != RedirectDrawNone)) {
164 if (should)
165 return compAllocPixmap(pWin);
166 else {
167 ScreenPtr pScreen = pWin->drawable.pScreen;
168 PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
169
170 compSetParentPixmap(pWin);
171 compRestoreWindow(pWin, pPixmap);
172 (*pScreen->DestroyPixmap) (pPixmap);
173 }
174 }
175 else if (should) {
176 if (cw->update == CompositeRedirectAutomatic)
177 pWin->redirectDraw = RedirectDrawAutomatic;
178 else
179 pWin->redirectDraw = RedirectDrawManual;
180 }
181 return TRUE;
182}
183
184static int
185updateOverlayWindow(ScreenPtr pScreen)
186{
187 CompScreenPtr cs;
188 WindowPtr pWin; /* overlay window */
189 XID vlist[2];
190 int w = pScreen->width;
191 int h = pScreen->height;
192
193#ifdef PANORAMIX
194 if (!noPanoramiXExtension) {
195 w = PanoramiXPixWidth;
196 h = PanoramiXPixHeight;
197 }
198#endif
199
200 cs = GetCompScreen(pScreen);
201 if ((pWin = cs->pOverlayWin) != NULL) {
202 if ((pWin->drawable.width == w) && (pWin->drawable.height == h))
203 return Success;
204
205 /* Let's resize the overlay window. */
206 vlist[0] = w;
207 vlist[1] = h;
208 return ConfigureWindow(pWin, CWWidth | CWHeight, vlist, wClient(pWin));
209 }
210
211 /* Let's be on the safe side and not assume an overlay window is
212 always allocated. */
213 return Success;
214}
215
216Bool
217compPositionWindow(WindowPtr pWin, int x, int y)
218{
219 ScreenPtr pScreen = pWin->drawable.pScreen;
220 CompScreenPtr cs = GetCompScreen(pScreen);
221 Bool ret = TRUE;
222
223 pScreen->PositionWindow = cs->PositionWindow;
224 /*
225 * "Shouldn't need this as all possible places should be wrapped
226 *
227 compCheckRedirect (pWin);
228 */
229#ifdef COMPOSITE_DEBUG
230 if ((pWin->redirectDraw != RedirectDrawNone) !=
231 (pWin->viewable && (GetCompWindow(pWin) != NULL)))
232 OsAbort();
233#endif
234 if (pWin->redirectDraw != RedirectDrawNone) {
235 PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
236 int bw = wBorderWidth(pWin);
237 int nx = pWin->drawable.x - bw;
238 int ny = pWin->drawable.y - bw;
239
240 if (pPixmap->screen_x != nx || pPixmap->screen_y != ny) {
241 pPixmap->screen_x = nx;
242 pPixmap->screen_y = ny;
243 pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
244 }
245 }
246
247 if (!(*pScreen->PositionWindow) (pWin, x, y))
248 ret = FALSE;
249 cs->PositionWindow = pScreen->PositionWindow;
250 pScreen->PositionWindow = compPositionWindow;
251 compCheckTree(pWin->drawable.pScreen);
252 if (updateOverlayWindow(pScreen) != Success)
253 ret = FALSE;
254 return ret;
255}
256
257Bool
258compRealizeWindow(WindowPtr pWin)
259{
260 ScreenPtr pScreen = pWin->drawable.pScreen;
261 CompScreenPtr cs = GetCompScreen(pScreen);
262 Bool ret = TRUE;
263
264 pScreen->RealizeWindow = cs->RealizeWindow;
265 compCheckRedirect(pWin);
266 if (!(*pScreen->RealizeWindow) (pWin))
267 ret = FALSE;
268 cs->RealizeWindow = pScreen->RealizeWindow;
269 pScreen->RealizeWindow = compRealizeWindow;
270 compCheckTree(pWin->drawable.pScreen);
271 return ret;
272}
273
274Bool
275compUnrealizeWindow(WindowPtr pWin)
276{
277 ScreenPtr pScreen = pWin->drawable.pScreen;
278 CompScreenPtr cs = GetCompScreen(pScreen);
279 Bool ret = TRUE;
280
281 pScreen->UnrealizeWindow = cs->UnrealizeWindow;
282 compCheckRedirect(pWin);
283 if (!(*pScreen->UnrealizeWindow) (pWin))
284 ret = FALSE;
285 cs->UnrealizeWindow = pScreen->UnrealizeWindow;
286 pScreen->UnrealizeWindow = compUnrealizeWindow;
287 compCheckTree(pWin->drawable.pScreen);
288 return ret;
289}
290
291/*
292 * Called after the borderClip for the window has settled down
293 * We use this to make sure our extra borderClip has the right origin
294 */
295
296void
297compClipNotify(WindowPtr pWin, int dx, int dy)
298{
299 ScreenPtr pScreen = pWin->drawable.pScreen;
300 CompScreenPtr cs = GetCompScreen(pScreen);
301 CompWindowPtr cw = GetCompWindow(pWin);
302
303 if (cw) {
304 if (cw->borderClipX != pWin->drawable.x ||
305 cw->borderClipY != pWin->drawable.y) {
306 RegionTranslate(&cw->borderClip,
307 pWin->drawable.x - cw->borderClipX,
308 pWin->drawable.y - cw->borderClipY);
309 cw->borderClipX = pWin->drawable.x;
310 cw->borderClipY = pWin->drawable.y;
311 }
312 }
313 if (cs->ClipNotify) {
314 pScreen->ClipNotify = cs->ClipNotify;
315 (*pScreen->ClipNotify) (pWin, dx, dy);
316 cs->ClipNotify = pScreen->ClipNotify;
317 pScreen->ClipNotify = compClipNotify;
318 }
319}
320
321/*
322 * Returns TRUE if the window needs server-provided automatic redirect,
323 * which is true if the child and parent aren't both regular or ARGB visuals
324 */
325
326static Bool
327compIsAlternateVisual(ScreenPtr pScreen, XID visual)
328{
329 CompScreenPtr cs = GetCompScreen(pScreen);
330 int i;
331
332 for (i = 0; i < cs->numAlternateVisuals; i++)
333 if (cs->alternateVisuals[i] == visual)
334 return TRUE;
335 return FALSE;
336}
337
338static Bool
339compImplicitRedirect(WindowPtr pWin, WindowPtr pParent)
340{
341 if (pParent) {
342 ScreenPtr pScreen = pWin->drawable.pScreen;
343 XID winVisual = wVisual(pWin);
344 XID parentVisual = wVisual(pParent);
345
346 if (winVisual != parentVisual &&
347 (compIsAlternateVisual(pScreen, winVisual) ||
348 compIsAlternateVisual(pScreen, parentVisual)))
349 return TRUE;
350 }
351 return FALSE;
352}
353
354static void
355compFreeOldPixmap(WindowPtr pWin)
356{
357 ScreenPtr pScreen = pWin->drawable.pScreen;
358
359 if (pWin->redirectDraw != RedirectDrawNone) {
360 CompWindowPtr cw = GetCompWindow(pWin);
361
362 if (cw->pOldPixmap) {
363 (*pScreen->DestroyPixmap) (cw->pOldPixmap);
364 cw->pOldPixmap = NullPixmap;
365 }
366 }
367}
368
369void
370compMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind)
371{
372 ScreenPtr pScreen = pWin->drawable.pScreen;
373 CompScreenPtr cs = GetCompScreen(pScreen);
374
375 pScreen->MoveWindow = cs->MoveWindow;
376 (*pScreen->MoveWindow) (pWin, x, y, pSib, kind);
377 cs->MoveWindow = pScreen->MoveWindow;
378 pScreen->MoveWindow = compMoveWindow;
379
380 compFreeOldPixmap(pWin);
381 compCheckTree(pScreen);
382}
383
384void
385compResizeWindow(WindowPtr pWin, int x, int y,
386 unsigned int w, unsigned int h, WindowPtr pSib)
387{
388 ScreenPtr pScreen = pWin->drawable.pScreen;
389 CompScreenPtr cs = GetCompScreen(pScreen);
390
391 pScreen->ResizeWindow = cs->ResizeWindow;
392 (*pScreen->ResizeWindow) (pWin, x, y, w, h, pSib);
393 cs->ResizeWindow = pScreen->ResizeWindow;
394 pScreen->ResizeWindow = compResizeWindow;
395
396 compFreeOldPixmap(pWin);
397 compCheckTree(pWin->drawable.pScreen);
398}
399
400void
401compChangeBorderWidth(WindowPtr pWin, unsigned int bw)
402{
403 ScreenPtr pScreen = pWin->drawable.pScreen;
404 CompScreenPtr cs = GetCompScreen(pScreen);
405
406 pScreen->ChangeBorderWidth = cs->ChangeBorderWidth;
407 (*pScreen->ChangeBorderWidth) (pWin, bw);
408 cs->ChangeBorderWidth = pScreen->ChangeBorderWidth;
409 pScreen->ChangeBorderWidth = compChangeBorderWidth;
410
411 compFreeOldPixmap(pWin);
412 compCheckTree(pWin->drawable.pScreen);
413}
414
415void
416compReparentWindow(WindowPtr pWin, WindowPtr pPriorParent)
417{
418 ScreenPtr pScreen = pWin->drawable.pScreen;
419 CompScreenPtr cs = GetCompScreen(pScreen);
420
421 pScreen->ReparentWindow = cs->ReparentWindow;
422 /*
423 * Remove any implicit redirect due to synthesized visual
424 */
425 if (compImplicitRedirect(pWin, pPriorParent))
426 compUnredirectWindow(serverClient, pWin, CompositeRedirectAutomatic);
427 /*
428 * Handle subwindows redirection
429 */
430 compUnredirectOneSubwindow(pPriorParent, pWin);
431 compRedirectOneSubwindow(pWin->parent, pWin);
432 /*
433 * Add any implict redirect due to synthesized visual
434 */
435 if (compImplicitRedirect(pWin, pWin->parent))
436 compRedirectWindow(serverClient, pWin, CompositeRedirectAutomatic);
437
438 /*
439 * Allocate any necessary redirect pixmap
440 * (this actually should never be true; pWin is always unmapped)
441 */
442 compCheckRedirect(pWin);
443
444 /*
445 * Reset pixmap pointers as appropriate
446 */
447 if (pWin->parent && pWin->redirectDraw == RedirectDrawNone)
448 compSetPixmap(pWin, (*pScreen->GetWindowPixmap) (pWin->parent));
449 /*
450 * Call down to next function
451 */
452 if (pScreen->ReparentWindow)
453 (*pScreen->ReparentWindow) (pWin, pPriorParent);
454 cs->ReparentWindow = pScreen->ReparentWindow;
455 pScreen->ReparentWindow = compReparentWindow;
456 compCheckTree(pWin->drawable.pScreen);
457}
458
459void
460compCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
461{
462 ScreenPtr pScreen = pWin->drawable.pScreen;
463 CompScreenPtr cs = GetCompScreen(pScreen);
464 int dx = 0, dy = 0;
465
466 if (pWin->redirectDraw != RedirectDrawNone) {
467 PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
468 CompWindowPtr cw = GetCompWindow(pWin);
469
470 assert(cw->oldx != COMP_ORIGIN_INVALID);
471 assert(cw->oldy != COMP_ORIGIN_INVALID);
472 if (cw->pOldPixmap) {
473 /*
474 * Ok, the old bits are available in pOldPixmap and
475 * need to be copied to pNewPixmap.
476 */
477 RegionRec rgnDst;
478 PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
479 GCPtr pGC;
480
481 dx = ptOldOrg.x - pWin->drawable.x;
482 dy = ptOldOrg.y - pWin->drawable.y;
483 RegionTranslate(prgnSrc, -dx, -dy);
484
485 RegionNull(&rgnDst);
486
487 RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc);
488
489 RegionTranslate(&rgnDst, -pPixmap->screen_x, -pPixmap->screen_y);
490
491 dx = dx + pPixmap->screen_x - cw->oldx;
492 dy = dy + pPixmap->screen_y - cw->oldy;
493 pGC = GetScratchGC(pPixmap->drawable.depth, pScreen);
494 if (pGC) {
495 BoxPtr pBox = RegionRects(&rgnDst);
496 int nBox = RegionNumRects(&rgnDst);
497
498 ValidateGC(&pPixmap->drawable, pGC);
499 while (nBox--) {
500 (void) (*pGC->ops->CopyArea) (&cw->pOldPixmap->drawable,
501 &pPixmap->drawable,
502 pGC,
503 pBox->x1 + dx, pBox->y1 + dy,
504 pBox->x2 - pBox->x1,
505 pBox->y2 - pBox->y1,
506 pBox->x1, pBox->y1);
507 pBox++;
508 }
509 FreeScratchGC(pGC);
510 }
511 return;
512 }
513 dx = pPixmap->screen_x - cw->oldx;
514 dy = pPixmap->screen_y - cw->oldy;
515 ptOldOrg.x += dx;
516 ptOldOrg.y += dy;
517 }
518
519 pScreen->CopyWindow = cs->CopyWindow;
520 if (ptOldOrg.x != pWin->drawable.x || ptOldOrg.y != pWin->drawable.y) {
521 if (dx || dy)
522 RegionTranslate(prgnSrc, dx, dy);
523 (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc);
524 if (dx || dy)
525 RegionTranslate(prgnSrc, -dx, -dy);
526 }
527 else {
528 ptOldOrg.x -= dx;
529 ptOldOrg.y -= dy;
530 RegionTranslate(prgnSrc,
531 pWin->drawable.x - ptOldOrg.x,
532 pWin->drawable.y - ptOldOrg.y);
533 DamageDamageRegion(&pWin->drawable, prgnSrc);
534 }
535 cs->CopyWindow = pScreen->CopyWindow;
536 pScreen->CopyWindow = compCopyWindow;
537 compCheckTree(pWin->drawable.pScreen);
538}
539
540Bool
541compCreateWindow(WindowPtr pWin)
542{
543 ScreenPtr pScreen = pWin->drawable.pScreen;
544 CompScreenPtr cs = GetCompScreen(pScreen);
545 Bool ret;
546
547 pScreen->CreateWindow = cs->CreateWindow;
548 ret = (*pScreen->CreateWindow) (pWin);
549 if (pWin->parent && ret) {
550 CompSubwindowsPtr csw = GetCompSubwindows(pWin->parent);
551 CompClientWindowPtr ccw;
552
553 (*pScreen->SetWindowPixmap) (pWin,
554 (*pScreen->GetWindowPixmap) (pWin->
555 parent));
556 if (csw)
557 for (ccw = csw->clients; ccw; ccw = ccw->next)
558 compRedirectWindow(clients[CLIENT_ID(ccw->id)],
559 pWin, ccw->update);
560 if (compImplicitRedirect(pWin, pWin->parent))
561 compRedirectWindow(serverClient, pWin, CompositeRedirectAutomatic);
562 }
563 cs->CreateWindow = pScreen->CreateWindow;
564 pScreen->CreateWindow = compCreateWindow;
565 compCheckTree(pWin->drawable.pScreen);
566 return ret;
567}
568
569Bool
570compDestroyWindow(WindowPtr pWin)
571{
572 ScreenPtr pScreen = pWin->drawable.pScreen;
573 CompScreenPtr cs = GetCompScreen(pScreen);
574 CompWindowPtr cw;
575 CompSubwindowsPtr csw;
576 Bool ret;
577
578 pScreen->DestroyWindow = cs->DestroyWindow;
579 while ((cw = GetCompWindow(pWin)))
580 FreeResource(cw->clients->id, RT_NONE);
581 while ((csw = GetCompSubwindows(pWin)))
582 FreeResource(csw->clients->id, RT_NONE);
583
584 if (pWin->redirectDraw != RedirectDrawNone) {
585 PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
586
587 compSetParentPixmap(pWin);
588 (*pScreen->DestroyPixmap) (pPixmap);
589 }
590 ret = (*pScreen->DestroyWindow) (pWin);
591 cs->DestroyWindow = pScreen->DestroyWindow;
592 pScreen->DestroyWindow = compDestroyWindow;
593/* compCheckTree (pWin->drawable.pScreen); can't check -- tree isn't good*/
594 return ret;
595}
596
597void
598compSetRedirectBorderClip(WindowPtr pWin, RegionPtr pRegion)
599{
600 CompWindowPtr cw = GetCompWindow(pWin);
601 RegionRec damage;
602
603 RegionNull(&damage);
604 /*
605 * Align old border clip with new border clip
606 */
607 RegionTranslate(&cw->borderClip,
608 pWin->drawable.x - cw->borderClipX,
609 pWin->drawable.y - cw->borderClipY);
610 /*
611 * Compute newly visible portion of window for repaint
612 */
613 RegionSubtract(&damage, pRegion, &cw->borderClip);
614 /*
615 * Report that as damaged so it will be redrawn
616 */
617 DamageDamageRegion(&pWin->drawable, &damage);
618 RegionUninit(&damage);
619 /*
620 * Save the new border clip region
621 */
622 RegionCopy(&cw->borderClip, pRegion);
623 cw->borderClipX = pWin->drawable.x;
624 cw->borderClipY = pWin->drawable.y;
625}
626
627RegionPtr
628compGetRedirectBorderClip(WindowPtr pWin)
629{
630 CompWindowPtr cw = GetCompWindow(pWin);
631
632 return &cw->borderClip;
633}
634
635static void
636compWindowUpdateAutomatic(WindowPtr pWin)
637{
638 CompWindowPtr cw = GetCompWindow(pWin);
639 ScreenPtr pScreen = pWin->drawable.pScreen;
640 WindowPtr pParent = pWin->parent;
641 PixmapPtr pSrcPixmap = (*pScreen->GetWindowPixmap) (pWin);
642 PictFormatPtr pSrcFormat = PictureWindowFormat(pWin);
643 PictFormatPtr pDstFormat = PictureWindowFormat(pWin->parent);
644 int error;
645 RegionPtr pRegion = DamageRegion(cw->damage);
646 PicturePtr pSrcPicture = CreatePicture(0, &pSrcPixmap->drawable,
647 pSrcFormat,
648 0, 0,
649 serverClient,
650 &error);
651 XID subwindowMode = IncludeInferiors;
652 PicturePtr pDstPicture = CreatePicture(0, &pParent->drawable,
653 pDstFormat,
654 CPSubwindowMode,
655 &subwindowMode,
656 serverClient,
657 &error);
658
659 /*
660 * First move the region from window to screen coordinates
661 */
662 RegionTranslate(pRegion, pWin->drawable.x, pWin->drawable.y);
663
664 /*
665 * Clip against the "real" border clip
666 */
667 RegionIntersect(pRegion, pRegion, &cw->borderClip);
668
669 /*
670 * Now translate from screen to dest coordinates
671 */
672 RegionTranslate(pRegion, -pParent->drawable.x, -pParent->drawable.y);
673
674 /*
675 * Clip the picture
676 */
677 SetPictureClipRegion(pDstPicture, 0, 0, pRegion);
678
679 /*
680 * And paint
681 */
682 CompositePicture(PictOpSrc, pSrcPicture, 0, pDstPicture,
683 0, 0, /* src_x, src_y */
684 0, 0, /* msk_x, msk_y */
685 pSrcPixmap->screen_x - pParent->drawable.x,
686 pSrcPixmap->screen_y - pParent->drawable.y,
687 pSrcPixmap->drawable.width, pSrcPixmap->drawable.height);
688 FreePicture(pSrcPicture, 0);
689 FreePicture(pDstPicture, 0);
690 /*
691 * Empty the damage region. This has the nice effect of
692 * rendering the translations above harmless
693 */
694 DamageEmpty(cw->damage);
695}
696
697static void
698compPaintWindowToParent(WindowPtr pWin)
699{
700 compPaintChildrenToWindow(pWin);
701
702 if (pWin->redirectDraw != RedirectDrawNone) {
703 CompWindowPtr cw = GetCompWindow(pWin);
704
705 if (cw->damaged) {
706 compWindowUpdateAutomatic(pWin);
707 cw->damaged = FALSE;
708 }
709 }
710}
711
712void
713compPaintChildrenToWindow(WindowPtr pWin)
714{
715 WindowPtr pChild;
716
717 if (!pWin->damagedDescendants)
718 return;
719
720 for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib)
721 compPaintWindowToParent(pChild);
722
723 pWin->damagedDescendants = FALSE;
724}
725
726WindowPtr
727CompositeRealChildHead(WindowPtr pWin)
728{
729 WindowPtr pChild, pChildBefore;
730 CompScreenPtr cs;
731
732 if (!pWin->parent &&
733 (screenIsSaved == SCREEN_SAVER_ON) &&
734 (HasSaverWindow(pWin->drawable.pScreen))) {
735
736 /* First child is the screen saver; see if next child is the overlay */
737 pChildBefore = pWin->firstChild;
738 pChild = pChildBefore->nextSib;
739
740 }
741 else {
742 pChildBefore = NullWindow;
743 pChild = pWin->firstChild;
744 }
745
746 if (!pChild) {
747 return NullWindow;
748 }
749
750 cs = GetCompScreen(pWin->drawable.pScreen);
751 if (pChild == cs->pOverlayWin) {
752 return pChild;
753 }
754 else {
755 return pChildBefore;
756 }
757}
758
759int
760compConfigNotify(WindowPtr pWin, int x, int y, int w, int h,
761 int bw, WindowPtr pSib)
762{
763 ScreenPtr pScreen = pWin->drawable.pScreen;
764 CompScreenPtr cs = GetCompScreen(pScreen);
765 Bool ret = 0;
766 WindowPtr pParent = pWin->parent;
767 int draw_x, draw_y;
768 Bool alloc_ret;
769
770 if (cs->ConfigNotify) {
771 pScreen->ConfigNotify = cs->ConfigNotify;
772 ret = (*pScreen->ConfigNotify) (pWin, x, y, w, h, bw, pSib);
773 cs->ConfigNotify = pScreen->ConfigNotify;
774 pScreen->ConfigNotify = compConfigNotify;
775
776 if (ret)
777 return ret;
778 }
779
780 if (pWin->redirectDraw == RedirectDrawNone)
781 return Success;
782
783 compCheckTree(pScreen);
784
785 draw_x = pParent->drawable.x + x + bw;
786 draw_y = pParent->drawable.y + y + bw;
787 alloc_ret = compReallocPixmap(pWin, draw_x, draw_y, w, h, bw);
788
789 if (alloc_ret == FALSE)
790 return BadAlloc;
791 return Success;
792}