rrdispatch.c revision 9ace9065
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#include "protocol-versions.h"
25
26Bool
27RRClientKnowsRates (ClientPtr	pClient)
28{
29    rrClientPriv(pClient);
30
31    return (pRRClient->major_version > 1 ||
32	    (pRRClient->major_version == 1 && pRRClient->minor_version >= 1));
33}
34
35static int
36ProcRRQueryVersion (ClientPtr client)
37{
38    xRRQueryVersionReply rep = {0};
39    register int n;
40    REQUEST(xRRQueryVersionReq);
41    rrClientPriv(client);
42
43    REQUEST_SIZE_MATCH(xRRQueryVersionReq);
44    pRRClient->major_version = stuff->majorVersion;
45    pRRClient->minor_version = stuff->minorVersion;
46    rep.type = X_Reply;
47    rep.length = 0;
48    rep.sequenceNumber = client->sequence;
49
50    if ((stuff->majorVersion * 1000 + stuff->minorVersion) <
51        (SERVER_RANDR_MAJOR_VERSION * 1000 + SERVER_RANDR_MINOR_VERSION))
52    {
53	rep.majorVersion = stuff->majorVersion;
54	rep.minorVersion = stuff->minorVersion;
55    } else
56    {
57        rep.majorVersion = SERVER_RANDR_MAJOR_VERSION;
58        rep.minorVersion = SERVER_RANDR_MINOR_VERSION;
59    }
60
61    if (client->swapped) {
62    	swaps(&rep.sequenceNumber, n);
63    	swapl(&rep.length, n);
64	swapl(&rep.majorVersion, n);
65	swapl(&rep.minorVersion, n);
66    }
67    WriteToClient(client, sizeof(xRRQueryVersionReply), (char *)&rep);
68    return Success;
69}
70
71static int
72ProcRRSelectInput (ClientPtr client)
73{
74    REQUEST(xRRSelectInputReq);
75    rrClientPriv(client);
76    RRTimesPtr	pTimes;
77    WindowPtr	pWin;
78    RREventPtr	pRREvent, *pHead;
79    XID		clientResource;
80    int		rc;
81
82    REQUEST_SIZE_MATCH(xRRSelectInputReq);
83    rc = dixLookupWindow(&pWin, stuff->window, client, DixReceiveAccess);
84    if (rc != Success)
85	return rc;
86    rc = dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id,
87				 RREventType, client, DixWriteAccess);
88    if (rc != Success && rc != BadValue)
89	return rc;
90
91    if (stuff->enable & (RRScreenChangeNotifyMask|
92			 RRCrtcChangeNotifyMask|
93			 RROutputChangeNotifyMask|
94			 RROutputPropertyNotifyMask))
95    {
96	ScreenPtr	pScreen = pWin->drawable.pScreen;
97	rrScrPriv	(pScreen);
98
99	pRREvent = NULL;
100	if (pHead)
101	{
102	    /* check for existing entry. */
103	    for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
104		if (pRREvent->client == client)
105		    break;
106	}
107
108	if (!pRREvent)
109	{
110	    /* build the entry */
111	    pRREvent = (RREventPtr) malloc(sizeof (RREventRec));
112	    if (!pRREvent)
113		return BadAlloc;
114	    pRREvent->next = 0;
115	    pRREvent->client = client;
116	    pRREvent->window = pWin;
117	    pRREvent->mask = stuff->enable;
118	    /*
119	     * add a resource that will be deleted when
120	     * the client goes away
121	     */
122	    clientResource = FakeClientID (client->index);
123	    pRREvent->clientResource = clientResource;
124	    if (!AddResource (clientResource, RRClientType, (pointer)pRREvent))
125		return BadAlloc;
126	    /*
127	     * create a resource to contain a pointer to the list
128	     * of clients selecting input.  This must be indirect as
129	     * the list may be arbitrarily rearranged which cannot be
130	     * done through the resource database.
131	     */
132	    if (!pHead)
133	    {
134		pHead = (RREventPtr *) malloc(sizeof (RREventPtr));
135		if (!pHead ||
136		    !AddResource (pWin->drawable.id, RREventType, (pointer)pHead))
137		{
138		    FreeResource (clientResource, RT_NONE);
139		    return BadAlloc;
140		}
141		*pHead = 0;
142	    }
143	    pRREvent->next = *pHead;
144	    *pHead = pRREvent;
145	}
146	/*
147	 * Now see if the client needs an event
148	 */
149	if (pScrPriv)
150	{
151	    pTimes = &((RRTimesPtr) (pRRClient + 1))[pScreen->myNum];
152	    if (CompareTimeStamps (pTimes->setTime,
153				   pScrPriv->lastSetTime) != 0 ||
154		CompareTimeStamps (pTimes->configTime,
155				   pScrPriv->lastConfigTime) != 0)
156	    {
157		if (pRREvent->mask & RRScreenChangeNotifyMask)
158		{
159		    RRDeliverScreenEvent (client, pWin, pScreen);
160		}
161
162		if (pRREvent->mask & RRCrtcChangeNotifyMask)
163		{
164		    int i;
165
166		    for (i = 0; i < pScrPriv->numCrtcs; i++)
167		    {
168			RRDeliverCrtcEvent (client, pWin, pScrPriv->crtcs[i]);
169		    }
170		}
171
172		if (pRREvent->mask & RROutputChangeNotifyMask)
173		{
174		    int i;
175
176		    for (i = 0; i < pScrPriv->numOutputs; i++)
177		    {
178			RRDeliverOutputEvent (client, pWin, pScrPriv->outputs[i]);
179		    }
180		}
181
182		/* We don't check for RROutputPropertyNotifyMask, as randrproto.txt doesn't
183		 * say if there ought to be notifications of changes to output properties
184		 * if those changes occurred before the time RRSelectInput is called.
185		 */
186	    }
187	}
188    }
189    else if (stuff->enable == 0)
190    {
191	/* delete the interest */
192	if (pHead) {
193	    RREventPtr pNewRREvent = 0;
194	    for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) {
195		if (pRREvent->client == client)
196		    break;
197		pNewRREvent = pRREvent;
198	    }
199	    if (pRREvent) {
200		FreeResource (pRREvent->clientResource, RRClientType);
201		if (pNewRREvent)
202		    pNewRREvent->next = pRREvent->next;
203		else
204		    *pHead = pRREvent->next;
205		free(pRREvent);
206	    }
207	}
208    }
209    else
210    {
211	client->errorValue = stuff->enable;
212	return BadValue;
213    }
214    return Success;
215}
216
217int (*ProcRandrVector[RRNumberRequests])(ClientPtr) = {
218    ProcRRQueryVersion,	/* 0 */
219/* we skip 1 to make old clients fail pretty immediately */
220    NULL,			/* 1 ProcRandrOldGetScreenInfo */
221/* V1.0 apps share the same set screen config request id */
222    ProcRRSetScreenConfig,	/* 2 */
223    NULL,			/* 3 ProcRandrOldScreenChangeSelectInput */
224/* 3 used to be ScreenChangeSelectInput; deprecated */
225    ProcRRSelectInput,		/* 4 */
226    ProcRRGetScreenInfo,    	/* 5 */
227/* V1.2 additions */
228    ProcRRGetScreenSizeRange,	/* 6 */
229    ProcRRSetScreenSize,	/* 7 */
230    ProcRRGetScreenResources,	/* 8 */
231    ProcRRGetOutputInfo,	/* 9 */
232    ProcRRListOutputProperties,	/* 10 */
233    ProcRRQueryOutputProperty,	/* 11 */
234    ProcRRConfigureOutputProperty,  /* 12 */
235    ProcRRChangeOutputProperty,	/* 13 */
236    ProcRRDeleteOutputProperty,	/* 14 */
237    ProcRRGetOutputProperty,	/* 15 */
238    ProcRRCreateMode,		/* 16 */
239    ProcRRDestroyMode,		/* 17 */
240    ProcRRAddOutputMode,	/* 18 */
241    ProcRRDeleteOutputMode,	/* 19 */
242    ProcRRGetCrtcInfo,		/* 20 */
243    ProcRRSetCrtcConfig,	/* 21 */
244    ProcRRGetCrtcGammaSize,	/* 22 */
245    ProcRRGetCrtcGamma,		/* 23 */
246    ProcRRSetCrtcGamma,		/* 24 */
247/* V1.3 additions */
248    ProcRRGetScreenResourcesCurrent, /* 25 */
249    ProcRRSetCrtcTransform,	/* 26 */
250    ProcRRGetCrtcTransform,	/* 27 */
251    ProcRRGetPanning,		/* 28 */
252    ProcRRSetPanning,		/* 29 */
253    ProcRRSetOutputPrimary,	/* 30 */
254    ProcRRGetOutputPrimary,	/* 31 */
255};
256
257