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

Xiè*_*léi 12 c linux keyboard console

我想在程序启动时检查用户是否按下了SHIFT键.(这意味着,在程序启动之前按下SHIFT键)这是一个简单的控制台程序,与X无关.

这可能类似于Win32 GetKeyboardState()功能.

我想知道我是否可以这样做,以及如何直接访问终端,但没有任何利弊.

You*_*nny 30

我想有办法做到这一点.问题是您必须直接从键盘设备读取.你不会从终端获得输入.我也有同样的问题.我有一个程序运行(在后台),我想知道用户是否按住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

}
Run Code Online (Sandbox Code Playgroud)

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

请注意

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

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

  • 此程序需要root权限,否则会在我的计算机上出现段错误.这是因为键盘设备文件的权限(顺便说一下,这里的平台i8042-serio-0-event-kbd`是相同的,所以至少每台PC都有它?).通过运行`须藤XXD的/ dev /输入/旁路系统/平台的i8042,里奥 - 0 - 事件kbd`我看到文件"成长"的另一个'的sizeof(键盘映射)`每次键盘状态的变化. (2认同)

小智 6

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);
}
Run Code Online (Sandbox Code Playgroud)


Lyn*_*Lyn 5

我通过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");
    }
}
Run Code Online (Sandbox Code Playgroud)


Bat*_*hyX -12

你不能。

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

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

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

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

当然,您不能在远程计算机上执行此操作,这将是一个安全缺陷。

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

  • 以“你不能”开始回答通常是不好的形式,因为这通常表明回答者完全否定了提问者的问题。此外,假设您有权授予任何人做某事的权利,这确实不公平。更糟糕的是,如果其他人回来并直率地展示你如何“可以”,这会让你看起来真的……很糟糕。无论如何,我以前写过类似的评论。这并不是一个新概念。而且,我没有写答案,因为我不知道,一点谦虚可以有很长的路要走;) (10认同)
  • [...]也许你不应该这样做。[...] 如果您的程序对按 Shift 键有反应,那么您的程序基本上无法使用。[...] 除了这仅对 GUI 处理有效。对于其他一切,“如果你的程序对这个 Shift 键没有反应,那么它基本上就无法使用。” IE。相机控制、图像编辑应用程序等,更不用说处理 ctrl、alt 或 esc 等键。简而言之:没有人根据你有限的经验征求你的意见,例如“你为什么要这样做?”之类的句子。和“你不能”。 (2认同)