blob: da62fd74dcf173e8db9d520d8c2bc552558f0377 [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>
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020027
28#include "compositor.h"
29#include "text-server-protocol.h"
Jan Arne Petersen30b66ef2012-09-09 23:08:41 +020030#include "input-method-server-protocol.h"
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020031
32struct input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020033struct input_method_context;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010034struct text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020035
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020036struct text_input {
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020037 struct wl_resource resource;
38
Jan Arne Petersene829adc2012-08-10 16:47:22 +020039 struct weston_compositor *ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020040
Jan Arne Petersene829adc2012-08-10 16:47:22 +020041 struct wl_list input_methods;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +020042
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -040043 struct weston_surface *surface;
Jan Arne Petersen61381972013-01-31 15:52:21 +010044
Jan Arne Petersen14da96b2013-04-18 16:47:28 +020045 pixman_box32_t cursor_rectangle;
46
Jan Arne Petersen61381972013-01-31 15:52:21 +010047 uint32_t input_panel_visible;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020048};
49
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020050struct text_input_manager {
51 struct wl_global *text_input_manager_global;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020052 struct wl_listener destroy_listener;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020053
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +020054 struct weston_compositor *ec;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +020055};
56
57struct input_method {
58 struct wl_resource *input_method_binding;
59 struct wl_global *input_method_global;
60 struct wl_listener destroy_listener;
61
62 struct weston_seat *seat;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020063 struct text_input *model;
Jan Arne Petersene829adc2012-08-10 16:47:22 +020064
65 struct wl_list link;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +020066
67 struct wl_listener keyboard_focus_listener;
68
69 int focus_listener_initialized;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020070
71 struct input_method_context *context;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010072
73 struct text_backend *text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020074};
75
Jan Arne Petersen620cd622012-09-09 23:08:32 +020076struct input_method_context {
77 struct wl_resource resource;
78
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020079 struct text_input *model;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +010080 struct input_method *input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020081
82 struct wl_list link;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +010083
84 struct wl_resource *keyboard;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020085};
86
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010087struct text_backend {
88 struct weston_compositor *compositor;
89
90 struct {
91 char *path;
92 struct wl_resource *binding;
93 struct weston_process process;
94 struct wl_client *client;
95 } input_method;
96
97 struct wl_listener seat_created_listener;
98 struct wl_listener destroy_listener;
99};
100
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200101static void input_method_context_create(struct text_input *model,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200102 struct input_method *input_method);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100103static void input_method_context_end_keyboard_grab(struct input_method_context *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200104
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200105static void input_method_init_seat(struct weston_seat *seat);
106
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200107static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200108deactivate_text_input(struct text_input *text_input,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200109 struct input_method *input_method)
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200110{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200111 struct weston_compositor *ec = text_input->ec;
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200112
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200113 if (input_method->model == text_input) {
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100114 if (input_method->context && input_method->input_method_binding) {
115 input_method_context_end_keyboard_grab(input_method->context);
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200116 wl_input_method_send_deactivate(input_method->input_method_binding,
117 &input_method->context->resource);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100118 }
119
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200120 wl_list_remove(&input_method->link);
121 input_method->model = NULL;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200122 input_method->context = NULL;
Kristian Høgsbergf97f3792012-07-22 11:51:42 -0400123 wl_signal_emit(&ec->hide_input_panel_signal, ec);
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200124 wl_text_input_send_leave(&text_input->resource);
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200125 }
126}
127
128static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200129destroy_text_input(struct wl_resource *resource)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200130{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200131 struct text_input *text_input =
132 container_of(resource, struct text_input, resource);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200133 struct input_method *input_method, *next;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200134
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200135 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link)
136 deactivate_text_input(text_input, input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200137
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200138 free(text_input);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200139}
140
141static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200142text_input_set_surrounding_text(struct wl_client *client,
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200143 struct wl_resource *resource,
Jan Arne Petersencb08f4d2012-09-09 23:08:40 +0200144 const char *text,
145 uint32_t cursor,
146 uint32_t anchor)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200147{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200148 struct text_input *text_input = resource->data;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200149 struct input_method *input_method, *next;
150
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200151 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200152 if (!input_method->context)
153 continue;
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200154 wl_input_method_context_send_surrounding_text(&input_method->context->resource,
155 text,
156 cursor,
157 anchor);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200158 }
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200159}
160
161static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200162text_input_activate(struct wl_client *client,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200163 struct wl_resource *resource,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200164 struct wl_resource *seat,
165 struct wl_resource *surface)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200166{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200167 struct text_input *text_input = resource->data;
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200168 struct weston_seat *weston_seat = seat->data;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200169 struct input_method *input_method = weston_seat->input_method;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200170 struct text_input *old = weston_seat->input_method->model;
171 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200172
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200173 if (old == text_input)
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200174 return;
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200175
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200176 if (old) {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200177 deactivate_text_input(old,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200178 weston_seat->input_method);
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200179 }
180
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200181 input_method->model = text_input;
182 wl_list_insert(&text_input->input_methods, &input_method->link);
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200183 input_method_init_seat(weston_seat);
184
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200185 text_input->surface = surface->data;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200186
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200187 input_method_context_create(text_input, input_method);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200188
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200189 if (text_input->input_panel_visible) {
190 wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
191 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
192 }
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200193
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200194 wl_text_input_send_enter(&text_input->resource, &text_input->surface->resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200195}
196
197static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200198text_input_deactivate(struct wl_client *client,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200199 struct wl_resource *resource,
200 struct wl_resource *seat)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200201{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200202 struct text_input *text_input = resource->data;
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200203 struct weston_seat *weston_seat = seat->data;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200204
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200205 deactivate_text_input(text_input,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200206 weston_seat->input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200207}
208
209static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200210text_input_reset(struct wl_client *client,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200211 struct wl_resource *resource)
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200212{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200213 struct text_input *text_input = resource->data;
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200214 struct input_method *input_method, *next;
215
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200216 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200217 if (!input_method->context)
218 continue;
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200219 wl_input_method_context_send_reset(&input_method->context->resource);
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200220 }
221}
222
223static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200224text_input_set_cursor_rectangle(struct wl_client *client,
Jan Arne Petersen7ef8eff2013-04-18 16:47:23 +0200225 struct wl_resource *resource,
226 int32_t x,
227 int32_t y,
228 int32_t width,
229 int32_t height)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200230{
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200231 struct text_input *text_input = resource->data;
232 struct weston_compositor *ec = text_input->ec;
233
234 text_input->cursor_rectangle.x1 = x;
235 text_input->cursor_rectangle.y1 = y;
236 text_input->cursor_rectangle.x2 = x + width;
237 text_input->cursor_rectangle.y2 = y + height;
238
239 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200240}
241
242static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200243text_input_set_content_type(struct wl_client *client,
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100244 struct wl_resource *resource,
245 uint32_t hint,
246 uint32_t purpose)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200247{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200248 struct text_input *text_input = resource->data;
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100249 struct input_method *input_method, *next;
250
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200251 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100252 if (!input_method->context)
253 continue;
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200254 wl_input_method_context_send_content_type(&input_method->context->resource, hint, purpose);
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100255 }
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200256}
257
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100258static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200259text_input_invoke_action(struct wl_client *client,
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100260 struct wl_resource *resource,
261 uint32_t button,
262 uint32_t index)
263{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200264 struct text_input *text_input = resource->data;
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100265 struct input_method *input_method, *next;
266
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200267 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100268 if (!input_method->context)
269 continue;
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200270 wl_input_method_context_send_invoke_action(&input_method->context->resource, button, index);
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100271 }
272}
273
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100274static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200275text_input_commit_state(struct wl_client *client,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200276 struct wl_resource *resource,
277 uint32_t serial)
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100278{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200279 struct text_input *text_input = resource->data;
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100280 struct input_method *input_method, *next;
281
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200282 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100283 if (!input_method->context)
284 continue;
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200285 wl_input_method_context_send_commit_state(&input_method->context->resource, serial);
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100286 }
287}
288
Jan Arne Petersen61381972013-01-31 15:52:21 +0100289static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200290text_input_show_input_panel(struct wl_client *client,
Jan Arne Petersen61381972013-01-31 15:52:21 +0100291 struct wl_resource *resource)
292{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200293 struct text_input *text_input = resource->data;
294 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100295
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200296 text_input->input_panel_visible = 1;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100297
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200298 if (!wl_list_empty(&text_input->input_methods)) {
299 wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
300 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
301 }
Jan Arne Petersen61381972013-01-31 15:52:21 +0100302}
303
304static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200305text_input_hide_input_panel(struct wl_client *client,
Jan Arne Petersen61381972013-01-31 15:52:21 +0100306 struct wl_resource *resource)
307{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200308 struct text_input *text_input = resource->data;
309 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100310
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200311 text_input->input_panel_visible = 0;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100312
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200313 if (!wl_list_empty(&text_input->input_methods))
Jan Arne Petersen61381972013-01-31 15:52:21 +0100314 wl_signal_emit(&ec->hide_input_panel_signal, ec);
315}
316
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200317static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200318text_input_set_preferred_language(struct wl_client *client,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200319 struct wl_resource *resource,
320 const char *language)
321{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200322 struct text_input *text_input = resource->data;
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200323 struct input_method *input_method, *next;
324
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200325 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200326 if (!input_method->context)
327 continue;
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200328 wl_input_method_context_send_preferred_language(&input_method->context->resource,
329 language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200330 }
331}
332
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200333static const struct wl_text_input_interface text_input_implementation = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200334 text_input_activate,
335 text_input_deactivate,
336 text_input_show_input_panel,
337 text_input_hide_input_panel,
338 text_input_reset,
339 text_input_set_surrounding_text,
340 text_input_set_content_type,
341 text_input_set_cursor_rectangle,
342 text_input_set_preferred_language,
343 text_input_commit_state,
344 text_input_invoke_action
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200345};
346
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200347static void text_input_manager_create_text_input(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200348 struct wl_resource *resource,
Jan Arne Petersen4c265182012-09-09 23:08:30 +0200349 uint32_t id)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200350{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200351 struct text_input_manager *text_input_manager = resource->data;
352 struct text_input *text_input;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200353
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200354 text_input = calloc(1, sizeof *text_input);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200355
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200356 text_input->resource.object.id = id;
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200357 text_input->resource.object.interface = &wl_text_input_interface;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200358 text_input->resource.object.implementation =
359 (void (**)(void)) &text_input_implementation;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200360
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200361 text_input->resource.data = text_input;
362 text_input->resource.destroy = destroy_text_input;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200363
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200364 text_input->ec = text_input_manager->ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200365
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200366 wl_list_init(&text_input->input_methods);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200367
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200368 wl_client_add_resource(client, &text_input->resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200369};
370
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200371static const struct wl_text_input_manager_interface text_input_manager_implementation = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200372 text_input_manager_create_text_input
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200373};
374
375static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200376bind_text_input_manager(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200377 void *data,
378 uint32_t version,
379 uint32_t id)
380{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200381 struct text_input_manager *text_input_manager = data;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200382
383 /* No checking for duplicate binding necessary.
384 * No events have to be sent, so we don't need the return value. */
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200385 wl_client_add_object(client, &wl_text_input_manager_interface,
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200386 &text_input_manager_implementation,
387 id, text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200388}
389
390static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200391text_input_manager_notifier_destroy(struct wl_listener *listener, void *data)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200392{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200393 struct text_input_manager *text_input_manager =
394 container_of(listener, struct text_input_manager, destroy_listener);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200395
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200396 wl_display_remove_global(text_input_manager->ec->wl_display,
397 text_input_manager->text_input_manager_global);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200398
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200399 free(text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200400}
401
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100402static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200403text_input_manager_create(struct weston_compositor *ec)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200404{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200405 struct text_input_manager *text_input_manager;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200406
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200407 text_input_manager = calloc(1, sizeof *text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200408
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200409 text_input_manager->ec = ec;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200410
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200411 text_input_manager->text_input_manager_global =
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200412 wl_display_add_global(ec->wl_display,
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200413 &wl_text_input_manager_interface,
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200414 text_input_manager, bind_text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200415
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200416 text_input_manager->destroy_listener.notify = text_input_manager_notifier_destroy;
417 wl_signal_add(&ec->destroy_signal, &text_input_manager->destroy_listener);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200418}
419
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200420static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200421input_method_context_destroy(struct wl_client *client,
422 struct wl_resource *resource)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200423{
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200424 wl_resource_destroy(resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200425}
426
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200427static void
428input_method_context_commit_string(struct wl_client *client,
429 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100430 uint32_t serial,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100431 const char *text)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200432{
433 struct input_method_context *context = resource->data;
434
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200435 wl_text_input_send_commit_string(&context->model->resource, serial, text);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200436}
437
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200438static void
439input_method_context_preedit_string(struct wl_client *client,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100440 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100441 uint32_t serial,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100442 const char *text,
443 const char *commit)
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200444{
445 struct input_method_context *context = resource->data;
446
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200447 wl_text_input_send_preedit_string(&context->model->resource, serial, text, commit);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100448}
449
450static void
451input_method_context_preedit_styling(struct wl_client *client,
452 struct wl_resource *resource,
453 uint32_t index,
454 uint32_t length,
455 uint32_t style)
456{
457 struct input_method_context *context = resource->data;
458
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200459 wl_text_input_send_preedit_styling(&context->model->resource, index, length, style);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100460}
461
462static void
463input_method_context_preedit_cursor(struct wl_client *client,
464 struct wl_resource *resource,
465 int32_t cursor)
466{
467 struct input_method_context *context = resource->data;
468
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200469 wl_text_input_send_preedit_cursor(&context->model->resource, cursor);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200470}
471
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200472static void
473input_method_context_delete_surrounding_text(struct wl_client *client,
474 struct wl_resource *resource,
475 int32_t index,
476 uint32_t length)
477{
478 struct input_method_context *context = resource->data;
479
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200480 wl_text_input_send_delete_surrounding_text(&context->model->resource, index, length);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200481}
482
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200483static void
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100484input_method_context_cursor_position(struct wl_client *client,
485 struct wl_resource *resource,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100486 int32_t index,
487 int32_t anchor)
488{
489 struct input_method_context *context = resource->data;
490
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200491 wl_text_input_send_cursor_position(&context->model->resource, index, anchor);
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100492}
493
494static void
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100495input_method_context_modifiers_map(struct wl_client *client,
496 struct wl_resource *resource,
497 struct wl_array *map)
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200498{
499 struct input_method_context *context = resource->data;
500
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200501 wl_text_input_send_modifiers_map(&context->model->resource, map);
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100502}
503
504static void
505input_method_context_keysym(struct wl_client *client,
506 struct wl_resource *resource,
507 uint32_t serial,
508 uint32_t time,
509 uint32_t sym,
510 uint32_t state,
511 uint32_t modifiers)
512{
513 struct input_method_context *context = resource->data;
514
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200515 wl_text_input_send_keysym(&context->model->resource, serial, time,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200516 sym, state, modifiers);
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200517}
518
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100519static void
520unbind_keyboard(struct wl_resource *resource)
521{
522 struct input_method_context *context = resource->data;
523
524 input_method_context_end_keyboard_grab(context);
525 context->keyboard = NULL;
526
527 free(resource);
528}
529
530static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400531input_method_context_grab_key(struct weston_keyboard_grab *grab,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100532 uint32_t time, uint32_t key, uint32_t state_w)
533{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400534 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100535 struct wl_display *display;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100536 uint32_t serial;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100537
538 if (!keyboard->input_method_resource)
539 return;
540
541 display = wl_client_get_display(keyboard->input_method_resource->client);
542 serial = wl_display_next_serial(display);
543 wl_keyboard_send_key(keyboard->input_method_resource,
544 serial, time, key, state_w);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100545}
546
547static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400548input_method_context_grab_modifier(struct weston_keyboard_grab *grab, uint32_t serial,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100549 uint32_t mods_depressed, uint32_t mods_latched,
550 uint32_t mods_locked, uint32_t group)
551{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400552 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100553
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100554 if (!keyboard->input_method_resource)
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100555 return;
556
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100557 wl_keyboard_send_modifiers(keyboard->input_method_resource,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100558 serial, mods_depressed, mods_latched,
559 mods_locked, group);
560}
561
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400562static const struct weston_keyboard_grab_interface input_method_context_grab = {
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100563 input_method_context_grab_key,
564 input_method_context_grab_modifier,
565};
566
567static void
568input_method_context_grab_keyboard(struct wl_client *client,
569 struct wl_resource *resource,
570 uint32_t id)
571{
572 struct input_method_context *context = resource->data;
573 struct wl_resource *cr;
574 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400575 struct weston_keyboard *keyboard = seat->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100576
577 cr = wl_client_add_object(client, &wl_keyboard_interface,
578 NULL, id, context);
579 cr->destroy = unbind_keyboard;
580
581 context->keyboard = cr;
582
583 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
584 seat->xkb_info.keymap_fd,
585 seat->xkb_info.keymap_size);
586
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400587 if (keyboard->grab != &keyboard->default_grab) {
588 weston_keyboard_end_grab(keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100589 }
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400590 weston_keyboard_start_grab(keyboard, &keyboard->input_method_grab);
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100591 keyboard->input_method_resource = cr;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100592}
593
Jan Arne Petersen337df952012-11-18 19:06:46 +0100594static void
595input_method_context_key(struct wl_client *client,
596 struct wl_resource *resource,
597 uint32_t serial,
598 uint32_t time,
599 uint32_t key,
600 uint32_t state_w)
601{
602 struct input_method_context *context = resource->data;
603 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400604 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400605 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100606
607 default_grab->interface->key(default_grab, time, key, state_w);
608}
609
610static void
611input_method_context_modifiers(struct wl_client *client,
612 struct wl_resource *resource,
613 uint32_t serial,
614 uint32_t mods_depressed,
615 uint32_t mods_latched,
616 uint32_t mods_locked,
617 uint32_t group)
618{
619 struct input_method_context *context = resource->data;
620
621 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400622 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400623 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100624
625 default_grab->interface->modifiers(default_grab,
626 serial, mods_depressed,
627 mods_latched, mods_locked,
628 group);
629}
630
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200631static void
632input_method_context_language(struct wl_client *client,
633 struct wl_resource *resource,
634 uint32_t serial,
635 const char *language)
636{
637 struct input_method_context *context = resource->data;
638
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200639 wl_text_input_send_language(&context->model->resource, serial, language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200640}
641
642static void
643input_method_context_text_direction(struct wl_client *client,
644 struct wl_resource *resource,
645 uint32_t serial,
646 uint32_t direction)
647{
648 struct input_method_context *context = resource->data;
649
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200650 wl_text_input_send_text_direction(&context->model->resource, serial, direction);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200651}
652
653
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200654static const struct wl_input_method_context_interface input_method_context_implementation = {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200655 input_method_context_destroy,
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200656 input_method_context_commit_string,
657 input_method_context_preedit_string,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100658 input_method_context_preedit_styling,
659 input_method_context_preedit_cursor,
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200660 input_method_context_delete_surrounding_text,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100661 input_method_context_cursor_position,
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100662 input_method_context_modifiers_map,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100663 input_method_context_keysym,
Jan Arne Petersen337df952012-11-18 19:06:46 +0100664 input_method_context_grab_keyboard,
665 input_method_context_key,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200666 input_method_context_modifiers,
667 input_method_context_language,
668 input_method_context_text_direction
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200669};
670
671static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200672destroy_input_method_context(struct wl_resource *resource)
673{
674 struct input_method_context *context = resource->data;
675
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100676 if (context->keyboard) {
677 wl_resource_destroy(context->keyboard);
678 }
679
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200680 free(context);
681}
682
683static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200684input_method_context_create(struct text_input *model,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200685 struct input_method *input_method)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200686{
687 struct input_method_context *context;
688
689 if (!input_method->input_method_binding)
690 return;
691
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100692 context = calloc(1, sizeof *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200693 if (context == NULL)
694 return;
695
696 context->resource.destroy = destroy_input_method_context;
697 context->resource.object.id = 0;
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200698 context->resource.object.interface = &wl_input_method_context_interface;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200699 context->resource.object.implementation =
700 (void (**)(void)) &input_method_context_implementation;
701 context->resource.data = context;
702 wl_signal_init(&context->resource.destroy_signal);
703
704 context->model = model;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100705 context->input_method = input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200706 input_method->context = context;
707
708 wl_client_add_resource(input_method->input_method_binding->client, &context->resource);
709
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200710 wl_input_method_send_activate(input_method->input_method_binding, &context->resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200711}
712
713static void
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100714input_method_context_end_keyboard_grab(struct input_method_context *context)
715{
Kristian Høgsberge3148752013-05-06 23:19:49 -0400716 struct weston_keyboard_grab *grab =
717 &context->input_method->seat->keyboard->input_method_grab;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400718 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100719
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100720 if (!grab->keyboard)
721 return;
722
723 if (grab->keyboard->grab == grab)
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400724 weston_keyboard_end_grab(grab->keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100725
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100726 keyboard->input_method_resource = NULL;
727}
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100728
729static void
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200730unbind_input_method(struct wl_resource *resource)
731{
732 struct input_method *input_method = resource->data;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100733 struct text_backend *text_backend = input_method->text_backend;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200734
735 input_method->input_method_binding = NULL;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200736 input_method->context = NULL;
737
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100738 text_backend->input_method.binding = NULL;
739
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200740 free(resource);
741}
742
743static void
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200744bind_input_method(struct wl_client *client,
745 void *data,
746 uint32_t version,
747 uint32_t id)
748{
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200749 struct input_method *input_method = data;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100750 struct text_backend *text_backend = input_method->text_backend;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200751 struct wl_resource *resource;
752
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200753 resource = wl_client_add_object(client, &wl_input_method_interface,
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200754 NULL,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200755 id, input_method);
756
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200757 if (input_method->input_method_binding != NULL) {
758 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
759 "interface object already bound");
760 wl_resource_destroy(resource);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200761 return;
762 }
763
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200764 if (text_backend->input_method.client != client) {
765 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
766 "permission to bind desktop_shell denied");
767 wl_resource_destroy(resource);
768 return;
769 }
770
771 resource->destroy = unbind_input_method;
772 input_method->input_method_binding = resource;
773
774 text_backend->input_method.binding = resource;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200775}
776
777static void
778input_method_notifier_destroy(struct wl_listener *listener, void *data)
779{
Kristian Høgsbergf97f3792012-07-22 11:51:42 -0400780 struct input_method *input_method =
781 container_of(listener, struct input_method, destroy_listener);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200782
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200783 if (input_method->model)
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200784 deactivate_text_input(input_method->model, input_method);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200785
786 wl_display_remove_global(input_method->seat->compositor->wl_display,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200787 input_method->input_method_global);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200788
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200789 free(input_method);
790}
791
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200792static void
793handle_keyboard_focus(struct wl_listener *listener, void *data)
794{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400795 struct weston_keyboard *keyboard = data;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200796 struct input_method *input_method =
797 container_of(listener, struct input_method, keyboard_focus_listener);
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400798 struct weston_surface *surface = keyboard->focus;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200799
800 if (!input_method->model)
801 return;
802
803 if (!surface || input_method->model->surface != surface)
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200804 deactivate_text_input(input_method->model,
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200805 input_method);
806}
807
808static void
809input_method_init_seat(struct weston_seat *seat)
810{
811 if (seat->input_method->focus_listener_initialized)
812 return;
813
Kristian Høgsberg2bf87622013-05-07 23:17:41 -0400814 if (seat->keyboard) {
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200815 seat->input_method->keyboard_focus_listener.notify = handle_keyboard_focus;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400816 wl_signal_add(&seat->keyboard->focus_signal, &seat->input_method->keyboard_focus_listener);
817 seat->keyboard->input_method_grab.interface = &input_method_context_grab;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200818 }
819
820 seat->input_method->focus_listener_initialized = 1;
821}
822
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100823static void
824handle_input_method_sigchld(struct weston_process *process, int status)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200825{
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100826 struct text_backend *text_backend =
827 container_of(process, struct text_backend, input_method.process);
828
829 text_backend->input_method.process.pid = 0;
830 text_backend->input_method.client = NULL;
831}
832
833static void
834launch_input_method(struct text_backend *text_backend)
835{
836 if (text_backend->input_method.binding)
837 return;
838
839 if (!text_backend->input_method.path)
840 return;
841
842 if (text_backend->input_method.process.pid != 0)
843 return;
844
845 text_backend->input_method.client = weston_client_launch(text_backend->compositor,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200846 &text_backend->input_method.process,
847 text_backend->input_method.path,
848 handle_input_method_sigchld);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100849
850 if (!text_backend->input_method.client)
851 weston_log("not able to start %s\n", text_backend->input_method.path);
852}
853
854static void
855handle_seat_created(struct wl_listener *listener,
856 void *data)
857{
858 struct weston_seat *seat = data;
859 struct text_backend *text_backend =
860 container_of(listener, struct text_backend,
861 seat_created_listener);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200862 struct input_method *input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100863 struct weston_compositor *ec = seat->compositor;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200864
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200865 input_method = calloc(1, sizeof *input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200866
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200867 input_method->seat = seat;
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200868 input_method->model = NULL;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200869 input_method->focus_listener_initialized = 0;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200870 input_method->context = NULL;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100871 input_method->text_backend = text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200872
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200873 input_method->input_method_global =
874 wl_display_add_global(ec->wl_display,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200875 &wl_input_method_interface,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200876 input_method, bind_input_method);
877
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200878 input_method->destroy_listener.notify = input_method_notifier_destroy;
Kristian Høgsberg49124542013-05-06 22:27:40 -0400879 wl_signal_add(&seat->destroy_signal, &input_method->destroy_listener);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200880
881 seat->input_method = input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100882
883 launch_input_method(text_backend);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200884}
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200885
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100886static void
887text_backend_configuration(struct text_backend *text_backend)
888{
Ossama Othmana50e6e42013-05-14 09:48:26 -0700889 int config_fd;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100890 char *path = NULL;
891
892 struct config_key input_method_keys[] = {
893 { "path", CONFIG_KEY_STRING, &path }
894 };
895
896 struct config_section cs[] = {
897 { "input-method", input_method_keys, ARRAY_LENGTH(input_method_keys), NULL }
898 };
899
Ossama Othmana50e6e42013-05-14 09:48:26 -0700900 config_fd = open_config_file("weston.ini");
901 parse_config_file(config_fd, cs, ARRAY_LENGTH(cs), text_backend);
902 close(config_fd);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100903
904 if (path)
905 text_backend->input_method.path = path;
906 else
907 text_backend->input_method.path = strdup(LIBEXECDIR "/weston-keyboard");
908}
909
910static void
911text_backend_notifier_destroy(struct wl_listener *listener, void *data)
912{
913 struct text_backend *text_backend =
914 container_of(listener, struct text_backend, destroy_listener);
915
916 if (text_backend->input_method.client)
917 wl_client_destroy(text_backend->input_method.client);
918
919 free(text_backend->input_method.path);
920
921 free(text_backend);
922}
923
924
925WL_EXPORT int
926text_backend_init(struct weston_compositor *ec)
927{
928 struct text_backend *text_backend;
929
930 text_backend = calloc(1, sizeof(*text_backend));
931
932 text_backend->compositor = ec;
933
934 text_backend->seat_created_listener.notify = handle_seat_created;
935 wl_signal_add(&ec->seat_created_signal,
936 &text_backend->seat_created_listener);
937
938 text_backend->destroy_listener.notify = text_backend_notifier_destroy;
939 wl_signal_add(&ec->destroy_signal, &text_backend->destroy_listener);
940
941 text_backend_configuration(text_backend);
942
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200943 text_input_manager_create(ec);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100944
945 return 0;
946}