xref: /OK3568_Linux_fs/external/xserver/randr/rrdispatch.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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