blob: 37dfb7566b5e7b5fe14d987e2400ed037081e0cc [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
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400573static const struct weston_keyboard_grab_interface input_method_context_grab = {
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100574 input_method_context_grab_key,
575 input_method_context_grab_modifier,
576};
577
578static void
579input_method_context_grab_keyboard(struct wl_client *client,
580 struct wl_resource *resource,
581 uint32_t id)
582{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500583 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100584 struct wl_resource *cr;
585 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400586 struct weston_keyboard *keyboard = seat->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100587
Jason Ekstranda85118c2013-06-27 20:17:02 -0500588 cr = wl_resource_create(client, &wl_keyboard_interface, 1, id);
589 wl_resource_set_implementation(cr, NULL, context, unbind_keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100590
591 context->keyboard = cr;
592
593 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
Andrew Wedgbury9a6f02a2013-09-05 13:31:40 +0000594 seat->xkb_info->keymap_fd,
595 seat->xkb_info->keymap_size);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100596
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400597 if (keyboard->grab != &keyboard->default_grab) {
598 weston_keyboard_end_grab(keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100599 }
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400600 weston_keyboard_start_grab(keyboard, &keyboard->input_method_grab);
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100601 keyboard->input_method_resource = cr;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100602}
603
Jan Arne Petersen337df952012-11-18 19:06:46 +0100604static void
605input_method_context_key(struct wl_client *client,
606 struct wl_resource *resource,
607 uint32_t serial,
608 uint32_t time,
609 uint32_t key,
610 uint32_t state_w)
611{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500612 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen337df952012-11-18 19:06:46 +0100613 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400614 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400615 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100616
617 default_grab->interface->key(default_grab, time, key, state_w);
618}
619
620static void
621input_method_context_modifiers(struct wl_client *client,
622 struct wl_resource *resource,
623 uint32_t serial,
624 uint32_t mods_depressed,
625 uint32_t mods_latched,
626 uint32_t mods_locked,
627 uint32_t group)
628{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500629 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen337df952012-11-18 19:06:46 +0100630
631 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400632 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400633 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100634
635 default_grab->interface->modifiers(default_grab,
636 serial, mods_depressed,
637 mods_latched, mods_locked,
638 group);
639}
640
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200641static void
642input_method_context_language(struct wl_client *client,
643 struct wl_resource *resource,
644 uint32_t serial,
645 const char *language)
646{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500647 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200648
Jason Ekstrand89d31992013-06-14 10:07:59 -0500649 wl_text_input_send_language(context->model->resource, serial, language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200650}
651
652static void
653input_method_context_text_direction(struct wl_client *client,
654 struct wl_resource *resource,
655 uint32_t serial,
656 uint32_t direction)
657{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500658 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200659
Jason Ekstrand89d31992013-06-14 10:07:59 -0500660 wl_text_input_send_text_direction(context->model->resource, serial, direction);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200661}
662
663
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200664static const struct wl_input_method_context_interface input_method_context_implementation = {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200665 input_method_context_destroy,
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200666 input_method_context_commit_string,
667 input_method_context_preedit_string,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100668 input_method_context_preedit_styling,
669 input_method_context_preedit_cursor,
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200670 input_method_context_delete_surrounding_text,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100671 input_method_context_cursor_position,
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100672 input_method_context_modifiers_map,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100673 input_method_context_keysym,
Jan Arne Petersen337df952012-11-18 19:06:46 +0100674 input_method_context_grab_keyboard,
675 input_method_context_key,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200676 input_method_context_modifiers,
677 input_method_context_language,
678 input_method_context_text_direction
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200679};
680
681static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200682destroy_input_method_context(struct wl_resource *resource)
683{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500684 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200685
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100686 if (context->keyboard) {
687 wl_resource_destroy(context->keyboard);
688 }
689
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200690 free(context);
691}
692
693static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200694input_method_context_create(struct text_input *model,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200695 struct input_method *input_method)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200696{
697 struct input_method_context *context;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500698 struct wl_resource *binding;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200699
700 if (!input_method->input_method_binding)
701 return;
702
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100703 context = calloc(1, sizeof *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200704 if (context == NULL)
705 return;
706
Jason Ekstrand89d31992013-06-14 10:07:59 -0500707 binding = input_method->input_method_binding;
Jason Ekstranda85118c2013-06-27 20:17:02 -0500708 context->resource =
709 wl_resource_create(wl_resource_get_client(binding),
710 &wl_input_method_context_interface, 1, 0);
711 wl_resource_set_implementation(context->resource,
712 &input_method_context_implementation,
713 context, destroy_input_method_context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200714
715 context->model = model;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100716 context->input_method = input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200717 input_method->context = context;
718
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200719
Jason Ekstrand89d31992013-06-14 10:07:59 -0500720 wl_input_method_send_activate(binding, context->resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200721}
722
723static void
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100724input_method_context_end_keyboard_grab(struct input_method_context *context)
725{
Kristian Høgsberge3148752013-05-06 23:19:49 -0400726 struct weston_keyboard_grab *grab =
727 &context->input_method->seat->keyboard->input_method_grab;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400728 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100729
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100730 if (!grab->keyboard)
731 return;
732
733 if (grab->keyboard->grab == grab)
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400734 weston_keyboard_end_grab(grab->keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100735
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100736 keyboard->input_method_resource = NULL;
737}
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100738
739static void
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200740unbind_input_method(struct wl_resource *resource)
741{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500742 struct input_method *input_method = wl_resource_get_user_data(resource);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100743 struct text_backend *text_backend = input_method->text_backend;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200744
745 input_method->input_method_binding = NULL;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200746 input_method->context = NULL;
747
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100748 text_backend->input_method.binding = NULL;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200749}
750
751static void
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200752bind_input_method(struct wl_client *client,
753 void *data,
754 uint32_t version,
755 uint32_t id)
756{
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200757 struct input_method *input_method = data;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100758 struct text_backend *text_backend = input_method->text_backend;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200759 struct wl_resource *resource;
760
Jason Ekstranda85118c2013-06-27 20:17:02 -0500761 resource =
762 wl_resource_create(client, &wl_input_method_interface, 1, id);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200763
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200764 if (input_method->input_method_binding != NULL) {
765 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
766 "interface object already bound");
767 wl_resource_destroy(resource);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200768 return;
769 }
770
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200771 if (text_backend->input_method.client != client) {
772 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
Eduardo Lima (Etrunko)a2ce68f2013-05-10 17:50:36 -0300773 "permission to bind input_method denied");
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200774 wl_resource_destroy(resource);
775 return;
776 }
777
Jason Ekstranda85118c2013-06-27 20:17:02 -0500778 wl_resource_set_implementation(resource, NULL, input_method,
779 unbind_input_method);
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200780 input_method->input_method_binding = resource;
781
782 text_backend->input_method.binding = resource;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200783}
784
785static void
786input_method_notifier_destroy(struct wl_listener *listener, void *data)
787{
Kristian Høgsbergf97f3792012-07-22 11:51:42 -0400788 struct input_method *input_method =
789 container_of(listener, struct input_method, destroy_listener);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200790
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200791 if (input_method->model)
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200792 deactivate_text_input(input_method->model, input_method);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200793
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400794 wl_global_destroy(input_method->input_method_global);
Rob Bradfordead3ef82013-07-24 16:57:32 +0100795 wl_list_remove(&input_method->destroy_listener.link);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200796
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200797 free(input_method);
798}
799
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200800static void
801handle_keyboard_focus(struct wl_listener *listener, void *data)
802{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400803 struct weston_keyboard *keyboard = data;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200804 struct input_method *input_method =
805 container_of(listener, struct input_method, keyboard_focus_listener);
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400806 struct weston_surface *surface = keyboard->focus;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200807
808 if (!input_method->model)
809 return;
810
811 if (!surface || input_method->model->surface != surface)
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200812 deactivate_text_input(input_method->model,
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200813 input_method);
814}
815
816static void
817input_method_init_seat(struct weston_seat *seat)
818{
819 if (seat->input_method->focus_listener_initialized)
820 return;
821
Kristian Høgsberg2bf87622013-05-07 23:17:41 -0400822 if (seat->keyboard) {
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200823 seat->input_method->keyboard_focus_listener.notify = handle_keyboard_focus;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400824 wl_signal_add(&seat->keyboard->focus_signal, &seat->input_method->keyboard_focus_listener);
825 seat->keyboard->input_method_grab.interface = &input_method_context_grab;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200826 }
827
828 seat->input_method->focus_listener_initialized = 1;
829}
830
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300831static void launch_input_method(struct text_backend *text_backend);
832
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100833static void
834handle_input_method_sigchld(struct weston_process *process, int status)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200835{
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300836 uint32_t time;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100837 struct text_backend *text_backend =
838 container_of(process, struct text_backend, input_method.process);
839
840 text_backend->input_method.process.pid = 0;
841 text_backend->input_method.client = NULL;
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300842
843 /* if input_method dies more than 5 times in 10 seconds, give up */
844 time = weston_compositor_get_time();
845 if (time - text_backend->input_method.deathstamp > 10000) {
846 text_backend->input_method.deathstamp = time;
847 text_backend->input_method.deathcount = 0;
848 }
849
850 text_backend->input_method.deathcount++;
851 if (text_backend->input_method.deathcount > 5) {
852 weston_log("input_method died, giving up.\n");
853 return;
854 }
855
856 weston_log("input_method died, respawning...\n");
857 launch_input_method(text_backend);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100858}
859
860static void
861launch_input_method(struct text_backend *text_backend)
862{
863 if (text_backend->input_method.binding)
864 return;
865
866 if (!text_backend->input_method.path)
867 return;
868
869 if (text_backend->input_method.process.pid != 0)
870 return;
871
872 text_backend->input_method.client = weston_client_launch(text_backend->compositor,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200873 &text_backend->input_method.process,
874 text_backend->input_method.path,
875 handle_input_method_sigchld);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100876
877 if (!text_backend->input_method.client)
878 weston_log("not able to start %s\n", text_backend->input_method.path);
879}
880
881static void
882handle_seat_created(struct wl_listener *listener,
883 void *data)
884{
885 struct weston_seat *seat = data;
886 struct text_backend *text_backend =
887 container_of(listener, struct text_backend,
888 seat_created_listener);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200889 struct input_method *input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100890 struct weston_compositor *ec = seat->compositor;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200891
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200892 input_method = calloc(1, sizeof *input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200893
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200894 input_method->seat = seat;
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200895 input_method->model = NULL;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200896 input_method->focus_listener_initialized = 0;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200897 input_method->context = NULL;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100898 input_method->text_backend = text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200899
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200900 input_method->input_method_global =
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400901 wl_global_create(ec->wl_display, &wl_input_method_interface, 1,
902 input_method, bind_input_method);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200903
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200904 input_method->destroy_listener.notify = input_method_notifier_destroy;
Kristian Høgsberg49124542013-05-06 22:27:40 -0400905 wl_signal_add(&seat->destroy_signal, &input_method->destroy_listener);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200906
907 seat->input_method = input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100908
909 launch_input_method(text_backend);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200910}
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200911
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100912static void
913text_backend_configuration(struct text_backend *text_backend)
914{
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -0400915 struct weston_config_section *section;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100916
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -0400917 section = weston_config_get_section(text_backend->compositor->config,
918 "input-method", NULL, NULL);
919 weston_config_section_get_string(section, "path",
920 &text_backend->input_method.path,
921 LIBEXECDIR "/weston-keyboard");
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100922}
923
924static void
925text_backend_notifier_destroy(struct wl_listener *listener, void *data)
926{
927 struct text_backend *text_backend =
928 container_of(listener, struct text_backend, destroy_listener);
929
930 if (text_backend->input_method.client)
931 wl_client_destroy(text_backend->input_method.client);
932
933 free(text_backend->input_method.path);
934
935 free(text_backend);
936}
937
938
939WL_EXPORT int
940text_backend_init(struct weston_compositor *ec)
941{
942 struct text_backend *text_backend;
943
944 text_backend = calloc(1, sizeof(*text_backend));
945
946 text_backend->compositor = ec;
947
948 text_backend->seat_created_listener.notify = handle_seat_created;
949 wl_signal_add(&ec->seat_created_signal,
950 &text_backend->seat_created_listener);
951
952 text_backend->destroy_listener.notify = text_backend_notifier_destroy;
953 wl_signal_add(&ec->destroy_signal, &text_backend->destroy_listener);
954
955 text_backend_configuration(text_backend);
956
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200957 text_input_manager_create(ec);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100958
959 return 0;
960}