[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