blob: e274f0ba5ba9999f7f677d85ec0a75157ad8b323 [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
Jan Arne Petersen466b9c12012-11-18 19:06:45 +010085 struct wl_resource *keyboard;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020086};
87
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010088struct text_backend {
89 struct weston_compositor *compositor;
90
91 struct {
92 char *path;
93 struct wl_resource *binding;
94 struct weston_process process;
95 struct wl_client *client;
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -030096
97 unsigned deathcount;
98 uint32_t deathstamp;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010099 } input_method;
100
101 struct wl_listener seat_created_listener;
102 struct wl_listener destroy_listener;
103};
104
Derek Foremancb5fcea2014-12-05 15:38:37 -0600105static void
106input_method_context_create(struct text_input *model,
107 struct input_method *input_method);
108static void
109input_method_context_end_keyboard_grab(struct input_method_context *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200110
Derek Foremancb5fcea2014-12-05 15:38:37 -0600111static void
112input_method_init_seat(struct weston_seat *seat);
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200113
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200114static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200115deactivate_text_input(struct text_input *text_input,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200116 struct input_method *input_method)
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200117{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200118 struct weston_compositor *ec = text_input->ec;
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200119
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200120 if (input_method->model == text_input) {
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100121 if (input_method->context && input_method->input_method_binding) {
122 input_method_context_end_keyboard_grab(input_method->context);
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200123 wl_input_method_send_deactivate(input_method->input_method_binding,
Jason Ekstrand89d31992013-06-14 10:07:59 -0500124 input_method->context->resource);
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800125 input_method->context->model = NULL;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100126 }
127
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200128 wl_list_remove(&input_method->link);
129 input_method->model = NULL;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200130 input_method->context = NULL;
Kristian Høgsbergf97f3792012-07-22 11:51:42 -0400131 wl_signal_emit(&ec->hide_input_panel_signal, ec);
Jason Ekstrand89d31992013-06-14 10:07:59 -0500132 wl_text_input_send_leave(text_input->resource);
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200133 }
134}
135
136static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200137destroy_text_input(struct wl_resource *resource)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200138{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500139 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200140 struct input_method *input_method, *next;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200141
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200142 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link)
143 deactivate_text_input(text_input, input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200144
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200145 free(text_input);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200146}
147
148static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200149text_input_set_surrounding_text(struct wl_client *client,
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200150 struct wl_resource *resource,
Jan Arne Petersencb08f4d2012-09-09 23:08:40 +0200151 const char *text,
152 uint32_t cursor,
153 uint32_t anchor)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200154{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500155 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200156 struct input_method *input_method, *next;
157
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200158 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200159 if (!input_method->context)
160 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500161 wl_input_method_context_send_surrounding_text(input_method->context->resource,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200162 text,
163 cursor,
164 anchor);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200165 }
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200166}
167
168static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200169text_input_activate(struct wl_client *client,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200170 struct wl_resource *resource,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200171 struct wl_resource *seat,
172 struct wl_resource *surface)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200173{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500174 struct text_input *text_input = wl_resource_get_user_data(resource);
Jason Ekstrand44a38632013-06-14 10:08:00 -0500175 struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200176 struct input_method *input_method = weston_seat->input_method;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200177 struct text_input *old = weston_seat->input_method->model;
178 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200179
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200180 if (old == text_input)
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200181 return;
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200182
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200183 if (old) {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200184 deactivate_text_input(old,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200185 weston_seat->input_method);
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200186 }
187
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200188 input_method->model = text_input;
189 wl_list_insert(&text_input->input_methods, &input_method->link);
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200190 input_method_init_seat(weston_seat);
191
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -0500192 text_input->surface = wl_resource_get_user_data(surface);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200193
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200194 input_method_context_create(text_input, input_method);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200195
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200196 if (text_input->input_panel_visible) {
197 wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
198 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
199 }
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200200
Jason Ekstrand89d31992013-06-14 10:07:59 -0500201 wl_text_input_send_enter(text_input->resource, text_input->surface->resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200202}
203
204static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200205text_input_deactivate(struct wl_client *client,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200206 struct wl_resource *resource,
207 struct wl_resource *seat)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200208{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500209 struct text_input *text_input = wl_resource_get_user_data(resource);
Jason Ekstrand44a38632013-06-14 10:08:00 -0500210 struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200211
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200212 deactivate_text_input(text_input,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200213 weston_seat->input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200214}
215
216static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200217text_input_reset(struct wl_client *client,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200218 struct wl_resource *resource)
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200219{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500220 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200221 struct input_method *input_method, *next;
222
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200223 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200224 if (!input_method->context)
225 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500226 wl_input_method_context_send_reset(input_method->context->resource);
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200227 }
228}
229
230static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200231text_input_set_cursor_rectangle(struct wl_client *client,
Jan Arne Petersen7ef8eff2013-04-18 16:47:23 +0200232 struct wl_resource *resource,
233 int32_t x,
234 int32_t y,
235 int32_t width,
236 int32_t height)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200237{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500238 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200239 struct weston_compositor *ec = text_input->ec;
240
241 text_input->cursor_rectangle.x1 = x;
242 text_input->cursor_rectangle.y1 = y;
243 text_input->cursor_rectangle.x2 = x + width;
244 text_input->cursor_rectangle.y2 = y + height;
245
246 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200247}
248
249static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200250text_input_set_content_type(struct wl_client *client,
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100251 struct wl_resource *resource,
252 uint32_t hint,
253 uint32_t purpose)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200254{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500255 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100256 struct input_method *input_method, *next;
257
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200258 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100259 if (!input_method->context)
260 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500261 wl_input_method_context_send_content_type(input_method->context->resource, hint, purpose);
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100262 }
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200263}
264
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100265static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200266text_input_invoke_action(struct wl_client *client,
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100267 struct wl_resource *resource,
268 uint32_t button,
269 uint32_t index)
270{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500271 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100272 struct input_method *input_method, *next;
273
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200274 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100275 if (!input_method->context)
276 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500277 wl_input_method_context_send_invoke_action(input_method->context->resource, button, index);
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100278 }
279}
280
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100281static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200282text_input_commit_state(struct wl_client *client,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200283 struct wl_resource *resource,
284 uint32_t serial)
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100285{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500286 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +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 Petersen0eabcaa2013-01-31 15:52:20 +0100290 if (!input_method->context)
291 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500292 wl_input_method_context_send_commit_state(input_method->context->resource, serial);
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100293 }
294}
295
Jan Arne Petersen61381972013-01-31 15:52:21 +0100296static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200297text_input_show_input_panel(struct wl_client *client,
Jan Arne Petersen61381972013-01-31 15:52:21 +0100298 struct wl_resource *resource)
299{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500300 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200301 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100302
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200303 text_input->input_panel_visible = 1;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100304
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200305 if (!wl_list_empty(&text_input->input_methods)) {
306 wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
307 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
308 }
Jan Arne Petersen61381972013-01-31 15:52:21 +0100309}
310
311static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200312text_input_hide_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
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200318 text_input->input_panel_visible = 0;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100319
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200320 if (!wl_list_empty(&text_input->input_methods))
Jan Arne Petersen61381972013-01-31 15:52:21 +0100321 wl_signal_emit(&ec->hide_input_panel_signal, ec);
322}
323
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200324static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200325text_input_set_preferred_language(struct wl_client *client,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200326 struct wl_resource *resource,
327 const char *language)
328{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500329 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200330 struct input_method *input_method, *next;
331
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200332 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200333 if (!input_method->context)
334 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500335 wl_input_method_context_send_preferred_language(input_method->context->resource,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200336 language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200337 }
338}
339
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200340static const struct wl_text_input_interface text_input_implementation = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200341 text_input_activate,
342 text_input_deactivate,
343 text_input_show_input_panel,
344 text_input_hide_input_panel,
345 text_input_reset,
346 text_input_set_surrounding_text,
347 text_input_set_content_type,
348 text_input_set_cursor_rectangle,
349 text_input_set_preferred_language,
350 text_input_commit_state,
351 text_input_invoke_action
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200352};
353
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200354static void text_input_manager_create_text_input(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200355 struct wl_resource *resource,
Jan Arne Petersen4c265182012-09-09 23:08:30 +0200356 uint32_t id)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200357{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500358 struct text_input_manager *text_input_manager = wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200359 struct text_input *text_input;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200360
Bryce Harringtonde16d892014-11-20 22:21:57 -0800361 text_input = zalloc(sizeof *text_input);
362 if (text_input == NULL)
363 return;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200364
Jason Ekstranda85118c2013-06-27 20:17:02 -0500365 text_input->resource =
366 wl_resource_create(client, &wl_text_input_interface, 1, id);
367 wl_resource_set_implementation(text_input->resource,
368 &text_input_implementation,
369 text_input, destroy_text_input);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200370
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200371 text_input->ec = text_input_manager->ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200372
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200373 wl_list_init(&text_input->input_methods);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200374};
375
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200376static const struct wl_text_input_manager_interface text_input_manager_implementation = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200377 text_input_manager_create_text_input
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200378};
379
380static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200381bind_text_input_manager(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200382 void *data,
383 uint32_t version,
384 uint32_t id)
385{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200386 struct text_input_manager *text_input_manager = data;
Jason Ekstranda85118c2013-06-27 20:17:02 -0500387 struct wl_resource *resource;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200388
Jason Ekstranda85118c2013-06-27 20:17:02 -0500389 /* No checking for duplicate binding necessary. */
390 resource =
391 wl_resource_create(client,
392 &wl_text_input_manager_interface, 1, id);
393 if (resource)
394 wl_resource_set_implementation(resource,
395 &text_input_manager_implementation,
396 text_input_manager, NULL);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200397}
398
399static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200400text_input_manager_notifier_destroy(struct wl_listener *listener, void *data)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200401{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200402 struct text_input_manager *text_input_manager =
403 container_of(listener, struct text_input_manager, destroy_listener);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200404
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400405 wl_global_destroy(text_input_manager->text_input_manager_global);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200406
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200407 free(text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200408}
409
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100410static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200411text_input_manager_create(struct weston_compositor *ec)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200412{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200413 struct text_input_manager *text_input_manager;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200414
Bryce Harringtonde16d892014-11-20 22:21:57 -0800415 text_input_manager = zalloc(sizeof *text_input_manager);
416 if (text_input_manager == NULL)
417 return;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200418
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200419 text_input_manager->ec = ec;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200420
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200421 text_input_manager->text_input_manager_global =
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400422 wl_global_create(ec->wl_display,
423 &wl_text_input_manager_interface, 1,
424 text_input_manager, bind_text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200425
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200426 text_input_manager->destroy_listener.notify = text_input_manager_notifier_destroy;
427 wl_signal_add(&ec->destroy_signal, &text_input_manager->destroy_listener);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200428}
429
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200430static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200431input_method_context_destroy(struct wl_client *client,
432 struct wl_resource *resource)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200433{
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200434 wl_resource_destroy(resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200435}
436
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200437static void
438input_method_context_commit_string(struct wl_client *client,
439 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100440 uint32_t serial,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100441 const char *text)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200442{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500443 struct input_method_context *context =
444 wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200445
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800446 if (context->model)
447 wl_text_input_send_commit_string(context->model->resource,
448 serial, text);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200449}
450
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200451static void
452input_method_context_preedit_string(struct wl_client *client,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100453 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100454 uint32_t serial,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100455 const char *text,
456 const char *commit)
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200457{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500458 struct input_method_context *context =
459 wl_resource_get_user_data(resource);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200460
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800461 if (context->model)
462 wl_text_input_send_preedit_string(context->model->resource,
463 serial, text, commit);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100464}
465
466static void
467input_method_context_preedit_styling(struct wl_client *client,
468 struct wl_resource *resource,
469 uint32_t index,
470 uint32_t length,
471 uint32_t style)
472{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500473 struct input_method_context *context =
474 wl_resource_get_user_data(resource);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100475
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800476 if (context->model)
477 wl_text_input_send_preedit_styling(context->model->resource,
478 index, length, style);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100479}
480
481static void
482input_method_context_preedit_cursor(struct wl_client *client,
483 struct wl_resource *resource,
484 int32_t cursor)
485{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500486 struct input_method_context *context =
487 wl_resource_get_user_data(resource);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100488
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800489 if (context->model)
490 wl_text_input_send_preedit_cursor(context->model->resource,
491 cursor);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200492}
493
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200494static void
495input_method_context_delete_surrounding_text(struct wl_client *client,
496 struct wl_resource *resource,
497 int32_t index,
498 uint32_t length)
499{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500500 struct input_method_context *context =
501 wl_resource_get_user_data(resource);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200502
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800503 if (context->model)
504 wl_text_input_send_delete_surrounding_text(context->model->resource,
505 index, length);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200506}
507
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200508static void
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100509input_method_context_cursor_position(struct wl_client *client,
510 struct wl_resource *resource,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100511 int32_t index,
512 int32_t anchor)
513{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500514 struct input_method_context *context =
515 wl_resource_get_user_data(resource);
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100516
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800517 if (context->model)
518 wl_text_input_send_cursor_position(context->model->resource,
519 index, anchor);
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100520}
521
522static void
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100523input_method_context_modifiers_map(struct wl_client *client,
524 struct wl_resource *resource,
525 struct wl_array *map)
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200526{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500527 struct input_method_context *context =
528 wl_resource_get_user_data(resource);
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200529
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800530 if (context->model)
531 wl_text_input_send_modifiers_map(context->model->resource, map);
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100532}
533
534static void
535input_method_context_keysym(struct wl_client *client,
536 struct wl_resource *resource,
537 uint32_t serial,
538 uint32_t time,
539 uint32_t sym,
540 uint32_t state,
541 uint32_t modifiers)
542{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500543 struct input_method_context *context =
544 wl_resource_get_user_data(resource);
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100545
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800546 if (context->model)
547 wl_text_input_send_keysym(context->model->resource,
548 serial, time, sym, state, modifiers);
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200549}
550
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100551static void
552unbind_keyboard(struct wl_resource *resource)
553{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500554 struct input_method_context *context =
555 wl_resource_get_user_data(resource);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100556
557 input_method_context_end_keyboard_grab(context);
558 context->keyboard = NULL;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100559}
560
561static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400562input_method_context_grab_key(struct weston_keyboard_grab *grab,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100563 uint32_t time, uint32_t key, uint32_t state_w)
564{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400565 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100566 struct wl_display *display;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100567 uint32_t serial;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100568
569 if (!keyboard->input_method_resource)
570 return;
571
Jason Ekstrand89d31992013-06-14 10:07:59 -0500572 display = wl_client_get_display(wl_resource_get_client(keyboard->input_method_resource));
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100573 serial = wl_display_next_serial(display);
574 wl_keyboard_send_key(keyboard->input_method_resource,
575 serial, time, key, state_w);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100576}
577
578static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400579input_method_context_grab_modifier(struct weston_keyboard_grab *grab, uint32_t serial,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100580 uint32_t mods_depressed, uint32_t mods_latched,
581 uint32_t mods_locked, uint32_t group)
582{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400583 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100584
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100585 if (!keyboard->input_method_resource)
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100586 return;
587
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100588 wl_keyboard_send_modifiers(keyboard->input_method_resource,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100589 serial, mods_depressed, mods_latched,
590 mods_locked, group);
591}
592
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200593static void
594input_method_context_grab_cancel(struct weston_keyboard_grab *grab)
595{
596 weston_keyboard_end_grab(grab->keyboard);
597}
598
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400599static const struct weston_keyboard_grab_interface input_method_context_grab = {
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100600 input_method_context_grab_key,
601 input_method_context_grab_modifier,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200602 input_method_context_grab_cancel,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100603};
604
605static void
606input_method_context_grab_keyboard(struct wl_client *client,
607 struct wl_resource *resource,
608 uint32_t id)
609{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500610 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100611 struct wl_resource *cr;
612 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400613 struct weston_keyboard *keyboard = seat->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100614
Jason Ekstranda85118c2013-06-27 20:17:02 -0500615 cr = wl_resource_create(client, &wl_keyboard_interface, 1, id);
616 wl_resource_set_implementation(cr, NULL, context, unbind_keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100617
618 context->keyboard = cr;
619
620 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
Jonas Ådahl7395ea02013-12-03 09:14:26 +0100621 keyboard->xkb_info->keymap_fd,
622 keyboard->xkb_info->keymap_size);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100623
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400624 if (keyboard->grab != &keyboard->default_grab) {
625 weston_keyboard_end_grab(keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100626 }
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400627 weston_keyboard_start_grab(keyboard, &keyboard->input_method_grab);
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100628 keyboard->input_method_resource = cr;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100629}
630
Jan Arne Petersen337df952012-11-18 19:06:46 +0100631static void
632input_method_context_key(struct wl_client *client,
633 struct wl_resource *resource,
634 uint32_t serial,
635 uint32_t time,
636 uint32_t key,
637 uint32_t state_w)
638{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500639 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen337df952012-11-18 19:06:46 +0100640 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400641 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400642 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100643
644 default_grab->interface->key(default_grab, time, key, state_w);
645}
646
647static void
648input_method_context_modifiers(struct wl_client *client,
649 struct wl_resource *resource,
650 uint32_t serial,
651 uint32_t mods_depressed,
652 uint32_t mods_latched,
653 uint32_t mods_locked,
654 uint32_t group)
655{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500656 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen337df952012-11-18 19:06:46 +0100657
658 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400659 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400660 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100661
662 default_grab->interface->modifiers(default_grab,
663 serial, mods_depressed,
664 mods_latched, mods_locked,
665 group);
666}
667
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200668static void
669input_method_context_language(struct wl_client *client,
670 struct wl_resource *resource,
671 uint32_t serial,
672 const char *language)
673{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500674 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200675
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800676 if (context->model)
677 wl_text_input_send_language(context->model->resource,
678 serial, language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200679}
680
681static void
682input_method_context_text_direction(struct wl_client *client,
683 struct wl_resource *resource,
684 uint32_t serial,
685 uint32_t direction)
686{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500687 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200688
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800689 if (context->model)
690 wl_text_input_send_text_direction(context->model->resource,
691 serial, direction);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200692}
693
694
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200695static const struct wl_input_method_context_interface input_method_context_implementation = {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200696 input_method_context_destroy,
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200697 input_method_context_commit_string,
698 input_method_context_preedit_string,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100699 input_method_context_preedit_styling,
700 input_method_context_preedit_cursor,
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200701 input_method_context_delete_surrounding_text,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100702 input_method_context_cursor_position,
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100703 input_method_context_modifiers_map,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100704 input_method_context_keysym,
Jan Arne Petersen337df952012-11-18 19:06:46 +0100705 input_method_context_grab_keyboard,
706 input_method_context_key,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200707 input_method_context_modifiers,
708 input_method_context_language,
709 input_method_context_text_direction
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200710};
711
712static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200713destroy_input_method_context(struct wl_resource *resource)
714{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500715 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200716
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100717 if (context->keyboard) {
718 wl_resource_destroy(context->keyboard);
719 }
720
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200721 free(context);
722}
723
724static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200725input_method_context_create(struct text_input *model,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200726 struct input_method *input_method)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200727{
728 struct input_method_context *context;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500729 struct wl_resource *binding;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200730
731 if (!input_method->input_method_binding)
732 return;
733
Bryce Harringtonde16d892014-11-20 22:21:57 -0800734 context = zalloc(sizeof *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200735 if (context == NULL)
736 return;
737
Jason Ekstrand89d31992013-06-14 10:07:59 -0500738 binding = input_method->input_method_binding;
Jason Ekstranda85118c2013-06-27 20:17:02 -0500739 context->resource =
740 wl_resource_create(wl_resource_get_client(binding),
741 &wl_input_method_context_interface, 1, 0);
742 wl_resource_set_implementation(context->resource,
743 &input_method_context_implementation,
744 context, destroy_input_method_context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200745
746 context->model = model;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100747 context->input_method = input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200748 input_method->context = context;
749
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200750
Jason Ekstrand89d31992013-06-14 10:07:59 -0500751 wl_input_method_send_activate(binding, context->resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200752}
753
754static void
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100755input_method_context_end_keyboard_grab(struct input_method_context *context)
756{
Kristian Høgsberge3148752013-05-06 23:19:49 -0400757 struct weston_keyboard_grab *grab =
758 &context->input_method->seat->keyboard->input_method_grab;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400759 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100760
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100761 if (!grab->keyboard)
762 return;
763
764 if (grab->keyboard->grab == grab)
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400765 weston_keyboard_end_grab(grab->keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100766
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100767 keyboard->input_method_resource = NULL;
768}
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100769
770static void
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200771unbind_input_method(struct wl_resource *resource)
772{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500773 struct input_method *input_method = wl_resource_get_user_data(resource);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100774 struct text_backend *text_backend = input_method->text_backend;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200775
776 input_method->input_method_binding = NULL;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200777 input_method->context = NULL;
778
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100779 text_backend->input_method.binding = NULL;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200780}
781
782static void
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200783bind_input_method(struct wl_client *client,
784 void *data,
785 uint32_t version,
786 uint32_t id)
787{
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200788 struct input_method *input_method = data;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100789 struct text_backend *text_backend = input_method->text_backend;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200790 struct wl_resource *resource;
791
Jason Ekstranda85118c2013-06-27 20:17:02 -0500792 resource =
793 wl_resource_create(client, &wl_input_method_interface, 1, id);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200794
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200795 if (input_method->input_method_binding != NULL) {
796 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
797 "interface object already bound");
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200798 return;
799 }
800
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200801 if (text_backend->input_method.client != client) {
802 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
Eduardo Lima (Etrunko)a2ce68f2013-05-10 17:50:36 -0300803 "permission to bind input_method denied");
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200804 return;
805 }
806
Jason Ekstranda85118c2013-06-27 20:17:02 -0500807 wl_resource_set_implementation(resource, NULL, input_method,
808 unbind_input_method);
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200809 input_method->input_method_binding = resource;
810
811 text_backend->input_method.binding = resource;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200812}
813
814static void
815input_method_notifier_destroy(struct wl_listener *listener, void *data)
816{
Kristian Høgsbergf97f3792012-07-22 11:51:42 -0400817 struct input_method *input_method =
818 container_of(listener, struct input_method, destroy_listener);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200819
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200820 if (input_method->model)
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200821 deactivate_text_input(input_method->model, input_method);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200822
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400823 wl_global_destroy(input_method->input_method_global);
Rob Bradfordead3ef82013-07-24 16:57:32 +0100824 wl_list_remove(&input_method->destroy_listener.link);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200825
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200826 free(input_method);
827}
828
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200829static void
830handle_keyboard_focus(struct wl_listener *listener, void *data)
831{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400832 struct weston_keyboard *keyboard = data;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200833 struct input_method *input_method =
834 container_of(listener, struct input_method, keyboard_focus_listener);
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400835 struct weston_surface *surface = keyboard->focus;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200836
837 if (!input_method->model)
838 return;
839
840 if (!surface || input_method->model->surface != surface)
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200841 deactivate_text_input(input_method->model,
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200842 input_method);
843}
844
845static void
846input_method_init_seat(struct weston_seat *seat)
847{
848 if (seat->input_method->focus_listener_initialized)
849 return;
850
Kristian Høgsberg2bf87622013-05-07 23:17:41 -0400851 if (seat->keyboard) {
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200852 seat->input_method->keyboard_focus_listener.notify = handle_keyboard_focus;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400853 wl_signal_add(&seat->keyboard->focus_signal, &seat->input_method->keyboard_focus_listener);
854 seat->keyboard->input_method_grab.interface = &input_method_context_grab;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200855 }
856
857 seat->input_method->focus_listener_initialized = 1;
858}
859
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300860static void launch_input_method(struct text_backend *text_backend);
861
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100862static void
863handle_input_method_sigchld(struct weston_process *process, int status)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200864{
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300865 uint32_t time;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100866 struct text_backend *text_backend =
867 container_of(process, struct text_backend, input_method.process);
868
869 text_backend->input_method.process.pid = 0;
870 text_backend->input_method.client = NULL;
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300871
872 /* if input_method dies more than 5 times in 10 seconds, give up */
873 time = weston_compositor_get_time();
874 if (time - text_backend->input_method.deathstamp > 10000) {
875 text_backend->input_method.deathstamp = time;
876 text_backend->input_method.deathcount = 0;
877 }
878
879 text_backend->input_method.deathcount++;
880 if (text_backend->input_method.deathcount > 5) {
881 weston_log("input_method died, giving up.\n");
882 return;
883 }
884
885 weston_log("input_method died, respawning...\n");
886 launch_input_method(text_backend);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100887}
888
889static void
890launch_input_method(struct text_backend *text_backend)
891{
892 if (text_backend->input_method.binding)
893 return;
894
895 if (!text_backend->input_method.path)
896 return;
897
898 if (text_backend->input_method.process.pid != 0)
899 return;
900
901 text_backend->input_method.client = weston_client_launch(text_backend->compositor,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200902 &text_backend->input_method.process,
903 text_backend->input_method.path,
904 handle_input_method_sigchld);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100905
906 if (!text_backend->input_method.client)
907 weston_log("not able to start %s\n", text_backend->input_method.path);
908}
909
910static void
911handle_seat_created(struct wl_listener *listener,
912 void *data)
913{
914 struct weston_seat *seat = data;
915 struct text_backend *text_backend =
916 container_of(listener, struct text_backend,
917 seat_created_listener);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200918 struct input_method *input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100919 struct weston_compositor *ec = seat->compositor;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200920
Bryce Harringtonde16d892014-11-20 22:21:57 -0800921 input_method = zalloc(sizeof *input_method);
922 if (input_method == NULL)
923 return;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200924
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200925 input_method->seat = seat;
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200926 input_method->model = NULL;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200927 input_method->focus_listener_initialized = 0;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200928 input_method->context = NULL;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100929 input_method->text_backend = text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200930
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200931 input_method->input_method_global =
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400932 wl_global_create(ec->wl_display, &wl_input_method_interface, 1,
933 input_method, bind_input_method);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200934
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200935 input_method->destroy_listener.notify = input_method_notifier_destroy;
Kristian Høgsberg49124542013-05-06 22:27:40 -0400936 wl_signal_add(&seat->destroy_signal, &input_method->destroy_listener);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200937
938 seat->input_method = input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100939
940 launch_input_method(text_backend);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200941}
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200942
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100943static void
944text_backend_configuration(struct text_backend *text_backend)
945{
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -0400946 struct weston_config_section *section;
Derek Foremanc7210432014-08-21 11:32:38 -0500947 char *client;
Pekka Paalanen974c0942014-09-05 14:45:09 +0300948 int ret;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100949
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -0400950 section = weston_config_get_section(text_backend->compositor->config,
951 "input-method", NULL, NULL);
Pekka Paalanen974c0942014-09-05 14:45:09 +0300952 ret = asprintf(&client, "%s/weston-keyboard",
953 weston_config_get_libexec_dir());
954 if (ret < 0)
955 client = NULL;
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -0400956 weston_config_section_get_string(section, "path",
957 &text_backend->input_method.path,
Derek Foremanc7210432014-08-21 11:32:38 -0500958 client);
959 free(client);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100960}
961
962static void
963text_backend_notifier_destroy(struct wl_listener *listener, void *data)
964{
965 struct text_backend *text_backend =
966 container_of(listener, struct text_backend, destroy_listener);
967
968 if (text_backend->input_method.client)
969 wl_client_destroy(text_backend->input_method.client);
970
971 free(text_backend->input_method.path);
972
973 free(text_backend);
974}
975
976
977WL_EXPORT int
978text_backend_init(struct weston_compositor *ec)
979{
980 struct text_backend *text_backend;
981
Bryce Harringtonde16d892014-11-20 22:21:57 -0800982 text_backend = zalloc(sizeof(*text_backend));
983 if (text_backend == NULL)
984 return -1;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100985
986 text_backend->compositor = ec;
987
988 text_backend->seat_created_listener.notify = handle_seat_created;
989 wl_signal_add(&ec->seat_created_signal,
990 &text_backend->seat_created_listener);
991
992 text_backend->destroy_listener.notify = text_backend_notifier_destroy;
993 wl_signal_add(&ec->destroy_signal, &text_backend->destroy_listener);
994
995 text_backend_configuration(text_backend);
996
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200997 text_input_manager_create(ec);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100998
999 return 0;
1000}