[英]How does XCB's event handling detect the ESC key in C?
I've been studying an XCB tutorial, but I'm stuck on this one.我一直在学习 XCB 教程,但我一直坚持这个教程。 In this example, the program quits when you press the ESC
key.在本例中,当您按ESC
键时程序退出。 But in the example code, I can't figure out how "case 9" catches the ESC
key.但是在示例代码中,我无法弄清楚“case 9”如何捕获ESC
键。 I've searched and looked all through xcb.h
and xproto.h
, and the ASCII table.我已经搜索并查看了xcb.h
和xproto.h
以及 ASCII 表。
I thought I understood it, until I got to "case 9".我以为我明白了,直到我到达“案例 9”。 This was where I got totally lost.这是我完全迷失的地方。 So basically, where do they get 9 from?所以基本上,他们从哪里得到 9? And how does that correspond to ESC
?这与ESC
有何对应?
Here's the example code I was studying:这是我正在研究的示例代码:
#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;
}
Thanks谢谢
Low-level X KeyCode
s lie in the range 8..255 and represent the physical layout of the keyboard.低级 X KeyCode
位于 8..255 范围内,代表键盘的物理布局。 Presumably in practice the value 9 ("1" relative to the start of the range, ie upper-left) is the Esc key.大概在实践中值 9(“1”相对于范围的开始,即左上角)是Esc键。
With that said, it seems like a really bad idea to hard-code device-specific knowledge like this rather than looking up which keycode is associated with the Esc KeySym
.话虽如此,像这样对特定于设备的知识进行硬编码而不是查找哪个键码与 Esc KeySym
相关联,这似乎是一个非常糟糕的主意。
This link seems to provide some useful information:此链接似乎提供了一些有用的信息:
https://tronche.com/gui/x/xlib/input/keyboard-encoding.html https://tronche.com/gui/x/xlib/input/keyboard-encoding.html
I thought I understood it, until I got to "case 9".我以为我明白了,直到我到达“案例 9”。 This was where I got totally lost.这是我完全迷失的地方。 So basically, where do they get 9 from?所以基本上,他们从哪里得到 9? And how does that correspond to ESC?这与 ESC 有何对应关系?
If you open a terminal and run:如果您打开终端并运行:
xev | grep keycode
Then you press the Esc key on the xev window that pops up, you will see:然后你在弹出的 xev 窗口上按 Esc 键,你会看到:
state 0x0, keycode 9 (keysym 0xff1b, Escape), same_screen YES,
state 0x0, keycode 9 (keysym 0xff1b, Escape), same_screen YES,
You could do crazy stuff like use xmodmap to remap your escape key, but it would still be keycode 9
, even though you mapped it to something else... Using xmodmap I reset keycode 9 to be F1, but xev can still see that I'm really using the Escape key (keycode 9)你可以做一些疯狂的事情,比如使用 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,
If you run:如果你运行:
showkey --ascii
# press the Escape key
^[ 27 0033 0x1b
You see that Escape maps to 27
on the ASCII table.您会看到 Escape 映射到 ASCII 表上的27
。 Meanwhile to grab the key's "Scancode":同时获取密钥的“扫描码”:
sudo showkey --scancodes
# press the Escape key
^[ 0x01 0x81
Since you're working with xcb in this tutorial and only Xcb/X11 must be considered, Code 9 will always be the hardware Escape key.由于您在本教程中使用的是 xcb 并且只需要考虑 Xcb/X11,因此 Code 9 将始终是硬件 Escape 键。
You can use the setkeycodes
( kbd
package) to set scancodes to map to other keycodes in Linux, but these codes WILL NOT be picked up by X.您可以使用setkeycodes
( kbd
包)设置扫描码以映射到 Linux 中的其他键码,但这些代码不会被 X 获取。
Depending on the layer (USB hardware/kernel/X11) that you're operating at, you'll need to choose the appropriate identifier for the appropriate key.根据您操作的层(USB 硬件/内核/X11),您需要为适当的密钥选择适当的标识符。
I believe the tutorial that @s0s was referring to is available online at:我相信@s0s 所指的教程可在线获取:
https://www.x.org/releases/X11R7.5/doc/libxcb/tutorial/ https://www.x.org/releases/X11R7.5/doc/libxcb/tutorial/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.