blob: 262ba9fb27c53881d91996e634b2691f828b88ac [file] [log] [blame]
Jan Arne Petersen1f17be42012-06-21 21:52:18 +02001/*
2 * Copyright © 2012 Openismus GmbH
Jan Arne Petersen4c265182012-09-09 23:08:30 +02003 * Copyright © 2012 Intel Corporation
Jan Arne Petersen1f17be42012-06-21 21:52:18 +02004 *
Bryce Harringtona0bbfea2015-06-11 15:35:43 -07005 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020012 *
Bryce Harringtona0bbfea2015-06-11 15:35:43 -070013 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020025 */
26
Daniel Stonec228e232013-05-22 18:03:19 +030027#include "config.h"
28
Derek Foremand09dbb32014-12-05 15:38:39 -060029#include <stdbool.h>
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020030#include <stdlib.h>
Jussi Kukkonen649bbce2016-07-19 14:16:27 +030031#include <stdint.h>
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010032#include <string.h>
Ossama Othmana50e6e42013-05-14 09:48:26 -070033#include <unistd.h>
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -030034#include <time.h>
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020035
36#include "compositor.h"
Giulio Camuffofba27fb2016-06-02 21:48:10 +030037#include "weston.h"
Jonas Ådahl3bcba342015-11-17 16:00:29 +080038#include "text-input-unstable-v1-server-protocol.h"
Jonas Ådahlb57f4722015-11-17 16:00:30 +080039#include "input-method-unstable-v1-server-protocol.h"
Jon Cruz867d50e2015-06-15 15:37:10 -070040#include "shared/helpers.h"
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020041
Derek Foreman516d6032015-05-08 17:08:40 -050042struct text_input_manager;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020043struct input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020044struct input_method_context;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010045struct text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020046
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020047struct text_input {
Jason Ekstrand89d31992013-06-14 10:07:59 -050048 struct wl_resource *resource;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020049
Jan Arne Petersene829adc2012-08-10 16:47:22 +020050 struct weston_compositor *ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020051
Jan Arne Petersene829adc2012-08-10 16:47:22 +020052 struct wl_list input_methods;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +020053
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -040054 struct weston_surface *surface;
Jan Arne Petersen61381972013-01-31 15:52:21 +010055
Jan Arne Petersen14da96b2013-04-18 16:47:28 +020056 pixman_box32_t cursor_rectangle;
57
Derek Foremand09dbb32014-12-05 15:38:39 -060058 bool input_panel_visible;
Derek Foreman516d6032015-05-08 17:08:40 -050059
60 struct text_input_manager *manager;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020061};
62
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020063struct text_input_manager {
64 struct wl_global *text_input_manager_global;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020065 struct wl_listener destroy_listener;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020066
Derek Foreman516d6032015-05-08 17:08:40 -050067 struct text_input *current_panel;
68
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +020069 struct weston_compositor *ec;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +020070};
71
72struct input_method {
73 struct wl_resource *input_method_binding;
74 struct wl_global *input_method_global;
75 struct wl_listener destroy_listener;
76
77 struct weston_seat *seat;
Derek Foreman0f299232015-05-08 17:08:41 -050078 struct text_input *input;
Jan Arne Petersene829adc2012-08-10 16:47:22 +020079
80 struct wl_list link;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +020081
82 struct wl_listener keyboard_focus_listener;
83
Derek Foremanddc2c972015-07-15 13:00:32 -050084 bool focus_listener_initialized;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020085
86 struct input_method_context *context;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010087
88 struct text_backend *text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020089};
90
Jan Arne Petersen620cd622012-09-09 23:08:32 +020091struct input_method_context {
Jason Ekstrand89d31992013-06-14 10:07:59 -050092 struct wl_resource *resource;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020093
Derek Foreman0f299232015-05-08 17:08:41 -050094 struct text_input *input;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +010095 struct input_method *input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020096
Jan Arne Petersen466b9c12012-11-18 19:06:45 +010097 struct wl_resource *keyboard;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020098};
99
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100100struct text_backend {
101 struct weston_compositor *compositor;
102
103 struct {
104 char *path;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100105 struct wl_client *client;
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300106
107 unsigned deathcount;
108 uint32_t deathstamp;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100109 } input_method;
110
Derek Foreman89dcea92015-06-25 15:49:49 -0500111 struct wl_listener client_listener;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100112 struct wl_listener seat_created_listener;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100113};
114
Derek Foremancb5fcea2014-12-05 15:38:37 -0600115static void
Derek Foreman0f299232015-05-08 17:08:41 -0500116input_method_context_create(struct text_input *input,
Derek Foremancb5fcea2014-12-05 15:38:37 -0600117 struct input_method *input_method);
118static void
119input_method_context_end_keyboard_grab(struct input_method_context *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200120
Derek Foremancb5fcea2014-12-05 15:38:37 -0600121static void
122input_method_init_seat(struct weston_seat *seat);
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200123
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200124static void
Derek Foreman516d6032015-05-08 17:08:40 -0500125deactivate_input_method(struct input_method *input_method)
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200126{
Derek Foreman0f299232015-05-08 17:08:41 -0500127 struct text_input *text_input = input_method->input;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200128 struct weston_compositor *ec = text_input->ec;
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200129
Derek Foreman516d6032015-05-08 17:08:40 -0500130 if (input_method->context && input_method->input_method_binding) {
131 input_method_context_end_keyboard_grab(input_method->context);
Jonas Ådahlb57f4722015-11-17 16:00:30 +0800132 zwp_input_method_v1_send_deactivate(
Murray Calavera972d1af2015-06-09 20:29:28 +0000133 input_method->input_method_binding,
134 input_method->context->resource);
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200135 }
Derek Foreman516d6032015-05-08 17:08:40 -0500136
137 wl_list_remove(&input_method->link);
Derek Foreman0f299232015-05-08 17:08:41 -0500138 input_method->input = NULL;
Derek Foreman516d6032015-05-08 17:08:40 -0500139 input_method->context = NULL;
140
141 if (wl_list_empty(&text_input->input_methods) &&
142 text_input->input_panel_visible) {
143 wl_signal_emit(&ec->hide_input_panel_signal, ec);
144 text_input->input_panel_visible = false;
145 text_input->manager->current_panel = NULL;
146 }
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800147 zwp_text_input_v1_send_leave(text_input->resource);
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200148}
149
150static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200151destroy_text_input(struct wl_resource *resource)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200152{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500153 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200154 struct input_method *input_method, *next;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200155
Murray Calavera972d1af2015-06-09 20:29:28 +0000156 wl_list_for_each_safe(input_method, next,
157 &text_input->input_methods, link)
Derek Foreman516d6032015-05-08 17:08:40 -0500158 deactivate_input_method(input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200159
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200160 free(text_input);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200161}
162
163static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200164text_input_set_surrounding_text(struct wl_client *client,
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200165 struct wl_resource *resource,
Jan Arne Petersencb08f4d2012-09-09 23:08:40 +0200166 const char *text,
167 uint32_t cursor,
168 uint32_t anchor)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200169{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500170 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200171 struct input_method *input_method, *next;
172
Murray Calavera972d1af2015-06-09 20:29:28 +0000173 wl_list_for_each_safe(input_method, next,
174 &text_input->input_methods, link) {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200175 if (!input_method->context)
176 continue;
Jonas Ådahlb57f4722015-11-17 16:00:30 +0800177 zwp_input_method_context_v1_send_surrounding_text(
Murray Calavera972d1af2015-06-09 20:29:28 +0000178 input_method->context->resource, text, cursor, anchor);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200179 }
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200180}
181
182static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200183text_input_activate(struct wl_client *client,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200184 struct wl_resource *resource,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200185 struct wl_resource *seat,
186 struct wl_resource *surface)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200187{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500188 struct text_input *text_input = wl_resource_get_user_data(resource);
Jason Ekstrand44a38632013-06-14 10:08:00 -0500189 struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200190 struct input_method *input_method = weston_seat->input_method;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200191 struct weston_compositor *ec = text_input->ec;
Derek Foreman516d6032015-05-08 17:08:40 -0500192 struct text_input *current;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200193
Derek Foreman0f299232015-05-08 17:08:41 -0500194 if (input_method->input == text_input)
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200195 return;
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200196
Derek Foreman0f299232015-05-08 17:08:41 -0500197 if (input_method->input)
Derek Foreman516d6032015-05-08 17:08:40 -0500198 deactivate_input_method(input_method);
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200199
Derek Foreman0f299232015-05-08 17:08:41 -0500200 input_method->input = text_input;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200201 wl_list_insert(&text_input->input_methods, &input_method->link);
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200202 input_method_init_seat(weston_seat);
203
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -0500204 text_input->surface = wl_resource_get_user_data(surface);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200205
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200206 input_method_context_create(text_input, input_method);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200207
Derek Foreman516d6032015-05-08 17:08:40 -0500208 current = text_input->manager->current_panel;
209
210 if (current && current != text_input) {
211 current->input_panel_visible = false;
212 wl_signal_emit(&ec->hide_input_panel_signal, ec);
213 text_input->manager->current_panel = NULL;
214 }
215
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200216 if (text_input->input_panel_visible) {
Murray Calavera972d1af2015-06-09 20:29:28 +0000217 wl_signal_emit(&ec->show_input_panel_signal,
218 text_input->surface);
219 wl_signal_emit(&ec->update_input_panel_signal,
220 &text_input->cursor_rectangle);
Derek Foreman516d6032015-05-08 17:08:40 -0500221 text_input->manager->current_panel = text_input;
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200222 }
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200223
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800224 zwp_text_input_v1_send_enter(text_input->resource,
225 text_input->surface->resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200226}
227
228static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200229text_input_deactivate(struct wl_client *client,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200230 struct wl_resource *resource,
231 struct wl_resource *seat)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200232{
Jason Ekstrand44a38632013-06-14 10:08:00 -0500233 struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200234
Derek Foreman0f299232015-05-08 17:08:41 -0500235 if (weston_seat->input_method->input)
Derek Foreman516d6032015-05-08 17:08:40 -0500236 deactivate_input_method(weston_seat->input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200237}
238
239static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200240text_input_reset(struct wl_client *client,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200241 struct wl_resource *resource)
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200242{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500243 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200244 struct input_method *input_method, *next;
245
Murray Calavera972d1af2015-06-09 20:29:28 +0000246 wl_list_for_each_safe(input_method, next,
247 &text_input->input_methods, link) {
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200248 if (!input_method->context)
249 continue;
Jonas Ådahlb57f4722015-11-17 16:00:30 +0800250 zwp_input_method_context_v1_send_reset(
Murray Calavera972d1af2015-06-09 20:29:28 +0000251 input_method->context->resource);
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200252 }
253}
254
255static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200256text_input_set_cursor_rectangle(struct wl_client *client,
Jan Arne Petersen7ef8eff2013-04-18 16:47:23 +0200257 struct wl_resource *resource,
258 int32_t x,
259 int32_t y,
260 int32_t width,
261 int32_t height)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200262{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500263 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200264 struct weston_compositor *ec = text_input->ec;
265
266 text_input->cursor_rectangle.x1 = x;
267 text_input->cursor_rectangle.y1 = y;
268 text_input->cursor_rectangle.x2 = x + width;
269 text_input->cursor_rectangle.y2 = y + height;
270
Murray Calavera972d1af2015-06-09 20:29:28 +0000271 wl_signal_emit(&ec->update_input_panel_signal,
272 &text_input->cursor_rectangle);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200273}
274
275static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200276text_input_set_content_type(struct wl_client *client,
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100277 struct wl_resource *resource,
278 uint32_t hint,
279 uint32_t purpose)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200280{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500281 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100282 struct input_method *input_method, *next;
283
Murray Calavera972d1af2015-06-09 20:29:28 +0000284 wl_list_for_each_safe(input_method, next,
285 &text_input->input_methods, link) {
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100286 if (!input_method->context)
287 continue;
Jonas Ådahlb57f4722015-11-17 16:00:30 +0800288 zwp_input_method_context_v1_send_content_type(
Murray Calavera972d1af2015-06-09 20:29:28 +0000289 input_method->context->resource, hint, purpose);
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100290 }
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200291}
292
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100293static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200294text_input_invoke_action(struct wl_client *client,
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100295 struct wl_resource *resource,
296 uint32_t button,
297 uint32_t index)
298{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500299 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100300 struct input_method *input_method, *next;
301
Murray Calavera972d1af2015-06-09 20:29:28 +0000302 wl_list_for_each_safe(input_method, next,
303 &text_input->input_methods, link) {
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100304 if (!input_method->context)
305 continue;
Jonas Ådahlb57f4722015-11-17 16:00:30 +0800306 zwp_input_method_context_v1_send_invoke_action(
Murray Calavera972d1af2015-06-09 20:29:28 +0000307 input_method->context->resource, button, index);
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100308 }
309}
310
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100311static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200312text_input_commit_state(struct wl_client *client,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200313 struct wl_resource *resource,
314 uint32_t serial)
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100315{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500316 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100317 struct input_method *input_method, *next;
318
Murray Calavera972d1af2015-06-09 20:29:28 +0000319 wl_list_for_each_safe(input_method, next,
320 &text_input->input_methods, link) {
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100321 if (!input_method->context)
322 continue;
Jonas Ådahlb57f4722015-11-17 16:00:30 +0800323 zwp_input_method_context_v1_send_commit_state(
Murray Calavera972d1af2015-06-09 20:29:28 +0000324 input_method->context->resource, serial);
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100325 }
326}
327
Jan Arne Petersen61381972013-01-31 15:52:21 +0100328static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200329text_input_show_input_panel(struct wl_client *client,
Jan Arne Petersen61381972013-01-31 15:52:21 +0100330 struct wl_resource *resource)
331{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500332 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200333 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100334
Derek Foremand09dbb32014-12-05 15:38:39 -0600335 text_input->input_panel_visible = true;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100336
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200337 if (!wl_list_empty(&text_input->input_methods)) {
Murray Calavera972d1af2015-06-09 20:29:28 +0000338 wl_signal_emit(&ec->show_input_panel_signal,
339 text_input->surface);
340 wl_signal_emit(&ec->update_input_panel_signal,
341 &text_input->cursor_rectangle);
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200342 }
Jan Arne Petersen61381972013-01-31 15:52:21 +0100343}
344
345static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200346text_input_hide_input_panel(struct wl_client *client,
Jan Arne Petersen61381972013-01-31 15:52:21 +0100347 struct wl_resource *resource)
348{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500349 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200350 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100351
Derek Foremand09dbb32014-12-05 15:38:39 -0600352 text_input->input_panel_visible = false;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100353
Derek Foreman516d6032015-05-08 17:08:40 -0500354 if (!wl_list_empty(&text_input->input_methods) &&
355 text_input == text_input->manager->current_panel) {
356 text_input->manager->current_panel = NULL;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100357 wl_signal_emit(&ec->hide_input_panel_signal, ec);
Derek Foreman516d6032015-05-08 17:08:40 -0500358 }
Jan Arne Petersen61381972013-01-31 15:52:21 +0100359}
360
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200361static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200362text_input_set_preferred_language(struct wl_client *client,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200363 struct wl_resource *resource,
364 const char *language)
365{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500366 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200367 struct input_method *input_method, *next;
368
Murray Calavera972d1af2015-06-09 20:29:28 +0000369 wl_list_for_each_safe(input_method, next,
370 &text_input->input_methods, link) {
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200371 if (!input_method->context)
372 continue;
Jonas Ådahlb57f4722015-11-17 16:00:30 +0800373 zwp_input_method_context_v1_send_preferred_language(
Murray Calavera972d1af2015-06-09 20:29:28 +0000374 input_method->context->resource, language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200375 }
376}
377
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800378static const struct zwp_text_input_v1_interface text_input_implementation = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200379 text_input_activate,
380 text_input_deactivate,
381 text_input_show_input_panel,
382 text_input_hide_input_panel,
383 text_input_reset,
384 text_input_set_surrounding_text,
385 text_input_set_content_type,
386 text_input_set_cursor_rectangle,
387 text_input_set_preferred_language,
388 text_input_commit_state,
389 text_input_invoke_action
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200390};
391
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200392static void text_input_manager_create_text_input(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200393 struct wl_resource *resource,
Jan Arne Petersen4c265182012-09-09 23:08:30 +0200394 uint32_t id)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200395{
Murray Calavera972d1af2015-06-09 20:29:28 +0000396 struct text_input_manager *text_input_manager =
397 wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200398 struct text_input *text_input;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200399
Bryce Harringtonde16d892014-11-20 22:21:57 -0800400 text_input = zalloc(sizeof *text_input);
401 if (text_input == NULL)
402 return;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200403
Jason Ekstranda85118c2013-06-27 20:17:02 -0500404 text_input->resource =
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800405 wl_resource_create(client, &zwp_text_input_v1_interface, 1, id);
Jason Ekstranda85118c2013-06-27 20:17:02 -0500406 wl_resource_set_implementation(text_input->resource,
407 &text_input_implementation,
408 text_input, destroy_text_input);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200409
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200410 text_input->ec = text_input_manager->ec;
Derek Foreman516d6032015-05-08 17:08:40 -0500411 text_input->manager = text_input_manager;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200412
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200413 wl_list_init(&text_input->input_methods);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200414};
415
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800416static const struct zwp_text_input_manager_v1_interface manager_implementation = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200417 text_input_manager_create_text_input
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200418};
419
420static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200421bind_text_input_manager(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200422 void *data,
423 uint32_t version,
424 uint32_t id)
425{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200426 struct text_input_manager *text_input_manager = data;
Jason Ekstranda85118c2013-06-27 20:17:02 -0500427 struct wl_resource *resource;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200428
Jason Ekstranda85118c2013-06-27 20:17:02 -0500429 /* No checking for duplicate binding necessary. */
430 resource =
431 wl_resource_create(client,
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800432 &zwp_text_input_manager_v1_interface, 1, id);
Jason Ekstranda85118c2013-06-27 20:17:02 -0500433 if (resource)
434 wl_resource_set_implementation(resource,
Murray Calavera972d1af2015-06-09 20:29:28 +0000435 &manager_implementation,
Jason Ekstranda85118c2013-06-27 20:17:02 -0500436 text_input_manager, NULL);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200437}
438
439static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200440text_input_manager_notifier_destroy(struct wl_listener *listener, void *data)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200441{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200442 struct text_input_manager *text_input_manager =
Murray Calavera972d1af2015-06-09 20:29:28 +0000443 container_of(listener,
444 struct text_input_manager,
445 destroy_listener);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200446
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400447 wl_global_destroy(text_input_manager->text_input_manager_global);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200448
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200449 free(text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200450}
451
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100452static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200453text_input_manager_create(struct weston_compositor *ec)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200454{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200455 struct text_input_manager *text_input_manager;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200456
Bryce Harringtonde16d892014-11-20 22:21:57 -0800457 text_input_manager = zalloc(sizeof *text_input_manager);
458 if (text_input_manager == NULL)
459 return;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200460
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200461 text_input_manager->ec = ec;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200462
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200463 text_input_manager->text_input_manager_global =
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400464 wl_global_create(ec->wl_display,
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800465 &zwp_text_input_manager_v1_interface, 1,
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400466 text_input_manager, bind_text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200467
Murray Calavera972d1af2015-06-09 20:29:28 +0000468 text_input_manager->destroy_listener.notify =
469 text_input_manager_notifier_destroy;
470 wl_signal_add(&ec->destroy_signal,
471 &text_input_manager->destroy_listener);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200472}
473
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200474static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200475input_method_context_destroy(struct wl_client *client,
476 struct wl_resource *resource)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200477{
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200478 wl_resource_destroy(resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200479}
480
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200481static void
482input_method_context_commit_string(struct wl_client *client,
483 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100484 uint32_t serial,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100485 const char *text)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200486{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500487 struct input_method_context *context =
488 wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200489
Derek Foreman0f299232015-05-08 17:08:41 -0500490 if (context->input)
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800491 zwp_text_input_v1_send_commit_string(context->input->resource,
492 serial, text);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200493}
494
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200495static void
496input_method_context_preedit_string(struct wl_client *client,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100497 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100498 uint32_t serial,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100499 const char *text,
500 const char *commit)
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200501{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500502 struct input_method_context *context =
503 wl_resource_get_user_data(resource);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200504
Derek Foreman0f299232015-05-08 17:08:41 -0500505 if (context->input)
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800506 zwp_text_input_v1_send_preedit_string(context->input->resource,
507 serial, text, commit);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100508}
509
510static void
511input_method_context_preedit_styling(struct wl_client *client,
512 struct wl_resource *resource,
513 uint32_t index,
514 uint32_t length,
515 uint32_t style)
516{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500517 struct input_method_context *context =
518 wl_resource_get_user_data(resource);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100519
Derek Foreman0f299232015-05-08 17:08:41 -0500520 if (context->input)
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800521 zwp_text_input_v1_send_preedit_styling(context->input->resource,
522 index, length, style);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100523}
524
525static void
526input_method_context_preedit_cursor(struct wl_client *client,
527 struct wl_resource *resource,
528 int32_t cursor)
529{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500530 struct input_method_context *context =
531 wl_resource_get_user_data(resource);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100532
Derek Foreman0f299232015-05-08 17:08:41 -0500533 if (context->input)
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800534 zwp_text_input_v1_send_preedit_cursor(context->input->resource,
535 cursor);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200536}
537
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200538static void
539input_method_context_delete_surrounding_text(struct wl_client *client,
540 struct wl_resource *resource,
541 int32_t index,
542 uint32_t length)
543{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500544 struct input_method_context *context =
545 wl_resource_get_user_data(resource);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200546
Derek Foreman0f299232015-05-08 17:08:41 -0500547 if (context->input)
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800548 zwp_text_input_v1_send_delete_surrounding_text(
Murray Calavera972d1af2015-06-09 20:29:28 +0000549 context->input->resource, index, length);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200550}
551
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200552static void
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100553input_method_context_cursor_position(struct wl_client *client,
554 struct wl_resource *resource,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100555 int32_t index,
556 int32_t anchor)
557{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500558 struct input_method_context *context =
559 wl_resource_get_user_data(resource);
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100560
Derek Foreman0f299232015-05-08 17:08:41 -0500561 if (context->input)
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800562 zwp_text_input_v1_send_cursor_position(context->input->resource,
563 index, anchor);
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100564}
565
566static void
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100567input_method_context_modifiers_map(struct wl_client *client,
568 struct wl_resource *resource,
569 struct wl_array *map)
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200570{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500571 struct input_method_context *context =
572 wl_resource_get_user_data(resource);
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200573
Derek Foreman0f299232015-05-08 17:08:41 -0500574 if (context->input)
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800575 zwp_text_input_v1_send_modifiers_map(context->input->resource,
576 map);
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100577}
578
579static void
580input_method_context_keysym(struct wl_client *client,
581 struct wl_resource *resource,
582 uint32_t serial,
583 uint32_t time,
584 uint32_t sym,
585 uint32_t state,
586 uint32_t modifiers)
587{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500588 struct input_method_context *context =
589 wl_resource_get_user_data(resource);
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100590
Derek Foreman0f299232015-05-08 17:08:41 -0500591 if (context->input)
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800592 zwp_text_input_v1_send_keysym(context->input->resource,
593 serial, time,
594 sym, state, modifiers);
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200595}
596
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100597static void
598unbind_keyboard(struct wl_resource *resource)
599{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500600 struct input_method_context *context =
601 wl_resource_get_user_data(resource);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100602
603 input_method_context_end_keyboard_grab(context);
604 context->keyboard = NULL;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100605}
606
607static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400608input_method_context_grab_key(struct weston_keyboard_grab *grab,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100609 uint32_t time, uint32_t key, uint32_t state_w)
610{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400611 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100612 struct wl_display *display;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100613 uint32_t serial;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100614
615 if (!keyboard->input_method_resource)
616 return;
617
Murray Calavera972d1af2015-06-09 20:29:28 +0000618 display = wl_client_get_display(
619 wl_resource_get_client(keyboard->input_method_resource));
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100620 serial = wl_display_next_serial(display);
621 wl_keyboard_send_key(keyboard->input_method_resource,
622 serial, time, key, state_w);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100623}
624
625static void
Murray Calavera972d1af2015-06-09 20:29:28 +0000626input_method_context_grab_modifier(struct weston_keyboard_grab *grab,
627 uint32_t serial,
628 uint32_t mods_depressed,
629 uint32_t mods_latched,
630 uint32_t mods_locked,
631 uint32_t group)
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100632{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400633 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100634
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100635 if (!keyboard->input_method_resource)
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100636 return;
637
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100638 wl_keyboard_send_modifiers(keyboard->input_method_resource,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100639 serial, mods_depressed, mods_latched,
640 mods_locked, group);
641}
642
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200643static void
644input_method_context_grab_cancel(struct weston_keyboard_grab *grab)
645{
646 weston_keyboard_end_grab(grab->keyboard);
647}
648
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400649static const struct weston_keyboard_grab_interface input_method_context_grab = {
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100650 input_method_context_grab_key,
651 input_method_context_grab_modifier,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200652 input_method_context_grab_cancel,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100653};
654
655static void
656input_method_context_grab_keyboard(struct wl_client *client,
657 struct wl_resource *resource,
658 uint32_t id)
659{
Murray Calavera972d1af2015-06-09 20:29:28 +0000660 struct input_method_context *context =
661 wl_resource_get_user_data(resource);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100662 struct wl_resource *cr;
663 struct weston_seat *seat = context->input_method->seat;
Derek Foreman1281a362015-07-31 16:55:32 -0500664 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100665
Jason Ekstranda85118c2013-06-27 20:17:02 -0500666 cr = wl_resource_create(client, &wl_keyboard_interface, 1, id);
667 wl_resource_set_implementation(cr, NULL, context, unbind_keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100668
669 context->keyboard = cr;
670
671 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
Jonas Ådahl7395ea02013-12-03 09:14:26 +0100672 keyboard->xkb_info->keymap_fd,
673 keyboard->xkb_info->keymap_size);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100674
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400675 if (keyboard->grab != &keyboard->default_grab) {
676 weston_keyboard_end_grab(keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100677 }
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400678 weston_keyboard_start_grab(keyboard, &keyboard->input_method_grab);
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100679 keyboard->input_method_resource = cr;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100680}
681
Jan Arne Petersen337df952012-11-18 19:06:46 +0100682static void
683input_method_context_key(struct wl_client *client,
684 struct wl_resource *resource,
685 uint32_t serial,
686 uint32_t time,
687 uint32_t key,
688 uint32_t state_w)
689{
Murray Calavera972d1af2015-06-09 20:29:28 +0000690 struct input_method_context *context =
691 wl_resource_get_user_data(resource);
Jan Arne Petersen337df952012-11-18 19:06:46 +0100692 struct weston_seat *seat = context->input_method->seat;
Derek Foreman1281a362015-07-31 16:55:32 -0500693 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400694 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100695
696 default_grab->interface->key(default_grab, time, key, state_w);
697}
698
699static void
700input_method_context_modifiers(struct wl_client *client,
701 struct wl_resource *resource,
702 uint32_t serial,
703 uint32_t mods_depressed,
704 uint32_t mods_latched,
705 uint32_t mods_locked,
706 uint32_t group)
707{
Murray Calavera972d1af2015-06-09 20:29:28 +0000708 struct input_method_context *context =
709 wl_resource_get_user_data(resource);
Jan Arne Petersen337df952012-11-18 19:06:46 +0100710
711 struct weston_seat *seat = context->input_method->seat;
Derek Foreman1281a362015-07-31 16:55:32 -0500712 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400713 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100714
715 default_grab->interface->modifiers(default_grab,
716 serial, mods_depressed,
717 mods_latched, mods_locked,
718 group);
719}
720
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200721static void
722input_method_context_language(struct wl_client *client,
723 struct wl_resource *resource,
724 uint32_t serial,
725 const char *language)
726{
Murray Calavera972d1af2015-06-09 20:29:28 +0000727 struct input_method_context *context =
728 wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200729
Derek Foreman0f299232015-05-08 17:08:41 -0500730 if (context->input)
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800731 zwp_text_input_v1_send_language(context->input->resource,
732 serial, language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200733}
734
735static void
736input_method_context_text_direction(struct wl_client *client,
737 struct wl_resource *resource,
738 uint32_t serial,
739 uint32_t direction)
740{
Murray Calavera972d1af2015-06-09 20:29:28 +0000741 struct input_method_context *context =
742 wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200743
Derek Foreman0f299232015-05-08 17:08:41 -0500744 if (context->input)
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800745 zwp_text_input_v1_send_text_direction(context->input->resource,
746 serial, direction);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200747}
748
749
Jonas Ådahlb57f4722015-11-17 16:00:30 +0800750static const struct zwp_input_method_context_v1_interface context_implementation = {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200751 input_method_context_destroy,
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200752 input_method_context_commit_string,
753 input_method_context_preedit_string,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100754 input_method_context_preedit_styling,
755 input_method_context_preedit_cursor,
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200756 input_method_context_delete_surrounding_text,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100757 input_method_context_cursor_position,
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100758 input_method_context_modifiers_map,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100759 input_method_context_keysym,
Jan Arne Petersen337df952012-11-18 19:06:46 +0100760 input_method_context_grab_keyboard,
761 input_method_context_key,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200762 input_method_context_modifiers,
763 input_method_context_language,
764 input_method_context_text_direction
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200765};
766
767static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200768destroy_input_method_context(struct wl_resource *resource)
769{
Murray Calavera972d1af2015-06-09 20:29:28 +0000770 struct input_method_context *context =
771 wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200772
Murray Calavera972d1af2015-06-09 20:29:28 +0000773 if (context->keyboard)
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100774 wl_resource_destroy(context->keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100775
Derek Foreman516d6032015-05-08 17:08:40 -0500776 if (context->input_method && context->input_method->context == context)
777 context->input_method->context = NULL;
778
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200779 free(context);
780}
781
782static void
Derek Foreman0f299232015-05-08 17:08:41 -0500783input_method_context_create(struct text_input *input,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200784 struct input_method *input_method)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200785{
786 struct input_method_context *context;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500787 struct wl_resource *binding;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200788
789 if (!input_method->input_method_binding)
790 return;
791
Bryce Harringtonde16d892014-11-20 22:21:57 -0800792 context = zalloc(sizeof *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200793 if (context == NULL)
794 return;
795
Jason Ekstrand89d31992013-06-14 10:07:59 -0500796 binding = input_method->input_method_binding;
Jason Ekstranda85118c2013-06-27 20:17:02 -0500797 context->resource =
798 wl_resource_create(wl_resource_get_client(binding),
Jonas Ådahlb57f4722015-11-17 16:00:30 +0800799 &zwp_input_method_context_v1_interface,
800 1, 0);
Jason Ekstranda85118c2013-06-27 20:17:02 -0500801 wl_resource_set_implementation(context->resource,
Murray Calavera972d1af2015-06-09 20:29:28 +0000802 &context_implementation,
Jason Ekstranda85118c2013-06-27 20:17:02 -0500803 context, destroy_input_method_context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200804
Derek Foreman0f299232015-05-08 17:08:41 -0500805 context->input = input;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100806 context->input_method = input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200807 input_method->context = context;
808
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200809
Jonas Ådahlb57f4722015-11-17 16:00:30 +0800810 zwp_input_method_v1_send_activate(binding, context->resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200811}
812
813static void
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100814input_method_context_end_keyboard_grab(struct input_method_context *context)
815{
Derek Foremanf0aaa412014-12-08 10:48:29 -0600816 struct weston_keyboard_grab *grab;
817 struct weston_keyboard *keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100818
Derek Foreman1281a362015-07-31 16:55:32 -0500819 keyboard = weston_seat_get_keyboard(context->input_method->seat);
820 if (!keyboard)
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100821 return;
822
Derek Foreman1281a362015-07-31 16:55:32 -0500823 grab = &keyboard->input_method_grab;
Derek Foremanf0aaa412014-12-08 10:48:29 -0600824 keyboard = grab->keyboard;
825 if (!keyboard)
826 return;
827
828 if (keyboard->grab == grab)
829 weston_keyboard_end_grab(keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100830
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100831 keyboard->input_method_resource = NULL;
832}
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100833
834static void
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200835unbind_input_method(struct wl_resource *resource)
836{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500837 struct input_method *input_method = wl_resource_get_user_data(resource);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200838
839 input_method->input_method_binding = NULL;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200840 input_method->context = NULL;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200841}
842
843static void
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200844bind_input_method(struct wl_client *client,
845 void *data,
846 uint32_t version,
847 uint32_t id)
848{
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200849 struct input_method *input_method = data;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100850 struct text_backend *text_backend = input_method->text_backend;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200851 struct wl_resource *resource;
852
Jason Ekstranda85118c2013-06-27 20:17:02 -0500853 resource =
Jonas Ådahlb57f4722015-11-17 16:00:30 +0800854 wl_resource_create(client,
855 &zwp_input_method_v1_interface, 1, id);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200856
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200857 if (input_method->input_method_binding != NULL) {
Murray Calavera972d1af2015-06-09 20:29:28 +0000858 wl_resource_post_error(resource,
859 WL_DISPLAY_ERROR_INVALID_OBJECT,
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200860 "interface object already bound");
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200861 return;
862 }
863
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200864 if (text_backend->input_method.client != client) {
Murray Calavera972d1af2015-06-09 20:29:28 +0000865 wl_resource_post_error(resource,
866 WL_DISPLAY_ERROR_INVALID_OBJECT,
867 "permission to bind "
868 "input_method denied");
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200869 return;
870 }
871
Jason Ekstranda85118c2013-06-27 20:17:02 -0500872 wl_resource_set_implementation(resource, NULL, input_method,
873 unbind_input_method);
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200874 input_method->input_method_binding = resource;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200875}
876
877static void
878input_method_notifier_destroy(struct wl_listener *listener, void *data)
879{
Kristian Høgsbergf97f3792012-07-22 11:51:42 -0400880 struct input_method *input_method =
881 container_of(listener, struct input_method, destroy_listener);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200882
Derek Foreman0f299232015-05-08 17:08:41 -0500883 if (input_method->input)
Derek Foreman516d6032015-05-08 17:08:40 -0500884 deactivate_input_method(input_method);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200885
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400886 wl_global_destroy(input_method->input_method_global);
Rob Bradfordead3ef82013-07-24 16:57:32 +0100887 wl_list_remove(&input_method->destroy_listener.link);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200888
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200889 free(input_method);
890}
891
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200892static void
893handle_keyboard_focus(struct wl_listener *listener, void *data)
894{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400895 struct weston_keyboard *keyboard = data;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200896 struct input_method *input_method =
Murray Calavera972d1af2015-06-09 20:29:28 +0000897 container_of(listener, struct input_method,
898 keyboard_focus_listener);
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400899 struct weston_surface *surface = keyboard->focus;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200900
Derek Foreman0f299232015-05-08 17:08:41 -0500901 if (!input_method->input)
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200902 return;
903
Derek Foreman0f299232015-05-08 17:08:41 -0500904 if (!surface || input_method->input->surface != surface)
Derek Foreman516d6032015-05-08 17:08:40 -0500905 deactivate_input_method(input_method);
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200906}
907
908static void
909input_method_init_seat(struct weston_seat *seat)
910{
Derek Foreman1281a362015-07-31 16:55:32 -0500911 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
912
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200913 if (seat->input_method->focus_listener_initialized)
914 return;
915
Derek Foreman1281a362015-07-31 16:55:32 -0500916 if (keyboard) {
Murray Calavera972d1af2015-06-09 20:29:28 +0000917 seat->input_method->keyboard_focus_listener.notify =
918 handle_keyboard_focus;
Derek Foreman1281a362015-07-31 16:55:32 -0500919 wl_signal_add(&keyboard->focus_signal,
Murray Calavera972d1af2015-06-09 20:29:28 +0000920 &seat->input_method->keyboard_focus_listener);
Derek Foreman1281a362015-07-31 16:55:32 -0500921 keyboard->input_method_grab.interface =
Murray Calavera972d1af2015-06-09 20:29:28 +0000922 &input_method_context_grab;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200923 }
924
Derek Foremanddc2c972015-07-15 13:00:32 -0500925 seat->input_method->focus_listener_initialized = true;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200926}
927
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300928static void launch_input_method(struct text_backend *text_backend);
929
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100930static void
Derek Foreman89dcea92015-06-25 15:49:49 -0500931respawn_input_method_process(struct text_backend *text_backend)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200932{
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300933 uint32_t time;
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300934
935 /* if input_method dies more than 5 times in 10 seconds, give up */
936 time = weston_compositor_get_time();
937 if (time - text_backend->input_method.deathstamp > 10000) {
938 text_backend->input_method.deathstamp = time;
939 text_backend->input_method.deathcount = 0;
940 }
941
942 text_backend->input_method.deathcount++;
943 if (text_backend->input_method.deathcount > 5) {
Derek Foreman89dcea92015-06-25 15:49:49 -0500944 weston_log("input_method disconnected, giving up.\n");
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300945 return;
946 }
947
Derek Foreman89dcea92015-06-25 15:49:49 -0500948 weston_log("input_method disconnected, respawning...\n");
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300949 launch_input_method(text_backend);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100950}
951
952static void
Derek Foreman89dcea92015-06-25 15:49:49 -0500953input_method_client_notifier(struct wl_listener *listener, void *data)
954{
955 struct text_backend *text_backend;
956
957 text_backend = container_of(listener, struct text_backend,
958 client_listener);
959
960 text_backend->input_method.client = NULL;
961 respawn_input_method_process(text_backend);
962}
963
964static void
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100965launch_input_method(struct text_backend *text_backend)
966{
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100967 if (!text_backend->input_method.path)
968 return;
969
Murray Calaveraf65f89b2015-06-09 20:28:06 +0000970 if (strcmp(text_backend->input_method.path, "") == 0)
971 return;
972
Murray Calavera972d1af2015-06-09 20:29:28 +0000973 text_backend->input_method.client =
Derek Foreman89dcea92015-06-25 15:49:49 -0500974 weston_client_start(text_backend->compositor,
975 text_backend->input_method.path);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100976
Derek Foreman89dcea92015-06-25 15:49:49 -0500977 if (!text_backend->input_method.client) {
Murray Calavera972d1af2015-06-09 20:29:28 +0000978 weston_log("not able to start %s\n",
979 text_backend->input_method.path);
Derek Foreman89dcea92015-06-25 15:49:49 -0500980 return;
981 }
982
983 text_backend->client_listener.notify = input_method_client_notifier;
984 wl_client_add_destroy_listener(text_backend->input_method.client,
985 &text_backend->client_listener);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100986}
987
988static void
Murray Calavera25881242015-06-10 21:15:30 +0000989text_backend_seat_created(struct text_backend *text_backend,
990 struct weston_seat *seat)
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100991{
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200992 struct input_method *input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100993 struct weston_compositor *ec = seat->compositor;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200994
Bryce Harringtonde16d892014-11-20 22:21:57 -0800995 input_method = zalloc(sizeof *input_method);
996 if (input_method == NULL)
997 return;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200998
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200999 input_method->seat = seat;
Derek Foreman0f299232015-05-08 17:08:41 -05001000 input_method->input = NULL;
Derek Foremanddc2c972015-07-15 13:00:32 -05001001 input_method->focus_listener_initialized = false;
Jan Arne Petersen620cd622012-09-09 23:08:32 +02001002 input_method->context = NULL;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001003 input_method->text_backend = text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +02001004
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +02001005 input_method->input_method_global =
Jonas Ådahlb57f4722015-11-17 16:00:30 +08001006 wl_global_create(ec->wl_display,
1007 &zwp_input_method_v1_interface, 1,
Kristian Høgsberg919cddb2013-07-08 19:03:57 -04001008 input_method, bind_input_method);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +02001009
Jan Arne Petersen1f17be42012-06-21 21:52:18 +02001010 input_method->destroy_listener.notify = input_method_notifier_destroy;
Kristian Høgsberg49124542013-05-06 22:27:40 -04001011 wl_signal_add(&seat->destroy_signal, &input_method->destroy_listener);
Jan Arne Petersene829adc2012-08-10 16:47:22 +02001012
1013 seat->input_method = input_method;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +02001014}
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +02001015
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001016static void
Murray Calavera25881242015-06-10 21:15:30 +00001017handle_seat_created(struct wl_listener *listener, void *data)
1018{
1019 struct weston_seat *seat = data;
1020 struct text_backend *text_backend =
1021 container_of(listener, struct text_backend,
1022 seat_created_listener);
1023
1024 text_backend_seat_created(text_backend, seat);
1025}
1026
1027static void
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001028text_backend_configuration(struct text_backend *text_backend)
1029{
Giulio Camuffod52f3b72016-06-02 21:48:11 +03001030 struct weston_config *config = wet_get_config(text_backend->compositor);
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -04001031 struct weston_config_section *section;
Derek Foremanc7210432014-08-21 11:32:38 -05001032 char *client;
Pekka Paalanen974c0942014-09-05 14:45:09 +03001033 int ret;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001034
Giulio Camuffod52f3b72016-06-02 21:48:11 +03001035 section = weston_config_get_section(config,
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -04001036 "input-method", NULL, NULL);
Pekka Paalanen974c0942014-09-05 14:45:09 +03001037 ret = asprintf(&client, "%s/weston-keyboard",
1038 weston_config_get_libexec_dir());
1039 if (ret < 0)
1040 client = NULL;
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -04001041 weston_config_section_get_string(section, "path",
1042 &text_backend->input_method.path,
Derek Foremanc7210432014-08-21 11:32:38 -05001043 client);
1044 free(client);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001045}
1046
Pekka Paalanenaa9536a2015-06-24 16:09:17 +03001047WL_EXPORT void
1048text_backend_destroy(struct text_backend *text_backend)
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001049{
Derek Foreman89dcea92015-06-25 15:49:49 -05001050 if (text_backend->input_method.client) {
1051 /* disable respawn */
1052 wl_list_remove(&text_backend->client_listener.link);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001053 wl_client_destroy(text_backend->input_method.client);
Derek Foreman89dcea92015-06-25 15:49:49 -05001054 }
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001055
1056 free(text_backend->input_method.path);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001057 free(text_backend);
1058}
1059
Pekka Paalanenaa9536a2015-06-24 16:09:17 +03001060WL_EXPORT struct text_backend *
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001061text_backend_init(struct weston_compositor *ec)
1062{
1063 struct text_backend *text_backend;
Murray Calavera25881242015-06-10 21:15:30 +00001064 struct weston_seat *seat;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001065
Bryce Harringtonde16d892014-11-20 22:21:57 -08001066 text_backend = zalloc(sizeof(*text_backend));
1067 if (text_backend == NULL)
Pekka Paalanenaa9536a2015-06-24 16:09:17 +03001068 return NULL;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001069
1070 text_backend->compositor = ec;
1071
Murray Calavera25881242015-06-10 21:15:30 +00001072 text_backend_configuration(text_backend);
1073
1074 wl_list_for_each(seat, &ec->seat_list, link)
1075 text_backend_seat_created(text_backend, seat);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001076 text_backend->seat_created_listener.notify = handle_seat_created;
1077 wl_signal_add(&ec->seat_created_signal,
1078 &text_backend->seat_created_listener);
1079
Jan Arne Petersen78d00e42013-04-18 16:47:24 +02001080 text_input_manager_create(ec);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001081
Derek Foremanb4bacd22015-06-25 15:49:47 -05001082 launch_input_method(text_backend);
1083
Pekka Paalanenaa9536a2015-06-24 16:09:17 +03001084 return text_backend;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001085}