This adds single-symbol compose support using libxkbcommon's compose functionality. E.g., assuming you have the right alt key defined as your compose key, typing <RAlt>+i+' will produce í, and <RAlt>+y+= will produce ¥. This makes compose key work for weston-editor, weston-terminal, weston-eventdemo, and any other clients that use Weston's window.* routines for accepting and managing keyboard input.
Compose sequences are loaded from the system's standard tables. As well, libxkbcommon will transparently load custom sequences from the user's ~/.XCompose file. Note that due to limitations in Weston's key handler interface, only compose sequences resulting in single symbols are supported. While libxkbcommon supports multi-symbol compose strings, support for passing text buffers to Weston clients is left as future work. This largely obviates the need for the weston-simple-im input method client, which had provided a very limited compose functionality that was only available in clients implementing the zwp_input_method protocol, and with no mechanism to load system or user-specified compose keys. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=53648 Signed-off-by: Bryce Harrington <[email protected]> --- clients/window.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/clients/window.c b/clients/window.c index 216ef96..1bb0b30 100644 --- a/clients/window.c +++ b/clients/window.c @@ -63,6 +63,7 @@ typedef void *EGLContext; #endif /* no HAVE_CAIRO_EGL */ #include <xkbcommon/xkbcommon.h> +#include <xkbcommon/xkbcommon-compose.h> #include <wayland-cursor.h> #include <linux/input.h> @@ -372,6 +373,8 @@ struct input { struct { struct xkb_keymap *keymap; struct xkb_state *state; + struct xkb_compose_table *compose_table; + struct xkb_compose_state *compose_state; xkb_mod_mask_t control_mask; xkb_mod_mask_t alt_mask; xkb_mod_mask_t shift_mask; @@ -2979,6 +2982,9 @@ keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, struct input *input = data; struct xkb_keymap *keymap; struct xkb_state *state; + struct xkb_compose_table *compose_table; + struct xkb_compose_state *compose_state; + char *locale; char *map_str; if (!data) { @@ -2997,6 +3003,7 @@ keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, return; } + /* Set up XKB keymap */ keymap = xkb_keymap_new_from_string(input->display->xkb_context, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, @@ -3009,6 +3016,7 @@ keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, return; } + /* Set up XKB state */ state = xkb_state_new(keymap); if (!state) { fprintf(stderr, "failed to create XKB state\n"); @@ -3016,8 +3024,38 @@ keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, return; } + /* Look up the appropriate locale, or use "C" as default */ + locale = getenv("LC_ALL"); + if (!locale) + locale = "C"; + + /* Set up XKB compose table */ + compose_table = xkb_compose_table_new_from_locale(input->display->xkb_context, + locale, + XKB_COMPOSE_COMPILE_NO_FLAGS); + if (!compose_table) { + fprintf(stderr, "could not create XKB compose table for locale '%s'\n", locale); + xkb_state_unref(state); + xkb_keymap_unref(keymap); + return; + } + + /* Set up XKB compose state */ + compose_state = xkb_compose_state_new(compose_table, + XKB_COMPOSE_STATE_NO_FLAGS); + if (!compose_state) { + fprintf(stderr, "could not create XKB compose state\n"); + xkb_compose_table_unref(compose_table); + xkb_state_unref(state); + xkb_keymap_unref(keymap); + } + + xkb_compose_state_unref(input->xkb.compose_state); + xkb_compose_table_unref(input->xkb.compose_table); xkb_keymap_unref(input->xkb.keymap); xkb_state_unref(input->xkb.state); + input->xkb.compose_state = compose_state; + input->xkb.compose_table = compose_table; input->xkb.keymap = keymap; input->xkb.state = state; @@ -3101,6 +3139,25 @@ keyboard_handle_key(void *data, struct wl_keyboard *keyboard, state == WL_KEYBOARD_KEY_STATE_PRESSED) { window_close(window); } else if (window->key_handler) { + if ((sym != XKB_KEY_NoSymbol) && + (state == WL_KEYBOARD_KEY_STATE_PRESSED) && + (xkb_compose_state_feed(input->xkb.compose_state, sym) == XKB_COMPOSE_FEED_ACCEPTED)) { + switch (xkb_compose_state_get_status(input->xkb.compose_state)) + { + case XKB_COMPOSE_COMPOSING: + sym = XKB_KEY_NoSymbol; + break; + + case XKB_COMPOSE_COMPOSED: + sym = xkb_compose_state_get_one_sym(input->xkb.compose_state); + break; + + case XKB_COMPOSE_CANCELLED: + case XKB_COMPOSE_NOTHING: + break; + } + } + (*window->key_handler)(window, input, time, key, sym, state, window->user_data); } -- 1.9.1 _______________________________________________ wayland-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/wayland-devel
