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 version_compare(pRRClient->major_version, pRRClient->minor_version, 32 1, 1) >= 0; 33} 34 35static int 36ProcRRQueryVersion(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 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((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 210int (*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