Keyboard
如何在控制台應用程序中獲得對修飾鍵的使用者級訪問權限?
我需要訪問我正在編寫的控制台應用程序(個性化編輯器)的修飾鍵狀態。
是否有任何包/庫/提供此訪問權限的任何東西?
我從某個地方拼湊了以下內容,但它只有在你是 root 時才有效,而且我真的不想在 root 級別搞砸。
#include <iostream> #include <string> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <termios.h> #include <fcntl.h> #include <linux/input.h> #include <unistd.h> #include <errno.h> int kbhit(void) { struct termios oldt, newt; int ch; int oldf; tcgetattr(STDIN_FILENO, &oldt); newt = oldt; newt.c_lflag &= ~0000172 ; //~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &newt); oldf = fcntl(STDIN_FILENO, F_GETFL, 0); fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK); ch = getchar(); tcsetattr(STDIN_FILENO, TCSANOW, &oldt); fcntl(STDIN_FILENO, F_SETFL, oldf); return ch; } enum MODKEYS { SHIFT_L = 1, SHIFT_R = 2, CTRL_L = 4, CTRL_R = 8, ALT_L = 16, ALT_R = 32, }; int chkmodifiers() { int mods=0,keyb,mask; char key_map[KEY_MAX/8 + 1]; // Create a byte array the size of the number of keys //event1 - got by inspecting /dev/input/... FILE *kbd = fopen("/dev/input/event1", "r"); if (kbd == NULL) { printf("(chkmodifiers) ERROR: %s\n", strerror(errno)); //permission - got to be root! return 0; } memset(key_map, 0, sizeof(key_map)); ioctl(fileno(kbd), EVIOCGKEY(sizeof(key_map)), key_map); // Fill the keymap with the current keyboard state keyb = key_map[KEY_LEFTSHIFT/8]; mask = 1 << (KEY_LEFTSHIFT % 8); if (keyb & mask) mods += SHIFT_L; keyb = key_map[KEY_RIGHTSHIFT/8]; mask = 1 << (KEY_RIGHTSHIFT % 8); if (keyb & mask) mods += SHIFT_R; keyb = key_map[KEY_LEFTCTRL/8]; mask = 1 << (KEY_LEFTCTRL % 8); if (keyb & mask) mods += CTRL_L; keyb = key_map[KEY_RIGHTCTRL/8]; mask = 1 << (KEY_RIGHTCTRL % 8); if (keyb & mask) mods += CTRL_R; keyb = key_map[KEY_LEFTALT/8]; mask = 1 << (KEY_LEFTALT % 8); if (keyb & mask) mods += ALT_L; keyb = key_map[KEY_RIGHTALT/8]; mask = 1 << (KEY_RIGHTALT % 8); if (keyb & mask) mods += ALT_R; return mods; } int main() { puts("Press a key!"); char ch=0; int n=0,m; while (ch != 'q') { n = kbhit(); if (n != -1) { m = chkmodifiers(); ch = (char)n; printf("You pressed '%c' [%d]\n", ch, n); if ((m & SHIFT_L) == SHIFT_L) printf(" .. and ls\n"); if ((m & SHIFT_R) == SHIFT_R) printf(" .. and rs\n"); if ((m & CTRL_L) == CTRL_L) printf(" .. and lc\n"); if ((m & CTRL_R) == CTRL_R) printf(" .. and rc\n"); if ((m & ALT_L) == ALT_L) printf(" .. and la\n"); if ((m & ALT_R) == ALT_R) printf(" .. and ra\n"); } } return 0; }
也許看看libtermkey,一個終端鍵輸入庫,可辨識特殊鍵(如箭頭和功能鍵),包括“修改”鍵,如
Ctrl-Left
.另一種選擇可能是增強charm的功能,這是一個最小的 ncurses 副本。
在終端中,一直很難獲得這種資訊。你只能得到一個“keycode”,當然,它意味著不同的東西,這取決於你使用的作業系統、鍵盤和終端的組合。
您可以通過呼叫xmodmap在您的作業系統上找到這些鍵碼的完整列表。
$ xmodmap -pke keycode 9 = Escape NoSymbol Escape keycode 10 = ampersand 1 ampersand 1 dead_caron dead_ogonek dead_caron dead_ogonek keycode 11 = eacute 2 eacute 2 asciitilde Eacute asciitilde Eacute [...] keycode 244 = XF86Battery NoSymbol XF86Battery keycode 245 = XF86Bluetooth NoSymbol XF86Bluetooth keycode 246 = XF86WLAN NoSymbol XF86WLAN keycode 247 =
以及所有修飾符值的列表:
$ xmodmap xmodmap: up to 4 keys per modifier, (keycodes in parentheses): shift Shift_L (0x32), Shift_R (0x3e) lock Caps_Lock (0x42) control Control_L (0x25), Control_R (0x69) mod1 Alt_L (0x40), Meta_L (0xcd) mod2 Num_Lock (0x4d) mod3 mod4 Super_L (0x85), Super_R (0x86), Super_L (0xce), Hyper_L (0xcf) mod5 ISO_Level3_Shift (0x5c), Mode_switch (0xcb)
terminfo數據庫中有一些原始資訊,或者在ncurses API 中更完善,以幫助系統開發人員克服這種混亂。
如果您可以重用現有的原始碼,例如nano 的原始碼,它應該可以為您節省大量時間。看看“get_escape_seq_kbinput”函式,看看我的意思。
如果您只需要現代 linux 支持,那麼呼叫keyname可能就足夠了。