blob: 036d48a69ff4fc567363a6427a8a28d5f39e21b4 [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>
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020026
27#include "compositor.h"
28#include "text-server-protocol.h"
Jan Arne Petersen30b66ef2012-09-09 23:08:41 +020029#include "input-method-server-protocol.h"
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020030
31struct input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020032struct input_method_context;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010033struct text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020034
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020035struct text_input {
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020036 struct wl_resource resource;
37
Jan Arne Petersene829adc2012-08-10 16:47:22 +020038 struct weston_compositor *ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020039
Jan Arne Petersene829adc2012-08-10 16:47:22 +020040 struct wl_list input_methods;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +020041
42 struct wl_surface *surface;
Jan Arne Petersen61381972013-01-31 15:52:21 +010043
Jan Arne Petersen14da96b2013-04-18 16:47:28 +020044 pixman_box32_t cursor_rectangle;
45
Jan Arne Petersen61381972013-01-31 15:52:21 +010046 uint32_t input_panel_visible;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020047};
48
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020049struct text_input_manager {
50 struct wl_global *text_input_manager_global;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020051 struct wl_listener destroy_listener;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020052
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +020053 struct weston_compositor *ec;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +020054};
55
56struct input_method {
57 struct wl_resource *input_method_binding;
58 struct wl_global *input_method_global;
59 struct wl_listener destroy_listener;
60
61 struct weston_seat *seat;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020062 struct text_input *model;
Jan Arne Petersene829adc2012-08-10 16:47:22 +020063
64 struct wl_list link;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +020065
66 struct wl_listener keyboard_focus_listener;
67
68 int focus_listener_initialized;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020069
70 struct input_method_context *context;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010071
72 struct text_backend *text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020073};
74
Jan Arne Petersen620cd622012-09-09 23:08:32 +020075struct input_method_context {
76 struct wl_resource resource;
77
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020078 struct text_input *model;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +010079 struct input_method *input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020080
81 struct wl_list link;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +010082
83 struct wl_resource *keyboard;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020084};
85
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010086struct text_backend {
87 struct weston_compositor *compositor;
88
89 struct {
90 char *path;
91 struct wl_resource *binding;
92 struct weston_process process;
93 struct wl_client *client;
94 } input_method;
95
96 struct wl_listener seat_created_listener;
97 struct wl_listener destroy_listener;
98};
99
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200100static void input_method_context_create(struct text_input *model,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200101 struct input_method *input_method);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100102static void input_method_context_end_keyboard_grab(struct input_method_context *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200103
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200104static void input_method_init_seat(struct weston_seat *seat);
105
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200106static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200107deactivate_text_input(struct text_input *text_input,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200108 struct input_method *input_method)
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200109{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200110 struct weston_compositor *ec = text_input->ec;
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200111
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200112 if (input_method->model == text_input) {
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100113 if (input_method->context && input_method->input_method_binding) {
114 input_method_context_end_keyboard_grab(input_method->context);
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200115 wl_input_method_send_deactivate(input_method->input_method_binding,
116 &input_method->context->resource);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100117 }
118
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200119 wl_list_remove(&input_method->link);
120 input_method->model = NULL;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200121 input_method->context = NULL;
Kristian Høgsbergf97f3792012-07-22 11:51:42 -0400122 wl_signal_emit(&ec->hide_input_panel_signal, ec);
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200123 wl_text_input_send_leave(&text_input->resource);
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200124 }
125}
126
127static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200128destroy_text_input(struct wl_resource *resource)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200129{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200130 struct text_input *text_input =
131 container_of(resource, struct text_input, resource);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200132 struct input_method *input_method, *next;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200133
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200134 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link)
135 deactivate_text_input(text_input, input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200136
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200137 free(text_input);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200138}
139
140static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200141text_input_set_surrounding_text(struct wl_client *client,
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200142 struct wl_resource *resource,
Jan Arne Petersencb08f4d2012-09-09 23:08:40 +0200143 const char *text,
144 uint32_t cursor,
145 uint32_t anchor)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200146{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200147 struct text_input *text_input = resource->data;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200148 struct input_method *input_method, *next;
149
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200150 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200151 if (!input_method->context)
152 continue;
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200153 wl_input_method_context_send_surrounding_text(&input_method->context->resource,
154 text,
155 cursor,
156 anchor);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200157 }
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200158}
159
160static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200161text_input_activate(struct wl_client *client,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200162 struct wl_resource *resource,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200163 struct wl_resource *seat,
164 struct wl_resource *surface)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200165{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200166 struct text_input *text_input = resource->data;
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200167 struct weston_seat *weston_seat = seat->data;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200168 struct input_method *input_method = weston_seat->input_method;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200169 struct text_input *old = weston_seat->input_method->model;
170 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200171
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200172 if (old == text_input)
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200173 return;
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200174
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200175 if (old) {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200176 deactivate_text_input(old,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200177 weston_seat->input_method);
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200178 }
179
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200180 input_method->model = text_input;
181 wl_list_insert(&text_input->input_methods, &input_method->link);
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200182 input_method_init_seat(weston_seat);
183
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200184 text_input->surface = surface->data;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200185
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200186 input_method_context_create(text_input, input_method);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200187
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200188 if (text_input->input_panel_visible) {
189 wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
190 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
191 }
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200192
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200193 wl_text_input_send_enter(&text_input->resource, &text_input->surface->resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200194}
195
196static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200197text_input_deactivate(struct wl_client *client,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200198 struct wl_resource *resource,
199 struct wl_resource *seat)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200200{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200201 struct text_input *text_input = resource->data;
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200202 struct weston_seat *weston_seat = seat->data;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200203
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200204 deactivate_text_input(text_input,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200205 weston_seat->input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200206}
207
208static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200209text_input_reset(struct wl_client *client,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200210 struct wl_resource *resource)
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200211{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200212 struct text_input *text_input = resource->data;
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200213 struct input_method *input_method, *next;
214
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200215 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200216 if (!input_method->context)
217 continue;
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200218 wl_input_method_context_send_reset(&input_method->context->resource);
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200219 }
220}
221
222static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200223text_input_set_cursor_rectangle(struct wl_client *client,
Jan Arne Petersen7ef8eff2013-04-18 16:47:23 +0200224 struct wl_resource *resource,
225 int32_t x,
226 int32_t y,
227 int32_t width,
228 int32_t height)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200229{
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200230 struct text_input *text_input = resource->data;
231 struct weston_compositor *ec = text_input->ec;
232
233 text_input->cursor_rectangle.x1 = x;
234 text_input->cursor_rectangle.y1 = y;
235 text_input->cursor_rectangle.x2 = x + width;
236 text_input->cursor_rectangle.y2 = y + height;
237
238 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200239}
240
241static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200242text_input_set_content_type(struct wl_client *client,
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100243 struct wl_resource *resource,
244 uint32_t hint,
245 uint32_t purpose)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200246{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200247 struct text_input *text_input = resource->data;
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100248 struct input_method *input_method, *next;
249
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200250 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100251 if (!input_method->context)
252 continue;
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200253 wl_input_method_context_send_content_type(&input_method->context->resource, hint, purpose);
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100254 }
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200255}
256
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100257static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200258text_input_invoke_action(struct wl_client *client,
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100259 struct wl_resource *resource,
260 uint32_t button,
261 uint32_t index)
262{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200263 struct text_input *text_input = resource->data;
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100264 struct input_method *input_method, *next;
265
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200266 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100267 if (!input_method->context)
268 continue;
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200269 wl_input_method_context_send_invoke_action(&input_method->context->resource, button, index);
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100270 }
271}
272
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100273static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200274text_input_commit_state(struct wl_client *client,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200275 struct wl_resource *resource,
276 uint32_t serial)
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100277{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200278 struct text_input *text_input = resource->data;
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100279 struct input_method *input_method, *next;
280
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200281 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100282 if (!input_method->context)
283 continue;
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200284 wl_input_method_context_send_commit_state(&input_method->context->resource, serial);
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100285 }
286}
287
Jan Arne Petersen61381972013-01-31 15:52:21 +0100288static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200289text_input_show_input_panel(struct wl_client *client,
Jan Arne Petersen61381972013-01-31 15:52:21 +0100290 struct wl_resource *resource)
291{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200292 struct text_input *text_input = resource->data;
293 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100294
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200295 text_input->input_panel_visible = 1;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100296
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200297 if (!wl_list_empty(&text_input->input_methods)) {
298 wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
299 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
300 }
Jan Arne Petersen61381972013-01-31 15:52:21 +0100301}
302
303static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200304text_input_hide_input_panel(struct wl_client *client,
Jan Arne Petersen61381972013-01-31 15:52:21 +0100305 struct wl_resource *resource)
306{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200307 struct text_input *text_input = resource->data;
308 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100309
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200310 text_input->input_panel_visible = 0;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100311
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200312 if (!wl_list_empty(&text_input->input_methods))
Jan Arne Petersen61381972013-01-31 15:52:21 +0100313 wl_signal_emit(&ec->hide_input_panel_signal, ec);
314}
315
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200316static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200317text_input_set_preferred_language(struct wl_client *client,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200318 struct wl_resource *resource,
319 const char *language)
320{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200321 struct text_input *text_input = resource->data;
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200322 struct input_method *input_method, *next;
323
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200324 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200325 if (!input_method->context)
326 continue;
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200327 wl_input_method_context_send_preferred_language(&input_method->context->resource,
328 language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200329 }
330}
331
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200332static const struct wl_text_input_interface text_input_implementation = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200333 text_input_activate,
334 text_input_deactivate,
335 text_input_show_input_panel,
336 text_input_hide_input_panel,
337 text_input_reset,
338 text_input_set_surrounding_text,
339 text_input_set_content_type,
340 text_input_set_cursor_rectangle,
341 text_input_set_preferred_language,
342 text_input_commit_state,
343 text_input_invoke_action
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200344};
345
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200346static void text_input_manager_create_text_input(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200347 struct wl_resource *resource,
Jan Arne Petersen4c265182012-09-09 23:08:30 +0200348 uint32_t id)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200349{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200350 struct text_input_manager *text_input_manager = resource->data;
351 struct text_input *text_input;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200352
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200353 text_input = calloc(1, sizeof *text_input);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200354
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200355 text_input->resource.object.id = id;
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200356 text_input->resource.object.interface = &wl_text_input_interface;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200357 text_input->resource.object.implementation =
358 (void (**)(void)) &text_input_implementation;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200359
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200360 text_input->resource.data = text_input;
361 text_input->resource.destroy = destroy_text_input;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200362
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200363 text_input->ec = text_input_manager->ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200364
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200365 wl_list_init(&text_input->input_methods);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200366
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200367 wl_client_add_resource(client, &text_input->resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200368};
369
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200370static const struct wl_text_input_manager_interface text_input_manager_implementation = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200371 text_input_manager_create_text_input
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200372};
373
374static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200375bind_text_input_manager(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200376 void *data,
377 uint32_t version,
378 uint32_t id)
379{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200380 struct text_input_manager *text_input_manager = data;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200381
382 /* No checking for duplicate binding necessary.
383 * No events have to be sent, so we don't need the return value. */
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200384 wl_client_add_object(client, &wl_text_input_manager_interface,
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200385 &text_input_manager_implementation,
386 id, text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200387}
388
389static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200390text_input_manager_notifier_destroy(struct wl_listener *listener, void *data)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200391{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200392 struct text_input_manager *text_input_manager =
393 container_of(listener, struct text_input_manager, destroy_listener);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200394
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200395 wl_display_remove_global(text_input_manager->ec->wl_display,
396 text_input_manager->text_input_manager_global);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200397
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200398 free(text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200399}
400
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100401static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200402text_input_manager_create(struct weston_compositor *ec)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200403{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200404 struct text_input_manager *text_input_manager;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200405
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200406 text_input_manager = calloc(1, sizeof *text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200407
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200408 text_input_manager->ec = ec;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200409
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200410 text_input_manager->text_input_manager_global =
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200411 wl_display_add_global(ec->wl_display,
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200412 &wl_text_input_manager_interface,
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200413 text_input_manager, bind_text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200414
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200415 text_input_manager->destroy_listener.notify = text_input_manager_notifier_destroy;
416 wl_signal_add(&ec->destroy_signal, &text_input_manager->destroy_listener);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200417}
418
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200419static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200420input_method_context_destroy(struct wl_client *client,
421 struct wl_resource *resource)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200422{
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200423 wl_resource_destroy(resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200424}
425
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200426static void
427input_method_context_commit_string(struct wl_client *client,
428 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100429 uint32_t serial,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100430 const char *text)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200431{
432 struct input_method_context *context = resource->data;
433
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200434 wl_text_input_send_commit_string(&context->model->resource, serial, text);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200435}
436
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200437static void
438input_method_context_preedit_string(struct wl_client *client,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100439 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100440 uint32_t serial,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100441 const char *text,
442 const char *commit)
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200443{
444 struct input_method_context *context = resource->data;
445
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200446 wl_text_input_send_preedit_string(&context->model->resource, serial, text, commit);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100447}
448
449static void
450input_method_context_preedit_styling(struct wl_client *client,
451 struct wl_resource *resource,
452 uint32_t index,
453 uint32_t length,
454 uint32_t style)
455{
456 struct input_method_context *context = resource->data;
457
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200458 wl_text_input_send_preedit_styling(&context->model->resource, index, length, style);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100459}
460
461static void
462input_method_context_preedit_cursor(struct wl_client *client,
463 struct wl_resource *resource,
464 int32_t cursor)
465{
466 struct input_method_context *context = resource->data;
467
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200468 wl_text_input_send_preedit_cursor(&context->model->resource, cursor);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200469}
470
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200471static void
472input_method_context_delete_surrounding_text(struct wl_client *client,
473 struct wl_resource *resource,
474 int32_t index,
475 uint32_t length)
476{
477 struct input_method_context *context = resource->data;
478
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200479 wl_text_input_send_delete_surrounding_text(&context->model->resource, index, length);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200480}
481
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200482static void
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100483input_method_context_cursor_position(struct wl_client *client,
484 struct wl_resource *resource,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100485 int32_t index,
486 int32_t anchor)
487{
488 struct input_method_context *context = resource->data;
489
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200490 wl_text_input_send_cursor_position(&context->model->resource, index, anchor);
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100491}
492
493static void
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100494input_method_context_modifiers_map(struct wl_client *client,
495 struct wl_resource *resource,
496 struct wl_array *map)
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200497{
498 struct input_method_context *context = resource->data;
499
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200500 wl_text_input_send_modifiers_map(&context->model->resource, map);
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100501}
502
503static void
504input_method_context_keysym(struct wl_client *client,
505 struct wl_resource *resource,
506 uint32_t serial,
507 uint32_t time,
508 uint32_t sym,
509 uint32_t state,
510 uint32_t modifiers)
511{
512 struct input_method_context *context = resource->data;
513
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200514 wl_text_input_send_keysym(&context->model->resource, serial, time,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200515 sym, state, modifiers);
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200516}
517
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100518static void
519unbind_keyboard(struct wl_resource *resource)
520{
521 struct input_method_context *context = resource->data;
522
523 input_method_context_end_keyboard_grab(context);
524 context->keyboard = NULL;
525
526 free(resource);
527}
528
529static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400530input_method_context_grab_key(struct weston_keyboard_grab *grab,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100531 uint32_t time, uint32_t key, uint32_t state_w)
532{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400533 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100534 struct wl_display *display;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100535 uint32_t serial;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100536
537 if (!keyboard->input_method_resource)
538 return;
539
540 display = wl_client_get_display(keyboard->input_method_resource->client);
541 serial = wl_display_next_serial(display);
542 wl_keyboard_send_key(keyboard->input_method_resource,
543 serial, time, key, state_w);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100544}
545
546static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400547input_method_context_grab_modifier(struct weston_keyboard_grab *grab, uint32_t serial,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100548 uint32_t mods_depressed, uint32_t mods_latched,
549 uint32_t mods_locked, uint32_t group)
550{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400551 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100552
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100553 if (!keyboard->input_method_resource)
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100554 return;
555
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100556 wl_keyboard_send_modifiers(keyboard->input_method_resource,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100557 serial, mods_depressed, mods_latched,
558 mods_locked, group);
559}
560
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400561static const struct weston_keyboard_grab_interface input_method_context_grab = {
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100562 input_method_context_grab_key,
563 input_method_context_grab_modifier,
564};
565
566static void
567input_method_context_grab_keyboard(struct wl_client *client,
568 struct wl_resource *resource,
569 uint32_t id)
570{
571 struct input_method_context *context = resource->data;
572 struct wl_resource *cr;
573 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400574 struct weston_keyboard *keyboard = seat->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100575
576 cr = wl_client_add_object(client, &wl_keyboard_interface,
577 NULL, id, context);
578 cr->destroy = unbind_keyboard;
579
580 context->keyboard = cr;
581
582 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
583 seat->xkb_info.keymap_fd,
584 seat->xkb_info.keymap_size);
585
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400586 if (keyboard->grab != &keyboard->default_grab) {
587 weston_keyboard_end_grab(keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100588 }
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400589 weston_keyboard_start_grab(keyboard, &keyboard->input_method_grab);
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100590 keyboard->input_method_resource = cr;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100591}
592
Jan Arne Petersen337df952012-11-18 19:06:46 +0100593static void
594input_method_context_key(struct wl_client *client,
595 struct wl_resource *resource,
596 uint32_t serial,
597 uint32_t time,
598 uint32_t key,
599 uint32_t state_w)
600{
601 struct input_method_context *context = resource->data;
602 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400603 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400604 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100605
606 default_grab->interface->key(default_grab, time, key, state_w);
607}
608
609static void
610input_method_context_modifiers(struct wl_client *client,
611 struct wl_resource *resource,
612 uint32_t serial,
613 uint32_t mods_depressed,
614 uint32_t mods_latched,
615 uint32_t mods_locked,
616 uint32_t group)
617{
618 struct input_method_context *context = resource->data;
619
620 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400621 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400622 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100623
624 default_grab->interface->modifiers(default_grab,
625 serial, mods_depressed,
626 mods_latched, mods_locked,
627 group);
628}
629
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200630static void
631input_method_context_language(struct wl_client *client,
632 struct wl_resource *resource,
633 uint32_t serial,
634 const char *language)
635{
636 struct input_method_context *context = resource->data;
637
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200638 wl_text_input_send_language(&context->model->resource, serial, language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200639}
640
641static void
642input_method_context_text_direction(struct wl_client *client,
643 struct wl_resource *resource,
644 uint32_t serial,
645 uint32_t direction)
646{
647 struct input_method_context *context = resource->data;
648
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200649 wl_text_input_send_text_direction(&context->model->resource, serial, direction);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200650}
651
652
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200653static const struct wl_input_method_context_interface input_method_context_implementation = {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200654 input_method_context_destroy,
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200655 input_method_context_commit_string,
656 input_method_context_preedit_string,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100657 input_method_context_preedit_styling,
658 input_method_context_preedit_cursor,
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200659 input_method_context_delete_surrounding_text,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100660 input_method_context_cursor_position,
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100661 input_method_context_modifiers_map,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100662 input_method_context_keysym,
Jan Arne Petersen337df952012-11-18 19:06:46 +0100663 input_method_context_grab_keyboard,
664 input_method_context_key,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200665 input_method_context_modifiers,
666 input_method_context_language,
667 input_method_context_text_direction
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200668};
669
670static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200671destroy_input_method_context(struct wl_resource *resource)
672{
673 struct input_method_context *context = resource->data;
674
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100675 if (context->keyboard) {
676 wl_resource_destroy(context->keyboard);
677 }
678
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200679 free(context);
680}
681
682static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200683input_method_context_create(struct text_input *model,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200684 struct input_method *input_method)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200685{
686 struct input_method_context *context;
687
688 if (!input_method->input_method_binding)
689 return;
690
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100691 context = calloc(1, sizeof *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200692 if (context == NULL)
693 return;
694
695 context->resource.destroy = destroy_input_method_context;
696 context->resource.object.id = 0;
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200697 context->resource.object.interface = &wl_input_method_context_interface;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200698 context->resource.object.implementation =
699 (void (**)(void)) &input_method_context_implementation;
700 context->resource.data = context;
701 wl_signal_init(&context->resource.destroy_signal);
702
703 context->model = model;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100704 context->input_method = input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200705 input_method->context = context;
706
707 wl_client_add_resource(input_method->input_method_binding->client, &context->resource);
708
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200709 wl_input_method_send_activate(input_method->input_method_binding, &context->resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200710}
711
712static void
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100713input_method_context_end_keyboard_grab(struct input_method_context *context)
714{
Kristian Høgsberge3148752013-05-06 23:19:49 -0400715 struct weston_keyboard_grab *grab =
716 &context->input_method->seat->keyboard->input_method_grab;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400717 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100718
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100719 if (!grab->keyboard)
720 return;
721
722 if (grab->keyboard->grab == grab)
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400723 weston_keyboard_end_grab(grab->keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100724
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100725 keyboard->input_method_resource = NULL;
726}
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100727
728static void
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200729unbind_input_method(struct wl_resource *resource)
730{
731 struct input_method *input_method = resource->data;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100732 struct text_backend *text_backend = input_method->text_backend;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200733
734 input_method->input_method_binding = NULL;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200735 input_method->context = NULL;
736
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100737 text_backend->input_method.binding = NULL;
738
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200739 free(resource);
740}
741
742static void
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200743bind_input_method(struct wl_client *client,
744 void *data,
745 uint32_t version,
746 uint32_t id)
747{
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200748 struct input_method *input_method = data;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100749 struct text_backend *text_backend = input_method->text_backend;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200750 struct wl_resource *resource;
751
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200752 resource = wl_client_add_object(client, &wl_input_method_interface,
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200753 NULL,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200754 id, input_method);
755
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200756 if (input_method->input_method_binding != NULL) {
757 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
758 "interface object already bound");
759 wl_resource_destroy(resource);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200760 return;
761 }
762
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200763 if (text_backend->input_method.client != client) {
764 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
765 "permission to bind desktop_shell denied");
766 wl_resource_destroy(resource);
767 return;
768 }
769
770 resource->destroy = unbind_input_method;
771 input_method->input_method_binding = resource;
772
773 text_backend->input_method.binding = resource;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200774}
775
776static void
777input_method_notifier_destroy(struct wl_listener *listener, void *data)
778{
Kristian Høgsbergf97f3792012-07-22 11:51:42 -0400779 struct input_method *input_method =
780 container_of(listener, struct input_method, destroy_listener);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200781
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200782 if (input_method->model)
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200783 deactivate_text_input(input_method->model, input_method);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200784
785 wl_display_remove_global(input_method->seat->compositor->wl_display,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200786 input_method->input_method_global);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200787
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200788 free(input_method);
789}
790
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200791static void
792handle_keyboard_focus(struct wl_listener *listener, void *data)
793{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400794 struct weston_keyboard *keyboard = data;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200795 struct input_method *input_method =
796 container_of(listener, struct input_method, keyboard_focus_listener);
797 struct wl_surface *surface = keyboard->focus;
798
799 if (!input_method->model)
800 return;
801
802 if (!surface || input_method->model->surface != surface)
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200803 deactivate_text_input(input_method->model,
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200804 input_method);
805}
806
807static void
808input_method_init_seat(struct weston_seat *seat)
809{
810 if (seat->input_method->focus_listener_initialized)
811 return;
812
Kristian Høgsberg2bf87622013-05-07 23:17:41 -0400813 if (seat->keyboard) {
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200814 seat->input_method->keyboard_focus_listener.notify = handle_keyboard_focus;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400815 wl_signal_add(&seat->keyboard->focus_signal, &seat->input_method->keyboard_focus_listener);
816 seat->keyboard->input_method_grab.interface = &input_method_context_grab;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200817 }
818
819 seat->input_method->focus_listener_initialized = 1;
820}
821
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100822static void
823handle_input_method_sigchld(struct weston_process *process, int status)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200824{
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100825 struct text_backend *text_backend =
826 container_of(process, struct text_backend, input_method.process);
827
828 text_backend->input_method.process.pid = 0;
829 text_backend->input_method.client = NULL;
830}
831
832static void
833launch_input_method(struct text_backend *text_backend)
834{
835 if (text_backend->input_method.binding)
836 return;
837
838 if (!text_backend->input_method.path)
839 return;
840
841 if (text_backend->input_method.process.pid != 0)
842 return;
843
844 text_backend->input_method.client = weston_client_launch(text_backend->compositor,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200845 &text_backend->input_method.process,
846 text_backend->input_method.path,
847 handle_input_method_sigchld);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100848
849 if (!text_backend->input_method.client)
850 weston_log("not able to start %s\n", text_backend->input_method.path);
851}
852
853static void
854handle_seat_created(struct wl_listener *listener,
855 void *data)
856{
857 struct weston_seat *seat = data;
858 struct text_backend *text_backend =
859 container_of(listener, struct text_backend,
860 seat_created_listener);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200861 struct input_method *input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100862 struct weston_compositor *ec = seat->compositor;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200863
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200864 input_method = calloc(1, sizeof *input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200865
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200866 input_method->seat = seat;
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200867 input_method->model = NULL;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200868 input_method->focus_listener_initialized = 0;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200869 input_method->context = NULL;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100870 input_method->text_backend = text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200871
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200872 input_method->input_method_global =
873 wl_display_add_global(ec->wl_display,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200874 &wl_input_method_interface,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200875 input_method, bind_input_method);
876
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200877 input_method->destroy_listener.notify = input_method_notifier_destroy;
Kristian Høgsberg49124542013-05-06 22:27:40 -0400878 wl_signal_add(&seat->destroy_signal, &input_method->destroy_listener);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200879
880 seat->input_method = input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100881
882 launch_input_method(text_backend);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200883}
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200884
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100885static void
886text_backend_configuration(struct text_backend *text_backend)
887{
888 char *config_file;
889 char *path = NULL;
890
891 struct config_key input_method_keys[] = {
892 { "path", CONFIG_KEY_STRING, &path }
893 };
894
895 struct config_section cs[] = {
896 { "input-method", input_method_keys, ARRAY_LENGTH(input_method_keys), NULL }
897 };
898
899 config_file = config_file_path("weston.ini");
900 parse_config_file(config_file, cs, ARRAY_LENGTH(cs), text_backend);
901 free(config_file);
902
903 if (path)
904 text_backend->input_method.path = path;
905 else
906 text_backend->input_method.path = strdup(LIBEXECDIR "/weston-keyboard");
907}
908
909static void
910text_backend_notifier_destroy(struct wl_listener *listener, void *data)
911{
912 struct text_backend *text_backend =
913 container_of(listener, struct text_backend, destroy_listener);
914
915 if (text_backend->input_method.client)
916 wl_client_destroy(text_backend->input_method.client);
917
918 free(text_backend->input_method.path);
919
920 free(text_backend);
921}
922
923
924WL_EXPORT int
925text_backend_init(struct weston_compositor *ec)
926{
927 struct text_backend *text_backend;
928
929 text_backend = calloc(1, sizeof(*text_backend));
930
931 text_backend->compositor = ec;
932
933 text_backend->seat_created_listener.notify = handle_seat_created;
934 wl_signal_add(&ec->seat_created_signal,
935 &text_backend->seat_created_listener);
936
937 text_backend->destroy_listener.notify = text_backend_notifier_destroy;
938 wl_signal_add(&ec->destroy_signal, &text_backend->destroy_listener);
939
940 text_backend_configuration(text_backend);
941
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200942 text_input_manager_create(ec);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100943
944 return 0;
945}