XWayland开发入门系列15:键盘输入

系列索引地址:X11/Wayland开发入门系列教程索引

上一篇:XWayland开发入门系列14:窗口操作

上一篇介绍了鼠标的相关操作,本文介绍键盘的相关操作。

使用的是标准的键盘库xkb,官网为:https://www.xkbcommon.org/

先把上一篇的鼠标操作的部分复制过来。

注册并绑定键盘相关的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
static void seat_capabilities(void *data, struct wl_seat *seat, uint32_t capabilities)
{
if ((capabilities & WL_SEAT_CAPABILITY_POINTER) && !pointer)
{
pointer = wl_seat_get_pointer(seat);
wl_pointer_add_listener(pointer, &pointer_listener, NULL);
}
if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD)
{
keyboard = wl_seat_get_keyboard(seat);
wl_keyboard_add_listener(keyboard, &keyboard_listener, NULL);
}
}

然后添加键盘的回调函数:字符映射、进入、离开、字符、修饰符(Ctrl/Shift之类的)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
static void keyboard_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format, int32_t fd, uint32_t size)
{
char *keymap_string = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
xkb_keymap_unref(keymap);
keymap = xkb_keymap_new_from_string(xkb_context, keymap_string, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
munmap(keymap_string, size);
close(fd);
xkb_state_unref(xkb_state);
xkb_state = xkb_state_new(keymap);
}

static void keyboard_enter(void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys)
{
}

static void keyboard_leave(void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface)
{
}

static void keyboard_key(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
{
if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
{
xkb_keysym_t keysym = xkb_state_key_get_one_sym(xkb_state, key + 8);
uint32_t utf32 = xkb_keysym_to_utf32(keysym);
if (utf32)
{
if (utf32 >= 0x21 && utf32 <= 0x7E)
{
printf("the key %c was pressed\n", (char)utf32);
if (utf32 == 'q')
running = 0;
}
else
{
printf("the key U+%04X was pressed\n", utf32);
}
}
else
{
char name[64];
xkb_keysym_get_name(keysym, name, 64);
printf("the key %s was pressed\n", name);
}
}
}

static void keyboard_modifiers(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group)
{
xkb_state_update_mask(xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group);
}

static struct wl_keyboard_listener keyboard_listener = {
keyboard_keymap,
keyboard_enter,
keyboard_leave,
keyboard_key,
keyboard_modifiers
};

wl_keyboard_listener是一个结构体,每个函数的功能都对应好了,就算不实现也要有个空函数占位。

在创建窗口之前,创建键盘上下文

1
xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);

然后编译执行。效果为:

keyboard

EGL版本只是替换了窗口显示部分,其他的代码一样。

完整代码在Wayland_Frashman下的15.keyboard、15.keyboard_EGL中。

下一篇: