[PATCH 1/1] input: Add support for zwp_text_input_v3 and zwp_input_method_v2
Andre Moreira Magalhaes (andrunko)
andrunko at gmail.com
Wed Mar 20 21:51:45 UTC 2019
From: "Andre Moreira Magalhaes (andrunko)" <andre.magalhaes at collabora.com>
Some clients such as gtk+3 require the zwp_text_input_v3 protocol for
input-method handling. This patch adds this protocol support to text-backend and also
modifies weston-keyboard to support zwp_input_method_v2, which is an update
for the v1 protocol and aligned with the updated text-input protocol.
The patch also adds support for zwp_virtual_keyboard_v1, used to emulate the
behaviour of a physical keyboard.
Note that the updated input-method v2 protocol does not support the input-panel interface
as it did on v1. The input panel interface is implemented by desktop-shell to properly
display the virtual keyboard interface.
To avoid depending on both input method v2 and v1 (for input-panel only), this patch adds
a new weston-input-panel internal protocol (a copy of the old interface from input-method v1),
which is then implemented by desktop-shell and used by weston-keyboard when displaying
its window.
Signed-off-by: Andre Moreira Magalhaes (andrunko) <andre.magalhaes at collabora.co.uk>
---
Makefile.am | 28 +-
clients/keyboard.c | 528 ++++++++-------
clients/meson.build | 12 +-
clients/window.c | 9 +
clients/window.h | 3 +
compositor/meson.build | 12 +-
compositor/text-backend.c | 1104 +++++++++++++++++--------------
desktop-shell/input-panel.c | 12 +-
desktop-shell/meson.build | 4 +-
protocol/meson.build | 4 +
protocol/weston-input-panel.xml | 63 ++
tests/meson.build | 6 +-
tests/text-test.c | 151 ++---
13 files changed, 1056 insertions(+), 880 deletions(-)
create mode 100644 protocol/weston-input-panel.xml
diff --git a/Makefile.am b/Makefile.am
index b2bb61f6..5faec4c0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -171,8 +171,12 @@ nodist_libweston_ at LIBWESTON_MAJOR@_la_SOURCES = \
protocol/text-cursor-position-server-protocol.h \
protocol/text-input-unstable-v1-protocol.c \
protocol/text-input-unstable-v1-server-protocol.h \
+ protocol/text-input-unstable-v3-protocol.c \
+ protocol/text-input-unstable-v3-server-protocol.h \
protocol/input-method-unstable-v1-protocol.c \
protocol/input-method-unstable-v1-server-protocol.h \
+ protocol/input-method-unstable-v2-protocol.c \
+ protocol/input-method-unstable-v2-server-protocol.h \
protocol/presentation-time-protocol.c \
protocol/presentation-time-server-protocol.h \
protocol/viewporter-protocol.c \
@@ -185,6 +189,10 @@ nodist_libweston_ at LIBWESTON_MAJOR@_la_SOURCES = \
protocol/pointer-constraints-unstable-v1-server-protocol.h \
protocol/input-timestamps-unstable-v1-protocol.c \
protocol/input-timestamps-unstable-v1-server-protocol.h \
+ protocol/virtual-keyboard-unstable-v1-protocol.c \
+ protocol/virtual-keyboard-unstable-v1-server-protocol.h \
+ protocol/weston-input-panel-protocol.c \
+ protocol/weston-input-panel-server-protocol.h \
protocol/weston-touch-calibration-protocol.c \
protocol/weston-touch-calibration-server-protocol.h \
protocol/linux-explicit-synchronization-unstable-v1-protocol.c \
@@ -879,8 +887,12 @@ weston_keyboard_SOURCES = clients/keyboard.c
nodist_weston_keyboard_SOURCES = \
protocol/weston-desktop-shell-client-protocol.h \
protocol/weston-desktop-shell-protocol.c \
- protocol/input-method-unstable-v1-protocol.c \
- protocol/input-method-unstable-v1-client-protocol.h
+ protocol/input-method-unstable-v2-protocol.c \
+ protocol/input-method-unstable-v2-client-protocol.h \
+ protocol/virtual-keyboard-unstable-v1-protocol.c \
+ protocol/virtual-keyboard-unstable-v1-client-protocol.h \
+ protocol/weston-input-panel-protocol.c \
+ protocol/weston-input-panel-client-protocol.h
weston_keyboard_LDADD = libtoytoolkit.la
weston_keyboard_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS)
@@ -957,10 +969,18 @@ BUILT_SOURCES += \
protocol/text-cursor-position-protocol.c \
protocol/text-input-unstable-v1-protocol.c \
protocol/text-input-unstable-v1-client-protocol.h \
+ protocol/text-input-unstable-v3-protocol.c \
+ protocol/text-input-unstable-v3-client-protocol.h \
protocol/input-method-unstable-v1-protocol.c \
protocol/input-method-unstable-v1-client-protocol.h \
+ protocol/input-method-unstable-v2-protocol.c \
+ protocol/input-method-unstable-v2-client-protocol.h \
+ protocol/virtual-keyboard-unstable-v1-protocol.c \
+ protocol/virtual-keyboard-unstable-v1-client-protocol.h \
protocol/weston-desktop-shell-client-protocol.h \
protocol/weston-desktop-shell-protocol.c \
+ protocol/weston-input-panel-client-protocol.h \
+ protocol/weston-input-panel-protocol.c \
protocol/viewporter-client-protocol.h \
protocol/viewporter-protocol.c \
protocol/presentation-time-protocol.c \
@@ -1628,9 +1648,7 @@ EXTRA_DIST += \
BUILT_SOURCES += \
protocol/weston-test-protocol.c \
protocol/weston-test-server-protocol.h \
- protocol/weston-test-client-protocol.h \
- protocol/text-input-unstable-v1-protocol.c \
- protocol/text-input-unstable-v1-client-protocol.h
+ protocol/weston-test-client-protocol.h
EXTRA_DIST += \
protocol/weston-desktop-shell.xml \
diff --git a/clients/keyboard.c b/clients/keyboard.c
index c9f6f28e..2ba036fb 100644
--- a/clients/keyboard.c
+++ b/clients/keyboard.c
@@ -1,6 +1,7 @@
/*
* Copyright © 2012 Openismus GmbH
* Copyright © 2012 Intel Corporation
+ * Copyright © 2019 Collabora Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -34,29 +35,39 @@
#include <cairo.h>
#include "window.h"
-#include "input-method-unstable-v1-client-protocol.h"
-#include "text-input-unstable-v1-client-protocol.h"
+#include "input-method-unstable-v2-client-protocol.h"
+#include "text-input-unstable-v3-client-protocol.h"
+#include "virtual-keyboard-unstable-v1-client-protocol.h"
+#include "weston-input-panel-client-protocol.h"
#include "shared/xalloc.h"
struct keyboard;
+struct text_input_state {
+ uint32_t content_hint;
+ uint32_t content_purpose;
+ uint32_t change_cause;
+ char *surrounding_text;
+ uint32_t surrounding_cursor;
+ bool active;
+};
+
struct virtual_keyboard {
- struct zwp_input_panel_v1 *input_panel;
- struct zwp_input_method_v1 *input_method;
- struct zwp_input_method_context_v1 *context;
+ struct weston_input_panel *input_panel;
+ struct zwp_input_method_manager_v2 *input_method_manager;
+ struct zwp_input_method_v2 *input_method;
+ struct zwp_virtual_keyboard_manager_v1 *virtual_keyboard_manager;
+ struct zwp_virtual_keyboard_v1 *virtual_keyboard;
struct display *display;
struct output *output;
- char *preedit_string;
- uint32_t preedit_style;
- struct {
- xkb_mod_mask_t shift_mask;
- } keysym;
+ struct wl_seat *seat;
+
uint32_t serial;
- uint32_t content_hint;
- uint32_t content_purpose;
+ char *preedit_string;
+ struct text_input_state pending;
+ struct text_input_state current;
+ // TODO - add support to change language (e.g. via config)
char *preferred_language;
- char *surrounding_text;
- uint32_t surrounding_cursor;
struct keyboard *keyboard;
bool toplevel;
};
@@ -73,7 +84,6 @@ enum key_type {
keytype_arrow_left,
keytype_arrow_right,
keytype_arrow_down,
- keytype_style
};
struct key {
@@ -94,7 +104,6 @@ struct layout {
uint32_t rows;
const char *language;
- uint32_t text_direction;
};
static const struct key normal_keys[] = {
@@ -140,7 +149,6 @@ static const struct key normal_keys[] = {
{ keytype_arrow_left, "<", "<", "<", 1},
{ keytype_arrow_right, ">", ">", ">", 1},
{ keytype_arrow_down, "\\/", "\\/", "\\/", 1},
- { keytype_style, "", "", "", 2}
};
static const struct key numeric_keys[] = {
@@ -162,7 +170,6 @@ static const struct key numeric_keys[] = {
{ keytype_arrow_left, "<", "<", "<", 1},
{ keytype_arrow_right, ">", ">", ">", 1},
{ keytype_arrow_down, "\\/", "\\/", "\\/", 1},
- { keytype_style, "", "", "", 2}
};
static const struct key arabic_keys[] = {
@@ -210,7 +217,6 @@ static const struct key arabic_keys[] = {
{ keytype_space, "", "", "", 6},
{ keytype_default, ".", "ذ", "]", 1},
{ keytype_default, "ط", "ﺝ", "[", 1},
- { keytype_style, "", "", "", 2}
};
@@ -219,8 +225,7 @@ static const struct layout normal_layout = {
sizeof(normal_keys) / sizeof(*normal_keys),
12,
4,
- "en",
- ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_LTR
+ "en"
};
static const struct layout numeric_layout = {
@@ -228,8 +233,7 @@ static const struct layout numeric_layout = {
sizeof(numeric_keys) / sizeof(*numeric_keys),
12,
2,
- "en",
- ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_LTR
+ "en"
};
static const struct layout arabic_layout = {
@@ -237,19 +241,7 @@ static const struct layout arabic_layout = {
sizeof(arabic_keys) / sizeof(*arabic_keys),
13,
4,
- "ar",
- ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_RTL
-};
-
-static const char *style_labels[] = {
- "default",
- "none",
- "active",
- "inactive",
- "highlight",
- "underline",
- "selection",
- "incorrect"
+ "ar"
};
static const double key_width = 60;
@@ -269,6 +261,9 @@ struct keyboard {
enum keyboard_state state;
};
+static void keyboard_set_visibility(struct virtual_keyboard *virtual_keyboard,
+ bool visible);
+
static void __attribute__ ((format (printf, 1, 2)))
dbg(const char *fmt, ...)
{
@@ -285,9 +280,6 @@ static const char *
label_from_key(struct keyboard *keyboard,
const struct key *key)
{
- if (key->key_type == keytype_style)
- return style_labels[keyboard->keyboard->preedit_style];
-
switch(keyboard->state) {
case KEYBOARD_STATE_DEFAULT:
return key->label;
@@ -341,9 +333,13 @@ draw_key(struct keyboard *keyboard,
static const struct layout *
get_current_layout(struct virtual_keyboard *keyboard)
{
- switch (keyboard->content_purpose) {
- case ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_DIGITS:
- case ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_NUMBER:
+ if (!keyboard->current.active) {
+ return &normal_layout;
+ }
+
+ switch (keyboard->current.content_purpose) {
+ case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_DIGITS:
+ case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NUMBER:
return &numeric_layout;
default:
if (keyboard->preferred_language &&
@@ -430,22 +426,21 @@ virtual_keyboard_commit_preedit(struct virtual_keyboard *keyboard)
strlen(keyboard->preedit_string) == 0)
return;
- zwp_input_method_context_v1_cursor_position(keyboard->context,
- 0, 0);
- zwp_input_method_context_v1_commit_string(keyboard->context,
- keyboard->serial,
- keyboard->preedit_string);
+ zwp_input_method_v2_commit_string(keyboard->input_method,
+ keyboard->preedit_string);
+ zwp_input_method_v2_commit(keyboard->input_method,
+ keyboard->serial);
- if (keyboard->surrounding_text) {
- surrounding_text = insert_text(keyboard->surrounding_text,
- keyboard->surrounding_cursor,
+ if (keyboard->current.surrounding_text) {
+ surrounding_text = insert_text(keyboard->current.surrounding_text,
+ keyboard->current.surrounding_cursor,
keyboard->preedit_string);
- free(keyboard->surrounding_text);
- keyboard->surrounding_text = surrounding_text;
- keyboard->surrounding_cursor += strlen(keyboard->preedit_string);
+ free(keyboard->current.surrounding_text);
+ keyboard->current.surrounding_text = surrounding_text;
+ keyboard->current.surrounding_cursor += strlen(keyboard->preedit_string);
} else {
- keyboard->surrounding_text = strdup(keyboard->preedit_string);
- keyboard->surrounding_cursor = strlen(keyboard->preedit_string);
+ keyboard->current.surrounding_text = strdup(keyboard->preedit_string);
+ keyboard->current.surrounding_cursor = strlen(keyboard->preedit_string);
}
free(keyboard->preedit_string);
@@ -458,19 +453,11 @@ virtual_keyboard_send_preedit(struct virtual_keyboard *keyboard,
{
uint32_t index = strlen(keyboard->preedit_string);
- if (keyboard->preedit_style)
- zwp_input_method_context_v1_preedit_styling(keyboard->context,
- 0,
- strlen(keyboard->preedit_string),
- keyboard->preedit_style);
if (cursor > 0)
index = cursor;
- zwp_input_method_context_v1_preedit_cursor(keyboard->context,
- index);
- zwp_input_method_context_v1_preedit_string(keyboard->context,
- keyboard->serial,
- keyboard->preedit_string,
- keyboard->preedit_string);
+ zwp_input_method_v2_set_preedit_string(keyboard->input_method,
+ keyboard->preedit_string, index, index);
+ zwp_input_method_v2_commit(keyboard->input_method, keyboard->serial);
}
static const char *
@@ -487,33 +474,33 @@ static void
delete_before_cursor(struct virtual_keyboard *keyboard)
{
const char *start, *end;
+ const char *surrounding_text = keyboard->current.surrounding_text;
+ uint32_t surrounding_cursor = keyboard->current.surrounding_cursor;
- if (!keyboard->surrounding_text) {
+ if (!surrounding_text) {
dbg("delete_before_cursor: No surrounding text available\n");
return;
}
- start = prev_utf8_char(keyboard->surrounding_text,
- keyboard->surrounding_text + keyboard->surrounding_cursor);
+ start = prev_utf8_char(surrounding_text,
+ surrounding_text + surrounding_cursor);
if (!start) {
dbg("delete_before_cursor: No previous character to delete\n");
return;
}
- end = keyboard->surrounding_text + keyboard->surrounding_cursor;
+ end = surrounding_text + surrounding_cursor;
- zwp_input_method_context_v1_delete_surrounding_text(keyboard->context,
- (start - keyboard->surrounding_text) - keyboard->surrounding_cursor,
- end - start);
- zwp_input_method_context_v1_commit_string(keyboard->context,
- keyboard->serial,
- "");
+ zwp_input_method_v2_delete_surrounding_text(keyboard->input_method,
+ surrounding_cursor - (start - surrounding_text), 0);
+ zwp_input_method_v2_commit(keyboard->input_method, keyboard->serial);
/* Update surrounding text */
- keyboard->surrounding_cursor = start - keyboard->surrounding_text;
- keyboard->surrounding_text[keyboard->surrounding_cursor] = '\0';
+ keyboard->current.surrounding_cursor = start - surrounding_text;
+ keyboard->current.surrounding_text[surrounding_cursor] = '\0';
if (*end)
- memmove(keyboard->surrounding_text + keyboard->surrounding_cursor, end, strlen(end));
+ memmove(keyboard->current.surrounding_text + keyboard->current.surrounding_cursor,
+ end, strlen(end));
}
static char *
@@ -548,7 +535,6 @@ keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key *
break;
}
- xkb_mod_mask_t mod_mask = keyboard->state == KEYBOARD_STATE_DEFAULT ? 0 : keyboard->keyboard->keysym.shift_mask;
uint32_t key_state = (state == WL_POINTER_BUTTON_STATE_PRESSED) ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED;
switch (key->key_type) {
@@ -562,6 +548,16 @@ keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key *
virtual_keyboard_send_preedit(keyboard->keyboard, -1);
break;
case keytype_backspace:
+ if (!keyboard->keyboard->current.active ||
+ ((!keyboard->keyboard->preedit_string ||
+ strlen(keyboard->keyboard->preedit_string) == 0) &&
+ (!keyboard->keyboard->current.surrounding_text ||
+ strlen(keyboard->keyboard->current.surrounding_text) == 0))) {
+ zwp_virtual_keyboard_v1_key(keyboard->keyboard->virtual_keyboard,
+ time, KEY_BACKSPACE, key_state);
+ break;
+ }
+
if (state != WL_POINTER_BUTTON_STATE_PRESSED)
break;
@@ -573,13 +569,18 @@ keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key *
}
break;
case keytype_enter:
- virtual_keyboard_commit_preedit(keyboard->keyboard);
- zwp_input_method_context_v1_keysym(keyboard->keyboard->context,
- display_get_serial(keyboard->keyboard->display),
- time,
- XKB_KEY_Return, key_state, mod_mask);
+ if (state == WL_POINTER_BUTTON_STATE_PRESSED &&
+ keyboard->keyboard->current.active)
+ virtual_keyboard_commit_preedit(keyboard->keyboard);
+ zwp_virtual_keyboard_v1_key(keyboard->keyboard->virtual_keyboard,
+ time, KEY_ENTER, key_state);
break;
case keytype_space:
+ if (!keyboard->keyboard->current.active) {
+ zwp_virtual_keyboard_v1_key(keyboard->keyboard->virtual_keyboard,
+ time, KEY_SPACE, key_state);
+ break;
+ }
if (state != WL_POINTER_BUTTON_STATE_PRESSED)
break;
keyboard->keyboard->preedit_string =
@@ -617,45 +618,39 @@ keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key *
}
break;
case keytype_tab:
- virtual_keyboard_commit_preedit(keyboard->keyboard);
- zwp_input_method_context_v1_keysym(keyboard->keyboard->context,
- display_get_serial(keyboard->keyboard->display),
- time,
- XKB_KEY_Tab, key_state, mod_mask);
+ if (state == WL_POINTER_BUTTON_STATE_PRESSED &&
+ keyboard->keyboard->current.active)
+ virtual_keyboard_commit_preedit(keyboard->keyboard);
+ zwp_virtual_keyboard_v1_key(keyboard->keyboard->virtual_keyboard,
+ time, KEY_TAB, key_state);
break;
case keytype_arrow_up:
- virtual_keyboard_commit_preedit(keyboard->keyboard);
- zwp_input_method_context_v1_keysym(keyboard->keyboard->context,
- display_get_serial(keyboard->keyboard->display),
- time,
- XKB_KEY_Up, key_state, mod_mask);
+ if (state == WL_POINTER_BUTTON_STATE_PRESSED &&
+ keyboard->keyboard->current.active)
+ virtual_keyboard_commit_preedit(keyboard->keyboard);
+ zwp_virtual_keyboard_v1_key(keyboard->keyboard->virtual_keyboard,
+ time, KEY_UP, key_state);
break;
case keytype_arrow_left:
- virtual_keyboard_commit_preedit(keyboard->keyboard);
- zwp_input_method_context_v1_keysym(keyboard->keyboard->context,
- display_get_serial(keyboard->keyboard->display),
- time,
- XKB_KEY_Left, key_state, mod_mask);
+ if (state == WL_POINTER_BUTTON_STATE_PRESSED &&
+ keyboard->keyboard->current.active)
+ virtual_keyboard_commit_preedit(keyboard->keyboard);
+ zwp_virtual_keyboard_v1_key(keyboard->keyboard->virtual_keyboard,
+ time, KEY_LEFT, key_state);
break;
case keytype_arrow_right:
- virtual_keyboard_commit_preedit(keyboard->keyboard);
- zwp_input_method_context_v1_keysym(keyboard->keyboard->context,
- display_get_serial(keyboard->keyboard->display),
- time,
- XKB_KEY_Right, key_state, mod_mask);
+ if (state == WL_POINTER_BUTTON_STATE_PRESSED &&
+ keyboard->keyboard->current.active)
+ virtual_keyboard_commit_preedit(keyboard->keyboard);
+ zwp_virtual_keyboard_v1_key(keyboard->keyboard->virtual_keyboard,
+ time, KEY_RIGHT, key_state);
break;
case keytype_arrow_down:
- virtual_keyboard_commit_preedit(keyboard->keyboard);
- zwp_input_method_context_v1_keysym(keyboard->keyboard->context,
- display_get_serial(keyboard->keyboard->display),
- time,
- XKB_KEY_Down, key_state, mod_mask);
- break;
- case keytype_style:
- if (state != WL_POINTER_BUTTON_STATE_PRESSED)
- break;
- keyboard->keyboard->preedit_style = (keyboard->keyboard->preedit_style + 1) % 8; /* TODO */
- virtual_keyboard_send_preedit(keyboard->keyboard, -1);
+ if (state == WL_POINTER_BUTTON_STATE_PRESSED &&
+ keyboard->keyboard->current.active)
+ virtual_keyboard_commit_preedit(keyboard->keyboard);
+ zwp_virtual_keyboard_v1_key(keyboard->keyboard->virtual_keyboard,
+ time, KEY_DOWN, key_state);
break;
}
}
@@ -751,248 +746,191 @@ touch_up_handler(struct widget *widget, struct input *input,
WL_POINTER_BUTTON_STATE_RELEASED, data);
}
+static void
+input_method_activate(void *data,
+ struct zwp_input_method_v2 *input_method)
+{
+ struct virtual_keyboard *virtual_keyboard = data;
+ struct text_input_state defaults = {0};
+
+ if (virtual_keyboard->pending.surrounding_text)
+ free(virtual_keyboard->pending.surrounding_text);
+ virtual_keyboard->pending.surrounding_text = NULL;
+ virtual_keyboard->pending = defaults;
+ if (virtual_keyboard->preedit_string)
+ free(virtual_keyboard->preedit_string);
+ virtual_keyboard->preedit_string = strdup("");
+ virtual_keyboard->pending.active = true;
+}
+
+static void
+input_method_deactivate(void *data,
+ struct zwp_input_method_v2 *input_method)
+{
+ struct virtual_keyboard *virtual_keyboard = data;
+
+ virtual_keyboard->pending.active = false;
+}
+
static void
handle_surrounding_text(void *data,
- struct zwp_input_method_context_v1 *context,
+ struct zwp_input_method_v2 *input_method,
const char *text,
uint32_t cursor,
uint32_t anchor)
{
struct virtual_keyboard *keyboard = data;
- free(keyboard->surrounding_text);
- keyboard->surrounding_text = strdup(text);
+ if (keyboard->pending.surrounding_text)
+ free(keyboard->pending.surrounding_text);
+ keyboard->pending.surrounding_text = strdup(text);
- keyboard->surrounding_cursor = cursor;
+ keyboard->pending.surrounding_cursor = cursor;
}
static void
-handle_reset(void *data,
- struct zwp_input_method_context_v1 *context)
+handle_text_change_cause(void *data,
+ struct zwp_input_method_v2 *zwp_input_method_v2,
+ uint32_t cause)
{
struct virtual_keyboard *keyboard = data;
- dbg("Reset pre-edit buffer\n");
-
- if (strlen(keyboard->preedit_string)) {
- free(keyboard->preedit_string);
- keyboard->preedit_string = strdup("");
- }
+ keyboard->pending.change_cause = cause;
}
static void
handle_content_type(void *data,
- struct zwp_input_method_context_v1 *context,
+ struct zwp_input_method_v2 *input_method,
uint32_t hint,
uint32_t purpose)
{
struct virtual_keyboard *keyboard = data;
- keyboard->content_hint = hint;
- keyboard->content_purpose = purpose;
-}
-
-static void
-handle_invoke_action(void *data,
- struct zwp_input_method_context_v1 *context,
- uint32_t button,
- uint32_t index)
-{
- struct virtual_keyboard *keyboard = data;
-
- if (button != BTN_LEFT)
- return;
-
- virtual_keyboard_send_preedit(keyboard, index);
+ keyboard->pending.content_hint = hint;
+ keyboard->pending.content_purpose = purpose;
}
static void
handle_commit_state(void *data,
- struct zwp_input_method_context_v1 *context,
- uint32_t serial)
+ struct zwp_input_method_v2 *input_method)
{
- struct virtual_keyboard *keyboard = data;
- const struct layout *layout;
-
- keyboard->serial = serial;
+ struct virtual_keyboard *virtual_keyboard = data;
+ struct text_input_state defaults = {0};
- layout = get_current_layout(keyboard);
+ virtual_keyboard->serial++;
- if (keyboard->surrounding_text)
- dbg("Surrounding text updated: %s\n", keyboard->surrounding_text);
+ if (virtual_keyboard->pending.surrounding_text)
+ free(virtual_keyboard->pending.surrounding_text);
+ virtual_keyboard->pending.surrounding_text = NULL;
+ virtual_keyboard->current = virtual_keyboard->pending;
+ virtual_keyboard->pending = defaults;
+ virtual_keyboard->pending.active = virtual_keyboard->current.active;
- window_schedule_resize(keyboard->keyboard->window,
- layout->columns * key_width,
- layout->rows * key_height);
-
- zwp_input_method_context_v1_language(context,
- keyboard->serial,
- layout->language);
- zwp_input_method_context_v1_text_direction(context,
- keyboard->serial,
- layout->text_direction);
-
- widget_schedule_redraw(keyboard->keyboard->widget);
+ keyboard_set_visibility(virtual_keyboard,
+ virtual_keyboard->current.active);
}
static void
-handle_preferred_language(void *data,
- struct zwp_input_method_context_v1 *context,
- const char *language)
+handle_unavailable(void *data,
+ struct zwp_input_method_v2 *zwp_input_method_v2)
{
- struct virtual_keyboard *keyboard = data;
-
- if (keyboard->preferred_language)
- free(keyboard->preferred_language);
+ struct virtual_keyboard *virtual_keyboard = data;
- keyboard->preferred_language = NULL;
-
- if (language)
- keyboard->preferred_language = strdup(language);
+ virtual_keyboard->current.active = false;
+ zwp_input_method_v2_destroy(virtual_keyboard->input_method);
+ virtual_keyboard->input_method = NULL;
+ keyboard_set_visibility(virtual_keyboard, false);
}
-static const struct zwp_input_method_context_v1_listener input_method_context_listener = {
+static const struct zwp_input_method_v2_listener input_method_listener = {
+ input_method_activate,
+ input_method_deactivate,
handle_surrounding_text,
- handle_reset,
+ handle_text_change_cause,
handle_content_type,
- handle_invoke_action,
handle_commit_state,
- handle_preferred_language
+ handle_unavailable
};
static void
-input_method_activate(void *data,
- struct zwp_input_method_v1 *input_method,
- struct zwp_input_method_context_v1 *context)
+make_input_method(struct virtual_keyboard *virtual_keyboard)
{
- struct virtual_keyboard *keyboard = data;
- struct wl_array modifiers_map;
- const struct layout *layout;
-
- keyboard->keyboard->state = KEYBOARD_STATE_DEFAULT;
-
- if (keyboard->context)
- zwp_input_method_context_v1_destroy(keyboard->context);
-
- if (keyboard->preedit_string)
- free(keyboard->preedit_string);
-
- keyboard->preedit_string = strdup("");
- keyboard->content_hint = 0;
- keyboard->content_purpose = 0;
- free(keyboard->preferred_language);
- keyboard->preferred_language = NULL;
- free(keyboard->surrounding_text);
- keyboard->surrounding_text = NULL;
-
- keyboard->serial = 0;
-
- keyboard->context = context;
- zwp_input_method_context_v1_add_listener(context,
- &input_method_context_listener,
- keyboard);
-
- wl_array_init(&modifiers_map);
- keysym_modifiers_add(&modifiers_map, "Shift");
- keysym_modifiers_add(&modifiers_map, "Control");
- keysym_modifiers_add(&modifiers_map, "Mod1");
- zwp_input_method_context_v1_modifiers_map(context, &modifiers_map);
- keyboard->keysym.shift_mask = keysym_modifiers_get_mask(&modifiers_map, "Shift");
- wl_array_release(&modifiers_map);
-
- layout = get_current_layout(keyboard);
-
- window_schedule_resize(keyboard->keyboard->window,
- layout->columns * key_width,
- layout->rows * key_height);
-
- zwp_input_method_context_v1_language(context,
- keyboard->serial,
- layout->language);
- zwp_input_method_context_v1_text_direction(context,
- keyboard->serial,
- layout->text_direction);
-
- widget_schedule_redraw(keyboard->keyboard->widget);
+ virtual_keyboard->input_method =
+ zwp_input_method_manager_v2_get_input_method(
+ virtual_keyboard->input_method_manager, virtual_keyboard->seat);
+ zwp_input_method_v2_add_listener(virtual_keyboard->input_method,
+ &input_method_listener, virtual_keyboard);
}
static void
-input_method_deactivate(void *data,
- struct zwp_input_method_v1 *input_method,
- struct zwp_input_method_context_v1 *context)
+make_virtual_keyboard(struct virtual_keyboard *virtual_keyboard)
{
- struct virtual_keyboard *keyboard = data;
-
- if (!keyboard->context)
- return;
-
- zwp_input_method_context_v1_destroy(keyboard->context);
- keyboard->context = NULL;
+ virtual_keyboard->virtual_keyboard =
+ zwp_virtual_keyboard_manager_v1_create_virtual_keyboard(
+ virtual_keyboard->virtual_keyboard_manager, virtual_keyboard->seat);
}
-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 virtual_keyboard *keyboard = data;
- if (!strcmp(interface, "zwp_input_panel_v1")) {
+ if (!strcmp(interface, "weston_input_panel")) {
keyboard->input_panel =
- display_bind(display, name, &zwp_input_panel_v1_interface, 1);
- } else if (!strcmp(interface, "zwp_input_method_v1")) {
- keyboard->input_method =
display_bind(display, name,
- &zwp_input_method_v1_interface, 1);
- zwp_input_method_v1_add_listener(keyboard->input_method,
- &input_method_listener,
- keyboard);
+ &weston_input_panel_interface, 1);
+ } else if (!strcmp(interface, "zwp_input_method_manager_v2")) {
+ keyboard->input_method_manager =
+ display_bind(display, name,
+ &zwp_input_method_manager_v2_interface, 1);
+ } else if (!strcmp(interface, "zwp_virtual_keyboard_manager_v1")) {
+ keyboard->virtual_keyboard_manager =
+ display_bind(display, name,
+ &zwp_virtual_keyboard_manager_v1_interface, 1);
}
+
}
static void
set_toplevel(struct output *output, struct virtual_keyboard *virtual_keyboard)
{
- struct zwp_input_panel_surface_v1 *ips;
+ struct weston_input_panel_surface *ips;
struct keyboard *keyboard = virtual_keyboard->keyboard;
- ips = zwp_input_panel_v1_get_input_panel_surface(virtual_keyboard->input_panel,
+ ips = weston_input_panel_get_input_panel_surface(virtual_keyboard->input_panel,
window_get_wl_surface(keyboard->window));
- zwp_input_panel_surface_v1_set_toplevel(ips,
+ weston_input_panel_surface_set_toplevel(ips,
output_get_wl_output(output),
- ZWP_INPUT_PANEL_SURFACE_V1_POSITION_CENTER_BOTTOM);
+ WESTON_INPUT_PANEL_SURFACE_POSITION_CENTER_BOTTOM);
virtual_keyboard->toplevel = true;
}
static void
-display_output_handler(struct output *output, void *data) {
+display_output_handler(struct output *output, void *data)
+{
struct virtual_keyboard *keyboard = data;
- if (!keyboard->toplevel)
+ if (!keyboard->toplevel && keyboard->keyboard->window)
set_toplevel(output, keyboard);
}
static void
-keyboard_create(struct virtual_keyboard *virtual_keyboard)
+keyboard_window_create(struct virtual_keyboard *virtual_keyboard)
{
- struct keyboard *keyboard;
+ struct keyboard *keyboard = virtual_keyboard->keyboard;
const struct layout *layout;
+ if (keyboard->window)
+ return;
+
layout = get_current_layout(virtual_keyboard);
- keyboard = xzalloc(sizeof *keyboard);
- keyboard->keyboard = virtual_keyboard;
keyboard->window = window_create_custom(virtual_keyboard->display);
keyboard->widget = window_add_widget(keyboard->window, keyboard);
- virtual_keyboard->keyboard = keyboard;
-
window_set_title(keyboard->window, "Virtual keyboard");
window_set_user_data(keyboard->window, keyboard);
@@ -1005,6 +943,38 @@ keyboard_create(struct virtual_keyboard *virtual_keyboard)
window_schedule_resize(keyboard->window,
layout->columns * key_width,
layout->rows * key_height);
+}
+
+static void
+keyboard_window_destroy(struct virtual_keyboard *virtual_keyboard)
+{
+ if (!virtual_keyboard->keyboard->window)
+ return;
+
+ widget_destroy(virtual_keyboard->keyboard->widget);
+ virtual_keyboard->keyboard->widget = NULL;
+ window_destroy(virtual_keyboard->keyboard->window);
+ virtual_keyboard->keyboard->window = NULL;
+}
+
+static void
+keyboard_set_visibility(struct virtual_keyboard *virtual_keyboard,
+ bool visible)
+{
+ if (visible)
+ keyboard_window_create(virtual_keyboard);
+ else
+ keyboard_window_destroy(virtual_keyboard);
+}
+
+static void
+keyboard_create(struct virtual_keyboard *virtual_keyboard)
+{
+ struct keyboard *keyboard;
+
+ keyboard = xzalloc(sizeof *keyboard);
+ keyboard->keyboard = virtual_keyboard;
+ virtual_keyboard->keyboard = keyboard;
display_set_output_configure_handler(virtual_keyboard->display,
display_output_handler);
@@ -1026,13 +996,35 @@ main(int argc, char *argv[])
display_set_user_data(virtual_keyboard.display, &virtual_keyboard);
display_set_global_handler(virtual_keyboard.display, global_handler);
+ virtual_keyboard.seat = display_get_seat(virtual_keyboard.display);
+
+ if (virtual_keyboard.seat == NULL) {
+ fprintf(stderr, "No seat available\n");
+ return -1;
+ }
+
+ if (virtual_keyboard.input_method_manager == NULL) {
+ fprintf(stderr, "No input method manager global\n");
+ return -1;
+ }
+
+ if (virtual_keyboard.virtual_keyboard_manager == NULL) {
+ fprintf(stderr, "No virtual keyboard manager global\n");
+ return -1;
+ }
+
if (virtual_keyboard.input_panel == NULL) {
fprintf(stderr, "No input panel global\n");
return -1;
}
+ make_input_method(&virtual_keyboard);
+ make_virtual_keyboard(&virtual_keyboard);
+
keyboard_create(&virtual_keyboard);
+ keyboard_set_visibility(&virtual_keyboard, true);
+
display_run(virtual_keyboard.display);
return 0;
diff --git a/clients/meson.build b/clients/meson.build
index 47e9e8ce..c1885c50 100644
--- a/clients/meson.build
+++ b/clients/meson.build
@@ -342,10 +342,14 @@ if get_option('shell-desktop')
exe_keyboard = executable(
'weston-keyboard',
'keyboard.c',
- text_input_unstable_v1_client_protocol_h,
- text_input_unstable_v1_protocol_c,
- input_method_unstable_v1_client_protocol_h,
- input_method_unstable_v1_protocol_c,
+ input_method_unstable_v2_client_protocol_h,
+ input_method_unstable_v2_protocol_c,
+ text_input_unstable_v3_client_protocol_h,
+ text_input_unstable_v3_protocol_c,
+ virtual_keyboard_unstable_v1_client_protocol_h,
+ virtual_keyboard_unstable_v1_protocol_c,
+ weston_input_panel_client_protocol_h,
+ weston_input_panel_protocol_c,
include_directories: include_directories('..'),
dependencies: dep_toytoolkit,
install_dir: get_option('libexecdir'),
diff --git a/clients/window.c b/clients/window.c
index bb9c708f..8e933f9b 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -6317,6 +6317,15 @@ display_get_compositor(struct display *display)
return display->compositor;
}
+struct wl_seat *
+display_get_seat(struct display *display)
+{
+ if (wl_list_empty(&display->input_list))
+ return NULL;
+
+ return container_of(display->input_list.next, struct input, link)->seat;
+}
+
uint32_t
display_get_serial(struct display *display)
{
diff --git a/clients/window.h b/clients/window.h
index fde5c2f0..13ceddee 100644
--- a/clients/window.h
+++ b/clients/window.h
@@ -77,6 +77,9 @@ display_get_cairo_device(struct display *display);
struct wl_compositor *
display_get_compositor(struct display *display);
+struct wl_seat *
+display_get_seat(struct display *display);
+
struct output *
display_get_output(struct display *display);
diff --git a/compositor/meson.build b/compositor/meson.build
index d5d7282f..7dba3373 100644
--- a/compositor/meson.build
+++ b/compositor/meson.build
@@ -3,10 +3,14 @@ srcs_weston = [
'main.c',
'text-backend.c',
'weston-screenshooter.c',
- text_input_unstable_v1_server_protocol_h,
- text_input_unstable_v1_protocol_c,
- input_method_unstable_v1_server_protocol_h,
- input_method_unstable_v1_protocol_c,
+ input_method_unstable_v2_server_protocol_h,
+ input_method_unstable_v2_protocol_c,
+ text_input_unstable_v3_server_protocol_h,
+ text_input_unstable_v3_protocol_c,
+ virtual_keyboard_unstable_v1_server_protocol_h,
+ virtual_keyboard_unstable_v1_protocol_c,
+ weston_input_panel_server_protocol_h,
+ weston_input_panel_protocol_c,
weston_screenshooter_server_protocol_h,
weston_screenshooter_protocol_c,
]
diff --git a/compositor/text-backend.c b/compositor/text-backend.c
index 03019584..3dd2f09f 100644
--- a/compositor/text-backend.c
+++ b/compositor/text-backend.c
@@ -1,6 +1,7 @@
/*
* Copyright © 2012 Openismus GmbH
* Copyright © 2012 Intel Corporation
+ * Copyright © 2019 Collabora Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@@ -33,32 +34,63 @@
#include <unistd.h>
#include <time.h>
+#include <linux/input.h>
+
#include "compositor.h"
#include "weston.h"
-#include "text-input-unstable-v1-server-protocol.h"
-#include "input-method-unstable-v1-server-protocol.h"
+#include "input-method-unstable-v2-server-protocol.h"
+#include "text-input-unstable-v3-server-protocol.h"
+#include "virtual-keyboard-unstable-v1-server-protocol.h"
#include "shared/helpers.h"
#include "shared/timespec-util.h"
-struct text_input_manager;
struct input_method;
-struct input_method_context;
+struct input_method_manager;
+struct virtual_keyboard;
+struct virtual_keyboard_manager;
struct text_backend;
+struct text_input_manager;
+
+struct text_input_state {
+ struct {
+ char *text; // NULL is allowed and equivalent to empty string
+ uint32_t cursor;
+ uint32_t anchor;
+ } surrounding;
+
+ uint32_t text_change_cause;
+
+ struct {
+ uint32_t hint;
+ uint32_t purpose;
+ } content_type;
+
+ pixman_box32_t cursor_rectangle;
+};
struct text_input {
struct wl_resource *resource;
struct weston_compositor *ec;
- struct wl_list input_methods;
+ struct weston_seat *seat;
- struct weston_surface *surface;
+ struct input_method *input_method;
- pixman_box32_t cursor_rectangle;
+ struct weston_surface *surface;
bool input_panel_visible;
struct text_input_manager *manager;
+
+ uint32_t current_serial;
+
+ bool pending_enabled;
+ bool current_enabled;
+ struct text_input_state pending;
+ struct text_input_state current;
+
+ struct wl_list link;
};
struct text_input_manager {
@@ -68,34 +100,77 @@ struct text_input_manager {
struct text_input *current_text_input;
struct weston_compositor *ec;
+
+ struct wl_list text_inputs;
+};
+
+struct input_method_state {
+ struct {
+ char *text;
+ int32_t cursor_begin;
+ int32_t cursor_end;
+ } preedit;
+
+ char *commit_text;
+
+ struct {
+ uint32_t before_length;
+ uint32_t after_length;
+ } delete;
};
struct input_method {
- struct wl_resource *input_method_binding;
- struct wl_global *input_method_global;
- struct wl_listener destroy_listener;
+ struct wl_resource *resource;
+
+ struct weston_compositor *ec;
struct weston_seat *seat;
struct text_input *input;
- struct wl_list link;
-
struct wl_listener keyboard_focus_listener;
bool focus_listener_initialized;
- struct input_method_context *context;
+ struct wl_resource *keyboard;
- struct text_backend *text_backend;
+ struct input_method_manager *manager;
+
+ struct weston_surface *pending_focused_surface;
+
+ struct input_method_state pending;
+ struct input_method_state current;
+
+ struct wl_list link;
+};
+
+struct input_method_manager {
+ struct wl_global *input_method_manager_global;
+ struct wl_listener destroy_listener;
+
+ struct weston_compositor *ec;
+
+ struct wl_list input_methods;
};
-struct input_method_context {
+struct virtual_keyboard {
struct wl_resource *resource;
- struct text_input *input;
- struct input_method *input_method;
+ struct weston_compositor *ec;
- struct wl_resource *keyboard;
+ struct weston_seat *seat;
+
+ struct virtual_keyboard_manager *manager;
+
+ struct wl_list link;
+};
+
+struct virtual_keyboard_manager {
+ struct wl_global *virtual_keyboard_manager_global;
+ struct wl_listener destroy_listener;
+
+ struct weston_compositor *ec;
+
+ struct wl_list virtual_keyboards;
};
struct text_backend {
@@ -110,37 +185,36 @@ struct text_backend {
} input_method;
struct wl_listener client_listener;
- struct wl_listener seat_created_listener;
};
static void
-input_method_context_create(struct text_input *input,
- struct input_method *input_method);
-static void
-input_method_context_end_keyboard_grab(struct input_method_context *context);
+input_method_end_keyboard_grab(struct input_method *input_method);
static void
input_method_init_seat(struct weston_seat *seat);
+static void
+text_input_show_input_panel(struct text_input *text_input);
+
static void
deactivate_input_method(struct input_method *input_method)
{
- struct text_input *text_input = input_method->input;
- struct weston_compositor *ec = text_input->ec;
-
- if (input_method->context && input_method->input_method_binding) {
- input_method_context_end_keyboard_grab(input_method->context);
- zwp_input_method_v1_send_deactivate(
- input_method->input_method_binding,
- input_method->context->resource);
- input_method->context->input = NULL;
+ if (input_method->resource) {
+ input_method_end_keyboard_grab(input_method);
+ zwp_input_method_v2_send_deactivate(input_method->resource);
}
+ if (input_method->input) {
+ input_method->input->input_method = NULL;
+ input_method->input = NULL;
+ }
+}
- wl_list_remove(&input_method->link);
- input_method->input = NULL;
- input_method->context = NULL;
+static void
+deactivate_text_input(struct text_input *text_input)
+{
+ struct weston_compositor *ec = text_input->ec;
- if (wl_list_empty(&text_input->input_methods) &&
+ if (text_input->input_method &&
text_input->input_panel_visible &&
text_input->manager->current_text_input == text_input) {
wl_signal_emit(&ec->hide_input_panel_signal, ec);
@@ -150,18 +224,30 @@ deactivate_input_method(struct input_method *input_method)
if (text_input->manager->current_text_input == text_input)
text_input->manager->current_text_input = NULL;
- zwp_text_input_v1_send_leave(text_input->resource);
+ if (text_input->input_method)
+ text_input->input_method->input = NULL;
+ text_input->input_method = NULL;
+
+ if (text_input->surface) {
+ zwp_text_input_v3_send_leave(text_input->resource,
+ text_input->surface->resource);
+ }
+ text_input->surface = NULL;
}
static void
destroy_text_input(struct wl_resource *resource)
{
struct text_input *text_input = wl_resource_get_user_data(resource);
- struct input_method *input_method, *next;
- wl_list_for_each_safe(input_method, next,
- &text_input->input_methods, link)
- deactivate_input_method(input_method);
+ deactivate_text_input(text_input);
+
+ if (text_input->current.surrounding.text)
+ free(text_input->current.surrounding.text);
+ if (text_input->pending.surrounding.text)
+ free(text_input->pending.surrounding.text);
+
+ wl_list_remove(&text_input->link);
free(text_input);
}
@@ -170,95 +256,69 @@ static void
text_input_set_surrounding_text(struct wl_client *client,
struct wl_resource *resource,
const char *text,
- uint32_t cursor,
- uint32_t anchor)
+ int32_t cursor,
+ int32_t anchor)
{
struct text_input *text_input = wl_resource_get_user_data(resource);
- struct input_method *input_method, *next;
-
- wl_list_for_each_safe(input_method, next,
- &text_input->input_methods, link) {
- if (!input_method->context)
- continue;
- zwp_input_method_context_v1_send_surrounding_text(
- input_method->context->resource, text, cursor, anchor);
- }
+
+ if (text_input->pending.surrounding.text)
+ free(text_input->pending.surrounding.text);
+ text_input->pending.surrounding.text = strdup(text);
+ text_input->pending.surrounding.cursor = cursor;
+ text_input->pending.surrounding.anchor = anchor;
}
static void
-text_input_activate(struct wl_client *client,
- struct wl_resource *resource,
- struct wl_resource *seat,
- struct wl_resource *surface)
+activate_text_input(struct text_input *text_input)
{
- struct text_input *text_input = wl_resource_get_user_data(resource);
- struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
+ struct weston_seat *weston_seat = text_input->seat;
struct input_method *input_method;
- struct weston_compositor *ec = text_input->ec;
- struct text_input *current;
if (!weston_seat)
return;
input_method = weston_seat->input_method;
- if (input_method->input == text_input)
+ if (!input_method || input_method->input == text_input)
return;
- if (input_method->input)
- deactivate_input_method(input_method);
+ if (!input_method->pending_focused_surface)
+ return;
input_method->input = text_input;
- wl_list_insert(&text_input->input_methods, &input_method->link);
- input_method_init_seat(weston_seat);
-
- text_input->surface = wl_resource_get_user_data(surface);
-
- input_method_context_create(text_input, input_method);
+ text_input->input_method = input_method;
- current = text_input->manager->current_text_input;
+ text_input->surface = input_method->pending_focused_surface;
- if (current && current != text_input) {
- current->input_panel_visible = false;
- wl_signal_emit(&ec->hide_input_panel_signal, ec);
- }
+ zwp_input_method_v2_send_activate(input_method->resource);
- if (text_input->input_panel_visible) {
- wl_signal_emit(&ec->show_input_panel_signal,
- text_input->surface);
- wl_signal_emit(&ec->update_input_panel_signal,
- &text_input->cursor_rectangle);
- }
text_input->manager->current_text_input = text_input;
- zwp_text_input_v1_send_enter(text_input->resource,
+ text_input_show_input_panel(text_input);
+
+ zwp_text_input_v3_send_enter(text_input->resource,
text_input->surface->resource);
}
static void
-text_input_deactivate(struct wl_client *client,
- struct wl_resource *resource,
- struct wl_resource *seat)
+text_input_enable(struct wl_client *client,
+ struct wl_resource *resource)
{
- struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
+ struct text_input *text_input = wl_resource_get_user_data(resource);
+ struct text_input_state defaults = {0};
- if (weston_seat && weston_seat->input_method->input)
- deactivate_input_method(weston_seat->input_method);
+ if (text_input->pending.surrounding.text)
+ free(text_input->pending.surrounding.text);
+ text_input->pending = defaults;
+ text_input->pending_enabled = true;
}
static void
-text_input_reset(struct wl_client *client,
- struct wl_resource *resource)
+text_input_disable(struct wl_client *client,
+ struct wl_resource *resource)
{
struct text_input *text_input = wl_resource_get_user_data(resource);
- struct input_method *input_method, *next;
-
- wl_list_for_each_safe(input_method, next,
- &text_input->input_methods, link) {
- if (!input_method->context)
- continue;
- zwp_input_method_context_v1_send_reset(
- input_method->context->resource);
- }
+
+ text_input->pending_enabled = false;
}
static void
@@ -270,15 +330,11 @@ text_input_set_cursor_rectangle(struct wl_client *client,
int32_t height)
{
struct text_input *text_input = wl_resource_get_user_data(resource);
- struct weston_compositor *ec = text_input->ec;
- text_input->cursor_rectangle.x1 = x;
- text_input->cursor_rectangle.y1 = y;
- text_input->cursor_rectangle.x2 = x + width;
- text_input->cursor_rectangle.y2 = y + height;
-
- wl_signal_emit(&ec->update_input_panel_signal,
- &text_input->cursor_rectangle);
+ text_input->pending.cursor_rectangle.x1 = x;
+ text_input->pending.cursor_rectangle.y1 = y;
+ text_input->pending.cursor_rectangle.x2 = x + width;
+ text_input->pending.cursor_rectangle.y2 = y + height;
}
static void
@@ -288,141 +344,139 @@ text_input_set_content_type(struct wl_client *client,
uint32_t purpose)
{
struct text_input *text_input = wl_resource_get_user_data(resource);
- struct input_method *input_method, *next;
-
- wl_list_for_each_safe(input_method, next,
- &text_input->input_methods, link) {
- if (!input_method->context)
- continue;
- zwp_input_method_context_v1_send_content_type(
- input_method->context->resource, hint, purpose);
- }
+
+ text_input->pending.content_type.hint = hint;
+ text_input->pending.content_type.purpose = purpose;
}
static void
-text_input_invoke_action(struct wl_client *client,
- struct wl_resource *resource,
- uint32_t button,
- uint32_t index)
+text_input_commit(struct wl_client *client,
+ struct wl_resource *resource)
{
struct text_input *text_input = wl_resource_get_user_data(resource);
- struct input_method *input_method, *next;
-
- wl_list_for_each_safe(input_method, next,
- &text_input->input_methods, link) {
- if (!input_method->context)
- continue;
- zwp_input_method_context_v1_send_invoke_action(
- input_method->context->resource, button, index);
+ struct weston_compositor *ec = text_input->ec;
+ struct input_method *input_method;
+ bool old_enabled;
+
+ text_input->current_serial++;
+ text_input->current = text_input->pending;
+ if (text_input->pending.surrounding.text)
+ text_input->current.surrounding.text =
+ strdup(text_input->pending.surrounding.text);
+
+ old_enabled = text_input->current_enabled;
+ text_input->current_enabled = text_input->pending_enabled;
+
+ input_method = text_input->input_method;
+ if (!old_enabled && text_input->current_enabled)
+ activate_text_input(text_input);
+ else if (old_enabled && !text_input->current_enabled) {
+ deactivate_text_input(text_input);
}
-}
-static void
-text_input_commit_state(struct wl_client *client,
- struct wl_resource *resource,
- uint32_t serial)
-{
- struct text_input *text_input = wl_resource_get_user_data(resource);
- struct input_method *input_method, *next;
-
- wl_list_for_each_safe(input_method, next,
- &text_input->input_methods, link) {
- if (!input_method->context)
- continue;
- zwp_input_method_context_v1_send_commit_state(
- input_method->context->resource, serial);
+ if (input_method) {
+ if (text_input->current.surrounding.text) {
+ zwp_input_method_v2_send_surrounding_text(
+ input_method->resource,
+ text_input->current.surrounding.text,
+ text_input->current.surrounding.cursor,
+ text_input->current.surrounding.anchor);
+ }
+ zwp_input_method_v2_send_text_change_cause(
+ input_method->resource,
+ text_input->current.text_change_cause);
+ zwp_input_method_v2_send_content_type(
+ input_method->resource,
+ text_input->current.content_type.hint,
+ text_input->current.content_type.purpose);
+ wl_signal_emit(&ec->update_input_panel_signal,
+ &text_input->current.cursor_rectangle);
+ zwp_input_method_v2_send_done(input_method->resource);
}
}
static void
-text_input_show_input_panel(struct wl_client *client,
- struct wl_resource *resource)
+text_input_show_input_panel(struct text_input *text_input)
{
- struct text_input *text_input = wl_resource_get_user_data(resource);
struct weston_compositor *ec = text_input->ec;
text_input->input_panel_visible = true;
- if (!wl_list_empty(&text_input->input_methods) &&
+ if (text_input->input_method &&
text_input == text_input->manager->current_text_input) {
wl_signal_emit(&ec->show_input_panel_signal,
text_input->surface);
wl_signal_emit(&ec->update_input_panel_signal,
- &text_input->cursor_rectangle);
+ &text_input->current.cursor_rectangle);
}
}
static void
-text_input_hide_input_panel(struct wl_client *client,
- struct wl_resource *resource)
+text_input_destroy(struct wl_client *client,
+ struct wl_resource *resource)
{
- struct text_input *text_input = wl_resource_get_user_data(resource);
- struct weston_compositor *ec = text_input->ec;
-
- text_input->input_panel_visible = false;
-
- if (!wl_list_empty(&text_input->input_methods) &&
- text_input == text_input->manager->current_text_input)
- wl_signal_emit(&ec->hide_input_panel_signal, ec);
+ wl_resource_destroy(resource);
}
static void
-text_input_set_preferred_language(struct wl_client *client,
- struct wl_resource *resource,
- const char *language)
+text_input_set_text_change_cause(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t cause)
{
struct text_input *text_input = wl_resource_get_user_data(resource);
- struct input_method *input_method, *next;
-
- wl_list_for_each_safe(input_method, next,
- &text_input->input_methods, link) {
- if (!input_method->context)
- continue;
- zwp_input_method_context_v1_send_preferred_language(
- input_method->context->resource, language);
- }
+
+ text_input->pending.text_change_cause = cause;
}
-static const struct zwp_text_input_v1_interface text_input_implementation = {
- text_input_activate,
- text_input_deactivate,
- text_input_show_input_panel,
- text_input_hide_input_panel,
- text_input_reset,
+static const struct zwp_text_input_v3_interface text_input_implementation = {
+ text_input_destroy,
+ text_input_enable,
+ text_input_disable,
text_input_set_surrounding_text,
+ text_input_set_text_change_cause,
text_input_set_content_type,
text_input_set_cursor_rectangle,
- text_input_set_preferred_language,
- text_input_commit_state,
- text_input_invoke_action
+ text_input_commit,
};
-static void text_input_manager_create_text_input(struct wl_client *client,
- struct wl_resource *resource,
- uint32_t id)
+static void
+text_input_manager_destroy(struct wl_client *client,
+ struct wl_resource *resource)
+{
+ wl_resource_destroy(resource);
+}
+
+static void text_input_manager_get_text_input(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t id,
+ struct wl_resource *seat)
{
struct text_input_manager *text_input_manager =
wl_resource_get_user_data(resource);
struct text_input *text_input;
+ struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
text_input = zalloc(sizeof *text_input);
if (text_input == NULL)
return;
text_input->resource =
- wl_resource_create(client, &zwp_text_input_v1_interface, 1, id);
+ wl_resource_create(client, &zwp_text_input_v3_interface, 1, id);
wl_resource_set_implementation(text_input->resource,
&text_input_implementation,
text_input, destroy_text_input);
text_input->ec = text_input_manager->ec;
text_input->manager = text_input_manager;
+ text_input->seat = weston_seat;
+ text_input->current_serial = 0;
- wl_list_init(&text_input->input_methods);
+ wl_list_insert(&text_input_manager->text_inputs, &text_input->link);
};
-static const struct zwp_text_input_manager_v1_interface manager_implementation = {
- text_input_manager_create_text_input
+static const struct zwp_text_input_manager_v3_interface text_input_manager_implementation = {
+ text_input_manager_destroy,
+ text_input_manager_get_text_input
};
static void
@@ -437,10 +491,10 @@ bind_text_input_manager(struct wl_client *client,
/* No checking for duplicate binding necessary. */
resource =
wl_resource_create(client,
- &zwp_text_input_manager_v1_interface, 1, id);
+ &zwp_text_input_manager_v3_interface, 1, id);
if (resource)
wl_resource_set_implementation(resource,
- &manager_implementation,
+ &text_input_manager_implementation,
text_input_manager, NULL);
}
@@ -451,6 +505,12 @@ text_input_manager_notifier_destroy(struct wl_listener *listener, void *data)
container_of(listener,
struct text_input_manager,
destroy_listener);
+ struct text_input *text_input, *text_input_tmp;
+
+ wl_list_for_each_safe(text_input, text_input_tmp,
+ &text_input_manager->text_inputs, link) {
+ wl_resource_destroy(text_input->resource);
+ }
wl_list_remove(&text_input_manager->destroy_listener.link);
wl_global_destroy(text_input_manager->text_input_manager_global);
@@ -471,151 +531,113 @@ text_input_manager_create(struct weston_compositor *ec)
text_input_manager->text_input_manager_global =
wl_global_create(ec->wl_display,
- &zwp_text_input_manager_v1_interface, 1,
+ &zwp_text_input_manager_v3_interface, 1,
text_input_manager, bind_text_input_manager);
text_input_manager->destroy_listener.notify =
text_input_manager_notifier_destroy;
wl_signal_add(&ec->destroy_signal,
&text_input_manager->destroy_listener);
-}
-
-static void
-input_method_context_destroy(struct wl_client *client,
- struct wl_resource *resource)
-{
- wl_resource_destroy(resource);
-}
-
-static void
-input_method_context_commit_string(struct wl_client *client,
- struct wl_resource *resource,
- uint32_t serial,
- const char *text)
-{
- struct input_method_context *context =
- wl_resource_get_user_data(resource);
- if (context->input)
- zwp_text_input_v1_send_commit_string(context->input->resource,
- serial, text);
+ wl_list_init(&text_input_manager->text_inputs);
}
static void
-input_method_context_preedit_string(struct wl_client *client,
- struct wl_resource *resource,
- uint32_t serial,
- const char *text,
- const char *commit)
+input_method_destroy(struct wl_client *client,
+ struct wl_resource *resource)
{
- struct input_method_context *context =
- wl_resource_get_user_data(resource);
-
- if (context->input)
- zwp_text_input_v1_send_preedit_string(context->input->resource,
- serial, text, commit);
-}
-
-static void
-input_method_context_preedit_styling(struct wl_client *client,
- struct wl_resource *resource,
- uint32_t index,
- uint32_t length,
- uint32_t style)
-{
- struct input_method_context *context =
- wl_resource_get_user_data(resource);
-
- if (context->input)
- zwp_text_input_v1_send_preedit_styling(context->input->resource,
- index, length, style);
+ wl_resource_destroy(resource);
}
static void
-input_method_context_preedit_cursor(struct wl_client *client,
- struct wl_resource *resource,
- int32_t cursor)
+input_method_commit_string(struct wl_client *client,
+ struct wl_resource *resource,
+ const char *text)
{
- struct input_method_context *context =
- wl_resource_get_user_data(resource);
+ struct input_method *input_method = wl_resource_get_user_data(resource);
- if (context->input)
- zwp_text_input_v1_send_preedit_cursor(context->input->resource,
- cursor);
+ if (input_method->pending.commit_text)
+ free(input_method->pending.commit_text);
+ input_method->pending.commit_text = strdup(text);
}
static void
-input_method_context_delete_surrounding_text(struct wl_client *client,
- struct wl_resource *resource,
- int32_t index,
- uint32_t length)
+input_method_set_preedit_string(struct wl_client *client,
+ struct wl_resource *resource,
+ const char *text,
+ int32_t cursor_begin,
+ int32_t cursor_end)
{
- struct input_method_context *context =
- wl_resource_get_user_data(resource);
+ struct input_method *input_method = wl_resource_get_user_data(resource);
- if (context->input)
- zwp_text_input_v1_send_delete_surrounding_text(
- context->input->resource, index, length);
+ if (input_method->pending.preedit.text)
+ free(input_method->pending.preedit.text);
+ input_method->pending.preedit.text = strdup(text);
+ input_method->pending.preedit.cursor_begin = cursor_begin;
+ input_method->pending.preedit.cursor_end = cursor_end;
}
static void
-input_method_context_cursor_position(struct wl_client *client,
+input_method_delete_surrounding_text(struct wl_client *client,
struct wl_resource *resource,
- int32_t index,
- int32_t anchor)
+ uint32_t before_length,
+ uint32_t after_length)
{
- struct input_method_context *context =
- wl_resource_get_user_data(resource);
+ struct input_method *input_method = wl_resource_get_user_data(resource);
- if (context->input)
- zwp_text_input_v1_send_cursor_position(context->input->resource,
- index, anchor);
+ input_method->pending.delete.before_length = before_length;
+ input_method->pending.delete.after_length = after_length;
}
static void
-input_method_context_modifiers_map(struct wl_client *client,
- struct wl_resource *resource,
- struct wl_array *map)
+input_method_commit(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t serial)
{
- struct input_method_context *context =
- wl_resource_get_user_data(resource);
+ struct input_method *input_method = wl_resource_get_user_data(resource);
- if (context->input)
- zwp_text_input_v1_send_modifiers_map(context->input->resource,
- map);
-}
+ if (!input_method->input) {
+ return;
+ }
-static void
-input_method_context_keysym(struct wl_client *client,
- struct wl_resource *resource,
- uint32_t serial,
- uint32_t time,
- uint32_t sym,
- uint32_t state,
- uint32_t modifiers)
-{
- struct input_method_context *context =
- wl_resource_get_user_data(resource);
+ input_method->current = input_method->pending;
+ struct input_method_state default_state = {0};
+ input_method->pending = default_state;
- if (context->input)
- zwp_text_input_v1_send_keysym(context->input->resource,
- serial, time,
- sym, state, modifiers);
+ if (input_method->current.preedit.text) {
+ zwp_text_input_v3_send_preedit_string(input_method->input->resource,
+ input_method->current.preedit.text,
+ input_method->current.preedit.cursor_begin,
+ input_method->current.preedit.cursor_end);
+ }
+ if (input_method->current.commit_text) {
+ zwp_text_input_v3_send_commit_string(input_method->input->resource,
+ input_method->current.commit_text);
+ }
+ if (input_method->current.delete.before_length ||
+ input_method->current.delete.after_length) {
+ zwp_text_input_v3_send_delete_surrounding_text(input_method->input->resource,
+ input_method->current.delete.before_length,
+ input_method->current.delete.after_length);
+ }
+ zwp_text_input_v3_send_done(input_method->input->resource,
+ input_method->input->current_serial);
}
static void
unbind_keyboard(struct wl_resource *resource)
{
- struct input_method_context *context =
+ struct input_method *input_method =
wl_resource_get_user_data(resource);
- input_method_context_end_keyboard_grab(context);
- context->keyboard = NULL;
+ input_method_end_keyboard_grab(input_method);
+ input_method->keyboard = NULL;
}
static void
input_method_context_grab_key(struct weston_keyboard_grab *grab,
- const struct timespec *time, uint32_t key,
+ const struct timespec *time,
+ uint32_t key,
uint32_t state_w)
{
struct weston_keyboard *keyboard = grab->keyboard;
@@ -665,20 +687,20 @@ static const struct weston_keyboard_grab_interface input_method_context_grab = {
};
static void
-input_method_context_grab_keyboard(struct wl_client *client,
- struct wl_resource *resource,
- uint32_t id)
+input_method_grab_keyboard(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t id)
{
- struct input_method_context *context =
+ struct input_method *input_method =
wl_resource_get_user_data(resource);
struct wl_resource *cr;
- struct weston_seat *seat = context->input_method->seat;
+ struct weston_seat *seat = input_method->seat;
struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
cr = wl_resource_create(client, &wl_keyboard_interface, 1, id);
- wl_resource_set_implementation(cr, NULL, context, unbind_keyboard);
+ wl_resource_set_implementation(cr, NULL, input_method, unbind_keyboard);
- context->keyboard = cr;
+ input_method->keyboard = cr;
weston_keyboard_send_keymap(keyboard, cr);
@@ -690,16 +712,25 @@ input_method_context_grab_keyboard(struct wl_client *client,
}
static void
-input_method_context_key(struct wl_client *client,
- struct wl_resource *resource,
- uint32_t serial,
- uint32_t time,
- uint32_t key,
- uint32_t state_w)
+virtual_keyboard_keymap(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t format,
+ int32_t fd,
+ uint32_t size)
{
- struct input_method_context *context =
+ weston_log("stub: zwp_virtual_keyboard_v1_interface:keymap\n");
+}
+
+static void
+virtual_keyboard_key(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t time,
+ uint32_t key,
+ uint32_t state_w)
+{
+ struct virtual_keyboard *virtual_keyboard =
wl_resource_get_user_data(resource);
- struct weston_seat *seat = context->input_method->seat;
+ struct weston_seat *seat = virtual_keyboard->seat;
struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
struct timespec ts;
@@ -710,20 +741,20 @@ input_method_context_key(struct wl_client *client,
}
static void
-input_method_context_modifiers(struct wl_client *client,
- struct wl_resource *resource,
- uint32_t serial,
- uint32_t mods_depressed,
- uint32_t mods_latched,
- uint32_t mods_locked,
- uint32_t group)
+virtual_keyboard_modifiers(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t mods_depressed,
+ uint32_t mods_latched,
+ uint32_t mods_locked,
+ uint32_t group)
{
- struct input_method_context *context =
+ struct virtual_keyboard *virtual_keyboard =
wl_resource_get_user_data(resource);
- struct weston_seat *seat = context->input_method->seat;
+ struct weston_seat *seat = virtual_keyboard->seat;
struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
+ int serial = wl_display_next_serial(virtual_keyboard->ec->wl_display);
default_grab->interface->modifiers(default_grab,
serial, mods_depressed,
@@ -732,104 +763,12 @@ input_method_context_modifiers(struct wl_client *client,
}
static void
-input_method_context_language(struct wl_client *client,
- struct wl_resource *resource,
- uint32_t serial,
- const char *language)
-{
- struct input_method_context *context =
- wl_resource_get_user_data(resource);
-
- if (context->input)
- zwp_text_input_v1_send_language(context->input->resource,
- serial, language);
-}
-
-static void
-input_method_context_text_direction(struct wl_client *client,
- struct wl_resource *resource,
- uint32_t serial,
- uint32_t direction)
-{
- struct input_method_context *context =
- wl_resource_get_user_data(resource);
-
- if (context->input)
- zwp_text_input_v1_send_text_direction(context->input->resource,
- serial, direction);
-}
-
-
-static const struct zwp_input_method_context_v1_interface context_implementation = {
- input_method_context_destroy,
- input_method_context_commit_string,
- input_method_context_preedit_string,
- input_method_context_preedit_styling,
- input_method_context_preedit_cursor,
- input_method_context_delete_surrounding_text,
- input_method_context_cursor_position,
- input_method_context_modifiers_map,
- input_method_context_keysym,
- input_method_context_grab_keyboard,
- input_method_context_key,
- input_method_context_modifiers,
- input_method_context_language,
- input_method_context_text_direction
-};
-
-static void
-destroy_input_method_context(struct wl_resource *resource)
-{
- struct input_method_context *context =
- wl_resource_get_user_data(resource);
-
- if (context->keyboard)
- wl_resource_destroy(context->keyboard);
-
- if (context->input_method && context->input_method->context == context)
- context->input_method->context = NULL;
-
- free(context);
-}
-
-static void
-input_method_context_create(struct text_input *input,
- struct input_method *input_method)
-{
- struct input_method_context *context;
- struct wl_resource *binding;
-
- if (!input_method->input_method_binding)
- return;
-
- context = zalloc(sizeof *context);
- if (context == NULL)
- return;
-
- binding = input_method->input_method_binding;
- context->resource =
- wl_resource_create(wl_resource_get_client(binding),
- &zwp_input_method_context_v1_interface,
- 1, 0);
- wl_resource_set_implementation(context->resource,
- &context_implementation,
- context, destroy_input_method_context);
-
- context->input = input;
- context->input_method = input_method;
- input_method->context = context;
-
-
- zwp_input_method_v1_send_activate(binding, context->resource);
-}
-
-static void
-input_method_context_end_keyboard_grab(struct input_method_context *context)
+input_method_end_keyboard_grab(struct input_method *input_method)
{
struct weston_keyboard_grab *grab;
struct weston_keyboard *keyboard;
- keyboard = weston_seat_get_keyboard(context->input_method->seat);
+ keyboard = weston_seat_get_keyboard(input_method->seat);
if (!keyboard)
return;
@@ -844,64 +783,6 @@ input_method_context_end_keyboard_grab(struct input_method_context *context)
keyboard->input_method_resource = NULL;
}
-static void
-unbind_input_method(struct wl_resource *resource)
-{
- struct input_method *input_method = wl_resource_get_user_data(resource);
-
- input_method->input_method_binding = NULL;
- input_method->context = NULL;
-}
-
-static void
-bind_input_method(struct wl_client *client,
- void *data,
- uint32_t version,
- uint32_t id)
-{
- struct input_method *input_method = data;
- struct text_backend *text_backend = input_method->text_backend;
- struct wl_resource *resource;
-
- resource =
- wl_resource_create(client,
- &zwp_input_method_v1_interface, 1, id);
-
- if (input_method->input_method_binding != NULL) {
- wl_resource_post_error(resource,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "interface object already bound");
- return;
- }
-
- if (text_backend->input_method.client != client) {
- wl_resource_post_error(resource,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "permission to bind "
- "input_method denied");
- return;
- }
-
- wl_resource_set_implementation(resource, NULL, input_method,
- unbind_input_method);
- input_method->input_method_binding = resource;
-}
-
-static void
-input_method_notifier_destroy(struct wl_listener *listener, void *data)
-{
- struct input_method *input_method =
- container_of(listener, struct input_method, destroy_listener);
-
- if (input_method->input)
- deactivate_input_method(input_method);
-
- wl_global_destroy(input_method->input_method_global);
- wl_list_remove(&input_method->destroy_listener.link);
-
- free(input_method);
-}
-
static void
handle_keyboard_focus(struct wl_listener *listener, void *data)
{
@@ -911,11 +792,16 @@ handle_keyboard_focus(struct wl_listener *listener, void *data)
keyboard_focus_listener);
struct weston_surface *surface = keyboard->focus;
- if (!input_method->input)
+ if (!input_method->input) {
+ input_method->pending_focused_surface = surface;
return;
+ }
- if (!surface || input_method->input->surface != surface)
- deactivate_input_method(input_method);
+ if (!surface || input_method->input->surface != surface) {
+ deactivate_text_input(input_method->input);
+ }
+
+ input_method->pending_focused_surface = surface;
}
static void
@@ -1001,43 +887,282 @@ launch_input_method(struct text_backend *text_backend)
&text_backend->client_listener);
}
+static void input_method_get_input_popup_surface(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t id,
+ struct wl_resource *surface)
+{
+ weston_log("stub: zwp_input_method_v2_interface:get_input_popup_surface\n");
+}
+
+static const struct zwp_input_method_v2_interface input_method_implementation = {
+ input_method_commit_string,
+ input_method_set_preedit_string,
+ input_method_delete_surrounding_text,
+ input_method_commit,
+ input_method_get_input_popup_surface,
+ input_method_grab_keyboard,
+ input_method_destroy,
+};
+
static void
-text_backend_seat_created(struct text_backend *text_backend,
- struct weston_seat *seat)
+destroy_input_method(struct wl_resource *resource)
{
+ struct input_method *input_method =
+ wl_resource_get_user_data(resource);
+
+ if (input_method->keyboard)
+ wl_resource_destroy(input_method->keyboard);
+
+ if (input_method->input)
+ deactivate_input_method(input_method);
+
+ if (input_method->pending.commit_text)
+ free(input_method->pending.commit_text);
+ if (input_method->pending.preedit.text)
+ free(input_method->pending.preedit.text);
+ if (input_method->current.commit_text)
+ free(input_method->current.commit_text);
+ if (input_method->current.preedit.text)
+ free(input_method->current.preedit.text);
+
+ wl_list_remove(&input_method->link);
+
+ free(input_method);
+}
+
+static void
+input_method_manager_get_input_method(struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *seat,
+ uint32_t id)
+{
+ struct input_method_manager *input_method_manager =
+ wl_resource_get_user_data(resource);
+ struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
struct input_method *input_method;
- struct weston_compositor *ec = seat->compositor;
input_method = zalloc(sizeof *input_method);
if (input_method == NULL)
return;
- input_method->seat = seat;
+ input_method->resource =
+ wl_resource_create(client, &zwp_input_method_v2_interface, 1, id);
+ wl_resource_set_implementation(input_method->resource,
+ &input_method_implementation,
+ input_method, destroy_input_method);
+
+ input_method->seat = weston_seat;
input_method->input = NULL;
input_method->focus_listener_initialized = false;
- input_method->context = NULL;
- input_method->text_backend = text_backend;
+ input_method->manager = input_method_manager;
+ input_method->pending_focused_surface = NULL;
+
+ weston_seat->input_method = input_method;
+
+ input_method_init_seat(weston_seat);
+
+ wl_list_insert(&input_method_manager->input_methods, &input_method->link);
+};
+
+static void
+input_method_manager_destroy(struct wl_client *client,
+ struct wl_resource *resource)
+{
+ wl_resource_destroy(resource);
+}
+
+static const struct zwp_input_method_manager_v2_interface input_method_manager_implementation = {
+ input_method_manager_get_input_method,
+ input_method_manager_destroy
+};
+
+static void
+bind_input_method_manager(struct wl_client *client,
+ void *data,
+ uint32_t version,
+ uint32_t id)
+{
+ struct input_method_manager *input_method_manager = data;
+ struct wl_resource *resource;
+
+ resource =
+ wl_resource_create(client,
+ &zwp_input_method_manager_v2_interface, 1, id);
+ if (resource)
+ wl_resource_set_implementation(resource,
+ &input_method_manager_implementation,
+ input_method_manager, NULL);
+}
+
+static void
+input_method_manager_notifier_destroy(struct wl_listener *listener, void *data)
+{
+ struct input_method_manager *input_method_manager =
+ container_of(listener,
+ struct input_method_manager,
+ destroy_listener);
+ struct input_method *input_method, *input_method_tmp;
+
+ wl_list_for_each_safe(input_method, input_method_tmp,
+ &input_method_manager->input_methods, link) {
+ wl_resource_destroy(input_method->resource);
+ }
+
+ wl_list_remove(&input_method_manager->destroy_listener.link);
+ wl_global_destroy(input_method_manager->input_method_manager_global);
+
+ free(input_method_manager);
+}
- input_method->input_method_global =
+static void
+input_method_manager_create(struct weston_compositor *ec)
+{
+ struct input_method_manager *input_method_manager;
+
+ input_method_manager = zalloc(sizeof *input_method_manager);
+ if (input_method_manager == NULL)
+ return;
+
+ input_method_manager->ec = ec;
+
+ input_method_manager->input_method_manager_global =
wl_global_create(ec->wl_display,
- &zwp_input_method_v1_interface, 1,
- input_method, bind_input_method);
+ &zwp_input_method_manager_v2_interface, 1,
+ input_method_manager, bind_input_method_manager);
- input_method->destroy_listener.notify = input_method_notifier_destroy;
- wl_signal_add(&seat->destroy_signal, &input_method->destroy_listener);
+ input_method_manager->destroy_listener.notify =
+ input_method_manager_notifier_destroy;
+ wl_signal_add(&ec->destroy_signal,
+ &input_method_manager->destroy_listener);
+
+ wl_list_init(&input_method_manager->input_methods);
+}
- seat->input_method = input_method;
+static void
+virtual_keyboard_destroy(struct wl_client *client,
+ struct wl_resource *resource)
+{
+ wl_resource_destroy(resource);
}
+static const struct zwp_virtual_keyboard_v1_interface virtual_keyboard_implementation = {
+ virtual_keyboard_keymap,
+ virtual_keyboard_key,
+ virtual_keyboard_modifiers,
+ virtual_keyboard_destroy,
+};
+
static void
-handle_seat_created(struct wl_listener *listener, void *data)
+destroy_virtual_keyboard(struct wl_resource *resource)
{
- struct weston_seat *seat = data;
- struct text_backend *text_backend =
- container_of(listener, struct text_backend,
- seat_created_listener);
+ struct virtual_keyboard *virtual_keyboard =
+ wl_resource_get_user_data(resource);
- text_backend_seat_created(text_backend, seat);
+ wl_list_remove(&virtual_keyboard->link);
+
+ free(virtual_keyboard);
+}
+
+static void
+virtual_keyboard_manager_create_virtual_keyboard(struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *seat,
+ uint32_t id)
+{
+ struct virtual_keyboard_manager *virtual_keyboard_manager =
+ wl_resource_get_user_data(resource);
+ struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
+ struct virtual_keyboard *virtual_keyboard;
+
+ virtual_keyboard = zalloc(sizeof *virtual_keyboard);
+ if (virtual_keyboard == NULL)
+ return;
+
+ virtual_keyboard->resource =
+ wl_resource_create(client, &zwp_virtual_keyboard_v1_interface, 1, id);
+ wl_resource_set_implementation(virtual_keyboard->resource,
+ &virtual_keyboard_implementation,
+ virtual_keyboard, destroy_virtual_keyboard);
+
+ virtual_keyboard->seat = weston_seat;
+ virtual_keyboard->manager = virtual_keyboard_manager;
+
+ wl_list_insert(&virtual_keyboard_manager->virtual_keyboards, &virtual_keyboard->link);
+};
+
+static void
+virtual_keyboard_manager_destroy(struct wl_client *client,
+ struct wl_resource *resource)
+{
+ wl_resource_destroy(resource);
+}
+
+static const struct zwp_virtual_keyboard_manager_v1_interface virtual_keyboard_manager_implementation = {
+ virtual_keyboard_manager_create_virtual_keyboard,
+ virtual_keyboard_manager_destroy,
+};
+
+static void
+bind_virtual_keyboard_manager(struct wl_client *client,
+ void *data,
+ uint32_t version,
+ uint32_t id)
+{
+ struct virtual_keyboard_manager *virtual_keyboard_manager = data;
+ struct wl_resource *resource;
+
+ resource =
+ wl_resource_create(client,
+ &zwp_virtual_keyboard_manager_v1_interface, 1, id);
+ if (resource)
+ wl_resource_set_implementation(resource,
+ &virtual_keyboard_manager_implementation,
+ virtual_keyboard_manager, NULL);
+}
+
+static void
+virtual_keyboard_manager_notifier_destroy(struct wl_listener *listener, void *data)
+{
+ struct virtual_keyboard_manager *virtual_keyboard_manager =
+ container_of(listener,
+ struct virtual_keyboard_manager,
+ destroy_listener);
+ struct virtual_keyboard *virtual_keyboard, *virtual_keyboard_tmp;
+
+ wl_list_for_each_safe(virtual_keyboard, virtual_keyboard_tmp,
+ &virtual_keyboard_manager->virtual_keyboards, link) {
+ wl_resource_destroy(virtual_keyboard->resource);
+ }
+
+ wl_list_remove(&virtual_keyboard_manager->destroy_listener.link);
+ wl_global_destroy(virtual_keyboard_manager->virtual_keyboard_manager_global);
+
+ free(virtual_keyboard_manager);
+}
+
+static void
+virtual_keyboard_manager_create(struct weston_compositor *ec)
+{
+ struct virtual_keyboard_manager *virtual_keyboard_manager;
+
+ virtual_keyboard_manager = zalloc(sizeof *virtual_keyboard_manager);
+ if (virtual_keyboard_manager == NULL)
+ return;
+
+ virtual_keyboard_manager->ec = ec;
+
+ virtual_keyboard_manager->virtual_keyboard_manager_global =
+ wl_global_create(ec->wl_display,
+ &zwp_virtual_keyboard_manager_v1_interface, 1,
+ virtual_keyboard_manager, bind_virtual_keyboard_manager);
+
+ virtual_keyboard_manager->destroy_listener.notify =
+ virtual_keyboard_manager_notifier_destroy;
+ wl_signal_add(&ec->destroy_signal,
+ &virtual_keyboard_manager->destroy_listener);
+
+ wl_list_init(&virtual_keyboard_manager->virtual_keyboards);
}
static void
@@ -1059,8 +1184,6 @@ text_backend_configuration(struct text_backend *text_backend)
WL_EXPORT void
text_backend_destroy(struct text_backend *text_backend)
{
- wl_list_remove(&text_backend->seat_created_listener.link);
-
if (text_backend->input_method.client) {
/* disable respawn */
wl_list_remove(&text_backend->client_listener.link);
@@ -1075,7 +1198,6 @@ WL_EXPORT struct text_backend *
text_backend_init(struct weston_compositor *ec)
{
struct text_backend *text_backend;
- struct weston_seat *seat;
text_backend = zalloc(sizeof(*text_backend));
if (text_backend == NULL)
@@ -1085,13 +1207,9 @@ text_backend_init(struct weston_compositor *ec)
text_backend_configuration(text_backend);
- wl_list_for_each(seat, &ec->seat_list, link)
- text_backend_seat_created(text_backend, seat);
- text_backend->seat_created_listener.notify = handle_seat_created;
- wl_signal_add(&ec->seat_created_signal,
- &text_backend->seat_created_listener);
-
+ input_method_manager_create(ec);
text_input_manager_create(ec);
+ virtual_keyboard_manager_create(ec);
launch_input_method(text_backend);
diff --git a/desktop-shell/input-panel.c b/desktop-shell/input-panel.c
index 8292f20a..f7a60809 100644
--- a/desktop-shell/input-panel.c
+++ b/desktop-shell/input-panel.c
@@ -31,7 +31,7 @@
#include <string.h>
#include "shell.h"
-#include "input-method-unstable-v1-server-protocol.h"
+#include "weston-input-panel-server-protocol.h"
#include "shared/helpers.h"
struct input_panel_surface {
@@ -294,7 +294,7 @@ input_panel_surface_set_overlay_panel(struct wl_client *client,
input_panel_surface->panel = 1;
}
-static const struct zwp_input_panel_surface_v1_interface input_panel_surface_implementation = {
+static const struct weston_input_panel_surface_interface input_panel_surface_implementation = {
input_panel_surface_set_toplevel,
input_panel_surface_set_overlay_panel
};
@@ -336,7 +336,7 @@ input_panel_get_input_panel_surface(struct wl_client *client,
ipsurf->resource =
wl_resource_create(client,
- &zwp_input_panel_surface_v1_interface,
+ &weston_input_panel_surface_interface,
1,
id);
wl_resource_set_implementation(ipsurf->resource,
@@ -345,7 +345,7 @@ input_panel_get_input_panel_surface(struct wl_client *client,
destroy_input_panel_surface_resource);
}
-static const struct zwp_input_panel_v1_interface input_panel_implementation = {
+static const struct weston_input_panel_interface input_panel_implementation = {
input_panel_get_input_panel_surface
};
@@ -365,7 +365,7 @@ bind_input_panel(struct wl_client *client,
struct wl_resource *resource;
resource = wl_resource_create(client,
- &zwp_input_panel_v1_interface, 1, id);
+ &weston_input_panel_interface, 1, id);
if (shell->input_panel.binding == NULL) {
wl_resource_set_implementation(resource,
@@ -404,7 +404,7 @@ input_panel_setup(struct desktop_shell *shell)
wl_list_init(&shell->input_panel.surfaces);
if (wl_global_create(shell->compositor->wl_display,
- &zwp_input_panel_v1_interface, 1,
+ &weston_input_panel_interface, 1,
shell, bind_input_panel) == NULL)
return -1;
diff --git a/desktop-shell/meson.build b/desktop-shell/meson.build
index 07013437..a785648b 100644
--- a/desktop-shell/meson.build
+++ b/desktop-shell/meson.build
@@ -8,8 +8,8 @@ if get_option('shell-desktop')
'../shared/matrix.c',
weston_desktop_shell_server_protocol_h,
weston_desktop_shell_protocol_c,
- input_method_unstable_v1_server_protocol_h,
- input_method_unstable_v1_protocol_c,
+ weston_input_panel_server_protocol_h,
+ weston_input_panel_protocol_c,
]
deps_shell_desktop = [
dep_libshared,
diff --git a/protocol/meson.build b/protocol/meson.build
index 34026ff9..b9c02376 100644
--- a/protocol/meson.build
+++ b/protocol/meson.build
@@ -16,6 +16,7 @@ install_data(
generated_protocols = [
[ 'input-method', 'v1' ],
+ [ 'input-method', 'v2' ],
[ 'input-timestamps', 'v1' ],
[ 'ivi-application', 'internal' ],
[ 'ivi-hmi-controller', 'internal' ],
@@ -28,9 +29,12 @@ generated_protocols = [
[ 'tablet', 'v2' ],
[ 'text-cursor-position', 'internal' ],
[ 'text-input', 'v1' ],
+ [ 'text-input', 'v3' ],
[ 'viewporter', 'stable' ],
+ [ 'virtual-keyboard', 'v1' ],
[ 'weston-debug', 'internal' ],
[ 'weston-desktop-shell', 'internal' ],
+ [ 'weston-input-panel', 'internal' ],
[ 'weston-screenshooter', 'internal' ],
[ 'weston-test', 'internal' ],
[ 'weston-touch-calibration', 'internal' ],
diff --git a/protocol/weston-input-panel.xml b/protocol/weston-input-panel.xml
new file mode 100644
index 00000000..9a68a441
--- /dev/null
+++ b/protocol/weston-input-panel.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="weston_input_panel">
+
+ <copyright>
+ Copyright © 2012, 2013 Intel Corporation
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice (including the next
+ paragraph) shall be included in all copies or substantial portions of the
+ Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+ </copyright>
+
+ <interface name="weston_input_panel" version="1">
+ <description summary="interface for implementing keyboards">
+ Only one client can bind this interface at a time.
+ </description>
+
+ <request name="get_input_panel_surface">
+ <arg name="id" type="new_id" interface="weston_input_panel_surface"/>
+ <arg name="surface" type="object" interface="wl_surface"/>
+ </request>
+ </interface>
+
+ <interface name="weston_input_panel_surface" version="1">
+ <enum name="position">
+ <entry name="center_bottom" value="0"/>
+ </enum>
+
+ <request name="set_toplevel">
+ <description summary="set the surface type as a keyboard">
+ Set the input_panel_surface type to keyboard.
+
+ A keyboard surface is only shown when a text input is active.
+ </description>
+ <arg name="output" type="object" interface="wl_output"/>
+ <arg name="position" type="uint"/>
+ </request>
+
+ <request name="set_overlay_panel">
+ <description summary="set the surface type as an overlay panel">
+ Set the input_panel_surface to be an overlay panel.
+
+ This is shown near the input cursor above the application window when
+ a text input is active.
+ </description>
+ </request>
+ </interface>
+
+</protocol>
diff --git a/tests/meson.build b/tests/meson.build
index 03692f47..ac65183d 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -156,8 +156,10 @@ tests_weston = [
[
'text',
[
- text_input_unstable_v1_client_protocol_h,
- text_input_unstable_v1_protocol_c,
+ text_input_unstable_v3_client_protocol_h,
+ text_input_unstable_v3_protocol_c,
+ input_method_unstable_v2_client_protocol_h,
+ input_method_unstable_v2_protocol_c,
]
],
[
diff --git a/tests/text-test.c b/tests/text-test.c
index 685a28dc..079a5d8e 100644
--- a/tests/text-test.c
+++ b/tests/text-test.c
@@ -30,7 +30,8 @@
#include <stdio.h>
#include "weston-test-client-helper.h"
-#include "text-input-unstable-v1-client-protocol.h"
+#include "text-input-unstable-v3-client-protocol.h"
+#include "input-method-unstable-v2-client-protocol.h"
struct text_input_state {
int activated;
@@ -39,74 +40,38 @@ struct text_input_state {
static void
text_input_commit_string(void *data,
- struct zwp_text_input_v1 *text_input,
- uint32_t serial,
+ struct zwp_text_input_v3 *text_input,
const char *text)
{
}
static void
text_input_preedit_string(void *data,
- struct zwp_text_input_v1 *text_input,
- uint32_t serial,
+ struct zwp_text_input_v3 *text_input,
const char *text,
- const char *commit)
+ int32_t cursor_begin,
+ int32_t cursor_end)
{
}
static void
text_input_delete_surrounding_text(void *data,
- struct zwp_text_input_v1 *text_input,
- int32_t index,
- uint32_t length)
+ struct zwp_text_input_v3 *text_input,
+ uint32_t before_length,
+ uint32_t after_length)
{
}
static void
-text_input_cursor_position(void *data,
- struct zwp_text_input_v1 *text_input,
- int32_t index,
- int32_t anchor)
-{
-}
-
-static void
-text_input_preedit_styling(void *data,
- struct zwp_text_input_v1 *text_input,
- uint32_t index,
- uint32_t length,
- uint32_t style)
-{
-}
-
-static void
-text_input_preedit_cursor(void *data,
- struct zwp_text_input_v1 *text_input,
- int32_t index)
-{
-}
-
-static void
-text_input_modifiers_map(void *data,
- struct zwp_text_input_v1 *text_input,
- struct wl_array *map)
-{
-}
-
-static void
-text_input_keysym(void *data,
- struct zwp_text_input_v1 *text_input,
- uint32_t serial,
- uint32_t time,
- uint32_t sym,
- uint32_t state,
- uint32_t modifiers)
+text_input_done(void *data,
+ struct zwp_text_input_v3 *zwp_text_input_v3,
+ uint32_t serial)
{
}
static void
text_input_enter(void *data,
- struct zwp_text_input_v1 *text_input,
+ struct zwp_text_input_v3 *text_input,
struct wl_surface *surface)
{
@@ -119,76 +84,69 @@ text_input_enter(void *data,
static void
text_input_leave(void *data,
- struct zwp_text_input_v1 *text_input)
+ struct zwp_text_input_v3 *text_input,
+ struct wl_surface *surface)
{
struct text_input_state *state = data;
state->deactivated += 1;
}
-static void
-text_input_input_panel_state(void *data,
- struct zwp_text_input_v1 *text_input,
- uint32_t state)
-{
-}
-
-static void
-text_input_language(void *data,
- struct zwp_text_input_v1 *text_input,
- uint32_t serial,
- const char *language)
-{
-}
-
-static void
-text_input_text_direction(void *data,
- struct zwp_text_input_v1 *text_input,
- uint32_t serial,
- uint32_t direction)
-{
-}
-
-static const struct zwp_text_input_v1_listener text_input_listener = {
+static const struct zwp_text_input_v3_listener text_input_listener = {
text_input_enter,
text_input_leave,
- text_input_modifiers_map,
- text_input_input_panel_state,
text_input_preedit_string,
- text_input_preedit_styling,
- text_input_preedit_cursor,
text_input_commit_string,
- text_input_cursor_position,
text_input_delete_surrounding_text,
- text_input_keysym,
- text_input_language,
- text_input_text_direction
+ text_input_done,
};
TEST(text_test)
{
struct client *client;
struct global *global;
- struct zwp_text_input_manager_v1 *factory;
- struct zwp_text_input_v1 *text_input;
+ struct zwp_input_method_manager_v2 *input_method_factory;
+ struct zwp_input_method_v2 *input_method;
+ struct zwp_text_input_manager_v3 *text_input_factory;
+ struct zwp_text_input_v3 *text_input;
struct text_input_state state;
client = create_client_and_test_surface(100, 100, 100, 100);
assert(client);
- factory = NULL;
+ input_method_factory = NULL;
+ text_input_factory = NULL;
wl_list_for_each(global, &client->global_list, link) {
- if (strcmp(global->interface, "zwp_text_input_manager_v1") == 0)
- factory = wl_registry_bind(client->wl_registry,
- global->name,
- &zwp_text_input_manager_v1_interface, 1);
+ if (strcmp(global->interface, "zwp_input_method_manager_v2") == 0) {
+ input_method_factory = wl_registry_bind(client->wl_registry,
+ global->name,
+ &zwp_input_method_manager_v2_interface, 1);
+ }
+ else if (strcmp(global->interface, "zwp_text_input_manager_v3") == 0) {
+ text_input_factory = wl_registry_bind(client->wl_registry,
+ global->name,
+ &zwp_text_input_manager_v3_interface, 1);
+ }
}
- assert(factory);
+ assert(input_method_factory);
+ assert(text_input_factory);
memset(&state, 0, sizeof state);
- text_input = zwp_text_input_manager_v1_create_text_input(factory);
- zwp_text_input_v1_add_listener(text_input,
+
+ /* Initialize input method for seat.
+ * text-input will only receive enter/leave events if there is
+ * an input method available.
+ */
+ input_method = zwp_input_method_manager_v2_get_input_method(input_method_factory,
+ client->input->wl_seat);
+ assert(input_method);
+
+ /* Initialize text input for seat. */
+ text_input = zwp_text_input_manager_v3_get_text_input(text_input_factory,
+ client->input->wl_seat);
+ assert(text_input);
+ zwp_text_input_v3_add_listener(text_input,
&text_input_listener,
&state);
@@ -199,19 +157,20 @@ TEST(text_test)
assert(client->input->keyboard->focus == client->surface);
/* Activate test model and make sure we get enter event. */
- zwp_text_input_v1_activate(text_input, client->input->wl_seat,
- client->surface->wl_surface);
+ zwp_text_input_v3_enable(text_input);
+ zwp_text_input_v3_commit(text_input);
client_roundtrip(client);
assert(state.activated == 1 && state.deactivated == 0);
/* Deactivate test model and make sure we get leave event. */
- zwp_text_input_v1_deactivate(text_input, client->input->wl_seat);
+ zwp_text_input_v3_disable(text_input);
+ zwp_text_input_v3_commit(text_input);
client_roundtrip(client);
assert(state.activated == 1 && state.deactivated == 1);
/* Activate test model again. */
- zwp_text_input_v1_activate(text_input, client->input->wl_seat,
- client->surface->wl_surface);
+ zwp_text_input_v3_enable(text_input);
+ zwp_text_input_v3_commit(text_input);
client_roundtrip(client);
assert(state.activated == 2 && state.deactivated == 1);
--
2.20.1
More information about the wayland-devel
mailing list