繁体   English   中英

如何在 Linux 中获取键盘状态?

[英]How can I get the keyboard state in Linux?

我想检查程序启动时用户是否按下了Shift键。 (也就是说,在程序启动前按下Shift键)这是一个简单的控制台程序,与 X 无关。

这可能类似于 Win32 GetKeyboardState()函数。

我想知道我是否可以执行此操作以及如何执行此操作,但不知道直接访问终端的优缺点。

我认为会有办法做到这一点。 问题是您必须直接从键盘设备读取。 您不会从终端获得输入。 我有同样的问题。 我有一个运行(在后台)的程序,我想知道用户是否按住了 shift 键。

我相信这是可能的,一个开始的地方可能是/dev/input/by-path/*-kbd

这个文件在每次按下一个键时都会提供输入,或者如果它被按住则重复输入,所以它可能值得一看。 (试试 cat /dev/input/by-path/*-kbd

如果你确实弄清楚了这一点,我很想听听你是如何做到的。

编辑:我找到了解决方案

我已经想出了如何做到这一点。 我的程序如下:

#include <stdlib.h>
#include <stdio.h>

#include <linux/input.h>

void usage ( int argc, char *argv[] )
{
    printf("Usage:\n\t%s key\n\nvalid keys are:\n\tlshift\t- Left Shift key\n" , argv[0]);

    exit(EXIT_FAILURE);
}

int main ( int argc, char *argv[], char *env[] )
{
    if ( argc != 2 )    usage(argc, argv);

    int key;

    if ( strcmp(argv[1], "lshift") == 0 )       key = KEY_LEFTSHIFT;
    else if ( strcmp(argv[1], "rshift") == 0 )  key = KEY_RIGHTSHIFT;
    else if ( strcmp(argv[1], "lalt") == 0 )    key = KEY_LEFTALT;
    else if ( strcmp(argv[1], "ralt") == 0 )    key = KEY_RIGHTALT;
    else if ( strcmp(argv[1], "lctrl") == 0 )   key = KEY_LEFTCTRL;
    else if ( strcmp(argv[1], "rctrl") == 0 )   key = KEY_RIGHTCTRL;


    FILE *kbd = fopen("/dev/input/by-path/platform-i8042-serio-0-event-kbd", "r");

    char key_map[KEY_MAX/8 + 1];    //  Create a byte array the size of the number of keys

    memset(key_map, 0, sizeof(key_map));    //  Initate the array to zero's
    ioctl(fileno(kbd), EVIOCGKEY(sizeof(key_map)), key_map);    //  Fill the keymap with the current keyboard state

    int keyb = key_map[key/8];  //  The key we want (and the seven others arround it)
    int mask = 1 << (key % 8);  //  Put a one in the same column as out key state will be in;

    return !(keyb & mask);  //  Returns true if pressed otherwise false

}

缺少信息消息(我太懒了)。 但本质上,第一个参数与键列表进行比较,并使用适当的键标识符。 如果按键被按下,则返回 true,否则返回 false。

请注意

您将需要更改键盘设备的名称。 我不知道找到默认键盘设备的方法。 (如果你知道我很想听听;))

这很好用:如果我按住 shift 键,我会用它来启动 Xorg 的自动启动。

AFAIK 如果没有没有根级别权限的 Xlib(又名 X),这是无法完成的。 使用 XQueryKeymap() 可以满足您的需求。 但是您指出 X 不能使用。 无论如何,还需要打开显示连接。

#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <stdbool.h>
#include <stdio.h>

int main()
{
    Display* dpy = XOpenDisplay(NULL);
    char keys_return[32];
    XQueryKeymap( dpy, keys_return );
    KeyCode kc2 = XKeysymToKeycode( dpy, XK_Shift_L );
    bool bShiftPressed = !!( keys_return[ kc2>>3 ] & ( 1<<(kc2&7) ) );
    printf("Shift is %spressed\n", bShiftPressed ? "" : "not ");
    XCloseDisplay(dpy);
}

我通过 gtk/gdk 找到了一个非常简单的方法。

int main ( int argc, char *argv[], char *env[] )
{
    gtk_init(&argc, &argv);

    GdkModifierType button_state;
    gdk_window_get_pointer(NULL, NULL, NULL, &button_state);
    if(button_state & GDK_CONTROL_MASK) {
        printf("ctrl key is pressed");
    }
}

你不能。

Shift键不被视为字符键,因此即使您直接访问终端,您也无法检测到此键。

也许你不应该这样做。 想象一下,例如,您正在使用美式键盘,在没有修饰符的情况下可以在顶行访问数字,并且还检查Shift键。 使用其他键盘布局的人可能必须使用Shift修饰符来访问数字。 如果您的程序对这个Shift键有反应,那么您的程序基本上无法使用。 同样的事情适用于其他修饰键:您可能只有在按下普通字符键后才能检测到其中的一些。 或者更糟的是,他们可能需要使用Shift键才能使用“输入”来运行您的程序。

另外,您要监控哪个Shift键? 本地机器上的那个,还是用户所在的那个? 请记住,SSH 存在并且通常用于远程访问伪终端。

如果您是 root 并且想要监视本地机器上的Shift键,您可以读取 evdev 设备以获取有关Shift键的事件。 但这只是由于自动重复按键才有可能,因此您不会检测到在运行程序之前按下的Shift键,而是仅在几秒钟之前按下的。

当然你不能在远程机器上这样做,那将是一个安全漏洞。

无论如何,你为什么要这样做? 在您的情况下,X 应用程序不是正确的做法吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM