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