blob: 3d1670b59493f90b48ada3ae4cc445d5b743b03e [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
24#include <stdlib.h>
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010025#include <string.h>
Ossama Othmana50e6e42013-05-14 09:48:26 -070026#include <unistd.h>
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -030027#include <time.h>
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020028
29#include "compositor.h"
30#include "text-server-protocol.h"
Jan Arne Petersen30b66ef2012-09-09 23:08:41 +020031#include "input-method-server-protocol.h"
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020032
33struct input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020034struct input_method_context;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010035struct text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020036
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020037struct text_input {
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020038 struct wl_resource resource;
39
Jan Arne Petersene829adc2012-08-10 16:47:22 +020040 struct weston_compositor *ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020041
Jan Arne Petersene829adc2012-08-10 16:47:22 +020042 struct wl_list input_methods;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +020043
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -040044 struct weston_surface *surface;
Jan Arne Petersen61381972013-01-31 15:52:21 +010045
Jan Arne Petersen14da96b2013-04-18 16:47:28 +020046 pixman_box32_t cursor_rectangle;
47
Jan Arne Petersen61381972013-01-31 15:52:21 +010048 uint32_t input_panel_visible;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020049};
50
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020051struct text_input_manager {
52 struct wl_global *text_input_manager_global;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020053 struct wl_listener destroy_listener;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020054
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +020055 struct weston_compositor *ec;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +020056};
57
58struct input_method {
59 struct wl_resource *input_method_binding;
60 struct wl_global *input_method_global;
61 struct wl_listener destroy_listener;
62
63 struct weston_seat *seat;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020064 struct text_input *model;
Jan Arne Petersene829adc2012-08-10 16:47:22 +020065
66 struct wl_list link;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +020067
68 struct wl_listener keyboard_focus_listener;
69
70 int focus_listener_initialized;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020071
72 struct input_method_context *context;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010073
74 struct text_backend *text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020075};
76
Jan Arne Petersen620cd622012-09-09 23:08:32 +020077struct input_method_context {
78 struct wl_resource resource;
79
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020080 struct text_input *model;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +010081 struct input_method *input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020082
83 struct wl_list link;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +010084
85 struct wl_resource *keyboard;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020086};
87
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010088struct text_backend {
89 struct weston_compositor *compositor;
90
91 struct {
92 char *path;
93 struct wl_resource *binding;
94 struct weston_process process;
95 struct wl_client *client;
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -030096
97 unsigned deathcount;
98 uint32_t deathstamp;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010099 } input_method;
100
101 struct wl_listener seat_created_listener;
102 struct wl_listener destroy_listener;
103};
104
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200105static void input_method_context_create(struct text_input *model,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200106 struct input_method *input_method);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100107static void input_method_context_end_keyboard_grab(struct input_method_context *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200108
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200109static void input_method_init_seat(struct weston_seat *seat);
110
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200111static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200112deactivate_text_input(struct text_input *text_input,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200113 struct input_method *input_method)
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200114{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200115 struct weston_compositor *ec = text_input->ec;
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200116
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200117 if (input_method->model == text_input) {
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100118 if (input_method->context && input_method->input_method_binding) {
119 input_method_context_end_keyboard_grab(input_method->context);
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200120 wl_input_method_send_deactivate(input_method->input_method_binding,
121 &input_method->context->resource);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100122 }
123
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200124 wl_list_remove(&input_method->link);
125 input_method->model = NULL;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200126 input_method->context = NULL;
Kristian Høgsbergf97f3792012-07-22 11:51:42 -0400127 wl_signal_emit(&ec->hide_input_panel_signal, ec);
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200128 wl_text_input_send_leave(&text_input->resource);
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200129 }
130}
131
132static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200133destroy_text_input(struct wl_resource *resource)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200134{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200135 struct text_input *text_input =
136 container_of(resource, struct text_input, resource);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200137 struct input_method *input_method, *next;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200138
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200139 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link)
140 deactivate_text_input(text_input, input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200141
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200142 free(text_input);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200143}
144
145static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200146text_input_set_surrounding_text(struct wl_client *client,
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200147 struct wl_resource *resource,
Jan Arne Petersencb08f4d2012-09-09 23:08:40 +0200148 const char *text,
149 uint32_t cursor,
150 uint32_t anchor)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200151{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200152 struct text_input *text_input = resource->data;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200153 struct input_method *input_method, *next;
154
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200155 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200156 if (!input_method->context)
157 continue;
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200158 wl_input_method_context_send_surrounding_text(&input_method->context->resource,
159 text,
160 cursor,
161 anchor);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200162 }
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200163}
164
165static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200166text_input_activate(struct wl_client *client,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200167 struct wl_resource *resource,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200168 struct wl_resource *seat,
169 struct wl_resource *surface)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200170{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200171 struct text_input *text_input = resource->data;
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200172 struct weston_seat *weston_seat = seat->data;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200173 struct input_method *input_method = weston_seat->input_method;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200174 struct text_input *old = weston_seat->input_method->model;
175 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200176
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200177 if (old == text_input)
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200178 return;
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200179
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200180 if (old) {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200181 deactivate_text_input(old,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200182 weston_seat->input_method);
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200183 }
184
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200185 input_method->model = text_input;
186 wl_list_insert(&text_input->input_methods, &input_method->link);
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200187 input_method_init_seat(weston_seat);
188
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200189 text_input->surface = surface->data;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200190
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200191 input_method_context_create(text_input, input_method);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200192
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200193 if (text_input->input_panel_visible) {
194 wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
195 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
196 }
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200197
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200198 wl_text_input_send_enter(&text_input->resource, &text_input->surface->resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200199}
200
201static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200202text_input_deactivate(struct wl_client *client,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200203 struct wl_resource *resource,
204 struct wl_resource *seat)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200205{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200206 struct text_input *text_input = resource->data;
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200207 struct weston_seat *weston_seat = seat->data;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200208
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200209 deactivate_text_input(text_input,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200210 weston_seat->input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200211}
212
213static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200214text_input_reset(struct wl_client *client,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200215 struct wl_resource *resource)
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200216{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200217 struct text_input *text_input = resource->data;
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200218 struct input_method *input_method, *next;
219
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200220 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200221 if (!input_method->context)
222 continue;
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200223 wl_input_method_context_send_reset(&input_method->context->resource);
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200224 }
225}
226
227static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200228text_input_set_cursor_rectangle(struct wl_client *client,
Jan Arne Petersen7ef8eff2013-04-18 16:47:23 +0200229 struct wl_resource *resource,
230 int32_t x,
231 int32_t y,
232 int32_t width,
233 int32_t height)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200234{
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200235 struct text_input *text_input = resource->data;
236 struct weston_compositor *ec = text_input->ec;
237
238 text_input->cursor_rectangle.x1 = x;
239 text_input->cursor_rectangle.y1 = y;
240 text_input->cursor_rectangle.x2 = x + width;
241 text_input->cursor_rectangle.y2 = y + height;
242
243 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200244}
245
246static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200247text_input_set_content_type(struct wl_client *client,
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100248 struct wl_resource *resource,
249 uint32_t hint,
250 uint32_t purpose)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200251{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200252 struct text_input *text_input = resource->data;
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100253 struct input_method *input_method, *next;
254
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200255 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100256 if (!input_method->context)
257 continue;
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200258 wl_input_method_context_send_content_type(&input_method->context->resource, hint, purpose);
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100259 }
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200260}
261
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100262static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200263text_input_invoke_action(struct wl_client *client,
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100264 struct wl_resource *resource,
265 uint32_t button,
266 uint32_t index)
267{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200268 struct text_input *text_input = resource->data;
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100269 struct input_method *input_method, *next;
270
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200271 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100272 if (!input_method->context)
273 continue;
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200274 wl_input_method_context_send_invoke_action(&input_method->context->resource, button, index);
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100275 }
276}
277
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100278static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200279text_input_commit_state(struct wl_client *client,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200280 struct wl_resource *resource,
281 uint32_t serial)
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100282{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200283 struct text_input *text_input = resource->data;
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100284 struct input_method *input_method, *next;
285
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200286 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100287 if (!input_method->context)
288 continue;
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200289 wl_input_method_context_send_commit_state(&input_method->context->resource, serial);
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100290 }
291}
292
Jan Arne Petersen61381972013-01-31 15:52:21 +0100293static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200294text_input_show_input_panel(struct wl_client *client,
Jan Arne Petersen61381972013-01-31 15:52:21 +0100295 struct wl_resource *resource)
296{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200297 struct text_input *text_input = resource->data;
298 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100299
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200300 text_input->input_panel_visible = 1;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100301
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200302 if (!wl_list_empty(&text_input->input_methods)) {
303 wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
304 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
305 }
Jan Arne Petersen61381972013-01-31 15:52:21 +0100306}
307
308static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200309text_input_hide_input_panel(struct wl_client *client,
Jan Arne Petersen61381972013-01-31 15:52:21 +0100310 struct wl_resource *resource)
311{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200312 struct text_input *text_input = resource->data;
313 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100314
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200315 text_input->input_panel_visible = 0;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100316
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200317 if (!wl_list_empty(&text_input->input_methods))
Jan Arne Petersen61381972013-01-31 15:52:21 +0100318 wl_signal_emit(&ec->hide_input_panel_signal, ec);
319}
320
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200321static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200322text_input_set_preferred_language(struct wl_client *client,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200323 struct wl_resource *resource,
324 const char *language)
325{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200326 struct text_input *text_input = resource->data;
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200327 struct input_method *input_method, *next;
328
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200329 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200330 if (!input_method->context)
331 continue;
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200332 wl_input_method_context_send_preferred_language(&input_method->context->resource,
333 language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200334 }
335}
336
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200337static const struct wl_text_input_interface text_input_implementation = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200338 text_input_activate,
339 text_input_deactivate,
340 text_input_show_input_panel,
341 text_input_hide_input_panel,
342 text_input_reset,
343 text_input_set_surrounding_text,
344 text_input_set_content_type,
345 text_input_set_cursor_rectangle,
346 text_input_set_preferred_language,
347 text_input_commit_state,
348 text_input_invoke_action
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200349};
350
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200351static void text_input_manager_create_text_input(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200352 struct wl_resource *resource,
Jan Arne Petersen4c265182012-09-09 23:08:30 +0200353 uint32_t id)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200354{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200355 struct text_input_manager *text_input_manager = resource->data;
356 struct text_input *text_input;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200357
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200358 text_input = calloc(1, sizeof *text_input);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200359
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200360 text_input->resource.object.id = id;
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200361 text_input->resource.object.interface = &wl_text_input_interface;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200362 text_input->resource.object.implementation =
363 (void (**)(void)) &text_input_implementation;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200364
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200365 text_input->resource.data = text_input;
366 text_input->resource.destroy = destroy_text_input;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200367
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200368 text_input->ec = text_input_manager->ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200369
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200370 wl_list_init(&text_input->input_methods);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200371
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200372 wl_client_add_resource(client, &text_input->resource);
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;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200386
387 /* No checking for duplicate binding necessary.
388 * No events have to be sent, so we don't need the return value. */
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200389 wl_client_add_object(client, &wl_text_input_manager_interface,
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200390 &text_input_manager_implementation,
391 id, text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200392}
393
394static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200395text_input_manager_notifier_destroy(struct wl_listener *listener, void *data)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200396{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200397 struct text_input_manager *text_input_manager =
398 container_of(listener, struct text_input_manager, destroy_listener);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200399
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200400 wl_display_remove_global(text_input_manager->ec->wl_display,
401 text_input_manager->text_input_manager_global);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200402
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200403 free(text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200404}
405
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100406static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200407text_input_manager_create(struct weston_compositor *ec)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200408{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200409 struct text_input_manager *text_input_manager;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200410
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200411 text_input_manager = calloc(1, sizeof *text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200412
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200413 text_input_manager->ec = ec;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200414
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200415 text_input_manager->text_input_manager_global =
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200416 wl_display_add_global(ec->wl_display,
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200417 &wl_text_input_manager_interface,
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200418 text_input_manager, bind_text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200419
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200420 text_input_manager->destroy_listener.notify = text_input_manager_notifier_destroy;
421 wl_signal_add(&ec->destroy_signal, &text_input_manager->destroy_listener);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200422}
423
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200424static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200425input_method_context_destroy(struct wl_client *client,
426 struct wl_resource *resource)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200427{
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200428 wl_resource_destroy(resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200429}
430
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200431static void
432input_method_context_commit_string(struct wl_client *client,
433 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100434 uint32_t serial,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100435 const char *text)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200436{
437 struct input_method_context *context = resource->data;
438
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200439 wl_text_input_send_commit_string(&context->model->resource, serial, text);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200440}
441
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200442static void
443input_method_context_preedit_string(struct wl_client *client,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100444 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100445 uint32_t serial,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100446 const char *text,
447 const char *commit)
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200448{
449 struct input_method_context *context = resource->data;
450
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200451 wl_text_input_send_preedit_string(&context->model->resource, serial, text, commit);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100452}
453
454static void
455input_method_context_preedit_styling(struct wl_client *client,
456 struct wl_resource *resource,
457 uint32_t index,
458 uint32_t length,
459 uint32_t style)
460{
461 struct input_method_context *context = resource->data;
462
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200463 wl_text_input_send_preedit_styling(&context->model->resource, index, length, style);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100464}
465
466static void
467input_method_context_preedit_cursor(struct wl_client *client,
468 struct wl_resource *resource,
469 int32_t cursor)
470{
471 struct input_method_context *context = resource->data;
472
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200473 wl_text_input_send_preedit_cursor(&context->model->resource, cursor);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200474}
475
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200476static void
477input_method_context_delete_surrounding_text(struct wl_client *client,
478 struct wl_resource *resource,
479 int32_t index,
480 uint32_t length)
481{
482 struct input_method_context *context = resource->data;
483
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200484 wl_text_input_send_delete_surrounding_text(&context->model->resource, index, length);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200485}
486
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200487static void
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100488input_method_context_cursor_position(struct wl_client *client,
489 struct wl_resource *resource,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100490 int32_t index,
491 int32_t anchor)
492{
493 struct input_method_context *context = resource->data;
494
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200495 wl_text_input_send_cursor_position(&context->model->resource, index, anchor);
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100496}
497
498static void
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100499input_method_context_modifiers_map(struct wl_client *client,
500 struct wl_resource *resource,
501 struct wl_array *map)
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200502{
503 struct input_method_context *context = resource->data;
504
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200505 wl_text_input_send_modifiers_map(&context->model->resource, map);
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100506}
507
508static void
509input_method_context_keysym(struct wl_client *client,
510 struct wl_resource *resource,
511 uint32_t serial,
512 uint32_t time,
513 uint32_t sym,
514 uint32_t state,
515 uint32_t modifiers)
516{
517 struct input_method_context *context = resource->data;
518
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200519 wl_text_input_send_keysym(&context->model->resource, serial, time,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200520 sym, state, modifiers);
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200521}
522
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100523static void
524unbind_keyboard(struct wl_resource *resource)
525{
526 struct input_method_context *context = resource->data;
527
528 input_method_context_end_keyboard_grab(context);
529 context->keyboard = NULL;
530
531 free(resource);
532}
533
534static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400535input_method_context_grab_key(struct weston_keyboard_grab *grab,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100536 uint32_t time, uint32_t key, uint32_t state_w)
537{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400538 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100539 struct wl_display *display;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100540 uint32_t serial;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100541
542 if (!keyboard->input_method_resource)
543 return;
544
545 display = wl_client_get_display(keyboard->input_method_resource->client);
546 serial = wl_display_next_serial(display);
547 wl_keyboard_send_key(keyboard->input_method_resource,
548 serial, time, key, state_w);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100549}
550
551static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400552input_method_context_grab_modifier(struct weston_keyboard_grab *grab, uint32_t serial,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100553 uint32_t mods_depressed, uint32_t mods_latched,
554 uint32_t mods_locked, uint32_t group)
555{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400556 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100557
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100558 if (!keyboard->input_method_resource)
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100559 return;
560
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100561 wl_keyboard_send_modifiers(keyboard->input_method_resource,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100562 serial, mods_depressed, mods_latched,
563 mods_locked, group);
564}
565
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400566static const struct weston_keyboard_grab_interface input_method_context_grab = {
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100567 input_method_context_grab_key,
568 input_method_context_grab_modifier,
569};
570
571static void
572input_method_context_grab_keyboard(struct wl_client *client,
573 struct wl_resource *resource,
574 uint32_t id)
575{
576 struct input_method_context *context = resource->data;
577 struct wl_resource *cr;
578 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400579 struct weston_keyboard *keyboard = seat->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100580
581 cr = wl_client_add_object(client, &wl_keyboard_interface,
582 NULL, id, context);
583 cr->destroy = unbind_keyboard;
584
585 context->keyboard = cr;
586
587 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
588 seat->xkb_info.keymap_fd,
589 seat->xkb_info.keymap_size);
590
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400591 if (keyboard->grab != &keyboard->default_grab) {
592 weston_keyboard_end_grab(keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100593 }
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400594 weston_keyboard_start_grab(keyboard, &keyboard->input_method_grab);
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100595 keyboard->input_method_resource = cr;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100596}
597
Jan Arne Petersen337df952012-11-18 19:06:46 +0100598static void
599input_method_context_key(struct wl_client *client,
600 struct wl_resource *resource,
601 uint32_t serial,
602 uint32_t time,
603 uint32_t key,
604 uint32_t state_w)
605{
606 struct input_method_context *context = resource->data;
607 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400608 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400609 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100610
611 default_grab->interface->key(default_grab, time, key, state_w);
612}
613
614static void
615input_method_context_modifiers(struct wl_client *client,
616 struct wl_resource *resource,
617 uint32_t serial,
618 uint32_t mods_depressed,
619 uint32_t mods_latched,
620 uint32_t mods_locked,
621 uint32_t group)
622{
623 struct input_method_context *context = resource->data;
624
625 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400626 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400627 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100628
629 default_grab->interface->modifiers(default_grab,
630 serial, mods_depressed,
631 mods_latched, mods_locked,
632 group);
633}
634
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200635static void
636input_method_context_language(struct wl_client *client,
637 struct wl_resource *resource,
638 uint32_t serial,
639 const char *language)
640{
641 struct input_method_context *context = resource->data;
642
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200643 wl_text_input_send_language(&context->model->resource, serial, language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200644}
645
646static void
647input_method_context_text_direction(struct wl_client *client,
648 struct wl_resource *resource,
649 uint32_t serial,
650 uint32_t direction)
651{
652 struct input_method_context *context = resource->data;
653
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200654 wl_text_input_send_text_direction(&context->model->resource, serial, direction);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200655}
656
657
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200658static const struct wl_input_method_context_interface input_method_context_implementation = {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200659 input_method_context_destroy,
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200660 input_method_context_commit_string,
661 input_method_context_preedit_string,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100662 input_method_context_preedit_styling,
663 input_method_context_preedit_cursor,
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200664 input_method_context_delete_surrounding_text,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100665 input_method_context_cursor_position,
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100666 input_method_context_modifiers_map,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100667 input_method_context_keysym,
Jan Arne Petersen337df952012-11-18 19:06:46 +0100668 input_method_context_grab_keyboard,
669 input_method_context_key,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200670 input_method_context_modifiers,
671 input_method_context_language,
672 input_method_context_text_direction
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200673};
674
675static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200676destroy_input_method_context(struct wl_resource *resource)
677{
678 struct input_method_context *context = resource->data;
679
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100680 if (context->keyboard) {
681 wl_resource_destroy(context->keyboard);
682 }
683
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200684 free(context);
685}
686
687static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200688input_method_context_create(struct text_input *model,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200689 struct input_method *input_method)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200690{
691 struct input_method_context *context;
692
693 if (!input_method->input_method_binding)
694 return;
695
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100696 context = calloc(1, sizeof *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200697 if (context == NULL)
698 return;
699
700 context->resource.destroy = destroy_input_method_context;
701 context->resource.object.id = 0;
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200702 context->resource.object.interface = &wl_input_method_context_interface;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200703 context->resource.object.implementation =
704 (void (**)(void)) &input_method_context_implementation;
705 context->resource.data = context;
706 wl_signal_init(&context->resource.destroy_signal);
707
708 context->model = model;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100709 context->input_method = input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200710 input_method->context = context;
711
712 wl_client_add_resource(input_method->input_method_binding->client, &context->resource);
713
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200714 wl_input_method_send_activate(input_method->input_method_binding, &context->resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200715}
716
717static void
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100718input_method_context_end_keyboard_grab(struct input_method_context *context)
719{
Kristian Høgsberge3148752013-05-06 23:19:49 -0400720 struct weston_keyboard_grab *grab =
721 &context->input_method->seat->keyboard->input_method_grab;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400722 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100723
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100724 if (!grab->keyboard)
725 return;
726
727 if (grab->keyboard->grab == grab)
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400728 weston_keyboard_end_grab(grab->keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100729
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100730 keyboard->input_method_resource = NULL;
731}
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100732
733static void
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200734unbind_input_method(struct wl_resource *resource)
735{
736 struct input_method *input_method = resource->data;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100737 struct text_backend *text_backend = input_method->text_backend;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200738
739 input_method->input_method_binding = NULL;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200740 input_method->context = NULL;
741
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100742 text_backend->input_method.binding = NULL;
743
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200744 free(resource);
745}
746
747static void
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200748bind_input_method(struct wl_client *client,
749 void *data,
750 uint32_t version,
751 uint32_t id)
752{
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200753 struct input_method *input_method = data;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100754 struct text_backend *text_backend = input_method->text_backend;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200755 struct wl_resource *resource;
756
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200757 resource = wl_client_add_object(client, &wl_input_method_interface,
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200758 NULL,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200759 id, input_method);
760
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200761 if (input_method->input_method_binding != NULL) {
762 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
763 "interface object already bound");
764 wl_resource_destroy(resource);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200765 return;
766 }
767
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200768 if (text_backend->input_method.client != client) {
769 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
770 "permission to bind desktop_shell denied");
771 wl_resource_destroy(resource);
772 return;
773 }
774
775 resource->destroy = unbind_input_method;
776 input_method->input_method_binding = resource;
777
778 text_backend->input_method.binding = resource;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200779}
780
781static void
782input_method_notifier_destroy(struct wl_listener *listener, void *data)
783{
Kristian Høgsbergf97f3792012-07-22 11:51:42 -0400784 struct input_method *input_method =
785 container_of(listener, struct input_method, destroy_listener);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200786
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200787 if (input_method->model)
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200788 deactivate_text_input(input_method->model, input_method);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200789
790 wl_display_remove_global(input_method->seat->compositor->wl_display,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200791 input_method->input_method_global);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200792
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200793 free(input_method);
794}
795
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200796static void
797handle_keyboard_focus(struct wl_listener *listener, void *data)
798{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400799 struct weston_keyboard *keyboard = data;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200800 struct input_method *input_method =
801 container_of(listener, struct input_method, keyboard_focus_listener);
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400802 struct weston_surface *surface = keyboard->focus;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200803
804 if (!input_method->model)
805 return;
806
807 if (!surface || input_method->model->surface != surface)
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200808 deactivate_text_input(input_method->model,
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200809 input_method);
810}
811
812static void
813input_method_init_seat(struct weston_seat *seat)
814{
815 if (seat->input_method->focus_listener_initialized)
816 return;
817
Kristian Høgsberg2bf87622013-05-07 23:17:41 -0400818 if (seat->keyboard) {
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200819 seat->input_method->keyboard_focus_listener.notify = handle_keyboard_focus;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400820 wl_signal_add(&seat->keyboard->focus_signal, &seat->input_method->keyboard_focus_listener);
821 seat->keyboard->input_method_grab.interface = &input_method_context_grab;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200822 }
823
824 seat->input_method->focus_listener_initialized = 1;
825}
826
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300827static void launch_input_method(struct text_backend *text_backend);
828
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100829static void
830handle_input_method_sigchld(struct weston_process *process, int status)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200831{
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300832 uint32_t time;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100833 struct text_backend *text_backend =
834 container_of(process, struct text_backend, input_method.process);
835
836 text_backend->input_method.process.pid = 0;
837 text_backend->input_method.client = NULL;
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300838
839 /* if input_method dies more than 5 times in 10 seconds, give up */
840 time = weston_compositor_get_time();
841 if (time - text_backend->input_method.deathstamp > 10000) {
842 text_backend->input_method.deathstamp = time;
843 text_backend->input_method.deathcount = 0;
844 }
845
846 text_backend->input_method.deathcount++;
847 if (text_backend->input_method.deathcount > 5) {
848 weston_log("input_method died, giving up.\n");
849 return;
850 }
851
852 weston_log("input_method died, respawning...\n");
853 launch_input_method(text_backend);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100854}
855
856static void
857launch_input_method(struct text_backend *text_backend)
858{
859 if (text_backend->input_method.binding)
860 return;
861
862 if (!text_backend->input_method.path)
863 return;
864
865 if (text_backend->input_method.process.pid != 0)
866 return;
867
868 text_backend->input_method.client = weston_client_launch(text_backend->compositor,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200869 &text_backend->input_method.process,
870 text_backend->input_method.path,
871 handle_input_method_sigchld);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100872
873 if (!text_backend->input_method.client)
874 weston_log("not able to start %s\n", text_backend->input_method.path);
875}
876
877static void
878handle_seat_created(struct wl_listener *listener,
879 void *data)
880{
881 struct weston_seat *seat = data;
882 struct text_backend *text_backend =
883 container_of(listener, struct text_backend,
884 seat_created_listener);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200885 struct input_method *input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100886 struct weston_compositor *ec = seat->compositor;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200887
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200888 input_method = calloc(1, sizeof *input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200889
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200890 input_method->seat = seat;
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200891 input_method->model = NULL;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200892 input_method->focus_listener_initialized = 0;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200893 input_method->context = NULL;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100894 input_method->text_backend = text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200895
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200896 input_method->input_method_global =
897 wl_display_add_global(ec->wl_display,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200898 &wl_input_method_interface,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200899 input_method, bind_input_method);
900
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200901 input_method->destroy_listener.notify = input_method_notifier_destroy;
Kristian Høgsberg49124542013-05-06 22:27:40 -0400902 wl_signal_add(&seat->destroy_signal, &input_method->destroy_listener);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200903
904 seat->input_method = input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100905
906 launch_input_method(text_backend);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200907}
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200908
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100909static void
910text_backend_configuration(struct text_backend *text_backend)
911{
Ossama Othmana50e6e42013-05-14 09:48:26 -0700912 int config_fd;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100913 char *path = NULL;
914
915 struct config_key input_method_keys[] = {
916 { "path", CONFIG_KEY_STRING, &path }
917 };
918
919 struct config_section cs[] = {
920 { "input-method", input_method_keys, ARRAY_LENGTH(input_method_keys), NULL }
921 };
922
Ossama Othmana50e6e42013-05-14 09:48:26 -0700923 config_fd = open_config_file("weston.ini");
924 parse_config_file(config_fd, cs, ARRAY_LENGTH(cs), text_backend);
925 close(config_fd);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100926
927 if (path)
928 text_backend->input_method.path = path;
929 else
930 text_backend->input_method.path = strdup(LIBEXECDIR "/weston-keyboard");
931}
932
933static void
934text_backend_notifier_destroy(struct wl_listener *listener, void *data)
935{
936 struct text_backend *text_backend =
937 container_of(listener, struct text_backend, destroy_listener);
938
939 if (text_backend->input_method.client)
940 wl_client_destroy(text_backend->input_method.client);
941
942 free(text_backend->input_method.path);
943
944 free(text_backend);
945}
946
947
948WL_EXPORT int
949text_backend_init(struct weston_compositor *ec)
950{
951 struct text_backend *text_backend;
952
953 text_backend = calloc(1, sizeof(*text_backend));
954
955 text_backend->compositor = ec;
956
957 text_backend->seat_created_listener.notify = handle_seat_created;
958 wl_signal_add(&ec->seat_created_signal,
959 &text_backend->seat_created_listener);
960
961 text_backend->destroy_listener.notify = text_backend_notifier_destroy;
962 wl_signal_add(&ec->destroy_signal, &text_backend->destroy_listener);
963
964 text_backend_configuration(text_backend);
965
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200966 text_input_manager_create(ec);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100967
968 return 0;
969}