blob: 6246b307571a38d6c22c37e5ec64f24a57a93b79 [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
Bryce Harringtonde16d892014-11-20 22:21:57 -0800360 text_input = zalloc(sizeof *text_input);
361 if (text_input == NULL)
362 return;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200363
Jason Ekstranda85118c2013-06-27 20:17:02 -0500364 text_input->resource =
365 wl_resource_create(client, &wl_text_input_interface, 1, id);
366 wl_resource_set_implementation(text_input->resource,
367 &text_input_implementation,
368 text_input, destroy_text_input);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200369
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200370 text_input->ec = text_input_manager->ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200371
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200372 wl_list_init(&text_input->input_methods);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200373};
374
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200375static const struct wl_text_input_manager_interface text_input_manager_implementation = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200376 text_input_manager_create_text_input
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200377};
378
379static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200380bind_text_input_manager(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200381 void *data,
382 uint32_t version,
383 uint32_t id)
384{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200385 struct text_input_manager *text_input_manager = data;
Jason Ekstranda85118c2013-06-27 20:17:02 -0500386 struct wl_resource *resource;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200387
Jason Ekstranda85118c2013-06-27 20:17:02 -0500388 /* No checking for duplicate binding necessary. */
389 resource =
390 wl_resource_create(client,
391 &wl_text_input_manager_interface, 1, id);
392 if (resource)
393 wl_resource_set_implementation(resource,
394 &text_input_manager_implementation,
395 text_input_manager, NULL);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200396}
397
398static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200399text_input_manager_notifier_destroy(struct wl_listener *listener, void *data)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200400{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200401 struct text_input_manager *text_input_manager =
402 container_of(listener, struct text_input_manager, destroy_listener);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200403
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400404 wl_global_destroy(text_input_manager->text_input_manager_global);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200405
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200406 free(text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200407}
408
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100409static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200410text_input_manager_create(struct weston_compositor *ec)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200411{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200412 struct text_input_manager *text_input_manager;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200413
Bryce Harringtonde16d892014-11-20 22:21:57 -0800414 text_input_manager = zalloc(sizeof *text_input_manager);
415 if (text_input_manager == NULL)
416 return;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200417
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200418 text_input_manager->ec = ec;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200419
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200420 text_input_manager->text_input_manager_global =
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400421 wl_global_create(ec->wl_display,
422 &wl_text_input_manager_interface, 1,
423 text_input_manager, bind_text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200424
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200425 text_input_manager->destroy_listener.notify = text_input_manager_notifier_destroy;
426 wl_signal_add(&ec->destroy_signal, &text_input_manager->destroy_listener);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200427}
428
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200429static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200430input_method_context_destroy(struct wl_client *client,
431 struct wl_resource *resource)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200432{
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200433 wl_resource_destroy(resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200434}
435
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200436static void
437input_method_context_commit_string(struct wl_client *client,
438 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100439 uint32_t serial,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100440 const char *text)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200441{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500442 struct input_method_context *context =
443 wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200444
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800445 if (context->model)
446 wl_text_input_send_commit_string(context->model->resource,
447 serial, text);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200448}
449
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200450static void
451input_method_context_preedit_string(struct wl_client *client,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100452 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100453 uint32_t serial,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100454 const char *text,
455 const char *commit)
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200456{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500457 struct input_method_context *context =
458 wl_resource_get_user_data(resource);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200459
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800460 if (context->model)
461 wl_text_input_send_preedit_string(context->model->resource,
462 serial, text, commit);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100463}
464
465static void
466input_method_context_preedit_styling(struct wl_client *client,
467 struct wl_resource *resource,
468 uint32_t index,
469 uint32_t length,
470 uint32_t style)
471{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500472 struct input_method_context *context =
473 wl_resource_get_user_data(resource);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100474
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800475 if (context->model)
476 wl_text_input_send_preedit_styling(context->model->resource,
477 index, length, style);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100478}
479
480static void
481input_method_context_preedit_cursor(struct wl_client *client,
482 struct wl_resource *resource,
483 int32_t cursor)
484{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500485 struct input_method_context *context =
486 wl_resource_get_user_data(resource);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100487
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800488 if (context->model)
489 wl_text_input_send_preedit_cursor(context->model->resource,
490 cursor);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200491}
492
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200493static void
494input_method_context_delete_surrounding_text(struct wl_client *client,
495 struct wl_resource *resource,
496 int32_t index,
497 uint32_t length)
498{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500499 struct input_method_context *context =
500 wl_resource_get_user_data(resource);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200501
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800502 if (context->model)
503 wl_text_input_send_delete_surrounding_text(context->model->resource,
504 index, length);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200505}
506
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200507static void
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100508input_method_context_cursor_position(struct wl_client *client,
509 struct wl_resource *resource,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100510 int32_t index,
511 int32_t anchor)
512{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500513 struct input_method_context *context =
514 wl_resource_get_user_data(resource);
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100515
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800516 if (context->model)
517 wl_text_input_send_cursor_position(context->model->resource,
518 index, anchor);
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100519}
520
521static void
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100522input_method_context_modifiers_map(struct wl_client *client,
523 struct wl_resource *resource,
524 struct wl_array *map)
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200525{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500526 struct input_method_context *context =
527 wl_resource_get_user_data(resource);
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200528
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800529 if (context->model)
530 wl_text_input_send_modifiers_map(context->model->resource, map);
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100531}
532
533static void
534input_method_context_keysym(struct wl_client *client,
535 struct wl_resource *resource,
536 uint32_t serial,
537 uint32_t time,
538 uint32_t sym,
539 uint32_t state,
540 uint32_t modifiers)
541{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500542 struct input_method_context *context =
543 wl_resource_get_user_data(resource);
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100544
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800545 if (context->model)
546 wl_text_input_send_keysym(context->model->resource,
547 serial, time, sym, state, modifiers);
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200548}
549
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100550static void
551unbind_keyboard(struct wl_resource *resource)
552{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500553 struct input_method_context *context =
554 wl_resource_get_user_data(resource);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100555
556 input_method_context_end_keyboard_grab(context);
557 context->keyboard = NULL;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100558}
559
560static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400561input_method_context_grab_key(struct weston_keyboard_grab *grab,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100562 uint32_t time, uint32_t key, uint32_t state_w)
563{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400564 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100565 struct wl_display *display;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100566 uint32_t serial;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100567
568 if (!keyboard->input_method_resource)
569 return;
570
Jason Ekstrand89d31992013-06-14 10:07:59 -0500571 display = wl_client_get_display(wl_resource_get_client(keyboard->input_method_resource));
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100572 serial = wl_display_next_serial(display);
573 wl_keyboard_send_key(keyboard->input_method_resource,
574 serial, time, key, state_w);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100575}
576
577static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400578input_method_context_grab_modifier(struct weston_keyboard_grab *grab, uint32_t serial,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100579 uint32_t mods_depressed, uint32_t mods_latched,
580 uint32_t mods_locked, uint32_t group)
581{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400582 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100583
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100584 if (!keyboard->input_method_resource)
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100585 return;
586
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100587 wl_keyboard_send_modifiers(keyboard->input_method_resource,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100588 serial, mods_depressed, mods_latched,
589 mods_locked, group);
590}
591
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200592static void
593input_method_context_grab_cancel(struct weston_keyboard_grab *grab)
594{
595 weston_keyboard_end_grab(grab->keyboard);
596}
597
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400598static const struct weston_keyboard_grab_interface input_method_context_grab = {
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100599 input_method_context_grab_key,
600 input_method_context_grab_modifier,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200601 input_method_context_grab_cancel,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100602};
603
604static void
605input_method_context_grab_keyboard(struct wl_client *client,
606 struct wl_resource *resource,
607 uint32_t id)
608{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500609 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100610 struct wl_resource *cr;
611 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400612 struct weston_keyboard *keyboard = seat->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100613
Jason Ekstranda85118c2013-06-27 20:17:02 -0500614 cr = wl_resource_create(client, &wl_keyboard_interface, 1, id);
615 wl_resource_set_implementation(cr, NULL, context, unbind_keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100616
617 context->keyboard = cr;
618
619 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
Jonas Ådahl7395ea02013-12-03 09:14:26 +0100620 keyboard->xkb_info->keymap_fd,
621 keyboard->xkb_info->keymap_size);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100622
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400623 if (keyboard->grab != &keyboard->default_grab) {
624 weston_keyboard_end_grab(keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100625 }
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400626 weston_keyboard_start_grab(keyboard, &keyboard->input_method_grab);
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100627 keyboard->input_method_resource = cr;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100628}
629
Jan Arne Petersen337df952012-11-18 19:06:46 +0100630static void
631input_method_context_key(struct wl_client *client,
632 struct wl_resource *resource,
633 uint32_t serial,
634 uint32_t time,
635 uint32_t key,
636 uint32_t state_w)
637{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500638 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen337df952012-11-18 19:06:46 +0100639 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400640 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400641 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100642
643 default_grab->interface->key(default_grab, time, key, state_w);
644}
645
646static void
647input_method_context_modifiers(struct wl_client *client,
648 struct wl_resource *resource,
649 uint32_t serial,
650 uint32_t mods_depressed,
651 uint32_t mods_latched,
652 uint32_t mods_locked,
653 uint32_t group)
654{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500655 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen337df952012-11-18 19:06:46 +0100656
657 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400658 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400659 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100660
661 default_grab->interface->modifiers(default_grab,
662 serial, mods_depressed,
663 mods_latched, mods_locked,
664 group);
665}
666
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200667static void
668input_method_context_language(struct wl_client *client,
669 struct wl_resource *resource,
670 uint32_t serial,
671 const char *language)
672{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500673 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200674
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800675 if (context->model)
676 wl_text_input_send_language(context->model->resource,
677 serial, language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200678}
679
680static void
681input_method_context_text_direction(struct wl_client *client,
682 struct wl_resource *resource,
683 uint32_t serial,
684 uint32_t direction)
685{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500686 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200687
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800688 if (context->model)
689 wl_text_input_send_text_direction(context->model->resource,
690 serial, direction);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200691}
692
693
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200694static const struct wl_input_method_context_interface input_method_context_implementation = {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200695 input_method_context_destroy,
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200696 input_method_context_commit_string,
697 input_method_context_preedit_string,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100698 input_method_context_preedit_styling,
699 input_method_context_preedit_cursor,
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200700 input_method_context_delete_surrounding_text,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100701 input_method_context_cursor_position,
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100702 input_method_context_modifiers_map,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100703 input_method_context_keysym,
Jan Arne Petersen337df952012-11-18 19:06:46 +0100704 input_method_context_grab_keyboard,
705 input_method_context_key,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200706 input_method_context_modifiers,
707 input_method_context_language,
708 input_method_context_text_direction
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200709};
710
711static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200712destroy_input_method_context(struct wl_resource *resource)
713{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500714 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200715
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100716 if (context->keyboard) {
717 wl_resource_destroy(context->keyboard);
718 }
719
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200720 free(context);
721}
722
723static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200724input_method_context_create(struct text_input *model,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200725 struct input_method *input_method)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200726{
727 struct input_method_context *context;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500728 struct wl_resource *binding;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200729
730 if (!input_method->input_method_binding)
731 return;
732
Bryce Harringtonde16d892014-11-20 22:21:57 -0800733 context = zalloc(sizeof *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200734 if (context == NULL)
735 return;
736
Jason Ekstrand89d31992013-06-14 10:07:59 -0500737 binding = input_method->input_method_binding;
Jason Ekstranda85118c2013-06-27 20:17:02 -0500738 context->resource =
739 wl_resource_create(wl_resource_get_client(binding),
740 &wl_input_method_context_interface, 1, 0);
741 wl_resource_set_implementation(context->resource,
742 &input_method_context_implementation,
743 context, destroy_input_method_context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200744
745 context->model = model;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100746 context->input_method = input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200747 input_method->context = context;
748
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200749
Jason Ekstrand89d31992013-06-14 10:07:59 -0500750 wl_input_method_send_activate(binding, context->resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200751}
752
753static void
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100754input_method_context_end_keyboard_grab(struct input_method_context *context)
755{
Kristian Høgsberge3148752013-05-06 23:19:49 -0400756 struct weston_keyboard_grab *grab =
757 &context->input_method->seat->keyboard->input_method_grab;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400758 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100759
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100760 if (!grab->keyboard)
761 return;
762
763 if (grab->keyboard->grab == grab)
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400764 weston_keyboard_end_grab(grab->keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100765
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100766 keyboard->input_method_resource = NULL;
767}
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100768
769static void
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200770unbind_input_method(struct wl_resource *resource)
771{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500772 struct input_method *input_method = wl_resource_get_user_data(resource);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100773 struct text_backend *text_backend = input_method->text_backend;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200774
775 input_method->input_method_binding = NULL;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200776 input_method->context = NULL;
777
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100778 text_backend->input_method.binding = NULL;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200779}
780
781static void
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200782bind_input_method(struct wl_client *client,
783 void *data,
784 uint32_t version,
785 uint32_t id)
786{
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200787 struct input_method *input_method = data;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100788 struct text_backend *text_backend = input_method->text_backend;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200789 struct wl_resource *resource;
790
Jason Ekstranda85118c2013-06-27 20:17:02 -0500791 resource =
792 wl_resource_create(client, &wl_input_method_interface, 1, id);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200793
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200794 if (input_method->input_method_binding != NULL) {
795 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
796 "interface object already bound");
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200797 return;
798 }
799
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200800 if (text_backend->input_method.client != client) {
801 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
Eduardo Lima (Etrunko)a2ce68f2013-05-10 17:50:36 -0300802 "permission to bind input_method denied");
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200803 return;
804 }
805
Jason Ekstranda85118c2013-06-27 20:17:02 -0500806 wl_resource_set_implementation(resource, NULL, input_method,
807 unbind_input_method);
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200808 input_method->input_method_binding = resource;
809
810 text_backend->input_method.binding = resource;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200811}
812
813static void
814input_method_notifier_destroy(struct wl_listener *listener, void *data)
815{
Kristian Høgsbergf97f3792012-07-22 11:51:42 -0400816 struct input_method *input_method =
817 container_of(listener, struct input_method, destroy_listener);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200818
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200819 if (input_method->model)
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200820 deactivate_text_input(input_method->model, input_method);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200821
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400822 wl_global_destroy(input_method->input_method_global);
Rob Bradfordead3ef82013-07-24 16:57:32 +0100823 wl_list_remove(&input_method->destroy_listener.link);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200824
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200825 free(input_method);
826}
827
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200828static void
829handle_keyboard_focus(struct wl_listener *listener, void *data)
830{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400831 struct weston_keyboard *keyboard = data;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200832 struct input_method *input_method =
833 container_of(listener, struct input_method, keyboard_focus_listener);
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400834 struct weston_surface *surface = keyboard->focus;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200835
836 if (!input_method->model)
837 return;
838
839 if (!surface || input_method->model->surface != surface)
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200840 deactivate_text_input(input_method->model,
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200841 input_method);
842}
843
844static void
845input_method_init_seat(struct weston_seat *seat)
846{
847 if (seat->input_method->focus_listener_initialized)
848 return;
849
Kristian Høgsberg2bf87622013-05-07 23:17:41 -0400850 if (seat->keyboard) {
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200851 seat->input_method->keyboard_focus_listener.notify = handle_keyboard_focus;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400852 wl_signal_add(&seat->keyboard->focus_signal, &seat->input_method->keyboard_focus_listener);
853 seat->keyboard->input_method_grab.interface = &input_method_context_grab;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200854 }
855
856 seat->input_method->focus_listener_initialized = 1;
857}
858
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300859static void launch_input_method(struct text_backend *text_backend);
860
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100861static void
862handle_input_method_sigchld(struct weston_process *process, int status)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200863{
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300864 uint32_t time;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100865 struct text_backend *text_backend =
866 container_of(process, struct text_backend, input_method.process);
867
868 text_backend->input_method.process.pid = 0;
869 text_backend->input_method.client = NULL;
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300870
871 /* if input_method dies more than 5 times in 10 seconds, give up */
872 time = weston_compositor_get_time();
873 if (time - text_backend->input_method.deathstamp > 10000) {
874 text_backend->input_method.deathstamp = time;
875 text_backend->input_method.deathcount = 0;
876 }
877
878 text_backend->input_method.deathcount++;
879 if (text_backend->input_method.deathcount > 5) {
880 weston_log("input_method died, giving up.\n");
881 return;
882 }
883
884 weston_log("input_method died, respawning...\n");
885 launch_input_method(text_backend);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100886}
887
888static void
889launch_input_method(struct text_backend *text_backend)
890{
891 if (text_backend->input_method.binding)
892 return;
893
894 if (!text_backend->input_method.path)
895 return;
896
897 if (text_backend->input_method.process.pid != 0)
898 return;
899
900 text_backend->input_method.client = weston_client_launch(text_backend->compositor,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200901 &text_backend->input_method.process,
902 text_backend->input_method.path,
903 handle_input_method_sigchld);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100904
905 if (!text_backend->input_method.client)
906 weston_log("not able to start %s\n", text_backend->input_method.path);
907}
908
909static void
910handle_seat_created(struct wl_listener *listener,
911 void *data)
912{
913 struct weston_seat *seat = data;
914 struct text_backend *text_backend =
915 container_of(listener, struct text_backend,
916 seat_created_listener);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200917 struct input_method *input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100918 struct weston_compositor *ec = seat->compositor;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200919
Bryce Harringtonde16d892014-11-20 22:21:57 -0800920 input_method = zalloc(sizeof *input_method);
921 if (input_method == NULL)
922 return;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200923
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200924 input_method->seat = seat;
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200925 input_method->model = NULL;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200926 input_method->focus_listener_initialized = 0;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200927 input_method->context = NULL;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100928 input_method->text_backend = text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200929
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200930 input_method->input_method_global =
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400931 wl_global_create(ec->wl_display, &wl_input_method_interface, 1,
932 input_method, bind_input_method);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200933
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200934 input_method->destroy_listener.notify = input_method_notifier_destroy;
Kristian Høgsberg49124542013-05-06 22:27:40 -0400935 wl_signal_add(&seat->destroy_signal, &input_method->destroy_listener);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200936
937 seat->input_method = input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100938
939 launch_input_method(text_backend);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200940}
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200941
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100942static void
943text_backend_configuration(struct text_backend *text_backend)
944{
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -0400945 struct weston_config_section *section;
Derek Foremanc7210432014-08-21 11:32:38 -0500946 char *client;
Pekka Paalanen974c0942014-09-05 14:45:09 +0300947 int ret;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100948
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -0400949 section = weston_config_get_section(text_backend->compositor->config,
950 "input-method", NULL, NULL);
Pekka Paalanen974c0942014-09-05 14:45:09 +0300951 ret = asprintf(&client, "%s/weston-keyboard",
952 weston_config_get_libexec_dir());
953 if (ret < 0)
954 client = NULL;
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -0400955 weston_config_section_get_string(section, "path",
956 &text_backend->input_method.path,
Derek Foremanc7210432014-08-21 11:32:38 -0500957 client);
958 free(client);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100959}
960
961static void
962text_backend_notifier_destroy(struct wl_listener *listener, void *data)
963{
964 struct text_backend *text_backend =
965 container_of(listener, struct text_backend, destroy_listener);
966
967 if (text_backend->input_method.client)
968 wl_client_destroy(text_backend->input_method.client);
969
970 free(text_backend->input_method.path);
971
972 free(text_backend);
973}
974
975
976WL_EXPORT int
977text_backend_init(struct weston_compositor *ec)
978{
979 struct text_backend *text_backend;
980
Bryce Harringtonde16d892014-11-20 22:21:57 -0800981 text_backend = zalloc(sizeof(*text_backend));
982 if (text_backend == NULL)
983 return -1;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100984
985 text_backend->compositor = ec;
986
987 text_backend->seat_created_listener.notify = handle_seat_created;
988 wl_signal_add(&ec->seat_created_signal,
989 &text_backend->seat_created_listener);
990
991 text_backend->destroy_listener.notify = text_backend_notifier_destroy;
992 wl_signal_add(&ec->destroy_signal, &text_backend->destroy_listener);
993
994 text_backend_configuration(text_backend);
995
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200996 text_input_manager_create(ec);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100997
998 return 0;
999}