blob: 107ccd63d85ed61524cf8ab669b8fb36756e60a3 [file] [log] [blame]
Jan Arne Petersen1f17be42012-06-21 21:52:18 +02001/*
2 * Copyright © 2012 Openismus GmbH
Jan Arne Petersen4c265182012-09-09 23:08:30 +02003 * Copyright © 2012 Intel Corporation
Jan Arne Petersen1f17be42012-06-21 21:52:18 +02004 *
5 * Permission to use, copy, modify, distribute, and sell this software and
6 * its documentation for any purpose is hereby granted without fee, provided
7 * that the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of the copyright holders not be used in
10 * advertising or publicity pertaining to distribution of the software
11 * without specific, written prior permission. The copyright holders make
12 * no representations about the suitability of this software for any
13 * purpose. It is provided "as is" without express or implied warranty.
14 *
15 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
16 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
19 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
20 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 */
23
Daniel Stonec228e232013-05-22 18:03:19 +030024#include "config.h"
25
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020026#include <stdlib.h>
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010027#include <string.h>
Ossama Othmana50e6e42013-05-14 09:48:26 -070028#include <unistd.h>
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -030029#include <time.h>
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020030
31#include "compositor.h"
32#include "text-server-protocol.h"
Jan Arne Petersen30b66ef2012-09-09 23:08:41 +020033#include "input-method-server-protocol.h"
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020034
35struct input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020036struct input_method_context;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010037struct text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020038
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020039struct text_input {
Jason Ekstrand89d31992013-06-14 10:07:59 -050040 struct wl_resource *resource;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020041
Jan Arne Petersene829adc2012-08-10 16:47:22 +020042 struct weston_compositor *ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020043
Jan Arne Petersene829adc2012-08-10 16:47:22 +020044 struct wl_list input_methods;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +020045
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -040046 struct weston_surface *surface;
Jan Arne Petersen61381972013-01-31 15:52:21 +010047
Jan Arne Petersen14da96b2013-04-18 16:47:28 +020048 pixman_box32_t cursor_rectangle;
49
Jan Arne Petersen61381972013-01-31 15:52:21 +010050 uint32_t input_panel_visible;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020051};
52
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020053struct text_input_manager {
54 struct wl_global *text_input_manager_global;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020055 struct wl_listener destroy_listener;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020056
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +020057 struct weston_compositor *ec;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +020058};
59
60struct input_method {
61 struct wl_resource *input_method_binding;
62 struct wl_global *input_method_global;
63 struct wl_listener destroy_listener;
64
65 struct weston_seat *seat;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020066 struct text_input *model;
Jan Arne Petersene829adc2012-08-10 16:47:22 +020067
68 struct wl_list link;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +020069
70 struct wl_listener keyboard_focus_listener;
71
72 int focus_listener_initialized;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020073
74 struct input_method_context *context;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010075
76 struct text_backend *text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020077};
78
Jan Arne Petersen620cd622012-09-09 23:08:32 +020079struct input_method_context {
Jason Ekstrand89d31992013-06-14 10:07:59 -050080 struct wl_resource *resource;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020081
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020082 struct text_input *model;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +010083 struct input_method *input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020084
85 struct wl_list link;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +010086
87 struct wl_resource *keyboard;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020088};
89
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010090struct text_backend {
91 struct weston_compositor *compositor;
92
93 struct {
94 char *path;
95 struct wl_resource *binding;
96 struct weston_process process;
97 struct wl_client *client;
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -030098
99 unsigned deathcount;
100 uint32_t deathstamp;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100101 } input_method;
102
103 struct wl_listener seat_created_listener;
104 struct wl_listener destroy_listener;
105};
106
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200107static void input_method_context_create(struct text_input *model,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200108 struct input_method *input_method);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100109static void input_method_context_end_keyboard_grab(struct input_method_context *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200110
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200111static void input_method_init_seat(struct weston_seat *seat);
112
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200113static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200114deactivate_text_input(struct text_input *text_input,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200115 struct input_method *input_method)
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200116{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200117 struct weston_compositor *ec = text_input->ec;
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200118
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200119 if (input_method->model == text_input) {
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100120 if (input_method->context && input_method->input_method_binding) {
121 input_method_context_end_keyboard_grab(input_method->context);
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200122 wl_input_method_send_deactivate(input_method->input_method_binding,
Jason Ekstrand89d31992013-06-14 10:07:59 -0500123 input_method->context->resource);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100124 }
125
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200126 wl_list_remove(&input_method->link);
127 input_method->model = NULL;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200128 input_method->context = NULL;
Kristian Høgsbergf97f3792012-07-22 11:51:42 -0400129 wl_signal_emit(&ec->hide_input_panel_signal, ec);
Jason Ekstrand89d31992013-06-14 10:07:59 -0500130 wl_text_input_send_leave(text_input->resource);
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200131 }
132}
133
134static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200135destroy_text_input(struct wl_resource *resource)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200136{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500137 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200138 struct input_method *input_method, *next;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200139
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200140 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link)
141 deactivate_text_input(text_input, input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200142
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200143 free(text_input);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200144}
145
146static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200147text_input_set_surrounding_text(struct wl_client *client,
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200148 struct wl_resource *resource,
Jan Arne Petersencb08f4d2012-09-09 23:08:40 +0200149 const char *text,
150 uint32_t cursor,
151 uint32_t anchor)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200152{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500153 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200154 struct input_method *input_method, *next;
155
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200156 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200157 if (!input_method->context)
158 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500159 wl_input_method_context_send_surrounding_text(input_method->context->resource,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200160 text,
161 cursor,
162 anchor);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200163 }
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200164}
165
166static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200167text_input_activate(struct wl_client *client,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200168 struct wl_resource *resource,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200169 struct wl_resource *seat,
170 struct wl_resource *surface)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200171{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500172 struct text_input *text_input = wl_resource_get_user_data(resource);
Jason Ekstrand44a38632013-06-14 10:08:00 -0500173 struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200174 struct input_method *input_method = weston_seat->input_method;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200175 struct text_input *old = weston_seat->input_method->model;
176 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200177
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200178 if (old == text_input)
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200179 return;
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200180
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200181 if (old) {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200182 deactivate_text_input(old,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200183 weston_seat->input_method);
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200184 }
185
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200186 input_method->model = text_input;
187 wl_list_insert(&text_input->input_methods, &input_method->link);
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200188 input_method_init_seat(weston_seat);
189
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -0500190 text_input->surface = wl_resource_get_user_data(surface);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200191
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200192 input_method_context_create(text_input, input_method);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200193
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200194 if (text_input->input_panel_visible) {
195 wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
196 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
197 }
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200198
Jason Ekstrand89d31992013-06-14 10:07:59 -0500199 wl_text_input_send_enter(text_input->resource, text_input->surface->resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200200}
201
202static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200203text_input_deactivate(struct wl_client *client,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200204 struct wl_resource *resource,
205 struct wl_resource *seat)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200206{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500207 struct text_input *text_input = wl_resource_get_user_data(resource);
Jason Ekstrand44a38632013-06-14 10:08:00 -0500208 struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200209
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200210 deactivate_text_input(text_input,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200211 weston_seat->input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200212}
213
214static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200215text_input_reset(struct wl_client *client,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200216 struct wl_resource *resource)
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200217{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500218 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200219 struct input_method *input_method, *next;
220
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200221 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200222 if (!input_method->context)
223 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500224 wl_input_method_context_send_reset(input_method->context->resource);
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200225 }
226}
227
228static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200229text_input_set_cursor_rectangle(struct wl_client *client,
Jan Arne Petersen7ef8eff2013-04-18 16:47:23 +0200230 struct wl_resource *resource,
231 int32_t x,
232 int32_t y,
233 int32_t width,
234 int32_t height)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200235{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500236 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200237 struct weston_compositor *ec = text_input->ec;
238
239 text_input->cursor_rectangle.x1 = x;
240 text_input->cursor_rectangle.y1 = y;
241 text_input->cursor_rectangle.x2 = x + width;
242 text_input->cursor_rectangle.y2 = y + height;
243
244 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200245}
246
247static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200248text_input_set_content_type(struct wl_client *client,
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100249 struct wl_resource *resource,
250 uint32_t hint,
251 uint32_t purpose)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200252{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500253 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100254 struct input_method *input_method, *next;
255
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200256 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100257 if (!input_method->context)
258 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500259 wl_input_method_context_send_content_type(input_method->context->resource, hint, purpose);
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100260 }
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200261}
262
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100263static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200264text_input_invoke_action(struct wl_client *client,
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100265 struct wl_resource *resource,
266 uint32_t button,
267 uint32_t index)
268{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500269 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100270 struct input_method *input_method, *next;
271
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200272 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100273 if (!input_method->context)
274 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500275 wl_input_method_context_send_invoke_action(input_method->context->resource, button, index);
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100276 }
277}
278
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100279static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200280text_input_commit_state(struct wl_client *client,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200281 struct wl_resource *resource,
282 uint32_t serial)
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100283{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500284 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100285 struct input_method *input_method, *next;
286
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200287 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100288 if (!input_method->context)
289 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500290 wl_input_method_context_send_commit_state(input_method->context->resource, serial);
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100291 }
292}
293
Jan Arne Petersen61381972013-01-31 15:52:21 +0100294static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200295text_input_show_input_panel(struct wl_client *client,
Jan Arne Petersen61381972013-01-31 15:52:21 +0100296 struct wl_resource *resource)
297{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500298 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200299 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100300
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200301 text_input->input_panel_visible = 1;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100302
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200303 if (!wl_list_empty(&text_input->input_methods)) {
304 wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
305 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
306 }
Jan Arne Petersen61381972013-01-31 15:52:21 +0100307}
308
309static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200310text_input_hide_input_panel(struct wl_client *client,
Jan Arne Petersen61381972013-01-31 15:52:21 +0100311 struct wl_resource *resource)
312{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500313 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200314 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100315
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200316 text_input->input_panel_visible = 0;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100317
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200318 if (!wl_list_empty(&text_input->input_methods))
Jan Arne Petersen61381972013-01-31 15:52:21 +0100319 wl_signal_emit(&ec->hide_input_panel_signal, ec);
320}
321
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200322static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200323text_input_set_preferred_language(struct wl_client *client,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200324 struct wl_resource *resource,
325 const char *language)
326{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500327 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200328 struct input_method *input_method, *next;
329
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200330 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200331 if (!input_method->context)
332 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500333 wl_input_method_context_send_preferred_language(input_method->context->resource,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200334 language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200335 }
336}
337
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200338static const struct wl_text_input_interface text_input_implementation = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200339 text_input_activate,
340 text_input_deactivate,
341 text_input_show_input_panel,
342 text_input_hide_input_panel,
343 text_input_reset,
344 text_input_set_surrounding_text,
345 text_input_set_content_type,
346 text_input_set_cursor_rectangle,
347 text_input_set_preferred_language,
348 text_input_commit_state,
349 text_input_invoke_action
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200350};
351
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200352static void text_input_manager_create_text_input(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200353 struct wl_resource *resource,
Jan Arne Petersen4c265182012-09-09 23:08:30 +0200354 uint32_t id)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200355{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500356 struct text_input_manager *text_input_manager = wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200357 struct text_input *text_input;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200358
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200359 text_input = calloc(1, sizeof *text_input);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200360
Jason Ekstranda85118c2013-06-27 20:17:02 -0500361 text_input->resource =
362 wl_resource_create(client, &wl_text_input_interface, 1, id);
363 wl_resource_set_implementation(text_input->resource,
364 &text_input_implementation,
365 text_input, destroy_text_input);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200366
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200367 text_input->ec = text_input_manager->ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200368
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200369 wl_list_init(&text_input->input_methods);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200370};
371
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200372static const struct wl_text_input_manager_interface text_input_manager_implementation = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200373 text_input_manager_create_text_input
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200374};
375
376static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200377bind_text_input_manager(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200378 void *data,
379 uint32_t version,
380 uint32_t id)
381{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200382 struct text_input_manager *text_input_manager = data;
Jason Ekstranda85118c2013-06-27 20:17:02 -0500383 struct wl_resource *resource;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200384
Jason Ekstranda85118c2013-06-27 20:17:02 -0500385 /* No checking for duplicate binding necessary. */
386 resource =
387 wl_resource_create(client,
388 &wl_text_input_manager_interface, 1, id);
389 if (resource)
390 wl_resource_set_implementation(resource,
391 &text_input_manager_implementation,
392 text_input_manager, NULL);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200393}
394
395static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200396text_input_manager_notifier_destroy(struct wl_listener *listener, void *data)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200397{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200398 struct text_input_manager *text_input_manager =
399 container_of(listener, struct text_input_manager, destroy_listener);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200400
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400401 wl_global_destroy(text_input_manager->text_input_manager_global);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200402
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200403 free(text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200404}
405
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100406static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200407text_input_manager_create(struct weston_compositor *ec)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200408{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200409 struct text_input_manager *text_input_manager;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200410
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200411 text_input_manager = calloc(1, sizeof *text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200412
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200413 text_input_manager->ec = ec;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200414
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200415 text_input_manager->text_input_manager_global =
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400416 wl_global_create(ec->wl_display,
417 &wl_text_input_manager_interface, 1,
418 text_input_manager, bind_text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200419
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200420 text_input_manager->destroy_listener.notify = text_input_manager_notifier_destroy;
421 wl_signal_add(&ec->destroy_signal, &text_input_manager->destroy_listener);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200422}
423
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200424static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200425input_method_context_destroy(struct wl_client *client,
426 struct wl_resource *resource)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200427{
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200428 wl_resource_destroy(resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200429}
430
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200431static void
432input_method_context_commit_string(struct wl_client *client,
433 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100434 uint32_t serial,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100435 const char *text)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200436{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500437 struct input_method_context *context =
438 wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200439
Jason Ekstrand89d31992013-06-14 10:07:59 -0500440 wl_text_input_send_commit_string(context->model->resource, serial, text);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200441}
442
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200443static void
444input_method_context_preedit_string(struct wl_client *client,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100445 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100446 uint32_t serial,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100447 const char *text,
448 const char *commit)
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200449{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500450 struct input_method_context *context =
451 wl_resource_get_user_data(resource);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200452
Jason Ekstrand89d31992013-06-14 10:07:59 -0500453 wl_text_input_send_preedit_string(context->model->resource, serial, text, commit);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100454}
455
456static void
457input_method_context_preedit_styling(struct wl_client *client,
458 struct wl_resource *resource,
459 uint32_t index,
460 uint32_t length,
461 uint32_t style)
462{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500463 struct input_method_context *context =
464 wl_resource_get_user_data(resource);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100465
Jason Ekstrand89d31992013-06-14 10:07:59 -0500466 wl_text_input_send_preedit_styling(context->model->resource, index, length, style);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100467}
468
469static void
470input_method_context_preedit_cursor(struct wl_client *client,
471 struct wl_resource *resource,
472 int32_t cursor)
473{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500474 struct input_method_context *context =
475 wl_resource_get_user_data(resource);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100476
Jason Ekstrand89d31992013-06-14 10:07:59 -0500477 wl_text_input_send_preedit_cursor(context->model->resource, cursor);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200478}
479
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200480static void
481input_method_context_delete_surrounding_text(struct wl_client *client,
482 struct wl_resource *resource,
483 int32_t index,
484 uint32_t length)
485{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500486 struct input_method_context *context =
487 wl_resource_get_user_data(resource);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200488
Jason Ekstrand89d31992013-06-14 10:07:59 -0500489 wl_text_input_send_delete_surrounding_text(context->model->resource, index, length);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200490}
491
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200492static void
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100493input_method_context_cursor_position(struct wl_client *client,
494 struct wl_resource *resource,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100495 int32_t index,
496 int32_t anchor)
497{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500498 struct input_method_context *context =
499 wl_resource_get_user_data(resource);
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100500
Jason Ekstrand89d31992013-06-14 10:07:59 -0500501 wl_text_input_send_cursor_position(context->model->resource, index, anchor);
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100502}
503
504static void
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100505input_method_context_modifiers_map(struct wl_client *client,
506 struct wl_resource *resource,
507 struct wl_array *map)
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200508{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500509 struct input_method_context *context =
510 wl_resource_get_user_data(resource);
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200511
Jason Ekstrand89d31992013-06-14 10:07:59 -0500512 wl_text_input_send_modifiers_map(context->model->resource, map);
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100513}
514
515static void
516input_method_context_keysym(struct wl_client *client,
517 struct wl_resource *resource,
518 uint32_t serial,
519 uint32_t time,
520 uint32_t sym,
521 uint32_t state,
522 uint32_t modifiers)
523{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500524 struct input_method_context *context =
525 wl_resource_get_user_data(resource);
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100526
Jason Ekstrand89d31992013-06-14 10:07:59 -0500527 wl_text_input_send_keysym(context->model->resource, serial, time,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200528 sym, state, modifiers);
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200529}
530
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100531static void
532unbind_keyboard(struct wl_resource *resource)
533{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500534 struct input_method_context *context =
535 wl_resource_get_user_data(resource);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100536
537 input_method_context_end_keyboard_grab(context);
538 context->keyboard = NULL;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100539}
540
541static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400542input_method_context_grab_key(struct weston_keyboard_grab *grab,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100543 uint32_t time, uint32_t key, uint32_t state_w)
544{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400545 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100546 struct wl_display *display;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100547 uint32_t serial;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100548
549 if (!keyboard->input_method_resource)
550 return;
551
Jason Ekstrand89d31992013-06-14 10:07:59 -0500552 display = wl_client_get_display(wl_resource_get_client(keyboard->input_method_resource));
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100553 serial = wl_display_next_serial(display);
554 wl_keyboard_send_key(keyboard->input_method_resource,
555 serial, time, key, state_w);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100556}
557
558static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400559input_method_context_grab_modifier(struct weston_keyboard_grab *grab, uint32_t serial,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100560 uint32_t mods_depressed, uint32_t mods_latched,
561 uint32_t mods_locked, uint32_t group)
562{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400563 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100564
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100565 if (!keyboard->input_method_resource)
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100566 return;
567
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100568 wl_keyboard_send_modifiers(keyboard->input_method_resource,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100569 serial, mods_depressed, mods_latched,
570 mods_locked, group);
571}
572
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200573static void
574input_method_context_grab_cancel(struct weston_keyboard_grab *grab)
575{
576 weston_keyboard_end_grab(grab->keyboard);
577}
578
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400579static const struct weston_keyboard_grab_interface input_method_context_grab = {
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100580 input_method_context_grab_key,
581 input_method_context_grab_modifier,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200582 input_method_context_grab_cancel,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100583};
584
585static void
586input_method_context_grab_keyboard(struct wl_client *client,
587 struct wl_resource *resource,
588 uint32_t id)
589{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500590 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100591 struct wl_resource *cr;
592 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400593 struct weston_keyboard *keyboard = seat->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100594
Jason Ekstranda85118c2013-06-27 20:17:02 -0500595 cr = wl_resource_create(client, &wl_keyboard_interface, 1, id);
596 wl_resource_set_implementation(cr, NULL, context, unbind_keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100597
598 context->keyboard = cr;
599
600 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +0000601 seat->xkb_info->keymap_fd,
602 seat->xkb_info->keymap_size);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100603
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400604 if (keyboard->grab != &keyboard->default_grab) {
605 weston_keyboard_end_grab(keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100606 }
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400607 weston_keyboard_start_grab(keyboard, &keyboard->input_method_grab);
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100608 keyboard->input_method_resource = cr;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100609}
610
Jan Arne Petersen337df952012-11-18 19:06:46 +0100611static void
612input_method_context_key(struct wl_client *client,
613 struct wl_resource *resource,
614 uint32_t serial,
615 uint32_t time,
616 uint32_t key,
617 uint32_t state_w)
618{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500619 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen337df952012-11-18 19:06:46 +0100620 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->key(default_grab, time, key, state_w);
625}
626
627static void
628input_method_context_modifiers(struct wl_client *client,
629 struct wl_resource *resource,
630 uint32_t serial,
631 uint32_t mods_depressed,
632 uint32_t mods_latched,
633 uint32_t mods_locked,
634 uint32_t group)
635{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500636 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen337df952012-11-18 19:06:46 +0100637
638 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400639 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400640 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100641
642 default_grab->interface->modifiers(default_grab,
643 serial, mods_depressed,
644 mods_latched, mods_locked,
645 group);
646}
647
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200648static void
649input_method_context_language(struct wl_client *client,
650 struct wl_resource *resource,
651 uint32_t serial,
652 const char *language)
653{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500654 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200655
Jason Ekstrand89d31992013-06-14 10:07:59 -0500656 wl_text_input_send_language(context->model->resource, serial, language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200657}
658
659static void
660input_method_context_text_direction(struct wl_client *client,
661 struct wl_resource *resource,
662 uint32_t serial,
663 uint32_t direction)
664{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500665 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200666
Jason Ekstrand89d31992013-06-14 10:07:59 -0500667 wl_text_input_send_text_direction(context->model->resource, serial, direction);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200668}
669
670
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200671static const struct wl_input_method_context_interface input_method_context_implementation = {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200672 input_method_context_destroy,
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200673 input_method_context_commit_string,
674 input_method_context_preedit_string,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100675 input_method_context_preedit_styling,
676 input_method_context_preedit_cursor,
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200677 input_method_context_delete_surrounding_text,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100678 input_method_context_cursor_position,
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100679 input_method_context_modifiers_map,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100680 input_method_context_keysym,
Jan Arne Petersen337df952012-11-18 19:06:46 +0100681 input_method_context_grab_keyboard,
682 input_method_context_key,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200683 input_method_context_modifiers,
684 input_method_context_language,
685 input_method_context_text_direction
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200686};
687
688static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200689destroy_input_method_context(struct wl_resource *resource)
690{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500691 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200692
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100693 if (context->keyboard) {
694 wl_resource_destroy(context->keyboard);
695 }
696
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200697 free(context);
698}
699
700static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200701input_method_context_create(struct text_input *model,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200702 struct input_method *input_method)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200703{
704 struct input_method_context *context;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500705 struct wl_resource *binding;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200706
707 if (!input_method->input_method_binding)
708 return;
709
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100710 context = calloc(1, sizeof *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200711 if (context == NULL)
712 return;
713
Jason Ekstrand89d31992013-06-14 10:07:59 -0500714 binding = input_method->input_method_binding;
Jason Ekstranda85118c2013-06-27 20:17:02 -0500715 context->resource =
716 wl_resource_create(wl_resource_get_client(binding),
717 &wl_input_method_context_interface, 1, 0);
718 wl_resource_set_implementation(context->resource,
719 &input_method_context_implementation,
720 context, destroy_input_method_context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200721
722 context->model = model;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100723 context->input_method = input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200724 input_method->context = context;
725
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200726
Jason Ekstrand89d31992013-06-14 10:07:59 -0500727 wl_input_method_send_activate(binding, context->resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200728}
729
730static void
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100731input_method_context_end_keyboard_grab(struct input_method_context *context)
732{
Kristian Høgsberge3148752013-05-06 23:19:49 -0400733 struct weston_keyboard_grab *grab =
734 &context->input_method->seat->keyboard->input_method_grab;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400735 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100736
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100737 if (!grab->keyboard)
738 return;
739
740 if (grab->keyboard->grab == grab)
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400741 weston_keyboard_end_grab(grab->keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100742
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100743 keyboard->input_method_resource = NULL;
744}
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100745
746static void
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200747unbind_input_method(struct wl_resource *resource)
748{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500749 struct input_method *input_method = wl_resource_get_user_data(resource);
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
752 input_method->input_method_binding = NULL;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200753 input_method->context = NULL;
754
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100755 text_backend->input_method.binding = NULL;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200756}
757
758static void
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200759bind_input_method(struct wl_client *client,
760 void *data,
761 uint32_t version,
762 uint32_t id)
763{
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200764 struct input_method *input_method = data;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100765 struct text_backend *text_backend = input_method->text_backend;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200766 struct wl_resource *resource;
767
Jason Ekstranda85118c2013-06-27 20:17:02 -0500768 resource =
769 wl_resource_create(client, &wl_input_method_interface, 1, id);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200770
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200771 if (input_method->input_method_binding != NULL) {
772 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
773 "interface object already bound");
774 wl_resource_destroy(resource);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200775 return;
776 }
777
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200778 if (text_backend->input_method.client != client) {
779 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
Eduardo Lima (Etrunko)a2ce68f2013-05-10 17:50:36 -0300780 "permission to bind input_method denied");
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200781 wl_resource_destroy(resource);
782 return;
783 }
784
Jason Ekstranda85118c2013-06-27 20:17:02 -0500785 wl_resource_set_implementation(resource, NULL, input_method,
786 unbind_input_method);
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200787 input_method->input_method_binding = resource;
788
789 text_backend->input_method.binding = resource;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200790}
791
792static void
793input_method_notifier_destroy(struct wl_listener *listener, void *data)
794{
Kristian Høgsbergf97f3792012-07-22 11:51:42 -0400795 struct input_method *input_method =
796 container_of(listener, struct input_method, destroy_listener);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200797
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200798 if (input_method->model)
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200799 deactivate_text_input(input_method->model, input_method);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200800
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400801 wl_global_destroy(input_method->input_method_global);
Rob Bradfordead3ef82013-07-24 16:57:32 +0100802 wl_list_remove(&input_method->destroy_listener.link);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200803
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200804 free(input_method);
805}
806
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200807static void
808handle_keyboard_focus(struct wl_listener *listener, void *data)
809{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400810 struct weston_keyboard *keyboard = data;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200811 struct input_method *input_method =
812 container_of(listener, struct input_method, keyboard_focus_listener);
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400813 struct weston_surface *surface = keyboard->focus;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200814
815 if (!input_method->model)
816 return;
817
818 if (!surface || input_method->model->surface != surface)
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200819 deactivate_text_input(input_method->model,
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200820 input_method);
821}
822
823static void
824input_method_init_seat(struct weston_seat *seat)
825{
826 if (seat->input_method->focus_listener_initialized)
827 return;
828
Kristian Høgsberg2bf87622013-05-07 23:17:41 -0400829 if (seat->keyboard) {
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200830 seat->input_method->keyboard_focus_listener.notify = handle_keyboard_focus;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400831 wl_signal_add(&seat->keyboard->focus_signal, &seat->input_method->keyboard_focus_listener);
832 seat->keyboard->input_method_grab.interface = &input_method_context_grab;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200833 }
834
835 seat->input_method->focus_listener_initialized = 1;
836}
837
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300838static void launch_input_method(struct text_backend *text_backend);
839
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100840static void
841handle_input_method_sigchld(struct weston_process *process, int status)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200842{
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300843 uint32_t time;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100844 struct text_backend *text_backend =
845 container_of(process, struct text_backend, input_method.process);
846
847 text_backend->input_method.process.pid = 0;
848 text_backend->input_method.client = NULL;
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300849
850 /* if input_method dies more than 5 times in 10 seconds, give up */
851 time = weston_compositor_get_time();
852 if (time - text_backend->input_method.deathstamp > 10000) {
853 text_backend->input_method.deathstamp = time;
854 text_backend->input_method.deathcount = 0;
855 }
856
857 text_backend->input_method.deathcount++;
858 if (text_backend->input_method.deathcount > 5) {
859 weston_log("input_method died, giving up.\n");
860 return;
861 }
862
863 weston_log("input_method died, respawning...\n");
864 launch_input_method(text_backend);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100865}
866
867static void
868launch_input_method(struct text_backend *text_backend)
869{
870 if (text_backend->input_method.binding)
871 return;
872
873 if (!text_backend->input_method.path)
874 return;
875
876 if (text_backend->input_method.process.pid != 0)
877 return;
878
879 text_backend->input_method.client = weston_client_launch(text_backend->compositor,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200880 &text_backend->input_method.process,
881 text_backend->input_method.path,
882 handle_input_method_sigchld);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100883
884 if (!text_backend->input_method.client)
885 weston_log("not able to start %s\n", text_backend->input_method.path);
886}
887
888static void
889handle_seat_created(struct wl_listener *listener,
890 void *data)
891{
892 struct weston_seat *seat = data;
893 struct text_backend *text_backend =
894 container_of(listener, struct text_backend,
895 seat_created_listener);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200896 struct input_method *input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100897 struct weston_compositor *ec = seat->compositor;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200898
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200899 input_method = calloc(1, sizeof *input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200900
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200901 input_method->seat = seat;
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200902 input_method->model = NULL;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200903 input_method->focus_listener_initialized = 0;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200904 input_method->context = NULL;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100905 input_method->text_backend = text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200906
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200907 input_method->input_method_global =
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400908 wl_global_create(ec->wl_display, &wl_input_method_interface, 1,
909 input_method, bind_input_method);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200910
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200911 input_method->destroy_listener.notify = input_method_notifier_destroy;
Kristian Høgsberg49124542013-05-06 22:27:40 -0400912 wl_signal_add(&seat->destroy_signal, &input_method->destroy_listener);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200913
914 seat->input_method = input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100915
916 launch_input_method(text_backend);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200917}
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200918
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100919static void
920text_backend_configuration(struct text_backend *text_backend)
921{
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -0400922 struct weston_config_section *section;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100923
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -0400924 section = weston_config_get_section(text_backend->compositor->config,
925 "input-method", NULL, NULL);
926 weston_config_section_get_string(section, "path",
927 &text_backend->input_method.path,
928 LIBEXECDIR "/weston-keyboard");
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100929}
930
931static void
932text_backend_notifier_destroy(struct wl_listener *listener, void *data)
933{
934 struct text_backend *text_backend =
935 container_of(listener, struct text_backend, destroy_listener);
936
937 if (text_backend->input_method.client)
938 wl_client_destroy(text_backend->input_method.client);
939
940 free(text_backend->input_method.path);
941
942 free(text_backend);
943}
944
945
946WL_EXPORT int
947text_backend_init(struct weston_compositor *ec)
948{
949 struct text_backend *text_backend;
950
951 text_backend = calloc(1, sizeof(*text_backend));
952
953 text_backend->compositor = ec;
954
955 text_backend->seat_created_listener.notify = handle_seat_created;
956 wl_signal_add(&ec->seat_created_signal,
957 &text_backend->seat_created_listener);
958
959 text_backend->destroy_listener.notify = text_backend_notifier_destroy;
960 wl_signal_add(&ec->destroy_signal, &text_backend->destroy_listener);
961
962 text_backend_configuration(text_backend);
963
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200964 text_input_manager_create(ec);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100965
966 return 0;
967}