Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Support input method and text input#1203

Merged
ddevault merged 4 commits intoswaywm:masterfrom
dcz-purism:input
Oct 12, 2018
Merged

Support input method and text input#1203
ddevault merged 4 commits intoswaywm:masterfrom
dcz-purism:input

Conversation

@dcz-purism
Copy link
Copy Markdown
Contributor

This change introduces basic but useful support for zwp-text-input-v3 and zwp-input-method-v2 protocols.

The compositor becomes a relay between the input method program and the user-facing text input application, passing messages between them, and gracefully handling connections and disconnections.

The text-input protocol is implemented fully. The basic and least controversial pieces to make input-method functionality complete are implemented as well. Remaining are the grab and popup functionality. What's currently implemented is enough to support virtual keyboards, but probably not enough for e.g. CJK input methods.

The structure doing most of the work is the rootston/text_input.h::roots_input_method_relay. One is attached to each seat, and each manages multiple text-input connections and zero or one input-method connections.

Testing possible using virtboard's input_method branch (at scaling factor x1) and gtk-3.24.

To test with system-wide GTK:

$WLROOTS/rootston/rootston &
$VIRTBOARD/virtboard &
yad --entry &

With locally-installed GTK, the yad line can look like this:

LD_LIBRAY_PATH=$GTK/lib yad --entry

or, in the unlikely case of issues:

GDK_BACKEND=wayland GTK_IM_MODULE=wayland GTK_IM_MODULE_FILE=$GTK/lib/gtk-3.0/3.0.0/immodules.cache yad --entry

@dcz-purism
Copy link
Copy Markdown
Contributor Author

Script for easier testing:

#!/bin/bash
set -e
PREFIX=`pwd`/local
BASE=`pwd`
export PATH=$PREFIX/bin/:$PATH
export PKG_CONFIG_PATH=$PREFIX/share/pkgconfig/:$PREFIX/lib/pkgconfig/

sudo apt-get -y update
sudo apt-get -y install wget git yad build-essential

# wayland 1.16 not in Debian
sudo apt-get -y install libffi-dev libxml2-dev automake libexpat1-dev
wget https://wayland.freedesktop.org/releases/wayland-1.16.0.tar.xz
tar -xf wayland-1.16.0.tar.xz
cd wayland-1.16.0
aclocal
automake
./configure --disable-documentation --prefix=$PREFIX
make -j4
make install

cd $BASE

# build virtboard
sudo apt-get -y install debhelper meson pkg-config libpixman-1-dev libpng-dev libxcb1-dev libxcb-xkb-dev libxkbcommon-dev libcairo2-dev libwayland-dev wayland-protocols
git clone https://source.puri.sm/Librem5/virtboard.git -b input_method
export LC_ALL=C.UTF-8
meson virtboard virtboard_build
ninja -C virtboard_build

# build rootston
sudo apt-get -y install debhelper libcap-dev libdrm-dev libegl1-mesa-dev libgbm-dev libgles2-mesa-dev libinput-dev libpixman-1-dev libsystemd-dev libwayland-dev libxcb1-dev libxcb-composite0-dev libxcb-icccm4-dev libxcb-image0-dev libxcb-render0-dev libxcb-xfixes0-dev libxkbcommon-dev meson pkg-config wayland-protocols build-essential
git clone https://github.com/dcz-purism/wlroots.git -b input
meson wlroots wlroots_build
ninja -C wlroots_build

# build GTK
sudo apt-get -y install gtk-doc-tools gobject-introspection libatk1.0-dev libgirepository1.0-dev libepoxy-dev libpango1.0-dev libgdk-pixbuf2.0-dev
git clone --depth 1 https://gitlab.gnome.org/GNOME/gtk.git -b gtk-3-24
cd gtk
./autogen.sh --disable-x11-backend --enable-wayland-backend --disable-documentation --prefix=$PREFIX
make -j4
make install

exit 0

# run a demo - better play with all the programs yourself

cd $BASE
./wlroots_build/rootston/rootston &
./virtboard_build/virtboard &
yad &
LD_LIBRARY_PATH=$PREFIX/lib yad --entry &

@ddevault
Copy link
Copy Markdown
Contributor

Thanks. I intend to get around to testing this over the weekend.

context->pending.preedit.cursor_end = cursor_end;
free(context->pending.preedit.text);
context->pending.preedit.text = strdup(text); // TODO: clean up
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This leaks on destroy.

struct wlr_input_method *context =
wl_resource_get_user_data(resource);
free(context->pending.commit_text);
context->pending.commit_text = strdup(text); // TODO: clean up
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This leaks on destroy.

