blob: dc672c6152614ebec74969c356af4f3891a0fd21 [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"
Jon Cruz867d50e2015-06-15 15:37:10 -070038#include "shared/helpers.h"
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020039
Derek Foreman516d6032015-05-08 17:08:40 -050040struct text_input_manager;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020041struct input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020042struct input_method_context;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010043struct text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020044
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020045struct text_input {
Jason Ekstrand89d31992013-06-14 10:07:59 -050046 struct wl_resource *resource;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020047
Jan Arne Petersene829adc2012-08-10 16:47:22 +020048 struct weston_compositor *ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020049
Jan Arne Petersene829adc2012-08-10 16:47:22 +020050 struct wl_list input_methods;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +020051
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -040052 struct weston_surface *surface;
Jan Arne Petersen61381972013-01-31 15:52:21 +010053
Jan Arne Petersen14da96b2013-04-18 16:47:28 +020054 pixman_box32_t cursor_rectangle;
55
Derek Foremand09dbb32014-12-05 15:38:39 -060056 bool input_panel_visible;
Derek Foreman516d6032015-05-08 17:08:40 -050057
58 struct text_input_manager *manager;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020059};
60
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020061struct text_input_manager {
62 struct wl_global *text_input_manager_global;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020063 struct wl_listener destroy_listener;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020064
Derek Foreman516d6032015-05-08 17:08:40 -050065 struct text_input *current_panel;
66
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +020067 struct weston_compositor *ec;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +020068};
69
70struct input_method {
71 struct wl_resource *input_method_binding;
72 struct wl_global *input_method_global;
73 struct wl_listener destroy_listener;
74
75 struct weston_seat *seat;
Derek Foreman0f299232015-05-08 17:08:41 -050076 struct text_input *input;
Jan Arne Petersene829adc2012-08-10 16:47:22 +020077
78 struct wl_list link;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +020079
80 struct wl_listener keyboard_focus_listener;
81
Derek Foremanddc2c972015-07-15 13:00:32 -050082 bool focus_listener_initialized;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020083
84 struct input_method_context *context;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010085
86 struct text_backend *text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020087};
88
Jan Arne Petersen620cd622012-09-09 23:08:32 +020089struct input_method_context {
Jason Ekstrand89d31992013-06-14 10:07:59 -050090 struct wl_resource *resource;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020091
Derek Foreman0f299232015-05-08 17:08:41 -050092 struct text_input *input;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +010093 struct input_method *input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020094
Jan Arne Petersen466b9c12012-11-18 19:06:45 +010095 struct wl_resource *keyboard;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020096};
97
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010098struct text_backend {
99 struct weston_compositor *compositor;
100
101 struct {
102 char *path;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100103 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;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100111};
112
Derek Foremancb5fcea2014-12-05 15:38:37 -0600113static void
Derek Foreman0f299232015-05-08 17:08:41 -0500114input_method_context_create(struct text_input *input,
Derek Foremancb5fcea2014-12-05 15:38:37 -0600115 struct input_method *input_method);
116static void
117input_method_context_end_keyboard_grab(struct input_method_context *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200118
Derek Foremancb5fcea2014-12-05 15:38:37 -0600119static void
120input_method_init_seat(struct weston_seat *seat);
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200121
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200122static void
Derek Foreman516d6032015-05-08 17:08:40 -0500123deactivate_input_method(struct input_method *input_method)
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200124{
Derek Foreman0f299232015-05-08 17:08:41 -0500125 struct text_input *text_input = input_method->input;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200126 struct weston_compositor *ec = text_input->ec;
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200127
Derek Foreman516d6032015-05-08 17:08:40 -0500128 if (input_method->context && input_method->input_method_binding) {
129 input_method_context_end_keyboard_grab(input_method->context);
Murray Calavera972d1af2015-06-09 20:29:28 +0000130 wl_input_method_send_deactivate(
131 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
Murray Calavera972d1af2015-06-09 20:29:28 +0000154 wl_list_for_each_safe(input_method, next,
155 &text_input->input_methods, link)
Derek Foreman516d6032015-05-08 17:08:40 -0500156 deactivate_input_method(input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200157
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200158 free(text_input);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200159}
160
161static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200162text_input_set_surrounding_text(struct wl_client *client,
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200163 struct wl_resource *resource,
Jan Arne Petersencb08f4d2012-09-09 23:08:40 +0200164 const char *text,
165 uint32_t cursor,
166 uint32_t anchor)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200167{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500168 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200169 struct input_method *input_method, *next;
170
Murray Calavera972d1af2015-06-09 20:29:28 +0000171 wl_list_for_each_safe(input_method, next,
172 &text_input->input_methods, link) {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200173 if (!input_method->context)
174 continue;
Murray Calavera972d1af2015-06-09 20:29:28 +0000175 wl_input_method_context_send_surrounding_text(
176 input_method->context->resource, text, cursor, 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) {
Murray Calavera972d1af2015-06-09 20:29:28 +0000215 wl_signal_emit(&ec->show_input_panel_signal,
216 text_input->surface);
217 wl_signal_emit(&ec->update_input_panel_signal,
218 &text_input->cursor_rectangle);
Derek Foreman516d6032015-05-08 17:08:40 -0500219 text_input->manager->current_panel = text_input;
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200220 }
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200221
Murray Calavera972d1af2015-06-09 20:29:28 +0000222 wl_text_input_send_enter(text_input->resource,
223 text_input->surface->resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200224}
225
226static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200227text_input_deactivate(struct wl_client *client,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200228 struct wl_resource *resource,
229 struct wl_resource *seat)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200230{
Jason Ekstrand44a38632013-06-14 10:08:00 -0500231 struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200232
Derek Foreman0f299232015-05-08 17:08:41 -0500233 if (weston_seat->input_method->input)
Derek Foreman516d6032015-05-08 17:08:40 -0500234 deactivate_input_method(weston_seat->input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200235}
236
237static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200238text_input_reset(struct wl_client *client,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200239 struct wl_resource *resource)
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200240{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500241 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200242 struct input_method *input_method, *next;
243
Murray Calavera972d1af2015-06-09 20:29:28 +0000244 wl_list_for_each_safe(input_method, next,
245 &text_input->input_methods, link) {
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200246 if (!input_method->context)
247 continue;
Murray Calavera972d1af2015-06-09 20:29:28 +0000248 wl_input_method_context_send_reset(
249 input_method->context->resource);
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200250 }
251}
252
253static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200254text_input_set_cursor_rectangle(struct wl_client *client,
Jan Arne Petersen7ef8eff2013-04-18 16:47:23 +0200255 struct wl_resource *resource,
256 int32_t x,
257 int32_t y,
258 int32_t width,
259 int32_t height)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200260{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500261 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200262 struct weston_compositor *ec = text_input->ec;
263
264 text_input->cursor_rectangle.x1 = x;
265 text_input->cursor_rectangle.y1 = y;
266 text_input->cursor_rectangle.x2 = x + width;
267 text_input->cursor_rectangle.y2 = y + height;
268
Murray Calavera972d1af2015-06-09 20:29:28 +0000269 wl_signal_emit(&ec->update_input_panel_signal,
270 &text_input->cursor_rectangle);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200271}
272
273static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200274text_input_set_content_type(struct wl_client *client,
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100275 struct wl_resource *resource,
276 uint32_t hint,
277 uint32_t purpose)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200278{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500279 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100280 struct input_method *input_method, *next;
281
Murray Calavera972d1af2015-06-09 20:29:28 +0000282 wl_list_for_each_safe(input_method, next,
283 &text_input->input_methods, link) {
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100284 if (!input_method->context)
285 continue;
Murray Calavera972d1af2015-06-09 20:29:28 +0000286 wl_input_method_context_send_content_type(
287 input_method->context->resource, hint, purpose);
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100288 }
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200289}
290
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100291static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200292text_input_invoke_action(struct wl_client *client,
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100293 struct wl_resource *resource,
294 uint32_t button,
295 uint32_t index)
296{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500297 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100298 struct input_method *input_method, *next;
299
Murray Calavera972d1af2015-06-09 20:29:28 +0000300 wl_list_for_each_safe(input_method, next,
301 &text_input->input_methods, link) {
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100302 if (!input_method->context)
303 continue;
Murray Calavera972d1af2015-06-09 20:29:28 +0000304 wl_input_method_context_send_invoke_action(
305 input_method->context->resource, button, index);
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100306 }
307}
308
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100309static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200310text_input_commit_state(struct wl_client *client,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200311 struct wl_resource *resource,
312 uint32_t serial)
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100313{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500314 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100315 struct input_method *input_method, *next;
316
Murray Calavera972d1af2015-06-09 20:29:28 +0000317 wl_list_for_each_safe(input_method, next,
318 &text_input->input_methods, link) {
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100319 if (!input_method->context)
320 continue;
Murray Calavera972d1af2015-06-09 20:29:28 +0000321 wl_input_method_context_send_commit_state(
322 input_method->context->resource, serial);
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100323 }
324}
325
Jan Arne Petersen61381972013-01-31 15:52:21 +0100326static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200327text_input_show_input_panel(struct wl_client *client,
Jan Arne Petersen61381972013-01-31 15:52:21 +0100328 struct wl_resource *resource)
329{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500330 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200331 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100332
Derek Foremand09dbb32014-12-05 15:38:39 -0600333 text_input->input_panel_visible = true;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100334
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200335 if (!wl_list_empty(&text_input->input_methods)) {
Murray Calavera972d1af2015-06-09 20:29:28 +0000336 wl_signal_emit(&ec->show_input_panel_signal,
337 text_input->surface);
338 wl_signal_emit(&ec->update_input_panel_signal,
339 &text_input->cursor_rectangle);
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200340 }
Jan Arne Petersen61381972013-01-31 15:52:21 +0100341}
342
343static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200344text_input_hide_input_panel(struct wl_client *client,
Jan Arne Petersen61381972013-01-31 15:52:21 +0100345 struct wl_resource *resource)
346{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500347 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200348 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100349
Derek Foremand09dbb32014-12-05 15:38:39 -0600350 text_input->input_panel_visible = false;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100351
Derek Foreman516d6032015-05-08 17:08:40 -0500352 if (!wl_list_empty(&text_input->input_methods) &&
353 text_input == text_input->manager->current_panel) {
354 text_input->manager->current_panel = NULL;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100355 wl_signal_emit(&ec->hide_input_panel_signal, ec);
Derek Foreman516d6032015-05-08 17:08:40 -0500356 }
Jan Arne Petersen61381972013-01-31 15:52:21 +0100357}
358
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200359static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200360text_input_set_preferred_language(struct wl_client *client,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200361 struct wl_resource *resource,
362 const char *language)
363{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500364 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200365 struct input_method *input_method, *next;
366
Murray Calavera972d1af2015-06-09 20:29:28 +0000367 wl_list_for_each_safe(input_method, next,
368 &text_input->input_methods, link) {
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200369 if (!input_method->context)
370 continue;
Murray Calavera972d1af2015-06-09 20:29:28 +0000371 wl_input_method_context_send_preferred_language(
372 input_method->context->resource, language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200373 }
374}
375
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200376static const struct wl_text_input_interface text_input_implementation = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200377 text_input_activate,
378 text_input_deactivate,
379 text_input_show_input_panel,
380 text_input_hide_input_panel,
381 text_input_reset,
382 text_input_set_surrounding_text,
383 text_input_set_content_type,
384 text_input_set_cursor_rectangle,
385 text_input_set_preferred_language,
386 text_input_commit_state,
387 text_input_invoke_action
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200388};
389
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200390static void text_input_manager_create_text_input(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200391 struct wl_resource *resource,
Jan Arne Petersen4c265182012-09-09 23:08:30 +0200392 uint32_t id)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200393{
Murray Calavera972d1af2015-06-09 20:29:28 +0000394 struct text_input_manager *text_input_manager =
395 wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200396 struct text_input *text_input;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200397
Bryce Harringtonde16d892014-11-20 22:21:57 -0800398 text_input = zalloc(sizeof *text_input);
399 if (text_input == NULL)
400 return;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200401
Jason Ekstranda85118c2013-06-27 20:17:02 -0500402 text_input->resource =
403 wl_resource_create(client, &wl_text_input_interface, 1, id);
404 wl_resource_set_implementation(text_input->resource,
405 &text_input_implementation,
406 text_input, destroy_text_input);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200407
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200408 text_input->ec = text_input_manager->ec;
Derek Foreman516d6032015-05-08 17:08:40 -0500409 text_input->manager = text_input_manager;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200410
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200411 wl_list_init(&text_input->input_methods);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200412};
413
Murray Calavera972d1af2015-06-09 20:29:28 +0000414static const struct wl_text_input_manager_interface manager_implementation = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200415 text_input_manager_create_text_input
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200416};
417
418static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200419bind_text_input_manager(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200420 void *data,
421 uint32_t version,
422 uint32_t id)
423{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200424 struct text_input_manager *text_input_manager = data;
Jason Ekstranda85118c2013-06-27 20:17:02 -0500425 struct wl_resource *resource;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200426
Jason Ekstranda85118c2013-06-27 20:17:02 -0500427 /* No checking for duplicate binding necessary. */
428 resource =
429 wl_resource_create(client,
430 &wl_text_input_manager_interface, 1, id);
431 if (resource)
432 wl_resource_set_implementation(resource,
Murray Calavera972d1af2015-06-09 20:29:28 +0000433 &manager_implementation,
Jason Ekstranda85118c2013-06-27 20:17:02 -0500434 text_input_manager, NULL);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200435}
436
437static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200438text_input_manager_notifier_destroy(struct wl_listener *listener, void *data)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200439{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200440 struct text_input_manager *text_input_manager =
Murray Calavera972d1af2015-06-09 20:29:28 +0000441 container_of(listener,
442 struct text_input_manager,
443 destroy_listener);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200444
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400445 wl_global_destroy(text_input_manager->text_input_manager_global);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200446
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200447 free(text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200448}
449
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100450static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200451text_input_manager_create(struct weston_compositor *ec)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200452{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200453 struct text_input_manager *text_input_manager;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200454
Bryce Harringtonde16d892014-11-20 22:21:57 -0800455 text_input_manager = zalloc(sizeof *text_input_manager);
456 if (text_input_manager == NULL)
457 return;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200458
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200459 text_input_manager->ec = ec;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200460
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200461 text_input_manager->text_input_manager_global =
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400462 wl_global_create(ec->wl_display,
463 &wl_text_input_manager_interface, 1,
464 text_input_manager, bind_text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200465
Murray Calavera972d1af2015-06-09 20:29:28 +0000466 text_input_manager->destroy_listener.notify =
467 text_input_manager_notifier_destroy;
468 wl_signal_add(&ec->destroy_signal,
469 &text_input_manager->destroy_listener);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200470}
471
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200472static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200473input_method_context_destroy(struct wl_client *client,
474 struct wl_resource *resource)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200475{
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200476 wl_resource_destroy(resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200477}
478
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200479static void
480input_method_context_commit_string(struct wl_client *client,
481 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100482 uint32_t serial,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100483 const char *text)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200484{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500485 struct input_method_context *context =
486 wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200487
Derek Foreman0f299232015-05-08 17:08:41 -0500488 if (context->input)
489 wl_text_input_send_commit_string(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800490 serial, text);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200491}
492
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200493static void
494input_method_context_preedit_string(struct wl_client *client,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100495 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100496 uint32_t serial,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100497 const char *text,
498 const char *commit)
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200499{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500500 struct input_method_context *context =
501 wl_resource_get_user_data(resource);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200502
Derek Foreman0f299232015-05-08 17:08:41 -0500503 if (context->input)
504 wl_text_input_send_preedit_string(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800505 serial, text, commit);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100506}
507
508static void
509input_method_context_preedit_styling(struct wl_client *client,
510 struct wl_resource *resource,
511 uint32_t index,
512 uint32_t length,
513 uint32_t style)
514{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500515 struct input_method_context *context =
516 wl_resource_get_user_data(resource);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100517
Derek Foreman0f299232015-05-08 17:08:41 -0500518 if (context->input)
519 wl_text_input_send_preedit_styling(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800520 index, length, style);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100521}
522
523static void
524input_method_context_preedit_cursor(struct wl_client *client,
525 struct wl_resource *resource,
526 int32_t cursor)
527{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500528 struct input_method_context *context =
529 wl_resource_get_user_data(resource);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100530
Derek Foreman0f299232015-05-08 17:08:41 -0500531 if (context->input)
532 wl_text_input_send_preedit_cursor(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800533 cursor);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200534}
535
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200536static void
537input_method_context_delete_surrounding_text(struct wl_client *client,
538 struct wl_resource *resource,
539 int32_t index,
540 uint32_t length)
541{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500542 struct input_method_context *context =
543 wl_resource_get_user_data(resource);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200544
Derek Foreman0f299232015-05-08 17:08:41 -0500545 if (context->input)
Murray Calavera972d1af2015-06-09 20:29:28 +0000546 wl_text_input_send_delete_surrounding_text(
547 context->input->resource, index, length);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200548}
549
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200550static void
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100551input_method_context_cursor_position(struct wl_client *client,
552 struct wl_resource *resource,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100553 int32_t index,
554 int32_t anchor)
555{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500556 struct input_method_context *context =
557 wl_resource_get_user_data(resource);
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100558
Derek Foreman0f299232015-05-08 17:08:41 -0500559 if (context->input)
560 wl_text_input_send_cursor_position(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800561 index, anchor);
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100562}
563
564static void
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100565input_method_context_modifiers_map(struct wl_client *client,
566 struct wl_resource *resource,
567 struct wl_array *map)
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200568{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500569 struct input_method_context *context =
570 wl_resource_get_user_data(resource);
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200571
Derek Foreman0f299232015-05-08 17:08:41 -0500572 if (context->input)
573 wl_text_input_send_modifiers_map(context->input->resource, map);
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100574}
575
576static void
577input_method_context_keysym(struct wl_client *client,
578 struct wl_resource *resource,
579 uint32_t serial,
580 uint32_t time,
581 uint32_t sym,
582 uint32_t state,
583 uint32_t modifiers)
584{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500585 struct input_method_context *context =
586 wl_resource_get_user_data(resource);
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100587
Derek Foreman0f299232015-05-08 17:08:41 -0500588 if (context->input)
589 wl_text_input_send_keysym(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800590 serial, time, sym, state, modifiers);
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200591}
592
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100593static void
594unbind_keyboard(struct wl_resource *resource)
595{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500596 struct input_method_context *context =
597 wl_resource_get_user_data(resource);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100598
599 input_method_context_end_keyboard_grab(context);
600 context->keyboard = NULL;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100601}
602
603static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400604input_method_context_grab_key(struct weston_keyboard_grab *grab,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100605 uint32_t time, uint32_t key, uint32_t state_w)
606{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400607 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100608 struct wl_display *display;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100609 uint32_t serial;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100610
611 if (!keyboard->input_method_resource)
612 return;
613
Murray Calavera972d1af2015-06-09 20:29:28 +0000614 display = wl_client_get_display(
615 wl_resource_get_client(keyboard->input_method_resource));
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100616 serial = wl_display_next_serial(display);
617 wl_keyboard_send_key(keyboard->input_method_resource,
618 serial, time, key, state_w);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100619}
620
621static void
Murray Calavera972d1af2015-06-09 20:29:28 +0000622input_method_context_grab_modifier(struct weston_keyboard_grab *grab,
623 uint32_t serial,
624 uint32_t mods_depressed,
625 uint32_t mods_latched,
626 uint32_t mods_locked,
627 uint32_t group)
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100628{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400629 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100630
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100631 if (!keyboard->input_method_resource)
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100632 return;
633
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100634 wl_keyboard_send_modifiers(keyboard->input_method_resource,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100635 serial, mods_depressed, mods_latched,
636 mods_locked, group);
637}
638
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200639static void
640input_method_context_grab_cancel(struct weston_keyboard_grab *grab)
641{
642 weston_keyboard_end_grab(grab->keyboard);
643}
644
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400645static const struct weston_keyboard_grab_interface input_method_context_grab = {
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100646 input_method_context_grab_key,
647 input_method_context_grab_modifier,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200648 input_method_context_grab_cancel,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100649};
650
651static void
652input_method_context_grab_keyboard(struct wl_client *client,
653 struct wl_resource *resource,
654 uint32_t id)
655{
Murray Calavera972d1af2015-06-09 20:29:28 +0000656 struct input_method_context *context =
657 wl_resource_get_user_data(resource);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100658 struct wl_resource *cr;
659 struct weston_seat *seat = context->input_method->seat;
Derek Foreman1281a362015-07-31 16:55:32 -0500660 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100661
Jason Ekstranda85118c2013-06-27 20:17:02 -0500662 cr = wl_resource_create(client, &wl_keyboard_interface, 1, id);
663 wl_resource_set_implementation(cr, NULL, context, unbind_keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100664
665 context->keyboard = cr;
666
667 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
Jonas Ådahl7395ea02013-12-03 09:14:26 +0100668 keyboard->xkb_info->keymap_fd,
669 keyboard->xkb_info->keymap_size);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100670
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400671 if (keyboard->grab != &keyboard->default_grab) {
672 weston_keyboard_end_grab(keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100673 }
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400674 weston_keyboard_start_grab(keyboard, &keyboard->input_method_grab);
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100675 keyboard->input_method_resource = cr;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100676}
677
Jan Arne Petersen337df952012-11-18 19:06:46 +0100678static void
679input_method_context_key(struct wl_client *client,
680 struct wl_resource *resource,
681 uint32_t serial,
682 uint32_t time,
683 uint32_t key,
684 uint32_t state_w)
685{
Murray Calavera972d1af2015-06-09 20:29:28 +0000686 struct input_method_context *context =
687 wl_resource_get_user_data(resource);
Jan Arne Petersen337df952012-11-18 19:06:46 +0100688 struct weston_seat *seat = context->input_method->seat;
Derek Foreman1281a362015-07-31 16:55:32 -0500689 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400690 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100691
692 default_grab->interface->key(default_grab, time, key, state_w);
693}
694
695static void
696input_method_context_modifiers(struct wl_client *client,
697 struct wl_resource *resource,
698 uint32_t serial,
699 uint32_t mods_depressed,
700 uint32_t mods_latched,
701 uint32_t mods_locked,
702 uint32_t group)
703{
Murray Calavera972d1af2015-06-09 20:29:28 +0000704 struct input_method_context *context =
705 wl_resource_get_user_data(resource);
Jan Arne Petersen337df952012-11-18 19:06:46 +0100706
707 struct weston_seat *seat = context->input_method->seat;
Derek Foreman1281a362015-07-31 16:55:32 -0500708 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400709 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100710
711 default_grab->interface->modifiers(default_grab,
712 serial, mods_depressed,
713 mods_latched, mods_locked,
714 group);
715}
716
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200717static void
718input_method_context_language(struct wl_client *client,
719 struct wl_resource *resource,
720 uint32_t serial,
721 const char *language)
722{
Murray Calavera972d1af2015-06-09 20:29:28 +0000723 struct input_method_context *context =
724 wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200725
Derek Foreman0f299232015-05-08 17:08:41 -0500726 if (context->input)
727 wl_text_input_send_language(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800728 serial, language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200729}
730
731static void
732input_method_context_text_direction(struct wl_client *client,
733 struct wl_resource *resource,
734 uint32_t serial,
735 uint32_t direction)
736{
Murray Calavera972d1af2015-06-09 20:29:28 +0000737 struct input_method_context *context =
738 wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200739
Derek Foreman0f299232015-05-08 17:08:41 -0500740 if (context->input)
741 wl_text_input_send_text_direction(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800742 serial, direction);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200743}
744
745
Murray Calavera972d1af2015-06-09 20:29:28 +0000746static const struct wl_input_method_context_interface context_implementation = {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200747 input_method_context_destroy,
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200748 input_method_context_commit_string,
749 input_method_context_preedit_string,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100750 input_method_context_preedit_styling,
751 input_method_context_preedit_cursor,
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200752 input_method_context_delete_surrounding_text,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100753 input_method_context_cursor_position,
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100754 input_method_context_modifiers_map,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100755 input_method_context_keysym,
Jan Arne Petersen337df952012-11-18 19:06:46 +0100756 input_method_context_grab_keyboard,
757 input_method_context_key,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200758 input_method_context_modifiers,
759 input_method_context_language,
760 input_method_context_text_direction
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200761};
762
763static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200764destroy_input_method_context(struct wl_resource *resource)
765{
Murray Calavera972d1af2015-06-09 20:29:28 +0000766 struct input_method_context *context =
767 wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200768
Murray Calavera972d1af2015-06-09 20:29:28 +0000769 if (context->keyboard)
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100770 wl_resource_destroy(context->keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100771
Derek Foreman516d6032015-05-08 17:08:40 -0500772 if (context->input_method && context->input_method->context == context)
773 context->input_method->context = NULL;
774
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200775 free(context);
776}
777
778static void
Derek Foreman0f299232015-05-08 17:08:41 -0500779input_method_context_create(struct text_input *input,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200780 struct input_method *input_method)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200781{
782 struct input_method_context *context;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500783 struct wl_resource *binding;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200784
785 if (!input_method->input_method_binding)
786 return;
787
Bryce Harringtonde16d892014-11-20 22:21:57 -0800788 context = zalloc(sizeof *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200789 if (context == NULL)
790 return;
791
Jason Ekstrand89d31992013-06-14 10:07:59 -0500792 binding = input_method->input_method_binding;
Jason Ekstranda85118c2013-06-27 20:17:02 -0500793 context->resource =
794 wl_resource_create(wl_resource_get_client(binding),
795 &wl_input_method_context_interface, 1, 0);
796 wl_resource_set_implementation(context->resource,
Murray Calavera972d1af2015-06-09 20:29:28 +0000797 &context_implementation,
Jason Ekstranda85118c2013-06-27 20:17:02 -0500798 context, destroy_input_method_context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200799
Derek Foreman0f299232015-05-08 17:08:41 -0500800 context->input = input;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100801 context->input_method = input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200802 input_method->context = context;
803
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200804
Jason Ekstrand89d31992013-06-14 10:07:59 -0500805 wl_input_method_send_activate(binding, context->resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200806}
807
808static void
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100809input_method_context_end_keyboard_grab(struct input_method_context *context)
810{
Derek Foremanf0aaa412014-12-08 10:48:29 -0600811 struct weston_keyboard_grab *grab;
812 struct weston_keyboard *keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100813
Derek Foreman1281a362015-07-31 16:55:32 -0500814 keyboard = weston_seat_get_keyboard(context->input_method->seat);
815 if (!keyboard)
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100816 return;
817
Derek Foreman1281a362015-07-31 16:55:32 -0500818 grab = &keyboard->input_method_grab;
Derek Foremanf0aaa412014-12-08 10:48:29 -0600819 keyboard = grab->keyboard;
820 if (!keyboard)
821 return;
822
823 if (keyboard->grab == grab)
824 weston_keyboard_end_grab(keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100825
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100826 keyboard->input_method_resource = NULL;
827}
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100828
829static void
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200830unbind_input_method(struct wl_resource *resource)
831{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500832 struct input_method *input_method = wl_resource_get_user_data(resource);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200833
834 input_method->input_method_binding = NULL;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200835 input_method->context = NULL;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200836}
837
838static void
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200839bind_input_method(struct wl_client *client,
840 void *data,
841 uint32_t version,
842 uint32_t id)
843{
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200844 struct input_method *input_method = data;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100845 struct text_backend *text_backend = input_method->text_backend;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200846 struct wl_resource *resource;
847
Jason Ekstranda85118c2013-06-27 20:17:02 -0500848 resource =
849 wl_resource_create(client, &wl_input_method_interface, 1, id);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200850
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200851 if (input_method->input_method_binding != NULL) {
Murray Calavera972d1af2015-06-09 20:29:28 +0000852 wl_resource_post_error(resource,
853 WL_DISPLAY_ERROR_INVALID_OBJECT,
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200854 "interface object already bound");
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200855 return;
856 }
857
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200858 if (text_backend->input_method.client != client) {
Murray Calavera972d1af2015-06-09 20:29:28 +0000859 wl_resource_post_error(resource,
860 WL_DISPLAY_ERROR_INVALID_OBJECT,
861 "permission to bind "
862 "input_method denied");
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200863 return;
864 }
865
Jason Ekstranda85118c2013-06-27 20:17:02 -0500866 wl_resource_set_implementation(resource, NULL, input_method,
867 unbind_input_method);
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200868 input_method->input_method_binding = resource;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200869}
870
871static void
872input_method_notifier_destroy(struct wl_listener *listener, void *data)
873{
Kristian Høgsbergf97f3792012-07-22 11:51:42 -0400874 struct input_method *input_method =
875 container_of(listener, struct input_method, destroy_listener);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200876
Derek Foreman0f299232015-05-08 17:08:41 -0500877 if (input_method->input)
Derek Foreman516d6032015-05-08 17:08:40 -0500878 deactivate_input_method(input_method);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200879
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400880 wl_global_destroy(input_method->input_method_global);
Rob Bradfordead3ef82013-07-24 16:57:32 +0100881 wl_list_remove(&input_method->destroy_listener.link);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200882
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200883 free(input_method);
884}
885
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200886static void
887handle_keyboard_focus(struct wl_listener *listener, void *data)
888{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400889 struct weston_keyboard *keyboard = data;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200890 struct input_method *input_method =
Murray Calavera972d1af2015-06-09 20:29:28 +0000891 container_of(listener, struct input_method,
892 keyboard_focus_listener);
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400893 struct weston_surface *surface = keyboard->focus;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200894
Derek Foreman0f299232015-05-08 17:08:41 -0500895 if (!input_method->input)
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200896 return;
897
Derek Foreman0f299232015-05-08 17:08:41 -0500898 if (!surface || input_method->input->surface != surface)
Derek Foreman516d6032015-05-08 17:08:40 -0500899 deactivate_input_method(input_method);
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200900}
901
902static void
903input_method_init_seat(struct weston_seat *seat)
904{
Derek Foreman1281a362015-07-31 16:55:32 -0500905 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
906
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200907 if (seat->input_method->focus_listener_initialized)
908 return;
909
Derek Foreman1281a362015-07-31 16:55:32 -0500910 if (keyboard) {
Murray Calavera972d1af2015-06-09 20:29:28 +0000911 seat->input_method->keyboard_focus_listener.notify =
912 handle_keyboard_focus;
Derek Foreman1281a362015-07-31 16:55:32 -0500913 wl_signal_add(&keyboard->focus_signal,
Murray Calavera972d1af2015-06-09 20:29:28 +0000914 &seat->input_method->keyboard_focus_listener);
Derek Foreman1281a362015-07-31 16:55:32 -0500915 keyboard->input_method_grab.interface =
Murray Calavera972d1af2015-06-09 20:29:28 +0000916 &input_method_context_grab;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200917 }
918
Derek Foremanddc2c972015-07-15 13:00:32 -0500919 seat->input_method->focus_listener_initialized = true;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200920}
921
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300922static void launch_input_method(struct text_backend *text_backend);
923
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100924static void
925handle_input_method_sigchld(struct weston_process *process, int status)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200926{
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300927 uint32_t time;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100928 struct text_backend *text_backend =
929 container_of(process, struct text_backend, input_method.process);
930
931 text_backend->input_method.process.pid = 0;
932 text_backend->input_method.client = NULL;
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300933
934 /* if input_method dies more than 5 times in 10 seconds, give up */
935 time = weston_compositor_get_time();
936 if (time - text_backend->input_method.deathstamp > 10000) {
937 text_backend->input_method.deathstamp = time;
938 text_backend->input_method.deathcount = 0;
939 }
940
941 text_backend->input_method.deathcount++;
942 if (text_backend->input_method.deathcount > 5) {
943 weston_log("input_method died, giving up.\n");
944 return;
945 }
946
947 weston_log("input_method died, respawning...\n");
948 launch_input_method(text_backend);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100949}
950
951static void
952launch_input_method(struct text_backend *text_backend)
953{
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100954 if (!text_backend->input_method.path)
955 return;
956
Murray Calaveraf65f89b2015-06-09 20:28:06 +0000957 if (strcmp(text_backend->input_method.path, "") == 0)
958 return;
959
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100960 if (text_backend->input_method.process.pid != 0)
961 return;
962
Murray Calavera972d1af2015-06-09 20:29:28 +0000963 text_backend->input_method.client =
964 weston_client_launch(text_backend->compositor,
965 &text_backend->input_method.process,
966 text_backend->input_method.path,
967 handle_input_method_sigchld);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100968
969 if (!text_backend->input_method.client)
Murray Calavera972d1af2015-06-09 20:29:28 +0000970 weston_log("not able to start %s\n",
971 text_backend->input_method.path);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100972}
973
974static void
Murray Calavera25881242015-06-10 21:15:30 +0000975text_backend_seat_created(struct text_backend *text_backend,
976 struct weston_seat *seat)
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100977{
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200978 struct input_method *input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100979 struct weston_compositor *ec = seat->compositor;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200980
Bryce Harringtonde16d892014-11-20 22:21:57 -0800981 input_method = zalloc(sizeof *input_method);
982 if (input_method == NULL)
983 return;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200984
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200985 input_method->seat = seat;
Derek Foreman0f299232015-05-08 17:08:41 -0500986 input_method->input = NULL;
Derek Foremanddc2c972015-07-15 13:00:32 -0500987 input_method->focus_listener_initialized = false;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200988 input_method->context = NULL;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100989 input_method->text_backend = text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200990
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200991 input_method->input_method_global =
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400992 wl_global_create(ec->wl_display, &wl_input_method_interface, 1,
993 input_method, bind_input_method);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200994
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200995 input_method->destroy_listener.notify = input_method_notifier_destroy;
Kristian Høgsberg49124542013-05-06 22:27:40 -0400996 wl_signal_add(&seat->destroy_signal, &input_method->destroy_listener);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200997
998 seat->input_method = input_method;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200999}
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +02001000
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001001static void
Murray Calavera25881242015-06-10 21:15:30 +00001002handle_seat_created(struct wl_listener *listener, void *data)
1003{
1004 struct weston_seat *seat = data;
1005 struct text_backend *text_backend =
1006 container_of(listener, struct text_backend,
1007 seat_created_listener);
1008
1009 text_backend_seat_created(text_backend, seat);
1010}
1011
1012static void
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001013text_backend_configuration(struct text_backend *text_backend)
1014{
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -04001015 struct weston_config_section *section;
Derek Foremanc7210432014-08-21 11:32:38 -05001016 char *client;
Pekka Paalanen974c0942014-09-05 14:45:09 +03001017 int ret;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001018
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -04001019 section = weston_config_get_section(text_backend->compositor->config,
1020 "input-method", NULL, NULL);
Pekka Paalanen974c0942014-09-05 14:45:09 +03001021 ret = asprintf(&client, "%s/weston-keyboard",
1022 weston_config_get_libexec_dir());
1023 if (ret < 0)
1024 client = NULL;
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -04001025 weston_config_section_get_string(section, "path",
1026 &text_backend->input_method.path,
Derek Foremanc7210432014-08-21 11:32:38 -05001027 client);
1028 free(client);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001029}
1030
Pekka Paalanenaa9536a2015-06-24 16:09:17 +03001031WL_EXPORT void
1032text_backend_destroy(struct text_backend *text_backend)
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001033{
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001034 if (text_backend->input_method.client)
1035 wl_client_destroy(text_backend->input_method.client);
1036
1037 free(text_backend->input_method.path);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001038 free(text_backend);
1039}
1040
Pekka Paalanenaa9536a2015-06-24 16:09:17 +03001041WL_EXPORT struct text_backend *
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001042text_backend_init(struct weston_compositor *ec)
1043{
1044 struct text_backend *text_backend;
Murray Calavera25881242015-06-10 21:15:30 +00001045 struct weston_seat *seat;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001046
Bryce Harringtonde16d892014-11-20 22:21:57 -08001047 text_backend = zalloc(sizeof(*text_backend));
1048 if (text_backend == NULL)
Pekka Paalanenaa9536a2015-06-24 16:09:17 +03001049 return NULL;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001050
1051 text_backend->compositor = ec;
1052
Murray Calavera25881242015-06-10 21:15:30 +00001053 text_backend_configuration(text_backend);
1054
1055 wl_list_for_each(seat, &ec->seat_list, link)
1056 text_backend_seat_created(text_backend, seat);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001057 text_backend->seat_created_listener.notify = handle_seat_created;
1058 wl_signal_add(&ec->seat_created_signal,
1059 &text_backend->seat_created_listener);
1060
Jan Arne Petersen78d00e42013-04-18 16:47:24 +02001061 text_input_manager_create(ec);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001062
Derek Foremanb4bacd22015-06-25 15:49:47 -05001063 launch_input_method(text_backend);
1064
Pekka Paalanenaa9536a2015-06-24 16:09:17 +03001065 return text_backend;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001066}