[PATCH weston v3] clients: Add XKB compose key support

Eric Engestrom eric.engestrom at imgtec.com
Tue Oct 11 10:21:35 UTC 2016


On Mon, Oct 10, 2016 at 03:31:47PM -0700, Bryce Harrington wrote:
> 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 toytoolkit'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 <bryce at osg.samsung.com>
> Reviewed-by: Daniel Stone <daniels at collabora.com>
> 
> Signed-off-by: Bryce Harrington <bryce at osg.samsung.com>

Reviewed-by: Eric Engestrom <eric.engestrom at imgtec.com>

> ---
> v3:  Don't die if compose can't be established
> 	 Format a couple lengthy lines to 80 columns
> 	 Also check LC_CTYPE and LANG for locale settings
> 
>  clients/window.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 66 insertions(+)
> 
> diff --git a/clients/window.c b/clients/window.c
> index 216ef96..1c53b5f 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,6 +3024,37 @@ keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
>  		return;
>  	}
>  
> +	/* Look up the preferred locale, falling back to "C" as default */
> +	if (!(locale = getenv("LC_ALL")))
> +		if (!(locale = getenv("LC_CTYPE")))
> +			if (!(locale = getenv("LANG")))
> +				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) {
> +		/* Set up XKB compose state */
> +		compose_state = xkb_compose_state_new(compose_table,
> +					      XKB_COMPOSE_STATE_NO_FLAGS);
> +		if (compose_state) {
> +			xkb_compose_state_unref(input->xkb.compose_state);
> +			xkb_compose_table_unref(input->xkb.compose_table);
> +			input->xkb.compose_state = compose_state;
> +			input->xkb.compose_table = compose_table;
> +		} else {
> +			fprintf(stderr, "could not create XKB compose state.  "
> +				"Disabiling compose.\n");
> +			xkb_compose_table_unref(compose_table);
> +			compose_table = NULL;
> +		}
> +	} else {
> +		fprintf(stderr, "could not create XKB compose table for locale '%s'.  "
> +			"Disabiling compose\n", locale);
> +	}
> +
>  	xkb_keymap_unref(input->xkb.keymap);
>  	xkb_state_unref(input->xkb.state);
>  	input->xkb.keymap = keymap;
> @@ -3056,6 +3095,30 @@ keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
>  	input_remove_keyboard_focus(input);
>  }
>  
> +/* Translate symbols appropriately if a compose sequence is being entered */
> +static xkb_keysym_t
> +process_key_press(xkb_keysym_t sym, struct input *input)
> +{
> +	if (sym == XKB_KEY_NoSymbol)
> +		return sym;
> +	if (xkb_compose_state_feed(input->xkb.compose_state,
> +				   sym) != XKB_COMPOSE_FEED_ACCEPTED)
> +		return sym;
> +
> +	switch (xkb_compose_state_get_status(input->xkb.compose_state)) {
> +	case XKB_COMPOSE_COMPOSING:
> +		return XKB_KEY_NoSymbol;
> +	case XKB_COMPOSE_COMPOSED:
> +		return xkb_compose_state_get_one_sym(input->xkb.compose_state);
> +	case XKB_COMPOSE_CANCELLED:
> +		return XKB_KEY_NoSymbol;
> +	case XKB_COMPOSE_NOTHING:
> +		return sym;
> +	default:
> +		return sym;
> +	}
> +}
> +
>  static void
>  keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
>  		    uint32_t serial, uint32_t time, uint32_t key,
> @@ -3101,6 +3164,9 @@ keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
>  		   state == WL_KEYBOARD_KEY_STATE_PRESSED) {
>  		window_close(window);
>  	} else if (window->key_handler) {
> +		if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
> +			sym = process_key_press(sym, input);
> +
>  		(*window->key_handler)(window, input, time, key,
>  				       sym, state, window->user_data);
>  	}
> -- 
> 1.9.1
> 
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list