从 X 会话中更改键盘 LED 的状态,无需 root 访问

T. *_*ron 10 linux xorg io-redirection x11 console

我正在尝试强制开启大写锁定。xset对我不起作用,所以我试图使用setleds.

在图形控制台中,此命令返回:

> LANG=C setleds -L +caps
KDGKBLED: Inappropriate ioctl for device
Error reading current flags setting. Maybe you are not on the console?
Run Code Online (Sandbox Code Playgroud)

在虚拟终端中,它起作用,但是效果是该虚拟终端本地的。据我了解,运行

> setleds -L +caps < /dev/tty1
Run Code Online (Sandbox Code Playgroud)

从虚拟终端(我的 X 服务器位于 tty1 上)应该可以工作。但是,这需要 root 访问权限。

有没有办法将命令发送到 X 服务器下的控制台,无论是来自所述 xserver 还是来自另一个 VT,而无需 root?

编辑:根据 Mark Plotnik 的建议,并根据此处找到的代码,我编写并编译了以下内容:

#include <X11/Xlib.h>
#include <X11/XKBlib.h>

#define SCROLLLOCK 1
#define CAPSLOCK 2
#define NUMLOCK 16

void setLeds(int leds) {
   Display *dpy = XOpenDisplay(0);
   XKeyboardControl values;
   values.led_mode = leds & SCROLLLOCK ? LedModeOn : LedModeOff;
   values.led = 3;
   XChangeKeyboardControl(dpy, KBLedMode, &values);
   XkbLockModifiers(dpy, XkbUseCoreKbd, CAPSLOCK | NUMLOCK,
                    leds & (CAPSLOCK | NUMLOCK) );
   XFlush(dpy);
   XCloseDisplay(dpy);
}

int main() {
   setLeds(CAPSLOCK);
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

从吉尔斯所写的内容来看xset,我没想到它会起作用,但它确实......在某种意义上:它设置了 LED,但它也设置了大写锁定状态。我没有完全理解上面的所有代码,所以我可能犯了一个愚蠢的错误。显然,该行XChangeKeyboardControl...不会改变程序的行为,XkbLockModifiers而是设置 LED 和大写锁定状态的原因。

Gil*_*il' 7

原则上,您应该能够使用 venerablexset命令来做到这一点。

xset led named 'Caps Lock'
Run Code Online (Sandbox Code Playgroud)

xset led 4设置 LED 编号 4,如果您的系统无法按名称识别 LED。

但是,这似乎并不可靠。在我的机器上,我只能这样设置 Scroll Lock,而且我不是唯一一个。这似乎是 XKB 配置的问题

以下用户级解决方法应该有效(在大多数情况下):

  1. 提取您当前的 xkb 配置:

    xkbcomp $DISPLAY myconf.xkb
    
    Run Code Online (Sandbox Code Playgroud)
  2. 编辑文件myconf.xkb,在相关块中替换!allowExplicitallowExplicit

    indicator "Caps Lock" {
        allowExplicit;
        whichModState= locked;
        modifiers= Lock;
    };
    indicator "Num Lock" {
        allowExplicit;
        whichModState= locked;
        modifiers= NumLock;
    };
    
    Run Code Online (Sandbox Code Playgroud)
  3. 加载新文件

    xkbcomp myconf.xkb $DISPLAY
    
    Run Code Online (Sandbox Code Playgroud)

现在打开和关闭 LEDxset应该可以工作。根据错误报告,当 LED 应该打开时,您将无法关闭它们(例如,如果启用了 CapsLock)。