2 * Copyright © 2006 Sun Microsystems
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Sun Microsystems not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. Sun Microsystems makes no
11 * representations about the suitability of this software for any purpose. It
12 * is provided "as is" without express or implied warranty.
14 * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
22 * Copyright © 2003 Keith Packard
24 * Permission to use, copy, modify, distribute, and sell this software and its
25 * documentation for any purpose is hereby granted without fee, provided that
26 * the above copyright notice appear in all copies and that both that
27 * copyright notice and this permission notice appear in supporting
28 * documentation, and that the name of Keith Packard not be used in
29 * advertising or publicity pertaining to distribution of the software without
30 * specific, written prior permission. Keith Packard makes no
31 * representations about the suitability of this software for any purpose. It
32 * is provided "as is" without express or implied warranty.
34 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
35 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
36 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
37 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
38 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
39 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
40 * PERFORMANCE OF THIS SOFTWARE.
43 #ifdef HAVE_DIX_CONFIG_H
44 #include <dix-config.h>
49 #define SERVER_COMPOSITE_MAJOR 0
50 #define SERVER_COMPOSITE_MINOR 4
52 static CARD8 CompositeReqCode
;
53 static int CompositeClientPrivateIndex
;
54 RESTYPE CompositeClientWindowType
;
55 RESTYPE CompositeClientSubwindowsType
;
56 static RESTYPE CompositeClientOverlayType
;
58 static void deleteCompOverlayClient (CompOverlayClientPtr pOcToDel
,
61 typedef struct _CompositeClient
{
64 } CompositeClientRec
, *CompositeClientPtr
;
66 #define GetCompositeClient(pClient) ((CompositeClientPtr) (pClient)->devPrivates[CompositeClientPrivateIndex].ptr)
69 CompositeClientCallback (CallbackListPtr
*list
,
73 NewClientInfoRec
*clientinfo
= (NewClientInfoRec
*) data
;
74 ClientPtr pClient
= clientinfo
->client
;
75 CompositeClientPtr pCompositeClient
= GetCompositeClient (pClient
);
77 pCompositeClient
->major_version
= 0;
78 pCompositeClient
->minor_version
= 0;
82 CompositeResetProc (ExtensionEntry
*extEntry
)
87 FreeCompositeClientWindow (pointer value
, XID ccwid
)
89 WindowPtr pWin
= value
;
91 compFreeClientWindow (pWin
, ccwid
);
96 FreeCompositeClientSubwindows (pointer value
, XID ccwid
)
98 WindowPtr pWin
= value
;
100 compFreeClientSubwindows (pWin
, ccwid
);
105 FreeCompositeClientOverlay (pointer value
, XID ccwid
)
107 CompOverlayClientPtr pOc
= (CompOverlayClientPtr
) value
;
108 ScreenPtr pScreen
= pOc
->pScreen
;
111 deleteCompOverlayClient(pOc
, pScreen
);
113 /* Unmap overlay window when there are no more clients using it */
114 cs
= GetCompScreen(pScreen
);
115 if (cs
->pOverlayClients
== NULL
) {
116 if (cs
->pOverlayWin
!= NULL
) {
117 UnmapWindow(cs
->pOverlayWin
, FALSE
);
125 ProcCompositeQueryVersion (ClientPtr client
)
127 CompositeClientPtr pCompositeClient
= GetCompositeClient (client
);
128 xCompositeQueryVersionReply rep
;
130 REQUEST(xCompositeQueryVersionReq
);
132 REQUEST_SIZE_MATCH(xCompositeQueryVersionReq
);
135 rep
.sequenceNumber
= client
->sequence
;
136 if (stuff
->majorVersion
< SERVER_COMPOSITE_MAJOR
) {
137 rep
.majorVersion
= stuff
->majorVersion
;
138 rep
.minorVersion
= stuff
->minorVersion
;
140 rep
.majorVersion
= SERVER_COMPOSITE_MAJOR
;
141 rep
.minorVersion
= SERVER_COMPOSITE_MINOR
;
143 pCompositeClient
->major_version
= rep
.majorVersion
;
144 pCompositeClient
->minor_version
= rep
.minorVersion
;
145 if (client
->swapped
) {
146 swaps(&rep
.sequenceNumber
, n
);
147 swapl(&rep
.length
, n
);
148 swapl(&rep
.majorVersion
, n
);
149 swapl(&rep
.minorVersion
, n
);
151 WriteToClient(client
, sizeof(xCompositeQueryVersionReply
), (char *)&rep
);
152 return(client
->noClientException
);
156 ProcCompositeRedirectWindow (ClientPtr client
)
159 REQUEST(xCompositeRedirectWindowReq
);
161 REQUEST_SIZE_MATCH(xCompositeRedirectWindowReq
);
162 pWin
= (WindowPtr
) LookupIDByType (stuff
->window
, RT_WINDOW
);
165 client
->errorValue
= stuff
->window
;
168 return compRedirectWindow (client
, pWin
, stuff
->update
);
172 ProcCompositeRedirectSubwindows (ClientPtr client
)
175 REQUEST(xCompositeRedirectSubwindowsReq
);
177 REQUEST_SIZE_MATCH(xCompositeRedirectSubwindowsReq
);
178 pWin
= (WindowPtr
) LookupIDByType (stuff
->window
, RT_WINDOW
);
181 client
->errorValue
= stuff
->window
;
184 return compRedirectSubwindows (client
, pWin
, stuff
->update
);
188 ProcCompositeUnredirectWindow (ClientPtr client
)
191 REQUEST(xCompositeUnredirectWindowReq
);
193 REQUEST_SIZE_MATCH(xCompositeUnredirectWindowReq
);
194 pWin
= (WindowPtr
) LookupIDByType (stuff
->window
, RT_WINDOW
);
197 client
->errorValue
= stuff
->window
;
200 return compUnredirectWindow (client
, pWin
, stuff
->update
);
204 ProcCompositeUnredirectSubwindows (ClientPtr client
)
207 REQUEST(xCompositeUnredirectSubwindowsReq
);
209 REQUEST_SIZE_MATCH(xCompositeUnredirectSubwindowsReq
);
210 pWin
= (WindowPtr
) LookupIDByType (stuff
->window
, RT_WINDOW
);
213 client
->errorValue
= stuff
->window
;
216 return compUnredirectSubwindows (client
, pWin
, stuff
->update
);
220 ProcCompositeCreateRegionFromBorderClip (ClientPtr client
)
224 RegionPtr pBorderClip
, pRegion
;
225 REQUEST(xCompositeCreateRegionFromBorderClipReq
);
227 REQUEST_SIZE_MATCH(xCompositeCreateRegionFromBorderClipReq
);
228 pWin
= (WindowPtr
) LookupIDByType (stuff
->window
, RT_WINDOW
);
231 client
->errorValue
= stuff
->window
;
235 LEGAL_NEW_RESOURCE (stuff
->region
, client
);
237 cw
= GetCompWindow (pWin
);
239 pBorderClip
= &cw
->borderClip
;
241 pBorderClip
= &pWin
->borderClip
;
242 pRegion
= XFixesRegionCopy (pBorderClip
);
245 REGION_TRANSLATE (pScreen
, pRegion
, -pWin
->drawable
.x
, -pWin
->drawable
.y
);
247 if (!AddResource (stuff
->region
, RegionResType
, (pointer
) pRegion
))
250 return(client
->noClientException
);
254 ProcCompositeNameWindowPixmap (ClientPtr client
)
259 REQUEST(xCompositeNameWindowPixmapReq
);
261 REQUEST_SIZE_MATCH(xCompositeNameWindowPixmapReq
);
262 pWin
= (WindowPtr
) LookupIDByType (stuff
->window
, RT_WINDOW
);
265 client
->errorValue
= stuff
->window
;
272 LEGAL_NEW_RESOURCE (stuff
->pixmap
, client
);
274 cw
= GetCompWindow (pWin
);
278 pPixmap
= (*pWin
->drawable
.pScreen
->GetWindowPixmap
) (pWin
);
284 if (!AddResource (stuff
->pixmap
, RT_PIXMAP
, (pointer
) pPixmap
))
287 return(client
->noClientException
);
292 * Routines for manipulating the per-screen overlay clients list.
293 * This list indicates which clients have called GetOverlayWindow
297 /* Return the screen's overlay client list element for the given client */
298 static CompOverlayClientPtr
299 findCompOverlayClient (ClientPtr pClient
, ScreenPtr pScreen
)
301 CompScreenPtr cs
= GetCompScreen(pScreen
);
302 CompOverlayClientPtr pOc
;
304 for (pOc
= cs
->pOverlayClients
; pOc
!= NULL
; pOc
= pOc
->pNext
) {
305 if (pOc
->pClient
== pClient
) {
314 createCompOverlayClient (ClientPtr pClient
, ScreenPtr pScreen
)
316 CompScreenPtr cs
= GetCompScreen(pScreen
);
317 CompOverlayClientPtr pOc
;
319 pOc
= (CompOverlayClientPtr
) xalloc(sizeof(CompOverlayClientRec
));
323 pOc
->pClient
= pClient
;
324 pOc
->pScreen
= pScreen
;
325 pOc
->resource
= FakeClientID(pClient
->index
);
326 pOc
->pNext
= cs
->pOverlayClients
;
327 cs
->pOverlayClients
= pOc
;
330 * Create a resource for this element so it can be deleted
331 * when the client goes away.
333 if (!AddResource (pOc
->resource
, CompositeClientOverlayType
,
343 * Delete the given overlay client list element from its screen list.
346 deleteCompOverlayClient (CompOverlayClientPtr pOcToDel
, ScreenPtr pScreen
)
348 CompScreenPtr cs
= GetCompScreen(pScreen
);
349 CompOverlayClientPtr pOc
, pNext
;
350 CompOverlayClientPtr pOcLast
= NULL
;
352 pOc
= cs
->pOverlayClients
;
353 while (pOc
!= NULL
) {
355 if (pOc
== pOcToDel
) {
357 if (pOcLast
== NULL
) {
358 cs
->pOverlayClients
= pNext
;
360 pOcLast
->pNext
= pNext
;
370 * Delete all the hide-counts list elements for this screen.
373 deleteCompOverlayClientsForScreen (ScreenPtr pScreen
)
375 CompScreenPtr cs
= GetCompScreen(pScreen
);
376 CompOverlayClientPtr pOc
, pTmp
;
378 pOc
= cs
->pOverlayClients
;
379 while (pOc
!= NULL
) {
381 FreeResource(pOc
->resource
, 0);
384 cs
->pOverlayClients
= NULL
;
388 ** If necessary, create the overlay window. And map it
389 ** Note: I found it excessively difficult to destroy this window
390 ** during compCloseScreen; DeleteWindow can't be called because
391 ** the input devices are already shut down. So we are going to
392 ** just allocate an overlay window once per screen per X server
397 createOverlayWindow (ScreenPtr pScreen
)
399 int wid
= FakeClientID(0);
401 XID overrideRedirect
= TRUE
;
404 pWin
= CreateWindow (
405 wid
, WindowTable
[pScreen
->myNum
],
406 0, 0, pScreen
->width
, pScreen
->height
, 0,
407 InputOutput
, CWOverrideRedirect
, &overrideRedirect
,
408 WindowTable
[pScreen
->myNum
]->drawable
.depth
,
409 serverClient
, pScreen
->rootVisual
, &result
);
414 if (!AddResource(wid
, RT_WINDOW
, (pointer
)pWin
)) {
415 DeleteWindow(pWin
, None
);
423 ProcCompositeGetOverlayWindow (ClientPtr client
)
425 REQUEST(xCompositeGetOverlayWindowReq
);
426 xCompositeGetOverlayWindowReply rep
;
430 CompOverlayClientPtr pOc
;
432 REQUEST_SIZE_MATCH(xCompositeGetOverlayWindowReq
);
433 pWin
= (WindowPtr
) LookupIDByType (stuff
->window
, RT_WINDOW
);
436 client
->errorValue
= stuff
->window
;
439 pScreen
= pWin
->drawable
.pScreen
;
441 cs
= GetCompScreen(pScreen
);
442 if (cs
->pOverlayWin
== NULL
) {
443 cs
->pOverlayWin
= createOverlayWindow(pScreen
);
444 if (cs
->pOverlayWin
== NULL
) {
448 MapWindow(cs
->pOverlayWin
, serverClient
);
450 /* Record that client is using this overlay window */
451 pOc
= findCompOverlayClient(client
, pScreen
);
453 int ret
= createCompOverlayClient(client
, pScreen
);
454 if (ret
!= Success
) {
460 rep
.sequenceNumber
= client
->sequence
;
462 rep
.overlayWin
= cs
->pOverlayWin
->drawable
.id
;
467 swaps(&rep
.sequenceNumber
, n
);
468 swapl(&rep
.length
, n
);
469 swapl(&rep
.overlayWin
, n
);
471 (void) WriteToClient(client
, sz_xCompositeGetOverlayWindowReply
, (char *)&rep
);
473 return client
->noClientException
;
477 ProcCompositeReleaseOverlayWindow (ClientPtr client
)
479 REQUEST(xCompositeReleaseOverlayWindowReq
);
482 CompOverlayClientPtr pOc
;
485 REQUEST_SIZE_MATCH(xCompositeReleaseOverlayWindowReq
);
486 pWin
= (WindowPtr
) LookupIDByType (stuff
->window
, RT_WINDOW
);
489 client
->errorValue
= stuff
->window
;
492 pScreen
= pWin
->drawable
.pScreen
;
495 * Has client queried a reference to the overlay window
496 * on this screen? If not, generate an error.
498 pOc
= findCompOverlayClient(client
, pWin
->drawable
.pScreen
);
503 /* The delete function will free the client structure */
504 FreeResource (pOc
->resource
, 0);
506 cs
= GetCompScreen(pScreen
);
507 if (cs
->pOverlayClients
== NULL
) {
508 UnmapWindow(cs
->pOverlayWin
, FALSE
);
511 return client
->noClientException
;
514 static int (*ProcCompositeVector
[CompositeNumberRequests
])(ClientPtr
) = {
515 ProcCompositeQueryVersion
,
516 ProcCompositeRedirectWindow
,
517 ProcCompositeRedirectSubwindows
,
518 ProcCompositeUnredirectWindow
,
519 ProcCompositeUnredirectSubwindows
,
520 ProcCompositeCreateRegionFromBorderClip
,
521 ProcCompositeNameWindowPixmap
,
522 ProcCompositeGetOverlayWindow
,
523 ProcCompositeReleaseOverlayWindow
,
527 ProcCompositeDispatch (ClientPtr client
)
531 if (stuff
->data
< CompositeNumberRequests
)
532 return (*ProcCompositeVector
[stuff
->data
]) (client
);
538 SProcCompositeQueryVersion (ClientPtr client
)
541 REQUEST(xCompositeQueryVersionReq
);
543 swaps(&stuff
->length
, n
);
544 REQUEST_SIZE_MATCH(xCompositeQueryVersionReq
);
545 swapl(&stuff
->majorVersion
, n
);
546 swapl(&stuff
->minorVersion
, n
);
547 return (*ProcCompositeVector
[stuff
->compositeReqType
]) (client
);
551 SProcCompositeRedirectWindow (ClientPtr client
)
554 REQUEST(xCompositeRedirectWindowReq
);
556 swaps(&stuff
->length
, n
);
557 REQUEST_SIZE_MATCH(xCompositeRedirectWindowReq
);
558 swapl (&stuff
->window
, n
);
559 return (*ProcCompositeVector
[stuff
->compositeReqType
]) (client
);
563 SProcCompositeRedirectSubwindows (ClientPtr client
)
566 REQUEST(xCompositeRedirectSubwindowsReq
);
568 swaps(&stuff
->length
, n
);
569 REQUEST_SIZE_MATCH(xCompositeRedirectSubwindowsReq
);
570 swapl (&stuff
->window
, n
);
571 return (*ProcCompositeVector
[stuff
->compositeReqType
]) (client
);
575 SProcCompositeUnredirectWindow (ClientPtr client
)
578 REQUEST(xCompositeUnredirectWindowReq
);
580 swaps(&stuff
->length
, n
);
581 REQUEST_SIZE_MATCH(xCompositeUnredirectWindowReq
);
582 swapl (&stuff
->window
, n
);
583 return (*ProcCompositeVector
[stuff
->compositeReqType
]) (client
);
587 SProcCompositeUnredirectSubwindows (ClientPtr client
)
590 REQUEST(xCompositeUnredirectSubwindowsReq
);
592 swaps(&stuff
->length
, n
);
593 REQUEST_SIZE_MATCH(xCompositeUnredirectSubwindowsReq
);
594 swapl (&stuff
->window
, n
);
595 return (*ProcCompositeVector
[stuff
->compositeReqType
]) (client
);
599 SProcCompositeCreateRegionFromBorderClip (ClientPtr client
)
602 REQUEST(xCompositeCreateRegionFromBorderClipReq
);
604 swaps(&stuff
->length
, n
);
605 REQUEST_SIZE_MATCH(xCompositeCreateRegionFromBorderClipReq
);
606 swapl (&stuff
->region
, n
);
607 swapl (&stuff
->window
, n
);
608 return (*ProcCompositeVector
[stuff
->compositeReqType
]) (client
);
612 SProcCompositeNameWindowPixmap (ClientPtr client
)
615 REQUEST(xCompositeNameWindowPixmapReq
);
617 swaps(&stuff
->length
, n
);
618 REQUEST_SIZE_MATCH(xCompositeNameWindowPixmapReq
);
619 swapl (&stuff
->window
, n
);
620 swapl (&stuff
->pixmap
, n
);
621 return (*ProcCompositeVector
[stuff
->compositeReqType
]) (client
);
625 SProcCompositeGetOverlayWindow (ClientPtr client
)
628 REQUEST(xCompositeGetOverlayWindowReq
);
630 swaps (&stuff
->length
, n
);
631 REQUEST_SIZE_MATCH(xCompositeGetOverlayWindowReq
);
632 swapl(&stuff
->window
, n
);
633 return (*ProcCompositeVector
[stuff
->compositeReqType
]) (client
);
637 SProcCompositeReleaseOverlayWindow (ClientPtr client
)
640 REQUEST(xCompositeReleaseOverlayWindowReq
);
642 swaps (&stuff
->length
, n
);
643 REQUEST_SIZE_MATCH(xCompositeReleaseOverlayWindowReq
);
644 swapl(&stuff
->window
, n
);
645 return (*ProcCompositeVector
[stuff
->compositeReqType
]) (client
);
648 static int (*SProcCompositeVector
[CompositeNumberRequests
])(ClientPtr
) = {
649 SProcCompositeQueryVersion
,
650 SProcCompositeRedirectWindow
,
651 SProcCompositeRedirectSubwindows
,
652 SProcCompositeUnredirectWindow
,
653 SProcCompositeUnredirectSubwindows
,
654 SProcCompositeCreateRegionFromBorderClip
,
655 SProcCompositeNameWindowPixmap
,
656 SProcCompositeGetOverlayWindow
,
657 SProcCompositeReleaseOverlayWindow
,
661 SProcCompositeDispatch (ClientPtr client
)
665 if (stuff
->data
< CompositeNumberRequests
)
666 return (*SProcCompositeVector
[stuff
->data
]) (client
);
672 CompositeExtensionInit (void)
674 ExtensionEntry
*extEntry
;
677 for (s
= 0; s
< screenInfo
.numScreens
; s
++) {
678 ScreenPtr pScreen
= screenInfo
.screens
[s
];
681 /* Composite on 8bpp pseudocolor root windows appears to fail, so
682 * just disable it on anything pseudocolor for safety.
684 for (vis
= pScreen
->visuals
; vis
->vid
!= pScreen
->rootVisual
; vis
++)
686 if ((vis
->class | DynamicClass
) == PseudoColor
)
689 /* Ensure that Render is initialized, which is required for automatic
692 if (GetPictureScreenIfSet(pScreen
) == NULL
)
696 /* Xinerama's rewriting of window drawing before Composite gets to it
699 if (!noPanoramiXExtension
)
703 CompositeClientWindowType
= CreateNewResourceType (FreeCompositeClientWindow
);
704 if (!CompositeClientWindowType
)
707 CompositeClientSubwindowsType
= CreateNewResourceType (FreeCompositeClientSubwindows
);
708 if (!CompositeClientSubwindowsType
)
711 CompositeClientOverlayType
= CreateNewResourceType (FreeCompositeClientOverlay
);
712 if (!CompositeClientOverlayType
)
715 CompositeClientPrivateIndex
= AllocateClientPrivateIndex ();
716 if (!AllocateClientPrivate (CompositeClientPrivateIndex
,
717 sizeof (CompositeClientRec
)))
719 if (!AddCallback (&ClientStateCallback
, CompositeClientCallback
, 0))
722 extEntry
= AddExtension (COMPOSITE_NAME
, 0, 0,
723 ProcCompositeDispatch
, SProcCompositeDispatch
,
724 CompositeResetProc
, StandardMinorOpcode
);
727 CompositeReqCode
= (CARD8
) extEntry
->base
;
729 for (s
= 0; s
< screenInfo
.numScreens
; s
++)
730 if (!compScreenInit (screenInfo
.screens
[s
]))
732 miRegisterRedirectBorderClipProc (compSetRedirectBorderClip
,
733 compGetRedirectBorderClip
);