blob: 4dc7179717c569dd1dff2cad5d5fe8535c87e095 [file] [log] [blame]
Jan Arne Petersen1f17be42012-06-21 21:52:18 +02001/*
2 * Copyright © 2012 Openismus GmbH
Jan Arne Petersen4c265182012-09-09 23:08:30 +02003 * Copyright © 2012 Intel Corporation
Jan Arne Petersen1f17be42012-06-21 21:52:18 +02004 *
5 * Permission to use, copy, modify, distribute, and sell this software and
6 * its documentation for any purpose is hereby granted without fee, provided
7 * that the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of the copyright holders not be used in
10 * advertising or publicity pertaining to distribution of the software
11 * without specific, written prior permission. The copyright holders make
12 * no representations about the suitability of this software for any
13 * purpose. It is provided "as is" without express or implied warranty.
14 *
15 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
16 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
19 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
20 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 */
23
Daniel Stonec228e232013-05-22 18:03:19 +030024#include "config.h"
25
Derek Foremand09dbb32014-12-05 15:38:39 -060026#include <stdbool.h>
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020027#include <stdlib.h>
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010028#include <string.h>
Ossama Othmana50e6e42013-05-14 09:48:26 -070029#include <unistd.h>
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -030030#include <time.h>
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020031
32#include "compositor.h"
33#include "text-server-protocol.h"
Jan Arne Petersen30b66ef2012-09-09 23:08:41 +020034#include "input-method-server-protocol.h"
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020035
36struct input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020037struct input_method_context;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010038struct text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020039
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020040struct text_input {
Jason Ekstrand89d31992013-06-14 10:07:59 -050041 struct wl_resource *resource;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020042
Jan Arne Petersene829adc2012-08-10 16:47:22 +020043 struct weston_compositor *ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020044
Jan Arne Petersene829adc2012-08-10 16:47:22 +020045 struct wl_list input_methods;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +020046
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -040047 struct weston_surface *surface;
Jan Arne Petersen61381972013-01-31 15:52:21 +010048
Jan Arne Petersen14da96b2013-04-18 16:47:28 +020049 pixman_box32_t cursor_rectangle;
50
Derek Foremand09dbb32014-12-05 15:38:39 -060051 bool input_panel_visible;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020052};
53
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020054struct text_input_manager {
55 struct wl_global *text_input_manager_global;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020056 struct wl_listener destroy_listener;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020057
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +020058 struct weston_compositor *ec;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +020059};
60
61struct input_method {
62 struct wl_resource *input_method_binding;
63 struct wl_global *input_method_global;
64 struct wl_listener destroy_listener;
65
66 struct weston_seat *seat;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020067 struct text_input *model;
Jan Arne Petersene829adc2012-08-10 16:47:22 +020068
69 struct wl_list link;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +020070
71 struct wl_listener keyboard_focus_listener;
72
73 int focus_listener_initialized;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020074
75 struct input_method_context *context;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010076
77 struct text_backend *text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020078};
79
Jan Arne Petersen620cd622012-09-09 23:08:32 +020080struct input_method_context {
Jason Ekstrand89d31992013-06-14 10:07:59 -050081 struct wl_resource *resource;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020082
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020083 struct text_input *model;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +010084 struct input_method *input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020085
Jan Arne Petersen466b9c12012-11-18 19:06:45 +010086 struct wl_resource *keyboard;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020087};
88
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010089struct text_backend {
90 struct weston_compositor *compositor;
91
92 struct {
93 char *path;
94 struct wl_resource *binding;
95 struct weston_process process;
96 struct wl_client *client;
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -030097
98 unsigned deathcount;
99 uint32_t deathstamp;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100100 } input_method;
101
102 struct wl_listener seat_created_listener;
103 struct wl_listener destroy_listener;
104};
105
Derek Foremancb5fcea2014-12-05 15:38:37 -0600106static void
107input_method_context_create(struct text_input *model,
108 struct input_method *input_method);
109static void
110input_method_context_end_keyboard_grab(struct input_method_context *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200111
Derek Foremancb5fcea2014-12-05 15:38:37 -0600112static void
113input_method_init_seat(struct weston_seat *seat);
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200114
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200115static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200116deactivate_text_input(struct text_input *text_input,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200117 struct input_method *input_method)
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200118{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200119 struct weston_compositor *ec = text_input->ec;
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200120
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200121 if (input_method->model == text_input) {
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100122 if (input_method->context && input_method->input_method_binding) {
123 input_method_context_end_keyboard_grab(input_method->context);
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200124 wl_input_method_send_deactivate(input_method->input_method_binding,
Jason Ekstrand89d31992013-06-14 10:07:59 -0500125 input_method->context->resource);
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800126 input_method->context->model = NULL;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100127 }
128
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200129 wl_list_remove(&input_method->link);
130 input_method->model = NULL;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200131 input_method->context = NULL;
Kristian Høgsbergf97f3792012-07-22 11:51:42 -0400132 wl_signal_emit(&ec->hide_input_panel_signal, ec);
Jason Ekstrand89d31992013-06-14 10:07:59 -0500133 wl_text_input_send_leave(text_input->resource);
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200134 }
135}
136
137static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200138destroy_text_input(struct wl_resource *resource)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200139{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500140 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200141 struct input_method *input_method, *next;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200142
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200143 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link)
144 deactivate_text_input(text_input, input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200145
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200146 free(text_input);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200147}
148
149static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200150text_input_set_surrounding_text(struct wl_client *client,
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200151 struct wl_resource *resource,
Jan Arne Petersencb08f4d2012-09-09 23:08:40 +0200152 const char *text,
153 uint32_t cursor,
154 uint32_t anchor)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200155{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500156 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200157 struct input_method *input_method, *next;
158
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200159 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200160 if (!input_method->context)
161 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500162 wl_input_method_context_send_surrounding_text(input_method->context->resource,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200163 text,
164 cursor,
165 anchor);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200166 }
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200167}
168
169static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200170text_input_activate(struct wl_client *client,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200171 struct wl_resource *resource,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200172 struct wl_resource *seat,
173 struct wl_resource *surface)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200174{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500175 struct text_input *text_input = wl_resource_get_user_data(resource);
Jason Ekstrand44a38632013-06-14 10:08:00 -0500176 struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200177 struct input_method *input_method = weston_seat->input_method;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200178 struct text_input *old = weston_seat->input_method->model;
179 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200180
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200181 if (old == text_input)
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200182 return;
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200183
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200184 if (old) {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200185 deactivate_text_input(old,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200186 weston_seat->input_method);
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200187 }
188
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200189 input_method->model = text_input;
190 wl_list_insert(&text_input->input_methods, &input_method->link);
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200191 input_method_init_seat(weston_seat);
192
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -0500193 text_input->surface = wl_resource_get_user_data(surface);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200194
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200195 input_method_context_create(text_input, input_method);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200196
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200197 if (text_input->input_panel_visible) {
198 wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
199 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
200 }
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200201
Jason Ekstrand89d31992013-06-14 10:07:59 -0500202 wl_text_input_send_enter(text_input->resource, text_input->surface->resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200203}
204
205static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200206text_input_deactivate(struct wl_client *client,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200207 struct wl_resource *resource,
208 struct wl_resource *seat)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200209{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500210 struct text_input *text_input = wl_resource_get_user_data(resource);
Jason Ekstrand44a38632013-06-14 10:08:00 -0500211 struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200212
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200213 deactivate_text_input(text_input,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200214 weston_seat->input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200215}
216
217static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200218text_input_reset(struct wl_client *client,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200219 struct wl_resource *resource)
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200220{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500221 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200222 struct input_method *input_method, *next;
223
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200224 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200225 if (!input_method->context)
226 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500227 wl_input_method_context_send_reset(input_method->context->resource);
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200228 }
229}
230
231static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200232text_input_set_cursor_rectangle(struct wl_client *client,
Jan Arne Petersen7ef8eff2013-04-18 16:47:23 +0200233 struct wl_resource *resource,
234 int32_t x,
235 int32_t y,
236 int32_t width,
237 int32_t height)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200238{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500239 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200240 struct weston_compositor *ec = text_input->ec;
241
242 text_input->cursor_rectangle.x1 = x;
243 text_input->cursor_rectangle.y1 = y;
244 text_input->cursor_rectangle.x2 = x + width;
245 text_input->cursor_rectangle.y2 = y + height;
246
247 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200248}
249
250static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200251text_input_set_content_type(struct wl_client *client,
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100252 struct wl_resource *resource,
253 uint32_t hint,
254 uint32_t purpose)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200255{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500256 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100257 struct input_method *input_method, *next;
258
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200259 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100260 if (!input_method->context)
261 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500262 wl_input_method_context_send_content_type(input_method->context->resource, hint, purpose);
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100263 }
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200264}
265
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100266static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200267text_input_invoke_action(struct wl_client *client,
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100268 struct wl_resource *resource,
269 uint32_t button,
270 uint32_t index)
271{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500272 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100273 struct input_method *input_method, *next;
274
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200275 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100276 if (!input_method->context)
277 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500278 wl_input_method_context_send_invoke_action(input_method->context->resource, button, index);
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100279 }
280}
281
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100282static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200283text_input_commit_state(struct wl_client *client,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200284 struct wl_resource *resource,
285 uint32_t serial)
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100286{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500287 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100288 struct input_method *input_method, *next;
289
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200290 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100291 if (!input_method->context)
292 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500293 wl_input_method_context_send_commit_state(input_method->context->resource, serial);
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100294 }
295}
296
Jan Arne Petersen61381972013-01-31 15:52:21 +0100297static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200298text_input_show_input_panel(struct wl_client *client,
Jan Arne Petersen61381972013-01-31 15:52:21 +0100299 struct wl_resource *resource)
300{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500301 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200302 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100303
Derek Foremand09dbb32014-12-05 15:38:39 -0600304 text_input->input_panel_visible = true;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100305
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200306 if (!wl_list_empty(&text_input->input_methods)) {
307 wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
308 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
309 }
Jan Arne Petersen61381972013-01-31 15:52:21 +0100310}
311
312static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200313text_input_hide_input_panel(struct wl_client *client,
Jan Arne Petersen61381972013-01-31 15:52:21 +0100314 struct wl_resource *resource)
315{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500316 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200317 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100318
Derek Foremand09dbb32014-12-05 15:38:39 -0600319 text_input->input_panel_visible = false;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100320
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200321 if (!wl_list_empty(&text_input->input_methods))
Jan Arne Petersen61381972013-01-31 15:52:21 +0100322 wl_signal_emit(&ec->hide_input_panel_signal, ec);
323}
324
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200325static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200326text_input_set_preferred_language(struct wl_client *client,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200327 struct wl_resource *resource,
328 const char *language)
329{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500330 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200331 struct input_method *input_method, *next;
332
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200333 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200334 if (!input_method->context)
335 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500336 wl_input_method_context_send_preferred_language(input_method->context->resource,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200337 language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200338 }
339}
340
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200341static const struct wl_text_input_interface text_input_implementation = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200342 text_input_activate,
343 text_input_deactivate,
344 text_input_show_input_panel,
345 text_input_hide_input_panel,
346 text_input_reset,
347 text_input_set_surrounding_text,
348 text_input_set_content_type,
349 text_input_set_cursor_rectangle,
350 text_input_set_preferred_language,
351 text_input_commit_state,
352 text_input_invoke_action
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200353};
354
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200355static void text_input_manager_create_text_input(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200356 struct wl_resource *resource,
Jan Arne Petersen4c265182012-09-09 23:08:30 +0200357 uint32_t id)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200358{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500359 struct text_input_manager *text_input_manager = wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200360 struct text_input *text_input;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200361
Bryce Harringtonde16d892014-11-20 22:21:57 -0800362 text_input = zalloc(sizeof *text_input);
363 if (text_input == NULL)
364 return;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200365
Jason Ekstranda85118c2013-06-27 20:17:02 -0500366 text_input->resource =
367 wl_resource_create(client, &wl_text_input_interface, 1, id);
368 wl_resource_set_implementation(text_input->resource,
369 &text_input_implementation,
370 text_input, destroy_text_input);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200371
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200372 text_input->ec = text_input_manager->ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200373
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200374 wl_list_init(&text_input->input_methods);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200375};
376
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200377static const struct wl_text_input_manager_interface text_input_manager_implementation = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200378 text_input_manager_create_text_input
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200379};
380
381static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200382bind_text_input_manager(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200383 void *data,
384 uint32_t version,
385 uint32_t id)
386{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200387 struct text_input_manager *text_input_manager = data;
Jason Ekstranda85118c2013-06-27 20:17:02 -0500388 struct wl_resource *resource;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200389
Jason Ekstranda85118c2013-06-27 20:17:02 -0500390 /* No checking for duplicate binding necessary. */
391 resource =
392 wl_resource_create(client,
393 &wl_text_input_manager_interface, 1, id);
394 if (resource)
395 wl_resource_set_implementation(resource,
396 &text_input_manager_implementation,
397 text_input_manager, NULL);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200398}
399
400static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200401text_input_manager_notifier_destroy(struct wl_listener *listener, void *data)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200402{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200403 struct text_input_manager *text_input_manager =
404 container_of(listener, struct text_input_manager, destroy_listener);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200405
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400406 wl_global_destroy(text_input_manager->text_input_manager_global);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200407
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200408 free(text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200409}
410
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100411static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200412text_input_manager_create(struct weston_compositor *ec)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200413{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200414 struct text_input_manager *text_input_manager;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200415
Bryce Harringtonde16d892014-11-20 22:21:57 -0800416 text_input_manager = zalloc(sizeof *text_input_manager);
417 if (text_input_manager == NULL)
418 return;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200419
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200420 text_input_manager->ec = ec;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200421
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200422 text_input_manager->text_input_manager_global =
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400423 wl_global_create(ec->wl_display,
424 &wl_text_input_manager_interface, 1,
425 text_input_manager, bind_text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200426
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200427 text_input_manager->destroy_listener.notify = text_input_manager_notifier_destroy;
428 wl_signal_add(&ec->destroy_signal, &text_input_manager->destroy_listener);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200429}
430
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200431static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200432input_method_context_destroy(struct wl_client *client,
433 struct wl_resource *resource)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200434{
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200435 wl_resource_destroy(resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200436}
437
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200438static void
439input_method_context_commit_string(struct wl_client *client,
440 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100441 uint32_t serial,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100442 const char *text)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200443{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500444 struct input_method_context *context =
445 wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200446
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800447 if (context->model)
448 wl_text_input_send_commit_string(context->model->resource,
449 serial, text);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200450}
451
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200452static void
453input_method_context_preedit_string(struct wl_client *client,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100454 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100455 uint32_t serial,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100456 const char *text,
457 const char *commit)
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200458{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500459 struct input_method_context *context =
460 wl_resource_get_user_data(resource);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200461
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800462 if (context->model)
463 wl_text_input_send_preedit_string(context->model->resource,
464 serial, text, commit);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100465}
466
467static void
468input_method_context_preedit_styling(struct wl_client *client,
469 struct wl_resource *resource,
470 uint32_t index,
471 uint32_t length,
472 uint32_t style)
473{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500474 struct input_method_context *context =
475 wl_resource_get_user_data(resource);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100476
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800477 if (context->model)
478 wl_text_input_send_preedit_styling(context->model->resource,
479 index, length, style);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100480}
481
482static void
483input_method_context_preedit_cursor(struct wl_client *client,
484 struct wl_resource *resource,
485 int32_t cursor)
486{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500487 struct input_method_context *context =
488 wl_resource_get_user_data(resource);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100489
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800490 if (context->model)
491 wl_text_input_send_preedit_cursor(context->model->resource,
492 cursor);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200493}
494
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200495static void
496input_method_context_delete_surrounding_text(struct wl_client *client,
497 struct wl_resource *resource,
498 int32_t index,
499 uint32_t length)
500{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500501 struct input_method_context *context =
502 wl_resource_get_user_data(resource);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200503
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800504 if (context->model)
505 wl_text_input_send_delete_surrounding_text(context->model->resource,
506 index, length);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200507}
508
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200509static void
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100510input_method_context_cursor_position(struct wl_client *client,
511 struct wl_resource *resource,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100512 int32_t index,
513 int32_t anchor)
514{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500515 struct input_method_context *context =
516 wl_resource_get_user_data(resource);
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100517
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800518 if (context->model)
519 wl_text_input_send_cursor_position(context->model->resource,
520 index, anchor);
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100521}
522
523static void
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100524input_method_context_modifiers_map(struct wl_client *client,
525 struct wl_resource *resource,
526 struct wl_array *map)
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200527{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500528 struct input_method_context *context =
529 wl_resource_get_user_data(resource);
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200530
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800531 if (context->model)
532 wl_text_input_send_modifiers_map(context->model->resource, map);
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100533}
534
535static void
536input_method_context_keysym(struct wl_client *client,
537 struct wl_resource *resource,
538 uint32_t serial,
539 uint32_t time,
540 uint32_t sym,
541 uint32_t state,
542 uint32_t modifiers)
543{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500544 struct input_method_context *context =
545 wl_resource_get_user_data(resource);
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100546
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800547 if (context->model)
548 wl_text_input_send_keysym(context->model->resource,
549 serial, time, sym, state, modifiers);
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200550}
551
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100552static void
553unbind_keyboard(struct wl_resource *resource)
554{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500555 struct input_method_context *context =
556 wl_resource_get_user_data(resource);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100557
558 input_method_context_end_keyboard_grab(context);
559 context->keyboard = NULL;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100560}
561
562static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400563input_method_context_grab_key(struct weston_keyboard_grab *grab,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100564 uint32_t time, uint32_t key, uint32_t state_w)
565{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400566 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100567 struct wl_display *display;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100568 uint32_t serial;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100569
570 if (!keyboard->input_method_resource)
571 return;
572
Jason Ekstrand89d31992013-06-14 10:07:59 -0500573 display = wl_client_get_display(wl_resource_get_client(keyboard->input_method_resource));
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100574 serial = wl_display_next_serial(display);
575 wl_keyboard_send_key(keyboard->input_method_resource,
576 serial, time, key, state_w);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100577}
578
579static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400580input_method_context_grab_modifier(struct weston_keyboard_grab *grab, uint32_t serial,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100581 uint32_t mods_depressed, uint32_t mods_latched,
582 uint32_t mods_locked, uint32_t group)
583{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400584 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100585
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100586 if (!keyboard->input_method_resource)
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100587 return;
588
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100589 wl_keyboard_send_modifiers(keyboard->input_method_resource,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100590 serial, mods_depressed, mods_latched,
591 mods_locked, group);
592}
593
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200594static void
595input_method_context_grab_cancel(struct weston_keyboard_grab *grab)
596{
597 weston_keyboard_end_grab(grab->keyboard);
598}
599
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400600static const struct weston_keyboard_grab_interface input_method_context_grab = {
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100601 input_method_context_grab_key,
602 input_method_context_grab_modifier,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200603 input_method_context_grab_cancel,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100604};
605
606static void
607input_method_context_grab_keyboard(struct wl_client *client,
608 struct wl_resource *resource,
609 uint32_t id)
610{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500611 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100612 struct wl_resource *cr;
613 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400614 struct weston_keyboard *keyboard = seat->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100615
Jason Ekstranda85118c2013-06-27 20:17:02 -0500616 cr = wl_resource_create(client, &wl_keyboard_interface, 1, id);
617 wl_resource_set_implementation(cr, NULL, context, unbind_keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100618
619 context->keyboard = cr;
620
621 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
Jonas Ådahl7395ea02013-12-03 09:14:26 +0100622 keyboard->xkb_info->keymap_fd,
623 keyboard->xkb_info->keymap_size);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100624
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400625 if (keyboard->grab != &keyboard->default_grab) {
626 weston_keyboard_end_grab(keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100627 }
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400628 weston_keyboard_start_grab(keyboard, &keyboard->input_method_grab);
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100629 keyboard->input_method_resource = cr;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100630}
631
Jan Arne Petersen337df952012-11-18 19:06:46 +0100632static void
633input_method_context_key(struct wl_client *client,
634 struct wl_resource *resource,
635 uint32_t serial,
636 uint32_t time,
637 uint32_t key,
638 uint32_t state_w)
639{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500640 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen337df952012-11-18 19:06:46 +0100641 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400642 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400643 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100644
645 default_grab->interface->key(default_grab, time, key, state_w);
646}
647
648static void
649input_method_context_modifiers(struct wl_client *client,
650 struct wl_resource *resource,
651 uint32_t serial,
652 uint32_t mods_depressed,
653 uint32_t mods_latched,
654 uint32_t mods_locked,
655 uint32_t group)
656{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500657 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen337df952012-11-18 19:06:46 +0100658
659 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400660 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400661 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100662
663 default_grab->interface->modifiers(default_grab,
664 serial, mods_depressed,
665 mods_latched, mods_locked,
666 group);
667}
668
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200669static void
670input_method_context_language(struct wl_client *client,
671 struct wl_resource *resource,
672 uint32_t serial,
673 const char *language)
674{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500675 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200676
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800677 if (context->model)
678 wl_text_input_send_language(context->model->resource,
679 serial, language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200680}
681
682static void
683input_method_context_text_direction(struct wl_client *client,
684 struct wl_resource *resource,
685 uint32_t serial,
686 uint32_t direction)
687{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500688 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200689
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800690 if (context->model)
691 wl_text_input_send_text_direction(context->model->resource,
692 serial, direction);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200693}
694
695
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200696static const struct wl_input_method_context_interface input_method_context_implementation = {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200697 input_method_context_destroy,
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200698 input_method_context_commit_string,
699 input_method_context_preedit_string,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100700 input_method_context_preedit_styling,
701 input_method_context_preedit_cursor,
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200702 input_method_context_delete_surrounding_text,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100703 input_method_context_cursor_position,
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100704 input_method_context_modifiers_map,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100705 input_method_context_keysym,
Jan Arne Petersen337df952012-11-18 19:06:46 +0100706 input_method_context_grab_keyboard,
707 input_method_context_key,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200708 input_method_context_modifiers,
709 input_method_context_language,
710 input_method_context_text_direction
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200711};
712
713static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200714destroy_input_method_context(struct wl_resource *resource)
715{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500716 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200717
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100718 if (context->keyboard) {
719 wl_resource_destroy(context->keyboard);
720 }
721
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200722 free(context);
723}
724
725static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200726input_method_context_create(struct text_input *model,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200727 struct input_method *input_method)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200728{
729 struct input_method_context *context;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500730 struct wl_resource *binding;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200731
732 if (!input_method->input_method_binding)
733 return;
734
Bryce Harringtonde16d892014-11-20 22:21:57 -0800735 context = zalloc(sizeof *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200736 if (context == NULL)
737 return;
738
Jason Ekstrand89d31992013-06-14 10:07:59 -0500739 binding = input_method->input_method_binding;
Jason Ekstranda85118c2013-06-27 20:17:02 -0500740 context->resource =
741 wl_resource_create(wl_resource_get_client(binding),
742 &wl_input_method_context_interface, 1, 0);
743 wl_resource_set_implementation(context->resource,
744 &input_method_context_implementation,
745 context, destroy_input_method_context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200746
747 context->model = model;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100748 context->input_method = input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200749 input_method->context = context;
750
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200751
Jason Ekstrand89d31992013-06-14 10:07:59 -0500752 wl_input_method_send_activate(binding, context->resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200753}
754
755static void
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100756input_method_context_end_keyboard_grab(struct input_method_context *context)
757{
Derek Foremanf0aaa412014-12-08 10:48:29 -0600758 struct weston_keyboard_grab *grab;
759 struct weston_keyboard *keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100760
Derek Foremanf0aaa412014-12-08 10:48:29 -0600761 if (!context->input_method->seat->keyboard)
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100762 return;
763
Derek Foremanf0aaa412014-12-08 10:48:29 -0600764 grab = &context->input_method->seat->keyboard->input_method_grab;
765 keyboard = grab->keyboard;
766 if (!keyboard)
767 return;
768
769 if (keyboard->grab == grab)
770 weston_keyboard_end_grab(keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100771
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100772 keyboard->input_method_resource = NULL;
773}
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100774
775static void
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200776unbind_input_method(struct wl_resource *resource)
777{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500778 struct input_method *input_method = wl_resource_get_user_data(resource);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100779 struct text_backend *text_backend = input_method->text_backend;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200780
781 input_method->input_method_binding = NULL;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200782 input_method->context = NULL;
783
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100784 text_backend->input_method.binding = NULL;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200785}
786
787static void
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200788bind_input_method(struct wl_client *client,
789 void *data,
790 uint32_t version,
791 uint32_t id)
792{
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200793 struct input_method *input_method = data;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100794 struct text_backend *text_backend = input_method->text_backend;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200795 struct wl_resource *resource;
796
Jason Ekstranda85118c2013-06-27 20:17:02 -0500797 resource =
798 wl_resource_create(client, &wl_input_method_interface, 1, id);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200799
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200800 if (input_method->input_method_binding != NULL) {
801 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
802 "interface object already bound");
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200803 return;
804 }
805
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200806 if (text_backend->input_method.client != client) {
807 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
Eduardo Lima (Etrunko)a2ce68f2013-05-10 17:50:36 -0300808 "permission to bind input_method denied");
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200809 return;
810 }
811
Jason Ekstranda85118c2013-06-27 20:17:02 -0500812 wl_resource_set_implementation(resource, NULL, input_method,
813 unbind_input_method);
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200814 input_method->input_method_binding = resource;
815
816 text_backend->input_method.binding = resource;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200817}
818
819static void
820input_method_notifier_destroy(struct wl_listener *listener, void *data)
821{
Kristian Høgsbergf97f3792012-07-22 11:51:42 -0400822 struct input_method *input_method =
823 container_of(listener, struct input_method, destroy_listener);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200824
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200825 if (input_method->model)
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200826 deactivate_text_input(input_method->model, input_method);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200827
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400828 wl_global_destroy(input_method->input_method_global);
Rob Bradfordead3ef82013-07-24 16:57:32 +0100829 wl_list_remove(&input_method->destroy_listener.link);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200830
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200831 free(input_method);
832}
833
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200834static void
835handle_keyboard_focus(struct wl_listener *listener, void *data)
836{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400837 struct weston_keyboard *keyboard = data;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200838 struct input_method *input_method =
839 container_of(listener, struct input_method, keyboard_focus_listener);
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400840 struct weston_surface *surface = keyboard->focus;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200841
842 if (!input_method->model)
843 return;
844
845 if (!surface || input_method->model->surface != surface)
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200846 deactivate_text_input(input_method->model,
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200847 input_method);
848}
849
850static void
851input_method_init_seat(struct weston_seat *seat)
852{
853 if (seat->input_method->focus_listener_initialized)
854 return;
855
Kristian Høgsberg2bf87622013-05-07 23:17:41 -0400856 if (seat->keyboard) {
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200857 seat->input_method->keyboard_focus_listener.notify = handle_keyboard_focus;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400858 wl_signal_add(&seat->keyboard->focus_signal, &seat->input_method->keyboard_focus_listener);
859 seat->keyboard->input_method_grab.interface = &input_method_context_grab;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200860 }
861
862 seat->input_method->focus_listener_initialized = 1;
863}
864
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300865static void launch_input_method(struct text_backend *text_backend);
866
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100867static void
868handle_input_method_sigchld(struct weston_process *process, int status)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200869{
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300870 uint32_t time;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100871 struct text_backend *text_backend =
872 container_of(process, struct text_backend, input_method.process);
873
874 text_backend->input_method.process.pid = 0;
875 text_backend->input_method.client = NULL;
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300876
877 /* if input_method dies more than 5 times in 10 seconds, give up */
878 time = weston_compositor_get_time();
879 if (time - text_backend->input_method.deathstamp > 10000) {
880 text_backend->input_method.deathstamp = time;
881 text_backend->input_method.deathcount = 0;
882 }
883
884 text_backend->input_method.deathcount++;
885 if (text_backend->input_method.deathcount > 5) {
886 weston_log("input_method died, giving up.\n");
887 return;
888 }
889
890 weston_log("input_method died, respawning...\n");
891 launch_input_method(text_backend);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100892}
893
894static void
895launch_input_method(struct text_backend *text_backend)
896{
897 if (text_backend->input_method.binding)
898 return;
899
900 if (!text_backend->input_method.path)
901 return;
902
903 if (text_backend->input_method.process.pid != 0)
904 return;
905
906 text_backend->input_method.client = weston_client_launch(text_backend->compositor,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200907 &text_backend->input_method.process,
908 text_backend->input_method.path,
909 handle_input_method_sigchld);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100910
911 if (!text_backend->input_method.client)
912 weston_log("not able to start %s\n", text_backend->input_method.path);
913}
914
915static void
916handle_seat_created(struct wl_listener *listener,
917 void *data)
918{
919 struct weston_seat *seat = data;
920 struct text_backend *text_backend =
921 container_of(listener, struct text_backend,
922 seat_created_listener);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200923 struct input_method *input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100924 struct weston_compositor *ec = seat->compositor;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200925
Bryce Harringtonde16d892014-11-20 22:21:57 -0800926 input_method = zalloc(sizeof *input_method);
927 if (input_method == NULL)
928 return;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200929
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200930 input_method->seat = seat;
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200931 input_method->model = NULL;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200932 input_method->focus_listener_initialized = 0;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200933 input_method->context = NULL;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100934 input_method->text_backend = text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200935
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200936 input_method->input_method_global =
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400937 wl_global_create(ec->wl_display, &wl_input_method_interface, 1,
938 input_method, bind_input_method);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200939
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200940 input_method->destroy_listener.notify = input_method_notifier_destroy;
Kristian Høgsberg49124542013-05-06 22:27:40 -0400941 wl_signal_add(&seat->destroy_signal, &input_method->destroy_listener);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200942
943 seat->input_method = input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100944
945 launch_input_method(text_backend);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200946}
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200947
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100948static void
949text_backend_configuration(struct text_backend *text_backend)
950{
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -0400951 struct weston_config_section *section;
Derek Foremanc7210432014-08-21 11:32:38 -0500952 char *client;
Pekka Paalanen974c0942014-09-05 14:45:09 +0300953 int ret;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100954
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -0400955 section = weston_config_get_section(text_backend->compositor->config,
956 "input-method", NULL, NULL);
Pekka Paalanen974c0942014-09-05 14:45:09 +0300957 ret = asprintf(&client, "%s/weston-keyboard",
958 weston_config_get_libexec_dir());
959 if (ret < 0)
960 client = NULL;
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -0400961 weston_config_section_get_string(section, "path",
962 &text_backend->input_method.path,
Derek Foremanc7210432014-08-21 11:32:38 -0500963 client);
964 free(client);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100965}
966
967static void
968text_backend_notifier_destroy(struct wl_listener *listener, void *data)
969{
970 struct text_backend *text_backend =
971 container_of(listener, struct text_backend, destroy_listener);
972
973 if (text_backend->input_method.client)
974 wl_client_destroy(text_backend->input_method.client);
975
976 free(text_backend->input_method.path);
977
978 free(text_backend);
979}
980
981
982WL_EXPORT int
983text_backend_init(struct weston_compositor *ec)
984{
985 struct text_backend *text_backend;
986
Bryce Harringtonde16d892014-11-20 22:21:57 -0800987 text_backend = zalloc(sizeof(*text_backend));
988 if (text_backend == NULL)
989 return -1;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100990
991 text_backend->compositor = ec;
992
993 text_backend->seat_created_listener.notify = handle_seat_created;
994 wl_signal_add(&ec->seat_created_signal,
995 &text_backend->seat_created_listener);
996
997 text_backend->destroy_listener.notify = text_backend_notifier_destroy;
998 wl_signal_add(&ec->destroy_signal, &text_backend->destroy_listener);
999
1000 text_backend_configuration(text_backend);
1001
Jan Arne Petersen78d00e42013-04-18 16:47:24 +02001002 text_input_manager_create(ec);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001003
1004 return 0;
1005}