簡體   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