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 ¥.
The actual symbols available will depend on what the system makes available in its default compose sequence tables. Most systems provide hundreds of symbols. Since libxkbcommon transparently handles loading of the user's ~/.XCompose file, the user can customize and extend the compose sequences in that file, beyond what the system provides by default. Note this only permits insertion of single-symbol compose strings; while libxkbcommon is able to handle translating multi-symbol compose strings to the corresponding char* strings for the client, weston's client.c does not currently have a mechanism for passing text buffers to the clients, only individual symbols, so this feature will need to be left for future work. Previously, there was a limited compose functionality provided by the weston-simple-im input method, however it only provided 18 compose key sequences, and no mechanism to add more other than modifying source code. Further, it was only available when using that specific input method and using a client like weston-editor that supports the zwp_input_method protocol. Notably, this enables compose key functionality in weston-terminal, allowing entry of, for example, French letter symbols like è, á, ï, ê, et al. weston-eventdemo will also register the composed symbols if entered, as should any other client that uses Weston's window.* routines for accepting and managing keyboard input. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=53648 Signed-off-by: Bryce Harrington <[email protected]> --- clients/window.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 66 insertions(+), 9 deletions(-) diff --git a/clients/window.c b/clients/window.c index 216ef96..f38b15a 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); } @@ -5726,10 +5783,10 @@ output_get_allocation(struct output *output, struct rectangle *base) case WL_OUTPUT_TRANSFORM_270: case WL_OUTPUT_TRANSFORM_FLIPPED_90: case WL_OUTPUT_TRANSFORM_FLIPPED_270: - /* Swap width and height */ - allocation.width = output->allocation.height; - allocation.height = output->allocation.width; - break; + /* Swap width and height */ + allocation.width = output->allocation.height; + allocation.height = output->allocation.width; + break; } *base = allocation; -- 1.9.1 _______________________________________________ wayland-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/wayland-devel
