1706f2543Smrg/* 2706f2543Smrg * Copyright © 2006 Keith Packard 3706f2543Smrg * 4706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its 5706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that 6706f2543Smrg * the above copyright notice appear in all copies and that both that copyright 7706f2543Smrg * notice and this permission notice appear in supporting documentation, and 8706f2543Smrg * that the name of the copyright holders not be used in advertising or 9706f2543Smrg * publicity pertaining to distribution of the software without specific, 10706f2543Smrg * written prior permission. The copyright holders make no representations 11706f2543Smrg * about the suitability of this software for any purpose. It is provided "as 12706f2543Smrg * is" without express or implied warranty. 13706f2543Smrg * 14706f2543Smrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15706f2543Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16706f2543Smrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17706f2543Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20706f2543Smrg * OF THIS SOFTWARE. 21706f2543Smrg */ 22706f2543Smrg 23706f2543Smrg#include "randrstr.h" 24706f2543Smrg#include "protocol-versions.h" 25706f2543Smrg 26706f2543SmrgBool 27706f2543SmrgRRClientKnowsRates (ClientPtr pClient) 28706f2543Smrg{ 29706f2543Smrg rrClientPriv(pClient); 30706f2543Smrg 31706f2543Smrg return (pRRClient->major_version > 1 || 32706f2543Smrg (pRRClient->major_version == 1 && pRRClient->minor_version >= 1)); 33706f2543Smrg} 34706f2543Smrg 35706f2543Smrgstatic int 36706f2543SmrgProcRRQueryVersion (ClientPtr client) 37706f2543Smrg{ 38706f2543Smrg xRRQueryVersionReply rep = {0}; 39706f2543Smrg register int n; 40706f2543Smrg REQUEST(xRRQueryVersionReq); 41706f2543Smrg rrClientPriv(client); 42706f2543Smrg 43706f2543Smrg REQUEST_SIZE_MATCH(xRRQueryVersionReq); 44706f2543Smrg pRRClient->major_version = stuff->majorVersion; 45706f2543Smrg pRRClient->minor_version = stuff->minorVersion; 46706f2543Smrg rep.type = X_Reply; 47706f2543Smrg rep.length = 0; 48706f2543Smrg rep.sequenceNumber = client->sequence; 49706f2543Smrg 50706f2543Smrg if ((stuff->majorVersion * 1000 + stuff->minorVersion) < 51706f2543Smrg (SERVER_RANDR_MAJOR_VERSION * 1000 + SERVER_RANDR_MINOR_VERSION)) 52706f2543Smrg { 53706f2543Smrg rep.majorVersion = stuff->majorVersion; 54706f2543Smrg rep.minorVersion = stuff->minorVersion; 55706f2543Smrg } else 56706f2543Smrg { 57706f2543Smrg rep.majorVersion = SERVER_RANDR_MAJOR_VERSION; 58706f2543Smrg rep.minorVersion = SERVER_RANDR_MINOR_VERSION; 59706f2543Smrg } 60706f2543Smrg 61706f2543Smrg if (client->swapped) { 62706f2543Smrg swaps(&rep.sequenceNumber, n); 63706f2543Smrg swapl(&rep.length, n); 64706f2543Smrg swapl(&rep.majorVersion, n); 65706f2543Smrg swapl(&rep.minorVersion, n); 66706f2543Smrg } 67706f2543Smrg WriteToClient(client, sizeof(xRRQueryVersionReply), (char *)&rep); 68706f2543Smrg return Success; 69706f2543Smrg} 70706f2543Smrg 71706f2543Smrgstatic int 72706f2543SmrgProcRRSelectInput (ClientPtr client) 73706f2543Smrg{ 74706f2543Smrg REQUEST(xRRSelectInputReq); 75706f2543Smrg rrClientPriv(client); 76706f2543Smrg RRTimesPtr pTimes; 77706f2543Smrg WindowPtr pWin; 78706f2543Smrg RREventPtr pRREvent, *pHead; 79706f2543Smrg XID clientResource; 80706f2543Smrg int rc; 81706f2543Smrg 82706f2543Smrg REQUEST_SIZE_MATCH(xRRSelectInputReq); 83706f2543Smrg rc = dixLookupWindow(&pWin, stuff->window, client, DixReceiveAccess); 84706f2543Smrg if (rc != Success) 85706f2543Smrg return rc; 86706f2543Smrg rc = dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id, 87706f2543Smrg RREventType, client, DixWriteAccess); 88706f2543Smrg if (rc != Success && rc != BadValue) 89706f2543Smrg return rc; 90706f2543Smrg 91706f2543Smrg if (stuff->enable & (RRScreenChangeNotifyMask| 92706f2543Smrg RRCrtcChangeNotifyMask| 93706f2543Smrg RROutputChangeNotifyMask| 94706f2543Smrg RROutputPropertyNotifyMask)) 95706f2543Smrg { 96706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 97706f2543Smrg rrScrPriv (pScreen); 98706f2543Smrg 99706f2543Smrg pRREvent = NULL; 100706f2543Smrg if (pHead) 101706f2543Smrg { 102706f2543Smrg /* check for existing entry. */ 103706f2543Smrg for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) 104706f2543Smrg if (pRREvent->client == client) 105706f2543Smrg break; 106706f2543Smrg } 107706f2543Smrg 108706f2543Smrg if (!pRREvent) 109706f2543Smrg { 110706f2543Smrg /* build the entry */ 111706f2543Smrg pRREvent = (RREventPtr) malloc(sizeof (RREventRec)); 112706f2543Smrg if (!pRREvent) 113706f2543Smrg return BadAlloc; 114706f2543Smrg pRREvent->next = 0; 115706f2543Smrg pRREvent->client = client; 116706f2543Smrg pRREvent->window = pWin; 117706f2543Smrg pRREvent->mask = stuff->enable; 118706f2543Smrg /* 119706f2543Smrg * add a resource that will be deleted when 120706f2543Smrg * the client goes away 121706f2543Smrg */ 122706f2543Smrg clientResource = FakeClientID (client->index); 123706f2543Smrg pRREvent->clientResource = clientResource; 124706f2543Smrg if (!AddResource (clientResource, RRClientType, (pointer)pRREvent)) 125706f2543Smrg return BadAlloc; 126706f2543Smrg /* 127706f2543Smrg * create a resource to contain a pointer to the list 128706f2543Smrg * of clients selecting input. This must be indirect as 129706f2543Smrg * the list may be arbitrarily rearranged which cannot be 130706f2543Smrg * done through the resource database. 131706f2543Smrg */ 132706f2543Smrg if (!pHead) 133706f2543Smrg { 134706f2543Smrg pHead = (RREventPtr *) malloc(sizeof (RREventPtr)); 135706f2543Smrg if (!pHead || 136706f2543Smrg !AddResource (pWin->drawable.id, RREventType, (pointer)pHead)) 137706f2543Smrg { 138706f2543Smrg FreeResource (clientResource, RT_NONE); 139706f2543Smrg return BadAlloc; 140706f2543Smrg } 141706f2543Smrg *pHead = 0; 142706f2543Smrg } 143706f2543Smrg pRREvent->next = *pHead; 144706f2543Smrg *pHead = pRREvent; 145706f2543Smrg } 146706f2543Smrg /* 147706f2543Smrg * Now see if the client needs an event 148706f2543Smrg */ 149706f2543Smrg if (pScrPriv) 150706f2543Smrg { 151706f2543Smrg pTimes = &((RRTimesPtr) (pRRClient + 1))[pScreen->myNum]; 152706f2543Smrg if (CompareTimeStamps (pTimes->setTime, 153706f2543Smrg pScrPriv->lastSetTime) != 0 || 154706f2543Smrg CompareTimeStamps (pTimes->configTime, 155706f2543Smrg pScrPriv->lastConfigTime) != 0) 156706f2543Smrg { 157706f2543Smrg if (pRREvent->mask & RRScreenChangeNotifyMask) 158706f2543Smrg { 159706f2543Smrg RRDeliverScreenEvent (client, pWin, pScreen); 160706f2543Smrg } 161706f2543Smrg 162706f2543Smrg if (pRREvent->mask & RRCrtcChangeNotifyMask) 163706f2543Smrg { 164706f2543Smrg int i; 165706f2543Smrg 166706f2543Smrg for (i = 0; i < pScrPriv->numCrtcs; i++) 167706f2543Smrg { 168706f2543Smrg RRDeliverCrtcEvent (client, pWin, pScrPriv->crtcs[i]); 169706f2543Smrg } 170706f2543Smrg } 171706f2543Smrg 172706f2543Smrg if (pRREvent->mask & RROutputChangeNotifyMask) 173706f2543Smrg { 174706f2543Smrg int i; 175706f2543Smrg 176706f2543Smrg for (i = 0; i < pScrPriv->numOutputs; i++) 177706f2543Smrg { 178706f2543Smrg RRDeliverOutputEvent (client, pWin, pScrPriv->outputs[i]); 179706f2543Smrg } 180706f2543Smrg } 181706f2543Smrg 182706f2543Smrg /* We don't check for RROutputPropertyNotifyMask, as randrproto.txt doesn't 183706f2543Smrg * say if there ought to be notifications of changes to output properties 184706f2543Smrg * if those changes occurred before the time RRSelectInput is called. 185706f2543Smrg */ 186706f2543Smrg } 187706f2543Smrg } 188706f2543Smrg } 189706f2543Smrg else if (stuff->enable == 0) 190706f2543Smrg { 191706f2543Smrg /* delete the interest */ 192706f2543Smrg if (pHead) { 193706f2543Smrg RREventPtr pNewRREvent = 0; 194706f2543Smrg for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) { 195706f2543Smrg if (pRREvent->client == client) 196706f2543Smrg break; 197706f2543Smrg pNewRREvent = pRREvent; 198706f2543Smrg } 199706f2543Smrg if (pRREvent) { 200706f2543Smrg FreeResource (pRREvent->clientResource, RRClientType); 201706f2543Smrg if (pNewRREvent) 202706f2543Smrg pNewRREvent->next = pRREvent->next; 203706f2543Smrg else 204706f2543Smrg *pHead = pRREvent->next; 205706f2543Smrg free(pRREvent); 206706f2543Smrg } 207706f2543Smrg } 208706f2543Smrg } 209706f2543Smrg else 210706f2543Smrg { 211706f2543Smrg client->errorValue = stuff->enable; 212706f2543Smrg return BadValue; 213706f2543Smrg } 214706f2543Smrg return Success; 215706f2543Smrg} 216706f2543Smrg 217706f2543Smrgint (*ProcRandrVector[RRNumberRequests])(ClientPtr) = { 218706f2543Smrg ProcRRQueryVersion, /* 0 */ 219706f2543Smrg/* we skip 1 to make old clients fail pretty immediately */ 220706f2543Smrg NULL, /* 1 ProcRandrOldGetScreenInfo */ 221706f2543Smrg/* V1.0 apps share the same set screen config request id */ 222706f2543Smrg ProcRRSetScreenConfig, /* 2 */ 223706f2543Smrg NULL, /* 3 ProcRandrOldScreenChangeSelectInput */ 224706f2543Smrg/* 3 used to be ScreenChangeSelectInput; deprecated */ 225706f2543Smrg ProcRRSelectInput, /* 4 */ 226706f2543Smrg ProcRRGetScreenInfo, /* 5 */ 227706f2543Smrg/* V1.2 additions */ 228706f2543Smrg ProcRRGetScreenSizeRange, /* 6 */ 229706f2543Smrg ProcRRSetScreenSize, /* 7 */ 230706f2543Smrg ProcRRGetScreenResources, /* 8 */ 231706f2543Smrg ProcRRGetOutputInfo, /* 9 */ 232706f2543Smrg ProcRRListOutputProperties, /* 10 */ 233706f2543Smrg ProcRRQueryOutputProperty, /* 11 */ 234706f2543Smrg ProcRRConfigureOutputProperty, /* 12 */ 235706f2543Smrg ProcRRChangeOutputProperty, /* 13 */ 236706f2543Smrg ProcRRDeleteOutputProperty, /* 14 */ 237706f2543Smrg ProcRRGetOutputProperty, /* 15 */ 238706f2543Smrg ProcRRCreateMode, /* 16 */ 239706f2543Smrg ProcRRDestroyMode, /* 17 */ 240706f2543Smrg ProcRRAddOutputMode, /* 18 */ 241706f2543Smrg ProcRRDeleteOutputMode, /* 19 */ 242706f2543Smrg ProcRRGetCrtcInfo, /* 20 */ 243706f2543Smrg ProcRRSetCrtcConfig, /* 21 */ 244706f2543Smrg ProcRRGetCrtcGammaSize, /* 22 */ 245706f2543Smrg ProcRRGetCrtcGamma, /* 23 */ 246706f2543Smrg ProcRRSetCrtcGamma, /* 24 */ 247706f2543Smrg/* V1.3 additions */ 248706f2543Smrg ProcRRGetScreenResourcesCurrent, /* 25 */ 249706f2543Smrg ProcRRSetCrtcTransform, /* 26 */ 250706f2543Smrg ProcRRGetCrtcTransform, /* 27 */ 251706f2543Smrg ProcRRGetPanning, /* 28 */ 252706f2543Smrg ProcRRSetPanning, /* 29 */ 253706f2543Smrg ProcRRSetOutputPrimary, /* 30 */ 254706f2543Smrg ProcRRGetOutputPrimary, /* 31 */ 255706f2543Smrg}; 256706f2543Smrg 257