feat: Initial usage of xkb.
This commit is contained in:
@@ -28,6 +28,12 @@ Build programs:
|
||||
cmake --build ./build
|
||||
```
|
||||
|
||||
Run tests:
|
||||
|
||||
```bash
|
||||
ctest --test-dir build
|
||||
```
|
||||
|
||||
Run program:
|
||||
|
||||
```bash
|
||||
|
||||
@@ -5,6 +5,9 @@ project(wlgol
|
||||
DESCRIPTION "Wayland Game Of Life"
|
||||
LANGUAGES C)
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(XKBCOMMON REQUIRED xkbcommon)
|
||||
|
||||
# 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")
|
||||
|
||||
@@ -37,11 +40,17 @@ add_executable(wlgol wlgol.c ${SOURCES} ${GENHEADERS})
|
||||
target_include_directories(wlgol
|
||||
PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/include
|
||||
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
PUBLIC ${XKBCOMMON_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_link_libraries(wlgol
|
||||
wayland-client
|
||||
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
|
||||
wayland-client
|
||||
wayland-cursor
|
||||
${XKBCOMMON_LIBRARIES}
|
||||
)
|
||||
target_include_directories(test_hashtable
|
||||
PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/include
|
||||
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
PUBLIC ${XKBCOMMON_INCLUDE_DIRS}
|
||||
)
|
||||
target_compile_options(test_hashtable PRIVATE
|
||||
${XKBCOMMON_CFLAGS_OTHER}
|
||||
)
|
||||
|
||||
enable_testing()
|
||||
|
||||
@@ -1,12 +1,24 @@
|
||||
#ifndef TKEYBOARD_H
|
||||
#define TKEYBOARD_H
|
||||
|
||||
#include <stdint.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 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;
|
||||
|
||||
void keyboard_set_handler(struct keyboard_data *kbd, keyboard_key_handler_t handler, void *user_data);
|
||||
|
||||
#endif
|
||||
|
||||
+61
-8
@@ -1,33 +1,82 @@
|
||||
#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>
|
||||
|
||||
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)
|
||||
{
|
||||
printf("keyboard_enter\n");
|
||||
// not implemented
|
||||
}
|
||||
|
||||
static void keyboard_leave(void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface)
|
||||
{
|
||||
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)
|
||||
{
|
||||
printf("keyboard_key: %d %d\n", key, state);
|
||||
// not implemented
|
||||
struct keyboard_data *kbd = data;
|
||||
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)
|
||||
{
|
||||
// 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)
|
||||
@@ -41,6 +90,10 @@ const struct wl_keyboard_listener keyboard_listener = {
|
||||
.leave = keyboard_leave,
|
||||
.key = keyboard_key,
|
||||
.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;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
#include <xdg-shell.h>
|
||||
#include <wayland-client.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <xkbcommon/xkbcommon-keysyms.h>
|
||||
|
||||
#include <tkeyboard.h>
|
||||
#include <tpointer.h>
|
||||
@@ -142,6 +144,18 @@ const struct wl_buffer_listener wl_buffer_listener = {
|
||||
|
||||
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)
|
||||
{
|
||||
if (canvas.frame)
|
||||
@@ -187,6 +201,7 @@ int main(void)
|
||||
wl_surface_commit(canvas.surface);
|
||||
|
||||
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);
|
||||
|
||||
pointer_init_cursor(&pointer_data, compositor, shm);
|
||||
@@ -230,6 +245,19 @@ int main(void)
|
||||
xdg_surface_destroy(xdg_surface);
|
||||
wl_surface_destroy(canvas.surface);
|
||||
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_display_disconnect(display);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user