GHOST/Wayland: support setting modifiers on window activation
Take advantage of Waylands wl_keyboard_listener.enter callback which takes an array of keys that are pressed when a window is activated. Resolves T74684 under Wayland.
This commit is contained in:
parent
1c716cbeb7
commit
aa0ca3aefa
Notes:
blender-bot
2023-02-14 11:20:29 +01:00
Referenced by issue #74684, Blender does not register modifier key combinations every first time when switching between windows
|
@ -13,6 +13,7 @@
|
|||
#include "GHOST_EventWheel.h"
|
||||
#include "GHOST_PathUtils.h"
|
||||
#include "GHOST_TimerManager.h"
|
||||
#include "GHOST_WaylandUtils.h"
|
||||
#include "GHOST_WindowManager.h"
|
||||
#include "GHOST_utildefines.h"
|
||||
|
||||
|
@ -2140,7 +2141,7 @@ static void keyboard_handle_enter(void *data,
|
|||
struct wl_keyboard * /*wl_keyboard*/,
|
||||
const uint32_t serial,
|
||||
struct wl_surface *surface,
|
||||
struct wl_array * /*keys*/)
|
||||
struct wl_array *keys)
|
||||
{
|
||||
if (!ghost_wl_surface_own(surface)) {
|
||||
CLOG_INFO(LOG, 2, "enter (skipped)");
|
||||
|
@ -2151,6 +2152,49 @@ static void keyboard_handle_enter(void *data,
|
|||
input_t *input = static_cast<input_t *>(data);
|
||||
input->keyboard.serial = serial;
|
||||
input->keyboard.wl_surface = surface;
|
||||
|
||||
if (keys->size != 0) {
|
||||
/* If there are any keys held when activating the window,
|
||||
* modifiers will be compared against the input state,
|
||||
* only enabling modifiers that were previously disabled. */
|
||||
|
||||
const xkb_mod_mask_t state = xkb_state_serialize_mods(input->xkb_state, XKB_STATE_MODS_ALL);
|
||||
uint32_t *key;
|
||||
WL_ARRAY_FOR_EACH (key, keys) {
|
||||
const xkb_keycode_t key_code = *key + EVDEV_OFFSET;
|
||||
const xkb_keysym_t sym = xkb_state_key_get_one_sym(input->xkb_state, key_code);
|
||||
GHOST_TKey gkey = GHOST_kKeyUnknown;
|
||||
|
||||
#define MOD_TEST(state, mod) ((mod != XKB_MOD_INVALID) && (state & (1 << mod)))
|
||||
#define MOD_TEST_CASE(xkb_key, ghost_key, mod_index) \
|
||||
case xkb_key: \
|
||||
if (!MOD_TEST(state, input->xkb_keymap_mod_index.mod_index)) { \
|
||||
gkey = ghost_key; \
|
||||
} \
|
||||
break
|
||||
|
||||
switch (sym) {
|
||||
MOD_TEST_CASE(XKB_KEY_Shift_L, GHOST_kKeyLeftShift, shift);
|
||||
MOD_TEST_CASE(XKB_KEY_Shift_R, GHOST_kKeyRightShift, shift);
|
||||
MOD_TEST_CASE(XKB_KEY_Control_L, GHOST_kKeyLeftControl, ctrl);
|
||||
MOD_TEST_CASE(XKB_KEY_Control_R, GHOST_kKeyRightControl, ctrl);
|
||||
MOD_TEST_CASE(XKB_KEY_Alt_L, GHOST_kKeyLeftAlt, alt);
|
||||
MOD_TEST_CASE(XKB_KEY_Alt_R, GHOST_kKeyRightAlt, alt);
|
||||
MOD_TEST_CASE(XKB_KEY_Super_L, GHOST_kKeyOS, logo);
|
||||
MOD_TEST_CASE(XKB_KEY_Super_R, GHOST_kKeyOS, logo);
|
||||
}
|
||||
|
||||
#undef MOD_TEST
|
||||
#undef MOD_TEST_CASE
|
||||
|
||||
if (gkey != GHOST_kKeyUnknown) {
|
||||
GHOST_IWindow *win = ghost_wl_surface_user_data(surface);
|
||||
GHOST_SystemWayland *system = input->system;
|
||||
input->system->pushEvent(
|
||||
new GHOST_EventKey(system->getMilliSeconds(), GHOST_kEventKeyDown, win, gkey, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2377,7 +2421,13 @@ static void keyboard_handle_modifiers(void *data,
|
|||
const uint32_t mods_locked,
|
||||
const uint32_t group)
|
||||
{
|
||||
CLOG_INFO(LOG, 2, "modifiers");
|
||||
CLOG_INFO(LOG,
|
||||
2,
|
||||
"modifiers (depressed=%u, latched=%u, locked=%u, group=%u)",
|
||||
mods_depressed,
|
||||
mods_latched,
|
||||
mods_locked,
|
||||
group);
|
||||
|
||||
input_t *input = static_cast<input_t *>(data);
|
||||
xkb_state_update_mask(input->xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group);
|
||||
|
|
Loading…
Reference in New Issue