blob: 27afdff47ac23da622b3460ba63c00449c40c019 [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 {
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020040 struct wl_resource resource;
41
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 {
80 struct wl_resource resource;
81
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,
123 &input_method->context->resource);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100124 }
125
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200126 wl_list_remove(&input_method->link);
127 input_method->model = NULL;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200128 input_method->context = NULL;
Kristian Høgsbergf97f3792012-07-22 11:51:42 -0400129 wl_signal_emit(&ec->hide_input_panel_signal, ec);
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200130 wl_text_input_send_leave(&text_input->resource);
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200131 }
132}
133
134static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200135destroy_text_input(struct wl_resource *resource)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200136{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200137 struct text_input *text_input =
138 container_of(resource, struct text_input, 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{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200154 struct text_input *text_input = resource->data;
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;
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200160 wl_input_method_context_send_surrounding_text(&input_method->context->resource,
161 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{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200173 struct text_input *text_input = resource->data;
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200174 struct weston_seat *weston_seat = seat->data;
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 Ekstrand26ed73c2013-06-06 22:34:41 -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{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200208 struct text_input *text_input = resource->data;
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200209 struct weston_seat *weston_seat = seat->data;
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{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200219 struct text_input *text_input = resource->data;
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;
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200225 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{
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200237 struct text_input *text_input = resource->data;
238 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{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200254 struct text_input *text_input = resource->data;
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;
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200260 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{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200270 struct text_input *text_input = resource->data;
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;
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200276 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{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200285 struct text_input *text_input = resource->data;
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;
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200291 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{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200299 struct text_input *text_input = resource->data;
300 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{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200314 struct text_input *text_input = resource->data;
315 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{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200328 struct text_input *text_input = resource->data;
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;
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200334 wl_input_method_context_send_preferred_language(&input_method->context->resource,
335 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{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200357 struct text_input_manager *text_input_manager = resource->data;
358 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
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200362 text_input->resource.object.id = id;
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200363 text_input->resource.object.interface = &wl_text_input_interface;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200364 text_input->resource.object.implementation =
365 (void (**)(void)) &text_input_implementation;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200366
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200367 text_input->resource.data = text_input;
368 text_input->resource.destroy = 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);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200373
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200374 wl_client_add_resource(client, &text_input->resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200375};
376
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200377static const struct wl_text_input_manager_interface text_input_manager_implementation = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200378 text_input_manager_create_text_input
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200379};
380
381static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200382bind_text_input_manager(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200383 void *data,
384 uint32_t version,
385 uint32_t id)
386{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200387 struct text_input_manager *text_input_manager = data;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200388
389 /* No checking for duplicate binding necessary.
390 * No events have to be sent, so we don't need the return value. */
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200391 wl_client_add_object(client, &wl_text_input_manager_interface,
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200392 &text_input_manager_implementation,
393 id, text_input_manager);
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
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200402 wl_display_remove_global(text_input_manager->ec->wl_display,
403 text_input_manager->text_input_manager_global);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200404
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200405 free(text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200406}
407
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100408static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200409text_input_manager_create(struct weston_compositor *ec)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200410{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200411 struct text_input_manager *text_input_manager;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200412
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200413 text_input_manager = calloc(1, sizeof *text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200414
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200415 text_input_manager->ec = ec;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200416
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200417 text_input_manager->text_input_manager_global =
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200418 wl_display_add_global(ec->wl_display,
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200419 &wl_text_input_manager_interface,
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200420 text_input_manager, bind_text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200421
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200422 text_input_manager->destroy_listener.notify = text_input_manager_notifier_destroy;
423 wl_signal_add(&ec->destroy_signal, &text_input_manager->destroy_listener);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200424}
425
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200426static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200427input_method_context_destroy(struct wl_client *client,
428 struct wl_resource *resource)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200429{
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200430 wl_resource_destroy(resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200431}
432
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200433static void
434input_method_context_commit_string(struct wl_client *client,
435 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100436 uint32_t serial,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100437 const char *text)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200438{
439 struct input_method_context *context = resource->data;
440
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200441 wl_text_input_send_commit_string(&context->model->resource, serial, text);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200442}
443
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200444static void
445input_method_context_preedit_string(struct wl_client *client,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100446 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100447 uint32_t serial,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100448 const char *text,
449 const char *commit)
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200450{
451 struct input_method_context *context = resource->data;
452
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200453 wl_text_input_send_preedit_string(&context->model->resource, serial, text, commit);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100454}
455
456static void
457input_method_context_preedit_styling(struct wl_client *client,
458 struct wl_resource *resource,
459 uint32_t index,
460 uint32_t length,
461 uint32_t style)
462{
463 struct input_method_context *context = resource->data;
464
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200465 wl_text_input_send_preedit_styling(&context->model->resource, index, length, style);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100466}
467
468static void
469input_method_context_preedit_cursor(struct wl_client *client,
470 struct wl_resource *resource,
471 int32_t cursor)
472{
473 struct input_method_context *context = resource->data;
474
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200475 wl_text_input_send_preedit_cursor(&context->model->resource, cursor);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200476}
477
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200478static void
479input_method_context_delete_surrounding_text(struct wl_client *client,
480 struct wl_resource *resource,
481 int32_t index,
482 uint32_t length)
483{
484 struct input_method_context *context = resource->data;
485
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200486 wl_text_input_send_delete_surrounding_text(&context->model->resource, index, length);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200487}
488
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200489static void
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100490input_method_context_cursor_position(struct wl_client *client,
491 struct wl_resource *resource,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100492 int32_t index,
493 int32_t anchor)
494{
495 struct input_method_context *context = resource->data;
496
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200497 wl_text_input_send_cursor_position(&context->model->resource, index, anchor);
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100498}
499
500static void
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100501input_method_context_modifiers_map(struct wl_client *client,
502 struct wl_resource *resource,
503 struct wl_array *map)
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200504{
505 struct input_method_context *context = resource->data;
506
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200507 wl_text_input_send_modifiers_map(&context->model->resource, map);
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100508}
509
510static void
511input_method_context_keysym(struct wl_client *client,
512 struct wl_resource *resource,
513 uint32_t serial,
514 uint32_t time,
515 uint32_t sym,
516 uint32_t state,
517 uint32_t modifiers)
518{
519 struct input_method_context *context = resource->data;
520
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200521 wl_text_input_send_keysym(&context->model->resource, serial, time,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200522 sym, state, modifiers);
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200523}
524
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100525static void
526unbind_keyboard(struct wl_resource *resource)
527{
528 struct input_method_context *context = resource->data;
529
530 input_method_context_end_keyboard_grab(context);
531 context->keyboard = NULL;
532
533 free(resource);
534}
535
536static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400537input_method_context_grab_key(struct weston_keyboard_grab *grab,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100538 uint32_t time, uint32_t key, uint32_t state_w)
539{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400540 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100541 struct wl_display *display;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100542 uint32_t serial;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100543
544 if (!keyboard->input_method_resource)
545 return;
546
547 display = wl_client_get_display(keyboard->input_method_resource->client);
548 serial = wl_display_next_serial(display);
549 wl_keyboard_send_key(keyboard->input_method_resource,
550 serial, time, key, state_w);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100551}
552
553static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400554input_method_context_grab_modifier(struct weston_keyboard_grab *grab, uint32_t serial,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100555 uint32_t mods_depressed, uint32_t mods_latched,
556 uint32_t mods_locked, uint32_t group)
557{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400558 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100559
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100560 if (!keyboard->input_method_resource)
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100561 return;
562
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100563 wl_keyboard_send_modifiers(keyboard->input_method_resource,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100564 serial, mods_depressed, mods_latched,
565 mods_locked, group);
566}
567
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400568static const struct weston_keyboard_grab_interface input_method_context_grab = {
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100569 input_method_context_grab_key,
570 input_method_context_grab_modifier,
571};
572
573static void
574input_method_context_grab_keyboard(struct wl_client *client,
575 struct wl_resource *resource,
576 uint32_t id)
577{
578 struct input_method_context *context = resource->data;
579 struct wl_resource *cr;
580 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400581 struct weston_keyboard *keyboard = seat->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100582
583 cr = wl_client_add_object(client, &wl_keyboard_interface,
584 NULL, id, context);
585 cr->destroy = unbind_keyboard;
586
587 context->keyboard = cr;
588
589 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
590 seat->xkb_info.keymap_fd,
591 seat->xkb_info.keymap_size);
592
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400593 if (keyboard->grab != &keyboard->default_grab) {
594 weston_keyboard_end_grab(keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100595 }
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400596 weston_keyboard_start_grab(keyboard, &keyboard->input_method_grab);
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100597 keyboard->input_method_resource = cr;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100598}
599
Jan Arne Petersen337df952012-11-18 19:06:46 +0100600static void
601input_method_context_key(struct wl_client *client,
602 struct wl_resource *resource,
603 uint32_t serial,
604 uint32_t time,
605 uint32_t key,
606 uint32_t state_w)
607{
608 struct input_method_context *context = resource->data;
609 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400610 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400611 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100612
613 default_grab->interface->key(default_grab, time, key, state_w);
614}
615
616static void
617input_method_context_modifiers(struct wl_client *client,
618 struct wl_resource *resource,
619 uint32_t serial,
620 uint32_t mods_depressed,
621 uint32_t mods_latched,
622 uint32_t mods_locked,
623 uint32_t group)
624{
625 struct input_method_context *context = resource->data;
626
627 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400628 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400629 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100630
631 default_grab->interface->modifiers(default_grab,
632 serial, mods_depressed,
633 mods_latched, mods_locked,
634 group);
635}
636
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200637static void
638input_method_context_language(struct wl_client *client,
639 struct wl_resource *resource,
640 uint32_t serial,
641 const char *language)
642{
643 struct input_method_context *context = resource->data;
644
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200645 wl_text_input_send_language(&context->model->resource, serial, language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200646}
647
648static void
649input_method_context_text_direction(struct wl_client *client,
650 struct wl_resource *resource,
651 uint32_t serial,
652 uint32_t direction)
653{
654 struct input_method_context *context = resource->data;
655
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200656 wl_text_input_send_text_direction(&context->model->resource, serial, direction);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200657}
658
659
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200660static const struct wl_input_method_context_interface input_method_context_implementation = {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200661 input_method_context_destroy,
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200662 input_method_context_commit_string,
663 input_method_context_preedit_string,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100664 input_method_context_preedit_styling,
665 input_method_context_preedit_cursor,
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200666 input_method_context_delete_surrounding_text,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100667 input_method_context_cursor_position,
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100668 input_method_context_modifiers_map,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100669 input_method_context_keysym,
Jan Arne Petersen337df952012-11-18 19:06:46 +0100670 input_method_context_grab_keyboard,
671 input_method_context_key,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200672 input_method_context_modifiers,
673 input_method_context_language,
674 input_method_context_text_direction
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200675};
676
677static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200678destroy_input_method_context(struct wl_resource *resource)
679{
680 struct input_method_context *context = resource->data;
681
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100682 if (context->keyboard) {
683 wl_resource_destroy(context->keyboard);
684 }
685
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200686 free(context);
687}
688
689static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200690input_method_context_create(struct text_input *model,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200691 struct input_method *input_method)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200692{
693 struct input_method_context *context;
694
695 if (!input_method->input_method_binding)
696 return;
697
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100698 context = calloc(1, sizeof *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200699 if (context == NULL)
700 return;
701
702 context->resource.destroy = destroy_input_method_context;
703 context->resource.object.id = 0;
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200704 context->resource.object.interface = &wl_input_method_context_interface;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200705 context->resource.object.implementation =
706 (void (**)(void)) &input_method_context_implementation;
707 context->resource.data = context;
708 wl_signal_init(&context->resource.destroy_signal);
709
710 context->model = model;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100711 context->input_method = input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200712 input_method->context = context;
713
714 wl_client_add_resource(input_method->input_method_binding->client, &context->resource);
715
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200716 wl_input_method_send_activate(input_method->input_method_binding, &context->resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200717}
718
719static void
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100720input_method_context_end_keyboard_grab(struct input_method_context *context)
721{
Kristian Høgsberge3148752013-05-06 23:19:49 -0400722 struct weston_keyboard_grab *grab =
723 &context->input_method->seat->keyboard->input_method_grab;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400724 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100725
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100726 if (!grab->keyboard)
727 return;
728
729 if (grab->keyboard->grab == grab)
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400730 weston_keyboard_end_grab(grab->keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100731
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100732 keyboard->input_method_resource = NULL;
733}
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100734
735static void
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200736unbind_input_method(struct wl_resource *resource)
737{
738 struct input_method *input_method = resource->data;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100739 struct text_backend *text_backend = input_method->text_backend;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200740
741 input_method->input_method_binding = NULL;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200742 input_method->context = NULL;
743
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100744 text_backend->input_method.binding = NULL;
745
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200746 free(resource);
747}
748
749static void
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200750bind_input_method(struct wl_client *client,
751 void *data,
752 uint32_t version,
753 uint32_t id)
754{
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200755 struct input_method *input_method = data;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100756 struct text_backend *text_backend = input_method->text_backend;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200757 struct wl_resource *resource;
758
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200759 resource = wl_client_add_object(client, &wl_input_method_interface,
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200760 NULL,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200761 id, input_method);
762
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200763 if (input_method->input_method_binding != NULL) {
764 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
765 "interface object already bound");
766 wl_resource_destroy(resource);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200767 return;
768 }
769
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200770 if (text_backend->input_method.client != client) {
771 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
Eduardo Lima (Etrunko)a2ce68f2013-05-10 17:50:36 -0300772 "permission to bind input_method denied");
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200773 wl_resource_destroy(resource);
774 return;
775 }
776
777 resource->destroy = unbind_input_method;
778 input_method->input_method_binding = resource;
779
780 text_backend->input_method.binding = resource;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200781}
782
783static void
784input_method_notifier_destroy(struct wl_listener *listener, void *data)
785{
Kristian Høgsbergf97f3792012-07-22 11:51:42 -0400786 struct input_method *input_method =
787 container_of(listener, struct input_method, destroy_listener);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200788
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200789 if (input_method->model)
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200790 deactivate_text_input(input_method->model, input_method);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200791
792 wl_display_remove_global(input_method->seat->compositor->wl_display,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200793 input_method->input_method_global);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200794
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200795 free(input_method);
796}
797
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200798static void
799handle_keyboard_focus(struct wl_listener *listener, void *data)
800{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400801 struct weston_keyboard *keyboard = data;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200802 struct input_method *input_method =
803 container_of(listener, struct input_method, keyboard_focus_listener);
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400804 struct weston_surface *surface = keyboard->focus;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200805
806 if (!input_method->model)
807 return;
808
809 if (!surface || input_method->model->surface != surface)
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200810 deactivate_text_input(input_method->model,
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200811 input_method);
812}
813
814static void
815input_method_init_seat(struct weston_seat *seat)
816{
817 if (seat->input_method->focus_listener_initialized)
818 return;
819
Kristian Høgsberg2bf87622013-05-07 23:17:41 -0400820 if (seat->keyboard) {
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200821 seat->input_method->keyboard_focus_listener.notify = handle_keyboard_focus;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400822 wl_signal_add(&seat->keyboard->focus_signal, &seat->input_method->keyboard_focus_listener);
823 seat->keyboard->input_method_grab.interface = &input_method_context_grab;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200824 }
825
826 seat->input_method->focus_listener_initialized = 1;
827}
828
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300829static void launch_input_method(struct text_backend *text_backend);
830
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100831static void
832handle_input_method_sigchld(struct weston_process *process, int status)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200833{
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300834 uint32_t time;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100835 struct text_backend *text_backend =
836 container_of(process, struct text_backend, input_method.process);
837
838 text_backend->input_method.process.pid = 0;
839 text_backend->input_method.client = NULL;
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300840
841 /* if input_method dies more than 5 times in 10 seconds, give up */
842 time = weston_compositor_get_time();
843 if (time - text_backend->input_method.deathstamp > 10000) {
844 text_backend->input_method.deathstamp = time;
845 text_backend->input_method.deathcount = 0;
846 }
847
848 text_backend->input_method.deathcount++;
849 if (text_backend->input_method.deathcount > 5) {
850 weston_log("input_method died, giving up.\n");
851 return;
852 }
853
854 weston_log("input_method died, respawning...\n");
855 launch_input_method(text_backend);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100856}
857
858static void
859launch_input_method(struct text_backend *text_backend)
860{
861 if (text_backend->input_method.binding)
862 return;
863
864 if (!text_backend->input_method.path)
865 return;
866
867 if (text_backend->input_method.process.pid != 0)
868 return;
869
870 text_backend->input_method.client = weston_client_launch(text_backend->compositor,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200871 &text_backend->input_method.process,
872 text_backend->input_method.path,
873 handle_input_method_sigchld);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100874
875 if (!text_backend->input_method.client)
876 weston_log("not able to start %s\n", text_backend->input_method.path);
877}
878
879static void
880handle_seat_created(struct wl_listener *listener,
881 void *data)
882{
883 struct weston_seat *seat = data;
884 struct text_backend *text_backend =
885 container_of(listener, struct text_backend,
886 seat_created_listener);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200887 struct input_method *input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100888 struct weston_compositor *ec = seat->compositor;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200889
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200890 input_method = calloc(1, sizeof *input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200891
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200892 input_method->seat = seat;
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200893 input_method->model = NULL;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200894 input_method->focus_listener_initialized = 0;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200895 input_method->context = NULL;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100896 input_method->text_backend = text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200897
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200898 input_method->input_method_global =
899 wl_display_add_global(ec->wl_display,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200900 &wl_input_method_interface,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200901 input_method, bind_input_method);
902
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200903 input_method->destroy_listener.notify = input_method_notifier_destroy;
Kristian Høgsberg49124542013-05-06 22:27:40 -0400904 wl_signal_add(&seat->destroy_signal, &input_method->destroy_listener);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200905
906 seat->input_method = input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100907
908 launch_input_method(text_backend);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200909}
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200910
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100911static void
912text_backend_configuration(struct text_backend *text_backend)
913{
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -0400914 struct weston_config_section *section;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100915
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -0400916 section = weston_config_get_section(text_backend->compositor->config,
917 "input-method", NULL, NULL);
918 weston_config_section_get_string(section, "path",
919 &text_backend->input_method.path,
920 LIBEXECDIR "/weston-keyboard");
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100921}
922
923static void
924text_backend_notifier_destroy(struct wl_listener *listener, void *data)
925{
926 struct text_backend *text_backend =
927 container_of(listener, struct text_backend, destroy_listener);
928
929 if (text_backend->input_method.client)
930 wl_client_destroy(text_backend->input_method.client);
931
932 free(text_backend->input_method.path);
933
934 free(text_backend);
935}
936
937
938WL_EXPORT int
939text_backend_init(struct weston_compositor *ec)
940{
941 struct text_backend *text_backend;
942
943 text_backend = calloc(1, sizeof(*text_backend));
944
945 text_backend->compositor = ec;
946
947 text_backend->seat_created_listener.notify = handle_seat_created;
948 wl_signal_add(&ec->seat_created_signal,
949 &text_backend->seat_created_listener);
950
951 text_backend->destroy_listener.notify = text_backend_notifier_destroy;
952 wl_signal_add(&ec->destroy_signal, &text_backend->destroy_listener);
953
954 text_backend_configuration(text_backend);
955
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200956 text_input_manager_create(ec);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100957
958 return 0;
959}