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
53static CARD8 CompositeReqCode;
54static DevPrivateKeyRec CompositeClientPrivateKeyRec;
55
56#define CompositeClientPrivateKey (&CompositeClientPrivateKeyRec)
57RESTYPE CompositeClientWindowType;
58RESTYPE CompositeClientSubwindowsType;
59RESTYPE CompositeClientOverlayType;
60
61typedef 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
69static int
70FreeCompositeClientWindow(void *value, XID ccwid)
71{
72    WindowPtr pWin = value;
73
74    compFreeClientWindow(pWin, ccwid);
75    return Success;
76}
77
78static int
79FreeCompositeClientSubwindows(void *value, XID ccwid)
80{
81    WindowPtr pWin = value;
82
83    compFreeClientSubwindows(pWin, ccwid);
84    return Success;
85}
86
87static int
88FreeCompositeClientOverlay(void *value, XID ccwid)
89{
90    CompOverlayClientPtr pOc = (CompOverlayClientPtr) value;
91
92    compFreeOverlayClient(pOc);
93    return Success;
94}
95
96static int
97ProcCompositeQueryVersion(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
140static int
141ProcCompositeRedirectWindow(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
154static int
155ProcCompositeRedirectSubwindows(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
168static int
169ProcCompositeUnredirectWindow(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
182static int
183ProcCompositeUnredirectSubwindows(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
196static int
197ProcCompositeCreateRegionFromBorderClip(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
225static int
226ProcCompositeNameWindowPixmap(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
276static int
277ProcCompositeGetOverlayWindow(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
333static int
334ProcCompositeReleaseOverlayWindow(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
357static int (*ProcCompositeVector[CompositeNumberRequests]) (ClientPtr) = {
358ProcCompositeQueryVersion,
359        ProcCompositeRedirectWindow,
360        ProcCompositeRedirectSubwindows,
361        ProcCompositeUnredirectWindow,
362        ProcCompositeUnredirectSubwindows,
363        ProcCompositeCreateRegionFromBorderClip,
364        ProcCompositeNameWindowPixmap,
365        ProcCompositeGetOverlayWindow, ProcCompositeReleaseOverlayWindow,};
366
367static int
368ProcCompositeDispatch(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
378static int _X_COLD
379SProcCompositeQueryVersion(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
390static int _X_COLD
391SProcCompositeRedirectWindow(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
401static int _X_COLD
402SProcCompositeRedirectSubwindows(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
412static int _X_COLD
413SProcCompositeUnredirectWindow(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
423static int _X_COLD
424SProcCompositeUnredirectSubwindows(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
434static int _X_COLD
435SProcCompositeCreateRegionFromBorderClip(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
446static int _X_COLD
447SProcCompositeNameWindowPixmap(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
458static int _X_COLD
459SProcCompositeGetOverlayWindow(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
469static int _X_COLD
470SProcCompositeReleaseOverlayWindow(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
480static 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
493static int _X_COLD
494SProcCompositeDispatch(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 */
505static SizeType coreGetWindowBytes;
506
507static void
508GetCompositeWindowBytes(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
527void
528CompositeExtensionInit(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
594int (*PanoramiXSaveCompositeVector[CompositeNumberRequests]) (ClientPtr);
595
596static int
597PanoramiXCompositeRedirectWindow(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
622static int
623PanoramiXCompositeRedirectSubwindows(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
648static int
649PanoramiXCompositeUnredirectWindow(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
674static int
675PanoramiXCompositeUnredirectSubwindows(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
700static int
701PanoramiXCompositeNameWindowPixmap(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
767static int
768PanoramiXCompositeGetOverlayWindow(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
867static int
868PanoramiXCompositeReleaseOverlayWindow(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
907void
908PanoramiXCompositeInit(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
933void
934PanoramiXCompositeReset(void)
935{
936    int i;
937
938    for (i = 0; i < CompositeNumberRequests; i++)
939        ProcCompositeVector[i] = PanoramiXSaveCompositeVector[i];
940}
941
942#endif
943