From 16e96493705678a823b521513585250ae24b197e Mon Sep 17 00:00:00 2001 From: Pierre Le Marre Date: Fri, 12 Jul 2024 04:09:39 +0200 Subject: [PATCH] Enable out-of-range layout action configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce 2 new keymap compilation flags to configure the action: - `XKB_KEYMAP_REDIRECT_OUT_OF_RANGE_LAYOUT` to use “redirect into range”. - `XKB_KEYMAP_CLAMP_OUT_OF_RANGE_LAYOUT` to use “clamp into range”. The default action remains “wrap into range” using integer modulus. --- .../+out-of-range-layout-config.feature.md | 6 ++ doc/message-registry.md | 12 ++- doc/message-registry.yaml | 5 ++ include/xkbcommon/xkbcommon.h | 58 ++++++++++++- src/keymap-priv.c | 34 ++++++++ src/keymap.c | 6 +- src/keymap.h | 26 +++++- src/messages-codes.h | 2 + src/state.c | 15 ++-- src/x11/keymap.c | 2 +- test/common.c | 20 +++-- test/keyseq.c | 85 +++++++++++++++++++ test/test.h | 6 ++ tools/messages.c | 1 + 14 files changed, 255 insertions(+), 23 deletions(-) create mode 100644 changes/api/+out-of-range-layout-config.feature.md diff --git a/changes/api/+out-of-range-layout-config.feature.md b/changes/api/+out-of-range-layout-config.feature.md new file mode 100644 index 000000000..b80291386 --- /dev/null +++ b/changes/api/+out-of-range-layout-config.feature.md @@ -0,0 +1,6 @@ +Enable the configuration of out-of-range layout handling using 2 new keymap compile flags: +- `XKB_KEYMAP_REDIRECT_OUT_OF_RANGE_LAYOUT`: redirect to a specific layout index. +- `XKB_KEYMAP_CLAMP_OUT_OF_RANGE_LAYOUT`: clamp into range, i.e. invalid indexes are + corrected to the closest valid bound (0 or highest layout index). + +When not specified, invalid groups are brought into range using integer modulus. diff --git a/doc/message-registry.md b/doc/message-registry.md index 0a5189326..01f529224 100644 --- a/doc/message-registry.md +++ b/doc/message-registry.md @@ -6,7 +6,7 @@ NOTE: This file has been generated automatically by “update-message-registry.p --> This page lists the warnings and errors generated by xkbcommon. -There are currently 55 entries. +There are currently 56 entries. @todo The documentation of the log messages is a work in progress. @@ -53,6 +53,7 @@ There are currently 55 entries. | [XKB-623] | `invalid-real-modifier` | Invalid _real_ modifier | Error | | [XKB-645] | `unknown-char-escape-sequence` | Warn on unknown escape sequence in string literal | Warning | | [XKB-661] | `invalid-included-file` | The target file of an include statement could not be processed | Error | +| [XKB-697] | `multiple-out-of-range-layout-flags` | Multiple out-of-range layout flags were set, but only one is allowed. | Error | | [XKB-700] | `multiple-groups-at-once` | Warn if a key defines multiple groups at once | Warning | | [XKB-711] | `unsupported-symbols-field` | A legacy X11 symbol field is not supported | Warning | | [XKB-769] | `invalid-syntax` | The syntax is invalid and the file cannot be parsed | Error | @@ -550,6 +551,14 @@ xkbcommon support the following escape sequences in string literals:
Summary
The target file of an include statement could not be processed
+### XKB-697 – Multiple out of range layout flags {#XKB-697} + +
+
Since
1.8.0
+
Type
Error
+
Summary
Multiple out-of-range layout flags were set, but only one is allowed.
+
+ ### XKB-700 – Multiple groups at once {#XKB-700}
@@ -724,6 +733,7 @@ The modifiers used in `map` or `preserve` entries should be declared using the e [XKB-623]: @ref XKB-623 [XKB-645]: @ref XKB-645 [XKB-661]: @ref XKB-661 +[XKB-697]: @ref XKB-697 [XKB-700]: @ref XKB-700 [XKB-711]: @ref XKB-711 [XKB-769]: @ref XKB-769 diff --git a/doc/message-registry.yaml b/doc/message-registry.yaml index 6a9725fd3..05d89be56 100644 --- a/doc/message-registry.yaml +++ b/doc/message-registry.yaml @@ -324,6 +324,11 @@ added: ALWAYS type: error description: "The target file of an include statement could not be processed" +- id: "multiple-out-of-range-layout-flags" + code: 697 + added: 1.8.0 + type: error + description: "Multiple out-of-range layout flags were set, but only one is allowed." - id: "multiple-groups-at-once" code: 700 added: ALWAYS diff --git a/include/xkbcommon/xkbcommon.h b/include/xkbcommon/xkbcommon.h index 219d197ba..18dbdc822 100644 --- a/include/xkbcommon/xkbcommon.h +++ b/include/xkbcommon/xkbcommon.h @@ -872,10 +872,60 @@ xkb_context_set_log_fn(struct xkb_context *context, * @{ */ -/** Flags for keymap compilation. */ +/** + * Flags for keymap compilation. + * + * @par Out-of-range layout action + * [Effective layout] index may be invalid in some contexts. + * One of the following out-of-range layout action is then used to bring invalid + * layout indexes back into range: + * + * - “redirect into range” (see: ::XKB_KEYMAP_REDIRECT_OUT_OF_RANGE_LAYOUT) + * - “clamp into range” (see: ::XKB_KEYMAP_CLAMP_OUT_OF_RANGE_LAYOUT) + * - “wrap into range” using integer modulus (default) + * + * [Effective layout]: @ref ::XKB_STATE_LAYOUT_EFFECTIVE + */ enum xkb_keymap_compile_flags { /** Do not apply any flags. */ - XKB_KEYMAP_COMPILE_NO_FLAGS = 0 + XKB_KEYMAP_COMPILE_NO_FLAGS = 0, + /* + * 4 least significant bit reserved to encode layout index (0..15) for + * XKB_KEYMAP_REDIRECT_OUT_OF_RANGE_LAYOUT. + */ + /** + * Set the out-of-range layout action to “redirect into range”. + * + * - If the [effective layout] is invalid, it is set to a *target layout*. + * - If the target layout is invalid, it is set to the first one (0). + * + * A *target layout index* (range 0..15) may be provided using the 4 least + * significant bits of the corresponding #xkb_keymap_compile_flags value, + * e.g.: + * + * ```c + * // Set the target layout index to 1. + * enum xkb_keymap_compile_flags flags = XKB_KEYMAP_REDIRECT_OUT_OF_RANGE_LAYOUT | 1; + * ``` + * + * @since 1.8.0 + * + * [effective layout]: @ref ::XKB_STATE_LAYOUT_EFFECTIVE + */ + XKB_KEYMAP_REDIRECT_OUT_OF_RANGE_LAYOUT = 1 << 4, + /** + * Set the out-of-range layout action to “clamp into range”: if the + * [effective layout] is invalid, it is set to nearest valid layout: + * + * - effective layout larger than the highest supported layout are mapped to + * the highest supported layout; + * - effective layout less than 0 are mapped to 0. + * + * @since 1.8.0 + * + * [effective layout]: @ref ::XKB_STATE_LAYOUT_EFFECTIVE + */ + XKB_KEYMAP_CLAMP_OUT_OF_RANGE_LAYOUT = 1 << 5 }; /** @@ -886,7 +936,7 @@ enum xkb_keymap_compile_flags { * * @param context The context in which to create the keymap. * @param names The RMLVO names to use. See xkb_rule_names. - * @param flags Optional flags for the keymap, or 0. + * @param flags Optional flags for the keymap, or ::XKB_KEYMAP_COMPILE_NO_FLAGS. * * @returns A keymap compiled according to the RMLVO names, or NULL if * the compilation failed. @@ -911,7 +961,7 @@ enum xkb_keymap_format { * @param context The context in which to create the keymap. * @param file The keymap file to compile. * @param format The text format of the keymap file to compile. - * @param flags Optional flags for the keymap, or 0. + * @param flags Optional flags for the keymap, or ::XKB_KEYMAP_COMPILE_NO_FLAGS. * * @returns A keymap compiled from the given XKB keymap file, or NULL if * the compilation failed. diff --git a/src/keymap-priv.c b/src/keymap-priv.c index 8fdaf5b6f..13129b777 100644 --- a/src/keymap-priv.c +++ b/src/keymap-priv.c @@ -52,12 +52,43 @@ update_builtin_keymap_fields(struct xkb_keymap *keymap) keymap->mods.num_mods = ARRAY_SIZE(builtin_mods); } +#define XKB_KEYMAP_OUT_OF_RANGE_LAYOUT_FLAGS \ + (XKB_KEYMAP_REDIRECT_OUT_OF_RANGE_LAYOUT | \ + XKB_KEYMAP_CLAMP_OUT_OF_RANGE_LAYOUT) + struct xkb_keymap * xkb_keymap_new(struct xkb_context *ctx, enum xkb_keymap_format format, enum xkb_keymap_compile_flags flags) { struct xkb_keymap *keymap; + enum xkb_range_exceed_type out_of_range_group_action; + xkb_layout_index_t out_of_range_group_number = + flags & XKB_REDIRECT_LAYOUT_INDEX_MASK; + + switch (flags & XKB_KEYMAP_OUT_OF_RANGE_LAYOUT_FLAGS) { + case 0: + out_of_range_group_action = RANGE_WRAP; + break; + case XKB_KEYMAP_REDIRECT_OUT_OF_RANGE_LAYOUT: + out_of_range_group_action = RANGE_REDIRECT; + break; + case XKB_KEYMAP_CLAMP_OUT_OF_RANGE_LAYOUT: + out_of_range_group_action = RANGE_SATURATE; + break; + default: + log_err(ctx, XKB_ERROR_MULTIPLE_OUT_OF_RANGE_LAYOUT_FLAGS, + "Cannot mix \"out of range layout\" keymap flags: %#x\n", flags); + return NULL; + } + + if (out_of_range_group_number && out_of_range_group_action != RANGE_REDIRECT) { + log_err(ctx, XKB_ERROR_MULTIPLE_OUT_OF_RANGE_LAYOUT_FLAGS, + "Redirect layout index can only be used in combination with " + "XKB_KEYMAP_REDIRECT_OUT_OF_RANGE_LAYOUT flag. " + "Invalid keymap flags: %#x\n", flags); + return NULL; + } keymap = calloc(1, sizeof(*keymap)); if (!keymap) @@ -69,6 +100,9 @@ xkb_keymap_new(struct xkb_context *ctx, keymap->format = format; keymap->flags = flags; + keymap->out_of_range_group_action = out_of_range_group_action; + keymap->out_of_range_group_number = out_of_range_group_number; + update_builtin_keymap_fields(keymap); return keymap; diff --git a/src/keymap.c b/src/keymap.c index 0291aedbb..6b8af980f 100644 --- a/src/keymap.c +++ b/src/keymap.c @@ -132,7 +132,7 @@ xkb_keymap_new_from_names(struct xkb_context *ctx, return NULL; } - if (flags & ~(XKB_KEYMAP_COMPILE_NO_FLAGS)) { + if (flags & ~XKB_KEYMAP_FLAGS_ALL) { log_err_func(ctx, "unrecognized flags: %#x\n", flags); return NULL; } @@ -180,7 +180,7 @@ xkb_keymap_new_from_buffer(struct xkb_context *ctx, return NULL; } - if (flags & ~(XKB_KEYMAP_COMPILE_NO_FLAGS)) { + if (flags & ~XKB_KEYMAP_FLAGS_ALL) { log_err_func(ctx, "unrecognized flags: %#x\n", flags); return NULL; } @@ -221,7 +221,7 @@ xkb_keymap_new_from_file(struct xkb_context *ctx, return NULL; } - if (flags & ~(XKB_KEYMAP_COMPILE_NO_FLAGS)) { + if (flags & ~XKB_KEYMAP_FLAGS_ALL) { log_err_func(ctx, "unrecognized flags: %#x\n", flags); return NULL; } diff --git a/src/keymap.h b/src/keymap.h index f7ea5bdf1..f023f68ad 100644 --- a/src/keymap.h +++ b/src/keymap.h @@ -120,6 +120,13 @@ enum mod_type { }; #define MOD_REAL_MASK_ALL ((xkb_mod_mask_t) 0x000000ff) +#define XKB_REDIRECT_LAYOUT_INDEX_MASK (XKB_KEYMAP_REDIRECT_OUT_OF_RANGE_LAYOUT - 1) + +#define XKB_KEYMAP_FLAGS_ALL \ + (XKB_REDIRECT_LAYOUT_INDEX_MASK | \ + XKB_KEYMAP_REDIRECT_OUT_OF_RANGE_LAYOUT | \ + XKB_KEYMAP_CLAMP_OUT_OF_RANGE_LAYOUT) + enum xkb_action_type { ACTION_TYPE_NONE = 0, ACTION_TYPE_MOD_SET, @@ -307,6 +314,7 @@ enum xkb_range_exceed_type { RANGE_WRAP = 0, RANGE_SATURATE, RANGE_REDIRECT, +#define _XKB_RANGE_EXCEED_TYPE_NUM_ENTRIES 3 }; enum xkb_explicit_components { @@ -332,6 +340,17 @@ struct xkb_group { struct xkb_level *levels; }; +/* Note: enum value may be interpreted as a signed int, so we need an extra bit + * to store the sign. */ +#define OUT_OF_RANGE_GROUP_ACTION_SIZE 3 +#define OUT_OF_RANGE_GROUP_NUMBER_SIZE (32 - OUT_OF_RANGE_GROUP_ACTION_SIZE) +#if _XKB_RANGE_EXCEED_TYPE_NUM_ENTRIES >= (1 << (OUT_OF_RANGE_GROUP_ACTION_SIZE - 1)) + #error "Cannot store enum xkb_range_exceed_type in bitfield out_of_range_group_number" +#endif +#if XKB_REDIRECT_LAYOUT_INDEX_MASK >= (1 << OUT_OF_RANGE_GROUP_NUMBER_SIZE) + #error "Cannot store layout index in bitfield out_of_range_group_number" +#endif + struct xkb_key { xkb_keycode_t keycode; xkb_atom_t name; @@ -343,8 +362,8 @@ struct xkb_key { bool repeats; - enum xkb_range_exceed_type out_of_range_group_action; - xkb_layout_index_t out_of_range_group_number; + xkb_layout_index_t out_of_range_group_number:OUT_OF_RANGE_GROUP_NUMBER_SIZE; + enum xkb_range_exceed_type out_of_range_group_action:OUT_OF_RANGE_GROUP_ACTION_SIZE; xkb_layout_index_t num_groups; struct xkb_group *groups; @@ -392,6 +411,9 @@ struct xkb_keymap { /* Not all groups must have names. */ xkb_layout_index_t num_group_names; xkb_atom_t *group_names; + /* groups_wrap control */ + xkb_layout_index_t out_of_range_group_number:OUT_OF_RANGE_GROUP_NUMBER_SIZE; + enum xkb_range_exceed_type out_of_range_group_action:OUT_OF_RANGE_GROUP_ACTION_SIZE; struct xkb_led leds[XKB_MAX_LEDS]; unsigned int num_leds; diff --git a/src/messages-codes.h b/src/messages-codes.h index 3be18db02..19a9e929c 100644 --- a/src/messages-codes.h +++ b/src/messages-codes.h @@ -94,6 +94,8 @@ enum xkb_message_code { XKB_WARNING_UNKNOWN_CHAR_ESCAPE_SEQUENCE = 645, /** The target file of an include statement could not be processed */ XKB_ERROR_INVALID_INCLUDED_FILE = 661, + /** Multiple out-of-range layout flags were set, but only one is allowed. */ + XKB_ERROR_MULTIPLE_OUT_OF_RANGE_LAYOUT_FLAGS = 697, /** Warn if a key defines multiple groups at once */ XKB_WARNING_MULTIPLE_GROUPS_AT_ONCE = 700, /** A legacy X11 symbol field is not supported */ diff --git a/src/state.c b/src/state.c index d5a60eb57..1984a191e 100644 --- a/src/state.c +++ b/src/state.c @@ -173,9 +173,9 @@ XkbWrapGroupIntoRange(int32_t group, switch (out_of_range_group_action) { case RANGE_REDIRECT: - if (out_of_range_group_number >= num_groups) - return 0; - return out_of_range_group_number; + return (out_of_range_group_number >= num_groups) + ? 0 + : out_of_range_group_number; case RANGE_SATURATE: if (group < 0) @@ -815,12 +815,11 @@ xkb_state_update_derived(struct xkb_state *state) state->components.latched_mods | state->components.locked_mods); - /* TODO: Use groups_wrap control instead of always RANGE_WRAP. */ - /* Lock group must be adjusted, but not base nor latched groups */ wrapped = XkbWrapGroupIntoRange(state->components.locked_group, state->keymap->num_groups, - RANGE_WRAP, 0); + state->keymap->out_of_range_group_action, + state->keymap->out_of_range_group_number); state->components.locked_group = (wrapped == XKB_LAYOUT_INVALID ? 0 : wrapped); @@ -829,7 +828,9 @@ xkb_state_update_derived(struct xkb_state *state) state->components.latched_group + state->components.locked_group, state->keymap->num_groups, - RANGE_WRAP, 0); + state->keymap->out_of_range_group_action, + state->keymap->out_of_range_group_number); + state->components.group = (wrapped == XKB_LAYOUT_INVALID ? 0 : wrapped); diff --git a/src/x11/keymap.c b/src/x11/keymap.c index 72f663927..1f58a3bf6 100644 --- a/src/x11/keymap.c +++ b/src/x11/keymap.c @@ -1142,7 +1142,7 @@ xkb_x11_keymap_new_from_device(struct xkb_context *ctx, struct xkb_keymap *keymap; const enum xkb_keymap_format format = XKB_KEYMAP_FORMAT_TEXT_V1; - if (flags & ~(XKB_KEYMAP_COMPILE_NO_FLAGS)) { + if (flags & ~XKB_KEYMAP_FLAGS_ALL) { log_err_func(ctx, "unrecognized flags: %#x\n", flags); return NULL; } diff --git a/test/common.c b/test/common.c index 392aacd4e..8330d6e9d 100644 --- a/test/common.c +++ b/test/common.c @@ -401,9 +401,10 @@ test_compile_buffer(struct xkb_context *context, const char *buf, size_t len) } struct xkb_keymap * -test_compile_rules(struct xkb_context *context, const char *rules, - const char *model, const char *layout, - const char *variant, const char *options) +test_compile_rules_with_flags(struct xkb_context *context, const char *rules, + const char *model, const char *layout, + const char *variant, const char *options, + enum xkb_keymap_compile_flags flags) { struct xkb_keymap *keymap; struct xkb_rule_names rmlvo = { @@ -415,9 +416,9 @@ test_compile_rules(struct xkb_context *context, const char *rules, }; if (!rules && !model && !layout && !variant && !options) - keymap = xkb_keymap_new_from_names(context, NULL, 0); + keymap = xkb_keymap_new_from_names(context, NULL, flags); else - keymap = xkb_keymap_new_from_names(context, &rmlvo, 0); + keymap = xkb_keymap_new_from_names(context, &rmlvo, flags); if (!keymap) { fprintf(stderr, @@ -428,3 +429,12 @@ test_compile_rules(struct xkb_context *context, const char *rules, return keymap; } + +struct xkb_keymap * +test_compile_rules(struct xkb_context *context, const char *rules, + const char *model, const char *layout, + const char *variant, const char *options) +{ + return test_compile_rules_with_flags(context, rules, model, layout, + variant, options, XKB_KEYMAP_COMPILE_NO_FLAGS); +} diff --git a/test/keyseq.c b/test/keyseq.c index 17d133565..91fe2a389 100644 --- a/test/keyseq.c +++ b/test/keyseq.c @@ -667,6 +667,91 @@ main(void) KEY_H, BOTH, XKB_KEY_h, FINISH)); xkb_keymap_unref(keymap); + keymap = test_compile_rules_with_flags( + ctx, "evdev", "", "us,il,ru", "", + "grp:alt_shift_toggle_bidir,grp:menu_toggle", + XKB_KEYMAP_REDIRECT_OUT_OF_RANGE_LAYOUT | 1); + assert(keymap); + + /* Out-of-range group action: redirect to valid group */ + assert(test_key_seq(keymap, + KEY_H, BOTH, XKB_KEY_h, NEXT, + KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, + KEY_LEFTALT, BOTH, XKB_KEY_ISO_Prev_Group, NEXT, + KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT, + /* Negative group: redirect to second layout */ + KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, + KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, + KEY_H, BOTH, XKB_KEY_Cyrillic_er, NEXT, + KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, + /* Greater that last group: redirect to second layout */ + KEY_H, BOTH, XKB_KEY_hebrew_yod, FINISH)); + + xkb_keymap_unref(keymap); + keymap = test_compile_rules_with_flags( + ctx, "evdev", "", "us,il,ru", "", + "grp:alt_shift_toggle_bidir,grp:menu_toggle", + XKB_KEYMAP_REDIRECT_OUT_OF_RANGE_LAYOUT | 4); + assert(keymap); + + /* Out-of-range group action: redirect to invalid group */ + assert(test_key_seq(keymap, + KEY_H, BOTH, XKB_KEY_h, NEXT, + KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, + KEY_LEFTALT, BOTH, XKB_KEY_ISO_Prev_Group, NEXT, + KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT, + /* Negative group: invalid redirect, default to first layout */ + KEY_H, BOTH, XKB_KEY_h, NEXT, + KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, + KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, + KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, + KEY_H, BOTH, XKB_KEY_Cyrillic_er, NEXT, + KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, + /* Greater that last group: invalid redirect, default to first layout */ + KEY_H, BOTH, XKB_KEY_h, FINISH)); + + xkb_keymap_unref(keymap); + keymap = test_compile_rules_with_flags( + ctx, "evdev", "", "us,il,ru", "", + "grp:alt_shift_toggle_bidir,grp:menu_toggle", + XKB_KEYMAP_CLAMP_OUT_OF_RANGE_LAYOUT); + assert(keymap); + + /* Out-of-range group action: clamp */ + assert(test_key_seq(keymap, + KEY_H, BOTH, XKB_KEY_h, NEXT, + KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, + KEY_LEFTALT, BOTH, XKB_KEY_ISO_Prev_Group, NEXT, + KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT, + /* Negative group: redirect to first layout */ + KEY_H, BOTH, XKB_KEY_h, NEXT, + KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, + KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, + KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, + KEY_H, BOTH, XKB_KEY_Cyrillic_er, NEXT, + KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, + KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, + /* Greater that last group: redirect to last layout */ + KEY_H, BOTH, XKB_KEY_Cyrillic_er, FINISH)); + + xkb_keymap_unref(keymap); + keymap = test_compile_rules_with_flags( + ctx, "evdev", "", "us,il", "", "", + XKB_KEYMAP_REDIRECT_OUT_OF_RANGE_LAYOUT | + XKB_KEYMAP_CLAMP_OUT_OF_RANGE_LAYOUT); + /* Cannot mix out-of-range layout flags */ + assert(!keymap); + /* Cannot use redirect layout index without + * XKB_KEYMAP_REDIRECT_OUT_OF_RANGE_LAYOUT */ + keymap = test_compile_rules_with_flags( + ctx, "evdev", "", "", "", "", + XKB_KEYMAP_COMPILE_NO_FLAGS | 1); + assert(!keymap); + keymap = test_compile_rules_with_flags( + ctx, "evdev", "", "", "", "", + XKB_KEYMAP_CLAMP_OUT_OF_RANGE_LAYOUT | 1); + assert(!keymap); + keymap = test_compile_rules(ctx, "evdev", "", "us,il,ru", "", "grp:switch,grp:lswitch,grp:menu_toggle"); assert(keymap); diff --git a/test/test.h b/test/test.h index 8a6e04178..55b41edb4 100644 --- a/test/test.h +++ b/test/test.h @@ -102,6 +102,12 @@ test_compile_rules(struct xkb_context *context, const char *rules, const char *model, const char *layout, const char *variant, const char *options); +struct xkb_keymap * +test_compile_rules_with_flags(struct xkb_context *context, const char *rules, + const char *model, const char *layout, + const char *variant, const char *options, + enum xkb_keymap_compile_flags flags); + #ifdef _WIN32 #define setenv(varname, value, overwrite) _putenv_s((varname), (value)) diff --git a/tools/messages.c b/tools/messages.c index 8fafd158d..a21acf0c6 100644 --- a/tools/messages.c +++ b/tools/messages.c @@ -77,6 +77,7 @@ static const struct xkb_message_entry xkb_messages[] = { {XKB_ERROR_INVALID_REAL_MODIFIER, "Invalid real modifier"}, {XKB_WARNING_UNKNOWN_CHAR_ESCAPE_SEQUENCE, "Unknown char escape sequence"}, {XKB_ERROR_INVALID_INCLUDED_FILE, "Invalid included file"}, + {XKB_ERROR_MULTIPLE_OUT_OF_RANGE_LAYOUT_FLAGS, "Multiple out of range layout flags"}, {XKB_WARNING_MULTIPLE_GROUPS_AT_ONCE, "Multiple groups at once"}, {XKB_WARNING_UNSUPPORTED_SYMBOLS_FIELD, "Unsupported symbols field"}, {XKB_ERROR_INVALID_SYNTAX, "Invalid syntax"},