blob: daae03c327cf828eb308cd1cf7947c01469a0a99 [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 *
5 * Permission to use, copy, modify, distribute, and sell this software and
6 * its documentation for any purpose is hereby granted without fee, provided
7 * that the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of the copyright holders not be used in
10 * advertising or publicity pertaining to distribution of the software
11 * without specific, written prior permission. The copyright holders make
12 * no representations about the suitability of this software for any
13 * purpose. It is provided "as is" without express or implied warranty.
14 *
15 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
16 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
19 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
20 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 */
23
Daniel Stonec228e232013-05-22 18:03:19 +030024#include "config.h"
25
Derek Foremand09dbb32014-12-05 15:38:39 -060026#include <stdbool.h>
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020027#include <stdlib.h>
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010028#include <string.h>
Ossama Othmana50e6e42013-05-14 09:48:26 -070029#include <unistd.h>
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -030030#include <time.h>
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020031
32#include "compositor.h"
33#include "text-server-protocol.h"
Jan Arne Petersen30b66ef2012-09-09 23:08:41 +020034#include "input-method-server-protocol.h"
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020035
Derek Foreman516d6032015-05-08 17:08:40 -050036struct text_input_manager;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020037struct input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020038struct input_method_context;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010039struct text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020040
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020041struct text_input {
Jason Ekstrand89d31992013-06-14 10:07:59 -050042 struct wl_resource *resource;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020043
Jan Arne Petersene829adc2012-08-10 16:47:22 +020044 struct weston_compositor *ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020045
Jan Arne Petersene829adc2012-08-10 16:47:22 +020046 struct wl_list input_methods;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +020047
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -040048 struct weston_surface *surface;
Jan Arne Petersen61381972013-01-31 15:52:21 +010049
Jan Arne Petersen14da96b2013-04-18 16:47:28 +020050 pixman_box32_t cursor_rectangle;
51
Derek Foremand09dbb32014-12-05 15:38:39 -060052 bool input_panel_visible;
Derek Foreman516d6032015-05-08 17:08:40 -050053
54 struct text_input_manager *manager;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020055};
56
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020057struct text_input_manager {
58 struct wl_global *text_input_manager_global;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020059 struct wl_listener destroy_listener;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020060
Derek Foreman516d6032015-05-08 17:08:40 -050061 struct text_input *current_panel;
62
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +020063 struct weston_compositor *ec;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +020064};
65
66struct input_method {
67 struct wl_resource *input_method_binding;
68 struct wl_global *input_method_global;
69 struct wl_listener destroy_listener;
70
71 struct weston_seat *seat;
Derek Foreman0f299232015-05-08 17:08:41 -050072 struct text_input *input;
Jan Arne Petersene829adc2012-08-10 16:47:22 +020073
74 struct wl_list link;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +020075
76 struct wl_listener keyboard_focus_listener;
77
78 int focus_listener_initialized;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020079
80 struct input_method_context *context;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010081
82 struct text_backend *text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020083};
84
Jan Arne Petersen620cd622012-09-09 23:08:32 +020085struct input_method_context {
Jason Ekstrand89d31992013-06-14 10:07:59 -050086 struct wl_resource *resource;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020087
Derek Foreman0f299232015-05-08 17:08:41 -050088 struct text_input *input;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +010089 struct input_method *input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020090
Jan Arne Petersen466b9c12012-11-18 19:06:45 +010091 struct wl_resource *keyboard;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020092};
93
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010094struct text_backend {
95 struct weston_compositor *compositor;
96
97 struct {
98 char *path;
99 struct wl_resource *binding;
100 struct weston_process process;
101 struct wl_client *client;
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300102
103 unsigned deathcount;
104 uint32_t deathstamp;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100105 } input_method;
106
107 struct wl_listener seat_created_listener;
108 struct wl_listener destroy_listener;
109};
110
Derek Foremancb5fcea2014-12-05 15:38:37 -0600111static void
Derek Foreman0f299232015-05-08 17:08:41 -0500112input_method_context_create(struct text_input *input,
Derek Foremancb5fcea2014-12-05 15:38:37 -0600113 struct input_method *input_method);
114static void
115input_method_context_end_keyboard_grab(struct input_method_context *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200116
Derek Foremancb5fcea2014-12-05 15:38:37 -0600117static void
118input_method_init_seat(struct weston_seat *seat);
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200119
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200120static void
Derek Foreman516d6032015-05-08 17:08:40 -0500121deactivate_input_method(struct input_method *input_method)
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200122{
Derek Foreman0f299232015-05-08 17:08:41 -0500123 struct text_input *text_input = input_method->input;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200124 struct weston_compositor *ec = text_input->ec;
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200125
Derek Foreman516d6032015-05-08 17:08:40 -0500126 if (input_method->context && input_method->input_method_binding) {
127 input_method_context_end_keyboard_grab(input_method->context);
128 wl_input_method_send_deactivate(input_method->input_method_binding,
129 input_method->context->resource);
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200130 }
Derek Foreman516d6032015-05-08 17:08:40 -0500131
132 wl_list_remove(&input_method->link);
Derek Foreman0f299232015-05-08 17:08:41 -0500133 input_method->input = NULL;
Derek Foreman516d6032015-05-08 17:08:40 -0500134 input_method->context = NULL;
135
136 if (wl_list_empty(&text_input->input_methods) &&
137 text_input->input_panel_visible) {
138 wl_signal_emit(&ec->hide_input_panel_signal, ec);
139 text_input->input_panel_visible = false;
140 text_input->manager->current_panel = NULL;
141 }
142 wl_text_input_send_leave(text_input->resource);
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200143}
144
145static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200146destroy_text_input(struct wl_resource *resource)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200147{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500148 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200149 struct input_method *input_method, *next;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200150
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200151 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link)
Derek Foreman516d6032015-05-08 17:08:40 -0500152 deactivate_input_method(input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200153
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200154 free(text_input);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200155}
156
157static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200158text_input_set_surrounding_text(struct wl_client *client,
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200159 struct wl_resource *resource,
Jan Arne Petersencb08f4d2012-09-09 23:08:40 +0200160 const char *text,
161 uint32_t cursor,
162 uint32_t anchor)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200163{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500164 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200165 struct input_method *input_method, *next;
166
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200167 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200168 if (!input_method->context)
169 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500170 wl_input_method_context_send_surrounding_text(input_method->context->resource,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200171 text,
172 cursor,
173 anchor);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200174 }
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200175}
176
177static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200178text_input_activate(struct wl_client *client,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200179 struct wl_resource *resource,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200180 struct wl_resource *seat,
181 struct wl_resource *surface)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200182{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500183 struct text_input *text_input = wl_resource_get_user_data(resource);
Jason Ekstrand44a38632013-06-14 10:08:00 -0500184 struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200185 struct input_method *input_method = weston_seat->input_method;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200186 struct weston_compositor *ec = text_input->ec;
Derek Foreman516d6032015-05-08 17:08:40 -0500187 struct text_input *current;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200188
Derek Foreman0f299232015-05-08 17:08:41 -0500189 if (input_method->input == text_input)
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200190 return;
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200191
Derek Foreman0f299232015-05-08 17:08:41 -0500192 if (input_method->input)
Derek Foreman516d6032015-05-08 17:08:40 -0500193 deactivate_input_method(input_method);
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200194
Derek Foreman0f299232015-05-08 17:08:41 -0500195 input_method->input = text_input;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200196 wl_list_insert(&text_input->input_methods, &input_method->link);
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200197 input_method_init_seat(weston_seat);
198
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -0500199 text_input->surface = wl_resource_get_user_data(surface);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200200
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200201 input_method_context_create(text_input, input_method);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200202
Derek Foreman516d6032015-05-08 17:08:40 -0500203 current = text_input->manager->current_panel;
204
205 if (current && current != text_input) {
206 current->input_panel_visible = false;
207 wl_signal_emit(&ec->hide_input_panel_signal, ec);
208 text_input->manager->current_panel = NULL;
209 }
210
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200211 if (text_input->input_panel_visible) {
212 wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
213 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
Derek Foreman516d6032015-05-08 17:08:40 -0500214 text_input->manager->current_panel = text_input;
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200215 }
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200216
Jason Ekstrand89d31992013-06-14 10:07:59 -0500217 wl_text_input_send_enter(text_input->resource, text_input->surface->resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200218}
219
220static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200221text_input_deactivate(struct wl_client *client,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200222 struct wl_resource *resource,
223 struct wl_resource *seat)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200224{
Jason Ekstrand44a38632013-06-14 10:08:00 -0500225 struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200226
Derek Foreman0f299232015-05-08 17:08:41 -0500227 if (weston_seat->input_method->input)
Derek Foreman516d6032015-05-08 17:08:40 -0500228 deactivate_input_method(weston_seat->input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200229}
230
231static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200232text_input_reset(struct wl_client *client,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200233 struct wl_resource *resource)
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200234{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500235 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200236 struct input_method *input_method, *next;
237
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200238 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200239 if (!input_method->context)
240 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500241 wl_input_method_context_send_reset(input_method->context->resource);
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200242 }
243}
244
245static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200246text_input_set_cursor_rectangle(struct wl_client *client,
Jan Arne Petersen7ef8eff2013-04-18 16:47:23 +0200247 struct wl_resource *resource,
248 int32_t x,
249 int32_t y,
250 int32_t width,
251 int32_t height)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200252{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500253 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200254 struct weston_compositor *ec = text_input->ec;
255
256 text_input->cursor_rectangle.x1 = x;
257 text_input->cursor_rectangle.y1 = y;
258 text_input->cursor_rectangle.x2 = x + width;
259 text_input->cursor_rectangle.y2 = y + height;
260
261 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200262}
263
264static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200265text_input_set_content_type(struct wl_client *client,
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100266 struct wl_resource *resource,
267 uint32_t hint,
268 uint32_t purpose)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200269{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500270 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100271 struct input_method *input_method, *next;
272
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200273 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100274 if (!input_method->context)
275 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500276 wl_input_method_context_send_content_type(input_method->context->resource, hint, purpose);
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100277 }
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200278}
279
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100280static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200281text_input_invoke_action(struct wl_client *client,
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100282 struct wl_resource *resource,
283 uint32_t button,
284 uint32_t index)
285{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500286 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100287 struct input_method *input_method, *next;
288
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200289 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100290 if (!input_method->context)
291 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500292 wl_input_method_context_send_invoke_action(input_method->context->resource, button, index);
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100293 }
294}
295
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100296static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200297text_input_commit_state(struct wl_client *client,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200298 struct wl_resource *resource,
299 uint32_t serial)
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100300{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500301 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100302 struct input_method *input_method, *next;
303
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200304 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100305 if (!input_method->context)
306 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500307 wl_input_method_context_send_commit_state(input_method->context->resource, serial);
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100308 }
309}
310
Jan Arne Petersen61381972013-01-31 15:52:21 +0100311static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200312text_input_show_input_panel(struct wl_client *client,
Jan Arne Petersen61381972013-01-31 15:52:21 +0100313 struct wl_resource *resource)
314{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500315 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200316 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100317
Derek Foremand09dbb32014-12-05 15:38:39 -0600318 text_input->input_panel_visible = true;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100319
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200320 if (!wl_list_empty(&text_input->input_methods)) {
321 wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
322 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
323 }
Jan Arne Petersen61381972013-01-31 15:52:21 +0100324}
325
326static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200327text_input_hide_input_panel(struct wl_client *client,
Jan Arne Petersen61381972013-01-31 15:52:21 +0100328 struct wl_resource *resource)
329{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500330 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200331 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100332
Derek Foremand09dbb32014-12-05 15:38:39 -0600333 text_input->input_panel_visible = false;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100334
Derek Foreman516d6032015-05-08 17:08:40 -0500335 if (!wl_list_empty(&text_input->input_methods) &&
336 text_input == text_input->manager->current_panel) {
337 text_input->manager->current_panel = NULL;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100338 wl_signal_emit(&ec->hide_input_panel_signal, ec);
Derek Foreman516d6032015-05-08 17:08:40 -0500339 }
Jan Arne Petersen61381972013-01-31 15:52:21 +0100340}
341
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200342static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200343text_input_set_preferred_language(struct wl_client *client,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200344 struct wl_resource *resource,
345 const char *language)
346{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500347 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200348 struct input_method *input_method, *next;
349
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200350 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200351 if (!input_method->context)
352 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500353 wl_input_method_context_send_preferred_language(input_method->context->resource,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200354 language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200355 }
356}
357
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200358static const struct wl_text_input_interface text_input_implementation = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200359 text_input_activate,
360 text_input_deactivate,
361 text_input_show_input_panel,
362 text_input_hide_input_panel,
363 text_input_reset,
364 text_input_set_surrounding_text,
365 text_input_set_content_type,
366 text_input_set_cursor_rectangle,
367 text_input_set_preferred_language,
368 text_input_commit_state,
369 text_input_invoke_action
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200370};
371
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200372static void text_input_manager_create_text_input(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200373 struct wl_resource *resource,
Jan Arne Petersen4c265182012-09-09 23:08:30 +0200374 uint32_t id)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200375{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500376 struct text_input_manager *text_input_manager = wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200377 struct text_input *text_input;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200378
Bryce Harringtonde16d892014-11-20 22:21:57 -0800379 text_input = zalloc(sizeof *text_input);
380 if (text_input == NULL)
381 return;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200382
Jason Ekstranda85118c2013-06-27 20:17:02 -0500383 text_input->resource =
384 wl_resource_create(client, &wl_text_input_interface, 1, id);
385 wl_resource_set_implementation(text_input->resource,
386 &text_input_implementation,
387 text_input, destroy_text_input);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200388
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200389 text_input->ec = text_input_manager->ec;
Derek Foreman516d6032015-05-08 17:08:40 -0500390 text_input->manager = text_input_manager;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200391
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200392 wl_list_init(&text_input->input_methods);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200393};
394
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200395static const struct wl_text_input_manager_interface text_input_manager_implementation = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200396 text_input_manager_create_text_input
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200397};
398
399static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200400bind_text_input_manager(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200401 void *data,
402 uint32_t version,
403 uint32_t id)
404{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200405 struct text_input_manager *text_input_manager = data;
Jason Ekstranda85118c2013-06-27 20:17:02 -0500406 struct wl_resource *resource;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200407
Jason Ekstranda85118c2013-06-27 20:17:02 -0500408 /* No checking for duplicate binding necessary. */
409 resource =
410 wl_resource_create(client,
411 &wl_text_input_manager_interface, 1, id);
412 if (resource)
413 wl_resource_set_implementation(resource,
414 &text_input_manager_implementation,
415 text_input_manager, NULL);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200416}
417
418static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200419text_input_manager_notifier_destroy(struct wl_listener *listener, void *data)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200420{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200421 struct text_input_manager *text_input_manager =
422 container_of(listener, struct text_input_manager, destroy_listener);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200423
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400424 wl_global_destroy(text_input_manager->text_input_manager_global);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200425
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200426 free(text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200427}
428
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100429static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200430text_input_manager_create(struct weston_compositor *ec)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200431{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200432 struct text_input_manager *text_input_manager;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200433
Bryce Harringtonde16d892014-11-20 22:21:57 -0800434 text_input_manager = zalloc(sizeof *text_input_manager);
435 if (text_input_manager == NULL)
436 return;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200437
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200438 text_input_manager->ec = ec;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200439
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200440 text_input_manager->text_input_manager_global =
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400441 wl_global_create(ec->wl_display,
442 &wl_text_input_manager_interface, 1,
443 text_input_manager, bind_text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200444
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200445 text_input_manager->destroy_listener.notify = text_input_manager_notifier_destroy;
446 wl_signal_add(&ec->destroy_signal, &text_input_manager->destroy_listener);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200447}
448
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200449static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200450input_method_context_destroy(struct wl_client *client,
451 struct wl_resource *resource)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200452{
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200453 wl_resource_destroy(resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200454}
455
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200456static void
457input_method_context_commit_string(struct wl_client *client,
458 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100459 uint32_t serial,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100460 const char *text)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200461{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500462 struct input_method_context *context =
463 wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200464
Derek Foreman0f299232015-05-08 17:08:41 -0500465 if (context->input)
466 wl_text_input_send_commit_string(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800467 serial, text);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200468}
469
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200470static void
471input_method_context_preedit_string(struct wl_client *client,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100472 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100473 uint32_t serial,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100474 const char *text,
475 const char *commit)
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200476{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500477 struct input_method_context *context =
478 wl_resource_get_user_data(resource);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200479
Derek Foreman0f299232015-05-08 17:08:41 -0500480 if (context->input)
481 wl_text_input_send_preedit_string(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800482 serial, text, commit);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100483}
484
485static void
486input_method_context_preedit_styling(struct wl_client *client,
487 struct wl_resource *resource,
488 uint32_t index,
489 uint32_t length,
490 uint32_t style)
491{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500492 struct input_method_context *context =
493 wl_resource_get_user_data(resource);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100494
Derek Foreman0f299232015-05-08 17:08:41 -0500495 if (context->input)
496 wl_text_input_send_preedit_styling(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800497 index, length, style);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100498}
499
500static void
501input_method_context_preedit_cursor(struct wl_client *client,
502 struct wl_resource *resource,
503 int32_t cursor)
504{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500505 struct input_method_context *context =
506 wl_resource_get_user_data(resource);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100507
Derek Foreman0f299232015-05-08 17:08:41 -0500508 if (context->input)
509 wl_text_input_send_preedit_cursor(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800510 cursor);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200511}
512
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200513static void
514input_method_context_delete_surrounding_text(struct wl_client *client,
515 struct wl_resource *resource,
516 int32_t index,
517 uint32_t length)
518{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500519 struct input_method_context *context =
520 wl_resource_get_user_data(resource);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200521
Derek Foreman0f299232015-05-08 17:08:41 -0500522 if (context->input)
523 wl_text_input_send_delete_surrounding_text(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800524 index, length);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200525}
526
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200527static void
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100528input_method_context_cursor_position(struct wl_client *client,
529 struct wl_resource *resource,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100530 int32_t index,
531 int32_t anchor)
532{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500533 struct input_method_context *context =
534 wl_resource_get_user_data(resource);
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100535
Derek Foreman0f299232015-05-08 17:08:41 -0500536 if (context->input)
537 wl_text_input_send_cursor_position(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800538 index, anchor);
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100539}
540
541static void
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100542input_method_context_modifiers_map(struct wl_client *client,
543 struct wl_resource *resource,
544 struct wl_array *map)
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200545{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500546 struct input_method_context *context =
547 wl_resource_get_user_data(resource);
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200548
Derek Foreman0f299232015-05-08 17:08:41 -0500549 if (context->input)
550 wl_text_input_send_modifiers_map(context->input->resource, map);
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100551}
552
553static void
554input_method_context_keysym(struct wl_client *client,
555 struct wl_resource *resource,
556 uint32_t serial,
557 uint32_t time,
558 uint32_t sym,
559 uint32_t state,
560 uint32_t modifiers)
561{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500562 struct input_method_context *context =
563 wl_resource_get_user_data(resource);
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100564
Derek Foreman0f299232015-05-08 17:08:41 -0500565 if (context->input)
566 wl_text_input_send_keysym(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800567 serial, time, sym, state, modifiers);
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200568}
569
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100570static void
571unbind_keyboard(struct wl_resource *resource)
572{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500573 struct input_method_context *context =
574 wl_resource_get_user_data(resource);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100575
576 input_method_context_end_keyboard_grab(context);
577 context->keyboard = NULL;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100578}
579
580static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400581input_method_context_grab_key(struct weston_keyboard_grab *grab,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100582 uint32_t time, uint32_t key, uint32_t state_w)
583{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400584 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100585 struct wl_display *display;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100586 uint32_t serial;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100587
588 if (!keyboard->input_method_resource)
589 return;
590
Jason Ekstrand89d31992013-06-14 10:07:59 -0500591 display = wl_client_get_display(wl_resource_get_client(keyboard->input_method_resource));
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100592 serial = wl_display_next_serial(display);
593 wl_keyboard_send_key(keyboard->input_method_resource,
594 serial, time, key, state_w);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100595}
596
597static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400598input_method_context_grab_modifier(struct weston_keyboard_grab *grab, uint32_t serial,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100599 uint32_t mods_depressed, uint32_t mods_latched,
600 uint32_t mods_locked, uint32_t group)
601{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400602 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100603
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100604 if (!keyboard->input_method_resource)
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100605 return;
606
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100607 wl_keyboard_send_modifiers(keyboard->input_method_resource,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100608 serial, mods_depressed, mods_latched,
609 mods_locked, group);
610}
611
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200612static void
613input_method_context_grab_cancel(struct weston_keyboard_grab *grab)
614{
615 weston_keyboard_end_grab(grab->keyboard);
616}
617
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400618static const struct weston_keyboard_grab_interface input_method_context_grab = {
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100619 input_method_context_grab_key,
620 input_method_context_grab_modifier,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200621 input_method_context_grab_cancel,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100622};
623
624static void
625input_method_context_grab_keyboard(struct wl_client *client,
626 struct wl_resource *resource,
627 uint32_t id)
628{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500629 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100630 struct wl_resource *cr;
631 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400632 struct weston_keyboard *keyboard = seat->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100633
Jason Ekstranda85118c2013-06-27 20:17:02 -0500634 cr = wl_resource_create(client, &wl_keyboard_interface, 1, id);
635 wl_resource_set_implementation(cr, NULL, context, unbind_keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100636
637 context->keyboard = cr;
638
639 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
Jonas Ådahl7395ea02013-12-03 09:14:26 +0100640 keyboard->xkb_info->keymap_fd,
641 keyboard->xkb_info->keymap_size);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100642
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400643 if (keyboard->grab != &keyboard->default_grab) {
644 weston_keyboard_end_grab(keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100645 }
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400646 weston_keyboard_start_grab(keyboard, &keyboard->input_method_grab);
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100647 keyboard->input_method_resource = cr;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100648}
649
Jan Arne Petersen337df952012-11-18 19:06:46 +0100650static void
651input_method_context_key(struct wl_client *client,
652 struct wl_resource *resource,
653 uint32_t serial,
654 uint32_t time,
655 uint32_t key,
656 uint32_t state_w)
657{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500658 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen337df952012-11-18 19:06:46 +0100659 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400660 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400661 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100662
663 default_grab->interface->key(default_grab, time, key, state_w);
664}
665
666static void
667input_method_context_modifiers(struct wl_client *client,
668 struct wl_resource *resource,
669 uint32_t serial,
670 uint32_t mods_depressed,
671 uint32_t mods_latched,
672 uint32_t mods_locked,
673 uint32_t group)
674{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500675 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen337df952012-11-18 19:06:46 +0100676
677 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400678 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400679 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100680
681 default_grab->interface->modifiers(default_grab,
682 serial, mods_depressed,
683 mods_latched, mods_locked,
684 group);
685}
686
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200687static void
688input_method_context_language(struct wl_client *client,
689 struct wl_resource *resource,
690 uint32_t serial,
691 const char *language)
692{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500693 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200694
Derek Foreman0f299232015-05-08 17:08:41 -0500695 if (context->input)
696 wl_text_input_send_language(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800697 serial, language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200698}
699
700static void
701input_method_context_text_direction(struct wl_client *client,
702 struct wl_resource *resource,
703 uint32_t serial,
704 uint32_t direction)
705{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500706 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200707
Derek Foreman0f299232015-05-08 17:08:41 -0500708 if (context->input)
709 wl_text_input_send_text_direction(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800710 serial, direction);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200711}
712
713
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200714static const struct wl_input_method_context_interface input_method_context_implementation = {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200715 input_method_context_destroy,
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200716 input_method_context_commit_string,
717 input_method_context_preedit_string,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100718 input_method_context_preedit_styling,
719 input_method_context_preedit_cursor,
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200720 input_method_context_delete_surrounding_text,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100721 input_method_context_cursor_position,
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100722 input_method_context_modifiers_map,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100723 input_method_context_keysym,
Jan Arne Petersen337df952012-11-18 19:06:46 +0100724 input_method_context_grab_keyboard,
725 input_method_context_key,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200726 input_method_context_modifiers,
727 input_method_context_language,
728 input_method_context_text_direction
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200729};
730
731static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200732destroy_input_method_context(struct wl_resource *resource)
733{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500734 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200735
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100736 if (context->keyboard) {
737 wl_resource_destroy(context->keyboard);
738 }
739
Derek Foreman516d6032015-05-08 17:08:40 -0500740 if (context->input_method && context->input_method->context == context)
741 context->input_method->context = NULL;
742
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200743 free(context);
744}
745
746static void
Derek Foreman0f299232015-05-08 17:08:41 -0500747input_method_context_create(struct text_input *input,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200748 struct input_method *input_method)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200749{
750 struct input_method_context *context;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500751 struct wl_resource *binding;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200752
753 if (!input_method->input_method_binding)
754 return;
755
Bryce Harringtonde16d892014-11-20 22:21:57 -0800756 context = zalloc(sizeof *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200757 if (context == NULL)
758 return;
759
Jason Ekstrand89d31992013-06-14 10:07:59 -0500760 binding = input_method->input_method_binding;
Jason Ekstranda85118c2013-06-27 20:17:02 -0500761 context->resource =
762 wl_resource_create(wl_resource_get_client(binding),
763 &wl_input_method_context_interface, 1, 0);
764 wl_resource_set_implementation(context->resource,
765 &input_method_context_implementation,
766 context, destroy_input_method_context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200767
Derek Foreman0f299232015-05-08 17:08:41 -0500768 context->input = input;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100769 context->input_method = input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200770 input_method->context = context;
771
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200772
Jason Ekstrand89d31992013-06-14 10:07:59 -0500773 wl_input_method_send_activate(binding, context->resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200774}
775
776static void
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100777input_method_context_end_keyboard_grab(struct input_method_context *context)
778{
Derek Foremanf0aaa412014-12-08 10:48:29 -0600779 struct weston_keyboard_grab *grab;
780 struct weston_keyboard *keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100781
Derek Foremanf0aaa412014-12-08 10:48:29 -0600782 if (!context->input_method->seat->keyboard)
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100783 return;
784
Derek Foremanf0aaa412014-12-08 10:48:29 -0600785 grab = &context->input_method->seat->keyboard->input_method_grab;
786 keyboard = grab->keyboard;
787 if (!keyboard)
788 return;
789
790 if (keyboard->grab == grab)
791 weston_keyboard_end_grab(keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100792
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100793 keyboard->input_method_resource = NULL;
794}
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100795
796static void
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200797unbind_input_method(struct wl_resource *resource)
798{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500799 struct input_method *input_method = wl_resource_get_user_data(resource);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100800 struct text_backend *text_backend = input_method->text_backend;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200801
802 input_method->input_method_binding = NULL;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200803 input_method->context = NULL;
804
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100805 text_backend->input_method.binding = NULL;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200806}
807
808static void
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200809bind_input_method(struct wl_client *client,
810 void *data,
811 uint32_t version,
812 uint32_t id)
813{
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200814 struct input_method *input_method = data;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100815 struct text_backend *text_backend = input_method->text_backend;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200816 struct wl_resource *resource;
817
Jason Ekstranda85118c2013-06-27 20:17:02 -0500818 resource =
819 wl_resource_create(client, &wl_input_method_interface, 1, id);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200820
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200821 if (input_method->input_method_binding != NULL) {
822 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
823 "interface object already bound");
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200824 return;
825 }
826
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200827 if (text_backend->input_method.client != client) {
828 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
Eduardo Lima (Etrunko)a2ce68f2013-05-10 17:50:36 -0300829 "permission to bind input_method denied");
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200830 return;
831 }
832
Jason Ekstranda85118c2013-06-27 20:17:02 -0500833 wl_resource_set_implementation(resource, NULL, input_method,
834 unbind_input_method);
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200835 input_method->input_method_binding = resource;
836
837 text_backend->input_method.binding = resource;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200838}
839
840static void
841input_method_notifier_destroy(struct wl_listener *listener, void *data)
842{
Kristian Høgsbergf97f3792012-07-22 11:51:42 -0400843 struct input_method *input_method =
844 container_of(listener, struct input_method, destroy_listener);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200845
Derek Foreman0f299232015-05-08 17:08:41 -0500846 if (input_method->input)
Derek Foreman516d6032015-05-08 17:08:40 -0500847 deactivate_input_method(input_method);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200848
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400849 wl_global_destroy(input_method->input_method_global);
Rob Bradfordead3ef82013-07-24 16:57:32 +0100850 wl_list_remove(&input_method->destroy_listener.link);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200851
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200852 free(input_method);
853}
854
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200855static void
856handle_keyboard_focus(struct wl_listener *listener, void *data)
857{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400858 struct weston_keyboard *keyboard = data;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200859 struct input_method *input_method =
860 container_of(listener, struct input_method, keyboard_focus_listener);
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400861 struct weston_surface *surface = keyboard->focus;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200862
Derek Foreman0f299232015-05-08 17:08:41 -0500863 if (!input_method->input)
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200864 return;
865
Derek Foreman0f299232015-05-08 17:08:41 -0500866 if (!surface || input_method->input->surface != surface)
Derek Foreman516d6032015-05-08 17:08:40 -0500867 deactivate_input_method(input_method);
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200868}
869
870static void
871input_method_init_seat(struct weston_seat *seat)
872{
873 if (seat->input_method->focus_listener_initialized)
874 return;
875
Kristian Høgsberg2bf87622013-05-07 23:17:41 -0400876 if (seat->keyboard) {
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200877 seat->input_method->keyboard_focus_listener.notify = handle_keyboard_focus;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400878 wl_signal_add(&seat->keyboard->focus_signal, &seat->input_method->keyboard_focus_listener);
879 seat->keyboard->input_method_grab.interface = &input_method_context_grab;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200880 }
881
882 seat->input_method->focus_listener_initialized = 1;
883}
884
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300885static void launch_input_method(struct text_backend *text_backend);
886
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100887static void
888handle_input_method_sigchld(struct weston_process *process, int status)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200889{
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300890 uint32_t time;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100891 struct text_backend *text_backend =
892 container_of(process, struct text_backend, input_method.process);
893
894 text_backend->input_method.process.pid = 0;
895 text_backend->input_method.client = NULL;
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300896
897 /* if input_method dies more than 5 times in 10 seconds, give up */
898 time = weston_compositor_get_time();
899 if (time - text_backend->input_method.deathstamp > 10000) {
900 text_backend->input_method.deathstamp = time;
901 text_backend->input_method.deathcount = 0;
902 }
903
904 text_backend->input_method.deathcount++;
905 if (text_backend->input_method.deathcount > 5) {
906 weston_log("input_method died, giving up.\n");
907 return;
908 }
909
910 weston_log("input_method died, respawning...\n");
911 launch_input_method(text_backend);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100912}
913
914static void
915launch_input_method(struct text_backend *text_backend)
916{
917 if (text_backend->input_method.binding)
918 return;
919
920 if (!text_backend->input_method.path)
921 return;
922
923 if (text_backend->input_method.process.pid != 0)
924 return;
925
926 text_backend->input_method.client = weston_client_launch(text_backend->compositor,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200927 &text_backend->input_method.process,
928 text_backend->input_method.path,
929 handle_input_method_sigchld);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100930
931 if (!text_backend->input_method.client)
932 weston_log("not able to start %s\n", text_backend->input_method.path);
933}
934
935static void
936handle_seat_created(struct wl_listener *listener,
937 void *data)
938{
939 struct weston_seat *seat = data;
940 struct text_backend *text_backend =
941 container_of(listener, struct text_backend,
942 seat_created_listener);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200943 struct input_method *input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100944 struct weston_compositor *ec = seat->compositor;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200945
Bryce Harringtonde16d892014-11-20 22:21:57 -0800946 input_method = zalloc(sizeof *input_method);
947 if (input_method == NULL)
948 return;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200949
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200950 input_method->seat = seat;
Derek Foreman0f299232015-05-08 17:08:41 -0500951 input_method->input = NULL;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200952 input_method->focus_listener_initialized = 0;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200953 input_method->context = NULL;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100954 input_method->text_backend = text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200955
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200956 input_method->input_method_global =
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400957 wl_global_create(ec->wl_display, &wl_input_method_interface, 1,
958 input_method, bind_input_method);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200959
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200960 input_method->destroy_listener.notify = input_method_notifier_destroy;
Kristian Høgsberg49124542013-05-06 22:27:40 -0400961 wl_signal_add(&seat->destroy_signal, &input_method->destroy_listener);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200962
963 seat->input_method = input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100964
965 launch_input_method(text_backend);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200966}
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200967
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100968static void
969text_backend_configuration(struct text_backend *text_backend)
970{
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -0400971 struct weston_config_section *section;
Derek Foremanc7210432014-08-21 11:32:38 -0500972 char *client;
Pekka Paalanen974c0942014-09-05 14:45:09 +0300973 int ret;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100974
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -0400975 section = weston_config_get_section(text_backend->compositor->config,
976 "input-method", NULL, NULL);
Pekka Paalanen974c0942014-09-05 14:45:09 +0300977 ret = asprintf(&client, "%s/weston-keyboard",
978 weston_config_get_libexec_dir());
979 if (ret < 0)
980 client = NULL;
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -0400981 weston_config_section_get_string(section, "path",
982 &text_backend->input_method.path,
Derek Foremanc7210432014-08-21 11:32:38 -0500983 client);
984 free(client);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100985}
986
987static void
988text_backend_notifier_destroy(struct wl_listener *listener, void *data)
989{
990 struct text_backend *text_backend =
991 container_of(listener, struct text_backend, destroy_listener);
992
993 if (text_backend->input_method.client)
994 wl_client_destroy(text_backend->input_method.client);
995
996 free(text_backend->input_method.path);
997
998 free(text_backend);
999}
1000
1001
1002WL_EXPORT int
1003text_backend_init(struct weston_compositor *ec)
1004{
1005 struct text_backend *text_backend;
1006
Bryce Harringtonde16d892014-11-20 22:21:57 -08001007 text_backend = zalloc(sizeof(*text_backend));
1008 if (text_backend == NULL)
1009 return -1;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001010
1011 text_backend->compositor = ec;
1012
1013 text_backend->seat_created_listener.notify = handle_seat_created;
1014 wl_signal_add(&ec->seat_created_signal,
1015 &text_backend->seat_created_listener);
1016
1017 text_backend->destroy_listener.notify = text_backend_notifier_destroy;
1018 wl_signal_add(&ec->destroy_signal, &text_backend->destroy_listener);
1019
1020 text_backend_configuration(text_backend);
1021
Jan Arne Petersen78d00e42013-04-18 16:47:24 +02001022 text_input_manager_create(ec);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001023
1024 return 0;
1025}