2
* Copyright (c) 2006, Oracle and/or its affiliates. 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
compScreenUpdate(ScreenPtr pScreen)
53
compCheckTree(pScreen);
54
compPaintChildrenToWindow(pScreen->root);
58
compBlockHandler(ScreenPtr pScreen, void *pTimeout, void *pReadmask)
60
CompScreenPtr cs = GetCompScreen(pScreen);
62
pScreen->BlockHandler = cs->BlockHandler;
63
compScreenUpdate(pScreen);
64
(*pScreen->BlockHandler) (pScreen, pTimeout, pReadmask);
66
/* Next damage will restore the block handler */
67
cs->BlockHandler = NULL;
71
compReportDamage(DamagePtr pDamage, RegionPtr pRegion, void *closure)
73
WindowPtr pWin = (WindowPtr) closure;
74
ScreenPtr pScreen = pWin->drawable.pScreen;
75
CompScreenPtr cs = GetCompScreen(pScreen);
76
CompWindowPtr cw = GetCompWindow(pWin);
78
if (!cs->BlockHandler) {
79
cs->BlockHandler = pScreen->BlockHandler;
80
pScreen->BlockHandler = compBlockHandler;
84
/* Mark the ancestors */
87
if (pWin->damagedDescendants)
89
pWin->damagedDescendants = TRUE;
95
compDestroyDamage(DamagePtr pDamage, void *closure)
97
WindowPtr pWin = (WindowPtr) closure;
98
CompWindowPtr cw = GetCompWindow(pWin);
104
compMarkWindows(WindowPtr pWin, WindowPtr *ppLayerWin)
106
ScreenPtr pScreen = pWin->drawable.pScreen;
107
WindowPtr pLayerWin = pWin;
112
(*pScreen->MarkOverlappedWindows) (pWin, pWin, &pLayerWin);
113
(*pScreen->MarkWindow) (pLayerWin->parent);
115
*ppLayerWin = pLayerWin;
121
compHandleMarkedWindows(WindowPtr pWin, WindowPtr pLayerWin)
123
ScreenPtr pScreen = pWin->drawable.pScreen;
125
(*pScreen->ValidateTree) (pLayerWin->parent, pLayerWin, VTOther);
126
(*pScreen->HandleExposures) (pLayerWin->parent);
127
if (pScreen->PostValidateTree)
128
(*pScreen->PostValidateTree) (pLayerWin->parent, pLayerWin, VTOther);
132
* Redirect one window for one client
135
compRedirectWindow(ClientPtr pClient, WindowPtr pWin, int update)
137
CompWindowPtr cw = GetCompWindow(pWin);
138
CompClientWindowPtr ccw;
139
CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen);
141
Bool anyMarked = FALSE;
143
if (pWin == cs->pOverlayWin) {
151
* Only one Manual update is allowed
153
if (cw && update == CompositeRedirectManual)
154
for (ccw = cw->clients; ccw; ccw = ccw->next)
155
if (ccw->update == CompositeRedirectManual)
159
* Allocate per-client per-window structure
160
* The client *could* allocate multiple, but while supported,
161
* it is not expected to be common
163
ccw = malloc(sizeof(CompClientWindowRec));
166
ccw->id = FakeClientID(pClient->index);
167
ccw->update = update;
169
* Now make sure there's a per-window structure to hang this from
172
cw = malloc(sizeof(CompWindowRec));
177
cw->damage = DamageCreate(compReportDamage,
179
DamageReportNonEmpty,
180
FALSE, pWin->drawable.pScreen, pWin);
187
anyMarked = compMarkWindows(pWin, &pLayerWin);
189
RegionNull(&cw->borderClip);
190
cw->update = CompositeRedirectAutomatic;
192
cw->oldx = COMP_ORIGIN_INVALID;
193
cw->oldy = COMP_ORIGIN_INVALID;
194
cw->damageRegistered = FALSE;
196
cw->pOldPixmap = NullPixmap;
197
dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, cw);
199
ccw->next = cw->clients;
201
if (!AddResource(ccw->id, CompositeClientWindowType, pWin))
203
if (ccw->update == CompositeRedirectManual) {
205
anyMarked = compMarkWindows(pWin, &pLayerWin);
207
if (cw->damageRegistered) {
208
DamageUnregister(cw->damage);
209
cw->damageRegistered = FALSE;
211
cw->update = CompositeRedirectManual;
213
else if (cw->update == CompositeRedirectAutomatic && !cw->damageRegistered) {
215
anyMarked = compMarkWindows(pWin, &pLayerWin);
218
if (!compCheckRedirect(pWin)) {
219
FreeResource(ccw->id, RT_NONE);
224
compHandleMarkedWindows(pWin, pLayerWin);
230
compRestoreWindow(WindowPtr pWin, PixmapPtr pPixmap)
232
ScreenPtr pScreen = pWin->drawable.pScreen;
233
WindowPtr pParent = pWin->parent;
235
if (pParent->drawable.depth == pWin->drawable.depth) {
236
GCPtr pGC = GetScratchGC(pWin->drawable.depth, pScreen);
237
int bw = (int) pWin->borderWidth;
240
int w = pWin->drawable.width;
241
int h = pWin->drawable.height;
246
val.val = IncludeInferiors;
247
ChangeGC(NullClient, pGC, GCSubwindowMode, &val);
248
ValidateGC(&pWin->drawable, pGC);
249
(*pGC->ops->CopyArea) (&pPixmap->drawable,
250
&pWin->drawable, pGC, x, y, w, h, 0, 0);
257
* Free one of the per-client per-window resources, clearing
258
* redirect and the per-window pointer as appropriate
261
compFreeClientWindow(WindowPtr pWin, XID id)
263
ScreenPtr pScreen = pWin->drawable.pScreen;
264
CompWindowPtr cw = GetCompWindow(pWin);
265
CompClientWindowPtr ccw, *prev;
266
Bool anyMarked = FALSE;
268
PixmapPtr pPixmap = NULL;
272
for (prev = &cw->clients; (ccw = *prev); prev = &ccw->next) {
275
if (ccw->update == CompositeRedirectManual)
276
cw->update = CompositeRedirectAutomatic;
282
anyMarked = compMarkWindows(pWin, &pLayerWin);
284
if (pWin->redirectDraw != RedirectDrawNone) {
285
pPixmap = (*pScreen->GetWindowPixmap) (pWin);
286
compSetParentPixmap(pWin);
290
DamageDestroy(cw->damage);
292
RegionUninit(&cw->borderClip);
294
dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, NULL);
297
else if (cw->update == CompositeRedirectAutomatic &&
298
!cw->damageRegistered && pWin->redirectDraw != RedirectDrawNone) {
299
anyMarked = compMarkWindows(pWin, &pLayerWin);
301
DamageRegister(&pWin->drawable, cw->damage);
302
cw->damageRegistered = TRUE;
303
pWin->redirectDraw = RedirectDrawAutomatic;
304
DamageDamageRegion(&pWin->drawable, &pWin->borderSize);
308
compHandleMarkedWindows(pWin, pLayerWin);
311
compRestoreWindow(pWin, pPixmap);
312
(*pScreen->DestroyPixmap) (pPixmap);
317
* This is easy, just free the appropriate resource.
321
compUnredirectWindow(ClientPtr pClient, WindowPtr pWin, int update)
323
CompWindowPtr cw = GetCompWindow(pWin);
324
CompClientWindowPtr ccw;
329
for (ccw = cw->clients; ccw; ccw = ccw->next)
330
if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index) {
331
FreeResource(ccw->id, RT_NONE);
338
* Redirect all subwindows for one client
342
compRedirectSubwindows(ClientPtr pClient, WindowPtr pWin, int update)
344
CompSubwindowsPtr csw = GetCompSubwindows(pWin);
345
CompClientWindowPtr ccw;
349
* Only one Manual update is allowed
351
if (csw && update == CompositeRedirectManual)
352
for (ccw = csw->clients; ccw; ccw = ccw->next)
353
if (ccw->update == CompositeRedirectManual)
356
* Allocate per-client per-window structure
357
* The client *could* allocate multiple, but while supported,
358
* it is not expected to be common
360
ccw = malloc(sizeof(CompClientWindowRec));
363
ccw->id = FakeClientID(pClient->index);
364
ccw->update = update;
366
* Now make sure there's a per-window structure to hang this from
369
csw = malloc(sizeof(CompSubwindowsRec));
374
csw->update = CompositeRedirectAutomatic;
376
dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, csw);
379
* Redirect all existing windows
381
for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib) {
382
int ret = compRedirectWindow(pClient, pChild, update);
384
if (ret != Success) {
385
for (pChild = pChild->nextSib; pChild; pChild = pChild->nextSib)
386
(void) compUnredirectWindow(pClient, pChild, update);
389
dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, 0);
396
* Hook into subwindows list
398
ccw->next = csw->clients;
400
if (!AddResource(ccw->id, CompositeClientSubwindowsType, pWin))
402
if (ccw->update == CompositeRedirectManual) {
403
csw->update = CompositeRedirectManual;
405
* tell damage extension that damage events for this client are
408
DamageExtSetCritical(pClient, TRUE);
409
pWin->inhibitBGPaint = TRUE;
415
* Free one of the per-client per-subwindows resources,
416
* which frees one redirect per subwindow
419
compFreeClientSubwindows(WindowPtr pWin, XID id)
421
CompSubwindowsPtr csw = GetCompSubwindows(pWin);
422
CompClientWindowPtr ccw, *prev;
427
for (prev = &csw->clients; (ccw = *prev); prev = &ccw->next) {
429
ClientPtr pClient = clients[CLIENT_ID(id)];
432
if (ccw->update == CompositeRedirectManual) {
434
* tell damage extension that damage events for this client are
437
DamageExtSetCritical(pClient, FALSE);
438
csw->update = CompositeRedirectAutomatic;
439
pWin->inhibitBGPaint = FALSE;
441
(*pWin->drawable.pScreen->ClearToBackground) (pWin, 0, 0, 0,
446
* Unredirect all existing subwindows
448
for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib)
449
(void) compUnredirectWindow(pClient, pChild, ccw->update);
457
* Check if all of the per-client records are gone
460
dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, NULL);
466
* This is easy, just free the appropriate resource.
470
compUnredirectSubwindows(ClientPtr pClient, WindowPtr pWin, int update)
472
CompSubwindowsPtr csw = GetCompSubwindows(pWin);
473
CompClientWindowPtr ccw;
477
for (ccw = csw->clients; ccw; ccw = ccw->next)
478
if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index) {
479
FreeResource(ccw->id, RT_NONE);
486
* Add redirection information for one subwindow (during reparent)
490
compRedirectOneSubwindow(WindowPtr pParent, WindowPtr pWin)
492
CompSubwindowsPtr csw = GetCompSubwindows(pParent);
493
CompClientWindowPtr ccw;
497
for (ccw = csw->clients; ccw; ccw = ccw->next) {
498
int ret = compRedirectWindow(clients[CLIENT_ID(ccw->id)],
508
* Remove redirection information for one subwindow (during reparent)
512
compUnredirectOneSubwindow(WindowPtr pParent, WindowPtr pWin)
514
CompSubwindowsPtr csw = GetCompSubwindows(pParent);
515
CompClientWindowPtr ccw;
519
for (ccw = csw->clients; ccw; ccw = ccw->next) {
520
int ret = compUnredirectWindow(clients[CLIENT_ID(ccw->id)],
530
compNewPixmap(WindowPtr pWin, int x, int y, int w, int h)
532
ScreenPtr pScreen = pWin->drawable.pScreen;
533
WindowPtr pParent = pWin->parent;
536
pPixmap = (*pScreen->CreatePixmap) (pScreen, w, h, pWin->drawable.depth,
537
CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
542
pPixmap->screen_x = x;
543
pPixmap->screen_y = y;
545
if (pParent->drawable.depth == pWin->drawable.depth) {
546
GCPtr pGC = GetScratchGC(pWin->drawable.depth, pScreen);
551
val.val = IncludeInferiors;
552
ChangeGC(NullClient, pGC, GCSubwindowMode, &val);
553
ValidateGC(&pPixmap->drawable, pGC);
554
(*pGC->ops->CopyArea) (&pParent->drawable,
557
x - pParent->drawable.x,
558
y - pParent->drawable.y, w, h, 0, 0);
563
PictFormatPtr pSrcFormat = PictureWindowFormat(pParent);
564
PictFormatPtr pDstFormat = PictureWindowFormat(pWin);
565
XID inferiors = IncludeInferiors;
568
PicturePtr pSrcPicture = CreatePicture(None,
573
serverClient, &error);
575
PicturePtr pDstPicture = CreatePicture(None,
579
serverClient, &error);
581
if (pSrcPicture && pDstPicture) {
582
CompositePicture(PictOpSrc,
586
x - pParent->drawable.x,
587
y - pParent->drawable.y, 0, 0, 0, 0, w, h);
590
FreePicture(pSrcPicture, 0);
592
FreePicture(pDstPicture, 0);
598
compAllocPixmap(WindowPtr pWin)
600
int bw = (int) pWin->borderWidth;
601
int x = pWin->drawable.x - bw;
602
int y = pWin->drawable.y - bw;
603
int w = pWin->drawable.width + (bw << 1);
604
int h = pWin->drawable.height + (bw << 1);
605
PixmapPtr pPixmap = compNewPixmap(pWin, x, y, w, h);
606
CompWindowPtr cw = GetCompWindow(pWin);
610
if (cw->update == CompositeRedirectAutomatic)
611
pWin->redirectDraw = RedirectDrawAutomatic;
613
pWin->redirectDraw = RedirectDrawManual;
615
compSetPixmap(pWin, pPixmap);
616
cw->oldx = COMP_ORIGIN_INVALID;
617
cw->oldy = COMP_ORIGIN_INVALID;
618
cw->damageRegistered = FALSE;
619
if (cw->update == CompositeRedirectAutomatic) {
620
DamageRegister(&pWin->drawable, cw->damage);
621
cw->damageRegistered = TRUE;
624
/* Make sure our borderClip is up to date */
625
RegionUninit(&cw->borderClip);
626
RegionCopy(&cw->borderClip, &pWin->borderClip);
627
cw->borderClipX = pWin->drawable.x;
628
cw->borderClipY = pWin->drawable.y;
634
compSetParentPixmap(WindowPtr pWin)
636
ScreenPtr pScreen = pWin->drawable.pScreen;
637
PixmapPtr pParentPixmap;
638
CompWindowPtr cw = GetCompWindow(pWin);
640
if (cw->damageRegistered) {
641
DamageUnregister(cw->damage);
642
cw->damageRegistered = FALSE;
643
DamageEmpty(cw->damage);
646
* Move the parent-constrained border clip region back into
647
* the window so that ValidateTree will handle the unmap
648
* case correctly. Unmap adds the window borderClip to the
649
* parent exposed area; regions beyond the parent cause crashes
651
RegionCopy(&pWin->borderClip, &cw->borderClip);
652
pParentPixmap = (*pScreen->GetWindowPixmap) (pWin->parent);
653
pWin->redirectDraw = RedirectDrawNone;
654
compSetPixmap(pWin, pParentPixmap);
658
* Make sure the pixmap is the right size and offset. Allocate a new
659
* pixmap to change size, adjust origin to change offset, leaving the
660
* old pixmap in cw->pOldPixmap so bits can be recovered
663
compReallocPixmap(WindowPtr pWin, int draw_x, int draw_y,
664
unsigned int w, unsigned int h, int bw)
666
ScreenPtr pScreen = pWin->drawable.pScreen;
667
PixmapPtr pOld = (*pScreen->GetWindowPixmap) (pWin);
669
CompWindowPtr cw = GetCompWindow(pWin);
673
assert(cw && pWin->redirectDraw != RedirectDrawNone);
674
cw->oldx = pOld->screen_x;
675
cw->oldy = pOld->screen_y;
678
pix_w = w + (bw << 1);
679
pix_h = h + (bw << 1);
680
if (pix_w != pOld->drawable.width || pix_h != pOld->drawable.height) {
681
pNew = compNewPixmap(pWin, pix_x, pix_y, pix_w, pix_h);
684
cw->pOldPixmap = pOld;
685
compSetPixmap(pWin, pNew);
691
pNew->screen_x = pix_x;
692
pNew->screen_y = pix_y;