Commit | Line | Data |
---|---|---|
a09e091a JB |
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 | |
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 | |
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 | |
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((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 | RRProviderPropertyNotifyMask)) { | |
96 | ScreenPtr pScreen = pWin->drawable.pScreen; | |
97 | ||
98 | rrScrPriv(pScreen); | |
99 | ||
100 | pRREvent = NULL; | |
101 | if (pHead) { | |
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 | /* build the entry */ | |
110 | pRREvent = (RREventPtr) malloc(sizeof(RREventRec)); | |
111 | if (!pRREvent) | |
112 | return BadAlloc; | |
113 | pRREvent->next = 0; | |
114 | pRREvent->client = client; | |
115 | pRREvent->window = pWin; | |
116 | pRREvent->mask = stuff->enable; | |
117 | /* | |
118 | * add a resource that will be deleted when | |
119 | * the client goes away | |
120 | */ | |
121 | clientResource = FakeClientID(client->index); | |
122 | pRREvent->clientResource = clientResource; | |
123 | if (!AddResource(clientResource, RRClientType, (pointer) pRREvent)) | |
124 | return BadAlloc; | |
125 | /* | |
126 | * create a resource to contain a pointer to the list | |
127 | * of clients selecting input. This must be indirect as | |
128 | * the list may be arbitrarily rearranged which cannot be | |
129 | * done through the resource database. | |
130 | */ | |
131 | if (!pHead) { | |
132 | pHead = (RREventPtr *) malloc(sizeof(RREventPtr)); | |
133 | if (!pHead || | |
134 | !AddResource(pWin->drawable.id, RREventType, | |
135 | (pointer) pHead)) { | |
136 | FreeResource(clientResource, RT_NONE); | |
137 | return BadAlloc; | |
138 | } | |
139 | *pHead = 0; | |
140 | } | |
141 | pRREvent->next = *pHead; | |
142 | *pHead = pRREvent; | |
143 | } | |
144 | /* | |
145 | * Now see if the client needs an event | |
146 | */ | |
147 | if (pScrPriv) { | |
148 | pTimes = &((RRTimesPtr) (pRRClient + 1))[pScreen->myNum]; | |
149 | if (CompareTimeStamps(pTimes->setTime, | |
150 | pScrPriv->lastSetTime) != 0 || | |
151 | CompareTimeStamps(pTimes->configTime, | |
152 | pScrPriv->lastConfigTime) != 0) { | |
153 | if (pRREvent->mask & RRScreenChangeNotifyMask) { | |
154 | RRDeliverScreenEvent(client, pWin, pScreen); | |
155 | } | |
156 | ||
157 | if (pRREvent->mask & RRCrtcChangeNotifyMask) { | |
158 | int i; | |
159 | ||
160 | for (i = 0; i < pScrPriv->numCrtcs; i++) { | |
161 | RRDeliverCrtcEvent(client, pWin, pScrPriv->crtcs[i]); | |
162 | } | |
163 | } | |
164 | ||
165 | if (pRREvent->mask & RROutputChangeNotifyMask) { | |
166 | int i; | |
167 | ||
168 | for (i = 0; i < pScrPriv->numOutputs; i++) { | |
169 | RRDeliverOutputEvent(client, pWin, | |
170 | pScrPriv->outputs[i]); | |
171 | } | |
172 | } | |
173 | ||
174 | /* We don't check for RROutputPropertyNotifyMask, as randrproto.txt doesn't | |
175 | * say if there ought to be notifications of changes to output properties | |
176 | * if those changes occurred before the time RRSelectInput is called. | |
177 | */ | |
178 | } | |
179 | } | |
180 | } | |
181 | else if (stuff->enable == 0) { | |
182 | /* delete the interest */ | |
183 | if (pHead) { | |
184 | RREventPtr pNewRREvent = 0; | |
185 | ||
186 | for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) { | |
187 | if (pRREvent->client == client) | |
188 | break; | |
189 | pNewRREvent = pRREvent; | |
190 | } | |
191 | if (pRREvent) { | |
192 | FreeResource(pRREvent->clientResource, RRClientType); | |
193 | if (pNewRREvent) | |
194 | pNewRREvent->next = pRREvent->next; | |
195 | else | |
196 | *pHead = pRREvent->next; | |
197 | free(pRREvent); | |
198 | } | |
199 | } | |
200 | } | |
201 | else { | |
202 | client->errorValue = stuff->enable; | |
203 | return BadValue; | |
204 | } | |
205 | return Success; | |
206 | } | |
207 | ||
208 | int (*ProcRandrVector[RRNumberRequests]) (ClientPtr) = { | |
209 | ProcRRQueryVersion, /* 0 */ | |
210 | /* we skip 1 to make old clients fail pretty immediately */ | |
211 | NULL, /* 1 ProcRandrOldGetScreenInfo */ | |
212 | /* V1.0 apps share the same set screen config request id */ | |
213 | ProcRRSetScreenConfig, /* 2 */ | |
214 | NULL, /* 3 ProcRandrOldScreenChangeSelectInput */ | |
215 | /* 3 used to be ScreenChangeSelectInput; deprecated */ | |
216 | ProcRRSelectInput, /* 4 */ | |
217 | ProcRRGetScreenInfo, /* 5 */ | |
218 | /* V1.2 additions */ | |
219 | ProcRRGetScreenSizeRange, /* 6 */ | |
220 | ProcRRSetScreenSize, /* 7 */ | |
221 | ProcRRGetScreenResources, /* 8 */ | |
222 | ProcRRGetOutputInfo, /* 9 */ | |
223 | ProcRRListOutputProperties, /* 10 */ | |
224 | ProcRRQueryOutputProperty, /* 11 */ | |
225 | ProcRRConfigureOutputProperty, /* 12 */ | |
226 | ProcRRChangeOutputProperty, /* 13 */ | |
227 | ProcRRDeleteOutputProperty, /* 14 */ | |
228 | ProcRRGetOutputProperty, /* 15 */ | |
229 | ProcRRCreateMode, /* 16 */ | |
230 | ProcRRDestroyMode, /* 17 */ | |
231 | ProcRRAddOutputMode, /* 18 */ | |
232 | ProcRRDeleteOutputMode, /* 19 */ | |
233 | ProcRRGetCrtcInfo, /* 20 */ | |
234 | ProcRRSetCrtcConfig, /* 21 */ | |
235 | ProcRRGetCrtcGammaSize, /* 22 */ | |
236 | ProcRRGetCrtcGamma, /* 23 */ | |
237 | ProcRRSetCrtcGamma, /* 24 */ | |
238 | /* V1.3 additions */ | |
239 | ProcRRGetScreenResourcesCurrent, /* 25 */ | |
240 | ProcRRSetCrtcTransform, /* 26 */ | |
241 | ProcRRGetCrtcTransform, /* 27 */ | |
242 | ProcRRGetPanning, /* 28 */ | |
243 | ProcRRSetPanning, /* 29 */ | |
244 | ProcRRSetOutputPrimary, /* 30 */ | |
245 | ProcRRGetOutputPrimary, /* 31 */ | |
246 | /* V1.4 additions */ | |
247 | ProcRRGetProviders, /* 32 */ | |
248 | ProcRRGetProviderInfo, /* 33 */ | |
249 | ProcRRSetProviderOffloadSink, /* 34 */ | |
250 | ProcRRSetProviderOutputSource, /* 35 */ | |
251 | ProcRRListProviderProperties, /* 36 */ | |
252 | ProcRRQueryProviderProperty, /* 37 */ | |
253 | ProcRRConfigureProviderProperty, /* 38 */ | |
254 | ProcRRChangeProviderProperty, /* 39 */ | |
255 | ProcRRDeleteProviderProperty, /* 40 */ | |
256 | ProcRRGetProviderProperty, /* 41 */ | |
257 | }; |