xserver: Branch 'server-1.3-branch' - 2 commits

Keith Packard keithp at kemper.freedesktop.org
Tue Feb 20 01:34:26 EET 2007


 hw/xfree86/modes/xf86RandR12.c |   50 +++++++++
 randr/mirandr.c                |   17 +++
 randr/randrstr.h               |   34 ++++++
 randr/rrcrtc.c                 |   11 +-
 randr/rrinfo.c                 |    6 -
 randr/rrmode.c                 |  218 +++++++++++++++++++++++++++++++++++------
 randr/rroutput.c               |   98 +++++++++++++++++-
 randr/rrscreen.c               |   16 ++-
 xfixes/cursor.c                |    3 
 xfixes/select.c                |    4 
 10 files changed, 405 insertions(+), 52 deletions(-)

New commits:
diff-tree d3e3490ac02cfe31b04637f847b30acf849a619a (from 63cc2a51ef87130c632a874672a8c9167f14314e)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Mon Feb 19 15:28:37 2007 -0800

    Check for clientGone before sending events from XFixes (bug #1753).
    
    Freeing resources during client closedown can cause cursor changes which
    attempt to send cursor events through the XFixes extension; a client in the
    process of closing down has no file to send events to, causing a crash when
    this path is hit.
    (cherry picked from commit 8a42af6a935b1cf0e15102e986bb527f4fab31a8)

diff --git a/xfixes/cursor.c b/xfixes/cursor.c
index c75e744..bfccadb 100755
--- a/xfixes/cursor.c
+++ b/xfixes/cursor.c
@@ -143,7 +143,8 @@ CursorDisplayCursor (ScreenPtr pScreen,
 	CursorCurrent = pCursor;
 	for (e = cursorEvents; e; e = e->next)
 	{
-	    if (e->eventMask & XFixesDisplayCursorNotifyMask)
+	    if ((e->eventMask & XFixesDisplayCursorNotifyMask) &&
+		!e->pClient->clientGone)
 	    {
 		xXFixesCursorNotifyEvent	ev;
 		ev.type = XFixesEventBase + XFixesCursorNotify;
diff --git a/xfixes/select.c b/xfixes/select.c
index 4c7a49d..77f2c27 100755
--- a/xfixes/select.c
+++ b/xfixes/select.c
@@ -78,7 +78,9 @@ XFixesSelectionCallback (CallbackListPtr
     }
     for (e = selectionEvents; e; e = e->next)
     {
-	if (e->selection == selection->selection && (e->eventMask & eventMask))
+	if (e->selection == selection->selection && 
+	    (e->eventMask & eventMask) &&
+	    !e->pClient->clientGone)
 	{
 	    xXFixesSelectionNotifyEvent	ev;
 
diff-tree 63cc2a51ef87130c632a874672a8c9167f14314e (from 1418fd8ce4c8459775bb362ca5fed4cacf1489bf)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Sun Feb 18 23:49:38 2007 -0800

    Add support for user-defined modelines in RandR.
    
    The RandR protocol spec has several requests in support of user-defined
    modes, but the implementation was stubbed out inside the X server. Fill out
    the DIX portion and start on the xf86 DDX portion. It might be necessary to
    add more code to the DDX to insert the user-defined modes into the output
    mode list.

diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index abdf92e..4e8984c 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -701,6 +701,54 @@ xf86RandR12OutputSetProperty (ScreenPtr 
     return output->funcs->set_property(output, property, value);
 }
 
+static Bool
+xf86RandR12OutputValidateMode (ScreenPtr    pScreen,
+			       RROutputPtr  randr_output,
+			       RRModePtr    randr_mode)
+{
+    xf86OutputPtr   output = randr_output->devPrivate;
+    DisplayModePtr  mode = randr_mode->devPrivate;
+
+    if (!mode)
+    {
+	mode = xalloc (sizeof (DisplayModeRec) + randr_mode->mode.nameLength + 1);
+	if (!mode)
+	    return FALSE;
+	mode->name = (char *) mode + 1;
+	memcpy (mode->name, randr_mode->name, randr_mode->mode.nameLength);
+	mode->name[randr_mode->mode.nameLength] = '\0';
+	mode->Clock = randr_mode->mode.dotClock / 1000;
+	mode->HDisplay = randr_mode->mode.width;
+	mode->HSyncStart = randr_mode->mode.hSyncStart;
+	mode->HSyncEnd = randr_mode->mode.hSyncEnd;
+	mode->HTotal = randr_mode->mode.hTotal;
+	mode->HSkew = randr_mode->mode.hSkew;
+	
+	mode->VDisplay = randr_mode->mode.height;
+	mode->VSyncStart = randr_mode->mode.vSyncStart;
+	mode->VSyncEnd = randr_mode->mode.vSyncEnd;
+	mode->VTotal = randr_mode->mode.vTotal;
+    
+	mode->Flags = randr_mode->mode.modeFlags;
+	randr_mode->devPrivate = mode;
+    }
+    if (!output->funcs->mode_valid (output, mode))
+	return FALSE;
+    return TRUE;
+}
+
+static void
+xf86RandR12ModeDestroy (ScreenPtr pScreen, RRModePtr randr_mode)
+{
+    DisplayModePtr  mode = randr_mode->devPrivate;
+
+    if (mode)
+    {
+	xfree (mode);
+	randr_mode->devPrivate = NULL;
+    }
+}
+
 /**
  * Given a list of xf86 modes and a RandR Output object, construct
  * RandR modes and assign them to the output
@@ -932,6 +980,8 @@ xf86RandR12Init12 (ScreenPtr pScreen)
     rp->rrCrtcSet = xf86RandR12CrtcSet;
     rp->rrCrtcSetGamma = xf86RandR12CrtcSetGamma;
     rp->rrOutputSetProperty = xf86RandR12OutputSetProperty;
+    rp->rrOutputValidateMode = xf86RandR12OutputValidateMode;
+    rp->rrModeDestroy = xf86RandR12ModeDestroy;
     rp->rrSetConfig = NULL;
     pScrn->PointerMoved = xf86RandR12PointerMoved;
     if (!xf86RandR12CreateObjects12 (pScreen))
diff --git a/randr/mirandr.c b/randr/mirandr.c
index 0b763e1..47136fb 100644
--- a/randr/mirandr.c
+++ b/randr/mirandr.c
@@ -73,6 +73,20 @@ miRROutputSetProperty (ScreenPtr	    pSc
     return TRUE;
 }
 
+Bool
+miRROutputValidateMode (ScreenPtr	    pScreen,
+			RROutputPtr	    output,
+			RRModePtr	    mode)
+{
+    return FALSE;
+}
+
+void
+miRRModeDestroy (ScreenPtr  pScreen,
+		 RRModePtr  mode)
+{
+}
+
 /*
  * This function assumes that only a single depth can be
  * displayed at a time, but that all visuals of that depth
@@ -102,7 +116,8 @@ miRandRInit (ScreenPtr pScreen)
     pScrPriv->rrCrtcSet = miRRCrtcSet;
     pScrPriv->rrCrtcSetGamma = miRRCrtcSetGamma;
     pScrPriv->rrOutputSetProperty = miRROutputSetProperty;
-    
+    pScrPriv->rrOutputValidateMode = miRROutputValidateMode;
+    pScrPriv->rrModeDestroy = miRRModeDestroy;
     
     RRScreenSetSizeRange (pScreen,
 			  pScreen->width, pScreen->height,
diff --git a/randr/randrstr.h b/randr/randrstr.h
index f86f9b5..1fc2520 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -80,7 +80,7 @@ struct _rrMode {
     xRRModeInfo	    mode;
     char	    *name;
     void	    *devPrivate;
-    Bool	    userDefined;
+    ScreenPtr	    userScreen;
 };
 
 struct _rrPropertyValue {
@@ -135,6 +135,8 @@ struct _rrOutput {
     int		    numModes;
     int		    numPreferred;
     RRModePtr	    *modes;
+    int		    numUserModes;
+    RRModePtr	    *userModes;
     Bool	    changed;
     RRPropertyPtr   properties;
     void	    *devPrivate;
@@ -164,6 +166,13 @@ typedef Bool (*RROutputSetPropertyProcPt
 					    Atom		property,
 					    RRPropertyValuePtr	value);
 
+typedef Bool (*RROutputValidateModeProcPtr) (ScreenPtr		pScreen,
+					     RROutputPtr	output,
+					     RRModePtr		mode);
+
+typedef void (*RRModeDestroyProcPtr) (ScreenPtr	    pScreen,
+				      RRModePtr	    mode);
+
 #endif
 
 typedef Bool (*RRGetInfoProcPtr) (ScreenPtr pScreen, Rotation *rotations);
@@ -208,6 +217,8 @@ typedef struct _rrScrPriv {
     RRCrtcSetProcPtr	    rrCrtcSet;
     RRCrtcSetGammaProcPtr   rrCrtcSetGamma;
     RROutputSetPropertyProcPtr	rrOutputSetProperty;
+    RROutputValidateModeProcPtr	rrOutputValidateMode;
+    RRModeDestroyProcPtr	rrModeDestroy;
 #endif
     
     /*
@@ -394,6 +405,15 @@ miRROutputSetProperty (ScreenPtr	    pSc
 		       Atom		    property,
 		       RRPropertyValuePtr   value);
 
+Bool
+miRROutputValidateMode (ScreenPtr	    pScreen,
+			RROutputPtr	    output,
+			RRModePtr	    mode);
+
+void
+miRRModeDestroy (ScreenPtr  pScreen,
+		 RRModePtr  mode);
+
 /* randr.c */
 /*
  * Send all pending events
@@ -548,6 +568,10 @@ Bool
 RRCrtcGammaSetSize (RRCrtcPtr	crtc,
 		    int		size);
 
+/*
+ * Return the area of the frame buffer scanned out by the crtc,
+ * taking into account the current mode and rotation
+ */
 void
 RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height);
 
@@ -671,6 +695,14 @@ RROutputSetModes (RROutputPtr	output,
 		  int		numModes,
 		  int		numPreferred);
 
+int
+RROutputAddUserMode (RROutputPtr    output,
+		     RRModePtr	    mode);
+
+int
+RROutputDeleteUserMode (RROutputPtr output,
+			RRModePtr   mode);
+
 Bool
 RROutputSetCrtcs (RROutputPtr	output,
 		  RRCrtcPtr	*crtcs,
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 2ae9040..a90b072 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -655,10 +655,15 @@ ProcRRSetCrtcConfig (ClientPtr client)
 	    return BadMatch;
 	}
 	/* validate mode for this output */
-	for (j = 0; j < outputs[i]->numModes; j++)
-	    if (outputs[i]->modes[j] == mode)
+	for (j = 0; j < outputs[i]->numModes + outputs[i]->numUserModes; j++)
+	{
+	    RRModePtr	m = (j < outputs[i]->numModes ? 
+			     outputs[i]->modes[j] :
+			     outputs[i]->userModes[j - outputs[i]->numModes]);
+	    if (m == mode)
 		break;
-	if (j == outputs[i]->numModes)
+	}
+	if (j == outputs[i]->numModes + outputs[i]->numUserModes)
 	{
 	    if (outputs)
 		xfree (outputs);
diff --git a/randr/rrinfo.c b/randr/rrinfo.c
index 797cdb1..549d501 100644
--- a/randr/rrinfo.c
+++ b/randr/rrinfo.c
@@ -157,9 +157,11 @@ RRScanOldConfig (ScreenPtr pScreen, Rota
     pScrPriv->nSizes = 0;
 	    
     /* find size bounds */
-    for (i = 0; i < output->numModes; i++) 
+    for (i = 0; i < output->numModes + output->numUserModes; i++) 
     {
-	RRModePtr   mode = output->modes[i];
+	RRModePtr   mode = (i < output->numModes ? 
+			    output->modes[i] : 
+			    output->userModes[i-output->numModes]);
         CARD16	    width = mode->mode.width;
         CARD16	    height = mode->mode.height;
 	
diff --git a/randr/rrmode.c b/randr/rrmode.c
index 261e1b7..e268cc2 100644
--- a/randr/rrmode.c
+++ b/randr/rrmode.c
@@ -48,25 +48,13 @@ RRModeEqual (xRRModeInfo *a, xRRModeInfo
 static int	    num_modes;
 static RRModePtr    *modes;
 
-RRModePtr
-RRModeGet (xRRModeInfo	*modeInfo,
-	   const char	*name)
+static RRModePtr
+RRModeCreate (xRRModeInfo   *modeInfo,
+	      const char    *name,
+	      ScreenPtr	    userScreen)
 {
-    int	i;
-    RRModePtr	mode;
-    RRModePtr	*newModes;
-
-    for (i = 0; i < num_modes; i++)
-    {
-	mode = modes[i];
-	if (RRModeEqual (&mode->mode, modeInfo) &&
-	    !memcmp (name, mode->name, modeInfo->nameLength))
-	{
-	    ++mode->refcnt;
-	    return mode;
-	}
-    }
-
+    RRModePtr	mode, *newModes;
+    
     if (!RRInit ())
 	return NULL;
 
@@ -78,7 +66,7 @@ RRModeGet (xRRModeInfo	*modeInfo,
     mode->name = (char *) (mode + 1);
     memcpy (mode->name, name, modeInfo->nameLength);
     mode->name[modeInfo->nameLength] = '\0';
-    mode->userDefined = FALSE;
+    mode->userScreen = userScreen;
 
     if (num_modes)
 	newModes = xrealloc (modes, (num_modes + 1) * sizeof (RRModePtr));
@@ -104,11 +92,75 @@ RRModeGet (xRRModeInfo	*modeInfo,
     return mode;
 }
 
+static RRModePtr
+RRModeFindByName (const char	*name,
+		  CARD16    	nameLength)
+{
+    int		i;
+    RRModePtr	mode;
+
+    for (i = 0; i < num_modes; i++)
+    {
+	mode = modes[i];
+	if (mode->mode.nameLength == nameLength &&
+	    !memcmp (name, mode->name, nameLength))
+	{
+	    return mode;
+	}
+    }
+    return NULL;
+}
+
+RRModePtr
+RRModeGet (xRRModeInfo	*modeInfo,
+	   const char	*name)
+{
+    int	i;
+
+    for (i = 0; i < num_modes; i++)
+    {
+	RRModePtr   mode = modes[i];
+	if (RRModeEqual (&mode->mode, modeInfo) &&
+	    !memcmp (name, mode->name, modeInfo->nameLength))
+	{
+	    ++mode->refcnt;
+	    return mode;
+	}
+    }
+
+    return RRModeCreate (modeInfo, name, NULL);
+}
+
+static RRModePtr
+RRModeCreateUser (ScreenPtr	pScreen,
+		  xRRModeInfo	*modeInfo,
+		  const char	*name,
+		  int		*error)
+{
+    RRModePtr	mode;
+
+    mode = RRModeFindByName (name, modeInfo->nameLength);
+    if (mode)
+    {
+	*error = BadName;
+	return NULL;
+    }
+    
+    mode = RRModeCreate (modeInfo, name, pScreen);
+    if (!mode)
+    {
+	*error = BadAlloc;
+	return NULL;
+    }
+    *error = Success;
+    return mode;
+}
+
 RRModePtr *
 RRModesForScreen (ScreenPtr pScreen, int *num_ret)
 {
     rrScrPriv(pScreen);
-    int	o, c;
+    int		o, c, m;
     RRModePtr	*screen_modes;
     int		num_screen_modes = 0;
 
@@ -122,9 +174,11 @@ RRModesForScreen (ScreenPtr pScreen, int
 	RROutputPtr	output = pScrPriv->outputs[o];
 	int		m, n;
 
-	for (m = 0; m < output->numModes; m++)
+	for (m = 0; m < output->numModes + output->numUserModes; m++)
 	{
-	    RRModePtr	mode = output->modes[m];
+	    RRModePtr   mode = (m < output->numModes ? 
+				output->modes[m] : 
+				output->userModes[m-output->numModes]);
 	    for (n = 0; n < num_screen_modes; n++)
 		if (screen_modes[n] == mode)
 		    break;
@@ -150,6 +204,23 @@ RRModesForScreen (ScreenPtr pScreen, int
 	if (n == num_screen_modes)
 	    screen_modes[num_screen_modes++] = mode;
     }
+    /*
+     * Add all user modes for this screen
+     */
+    for (m = 0; m < num_modes; m++)
+    {
+	RRModePtr	mode = modes[m];
+	int		n;
+
+	if (mode->userScreen != pScreen)
+	    continue;
+	for (n = 0; n < num_screen_modes; n++)
+	    if (screen_modes[n] == mode)
+		break;
+	if (n == num_screen_modes)
+	    screen_modes[num_screen_modes++] = mode;
+    }
+    
     *num_ret = num_screen_modes;
     return screen_modes;
 }
@@ -205,38 +276,123 @@ int
 ProcRRCreateMode (ClientPtr client)
 {
     REQUEST(xRRCreateModeReq);
+    xRRCreateModeReply	rep;
+    WindowPtr		pWin;
+    ScreenPtr		pScreen;
+    rrScrPrivPtr	pScrPriv;
+    xRRModeInfo		*modeInfo;
+    long		units_after;
+    char		*name;
+    int			error;
+    RRModePtr		mode;
+    
+    REQUEST_AT_LEAST_SIZE (xRRCreateModeReq);
+    pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
+					   SecurityReadAccess);
+
+    if (!pWin)
+	return BadWindow;
+    pScreen = pWin->drawable.pScreen;
+    pScrPriv = rrGetScrPriv(pScreen);
+    
+    modeInfo = &stuff->modeInfo;
+    name = (char *) (stuff + 1);
+    units_after = (stuff->length - (sizeof (xRRCreateModeReq) >> 2));
+
+    /* check to make sure requested name fits within the data provided */
+    if ((int) (modeInfo->nameLength + 3) >> 2 > units_after)
+	return BadLength;
+
+    mode = RRModeCreateUser (pScreen, modeInfo, name, &error);
+    if (!mode)
+	return error;
+
+    rep.type = X_Reply;
+    rep.pad0 = 0;
+    rep.sequenceNumber = client->sequence;
+    rep.length = 0;
+    rep.mode = mode->mode.id;
+    if (client->swapped)
+    {
+	int n;
+    	swaps(&rep.sequenceNumber, n);
+    	swapl(&rep.length, n);
+	swapl(&rep.mode, n);
+    }
+    WriteToClient(client, sizeof(xRRCreateModeReply), (char *)&rep);
     
-    REQUEST_SIZE_MATCH(xRRCreateModeReq);
-    (void) stuff;
-    return BadImplementation; 
+    return client->noClientException;
 }
 
 int
 ProcRRDestroyMode (ClientPtr client)
 {
     REQUEST(xRRDestroyModeReq);
+    RRModePtr	mode;
     
     REQUEST_SIZE_MATCH(xRRDestroyModeReq);
-    (void) stuff;
-    return BadImplementation; 
+    mode = LookupIDByType (stuff->mode, RRModeType);
+    if (!mode)
+    {
+	client->errorValue = stuff->mode;
+	return RRErrorBase + BadRRMode;
+    }
+    if (!mode->userScreen)
+	return BadMatch;
+    if (mode->refcnt > 1)
+	return BadAccess;
+    FreeResource (stuff->mode, 0);
+    return Success;
 }
 
 int
 ProcRRAddOutputMode (ClientPtr client)
 {
     REQUEST(xRRAddOutputModeReq);
+    RRModePtr	mode;
+    RROutputPtr	output;
     
     REQUEST_SIZE_MATCH(xRRAddOutputModeReq);
-    (void) stuff;
-    return BadImplementation; 
+    output = LookupOutput(client, stuff->output, SecurityReadAccess);
+
+    if (!output)
+    {
+	client->errorValue = stuff->output;
+	return RRErrorBase + BadRROutput;
+    }
+    
+    mode = LookupIDByType (stuff->mode, RRModeType);
+    if (!mode)
+    {
+	client->errorValue = stuff->mode;
+	return RRErrorBase + BadRRMode;
+    }
+    
+    return RROutputAddUserMode (output, mode);
 }
 
 int
 ProcRRDeleteOutputMode (ClientPtr client)
 {
     REQUEST(xRRDeleteOutputModeReq);
+    RRModePtr	mode;
+    RROutputPtr	output;
     
     REQUEST_SIZE_MATCH(xRRDeleteOutputModeReq);
-    (void) stuff;
-    return BadImplementation; 
+    output = LookupOutput(client, stuff->output, SecurityReadAccess);
+
+    if (!output)
+    {
+	client->errorValue = stuff->output;
+	return RRErrorBase + BadRROutput;
+    }
+    
+    mode = LookupIDByType (stuff->mode, RRModeType);
+    if (!mode)
+    {
+	client->errorValue = stuff->mode;
+	return RRErrorBase + BadRRMode;
+    }
+    
+    return RROutputDeleteUserMode (output, mode);
 }
diff --git a/randr/rroutput.c b/randr/rroutput.c
index 8007a8a..31ec924 100644
--- a/randr/rroutput.c
+++ b/randr/rroutput.c
@@ -76,6 +76,8 @@ RROutputCreate (const char  *name,
     output->numModes = 0;
     output->numPreferred = 0;
     output->modes = NULL;
+    output->numUserModes = 0;
+    output->userModes = NULL;
     output->properties = NULL;
     output->changed = FALSE;
     output->devPrivate = devPrivate;
@@ -192,6 +194,74 @@ RROutputSetModes (RROutputPtr	output,
     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 = xrealloc (output->userModes,
+			     (output->numUserModes + 1) * sizeof (RRModePtr));
+    else
+	newModes = xalloc (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));
+    RRModeDestroy (mode);
+    return Success;
+}
+
 Bool
 RROutputSetCrtcs (RROutputPtr	output,
 		  RRCrtcPtr	*crtcs,
@@ -308,9 +378,9 @@ RRDeliverOutputEvent(ClientPtr client, W
  * Destroy a Output at shutdown
  */
 void
-RROutputDestroy (RROutputPtr crtc)
+RROutputDestroy (RROutputPtr output)
 {
-    FreeResource (crtc->id, 0);
+    FreeResource (output->id, 0);
 }
 
 static int
@@ -318,6 +388,7 @@ RROutputDestroyResource (pointer value, 
 {
     RROutputPtr	output = (RROutputPtr) value;
     ScreenPtr	pScreen = output->pScreen;
+    int		m;
 
     if (pScreen)
     {
@@ -335,8 +406,15 @@ RROutputDestroyResource (pointer value, 
 	    }
 	}
     }
+    /* XXX destroy all modes? */
     if (output->modes)
 	xfree (output->modes);
+    
+    for (m = 0; m < output->numUserModes; m++)
+	RRModeDestroy (output->userModes[m]);
+    if (output->userModes)
+	xfree (output->userModes);
+
     if (output->crtcs)
 	xfree (output->crtcs);
     if (output->clones)
@@ -383,7 +461,10 @@ ProcRRGetOutputInfo (ClientPtr client)
     output = LookupOutput(client, stuff->output, SecurityReadAccess);
 
     if (!output)
+    {
+	client->errorValue = stuff->output;
 	return RRErrorBase + BadRROutput;
+    }
 
     pScreen = output->pScreen;
     pScrPriv = rrGetScrPriv(pScreen);
@@ -398,13 +479,13 @@ ProcRRGetOutputInfo (ClientPtr client)
     rep.connection = output->connection;
     rep.subpixelOrder = output->subpixelOrder;
     rep.nCrtcs = output->numCrtcs;
-    rep.nModes = output->numModes;
+    rep.nModes = output->numModes + output->numUserModes;
     rep.nPreferred = output->numPreferred;
     rep.nClones = output->numClones;
     rep.nameLength = output->nameLength;
     
     extraLen = ((output->numCrtcs + 
-		 output->numModes + 
+		 output->numModes + output->numUserModes +
 		 output->numClones +
 		 ((rep.nameLength + 3) >> 2)) << 2);
 
@@ -420,7 +501,7 @@ ProcRRGetOutputInfo (ClientPtr client)
 
     crtcs = (RRCrtc *) extra;
     modes = (RRMode *) (crtcs + output->numCrtcs);
-    clones = (RROutput *) (modes + output->numModes);
+    clones = (RROutput *) (modes + output->numModes + output->numUserModes);
     name = (char *) (clones + output->numClones);
     
     for (i = 0; i < output->numCrtcs; i++)
@@ -429,9 +510,12 @@ ProcRRGetOutputInfo (ClientPtr client)
 	if (client->swapped)
 	    swapl (&crtcs[i], n);
     }
-    for (i = 0; i < output->numModes; i++)
+    for (i = 0; i < output->numModes + output->numUserModes; i++)
     {
-	modes[i] = output->modes[i]->mode.id;
+	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);
     }
diff --git a/randr/rrscreen.c b/randr/rrscreen.c
index 7a33ef6..8aa26fa 100644
--- a/randr/rrscreen.c
+++ b/randr/rrscreen.c
@@ -479,7 +479,7 @@ RR10GetData (ScreenPtr pScreen, RROutput
 {
     RR10DataPtr	    data;
     RRScreenSizePtr size;
-    int		    nmode = output->numModes;
+    int		    nmode = output->numModes + output->numUserModes;
     int		    o, os, l, r;
     RRScreenRatePtr refresh;
     CARD16	    vRefresh;
@@ -506,11 +506,14 @@ RR10GetData (ScreenPtr pScreen, RROutput
     /*
      * find modes not yet listed
      */
-    for (o = 0; o < output->numModes; o++)
+    for (o = 0; o < output->numModes + output->numUserModes; o++)
     {
 	if (used[o]) continue;
 	
-	mode = output->modes[o];
+	if (o < output->numModes)
+	    mode = output->modes[o];
+	else
+	    mode = output->userModes[o - output->numModes];
 	
 	l = data->nsize;
 	size[l].id = data->nsize;
@@ -530,9 +533,12 @@ RR10GetData (ScreenPtr pScreen, RROutput
 	/*
 	 * Find all modes with matching size
 	 */
-	for (os = o; os < output->numModes; os++)
+	for (os = o; os < output->numModes + output->numUserModes; os++)
 	{
-	    mode = output->modes[os];
+	    if (os < output->numModes)
+		mode = output->modes[os];
+	    else
+		mode = output->userModes[os - output->numModes];
 	    if (mode->mode.width == size[l].width &&
 		mode->mode.height == size[l].height)
 	    {



More information about the xorg-commit mailing list