'text-input': {
'src': 'text-input.c',
'dep': [wayland_cursor, wayland_client, wlr_protos, wlroots],
},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're adding both in the same commi alhough one should be in text-input and the other one in input-method.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fixed now.

'input-method-unstable-v2.xml',
'screenshooter.xml',
'text-input-unstable-v3.xml',
'wlr-export-dmabuf-unstable-v1.xml',
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're adding both in the same commit although one should be in text input and the other one in input-method (to make reverts, etc simpler).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fixed now.

Copy link
Copy Markdown
Contributor

@ddevault ddevault left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot of this still looks WIP, definitely fix up the TODOs and FIXMEs. Overall code looks good

@@ -0,0 +1,214 @@
#ifndef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200809L
#endif
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to wrap this in ifndef

}

return EXIT_SUCCESS;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole file looks pretty wip

eglSwapBuffers(egl.display, egl_surface);
}

static void noop() {}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/* This space intentionally left blank */

void text_input_handle_leave(void *data,
struct zwp_text_input_v3 *zwp_text_input_v3,
struct wl_surface *surface) {
enabled = 2;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This variable is poorly named

} else if (strcmp(interface, zwp_text_input_manager_v3_interface.name) == 0) {
text_input_manager = wl_registry_bind(registry, name,
&zwp_text_input_manager_v3_interface, 1);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extraneous newline

#include <stdlib.h>
#include <wayland-server.h>


Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra newline here and on line 3

struct wl_global *input_method_manager;
struct wl_resource *resource; // FIXME: turn into a list, each entry per-client

struct wlr_input_method *input_method; // FIXME: turn into a list, each entry per-seat
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you fix this now?

Copy link
Copy Markdown
Contributor Author

@dcz-purism dcz-purism Sep 24, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first FIXME pertains to a list of all input methods - since input methods are meant to take over inputs using grabs, does it make sense to allow multiple ones to be present at the same time?
(this doesn't actually change the shape of the struct, but still)
(after thinking a little, the answer is already in the code - each seat has a unique input method, and no one seems to have complained yet)

void *data) {
struct wlr_text_input *text_input = wl_container_of(listener, text_input,
seat_destroy_listener);
// wlr_text_input_destroy(text_input); TODO: what to do when the seat goes under?
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

become inert, probably

static void text_input_enable(struct wl_client *client,
struct wl_resource *resource) {
struct wlr_text_input *text_input = text_input_from_resource(resource);
struct wlr_text_input_properties defaults = {0};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be static.

.preedit_string = preedit_string,
.delete_surrounding_text = delete_surrounding_text,
.get_input_popup_surface = noop,
.grab_keyboard = noop,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume the noops here are still on the TODO list, correct?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I wanted to get the whole concept into shape before I tackle these. They can be placed on top of the current patch independently, which helps to avoid a huge change at once.

@Shugyousha
Copy link
Copy Markdown
Contributor

Shugyousha commented Sep 2, 2018 via email


static void handle_unavailable(void *data,
struct zwp_input_method_v2 *zwp_input_method_v2) {
printf("IM disappeared");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing \n

#include "text-input-unstable-v3-client-protocol.h"
#include "xdg-shell-client-protocol.h"

#include <linux/input-event-codes.h>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add in FreeBSD too. You can find examples of how to do this by grepping other examples.

#include "input-method-unstable-v2-client-protocol.h"
#include "xdg-shell-client-protocol.h"

#include <linux/input-event-codes.h>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FreeBSD compat

@@ -0,0 +1,73 @@
#ifndef WLR_TYPES_WLR_INPUT_METHOD_H
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file should have a _v2 suffix

@@ -0,0 +1,77 @@
#ifndef WLR_TYPES_WLR_TEXT_INPUT_H
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file should have a _v3 suffix (alongside with all structs).

Ah, and you need to add the WLR_USE_UNSTABLE stuff too at the beginning of all new header files.

};

struct wlr_text_input_manager {
struct wl_global *wl_global;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be named global


struct {
struct wl_signal text_input; // (struct wlr_text_input*)
} events;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should have a destroy event

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean a destroy event on the manager. The manager gets destroyed with the display. If the compositor has objects that depend on it it needs to destroy them with the manager (it can't destroy them with the display because the destroy listener of the manager may be triggered before the destroy listener of the objects, this has caused issues in the past).


struct wlr_text_input_manager {
struct wl_global *wl_global;
struct wl_list text_inputs; // wlr_text_input::resource::link
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, you mean wlr_text_input::link?

#include <wlr/types/wlr_seat.h>
#include <wlr/types/wlr_surface.h>

struct wlr_text_input_properties {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We generally use state instead of properties

uint32_t anchor;
} surrounding;

uint32_t text_change_cause;
Copy link
Copy Markdown
Member

@emersion emersion Sep 5, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be an enum? (applies to other fields too)

struct wlr_surface *focused_surface;
struct wlr_text_input_properties pending;
struct wlr_text_input_properties current;
uint32_t current_serial; // next to send
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's the next serial, maybe we should rename to next_serial?

static void commit(struct wl_client *client, struct wl_resource *resource,
uint32_t serial) {
struct wlr_input_method *context =
wl_resource_get_user_data(resource);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should add a safe wrapper input_method_from_resource for this

context->current_serial = serial;
struct wlr_input_method_state default_state = {0};
context->pending = default_state;
wlr_signal_emit_safe(&context->events.commit, (void*)context);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to cast to void *


static void input_method_handle_resource_destroy(struct wl_resource *resource) {
struct wlr_input_method *context = input_method_from_resource(resource);
if (!context) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

input_method_destroy should check for NULL

Copy link
Copy Markdown
Contributor Author

@dcz-purism dcz-purism Sep 24, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it apply to all destructors? The check was something I realized is not needed.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, but that's how inert resources work. See the last part of CONTRIBUTING.md.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I didn't realize this guide was there.

@dcz-purism
Copy link
Copy Markdown
Contributor Author

It would definitely be good to be able to do some testing with more complex input methods, i. e. ones that show word suggestions for example. Is the plan to add something like that to wlroots/examples/input-method.c?

Yes, I want to create additional examples for testing once I start working on the floating popup and keyboard grab interfaces.


static void manager_destroy(struct wl_client *client,
struct wl_resource *resource) {
// FIXME
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should call wl_resource_destroy

wl_list_remove(&text_input->link);
// no need to destroy the resource if client closed, prompting the server to do it
if (text_input->resource) {
wl_resource_destroy(text_input->resource);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should never do this. Instead, the client should always send a request to destroy the resource.


static void text_input_destroy(struct wl_client *client,
struct wl_resource *resource) {
text_input_resource_destroy(resource);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should just call wl_resource_destroy

@ddevault
Copy link
Copy Markdown
Contributor

bump

wayland-scanner >= 1.15.0 accepts foreign struct references, necessary in protocols like zwp-input-method-v2
Implemented basic input method functionality. Not included: popups, grabbing.
The compositor acts as a relay between applications using the text-input protocol and input methods using the input-method protocol.

This change implements the basic but useful support for input-method, leaving out grabs as well as popups.
@dcz-purism
Copy link
Copy Markdown
Contributor Author

Bump

@ddevault
Copy link
Copy Markdown
Contributor

Well, I like it. Thanks!

@ddevault ddevault merged commit 66e8908 into swaywm:master Oct 12, 2018
@edo-codes
Copy link
Copy Markdown

It seems this merge has broken the build on an unused-result warning. Am I the only one?

[229/264] Compiling C object 'examples/examples@@input-method@exe/input-method.c.o'.
FAILED: examples/examples@@input-method@exe/input-method.c.o 
cc -Iexamples/examples@@input-method@exe -Iexamples -I../examples -I. -I../ -Iinclude -I../include -Iprotocol -I/usr/include/libdrm -I/usr/include/pixman-1 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wextra -Werror -std=c11 -g -Wno-unused-parameter '-DWLR_SRC_DIR="/home/edo/.cache/yay/wlroots-git/src/wlroots-git"' -DWLR_USE_UNSTABLE -DWL_HIDE_DEPRECATED -march=x86-64 -mtune=generic -O2 -fstack-protector-strong -fno-plt -g -fvar-tracking-assignments -fdebug-prefix-map=/home/edo/.cache/yay/wlroots-git/src=/usr/src/debug -D_FORTIFY_SOURCE=2  -MD -MQ 'examples/examples@@input-method@exe/input-method.c.o' -MF 'examples/examples@@input-method@exe/input-method.c.o.d' -o 'examples/examples@@input-method@exe/input-method.c.o' -c ../examples/input-method.c
../examples/input-method.c: In function ‘main’:
../examples/input-method.c:393:4: error: ignoring return value of ‘read’, declared with attribute warn_unused_result [-Werror=unused-result]
    read(timer_fd, &expirations, sizeof(expirations));
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
[238/264] Compiling C object 'rootston/rootston@@rootston@exe/desktop.c.o'.
ninja: build stopped: subcommand failed.

@ddevault
Copy link
Copy Markdown
Contributor

Send a patch!

@dcz-purism
Copy link
Copy Markdown
Contributor Author

Thank you!

@dcz-purism
Copy link
Copy Markdown
Contributor Author

@Edootjuh I can't reproduce this, how are you compiling it?

@agx
Copy link
Copy Markdown
Contributor

agx commented Oct 12, 2018

@SirCmpwn thanks for fixing this up so quickly.

@ddevault
Copy link
Copy Markdown
Contributor

@dcz-purism I pushed a fix

xdavidwu added a commit to xdavidwu/sway that referenced this pull request Oct 18, 2019
Leo1003 pushed a commit to xdavidwu/sway that referenced this pull request Nov 15, 2019
Leo1003 added a commit to xdavidwu/sway that referenced this pull request Nov 20, 2019
This ports swaywm/wlroots#1203, swaywm/wlroots#1303,
swaywm/wlroots#1308, swaywm/wlroots#1759 rootston part to sway.

Co-Authored-By: Leo Chen <leo881003@gmail.com>
Leo1003 added a commit to xdavidwu/sway that referenced this pull request Nov 20, 2019
This ports swaywm/wlroots#1203, swaywm/wlroots#1303,
swaywm/wlroots#1308, swaywm/wlroots#1759 rootston part to sway.

Co-Authored-By: Leo Chen <leo881003@gmail.com>
xdavidwu added a commit to xdavidwu/sway that referenced this pull request Jan 2, 2020
This ports swaywm/wlroots#1203, swaywm/wlroots#1303,
swaywm/wlroots#1308, swaywm/wlroots#1759 rootston part to sway.

Co-Authored-By: Leo Chen <leo881003@gmail.com>
xdavidwu added a commit to xdavidwu/sway that referenced this pull request Jan 12, 2020
This ports swaywm/wlroots#1203, swaywm/wlroots#1303,
swaywm/wlroots#1308, swaywm/wlroots#1759 rootston part to sway.

Co-Authored-By: Leo Chen <leo881003@gmail.com>
xdavidwu added a commit to xdavidwu/sway that referenced this pull request Jan 21, 2020
This ports swaywm/wlroots#1203, swaywm/wlroots#1303,
swaywm/wlroots#1308, swaywm/wlroots#1759 rootston part to sway.

Co-Authored-By: Leo Chen <leo881003@gmail.com>
xdavidwu added a commit to xdavidwu/sway that referenced this pull request Feb 14, 2020
This ports swaywm/wlroots#1203, swaywm/wlroots#1303,
swaywm/wlroots#1308, swaywm/wlroots#1759 rootston part to sway.

Co-Authored-By: Leo Chen <leo881003@gmail.com>
xdavidwu added a commit to xdavidwu/sway that referenced this pull request Feb 20, 2020
This ports swaywm/wlroots#1203, swaywm/wlroots#1303,
swaywm/wlroots#1308, swaywm/wlroots#1759 rootston part to sway.

Co-Authored-By: Leo Chen <leo881003@gmail.com>
xdavidwu added a commit to xdavidwu/sway that referenced this pull request Feb 27, 2020
This ports swaywm/wlroots#1203, swaywm/wlroots#1303,
swaywm/wlroots#1308, swaywm/wlroots#1759 rootston part to sway.

Co-Authored-By: Leo Chen <leo881003@gmail.com>
xdavidwu added a commit to xdavidwu/sway that referenced this pull request Mar 11, 2020
This ports swaywm/wlroots#1203, swaywm/wlroots#1303,
swaywm/wlroots#1308, swaywm/wlroots#1759 rootston part to sway.

Co-Authored-By: Leo Chen <leo881003@gmail.com>
Leo1003 added a commit to xdavidwu/sway that referenced this pull request Mar 24, 2020
This ports swaywm/wlroots#1203, swaywm/wlroots#1303,
swaywm/wlroots#1308, swaywm/wlroots#1759 rootston part to sway.

Co-Authored-By: Leo Chen <leo881003@gmail.com>
Leo1003 added a commit to xdavidwu/sway that referenced this pull request Apr 4, 2020
This ports swaywm/wlroots#1203, swaywm/wlroots#1303,
swaywm/wlroots#1308, swaywm/wlroots#1759 rootston part to sway.

Co-Authored-By: Leo Chen <leo881003@gmail.com>
emersion pushed a commit to swaywm/sway that referenced this pull request Apr 4, 2020
This ports swaywm/wlroots#1203, swaywm/wlroots#1303,
swaywm/wlroots#1308, swaywm/wlroots#1759 rootston part to sway.

Co-Authored-By: Leo Chen <leo881003@gmail.com>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Development

Successfully merging this pull request may close these issues.

6 participants