[PATCH weston v2] clients: Add XKB compose key support
Bryce Harrington
bryce at osg.samsung.com
Fri Oct 7 04:24:41 UTC 2016
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>
---
clients/window.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
diff --git a/clients/window.c b/clients/window.c
index 216ef96..0110ae4 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;
@@ -3056,6 +3094,29 @@ 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;
+ }
+
+ return sym;
+}
+
static void
keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
uint32_t serial, uint32_t time, uint32_t key,
@@ -3101,6 +3162,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
More information about the wayland-devel
mailing list