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 <[email protected]>
---

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-           [email protected]
         Sun Microsystems, Inc. - X Window System Engineering

_______________________________________________
xorg-devel mailing list
[email protected]
http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to