xserver-multidpi/composite/compext.c
Keith Packard f106c04b62 Have Composite always report server version.
It was reporting the lessor of the server and client versions, which doesn't
make sense with the 0.4 semantic change in clipping.
2007-07-03 14:47:19 -07:00

735 lines
20 KiB
C

/*
* Copyright © 2006 Sun Microsystems
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Sun Microsystems not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Sun Microsystems makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* Copyright © 2003 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include "compint.h"
#define SERVER_COMPOSITE_MAJOR 0
#define SERVER_COMPOSITE_MINOR 4
static CARD8 CompositeReqCode;
static int CompositeClientPrivateIndex;
RESTYPE CompositeClientWindowType;
RESTYPE CompositeClientSubwindowsType;
static RESTYPE CompositeClientOverlayType;
static void deleteCompOverlayClient (CompOverlayClientPtr pOcToDel,
ScreenPtr pScreen);
typedef struct _CompositeClient {
int major_version;
int minor_version;
} CompositeClientRec, *CompositeClientPtr;
#define GetCompositeClient(pClient) ((CompositeClientPtr) (pClient)->devPrivates[CompositeClientPrivateIndex].ptr)
static void
CompositeClientCallback (CallbackListPtr *list,
pointer closure,
pointer data)
{
NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
ClientPtr pClient = clientinfo->client;
CompositeClientPtr pCompositeClient = GetCompositeClient (pClient);
pCompositeClient->major_version = 0;
pCompositeClient->minor_version = 0;
}
static void
CompositeResetProc (ExtensionEntry *extEntry)
{
}
static int
FreeCompositeClientWindow (pointer value, XID ccwid)
{
WindowPtr pWin = value;
compFreeClientWindow (pWin, ccwid);
return Success;
}
static int
FreeCompositeClientSubwindows (pointer value, XID ccwid)
{
WindowPtr pWin = value;
compFreeClientSubwindows (pWin, ccwid);
return Success;
}
static int
FreeCompositeClientOverlay (pointer value, XID ccwid)
{
CompOverlayClientPtr pOc = (CompOverlayClientPtr) value;
ScreenPtr pScreen = pOc->pScreen;
CompScreenPtr cs;
deleteCompOverlayClient(pOc, pScreen);
/* Unmap overlay window when there are no more clients using it */
cs = GetCompScreen(pScreen);
if (cs->pOverlayClients == NULL) {
if (cs->pOverlayWin != NULL) {
UnmapWindow(cs->pOverlayWin, FALSE);
}
}
return Success;
}
static int
ProcCompositeQueryVersion (ClientPtr client)
{
CompositeClientPtr pCompositeClient = GetCompositeClient (client);
xCompositeQueryVersionReply rep;
register int n;
REQUEST(xCompositeQueryVersionReq);
REQUEST_SIZE_MATCH(xCompositeQueryVersionReq);
rep.type = X_Reply;
rep.length = 0;
rep.sequenceNumber = client->sequence;
if (stuff->majorVersion < SERVER_COMPOSITE_MAJOR) {
rep.majorVersion = stuff->majorVersion;
rep.minorVersion = stuff->minorVersion;
} else {
rep.majorVersion = SERVER_COMPOSITE_MAJOR;
rep.minorVersion = SERVER_COMPOSITE_MINOR;
}
pCompositeClient->major_version = rep.majorVersion;
pCompositeClient->minor_version = rep.minorVersion;
if (client->swapped) {
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swapl(&rep.majorVersion, n);
swapl(&rep.minorVersion, n);
}
WriteToClient(client, sizeof(xCompositeQueryVersionReply), (char *)&rep);
return(client->noClientException);
}
static int
ProcCompositeRedirectWindow (ClientPtr client)
{
WindowPtr pWin;
REQUEST(xCompositeRedirectWindowReq);
REQUEST_SIZE_MATCH(xCompositeRedirectWindowReq);
pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
if (!pWin)
{
client->errorValue = stuff->window;
return BadWindow;
}
return compRedirectWindow (client, pWin, stuff->update);
}
static int
ProcCompositeRedirectSubwindows (ClientPtr client)
{
WindowPtr pWin;
REQUEST(xCompositeRedirectSubwindowsReq);
REQUEST_SIZE_MATCH(xCompositeRedirectSubwindowsReq);
pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
if (!pWin)
{
client->errorValue = stuff->window;
return BadWindow;
}
return compRedirectSubwindows (client, pWin, stuff->update);
}
static int
ProcCompositeUnredirectWindow (ClientPtr client)
{
WindowPtr pWin;
REQUEST(xCompositeUnredirectWindowReq);
REQUEST_SIZE_MATCH(xCompositeUnredirectWindowReq);
pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
if (!pWin)
{
client->errorValue = stuff->window;
return BadWindow;
}
return compUnredirectWindow (client, pWin, stuff->update);
}
static int
ProcCompositeUnredirectSubwindows (ClientPtr client)
{
WindowPtr pWin;
REQUEST(xCompositeUnredirectSubwindowsReq);
REQUEST_SIZE_MATCH(xCompositeUnredirectSubwindowsReq);
pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
if (!pWin)
{
client->errorValue = stuff->window;
return BadWindow;
}
return compUnredirectSubwindows (client, pWin, stuff->update);
}
static int
ProcCompositeCreateRegionFromBorderClip (ClientPtr client)
{
WindowPtr pWin;
CompWindowPtr cw;
RegionPtr pBorderClip, pRegion;
REQUEST(xCompositeCreateRegionFromBorderClipReq);
REQUEST_SIZE_MATCH(xCompositeCreateRegionFromBorderClipReq);
pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
if (!pWin)
{
client->errorValue = stuff->window;
return BadWindow;
}
LEGAL_NEW_RESOURCE (stuff->region, client);
cw = GetCompWindow (pWin);
if (cw)
pBorderClip = &cw->borderClip;
else
pBorderClip = &pWin->borderClip;
pRegion = XFixesRegionCopy (pBorderClip);
if (!pRegion)
return BadAlloc;
REGION_TRANSLATE (pScreen, pRegion, -pWin->drawable.x, -pWin->drawable.y);
if (!AddResource (stuff->region, RegionResType, (pointer) pRegion))
return BadAlloc;
return(client->noClientException);
}
static int
ProcCompositeNameWindowPixmap (ClientPtr client)
{
WindowPtr pWin;
CompWindowPtr cw;
PixmapPtr pPixmap;
REQUEST(xCompositeNameWindowPixmapReq);
REQUEST_SIZE_MATCH(xCompositeNameWindowPixmapReq);
pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
if (!pWin)
{
client->errorValue = stuff->window;
return BadWindow;
}
if (!pWin->viewable)
return BadMatch;
LEGAL_NEW_RESOURCE (stuff->pixmap, client);
cw = GetCompWindow (pWin);
if (!cw)
return BadMatch;
pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin);
if (!pPixmap)
return BadMatch;
++pPixmap->refcnt;
if (!AddResource (stuff->pixmap, RT_PIXMAP, (pointer) pPixmap))
return BadAlloc;
return(client->noClientException);
}
/*
* Routines for manipulating the per-screen overlay clients list.
* This list indicates which clients have called GetOverlayWindow
* for this screen.
*/
/* Return the screen's overlay client list element for the given client */
static CompOverlayClientPtr
findCompOverlayClient (ClientPtr pClient, ScreenPtr pScreen)
{
CompScreenPtr cs = GetCompScreen(pScreen);
CompOverlayClientPtr pOc;
for (pOc = cs->pOverlayClients; pOc != NULL; pOc = pOc->pNext) {
if (pOc->pClient == pClient) {
return pOc;
}
}
return NULL;
}
static int
createCompOverlayClient (ClientPtr pClient, ScreenPtr pScreen)
{
CompScreenPtr cs = GetCompScreen(pScreen);
CompOverlayClientPtr pOc;
pOc = (CompOverlayClientPtr) xalloc(sizeof(CompOverlayClientRec));
if (pOc == NULL) {
return BadAlloc;
}
pOc->pClient = pClient;
pOc->pScreen = pScreen;
pOc->resource = FakeClientID(pClient->index);
pOc->pNext = cs->pOverlayClients;
cs->pOverlayClients = pOc;
/*
* Create a resource for this element so it can be deleted
* when the client goes away.
*/
if (!AddResource (pOc->resource, CompositeClientOverlayType,
(pointer) pOc)) {
xfree(pOc);
return BadAlloc;
}
return Success;
}
/*
* Delete the given overlay client list element from its screen list.
*/
static void
deleteCompOverlayClient (CompOverlayClientPtr pOcToDel, ScreenPtr pScreen)
{
CompScreenPtr cs = GetCompScreen(pScreen);
CompOverlayClientPtr pOc, pNext;
CompOverlayClientPtr pOcLast = NULL;
pOc = cs->pOverlayClients;
while (pOc != NULL) {
pNext = pOc->pNext;
if (pOc == pOcToDel) {
xfree(pOc);
if (pOcLast == NULL) {
cs->pOverlayClients = pNext;
} else {
pOcLast->pNext = pNext;
}
break;
}
pOcLast = pOc;
pOc = pNext;
}
}
/*
* Delete all the hide-counts list elements for this screen.
*/
void
deleteCompOverlayClientsForScreen (ScreenPtr pScreen)
{
CompScreenPtr cs = GetCompScreen(pScreen);
CompOverlayClientPtr pOc, pTmp;
pOc = cs->pOverlayClients;
while (pOc != NULL) {
pTmp = pOc->pNext;
FreeResource(pOc->resource, 0);
pOc = pTmp;
}
cs->pOverlayClients = NULL;
}
/*
** If necessary, create the overlay window. And map it
** Note: I found it excessively difficult to destroy this window
** during compCloseScreen; DeleteWindow can't be called because
** the input devices are already shut down. So we are going to
** just allocate an overlay window once per screen per X server
** invocation.
*/
static WindowPtr
createOverlayWindow (ScreenPtr pScreen)
{
int wid = FakeClientID(0);
WindowPtr pWin;
XID overrideRedirect = TRUE;
int result;
pWin = CreateWindow (
wid, WindowTable[pScreen->myNum],
0, 0, pScreen->width, pScreen->height, 0,
InputOutput, CWOverrideRedirect, &overrideRedirect,
WindowTable[pScreen->myNum]->drawable.depth,
serverClient, pScreen->rootVisual, &result);
if (pWin == NULL) {
return NULL;
}
if (!AddResource(wid, RT_WINDOW, (pointer)pWin)) {
DeleteWindow(pWin, None);
return NULL;
}
return pWin;
}
static int
ProcCompositeGetOverlayWindow (ClientPtr client)
{
REQUEST(xCompositeGetOverlayWindowReq);
xCompositeGetOverlayWindowReply rep;
WindowPtr pWin;
ScreenPtr pScreen;
CompScreenPtr cs;
CompOverlayClientPtr pOc;
REQUEST_SIZE_MATCH(xCompositeGetOverlayWindowReq);
pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
if (!pWin)
{
client->errorValue = stuff->window;
return BadWindow;
}
pScreen = pWin->drawable.pScreen;
cs = GetCompScreen(pScreen);
if (cs->pOverlayWin == NULL) {
cs->pOverlayWin = createOverlayWindow(pScreen);
if (cs->pOverlayWin == NULL) {
return BadAlloc;
}
}
MapWindow(cs->pOverlayWin, serverClient);
/* Record that client is using this overlay window */
pOc = findCompOverlayClient(client, pScreen);
if (pOc == NULL) {
int ret = createCompOverlayClient(client, pScreen);
if (ret != Success) {
return ret;
}
}
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.length = 0;
rep.overlayWin = cs->pOverlayWin->drawable.id;
if (client->swapped)
{
int n;
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swapl(&rep.overlayWin, n);
}
(void) WriteToClient(client, sz_xCompositeGetOverlayWindowReply, (char *)&rep);
return client->noClientException;
}
static int
ProcCompositeReleaseOverlayWindow (ClientPtr client)
{
REQUEST(xCompositeReleaseOverlayWindowReq);
WindowPtr pWin;
ScreenPtr pScreen;
CompOverlayClientPtr pOc;
CompScreenPtr cs;
REQUEST_SIZE_MATCH(xCompositeReleaseOverlayWindowReq);
pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
if (!pWin)
{
client->errorValue = stuff->window;
return BadWindow;
}
pScreen = pWin->drawable.pScreen;
/*
* Has client queried a reference to the overlay window
* on this screen? If not, generate an error.
*/
pOc = findCompOverlayClient(client, pWin->drawable.pScreen);
if (pOc == NULL) {
return BadMatch;
}
/* The delete function will free the client structure */
FreeResource (pOc->resource, 0);
cs = GetCompScreen(pScreen);
if (cs->pOverlayClients == NULL) {
UnmapWindow(cs->pOverlayWin, FALSE);
}
return client->noClientException;
}
static int (*ProcCompositeVector[CompositeNumberRequests])(ClientPtr) = {
ProcCompositeQueryVersion,
ProcCompositeRedirectWindow,
ProcCompositeRedirectSubwindows,
ProcCompositeUnredirectWindow,
ProcCompositeUnredirectSubwindows,
ProcCompositeCreateRegionFromBorderClip,
ProcCompositeNameWindowPixmap,
ProcCompositeGetOverlayWindow,
ProcCompositeReleaseOverlayWindow,
};
static int
ProcCompositeDispatch (ClientPtr client)
{
REQUEST(xReq);
if (stuff->data < CompositeNumberRequests)
return (*ProcCompositeVector[stuff->data]) (client);
else
return BadRequest;
}
static int
SProcCompositeQueryVersion (ClientPtr client)
{
int n;
REQUEST(xCompositeQueryVersionReq);
swaps(&stuff->length, n);
REQUEST_SIZE_MATCH(xCompositeQueryVersionReq);
swapl(&stuff->majorVersion, n);
swapl(&stuff->minorVersion, n);
return (*ProcCompositeVector[stuff->compositeReqType]) (client);
}
static int
SProcCompositeRedirectWindow (ClientPtr client)
{
int n;
REQUEST(xCompositeRedirectWindowReq);
swaps(&stuff->length, n);
REQUEST_SIZE_MATCH(xCompositeRedirectWindowReq);
swapl (&stuff->window, n);
return (*ProcCompositeVector[stuff->compositeReqType]) (client);
}
static int
SProcCompositeRedirectSubwindows (ClientPtr client)
{
int n;
REQUEST(xCompositeRedirectSubwindowsReq);
swaps(&stuff->length, n);
REQUEST_SIZE_MATCH(xCompositeRedirectSubwindowsReq);
swapl (&stuff->window, n);
return (*ProcCompositeVector[stuff->compositeReqType]) (client);
}
static int
SProcCompositeUnredirectWindow (ClientPtr client)
{
int n;
REQUEST(xCompositeUnredirectWindowReq);
swaps(&stuff->length, n);
REQUEST_SIZE_MATCH(xCompositeUnredirectWindowReq);
swapl (&stuff->window, n);
return (*ProcCompositeVector[stuff->compositeReqType]) (client);
}
static int
SProcCompositeUnredirectSubwindows (ClientPtr client)
{
int n;
REQUEST(xCompositeUnredirectSubwindowsReq);
swaps(&stuff->length, n);
REQUEST_SIZE_MATCH(xCompositeUnredirectSubwindowsReq);
swapl (&stuff->window, n);
return (*ProcCompositeVector[stuff->compositeReqType]) (client);
}
static int
SProcCompositeCreateRegionFromBorderClip (ClientPtr client)
{
int n;
REQUEST(xCompositeCreateRegionFromBorderClipReq);
swaps(&stuff->length, n);
REQUEST_SIZE_MATCH(xCompositeCreateRegionFromBorderClipReq);
swapl (&stuff->region, n);
swapl (&stuff->window, n);
return (*ProcCompositeVector[stuff->compositeReqType]) (client);
}
static int
SProcCompositeNameWindowPixmap (ClientPtr client)
{
int n;
REQUEST(xCompositeNameWindowPixmapReq);
swaps(&stuff->length, n);
REQUEST_SIZE_MATCH(xCompositeNameWindowPixmapReq);
swapl (&stuff->window, n);
swapl (&stuff->pixmap, n);
return (*ProcCompositeVector[stuff->compositeReqType]) (client);
}
static int
SProcCompositeGetOverlayWindow (ClientPtr client)
{
int n;
REQUEST(xCompositeGetOverlayWindowReq);
swaps (&stuff->length, n);
REQUEST_SIZE_MATCH(xCompositeGetOverlayWindowReq);
swapl(&stuff->window, n);
return (*ProcCompositeVector[stuff->compositeReqType]) (client);
}
static int
SProcCompositeReleaseOverlayWindow (ClientPtr client)
{
int n;
REQUEST(xCompositeReleaseOverlayWindowReq);
swaps (&stuff->length, n);
REQUEST_SIZE_MATCH(xCompositeReleaseOverlayWindowReq);
swapl(&stuff->window, n);
return (*ProcCompositeVector[stuff->compositeReqType]) (client);
}
static int (*SProcCompositeVector[CompositeNumberRequests])(ClientPtr) = {
SProcCompositeQueryVersion,
SProcCompositeRedirectWindow,
SProcCompositeRedirectSubwindows,
SProcCompositeUnredirectWindow,
SProcCompositeUnredirectSubwindows,
SProcCompositeCreateRegionFromBorderClip,
SProcCompositeNameWindowPixmap,
SProcCompositeGetOverlayWindow,
SProcCompositeReleaseOverlayWindow,
};
static int
SProcCompositeDispatch (ClientPtr client)
{
REQUEST(xReq);
if (stuff->data < CompositeNumberRequests)
return (*SProcCompositeVector[stuff->data]) (client);
else
return BadRequest;
}
void
CompositeExtensionInit (void)
{
ExtensionEntry *extEntry;
int s;
for (s = 0; s < screenInfo.numScreens; s++) {
ScreenPtr pScreen = screenInfo.screens[s];
VisualPtr vis;
/* Composite on 8bpp pseudocolor root windows appears to fail, so
* just disable it on anything pseudocolor for safety.
*/
for (vis = pScreen->visuals; vis->vid != pScreen->rootVisual; vis++)
;
if ((vis->class | DynamicClass) == PseudoColor)
return;
/* Ensure that Render is initialized, which is required for automatic
* compositing.
*/
if (GetPictureScreenIfSet(pScreen) == NULL)
return;
}
#ifdef PANORAMIX
/* Xinerama's rewriting of window drawing before Composite gets to it
* breaks Composite.
*/
if (!noPanoramiXExtension)
return;
#endif
CompositeClientWindowType = CreateNewResourceType (FreeCompositeClientWindow);
if (!CompositeClientWindowType)
return;
CompositeClientSubwindowsType = CreateNewResourceType (FreeCompositeClientSubwindows);
if (!CompositeClientSubwindowsType)
return;
CompositeClientOverlayType = CreateNewResourceType (FreeCompositeClientOverlay);
if (!CompositeClientOverlayType)
return;
CompositeClientPrivateIndex = AllocateClientPrivateIndex ();
if (!AllocateClientPrivate (CompositeClientPrivateIndex,
sizeof (CompositeClientRec)))
return;
if (!AddCallback (&ClientStateCallback, CompositeClientCallback, 0))
return;
extEntry = AddExtension (COMPOSITE_NAME, 0, 0,
ProcCompositeDispatch, SProcCompositeDispatch,
CompositeResetProc, StandardMinorOpcode);
if (!extEntry)
return;
CompositeReqCode = (CARD8) extEntry->base;
for (s = 0; s < screenInfo.numScreens; s++)
if (!compScreenInit (screenInfo.screens[s]))
return;
miRegisterRedirectBorderClipProc (compSetRedirectBorderClip,
compGetRedirectBorderClip);
}