[PATCH] XKB named indicator support for led state query/set
Alan Coopersmith
Alan.Coopersmith at Sun.COM
Tue Jun 16 13:26:11 PDT 2009
xset q now lists XKB named indicator states in addition to led bitmask
Sample output:
Keyboard Control:
auto repeat: on key click percent: 0 LED mask: 0000000a
XKB indicators:
00: Caps Lock: off 01: Num Lock: on 02: Scroll Lock: off
03: Compose: on 04: Shift Lock: off 05: Group 2: off
06: Mouse Keys: off
[...]
New options "xset led named <name>" and "xset -led named <name>" allow
turning named leds/virtual indicators on & off.
('named' is keyword necessary to avoid ambiguity if an XKB indicator
is given a numeric name or a name that matches an existing xkb option
due to xset's horrible historic command line syntax model.)
Signed-off-by: Alan Coopersmith <alan.coopersmith at sun.com>
---
While debugging a complex application recently failing in XkbSetNamedIndicator,
I wished for a simpler test case - since xset already has get/state for leds by
number, it seemed the most likely place to stick such functionality, even though
xset has too many options already, with a horrible command line syntax for them.
Still, "xset led named 'Scroll Lock'" seems more user friendly than "xset led 2"
and saves the long diatribe on how different X servers may have different led
values for the same led and leaving users to trial & error to find what theirs
are.
xset.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
xset.man | 10 +++-
2 files changed, 140 insertions(+), 7 deletions(-)
diff --git a/xset.c b/xset.c
index ae1d818..5283b09 100644
--- a/xset.c
+++ b/xset.c
@@ -153,6 +153,7 @@ static void set_bell_dur(Display *dpy, int duration);
static void set_font_path(Display *dpy, char *path, int special,
int before, int after);
static void set_led(Display *dpy, int led, int led_mode);
+static void xkbset_led(Display *dpy, const char *led, int led_mode);
static void set_mouse(Display *dpy, int acc_num, int acc_denom, int threshold);
static void set_saver(Display *dpy, int mask, int value);
static void set_repeat(Display *dpy, int key, int auto_repeat_mode);
@@ -439,6 +440,15 @@ main(int argc, char *argv[])
break;
}
arg = nextarg(i, argv);
+ if (strcmp(arg, "named") == 0) {
+ if (++i >= argc) {
+ usage("missing argument to led named", NULL);
+ } else {
+ arg = nextarg(i, argv);
+ xkbset_led(dpy, arg, values.led_mode);
+ }
+ break;
+ }
if (is_number(arg, 32) && atoi(arg) > 0) {
values.led = atoi(arg);
i++;
@@ -453,6 +463,15 @@ main(int argc, char *argv[])
break;
}
arg = nextarg(i, argv);
+ if (strcmp(arg, "named") == 0) {
+ if (++i >= argc) {
+ usage("missing argument to -led named", NULL);
+ } else {
+ arg = nextarg(i, argv);
+ xkbset_led(dpy, arg, values.led_mode);
+ }
+ break;
+ }
if (strcmp(arg, "on") == 0) {
i++;
} else if (strcmp(arg, "off") == 0) { /* ...except in this case. */
@@ -1061,6 +1080,36 @@ set_led(Display *dpy, int led, int led_mode)
}
static void
+xkbset_led(Display *dpy, const char *led, int led_mode)
+{
+#ifndef XKB
+ error(" xset was not built with XKB Extension support\n");
+#else
+ int xkbmajor = XkbMajorVersion, xkbminor = XkbMinorVersion;
+ int xkbopcode, xkbevent, xkberror;
+ Atom ledatom;
+
+ if (XkbQueryExtension(dpy, &xkbopcode, &xkbevent, &xkberror,
+ &xkbmajor, &xkbminor)) {
+ ledatom = XInternAtom(dpy, led, True);
+ if ((ledatom != None) &&
+ XkbGetNamedIndicator(dpy, ledatom, NULL, NULL, NULL, NULL)) {
+ if (XkbSetNamedIndicator(dpy, ledatom, True,
+ led_mode, False, NULL) == False) {
+ printf("Failed to set led named %s %s\n",
+ led, led_mode ? "on" : "off");
+ }
+ } else {
+ fprintf(stderr,"%s: Invalid led name: %s\n", progName, led);
+ }
+ } else {
+ printf(" Server does not have the XKB Extension\n");
+ }
+#endif
+ return;
+}
+
+static void
set_mouse(Display *dpy, int acc_num, int acc_denom, int threshold)
{
int do_accel = True, do_threshold = True;
@@ -1314,10 +1363,86 @@ query(Display *dpy)
#ifdef XKB
if (XkbQueryExtension(dpy, &xkbopcode, &xkbevent, &xkberror, &xkbmajor,
&xkbminor)
- && (xkb = XkbAllocKeyboard()) != NULL
- && XkbGetControls(dpy, XkbRepeatKeysMask, xkb) == Success)
- printf(" auto repeat delay: %d repeat rate: %d\n",
- xkb->ctrls->repeat_delay, 1000 / xkb->ctrls->repeat_interval);
+ && (xkb = XkbAllocKeyboard()) != NULL) {
+ if (XkbGetNames(dpy, XkbIndicatorNamesMask, xkb) == Success) {
+ Atom iatoms[XkbNumIndicators];
+ char *iatomnames[XkbNumIndicators];
+ Bool istates[XkbNumIndicators];
+ int inds[XkbNumIndicators];
+ int activecount = 0;
+ int maxnamelen = 0;
+ int columnwidth;
+ int linewidth;
+
+ printf(" XKB indicators:\n");
+
+ for (i = 0, j = 0; i < XkbNumIndicators; i++) {
+ if (xkb->names->indicators[i] != None) {
+ iatoms[j++] = xkb->names->indicators[i];
+ }
+ }
+
+ if (XGetAtomNames(dpy, iatoms, j, iatomnames)) {
+ for (i = 0; i < j; i++) {
+ Bool state;
+ int ind;
+
+ if (XkbGetNamedIndicator(dpy, iatoms[i], &inds[i],
+ &istates[i], NULL, NULL)) {
+ int namelen = strlen(iatomnames[i]);
+ if (namelen > maxnamelen) {
+ maxnamelen = namelen;
+ }
+ activecount++;
+ } else {
+ inds[i] = -1;
+ }
+ }
+ }
+
+ if (activecount == 0) {
+ printf(" None\n");
+ } else {
+
+#define XKB_IND_FORMAT_CHARS 13 /* size of other chars in ' DD: X: off' */
+#define MAX_LINE_WIDTH 76
+
+ columnwidth = maxnamelen + XKB_IND_FORMAT_CHARS;
+ if (columnwidth > MAX_LINE_WIDTH) {
+ columnwidth = MAX_LINE_WIDTH;
+ }
+
+ for (i = 0, linewidth = 0; i < activecount ; i++) {
+ if (inds[i] != -1) {
+ int spaces = columnwidth - XKB_IND_FORMAT_CHARS
+ - strlen(iatomnames[i]);
+
+ if (spaces < 0)
+ spaces = 0;
+
+ linewidth += printf(" %02d: %s: %*s",
+ inds[i], iatomnames[i],
+ spaces + 3,
+ on_or_off(istates[i],
+ True, "on ",
+ False, "off", buf));
+ }
+ if (linewidth > (MAX_LINE_WIDTH - columnwidth)) {
+ printf("\n");
+ linewidth = 0;
+ }
+ }
+ if (linewidth > 0) {
+ printf("\n");
+ }
+ }
+ }
+ if (XkbGetControls(dpy, XkbRepeatKeysMask, xkb) == Success) {
+ printf(" auto repeat delay: %d repeat rate: %d\n",
+ xkb->ctrls->repeat_delay,
+ 1000 / xkb->ctrls->repeat_interval);
+ }
+ }
#ifdef XF86MISC
else
#endif
@@ -1578,6 +1703,10 @@ usage(char *fmt, ...)
fprintf(stderr, " To set LED states off or on:\n");
fprintf(stderr, "\t-led [1-32] led off\n");
fprintf(stderr, "\t led [1-32] led on\n");
+#ifdef XKB
+ fprintf(stderr, "\t-led named 'name' led off\n");
+ fprintf(stderr, "\t led named 'name' led on\n");
+#endif
fprintf(stderr, " To set mouse acceleration and threshold:\n");
fprintf(stderr, "\t m [acc_mult[/acc_div] [thr]] m default\n");
fprintf(stderr, " To set pixel colors:\n");
diff --git a/xset.man b/xset.man
index 02cd87c..7446efc 100644
--- a/xset.man
+++ b/xset.man
@@ -54,7 +54,7 @@ xset - user preference utility for X
[-led [\fIinteger\fP]]
[+led [\fIinteger\fP]]
.br
-[led {on|off}]
+[led {on|off|named \fIindicator\fP}]
.br
[mouse [\fIaccel_mult\fP[/\fIaccel_div\fP] [\fIthreshold\fP]]] [mouse default]
.br
@@ -176,10 +176,14 @@ If no parameter or the 'on' flag is given, all LEDs are
turned on.
If a preceding dash or the flag 'off' is given, all LEDs are turned off.
If a value between 1 and 32 is given, that LED will be turned on or off
depending on the existence of a preceding dash.
-A common LED which can be controlled is the ``Caps Lock'' LED. ``xset
-led 3'' would turn led #3 on. ``xset -led 3'' would turn it off.
+``xset led 3'' would turn led #3 on. ``xset -led 3'' would turn it off.
The particular LED values may refer to different LEDs on different
hardware.
+If the X server supports the XKEYBOARD (XKB) extension, leds may be
+referenced by the XKB indicator name by specifying the `named' keyword
+and the indicator name. For example, to turn on the Scroll Lock LED:
+.IP
+xset led named "Scroll Lock"
.PP
.TP 8
.B mouse
--
1.5.6.5
--
-Alan Coopersmith- alan.coopersmith at sun.com
Sun Microsystems, Inc. - X Window System Engineering
More information about the xorg-devel
mailing list