The Basics of Input Methods in Weston

Wayland provides an optional protocol, zwp_input_method, for defining alternate ways of sending keystrokes and mouse activity to clients. This could be things such as an onscreen keyboard or a popup for building Korean characters. The design of the protocol allows for different kinds of input methods to be made available via modular plugins, allowing them to be coded as discrete client applications, separate from the compositor’s core.

The Wayland project maintains a reference compositor named Weston that provides implementations of the various protocols for demonstrative purposes, including two implementations of the zwp_input_method protocol. One input method, weston-keyboard, manages an on-screen keyboard that pops up at the bottom of the screen, similar to on-screen keyboards typically seen on touch-based mobile devices. The other input method, weston-simple-im, enables a compose key functionality.

The user can configure which input method to use via their weston.ini file. No more than one input method can be registered with the Weston compositor at a time, and it cannot be changed at runtime.

What Does it Take to Create a New Input Method?

Input method modules are essentially just Weston clients. So, a trivial input method resembles a trivial Weston client with input method protocol sprinkled throughout:

   #include "config.h"
    #include "window.h"
    #include "input-method-unstable-v1-client-protocol.h"

    struct demo_input_method {
        struct zwp_input_method_v1 *input_method;
        struct zwp_input_method_context_v1 *im_context;
        struct display *display;
    };

    static void
    input_method_activate(void *data,
                          struct zwp_input_method_v1 *input_method,
                          struct zwp_input_method_context_v1 *new_context)
    {
        struct demo_input_method *im = data;
        if (im->im_context)
                zwp_input_method_context_v1_destroy(im->im_context);
        im->im_context = context;
    }

    static void
    input_method_deactivate(void *data,
                            struct zwp_input_method_v1 *input_method,
                            struct zwp_input_method_context_v1 *context)
    {
        struct demo_input_method *im = data;
        if (!im->im_context)
            return;
        zwp_input_method_context_v1_destroy(desktop_im->im_context);
        desktop_im->im_context = NULL;
    }

    static const struct zwp_input_method_v1_listener input_method_listener =
    {
        input_method_activate,
        input_method_deactivate
    };

    static void
    global_handler(struct display *display, uint32_t name,
                   const char *interface, uint32_t version, void *data)
    {
        struct demo_input_method *im = data;
        if (!strcmp(interface, "zwp_input_method_v1")) {
                im->input_method = display_bind(display, name, &zwp_input_method_v1_interface, 1);
                zwp_input_method_v1_add_listener(im->input_method, &input_method_listener, im);
        }
    }

    int main(int argc, char *argv[])
    {
        struct demo_input_method im;
        memset(&im, 0, sizeof im);

        /* Connect to the Weston display */
        im.display = display_create(&argc, argv);
        if (im.display == NULL)
            return -1;

        display_set_user_data(im.display, &im);
        display_set_global_handler(im.display, global_handler);
        display_run(im.display);
        display_destroy(im.display);
        return 0;
    }

The above implements a bare minimum input method client, that you can then expand to hang on whatever additional functionality you need.  It makes use of Toytoolkit, which is Weston’s simple widget library provided by the API in client/window.h, to handle making the connection to the display and setting up raw input handling.

All Wayland applications need to register the set of protocols they are interested in receiving from the compositor.  In this example, you can see this in the global_handler function, which registers the zwp_input_method protocol.  Part of registering a protocol with the compositor is to hook up the client-side routines that will be handling the API operations, typically called listeners; for our zwp_input_method protocol we are just registering two functions: one to activate the input method (input_method_activate()), another to deactivate it (input_method_deactivate()).  We set up pointers to these two functions when creating the input_method_listener structure, and then register it via the zwp_input_method_v1_add_listener() call.

Expanding this quick sketch of an input method into an actually useful method would involve adding more protocols (like zwp_input_pane) and registering more functions for the relevant API.  A logical next step would be to associate input handlers: a keyboard handler if your input method serves to translate key codes (weston-simple-im is an example of this approach), or perhaps button and touch events for an input method that provides an input panel (see weston-keyboard’s on-screen keyboard as an example). If your input method involves an input panel, code will be needed to handle redraw requests and manage the client’s visual state.

How are Input Methods Useful?

What kinds of input methods might one wish to create? One of the most common and traditional uses for input methods is to enter characters for non-Latin scripts such as for the Chinese, Japanese, Korean, Vietnamese, and Indic languages. Even for a given language, there can be different methods for entering characters, such as Cangjie and Pinyin for Chinese. Weston currently does not support any of these languages, so input methods for handling one or more of them would be useful additions.

But input methods can also be used with Latin scripts, like English, to provide various specialized behaviors. For example, automatic capitalization, automatic punctuation, spelling correction, and word suggestion are all possibilities. They can also support alternative forms of input entry, such as handwriting recognition, voice typing, and voice recognition.

Author: Bryce Harrington

Bryce is a founder and developer of the Inkscape project, but began his career in the aerospace industry as a spacecraft propulsions engineer.