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 #include "xace.h"
50 #include "protocol-versions.h"
51 #include "extinit.h"
52 
53 static CARD8 CompositeReqCode;
54 static DevPrivateKeyRec CompositeClientPrivateKeyRec;
55 
56 #define CompositeClientPrivateKey (&CompositeClientPrivateKeyRec)
57 RESTYPE CompositeClientWindowType;
58 RESTYPE CompositeClientSubwindowsType;
59 RESTYPE CompositeClientOverlayType;
60 
61 typedef struct _CompositeClient {
62     int major_version;
63     int minor_version;
64 } CompositeClientRec, *CompositeClientPtr;
65 
66 #define GetCompositeClient(pClient) ((CompositeClientPtr) \
67     dixLookupPrivate(&(pClient)->devPrivates, CompositeClientPrivateKey))
68 
69 static int
FreeCompositeClientWindow(void * value,XID ccwid)70 FreeCompositeClientWindow(void *value, XID ccwid)
71 {
72     WindowPtr pWin = value;
73 
74     compFreeClientWindow(pWin, ccwid);
75     return Success;
76 }
77 
78 static int
FreeCompositeClientSubwindows(void * value,XID ccwid)79 FreeCompositeClientSubwindows(void *value, XID ccwid)
80 {
81     WindowPtr pWin = value;
82 
83     compFreeClientSubwindows(pWin, ccwid);
84     return Success;
85 }
86 
87 static int
FreeCompositeClientOverlay(void * value,XID ccwid)88 FreeCompositeClientOverlay(void *value, XID ccwid)
89 {
90     CompOverlayClientPtr pOc = (CompOverlayClientPtr) value;
91 
92     compFreeOverlayClient(pOc);
93     return Success;
94 }
95 
96 static int
ProcCompositeQueryVersion(ClientPtr client)97 ProcCompositeQueryVersion(ClientPtr client)
98 {
99     CompositeClientPtr pCompositeClient = GetCompositeClient(client);
100     xCompositeQueryVersionReply rep = {
101         .type = X_Reply,
102         .sequenceNumber = client->sequence,
103         .length = 0
104     };
105 
106     REQUEST(xCompositeQueryVersionReq);
107 
108     REQUEST_SIZE_MATCH(xCompositeQueryVersionReq);
109     if (stuff->majorVersion < SERVER_COMPOSITE_MAJOR_VERSION) {
110         rep.majorVersion = stuff->majorVersion;
111         rep.minorVersion = stuff->minorVersion;
112     }
113     else {
114         rep.majorVersion = SERVER_COMPOSITE_MAJOR_VERSION;
115         rep.minorVersion = SERVER_COMPOSITE_MINOR_VERSION;
116     }
117     pCompositeClient->major_version = rep.majorVersion;
118     pCompositeClient->minor_version = rep.minorVersion;
119     if (client->swapped) {
120         swaps(&rep.sequenceNumber);
121         swapl(&rep.length);
122         swapl(&rep.majorVersion);
123         swapl(&rep.minorVersion);
124     }
125     WriteToClient(client, sizeof(xCompositeQueryVersionReply), &rep);
126     return Success;
127 }
128 
129 #define VERIFY_WINDOW(pWindow, wid, client, mode)			\
130     do {								\
131 	int err;							\
132 	err = dixLookupResourceByType((void **) &pWindow, wid,	\
133 				      RT_WINDOW, client, mode);		\
134 	if (err != Success) {						\
135 	    client->errorValue = wid;					\
136 	    return err;							\
137 	}								\
138     } while (0)
139 
140 static int
ProcCompositeRedirectWindow(ClientPtr client)141 ProcCompositeRedirectWindow(ClientPtr client)
142 {
143     WindowPtr pWin;
144 
145     REQUEST(xCompositeRedirectWindowReq);
146 
147     REQUEST_SIZE_MATCH(xCompositeRedirectWindowReq);
148     VERIFY_WINDOW(pWin, stuff->window, client,
149                   DixSetAttrAccess | DixManageAccess | DixBlendAccess);
150 
151     return compRedirectWindow(client, pWin, stuff->update);
152 }
153 
154 static int
ProcCompositeRedirectSubwindows(ClientPtr client)155 ProcCompositeRedirectSubwindows(ClientPtr client)
156 {
157     WindowPtr pWin;
158 
159     REQUEST(xCompositeRedirectSubwindowsReq);
160 
161     REQUEST_SIZE_MATCH(xCompositeRedirectSubwindowsReq);
162     VERIFY_WINDOW(pWin, stuff->window, client,
163                   DixSetAttrAccess | DixManageAccess | DixBlendAccess);
164 
165     return compRedirectSubwindows(client, pWin, stuff->update);
166 }
167 
168 static int
ProcCompositeUnredirectWindow(ClientPtr client)169 ProcCompositeUnredirectWindow(ClientPtr client)
170 {
171     WindowPtr pWin;
172 
173     REQUEST(xCompositeUnredirectWindowReq);
174 
175     REQUEST_SIZE_MATCH(xCompositeUnredirectWindowReq);
176     VERIFY_WINDOW(pWin, stuff->window, client,
177                   DixSetAttrAccess | DixManageAccess | DixBlendAccess);
178 
179     return compUnredirectWindow(client, pWin, stuff->update);
180 }
181 
182 static int
ProcCompositeUnredirectSubwindows(ClientPtr client)183 ProcCompositeUnredirectSubwindows(ClientPtr client)
184 {
185     WindowPtr pWin;
186 
187     REQUEST(xCompositeUnredirectSubwindowsReq);
188 
189     REQUEST_SIZE_MATCH(xCompositeUnredirectSubwindowsReq);
190     VERIFY_WINDOW(pWin, stuff->window, client,
191                   DixSetAttrAccess | DixManageAccess | DixBlendAccess);
192 
193     return compUnredirectSubwindows(client, pWin, stuff->update);
194 }
195 
196 static int
ProcCompositeCreateRegionFromBorderClip(ClientPtr client)197 ProcCompositeCreateRegionFromBorderClip(ClientPtr client)
198 {
199     WindowPtr pWin;
200     CompWindowPtr cw;
201     RegionPtr pBorderClip, pRegion;
202 
203     REQUEST(xCompositeCreateRegionFromBorderClipReq);
204 
205     REQUEST_SIZE_MATCH(xCompositeCreateRegionFromBorderClipReq);
206     VERIFY_WINDOW(pWin, stuff->window, client, DixGetAttrAccess);
207     LEGAL_NEW_RESOURCE(stuff->region, client);
208 
209     cw = GetCompWindow(pWin);
210     if (cw)
211         pBorderClip = &cw->borderClip;
212     else
213         pBorderClip = &pWin->borderClip;
214     pRegion = XFixesRegionCopy(pBorderClip);
215     if (!pRegion)
216         return BadAlloc;
217     RegionTranslate(pRegion, -pWin->drawable.x, -pWin->drawable.y);
218 
219     if (!AddResource(stuff->region, RegionResType, (void *) pRegion))
220         return BadAlloc;
221 
222     return Success;
223 }
224 
225 static int
ProcCompositeNameWindowPixmap(ClientPtr client)226 ProcCompositeNameWindowPixmap(ClientPtr client)
227 {
228     WindowPtr pWin;
229     CompWindowPtr cw;
230     PixmapPtr pPixmap;
231     ScreenPtr pScreen;
232     int rc;
233 
234     REQUEST(xCompositeNameWindowPixmapReq);
235 
236     REQUEST_SIZE_MATCH(xCompositeNameWindowPixmapReq);
237     VERIFY_WINDOW(pWin, stuff->window, client, DixGetAttrAccess);
238 
239     pScreen = pWin->drawable.pScreen;
240 
241     if (!pWin->viewable)
242         return BadMatch;
243 
244     LEGAL_NEW_RESOURCE(stuff->pixmap, client);
245 
246     cw = GetCompWindow(pWin);
247     if (!cw)
248         return BadMatch;
249 
250     pPixmap = (*pScreen->GetWindowPixmap) (pWin);
251     if (!pPixmap)
252         return BadMatch;
253 
254     /* security creation/labeling check */
255     rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pixmap, RT_PIXMAP,
256                   pPixmap, RT_WINDOW, pWin, DixCreateAccess);
257     if (rc != Success)
258         return rc;
259 
260     ++pPixmap->refcnt;
261 
262     if (!AddResource(stuff->pixmap, RT_PIXMAP, (void *) pPixmap))
263         return BadAlloc;
264 
265     if (pScreen->NameWindowPixmap) {
266         rc = pScreen->NameWindowPixmap(pWin, pPixmap, stuff->pixmap);
267         if (rc != Success) {
268             FreeResource(stuff->pixmap, RT_NONE);
269             return rc;
270         }
271     }
272 
273     return Success;
274 }
275 
276 static int
ProcCompositeGetOverlayWindow(ClientPtr client)277 ProcCompositeGetOverlayWindow(ClientPtr client)
278 {
279     REQUEST(xCompositeGetOverlayWindowReq);
280     xCompositeGetOverlayWindowReply rep;
281     WindowPtr pWin;
282     ScreenPtr pScreen;
283     CompScreenPtr cs;
284     CompOverlayClientPtr pOc;
285     int rc;
286 
287     REQUEST_SIZE_MATCH(xCompositeGetOverlayWindowReq);
288     VERIFY_WINDOW(pWin, stuff->window, client, DixGetAttrAccess);
289     pScreen = pWin->drawable.pScreen;
290 
291     /*
292      * Create an OverlayClient structure to mark this client's
293      * interest in the overlay window
294      */
295     pOc = compCreateOverlayClient(pScreen, client);
296     if (pOc == NULL)
297         return BadAlloc;
298 
299     /*
300      * Make sure the overlay window exists
301      */
302     cs = GetCompScreen(pScreen);
303     if (cs->pOverlayWin == NULL)
304         if (!compCreateOverlayWindow(pScreen)) {
305             FreeResource(pOc->resource, RT_NONE);
306             return BadAlloc;
307         }
308 
309     rc = XaceHook(XACE_RESOURCE_ACCESS, client, cs->pOverlayWin->drawable.id,
310                   RT_WINDOW, cs->pOverlayWin, RT_NONE, NULL, DixGetAttrAccess);
311     if (rc != Success) {
312         FreeResource(pOc->resource, RT_NONE);
313         return rc;
314     }
315 
316     rep = (xCompositeGetOverlayWindowReply) {
317         .type = X_Reply,
318         .sequenceNumber = client->sequence,
319         .length = 0,
320         .overlayWin = cs->pOverlayWin->drawable.id
321     };
322 
323     if (client->swapped) {
324         swaps(&rep.sequenceNumber);
325         swapl(&rep.length);
326         swapl(&rep.overlayWin);
327     }
328     WriteToClient(client, sz_xCompositeGetOverlayWindowReply, &rep);
329 
330     return Success;
331 }
332 
333 static int
ProcCompositeReleaseOverlayWindow(ClientPtr client)334 ProcCompositeReleaseOverlayWindow(ClientPtr client)
335 {
336     REQUEST(xCompositeReleaseOverlayWindowReq);
337     WindowPtr pWin;
338     CompOverlayClientPtr pOc;
339 
340     REQUEST_SIZE_MATCH(xCompositeReleaseOverlayWindowReq);
341     VERIFY_WINDOW(pWin, stuff->window, client, DixGetAttrAccess);
342 
343     /*
344      * Has client queried a reference to the overlay window
345      * on this screen? If not, generate an error.
346      */
347     pOc = compFindOverlayClient(pWin->drawable.pScreen, client);
348     if (pOc == NULL)
349         return BadMatch;
350 
351     /* The delete function will free the client structure */
352     FreeResource(pOc->resource, RT_NONE);
353 
354     return Success;
355 }
356 
357 static int (*ProcCompositeVector[CompositeNumberRequests]) (ClientPtr) = {
358 ProcCompositeQueryVersion,
359         ProcCompositeRedirectWindow,
360         ProcCompositeRedirectSubwindows,
361         ProcCompositeUnredirectWindow,
362         ProcCompositeUnredirectSubwindows,
363         ProcCompositeCreateRegionFromBorderClip,
364         ProcCompositeNameWindowPixmap,
365         ProcCompositeGetOverlayWindow, ProcCompositeReleaseOverlayWindow,};
366 
367 static int
ProcCompositeDispatch(ClientPtr client)368 ProcCompositeDispatch(ClientPtr client)
369 {
370     REQUEST(xReq);
371 
372     if (stuff->data < CompositeNumberRequests)
373         return (*ProcCompositeVector[stuff->data]) (client);
374     else
375         return BadRequest;
376 }
377 
378 static int _X_COLD
SProcCompositeQueryVersion(ClientPtr client)379 SProcCompositeQueryVersion(ClientPtr client)
380 {
381     REQUEST(xCompositeQueryVersionReq);
382 
383     swaps(&stuff->length);
384     REQUEST_SIZE_MATCH(xCompositeQueryVersionReq);
385     swapl(&stuff->majorVersion);
386     swapl(&stuff->minorVersion);
387     return (*ProcCompositeVector[stuff->compositeReqType]) (client);
388 }
389 
390 static int _X_COLD
SProcCompositeRedirectWindow(ClientPtr client)391 SProcCompositeRedirectWindow(ClientPtr client)
392 {
393     REQUEST(xCompositeRedirectWindowReq);
394 
395     swaps(&stuff->length);
396     REQUEST_SIZE_MATCH(xCompositeRedirectWindowReq);
397     swapl(&stuff->window);
398     return (*ProcCompositeVector[stuff->compositeReqType]) (client);
399 }
400 
401 static int _X_COLD
SProcCompositeRedirectSubwindows(ClientPtr client)402 SProcCompositeRedirectSubwindows(ClientPtr client)
403 {
404     REQUEST(xCompositeRedirectSubwindowsReq);
405 
406     swaps(&stuff->length);
407     REQUEST_SIZE_MATCH(xCompositeRedirectSubwindowsReq);
408     swapl(&stuff->window);
409     return (*ProcCompositeVector[stuff->compositeReqType]) (client);
410 }
411 
412 static int _X_COLD
SProcCompositeUnredirectWindow(ClientPtr client)413 SProcCompositeUnredirectWindow(ClientPtr client)
414 {
415     REQUEST(xCompositeUnredirectWindowReq);
416 
417     swaps(&stuff->length);
418     REQUEST_SIZE_MATCH(xCompositeUnredirectWindowReq);
419     swapl(&stuff->window);
420     return (*ProcCompositeVector[stuff->compositeReqType]) (client);
421 }
422 
423 static int _X_COLD
SProcCompositeUnredirectSubwindows(ClientPtr client)424 SProcCompositeUnredirectSubwindows(ClientPtr client)
425 {
426     REQUEST(xCompositeUnredirectSubwindowsReq);
427 
428     swaps(&stuff->length);
429     REQUEST_SIZE_MATCH(xCompositeUnredirectSubwindowsReq);
430     swapl(&stuff->window);
431     return (*ProcCompositeVector[stuff->compositeReqType]) (client);
432 }
433 
434 static int _X_COLD
SProcCompositeCreateRegionFromBorderClip(ClientPtr client)435 SProcCompositeCreateRegionFromBorderClip(ClientPtr client)
436 {
437     REQUEST(xCompositeCreateRegionFromBorderClipReq);
438 
439     swaps(&stuff->length);
440     REQUEST_SIZE_MATCH(xCompositeCreateRegionFromBorderClipReq);
441     swapl(&stuff->region);
442     swapl(&stuff->window);
443     return (*ProcCompositeVector[stuff->compositeReqType]) (client);
444 }
445 
446 static int _X_COLD
SProcCompositeNameWindowPixmap(ClientPtr client)447 SProcCompositeNameWindowPixmap(ClientPtr client)
448 {
449     REQUEST(xCompositeNameWindowPixmapReq);
450 
451     swaps(&stuff->length);
452     REQUEST_SIZE_MATCH(xCompositeNameWindowPixmapReq);
453     swapl(&stuff->window);
454     swapl(&stuff->pixmap);
455     return (*ProcCompositeVector[stuff->compositeReqType]) (client);
456 }
457 
458 static int _X_COLD
SProcCompositeGetOverlayWindow(ClientPtr client)459 SProcCompositeGetOverlayWindow(ClientPtr client)
460 {
461     REQUEST(xCompositeGetOverlayWindowReq);
462 
463     swaps(&stuff->length);
464     REQUEST_SIZE_MATCH(xCompositeGetOverlayWindowReq);
465     swapl(&stuff->window);
466     return (*ProcCompositeVector[stuff->compositeReqType]) (client);
467 }
468 
469 static int _X_COLD
SProcCompositeReleaseOverlayWindow(ClientPtr client)470 SProcCompositeReleaseOverlayWindow(ClientPtr client)
471 {
472     REQUEST(xCompositeReleaseOverlayWindowReq);
473 
474     swaps(&stuff->length);
475     REQUEST_SIZE_MATCH(xCompositeReleaseOverlayWindowReq);
476     swapl(&stuff->window);
477     return (*ProcCompositeVector[stuff->compositeReqType]) (client);
478 }
479 
480 static int
481 (*SProcCompositeVector[CompositeNumberRequests]) (ClientPtr) = {
482     SProcCompositeQueryVersion,
483     SProcCompositeRedirectWindow,
484     SProcCompositeRedirectSubwindows,
485     SProcCompositeUnredirectWindow,
486     SProcCompositeUnredirectSubwindows,
487     SProcCompositeCreateRegionFromBorderClip,
488     SProcCompositeNameWindowPixmap,
489     SProcCompositeGetOverlayWindow,
490     SProcCompositeReleaseOverlayWindow,
491 };
492 
493 static int _X_COLD
SProcCompositeDispatch(ClientPtr client)494 SProcCompositeDispatch(ClientPtr client)
495 {
496     REQUEST(xReq);
497 
498     if (stuff->data < CompositeNumberRequests)
499         return (*SProcCompositeVector[stuff->data]) (client);
500     else
501         return BadRequest;
502 }
503 
504 /** @see GetDefaultBytes */
505 static SizeType coreGetWindowBytes;
506 
507 static void
GetCompositeWindowBytes(void * value,XID id,ResourceSizePtr size)508 GetCompositeWindowBytes(void *value, XID id, ResourceSizePtr size)
509 {
510     WindowPtr window = value;
511 
512     /* call down */
513     coreGetWindowBytes(value, id, size);
514 
515     /* account for redirection */
516     if (window->redirectDraw != RedirectDrawNone)
517     {
518         SizeType pixmapSizeFunc = GetResourceTypeSizeFunc(RT_PIXMAP);
519         ResourceSizeRec pixmapSize = { 0, 0 };
520         ScreenPtr screen = window->drawable.pScreen;
521         PixmapPtr pixmap = screen->GetWindowPixmap(window);
522         pixmapSizeFunc(pixmap, pixmap->drawable.id, &pixmapSize);
523         size->pixmapRefSize += pixmapSize.pixmapRefSize;
524     }
525 }
526 
527 void
CompositeExtensionInit(void)528 CompositeExtensionInit(void)
529 {
530     ExtensionEntry *extEntry;
531     int s;
532 
533     /* Assume initialization is going to fail */
534     noCompositeExtension = TRUE;
535 
536     for (s = 0; s < screenInfo.numScreens; s++) {
537         ScreenPtr pScreen = screenInfo.screens[s];
538         VisualPtr vis;
539 
540         /* Composite on 8bpp pseudocolor root windows appears to fail, so
541          * just disable it on anything pseudocolor for safety.
542          */
543         for (vis = pScreen->visuals; vis->vid != pScreen->rootVisual; vis++);
544         if ((vis->class | DynamicClass) == PseudoColor)
545             return;
546 
547         /* Ensure that Render is initialized, which is required for automatic
548          * compositing.
549          */
550         if (GetPictureScreenIfSet(pScreen) == NULL)
551             return;
552     }
553 
554     CompositeClientWindowType = CreateNewResourceType
555         (FreeCompositeClientWindow, "CompositeClientWindow");
556     if (!CompositeClientWindowType)
557         return;
558 
559     coreGetWindowBytes = GetResourceTypeSizeFunc(RT_WINDOW);
560     SetResourceTypeSizeFunc(RT_WINDOW, GetCompositeWindowBytes);
561 
562     CompositeClientSubwindowsType = CreateNewResourceType
563         (FreeCompositeClientSubwindows, "CompositeClientSubwindows");
564     if (!CompositeClientSubwindowsType)
565         return;
566 
567     CompositeClientOverlayType = CreateNewResourceType
568         (FreeCompositeClientOverlay, "CompositeClientOverlay");
569     if (!CompositeClientOverlayType)
570         return;
571 
572     if (!dixRegisterPrivateKey(&CompositeClientPrivateKeyRec, PRIVATE_CLIENT,
573                                sizeof(CompositeClientRec)))
574         return;
575 
576     for (s = 0; s < screenInfo.numScreens; s++)
577         if (!compScreenInit(screenInfo.screens[s]))
578             return;
579 
580     extEntry = AddExtension(COMPOSITE_NAME, 0, 0,
581                             ProcCompositeDispatch, SProcCompositeDispatch,
582                             NULL, StandardMinorOpcode);
583     if (!extEntry)
584         return;
585     CompositeReqCode = (CARD8) extEntry->base;
586 
587     /* Initialization succeeded */
588     noCompositeExtension = FALSE;
589 }
590 
591 #ifdef PANORAMIX
592 #include "panoramiXsrv.h"
593 
594 int (*PanoramiXSaveCompositeVector[CompositeNumberRequests]) (ClientPtr);
595 
596 static int
PanoramiXCompositeRedirectWindow(ClientPtr client)597 PanoramiXCompositeRedirectWindow(ClientPtr client)
598 {
599     PanoramiXRes *win;
600     int rc = 0, j;
601 
602     REQUEST(xCompositeRedirectWindowReq);
603 
604     REQUEST_SIZE_MATCH(xCompositeRedirectWindowReq);
605 
606     if ((rc = dixLookupResourceByType((void **) &win, stuff->window, XRT_WINDOW,
607                                       client, DixUnknownAccess))) {
608         client->errorValue = stuff->window;
609         return rc;
610     }
611 
612     FOR_NSCREENS_FORWARD(j) {
613         stuff->window = win->info[j].id;
614         rc = (*PanoramiXSaveCompositeVector[stuff->compositeReqType]) (client);
615         if (rc != Success)
616             break;
617     }
618 
619     return rc;
620 }
621 
622 static int
PanoramiXCompositeRedirectSubwindows(ClientPtr client)623 PanoramiXCompositeRedirectSubwindows(ClientPtr client)
624 {
625     PanoramiXRes *win;
626     int rc = 0, j;
627 
628     REQUEST(xCompositeRedirectSubwindowsReq);
629 
630     REQUEST_SIZE_MATCH(xCompositeRedirectSubwindowsReq);
631 
632     if ((rc = dixLookupResourceByType((void **) &win, stuff->window, XRT_WINDOW,
633                                       client, DixUnknownAccess))) {
634         client->errorValue = stuff->window;
635         return rc;
636     }
637 
638     FOR_NSCREENS_FORWARD(j) {
639         stuff->window = win->info[j].id;
640         rc = (*PanoramiXSaveCompositeVector[stuff->compositeReqType]) (client);
641         if (rc != Success)
642             break;
643     }
644 
645     return rc;
646 }
647 
648 static int
PanoramiXCompositeUnredirectWindow(ClientPtr client)649 PanoramiXCompositeUnredirectWindow(ClientPtr client)
650 {
651     PanoramiXRes *win;
652     int rc = 0, j;
653 
654     REQUEST(xCompositeUnredirectWindowReq);
655 
656     REQUEST_SIZE_MATCH(xCompositeUnredirectWindowReq);
657 
658     if ((rc = dixLookupResourceByType((void **) &win, stuff->window, XRT_WINDOW,
659                                       client, DixUnknownAccess))) {
660         client->errorValue = stuff->window;
661         return rc;
662     }
663 
664     FOR_NSCREENS_FORWARD(j) {
665         stuff->window = win->info[j].id;
666         rc = (*PanoramiXSaveCompositeVector[stuff->compositeReqType]) (client);
667         if (rc != Success)
668             break;
669     }
670 
671     return rc;
672 }
673 
674 static int
PanoramiXCompositeUnredirectSubwindows(ClientPtr client)675 PanoramiXCompositeUnredirectSubwindows(ClientPtr client)
676 {
677     PanoramiXRes *win;
678     int rc = 0, j;
679 
680     REQUEST(xCompositeUnredirectSubwindowsReq);
681 
682     REQUEST_SIZE_MATCH(xCompositeUnredirectSubwindowsReq);
683 
684     if ((rc = dixLookupResourceByType((void **) &win, stuff->window, XRT_WINDOW,
685                                       client, DixUnknownAccess))) {
686         client->errorValue = stuff->window;
687         return rc;
688     }
689 
690     FOR_NSCREENS_FORWARD(j) {
691         stuff->window = win->info[j].id;
692         rc = (*PanoramiXSaveCompositeVector[stuff->compositeReqType]) (client);
693         if (rc != Success)
694             break;
695     }
696 
697     return rc;
698 }
699 
700 static int
PanoramiXCompositeNameWindowPixmap(ClientPtr client)701 PanoramiXCompositeNameWindowPixmap(ClientPtr client)
702 {
703     WindowPtr pWin;
704     CompWindowPtr cw;
705     PixmapPtr pPixmap;
706     int rc;
707     PanoramiXRes *win, *newPix;
708     int i;
709 
710     REQUEST(xCompositeNameWindowPixmapReq);
711 
712     REQUEST_SIZE_MATCH(xCompositeNameWindowPixmapReq);
713 
714     if ((rc = dixLookupResourceByType((void **) &win, stuff->window, XRT_WINDOW,
715                                       client, DixUnknownAccess))) {
716         client->errorValue = stuff->window;
717         return rc;
718     }
719 
720     LEGAL_NEW_RESOURCE(stuff->pixmap, client);
721 
722     if (!(newPix = malloc(sizeof(PanoramiXRes))))
723         return BadAlloc;
724 
725     newPix->type = XRT_PIXMAP;
726     newPix->u.pix.shared = FALSE;
727     panoramix_setup_ids(newPix, client, stuff->pixmap);
728 
729     FOR_NSCREENS(i) {
730         rc = dixLookupResourceByType((void **) &pWin, win->info[i].id,
731                                      RT_WINDOW, client, DixGetAttrAccess);
732         if (rc != Success) {
733             client->errorValue = stuff->window;
734             free(newPix);
735             return rc;
736         }
737 
738         if (!pWin->viewable) {
739             free(newPix);
740             return BadMatch;
741         }
742 
743         cw = GetCompWindow(pWin);
744         if (!cw) {
745             free(newPix);
746             return BadMatch;
747         }
748 
749         pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin);
750         if (!pPixmap) {
751             free(newPix);
752             return BadMatch;
753         }
754 
755         if (!AddResource(newPix->info[i].id, RT_PIXMAP, (void *) pPixmap))
756             return BadAlloc;
757 
758         ++pPixmap->refcnt;
759     }
760 
761     if (!AddResource(stuff->pixmap, XRT_PIXMAP, (void *) newPix))
762         return BadAlloc;
763 
764     return Success;
765 }
766 
767 static int
PanoramiXCompositeGetOverlayWindow(ClientPtr client)768 PanoramiXCompositeGetOverlayWindow(ClientPtr client)
769 {
770     REQUEST(xCompositeGetOverlayWindowReq);
771     xCompositeGetOverlayWindowReply rep;
772     WindowPtr pWin;
773     ScreenPtr pScreen;
774     CompScreenPtr cs;
775     CompOverlayClientPtr pOc;
776     int rc;
777     PanoramiXRes *win, *overlayWin = NULL;
778     int i;
779 
780     REQUEST_SIZE_MATCH(xCompositeGetOverlayWindowReq);
781 
782     if ((rc = dixLookupResourceByType((void **) &win, stuff->window, XRT_WINDOW,
783                                       client, DixUnknownAccess))) {
784         client->errorValue = stuff->window;
785         return rc;
786     }
787 
788     cs = GetCompScreen(screenInfo.screens[0]);
789     if (!cs->pOverlayWin) {
790         if (!(overlayWin = malloc(sizeof(PanoramiXRes))))
791             return BadAlloc;
792 
793         overlayWin->type = XRT_WINDOW;
794         overlayWin->u.win.root = FALSE;
795     }
796 
797     FOR_NSCREENS_BACKWARD(i) {
798         rc = dixLookupResourceByType((void **) &pWin, win->info[i].id,
799                                      RT_WINDOW, client, DixGetAttrAccess);
800         if (rc != Success) {
801             client->errorValue = stuff->window;
802             free(overlayWin);
803             return rc;
804         }
805         pScreen = pWin->drawable.pScreen;
806 
807         /*
808          * Create an OverlayClient structure to mark this client's
809          * interest in the overlay window
810          */
811         pOc = compCreateOverlayClient(pScreen, client);
812         if (pOc == NULL) {
813             free(overlayWin);
814             return BadAlloc;
815         }
816 
817         /*
818          * Make sure the overlay window exists
819          */
820         cs = GetCompScreen(pScreen);
821         if (cs->pOverlayWin == NULL)
822             if (!compCreateOverlayWindow(pScreen)) {
823                 FreeResource(pOc->resource, RT_NONE);
824                 free(overlayWin);
825                 return BadAlloc;
826             }
827 
828         rc = XaceHook(XACE_RESOURCE_ACCESS, client,
829                       cs->pOverlayWin->drawable.id,
830                       RT_WINDOW, cs->pOverlayWin, RT_NONE, NULL,
831                       DixGetAttrAccess);
832         if (rc != Success) {
833             FreeResource(pOc->resource, RT_NONE);
834             free(overlayWin);
835             return rc;
836         }
837     }
838 
839     if (overlayWin) {
840         FOR_NSCREENS(i) {
841             cs = GetCompScreen(screenInfo.screens[i]);
842             overlayWin->info[i].id = cs->pOverlayWin->drawable.id;
843         }
844 
845         AddResource(overlayWin->info[0].id, XRT_WINDOW, overlayWin);
846     }
847 
848     cs = GetCompScreen(screenInfo.screens[0]);
849 
850     rep = (xCompositeGetOverlayWindowReply) {
851         .type = X_Reply,
852         .sequenceNumber = client->sequence,
853         .length = 0,
854         .overlayWin = cs->pOverlayWin->drawable.id
855     };
856 
857     if (client->swapped) {
858         swaps(&rep.sequenceNumber);
859         swapl(&rep.length);
860         swapl(&rep.overlayWin);
861     }
862     WriteToClient(client, sz_xCompositeGetOverlayWindowReply, &rep);
863 
864     return Success;
865 }
866 
867 static int
PanoramiXCompositeReleaseOverlayWindow(ClientPtr client)868 PanoramiXCompositeReleaseOverlayWindow(ClientPtr client)
869 {
870     REQUEST(xCompositeReleaseOverlayWindowReq);
871     WindowPtr pWin;
872     CompOverlayClientPtr pOc;
873     PanoramiXRes *win;
874     int i, rc;
875 
876     REQUEST_SIZE_MATCH(xCompositeReleaseOverlayWindowReq);
877 
878     if ((rc = dixLookupResourceByType((void **) &win, stuff->window, XRT_WINDOW,
879                                       client, DixUnknownAccess))) {
880         client->errorValue = stuff->window;
881         return rc;
882     }
883 
884     FOR_NSCREENS_BACKWARD(i) {
885         if ((rc = dixLookupResourceByType((void **) &pWin, win->info[i].id,
886                                           XRT_WINDOW, client,
887                                           DixUnknownAccess))) {
888             client->errorValue = stuff->window;
889             return rc;
890         }
891 
892         /*
893          * Has client queried a reference to the overlay window
894          * on this screen? If not, generate an error.
895          */
896         pOc = compFindOverlayClient(pWin->drawable.pScreen, client);
897         if (pOc == NULL)
898             return BadMatch;
899 
900         /* The delete function will free the client structure */
901         FreeResource(pOc->resource, RT_NONE);
902     }
903 
904     return Success;
905 }
906 
907 void
PanoramiXCompositeInit(void)908 PanoramiXCompositeInit(void)
909 {
910     int i;
911 
912     for (i = 0; i < CompositeNumberRequests; i++)
913         PanoramiXSaveCompositeVector[i] = ProcCompositeVector[i];
914     /*
915      * Stuff in Xinerama aware request processing hooks
916      */
917     ProcCompositeVector[X_CompositeRedirectWindow] =
918         PanoramiXCompositeRedirectWindow;
919     ProcCompositeVector[X_CompositeRedirectSubwindows] =
920         PanoramiXCompositeRedirectSubwindows;
921     ProcCompositeVector[X_CompositeUnredirectWindow] =
922         PanoramiXCompositeUnredirectWindow;
923     ProcCompositeVector[X_CompositeUnredirectSubwindows] =
924         PanoramiXCompositeUnredirectSubwindows;
925     ProcCompositeVector[X_CompositeNameWindowPixmap] =
926         PanoramiXCompositeNameWindowPixmap;
927     ProcCompositeVector[X_CompositeGetOverlayWindow] =
928         PanoramiXCompositeGetOverlayWindow;
929     ProcCompositeVector[X_CompositeReleaseOverlayWindow] =
930         PanoramiXCompositeReleaseOverlayWindow;
931 }
932 
933 void
PanoramiXCompositeReset(void)934 PanoramiXCompositeReset(void)
935 {
936     int i;
937 
938     for (i = 0; i < CompositeNumberRequests; i++)
939         ProcCompositeVector[i] = PanoramiXSaveCompositeVector[i];
940 }
941 
942 #endif
943