.gitignore | 2 LICENSE | 2 Makefile.am | 36 ++ NEWS | 25 + PACKAGING | 5 README.md | 17 + bench/bench.c | 1 bench/bench.h | 2 bench/compose.c | 6 configure.ac | 23 + doc/compat.md | 4 doc/quick-guide.md | 5 src/state.c | 124 +++++-- src/utils.h | 13 src/xkbcomp/keymap-dump.c | 2 test/.gitignore | 1 test/common.c | 29 + test/interactive-evdev.c | 21 - test/interactive-wayland.c | 693 ++++++++++++++++++++++++++++++++++++++++++++ test/interactive-x11.c | 7 test/state.c | 34 ++ test/symbols-leak-test.bash | 2 test/test.h | 9 xkbcommon.map | 6 xkbcommon/xkbcommon.h | 99 +++++- 25 files changed, 1088 insertions(+), 80 deletions(-)
New commits: commit d596f6e3ff2d1fde0491907fa9354e5cdf154ed1 Author: Ran Benita <ran...@gmail.com> Date: Fri Nov 11 20:02:41 2016 +0200 Bump version to 0.7.0 Signed-off-by: Ran Benita <ran...@gmail.com> diff --git a/configure.ac b/configure.ac index da201e1..fdab4ab 100644 --- a/configure.ac +++ b/configure.ac @@ -22,7 +22,7 @@ dnl Process this file with autoconf to create configure. # Initialize Autoconf AC_PREREQ([2.62]) -AC_INIT([libxkbcommon], [0.6.1], +AC_INIT([libxkbcommon], [0.7.0], [https://bugs.freedesktop.org/enter_bug.cgi?product=libxkbcommon], [libxkbcommon], [http://xkbcommon.org]) AC_CONFIG_SRCDIR([Makefile.am]) commit e7f73940b568b1e71df424e349402a02222f1954 Author: Ran Benita <ran...@gmail.com> Date: Fri Nov 11 20:00:26 2016 +0200 Update NEWS Signed-off-by: Ran Benita <ran...@gmail.com> diff --git a/NEWS b/NEWS index 94506e5..27d5c29 100644 --- a/NEWS +++ b/NEWS @@ -1,7 +1,30 @@ +libxkbcommon 0.7.0 - 2016-11-11 +================== + +- Added support for different "modes" of calculating consumed modifiers. + The existing mode, based on the XKB standard, has proven to be + unintuitive in various shortcut implementations. + + A new mode, based on the calculation used by the GTK toolkit, is added. + This mode is less eager to declare a modifier as consumed. + +- Added a new interactive demo program using the Wayland protocol. + See the PACKAGING file for the new (optional) test dependencies. + +- Fixed a compilation error on GNU Hurd. + +- New API: + enum xkb_consumed_mode + XKB_CONSUMED_MODE_XKB + XKB_CONSUMED_MODE_GTK + xkb_state_key_get_consumed_mods2 + xkb_state_mod_index_is_consumed2 + + libxkbcommon 0.6.1 - 2016-04-08 ================== -- Add LICENSE to distributed files in tarball releases. +- Added LICENSE to distributed files in tarball releases. - Minor typo fix in xkb_keymap_get_as_string() documentation. commit babc9e0c30918d3e12dea9e2e47b6c1c9c6cc1fb Author: Ran Benita <ran...@gmail.com> Date: Sat Feb 27 22:31:16 2016 +0200 state: add GTK consumed modifiers mode This is more or less what is implemented here: https://git.gnome.org/browse/gtk+/tree/gdk/x11/gdkkeys-x11.c?h=3.19.10#n1131 The implementation here is more technically correct but should provide the same results. Try it out with ./test/interactive-evdev -g (modifiers prefixed with "-" are consumed). https://bugzilla.gnome.org/show_bug.cgi?id=754110 https://github.com/xkbcommon/libxkbcommon/issues/17 Signed-off-by: Ran Benita <ran...@gmail.com> diff --git a/src/state.c b/src/state.c index 6611d33..039115a 100644 --- a/src/state.c +++ b/src/state.c @@ -1340,6 +1340,30 @@ key_get_consumed(struct xkb_state *state, const struct xkb_key *key, case XKB_CONSUMED_MODE_XKB: consumed = type->mods.mask; break; + + case XKB_CONSUMED_MODE_GTK: { + const struct xkb_key_type_entry *no_mods_entry; + xkb_level_index_t no_mods_leveli; + const struct xkb_level *no_mods_level, *level; + + no_mods_entry = get_entry_for_mods(type, 0); + no_mods_leveli = no_mods_entry ? no_mods_entry->level : 0; + no_mods_level = &key->groups[group].levels[no_mods_leveli]; + + for (unsigned i = 0; i < type->num_entries; i++) { + const struct xkb_key_type_entry *entry = &type->entries[i]; + if (!entry_is_active(entry)) + continue; + + level = &key->groups[group].levels[entry->level]; + if (XkbLevelsSameSyms(level, no_mods_level)) + continue; + + if (entry == matching_entry || popcount(entry->mods.mask) == 1) + consumed |= entry->mods.mask & ~entry->preserve.mask; + } + break; + } } return consumed & ~preserve; @@ -1386,6 +1410,7 @@ xkb_state_key_get_consumed_mods2(struct xkb_state *state, xkb_keycode_t kc, switch (mode) { case XKB_CONSUMED_MODE_XKB: + case XKB_CONSUMED_MODE_GTK: break; default: log_err_func(state->keymap->ctx, diff --git a/test/interactive-evdev.c b/test/interactive-evdev.c index 0ba3eab..4f12e67 100644 --- a/test/interactive-evdev.c +++ b/test/interactive-evdev.c @@ -48,6 +48,7 @@ static bool terminate; static int evdev_offset = 8; static bool report_state_changes; static bool with_compose; +static enum xkb_consumed_mode consumed_mode = XKB_CONSUMED_MODE_XKB; #define NLONGS(n) (((n) + LONG_BIT - 1) / LONG_BIT) @@ -261,7 +262,7 @@ process_event(struct keyboard *kbd, uint16_t type, uint16_t code, int32_t value) if (value != KEY_STATE_RELEASE) test_print_keycode_state(kbd->state, kbd->compose_state, keycode, - XKB_CONSUMED_MODE_XKB); + consumed_mode); if (with_compose) { status = xkb_compose_state_get_status(kbd->compose_state); @@ -382,7 +383,7 @@ main(int argc, char *argv[]) setlocale(LC_ALL, ""); - while ((opt = getopt(argc, argv, "r:m:l:v:o:k:n:cd")) != -1) { + while ((opt = getopt(argc, argv, "r:m:l:v:o:k:n:cdg")) != -1) { switch (opt) { case 'r': rules = optarg; @@ -416,6 +417,9 @@ main(int argc, char *argv[]) case 'd': with_compose = true; break; + case 'g': + consumed_mode = XKB_CONSUMED_MODE_GTK; + break; case '?': fprintf(stderr, " Usage: %s [-r <rules>] [-m <model>] " "[-l <layout>] [-v <variant>] [-o <options>]\n", @@ -424,7 +428,8 @@ main(int argc, char *argv[]) argv[0]); fprintf(stderr, "For both: -n <evdev keycode offset>\n" " -c (to report changes to the state)\n" - " -d (to enable compose)\n"); + " -d (to enable compose)\n" + " -g (to use GTK consumed mode)\n"); exit(2); } } diff --git a/test/state.c b/test/state.c index d774496..1f2c75d 100644 --- a/test/state.c +++ b/test/state.c @@ -460,6 +460,41 @@ test_consume(struct xkb_keymap *keymap) assert(mask == ((1U << shift) | (1U << alt) | (1U << ctrl) | (1U << mod5))); xkb_state_unref(state); + + /* Test XKB_CONSUMED_MODE_GTK, CTRL+ALT */ + state = xkb_state_new(keymap); + assert(state); + + mask = xkb_state_key_get_consumed_mods2(state, KEY_F1 + EVDEV_OFFSET, + XKB_CONSUMED_MODE_GTK); + assert(mask == 0); + + xkb_state_update_key(state, KEY_LEFTCTRL + EVDEV_OFFSET, XKB_KEY_DOWN); + mask = xkb_state_key_get_consumed_mods2(state, KEY_F1 + EVDEV_OFFSET, + XKB_CONSUMED_MODE_GTK); + assert(mask == 0); + + xkb_state_update_key(state, KEY_LEFTALT + EVDEV_OFFSET, XKB_KEY_DOWN); + mask = xkb_state_key_get_consumed_mods2(state, KEY_F1 + EVDEV_OFFSET, + XKB_CONSUMED_MODE_GTK); + assert(mask == ((1U << alt) | (1U << ctrl))); + + xkb_state_unref(state); + + /* Test XKB_CONSUMED_MODE_GTK, Simple Shift */ + state = xkb_state_new(keymap); + assert(state); + + mask = xkb_state_key_get_consumed_mods2(state, KEY_A + EVDEV_OFFSET, + XKB_CONSUMED_MODE_GTK); + assert(mask == ((1U << shift) | (1U << caps))); + + xkb_state_update_key(state, KEY_LEFTALT + EVDEV_OFFSET, XKB_KEY_DOWN); + mask = xkb_state_key_get_consumed_mods2(state, KEY_A + EVDEV_OFFSET, + XKB_CONSUMED_MODE_GTK); + assert(mask == ((1U << shift) | (1U << caps))); + + xkb_state_unref(state); } static void diff --git a/xkbcommon/xkbcommon.h b/xkbcommon/xkbcommon.h index 30c0508..4902dc4 100644 --- a/xkbcommon/xkbcommon.h +++ b/xkbcommon/xkbcommon.h @@ -1687,7 +1687,22 @@ enum xkb_consumed_mode { * even though they are not active, since if they *were* active they would * have affected key translation. */ - XKB_CONSUMED_MODE_XKB + XKB_CONSUMED_MODE_XKB, + /** + * This is the mode used by the GTK+ toolkit. + * + * The mode consists of the following two heuristics: + * + * - The active set of modifiers, excluding modifiers which do not affect + * the key (as described above), are considered consumed, if they result + * in different keysyms being produced than when no modifiers are active. + * + * - Additionally, a single modifier is considered consumed if, were it the + * only active modifier affecting the key (as described above), it would + * result in different keysyms being produced than when no modifiers are + * active. + */ + XKB_CONSUMED_MODE_GTK }; /** commit a0a41332cc3811370b4f9d46528b7a590846e289 Author: Ran Benita <ran...@gmail.com> Date: Sat Feb 27 19:06:14 2016 +0200 state: allow different modes for calculating consumed modifiers The current functions dealing with consumed modifiers use the traditional XKB definition of consumed modifiers (see description in the added documentation). However, for several users of the library (e.g. GTK) this definition is unsuitable or too eager. This is exacerbated by some less-than-ideal xkeyboard-config type definitions (CTRL+ALT seems to cause most grief...). So, because we - want to enable alternative interpretations, but - don't want to expose too much internal details, and - want to keep things simple for all library users, we add a high-level "mode" parameter which selects the desired interpretation. New ones can be added as long as they make some sense. All of the old consumed-modifiers functions keep using the traditional ("XKB") mode. I mark xkb_state_mod_mask_remove_consumed() and as deprecated without adding a *2 variant because I don't it is very useful (or used) in practice. Alternative modes are added in subsequent commits (this commit only adds a mode for the existing behavior). https://github.com/xkbcommon/libxkbcommon/issues/17 Signed-off-by: Ran Benita <ran...@gmail.com> diff --git a/src/state.c b/src/state.c index 8845a4e..6611d33 100644 --- a/src/state.c +++ b/src/state.c @@ -1311,13 +1311,20 @@ xkb_state_led_name_is_active(struct xkb_state *state, const char *name) return xkb_state_led_index_is_active(state, idx); } +/** + * See: + * - XkbTranslateKeyCode(3), mod_rtrn return value, from libX11. + * - MyEnhancedXkbTranslateKeyCode(), a modification of the above, from GTK+. + */ static xkb_mod_mask_t -key_get_consumed(struct xkb_state *state, const struct xkb_key *key) +key_get_consumed(struct xkb_state *state, const struct xkb_key *key, + enum xkb_consumed_mode mode) { const struct xkb_key_type *type; - const struct xkb_key_type_entry *entry; - xkb_mod_mask_t preserve; + const struct xkb_key_type_entry *matching_entry; + xkb_mod_mask_t preserve = 0; xkb_layout_index_t group; + xkb_mod_mask_t consumed = 0; group = xkb_state_key_get_layout(state, key->keycode); if (group == XKB_LAYOUT_INVALID) @@ -1325,47 +1332,40 @@ key_get_consumed(struct xkb_state *state, const struct xkb_key *key) type = key->groups[group].type; - entry = get_entry_for_key_state(state, key, group); - if (entry) - preserve = entry->preserve.mask; - else - preserve = 0; + matching_entry = get_entry_for_key_state(state, key, group); + if (matching_entry) + preserve = matching_entry->preserve.mask; - return type->mods.mask & ~preserve; + switch (mode) { + case XKB_CONSUMED_MODE_XKB: + consumed = type->mods.mask; + break; + } + + return consumed & ~preserve; } -/** - * Tests to see if a modifier is used up by our translation of a - * keycode to keysyms, taking note of the current modifier state and - * the appropriate key type's preserve information, if any. This allows - * the user to mask out the modifier in later processing of the - * modifiers, e.g. when implementing hot keys or accelerators. - * - * See also, for example: - * - XkbTranslateKeyCode(3), mod_rtrn return value, from libX11. - * - gdk_keymap_translate_keyboard_state, consumed_modifiers return value, - * from gtk+. - */ XKB_EXPORT int -xkb_state_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t kc, - xkb_mod_index_t idx) +xkb_state_mod_index_is_consumed2(struct xkb_state *state, xkb_keycode_t kc, + xkb_mod_index_t idx, + enum xkb_consumed_mode mode) { const struct xkb_key *key = XkbKey(state->keymap, kc); if (!key || idx >= xkb_keymap_num_mods(state->keymap)) return -1; - return !!((1u << idx) & key_get_consumed(state, key)); + return !!((1u << idx) & key_get_consumed(state, key, mode)); +} + +XKB_EXPORT int +xkb_state_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t kc, + xkb_mod_index_t idx) +{ + return xkb_state_mod_index_is_consumed2(state, kc, idx, + XKB_CONSUMED_MODE_XKB); } -/** - * Calculates which modifiers should be consumed during key processing, - * and returns the mask with all these modifiers removed. e.g. if - * given a state of Alt and Shift active for a two-level alphabetic - * key containing plus and equal on the first and second level - * respectively, will return a mask of only Alt, as Shift has been - * consumed by the type handling. - */ XKB_EXPORT xkb_mod_mask_t xkb_state_mod_mask_remove_consumed(struct xkb_state *state, xkb_keycode_t kc, xkb_mod_mask_t mask) @@ -1375,16 +1375,33 @@ xkb_state_mod_mask_remove_consumed(struct xkb_state *state, xkb_keycode_t kc, if (!key) return 0; - return mask & ~key_get_consumed(state, key); + return mask & ~key_get_consumed(state, key, XKB_CONSUMED_MODE_XKB); } XKB_EXPORT xkb_mod_mask_t -xkb_state_key_get_consumed_mods(struct xkb_state *state, xkb_keycode_t kc) +xkb_state_key_get_consumed_mods2(struct xkb_state *state, xkb_keycode_t kc, + enum xkb_consumed_mode mode) { - const struct xkb_key *key = XkbKey(state->keymap, kc); + const struct xkb_key *key; + switch (mode) { + case XKB_CONSUMED_MODE_XKB: + break; + default: + log_err_func(state->keymap->ctx, + "unrecognized consumed modifiers mode: %d\n", mode); + return 0; + } + + key = XkbKey(state->keymap, kc); if (!key) return 0; - return key_get_consumed(state, key); + return key_get_consumed(state, key, mode); +} + +XKB_EXPORT xkb_mod_mask_t +xkb_state_key_get_consumed_mods(struct xkb_state *state, xkb_keycode_t kc) +{ + return xkb_state_key_get_consumed_mods2(state, kc, XKB_CONSUMED_MODE_XKB); } diff --git a/test/common.c b/test/common.c index 2dd10a0..1bb6d35 100644 --- a/test/common.c +++ b/test/common.c @@ -350,7 +350,8 @@ test_compile_rules(struct xkb_context *context, const char *rules, void test_print_keycode_state(struct xkb_state *state, struct xkb_compose_state *compose_state, - xkb_keycode_t keycode) + xkb_keycode_t keycode, + enum xkb_consumed_mode consumed_mode) { struct xkb_keymap *keymap; @@ -410,7 +411,8 @@ test_print_keycode_state(struct xkb_state *state, if (xkb_state_mod_index_is_active(state, mod, XKB_STATE_MODS_EFFECTIVE) <= 0) continue; - if (xkb_state_mod_index_is_consumed(state, keycode, mod)) + if (xkb_state_mod_index_is_consumed2(state, keycode, mod, + consumed_mode)) printf("-%s ", xkb_keymap_mod_get_name(keymap, mod)); else printf("%s ", xkb_keymap_mod_get_name(keymap, mod)); diff --git a/test/interactive-evdev.c b/test/interactive-evdev.c index 7853e59..0ba3eab 100644 --- a/test/interactive-evdev.c +++ b/test/interactive-evdev.c @@ -260,7 +260,8 @@ process_event(struct keyboard *kbd, uint16_t type, uint16_t code, int32_t value) } if (value != KEY_STATE_RELEASE) - test_print_keycode_state(kbd->state, kbd->compose_state, keycode); + test_print_keycode_state(kbd->state, kbd->compose_state, keycode, + XKB_CONSUMED_MODE_XKB); if (with_compose) { status = xkb_compose_state_get_status(kbd->compose_state); diff --git a/test/interactive-wayland.c b/test/interactive-wayland.c index 6769b12..94c60c8 100644 --- a/test/interactive-wayland.c +++ b/test/interactive-wayland.c @@ -360,7 +360,8 @@ kbd_key(void *data, struct wl_keyboard *wl_kbd, uint32_t serial, uint32_t time, return; printf("%s: ", seat->name_str); - test_print_keycode_state(seat->state, NULL, key + 8); + test_print_keycode_state(seat->state, NULL, key + 8, + XKB_CONSUMED_MODE_XKB); /* Exit on ESC. */ if (xkb_state_key_get_one_sym(seat->state, key + 8) == XKB_KEY_Escape) diff --git a/test/interactive-x11.c b/test/interactive-x11.c index 904136f..bb641dd 100644 --- a/test/interactive-x11.c +++ b/test/interactive-x11.c @@ -236,7 +236,8 @@ process_event(xcb_generic_event_t *gevent, struct keyboard *kbd) xcb_key_press_event_t *event = (xcb_key_press_event_t *) gevent; xkb_keycode_t keycode = event->detail; - test_print_keycode_state(kbd->state, NULL, keycode); + test_print_keycode_state(kbd->state, NULL, keycode, + XKB_CONSUMED_MODE_XKB); /* Exit on ESC. */ if (keycode == 9) diff --git a/test/test.h b/test/test.h index 440c7ea..297c062 100644 --- a/test/test.h +++ b/test/test.h @@ -84,7 +84,8 @@ test_compile_rules(struct xkb_context *context, const char *rules, void test_print_keycode_state(struct xkb_state *state, struct xkb_compose_state *compose_state, - xkb_keycode_t keycode); + xkb_keycode_t keycode, + enum xkb_consumed_mode consumed_mode); void test_print_state_changes(enum xkb_state_component changed); diff --git a/xkbcommon.map b/xkbcommon.map index ac01fcb..cc468c6 100644 --- a/xkbcommon.map +++ b/xkbcommon.map @@ -91,3 +91,9 @@ global: xkb_keymap_key_get_name; xkb_keymap_key_by_name; } V_0.5.0; + +V_0.7.0 { +global: + xkb_state_key_get_consumed_mods2; + xkb_state_mod_index_is_consumed2; +} V_0.6.0; diff --git a/xkbcommon/xkbcommon.h b/xkbcommon/xkbcommon.h index 6f96e4f..30c0508 100644 --- a/xkbcommon/xkbcommon.h +++ b/xkbcommon/xkbcommon.h @@ -1649,7 +1649,7 @@ xkb_state_mod_indices_are_active(struct xkb_state *state, * Effectively, this means that consumed modifiers (Shift in this example) * are masked out as well, before doing the comparison. * - * In summary, this is how the matching would be performed: + * In summary, this is approximately how the matching would be performed: * @code * (keysym == shortcut_keysym) && * ((state_mods & ~consumed_mods & significant_mods) == shortcut_mods) @@ -1666,15 +1666,83 @@ xkb_state_mod_indices_are_active(struct xkb_state *state, */ /** + * Consumed modifiers mode. + * + * There are several possible methods for deciding which modifiers are + * consumed and which are not, each applicable for different systems or + * situations. The mode selects the method to use. + * + * Keep in mind that in all methods, the keymap may decide to "preserve" + * a modifier, meaning it is not reported as consumed even if it would + * have otherwise. + */ +enum xkb_consumed_mode { + /** + * This is the mode defined in the XKB specification and used by libX11. + * + * A modifier is consumed iff it *may affect* key translation. + * + * For example, if `Control+Alt+<Backspace>` produces some assigned keysym, + * then when pressing just `<Backspace>`, `Control` and `Alt` are consumed, + * even though they are not active, since if they *were* active they would + * have affected key translation. + */ + XKB_CONSUMED_MODE_XKB +}; + +/** + * Get the mask of modifiers consumed by translating a given key. + * + * @param state The keyboard state. + * @param key The keycode of the key. + * @param mode The consumed modifiers mode to use; see enum description. + * + * @returns a mask of the consumed modifiers. + * + * @memberof xkb_state + * @since 0.7.0 + */ +xkb_mod_mask_t +xkb_state_key_get_consumed_mods2(struct xkb_state *state, xkb_keycode_t key, + enum xkb_consumed_mode mode); + +/** + * Same as xkb_state_key_get_consumed_mods2() with mode XKB_CONSUMED_MODE_XKB. + * + * @memberof xkb_state + * @since 0.4.1 + */ +xkb_mod_mask_t +xkb_state_key_get_consumed_mods(struct xkb_state *state, xkb_keycode_t key); + +/** * Test whether a modifier is consumed by keyboard state translation for * a key. * + * @param state The keyboard state. + * @param key The keycode of the key. + * @param idx The index of the modifier to check. + * @param mode The consumed modifiers mode to use; see enum description. + * * @returns 1 if the modifier is consumed, 0 if it is not. If the modifier * index is not valid in the keymap, returns -1. * * @sa xkb_state_mod_mask_remove_consumed() * @sa xkb_state_key_get_consumed_mods() * @memberof xkb_state + * @since 0.7.0 + */ +int +xkb_state_mod_index_is_consumed2(struct xkb_state *state, + xkb_keycode_t key, + xkb_mod_index_t idx, + enum xkb_consumed_mode mode); + +/** + * Same as xkb_state_mod_index_is_consumed2() with mode XKB_CONSUMED_MOD_XKB. + * + * @memberof xkb_state + * @since 0.4.1 */ int xkb_state_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t key, @@ -1683,6 +1751,8 @@ xkb_state_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t key, /** * Remove consumed modifiers from a modifier mask for a key. * + * @deprecated Use xkb_state_key_get_consumed_mods2() instead. + * * Takes the given modifier mask, and removes all modifiers which are * consumed for that particular key (as in xkb_state_mod_index_is_consumed()). * @@ -1694,18 +1764,6 @@ xkb_state_mod_mask_remove_consumed(struct xkb_state *state, xkb_keycode_t key, xkb_mod_mask_t mask); /** - * Get the mask of modifiers consumed by translating a given key. - * - * @returns a mask of the consumed modifiers. - * - * @sa xkb_state_mod_index_is_consumed() - * @memberof xkb_state - * @since 0.4.1 - */ -xkb_mod_mask_t -xkb_state_key_get_consumed_mods(struct xkb_state *state, xkb_keycode_t key); - -/** * Test whether a layout is active in a given keyboard state by name. * * @returns 1 if the layout is active, 0 if it is not. If no layout with commit 90611719572fbac04ddf3329f5683feb3b71e681 Author: Ran Benita <ran...@gmail.com> Date: Sat Feb 27 22:29:57 2016 +0200 utils: add popcount function Signed-off-by: Ran Benita <ran...@gmail.com> diff --git a/configure.ac b/configure.ac index 3f8de97..da201e1 100644 --- a/configure.ac +++ b/configure.ac @@ -83,6 +83,7 @@ AS_IF([test "x$ac_cv_func_secure_getenv" = xno -a \ ]) AX_GCC_BUILTIN(__builtin_expect) +AX_GCC_BUILTIN(__builtin_popcount) # Some tests use Linux-specific headers AC_CHECK_HEADER([linux/input.h]) diff --git a/src/utils.h b/src/utils.h index 4b7e81c..11ef735 100644 --- a/src/utils.h +++ b/src/utils.h @@ -178,6 +178,19 @@ msb_pos(uint32_t mask) return pos; } +static inline int +popcount(uint32_t x) +{ + int count; +#if defined(HAVE___BUILTIN_POPCOUNT) + count = __builtin_popcount(x); +#else + for (count = 0; x; count++) + x &= x - 1; +#endif + return count; +} + bool map_file(FILE *file, char **string_out, size_t *size_out); commit 914c060a1dacb5b42b4bb9ded036c5c6951d842a Author: Ran Benita <ran...@gmail.com> Date: Sat Oct 22 20:13:11 2016 +0300 test/state: move wrongly-placed assert Signed-off-by: Ran Benita <ran...@gmail.com> diff --git a/test/state.c b/test/state.c index 8ae718c..d774496 100644 --- a/test/state.c +++ b/test/state.c @@ -445,6 +445,7 @@ test_consume(struct xkb_keymap *keymap) /* More complicated - CTRL+ALT */ state = xkb_state_new(keymap); + assert(state); mask = xkb_state_key_get_consumed_mods(state, KEY_F1 + EVDEV_OFFSET); assert(mask == ((1U << shift) | (1U << alt) | (1U << ctrl) | (1U << mod5))); @@ -458,8 +459,6 @@ test_consume(struct xkb_keymap *keymap) mask = xkb_state_key_get_consumed_mods(state, KEY_F1 + EVDEV_OFFSET); assert(mask == ((1U << shift) | (1U << alt) | (1U << ctrl) | (1U << mod5))); - assert(state); - xkb_state_unref(state); } commit fe81dcbd2f9a375b46f4e1b8cc1d1045bd112cf6 Author: Ran Benita <ran...@gmail.com> Date: Mon Sep 19 10:09:12 2016 +0300 bench: fix compilation on hurd Patch by Samuel Thibault. https://github.com/xkbcommon/libxkbcommon/issues/39 Signed-off-by: Ran Benita <ran...@gmail.com> diff --git a/bench/bench.c b/bench/bench.c index 37e41f5..6aa43d9 100644 --- a/bench/bench.c +++ b/bench/bench.c @@ -35,6 +35,7 @@ #include <assert.h> #include <stdlib.h> +#include <stdint.h> #include <string.h> #include <stdio.h> diff --git a/bench/bench.h b/bench/bench.h index 5c1769e..adc15bb 100644 --- a/bench/bench.h +++ b/bench/bench.h @@ -25,6 +25,8 @@ #ifndef LIBXKBCOMMON_BENCH_H #define LIBXKBCOMMON_BENCH_H +#include <stdint.h> + struct bench_time { long seconds; long milliseconds; commit 853b7502f4c8e90480f58b3909fbd008587a1ba6 Author: Ran Benita <ran...@gmail.com> Date: Fri Sep 16 09:36:27 2016 +0300 bench/compose: tabs -> spaces Signed-off-by: Ran Benita <ran...@gmail.com> diff --git a/bench/compose.c b/bench/compose.c index 04873a7..e2bf3e0 100644 --- a/bench/compose.c +++ b/bench/compose.c @@ -46,10 +46,10 @@ main(void) path = test_get_path("compose/en_US.UTF-8/Compose"); file = fopen(path, "r"); if (file == NULL) { - perror(path); - free(path); - xkb_context_unref(ctx); - return -1; + perror(path); + free(path); + xkb_context_unref(ctx); + return -1; } xkb_context_set_log_level(ctx, XKB_LOG_LEVEL_CRITICAL); commit af2c83b6642591cf36d4002decef6757ec90b3e2 Author: Bryce Harrington <br...@osg.samsung.com> Date: Thu Sep 15 14:31:55 2016 -0700 README: Add basic build directions In particular, highlight the use of configure flags to control locating X11 keyboard stuff when building for Wayland. Of particular note, if the locale root is not specified, then xkbcommon will look for them under $prefix (i.e. /usr/local/share/X11/locale). But unless the user has specifically installed them there, it is better to look in the standard system location, /usr/share/X11/locale. Otherwise, xkbcommon will error when it can't find them, e.g.: xkbcommon: ERROR: ~/.XCompose:4:9: failed to expand %L to the locale Compose file xkbcommon: ERROR: ~/.XCompose:4:12: unterminated string literal Signed-off-by: Bryce Harrington <br...@osg.samsung.com> Signed-off-by: Ran Benita <ran...@gmail.com> diff --git a/README.md b/README.md index 706822a..04a5df0 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,21 @@ and dead keys. See [Quick Guide](doc/quick-guide.md). +## Building + +libxkbcommon is built the typical autoconf way: + + ./autogen.sh + make + +To build for use with Wayland, you can disable X11 support while still +using the X11 keyboard configuration resource files thusly: + + ./autogen.sh --disable-x11 \ + --with-xkb-config-root=/usr/share/X11/xkb \ + --with-x-locale-root=/usr/share/X11/locale + make + ## API While libxkbcommon's API is somewhat derived from the classic XKB API as found commit e92e0b88c6e3f7e6005d208e95f5dff760d7a3c4 Author: Bryce Harrington <br...@osg.samsung.com> Date: Thu Sep 15 14:31:54 2016 -0700 README: Bug *reports* are welcome Signed-off-by: Bryce Harrington <br...@osg.samsung.com> Reviewed-by: Yong Bakos <yba...@humanoriented.com> Signed-off-by: Ran Benita <ran...@gmail.com> diff --git a/README.md b/README.md index 867b532..706822a 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ Patches are always welcome, and may be sent to either <xorg-de...@lists.x.org> or <wayland-de...@lists.freedesktop.org> or through github. -Bugs are also welcome, and may be reported either at +Bug reports are also welcome, and may be filed either at Bugzilla https://bugs.freedesktop.org/describecomponents.cgi?product=libxkbcommon or Github https://github.com/xkbcommon/libxkbcommon/issues commit ea9a5bcfd7cd20a2ecce4f92915fd537a0a84d90 Author: Bryce Harrington <br...@bryceharrington.org> Date: Thu Sep 15 14:12:38 2016 -0700 bench: Check for errors opening Compose file Otherwise it can segfault e.g. running ./compose inside the bench directory. Signed-off-by: Bryce Harrington <br...@bryceharrington.org> Signed-off-by: Ran Benita <ran...@gmail.com> diff --git a/bench/compose.c b/bench/compose.c index 267b757..04873a7 100644 --- a/bench/compose.c +++ b/bench/compose.c @@ -45,6 +45,12 @@ main(void) path = test_get_path("compose/en_US.UTF-8/Compose"); file = fopen(path, "r"); + if (file == NULL) { + perror(path); + free(path); + xkb_context_unref(ctx); + return -1; + } xkb_context_set_log_level(ctx, XKB_LOG_LEVEL_CRITICAL); xkb_context_set_log_verbosity(ctx, 0); commit 599fd9ba39f6343644d621bd02a23b2656e91b51 Author: Ran Benita <ran...@gmail.com> Date: Thu Sep 1 21:17:43 2016 +0300 doc/compat: (! MODIFIER) syntax is parsed but ignored Signed-off-by: Ran Benita <ran...@gmail.com> diff --git a/doc/compat.md b/doc/compat.md index c378133..d863787 100644 --- a/doc/compat.md +++ b/doc/compat.md @@ -51,5 +51,6 @@ Relative to the standard implementation in libX11 (described in the Compose(5) man-page), some features are not supported: - the (! MODIFIER) syntax + + parsed correctly but ignored. - using modifier keysyms in Compose sequences - several interactions with Braille keysyms commit c29afcc346f903efaa2ecac0c121244373d59eea Author: Ran Benita <ran...@gmail.com> Date: Thu Sep 1 21:13:49 2016 +0300 doc/compat.md: xkbcomp ignores multiple-keysyms these days https://cgit.freedesktop.org/xorg/app/xkbcomp/commit/?id=e119cbec7e750ffc4d4bd08b577db2c697035a30 Signed-off-by: Ran Benita <ran...@gmail.com> diff --git a/doc/compat.md b/doc/compat.md index 14c57c5..c378133 100644 --- a/doc/compat.md +++ b/doc/compat.md @@ -42,8 +42,7 @@ Notable additions: - extended number of modifiers (planned) - extended number of groups (planned) - multiple keysyms per level - + this requires incompatible dataset changes, such that X11 would - not be able to parse these + + such levels are ignored by x11/xkbcomp. - key names (e.g. `<AE11>`) can be longer than 4 characters. ## Compose support commit d58fc90a2917e482470e74a662373f85ccb23f31 Author: Bryce Harrington <br...@osg.samsung.com> Date: Wed Jun 15 17:36:18 2016 -0700 doc: Also mention the wayland test client in the quick guide Signed-off-by: Bryce Harrington <br...@osg.samsung.com> diff --git a/doc/quick-guide.md b/doc/quick-guide.md index 6e04ba5..9d66475 100644 --- a/doc/quick-guide.md +++ b/doc/quick-guide.md @@ -20,6 +20,8 @@ can find complete and more complex examples in the source directory: 2. test/interactive-x11.c contains an interactive X11 client. +3. test/interactive-wayland.c contains an interactive Wayland client. + Also, the library contains many more functions for examining and using the library context, the keymap and the keyboard state. See the hyper-linked reference documentation or go through the header files in commit 094c8dc59bd3a7b6e4ebd80c07ab8fdbc8eaf749 Author: Bryce Harrington <br...@osg.samsung.com> Date: Wed Jun 15 17:36:17 2016 -0700 doc: Declare keymap for wayland example keymap was defined in the X11 example, but also define it in the wayland example just to make it a bit more standalone Signed-off-by: Bryce Harrington <br...@osg.samsung.com> diff --git a/doc/quick-guide.md b/doc/quick-guide.md index a576070..6e04ba5 100644 --- a/doc/quick-guide.md +++ b/doc/quick-guide.md @@ -74,6 +74,7 @@ with a keymap. In this case, we can create the keymap object like this: ~~~{.c} /* From the wl_keyboard::keymap event. */