mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-25 14:57:20 +00:00
[client] wayland: add keyboard typing handling with xkbcommon
This commit is contained in:
parent
9414449408
commit
7045760490
@ -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 "")
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user