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