diff --git a/examples/agl-simple-shm.cc b/examples/agl-simple-shm.cc index 304da1c..d1a9b5b 100644 --- a/examples/agl-simple-shm.cc +++ b/examples/agl-simple-shm.cc @@ -213,15 +213,15 @@ class App : public PointerObserver, public KeyboardObserver, public SeatObserver spdlog::info("Keymap: format: {}, fd: {}, size: {}", format, fd, size); } - void notify_keyboard_key(Keyboard * /* keyboard */, - wl_keyboard * /* wl_keyboard */, - uint32_t serial, - uint32_t time, - uint32_t xkb_scancode, - bool key_repeats, - uint32_t state, - int xdg_key_symbol_count, - const xkb_keysym_t *xdg_key_symbols) override { + void notify_keyboard_xkb_v1_key(Keyboard * /* keyboard */, + wl_keyboard * /* wl_keyboard */, + uint32_t serial, + uint32_t time, + uint32_t xkb_scancode, + bool key_repeats, + uint32_t state, + int xdg_key_symbol_count, + const xkb_keysym_t *xdg_key_symbols) override { spdlog::info( "Key: serial: {}, time: {}, xkb_scancode: 0x{:X}, key_repeats: {}, state: {}, xdg_keysym_count: {}, syms_out[0]: 0x{:X}", serial, time, xkb_scancode, key_repeats, state == KeyState::KEY_STATE_PRESS ? "press" : "release", diff --git a/examples/gl-shadertoy/shadertoy.cc b/examples/gl-shadertoy/shadertoy.cc index 9cb332e..df76035 100644 --- a/examples/gl-shadertoy/shadertoy.cc +++ b/examples/gl-shadertoy/shadertoy.cc @@ -299,15 +299,15 @@ class KeyboardHandler : public SeatObserver, public KeyboardObserver { spdlog::info("Keymap: format: {}, fd: {}, size: {}", format, fd, size); } - void notify_keyboard_key(Keyboard * /* keyboard */, - wl_keyboard * /* wl_keyboard */, - uint32_t serial, - uint32_t time, - uint32_t xkb_scancode, - bool key_repeats, - uint32_t state, - int xdg_key_symbol_count, - const xkb_keysym_t *xdg_key_symbols) override { + void notify_keyboard_xkb_v1_key(Keyboard * /* keyboard */, + wl_keyboard * /* wl_keyboard */, + uint32_t serial, + uint32_t time, + uint32_t xkb_scancode, + bool key_repeats, + uint32_t state, + int xdg_key_symbol_count, + const xkb_keysym_t *xdg_key_symbols) override { spdlog::info( "Key: serial: {}, time: {}, xkb_scancode: 0x{:X}, key_repeats: {}, state: {}, xdg_keysym_count: {}, syms_out[0]: 0x{:X}", serial, time, xkb_scancode, key_repeats, state == KeyState::KEY_STATE_PRESS ? "press" : "release", diff --git a/examples/simple-egl.cc b/examples/simple-egl.cc index 7455ca3..a13e4b7 100644 --- a/examples/simple-egl.cc +++ b/examples/simple-egl.cc @@ -423,15 +423,15 @@ class KeyboardHandler : public SeatObserver, public KeyboardObserver { spdlog::info("Keymap: format: {}, fd: {}, size: {}", format, fd, size); } - void notify_keyboard_key(Keyboard * /* keyboard */, - wl_keyboard * /* wl_keyboard */, - uint32_t serial, - uint32_t time, - uint32_t xkb_scancode, - bool key_repeats, - uint32_t state, - int xdg_key_symbol_count, - const xkb_keysym_t *xdg_key_symbols) override { + void notify_keyboard_xkb_v1_key(Keyboard * /* keyboard */, + wl_keyboard * /* wl_keyboard */, + uint32_t serial, + uint32_t time, + uint32_t xkb_scancode, + bool key_repeats, + uint32_t state, + int xdg_key_symbol_count, + const xkb_keysym_t *xdg_key_symbols) override { spdlog::info( "Key: serial: {}, time: {}, xkb_scancode: 0x{:X}, key_repeats: {}, state: {}, xdg_keysym_count: {}, syms_out[0]: 0x{:X}", serial, time, xkb_scancode, key_repeats, state == KeyState::KEY_STATE_PRESS ? "press" : "release", diff --git a/examples/simple-shm.cc b/examples/simple-shm.cc index f5cbe50..30c094b 100644 --- a/examples/simple-shm.cc +++ b/examples/simple-shm.cc @@ -206,15 +206,15 @@ class App : public PointerObserver, public KeyboardObserver, public SeatObserver spdlog::info("Keymap: format: {}, fd: {}, size: {}", format, fd, size); } - void notify_keyboard_key(Keyboard * /* keyboard */, - wl_keyboard * /* wl_keyboard */, - uint32_t serial, - uint32_t time, - uint32_t xkb_scancode, - bool key_repeats, - uint32_t state, - int xdg_key_symbol_count, - const xkb_keysym_t *xdg_key_symbols) override { + void notify_keyboard_xkb_v1_key(Keyboard * /* keyboard */, + wl_keyboard * /* wl_keyboard */, + uint32_t serial, + uint32_t time, + uint32_t xkb_scancode, + bool key_repeats, + uint32_t state, + int xdg_key_symbol_count, + const xkb_keysym_t *xdg_key_symbols) override { spdlog::info( "Key: serial: {}, time: {}, xkb_scancode: 0x{:X}, key_repeats: {}, state: {}, xdg_keysym_count: {}, syms_out[0]: 0x{:X}", serial, time, xkb_scancode, key_repeats, state == KeyState::KEY_STATE_PRESS ? "press" : "release", diff --git a/examples/vk-shadertoy/handlers.cc b/examples/vk-shadertoy/handlers.cc index 76a0a7e..a8bd68b 100644 --- a/examples/vk-shadertoy/handlers.cc +++ b/examples/vk-shadertoy/handlers.cc @@ -70,15 +70,15 @@ void Handlers::notify_keyboard_keymap(Keyboard * /* keyboard */, spdlog::info("Keymap: format: {}, fd: {}, size: {}", format, fd, size); } -void Handlers::notify_keyboard_key(Keyboard * /* keyboard */, - wl_keyboard * /* wl_keyboard */, - uint32_t serial, - uint32_t time, - uint32_t xkb_scancode, - bool key_repeats, - uint32_t state, - int xdg_key_symbol_count, - const xkb_keysym_t *xdg_key_symbols) { +void Handlers::notify_keyboard_xkb_v1_key(Keyboard * /* keyboard */, + wl_keyboard * /* wl_keyboard */, + uint32_t serial, + uint32_t time, + uint32_t xkb_scancode, + bool key_repeats, + uint32_t state, + int xdg_key_symbol_count, + const xkb_keysym_t *xdg_key_symbols) { spdlog::info( "Key: serial: {}, time: {}, xkb_scancode: 0x{:X}, key_repeats: {}, state: {}, xdg_keysym_count: {}, syms_out[0]: 0x{:X}", serial, time, xkb_scancode, key_repeats, state == KeyState::KEY_STATE_PRESS ? "press" : "release", diff --git a/examples/vk-shadertoy/handlers.h b/examples/vk-shadertoy/handlers.h index cfd9d5a..eab80d8 100644 --- a/examples/vk-shadertoy/handlers.h +++ b/examples/vk-shadertoy/handlers.h @@ -47,8 +47,8 @@ class Handlers final : public SeatObserver, public PointerObserver, public Keybo void notify_keyboard_keymap(Keyboard *, wl_keyboard *, uint32_t, int32_t, uint32_t) override; - void notify_keyboard_key(Keyboard *, wl_keyboard *, uint32_t, uint32_t, uint32_t, bool, uint32_t, int, - const xkb_keysym_t *) override; + void notify_keyboard_xkb_v1_key(Keyboard *, wl_keyboard *, uint32_t, uint32_t, uint32_t, bool, uint32_t, int, + const xkb_keysym_t *) override; void notify_pointer_enter(Pointer *, wl_pointer *, uint32_t, wl_surface *, double, double) override; diff --git a/src/seat/keyboard.cc b/src/seat/keyboard.cc index 99bfc09..9389ea5 100644 --- a/src/seat/keyboard.cc +++ b/src/seat/keyboard.cc @@ -79,27 +79,28 @@ void Keyboard::handle_keymap(void *data, return; } - if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { - spdlog::critical( - "Usage with a libxkbcommon is currently required. Please file a bug with configuration information to enable support."); - abort(); + obj->format_ = static_cast(format); + + if (obj->format_ == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { + char *keymap_string; + /// From version 7 onwards, the fd must be mapped with MAP_PRIVATE by the recipient, as MAP_SHARED may fail. + if (wl_keyboard_get_version(wl_keyboard) >= 7) { + keymap_string = static_cast(mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0)); + } else { + keymap_string = static_cast(mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0)); + } + xkb_keymap_unref(obj->xkb_keymap_); + obj->xkb_keymap_ = xkb_keymap_new_from_string(obj->xkb_context_, keymap_string, + XKB_KEYMAP_FORMAT_TEXT_V1, + XKB_KEYMAP_COMPILE_NO_FLAGS); + munmap(keymap_string, size); + close(fd); + xkb_state_unref(obj->xkb_state_); + obj->xkb_state_ = xkb_state_new(obj->xkb_keymap_); } - - char *keymap_string; - /// From version 7 onwards, the fd must be mapped with MAP_PRIVATE by the recipient, as MAP_SHARED may fail. - if (wl_keyboard_get_version(wl_keyboard) >= 7) { - keymap_string = static_cast(mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0)); - } else { - keymap_string = static_cast(mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0)); + else { + spdlog::warn("Usage without libxkbcommon is currently not supported."); } - xkb_keymap_unref(obj->xkb_keymap_); - obj->xkb_keymap_ = xkb_keymap_new_from_string(obj->xkb_context_, keymap_string, - XKB_KEYMAP_FORMAT_TEXT_V1, - XKB_KEYMAP_COMPILE_NO_FLAGS); - munmap(keymap_string, size); - close(fd); - xkb_state_unref(obj->xkb_state_); - obj->xkb_state_ = xkb_state_new(obj->xkb_keymap_); for (auto observer: obj->observers_) { observer->notify_keyboard_keymap(obj, wl_keyboard, format, fd, size); @@ -120,10 +121,12 @@ void Keyboard::handle_enter(void *data, obj->wl_surface = wl_surface; - if (keys->size) { - const uint32_t *key; - WL_ARRAY_FOR_EACH(key, keys, const uint32_t*) { - handle_key(data, wl_keyboard, serial, 0, *key, WL_KEYBOARD_KEY_STATE_PRESSED); + if (obj->format_ == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { + if (keys->size) { + const uint32_t *key; + WL_ARRAY_FOR_EACH(key, keys, const uint32_t*) { + handle_key(data, wl_keyboard, serial, 0, *key, WL_KEYBOARD_KEY_STATE_PRESSED); + } } } @@ -163,44 +166,47 @@ void Keyboard::handle_key(void *data, if (!obj->xkb_state_) return; - /// translate scancode to XKB scancode - auto xkb_scancode = key + 8; - auto key_repeats = xkb_keymap_key_repeats(obj->xkb_keymap_, xkb_scancode); - - const xkb_keysym_t *key_syms; - auto xdg_keysym_count = xkb_state_key_get_syms(obj->xkb_state_, xkb_scancode, &key_syms); - - if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { - if (key_repeats) { - // start/restart timer - struct itimerspec in{}; - in.it_value.tv_nsec = obj->repeat_.delay * 1000000; - in.it_interval.tv_nsec = obj->repeat_.rate * 1000000; - timer_settime(obj->repeat_.timer, 0, &in, nullptr); - - // update notify values - obj->repeat_.notify = { - .serial = serial, - .time = time, - .xkb_scancode = xkb_scancode, - .key_repeats = key_repeats, - .xdg_keysym_count = xdg_keysym_count, - .key_syms = key_syms, - }; + if (obj->format_ == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { + + /// translate scancode to XKB scancode + auto xkb_scancode = key + 8; + auto key_repeats = xkb_keymap_key_repeats(obj->xkb_keymap_, xkb_scancode); + + const xkb_keysym_t *key_syms; + auto xdg_keysym_count = xkb_state_key_get_syms(obj->xkb_state_, xkb_scancode, &key_syms); + + if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { + if (key_repeats) { + // start/restart timer + struct itimerspec in{}; + in.it_value.tv_nsec = obj->repeat_.delay * 1000000; + in.it_interval.tv_nsec = obj->repeat_.rate * 1000000; + timer_settime(obj->repeat_.timer, 0, &in, nullptr); + + // update notify values + obj->repeat_.notify = { + .serial = serial, + .time = time, + .xkb_scancode = xkb_scancode, + .key_repeats = key_repeats, + .xdg_keysym_count = xdg_keysym_count, + .key_syms = key_syms, + }; + } + + } else if (state == WL_KEYBOARD_KEY_STATE_RELEASED) { + if (obj->repeat_.notify.xkb_scancode == xkb_scancode) { + // stop timer + struct itimerspec its{}; + timer_settime(obj->repeat_.timer, 0, &its, nullptr); + } } - } else if (state == WL_KEYBOARD_KEY_STATE_RELEASED) { - if (obj->repeat_.notify.xkb_scancode == xkb_scancode) { - // stop timer - struct itimerspec its{}; - timer_settime(obj->repeat_.timer, 0, &its, nullptr); + for (auto observer: obj->observers_) { + observer->notify_keyboard_xkb_v1_key(obj, wl_keyboard, serial, time, xkb_scancode, key_repeats, state, + xdg_keysym_count, key_syms); } } - - for (auto observer: obj->observers_) { - observer->notify_keyboard_key(obj, wl_keyboard, serial, time, xkb_scancode, key_repeats, state, - xdg_keysym_count, key_syms); - } } void Keyboard::handle_modifiers(void *data, @@ -217,7 +223,9 @@ void Keyboard::handle_modifiers(void *data, SPDLOG_TRACE("[Keyboard] handle_modifiers"); - xkb_state_update_mask(obj->xkb_state_, mods_depressed, mods_latched, mods_locked, 0, 0, group); + if (obj->format_ == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { + xkb_state_update_mask(obj->xkb_state_, mods_depressed, mods_latched, mods_locked, 0, 0, group); + } } void Keyboard::handle_repeat_info(void *data, @@ -234,25 +242,28 @@ void Keyboard::handle_repeat_info(void *data, obj->repeat_.rate = rate; obj->repeat_.delay = delay; - if (!obj->repeat_.timer) { - - /// Setup signal event - obj->repeat_.sev.sigev_notify = SIGEV_SIGNAL; - obj->repeat_.sev.sigev_signo = SIGRTMIN; - obj->repeat_.sev.sigev_value.sival_ptr = data; - auto res = timer_create(CLOCK_REALTIME, &obj->repeat_.sev, &obj->repeat_.timer); - if (res != 0) { - spdlog::critical("Error timer_create: {}", strerror(errno)); - abort(); - } - - /// Setup signal action - obj->repeat_.sa.sa_flags = SA_SIGINFO; - obj->repeat_.sa.sa_sigaction = repeat_callback; - sigemptyset(&obj->repeat_.sa.sa_mask); - if (sigaction(SIGRTMIN, &obj->repeat_.sa, nullptr) == -1) { - spdlog::critical("Error sigaction: {}", strerror(errno)); - abort(); + if (obj->format_ == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { + + if (!obj->repeat_.timer) { + + /// Setup signal event + obj->repeat_.sev.sigev_notify = SIGEV_SIGNAL; + obj->repeat_.sev.sigev_signo = SIGRTMIN; + obj->repeat_.sev.sigev_value.sival_ptr = data; + auto res = timer_create(CLOCK_REALTIME, &obj->repeat_.sev, &obj->repeat_.timer); + if (res != 0) { + spdlog::critical("Error timer_create: {}", strerror(errno)); + abort(); + } + + /// Setup signal action + obj->repeat_.sa.sa_flags = SA_SIGINFO; + obj->repeat_.sa.sa_sigaction = repeat_xkb_v1_key_callback; + sigemptyset(&obj->repeat_.sa.sa_mask); + if (sigaction(SIGRTMIN, &obj->repeat_.sa, nullptr) == -1) { + spdlog::critical("Error sigaction: {}", strerror(errno)); + abort(); + } } } } @@ -266,13 +277,13 @@ const struct wl_keyboard_listener Keyboard::keyboard_listener_ = { .repeat_info = handle_repeat_info, }; -void Keyboard::repeat_callback(int /* sig */, siginfo_t *si, void * /* uc */) { +void Keyboard::repeat_xkb_v1_key_callback(int /* sig */, siginfo_t *si, void * /* uc */) { auto obj = static_cast(si->_sifields._rt.si_sigval.sival_ptr); for (auto observer: obj->observers_) { - observer->notify_keyboard_key(obj, obj->repeat_.notify.wl_keyboard, obj->repeat_.notify.serial, - obj->repeat_.notify.time, obj->repeat_.notify.xkb_scancode, - obj->repeat_.notify.key_repeats, WL_KEYBOARD_KEY_STATE_PRESSED, - obj->repeat_.notify.xdg_keysym_count, obj->repeat_.notify.key_syms); + observer->notify_keyboard_xkb_v1_key(obj, obj->repeat_.notify.wl_keyboard, obj->repeat_.notify.serial, + obj->repeat_.notify.time, obj->repeat_.notify.xkb_scancode, + obj->repeat_.notify.key_repeats, WL_KEYBOARD_KEY_STATE_PRESSED, + obj->repeat_.notify.xdg_keysym_count, obj->repeat_.notify.key_syms); } } diff --git a/src/seat/keyboard.h b/src/seat/keyboard.h index 0950216..08d165f 100644 --- a/src/seat/keyboard.h +++ b/src/seat/keyboard.h @@ -22,6 +22,7 @@ #include #include +#include #include class Keyboard; @@ -52,15 +53,15 @@ class KeyboardObserver { int32_t fd, uint32_t size) = 0; - virtual void notify_keyboard_key(Keyboard *keyboard, - struct wl_keyboard *wl_keyboard, - uint32_t serial, - uint32_t time, - uint32_t xkb_scancode, - bool keymap_key_repeats, - uint32_t state, - int xdg_key_symbol_count, - const xkb_keysym_t *xdg_key_symbols) = 0; + virtual void notify_keyboard_xkb_v1_key(Keyboard *keyboard, + struct wl_keyboard *wl_keyboard, + uint32_t serial, + uint32_t time, + uint32_t xkb_scancode, + bool keymap_key_repeats, + uint32_t state, + int xdg_key_symbol_count, + const xkb_keysym_t *xdg_key_symbols) = 0; }; class Keyboard { @@ -92,6 +93,7 @@ class Keyboard { struct xkb_context *xkb_context_; struct xkb_keymap *xkb_keymap_{}; struct xkb_state *xkb_state_{}; + enum wl_keyboard_keymap_format format_{}; std::list observers_{}; struct { @@ -118,7 +120,7 @@ class Keyboard { * This function is called by the kernel. * */ - static void repeat_callback(int sig, siginfo_t *si, void *uc); + static void repeat_xkb_v1_key_callback(int, siginfo_t *si, void *); /** * keyboard mapping