[PATCH xserver/hw/xfree86/modes/xf86Crtc.c] add monitor Option "ZoomModes"

vdb at picaros.org vdb at picaros.org
Tue Aug 30 22:34:26 PDT 2011


This patch adds support for the

  Option "ZoomModes" "1600x1200 1280x1024 1280x1024 640x480"

in a monitor section.  The code tries to match each mode name and 
sets the M_T_USERDEF mode type bit if found.  A mode will not be 
rematched so specifying a name twice selects the next, usually lower 
refresh rate, mode.

The option value is a string of mode names delimited by spaces.  As 
such, name tokenization is done at output enable time.  Ideally 
this should be done when parsing the Xorg.conf file.  A check of 
xserver/hw/xfree86/parser/{Flags.c Monitor.c scan.c xf86Optrec.h} 
shows 2 other possibilities:

1. Allow a new keyword ZoomModes followed by multiple mode names.  This
  would be a port of the Screen/Display/Modes code.

2. Allow generic options to be followed by multiple arguments.  This 
  requires either a char *opt_val[MAXVALS] thus introducing a compile 
  time maximum, a linked list of values, or a flexible array using 
  e.g. a char *opt_val[].  

These alternatives are not forward compatible since an older X server 
will fail to parse such constructs.  The option keyword extension is 
the logical choice but seems not worth the added complexity.  

Since enabling and disabling outputs is not a common event nor time 
critical the subideal form, the string of mode names, seems the best 
choice.  

A patch for the man page is included.

http://bugs.freedesktop.org/show_bug.cgi?id=17954

Signed-off-by: Servaas Vandenberghe
diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index c2814d4..74c8d66 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -432,6 +433,7 @@ extern XF86ConfigPtr xf86configptr;
 
 typedef enum {
     OPTION_PREFERRED_MODE,
+    OPTION_ZOOM_MODES,
     OPTION_POSITION,
     OPTION_BELOW,
     OPTION_RIGHT_OF,
@@ -450,6 +452,7 @@ typedef enum {
 
 static OptionInfoRec xf86OutputOptions[] = {
     {OPTION_PREFERRED_MODE, "PreferredMode",	OPTV_STRING,  {0}, FALSE },
+    {OPTION_ZOOM_MODES,     "ZoomModes",	OPTV_STRING,  {0}, FALSE },
     {OPTION_POSITION,	    "Position",		OPTV_STRING,  {0}, FALSE },
     {OPTION_BELOW,	    "Below",		OPTV_STRING,  {0}, FALSE },
     {OPTION_RIGHT_OF,	    "RightOf",		OPTV_STRING,  {0}, FALSE },
@@ -1453,6 +1456,73 @@ preferredMode(ScrnInfoPtr pScrn, xf86OutputPtr output)
     return preferred_mode;
 }
 
+/** identify a token
+ * args
+ *   src[]  the string with zero or more tokens, e.g. "tok0 tok1".
+ *   buf[]  used to store a '\0' terminated copy of the first token.
+ * return
+ *   a pointer into src[] at the token terminating character, or
+ *   NULL if no token is found.
+ */
+static const char *
+gettoken(const char *src, char *buf)
+{
+    const char *token, *next, *delim = " \t";
+    int skip, len;
+
+    if (!src)
+	return NULL;
+
+    skip = strspn(src, delim);
+    token = &src[skip];
+
+    /* Support for backslash escaped delimiters could be implemented here. */
+    len = strcspn(token, delim);
+    if (buf) {
+	strncpy(buf, token, len);
+	buf[len] = '\0';
+    }
+
+    /* token[0] != '\0'  <==>  len > 0 */
+    next = len ? &token[len] : NULL;
+
+    return next;
+}
+
+static int
+processZoomModes(xf86OutputPtr output)
+{
+    const char *zoom_modes;
+    int count = 0;
+
+    /* Check for a user configured zoom mode list
+     * e.g. Option "ZoomModes" "1600x1200 1280x1024 1280x1024 640x480"
+     */
+    zoom_modes = xf86GetOptValString(output->options, OPTION_ZOOM_MODES);
+
+    if (zoom_modes) {
+	int bufsiz = strlen(zoom_modes) + 1;
+	char buf[bufsiz];
+	const char *next;
+
+	next = gettoken(zoom_modes, buf);
+	while (next) {
+	    DisplayModePtr mode;
+
+	    for (mode = output->probed_modes; mode; mode = mode->next)
+		if (!strcmp(buf, mode->name) && !(mode->type & M_T_USERDEF)) {
+		    mode->type |= M_T_USERDEF;
+		    break;
+		}
+
+	    count++;
+	    next = gettoken(next, buf);
+	}
+    }
+
+    return count;
+}
+
 static void
 GuessRangeFromModes(MonPtr mon, DisplayModePtr mode)
 {
@@ -1734,7 +1804,6 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY)
 	
 	/* Check for a configured preference for a particular mode */
 	preferred_mode = preferredMode(scrn, output);
-
 	if (preferred_mode)
 	{
 	    for (mode = output->probed_modes; mode; mode = mode->next)
@@ -1752,12 +1821,15 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY)
 			mode->prev = NULL;
 			output->probed_modes = mode;
 		    }
-		    mode->type |= (M_T_PREFERRED|M_T_USERPREF);
+		    mode->type |= (M_T_USERPREF|M_T_PREFERRED);
 		    break;
 		}
 	    }
 	}
-	
+
+	/* Ctrl+Alt+Keypad-{Plus,Minus} zoom mode M_T_USERDEF */
+	processZoomModes(output);
+
 	output->initial_rotation = xf86OutputInitialRotation (output);
 
 	if (debug_modes) {
--- xserver/hw/xfree86/man/xorg.conf.man-b	2011-08-28 23:25:27.000000000 +0200
+++ xserver/hw/xfree86/man/xorg.conf.man	2011-08-30 19:02:50.000000000 +0200
@@ -1671,6 +1671,18 @@
 of the monitor.
 (RandR 1.2-supporting drivers only)
 .TP 7
+.BI "Option \*qZoomModes\*q \*q" name " " name " " ... \*q
+This optional entry specifies modes to be marked as zoom modes.  
+It is possible to switch to the next and previous mode with
+.B Ctrl+Alt+Keypad\-Plus
+and
+.BR Ctrl+Alt+Keypad\-Minus .
+All these keypad available modes are selected from the screen mode list.  
+This list is a copy of the compatibility output monitor mode list.  
+Since this output is the output connected to the lowest dot\-resolution 
+monitor, as determined from its largest mode, that monitor defines the 
+available zoom modes.  (RandR 1.2-supporting drivers only)
+.TP 7
 .BI "Option \*qPosition\*q \*q" x " " y \*q
 This optional entry specifies the position of the monitor within the X
 screen.


More information about the xorg-devel mailing list