Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions src/video/wayland/SDL_waylandevents.c
Original file line number Diff line number Diff line change
Expand Up @@ -1414,6 +1414,58 @@ static const struct wl_touch_listener touch_listener = {
touch_handler_orientation // Version 6
};

// Fallback for xkb_keymap_key_get_mods_for_level(), which is only available from 1.0.0, while the SDL minimum os 0.5.0.
#if !SDL_XKBCOMMON_CHECK_VERSION(1, 0, 0)
static size_t xkb_legacy_get_mods_for_level(SDL_WaylandSeat *seat, xkb_keycode_t key, xkb_layout_index_t layout, xkb_level_index_t level, xkb_mod_mask_t *masks_out, size_t masks_size)
{
if (!masks_out || !masks_size) {
return 0;
}

// Level 0 is always unmodified, so early out.
if (level == 0) {
*masks_out = 0;
return 1;
}

struct xkb_state *state = WAYLAND_xkb_state_new(seat->keyboard.xkb.keymap);
if (state) {
const xkb_mod_mask_t keymod_masks[] = {
0,
seat->keyboard.xkb.shift_mask,
seat->keyboard.xkb.caps_mask,
seat->keyboard.xkb.shift_mask | seat->keyboard.xkb.caps_mask,
seat->keyboard.xkb.level3_mask,
seat->keyboard.xkb.level3_mask | seat->keyboard.xkb.shift_mask,
seat->keyboard.xkb.level3_mask | seat->keyboard.xkb.caps_mask,
seat->keyboard.xkb.level3_mask | seat->keyboard.xkb.shift_mask | seat->keyboard.xkb.caps_mask,
seat->keyboard.xkb.level5_mask,
seat->keyboard.xkb.level5_mask | seat->keyboard.xkb.shift_mask,
seat->keyboard.xkb.level5_mask | seat->keyboard.xkb.caps_mask,
seat->keyboard.xkb.level5_mask | seat->keyboard.xkb.shift_mask | seat->keyboard.xkb.caps_mask
};
const xkb_mod_mask_t pressed_mod_mask = seat->keyboard.xkb.shift_mask | seat->keyboard.xkb.level3_mask | seat->keyboard.xkb.level5_mask;
const xkb_mod_mask_t locked_mod_mask = seat->keyboard.xkb.caps_mask;

size_t mask_idx = 0;

for (size_t i = 0; i < SDL_arraysize(keymod_masks); ++i) {
WAYLAND_xkb_state_update_mask(state, keymod_masks[i] & pressed_mod_mask, 0, keymod_masks[i] & locked_mod_mask, 0, 0, layout);
if (WAYLAND_xkb_state_key_get_level(state, key, layout) == level) {
masks_out[mask_idx] = keymod_masks[i];

if (++mask_idx == masks_size) {
break;
}
}
}

WAYLAND_xkb_state_unref(state);
}
return mask_idx;
}
#endif

static void Wayland_KeymapIterator(struct xkb_keymap *keymap, xkb_keycode_t key, void *data)
{
SDL_WaylandSeat *seat = (SDL_WaylandSeat *)data;
Expand Down Expand Up @@ -1450,7 +1502,11 @@ static void Wayland_KeymapIterator(struct xkb_keymap *keymap, xkb_keycode_t key,
}

xkb_mod_mask_t xkb_mod_masks[16];
#if SDL_XKBCOMMON_CHECK_VERSION(1, 0, 0)
const size_t num_masks = WAYLAND_xkb_keymap_key_get_mods_for_level(seat->keyboard.xkb.keymap, key, layout, level, xkb_mod_masks, SDL_arraysize(xkb_mod_masks));
#else
const size_t num_masks = xkb_legacy_get_mods_for_level(seat, key, layout, level, xkb_mod_masks, SDL_arraysize(xkb_mod_masks));
#endif
for (size_t mask = 0; mask < num_masks; ++mask) {
// Ignore this modifier set if it uses unsupported modifier types.
if ((xkb_mod_masks[mask] | xkb_valid_mod_mask) != xkb_valid_mod_mask) {
Expand Down
23 changes: 10 additions & 13 deletions src/video/wayland/SDL_waylandsym.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,22 +151,19 @@ SDL_WAYLAND_SYM(enum xkb_compose_status, xkb_compose_state_get_status, (struct x
SDL_WAYLAND_SYM(xkb_keysym_t, xkb_compose_state_get_one_sym, (struct xkb_compose_state *) )
SDL_WAYLAND_SYM(void, xkb_keymap_key_for_each, (struct xkb_keymap *, xkb_keymap_key_iter_t, void *) )
SDL_WAYLAND_SYM(xkb_layout_index_t, xkb_keymap_num_layouts, (struct xkb_keymap *) )
SDL_WAYLAND_SYM(int, xkb_keymap_key_get_syms_by_level, (struct xkb_keymap *,
xkb_keycode_t,
xkb_layout_index_t,
xkb_level_index_t,
const xkb_keysym_t **) )
SDL_WAYLAND_SYM(int, xkb_keymap_key_get_syms_by_level, (struct xkb_keymap *, xkb_keycode_t, xkb_layout_index_t, xkb_level_index_t, const xkb_keysym_t **) )
SDL_WAYLAND_SYM(xkb_level_index_t, xkb_keymap_num_levels_for_key, (struct xkb_keymap *, xkb_keycode_t, xkb_layout_index_t) )
SDL_WAYLAND_SYM(size_t, xkb_keymap_key_get_mods_for_level, (struct xkb_keymap *,
xkb_keycode_t,
xkb_layout_index_t,
xkb_level_index_t,
xkb_mod_mask_t *,
size_t masks_size) )
SDL_WAYLAND_SYM(uint32_t, xkb_keysym_to_utf32, (xkb_keysym_t) )
SDL_WAYLAND_SYM(uint32_t, xkb_keymap_mod_get_index, (struct xkb_keymap *,
const char *) )
SDL_WAYLAND_SYM(uint32_t, xkb_keymap_mod_get_index, (struct xkb_keymap *, const char *) )
SDL_WAYLAND_SYM(const char *, xkb_keymap_layout_get_name, (struct xkb_keymap *, xkb_layout_index_t))

#if SDL_XKBCOMMON_CHECK_VERSION(1, 0, 0)
SDL_WAYLAND_SYM(size_t, xkb_keymap_key_get_mods_for_level, (struct xkb_keymap *, xkb_keycode_t, xkb_layout_index_t, xkb_level_index_t, xkb_mod_mask_t *, size_t) )
#else
// Only needed in the fallback replacement for xkb_keymap_key_get_mods_for_level().
SDL_WAYLAND_SYM(xkb_level_index_t, xkb_state_key_get_level, (struct xkb_state *, xkb_keycode_t, xkb_layout_index_t) )
#endif

#if SDL_XKBCOMMON_CHECK_VERSION(1, 10, 0)
SDL_WAYLAND_SYM(xkb_mod_mask_t, xkb_keymap_mod_get_mask, (struct xkb_keymap *, const char *))
#endif
Expand Down
Loading