blob: d33f7038b9e8aa23984cc0d191cdabc9166be0c0 [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
82 int 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;
103 struct wl_resource *binding;
104 struct weston_process process;
105 struct wl_client *client;
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300106
107 unsigned deathcount;
108 uint32_t deathstamp;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100109 } input_method;
110
111 struct wl_listener seat_created_listener;
112 struct wl_listener destroy_listener;
113};
114
Derek Foremancb5fcea2014-12-05 15:38:37 -0600115static void
Derek Foreman0f299232015-05-08 17:08:41 -0500116input_method_context_create(struct text_input *input,
Derek Foremancb5fcea2014-12-05 15:38:37 -0600117 struct input_method *input_method);
118static void
119input_method_context_end_keyboard_grab(struct input_method_context *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200120
Derek Foremancb5fcea2014-12-05 15:38:37 -0600121static void
122input_method_init_seat(struct weston_seat *seat);
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200123
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200124static void
Derek Foreman516d6032015-05-08 17:08:40 -0500125deactivate_input_method(struct input_method *input_method)
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200126{
Derek Foreman0f299232015-05-08 17:08:41 -0500127 struct text_input *text_input = input_method->input;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200128 struct weston_compositor *ec = text_input->ec;
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200129
Derek Foreman516d6032015-05-08 17:08:40 -0500130 if (input_method->context && input_method->input_method_binding) {
131 input_method_context_end_keyboard_grab(input_method->context);
132 wl_input_method_send_deactivate(input_method->input_method_binding,
133 input_method->context->resource);
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200134 }
Derek Foreman516d6032015-05-08 17:08:40 -0500135
136 wl_list_remove(&input_method->link);
Derek Foreman0f299232015-05-08 17:08:41 -0500137 input_method->input = NULL;
Derek Foreman516d6032015-05-08 17:08:40 -0500138 input_method->context = NULL;
139
140 if (wl_list_empty(&text_input->input_methods) &&
141 text_input->input_panel_visible) {
142 wl_signal_emit(&ec->hide_input_panel_signal, ec);
143 text_input->input_panel_visible = false;
144 text_input->manager->current_panel = NULL;
145 }
146 wl_text_input_send_leave(text_input->resource);
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200147}
148
149static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200150destroy_text_input(struct wl_resource *resource)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200151{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500152 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200153 struct input_method *input_method, *next;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200154
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200155 wl_list_for_each_safe(input_method, next, &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
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200171 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200172 if (!input_method->context)
173 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500174 wl_input_method_context_send_surrounding_text(input_method->context->resource,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200175 text,
176 cursor,
177 anchor);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200178 }
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200179}
180
181static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200182text_input_activate(struct wl_client *client,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200183 struct wl_resource *resource,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200184 struct wl_resource *seat,
185 struct wl_resource *surface)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200186{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500187 struct text_input *text_input = wl_resource_get_user_data(resource);
Jason Ekstrand44a38632013-06-14 10:08:00 -0500188 struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200189 struct input_method *input_method = weston_seat->input_method;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200190 struct weston_compositor *ec = text_input->ec;
Derek Foreman516d6032015-05-08 17:08:40 -0500191 struct text_input *current;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200192
Derek Foreman0f299232015-05-08 17:08:41 -0500193 if (input_method->input == text_input)
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200194 return;
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200195
Derek Foreman0f299232015-05-08 17:08:41 -0500196 if (input_method->input)
Derek Foreman516d6032015-05-08 17:08:40 -0500197 deactivate_input_method(input_method);
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200198
Derek Foreman0f299232015-05-08 17:08:41 -0500199 input_method->input = text_input;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200200 wl_list_insert(&text_input->input_methods, &input_method->link);
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200201 input_method_init_seat(weston_seat);
202
Jason Ekstrand0f2ef7e2013-06-14 10:07:53 -0500203 text_input->surface = wl_resource_get_user_data(surface);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200204
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200205 input_method_context_create(text_input, input_method);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200206
Derek Foreman516d6032015-05-08 17:08:40 -0500207 current = text_input->manager->current_panel;
208
209 if (current && current != text_input) {
210 current->input_panel_visible = false;
211 wl_signal_emit(&ec->hide_input_panel_signal, ec);
212 text_input->manager->current_panel = NULL;
213 }
214
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200215 if (text_input->input_panel_visible) {
216 wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
217 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
Derek Foreman516d6032015-05-08 17:08:40 -0500218 text_input->manager->current_panel = text_input;
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200219 }
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200220
Jason Ekstrand89d31992013-06-14 10:07:59 -0500221 wl_text_input_send_enter(text_input->resource, text_input->surface->resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200222}
223
224static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200225text_input_deactivate(struct wl_client *client,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200226 struct wl_resource *resource,
227 struct wl_resource *seat)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200228{
Jason Ekstrand44a38632013-06-14 10:08:00 -0500229 struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200230
Derek Foreman0f299232015-05-08 17:08:41 -0500231 if (weston_seat->input_method->input)
Derek Foreman516d6032015-05-08 17:08:40 -0500232 deactivate_input_method(weston_seat->input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200233}
234
235static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200236text_input_reset(struct wl_client *client,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200237 struct wl_resource *resource)
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200238{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500239 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200240 struct input_method *input_method, *next;
241
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200242 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200243 if (!input_method->context)
244 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500245 wl_input_method_context_send_reset(input_method->context->resource);
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200246 }
247}
248
249static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200250text_input_set_cursor_rectangle(struct wl_client *client,
Jan Arne Petersen7ef8eff2013-04-18 16:47:23 +0200251 struct wl_resource *resource,
252 int32_t x,
253 int32_t y,
254 int32_t width,
255 int32_t height)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200256{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500257 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200258 struct weston_compositor *ec = text_input->ec;
259
260 text_input->cursor_rectangle.x1 = x;
261 text_input->cursor_rectangle.y1 = y;
262 text_input->cursor_rectangle.x2 = x + width;
263 text_input->cursor_rectangle.y2 = y + height;
264
265 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200266}
267
268static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200269text_input_set_content_type(struct wl_client *client,
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100270 struct wl_resource *resource,
271 uint32_t hint,
272 uint32_t purpose)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200273{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500274 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100275 struct input_method *input_method, *next;
276
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200277 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100278 if (!input_method->context)
279 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500280 wl_input_method_context_send_content_type(input_method->context->resource, hint, purpose);
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100281 }
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200282}
283
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100284static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200285text_input_invoke_action(struct wl_client *client,
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100286 struct wl_resource *resource,
287 uint32_t button,
288 uint32_t index)
289{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500290 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100291 struct input_method *input_method, *next;
292
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200293 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100294 if (!input_method->context)
295 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500296 wl_input_method_context_send_invoke_action(input_method->context->resource, button, index);
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100297 }
298}
299
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100300static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200301text_input_commit_state(struct wl_client *client,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200302 struct wl_resource *resource,
303 uint32_t serial)
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100304{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500305 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100306 struct input_method *input_method, *next;
307
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200308 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100309 if (!input_method->context)
310 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500311 wl_input_method_context_send_commit_state(input_method->context->resource, serial);
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100312 }
313}
314
Jan Arne Petersen61381972013-01-31 15:52:21 +0100315static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200316text_input_show_input_panel(struct wl_client *client,
Jan Arne Petersen61381972013-01-31 15:52:21 +0100317 struct wl_resource *resource)
318{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500319 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200320 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100321
Derek Foremand09dbb32014-12-05 15:38:39 -0600322 text_input->input_panel_visible = true;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100323
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200324 if (!wl_list_empty(&text_input->input_methods)) {
325 wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
326 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
327 }
Jan Arne Petersen61381972013-01-31 15:52:21 +0100328}
329
330static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200331text_input_hide_input_panel(struct wl_client *client,
Jan Arne Petersen61381972013-01-31 15:52:21 +0100332 struct wl_resource *resource)
333{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500334 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200335 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100336
Derek Foremand09dbb32014-12-05 15:38:39 -0600337 text_input->input_panel_visible = false;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100338
Derek Foreman516d6032015-05-08 17:08:40 -0500339 if (!wl_list_empty(&text_input->input_methods) &&
340 text_input == text_input->manager->current_panel) {
341 text_input->manager->current_panel = NULL;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100342 wl_signal_emit(&ec->hide_input_panel_signal, ec);
Derek Foreman516d6032015-05-08 17:08:40 -0500343 }
Jan Arne Petersen61381972013-01-31 15:52:21 +0100344}
345
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200346static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200347text_input_set_preferred_language(struct wl_client *client,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200348 struct wl_resource *resource,
349 const char *language)
350{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500351 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200352 struct input_method *input_method, *next;
353
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200354 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200355 if (!input_method->context)
356 continue;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500357 wl_input_method_context_send_preferred_language(input_method->context->resource,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200358 language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200359 }
360}
361
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200362static const struct wl_text_input_interface text_input_implementation = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200363 text_input_activate,
364 text_input_deactivate,
365 text_input_show_input_panel,
366 text_input_hide_input_panel,
367 text_input_reset,
368 text_input_set_surrounding_text,
369 text_input_set_content_type,
370 text_input_set_cursor_rectangle,
371 text_input_set_preferred_language,
372 text_input_commit_state,
373 text_input_invoke_action
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200374};
375
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200376static void text_input_manager_create_text_input(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200377 struct wl_resource *resource,
Jan Arne Petersen4c265182012-09-09 23:08:30 +0200378 uint32_t id)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200379{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500380 struct text_input_manager *text_input_manager = wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200381 struct text_input *text_input;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200382
Bryce Harringtonde16d892014-11-20 22:21:57 -0800383 text_input = zalloc(sizeof *text_input);
384 if (text_input == NULL)
385 return;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200386
Jason Ekstranda85118c2013-06-27 20:17:02 -0500387 text_input->resource =
388 wl_resource_create(client, &wl_text_input_interface, 1, id);
389 wl_resource_set_implementation(text_input->resource,
390 &text_input_implementation,
391 text_input, destroy_text_input);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200392
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200393 text_input->ec = text_input_manager->ec;
Derek Foreman516d6032015-05-08 17:08:40 -0500394 text_input->manager = text_input_manager;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200395
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200396 wl_list_init(&text_input->input_methods);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200397};
398
Jan Arne Petersen62ece762013-04-18 16:47:36 +0200399static const struct wl_text_input_manager_interface text_input_manager_implementation = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200400 text_input_manager_create_text_input
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200401};
402
403static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200404bind_text_input_manager(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200405 void *data,
406 uint32_t version,
407 uint32_t id)
408{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200409 struct text_input_manager *text_input_manager = data;
Jason Ekstranda85118c2013-06-27 20:17:02 -0500410 struct wl_resource *resource;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200411
Jason Ekstranda85118c2013-06-27 20:17:02 -0500412 /* No checking for duplicate binding necessary. */
413 resource =
414 wl_resource_create(client,
415 &wl_text_input_manager_interface, 1, id);
416 if (resource)
417 wl_resource_set_implementation(resource,
418 &text_input_manager_implementation,
419 text_input_manager, NULL);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200420}
421
422static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200423text_input_manager_notifier_destroy(struct wl_listener *listener, void *data)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200424{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200425 struct text_input_manager *text_input_manager =
426 container_of(listener, struct text_input_manager, destroy_listener);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200427
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400428 wl_global_destroy(text_input_manager->text_input_manager_global);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200429
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200430 free(text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200431}
432
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100433static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200434text_input_manager_create(struct weston_compositor *ec)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200435{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200436 struct text_input_manager *text_input_manager;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200437
Bryce Harringtonde16d892014-11-20 22:21:57 -0800438 text_input_manager = zalloc(sizeof *text_input_manager);
439 if (text_input_manager == NULL)
440 return;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200441
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200442 text_input_manager->ec = ec;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200443
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200444 text_input_manager->text_input_manager_global =
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400445 wl_global_create(ec->wl_display,
446 &wl_text_input_manager_interface, 1,
447 text_input_manager, bind_text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200448
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200449 text_input_manager->destroy_listener.notify = text_input_manager_notifier_destroy;
450 wl_signal_add(&ec->destroy_signal, &text_input_manager->destroy_listener);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200451}
452
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200453static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200454input_method_context_destroy(struct wl_client *client,
455 struct wl_resource *resource)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200456{
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200457 wl_resource_destroy(resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200458}
459
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200460static void
461input_method_context_commit_string(struct wl_client *client,
462 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100463 uint32_t serial,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100464 const char *text)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200465{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500466 struct input_method_context *context =
467 wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200468
Derek Foreman0f299232015-05-08 17:08:41 -0500469 if (context->input)
470 wl_text_input_send_commit_string(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800471 serial, text);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200472}
473
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200474static void
475input_method_context_preedit_string(struct wl_client *client,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100476 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100477 uint32_t serial,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100478 const char *text,
479 const char *commit)
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200480{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500481 struct input_method_context *context =
482 wl_resource_get_user_data(resource);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200483
Derek Foreman0f299232015-05-08 17:08:41 -0500484 if (context->input)
485 wl_text_input_send_preedit_string(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800486 serial, text, commit);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100487}
488
489static void
490input_method_context_preedit_styling(struct wl_client *client,
491 struct wl_resource *resource,
492 uint32_t index,
493 uint32_t length,
494 uint32_t style)
495{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500496 struct input_method_context *context =
497 wl_resource_get_user_data(resource);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100498
Derek Foreman0f299232015-05-08 17:08:41 -0500499 if (context->input)
500 wl_text_input_send_preedit_styling(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800501 index, length, style);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100502}
503
504static void
505input_method_context_preedit_cursor(struct wl_client *client,
506 struct wl_resource *resource,
507 int32_t cursor)
508{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500509 struct input_method_context *context =
510 wl_resource_get_user_data(resource);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100511
Derek Foreman0f299232015-05-08 17:08:41 -0500512 if (context->input)
513 wl_text_input_send_preedit_cursor(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800514 cursor);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200515}
516
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200517static void
518input_method_context_delete_surrounding_text(struct wl_client *client,
519 struct wl_resource *resource,
520 int32_t index,
521 uint32_t length)
522{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500523 struct input_method_context *context =
524 wl_resource_get_user_data(resource);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200525
Derek Foreman0f299232015-05-08 17:08:41 -0500526 if (context->input)
527 wl_text_input_send_delete_surrounding_text(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800528 index, length);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200529}
530
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200531static void
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100532input_method_context_cursor_position(struct wl_client *client,
533 struct wl_resource *resource,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100534 int32_t index,
535 int32_t anchor)
536{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500537 struct input_method_context *context =
538 wl_resource_get_user_data(resource);
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100539
Derek Foreman0f299232015-05-08 17:08:41 -0500540 if (context->input)
541 wl_text_input_send_cursor_position(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800542 index, anchor);
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100543}
544
545static void
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100546input_method_context_modifiers_map(struct wl_client *client,
547 struct wl_resource *resource,
548 struct wl_array *map)
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200549{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500550 struct input_method_context *context =
551 wl_resource_get_user_data(resource);
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200552
Derek Foreman0f299232015-05-08 17:08:41 -0500553 if (context->input)
554 wl_text_input_send_modifiers_map(context->input->resource, map);
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100555}
556
557static void
558input_method_context_keysym(struct wl_client *client,
559 struct wl_resource *resource,
560 uint32_t serial,
561 uint32_t time,
562 uint32_t sym,
563 uint32_t state,
564 uint32_t modifiers)
565{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500566 struct input_method_context *context =
567 wl_resource_get_user_data(resource);
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100568
Derek Foreman0f299232015-05-08 17:08:41 -0500569 if (context->input)
570 wl_text_input_send_keysym(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800571 serial, time, sym, state, modifiers);
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200572}
573
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100574static void
575unbind_keyboard(struct wl_resource *resource)
576{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500577 struct input_method_context *context =
578 wl_resource_get_user_data(resource);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100579
580 input_method_context_end_keyboard_grab(context);
581 context->keyboard = NULL;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100582}
583
584static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400585input_method_context_grab_key(struct weston_keyboard_grab *grab,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100586 uint32_t time, uint32_t key, uint32_t state_w)
587{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400588 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100589 struct wl_display *display;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100590 uint32_t serial;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100591
592 if (!keyboard->input_method_resource)
593 return;
594
Jason Ekstrand89d31992013-06-14 10:07:59 -0500595 display = wl_client_get_display(wl_resource_get_client(keyboard->input_method_resource));
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100596 serial = wl_display_next_serial(display);
597 wl_keyboard_send_key(keyboard->input_method_resource,
598 serial, time, key, state_w);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100599}
600
601static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400602input_method_context_grab_modifier(struct weston_keyboard_grab *grab, uint32_t serial,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100603 uint32_t mods_depressed, uint32_t mods_latched,
604 uint32_t mods_locked, uint32_t group)
605{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400606 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100607
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100608 if (!keyboard->input_method_resource)
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100609 return;
610
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100611 wl_keyboard_send_modifiers(keyboard->input_method_resource,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100612 serial, mods_depressed, mods_latched,
613 mods_locked, group);
614}
615
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200616static void
617input_method_context_grab_cancel(struct weston_keyboard_grab *grab)
618{
619 weston_keyboard_end_grab(grab->keyboard);
620}
621
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400622static const struct weston_keyboard_grab_interface input_method_context_grab = {
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100623 input_method_context_grab_key,
624 input_method_context_grab_modifier,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200625 input_method_context_grab_cancel,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100626};
627
628static void
629input_method_context_grab_keyboard(struct wl_client *client,
630 struct wl_resource *resource,
631 uint32_t id)
632{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500633 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100634 struct wl_resource *cr;
635 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400636 struct weston_keyboard *keyboard = seat->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100637
Jason Ekstranda85118c2013-06-27 20:17:02 -0500638 cr = wl_resource_create(client, &wl_keyboard_interface, 1, id);
639 wl_resource_set_implementation(cr, NULL, context, unbind_keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100640
641 context->keyboard = cr;
642
643 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
Jonas Ådahl7395ea02013-12-03 09:14:26 +0100644 keyboard->xkb_info->keymap_fd,
645 keyboard->xkb_info->keymap_size);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100646
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400647 if (keyboard->grab != &keyboard->default_grab) {
648 weston_keyboard_end_grab(keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100649 }
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400650 weston_keyboard_start_grab(keyboard, &keyboard->input_method_grab);
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100651 keyboard->input_method_resource = cr;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100652}
653
Jan Arne Petersen337df952012-11-18 19:06:46 +0100654static void
655input_method_context_key(struct wl_client *client,
656 struct wl_resource *resource,
657 uint32_t serial,
658 uint32_t time,
659 uint32_t key,
660 uint32_t state_w)
661{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500662 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen337df952012-11-18 19:06:46 +0100663 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400664 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400665 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100666
667 default_grab->interface->key(default_grab, time, key, state_w);
668}
669
670static void
671input_method_context_modifiers(struct wl_client *client,
672 struct wl_resource *resource,
673 uint32_t serial,
674 uint32_t mods_depressed,
675 uint32_t mods_latched,
676 uint32_t mods_locked,
677 uint32_t group)
678{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500679 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen337df952012-11-18 19:06:46 +0100680
681 struct weston_seat *seat = context->input_method->seat;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400682 struct weston_keyboard *keyboard = seat->keyboard;
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400683 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100684
685 default_grab->interface->modifiers(default_grab,
686 serial, mods_depressed,
687 mods_latched, mods_locked,
688 group);
689}
690
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200691static void
692input_method_context_language(struct wl_client *client,
693 struct wl_resource *resource,
694 uint32_t serial,
695 const char *language)
696{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500697 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200698
Derek Foreman0f299232015-05-08 17:08:41 -0500699 if (context->input)
700 wl_text_input_send_language(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800701 serial, language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200702}
703
704static void
705input_method_context_text_direction(struct wl_client *client,
706 struct wl_resource *resource,
707 uint32_t serial,
708 uint32_t direction)
709{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500710 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200711
Derek Foreman0f299232015-05-08 17:08:41 -0500712 if (context->input)
713 wl_text_input_send_text_direction(context->input->resource,
Kristian Høgsbergc1809772014-01-13 15:06:10 -0800714 serial, direction);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200715}
716
717
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200718static const struct wl_input_method_context_interface input_method_context_implementation = {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200719 input_method_context_destroy,
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200720 input_method_context_commit_string,
721 input_method_context_preedit_string,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100722 input_method_context_preedit_styling,
723 input_method_context_preedit_cursor,
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200724 input_method_context_delete_surrounding_text,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100725 input_method_context_cursor_position,
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100726 input_method_context_modifiers_map,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100727 input_method_context_keysym,
Jan Arne Petersen337df952012-11-18 19:06:46 +0100728 input_method_context_grab_keyboard,
729 input_method_context_key,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200730 input_method_context_modifiers,
731 input_method_context_language,
732 input_method_context_text_direction
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200733};
734
735static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200736destroy_input_method_context(struct wl_resource *resource)
737{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500738 struct input_method_context *context = wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200739
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100740 if (context->keyboard) {
741 wl_resource_destroy(context->keyboard);
742 }
743
Derek Foreman516d6032015-05-08 17:08:40 -0500744 if (context->input_method && context->input_method->context == context)
745 context->input_method->context = NULL;
746
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200747 free(context);
748}
749
750static void
Derek Foreman0f299232015-05-08 17:08:41 -0500751input_method_context_create(struct text_input *input,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200752 struct input_method *input_method)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200753{
754 struct input_method_context *context;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500755 struct wl_resource *binding;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200756
757 if (!input_method->input_method_binding)
758 return;
759
Bryce Harringtonde16d892014-11-20 22:21:57 -0800760 context = zalloc(sizeof *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200761 if (context == NULL)
762 return;
763
Jason Ekstrand89d31992013-06-14 10:07:59 -0500764 binding = input_method->input_method_binding;
Jason Ekstranda85118c2013-06-27 20:17:02 -0500765 context->resource =
766 wl_resource_create(wl_resource_get_client(binding),
767 &wl_input_method_context_interface, 1, 0);
768 wl_resource_set_implementation(context->resource,
769 &input_method_context_implementation,
770 context, destroy_input_method_context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200771
Derek Foreman0f299232015-05-08 17:08:41 -0500772 context->input = input;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100773 context->input_method = input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200774 input_method->context = context;
775
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200776
Jason Ekstrand89d31992013-06-14 10:07:59 -0500777 wl_input_method_send_activate(binding, context->resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200778}
779
780static void
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100781input_method_context_end_keyboard_grab(struct input_method_context *context)
782{
Derek Foremanf0aaa412014-12-08 10:48:29 -0600783 struct weston_keyboard_grab *grab;
784 struct weston_keyboard *keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100785
Derek Foremanf0aaa412014-12-08 10:48:29 -0600786 if (!context->input_method->seat->keyboard)
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100787 return;
788
Derek Foremanf0aaa412014-12-08 10:48:29 -0600789 grab = &context->input_method->seat->keyboard->input_method_grab;
790 keyboard = grab->keyboard;
791 if (!keyboard)
792 return;
793
794 if (keyboard->grab == grab)
795 weston_keyboard_end_grab(keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100796
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100797 keyboard->input_method_resource = NULL;
798}
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100799
800static void
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200801unbind_input_method(struct wl_resource *resource)
802{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500803 struct input_method *input_method = wl_resource_get_user_data(resource);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100804 struct text_backend *text_backend = input_method->text_backend;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200805
806 input_method->input_method_binding = NULL;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200807 input_method->context = NULL;
808
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100809 text_backend->input_method.binding = NULL;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200810}
811
812static void
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200813bind_input_method(struct wl_client *client,
814 void *data,
815 uint32_t version,
816 uint32_t id)
817{
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200818 struct input_method *input_method = data;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100819 struct text_backend *text_backend = input_method->text_backend;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200820 struct wl_resource *resource;
821
Jason Ekstranda85118c2013-06-27 20:17:02 -0500822 resource =
823 wl_resource_create(client, &wl_input_method_interface, 1, id);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200824
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200825 if (input_method->input_method_binding != NULL) {
826 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
827 "interface object already bound");
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200828 return;
829 }
830
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200831 if (text_backend->input_method.client != client) {
832 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
Eduardo Lima (Etrunko)a2ce68f2013-05-10 17:50:36 -0300833 "permission to bind input_method denied");
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200834 return;
835 }
836
Jason Ekstranda85118c2013-06-27 20:17:02 -0500837 wl_resource_set_implementation(resource, NULL, input_method,
838 unbind_input_method);
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200839 input_method->input_method_binding = resource;
840
841 text_backend->input_method.binding = resource;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200842}
843
844static void
845input_method_notifier_destroy(struct wl_listener *listener, void *data)
846{
Kristian Høgsbergf97f3792012-07-22 11:51:42 -0400847 struct input_method *input_method =
848 container_of(listener, struct input_method, destroy_listener);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200849
Derek Foreman0f299232015-05-08 17:08:41 -0500850 if (input_method->input)
Derek Foreman516d6032015-05-08 17:08:40 -0500851 deactivate_input_method(input_method);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200852
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400853 wl_global_destroy(input_method->input_method_global);
Rob Bradfordead3ef82013-07-24 16:57:32 +0100854 wl_list_remove(&input_method->destroy_listener.link);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200855
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200856 free(input_method);
857}
858
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200859static void
860handle_keyboard_focus(struct wl_listener *listener, void *data)
861{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400862 struct weston_keyboard *keyboard = data;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200863 struct input_method *input_method =
864 container_of(listener, struct input_method, keyboard_focus_listener);
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400865 struct weston_surface *surface = keyboard->focus;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200866
Derek Foreman0f299232015-05-08 17:08:41 -0500867 if (!input_method->input)
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200868 return;
869
Derek Foreman0f299232015-05-08 17:08:41 -0500870 if (!surface || input_method->input->surface != surface)
Derek Foreman516d6032015-05-08 17:08:40 -0500871 deactivate_input_method(input_method);
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200872}
873
874static void
875input_method_init_seat(struct weston_seat *seat)
876{
877 if (seat->input_method->focus_listener_initialized)
878 return;
879
Kristian Høgsberg2bf87622013-05-07 23:17:41 -0400880 if (seat->keyboard) {
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200881 seat->input_method->keyboard_focus_listener.notify = handle_keyboard_focus;
Kristian Høgsberge3148752013-05-06 23:19:49 -0400882 wl_signal_add(&seat->keyboard->focus_signal, &seat->input_method->keyboard_focus_listener);
883 seat->keyboard->input_method_grab.interface = &input_method_context_grab;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200884 }
885
886 seat->input_method->focus_listener_initialized = 1;
887}
888
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300889static void launch_input_method(struct text_backend *text_backend);
890
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100891static void
892handle_input_method_sigchld(struct weston_process *process, int status)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200893{
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300894 uint32_t time;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100895 struct text_backend *text_backend =
896 container_of(process, struct text_backend, input_method.process);
897
898 text_backend->input_method.process.pid = 0;
899 text_backend->input_method.client = NULL;
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300900
901 /* if input_method dies more than 5 times in 10 seconds, give up */
902 time = weston_compositor_get_time();
903 if (time - text_backend->input_method.deathstamp > 10000) {
904 text_backend->input_method.deathstamp = time;
905 text_backend->input_method.deathcount = 0;
906 }
907
908 text_backend->input_method.deathcount++;
909 if (text_backend->input_method.deathcount > 5) {
910 weston_log("input_method died, giving up.\n");
911 return;
912 }
913
914 weston_log("input_method died, respawning...\n");
915 launch_input_method(text_backend);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100916}
917
918static void
919launch_input_method(struct text_backend *text_backend)
920{
921 if (text_backend->input_method.binding)
922 return;
923
924 if (!text_backend->input_method.path)
925 return;
926
Murray Calaveraf65f89b2015-06-09 20:28:06 +0000927 if (strcmp(text_backend->input_method.path, "") == 0)
928 return;
929
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100930 if (text_backend->input_method.process.pid != 0)
931 return;
932
933 text_backend->input_method.client = weston_client_launch(text_backend->compositor,
Jan Arne Petersencc75ec12013-04-18 16:47:39 +0200934 &text_backend->input_method.process,
935 text_backend->input_method.path,
936 handle_input_method_sigchld);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100937
938 if (!text_backend->input_method.client)
939 weston_log("not able to start %s\n", text_backend->input_method.path);
940}
941
942static void
Murray Calavera25881242015-06-10 21:15:30 +0000943text_backend_seat_created(struct text_backend *text_backend,
944 struct weston_seat *seat)
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100945{
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200946 struct input_method *input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100947 struct weston_compositor *ec = seat->compositor;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200948
Bryce Harringtonde16d892014-11-20 22:21:57 -0800949 input_method = zalloc(sizeof *input_method);
950 if (input_method == NULL)
951 return;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200952
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200953 input_method->seat = seat;
Derek Foreman0f299232015-05-08 17:08:41 -0500954 input_method->input = NULL;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200955 input_method->focus_listener_initialized = 0;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200956 input_method->context = NULL;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100957 input_method->text_backend = text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200958
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200959 input_method->input_method_global =
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400960 wl_global_create(ec->wl_display, &wl_input_method_interface, 1,
961 input_method, bind_input_method);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200962
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200963 input_method->destroy_listener.notify = input_method_notifier_destroy;
Kristian Høgsberg49124542013-05-06 22:27:40 -0400964 wl_signal_add(&seat->destroy_signal, &input_method->destroy_listener);
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200965
966 seat->input_method = input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100967
968 launch_input_method(text_backend);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200969}
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200970
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100971static void
Murray Calavera25881242015-06-10 21:15:30 +0000972handle_seat_created(struct wl_listener *listener, void *data)
973{
974 struct weston_seat *seat = data;
975 struct text_backend *text_backend =
976 container_of(listener, struct text_backend,
977 seat_created_listener);
978
979 text_backend_seat_created(text_backend, seat);
980}
981
982static void
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100983text_backend_configuration(struct text_backend *text_backend)
984{
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -0400985 struct weston_config_section *section;
Derek Foremanc7210432014-08-21 11:32:38 -0500986 char *client;
Pekka Paalanen974c0942014-09-05 14:45:09 +0300987 int ret;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100988
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -0400989 section = weston_config_get_section(text_backend->compositor->config,
990 "input-method", NULL, NULL);
Pekka Paalanen974c0942014-09-05 14:45:09 +0300991 ret = asprintf(&client, "%s/weston-keyboard",
992 weston_config_get_libexec_dir());
993 if (ret < 0)
994 client = NULL;
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -0400995 weston_config_section_get_string(section, "path",
996 &text_backend->input_method.path,
Derek Foremanc7210432014-08-21 11:32:38 -0500997 client);
998 free(client);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100999}
1000
1001static void
1002text_backend_notifier_destroy(struct wl_listener *listener, void *data)
1003{
1004 struct text_backend *text_backend =
1005 container_of(listener, struct text_backend, destroy_listener);
1006
1007 if (text_backend->input_method.client)
1008 wl_client_destroy(text_backend->input_method.client);
1009
1010 free(text_backend->input_method.path);
1011
1012 free(text_backend);
1013}
1014
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001015WL_EXPORT int
1016text_backend_init(struct weston_compositor *ec)
1017{
1018 struct text_backend *text_backend;
Murray Calavera25881242015-06-10 21:15:30 +00001019 struct weston_seat *seat;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001020
Bryce Harringtonde16d892014-11-20 22:21:57 -08001021 text_backend = zalloc(sizeof(*text_backend));
1022 if (text_backend == NULL)
1023 return -1;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001024
1025 text_backend->compositor = ec;
1026
Murray Calavera25881242015-06-10 21:15:30 +00001027 text_backend_configuration(text_backend);
1028
1029 wl_list_for_each(seat, &ec->seat_list, link)
1030 text_backend_seat_created(text_backend, seat);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001031 text_backend->seat_created_listener.notify = handle_seat_created;
1032 wl_signal_add(&ec->seat_created_signal,
1033 &text_backend->seat_created_listener);
1034
1035 text_backend->destroy_listener.notify = text_backend_notifier_destroy;
1036 wl_signal_add(&ec->destroy_signal, &text_backend->destroy_listener);
1037
Jan Arne Petersen78d00e42013-04-18 16:47:24 +02001038 text_input_manager_create(ec);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001039
1040 return 0;
1041}