QtVirtualKeyboard on Wayland

QtVirtualKeyboard on Wayland

For the last couple of years my focus was on the Osmocom project to bring Free Software to the world of telecommunication. With a group of enthusiasts we have implemented the components necessary to run a complete network using Free Software. The Rhizomatica project is using the software to connecting people that were left behind. Our tools enabled high impact security research leading, leading to improvements to privacy and security for all of us….

But during the last months I had the opportunity to return to C++ and Qt work and it feels like coming home to the world of ARM powered hardware. When I left, the transition from consumer electronics (e.g. settop boxes) to automative (e.g. IVI) began and it seems it successfully completed! On Friday I explored a regression in OpenSSL and today I had the pleasure to understand input method handling of wayland a little bit better.

I wanted to see if I can use wayland and run QtVirtualKeyboard only in the Compositor. I couldn’t find answers in the documentation and started to read the code. Once I understood how it should work, I found a simple example in QtWayland. Isn’t Qt wonderful?

As I have gone down the rabbit hole let me try to share some of my reading. At the core is the unstable (API subject to change) text-input protocol. Upstream of wayland-protocols is still at v1 of the protocol but QtWayland includes a copy of v2 and has rather complete support for the compositor and client (thanks KDAB!).

Compositor/Server

To make it work the compositor needs to signal support for the “zwp_text_input_manager_v2” interface. In QML/Quick this needs to be done by adding the following inside the WaylandCompositor component:

...
TextInputManager {
}
...

This will instantiate a QWaylandTextInputManager and call ::initialize on it. Then auto-generated code will use wl_global_create to register the interface in the global registry. Clients will request a text_input and the manager will create one or use a QWaylandTextInput and then send events down to the client. E.g. if there is a soft keyboard set a breakpoint in QWaylandTextInput::sendKeyEvent in the compositor and see from where it is coming and how it will send the event to a client.

Client

Once the client starts the QWaylandIntegration will create a QWaylandDisplay and then query/initialize the registry. The answer will call QWaylandDisplay::registry_global for every registered interface. For the the zwp_text_input_manager_v2 interface the integration will initialize a QtWayland::zwp_text_input_manager_v2 and for each input device a QtWaylandClient::QWaylandTextInput (different namespace) will be created.

Communication

Now Compositor and Client will communicate through the wayland connection (no dbus). With Qt APIs the client will notice which element has been focused and will request the input method to be shown (QtWaylandClient::QWaylandInputContext::showInputPanel) and the Compositor  will forward this to the QInputMethod (see QWaylandTextInputPrivate::zwp_text_input_v2_show_input_panel)

Putting it together

In the end this is rather simple.. create a TextInputManager, use the InputPanel of the QtVirtualKeyboard and start your compositor with QT_IM_MODULE=qtvirtualkeyboard. Done!