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

Reply via email to