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