rrdispatch.c revision 05b261ec
105b261ecSmrg/* 205b261ecSmrg * Copyright © 2006 Keith Packard 305b261ecSmrg * 405b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its 505b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that 605b261ecSmrg * the above copyright notice appear in all copies and that both that copyright 705b261ecSmrg * notice and this permission notice appear in supporting documentation, and 805b261ecSmrg * that the name of the copyright holders not be used in advertising or 905b261ecSmrg * publicity pertaining to distribution of the software without specific, 1005b261ecSmrg * written prior permission. The copyright holders make no representations 1105b261ecSmrg * about the suitability of this software for any purpose. It is provided "as 1205b261ecSmrg * is" without express or implied warranty. 1305b261ecSmrg * 1405b261ecSmrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1505b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1605b261ecSmrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1705b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1805b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 1905b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 2005b261ecSmrg * OF THIS SOFTWARE. 2105b261ecSmrg */ 2205b261ecSmrg 2305b261ecSmrg#include "randrstr.h" 2405b261ecSmrg 2505b261ecSmrg#define SERVER_RANDR_MAJOR 1 2605b261ecSmrg#define SERVER_RANDR_MINOR 2 2705b261ecSmrg 2805b261ecSmrgBool 2905b261ecSmrgRRClientKnowsRates (ClientPtr pClient) 3005b261ecSmrg{ 3105b261ecSmrg rrClientPriv(pClient); 3205b261ecSmrg 3305b261ecSmrg return (pRRClient->major_version > 1 || 3405b261ecSmrg (pRRClient->major_version == 1 && pRRClient->minor_version >= 1)); 3505b261ecSmrg} 3605b261ecSmrg 3705b261ecSmrgstatic int 3805b261ecSmrgProcRRQueryVersion (ClientPtr client) 3905b261ecSmrg{ 4005b261ecSmrg xRRQueryVersionReply rep; 4105b261ecSmrg register int n; 4205b261ecSmrg REQUEST(xRRQueryVersionReq); 4305b261ecSmrg rrClientPriv(client); 4405b261ecSmrg 4505b261ecSmrg REQUEST_SIZE_MATCH(xRRQueryVersionReq); 4605b261ecSmrg pRRClient->major_version = stuff->majorVersion; 4705b261ecSmrg pRRClient->minor_version = stuff->minorVersion; 4805b261ecSmrg rep.type = X_Reply; 4905b261ecSmrg rep.length = 0; 5005b261ecSmrg rep.sequenceNumber = client->sequence; 5105b261ecSmrg /* 5205b261ecSmrg * Report the current version; the current 5305b261ecSmrg * spec says they're all compatible after 1.0 5405b261ecSmrg */ 5505b261ecSmrg rep.majorVersion = SERVER_RANDR_MAJOR; 5605b261ecSmrg rep.minorVersion = SERVER_RANDR_MINOR; 5705b261ecSmrg if (client->swapped) { 5805b261ecSmrg swaps(&rep.sequenceNumber, n); 5905b261ecSmrg swapl(&rep.length, n); 6005b261ecSmrg swapl(&rep.majorVersion, n); 6105b261ecSmrg swapl(&rep.minorVersion, n); 6205b261ecSmrg } 6305b261ecSmrg WriteToClient(client, sizeof(xRRQueryVersionReply), (char *)&rep); 6405b261ecSmrg return (client->noClientException); 6505b261ecSmrg} 6605b261ecSmrg 6705b261ecSmrgstatic int 6805b261ecSmrgProcRRSelectInput (ClientPtr client) 6905b261ecSmrg{ 7005b261ecSmrg REQUEST(xRRSelectInputReq); 7105b261ecSmrg rrClientPriv(client); 7205b261ecSmrg RRTimesPtr pTimes; 7305b261ecSmrg WindowPtr pWin; 7405b261ecSmrg RREventPtr pRREvent, *pHead; 7505b261ecSmrg XID clientResource; 7605b261ecSmrg int rc; 7705b261ecSmrg 7805b261ecSmrg REQUEST_SIZE_MATCH(xRRSelectInputReq); 7905b261ecSmrg rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess); 8005b261ecSmrg if (rc != Success) 8105b261ecSmrg return rc; 8205b261ecSmrg pHead = (RREventPtr *)SecurityLookupIDByType(client, 8305b261ecSmrg pWin->drawable.id, RREventType, 8405b261ecSmrg DixWriteAccess); 8505b261ecSmrg 8605b261ecSmrg if (stuff->enable & (RRScreenChangeNotifyMask| 8705b261ecSmrg RRCrtcChangeNotifyMask| 8805b261ecSmrg RROutputChangeNotifyMask)) 8905b261ecSmrg { 9005b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 9105b261ecSmrg rrScrPriv (pScreen); 9205b261ecSmrg 9305b261ecSmrg pRREvent = NULL; 9405b261ecSmrg if (pHead) 9505b261ecSmrg { 9605b261ecSmrg /* check for existing entry. */ 9705b261ecSmrg for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) 9805b261ecSmrg if (pRREvent->client == client) 9905b261ecSmrg break; 10005b261ecSmrg } 10105b261ecSmrg 10205b261ecSmrg if (!pRREvent) 10305b261ecSmrg { 10405b261ecSmrg /* build the entry */ 10505b261ecSmrg pRREvent = (RREventPtr) xalloc (sizeof (RREventRec)); 10605b261ecSmrg if (!pRREvent) 10705b261ecSmrg return BadAlloc; 10805b261ecSmrg pRREvent->next = 0; 10905b261ecSmrg pRREvent->client = client; 11005b261ecSmrg pRREvent->window = pWin; 11105b261ecSmrg pRREvent->mask = stuff->enable; 11205b261ecSmrg /* 11305b261ecSmrg * add a resource that will be deleted when 11405b261ecSmrg * the client goes away 11505b261ecSmrg */ 11605b261ecSmrg clientResource = FakeClientID (client->index); 11705b261ecSmrg pRREvent->clientResource = clientResource; 11805b261ecSmrg if (!AddResource (clientResource, RRClientType, (pointer)pRREvent)) 11905b261ecSmrg return BadAlloc; 12005b261ecSmrg /* 12105b261ecSmrg * create a resource to contain a pointer to the list 12205b261ecSmrg * of clients selecting input. This must be indirect as 12305b261ecSmrg * the list may be arbitrarily rearranged which cannot be 12405b261ecSmrg * done through the resource database. 12505b261ecSmrg */ 12605b261ecSmrg if (!pHead) 12705b261ecSmrg { 12805b261ecSmrg pHead = (RREventPtr *) xalloc (sizeof (RREventPtr)); 12905b261ecSmrg if (!pHead || 13005b261ecSmrg !AddResource (pWin->drawable.id, RREventType, (pointer)pHead)) 13105b261ecSmrg { 13205b261ecSmrg FreeResource (clientResource, RT_NONE); 13305b261ecSmrg return BadAlloc; 13405b261ecSmrg } 13505b261ecSmrg *pHead = 0; 13605b261ecSmrg } 13705b261ecSmrg pRREvent->next = *pHead; 13805b261ecSmrg *pHead = pRREvent; 13905b261ecSmrg } 14005b261ecSmrg /* 14105b261ecSmrg * Now see if the client needs an event 14205b261ecSmrg */ 14305b261ecSmrg if (pScrPriv && (pRREvent->mask & RRScreenChangeNotifyMask)) 14405b261ecSmrg { 14505b261ecSmrg pTimes = &((RRTimesPtr) (pRRClient + 1))[pScreen->myNum]; 14605b261ecSmrg if (CompareTimeStamps (pTimes->setTime, 14705b261ecSmrg pScrPriv->lastSetTime) != 0 || 14805b261ecSmrg CompareTimeStamps (pTimes->configTime, 14905b261ecSmrg pScrPriv->lastConfigTime) != 0) 15005b261ecSmrg { 15105b261ecSmrg RRDeliverScreenEvent (client, pWin, pScreen); 15205b261ecSmrg } 15305b261ecSmrg } 15405b261ecSmrg } 15505b261ecSmrg else if (stuff->enable == 0) 15605b261ecSmrg { 15705b261ecSmrg /* delete the interest */ 15805b261ecSmrg if (pHead) { 15905b261ecSmrg RREventPtr pNewRREvent = 0; 16005b261ecSmrg for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) { 16105b261ecSmrg if (pRREvent->client == client) 16205b261ecSmrg break; 16305b261ecSmrg pNewRREvent = pRREvent; 16405b261ecSmrg } 16505b261ecSmrg if (pRREvent) { 16605b261ecSmrg FreeResource (pRREvent->clientResource, RRClientType); 16705b261ecSmrg if (pNewRREvent) 16805b261ecSmrg pNewRREvent->next = pRREvent->next; 16905b261ecSmrg else 17005b261ecSmrg *pHead = pRREvent->next; 17105b261ecSmrg xfree (pRREvent); 17205b261ecSmrg } 17305b261ecSmrg } 17405b261ecSmrg } 17505b261ecSmrg else 17605b261ecSmrg { 17705b261ecSmrg client->errorValue = stuff->enable; 17805b261ecSmrg return BadValue; 17905b261ecSmrg } 18005b261ecSmrg return Success; 18105b261ecSmrg} 18205b261ecSmrg 18305b261ecSmrgint (*ProcRandrVector[RRNumberRequests])(ClientPtr) = { 18405b261ecSmrg ProcRRQueryVersion, /* 0 */ 18505b261ecSmrg/* we skip 1 to make old clients fail pretty immediately */ 18605b261ecSmrg NULL, /* 1 ProcRandrOldGetScreenInfo */ 18705b261ecSmrg/* V1.0 apps share the same set screen config request id */ 18805b261ecSmrg ProcRRSetScreenConfig, /* 2 */ 18905b261ecSmrg NULL, /* 3 ProcRandrOldScreenChangeSelectInput */ 19005b261ecSmrg/* 3 used to be ScreenChangeSelectInput; deprecated */ 19105b261ecSmrg ProcRRSelectInput, /* 4 */ 19205b261ecSmrg ProcRRGetScreenInfo, /* 5 */ 19305b261ecSmrg/* V1.2 additions */ 19405b261ecSmrg ProcRRGetScreenSizeRange, /* 6 */ 19505b261ecSmrg ProcRRSetScreenSize, /* 7 */ 19605b261ecSmrg ProcRRGetScreenResources, /* 8 */ 19705b261ecSmrg ProcRRGetOutputInfo, /* 9 */ 19805b261ecSmrg ProcRRListOutputProperties, /* 10 */ 19905b261ecSmrg ProcRRQueryOutputProperty, /* 11 */ 20005b261ecSmrg ProcRRConfigureOutputProperty, /* 12 */ 20105b261ecSmrg ProcRRChangeOutputProperty, /* 13 */ 20205b261ecSmrg ProcRRDeleteOutputProperty, /* 14 */ 20305b261ecSmrg ProcRRGetOutputProperty, /* 15 */ 20405b261ecSmrg ProcRRCreateMode, /* 16 */ 20505b261ecSmrg ProcRRDestroyMode, /* 17 */ 20605b261ecSmrg ProcRRAddOutputMode, /* 18 */ 20705b261ecSmrg ProcRRDeleteOutputMode, /* 19 */ 20805b261ecSmrg ProcRRGetCrtcInfo, /* 20 */ 20905b261ecSmrg ProcRRSetCrtcConfig, /* 21 */ 21005b261ecSmrg ProcRRGetCrtcGammaSize, /* 22 */ 21105b261ecSmrg ProcRRGetCrtcGamma, /* 23 */ 21205b261ecSmrg ProcRRSetCrtcGamma, /* 24 */ 21305b261ecSmrg}; 21405b261ecSmrg 215