[英]How does XCB's event handling detect the ESC key in C?
我一直在學習 XCB 教程,但我一直堅持這個教程。 在本例中,當您按ESC
鍵時程序退出。 但是在示例代碼中,我無法弄清楚“case 9”如何捕獲ESC
鍵。 我已經搜索並查看了xcb.h
和xproto.h
以及 ASCII 表。
我以為我明白了,直到我到達“案例 9”。 這是我完全迷失的地方。 所以基本上,他們從哪里得到 9? 這與ESC
有何對應?
這是我正在研究的示例代碼:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <xcb/xcb.h>
#define WIDTH 300
#define HEIGHT 100
static xcb_gc_t gc_font_get (xcb_connection_t *c,
xcb_screen_t *screen,
xcb_window_t window,
const char *font_name);
static void text_draw (xcb_connection_t *c,
xcb_screen_t *screen,
xcb_window_t window,
int16_t x1,
int16_t y1,
const char *label)
{
xcb_void_cookie_t cookie_gc;
xcb_void_cookie_t cookie_text;
xcb_generic_error_t *error;
xcb_gcontext_t gc;
uint8_t length;
length = strlen (label);
gc = gc_font_get(c, screen, window, "7x13");
cookie_text = xcb_image_text_8_checked (c, length, window, gc,
x1,
y1, label);
error = xcb_request_check (c, cookie_text);
if (error) {
fprintf (stderr, "ERROR: can't paste text : %d\n", error->error_code);
xcb_disconnect (c);
exit (-1);
}
cookie_gc = xcb_free_gc (c, gc);
error = xcb_request_check (c, cookie_gc);
if (error) {
fprintf (stderr, "ERROR: can't free gc : %d\n", error->error_code);
xcb_disconnect (c);
exit (-1);
}
}
static xcb_gc_t gc_font_get (xcb_connection_t *c,
xcb_screen_t *screen,
xcb_window_t window,
const char *font_name)
{
uint32_t value_list[3];
xcb_void_cookie_t cookie_font;
xcb_void_cookie_t cookie_gc;
xcb_generic_error_t *error;
xcb_font_t font;
xcb_gcontext_t gc;
uint32_t mask;
font = xcb_generate_id (c);
cookie_font = xcb_open_font_checked (c, font,
strlen (font_name),
font_name);
error = xcb_request_check (c, cookie_font);
if (error) {
fprintf (stderr, "ERROR: can't open font : %d\n", error->error_code);
xcb_disconnect (c);
return -1;
}
gc = xcb_generate_id (c);
mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT;
value_list[0] = screen->black_pixel;
value_list[1] = screen->white_pixel;
value_list[2] = font;
cookie_gc = xcb_create_gc_checked (c, gc, window, mask, value_list);
error = xcb_request_check (c, cookie_gc);
if (error) {
fprintf (stderr, "ERROR: can't create gc : %d\n", error->error_code);
xcb_disconnect (c);
exit (-1);
}
cookie_font = xcb_close_font_checked (c, font);
error = xcb_request_check (c, cookie_font);
if (error) {
fprintf (stderr, "ERROR: can't close font : %d\n", error->error_code);
xcb_disconnect (c);
exit (-1);
}
return gc;
}
int main ()
{
xcb_screen_iterator_t screen_iter;
xcb_connection_t *c;
const xcb_setup_t *setup;
xcb_screen_t *screen;
xcb_generic_event_t *e;
xcb_generic_error_t *error;
xcb_void_cookie_t cookie_window;
xcb_void_cookie_t cookie_map;
xcb_window_t window;
uint32_t mask;
uint32_t values[2];
int screen_number;
/* getting the connection */
c = xcb_connect (NULL, &screen_number);
if (!c) {
fprintf (stderr, "ERROR: can't connect to an X server\n");
return -1;
}
/* getting the current screen */
setup = xcb_get_setup (c);
screen = NULL;
screen_iter = xcb_setup_roots_iterator (setup);
for (; screen_iter.rem != 0; --screen_number, xcb_screen_next (&screen_iter))
if (screen_number == 0)
{
screen = screen_iter.data;
break;
}
if (!screen) {
fprintf (stderr, "ERROR: can't get the current screen\n");
xcb_disconnect (c);
return -1;
}
/* creating the window */
window = xcb_generate_id (c);
mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
values[0] = screen->white_pixel;
values[1] =
XCB_EVENT_MASK_KEY_RELEASE |
XCB_EVENT_MASK_BUTTON_PRESS |
XCB_EVENT_MASK_EXPOSURE |
XCB_EVENT_MASK_POINTER_MOTION;
cookie_window = xcb_create_window_checked (c,
screen->root_depth,
window, screen->root,
20, 200, WIDTH, HEIGHT,
0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
screen->root_visual,
mask, values);
cookie_map = xcb_map_window_checked (c, window);
/* error managing */
error = xcb_request_check (c, cookie_window);
if (error) {
fprintf (stderr, "ERROR: can't create window : %d\n", error->error_code);
xcb_disconnect (c);
return -1;
}
error = xcb_request_check (c, cookie_map);
if (error) {
fprintf (stderr, "ERROR: can't map window : %d\n", error->error_code);
xcb_disconnect (c);
return -1;
}
xcb_flush(c);
while (1) {
e = xcb_poll_for_event(c);
if (e) {
switch (e->response_type & ~0x80) {
case XCB_EXPOSE: {
char *text;
text = "Press ESC key to exit...";
text_draw (c, screen, window, 10, HEIGHT - 10, text);
break;
}
case XCB_KEY_RELEASE: {
xcb_key_release_event_t *ev;
ev = (xcb_key_release_event_t *)e;
switch (ev->detail) {
/* ESC */
case 9:
free (e);
xcb_disconnect (c);
return 0;
}
}
}
free (e);
}
}
return 0;
}
謝謝
低級 X KeyCode
位於 8..255 范圍內,代表鍵盤的物理布局。 大概在實踐中值 9(“1”相對於范圍的開始,即左上角)是Esc鍵。
話雖如此,像這樣對特定於設備的知識進行硬編碼而不是查找哪個鍵碼與 Esc KeySym
相關聯,這似乎是一個非常糟糕的主意。
此鏈接似乎提供了一些有用的信息:
我以為我明白了,直到我到達“案例 9”。 這是我完全迷失的地方。 所以基本上,他們從哪里得到 9? 這與 ESC 有何對應關系?
如果您打開終端並運行:
xev | grep keycode
然后你在彈出的 xev 窗口上按 Esc 鍵,你會看到:
state 0x0, keycode 9 (keysym 0xff1b, Escape), same_screen YES,
state 0x0, keycode 9 (keysym 0xff1b, Escape), same_screen YES,
你可以做一些瘋狂的事情,比如使用 xmodmap 重新映射你的轉義鍵,但它仍然是 keycode 9
,即使你將它映射到其他東西......使用 xmodmap 我將 keycode 9 重置為 F1,但 xev 仍然可以看到我'我真的在使用 Escape 鍵(鍵碼 9)
state 0x0, keycode 9 (keysym 0xffbe, F1), same_screen YES,
state 0x0, keycode 9 (keysym 0xffbe, F1), same_screen YES,
如果你運行:
showkey --ascii
# press the Escape key
^[ 27 0033 0x1b
您會看到 Escape 映射到 ASCII 表上的27
。 同時獲取密鑰的“掃描碼”:
sudo showkey --scancodes
# press the Escape key
^[ 0x01 0x81
由於您在本教程中使用的是 xcb 並且只需要考慮 Xcb/X11,因此 Code 9 將始終是硬件 Escape 鍵。
您可以使用setkeycodes
( kbd
包)設置掃描碼以映射到 Linux 中的其他鍵碼,但這些代碼不會被 X 獲取。
根據您操作的層(USB 硬件/內核/X11),您需要為適當的密鑰選擇適當的標識符。
我相信@s0s 所指的教程可在線獲取:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.