rrdispatch.c revision 9ace9065
105b261ecSmrg/*
205b261ecSmrg * Copyright © 2006 Keith Packard
305b261ecSmrg *
405b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its
505b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that
605b261ecSmrg * the above copyright notice appear in all copies and that both that copyright
705b261ecSmrg * notice and this permission notice appear in supporting documentation, and
805b261ecSmrg * that the name of the copyright holders not be used in advertising or
905b261ecSmrg * publicity pertaining to distribution of the software without specific,
1005b261ecSmrg * written prior permission.  The copyright holders make no representations
1105b261ecSmrg * about the suitability of this software for any purpose.  It is provided "as
1205b261ecSmrg * is" without express or implied warranty.
1305b261ecSmrg *
1405b261ecSmrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1505b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1605b261ecSmrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1705b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1805b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1905b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
2005b261ecSmrg * OF THIS SOFTWARE.
2105b261ecSmrg */
2205b261ecSmrg
2305b261ecSmrg#include "randrstr.h"
246747b715Smrg#include "protocol-versions.h"
2505b261ecSmrg
2605b261ecSmrgBool
2705b261ecSmrgRRClientKnowsRates (ClientPtr	pClient)
2805b261ecSmrg{
2905b261ecSmrg    rrClientPriv(pClient);
3005b261ecSmrg
3105b261ecSmrg    return (pRRClient->major_version > 1 ||
3205b261ecSmrg	    (pRRClient->major_version == 1 && pRRClient->minor_version >= 1));
3305b261ecSmrg}
3405b261ecSmrg
3505b261ecSmrgstatic int
3605b261ecSmrgProcRRQueryVersion (ClientPtr client)
3705b261ecSmrg{
389ace9065Smrg    xRRQueryVersionReply rep = {0};
3905b261ecSmrg    register int n;
4005b261ecSmrg    REQUEST(xRRQueryVersionReq);
4105b261ecSmrg    rrClientPriv(client);
4205b261ecSmrg
4305b261ecSmrg    REQUEST_SIZE_MATCH(xRRQueryVersionReq);
4405b261ecSmrg    pRRClient->major_version = stuff->majorVersion;
4505b261ecSmrg    pRRClient->minor_version = stuff->minorVersion;
4605b261ecSmrg    rep.type = X_Reply;
4705b261ecSmrg    rep.length = 0;
4805b261ecSmrg    rep.sequenceNumber = client->sequence;
496747b715Smrg
506747b715Smrg    if ((stuff->majorVersion * 1000 + stuff->minorVersion) <
516747b715Smrg        (SERVER_RANDR_MAJOR_VERSION * 1000 + SERVER_RANDR_MINOR_VERSION))
526747b715Smrg    {
536747b715Smrg	rep.majorVersion = stuff->majorVersion;
546747b715Smrg	rep.minorVersion = stuff->minorVersion;
556747b715Smrg    } else
566747b715Smrg    {
576747b715Smrg        rep.majorVersion = SERVER_RANDR_MAJOR_VERSION;
586747b715Smrg        rep.minorVersion = SERVER_RANDR_MINOR_VERSION;
596747b715Smrg    }
606747b715Smrg
6105b261ecSmrg    if (client->swapped) {
6205b261ecSmrg    	swaps(&rep.sequenceNumber, n);
6305b261ecSmrg    	swapl(&rep.length, n);
6405b261ecSmrg	swapl(&rep.majorVersion, n);
6505b261ecSmrg	swapl(&rep.minorVersion, n);
6605b261ecSmrg    }
6705b261ecSmrg    WriteToClient(client, sizeof(xRRQueryVersionReply), (char *)&rep);
686747b715Smrg    return Success;
6905b261ecSmrg}
7005b261ecSmrg
7105b261ecSmrgstatic int
7205b261ecSmrgProcRRSelectInput (ClientPtr client)
7305b261ecSmrg{
7405b261ecSmrg    REQUEST(xRRSelectInputReq);
7505b261ecSmrg    rrClientPriv(client);
7605b261ecSmrg    RRTimesPtr	pTimes;
7705b261ecSmrg    WindowPtr	pWin;
7805b261ecSmrg    RREventPtr	pRREvent, *pHead;
7905b261ecSmrg    XID		clientResource;
8005b261ecSmrg    int		rc;
8105b261ecSmrg
8205b261ecSmrg    REQUEST_SIZE_MATCH(xRRSelectInputReq);
834642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixReceiveAccess);
8405b261ecSmrg    if (rc != Success)
8505b261ecSmrg	return rc;
866747b715Smrg    rc = dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id,
876747b715Smrg				 RREventType, client, DixWriteAccess);
886747b715Smrg    if (rc != Success && rc != BadValue)
896747b715Smrg	return rc;
9005b261ecSmrg
9105b261ecSmrg    if (stuff->enable & (RRScreenChangeNotifyMask|
9205b261ecSmrg			 RRCrtcChangeNotifyMask|
934642e01fSmrg			 RROutputChangeNotifyMask|
944642e01fSmrg			 RROutputPropertyNotifyMask))
9505b261ecSmrg    {
9605b261ecSmrg	ScreenPtr	pScreen = pWin->drawable.pScreen;
9705b261ecSmrg	rrScrPriv	(pScreen);
9805b261ecSmrg
9905b261ecSmrg	pRREvent = NULL;
10005b261ecSmrg	if (pHead)
10105b261ecSmrg	{
10205b261ecSmrg	    /* check for existing entry. */
10305b261ecSmrg	    for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
10405b261ecSmrg		if (pRREvent->client == client)
10505b261ecSmrg		    break;
10605b261ecSmrg	}
10705b261ecSmrg
10805b261ecSmrg	if (!pRREvent)
10905b261ecSmrg	{
11005b261ecSmrg	    /* build the entry */
1116747b715Smrg	    pRREvent = (RREventPtr) malloc(sizeof (RREventRec));
11205b261ecSmrg	    if (!pRREvent)
11305b261ecSmrg		return BadAlloc;
11405b261ecSmrg	    pRREvent->next = 0;
11505b261ecSmrg	    pRREvent->client = client;
11605b261ecSmrg	    pRREvent->window = pWin;
11705b261ecSmrg	    pRREvent->mask = stuff->enable;
11805b261ecSmrg	    /*
11905b261ecSmrg	     * add a resource that will be deleted when
12005b261ecSmrg	     * the client goes away
12105b261ecSmrg	     */
12205b261ecSmrg	    clientResource = FakeClientID (client->index);
12305b261ecSmrg	    pRREvent->clientResource = clientResource;
12405b261ecSmrg	    if (!AddResource (clientResource, RRClientType, (pointer)pRREvent))
12505b261ecSmrg		return BadAlloc;
12605b261ecSmrg	    /*
12705b261ecSmrg	     * create a resource to contain a pointer to the list
12805b261ecSmrg	     * of clients selecting input.  This must be indirect as
12905b261ecSmrg	     * the list may be arbitrarily rearranged which cannot be
13005b261ecSmrg	     * done through the resource database.
13105b261ecSmrg	     */
13205b261ecSmrg	    if (!pHead)
13305b261ecSmrg	    {
1346747b715Smrg		pHead = (RREventPtr *) malloc(sizeof (RREventPtr));
13505b261ecSmrg		if (!pHead ||
13605b261ecSmrg		    !AddResource (pWin->drawable.id, RREventType, (pointer)pHead))
13705b261ecSmrg		{
13805b261ecSmrg		    FreeResource (clientResource, RT_NONE);
13905b261ecSmrg		    return BadAlloc;
14005b261ecSmrg		}
14105b261ecSmrg		*pHead = 0;
14205b261ecSmrg	    }
14305b261ecSmrg	    pRREvent->next = *pHead;
14405b261ecSmrg	    *pHead = pRREvent;
14505b261ecSmrg	}
14605b261ecSmrg	/*
14705b261ecSmrg	 * Now see if the client needs an event
14805b261ecSmrg	 */
1499ace9065Smrg	if (pScrPriv)
15005b261ecSmrg	{
15105b261ecSmrg	    pTimes = &((RRTimesPtr) (pRRClient + 1))[pScreen->myNum];
15205b261ecSmrg	    if (CompareTimeStamps (pTimes->setTime,
15305b261ecSmrg				   pScrPriv->lastSetTime) != 0 ||
15405b261ecSmrg		CompareTimeStamps (pTimes->configTime,
15505b261ecSmrg				   pScrPriv->lastConfigTime) != 0)
15605b261ecSmrg	    {
1579ace9065Smrg		if (pRREvent->mask & RRScreenChangeNotifyMask)
1589ace9065Smrg		{
1599ace9065Smrg		    RRDeliverScreenEvent (client, pWin, pScreen);
1609ace9065Smrg		}
1619ace9065Smrg
1629ace9065Smrg		if (pRREvent->mask & RRCrtcChangeNotifyMask)
1639ace9065Smrg		{
1649ace9065Smrg		    int i;
1659ace9065Smrg
1669ace9065Smrg		    for (i = 0; i < pScrPriv->numCrtcs; i++)
1679ace9065Smrg		    {
1689ace9065Smrg			RRDeliverCrtcEvent (client, pWin, pScrPriv->crtcs[i]);
1699ace9065Smrg		    }
1709ace9065Smrg		}
1719ace9065Smrg
1729ace9065Smrg		if (pRREvent->mask & RROutputChangeNotifyMask)
1739ace9065Smrg		{
1749ace9065Smrg		    int i;
1759ace9065Smrg
1769ace9065Smrg		    for (i = 0; i < pScrPriv->numOutputs; i++)
1779ace9065Smrg		    {
1789ace9065Smrg			RRDeliverOutputEvent (client, pWin, pScrPriv->outputs[i]);
1799ace9065Smrg		    }
1809ace9065Smrg		}
1819ace9065Smrg
1829ace9065Smrg		/* We don't check for RROutputPropertyNotifyMask, as randrproto.txt doesn't
1839ace9065Smrg		 * say if there ought to be notifications of changes to output properties
1849ace9065Smrg		 * if those changes occurred before the time RRSelectInput is called.
1859ace9065Smrg		 */
18605b261ecSmrg	    }
18705b261ecSmrg	}
18805b261ecSmrg    }
18905b261ecSmrg    else if (stuff->enable == 0)
19005b261ecSmrg    {
19105b261ecSmrg	/* delete the interest */
19205b261ecSmrg	if (pHead) {
19305b261ecSmrg	    RREventPtr pNewRREvent = 0;
19405b261ecSmrg	    for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) {
19505b261ecSmrg		if (pRREvent->client == client)
19605b261ecSmrg		    break;
19705b261ecSmrg		pNewRREvent = pRREvent;
19805b261ecSmrg	    }
19905b261ecSmrg	    if (pRREvent) {
20005b261ecSmrg		FreeResource (pRREvent->clientResource, RRClientType);
20105b261ecSmrg		if (pNewRREvent)
20205b261ecSmrg		    pNewRREvent->next = pRREvent->next;
20305b261ecSmrg		else
20405b261ecSmrg		    *pHead = pRREvent->next;
2056747b715Smrg		free(pRREvent);
20605b261ecSmrg	    }
20705b261ecSmrg	}
20805b261ecSmrg    }
20905b261ecSmrg    else
21005b261ecSmrg    {
21105b261ecSmrg	client->errorValue = stuff->enable;
21205b261ecSmrg	return BadValue;
21305b261ecSmrg    }
21405b261ecSmrg    return Success;
21505b261ecSmrg}
21605b261ecSmrg
21705b261ecSmrgint (*ProcRandrVector[RRNumberRequests])(ClientPtr) = {
21805b261ecSmrg    ProcRRQueryVersion,	/* 0 */
21905b261ecSmrg/* we skip 1 to make old clients fail pretty immediately */
22005b261ecSmrg    NULL,			/* 1 ProcRandrOldGetScreenInfo */
22105b261ecSmrg/* V1.0 apps share the same set screen config request id */
22205b261ecSmrg    ProcRRSetScreenConfig,	/* 2 */
22305b261ecSmrg    NULL,			/* 3 ProcRandrOldScreenChangeSelectInput */
22405b261ecSmrg/* 3 used to be ScreenChangeSelectInput; deprecated */
22505b261ecSmrg    ProcRRSelectInput,		/* 4 */
22605b261ecSmrg    ProcRRGetScreenInfo,    	/* 5 */
22705b261ecSmrg/* V1.2 additions */
22805b261ecSmrg    ProcRRGetScreenSizeRange,	/* 6 */
22905b261ecSmrg    ProcRRSetScreenSize,	/* 7 */
23005b261ecSmrg    ProcRRGetScreenResources,	/* 8 */
23105b261ecSmrg    ProcRRGetOutputInfo,	/* 9 */
23205b261ecSmrg    ProcRRListOutputProperties,	/* 10 */
23305b261ecSmrg    ProcRRQueryOutputProperty,	/* 11 */
23405b261ecSmrg    ProcRRConfigureOutputProperty,  /* 12 */
23505b261ecSmrg    ProcRRChangeOutputProperty,	/* 13 */
23605b261ecSmrg    ProcRRDeleteOutputProperty,	/* 14 */
23705b261ecSmrg    ProcRRGetOutputProperty,	/* 15 */
23805b261ecSmrg    ProcRRCreateMode,		/* 16 */
23905b261ecSmrg    ProcRRDestroyMode,		/* 17 */
24005b261ecSmrg    ProcRRAddOutputMode,	/* 18 */
24105b261ecSmrg    ProcRRDeleteOutputMode,	/* 19 */
24205b261ecSmrg    ProcRRGetCrtcInfo,		/* 20 */
24305b261ecSmrg    ProcRRSetCrtcConfig,	/* 21 */
24405b261ecSmrg    ProcRRGetCrtcGammaSize,	/* 22 */
24505b261ecSmrg    ProcRRGetCrtcGamma,		/* 23 */
24605b261ecSmrg    ProcRRSetCrtcGamma,		/* 24 */
2474642e01fSmrg/* V1.3 additions */
2484642e01fSmrg    ProcRRGetScreenResourcesCurrent, /* 25 */
2494642e01fSmrg    ProcRRSetCrtcTransform,	/* 26 */
2504642e01fSmrg    ProcRRGetCrtcTransform,	/* 27 */
2514642e01fSmrg    ProcRRGetPanning,		/* 28 */
2524642e01fSmrg    ProcRRSetPanning,		/* 29 */
2534642e01fSmrg    ProcRRSetOutputPrimary,	/* 30 */
2544642e01fSmrg    ProcRRGetOutputPrimary,	/* 31 */
25505b261ecSmrg};
25605b261ecSmrg
257