【问题标题】:How can I get the keyboard state in Linux?如何在 Linux 中获取键盘状态?
【发布时间】:2011-04-08 16:06:05
【问题描述】:

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

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

我想知道我是否可以这样做以及如何做到这一点,但不知道直接访问终端的任何利弊。

【问题讨论】:

  • 您使用哪种语言?

标签: c linux console keyboard


【解决方案1】:

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

我相信这是可能的,一个起点可能是/dev/input/by-path/*-kbd。

这个文件确实会在每次按下一个键时给出输入,或者如果它被按住则重复输入,所以它可能值得一看。 (试试猫/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 的自动启动。

【讨论】:

  • 这个程序需要root权限,否则它会在我的机器上出现段错误。这是因为键盘设备文件的权限(顺便说一句,这里是相同的platform-i8042-serio-0-event-kbd,所以也许至少每台 PC 都有它?)。通过运行sudo xxd /dev/input/by-path/platform-i8042-serio-0-event-kbd,我看到每次键盘状态发生变化时,文件都会“增长”另一个sizeof(keymap)。
  • @Youarefunny,这太棒了。你应该用它做一个小包!
【解决方案2】:

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);
}

【讨论】:

    【解决方案3】:

    我通过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");
        }
    }
    

    【讨论】:

      【解决方案4】:

      你不能。

      Shift键不被认为是字符键,所以即使你直接访问终端,也无法检测到这个键。

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

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

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

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

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

      【讨论】:

      • 这是一个通用的命令调用器,当按住SHIFT键时,调用器将进入配置模式。虽然还有其他方法可以做到这一点,例如命令行--conf 选项,好吧,知道这是不可能的就足够了,我会尝试其他方式。
      • 以“你不能”开始回答通常是不好的形式,因为这通常表明回答者完全否定了提问者的问题。此外,假设您有权允许任何人做某事,这确实是不公平的。更糟糕的是,如果其他人回来并坦率地展示你如何“可以”,它会让你看起来真的......很糟糕。无论如何,我以前写过这样的 cmets。这并不是一个真正的新概念。而且,我没有写答案,因为我不知道,有点谦虚可以走很长一段路;)
      • [...]也许你不应该这样做。 [...] 如果您的程序对这个 shift press 做出反应,那么您的程序基本上是不可用的。[...] 除了这仅对 GUI 处理有效。对于其他所有内容,“如果您的程序对这个移位按下没有反应,那么它基本上是不可用的。” IE。相机控制、图像编辑应用程序等,更不用说 ctrl、alt 或 esc 等处理键了。简而言之:没有人根据您有限的经验询问您的意见,例如“您为什么要这样做?”这样的句子很明显。和“你不能”。
      猜你喜欢
      • 2021-02-22
      • 1970-01-01
      • 2011-08-11
      • 1970-01-01
      • 2016-05-10
      • 2011-11-02
      • 2017-12-27
      • 2014-08-19
      相关资源
      最近更新 更多