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