diff --git a/src/keymap.c b/src/keymap.c index 6736c2c..87694cf 100644 --- a/src/keymap.c +++ b/src/keymap.c @@ -227,6 +227,12 @@ xkb_keymap_num_levels_for_key(struct xkb_keymap *keymap, xkb_keycode_t kc, if (!key) return 0; + layout = wrap_group_into_range(layout, key->num_groups, + key->out_of_range_group_action, + key->out_of_range_group_number); + if (layout == XKB_LAYOUT_INVALID) + return 0; + return XkbKeyGroupWidth(key, layout); } @@ -287,8 +293,13 @@ xkb_keymap_key_get_syms_by_level(struct xkb_keymap *keymap, if (!key) goto err; - if (layout >= key->num_groups) + + layout = wrap_group_into_range(layout, key->num_groups, + key->out_of_range_group_action, + key->out_of_range_group_number); + if (layout == XKB_LAYOUT_INVALID) goto err; + if (level >= XkbKeyGroupWidth(key, layout)) goto err; diff --git a/src/keymap.h b/src/keymap.h index 483ee90..cb035b0 100644 --- a/src/keymap.h +++ b/src/keymap.h @@ -427,4 +427,10 @@ xkb_keymap_new(struct xkb_context *ctx, enum xkb_keymap_format format, enum xkb_keymap_compile_flags); +xkb_layout_index_t +wrap_group_into_range(int32_t group, + xkb_layout_index_t num_groups, + enum xkb_range_exceed_type out_of_range_group_action, + xkb_layout_index_t out_of_range_group_number); + #endif diff --git a/src/state.c b/src/state.c index 48b2132..19b372a 100644 --- a/src/state.c +++ b/src/state.c @@ -151,7 +151,7 @@ xkb_state_key_get_level(struct xkb_state *state, xkb_keycode_t kc, return entry->level; } -static xkb_layout_index_t +xkb_layout_index_t wrap_group_into_range(int32_t group, xkb_layout_index_t num_groups, enum xkb_range_exceed_type out_of_range_group_action, diff --git a/xkbcommon/xkbcommon.h b/xkbcommon/xkbcommon.h index 43f9df1..244b35b 100644 --- a/xkbcommon/xkbcommon.h +++ b/xkbcommon/xkbcommon.h @@ -864,6 +864,10 @@ xkb_keymap_num_layouts_for_key(struct xkb_keymap *keymap, xkb_keycode_t key); /** * Get the number of shift levels for a specific key and layout. * + * If @c layout is out of range for this key (that is, larger or equal to + * the value returned by xkb_keymap_num_layouts_for_key()), it is brought + * back into range in a manner consistent with xkb_state_key_get_layout(). + * * @sa xkb_level_index_t * @memberof xkb_keymap */ @@ -881,19 +885,17 @@ xkb_keymap_num_levels_for_key(struct xkb_keymap *keymap, xkb_keycode_t key, * * @param[in] keymap The keymap. * @param[in] key The keycode of the key. - * @param[in] layout The layout for which to get the keysyms. This must - * be smaller than: - * @code xkb_keymap_num_layouts_for_key(keymap, key) @endcode - * Usually it would be: - * @code xkb_state_key_get_layout(state, key) @endcode + * @param[in] layout The layout for which to get the keysyms. * @param[in] level The shift level in the layout for which to get the * keysyms. This must be smaller than: * @code xkb_keymap_num_layouts_for_key(keymap, key) @endcode - * usually it would be: - * @code xkb_state_key_get_level(state, key, layout) @endcode - * @param[out] syms_out An immutible array of keysyms corresponding the + * @param[out] syms_out An immutible array of keysyms corresponding to the * key in the given layout and shift level. * + * If @c layout is out of range for this key (that is, larger or equal to + * the value returned by xkb_keymap_num_layouts_for_key()), it is brought + * back into range in a manner consistent with xkb_state_key_get_layout(). + * * @returns The number of keysyms in the syms_out array. If no keysyms * are produced by the key in the given layout and shift level, returns 0 * and sets syms_out to NULL.