[client] wayland: add keyboard typing handling with xkbcommon

This commit is contained in:
Quantum 2021-08-14 00:20:34 -04:00 committed by Geoffrey McRae
parent 9414449408
commit 7045760490
3 changed files with 91 additions and 1 deletions

View file

@ -5,6 +5,7 @@ find_package(PkgConfig)
pkg_check_modules(DISPLAYSERVER_Wayland REQUIRED IMPORTED_TARGET
wayland-client
wayland-cursor
xkbcommon
)
set(DISPLAYSERVER_Wayland_OPT_PKGCONFIG_LIBRARIES "")

View file

@ -20,11 +20,14 @@
#include "wayland.h"
#include <errno.h>
#include <stdbool.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#include <wayland-client.h>
#include <xkbcommon/xkbcommon.h>
#include "app.h"
#include "common/debug.h"
@ -159,6 +162,50 @@ static const struct zwp_relative_pointer_v1_listener relativePointerListener = {
static void keyboardKeymapHandler(void * data, struct wl_keyboard * keyboard,
uint32_t format, int fd, uint32_t size)
{
if (!wlWm.xkb)
goto done;
if (wlWm.keymap)
{
xkb_keymap_unref(wlWm.keymap);
wlWm.keymap = NULL;
}
if (wlWm.xkbState)
{
xkb_state_unref(wlWm.xkbState);
wlWm.xkbState = NULL;
}
if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)
{
DEBUG_WARN("Unsupported keymap format, keyboard input will not work: %d", format);
goto done;
}
char * map = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
if (map == MAP_FAILED)
{
DEBUG_ERROR("Failed to mmap keymap: %s", strerror(errno));
goto done;
}
wlWm.keymap = xkb_keymap_new_from_string(wlWm.xkb, map,
XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
if (!wlWm.keymap)
DEBUG_WARN("Failed to load keymap, keyboard input will not work");
munmap(map, size);
if (wlWm.keymap)
{
wlWm.xkbState = xkb_state_new(wlWm.keymap);
if (!wlWm.xkbState)
DEBUG_WARN("Failed to create xkb_state");
}
done:
close(fd);
}
@ -198,13 +245,35 @@ static void keyboardKeyHandler(void * data, struct wl_keyboard * keyboard,
app_handleKeyPress(key);
else
app_handleKeyRelease(key);
if (!wlWm.xkbState || !app_isOverlayMode() || state != WL_KEYBOARD_KEY_STATE_PRESSED)
return;
key += 8; // xkb scancode is evdev scancode + 8
int size = xkb_state_key_get_utf8(wlWm.xkbState, key, NULL, 0);
if (size <= 0)
return;
char buffer[size + 1];
xkb_state_key_get_utf8(wlWm.xkbState, key, buffer, size + 1);
app_handleKeyboardTyped(buffer);
}
static void keyboardModifiersHandler(void * data,
struct wl_keyboard * keyboard, uint32_t serial, uint32_t modsDepressed,
uint32_t modsLatched, uint32_t modsLocked, uint32_t group)
{
// Do nothing.
if (!wlWm.xkbState)
return;
xkb_state_update_mask(wlWm.xkbState, modsDepressed, modsLatched, modsLocked, 0, 0, group);
app_handleKeyboardModifiers(
xkb_state_mod_name_is_active(wlWm.xkbState, XKB_MOD_NAME_CTRL, XKB_STATE_MODS_EFFECTIVE) > 0,
xkb_state_mod_name_is_active(wlWm.xkbState, XKB_MOD_NAME_SHIFT, XKB_STATE_MODS_EFFECTIVE) > 0,
xkb_state_mod_name_is_active(wlWm.xkbState, XKB_MOD_NAME_ALT, XKB_STATE_MODS_EFFECTIVE) > 0,
xkb_state_mod_name_is_active(wlWm.xkbState, XKB_MOD_NAME_LOGO, XKB_STATE_MODS_EFFECTIVE) > 0
);
}
static const struct wl_keyboard_listener keyboardListener = {
@ -293,6 +362,10 @@ bool waylandInputInit(void)
DEBUG_WARN("zwp_keyboard_shortcuts_inhibit_manager_v1 not exported by "
"compositor, keyboard will not be grabbed");
wlWm.xkb = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
if (!wlWm.xkb)
DEBUG_WARN("Failed to initialize xkb, keyboard input will not work");
wl_seat_add_listener(wlWm.seat, &seatListener, NULL);
wl_display_roundtrip(wlWm.display);
@ -317,6 +390,15 @@ void waylandInputFree(void)
wl_pointer_destroy(wlWm.pointer);
wl_keyboard_destroy(wlWm.keyboard);
wl_seat_destroy(wlWm.seat);
if (wlWm.xkbState)
xkb_state_unref(wlWm.xkbState);
if (wlWm.keymap)
xkb_keymap_unref(wlWm.keymap);
if (wlWm.xkb)
xkb_context_unref(wlWm.xkb);
}
void waylandGrabPointer(void)

View file

@ -88,6 +88,10 @@ enum EGLSwapWithDamageState {
SWAP_WITH_DAMAGE_EXT,
};
struct xkb_context;
struct xkb_keymap;
struct xkb_state;
struct WaylandDSState
{
bool pointerGrabbed;
@ -155,6 +159,9 @@ struct WaylandDSState
struct zwp_keyboard_shortcuts_inhibit_manager_v1 * keyboardInhibitManager;
struct zwp_keyboard_shortcuts_inhibitor_v1 * keyboardInhibitor;
uint32_t keyboardEnterSerial;
struct xkb_context * xkb;
struct xkb_state * xkbState;
struct xkb_keymap * keymap;
struct wl_pointer * pointer;
struct zwp_relative_pointer_manager_v1 * relativePointerManager;