2 * Copyright © 2006 Sun Microsystems, Inc. All rights reserved.
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:
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
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.
23 * Copyright © 2003 Keith Packard
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.
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.
44 #ifdef HAVE_DIX_CONFIG_H
45 #include <dix-config.h>
51 compReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
53 WindowPtr pWin = (WindowPtr) closure;
54 ScreenPtr pScreen = pWin->drawable.pScreen;
55 CompScreenPtr cs = GetCompScreen (pScreen);
56 CompWindowPtr cw = GetCompWindow (pWin);
63 compDestroyDamage (DamagePtr pDamage, void *closure)
65 WindowPtr pWin = (WindowPtr) closure;
66 CompWindowPtr cw = GetCompWindow (pWin);
72 * Redirect one window for one client
75 compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update)
77 CompWindowPtr cw = GetCompWindow (pWin);
78 CompClientWindowPtr ccw;
79 Bool wasMapped = pWin->mapped;
80 CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen);
82 if (pWin == cs->pOverlayWin) {
90 * Only one Manual update is allowed
92 if (cw && update == CompositeRedirectManual)
93 for (ccw = cw->clients; ccw; ccw = ccw->next)
94 if (ccw->update == CompositeRedirectManual)
98 * Allocate per-client per-window structure
99 * The client *could* allocate multiple, but while supported,
100 * it is not expected to be common
102 ccw = malloc(sizeof (CompClientWindowRec));
105 ccw->id = FakeClientID (pClient->index);
106 ccw->update = update;
108 * Now make sure there's a per-window structure to hang this from
112 cw = malloc(sizeof (CompWindowRec));
118 cw->damage = DamageCreate (compReportDamage,
120 DamageReportNonEmpty,
122 pWin->drawable.pScreen,
132 DisableMapUnmapEvents (pWin);
133 UnmapWindow (pWin, FALSE);
134 EnableMapUnmapEvents (pWin);
137 RegionNull(&cw->borderClip);
140 cw->update = CompositeRedirectAutomatic;
142 cw->oldx = COMP_ORIGIN_INVALID;
143 cw->oldy = COMP_ORIGIN_INVALID;
144 cw->damageRegistered = FALSE;
146 cw->pOldPixmap = NullPixmap;
147 dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, cw);
149 ccw->next = cw->clients;
151 if (!AddResource (ccw->id, CompositeClientWindowType, pWin))
153 if (ccw->update == CompositeRedirectManual)
155 /* If the window was CompositeRedirectAutomatic, then
156 * unmap the window so that the parent clip list will
157 * be correctly recomputed.
161 DisableMapUnmapEvents (pWin);
162 UnmapWindow (pWin, FALSE);
163 EnableMapUnmapEvents (pWin);
165 if (cw->damageRegistered)
167 DamageUnregister (&pWin->drawable, cw->damage);
168 cw->damageRegistered = FALSE;
170 cw->update = CompositeRedirectManual;
173 if (!compCheckRedirect (pWin))
175 FreeResource (ccw->id, RT_NONE);
178 if (wasMapped && !pWin->mapped)
180 Bool overrideRedirect = pWin->overrideRedirect;
181 pWin->overrideRedirect = TRUE;
182 DisableMapUnmapEvents (pWin);
183 MapWindow (pWin, pClient);
184 EnableMapUnmapEvents (pWin);
185 pWin->overrideRedirect = overrideRedirect;
192 * Free one of the per-client per-window resources, clearing
193 * redirect and the per-window pointer as appropriate
196 compFreeClientWindow (WindowPtr pWin, XID id)
198 CompWindowPtr cw = GetCompWindow (pWin);
199 CompClientWindowPtr ccw, *prev;
200 Bool wasMapped = pWin->mapped;
204 for (prev = &cw->clients; (ccw = *prev); prev = &ccw->next)
209 if (ccw->update == CompositeRedirectManual)
210 cw->update = CompositeRedirectAutomatic;
219 DisableMapUnmapEvents (pWin);
220 UnmapWindow (pWin, FALSE);
221 EnableMapUnmapEvents (pWin);
224 if (pWin->redirectDraw != RedirectDrawNone)
225 compFreePixmap (pWin);
228 DamageDestroy (cw->damage);
230 RegionUninit(&cw->borderClip);
232 dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, NULL);
235 else if (cw->update == CompositeRedirectAutomatic &&
236 !cw->damageRegistered && pWin->redirectDraw != RedirectDrawNone)
238 DamageRegister (&pWin->drawable, cw->damage);
239 cw->damageRegistered = TRUE;
240 pWin->redirectDraw = RedirectDrawAutomatic;
241 DamageDamageRegion(&pWin->drawable, &pWin->borderSize);
243 if (wasMapped && !pWin->mapped)
245 Bool overrideRedirect = pWin->overrideRedirect;
246 pWin->overrideRedirect = TRUE;
247 DisableMapUnmapEvents (pWin);
248 MapWindow (pWin, clients[CLIENT_ID(id)]);
249 EnableMapUnmapEvents (pWin);
250 pWin->overrideRedirect = overrideRedirect;
255 * This is easy, just free the appropriate resource.
259 compUnredirectWindow (ClientPtr pClient, WindowPtr pWin, int update)
261 CompWindowPtr cw = GetCompWindow (pWin);
262 CompClientWindowPtr ccw;
267 for (ccw = cw->clients; ccw; ccw = ccw->next)
268 if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index)
270 FreeResource (ccw->id, RT_NONE);
277 * Redirect all subwindows for one client
281 compRedirectSubwindows (ClientPtr pClient, WindowPtr pWin, int update)
283 CompSubwindowsPtr csw = GetCompSubwindows (pWin);
284 CompClientWindowPtr ccw;
288 * Only one Manual update is allowed
290 if (csw && update == CompositeRedirectManual)
291 for (ccw = csw->clients; ccw; ccw = ccw->next)
292 if (ccw->update == CompositeRedirectManual)
295 * Allocate per-client per-window structure
296 * The client *could* allocate multiple, but while supported,
297 * it is not expected to be common
299 ccw = malloc(sizeof (CompClientWindowRec));
302 ccw->id = FakeClientID (pClient->index);
303 ccw->update = update;
305 * Now make sure there's a per-window structure to hang this from
309 csw = malloc(sizeof (CompSubwindowsRec));
315 csw->update = CompositeRedirectAutomatic;
317 dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, csw);
320 * Redirect all existing windows
322 for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib)
324 int ret = compRedirectWindow (pClient, pChild, update);
327 for (pChild = pChild->nextSib; pChild; pChild = pChild->nextSib)
328 (void) compUnredirectWindow (pClient, pChild, update);
332 dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, 0);
339 * Hook into subwindows list
341 ccw->next = csw->clients;
343 if (!AddResource (ccw->id, CompositeClientSubwindowsType, pWin))
345 if (ccw->update == CompositeRedirectManual)
347 csw->update = CompositeRedirectManual;
349 * tell damage extension that damage events for this client are
352 DamageExtSetCritical (pClient, TRUE);
358 * Free one of the per-client per-subwindows resources,
359 * which frees one redirect per subwindow
362 compFreeClientSubwindows (WindowPtr pWin, XID id)
364 CompSubwindowsPtr csw = GetCompSubwindows (pWin);
365 CompClientWindowPtr ccw, *prev;
370 for (prev = &csw->clients; (ccw = *prev); prev = &ccw->next)
374 ClientPtr pClient = clients[CLIENT_ID(id)];
377 if (ccw->update == CompositeRedirectManual)
380 * tell damage extension that damage events for this client are
383 DamageExtSetCritical (pClient, FALSE);
384 csw->update = CompositeRedirectAutomatic;
386 (*pWin->drawable.pScreen->ClearToBackground)(pWin, 0, 0, 0, 0, TRUE);
390 * Unredirect all existing subwindows
392 for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib)
393 (void) compUnredirectWindow (pClient, pChild, ccw->update);
401 * Check if all of the per-client records are gone
405 dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, NULL);
411 * This is easy, just free the appropriate resource.
415 compUnredirectSubwindows (ClientPtr pClient, WindowPtr pWin, int update)
417 CompSubwindowsPtr csw = GetCompSubwindows (pWin);
418 CompClientWindowPtr ccw;
422 for (ccw = csw->clients; ccw; ccw = ccw->next)
423 if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index)
425 FreeResource (ccw->id, RT_NONE);
432 * Add redirection information for one subwindow (during reparent)
436 compRedirectOneSubwindow (WindowPtr pParent, WindowPtr pWin)
438 CompSubwindowsPtr csw = GetCompSubwindows (pParent);
439 CompClientWindowPtr ccw;
443 for (ccw = csw->clients; ccw; ccw = ccw->next)
445 int ret = compRedirectWindow (clients[CLIENT_ID(ccw->id)],
454 * Remove redirection information for one subwindow (during reparent)
458 compUnredirectOneSubwindow (WindowPtr pParent, WindowPtr pWin)
460 CompSubwindowsPtr csw = GetCompSubwindows (pParent);
461 CompClientWindowPtr ccw;
465 for (ccw = csw->clients; ccw; ccw = ccw->next)
467 int ret = compUnredirectWindow (clients[CLIENT_ID(ccw->id)],
476 compNewPixmap (WindowPtr pWin, int x, int y, int w, int h)
478 ScreenPtr pScreen = pWin->drawable.pScreen;
479 WindowPtr pParent = pWin->parent;
482 CompScreenPtr cs = GetCompScreen(pScreen);
484 #ifndef _F_COMP_OVL_PATCH
485 pPixmap = (*pScreen->CreatePixmap) (pScreen, w, h, pWin->drawable.depth,
486 CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
488 if(IsParent(cs->pOverlayWin, pWin))
490 pPixmap = (*pScreen->CreatePixmap) (pScreen, w, h, pWin->drawable.depth,
491 CREATE_PIXMAP_USAGE_OVERLAY);
495 pPixmap = (*pScreen->CreatePixmap) (pScreen, w, h, pWin->drawable.depth,
496 CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
503 pPixmap->screen_x = x;
504 pPixmap->screen_y = y;
506 if (pParent->drawable.depth == pWin->drawable.depth)
508 GCPtr pGC = GetScratchGC (pWin->drawable.depth, pScreen);
511 * Copy bits from the parent into the new pixmap so that it will
512 * have "reasonable" contents in case for background None areas.
517 val.val = IncludeInferiors;
519 ValidateGC(&pPixmap->drawable, pGC);
520 ChangeGC (serverClient, pGC, GCSubwindowMode, &val);
521 (*pGC->ops->CopyArea) (&pParent->drawable,
524 x - pParent->drawable.x,
525 y - pParent->drawable.y,
532 PictFormatPtr pSrcFormat = compWindowFormat (pParent);
533 PictFormatPtr pDstFormat = compWindowFormat (pWin);
534 XID inferiors = IncludeInferiors;
537 PicturePtr pSrcPicture = CreatePicture (None,
542 serverClient, &error);
544 PicturePtr pDstPicture = CreatePicture (None,
548 serverClient, &error);
550 if (pSrcPicture && pDstPicture)
552 CompositePicture (PictOpSrc,
556 x - pParent->drawable.x,
557 y - pParent->drawable.y,
561 FreePicture (pSrcPicture, 0);
563 FreePicture (pDstPicture, 0);
569 compAllocPixmap (WindowPtr pWin)
571 int bw = (int) pWin->borderWidth;
572 int x = pWin->drawable.x - bw;
573 int y = pWin->drawable.y - bw;
574 int w = pWin->drawable.width + (bw << 1);
575 int h = pWin->drawable.height + (bw << 1);
576 PixmapPtr pPixmap = compNewPixmap (pWin, x, y, w, h);
577 CompWindowPtr cw = GetCompWindow (pWin);
581 if (cw->update == CompositeRedirectAutomatic)
582 pWin->redirectDraw = RedirectDrawAutomatic;
584 pWin->redirectDraw = RedirectDrawManual;
586 compSetPixmap (pWin, pPixmap);
587 cw->oldx = COMP_ORIGIN_INVALID;
588 cw->oldy = COMP_ORIGIN_INVALID;
589 cw->damageRegistered = FALSE;
590 if (cw->update == CompositeRedirectAutomatic)
592 DamageRegister (&pWin->drawable, cw->damage);
593 cw->damageRegistered = TRUE;
599 compFreePixmap (WindowPtr pWin)
601 ScreenPtr pScreen = pWin->drawable.pScreen;
602 PixmapPtr pRedirectPixmap, pParentPixmap;
603 CompWindowPtr cw = GetCompWindow (pWin);
605 if (cw->damageRegistered)
607 DamageUnregister (&pWin->drawable, cw->damage);
608 cw->damageRegistered = FALSE;
609 DamageEmpty (cw->damage);
612 * Move the parent-constrained border clip region back into
613 * the window so that ValidateTree will handle the unmap
614 * case correctly. Unmap adds the window borderClip to the
615 * parent exposed area; regions beyond the parent cause crashes
617 RegionCopy(&pWin->borderClip, &cw->borderClip);
618 pRedirectPixmap = (*pScreen->GetWindowPixmap) (pWin);
619 pParentPixmap = (*pScreen->GetWindowPixmap) (pWin->parent);
620 pWin->redirectDraw = RedirectDrawNone;
621 compSetPixmap (pWin, pParentPixmap);
622 (*pScreen->DestroyPixmap) (pRedirectPixmap);
626 * Make sure the pixmap is the right size and offset. Allocate a new
627 * pixmap to change size, adjust origin to change offset, leaving the
628 * old pixmap in cw->pOldPixmap so bits can be recovered
631 compReallocPixmap (WindowPtr pWin, int draw_x, int draw_y,
632 unsigned int w, unsigned int h, int bw)
634 ScreenPtr pScreen = pWin->drawable.pScreen;
635 PixmapPtr pOld = (*pScreen->GetWindowPixmap) (pWin);
637 CompWindowPtr cw = GetCompWindow (pWin);
641 assert (cw && pWin->redirectDraw != RedirectDrawNone);
642 cw->oldx = pOld->screen_x;
643 cw->oldy = pOld->screen_y;
646 pix_w = w + (bw << 1);
647 pix_h = h + (bw << 1);
648 if (pix_w != pOld->drawable.width || pix_h != pOld->drawable.height)
650 pNew = compNewPixmap (pWin, pix_x, pix_y, pix_w, pix_h);
653 cw->pOldPixmap = pOld;
654 compSetPixmap (pWin, pNew);
661 pNew->screen_x = pix_x;
662 pNew->screen_y = pix_y;