626 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			626 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * Copyright © 2006 Keith Packard
 | |
|  * Copyright © 2008 Red Hat, 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 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"
 | |
| 
 | |
| RESTYPE	RROutputType;
 | |
| 
 | |
| /*
 | |
|  * Notify the output of some change
 | |
|  */
 | |
| void
 | |
| RROutputChanged (RROutputPtr output, Bool configChanged)
 | |
| {
 | |
|     ScreenPtr	pScreen = output->pScreen;
 | |
|     
 | |
|     output->changed = TRUE;
 | |
|     if (pScreen)
 | |
|     {
 | |
| 	rrScrPriv (pScreen);
 | |
| 	pScrPriv->changed = TRUE;
 | |
| 	if (configChanged)
 | |
| 	    pScrPriv->configChanged = TRUE;
 | |
|     }
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Create an output
 | |
|  */
 | |
| 
 | |
| RROutputPtr
 | |
| RROutputCreate (ScreenPtr   pScreen,
 | |
| 		const char  *name,
 | |
| 		int	    nameLength,
 | |
| 		void	    *devPrivate)
 | |
| {
 | |
|     RROutputPtr	    output;
 | |
|     RROutputPtr	    *outputs;
 | |
|     rrScrPrivPtr    pScrPriv;
 | |
| 
 | |
|     if (!RRInit())
 | |
| 	return NULL;
 | |
|     
 | |
|     pScrPriv = rrGetScrPriv(pScreen);
 | |
| 
 | |
|     if (pScrPriv->numOutputs)
 | |
| 	outputs = realloc(pScrPriv->outputs,
 | |
| 			    (pScrPriv->numOutputs + 1) * sizeof (RROutputPtr));
 | |
|     else
 | |
| 	outputs = malloc(sizeof (RROutputPtr));
 | |
|     if (!outputs)
 | |
| 	return FALSE;
 | |
| 
 | |
|     pScrPriv->outputs = outputs;
 | |
|     
 | |
|     output = malloc(sizeof (RROutputRec) + nameLength + 1);
 | |
|     if (!output)
 | |
| 	return NULL;
 | |
|     output->id = FakeClientID (0);
 | |
|     output->pScreen = pScreen;
 | |
|     output->name = (char *) (output + 1);
 | |
|     output->nameLength = nameLength;
 | |
|     memcpy (output->name, name, nameLength);
 | |
|     output->name[nameLength] = '\0';
 | |
|     output->connection = RR_UnknownConnection;
 | |
|     output->subpixelOrder = SubPixelUnknown;
 | |
|     output->mmWidth = 0;
 | |
|     output->mmHeight = 0;
 | |
|     output->crtc = NULL;
 | |
|     output->numCrtcs = 0;
 | |
|     output->crtcs = NULL;
 | |
|     output->numClones = 0;
 | |
|     output->clones = NULL;
 | |
|     output->numModes = 0;
 | |
|     output->numPreferred = 0;
 | |
|     output->modes = NULL;
 | |
|     output->numUserModes = 0;
 | |
|     output->userModes = NULL;
 | |
|     output->properties = NULL;
 | |
|     output->pendingProperties = FALSE;
 | |
|     output->changed = FALSE;
 | |
|     output->devPrivate = devPrivate;
 | |
|     
 | |
|     if (!AddResource (output->id, RROutputType, (pointer) output))
 | |
| 	return NULL;
 | |
| 
 | |
|     pScrPriv->outputs[pScrPriv->numOutputs++] = output;
 | |
|     return output;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Notify extension that output parameters have been changed
 | |
|  */
 | |
| Bool
 | |
| RROutputSetClones (RROutputPtr  output,
 | |
| 		   RROutputPtr  *clones,
 | |
| 		   int		numClones)
 | |
| {
 | |
|     RROutputPtr	*newClones;
 | |
|     int		i;
 | |
| 
 | |
|     if (numClones == output->numClones)
 | |
|     {
 | |
| 	for (i = 0; i < numClones; i++)
 | |
| 	    if (output->clones[i] != clones[i])
 | |
| 		break;
 | |
| 	if (i == numClones)
 | |
| 	    return TRUE;
 | |
|     }
 | |
|     if (numClones)
 | |
|     {
 | |
| 	newClones = malloc(numClones * sizeof (RROutputPtr));
 | |
| 	if (!newClones)
 | |
| 	    return FALSE;
 | |
|     }
 | |
|     else
 | |
| 	newClones = NULL;
 | |
|     free(output->clones);
 | |
|     memcpy (newClones, clones, numClones * sizeof (RROutputPtr));
 | |
|     output->clones = newClones;
 | |
|     output->numClones = numClones;
 | |
|     RROutputChanged (output, TRUE);
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| Bool
 | |
| RROutputSetModes (RROutputPtr	output,
 | |
| 		  RRModePtr	*modes,
 | |
| 		  int		numModes,
 | |
| 		  int		numPreferred)
 | |
| {
 | |
|     RRModePtr	*newModes;
 | |
|     int		i;
 | |
| 
 | |
|     if (numModes == output->numModes && numPreferred == output->numPreferred)
 | |
|     {
 | |
| 	for (i = 0; i < numModes; i++)
 | |
| 	    if (output->modes[i] != modes[i])
 | |
| 		break;
 | |
| 	if (i == numModes)
 | |
| 	{
 | |
| 	    for (i = 0; i < numModes; i++)
 | |
| 		RRModeDestroy (modes[i]);
 | |
| 	    return TRUE;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     if (numModes)
 | |
|     {
 | |
| 	newModes = malloc(numModes * sizeof (RRModePtr));
 | |
| 	if (!newModes)
 | |
| 	    return FALSE;
 | |
|     }
 | |
|     else
 | |
| 	newModes = NULL;
 | |
|     if (output->modes)
 | |
|     {
 | |
| 	for (i = 0; i < output->numModes; i++)
 | |
| 	    RRModeDestroy (output->modes[i]);
 | |
| 	free(output->modes);
 | |
|     }
 | |
|     memcpy (newModes, modes, numModes * sizeof (RRModePtr));
 | |
|     output->modes = newModes;
 | |
|     output->numModes = numModes;
 | |
|     output->numPreferred = numPreferred;
 | |
|     RROutputChanged (output, TRUE);
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| int
 | |
| RROutputAddUserMode (RROutputPtr    output,
 | |
| 		     RRModePtr	    mode)
 | |
| {
 | |
|     int		m;
 | |
|     ScreenPtr	pScreen = output->pScreen;
 | |
|     rrScrPriv(pScreen);
 | |
|     RRModePtr	*newModes;
 | |
| 
 | |
|     /* Check to see if this mode is already listed for this output */
 | |
|     for (m = 0; m < output->numModes + output->numUserModes; m++)
 | |
|     {
 | |
| 	RRModePtr   e = (m < output->numModes ?
 | |
| 			 output->modes[m] :
 | |
| 			 output->userModes[m - output->numModes]);
 | |
| 	if (mode == e)
 | |
| 	    return Success;
 | |
|     }
 | |
| 
 | |
|     /* Check with the DDX to see if this mode is OK */
 | |
|     if (pScrPriv->rrOutputValidateMode)
 | |
| 	if (!pScrPriv->rrOutputValidateMode (pScreen, output, mode))
 | |
| 	    return BadMatch;
 | |
| 
 | |
|     if (output->userModes)
 | |
| 	newModes = realloc(output->userModes,
 | |
| 			     (output->numUserModes + 1) * sizeof (RRModePtr));
 | |
|     else
 | |
| 	newModes = malloc(sizeof (RRModePtr));
 | |
|     if (!newModes)
 | |
| 	return BadAlloc;
 | |
| 
 | |
|     output->userModes = newModes;
 | |
|     output->userModes[output->numUserModes++] = mode;
 | |
|     ++mode->refcnt;
 | |
|     RROutputChanged (output, TRUE);
 | |
|     RRTellChanged (pScreen);
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| int
 | |
| RROutputDeleteUserMode (RROutputPtr output,
 | |
| 			RRModePtr   mode)
 | |
| {
 | |
|     int		m;
 | |
|     
 | |
|     /* Find this mode in the user mode list */
 | |
|     for (m = 0; m < output->numUserModes; m++)
 | |
|     {
 | |
| 	RRModePtr   e = output->userModes[m];
 | |
| 
 | |
| 	if (mode == e)
 | |
| 	    break;
 | |
|     }
 | |
|     /* Not there, access error */
 | |
|     if (m == output->numUserModes)
 | |
| 	return BadAccess;
 | |
| 
 | |
|     /* make sure the mode isn't active for this output */
 | |
|     if (output->crtc && output->crtc->mode == mode)
 | |
| 	return BadMatch;
 | |
| 
 | |
|     memmove (output->userModes + m, output->userModes + m + 1,
 | |
| 	     (output->numUserModes - m - 1) * sizeof (RRModePtr));
 | |
|     output->numUserModes--;
 | |
|     RRModeDestroy (mode);
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| Bool
 | |
| RROutputSetCrtcs (RROutputPtr	output,
 | |
| 		  RRCrtcPtr	*crtcs,
 | |
| 		  int		numCrtcs)
 | |
| {
 | |
|     RRCrtcPtr	*newCrtcs;
 | |
|     int		i;
 | |
| 
 | |
|     if (numCrtcs == output->numCrtcs)
 | |
|     {
 | |
| 	for (i = 0; i < numCrtcs; i++)
 | |
| 	    if (output->crtcs[i] != crtcs[i])
 | |
| 		break;
 | |
| 	if (i == numCrtcs)
 | |
| 	    return TRUE;
 | |
|     }
 | |
|     if (numCrtcs)
 | |
|     {
 | |
| 	newCrtcs = malloc(numCrtcs * sizeof (RRCrtcPtr));
 | |
| 	if (!newCrtcs)
 | |
| 	    return FALSE;
 | |
|     }
 | |
|     else
 | |
| 	newCrtcs = NULL;
 | |
|     free(output->crtcs);
 | |
|     memcpy (newCrtcs, crtcs, numCrtcs * sizeof (RRCrtcPtr));
 | |
|     output->crtcs = newCrtcs;
 | |
|     output->numCrtcs = numCrtcs;
 | |
|     RROutputChanged (output, TRUE);
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| Bool
 | |
| RROutputSetConnection (RROutputPtr  output,
 | |
| 		       CARD8	    connection)
 | |
| {
 | |
|     if (output->connection == connection)
 | |
| 	return TRUE;
 | |
|     output->connection = connection;
 | |
|     RROutputChanged (output, TRUE);
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| Bool
 | |
| RROutputSetSubpixelOrder (RROutputPtr output,
 | |
| 			  int	      subpixelOrder)
 | |
| {
 | |
|     if (output->subpixelOrder == subpixelOrder)
 | |
| 	return TRUE;
 | |
| 
 | |
|     output->subpixelOrder = subpixelOrder;
 | |
|     RROutputChanged (output, FALSE);
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| Bool
 | |
| RROutputSetPhysicalSize (RROutputPtr	output,
 | |
| 			 int		mmWidth,
 | |
| 			 int		mmHeight)
 | |
| {
 | |
|     if (output->mmWidth == mmWidth && output->mmHeight == mmHeight)
 | |
| 	return TRUE;
 | |
|     output->mmWidth = mmWidth;
 | |
|     output->mmHeight = mmHeight;
 | |
|     RROutputChanged (output, FALSE);
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| void
 | |
| RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output)
 | |
| {
 | |
|     ScreenPtr pScreen = pWin->drawable.pScreen;
 | |
|     rrScrPriv (pScreen);
 | |
|     xRROutputChangeNotifyEvent	oe;
 | |
|     RRCrtcPtr	crtc = output->crtc;
 | |
|     RRModePtr	mode = crtc ? crtc->mode : 0;
 | |
|     
 | |
|     oe.type = RRNotify + RREventBase;
 | |
|     oe.subCode = RRNotify_OutputChange;
 | |
|     oe.timestamp = pScrPriv->lastSetTime.milliseconds;
 | |
|     oe.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
 | |
|     oe.window = pWin->drawable.id;
 | |
|     oe.output = output->id;
 | |
|     if (crtc)
 | |
|     {
 | |
| 	oe.crtc = crtc->id;
 | |
| 	oe.mode = mode ? mode->mode.id : None;
 | |
| 	oe.rotation = crtc->rotation;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	oe.crtc = None;
 | |
| 	oe.mode = None;
 | |
| 	oe.rotation = RR_Rotate_0;
 | |
|     }
 | |
|     oe.connection = output->connection;
 | |
|     oe.subpixelOrder = output->subpixelOrder;
 | |
|     WriteEventsToClient (client, 1, (xEvent *) &oe);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Destroy a Output at shutdown
 | |
|  */
 | |
| void
 | |
| RROutputDestroy (RROutputPtr output)
 | |
| {
 | |
|     FreeResource (output->id, 0);
 | |
| }
 | |
| 
 | |
| static int
 | |
| RROutputDestroyResource (pointer value, XID pid)
 | |
| {
 | |
|     RROutputPtr	output = (RROutputPtr) value;
 | |
|     ScreenPtr	pScreen = output->pScreen;
 | |
|     int		m;
 | |
| 
 | |
|     if (pScreen)
 | |
|     {
 | |
| 	rrScrPriv(pScreen);
 | |
| 	int		i;
 | |
| 
 | |
| 	if (pScrPriv->primaryOutput == output)
 | |
| 	    pScrPriv->primaryOutput = NULL;
 | |
|     
 | |
| 	for (i = 0; i < pScrPriv->numOutputs; i++)
 | |
| 	{
 | |
| 	    if (pScrPriv->outputs[i] == output)
 | |
| 	    {
 | |
| 		memmove (pScrPriv->outputs + i, pScrPriv->outputs + i + 1,
 | |
| 			 (pScrPriv->numOutputs - (i + 1)) * sizeof (RROutputPtr));
 | |
| 		--pScrPriv->numOutputs;
 | |
| 		break;
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
|     if (output->modes)
 | |
|     {
 | |
| 	for (m = 0; m < output->numModes; m++)
 | |
| 	    RRModeDestroy (output->modes[m]);
 | |
| 	free(output->modes);
 | |
|     }
 | |
|     
 | |
|     for (m = 0; m < output->numUserModes; m++)
 | |
| 	RRModeDestroy (output->userModes[m]);
 | |
|     free(output->userModes);
 | |
| 
 | |
|     free(output->crtcs);
 | |
|     free(output->clones);
 | |
|     RRDeleteAllOutputProperties (output);
 | |
|     free(output);
 | |
|     return 1;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Initialize output type
 | |
|  */
 | |
| Bool
 | |
| RROutputInit (void)
 | |
| {
 | |
|     RROutputType = CreateNewResourceType (RROutputDestroyResource, "OUTPUT");
 | |
|     if (!RROutputType)
 | |
| 	return FALSE;
 | |
| 
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Initialize output type error value
 | |
|  */
 | |
| void
 | |
| RROutputInitErrorValue(void)
 | |
| {
 | |
|     SetResourceTypeErrorValue(RROutputType, RRErrorBase + BadRROutput);
 | |
| }
 | |
| 
 | |
| #define OutputInfoExtra	(SIZEOF(xRRGetOutputInfoReply) - 32)
 | |
| 
 | |
| int
 | |
| ProcRRGetOutputInfo (ClientPtr client)
 | |
| {
 | |
|     REQUEST(xRRGetOutputInfoReq);
 | |
|     xRRGetOutputInfoReply	rep;
 | |
|     RROutputPtr			output;
 | |
|     CARD8			*extra;
 | |
|     unsigned long		extraLen;
 | |
|     ScreenPtr			pScreen;
 | |
|     rrScrPrivPtr		pScrPriv;
 | |
|     RRCrtc			*crtcs;
 | |
|     RRMode			*modes;
 | |
|     RROutput			*clones;
 | |
|     char			*name;
 | |
|     int				i, n;
 | |
|     
 | |
|     REQUEST_SIZE_MATCH(xRRGetOutputInfoReq);
 | |
|     VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
 | |
| 
 | |
|     pScreen = output->pScreen;
 | |
|     pScrPriv = rrGetScrPriv(pScreen);
 | |
| 
 | |
|     rep.type = X_Reply;
 | |
|     rep.sequenceNumber = client->sequence;
 | |
|     rep.length = bytes_to_int32(OutputInfoExtra);
 | |
|     rep.timestamp = pScrPriv->lastSetTime.milliseconds;
 | |
|     rep.crtc = output->crtc ? output->crtc->id : None;
 | |
|     rep.mmWidth = output->mmWidth;
 | |
|     rep.mmHeight = output->mmHeight;
 | |
|     rep.connection = output->connection;
 | |
|     rep.subpixelOrder = output->subpixelOrder;
 | |
|     rep.nCrtcs = output->numCrtcs;
 | |
|     rep.nModes = output->numModes + output->numUserModes;
 | |
|     rep.nPreferred = output->numPreferred;
 | |
|     rep.nClones = output->numClones;
 | |
|     rep.nameLength = output->nameLength;
 | |
|     
 | |
|     extraLen = ((output->numCrtcs +
 | |
| 		 output->numModes + output->numUserModes +
 | |
| 		 output->numClones +
 | |
| 		 bytes_to_int32(rep.nameLength)) << 2);
 | |
| 
 | |
|     if (extraLen)
 | |
|     {
 | |
| 	rep.length += bytes_to_int32(extraLen);
 | |
| 	extra = malloc(extraLen);
 | |
| 	if (!extra)
 | |
| 	    return BadAlloc;
 | |
|     }
 | |
|     else
 | |
| 	extra = NULL;
 | |
| 
 | |
|     crtcs = (RRCrtc *) extra;
 | |
|     modes = (RRMode *) (crtcs + output->numCrtcs);
 | |
|     clones = (RROutput *) (modes + output->numModes + output->numUserModes);
 | |
|     name = (char *) (clones + output->numClones);
 | |
|     
 | |
|     for (i = 0; i < output->numCrtcs; i++)
 | |
|     {
 | |
| 	crtcs[i] = output->crtcs[i]->id;
 | |
| 	if (client->swapped)
 | |
| 	    swapl (&crtcs[i], n);
 | |
|     }
 | |
|     for (i = 0; i < output->numModes + output->numUserModes; i++)
 | |
|     {
 | |
| 	if (i < output->numModes)
 | |
| 	    modes[i] = output->modes[i]->mode.id;
 | |
| 	else
 | |
| 	    modes[i] = output->userModes[i - output->numModes]->mode.id;
 | |
| 	if (client->swapped)
 | |
| 	    swapl (&modes[i], n);
 | |
|     }
 | |
|     for (i = 0; i < output->numClones; i++)
 | |
|     {
 | |
| 	clones[i] = output->clones[i]->id;
 | |
| 	if (client->swapped)
 | |
| 	    swapl (&clones[i], n);
 | |
|     }
 | |
|     memcpy (name, output->name, output->nameLength);
 | |
|     if (client->swapped) {
 | |
| 	swaps(&rep.sequenceNumber, n);
 | |
| 	swapl(&rep.length, n);
 | |
| 	swapl(&rep.timestamp, n);
 | |
| 	swapl(&rep.crtc, n);
 | |
| 	swapl(&rep.mmWidth, n);
 | |
| 	swapl(&rep.mmHeight, n);
 | |
| 	swaps(&rep.nCrtcs, n);
 | |
| 	swaps(&rep.nModes, n);
 | |
| 	swaps(&rep.nClones, n);
 | |
| 	swaps(&rep.nameLength, n);
 | |
|     }
 | |
|     WriteToClient(client, sizeof(xRRGetOutputInfoReply), (char *)&rep);
 | |
|     if (extraLen)
 | |
|     {
 | |
| 	WriteToClient (client, extraLen, (char *) extra);
 | |
| 	free(extra);
 | |
|     }
 | |
|     
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| static void
 | |
| RRSetPrimaryOutput(ScreenPtr pScreen, rrScrPrivPtr pScrPriv,
 | |
| 		   RROutputPtr output)
 | |
| {
 | |
|     if (pScrPriv->primaryOutput == output)
 | |
| 	return;
 | |
| 
 | |
|     /* clear the old primary */
 | |
|     if (pScrPriv->primaryOutput) {
 | |
| 	RROutputChanged(pScrPriv->primaryOutput, 0);
 | |
| 	pScrPriv->primaryOutput = NULL;
 | |
|     }
 | |
| 
 | |
|     /* set the new primary */
 | |
|     if (output) {
 | |
| 	pScrPriv->primaryOutput = output;
 | |
| 	RROutputChanged(output, 0);
 | |
|     }
 | |
| 
 | |
|     pScrPriv->layoutChanged = TRUE;
 | |
| 
 | |
|     RRTellChanged(pScreen);
 | |
| }
 | |
| 
 | |
| int
 | |
| ProcRRSetOutputPrimary(ClientPtr client)
 | |
| {
 | |
|     REQUEST(xRRSetOutputPrimaryReq);
 | |
|     RROutputPtr output = NULL;
 | |
|     WindowPtr pWin;
 | |
|     rrScrPrivPtr pScrPriv;
 | |
|     int rc;
 | |
| 
 | |
|     REQUEST_SIZE_MATCH(xRRSetOutputPrimaryReq);
 | |
| 
 | |
|     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
 | |
|     if (rc != Success)
 | |
| 	return rc;
 | |
| 
 | |
|     if (stuff->output) {
 | |
| 	VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
 | |
| 
 | |
| 	if (output->pScreen != pWin->drawable.pScreen) {
 | |
| 	    client->errorValue = stuff->window;
 | |
| 	    return BadMatch;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     pScrPriv = rrGetScrPriv(pWin->drawable.pScreen);
 | |
|     RRSetPrimaryOutput(pWin->drawable.pScreen, pScrPriv, output);
 | |
| 
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| int
 | |
| ProcRRGetOutputPrimary(ClientPtr client)
 | |
| {
 | |
|     REQUEST(xRRGetOutputPrimaryReq);
 | |
|     WindowPtr pWin;
 | |
|     rrScrPrivPtr pScrPriv;
 | |
|     xRRGetOutputPrimaryReply rep;
 | |
|     RROutputPtr primary = NULL;
 | |
|     int rc;
 | |
| 
 | |
|     REQUEST_SIZE_MATCH(xRRGetOutputPrimaryReq);
 | |
| 
 | |
|     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
 | |
|     if (rc != Success)
 | |
| 	return rc;
 | |
| 
 | |
|     pScrPriv = rrGetScrPriv(pWin->drawable.pScreen);
 | |
|     if (pScrPriv)
 | |
| 	primary = pScrPriv->primaryOutput;
 | |
| 
 | |
|     memset(&rep, 0, sizeof(rep));
 | |
|     rep.type = X_Reply;
 | |
|     rep.sequenceNumber = client->sequence;
 | |
|     rep.output = primary ? primary->id : None;
 | |
| 
 | |
|     if (client->swapped) {
 | |
| 	int n;
 | |
| 	swaps(&rep.sequenceNumber, n);
 | |
| 	swapl(&rep.output, n);
 | |
|     }
 | |
| 
 | |
|     WriteToClient(client, sizeof(xRRGetOutputPrimaryReply), &rep);
 | |
| 
 | |
|     return Success;
 | |
| }
 |