[英]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.