1213 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1213 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * $XFree86: xc/programs/Xserver/randr/randr.c,v 1.22 2003/11/06 18:38:15 tsi Exp $
 | |
|  *
 | |
|  * Copyright © 2000, Compaq Computer Corporation, 
 | |
|  * Copyright © 2002, Hewlett Packard, Inc.
 | |
|  *
 | |
|  * 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 Compaq or HP not be used in advertising
 | |
|  * or publicity pertaining to distribution of the software without specific,
 | |
|  * written prior permission.  HP makes no representations about the
 | |
|  * suitability of this software for any purpose.  It is provided "as is"
 | |
|  * without express or implied warranty.
 | |
|  *
 | |
|  * HP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
 | |
|  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL HP
 | |
|  * 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.
 | |
|  *
 | |
|  * Author:  Jim Gettys, HP Labs, Hewlett-Packard, Inc.
 | |
|  */
 | |
| 
 | |
| 
 | |
| #define NEED_REPLIES
 | |
| #define NEED_EVENTS
 | |
| #include "X.h"
 | |
| #include "Xproto.h"
 | |
| #include "misc.h"
 | |
| #include "os.h"
 | |
| #include "dixstruct.h"
 | |
| #include "resource.h"
 | |
| #include "scrnintstr.h"
 | |
| #include "windowstr.h"
 | |
| #include "pixmapstr.h"
 | |
| #include "extnsionst.h"
 | |
| #include "servermd.h"
 | |
| #include "randr.h"
 | |
| #include "randrproto.h"
 | |
| #include "randrstr.h"
 | |
| #ifdef RENDER
 | |
| #include "render.h" 	/* we share subpixel order information */
 | |
| #include "picturestr.h"
 | |
| #endif
 | |
| #include "Xfuncproto.h"
 | |
| #ifdef EXTMODULE
 | |
| #include "xf86_ansic.h"
 | |
| #endif
 | |
| 
 | |
| /* From render.h */
 | |
| #ifndef SubPixelUnknown
 | |
| #define SubPixelUnknown 0
 | |
| #endif
 | |
| 
 | |
| #define RR_VALIDATE
 | |
| int	RRGeneration;
 | |
| int	RRNScreens;
 | |
| 
 | |
| static int ProcRRQueryVersion (ClientPtr pClient);
 | |
| static int ProcRRDispatch (ClientPtr pClient);
 | |
| static int SProcRRDispatch (ClientPtr pClient);
 | |
| static int SProcRRQueryVersion (ClientPtr pClient);
 | |
| 
 | |
| #define wrap(priv,real,mem,func) {\
 | |
|     priv->mem = real->mem; \
 | |
|     real->mem = func; \
 | |
| }
 | |
| 
 | |
| #define unwrap(priv,real,mem) {\
 | |
|     real->mem = priv->mem; \
 | |
| }
 | |
| 
 | |
| #if 0
 | |
| static CARD8	RRReqCode;
 | |
| static int	RRErrBase;
 | |
| #endif
 | |
| static int	RREventBase;
 | |
| static RESTYPE ClientType, EventType; /* resource types for event masks */
 | |
| static int	RRClientPrivateIndex;
 | |
| 
 | |
| typedef struct _RRTimes {
 | |
|     TimeStamp	setTime;
 | |
|     TimeStamp	configTime;
 | |
| } RRTimesRec, *RRTimesPtr;
 | |
| 
 | |
| typedef struct _RRClient {
 | |
|     int		major_version;
 | |
|     int		minor_version;
 | |
| /*  RRTimesRec	times[0]; */
 | |
| } RRClientRec, *RRClientPtr;
 | |
| 
 | |
| /*
 | |
|  * each window has a list of clients requesting
 | |
|  * RRNotify events.  Each client has a resource
 | |
|  * for each window it selects RRNotify input for,
 | |
|  * this resource is used to delete the RRNotifyRec
 | |
|  * entry from the per-window queue.
 | |
|  */
 | |
| 
 | |
| typedef struct _RREvent *RREventPtr;
 | |
| 
 | |
| typedef struct _RREvent {
 | |
|     RREventPtr  next;
 | |
|     ClientPtr	client;
 | |
|     WindowPtr	window;
 | |
|     XID		clientResource;
 | |
|     int		mask;
 | |
| } RREventRec;
 | |
| 
 | |
| int	rrPrivIndex = -1;
 | |
| 
 | |
| #define GetRRClient(pClient)    ((RRClientPtr) (pClient)->devPrivates[RRClientPrivateIndex].ptr)
 | |
| #define rrClientPriv(pClient)	RRClientPtr pRRClient = GetRRClient(pClient)
 | |
| 
 | |
| static Bool
 | |
| RRClientKnowsRates (ClientPtr	pClient)
 | |
| {
 | |
|     rrClientPriv(pClient);
 | |
| 
 | |
|     return (pRRClient->major_version > 1 ||
 | |
| 	    (pRRClient->major_version == 1 && pRRClient->minor_version >= 1));
 | |
| }
 | |
| 
 | |
| static void
 | |
| RRClientCallback (CallbackListPtr	*list,
 | |
| 		  pointer		closure,
 | |
| 		  pointer		data)
 | |
| {
 | |
|     NewClientInfoRec	*clientinfo = (NewClientInfoRec *) data;
 | |
|     ClientPtr		pClient = clientinfo->client;
 | |
|     rrClientPriv(pClient);
 | |
|     RRTimesPtr		pTimes = (RRTimesPtr) (pRRClient + 1);
 | |
|     int			i;
 | |
| 
 | |
|     pRRClient->major_version = 0;
 | |
|     pRRClient->minor_version = 0;
 | |
|     for (i = 0; i < screenInfo.numScreens; i++)
 | |
|     {
 | |
| 	ScreenPtr   pScreen = screenInfo.screens[i];
 | |
| 	rrScrPriv(pScreen);
 | |
| 
 | |
| 	if (pScrPriv)
 | |
| 	{
 | |
| 	    pTimes[i].setTime = pScrPriv->lastSetTime;
 | |
| 	    pTimes[i].configTime = pScrPriv->lastConfigTime;
 | |
| 	}
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void
 | |
| RRResetProc (ExtensionEntry *extEntry)
 | |
| {
 | |
| }
 | |
|     
 | |
| static Bool
 | |
| RRCloseScreen (int i, ScreenPtr pScreen)
 | |
| {
 | |
|     rrScrPriv(pScreen);
 | |
| 
 | |
|     unwrap (pScrPriv, pScreen, CloseScreen);
 | |
|     if (pScrPriv->pSizes)
 | |
| 	xfree (pScrPriv->pSizes);
 | |
|     xfree (pScrPriv);
 | |
|     RRNScreens -= 1;	/* ok, one fewer screen with RandR running */
 | |
|     return (*pScreen->CloseScreen) (i, pScreen);    
 | |
| }
 | |
| 
 | |
| static void
 | |
| SRRScreenChangeNotifyEvent(xRRScreenChangeNotifyEvent *from,
 | |
| 			   xRRScreenChangeNotifyEvent *to)
 | |
| {
 | |
|     to->type = from->type;
 | |
|     to->rotation = from->rotation;
 | |
|     cpswaps(from->sequenceNumber, to->sequenceNumber);
 | |
|     cpswapl(from->timestamp, to->timestamp);
 | |
|     cpswapl(from->configTimestamp, to->configTimestamp);
 | |
|     cpswapl(from->root, to->root);
 | |
|     cpswapl(from->window, to->window);
 | |
|     cpswaps(from->sizeID, to->sizeID);
 | |
|     cpswaps(from->widthInPixels, to->widthInPixels);
 | |
|     cpswaps(from->heightInPixels, to->heightInPixels);
 | |
|     cpswaps(from->widthInMillimeters, to->widthInMillimeters);
 | |
|     cpswaps(from->heightInMillimeters, to->heightInMillimeters);
 | |
|     cpswaps(from->subpixelOrder, to->subpixelOrder);
 | |
| }
 | |
| 
 | |
| Bool RRScreenInit(ScreenPtr pScreen)
 | |
| {
 | |
|     rrScrPrivPtr   pScrPriv;
 | |
| 
 | |
|     if (RRGeneration != serverGeneration)
 | |
|     {
 | |
| 	if ((rrPrivIndex = AllocateScreenPrivateIndex()) < 0)
 | |
| 	    return FALSE;
 | |
| 	RRGeneration = serverGeneration;
 | |
|     }
 | |
| 
 | |
|     pScrPriv = (rrScrPrivPtr) xalloc (sizeof (rrScrPrivRec));
 | |
|     if (!pScrPriv)
 | |
| 	return FALSE;
 | |
| 
 | |
|     SetRRScreen(pScreen, pScrPriv);
 | |
| 
 | |
|     /*
 | |
|      * Calling function best set these function vectors
 | |
|      */
 | |
|     pScrPriv->rrSetConfig = 0;
 | |
|     pScrPriv->rrGetInfo = 0;
 | |
|     /*
 | |
|      * This value doesn't really matter -- any client must call
 | |
|      * GetScreenInfo before reading it which will automatically update
 | |
|      * the time
 | |
|      */
 | |
|     pScrPriv->lastSetTime = currentTime;
 | |
|     pScrPriv->lastConfigTime = currentTime;
 | |
|     
 | |
|     wrap (pScrPriv, pScreen, CloseScreen, RRCloseScreen);
 | |
| 
 | |
|     pScrPriv->rotations = RR_Rotate_0;
 | |
|     
 | |
|     pScrPriv->nSizes = 0;
 | |
|     pScrPriv->nSizesInUse = 0;
 | |
|     pScrPriv->pSizes = 0;
 | |
|     
 | |
|     pScrPriv->rotation = RR_Rotate_0;
 | |
|     pScrPriv->size = -1;
 | |
|     
 | |
|     RRNScreens += 1;	/* keep count of screens that implement randr */
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| static int
 | |
| RRFreeClient (pointer data, XID id)
 | |
| {
 | |
|     RREventPtr   pRREvent;
 | |
|     WindowPtr	    pWin;
 | |
|     RREventPtr   *pHead, pCur, pPrev;
 | |
| 
 | |
|     pRREvent = (RREventPtr) data;
 | |
|     pWin = pRREvent->window;
 | |
|     pHead = (RREventPtr *) LookupIDByType(pWin->drawable.id, EventType);
 | |
|     if (pHead) {
 | |
| 	pPrev = 0;
 | |
| 	for (pCur = *pHead; pCur && pCur != pRREvent; pCur=pCur->next)
 | |
| 	    pPrev = pCur;
 | |
| 	if (pCur)
 | |
| 	{
 | |
| 	    if (pPrev)
 | |
| 	    	pPrev->next = pRREvent->next;
 | |
| 	    else
 | |
| 	    	*pHead = pRREvent->next;
 | |
| 	}
 | |
|     }
 | |
|     xfree ((pointer) pRREvent);
 | |
|     return 1;
 | |
| }
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| static int
 | |
| RRFreeEvents (pointer data, XID id)
 | |
| {
 | |
|     RREventPtr   *pHead, pCur, pNext;
 | |
| 
 | |
|     pHead = (RREventPtr *) data;
 | |
|     for (pCur = *pHead; pCur; pCur = pNext) {
 | |
| 	pNext = pCur->next;
 | |
| 	FreeResource (pCur->clientResource, ClientType);
 | |
| 	xfree ((pointer) pCur);
 | |
|     }
 | |
|     xfree ((pointer) pHead);
 | |
|     return 1;
 | |
| }
 | |
| 
 | |
| void
 | |
| RRExtensionInit (void)
 | |
| {
 | |
|     ExtensionEntry *extEntry;
 | |
| 
 | |
|     if (RRNScreens == 0) return;
 | |
| 
 | |
|     RRClientPrivateIndex = AllocateClientPrivateIndex ();
 | |
|     if (!AllocateClientPrivate (RRClientPrivateIndex,
 | |
| 				sizeof (RRClientRec) +
 | |
| 				screenInfo.numScreens * sizeof (RRTimesRec)))
 | |
| 	return;
 | |
|     if (!AddCallback (&ClientStateCallback, RRClientCallback, 0))
 | |
| 	return;
 | |
| 
 | |
|     ClientType = CreateNewResourceType(RRFreeClient);
 | |
|     if (!ClientType)
 | |
| 	return;
 | |
|     EventType = CreateNewResourceType(RRFreeEvents);
 | |
|     if (!EventType)
 | |
| 	return;
 | |
|     extEntry = AddExtension (RANDR_NAME, RRNumberEvents, RRNumberErrors,
 | |
| 			     ProcRRDispatch, SProcRRDispatch,
 | |
| 			     RRResetProc, StandardMinorOpcode);
 | |
|     if (!extEntry)
 | |
| 	return;
 | |
| #if 0
 | |
|     RRReqCode = (CARD8) extEntry->base;
 | |
|     RRErrBase = extEntry->errorBase;
 | |
| #endif
 | |
|     RREventBase = extEntry->eventBase;
 | |
|     EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr) 
 | |
|       SRRScreenChangeNotifyEvent;
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 		
 | |
| static int
 | |
| TellChanged (WindowPtr pWin, pointer value)
 | |
| {
 | |
|     RREventPtr			*pHead, pRREvent;
 | |
|     ClientPtr			client;
 | |
|     xRRScreenChangeNotifyEvent	se;
 | |
|     ScreenPtr			pScreen = pWin->drawable.pScreen;
 | |
|     rrScrPriv(pScreen);
 | |
|     RRScreenSizePtr		pSize;
 | |
|     WindowPtr			pRoot = WindowTable[pScreen->myNum];
 | |
| 
 | |
|     pHead = (RREventPtr *) LookupIDByType (pWin->drawable.id, EventType);
 | |
|     if (!pHead)
 | |
| 	return WT_WALKCHILDREN;
 | |
| 
 | |
|     se.type = RRScreenChangeNotify + RREventBase;
 | |
|     se.rotation = (CARD8) pScrPriv->rotation;
 | |
|     se.timestamp = pScrPriv->lastSetTime.milliseconds;
 | |
|     se.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
 | |
|     se.root =  pRoot->drawable.id;
 | |
|     se.window = pWin->drawable.id;
 | |
| #ifdef RENDER
 | |
|     se.subpixelOrder = PictureGetSubpixelOrder (pScreen);
 | |
| #else
 | |
|     se.subpixelOrder = SubPixelUnknown;
 | |
| #endif
 | |
|     if (pScrPriv->size >= 0)
 | |
|     {
 | |
| 	pSize = &pScrPriv->pSizes[pScrPriv->size];
 | |
| 	se.sizeID = pSize->id;
 | |
| 	se.widthInPixels = pSize->width;
 | |
| 	se.heightInPixels = pSize->height;
 | |
| 	se.widthInMillimeters = pSize->mmWidth;
 | |
| 	se.heightInMillimeters = pSize->mmHeight;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	/*
 | |
| 	 * This "shouldn't happen", but a broken DDX can
 | |
| 	 * forget to set the current configuration on GetInfo
 | |
| 	 */
 | |
| 	se.sizeID = 0xffff;
 | |
| 	se.widthInPixels = 0;
 | |
| 	se.heightInPixels = 0;
 | |
| 	se.widthInMillimeters = 0;
 | |
| 	se.heightInMillimeters = 0;
 | |
|     }    
 | |
|     for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) 
 | |
|     {
 | |
| 	client = pRREvent->client;
 | |
| 	if (client == serverClient || client->clientGone)
 | |
| 	    continue;
 | |
| 	se.sequenceNumber = client->sequence;
 | |
| 	if(pRREvent->mask & RRScreenChangeNotifyMask)
 | |
| 	  WriteEventsToClient (client, 1, (xEvent *) &se);
 | |
|     }
 | |
|     return WT_WALKCHILDREN;
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| RRGetInfo (ScreenPtr pScreen)
 | |
| {
 | |
|     rrScrPriv (pScreen);
 | |
|     int		    i, j, k, l;
 | |
|     Bool	    changed;
 | |
|     Rotation	    rotations;
 | |
|     RRScreenSizePtr pSize;
 | |
|     RRScreenRatePtr pRate;
 | |
| 
 | |
|     for (i = 0; i < pScrPriv->nSizes; i++)
 | |
|     {
 | |
| 	pSize = &pScrPriv->pSizes[i];
 | |
| 	pSize->oldReferenced = pSize->referenced;
 | |
| 	pSize->referenced = FALSE;
 | |
| 	for (k = 0; k < pSize->nRates; k++)
 | |
| 	{
 | |
| 	    pRate = &pSize->pRates[k];
 | |
| 	    pRate->oldReferenced = pRate->referenced;
 | |
| 	    pRate->referenced = FALSE;
 | |
| 	}
 | |
|     }
 | |
|     if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations))
 | |
| 	return FALSE;
 | |
| 
 | |
|     changed = FALSE;
 | |
| 
 | |
|     /*
 | |
|      * Check whether anything changed and simultaneously generate
 | |
|      * the protocol id values for the objects
 | |
|      */
 | |
|     if (rotations != pScrPriv->rotations)
 | |
|     {
 | |
| 	pScrPriv->rotations = rotations;
 | |
| 	changed = TRUE;
 | |
|     }
 | |
| 
 | |
|     j = 0;
 | |
|     for (i = 0; i < pScrPriv->nSizes; i++)
 | |
|     {
 | |
| 	pSize = &pScrPriv->pSizes[i];
 | |
| 	if (pSize->oldReferenced != pSize->referenced)
 | |
| 	    changed = TRUE;
 | |
| 	if (pSize->referenced)
 | |
| 	    pSize->id = j++;
 | |
| 	l = 0;
 | |
| 	for (k = 0; k < pSize->nRates; k++)
 | |
| 	{
 | |
| 	    pRate = &pSize->pRates[k];
 | |
| 	    if (pRate->oldReferenced != pRate->referenced)
 | |
| 		changed = TRUE;
 | |
| 	    if (pRate->referenced)
 | |
| 		l++;
 | |
| 	}
 | |
| 	pSize->nRatesInUse = l;
 | |
|     }
 | |
|     pScrPriv->nSizesInUse = j;
 | |
|     if (changed)
 | |
|     {
 | |
| 	UpdateCurrentTime ();
 | |
| 	pScrPriv->lastConfigTime = currentTime;
 | |
| 	WalkTree (pScreen, TellChanged, (pointer) pScreen);
 | |
|     }
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| static void
 | |
| RRSendConfigNotify (ScreenPtr pScreen)
 | |
| {
 | |
|     WindowPtr	pWin = WindowTable[pScreen->myNum];
 | |
|     xEvent	event;
 | |
| 
 | |
|     event.u.u.type = ConfigureNotify;
 | |
|     event.u.configureNotify.window = pWin->drawable.id;
 | |
|     event.u.configureNotify.aboveSibling = None;
 | |
|     event.u.configureNotify.x = 0;
 | |
|     event.u.configureNotify.y = 0;
 | |
| 
 | |
|     /* XXX xinerama stuff ? */
 | |
|     
 | |
|     event.u.configureNotify.width = pWin->drawable.width;
 | |
|     event.u.configureNotify.height = pWin->drawable.height;
 | |
|     event.u.configureNotify.borderWidth = wBorderWidth (pWin);
 | |
|     event.u.configureNotify.override = pWin->overrideRedirect;
 | |
|     DeliverEvents(pWin, &event, 1, NullWindow);
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcRRQueryVersion (ClientPtr client)
 | |
| {
 | |
|     xRRQueryVersionReply rep;
 | |
|     register int n;
 | |
|     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;
 | |
|     rep.majorVersion = RANDR_MAJOR;
 | |
|     rep.minorVersion = RANDR_MINOR;
 | |
|     if (client->swapped) {
 | |
|     	swaps(&rep.sequenceNumber, n);
 | |
|     	swapl(&rep.length, n);
 | |
| 	swapl(&rep.majorVersion, n);
 | |
| 	swapl(&rep.minorVersion, n);
 | |
|     }
 | |
|     WriteToClient(client, sizeof(xRRQueryVersionReply), (char *)&rep);
 | |
|     return (client->noClientException);
 | |
| }
 | |
| 
 | |
| 
 | |
| extern char	*ConnectionInfo;
 | |
| 
 | |
| static int padlength[4] = {0, 3, 2, 1};
 | |
| 
 | |
| static void
 | |
| RREditConnectionInfo (ScreenPtr pScreen)
 | |
| {
 | |
|     xConnSetup	    *connSetup;
 | |
|     char	    *vendor;
 | |
|     xPixmapFormat   *formats;
 | |
|     xWindowRoot	    *root;
 | |
|     xDepth	    *depth;
 | |
|     xVisualType	    *visual;
 | |
|     int		    screen = 0;
 | |
|     int		    d;
 | |
| 
 | |
|     connSetup = (xConnSetup *) ConnectionInfo;
 | |
|     vendor = (char *) connSetup + sizeof (xConnSetup);
 | |
|     formats = (xPixmapFormat *) ((char *) vendor +
 | |
| 				 connSetup->nbytesVendor +
 | |
| 				 padlength[connSetup->nbytesVendor & 3]);
 | |
|     root = (xWindowRoot *) ((char *) formats +
 | |
| 			    sizeof (xPixmapFormat) * screenInfo.numPixmapFormats);
 | |
|     while (screen != pScreen->myNum)
 | |
|     {
 | |
| 	depth = (xDepth *) ((char *) root + 
 | |
| 			    sizeof (xWindowRoot));
 | |
| 	for (d = 0; d < root->nDepths; d++)
 | |
| 	{
 | |
| 	    visual = (xVisualType *) ((char *) depth +
 | |
| 				      sizeof (xDepth));
 | |
| 	    depth = (xDepth *) ((char *) visual +
 | |
| 				depth->nVisuals * sizeof (xVisualType));
 | |
| 	}
 | |
| 	root = (xWindowRoot *) ((char *) depth);
 | |
| 	screen++;
 | |
|     }
 | |
|     root->pixWidth = pScreen->width;
 | |
|     root->pixHeight = pScreen->height;
 | |
|     root->mmWidth = pScreen->mmWidth;
 | |
|     root->mmHeight = pScreen->mmHeight;
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcRRGetScreenInfo (ClientPtr client)
 | |
| {
 | |
|     REQUEST(xRRGetScreenInfoReq);
 | |
|     xRRGetScreenInfoReply   rep;
 | |
|     WindowPtr	    	    pWin;
 | |
|     int			    n;
 | |
|     ScreenPtr		    pScreen;
 | |
|     rrScrPrivPtr	    pScrPriv;
 | |
|     CARD8		    *extra;
 | |
|     unsigned long	    extraLen;
 | |
| 
 | |
|     REQUEST_SIZE_MATCH(xRRGetScreenInfoReq);
 | |
|     pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
 | |
| 					   SecurityReadAccess);
 | |
| 
 | |
|     if (!pWin)
 | |
| 	return BadWindow;
 | |
| 
 | |
|     pScreen = pWin->drawable.pScreen;
 | |
|     pScrPriv = rrGetScrPriv(pScreen);
 | |
|     rep.pad = 0;
 | |
|     if (!pScrPriv)
 | |
|     {
 | |
| 	rep.type = X_Reply;
 | |
| 	rep.setOfRotations = RR_Rotate_0;;
 | |
| 	rep.sequenceNumber = client->sequence;
 | |
| 	rep.length = 0;
 | |
| 	rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
 | |
| 	rep.timestamp = currentTime.milliseconds;
 | |
| 	rep.configTimestamp = currentTime.milliseconds;
 | |
| 	rep.nSizes = 0;
 | |
| 	rep.sizeID = 0;
 | |
| 	rep.rotation = RR_Rotate_0;
 | |
| 	rep.rate = 0;
 | |
| 	rep.nrateEnts = 0;
 | |
| 	extra = 0;
 | |
| 	extraLen = 0;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	int			i, j;
 | |
| 	xScreenSizes		*size;
 | |
| 	CARD16			*rates;
 | |
| 	CARD8			*data8;
 | |
| 	Bool			has_rate = RRClientKnowsRates (client);
 | |
|     
 | |
| 	RRGetInfo (pScreen);
 | |
| 
 | |
| 	rep.type = X_Reply;
 | |
| 	rep.setOfRotations = pScrPriv->rotations;
 | |
| 	rep.sequenceNumber = client->sequence;
 | |
| 	rep.length = 0;
 | |
| 	rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
 | |
| 	rep.timestamp = pScrPriv->lastSetTime.milliseconds;
 | |
| 	rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
 | |
| 	rep.rotation = pScrPriv->rotation;
 | |
| 	rep.nSizes = pScrPriv->nSizesInUse;
 | |
| 	rep.rate = pScrPriv->rate;
 | |
|         rep.nrateEnts = 0;
 | |
| 	if (has_rate)
 | |
| 	{
 | |
| 	    for (i = 0; i < pScrPriv->nSizes; i++)
 | |
| 	    {
 | |
| 		RRScreenSizePtr pSize = &pScrPriv->pSizes[i];
 | |
| 		if (pSize->referenced)
 | |
| 		{
 | |
| 		    rep.nrateEnts += (1 + pSize->nRatesInUse);
 | |
| 		}
 | |
| 	    }
 | |
| 	}
 | |
| 
 | |
| 	if (pScrPriv->size >= 0)
 | |
| 	    rep.sizeID = pScrPriv->pSizes[pScrPriv->size].id;
 | |
| 	else
 | |
| 	    return BadImplementation;
 | |
| 
 | |
| 	extraLen = (rep.nSizes * sizeof (xScreenSizes) +
 | |
| 		    rep.nrateEnts * sizeof (CARD16));
 | |
| 
 | |
| 	extra = (CARD8 *) xalloc (extraLen);
 | |
| 	if (!extra)
 | |
| 	    return BadAlloc;
 | |
| 	/*
 | |
| 	 * First comes the size information
 | |
| 	 */
 | |
| 	size = (xScreenSizes *) extra;
 | |
| 	rates = (CARD16 *) (size + rep.nSizes);
 | |
| 	for (i = 0; i < pScrPriv->nSizes; i++)
 | |
| 	{
 | |
| 	    RRScreenSizePtr pSize = &pScrPriv->pSizes[i];
 | |
| 	    if (pSize->referenced)
 | |
| 	    {
 | |
| 		size->widthInPixels = pSize->width;
 | |
| 		size->heightInPixels = pSize->height;
 | |
| 		size->widthInMillimeters = pSize->mmWidth;
 | |
| 		size->heightInMillimeters = pSize->mmHeight;
 | |
| 		if (client->swapped)
 | |
| 		{
 | |
| 		    swaps (&size->widthInPixels, n);
 | |
| 		    swaps (&size->heightInPixels, n);
 | |
| 		    swaps (&size->widthInMillimeters, n);
 | |
| 		    swaps (&size->heightInMillimeters, n);
 | |
| 		}
 | |
| 		size++;
 | |
| 		if (has_rate)
 | |
| 		{
 | |
| 		    *rates = pSize->nRatesInUse;
 | |
| 		    if (client->swapped)
 | |
| 		    {
 | |
| 			swaps (rates, n);
 | |
| 		    }
 | |
| 		    rates++;
 | |
| 		    for (j = 0; j < pSize->nRates; j++)
 | |
| 		    {
 | |
| 			RRScreenRatePtr	pRate = &pSize->pRates[j];
 | |
| 			if (pRate->referenced)
 | |
| 			{
 | |
| 			    *rates = pRate->rate;
 | |
| 			    if (client->swapped)
 | |
| 			    {
 | |
| 				swaps (rates, n);
 | |
| 			    }
 | |
| 			    rates++;
 | |
| 			}
 | |
| 		    }
 | |
| 		}
 | |
| 	    }
 | |
| 	}
 | |
| 	data8 = (CARD8 *) rates;
 | |
| 
 | |
| 	if (data8 - (CARD8 *) extra != extraLen)
 | |
| 	    FatalError ("RRGetScreenInfo bad extra len %ld != %ld\n",
 | |
| 			(unsigned long)(data8 - (CARD8 *) extra), extraLen);
 | |
| 	rep.length =  (extraLen + 3) >> 2;
 | |
|     }
 | |
|     if (client->swapped) {
 | |
| 	swaps(&rep.sequenceNumber, n);
 | |
| 	swapl(&rep.length, n);
 | |
| 	swapl(&rep.timestamp, n);
 | |
| 	swaps(&rep.rotation, n);
 | |
| 	swaps(&rep.nSizes, n);
 | |
| 	swaps(&rep.sizeID, n);
 | |
| 	swaps(&rep.rate, n);
 | |
| 	swaps(&rep.nrateEnts, n);
 | |
|     }
 | |
|     WriteToClient(client, sizeof(xRRGetScreenInfoReply), (char *)&rep);
 | |
|     if (extraLen)
 | |
|     {
 | |
| 	WriteToClient (client, extraLen, (char *) extra);
 | |
| 	xfree (extra);
 | |
|     }
 | |
|     return (client->noClientException);
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcRRSetScreenConfig (ClientPtr client)
 | |
| {
 | |
|     REQUEST(xRRSetScreenConfigReq);
 | |
|     xRRSetScreenConfigReply rep;
 | |
|     DrawablePtr		    pDraw;
 | |
|     int			    n;
 | |
|     ScreenPtr		    pScreen;
 | |
|     rrScrPrivPtr	    pScrPriv;
 | |
|     TimeStamp		    configTime;
 | |
|     TimeStamp		    time;
 | |
|     RRScreenSizePtr	    pSize;
 | |
|     int			    i;
 | |
|     Rotation		    rotation;
 | |
|     int			    rate;
 | |
|     short		    oldWidth, oldHeight;
 | |
|     Bool		    has_rate;
 | |
| 
 | |
|     UpdateCurrentTime ();
 | |
| 
 | |
|     if (RRClientKnowsRates (client))
 | |
|     {
 | |
| 	REQUEST_SIZE_MATCH (xRRSetScreenConfigReq);
 | |
| 	has_rate = TRUE;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq);
 | |
| 	has_rate = FALSE;
 | |
|     }
 | |
|     
 | |
|     SECURITY_VERIFY_DRAWABLE(pDraw, stuff->drawable, client,
 | |
| 			     SecurityWriteAccess);
 | |
| 
 | |
|     pScreen = pDraw->pScreen;
 | |
| 
 | |
|     pScrPriv= rrGetScrPriv(pScreen);
 | |
|     
 | |
|     time = ClientTimeToServerTime(stuff->timestamp);
 | |
|     configTime = ClientTimeToServerTime(stuff->configTimestamp);
 | |
|     
 | |
|     oldWidth = pScreen->width;
 | |
|     oldHeight = pScreen->height;
 | |
|     
 | |
|     if (!pScrPriv)
 | |
|     {
 | |
| 	time = currentTime;
 | |
| 	rep.status = RRSetConfigFailed;
 | |
| 	goto sendReply;
 | |
|     }
 | |
|     if (!RRGetInfo (pScreen))
 | |
| 	return BadAlloc;
 | |
|     
 | |
|     /*
 | |
|      * if the client's config timestamp is not the same as the last config
 | |
|      * timestamp, then the config information isn't up-to-date and
 | |
|      * can't even be validated
 | |
|      */
 | |
|     if (CompareTimeStamps (configTime, pScrPriv->lastConfigTime) != 0)
 | |
|     {
 | |
| 	rep.status = RRSetConfigInvalidConfigTime;
 | |
| 	goto sendReply;
 | |
|     }
 | |
|     
 | |
|     /*
 | |
|      * Search for the requested size
 | |
|      */
 | |
|     pSize = 0;
 | |
|     for (i = 0; i < pScrPriv->nSizes; i++)
 | |
|     {
 | |
| 	pSize = &pScrPriv->pSizes[i];
 | |
| 	if (pSize->referenced && pSize->id == stuff->sizeID)
 | |
| 	{
 | |
| 	    break;
 | |
| 	}
 | |
|     }
 | |
|     if (i == pScrPriv->nSizes)
 | |
|     {
 | |
| 	/*
 | |
| 	 * Invalid size ID
 | |
| 	 */
 | |
| 	client->errorValue = stuff->sizeID;
 | |
| 	return BadValue;
 | |
|     }
 | |
|     
 | |
|     /*
 | |
|      * Validate requested rotation
 | |
|      */
 | |
|     rotation = (Rotation) stuff->rotation;
 | |
| 
 | |
|     /* test the rotation bits only! */
 | |
|     switch (rotation & 0xf) {
 | |
|     case RR_Rotate_0:
 | |
|     case RR_Rotate_90:
 | |
|     case RR_Rotate_180:
 | |
|     case RR_Rotate_270:
 | |
| 	break;
 | |
|     default:
 | |
| 	/*
 | |
| 	 * Invalid rotation
 | |
| 	 */
 | |
| 	client->errorValue = stuff->rotation;
 | |
| 	return BadValue;
 | |
|     }
 | |
| 
 | |
|     if ((~pScrPriv->rotations) & rotation)
 | |
|     {
 | |
| 	/*
 | |
| 	 * requested rotation or reflection not supported by screen
 | |
| 	 */
 | |
| 	client->errorValue = stuff->rotation;
 | |
| 	return BadMatch;
 | |
|     }
 | |
| 
 | |
|     /*
 | |
|      * Validate requested refresh
 | |
|      */
 | |
|     if (has_rate)
 | |
| 	rate = (int) stuff->rate;
 | |
|     else
 | |
| 	rate = 0;
 | |
| 
 | |
|     if (rate)
 | |
|     {
 | |
| 	for (i = 0; i < pSize->nRates; i++)
 | |
| 	{
 | |
| 	    RRScreenRatePtr pRate = &pSize->pRates[i];
 | |
| 	    if (pRate->referenced && pRate->rate == rate)
 | |
| 		break;
 | |
| 	}
 | |
| 	if (i == pSize->nRates)
 | |
| 	{
 | |
| 	    /*
 | |
| 	     * Invalid rate
 | |
| 	     */
 | |
| 	    client->errorValue = rate;
 | |
| 	    return BadValue;
 | |
| 	}
 | |
|     }
 | |
|     
 | |
|     /*
 | |
|      * Make sure the requested set-time is not older than
 | |
|      * the last set-time
 | |
|      */
 | |
|     if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0)
 | |
|     {
 | |
| 	rep.status = RRSetConfigInvalidTime;
 | |
| 	goto sendReply;
 | |
|     }
 | |
| 
 | |
|     /*
 | |
|      * call out to ddx routine to effect the change
 | |
|      */
 | |
|     if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate,
 | |
| 				   pSize))
 | |
|     {
 | |
| 	/*
 | |
| 	 * unknown DDX failure, report to client
 | |
| 	 */
 | |
| 	rep.status = RRSetConfigFailed;
 | |
| 	goto sendReply;
 | |
|     }
 | |
|     
 | |
|     /*
 | |
|      * set current extension configuration pointers
 | |
|      */
 | |
|     RRSetCurrentConfig (pScreen, rotation, rate, pSize);
 | |
|     
 | |
|     /*
 | |
|      * Deliver ScreenChangeNotify events whenever
 | |
|      * the configuration is updated
 | |
|      */
 | |
|     WalkTree (pScreen, TellChanged, (pointer) pScreen);
 | |
|     
 | |
|     /*
 | |
|      * Deliver ConfigureNotify events when root changes
 | |
|      * pixel size
 | |
|      */
 | |
|     if (oldWidth != pScreen->width || oldHeight != pScreen->height)
 | |
| 	RRSendConfigNotify (pScreen);
 | |
|     RREditConnectionInfo (pScreen);
 | |
|     
 | |
|     /*
 | |
|      * Fix pointer bounds and location
 | |
|      */
 | |
|     ScreenRestructured (pScreen);
 | |
|     pScrPriv->lastSetTime = time;
 | |
|     
 | |
|     /*
 | |
|      * Report Success
 | |
|      */
 | |
|     rep.status = RRSetConfigSuccess;
 | |
|     
 | |
| sendReply:
 | |
|     
 | |
|     rep.type = X_Reply;
 | |
|     /* rep.status has already been filled in */
 | |
|     rep.length = 0;
 | |
|     rep.sequenceNumber = client->sequence;
 | |
| 
 | |
|     rep.newTimestamp = pScrPriv->lastSetTime.milliseconds;
 | |
|     rep.newConfigTimestamp = pScrPriv->lastConfigTime.milliseconds;
 | |
|     rep.root = WindowTable[pDraw->pScreen->myNum]->drawable.id;
 | |
| 
 | |
|     if (client->swapped) 
 | |
|     {
 | |
|     	swaps(&rep.sequenceNumber, n);
 | |
|     	swapl(&rep.length, n);
 | |
| 	swapl(&rep.newTimestamp, n);
 | |
| 	swapl(&rep.newConfigTimestamp, n);
 | |
| 	swapl(&rep.root, n);
 | |
|     }
 | |
|     WriteToClient(client, sizeof(xRRSetScreenConfigReply), (char *)&rep);
 | |
| 
 | |
|     return (client->noClientException);
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcRRSelectInput (ClientPtr client)
 | |
| {
 | |
|     REQUEST(xRRSelectInputReq);
 | |
|     rrClientPriv(client);
 | |
|     RRTimesPtr	pTimes;
 | |
|     WindowPtr	pWin;
 | |
|     RREventPtr	pRREvent, pNewRREvent, *pHead;
 | |
|     XID		clientResource;
 | |
| 
 | |
|     REQUEST_SIZE_MATCH(xRRSelectInputReq);
 | |
|     pWin = SecurityLookupWindow (stuff->window, client, SecurityWriteAccess);
 | |
|     if (!pWin)
 | |
| 	return BadWindow;
 | |
|     pHead = (RREventPtr *)SecurityLookupIDByType(client,
 | |
| 						 pWin->drawable.id, EventType,
 | |
| 						 SecurityWriteAccess);
 | |
| 
 | |
|     if (stuff->enable & (RRScreenChangeNotifyMask)) 
 | |
|     {
 | |
| 	ScreenPtr	pScreen = pWin->drawable.pScreen;
 | |
| 	rrScrPriv	(pScreen);
 | |
| 
 | |
| 	if (pHead) 
 | |
| 	{
 | |
| 	    /* check for existing entry. */
 | |
| 	    for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
 | |
| 		if (pRREvent->client == client)
 | |
| 		    return Success;
 | |
| 	}
 | |
| 
 | |
| 	/* build the entry */
 | |
| 	pNewRREvent = (RREventPtr) xalloc (sizeof (RREventRec));
 | |
| 	if (!pNewRREvent)
 | |
| 	    return BadAlloc;
 | |
| 	pNewRREvent->next = 0;
 | |
| 	pNewRREvent->client = client;
 | |
| 	pNewRREvent->window = pWin;
 | |
| 	pNewRREvent->mask = stuff->enable;
 | |
| 	/*
 | |
| 	 * add a resource that will be deleted when
 | |
| 	 * the client goes away
 | |
| 	 */
 | |
| 	clientResource = FakeClientID (client->index);
 | |
| 	pNewRREvent->clientResource = clientResource;
 | |
| 	if (!AddResource (clientResource, ClientType, (pointer)pNewRREvent))
 | |
| 	    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 *) xalloc (sizeof (RREventPtr));
 | |
| 	    if (!pHead ||
 | |
| 		!AddResource (pWin->drawable.id, EventType, (pointer)pHead))
 | |
| 	    {
 | |
| 		FreeResource (clientResource, RT_NONE);
 | |
| 		return BadAlloc;
 | |
| 	    }
 | |
| 	    *pHead = 0;
 | |
| 	}
 | |
| 	pNewRREvent->next = *pHead;
 | |
| 	*pHead = pNewRREvent;
 | |
| 	/*
 | |
| 	 * 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)
 | |
| 	    {
 | |
| 		TellChanged (pWin, (pointer) pScreen);
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
|     else if (stuff->enable == xFalse) 
 | |
|     {
 | |
| 	/* delete the interest */
 | |
| 	if (pHead) {
 | |
| 	    pNewRREvent = 0;
 | |
| 	    for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) {
 | |
| 		if (pRREvent->client == client)
 | |
| 		    break;
 | |
| 		pNewRREvent = pRREvent;
 | |
| 	    }
 | |
| 	    if (pRREvent) {
 | |
| 		FreeResource (pRREvent->clientResource, ClientType);
 | |
| 		if (pNewRREvent)
 | |
| 		    pNewRREvent->next = pRREvent->next;
 | |
| 		else
 | |
| 		    *pHead = pRREvent->next;
 | |
| 		xfree (pRREvent);
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
|     else 
 | |
|     {
 | |
| 	client->errorValue = stuff->enable;
 | |
| 	return BadValue;
 | |
|     }
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| 
 | |
| static int
 | |
| ProcRRDispatch (ClientPtr client)
 | |
| {
 | |
|     REQUEST(xReq);
 | |
|     switch (stuff->data)
 | |
|     {
 | |
|     case X_RRQueryVersion:
 | |
| 	return ProcRRQueryVersion(client);
 | |
|     case X_RRSetScreenConfig:
 | |
|         return ProcRRSetScreenConfig(client);
 | |
|     case X_RRSelectInput:
 | |
|         return ProcRRSelectInput(client);
 | |
|     case X_RRGetScreenInfo:
 | |
|         return ProcRRGetScreenInfo(client);
 | |
|     default:
 | |
| 	return BadRequest;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static int
 | |
| SProcRRQueryVersion (ClientPtr client)
 | |
| {
 | |
|     register int n;
 | |
|     REQUEST(xRRQueryVersionReq);
 | |
| 
 | |
|     swaps(&stuff->length, n);
 | |
|     swapl(&stuff->majorVersion, n);
 | |
|     swapl(&stuff->minorVersion, n);
 | |
|     return ProcRRQueryVersion(client);
 | |
| }
 | |
| 
 | |
| static int
 | |
| SProcRRGetScreenInfo (ClientPtr client)
 | |
| {
 | |
|     register int n;
 | |
|     REQUEST(xRRGetScreenInfoReq);
 | |
| 
 | |
|     swaps(&stuff->length, n);
 | |
|     swapl(&stuff->window, n);
 | |
|     return ProcRRGetScreenInfo(client);
 | |
| }
 | |
| 
 | |
| static int
 | |
| SProcRRSetScreenConfig (ClientPtr client)
 | |
| {
 | |
|     register int n;
 | |
|     REQUEST(xRRSetScreenConfigReq);
 | |
| 
 | |
|     if (RRClientKnowsRates (client))
 | |
|     {
 | |
| 	REQUEST_SIZE_MATCH (xRRSetScreenConfigReq);
 | |
| 	swaps (&stuff->rate, n);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	REQUEST_SIZE_MATCH (xRR1_0SetScreenConfigReq);
 | |
|     }
 | |
|     
 | |
|     swaps(&stuff->length, n);
 | |
|     swapl(&stuff->drawable, n);
 | |
|     swapl(&stuff->timestamp, n);
 | |
|     swaps(&stuff->sizeID, n);
 | |
|     swaps(&stuff->rotation, n);
 | |
|     return ProcRRSetScreenConfig(client);
 | |
| }
 | |
| 
 | |
| static int
 | |
| SProcRRSelectInput (ClientPtr client)
 | |
| {
 | |
|     register int n;
 | |
|     REQUEST(xRRSelectInputReq);
 | |
| 
 | |
|     swaps(&stuff->length, n);
 | |
|     swapl(&stuff->window, n);
 | |
|     return ProcRRSelectInput(client);
 | |
| }
 | |
| 
 | |
| 
 | |
| static int
 | |
| SProcRRDispatch (ClientPtr client)
 | |
| {
 | |
|     REQUEST(xReq);
 | |
|     switch (stuff->data)
 | |
|     {
 | |
|     case X_RRQueryVersion:
 | |
| 	return SProcRRQueryVersion(client);
 | |
|     case X_RRSetScreenConfig:
 | |
|         return SProcRRSetScreenConfig(client);
 | |
|     case X_RRSelectInput:
 | |
|         return SProcRRSelectInput(client);
 | |
|     case X_RRGetScreenInfo:
 | |
|         return SProcRRGetScreenInfo(client);
 | |
|     default:
 | |
| 	return BadRequest;
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| static Bool
 | |
| RRScreenSizeMatches (RRScreenSizePtr  a,
 | |
| 		   RRScreenSizePtr  b)
 | |
| {
 | |
|     if (a->width != b->width)
 | |
| 	return FALSE;
 | |
|     if (a->height != b->height)
 | |
| 	return FALSE;
 | |
|     if (a->mmWidth != b->mmWidth)
 | |
| 	return FALSE;
 | |
|     if (a->mmHeight != b->mmHeight)
 | |
| 	return FALSE;
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| RRScreenSizePtr
 | |
| RRRegisterSize (ScreenPtr	    pScreen,
 | |
| 		short		    width, 
 | |
| 		short		    height,
 | |
| 		short		    mmWidth,
 | |
| 		short		    mmHeight)
 | |
| {
 | |
|     rrScrPriv (pScreen);
 | |
|     int		    i;
 | |
|     RRScreenSize    tmp;
 | |
|     RRScreenSizePtr pNew;
 | |
| 
 | |
|     if (!pScrPriv)
 | |
| 	return 0;
 | |
|     
 | |
|     tmp.width = width;
 | |
|     tmp.height= height;
 | |
|     tmp.mmWidth = mmWidth;
 | |
|     tmp.mmHeight = mmHeight;
 | |
|     tmp.pRates = 0;
 | |
|     tmp.nRates = 0;
 | |
|     tmp.nRatesInUse = 0;
 | |
|     tmp.referenced = TRUE;
 | |
|     tmp.oldReferenced = FALSE;
 | |
|     for (i = 0; i < pScrPriv->nSizes; i++)
 | |
| 	if (RRScreenSizeMatches (&tmp, &pScrPriv->pSizes[i]))
 | |
| 	{
 | |
| 	    pScrPriv->pSizes[i].referenced = TRUE;
 | |
| 	    return &pScrPriv->pSizes[i];
 | |
| 	}
 | |
|     pNew = xrealloc (pScrPriv->pSizes,
 | |
| 		     (pScrPriv->nSizes + 1) * sizeof (RRScreenSize));
 | |
|     if (!pNew)
 | |
| 	return 0;
 | |
|     pNew[pScrPriv->nSizes++] = tmp;
 | |
|     pScrPriv->pSizes = pNew;
 | |
|     return &pNew[pScrPriv->nSizes-1];
 | |
| }
 | |
| 
 | |
| Bool RRRegisterRate (ScreenPtr		pScreen,
 | |
| 		     RRScreenSizePtr	pSize,
 | |
| 		     int		rate)
 | |
| {
 | |
|     rrScrPriv(pScreen);
 | |
|     int		    i;
 | |
|     RRScreenRatePtr pNew, pRate;
 | |
| 
 | |
|     if (!pScrPriv)
 | |
| 	return FALSE;
 | |
|     
 | |
|     for (i = 0; i < pSize->nRates; i++)
 | |
|     {
 | |
| 	pRate = &pSize->pRates[i];
 | |
| 	if (pRate->rate == rate)
 | |
| 	{
 | |
| 	    pRate->referenced = TRUE;
 | |
| 	    return TRUE;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     pNew = xrealloc (pSize->pRates,
 | |
| 		     (pSize->nRates + 1) * sizeof (RRScreenRate));
 | |
|     if (!pNew)
 | |
| 	return FALSE;
 | |
|     pRate = &pNew[pSize->nRates++];
 | |
|     pRate->rate = rate;
 | |
|     pRate->referenced = TRUE;
 | |
|     pRate->oldReferenced = FALSE;
 | |
|     pSize->pRates = pNew;
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| void
 | |
| RRSetCurrentConfig (ScreenPtr		pScreen,
 | |
| 		    Rotation		rotation,
 | |
| 		    int			rate,
 | |
| 		    RRScreenSizePtr	pSize)
 | |
| {
 | |
|     rrScrPriv (pScreen);
 | |
| 
 | |
|     if (!pScrPriv)
 | |
| 	return;
 | |
| 
 | |
|     pScrPriv->rotation = rotation;
 | |
|     pScrPriv->size = pSize - pScrPriv->pSizes;
 | |
|     pScrPriv->rate = rate;
 | |
| }
 |