feat: Initial usage of xkb.

This commit is contained in:
2026-06-13 10:22:08 +02:00
parent 32ff1b18c0
commit ca89ada4b1
5 changed files with 121 additions and 8 deletions
+6
View File
@@ -28,6 +28,12 @@ Build programs:
cmake --build ./build cmake --build ./build
``` ```
Run tests:
```bash
ctest --test-dir build
```
Run program: Run program:
```bash ```bash
+14
View File
@@ -5,6 +5,9 @@ project(wlgol
DESCRIPTION "Wayland Game Of Life" DESCRIPTION "Wayland Game Of Life"
LANGUAGES C) LANGUAGES C)
find_package(PkgConfig REQUIRED)
pkg_check_modules(XKBCOMMON REQUIRED xkbcommon)
# Download xdg-shell.xml # Download xdg-shell.xml
# file(DOWNLOAD "https://cgit.freedesktop.org/wayland/wayland-protocols/plain/stable/xdg-shell/xdg-shell.xml" "${CMAKE_CURRENT_BINARY_DIR}/xdg-shell.xml") # file(DOWNLOAD "https://cgit.freedesktop.org/wayland/wayland-protocols/plain/stable/xdg-shell/xdg-shell.xml" "${CMAKE_CURRENT_BINARY_DIR}/xdg-shell.xml")
@@ -37,11 +40,17 @@ add_executable(wlgol wlgol.c ${SOURCES} ${GENHEADERS})
target_include_directories(wlgol target_include_directories(wlgol
PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/include PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/include
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include
PUBLIC ${XKBCOMMON_INCLUDE_DIRS}
) )
target_link_libraries(wlgol target_link_libraries(wlgol
wayland-client wayland-client
wayland-cursor wayland-cursor
${XKBCOMMON_LIBRARIES}
)
target_compile_options(wlgol PRIVATE
${XKBCOMMON_CFLAGS_OTHER}
) )
@@ -52,10 +61,15 @@ add_executable(test_hashtable tests/test_hashtable.c
target_link_libraries(test_hashtable target_link_libraries(test_hashtable
wayland-client wayland-client
wayland-cursor wayland-cursor
${XKBCOMMON_LIBRARIES}
) )
target_include_directories(test_hashtable target_include_directories(test_hashtable
PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/include PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/include
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include
PUBLIC ${XKBCOMMON_INCLUDE_DIRS}
)
target_compile_options(test_hashtable PRIVATE
${XKBCOMMON_CFLAGS_OTHER}
) )
enable_testing() enable_testing()
+12
View File
@@ -1,12 +1,24 @@
#ifndef TKEYBOARD_H #ifndef TKEYBOARD_H
#define TKEYBOARD_H #define TKEYBOARD_H
#include <stdint.h>
#include <wayland-client.h> #include <wayland-client.h>
#include <xkbcommon/xkbcommon.h>
typedef void (*keyboard_key_handler_t)(uint32_t key, uint32_t state, xkb_keysym_t sym, void *user_data);
struct keyboard_data { struct keyboard_data {
struct wl_keyboard *keyboard; struct wl_keyboard *keyboard;
struct xkb_context *xkb_context;
struct xkb_keymap *xkb_keymap;
struct xkb_state *xkb_state;
keyboard_key_handler_t handler;
void *user_data;
}; };
extern const struct wl_keyboard_listener keyboard_listener; extern const struct wl_keyboard_listener keyboard_listener;
void keyboard_set_handler(struct keyboard_data *kbd, keyboard_key_handler_t handler, void *user_data);
#endif #endif
+61 -8
View File
@@ -1,33 +1,82 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <wayland-client.h>
#include <xkbcommon/xkbcommon.h>
#include <tkeyboard.h> #include <tkeyboard.h>
static void keyboard_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format, int32_t fd, uint32_t size) static void keyboard_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format, int32_t fd, uint32_t size)
{ {
// not implemented struct keyboard_data *kbd = data;
if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)
{
close(fd);
return;
}
char *map_str = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
if (map_str == MAP_FAILED)
{
close(fd);
return;
}
kbd->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
kbd->xkb_keymap = xkb_keymap_new_from_string(
kbd->xkb_context, map_str,
XKB_KEYMAP_FORMAT_TEXT_V1,
XKB_KEYMAP_COMPILE_NO_FLAGS);
kbd->xkb_state = xkb_state_new(kbd->xkb_keymap);
munmap(map_str, size);
close(fd);
} }
static void keyboard_enter(void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys) static void keyboard_enter(void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys)
{ {
printf("keyboard_enter\n"); printf("keyboard_enter\n");
// not implemented
} }
static void keyboard_leave(void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface) static void keyboard_leave(void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface)
{ {
printf("keyboard_leave\n"); printf("keyboard_leave\n");
// not implemented
} }
static void keyboard_key(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) static void keyboard_key(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
{ {
printf("keyboard_key: %d %d\n", key, state); struct keyboard_data *kbd = data;
// not implemented xkb_keysym_t sym = XKB_KEY_NoSymbol;
if (kbd->xkb_state != NULL)
{
// Wayland keycodes are Linux evdev scancodes;
// xkbcommon expects keycodes offset by 8.
sym = xkb_state_key_get_one_sym(kbd->xkb_state, key + 8);
}
printf("keyboard_key: scancode=%d state=%d keysym=%u\n", key, state, sym);
if (kbd->handler != NULL)
{
kbd->handler(key, state, sym, kbd->user_data);
}
} }
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) 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)
{ {
// not implemented struct keyboard_data *kbd = data;
if (kbd->xkb_state != NULL)
{
xkb_state_update_mask(kbd->xkb_state,
mods_depressed, mods_latched, mods_locked,
0, 0, group);
}
} }
static void keyboard_repeat_info(void *data, struct wl_keyboard *keyboard, int32_t rate, int32_t delay) static void keyboard_repeat_info(void *data, struct wl_keyboard *keyboard, int32_t rate, int32_t delay)
@@ -41,6 +90,10 @@ const struct wl_keyboard_listener keyboard_listener = {
.leave = keyboard_leave, .leave = keyboard_leave,
.key = keyboard_key, .key = keyboard_key,
.modifiers = keyboard_modifiers, .modifiers = keyboard_modifiers,
.repeat_info = keyboard_repeat_info .repeat_info = keyboard_repeat_info};
};
void keyboard_set_handler(struct keyboard_data *kbd, keyboard_key_handler_t handler, void *user_data)
{
kbd->handler = handler;
kbd->user_data = user_data;
}
+28
View File
@@ -11,6 +11,8 @@
#include <xdg-shell.h> #include <xdg-shell.h>
#include <wayland-client.h> #include <wayland-client.h>
#include <xkbcommon/xkbcommon.h>
#include <xkbcommon/xkbcommon-keysyms.h>
#include <tkeyboard.h> #include <tkeyboard.h>
#include <tpointer.h> #include <tpointer.h>
@@ -142,6 +144,18 @@ const struct wl_buffer_listener wl_buffer_listener = {
void redraw(); // forward declaration void redraw(); // forward declaration
static void handle_key(uint32_t key, uint32_t state, xkb_keysym_t sym, void *user_data)
{
(void)key;
(void)user_data;
if (state == WL_KEYBOARD_KEY_STATE_PRESSED && sym == XKB_KEY_Escape)
{
printf("Escape pressed, exiting.\n");
running = 0;
}
}
void wl_callack_done(void *data, struct wl_callback *callback, uint32_t time) void wl_callack_done(void *data, struct wl_callback *callback, uint32_t time)
{ {
if (canvas.frame) if (canvas.frame)
@@ -187,6 +201,7 @@ int main(void)
wl_surface_commit(canvas.surface); wl_surface_commit(canvas.surface);
keyboard_data.keyboard = wl_seat_get_keyboard(wl_seat); keyboard_data.keyboard = wl_seat_get_keyboard(wl_seat);
keyboard_set_handler(&keyboard_data, handle_key, NULL);
wl_keyboard_add_listener(keyboard_data.keyboard, &keyboard_listener, &keyboard_data); wl_keyboard_add_listener(keyboard_data.keyboard, &keyboard_listener, &keyboard_data);
pointer_init_cursor(&pointer_data, compositor, shm); pointer_init_cursor(&pointer_data, compositor, shm);
@@ -230,6 +245,19 @@ int main(void)
xdg_surface_destroy(xdg_surface); xdg_surface_destroy(xdg_surface);
wl_surface_destroy(canvas.surface); wl_surface_destroy(canvas.surface);
wl_shm_pool_destroy(pool); wl_shm_pool_destroy(pool);
wl_keyboard_destroy(keyboard_data.keyboard);
if (keyboard_data.xkb_state != NULL)
{
xkb_state_unref(keyboard_data.xkb_state);
}
if (keyboard_data.xkb_keymap != NULL)
{
xkb_keymap_unref(keyboard_data.xkb_keymap);
}
if (keyboard_data.xkb_context != NULL)
{
xkb_context_unref(keyboard_data.xkb_context);
}
wl_registry_destroy(registry); wl_registry_destroy(registry);
wl_display_disconnect(display); wl_display_disconnect(display);
} }