rrdispatch.c revision 05b261ec
1/*
2 * Copyright © 2006 Keith Packard
3 *
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 copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission.  The copyright holders make no representations
11 * about the suitability of this software for any purpose.  It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS 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 PERFORMANCE
20 * OF THIS SOFTWARE.
21 */
22
23#include "randrstr.h"
24
25#define SERVER_RANDR_MAJOR	1
26#define SERVER_RANDR_MINOR	2
27
28Bool
29RRClientKnowsRates (ClientPtr	pClient)
30{
31    rrClientPriv(pClient);
32
33    return (pRRClient->major_version > 1 ||
34	    (pRRClient->major_version == 1 && pRRClient->minor_version >= 1));
35}
36
37static int
38ProcRRQueryVersion (ClientPtr client)
39{
40    xRRQueryVersionReply rep;
41    register int n;
42    REQUEST(xRRQueryVersionReq);
43    rrClientPriv(client);
44
45    REQUEST_SIZE_MATCH(xRRQueryVersionReq);
46    pRRClient->major_version = stuff->majorVersion;
47    pRRClient->minor_version = stuff->minorVersion;
48    rep.type = X_Reply;
49    rep.length = 0;
50    rep.sequenceNumber = client->sequence;
51    /*
52     * Report the current version; the current
53     * spec says they're all compatible after 1.0
54     */
55    rep.majorVersion = SERVER_RANDR_MAJOR;
56    rep.minorVersion = SERVER_RANDR_MINOR;
57    if (client->swapped) {
58    	swaps(&rep.sequenceNumber, n);
59    	swapl(&rep.length, n);
60	swapl(&rep.majorVersion, n);
61	swapl(&rep.minorVersion, n);
62    }
63    WriteToClient(client, sizeof(xRRQueryVersionReply), (char *)&rep);
64    return (client->noClientException);
65}
66
67static int
68ProcRRSelectInput (ClientPtr client)
69{
70    REQUEST(xRRSelectInputReq);
71    rrClientPriv(client);
72    RRTimesPtr	pTimes;
73    WindowPtr	pWin;
74    RREventPtr	pRREvent, *pHead;
75    XID		clientResource;
76    int		rc;
77
78    REQUEST_SIZE_MATCH(xRRSelectInputReq);
79    rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess);
80    if (rc != Success)
81	return rc;
82    pHead = (RREventPtr *)SecurityLookupIDByType(client,
83						 pWin->drawable.id, RREventType,
84						 DixWriteAccess);
85
86    if (stuff->enable & (RRScreenChangeNotifyMask|
87			 RRCrtcChangeNotifyMask|
88			 RROutputChangeNotifyMask))
89    {
90	ScreenPtr	pScreen = pWin->drawable.pScreen;
91	rrScrPriv	(pScreen);
92
93	pRREvent = NULL;
94	if (pHead)
95	{
96	    /* check for existing entry. */
97	    for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
98		if (pRREvent->client == client)
99		    break;
100	}
101
102	if (!pRREvent)
103	{
104	    /* build the entry */
105	    pRREvent = (RREventPtr) xalloc (sizeof (RREventRec));
106	    if (!pRREvent)
107		return BadAlloc;
108	    pRREvent->next = 0;
109	    pRREvent->client = client;
110	    pRREvent->window = pWin;
111	    pRREvent->mask = stuff->enable;
112	    /*
113	     * add a resource that will be deleted when
114	     * the client goes away
115	     */
116	    clientResource = FakeClientID (client->index);
117	    pRREvent->clientResource = clientResource;
118	    if (!AddResource (clientResource, RRClientType, (pointer)pRREvent))
119		return BadAlloc;
120	    /*
121	     * create a resource to contain a pointer to the list
122	     * of clients selecting input.  This must be indirect as
123	     * the list may be arbitrarily rearranged which cannot be
124	     * done through the resource database.
125	     */
126	    if (!pHead)
127	    {
128		pHead = (RREventPtr *) xalloc (sizeof (RREventPtr));
129		if (!pHead ||
130		    !AddResource (pWin->drawable.id, RREventType, (pointer)pHead))
131		{
132		    FreeResource (clientResource, RT_NONE);
133		    return BadAlloc;
134		}
135		*pHead = 0;
136	    }
137	    pRREvent->next = *pHead;
138	    *pHead = pRREvent;
139	}
140	/*
141	 * Now see if the client needs an event
142	 */
143	if (pScrPriv && (pRREvent->mask & RRScreenChangeNotifyMask))
144	{
145	    pTimes = &((RRTimesPtr) (pRRClient + 1))[pScreen->myNum];
146	    if (CompareTimeStamps (pTimes->setTime,
147				   pScrPriv->lastSetTime) != 0 ||
148		CompareTimeStamps (pTimes->configTime,
149				   pScrPriv->lastConfigTime) != 0)
150	    {
151		RRDeliverScreenEvent (client, pWin, pScreen);
152	    }
153	}
154    }
155    else if (stuff->enable == 0)
156    {
157	/* delete the interest */
158	if (pHead) {
159	    RREventPtr pNewRREvent = 0;
160	    for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) {
161		if (pRREvent->client == client)
162		    break;
163		pNewRREvent = pRREvent;
164	    }
165	    if (pRREvent) {
166		FreeResource (pRREvent->clientResource, RRClientType);
167		if (pNewRREvent)
168		    pNewRREvent->next = pRREvent->next;
169		else
170		    *pHead = pRREvent->next;
171		xfree (pRREvent);
172	    }
173	}
174    }
175    else
176    {
177	client->errorValue = stuff->enable;
178	return BadValue;
179    }
180    return Success;
181}
182
183int (*ProcRandrVector[RRNumberRequests])(ClientPtr) = {
184    ProcRRQueryVersion,	/* 0 */
185/* we skip 1 to make old clients fail pretty immediately */
186    NULL,			/* 1 ProcRandrOldGetScreenInfo */
187/* V1.0 apps share the same set screen config request id */
188    ProcRRSetScreenConfig,	/* 2 */
189    NULL,			/* 3 ProcRandrOldScreenChangeSelectInput */
190/* 3 used to be ScreenChangeSelectInput; deprecated */
191    ProcRRSelectInput,		/* 4 */
192    ProcRRGetScreenInfo,    	/* 5 */
193/* V1.2 additions */
194    ProcRRGetScreenSizeRange,	/* 6 */
195    ProcRRSetScreenSize,	/* 7 */
196    ProcRRGetScreenResources,	/* 8 */
197    ProcRRGetOutputInfo,	/* 9 */
198    ProcRRListOutputProperties,	/* 10 */
199    ProcRRQueryOutputProperty,	/* 11 */
200    ProcRRConfigureOutputProperty,  /* 12 */
201    ProcRRChangeOutputProperty,	/* 13 */
202    ProcRRDeleteOutputProperty,	/* 14 */
203    ProcRRGetOutputProperty,	/* 15 */
204    ProcRRCreateMode,		/* 16 */
205    ProcRRDestroyMode,		/* 17 */
206    ProcRRAddOutputMode,	/* 18 */
207    ProcRRDeleteOutputMode,	/* 19 */
208    ProcRRGetCrtcInfo,		/* 20 */
209    ProcRRSetCrtcConfig,	/* 21 */
210    ProcRRGetCrtcGammaSize,	/* 22 */
211    ProcRRGetCrtcGamma,		/* 23 */
212    ProcRRSetCrtcGamma,		/* 24 */
213};
214
215