blob: d6a6f3b3a90d76865f89ed916ae17d7e46858cc6 [file] [log] [blame]
Jan Arne Petersen1f17be42012-06-21 21:52:18 +02001/*
2 * Copyright © 2012 Openismus GmbH
Jan Arne Petersen4c265182012-09-09 23:08:30 +02003 * Copyright © 2012 Intel Corporation
Jan Arne Petersen1f17be42012-06-21 21:52:18 +02004 *
5 * Permission to use, copy, modify, distribute, and sell this software and
6 * its documentation for any purpose is hereby granted without fee, provided
7 * that the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of the copyright holders not be used in
10 * advertising or publicity pertaining to distribution of the software
11 * without specific, written prior permission. The copyright holders make
12 * no representations about the suitability of this software for any
13 * purpose. It is provided "as is" without express or implied warranty.
14 *
15 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
16 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
19 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
20 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 */
23
Daniel Stonec228e232013-05-22 18:03:19 +030024#include "config.h"
25
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020026#include <stdlib.h>
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010027#include <string.h>
Ossama Othmana50e6e42013-05-14 09:48:26 -070028#include <unistd.h>
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -030029#include <time.h>
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020030
31#include "compositor.h"
32#include "text-server-protocol.h"
Jan Arne Petersen30b66ef2012-09-09 23:08:41 +020033#include "input-method-server-protocol.h"
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020034
35struct input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020036struct input_method_context;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010037struct text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020038
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020039struct text_input {
Jason Ekstrand89d31992013-06-14 10:07:59 -050040 struct wl_resource *resource;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020041
Jan Arne Petersene829adc2012-08-10 16:47:22 +020042 struct weston_compositor *ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020043
Jan Arne Petersene829adc2012-08-10 16:47:22 +020044 struct wl_list input_methods;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +020045
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -040046 struct weston_surface *surface;
Jan Arne Petersen61381972013-01-31 15:52:21 +010047
Jan Arne Petersen14da96b2013-04-18 16:47:28 +020048 pixman_box32_t cursor_rectangle;
49
Jan Arne Petersen61381972013-01-31 15:52:21 +010050 uint32_t input_panel_visible;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020051};
52
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020053struct text_input_manager {
54 struct wl_global *text_input_manager_global;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020055 struct wl_listener destroy_listener;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020056
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +020057 struct weston_compositor *ec;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +020058};
59
60struct input_method {
61 struct wl_resource *input_method_binding;
62 struct wl_global *input_method_global;
63 struct wl_listener destroy_listener;
64
65 struct weston_seat *seat;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020066 struct text_input *model;
Jan Arne Petersene829adc2012-08-10 16:47:22 +020067
68 struct wl_list link;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +020069
70 struct wl_listener keyboard_focus_listener;
71
72 int focus_listener_initialized;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020073
74 struct input_method_context *context;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010075
76 struct text_backend *text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020077};
78
Jan Arne Petersen620cd622012-09-09 23:08:32 +020079struct input_method_context {
Jason Ekstrand89d31992013-06-14 10:07:59 -050080 struct wl_resource *resource;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020081
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020082 struct text_input *model;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +010083 struct input_method *input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020084
85 struct wl_list link;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +010086
87 struct wl_resource *keyboard;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020088};
89
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010090struct text_backend {
91 struct weston_compositor *compositor;
92
93 struct {
94 char *path;
95 struct wl_resource *binding;
96 struct weston_process process;
97 struct wl_client *client;
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -030098
99 unsigned deathcount;
100 uint32_t deathstamp;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100101 } input_method;
102
103 struct wl_listener seat_created_listener;
104 struct wl_listener destroy_listener;
105};
106
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200107static void input_method_context_create(struct text_input *model,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200108 struct input_method *input_method);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100109static void input_method_context_end_keyboard_grab(struct input_method_context *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200110
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200111static void input_method_init_seat(struct weston_seat *seat);
112
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200113static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200114deactivate_text_input(struct text_input *text_input,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200115 struct input_method *input_method)
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200116{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200117 struct weston_compositor *ec = text_input->ec;
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200118
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200119 if (input_method->model == text_input) {
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100120 if (input_method->context && input_method->input_method_binding) {
121 input_method_context_end_keyboard_grab(input_method->context);
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200122 wl_input_method_send_deactivate(input_method->input_method_binding,
Jason Ekstrand89d31992013-06-14 10:07:59 -0500123 input_method->context->resource);
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800124 input_method->context->model = NULL;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100125 }
126
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200127 wl_list_remove(&input_method->link);
128 input_method->model = NULL;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200129 input_method->context = NULL;
Kristian Høgsbergf97f3792012-07-22 11:51:42 -0400130 wl_signal_emit(&ec->hide_input_panel_signal, ec);
Jason Ekstrand89d31992013-06-14 10:07:59 -0500131 wl_text_input_send_leave(text_input->resource);
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200132 }
133}
134
135static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200136destroy_text_input(struct wl_resource *resource)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200137{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500138 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200139 struct input_method *input_method, *next;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200140
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200141 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link)
142 deactivate_text_input(text_input, input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200143
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200144 free(text_input);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200145}
146
147static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200148text_input_set_surrounding_text(struct wl_client *client,
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200149 struct wl_resource *resource,
Jan Arne Petersencb08f4d2012-09-09 23:08:40 +0200150 const char *text,
151 uint32_t cursor,
152 uint32_t anchor)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200153{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500154 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200155 struct input_method *input_method, *next;
156
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200157 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200158 if (!input_method->context)
159 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500160 wl_input_method_context_send_surrounding_text(input_method->context->resource,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200161 text,
162 cursor,
163 anchor);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200164 }
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200165}
166
167static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200168text_input_activate(struct wl_client *client,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200169 struct wl_resource *resource,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200170 struct wl_resource *seat,
171 struct wl_resource *surface)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200172{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500173 struct text_input *text_input = wl_resource_get_user_data(resource);
Jason Ekstrand44a38632013-06-14 10:08:00 -0500174 struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200175 struct input_method *input_method = weston_seat->input_method;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200176 struct text_input *old = weston_seat->input_method->model;
177 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200178
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200179 if (old == text_input)
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200180 return;
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200181
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200182 if (old) {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200183 deactivate_text_input(old,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200184 weston_seat->input_method);
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200185 }
186
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200187 input_method->model = text_input;
188 wl_list_insert(&text_input->input_methods, &input_method->link);
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200189 input_method_init_seat(weston_seat);
190
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -0500191 text_input->surface = wl_resource_get_user_data(surface);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200192
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200193 input_method_context_create(text_input, input_method);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200194
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200195 if (text_input->input_panel_visible) {
196 wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
197 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
198 }
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200199
Jason Ekstrand89d31992013-06-14 10:07:59 -0500200 wl_text_input_send_enter(text_input->resource, text_input->surface->resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200201}
202
203static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200204text_input_deactivate(struct wl_client *client,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200205 struct wl_resource *resource,
206 struct wl_resource *seat)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200207{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500208 struct text_input *text_input = wl_resource_get_user_data(resource);
Jason Ekstrand44a38632013-06-14 10:08:00 -0500209 struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200210
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200211 deactivate_text_input(text_input,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200212 weston_seat->input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200213}
214
215static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200216text_input_reset(struct wl_client *client,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200217 struct wl_resource *resource)
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200218{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500219 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200220 struct input_method *input_method, *next;
221
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200222 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200223 if (!input_method->context)
224 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500225 wl_input_method_context_send_reset(input_method->context->resource);
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200226 }
227}
228
229static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200230text_input_set_cursor_rectangle(struct wl_client *client,
Jan Arne Petersen7ef8eff2013-04-18 16:47:23 +0200231 struct wl_resource *resource,
232 int32_t x,
233 int32_t y,
234 int32_t width,
235 int32_t height)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200236{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500237 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200238 struct weston_compositor *ec = text_input->ec;
239
240 text_input->cursor_rectangle.x1 = x;
241 text_input->cursor_rectangle.y1 = y;
242 text_input->cursor_rectangle.x2 = x + width;
243 text_input->cursor_rectangle.y2 = y + height;
244
245 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200246}
247
248static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200249text_input_set_content_type(struct wl_client *client,
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100250 struct wl_resource *resource,
251 uint32_t hint,
252 uint32_t purpose)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200253{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500254 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100255 struct input_method *input_method, *next;
256
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200257 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100258 if (!input_method->context)
259 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500260 wl_input_method_context_send_content_type(input_method->context->resource, hint, purpose);
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100261 }
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200262}
263
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100264static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200265text_input_invoke_action(struct wl_client *client,
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100266 struct wl_resource *resource,
267 uint32_t button,
268 uint32_t index)
269{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500270 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100271 struct input_method *input_method, *next;
272
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200273 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100274 if (!input_method->context)
275 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500276 wl_input_method_context_send_invoke_action(input_method->context->resource, button, index);
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100277 }
278}
279
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100280static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200281text_input_commit_state(struct wl_client *client,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200282 struct wl_resource *resource,
283 uint32_t serial)
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100284{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500285 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100286 struct input_method *input_method, *next;
287
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200288 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100289 if (!input_method->context)
290 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500291 wl_input_method_context_send_commit_state(input_method->context->resource, serial);
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100292 }
293}
294
Jan Arne Petersen61381972013-01-31 15:52:21 +0100295static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200296text_input_show_input_panel(struct wl_client *client,
Jan Arne Petersen61381972013-01-31 15:52:21 +0100297 struct wl_resource *resource)
298{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500299 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200300 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100301
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200302 text_input->input_panel_visible = 1;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100303
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200304 if (!wl_list_empty(&text_input->input_methods)) {
305 wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
306 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
307 }
Jan Arne Petersen61381972013-01-31 15:52:21 +0100308}
309
310static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200311text_input_hide_input_panel(struct wl_client *client,
Jan Arne Petersen61381972013-01-31 15:52:21 +0100312 struct wl_resource *resource)
313{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500314 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200315 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100316
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200317 text_input->input_panel_visible = 0;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100318
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200319 if (!wl_list_empty(&text_input->input_methods))
Jan Arne Petersen61381972013-01-31 15:52:21 +0100320 wl_signal_emit(&ec->hide_input_panel_signal, ec);
321}
322
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200323static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200324text_input_set_preferred_language(struct wl_client *client,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200325 struct wl_resource *resource,
326 const char *language)
327{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500328 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200329 struct input_method *input_method, *next;
330
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200331 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200332 if (!input_method->context)
333 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500334 wl_input_method_context_send_preferred_language(input_method->context->resource,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200335 language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200336 }
337}
338
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200339static const struct wl_text_input_interface text_input_implementation = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200340 text_input_activate,
341 text_input_deactivate,
342 text_input_show_input_panel,
343 text_input_hide_input_panel,
344 text_input_reset,
345 text_input_set_surrounding_text,
346 text_input_set_content_type,
347 text_input_set_cursor_rectangle,
348 text_input_set_preferred_language,
349 text_input_commit_state,
350 text_input_invoke_action
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200351};
352
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200353static void text_input_manager_create_text_input(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200354 struct wl_resource *resource,
Jan Arne Petersen4c265182012-09-09 23:08:30 +0200355 uint32_t id)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200356{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500357 struct text_input_manager *text_input_manager = wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200358 struct text_input *text_input;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200359
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200360 text_input = calloc(1, sizeof *text_input);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200361
Jason Ekstranda85118c2013-06-27 20:17:02 -0500362 text_input->resource =
363 wl_resource_create(client, &wl_text_input_interface, 1, id);
364 wl_resource_set_implementation(text_input->resource,
365 &text_input_implementation,
366 text_input, destroy_text_input);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200367
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200368 text_input->ec = text_input_manager->ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200369
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200370 wl_list_init(&text_input->input_methods);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200371};
372
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200373static const struct wl_text_input_manager_interface text_input_manager_implementation = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200374 text_input_manager_create_text_input
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200375};
376
377static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200378bind_text_input_manager(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200379 void *data,
380 uint32_t version,
381 uint32_t id)
382{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200383 struct text_input_manager *text_input_manager = data;
Jason Ekstranda85118c2013-06-27 20:17:02 -0500384 struct wl_resource *resource;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200385
Jason Ekstranda85118c2013-06-27 20:17:02 -0500386 /* No checking for duplicate binding necessary. */
387 resource =
388 wl_resource_create(client,
389 &wl_text_input_manager_interface, 1, id);
390 if (resource)
391 wl_resource_set_implementation(resource,
392 &text_input_manager_implementation,
393 text_input_manager, NULL);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200394}
395
396static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200397text_input_manager_notifier_destroy(struct wl_listener *listener, void *data)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200398{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200399 struct text_input_manager *text_input_manager =
400 container_of(listener, struct text_input_manager, destroy_listener);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200401
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400402 wl_global_destroy(text_input_manager->text_input_manager_global);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200403
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200404 free(text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200405}
406
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100407static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200408text_input_manager_create(struct weston_compositor *ec)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200409{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200410 struct text_input_manager *text_input_manager;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200411
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200412 text_input_manager = calloc(1, sizeof *text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200413
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200414 text_input_manager->ec = ec;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200415
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200416 text_input_manager->text_input_manager_global =
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400417 wl_global_create(ec->wl_display,
418 &wl_text_input_manager_interface, 1,
419 text_input_manager, bind_text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200420
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200421 text_input_manager->destroy_listener.notify = text_input_manager_notifier_destroy;
422 wl_signal_add(&ec->destroy_signal, &text_input_manager->destroy_listener);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200423}
424
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200425static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200426input_method_context_destroy(struct wl_client *client,
427 struct wl_resource *resource)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200428{
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200429 wl_resource_destroy(resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200430}
431
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200432static void
433input_method_context_commit_string(struct wl_client *client,
434 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100435 uint32_t serial,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100436 const char *text)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200437{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500438 struct input_method_context *context =
439 wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200440
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800441 if (context->model)
442 wl_text_input_send_commit_string(context->model->resource,
443 serial, text);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200444}
445
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200446static void
447input_method_context_preedit_string(struct wl_client *client,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100448 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100449 uint32_t serial,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100450 const char *text,
451 const char *commit)
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200452{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500453 struct input_method_context *context =
454 wl_resource_get_user_data(resource);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200455
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800456 if (context->model)
457 wl_text_input_send_preedit_string(context->model->resource,
458 serial, text, commit);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100459}
460
461static void
462input_method_context_preedit_styling(struct wl_client *client,
463 struct wl_resource *resource,
464 uint32_t index,
465 uint32_t length,
466 uint32_t style)
467{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500468 struct input_method_context *context =
469 wl_resource_get_user_data(resource);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100470
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800471 if (context->model)
472 wl_text_input_send_preedit_styling(context->model->resource,
473 index, length, style);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100474}
475
476static void
477input_method_context_preedit_cursor(struct wl_client *client,
478 struct wl_resource *resource,
479 int32_t cursor)
480{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500481 struct input_method_context *context =
482 wl_resource_get_user_data(resource);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100483
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800484 if (context->model)
485 wl_text_input_send_preedit_cursor(context->model->resource,
486 cursor);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200487}
488
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200489static void
490input_method_context_delete_surrounding_text(struct wl_client *client,
491 struct wl_resource *resource,
492 int32_t index,
493 uint32_t length)
494{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500495 struct input_method_context *context =
496 wl_resource_get_user_data(resource);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200497
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800498 if (context->model)
499 wl_text_input_send_delete_surrounding_text(context->model->resource,
500 index, length);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200501}
502
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200503static void
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100504input_method_context_cursor_position(struct wl_client *client,
505 struct wl_resource *resource,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100506 int32_t index,
507 int32_t anchor)
508{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500509 struct input_method_context *context =
510 wl_resource_get_user_data(resource);
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100511
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800512 if (context->model)
513 wl_text_input_send_cursor_position(context->model->resource,
514 index, anchor);
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100515}
516
517static void
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100518input_method_context_modifiers_map(struct wl_client *client,
519 struct wl_resource *resource,
520 struct wl_array *map)
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200521{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500522 struct input_method_context *context =
523 wl_resource_get_user_data(resource);
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200524
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800525 if (context->model)
526 wl_text_input_send_modifiers_map(context->model->resource, map);
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100527}
528
529static void
530input_method_context_keysym(struct wl_client *client,
531 struct wl_resource *resource,
532 uint32_t serial,
533 uint32_t time,
534 uint32_t sym,
535 uint32_t state,
536 uint32_t modifiers)
537{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500538 struct input_method_context *context =
539 wl_resource_get_user_data(resource);
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100540
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800541 if (context->model)
542 wl_text_input_send_keysym(context->model->resource,
543 serial, time, sym, state, modifiers);
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200544}
545
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100546static void
547unbind_keyboard(struct wl_resource *resource)
548{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500549 struct input_method_context *context =
550 wl_resource_get_user_data(resource);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100551
552 input_method_context_end_keyboard_grab(context);
553 context->keyboard = NULL;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100554}
555
556static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400557input_method_context_grab_key(struct weston_keyboard_grab *grab,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100558 uint32_t time, uint32_t key, uint32_t state_w)
559{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400560 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100561 struct wl_display *display;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100562 uint32_t serial;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100563
564 if (!keyboard->input_method_resource)
565 return;
566
Jason Ekstrand89d31992013-06-14 10:07:59 -0500567 display = wl_client_get_display(wl_resource_get_client(keyboard->input_method_resource));
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100568 serial = wl_display_next_serial(display);
569 wl_keyboard_send_key(keyboard->input_method_resource,
570 serial, time, key, state_w);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100571}
572
573static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400574input_method_context_grab_modifier(struct weston_keyboard_grab *grab, uint32_t serial,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100575 uint32_t mods_depressed, uint32_t mods_latched,
576 uint32_t mods_locked, uint32_t group)
577{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400578 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100579
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100580 if (!keyboard->input_method_resource)
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100581 return;
582
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100583 wl_keyboard_send_modifiers(keyboard->input_method_resource,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100584 serial, mods_depressed, mods_latched,
585 mods_locked, group);
586}
587
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200588static void
589input_method_context_grab_cancel(struct weston_keyboard_grab *grab)
590{
591 weston_keyboard_end_grab(grab->keyboard);
592}
593
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400594static const struct weston_keyboard_grab_interface input_method_context_grab = {
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100595 input_method_context_grab_key,
596 input_method_context_grab_modifier,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200597 input_method_context_grab_cancel,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100598};
599
600static void
601input_method_context_grab_keyboard(struct wl_client *client,
602 struct wl_resource *resource,
603 uint32_t id)
604{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500605 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100606 struct wl_resource *cr;
607 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400608 struct weston_keyboard *keyboard = seat->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100609
Jason Ekstranda85118c2013-06-27 20:17:02 -0500610 cr = wl_resource_create(client, &wl_keyboard_interface, 1, id);
611 wl_resource_set_implementation(cr, NULL, context, unbind_keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100612
613 context->keyboard = cr;
614
615 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
Jonas Ådahl7395ea02013-12-03 09:14:26 +0100616 keyboard->xkb_info->keymap_fd,
617 keyboard->xkb_info->keymap_size);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100618
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400619 if (keyboard->grab != &keyboard->default_grab) {
620 weston_keyboard_end_grab(keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100621 }
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400622 weston_keyboard_start_grab(keyboard, &keyboard->input_method_grab);
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100623 keyboard->input_method_resource = cr;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100624}
625
Jan Arne Petersen337df952012-11-18 19:06:46 +0100626static void
627input_method_context_key(struct wl_client *client,
628 struct wl_resource *resource,
629 uint32_t serial,
630 uint32_t time,
631 uint32_t key,
632 uint32_t state_w)
633{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500634 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen337df952012-11-18 19:06:46 +0100635 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400636 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400637 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100638
639 default_grab->interface->key(default_grab, time, key, state_w);
640}
641
642static void
643input_method_context_modifiers(struct wl_client *client,
644 struct wl_resource *resource,
645 uint32_t serial,
646 uint32_t mods_depressed,
647 uint32_t mods_latched,
648 uint32_t mods_locked,
649 uint32_t group)
650{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500651 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen337df952012-11-18 19:06:46 +0100652
653 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400654 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400655 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100656
657 default_grab->interface->modifiers(default_grab,
658 serial, mods_depressed,
659 mods_latched, mods_locked,
660 group);
661}
662
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200663static void
664input_method_context_language(struct wl_client *client,
665 struct wl_resource *resource,
666 uint32_t serial,
667 const char *language)
668{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500669 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200670
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800671 if (context->model)
672 wl_text_input_send_language(context->model->resource,
673 serial, language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200674}
675
676static void
677input_method_context_text_direction(struct wl_client *client,
678 struct wl_resource *resource,
679 uint32_t serial,
680 uint32_t direction)
681{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500682 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200683
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800684 if (context->model)
685 wl_text_input_send_text_direction(context->model->resource,
686 serial, direction);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200687}
688
689
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200690static const struct wl_input_method_context_interface input_method_context_implementation = {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200691 input_method_context_destroy,
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200692 input_method_context_commit_string,
693 input_method_context_preedit_string,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100694 input_method_context_preedit_styling,
695 input_method_context_preedit_cursor,
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200696 input_method_context_delete_surrounding_text,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100697 input_method_context_cursor_position,
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100698 input_method_context_modifiers_map,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100699 input_method_context_keysym,
Jan Arne Petersen337df952012-11-18 19:06:46 +0100700 input_method_context_grab_keyboard,
701 input_method_context_key,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200702 input_method_context_modifiers,
703 input_method_context_language,
704 input_method_context_text_direction
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200705};
706
707static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200708destroy_input_method_context(struct wl_resource *resource)
709{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500710 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200711
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100712 if (context->keyboard) {
713 wl_resource_destroy(context->keyboard);
714 }
715
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200716 free(context);
717}
718
719static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200720input_method_context_create(struct text_input *model,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200721 struct input_method *input_method)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200722{
723 struct input_method_context *context;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500724 struct wl_resource *binding;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200725
726 if (!input_method->input_method_binding)
727 return;
728
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100729 context = calloc(1, sizeof *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200730 if (context == NULL)
731 return;
732
Jason Ekstrand89d31992013-06-14 10:07:59 -0500733 binding = input_method->input_method_binding;
Jason Ekstranda85118c2013-06-27 20:17:02 -0500734 context->resource =
735 wl_resource_create(wl_resource_get_client(binding),
736 &wl_input_method_context_interface, 1, 0);
737 wl_resource_set_implementation(context->resource,
738 &input_method_context_implementation,
739 context, destroy_input_method_context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200740
741 context->model = model;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100742 context->input_method = input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200743 input_method->context = context;
744
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200745
Jason Ekstrand89d31992013-06-14 10:07:59 -0500746 wl_input_method_send_activate(binding, context->resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200747}
748
749static void
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100750input_method_context_end_keyboard_grab(struct input_method_context *context)
751{
Kristian Høgsberge3148752013-05-06 23:19:49 -0400752 struct weston_keyboard_grab *grab =
753 &context->input_method->seat->keyboard->input_method_grab;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400754 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100755
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100756 if (!grab->keyboard)
757 return;
758
759 if (grab->keyboard->grab == grab)
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400760 weston_keyboard_end_grab(grab->keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100761
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100762 keyboard->input_method_resource = NULL;
763}
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100764
765static void
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200766unbind_input_method(struct wl_resource *resource)
767{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500768 struct input_method *input_method = wl_resource_get_user_data(resource);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100769 struct text_backend *text_backend = input_method->text_backend;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200770
771 input_method->input_method_binding = NULL;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200772 input_method->context = NULL;
773
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100774 text_backend->input_method.binding = NULL;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200775}
776
777static void
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200778bind_input_method(struct wl_client *client,
779 void *data,
780 uint32_t version,
781 uint32_t id)
782{
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200783 struct input_method *input_method = data;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100784 struct text_backend *text_backend = input_method->text_backend;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200785 struct wl_resource *resource;
786
Jason Ekstranda85118c2013-06-27 20:17:02 -0500787 resource =
788 wl_resource_create(client, &wl_input_method_interface, 1, id);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200789
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200790 if (input_method->input_method_binding != NULL) {
791 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
792 "interface object already bound");
793 wl_resource_destroy(resource);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200794 return;
795 }
796
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200797 if (text_backend->input_method.client != client) {
798 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
Eduardo Lima (Etrunko)a2ce68f2013-05-10 17:50:36 -0300799 "permission to bind input_method denied");
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200800 wl_resource_destroy(resource);
801 return;
802 }
803
Jason Ekstranda85118c2013-06-27 20:17:02 -0500804 wl_resource_set_implementation(resource, NULL, input_method,
805 unbind_input_method);
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200806 input_method->input_method_binding = resource;
807
808 text_backend->input_method.binding = resource;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200809}
810
811static void
812input_method_notifier_destroy(struct wl_listener *listener, void *data)
813{
Kristian Høgsbergf97f3792012-07-22 11:51:42 -0400814 struct input_method *input_method =
815 container_of(listener, struct input_method, destroy_listener);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200816
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200817 if (input_method->model)
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200818 deactivate_text_input(input_method->model, input_method);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200819
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400820 wl_global_destroy(input_method->input_method_global);
Rob Bradfordead3ef82013-07-24 16:57:32 +0100821 wl_list_remove(&input_method->destroy_listener.link);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200822
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200823 free(input_method);
824}
825
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200826static void
827handle_keyboard_focus(struct wl_listener *listener, void *data)
828{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400829 struct weston_keyboard *keyboard = data;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200830 struct input_method *input_method =
831 container_of(listener, struct input_method, keyboard_focus_listener);
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400832 struct weston_surface *surface = keyboard->focus;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200833
834 if (!input_method->model)
835 return;
836
837 if (!surface || input_method->model->surface != surface)
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200838 deactivate_text_input(input_method->model,
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200839 input_method);
840}
841
842static void
843input_method_init_seat(struct weston_seat *seat)
844{
845 if (seat->input_method->focus_listener_initialized)
846 return;
847
Kristian Høgsberg2bf87622013-05-07 23:17:41 -0400848 if (seat->keyboard) {
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200849 seat->input_method->keyboard_focus_listener.notify = handle_keyboard_focus;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400850 wl_signal_add(&seat->keyboard->focus_signal, &seat->input_method->keyboard_focus_listener);
851 seat->keyboard->input_method_grab.interface = &input_method_context_grab;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200852 }
853
854 seat->input_method->focus_listener_initialized = 1;
855}
856
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300857static void launch_input_method(struct text_backend *text_backend);
858
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100859static void
860handle_input_method_sigchld(struct weston_process *process, int status)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200861{
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300862 uint32_t time;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100863 struct text_backend *text_backend =
864 container_of(process, struct text_backend, input_method.process);
865
866 text_backend->input_method.process.pid = 0;
867 text_backend->input_method.client = NULL;
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300868
869 /* if input_method dies more than 5 times in 10 seconds, give up */
870 time = weston_compositor_get_time();
871 if (time - text_backend->input_method.deathstamp > 10000) {
872 text_backend->input_method.deathstamp = time;
873 text_backend->input_method.deathcount = 0;
874 }
875
876 text_backend->input_method.deathcount++;
877 if (text_backend->input_method.deathcount > 5) {
878 weston_log("input_method died, giving up.\n");
879 return;
880 }
881
882 weston_log("input_method died, respawning...\n");
883 launch_input_method(text_backend);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100884}
885
886static void
887launch_input_method(struct text_backend *text_backend)
888{
889 if (text_backend->input_method.binding)
890 return;
891
892 if (!text_backend->input_method.path)
893 return;
894
895 if (text_backend->input_method.process.pid != 0)
896 return;
897
898 text_backend->input_method.client = weston_client_launch(text_backend->compositor,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200899 &text_backend->input_method.process,
900 text_backend->input_method.path,
901 handle_input_method_sigchld);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100902
903 if (!text_backend->input_method.client)
904 weston_log("not able to start %s\n", text_backend->input_method.path);
905}
906
907static void
908handle_seat_created(struct wl_listener *listener,
909 void *data)
910{
911 struct weston_seat *seat = data;
912 struct text_backend *text_backend =
913 container_of(listener, struct text_backend,
914 seat_created_listener);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200915 struct input_method *input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100916 struct weston_compositor *ec = seat->compositor;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200917
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200918 input_method = calloc(1, sizeof *input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200919
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200920 input_method->seat = seat;
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200921 input_method->model = NULL;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200922 input_method->focus_listener_initialized = 0;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200923 input_method->context = NULL;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100924 input_method->text_backend = text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200925
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200926 input_method->input_method_global =
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400927 wl_global_create(ec->wl_display, &wl_input_method_interface, 1,
928 input_method, bind_input_method);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200929
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200930 input_method->destroy_listener.notify = input_method_notifier_destroy;
Kristian Høgsberg49124542013-05-06 22:27:40 -0400931 wl_signal_add(&seat->destroy_signal, &input_method->destroy_listener);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200932
933 seat->input_method = input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100934
935 launch_input_method(text_backend);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200936}
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200937
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100938static void
939text_backend_configuration(struct text_backend *text_backend)
940{
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -0400941 struct weston_config_section *section;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100942
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -0400943 section = weston_config_get_section(text_backend->compositor->config,
944 "input-method", NULL, NULL);
945 weston_config_section_get_string(section, "path",
946 &text_backend->input_method.path,
947 LIBEXECDIR "/weston-keyboard");
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100948}
949
950static void
951text_backend_notifier_destroy(struct wl_listener *listener, void *data)
952{
953 struct text_backend *text_backend =
954 container_of(listener, struct text_backend, destroy_listener);
955
956 if (text_backend->input_method.client)
957 wl_client_destroy(text_backend->input_method.client);
958
959 free(text_backend->input_method.path);
960
961 free(text_backend);
962}
963
964
965WL_EXPORT int
966text_backend_init(struct weston_compositor *ec)
967{
968 struct text_backend *text_backend;
969
970 text_backend = calloc(1, sizeof(*text_backend));
971
972 text_backend->compositor = ec;
973
974 text_backend->seat_created_listener.notify = handle_seat_created;
975 wl_signal_add(&ec->seat_created_signal,
976 &text_backend->seat_created_listener);
977
978 text_backend->destroy_listener.notify = text_backend_notifier_destroy;
979 wl_signal_add(&ec->destroy_signal, &text_backend->destroy_listener);
980
981 text_backend_configuration(text_backend);
982
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200983 text_input_manager_create(ec);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100984
985 return 0;
986}