blob: 4ebbbddb3cc245c4688cf8645e47bfb11779d591 [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 *
Bryce Harringtona0bbfea2015-06-11 15:35:43 -07005 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020012 *
Bryce Harringtona0bbfea2015-06-11 15:35:43 -070013 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020025 */
26
Daniel Stonec228e232013-05-22 18:03:19 +030027#include "config.h"
28
Derek Foremand09dbb32014-12-05 15:38:39 -060029#include <stdbool.h>
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020030#include <stdlib.h>
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010031#include <string.h>
Ossama Othmana50e6e42013-05-14 09:48:26 -070032#include <unistd.h>
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -030033#include <time.h>
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020034
35#include "compositor.h"
36#include "text-server-protocol.h"
Jan Arne Petersen30b66ef2012-09-09 23:08:41 +020037#include "input-method-server-protocol.h"
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020038
Derek Foreman516d6032015-05-08 17:08:40 -050039struct text_input_manager;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020040struct input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020041struct input_method_context;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010042struct text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020043
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020044struct text_input {
Jason Ekstrand89d31992013-06-14 10:07:59 -050045 struct wl_resource *resource;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020046
Jan Arne Petersene829adc2012-08-10 16:47:22 +020047 struct weston_compositor *ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020048
Jan Arne Petersene829adc2012-08-10 16:47:22 +020049 struct wl_list input_methods;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +020050
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -040051 struct weston_surface *surface;
Jan Arne Petersen61381972013-01-31 15:52:21 +010052
Jan Arne Petersen14da96b2013-04-18 16:47:28 +020053 pixman_box32_t cursor_rectangle;
54
Derek Foremand09dbb32014-12-05 15:38:39 -060055 bool input_panel_visible;
Derek Foreman516d6032015-05-08 17:08:40 -050056
57 struct text_input_manager *manager;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020058};
59
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020060struct text_input_manager {
61 struct wl_global *text_input_manager_global;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020062 struct wl_listener destroy_listener;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020063
Derek Foreman516d6032015-05-08 17:08:40 -050064 struct text_input *current_panel;
65
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +020066 struct weston_compositor *ec;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +020067};
68
69struct input_method {
70 struct wl_resource *input_method_binding;
71 struct wl_global *input_method_global;
72 struct wl_listener destroy_listener;
73
74 struct weston_seat *seat;
Derek Foreman0f299232015-05-08 17:08:41 -050075 struct text_input *input;
Jan Arne Petersene829adc2012-08-10 16:47:22 +020076
77 struct wl_list link;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +020078
79 struct wl_listener keyboard_focus_listener;
80
81 int focus_listener_initialized;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020082
83 struct input_method_context *context;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010084
85 struct text_backend *text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020086};
87
Jan Arne Petersen620cd622012-09-09 23:08:32 +020088struct input_method_context {
Jason Ekstrand89d31992013-06-14 10:07:59 -050089 struct wl_resource *resource;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020090
Derek Foreman0f299232015-05-08 17:08:41 -050091 struct text_input *input;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +010092 struct input_method *input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020093
Jan Arne Petersen466b9c12012-11-18 19:06:45 +010094 struct wl_resource *keyboard;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020095};
96
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010097struct text_backend {
98 struct weston_compositor *compositor;
99
100 struct {
101 char *path;
102 struct wl_resource *binding;
103 struct weston_process process;
104 struct wl_client *client;
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300105
106 unsigned deathcount;
107 uint32_t deathstamp;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100108 } input_method;
109
110 struct wl_listener seat_created_listener;
111 struct wl_listener destroy_listener;
112};
113
Derek Foremancb5fcea2014-12-05 15:38:37 -0600114static void
Derek Foreman0f299232015-05-08 17:08:41 -0500115input_method_context_create(struct text_input *input,
Derek Foremancb5fcea2014-12-05 15:38:37 -0600116 struct input_method *input_method);
117static void
118input_method_context_end_keyboard_grab(struct input_method_context *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200119
Derek Foremancb5fcea2014-12-05 15:38:37 -0600120static void
121input_method_init_seat(struct weston_seat *seat);
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200122
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200123static void
Derek Foreman516d6032015-05-08 17:08:40 -0500124deactivate_input_method(struct input_method *input_method)
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200125{
Derek Foreman0f299232015-05-08 17:08:41 -0500126 struct text_input *text_input = input_method->input;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200127 struct weston_compositor *ec = text_input->ec;
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200128
Derek Foreman516d6032015-05-08 17:08:40 -0500129 if (input_method->context && input_method->input_method_binding) {
130 input_method_context_end_keyboard_grab(input_method->context);
131 wl_input_method_send_deactivate(input_method->input_method_binding,
132 input_method->context->resource);
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200133 }
Derek Foreman516d6032015-05-08 17:08:40 -0500134
135 wl_list_remove(&input_method->link);
Derek Foreman0f299232015-05-08 17:08:41 -0500136 input_method->input = NULL;
Derek Foreman516d6032015-05-08 17:08:40 -0500137 input_method->context = NULL;
138
139 if (wl_list_empty(&text_input->input_methods) &&
140 text_input->input_panel_visible) {
141 wl_signal_emit(&ec->hide_input_panel_signal, ec);
142 text_input->input_panel_visible = false;
143 text_input->manager->current_panel = NULL;
144 }
145 wl_text_input_send_leave(text_input->resource);
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200146}
147
148static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200149destroy_text_input(struct wl_resource *resource)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200150{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500151 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200152 struct input_method *input_method, *next;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200153
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200154 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link)
Derek Foreman516d6032015-05-08 17:08:40 -0500155 deactivate_input_method(input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200156
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200157 free(text_input);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200158}
159
160static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200161text_input_set_surrounding_text(struct wl_client *client,
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200162 struct wl_resource *resource,
Jan Arne Petersencb08f4d2012-09-09 23:08:40 +0200163 const char *text,
164 uint32_t cursor,
165 uint32_t anchor)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200166{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500167 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200168 struct input_method *input_method, *next;
169
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200170 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200171 if (!input_method->context)
172 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500173 wl_input_method_context_send_surrounding_text(input_method->context->resource,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200174 text,
175 cursor,
176 anchor);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200177 }
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200178}
179
180static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200181text_input_activate(struct wl_client *client,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200182 struct wl_resource *resource,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200183 struct wl_resource *seat,
184 struct wl_resource *surface)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200185{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500186 struct text_input *text_input = wl_resource_get_user_data(resource);
Jason Ekstrand44a38632013-06-14 10:08:00 -0500187 struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200188 struct input_method *input_method = weston_seat->input_method;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200189 struct weston_compositor *ec = text_input->ec;
Derek Foreman516d6032015-05-08 17:08:40 -0500190 struct text_input *current;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200191
Derek Foreman0f299232015-05-08 17:08:41 -0500192 if (input_method->input == text_input)
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200193 return;
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200194
Derek Foreman0f299232015-05-08 17:08:41 -0500195 if (input_method->input)
Derek Foreman516d6032015-05-08 17:08:40 -0500196 deactivate_input_method(input_method);
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200197
Derek Foreman0f299232015-05-08 17:08:41 -0500198 input_method->input = text_input;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200199 wl_list_insert(&text_input->input_methods, &input_method->link);
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200200 input_method_init_seat(weston_seat);
201
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -0500202 text_input->surface = wl_resource_get_user_data(surface);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200203
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200204 input_method_context_create(text_input, input_method);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200205
Derek Foreman516d6032015-05-08 17:08:40 -0500206 current = text_input->manager->current_panel;
207
208 if (current && current != text_input) {
209 current->input_panel_visible = false;
210 wl_signal_emit(&ec->hide_input_panel_signal, ec);
211 text_input->manager->current_panel = NULL;
212 }
213
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200214 if (text_input->input_panel_visible) {
215 wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
216 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
Derek Foreman516d6032015-05-08 17:08:40 -0500217 text_input->manager->current_panel = text_input;
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200218 }
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200219
Jason Ekstrand89d31992013-06-14 10:07:59 -0500220 wl_text_input_send_enter(text_input->resource, text_input->surface->resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200221}
222
223static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200224text_input_deactivate(struct wl_client *client,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200225 struct wl_resource *resource,
226 struct wl_resource *seat)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200227{
Jason Ekstrand44a38632013-06-14 10:08:00 -0500228 struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200229
Derek Foreman0f299232015-05-08 17:08:41 -0500230 if (weston_seat->input_method->input)
Derek Foreman516d6032015-05-08 17:08:40 -0500231 deactivate_input_method(weston_seat->input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200232}
233
234static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200235text_input_reset(struct wl_client *client,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200236 struct wl_resource *resource)
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200237{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500238 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200239 struct input_method *input_method, *next;
240
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200241 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200242 if (!input_method->context)
243 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500244 wl_input_method_context_send_reset(input_method->context->resource);
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200245 }
246}
247
248static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200249text_input_set_cursor_rectangle(struct wl_client *client,
Jan Arne Petersen7ef8eff2013-04-18 16:47:23 +0200250 struct wl_resource *resource,
251 int32_t x,
252 int32_t y,
253 int32_t width,
254 int32_t height)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200255{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500256 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200257 struct weston_compositor *ec = text_input->ec;
258
259 text_input->cursor_rectangle.x1 = x;
260 text_input->cursor_rectangle.y1 = y;
261 text_input->cursor_rectangle.x2 = x + width;
262 text_input->cursor_rectangle.y2 = y + height;
263
264 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200265}
266
267static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200268text_input_set_content_type(struct wl_client *client,
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100269 struct wl_resource *resource,
270 uint32_t hint,
271 uint32_t purpose)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200272{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500273 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100274 struct input_method *input_method, *next;
275
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200276 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100277 if (!input_method->context)
278 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500279 wl_input_method_context_send_content_type(input_method->context->resource, hint, purpose);
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100280 }
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200281}
282
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100283static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200284text_input_invoke_action(struct wl_client *client,
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100285 struct wl_resource *resource,
286 uint32_t button,
287 uint32_t index)
288{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500289 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100290 struct input_method *input_method, *next;
291
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200292 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100293 if (!input_method->context)
294 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500295 wl_input_method_context_send_invoke_action(input_method->context->resource, button, index);
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100296 }
297}
298
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100299static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200300text_input_commit_state(struct wl_client *client,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200301 struct wl_resource *resource,
302 uint32_t serial)
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100303{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500304 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100305 struct input_method *input_method, *next;
306
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200307 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100308 if (!input_method->context)
309 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500310 wl_input_method_context_send_commit_state(input_method->context->resource, serial);
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100311 }
312}
313
Jan Arne Petersen61381972013-01-31 15:52:21 +0100314static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200315text_input_show_input_panel(struct wl_client *client,
Jan Arne Petersen61381972013-01-31 15:52:21 +0100316 struct wl_resource *resource)
317{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500318 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200319 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100320
Derek Foremand09dbb32014-12-05 15:38:39 -0600321 text_input->input_panel_visible = true;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100322
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200323 if (!wl_list_empty(&text_input->input_methods)) {
324 wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
325 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
326 }
Jan Arne Petersen61381972013-01-31 15:52:21 +0100327}
328
329static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200330text_input_hide_input_panel(struct wl_client *client,
Jan Arne Petersen61381972013-01-31 15:52:21 +0100331 struct wl_resource *resource)
332{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500333 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200334 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100335
Derek Foremand09dbb32014-12-05 15:38:39 -0600336 text_input->input_panel_visible = false;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100337
Derek Foreman516d6032015-05-08 17:08:40 -0500338 if (!wl_list_empty(&text_input->input_methods) &&
339 text_input == text_input->manager->current_panel) {
340 text_input->manager->current_panel = NULL;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100341 wl_signal_emit(&ec->hide_input_panel_signal, ec);
Derek Foreman516d6032015-05-08 17:08:40 -0500342 }
Jan Arne Petersen61381972013-01-31 15:52:21 +0100343}
344
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200345static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200346text_input_set_preferred_language(struct wl_client *client,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200347 struct wl_resource *resource,
348 const char *language)
349{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500350 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200351 struct input_method *input_method, *next;
352
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200353 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200354 if (!input_method->context)
355 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500356 wl_input_method_context_send_preferred_language(input_method->context->resource,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200357 language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200358 }
359}
360
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200361static const struct wl_text_input_interface text_input_implementation = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200362 text_input_activate,
363 text_input_deactivate,
364 text_input_show_input_panel,
365 text_input_hide_input_panel,
366 text_input_reset,
367 text_input_set_surrounding_text,
368 text_input_set_content_type,
369 text_input_set_cursor_rectangle,
370 text_input_set_preferred_language,
371 text_input_commit_state,
372 text_input_invoke_action
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200373};
374
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200375static void text_input_manager_create_text_input(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200376 struct wl_resource *resource,
Jan Arne Petersen4c265182012-09-09 23:08:30 +0200377 uint32_t id)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200378{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500379 struct text_input_manager *text_input_manager = wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200380 struct text_input *text_input;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200381
Bryce Harringtonde16d892014-11-20 22:21:57 -0800382 text_input = zalloc(sizeof *text_input);
383 if (text_input == NULL)
384 return;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200385
Jason Ekstranda85118c2013-06-27 20:17:02 -0500386 text_input->resource =
387 wl_resource_create(client, &wl_text_input_interface, 1, id);
388 wl_resource_set_implementation(text_input->resource,
389 &text_input_implementation,
390 text_input, destroy_text_input);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200391
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200392 text_input->ec = text_input_manager->ec;
Derek Foreman516d6032015-05-08 17:08:40 -0500393 text_input->manager = text_input_manager;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200394
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200395 wl_list_init(&text_input->input_methods);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200396};
397
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200398static const struct wl_text_input_manager_interface text_input_manager_implementation = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200399 text_input_manager_create_text_input
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200400};
401
402static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200403bind_text_input_manager(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200404 void *data,
405 uint32_t version,
406 uint32_t id)
407{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200408 struct text_input_manager *text_input_manager = data;
Jason Ekstranda85118c2013-06-27 20:17:02 -0500409 struct wl_resource *resource;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200410
Jason Ekstranda85118c2013-06-27 20:17:02 -0500411 /* No checking for duplicate binding necessary. */
412 resource =
413 wl_resource_create(client,
414 &wl_text_input_manager_interface, 1, id);
415 if (resource)
416 wl_resource_set_implementation(resource,
417 &text_input_manager_implementation,
418 text_input_manager, NULL);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200419}
420
421static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200422text_input_manager_notifier_destroy(struct wl_listener *listener, void *data)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200423{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200424 struct text_input_manager *text_input_manager =
425 container_of(listener, struct text_input_manager, destroy_listener);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200426
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400427 wl_global_destroy(text_input_manager->text_input_manager_global);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200428
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200429 free(text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200430}
431
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100432static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200433text_input_manager_create(struct weston_compositor *ec)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200434{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200435 struct text_input_manager *text_input_manager;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200436
Bryce Harringtonde16d892014-11-20 22:21:57 -0800437 text_input_manager = zalloc(sizeof *text_input_manager);
438 if (text_input_manager == NULL)
439 return;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200440
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200441 text_input_manager->ec = ec;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200442
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200443 text_input_manager->text_input_manager_global =
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400444 wl_global_create(ec->wl_display,
445 &wl_text_input_manager_interface, 1,
446 text_input_manager, bind_text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200447
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200448 text_input_manager->destroy_listener.notify = text_input_manager_notifier_destroy;
449 wl_signal_add(&ec->destroy_signal, &text_input_manager->destroy_listener);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200450}
451
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200452static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200453input_method_context_destroy(struct wl_client *client,
454 struct wl_resource *resource)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200455{
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200456 wl_resource_destroy(resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200457}
458
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200459static void
460input_method_context_commit_string(struct wl_client *client,
461 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100462 uint32_t serial,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100463 const char *text)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200464{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500465 struct input_method_context *context =
466 wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200467
Derek Foreman0f299232015-05-08 17:08:41 -0500468 if (context->input)
469 wl_text_input_send_commit_string(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800470 serial, text);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200471}
472
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200473static void
474input_method_context_preedit_string(struct wl_client *client,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100475 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100476 uint32_t serial,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100477 const char *text,
478 const char *commit)
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200479{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500480 struct input_method_context *context =
481 wl_resource_get_user_data(resource);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200482
Derek Foreman0f299232015-05-08 17:08:41 -0500483 if (context->input)
484 wl_text_input_send_preedit_string(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800485 serial, text, commit);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100486}
487
488static void
489input_method_context_preedit_styling(struct wl_client *client,
490 struct wl_resource *resource,
491 uint32_t index,
492 uint32_t length,
493 uint32_t style)
494{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500495 struct input_method_context *context =
496 wl_resource_get_user_data(resource);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100497
Derek Foreman0f299232015-05-08 17:08:41 -0500498 if (context->input)
499 wl_text_input_send_preedit_styling(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800500 index, length, style);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100501}
502
503static void
504input_method_context_preedit_cursor(struct wl_client *client,
505 struct wl_resource *resource,
506 int32_t cursor)
507{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500508 struct input_method_context *context =
509 wl_resource_get_user_data(resource);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100510
Derek Foreman0f299232015-05-08 17:08:41 -0500511 if (context->input)
512 wl_text_input_send_preedit_cursor(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800513 cursor);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200514}
515
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200516static void
517input_method_context_delete_surrounding_text(struct wl_client *client,
518 struct wl_resource *resource,
519 int32_t index,
520 uint32_t length)
521{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500522 struct input_method_context *context =
523 wl_resource_get_user_data(resource);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200524
Derek Foreman0f299232015-05-08 17:08:41 -0500525 if (context->input)
526 wl_text_input_send_delete_surrounding_text(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800527 index, length);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200528}
529
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200530static void
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100531input_method_context_cursor_position(struct wl_client *client,
532 struct wl_resource *resource,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100533 int32_t index,
534 int32_t anchor)
535{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500536 struct input_method_context *context =
537 wl_resource_get_user_data(resource);
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100538
Derek Foreman0f299232015-05-08 17:08:41 -0500539 if (context->input)
540 wl_text_input_send_cursor_position(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800541 index, anchor);
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100542}
543
544static void
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100545input_method_context_modifiers_map(struct wl_client *client,
546 struct wl_resource *resource,
547 struct wl_array *map)
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200548{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500549 struct input_method_context *context =
550 wl_resource_get_user_data(resource);
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200551
Derek Foreman0f299232015-05-08 17:08:41 -0500552 if (context->input)
553 wl_text_input_send_modifiers_map(context->input->resource, map);
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100554}
555
556static void
557input_method_context_keysym(struct wl_client *client,
558 struct wl_resource *resource,
559 uint32_t serial,
560 uint32_t time,
561 uint32_t sym,
562 uint32_t state,
563 uint32_t modifiers)
564{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500565 struct input_method_context *context =
566 wl_resource_get_user_data(resource);
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100567
Derek Foreman0f299232015-05-08 17:08:41 -0500568 if (context->input)
569 wl_text_input_send_keysym(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800570 serial, time, sym, state, modifiers);
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200571}
572
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100573static void
574unbind_keyboard(struct wl_resource *resource)
575{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500576 struct input_method_context *context =
577 wl_resource_get_user_data(resource);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100578
579 input_method_context_end_keyboard_grab(context);
580 context->keyboard = NULL;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100581}
582
583static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400584input_method_context_grab_key(struct weston_keyboard_grab *grab,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100585 uint32_t time, uint32_t key, uint32_t state_w)
586{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400587 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100588 struct wl_display *display;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100589 uint32_t serial;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100590
591 if (!keyboard->input_method_resource)
592 return;
593
Jason Ekstrand89d31992013-06-14 10:07:59 -0500594 display = wl_client_get_display(wl_resource_get_client(keyboard->input_method_resource));
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100595 serial = wl_display_next_serial(display);
596 wl_keyboard_send_key(keyboard->input_method_resource,
597 serial, time, key, state_w);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100598}
599
600static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400601input_method_context_grab_modifier(struct weston_keyboard_grab *grab, uint32_t serial,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100602 uint32_t mods_depressed, uint32_t mods_latched,
603 uint32_t mods_locked, uint32_t group)
604{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400605 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100606
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100607 if (!keyboard->input_method_resource)
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100608 return;
609
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100610 wl_keyboard_send_modifiers(keyboard->input_method_resource,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100611 serial, mods_depressed, mods_latched,
612 mods_locked, group);
613}
614
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200615static void
616input_method_context_grab_cancel(struct weston_keyboard_grab *grab)
617{
618 weston_keyboard_end_grab(grab->keyboard);
619}
620
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400621static const struct weston_keyboard_grab_interface input_method_context_grab = {
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100622 input_method_context_grab_key,
623 input_method_context_grab_modifier,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200624 input_method_context_grab_cancel,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100625};
626
627static void
628input_method_context_grab_keyboard(struct wl_client *client,
629 struct wl_resource *resource,
630 uint32_t id)
631{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500632 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100633 struct wl_resource *cr;
634 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400635 struct weston_keyboard *keyboard = seat->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100636
Jason Ekstranda85118c2013-06-27 20:17:02 -0500637 cr = wl_resource_create(client, &wl_keyboard_interface, 1, id);
638 wl_resource_set_implementation(cr, NULL, context, unbind_keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100639
640 context->keyboard = cr;
641
642 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
Jonas Ådahl7395ea02013-12-03 09:14:26 +0100643 keyboard->xkb_info->keymap_fd,
644 keyboard->xkb_info->keymap_size);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100645
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400646 if (keyboard->grab != &keyboard->default_grab) {
647 weston_keyboard_end_grab(keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100648 }
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400649 weston_keyboard_start_grab(keyboard, &keyboard->input_method_grab);
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100650 keyboard->input_method_resource = cr;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100651}
652
Jan Arne Petersen337df952012-11-18 19:06:46 +0100653static void
654input_method_context_key(struct wl_client *client,
655 struct wl_resource *resource,
656 uint32_t serial,
657 uint32_t time,
658 uint32_t key,
659 uint32_t state_w)
660{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500661 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen337df952012-11-18 19:06:46 +0100662 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400663 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400664 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100665
666 default_grab->interface->key(default_grab, time, key, state_w);
667}
668
669static void
670input_method_context_modifiers(struct wl_client *client,
671 struct wl_resource *resource,
672 uint32_t serial,
673 uint32_t mods_depressed,
674 uint32_t mods_latched,
675 uint32_t mods_locked,
676 uint32_t group)
677{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500678 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen337df952012-11-18 19:06:46 +0100679
680 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400681 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400682 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100683
684 default_grab->interface->modifiers(default_grab,
685 serial, mods_depressed,
686 mods_latched, mods_locked,
687 group);
688}
689
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200690static void
691input_method_context_language(struct wl_client *client,
692 struct wl_resource *resource,
693 uint32_t serial,
694 const char *language)
695{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500696 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200697
Derek Foreman0f299232015-05-08 17:08:41 -0500698 if (context->input)
699 wl_text_input_send_language(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800700 serial, language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200701}
702
703static void
704input_method_context_text_direction(struct wl_client *client,
705 struct wl_resource *resource,
706 uint32_t serial,
707 uint32_t direction)
708{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500709 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200710
Derek Foreman0f299232015-05-08 17:08:41 -0500711 if (context->input)
712 wl_text_input_send_text_direction(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800713 serial, direction);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200714}
715
716
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200717static const struct wl_input_method_context_interface input_method_context_implementation = {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200718 input_method_context_destroy,
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200719 input_method_context_commit_string,
720 input_method_context_preedit_string,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100721 input_method_context_preedit_styling,
722 input_method_context_preedit_cursor,
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200723 input_method_context_delete_surrounding_text,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100724 input_method_context_cursor_position,
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100725 input_method_context_modifiers_map,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100726 input_method_context_keysym,
Jan Arne Petersen337df952012-11-18 19:06:46 +0100727 input_method_context_grab_keyboard,
728 input_method_context_key,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200729 input_method_context_modifiers,
730 input_method_context_language,
731 input_method_context_text_direction
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200732};
733
734static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200735destroy_input_method_context(struct wl_resource *resource)
736{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500737 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200738
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100739 if (context->keyboard) {
740 wl_resource_destroy(context->keyboard);
741 }
742
Derek Foreman516d6032015-05-08 17:08:40 -0500743 if (context->input_method && context->input_method->context == context)
744 context->input_method->context = NULL;
745
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200746 free(context);
747}
748
749static void
Derek Foreman0f299232015-05-08 17:08:41 -0500750input_method_context_create(struct text_input *input,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200751 struct input_method *input_method)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200752{
753 struct input_method_context *context;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500754 struct wl_resource *binding;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200755
756 if (!input_method->input_method_binding)
757 return;
758
Bryce Harringtonde16d892014-11-20 22:21:57 -0800759 context = zalloc(sizeof *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200760 if (context == NULL)
761 return;
762
Jason Ekstrand89d31992013-06-14 10:07:59 -0500763 binding = input_method->input_method_binding;
Jason Ekstranda85118c2013-06-27 20:17:02 -0500764 context->resource =
765 wl_resource_create(wl_resource_get_client(binding),
766 &wl_input_method_context_interface, 1, 0);
767 wl_resource_set_implementation(context->resource,
768 &input_method_context_implementation,
769 context, destroy_input_method_context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200770
Derek Foreman0f299232015-05-08 17:08:41 -0500771 context->input = input;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100772 context->input_method = input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200773 input_method->context = context;
774
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200775
Jason Ekstrand89d31992013-06-14 10:07:59 -0500776 wl_input_method_send_activate(binding, context->resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200777}
778
779static void
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100780input_method_context_end_keyboard_grab(struct input_method_context *context)
781{
Derek Foremanf0aaa412014-12-08 10:48:29 -0600782 struct weston_keyboard_grab *grab;
783 struct weston_keyboard *keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100784
Derek Foremanf0aaa412014-12-08 10:48:29 -0600785 if (!context->input_method->seat->keyboard)
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100786 return;
787
Derek Foremanf0aaa412014-12-08 10:48:29 -0600788 grab = &context->input_method->seat->keyboard->input_method_grab;
789 keyboard = grab->keyboard;
790 if (!keyboard)
791 return;
792
793 if (keyboard->grab == grab)
794 weston_keyboard_end_grab(keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100795
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100796 keyboard->input_method_resource = NULL;
797}
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100798
799static void
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200800unbind_input_method(struct wl_resource *resource)
801{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500802 struct input_method *input_method = wl_resource_get_user_data(resource);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100803 struct text_backend *text_backend = input_method->text_backend;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200804
805 input_method->input_method_binding = NULL;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200806 input_method->context = NULL;
807
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100808 text_backend->input_method.binding = NULL;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200809}
810
811static void
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200812bind_input_method(struct wl_client *client,
813 void *data,
814 uint32_t version,
815 uint32_t id)
816{
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200817 struct input_method *input_method = data;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100818 struct text_backend *text_backend = input_method->text_backend;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200819 struct wl_resource *resource;
820
Jason Ekstranda85118c2013-06-27 20:17:02 -0500821 resource =
822 wl_resource_create(client, &wl_input_method_interface, 1, id);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200823
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200824 if (input_method->input_method_binding != NULL) {
825 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
826 "interface object already bound");
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200827 return;
828 }
829
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200830 if (text_backend->input_method.client != client) {
831 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
Eduardo Lima (Etrunko)a2ce68f2013-05-10 17:50:36 -0300832 "permission to bind input_method denied");
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200833 return;
834 }
835
Jason Ekstranda85118c2013-06-27 20:17:02 -0500836 wl_resource_set_implementation(resource, NULL, input_method,
837 unbind_input_method);
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200838 input_method->input_method_binding = resource;
839
840 text_backend->input_method.binding = resource;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200841}
842
843static void
844input_method_notifier_destroy(struct wl_listener *listener, void *data)
845{
Kristian Høgsbergf97f3792012-07-22 11:51:42 -0400846 struct input_method *input_method =
847 container_of(listener, struct input_method, destroy_listener);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200848
Derek Foreman0f299232015-05-08 17:08:41 -0500849 if (input_method->input)
Derek Foreman516d6032015-05-08 17:08:40 -0500850 deactivate_input_method(input_method);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200851
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400852 wl_global_destroy(input_method->input_method_global);
Rob Bradfordead3ef82013-07-24 16:57:32 +0100853 wl_list_remove(&input_method->destroy_listener.link);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200854
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200855 free(input_method);
856}
857
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200858static void
859handle_keyboard_focus(struct wl_listener *listener, void *data)
860{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400861 struct weston_keyboard *keyboard = data;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200862 struct input_method *input_method =
863 container_of(listener, struct input_method, keyboard_focus_listener);
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400864 struct weston_surface *surface = keyboard->focus;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200865
Derek Foreman0f299232015-05-08 17:08:41 -0500866 if (!input_method->input)
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200867 return;
868
Derek Foreman0f299232015-05-08 17:08:41 -0500869 if (!surface || input_method->input->surface != surface)
Derek Foreman516d6032015-05-08 17:08:40 -0500870 deactivate_input_method(input_method);
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200871}
872
873static void
874input_method_init_seat(struct weston_seat *seat)
875{
876 if (seat->input_method->focus_listener_initialized)
877 return;
878
Kristian Høgsberg2bf87622013-05-07 23:17:41 -0400879 if (seat->keyboard) {
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200880 seat->input_method->keyboard_focus_listener.notify = handle_keyboard_focus;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400881 wl_signal_add(&seat->keyboard->focus_signal, &seat->input_method->keyboard_focus_listener);
882 seat->keyboard->input_method_grab.interface = &input_method_context_grab;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200883 }
884
885 seat->input_method->focus_listener_initialized = 1;
886}
887
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300888static void launch_input_method(struct text_backend *text_backend);
889
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100890static void
891handle_input_method_sigchld(struct weston_process *process, int status)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200892{
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300893 uint32_t time;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100894 struct text_backend *text_backend =
895 container_of(process, struct text_backend, input_method.process);
896
897 text_backend->input_method.process.pid = 0;
898 text_backend->input_method.client = NULL;
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300899
900 /* if input_method dies more than 5 times in 10 seconds, give up */
901 time = weston_compositor_get_time();
902 if (time - text_backend->input_method.deathstamp > 10000) {
903 text_backend->input_method.deathstamp = time;
904 text_backend->input_method.deathcount = 0;
905 }
906
907 text_backend->input_method.deathcount++;
908 if (text_backend->input_method.deathcount > 5) {
909 weston_log("input_method died, giving up.\n");
910 return;
911 }
912
913 weston_log("input_method died, respawning...\n");
914 launch_input_method(text_backend);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100915}
916
917static void
918launch_input_method(struct text_backend *text_backend)
919{
920 if (text_backend->input_method.binding)
921 return;
922
923 if (!text_backend->input_method.path)
924 return;
925
Murray Calaveraf65f89b2015-06-09 20:28:06 +0000926 if (strcmp(text_backend->input_method.path, "") == 0)
927 return;
928
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100929 if (text_backend->input_method.process.pid != 0)
930 return;
931
932 text_backend->input_method.client = weston_client_launch(text_backend->compositor,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200933 &text_backend->input_method.process,
934 text_backend->input_method.path,
935 handle_input_method_sigchld);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100936
937 if (!text_backend->input_method.client)
938 weston_log("not able to start %s\n", text_backend->input_method.path);
939}
940
941static void
Murray Calavera25881242015-06-10 21:15:30 +0000942text_backend_seat_created(struct text_backend *text_backend,
943 struct weston_seat *seat)
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100944{
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200945 struct input_method *input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100946 struct weston_compositor *ec = seat->compositor;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200947
Bryce Harringtonde16d892014-11-20 22:21:57 -0800948 input_method = zalloc(sizeof *input_method);
949 if (input_method == NULL)
950 return;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200951
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200952 input_method->seat = seat;
Derek Foreman0f299232015-05-08 17:08:41 -0500953 input_method->input = NULL;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200954 input_method->focus_listener_initialized = 0;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200955 input_method->context = NULL;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100956 input_method->text_backend = text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200957
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200958 input_method->input_method_global =
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400959 wl_global_create(ec->wl_display, &wl_input_method_interface, 1,
960 input_method, bind_input_method);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200961
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200962 input_method->destroy_listener.notify = input_method_notifier_destroy;
Kristian Høgsberg49124542013-05-06 22:27:40 -0400963 wl_signal_add(&seat->destroy_signal, &input_method->destroy_listener);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200964
965 seat->input_method = input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100966
967 launch_input_method(text_backend);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200968}
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200969
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100970static void
Murray Calavera25881242015-06-10 21:15:30 +0000971handle_seat_created(struct wl_listener *listener, void *data)
972{
973 struct weston_seat *seat = data;
974 struct text_backend *text_backend =
975 container_of(listener, struct text_backend,
976 seat_created_listener);
977
978 text_backend_seat_created(text_backend, seat);
979}
980
981static void
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100982text_backend_configuration(struct text_backend *text_backend)
983{
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -0400984 struct weston_config_section *section;
Derek Foremanc7210432014-08-21 11:32:38 -0500985 char *client;
Pekka Paalanen974c0942014-09-05 14:45:09 +0300986 int ret;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100987
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -0400988 section = weston_config_get_section(text_backend->compositor->config,
989 "input-method", NULL, NULL);
Pekka Paalanen974c0942014-09-05 14:45:09 +0300990 ret = asprintf(&client, "%s/weston-keyboard",
991 weston_config_get_libexec_dir());
992 if (ret < 0)
993 client = NULL;
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -0400994 weston_config_section_get_string(section, "path",
995 &text_backend->input_method.path,
Derek Foremanc7210432014-08-21 11:32:38 -0500996 client);
997 free(client);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100998}
999
1000static void
1001text_backend_notifier_destroy(struct wl_listener *listener, void *data)
1002{
1003 struct text_backend *text_backend =
1004 container_of(listener, struct text_backend, destroy_listener);
1005
1006 if (text_backend->input_method.client)
1007 wl_client_destroy(text_backend->input_method.client);
1008
1009 free(text_backend->input_method.path);
1010
1011 free(text_backend);
1012}
1013
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001014WL_EXPORT int
1015text_backend_init(struct weston_compositor *ec)
1016{
1017 struct text_backend *text_backend;
Murray Calavera25881242015-06-10 21:15:30 +00001018 struct weston_seat *seat;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001019
Bryce Harringtonde16d892014-11-20 22:21:57 -08001020 text_backend = zalloc(sizeof(*text_backend));
1021 if (text_backend == NULL)
1022 return -1;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001023
1024 text_backend->compositor = ec;
1025
Murray Calavera25881242015-06-10 21:15:30 +00001026 text_backend_configuration(text_backend);
1027
1028 wl_list_for_each(seat, &ec->seat_list, link)
1029 text_backend_seat_created(text_backend, seat);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001030 text_backend->seat_created_listener.notify = handle_seat_created;
1031 wl_signal_add(&ec->seat_created_signal,
1032 &text_backend->seat_created_listener);
1033
1034 text_backend->destroy_listener.notify = text_backend_notifier_destroy;
1035 wl_signal_add(&ec->destroy_signal, &text_backend->destroy_listener);
1036
Jan Arne Petersen78d00e42013-04-18 16:47:24 +02001037 text_input_manager_create(ec);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001038
1039 return 0;
1040}