blob: 092321a6e79d18e880d6acf91c4b741458111525 [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
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020026#include <stdlib.h>
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010027#include <string.h>
Ossama Othmana50e6e42013-05-14 09:48:26 -070028#include <unistd.h>
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -030029#include <time.h>
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020030
31#include "compositor.h"
32#include "text-server-protocol.h"
Jan Arne Petersen30b66ef2012-09-09 23:08:41 +020033#include "input-method-server-protocol.h"
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020034
35struct input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020036struct input_method_context;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010037struct text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020038
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020039struct text_input {
Jason Ekstrand89d31992013-06-14 10:07:59 -050040 struct wl_resource *resource;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020041
Jan Arne Petersene829adc2012-08-10 16:47:22 +020042 struct weston_compositor *ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020043
Jan Arne Petersene829adc2012-08-10 16:47:22 +020044 struct wl_list input_methods;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +020045
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -040046 struct weston_surface *surface;
Jan Arne Petersen61381972013-01-31 15:52:21 +010047
Jan Arne Petersen14da96b2013-04-18 16:47:28 +020048 pixman_box32_t cursor_rectangle;
49
Jan Arne Petersen61381972013-01-31 15:52:21 +010050 uint32_t input_panel_visible;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020051};
52
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020053struct text_input_manager {
54 struct wl_global *text_input_manager_global;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020055 struct wl_listener destroy_listener;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020056
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +020057 struct weston_compositor *ec;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +020058};
59
60struct input_method {
61 struct wl_resource *input_method_binding;
62 struct wl_global *input_method_global;
63 struct wl_listener destroy_listener;
64
65 struct weston_seat *seat;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020066 struct text_input *model;
Jan Arne Petersene829adc2012-08-10 16:47:22 +020067
68 struct wl_list link;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +020069
70 struct wl_listener keyboard_focus_listener;
71
72 int focus_listener_initialized;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020073
74 struct input_method_context *context;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010075
76 struct text_backend *text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020077};
78
Jan Arne Petersen620cd622012-09-09 23:08:32 +020079struct input_method_context {
Jason Ekstrand89d31992013-06-14 10:07:59 -050080 struct wl_resource *resource;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020081
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020082 struct text_input *model;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +010083 struct input_method *input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020084
85 struct wl_list link;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +010086
87 struct wl_resource *keyboard;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020088};
89
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010090struct text_backend {
91 struct weston_compositor *compositor;
92
93 struct {
94 char *path;
95 struct wl_resource *binding;
96 struct weston_process process;
97 struct wl_client *client;
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -030098
99 unsigned deathcount;
100 uint32_t deathstamp;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100101 } input_method;
102
103 struct wl_listener seat_created_listener;
104 struct wl_listener destroy_listener;
105};
106
Derek Foremancb5fcea2014-12-05 15:38:37 -0600107static void
108input_method_context_create(struct text_input *model,
109 struct input_method *input_method);
110static void
111input_method_context_end_keyboard_grab(struct input_method_context *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200112
Derek Foremancb5fcea2014-12-05 15:38:37 -0600113static void
114input_method_init_seat(struct weston_seat *seat);
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200115
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200116static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200117deactivate_text_input(struct text_input *text_input,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200118 struct input_method *input_method)
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200119{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200120 struct weston_compositor *ec = text_input->ec;
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200121
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200122 if (input_method->model == text_input) {
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100123 if (input_method->context && input_method->input_method_binding) {
124 input_method_context_end_keyboard_grab(input_method->context);
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200125 wl_input_method_send_deactivate(input_method->input_method_binding,
Jason Ekstrand89d31992013-06-14 10:07:59 -0500126 input_method->context->resource);
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800127 input_method->context->model = NULL;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100128 }
129
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200130 wl_list_remove(&input_method->link);
131 input_method->model = NULL;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200132 input_method->context = NULL;
Kristian Høgsbergf97f3792012-07-22 11:51:42 -0400133 wl_signal_emit(&ec->hide_input_panel_signal, ec);
Jason Ekstrand89d31992013-06-14 10:07:59 -0500134 wl_text_input_send_leave(text_input->resource);
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200135 }
136}
137
138static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200139destroy_text_input(struct wl_resource *resource)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200140{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500141 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200142 struct input_method *input_method, *next;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200143
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200144 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link)
145 deactivate_text_input(text_input, input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200146
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200147 free(text_input);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200148}
149
150static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200151text_input_set_surrounding_text(struct wl_client *client,
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200152 struct wl_resource *resource,
Jan Arne Petersencb08f4d2012-09-09 23:08:40 +0200153 const char *text,
154 uint32_t cursor,
155 uint32_t anchor)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200156{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500157 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200158 struct input_method *input_method, *next;
159
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200160 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200161 if (!input_method->context)
162 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500163 wl_input_method_context_send_surrounding_text(input_method->context->resource,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200164 text,
165 cursor,
166 anchor);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200167 }
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200168}
169
170static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200171text_input_activate(struct wl_client *client,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200172 struct wl_resource *resource,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200173 struct wl_resource *seat,
174 struct wl_resource *surface)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200175{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500176 struct text_input *text_input = wl_resource_get_user_data(resource);
Jason Ekstrand44a38632013-06-14 10:08:00 -0500177 struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200178 struct input_method *input_method = weston_seat->input_method;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200179 struct text_input *old = weston_seat->input_method->model;
180 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200181
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200182 if (old == text_input)
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200183 return;
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200184
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200185 if (old) {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200186 deactivate_text_input(old,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200187 weston_seat->input_method);
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200188 }
189
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200190 input_method->model = text_input;
191 wl_list_insert(&text_input->input_methods, &input_method->link);
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200192 input_method_init_seat(weston_seat);
193
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -0500194 text_input->surface = wl_resource_get_user_data(surface);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200195
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200196 input_method_context_create(text_input, input_method);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200197
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200198 if (text_input->input_panel_visible) {
199 wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
200 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
201 }
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200202
Jason Ekstrand89d31992013-06-14 10:07:59 -0500203 wl_text_input_send_enter(text_input->resource, text_input->surface->resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200204}
205
206static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200207text_input_deactivate(struct wl_client *client,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200208 struct wl_resource *resource,
209 struct wl_resource *seat)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200210{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500211 struct text_input *text_input = wl_resource_get_user_data(resource);
Jason Ekstrand44a38632013-06-14 10:08:00 -0500212 struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200213
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200214 deactivate_text_input(text_input,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200215 weston_seat->input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200216}
217
218static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200219text_input_reset(struct wl_client *client,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200220 struct wl_resource *resource)
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200221{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500222 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200223 struct input_method *input_method, *next;
224
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200225 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200226 if (!input_method->context)
227 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500228 wl_input_method_context_send_reset(input_method->context->resource);
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200229 }
230}
231
232static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200233text_input_set_cursor_rectangle(struct wl_client *client,
Jan Arne Petersen7ef8eff2013-04-18 16:47:23 +0200234 struct wl_resource *resource,
235 int32_t x,
236 int32_t y,
237 int32_t width,
238 int32_t height)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200239{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500240 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200241 struct weston_compositor *ec = text_input->ec;
242
243 text_input->cursor_rectangle.x1 = x;
244 text_input->cursor_rectangle.y1 = y;
245 text_input->cursor_rectangle.x2 = x + width;
246 text_input->cursor_rectangle.y2 = y + height;
247
248 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200249}
250
251static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200252text_input_set_content_type(struct wl_client *client,
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100253 struct wl_resource *resource,
254 uint32_t hint,
255 uint32_t purpose)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200256{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500257 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100258 struct input_method *input_method, *next;
259
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200260 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100261 if (!input_method->context)
262 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500263 wl_input_method_context_send_content_type(input_method->context->resource, hint, purpose);
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100264 }
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200265}
266
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100267static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200268text_input_invoke_action(struct wl_client *client,
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100269 struct wl_resource *resource,
270 uint32_t button,
271 uint32_t index)
272{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500273 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100274 struct input_method *input_method, *next;
275
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200276 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100277 if (!input_method->context)
278 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500279 wl_input_method_context_send_invoke_action(input_method->context->resource, button, index);
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100280 }
281}
282
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100283static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200284text_input_commit_state(struct wl_client *client,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200285 struct wl_resource *resource,
286 uint32_t serial)
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100287{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500288 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100289 struct input_method *input_method, *next;
290
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200291 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100292 if (!input_method->context)
293 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500294 wl_input_method_context_send_commit_state(input_method->context->resource, serial);
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100295 }
296}
297
Jan Arne Petersen61381972013-01-31 15:52:21 +0100298static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200299text_input_show_input_panel(struct wl_client *client,
Jan Arne Petersen61381972013-01-31 15:52:21 +0100300 struct wl_resource *resource)
301{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500302 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200303 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100304
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200305 text_input->input_panel_visible = 1;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100306
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200307 if (!wl_list_empty(&text_input->input_methods)) {
308 wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
309 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
310 }
Jan Arne Petersen61381972013-01-31 15:52:21 +0100311}
312
313static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200314text_input_hide_input_panel(struct wl_client *client,
Jan Arne Petersen61381972013-01-31 15:52:21 +0100315 struct wl_resource *resource)
316{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500317 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200318 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100319
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200320 text_input->input_panel_visible = 0;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100321
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200322 if (!wl_list_empty(&text_input->input_methods))
Jan Arne Petersen61381972013-01-31 15:52:21 +0100323 wl_signal_emit(&ec->hide_input_panel_signal, ec);
324}
325
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200326static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200327text_input_set_preferred_language(struct wl_client *client,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200328 struct wl_resource *resource,
329 const char *language)
330{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500331 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200332 struct input_method *input_method, *next;
333
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200334 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200335 if (!input_method->context)
336 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500337 wl_input_method_context_send_preferred_language(input_method->context->resource,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200338 language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200339 }
340}
341
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200342static const struct wl_text_input_interface text_input_implementation = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200343 text_input_activate,
344 text_input_deactivate,
345 text_input_show_input_panel,
346 text_input_hide_input_panel,
347 text_input_reset,
348 text_input_set_surrounding_text,
349 text_input_set_content_type,
350 text_input_set_cursor_rectangle,
351 text_input_set_preferred_language,
352 text_input_commit_state,
353 text_input_invoke_action
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200354};
355
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200356static void text_input_manager_create_text_input(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200357 struct wl_resource *resource,
Jan Arne Petersen4c265182012-09-09 23:08:30 +0200358 uint32_t id)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200359{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500360 struct text_input_manager *text_input_manager = wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200361 struct text_input *text_input;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200362
Bryce Harringtonde16d892014-11-20 22:21:57 -0800363 text_input = zalloc(sizeof *text_input);
364 if (text_input == NULL)
365 return;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200366
Jason Ekstranda85118c2013-06-27 20:17:02 -0500367 text_input->resource =
368 wl_resource_create(client, &wl_text_input_interface, 1, id);
369 wl_resource_set_implementation(text_input->resource,
370 &text_input_implementation,
371 text_input, destroy_text_input);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200372
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200373 text_input->ec = text_input_manager->ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200374
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200375 wl_list_init(&text_input->input_methods);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200376};
377
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200378static const struct wl_text_input_manager_interface text_input_manager_implementation = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200379 text_input_manager_create_text_input
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200380};
381
382static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200383bind_text_input_manager(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200384 void *data,
385 uint32_t version,
386 uint32_t id)
387{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200388 struct text_input_manager *text_input_manager = data;
Jason Ekstranda85118c2013-06-27 20:17:02 -0500389 struct wl_resource *resource;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200390
Jason Ekstranda85118c2013-06-27 20:17:02 -0500391 /* No checking for duplicate binding necessary. */
392 resource =
393 wl_resource_create(client,
394 &wl_text_input_manager_interface, 1, id);
395 if (resource)
396 wl_resource_set_implementation(resource,
397 &text_input_manager_implementation,
398 text_input_manager, NULL);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200399}
400
401static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200402text_input_manager_notifier_destroy(struct wl_listener *listener, void *data)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200403{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200404 struct text_input_manager *text_input_manager =
405 container_of(listener, struct text_input_manager, destroy_listener);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200406
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400407 wl_global_destroy(text_input_manager->text_input_manager_global);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200408
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200409 free(text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200410}
411
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100412static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200413text_input_manager_create(struct weston_compositor *ec)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200414{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200415 struct text_input_manager *text_input_manager;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200416
Bryce Harringtonde16d892014-11-20 22:21:57 -0800417 text_input_manager = zalloc(sizeof *text_input_manager);
418 if (text_input_manager == NULL)
419 return;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200420
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200421 text_input_manager->ec = ec;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200422
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200423 text_input_manager->text_input_manager_global =
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400424 wl_global_create(ec->wl_display,
425 &wl_text_input_manager_interface, 1,
426 text_input_manager, bind_text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200427
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200428 text_input_manager->destroy_listener.notify = text_input_manager_notifier_destroy;
429 wl_signal_add(&ec->destroy_signal, &text_input_manager->destroy_listener);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200430}
431
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200432static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200433input_method_context_destroy(struct wl_client *client,
434 struct wl_resource *resource)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200435{
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200436 wl_resource_destroy(resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200437}
438
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200439static void
440input_method_context_commit_string(struct wl_client *client,
441 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100442 uint32_t serial,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100443 const char *text)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200444{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500445 struct input_method_context *context =
446 wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200447
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800448 if (context->model)
449 wl_text_input_send_commit_string(context->model->resource,
450 serial, text);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200451}
452
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200453static void
454input_method_context_preedit_string(struct wl_client *client,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100455 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100456 uint32_t serial,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100457 const char *text,
458 const char *commit)
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200459{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500460 struct input_method_context *context =
461 wl_resource_get_user_data(resource);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200462
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800463 if (context->model)
464 wl_text_input_send_preedit_string(context->model->resource,
465 serial, text, commit);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100466}
467
468static void
469input_method_context_preedit_styling(struct wl_client *client,
470 struct wl_resource *resource,
471 uint32_t index,
472 uint32_t length,
473 uint32_t style)
474{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500475 struct input_method_context *context =
476 wl_resource_get_user_data(resource);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100477
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800478 if (context->model)
479 wl_text_input_send_preedit_styling(context->model->resource,
480 index, length, style);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100481}
482
483static void
484input_method_context_preedit_cursor(struct wl_client *client,
485 struct wl_resource *resource,
486 int32_t cursor)
487{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500488 struct input_method_context *context =
489 wl_resource_get_user_data(resource);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100490
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800491 if (context->model)
492 wl_text_input_send_preedit_cursor(context->model->resource,
493 cursor);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200494}
495
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200496static void
497input_method_context_delete_surrounding_text(struct wl_client *client,
498 struct wl_resource *resource,
499 int32_t index,
500 uint32_t length)
501{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500502 struct input_method_context *context =
503 wl_resource_get_user_data(resource);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200504
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800505 if (context->model)
506 wl_text_input_send_delete_surrounding_text(context->model->resource,
507 index, length);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200508}
509
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200510static void
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100511input_method_context_cursor_position(struct wl_client *client,
512 struct wl_resource *resource,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100513 int32_t index,
514 int32_t anchor)
515{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500516 struct input_method_context *context =
517 wl_resource_get_user_data(resource);
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100518
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800519 if (context->model)
520 wl_text_input_send_cursor_position(context->model->resource,
521 index, anchor);
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100522}
523
524static void
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100525input_method_context_modifiers_map(struct wl_client *client,
526 struct wl_resource *resource,
527 struct wl_array *map)
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200528{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500529 struct input_method_context *context =
530 wl_resource_get_user_data(resource);
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200531
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800532 if (context->model)
533 wl_text_input_send_modifiers_map(context->model->resource, map);
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100534}
535
536static void
537input_method_context_keysym(struct wl_client *client,
538 struct wl_resource *resource,
539 uint32_t serial,
540 uint32_t time,
541 uint32_t sym,
542 uint32_t state,
543 uint32_t modifiers)
544{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500545 struct input_method_context *context =
546 wl_resource_get_user_data(resource);
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100547
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800548 if (context->model)
549 wl_text_input_send_keysym(context->model->resource,
550 serial, time, sym, state, modifiers);
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200551}
552
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100553static void
554unbind_keyboard(struct wl_resource *resource)
555{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500556 struct input_method_context *context =
557 wl_resource_get_user_data(resource);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100558
559 input_method_context_end_keyboard_grab(context);
560 context->keyboard = NULL;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100561}
562
563static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400564input_method_context_grab_key(struct weston_keyboard_grab *grab,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100565 uint32_t time, uint32_t key, uint32_t state_w)
566{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400567 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100568 struct wl_display *display;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100569 uint32_t serial;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100570
571 if (!keyboard->input_method_resource)
572 return;
573
Jason Ekstrand89d31992013-06-14 10:07:59 -0500574 display = wl_client_get_display(wl_resource_get_client(keyboard->input_method_resource));
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100575 serial = wl_display_next_serial(display);
576 wl_keyboard_send_key(keyboard->input_method_resource,
577 serial, time, key, state_w);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100578}
579
580static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400581input_method_context_grab_modifier(struct weston_keyboard_grab *grab, uint32_t serial,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100582 uint32_t mods_depressed, uint32_t mods_latched,
583 uint32_t mods_locked, uint32_t group)
584{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400585 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100586
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100587 if (!keyboard->input_method_resource)
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100588 return;
589
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100590 wl_keyboard_send_modifiers(keyboard->input_method_resource,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100591 serial, mods_depressed, mods_latched,
592 mods_locked, group);
593}
594
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200595static void
596input_method_context_grab_cancel(struct weston_keyboard_grab *grab)
597{
598 weston_keyboard_end_grab(grab->keyboard);
599}
600
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400601static const struct weston_keyboard_grab_interface input_method_context_grab = {
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100602 input_method_context_grab_key,
603 input_method_context_grab_modifier,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200604 input_method_context_grab_cancel,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100605};
606
607static void
608input_method_context_grab_keyboard(struct wl_client *client,
609 struct wl_resource *resource,
610 uint32_t id)
611{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500612 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100613 struct wl_resource *cr;
614 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400615 struct weston_keyboard *keyboard = seat->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100616
Jason Ekstranda85118c2013-06-27 20:17:02 -0500617 cr = wl_resource_create(client, &wl_keyboard_interface, 1, id);
618 wl_resource_set_implementation(cr, NULL, context, unbind_keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100619
620 context->keyboard = cr;
621
622 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
Jonas Ådahl7395ea02013-12-03 09:14:26 +0100623 keyboard->xkb_info->keymap_fd,
624 keyboard->xkb_info->keymap_size);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100625
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400626 if (keyboard->grab != &keyboard->default_grab) {
627 weston_keyboard_end_grab(keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100628 }
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400629 weston_keyboard_start_grab(keyboard, &keyboard->input_method_grab);
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100630 keyboard->input_method_resource = cr;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100631}
632
Jan Arne Petersen337df952012-11-18 19:06:46 +0100633static void
634input_method_context_key(struct wl_client *client,
635 struct wl_resource *resource,
636 uint32_t serial,
637 uint32_t time,
638 uint32_t key,
639 uint32_t state_w)
640{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500641 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen337df952012-11-18 19:06:46 +0100642 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400643 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400644 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100645
646 default_grab->interface->key(default_grab, time, key, state_w);
647}
648
649static void
650input_method_context_modifiers(struct wl_client *client,
651 struct wl_resource *resource,
652 uint32_t serial,
653 uint32_t mods_depressed,
654 uint32_t mods_latched,
655 uint32_t mods_locked,
656 uint32_t group)
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
660 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400661 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400662 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100663
664 default_grab->interface->modifiers(default_grab,
665 serial, mods_depressed,
666 mods_latched, mods_locked,
667 group);
668}
669
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200670static void
671input_method_context_language(struct wl_client *client,
672 struct wl_resource *resource,
673 uint32_t serial,
674 const char *language)
675{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500676 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200677
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800678 if (context->model)
679 wl_text_input_send_language(context->model->resource,
680 serial, language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200681}
682
683static void
684input_method_context_text_direction(struct wl_client *client,
685 struct wl_resource *resource,
686 uint32_t serial,
687 uint32_t direction)
688{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500689 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200690
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800691 if (context->model)
692 wl_text_input_send_text_direction(context->model->resource,
693 serial, direction);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200694}
695
696
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200697static const struct wl_input_method_context_interface input_method_context_implementation = {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200698 input_method_context_destroy,
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200699 input_method_context_commit_string,
700 input_method_context_preedit_string,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100701 input_method_context_preedit_styling,
702 input_method_context_preedit_cursor,
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200703 input_method_context_delete_surrounding_text,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100704 input_method_context_cursor_position,
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100705 input_method_context_modifiers_map,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100706 input_method_context_keysym,
Jan Arne Petersen337df952012-11-18 19:06:46 +0100707 input_method_context_grab_keyboard,
708 input_method_context_key,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200709 input_method_context_modifiers,
710 input_method_context_language,
711 input_method_context_text_direction
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200712};
713
714static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200715destroy_input_method_context(struct wl_resource *resource)
716{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500717 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200718
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100719 if (context->keyboard) {
720 wl_resource_destroy(context->keyboard);
721 }
722
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200723 free(context);
724}
725
726static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200727input_method_context_create(struct text_input *model,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200728 struct input_method *input_method)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200729{
730 struct input_method_context *context;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500731 struct wl_resource *binding;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200732
733 if (!input_method->input_method_binding)
734 return;
735
Bryce Harringtonde16d892014-11-20 22:21:57 -0800736 context = zalloc(sizeof *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200737 if (context == NULL)
738 return;
739
Jason Ekstrand89d31992013-06-14 10:07:59 -0500740 binding = input_method->input_method_binding;
Jason Ekstranda85118c2013-06-27 20:17:02 -0500741 context->resource =
742 wl_resource_create(wl_resource_get_client(binding),
743 &wl_input_method_context_interface, 1, 0);
744 wl_resource_set_implementation(context->resource,
745 &input_method_context_implementation,
746 context, destroy_input_method_context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200747
748 context->model = model;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100749 context->input_method = input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200750 input_method->context = context;
751
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200752
Jason Ekstrand89d31992013-06-14 10:07:59 -0500753 wl_input_method_send_activate(binding, context->resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200754}
755
756static void
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100757input_method_context_end_keyboard_grab(struct input_method_context *context)
758{
Kristian Høgsberge3148752013-05-06 23:19:49 -0400759 struct weston_keyboard_grab *grab =
760 &context->input_method->seat->keyboard->input_method_grab;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400761 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100762
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100763 if (!grab->keyboard)
764 return;
765
766 if (grab->keyboard->grab == grab)
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400767 weston_keyboard_end_grab(grab->keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100768
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100769 keyboard->input_method_resource = NULL;
770}
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100771
772static void
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200773unbind_input_method(struct wl_resource *resource)
774{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500775 struct input_method *input_method = wl_resource_get_user_data(resource);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100776 struct text_backend *text_backend = input_method->text_backend;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200777
778 input_method->input_method_binding = NULL;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200779 input_method->context = NULL;
780
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100781 text_backend->input_method.binding = NULL;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200782}
783
784static void
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200785bind_input_method(struct wl_client *client,
786 void *data,
787 uint32_t version,
788 uint32_t id)
789{
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200790 struct input_method *input_method = data;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100791 struct text_backend *text_backend = input_method->text_backend;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200792 struct wl_resource *resource;
793
Jason Ekstranda85118c2013-06-27 20:17:02 -0500794 resource =
795 wl_resource_create(client, &wl_input_method_interface, 1, id);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200796
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200797 if (input_method->input_method_binding != NULL) {
798 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
799 "interface object already bound");
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200800 return;
801 }
802
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200803 if (text_backend->input_method.client != client) {
804 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
Eduardo Lima (Etrunko)a2ce68f2013-05-10 17:50:36 -0300805 "permission to bind input_method denied");
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200806 return;
807 }
808
Jason Ekstranda85118c2013-06-27 20:17:02 -0500809 wl_resource_set_implementation(resource, NULL, input_method,
810 unbind_input_method);
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200811 input_method->input_method_binding = resource;
812
813 text_backend->input_method.binding = resource;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200814}
815
816static void
817input_method_notifier_destroy(struct wl_listener *listener, void *data)
818{
Kristian Høgsbergf97f3792012-07-22 11:51:42 -0400819 struct input_method *input_method =
820 container_of(listener, struct input_method, destroy_listener);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200821
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200822 if (input_method->model)
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200823 deactivate_text_input(input_method->model, input_method);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200824
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400825 wl_global_destroy(input_method->input_method_global);
Rob Bradfordead3ef82013-07-24 16:57:32 +0100826 wl_list_remove(&input_method->destroy_listener.link);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200827
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200828 free(input_method);
829}
830
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200831static void
832handle_keyboard_focus(struct wl_listener *listener, void *data)
833{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400834 struct weston_keyboard *keyboard = data;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200835 struct input_method *input_method =
836 container_of(listener, struct input_method, keyboard_focus_listener);
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400837 struct weston_surface *surface = keyboard->focus;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200838
839 if (!input_method->model)
840 return;
841
842 if (!surface || input_method->model->surface != surface)
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200843 deactivate_text_input(input_method->model,
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200844 input_method);
845}
846
847static void
848input_method_init_seat(struct weston_seat *seat)
849{
850 if (seat->input_method->focus_listener_initialized)
851 return;
852
Kristian Høgsberg2bf87622013-05-07 23:17:41 -0400853 if (seat->keyboard) {
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200854 seat->input_method->keyboard_focus_listener.notify = handle_keyboard_focus;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400855 wl_signal_add(&seat->keyboard->focus_signal, &seat->input_method->keyboard_focus_listener);
856 seat->keyboard->input_method_grab.interface = &input_method_context_grab;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200857 }
858
859 seat->input_method->focus_listener_initialized = 1;
860}
861
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300862static void launch_input_method(struct text_backend *text_backend);
863
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100864static void
865handle_input_method_sigchld(struct weston_process *process, int status)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200866{
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300867 uint32_t time;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100868 struct text_backend *text_backend =
869 container_of(process, struct text_backend, input_method.process);
870
871 text_backend->input_method.process.pid = 0;
872 text_backend->input_method.client = NULL;
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300873
874 /* if input_method dies more than 5 times in 10 seconds, give up */
875 time = weston_compositor_get_time();
876 if (time - text_backend->input_method.deathstamp > 10000) {
877 text_backend->input_method.deathstamp = time;
878 text_backend->input_method.deathcount = 0;
879 }
880
881 text_backend->input_method.deathcount++;
882 if (text_backend->input_method.deathcount > 5) {
883 weston_log("input_method died, giving up.\n");
884 return;
885 }
886
887 weston_log("input_method died, respawning...\n");
888 launch_input_method(text_backend);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100889}
890
891static void
892launch_input_method(struct text_backend *text_backend)
893{
894 if (text_backend->input_method.binding)
895 return;
896
897 if (!text_backend->input_method.path)
898 return;
899
900 if (text_backend->input_method.process.pid != 0)
901 return;
902
903 text_backend->input_method.client = weston_client_launch(text_backend->compositor,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200904 &text_backend->input_method.process,
905 text_backend->input_method.path,
906 handle_input_method_sigchld);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100907
908 if (!text_backend->input_method.client)
909 weston_log("not able to start %s\n", text_backend->input_method.path);
910}
911
912static void
913handle_seat_created(struct wl_listener *listener,
914 void *data)
915{
916 struct weston_seat *seat = data;
917 struct text_backend *text_backend =
918 container_of(listener, struct text_backend,
919 seat_created_listener);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200920 struct input_method *input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100921 struct weston_compositor *ec = seat->compositor;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200922
Bryce Harringtonde16d892014-11-20 22:21:57 -0800923 input_method = zalloc(sizeof *input_method);
924 if (input_method == NULL)
925 return;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200926
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200927 input_method->seat = seat;
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200928 input_method->model = NULL;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200929 input_method->focus_listener_initialized = 0;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200930 input_method->context = NULL;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100931 input_method->text_backend = text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200932
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200933 input_method->input_method_global =
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400934 wl_global_create(ec->wl_display, &wl_input_method_interface, 1,
935 input_method, bind_input_method);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200936
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200937 input_method->destroy_listener.notify = input_method_notifier_destroy;
Kristian Høgsberg49124542013-05-06 22:27:40 -0400938 wl_signal_add(&seat->destroy_signal, &input_method->destroy_listener);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200939
940 seat->input_method = input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100941
942 launch_input_method(text_backend);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200943}
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200944
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100945static void
946text_backend_configuration(struct text_backend *text_backend)
947{
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -0400948 struct weston_config_section *section;
Derek Foremanc7210432014-08-21 11:32:38 -0500949 char *client;
Pekka Paalanen974c0942014-09-05 14:45:09 +0300950 int ret;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100951
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -0400952 section = weston_config_get_section(text_backend->compositor->config,
953 "input-method", NULL, NULL);
Pekka Paalanen974c0942014-09-05 14:45:09 +0300954 ret = asprintf(&client, "%s/weston-keyboard",
955 weston_config_get_libexec_dir());
956 if (ret < 0)
957 client = NULL;
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -0400958 weston_config_section_get_string(section, "path",
959 &text_backend->input_method.path,
Derek Foremanc7210432014-08-21 11:32:38 -0500960 client);
961 free(client);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100962}
963
964static void
965text_backend_notifier_destroy(struct wl_listener *listener, void *data)
966{
967 struct text_backend *text_backend =
968 container_of(listener, struct text_backend, destroy_listener);
969
970 if (text_backend->input_method.client)
971 wl_client_destroy(text_backend->input_method.client);
972
973 free(text_backend->input_method.path);
974
975 free(text_backend);
976}
977
978
979WL_EXPORT int
980text_backend_init(struct weston_compositor *ec)
981{
982 struct text_backend *text_backend;
983
Bryce Harringtonde16d892014-11-20 22:21:57 -0800984 text_backend = zalloc(sizeof(*text_backend));
985 if (text_backend == NULL)
986 return -1;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100987
988 text_backend->compositor = ec;
989
990 text_backend->seat_created_listener.notify = handle_seat_created;
991 wl_signal_add(&ec->seat_created_signal,
992 &text_backend->seat_created_listener);
993
994 text_backend->destroy_listener.notify = text_backend_notifier_destroy;
995 wl_signal_add(&ec->destroy_signal, &text_backend->destroy_listener);
996
997 text_backend_configuration(text_backend);
998
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200999 text_input_manager_create(ec);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001000
1001 return 0;
1002}