256 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			256 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * Copyright © 2006 Keith Packard
 | |
|  *
 | |
|  * Permission to use, copy, modify, distribute, and sell this software and its
 | |
|  * documentation for any purpose is hereby granted without fee, provided that
 | |
|  * the above copyright notice appear in all copies and that both that copyright
 | |
|  * notice and this permission notice appear in supporting documentation, and
 | |
|  * that the name of the copyright holders not be used in advertising or
 | |
|  * publicity pertaining to distribution of the software without specific,
 | |
|  * written prior permission.  The copyright holders make no representations
 | |
|  * about the suitability of this software for any purpose.  It is provided "as
 | |
|  * is" without express or implied warranty.
 | |
|  *
 | |
|  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 | |
|  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 | |
|  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 | |
|  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 | |
|  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 | |
|  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
 | |
|  * OF THIS SOFTWARE.
 | |
|  */
 | |
| 
 | |
| #include "randrstr.h"
 | |
| #include "protocol-versions.h"
 | |
| 
 | |
| Bool
 | |
| RRClientKnowsRates (ClientPtr	pClient)
 | |
| {
 | |
|     rrClientPriv(pClient);
 | |
| 
 | |
|     return version_compare(pRRClient->major_version, pRRClient->minor_version,
 | |
|                            1, 1) >= 0;
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcRRQueryVersion (ClientPtr client)
 | |
| {
 | |
|     xRRQueryVersionReply rep = {0};
 | |
|     REQUEST(xRRQueryVersionReq);
 | |
|     rrClientPriv(client);
 | |
| 
 | |
|     REQUEST_SIZE_MATCH(xRRQueryVersionReq);
 | |
|     pRRClient->major_version = stuff->majorVersion;
 | |
|     pRRClient->minor_version = stuff->minorVersion;
 | |
|     rep.type = X_Reply;
 | |
|     rep.length = 0;
 | |
|     rep.sequenceNumber = client->sequence;
 | |
| 
 | |
|     if (version_compare(stuff->majorVersion, stuff->minorVersion,
 | |
|                         SERVER_RANDR_MAJOR_VERSION, SERVER_RANDR_MINOR_VERSION) < 0)
 | |
|     {
 | |
| 	rep.majorVersion = stuff->majorVersion;
 | |
| 	rep.minorVersion = stuff->minorVersion;
 | |
|     } else
 | |
|     {
 | |
|         rep.majorVersion = SERVER_RANDR_MAJOR_VERSION;
 | |
|         rep.minorVersion = SERVER_RANDR_MINOR_VERSION;
 | |
|     }
 | |
| 
 | |
|     if (client->swapped) {
 | |
| 	swaps(&rep.sequenceNumber);
 | |
| 	swapl(&rep.length);
 | |
| 	swapl(&rep.majorVersion);
 | |
| 	swapl(&rep.minorVersion);
 | |
|     }
 | |
|     WriteToClient(client, sizeof(xRRQueryVersionReply), (char *)&rep);
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcRRSelectInput (ClientPtr client)
 | |
| {
 | |
|     REQUEST(xRRSelectInputReq);
 | |
|     rrClientPriv(client);
 | |
|     RRTimesPtr	pTimes;
 | |
|     WindowPtr	pWin;
 | |
|     RREventPtr	pRREvent, *pHead;
 | |
|     XID		clientResource;
 | |
|     int		rc;
 | |
| 
 | |
|     REQUEST_SIZE_MATCH(xRRSelectInputReq);
 | |
|     rc = dixLookupWindow(&pWin, stuff->window, client, DixReceiveAccess);
 | |
|     if (rc != Success)
 | |
| 	return rc;
 | |
|     rc = dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id,
 | |
| 				 RREventType, client, DixWriteAccess);
 | |
|     if (rc != Success && rc != BadValue)
 | |
| 	return rc;
 | |
| 
 | |
|     if (stuff->enable & (RRScreenChangeNotifyMask|
 | |
| 			 RRCrtcChangeNotifyMask|
 | |
| 			 RROutputChangeNotifyMask|
 | |
| 			 RROutputPropertyNotifyMask)) 
 | |
|     {
 | |
| 	ScreenPtr	pScreen = pWin->drawable.pScreen;
 | |
| 	rrScrPriv	(pScreen);
 | |
| 
 | |
| 	pRREvent = NULL;
 | |
| 	if (pHead) 
 | |
| 	{
 | |
| 	    /* check for existing entry. */
 | |
| 	    for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
 | |
| 		if (pRREvent->client == client)
 | |
| 		    break;
 | |
| 	}
 | |
| 
 | |
| 	if (!pRREvent)
 | |
| 	{
 | |
| 	    /* build the entry */
 | |
| 	    pRREvent = (RREventPtr) malloc(sizeof (RREventRec));
 | |
| 	    if (!pRREvent)
 | |
| 		return BadAlloc;
 | |
| 	    pRREvent->next = 0;
 | |
| 	    pRREvent->client = client;
 | |
| 	    pRREvent->window = pWin;
 | |
| 	    pRREvent->mask = stuff->enable;
 | |
| 	    /*
 | |
| 	     * add a resource that will be deleted when
 | |
| 	     * the client goes away
 | |
| 	     */
 | |
| 	    clientResource = FakeClientID (client->index);
 | |
| 	    pRREvent->clientResource = clientResource;
 | |
| 	    if (!AddResource (clientResource, RRClientType, (pointer)pRREvent))
 | |
| 		return BadAlloc;
 | |
| 	    /*
 | |
| 	     * create a resource to contain a pointer to the list
 | |
| 	     * of clients selecting input.  This must be indirect as
 | |
| 	     * the list may be arbitrarily rearranged which cannot be
 | |
| 	     * done through the resource database.
 | |
| 	     */
 | |
| 	    if (!pHead)
 | |
| 	    {
 | |
| 		pHead = (RREventPtr *) malloc(sizeof (RREventPtr));
 | |
| 		if (!pHead ||
 | |
| 		    !AddResource (pWin->drawable.id, RREventType, (pointer)pHead))
 | |
| 		{
 | |
| 		    FreeResource (clientResource, RT_NONE);
 | |
| 		    return BadAlloc;
 | |
| 		}
 | |
| 		*pHead = 0;
 | |
| 	    }
 | |
| 	    pRREvent->next = *pHead;
 | |
| 	    *pHead = pRREvent;
 | |
| 	}
 | |
| 	/*
 | |
| 	 * Now see if the client needs an event
 | |
| 	 */
 | |
| 	if (pScrPriv)
 | |
| 	{
 | |
| 	    pTimes = &((RRTimesPtr) (pRRClient + 1))[pScreen->myNum];
 | |
| 	    if (CompareTimeStamps (pTimes->setTime, 
 | |
| 				   pScrPriv->lastSetTime) != 0 ||
 | |
| 		CompareTimeStamps (pTimes->configTime, 
 | |
| 				   pScrPriv->lastConfigTime) != 0)
 | |
| 	    {
 | |
| 		if (pRREvent->mask & RRScreenChangeNotifyMask)
 | |
| 		{
 | |
| 		    RRDeliverScreenEvent (client, pWin, pScreen);
 | |
| 		}
 | |
| 
 | |
| 		if (pRREvent->mask & RRCrtcChangeNotifyMask)
 | |
| 		{
 | |
| 		    int i;
 | |
| 
 | |
| 		    for (i = 0; i < pScrPriv->numCrtcs; i++)
 | |
| 		    {
 | |
| 			RRDeliverCrtcEvent (client, pWin, pScrPriv->crtcs[i]);
 | |
| 		    }
 | |
| 		}
 | |
| 
 | |
| 		if (pRREvent->mask & RROutputChangeNotifyMask)
 | |
| 		{
 | |
| 		    int i;
 | |
| 
 | |
| 		    for (i = 0; i < pScrPriv->numOutputs; i++)
 | |
| 		    {
 | |
| 			RRDeliverOutputEvent (client, pWin, pScrPriv->outputs[i]);
 | |
| 		    }
 | |
| 		}
 | |
| 
 | |
| 		/* We don't check for RROutputPropertyNotifyMask, as randrproto.txt doesn't
 | |
| 		 * say if there ought to be notifications of changes to output properties
 | |
| 		 * if those changes occurred before the time RRSelectInput is called.
 | |
| 		 */
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
|     else if (stuff->enable == 0) 
 | |
|     {
 | |
| 	/* delete the interest */
 | |
| 	if (pHead) {
 | |
| 	    RREventPtr pNewRREvent = 0;
 | |
| 	    for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) {
 | |
| 		if (pRREvent->client == client)
 | |
| 		    break;
 | |
| 		pNewRREvent = pRREvent;
 | |
| 	    }
 | |
| 	    if (pRREvent) {
 | |
| 		FreeResource (pRREvent->clientResource, RRClientType);
 | |
| 		if (pNewRREvent)
 | |
| 		    pNewRREvent->next = pRREvent->next;
 | |
| 		else
 | |
| 		    *pHead = pRREvent->next;
 | |
| 		free(pRREvent);
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
|     else 
 | |
|     {
 | |
| 	client->errorValue = stuff->enable;
 | |
| 	return BadValue;
 | |
|     }
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| int (*ProcRandrVector[RRNumberRequests])(ClientPtr) = {
 | |
|     ProcRRQueryVersion,	/* 0 */
 | |
| /* we skip 1 to make old clients fail pretty immediately */
 | |
|     NULL,			/* 1 ProcRandrOldGetScreenInfo */
 | |
| /* V1.0 apps share the same set screen config request id */
 | |
|     ProcRRSetScreenConfig,	/* 2 */
 | |
|     NULL,			/* 3 ProcRandrOldScreenChangeSelectInput */
 | |
| /* 3 used to be ScreenChangeSelectInput; deprecated */
 | |
|     ProcRRSelectInput,		/* 4 */
 | |
|     ProcRRGetScreenInfo,    	/* 5 */
 | |
| /* V1.2 additions */
 | |
|     ProcRRGetScreenSizeRange,	/* 6 */
 | |
|     ProcRRSetScreenSize,	/* 7 */
 | |
|     ProcRRGetScreenResources,	/* 8 */
 | |
|     ProcRRGetOutputInfo,	/* 9 */
 | |
|     ProcRRListOutputProperties,	/* 10 */
 | |
|     ProcRRQueryOutputProperty,	/* 11 */
 | |
|     ProcRRConfigureOutputProperty,  /* 12 */
 | |
|     ProcRRChangeOutputProperty,	/* 13 */
 | |
|     ProcRRDeleteOutputProperty,	/* 14 */
 | |
|     ProcRRGetOutputProperty,	/* 15 */
 | |
|     ProcRRCreateMode,		/* 16 */
 | |
|     ProcRRDestroyMode,		/* 17 */
 | |
|     ProcRRAddOutputMode,	/* 18 */
 | |
|     ProcRRDeleteOutputMode,	/* 19 */
 | |
|     ProcRRGetCrtcInfo,		/* 20 */
 | |
|     ProcRRSetCrtcConfig,	/* 21 */
 | |
|     ProcRRGetCrtcGammaSize,	/* 22 */
 | |
|     ProcRRGetCrtcGamma,		/* 23 */
 | |
|     ProcRRSetCrtcGamma,		/* 24 */
 | |
| /* V1.3 additions */
 | |
|     ProcRRGetScreenResourcesCurrent, /* 25 */
 | |
|     ProcRRSetCrtcTransform,	/* 26 */
 | |
|     ProcRRGetCrtcTransform,	/* 27 */
 | |
|     ProcRRGetPanning,		/* 28 */
 | |
|     ProcRRSetPanning,		/* 29 */
 | |
|     ProcRRSetOutputPrimary,	/* 30 */
 | |
|     ProcRRGetOutputPrimary,	/* 31 */
 | |
| };
 | |
| 
 |