blob: 743cbc41760fed097952059495fe407aa7c32d0f [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"
Giulio Camuffofba27fb2016-06-02 21:48:10 +030036#include "weston.h"
Jonas Ådahl3bcba342015-11-17 16:00:29 +080037#include "text-input-unstable-v1-server-protocol.h"
Jonas Ådahlb57f4722015-11-17 16:00:30 +080038#include "input-method-unstable-v1-server-protocol.h"
Jon Cruz867d50e2015-06-15 15:37:10 -070039#include "shared/helpers.h"
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020040
Derek Foreman516d6032015-05-08 17:08:40 -050041struct text_input_manager;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020042struct input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020043struct input_method_context;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010044struct text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020045
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020046struct text_input {
Jason Ekstrand89d31992013-06-14 10:07:59 -050047 struct wl_resource *resource;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020048
Jan Arne Petersene829adc2012-08-10 16:47:22 +020049 struct weston_compositor *ec;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020050
Jan Arne Petersene829adc2012-08-10 16:47:22 +020051 struct wl_list input_methods;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +020052
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -040053 struct weston_surface *surface;
Jan Arne Petersen61381972013-01-31 15:52:21 +010054
Jan Arne Petersen14da96b2013-04-18 16:47:28 +020055 pixman_box32_t cursor_rectangle;
56
Derek Foremand09dbb32014-12-05 15:38:39 -060057 bool input_panel_visible;
Derek Foreman516d6032015-05-08 17:08:40 -050058
59 struct text_input_manager *manager;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020060};
61
Jan Arne Petersen78d00e42013-04-18 16:47:24 +020062struct text_input_manager {
63 struct wl_global *text_input_manager_global;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020064 struct wl_listener destroy_listener;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020065
Derek Foreman516d6032015-05-08 17:08:40 -050066 struct text_input *current_panel;
67
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +020068 struct weston_compositor *ec;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +020069};
70
71struct input_method {
72 struct wl_resource *input_method_binding;
73 struct wl_global *input_method_global;
74 struct wl_listener destroy_listener;
75
76 struct weston_seat *seat;
Derek Foreman0f299232015-05-08 17:08:41 -050077 struct text_input *input;
Jan Arne Petersene829adc2012-08-10 16:47:22 +020078
79 struct wl_list link;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +020080
81 struct wl_listener keyboard_focus_listener;
82
Derek Foremanddc2c972015-07-15 13:00:32 -050083 bool focus_listener_initialized;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020084
85 struct input_method_context *context;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010086
87 struct text_backend *text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +020088};
89
Jan Arne Petersen620cd622012-09-09 23:08:32 +020090struct input_method_context {
Jason Ekstrand89d31992013-06-14 10:07:59 -050091 struct wl_resource *resource;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020092
Derek Foreman0f299232015-05-08 17:08:41 -050093 struct text_input *input;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +010094 struct input_method *input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020095
Jan Arne Petersen466b9c12012-11-18 19:06:45 +010096 struct wl_resource *keyboard;
Jan Arne Petersen620cd622012-09-09 23:08:32 +020097};
98
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +010099struct text_backend {
100 struct weston_compositor *compositor;
101
102 struct {
103 char *path;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100104 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
Derek Foreman89dcea92015-06-25 15:49:49 -0500110 struct wl_listener client_listener;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100111 struct wl_listener seat_created_listener;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100112};
113
Derek Foremancb5fcea2014-12-05 15:38:37 -0600114static void
Derek Foreman0f299232015-05-08 17:08:41 -0500115input_method_context_create(struct text_input *input,
Derek Foremancb5fcea2014-12-05 15:38:37 -0600116 struct input_method *input_method);
117static void
118input_method_context_end_keyboard_grab(struct input_method_context *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200119
Derek Foremancb5fcea2014-12-05 15:38:37 -0600120static void
121input_method_init_seat(struct weston_seat *seat);
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200122
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200123static void
Derek Foreman516d6032015-05-08 17:08:40 -0500124deactivate_input_method(struct input_method *input_method)
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200125{
Derek Foreman0f299232015-05-08 17:08:41 -0500126 struct text_input *text_input = input_method->input;
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200127 struct weston_compositor *ec = text_input->ec;
Philipp Brüschweiler17467812012-07-11 22:25:30 +0200128
Derek Foreman516d6032015-05-08 17:08:40 -0500129 if (input_method->context && input_method->input_method_binding) {
130 input_method_context_end_keyboard_grab(input_method->context);
Jonas Ådahlb57f4722015-11-17 16:00:30 +0800131 zwp_input_method_v1_send_deactivate(
Murray Calavera972d1af2015-06-09 20:29:28 +0000132 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 }
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800146 zwp_text_input_v1_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
Murray Calavera972d1af2015-06-09 20:29:28 +0000155 wl_list_for_each_safe(input_method, next,
156 &text_input->input_methods, link)
Derek Foreman516d6032015-05-08 17:08:40 -0500157 deactivate_input_method(input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200158
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200159 free(text_input);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200160}
161
162static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200163text_input_set_surrounding_text(struct wl_client *client,
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200164 struct wl_resource *resource,
Jan Arne Petersencb08f4d2012-09-09 23:08:40 +0200165 const char *text,
166 uint32_t cursor,
167 uint32_t anchor)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200168{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500169 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200170 struct input_method *input_method, *next;
171
Murray Calavera972d1af2015-06-09 20:29:28 +0000172 wl_list_for_each_safe(input_method, next,
173 &text_input->input_methods, link) {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200174 if (!input_method->context)
175 continue;
Jonas Ådahlb57f4722015-11-17 16:00:30 +0800176 zwp_input_method_context_v1_send_surrounding_text(
Murray Calavera972d1af2015-06-09 20:29:28 +0000177 input_method->context->resource, text, cursor, 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) {
Murray Calavera972d1af2015-06-09 20:29:28 +0000216 wl_signal_emit(&ec->show_input_panel_signal,
217 text_input->surface);
218 wl_signal_emit(&ec->update_input_panel_signal,
219 &text_input->cursor_rectangle);
Derek Foreman516d6032015-05-08 17:08:40 -0500220 text_input->manager->current_panel = text_input;
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200221 }
Jan Arne Petersende3b6a12012-08-10 16:47:21 +0200222
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800223 zwp_text_input_v1_send_enter(text_input->resource,
224 text_input->surface->resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200225}
226
227static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200228text_input_deactivate(struct wl_client *client,
Jan Arne Petersene829adc2012-08-10 16:47:22 +0200229 struct wl_resource *resource,
230 struct wl_resource *seat)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200231{
Jason Ekstrand44a38632013-06-14 10:08:00 -0500232 struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200233
Derek Foreman0f299232015-05-08 17:08:41 -0500234 if (weston_seat->input_method->input)
Derek Foreman516d6032015-05-08 17:08:40 -0500235 deactivate_input_method(weston_seat->input_method);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200236}
237
238static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200239text_input_reset(struct wl_client *client,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200240 struct wl_resource *resource)
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200241{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500242 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200243 struct input_method *input_method, *next;
244
Murray Calavera972d1af2015-06-09 20:29:28 +0000245 wl_list_for_each_safe(input_method, next,
246 &text_input->input_methods, link) {
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200247 if (!input_method->context)
248 continue;
Jonas Ådahlb57f4722015-11-17 16:00:30 +0800249 zwp_input_method_context_v1_send_reset(
Murray Calavera972d1af2015-06-09 20:29:28 +0000250 input_method->context->resource);
Jan Arne Petersenc1e481e2012-09-09 23:08:46 +0200251 }
252}
253
254static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200255text_input_set_cursor_rectangle(struct wl_client *client,
Jan Arne Petersen7ef8eff2013-04-18 16:47:23 +0200256 struct wl_resource *resource,
257 int32_t x,
258 int32_t y,
259 int32_t width,
260 int32_t height)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200261{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500262 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200263 struct weston_compositor *ec = text_input->ec;
264
265 text_input->cursor_rectangle.x1 = x;
266 text_input->cursor_rectangle.y1 = y;
267 text_input->cursor_rectangle.x2 = x + width;
268 text_input->cursor_rectangle.y2 = y + height;
269
Murray Calavera972d1af2015-06-09 20:29:28 +0000270 wl_signal_emit(&ec->update_input_panel_signal,
271 &text_input->cursor_rectangle);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200272}
273
274static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200275text_input_set_content_type(struct wl_client *client,
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100276 struct wl_resource *resource,
277 uint32_t hint,
278 uint32_t purpose)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200279{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500280 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100281 struct input_method *input_method, *next;
282
Murray Calavera972d1af2015-06-09 20:29:28 +0000283 wl_list_for_each_safe(input_method, next,
284 &text_input->input_methods, link) {
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100285 if (!input_method->context)
286 continue;
Jonas Ådahlb57f4722015-11-17 16:00:30 +0800287 zwp_input_method_context_v1_send_content_type(
Murray Calavera972d1af2015-06-09 20:29:28 +0000288 input_method->context->resource, hint, purpose);
Jan Arne Petersen26ffa812013-01-16 21:26:43 +0100289 }
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200290}
291
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100292static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200293text_input_invoke_action(struct wl_client *client,
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100294 struct wl_resource *resource,
295 uint32_t button,
296 uint32_t index)
297{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500298 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100299 struct input_method *input_method, *next;
300
Murray Calavera972d1af2015-06-09 20:29:28 +0000301 wl_list_for_each_safe(input_method, next,
302 &text_input->input_methods, link) {
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100303 if (!input_method->context)
304 continue;
Jonas Ådahlb57f4722015-11-17 16:00:30 +0800305 zwp_input_method_context_v1_send_invoke_action(
Murray Calavera972d1af2015-06-09 20:29:28 +0000306 input_method->context->resource, button, index);
Jan Arne Petersenadfedc12013-01-16 21:26:46 +0100307 }
308}
309
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100310static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200311text_input_commit_state(struct wl_client *client,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200312 struct wl_resource *resource,
313 uint32_t serial)
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100314{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500315 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100316 struct input_method *input_method, *next;
317
Murray Calavera972d1af2015-06-09 20:29:28 +0000318 wl_list_for_each_safe(input_method, next,
319 &text_input->input_methods, link) {
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100320 if (!input_method->context)
321 continue;
Jonas Ådahlb57f4722015-11-17 16:00:30 +0800322 zwp_input_method_context_v1_send_commit_state(
Murray Calavera972d1af2015-06-09 20:29:28 +0000323 input_method->context->resource, serial);
Jan Arne Petersen0eabcaa2013-01-31 15:52:20 +0100324 }
325}
326
Jan Arne Petersen61381972013-01-31 15:52:21 +0100327static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200328text_input_show_input_panel(struct wl_client *client,
Jan Arne Petersen61381972013-01-31 15:52:21 +0100329 struct wl_resource *resource)
330{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500331 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200332 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100333
Derek Foremand09dbb32014-12-05 15:38:39 -0600334 text_input->input_panel_visible = true;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100335
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200336 if (!wl_list_empty(&text_input->input_methods)) {
Murray Calavera972d1af2015-06-09 20:29:28 +0000337 wl_signal_emit(&ec->show_input_panel_signal,
338 text_input->surface);
339 wl_signal_emit(&ec->update_input_panel_signal,
340 &text_input->cursor_rectangle);
Jan Arne Petersen14da96b2013-04-18 16:47:28 +0200341 }
Jan Arne Petersen61381972013-01-31 15:52:21 +0100342}
343
344static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200345text_input_hide_input_panel(struct wl_client *client,
Jan Arne Petersen61381972013-01-31 15:52:21 +0100346 struct wl_resource *resource)
347{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500348 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200349 struct weston_compositor *ec = text_input->ec;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100350
Derek Foremand09dbb32014-12-05 15:38:39 -0600351 text_input->input_panel_visible = false;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100352
Derek Foreman516d6032015-05-08 17:08:40 -0500353 if (!wl_list_empty(&text_input->input_methods) &&
354 text_input == text_input->manager->current_panel) {
355 text_input->manager->current_panel = NULL;
Jan Arne Petersen61381972013-01-31 15:52:21 +0100356 wl_signal_emit(&ec->hide_input_panel_signal, ec);
Derek Foreman516d6032015-05-08 17:08:40 -0500357 }
Jan Arne Petersen61381972013-01-31 15:52:21 +0100358}
359
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200360static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200361text_input_set_preferred_language(struct wl_client *client,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200362 struct wl_resource *resource,
363 const char *language)
364{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500365 struct text_input *text_input = wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200366 struct input_method *input_method, *next;
367
Murray Calavera972d1af2015-06-09 20:29:28 +0000368 wl_list_for_each_safe(input_method, next,
369 &text_input->input_methods, link) {
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200370 if (!input_method->context)
371 continue;
Jonas Ådahlb57f4722015-11-17 16:00:30 +0800372 zwp_input_method_context_v1_send_preferred_language(
Murray Calavera972d1af2015-06-09 20:29:28 +0000373 input_method->context->resource, language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200374 }
375}
376
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800377static const struct zwp_text_input_v1_interface text_input_implementation = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200378 text_input_activate,
379 text_input_deactivate,
380 text_input_show_input_panel,
381 text_input_hide_input_panel,
382 text_input_reset,
383 text_input_set_surrounding_text,
384 text_input_set_content_type,
385 text_input_set_cursor_rectangle,
386 text_input_set_preferred_language,
387 text_input_commit_state,
388 text_input_invoke_action
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200389};
390
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200391static void text_input_manager_create_text_input(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200392 struct wl_resource *resource,
Jan Arne Petersen4c265182012-09-09 23:08:30 +0200393 uint32_t id)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200394{
Murray Calavera972d1af2015-06-09 20:29:28 +0000395 struct text_input_manager *text_input_manager =
396 wl_resource_get_user_data(resource);
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200397 struct text_input *text_input;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200398
Bryce Harringtonde16d892014-11-20 22:21:57 -0800399 text_input = zalloc(sizeof *text_input);
400 if (text_input == NULL)
401 return;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200402
Jason Ekstranda85118c2013-06-27 20:17:02 -0500403 text_input->resource =
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800404 wl_resource_create(client, &zwp_text_input_v1_interface, 1, id);
Jason Ekstranda85118c2013-06-27 20:17:02 -0500405 wl_resource_set_implementation(text_input->resource,
406 &text_input_implementation,
407 text_input, destroy_text_input);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200408
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200409 text_input->ec = text_input_manager->ec;
Derek Foreman516d6032015-05-08 17:08:40 -0500410 text_input->manager = text_input_manager;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200411
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200412 wl_list_init(&text_input->input_methods);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200413};
414
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800415static const struct zwp_text_input_manager_v1_interface manager_implementation = {
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200416 text_input_manager_create_text_input
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200417};
418
419static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200420bind_text_input_manager(struct wl_client *client,
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200421 void *data,
422 uint32_t version,
423 uint32_t id)
424{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200425 struct text_input_manager *text_input_manager = data;
Jason Ekstranda85118c2013-06-27 20:17:02 -0500426 struct wl_resource *resource;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200427
Jason Ekstranda85118c2013-06-27 20:17:02 -0500428 /* No checking for duplicate binding necessary. */
429 resource =
430 wl_resource_create(client,
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800431 &zwp_text_input_manager_v1_interface, 1, id);
Jason Ekstranda85118c2013-06-27 20:17:02 -0500432 if (resource)
433 wl_resource_set_implementation(resource,
Murray Calavera972d1af2015-06-09 20:29:28 +0000434 &manager_implementation,
Jason Ekstranda85118c2013-06-27 20:17:02 -0500435 text_input_manager, NULL);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200436}
437
438static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200439text_input_manager_notifier_destroy(struct wl_listener *listener, void *data)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200440{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200441 struct text_input_manager *text_input_manager =
Murray Calavera972d1af2015-06-09 20:29:28 +0000442 container_of(listener,
443 struct text_input_manager,
444 destroy_listener);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200445
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400446 wl_global_destroy(text_input_manager->text_input_manager_global);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200447
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200448 free(text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200449}
450
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100451static void
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200452text_input_manager_create(struct weston_compositor *ec)
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200453{
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200454 struct text_input_manager *text_input_manager;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200455
Bryce Harringtonde16d892014-11-20 22:21:57 -0800456 text_input_manager = zalloc(sizeof *text_input_manager);
457 if (text_input_manager == NULL)
458 return;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200459
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200460 text_input_manager->ec = ec;
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200461
Jan Arne Petersen78d00e42013-04-18 16:47:24 +0200462 text_input_manager->text_input_manager_global =
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400463 wl_global_create(ec->wl_display,
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800464 &zwp_text_input_manager_v1_interface, 1,
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400465 text_input_manager, bind_text_input_manager);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200466
Murray Calavera972d1af2015-06-09 20:29:28 +0000467 text_input_manager->destroy_listener.notify =
468 text_input_manager_notifier_destroy;
469 wl_signal_add(&ec->destroy_signal,
470 &text_input_manager->destroy_listener);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200471}
472
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200473static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200474input_method_context_destroy(struct wl_client *client,
475 struct wl_resource *resource)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200476{
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200477 wl_resource_destroy(resource);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200478}
479
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200480static void
481input_method_context_commit_string(struct wl_client *client,
482 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100483 uint32_t serial,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100484 const char *text)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200485{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500486 struct input_method_context *context =
487 wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200488
Derek Foreman0f299232015-05-08 17:08:41 -0500489 if (context->input)
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800490 zwp_text_input_v1_send_commit_string(context->input->resource,
491 serial, text);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200492}
493
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200494static void
495input_method_context_preedit_string(struct wl_client *client,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100496 struct wl_resource *resource,
Jan Arne Petersenc7d2a982013-01-16 21:26:39 +0100497 uint32_t serial,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100498 const char *text,
499 const char *commit)
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200500{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500501 struct input_method_context *context =
502 wl_resource_get_user_data(resource);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200503
Derek Foreman0f299232015-05-08 17:08:41 -0500504 if (context->input)
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800505 zwp_text_input_v1_send_preedit_string(context->input->resource,
506 serial, text, commit);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100507}
508
509static void
510input_method_context_preedit_styling(struct wl_client *client,
511 struct wl_resource *resource,
512 uint32_t index,
513 uint32_t length,
514 uint32_t style)
515{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500516 struct input_method_context *context =
517 wl_resource_get_user_data(resource);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100518
Derek Foreman0f299232015-05-08 17:08:41 -0500519 if (context->input)
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800520 zwp_text_input_v1_send_preedit_styling(context->input->resource,
521 index, length, style);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100522}
523
524static void
525input_method_context_preedit_cursor(struct wl_client *client,
526 struct wl_resource *resource,
527 int32_t cursor)
528{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500529 struct input_method_context *context =
530 wl_resource_get_user_data(resource);
Jan Arne Petersen46535312013-01-16 21:26:38 +0100531
Derek Foreman0f299232015-05-08 17:08:41 -0500532 if (context->input)
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800533 zwp_text_input_v1_send_preedit_cursor(context->input->resource,
534 cursor);
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200535}
536
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200537static void
538input_method_context_delete_surrounding_text(struct wl_client *client,
539 struct wl_resource *resource,
540 int32_t index,
541 uint32_t length)
542{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500543 struct input_method_context *context =
544 wl_resource_get_user_data(resource);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200545
Derek Foreman0f299232015-05-08 17:08:41 -0500546 if (context->input)
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800547 zwp_text_input_v1_send_delete_surrounding_text(
Murray Calavera972d1af2015-06-09 20:29:28 +0000548 context->input->resource, index, length);
Jan Arne Petersene202bae2012-09-09 23:08:44 +0200549}
550
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200551static void
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100552input_method_context_cursor_position(struct wl_client *client,
553 struct wl_resource *resource,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100554 int32_t index,
555 int32_t anchor)
556{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500557 struct input_method_context *context =
558 wl_resource_get_user_data(resource);
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100559
Derek Foreman0f299232015-05-08 17:08:41 -0500560 if (context->input)
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800561 zwp_text_input_v1_send_cursor_position(context->input->resource,
562 index, anchor);
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100563}
564
565static void
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100566input_method_context_modifiers_map(struct wl_client *client,
567 struct wl_resource *resource,
568 struct wl_array *map)
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200569{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500570 struct input_method_context *context =
571 wl_resource_get_user_data(resource);
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200572
Derek Foreman0f299232015-05-08 17:08:41 -0500573 if (context->input)
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800574 zwp_text_input_v1_send_modifiers_map(context->input->resource,
575 map);
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100576}
577
578static void
579input_method_context_keysym(struct wl_client *client,
580 struct wl_resource *resource,
581 uint32_t serial,
582 uint32_t time,
583 uint32_t sym,
584 uint32_t state,
585 uint32_t modifiers)
586{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500587 struct input_method_context *context =
588 wl_resource_get_user_data(resource);
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100589
Derek Foreman0f299232015-05-08 17:08:41 -0500590 if (context->input)
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800591 zwp_text_input_v1_send_keysym(context->input->resource,
592 serial, time,
593 sym, state, modifiers);
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200594}
595
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100596static void
597unbind_keyboard(struct wl_resource *resource)
598{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500599 struct input_method_context *context =
600 wl_resource_get_user_data(resource);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100601
602 input_method_context_end_keyboard_grab(context);
603 context->keyboard = NULL;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100604}
605
606static void
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400607input_method_context_grab_key(struct weston_keyboard_grab *grab,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100608 uint32_t time, uint32_t key, uint32_t state_w)
609{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400610 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100611 struct wl_display *display;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100612 uint32_t serial;
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100613
614 if (!keyboard->input_method_resource)
615 return;
616
Murray Calavera972d1af2015-06-09 20:29:28 +0000617 display = wl_client_get_display(
618 wl_resource_get_client(keyboard->input_method_resource));
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100619 serial = wl_display_next_serial(display);
620 wl_keyboard_send_key(keyboard->input_method_resource,
621 serial, time, key, state_w);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100622}
623
624static void
Murray Calavera972d1af2015-06-09 20:29:28 +0000625input_method_context_grab_modifier(struct weston_keyboard_grab *grab,
626 uint32_t serial,
627 uint32_t mods_depressed,
628 uint32_t mods_latched,
629 uint32_t mods_locked,
630 uint32_t group)
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100631{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400632 struct weston_keyboard *keyboard = grab->keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100633
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100634 if (!keyboard->input_method_resource)
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100635 return;
636
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100637 wl_keyboard_send_modifiers(keyboard->input_method_resource,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100638 serial, mods_depressed, mods_latched,
639 mods_locked, group);
640}
641
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200642static void
643input_method_context_grab_cancel(struct weston_keyboard_grab *grab)
644{
645 weston_keyboard_end_grab(grab->keyboard);
646}
647
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400648static const struct weston_keyboard_grab_interface input_method_context_grab = {
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100649 input_method_context_grab_key,
650 input_method_context_grab_modifier,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200651 input_method_context_grab_cancel,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100652};
653
654static void
655input_method_context_grab_keyboard(struct wl_client *client,
656 struct wl_resource *resource,
657 uint32_t id)
658{
Murray Calavera972d1af2015-06-09 20:29:28 +0000659 struct input_method_context *context =
660 wl_resource_get_user_data(resource);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100661 struct wl_resource *cr;
662 struct weston_seat *seat = context->input_method->seat;
Derek Foreman1281a362015-07-31 16:55:32 -0500663 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100664
Jason Ekstranda85118c2013-06-27 20:17:02 -0500665 cr = wl_resource_create(client, &wl_keyboard_interface, 1, id);
666 wl_resource_set_implementation(cr, NULL, context, unbind_keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100667
668 context->keyboard = cr;
669
670 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
Jonas Ådahl7395ea02013-12-03 09:14:26 +0100671 keyboard->xkb_info->keymap_fd,
672 keyboard->xkb_info->keymap_size);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100673
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400674 if (keyboard->grab != &keyboard->default_grab) {
675 weston_keyboard_end_grab(keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100676 }
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400677 weston_keyboard_start_grab(keyboard, &keyboard->input_method_grab);
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100678 keyboard->input_method_resource = cr;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100679}
680
Jan Arne Petersen337df952012-11-18 19:06:46 +0100681static void
682input_method_context_key(struct wl_client *client,
683 struct wl_resource *resource,
684 uint32_t serial,
685 uint32_t time,
686 uint32_t key,
687 uint32_t state_w)
688{
Murray Calavera972d1af2015-06-09 20:29:28 +0000689 struct input_method_context *context =
690 wl_resource_get_user_data(resource);
Jan Arne Petersen337df952012-11-18 19:06:46 +0100691 struct weston_seat *seat = context->input_method->seat;
Derek Foreman1281a362015-07-31 16:55:32 -0500692 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400693 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100694
695 default_grab->interface->key(default_grab, time, key, state_w);
696}
697
698static void
699input_method_context_modifiers(struct wl_client *client,
700 struct wl_resource *resource,
701 uint32_t serial,
702 uint32_t mods_depressed,
703 uint32_t mods_latched,
704 uint32_t mods_locked,
705 uint32_t group)
706{
Murray Calavera972d1af2015-06-09 20:29:28 +0000707 struct input_method_context *context =
708 wl_resource_get_user_data(resource);
Jan Arne Petersen337df952012-11-18 19:06:46 +0100709
710 struct weston_seat *seat = context->input_method->seat;
Derek Foreman1281a362015-07-31 16:55:32 -0500711 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400712 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
Jan Arne Petersen337df952012-11-18 19:06:46 +0100713
714 default_grab->interface->modifiers(default_grab,
715 serial, mods_depressed,
716 mods_latched, mods_locked,
717 group);
718}
719
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200720static void
721input_method_context_language(struct wl_client *client,
722 struct wl_resource *resource,
723 uint32_t serial,
724 const char *language)
725{
Murray Calavera972d1af2015-06-09 20:29:28 +0000726 struct input_method_context *context =
727 wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200728
Derek Foreman0f299232015-05-08 17:08:41 -0500729 if (context->input)
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800730 zwp_text_input_v1_send_language(context->input->resource,
731 serial, language);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200732}
733
734static void
735input_method_context_text_direction(struct wl_client *client,
736 struct wl_resource *resource,
737 uint32_t serial,
738 uint32_t direction)
739{
Murray Calavera972d1af2015-06-09 20:29:28 +0000740 struct input_method_context *context =
741 wl_resource_get_user_data(resource);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200742
Derek Foreman0f299232015-05-08 17:08:41 -0500743 if (context->input)
Jonas Ådahl3bcba342015-11-17 16:00:29 +0800744 zwp_text_input_v1_send_text_direction(context->input->resource,
745 serial, direction);
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200746}
747
748
Jonas Ådahlb57f4722015-11-17 16:00:30 +0800749static const struct zwp_input_method_context_v1_interface context_implementation = {
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200750 input_method_context_destroy,
Jan Arne Petersen43f4aa82012-09-09 23:08:43 +0200751 input_method_context_commit_string,
752 input_method_context_preedit_string,
Jan Arne Petersen46535312013-01-16 21:26:38 +0100753 input_method_context_preedit_styling,
754 input_method_context_preedit_cursor,
Jan Arne Petersence8a4432012-09-09 23:08:45 +0200755 input_method_context_delete_surrounding_text,
Jan Arne Petersen1cc9e082013-01-31 15:52:23 +0100756 input_method_context_cursor_position,
Jan Arne Petersend9be93b2012-11-18 19:06:43 +0100757 input_method_context_modifiers_map,
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100758 input_method_context_keysym,
Jan Arne Petersen337df952012-11-18 19:06:46 +0100759 input_method_context_grab_keyboard,
760 input_method_context_key,
Jan Arne Petersenece6b5a2013-04-18 16:47:15 +0200761 input_method_context_modifiers,
762 input_method_context_language,
763 input_method_context_text_direction
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200764};
765
766static void
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200767destroy_input_method_context(struct wl_resource *resource)
768{
Murray Calavera972d1af2015-06-09 20:29:28 +0000769 struct input_method_context *context =
770 wl_resource_get_user_data(resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200771
Murray Calavera972d1af2015-06-09 20:29:28 +0000772 if (context->keyboard)
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100773 wl_resource_destroy(context->keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100774
Derek Foreman516d6032015-05-08 17:08:40 -0500775 if (context->input_method && context->input_method->context == context)
776 context->input_method->context = NULL;
777
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200778 free(context);
779}
780
781static void
Derek Foreman0f299232015-05-08 17:08:41 -0500782input_method_context_create(struct text_input *input,
Jan Arne Petersen00191c72013-04-18 16:47:33 +0200783 struct input_method *input_method)
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200784{
785 struct input_method_context *context;
Jason Ekstrand89d31992013-06-14 10:07:59 -0500786 struct wl_resource *binding;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200787
788 if (!input_method->input_method_binding)
789 return;
790
Bryce Harringtonde16d892014-11-20 22:21:57 -0800791 context = zalloc(sizeof *context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200792 if (context == NULL)
793 return;
794
Jason Ekstrand89d31992013-06-14 10:07:59 -0500795 binding = input_method->input_method_binding;
Jason Ekstranda85118c2013-06-27 20:17:02 -0500796 context->resource =
797 wl_resource_create(wl_resource_get_client(binding),
Jonas Ådahlb57f4722015-11-17 16:00:30 +0800798 &zwp_input_method_context_v1_interface,
799 1, 0);
Jason Ekstranda85118c2013-06-27 20:17:02 -0500800 wl_resource_set_implementation(context->resource,
Murray Calavera972d1af2015-06-09 20:29:28 +0000801 &context_implementation,
Jason Ekstranda85118c2013-06-27 20:17:02 -0500802 context, destroy_input_method_context);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200803
Derek Foreman0f299232015-05-08 17:08:41 -0500804 context->input = input;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100805 context->input_method = input_method;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200806 input_method->context = context;
807
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200808
Jonas Ådahlb57f4722015-11-17 16:00:30 +0800809 zwp_input_method_v1_send_activate(binding, context->resource);
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200810}
811
812static void
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100813input_method_context_end_keyboard_grab(struct input_method_context *context)
814{
Derek Foremanf0aaa412014-12-08 10:48:29 -0600815 struct weston_keyboard_grab *grab;
816 struct weston_keyboard *keyboard;
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100817
Derek Foreman1281a362015-07-31 16:55:32 -0500818 keyboard = weston_seat_get_keyboard(context->input_method->seat);
819 if (!keyboard)
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100820 return;
821
Derek Foreman1281a362015-07-31 16:55:32 -0500822 grab = &keyboard->input_method_grab;
Derek Foremanf0aaa412014-12-08 10:48:29 -0600823 keyboard = grab->keyboard;
824 if (!keyboard)
825 return;
826
827 if (keyboard->grab == grab)
828 weston_keyboard_end_grab(keyboard);
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100829
Jan Arne Petersena75a7892013-01-16 21:26:50 +0100830 keyboard->input_method_resource = NULL;
831}
Jan Arne Petersen466b9c12012-11-18 19:06:45 +0100832
833static void
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200834unbind_input_method(struct wl_resource *resource)
835{
Jason Ekstrand89d31992013-06-14 10:07:59 -0500836 struct input_method *input_method = wl_resource_get_user_data(resource);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200837
838 input_method->input_method_binding = NULL;
Jan Arne Petersen620cd622012-09-09 23:08:32 +0200839 input_method->context = NULL;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200840}
841
842static void
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200843bind_input_method(struct wl_client *client,
844 void *data,
845 uint32_t version,
846 uint32_t id)
847{
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200848 struct input_method *input_method = data;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100849 struct text_backend *text_backend = input_method->text_backend;
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200850 struct wl_resource *resource;
851
Jason Ekstranda85118c2013-06-27 20:17:02 -0500852 resource =
Jonas Ådahlb57f4722015-11-17 16:00:30 +0800853 wl_resource_create(client,
854 &zwp_input_method_v1_interface, 1, id);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200855
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200856 if (input_method->input_method_binding != NULL) {
Murray Calavera972d1af2015-06-09 20:29:28 +0000857 wl_resource_post_error(resource,
858 WL_DISPLAY_ERROR_INVALID_OBJECT,
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200859 "interface object already bound");
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +0200860 return;
861 }
862
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200863 if (text_backend->input_method.client != client) {
Murray Calavera972d1af2015-06-09 20:29:28 +0000864 wl_resource_post_error(resource,
865 WL_DISPLAY_ERROR_INVALID_OBJECT,
866 "permission to bind "
867 "input_method denied");
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200868 return;
869 }
870
Jason Ekstranda85118c2013-06-27 20:17:02 -0500871 wl_resource_set_implementation(resource, NULL, input_method,
872 unbind_input_method);
Jan Arne Petersenb41531a2013-04-18 16:47:31 +0200873 input_method->input_method_binding = resource;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200874}
875
876static void
877input_method_notifier_destroy(struct wl_listener *listener, void *data)
878{
Kristian Høgsbergf97f3792012-07-22 11:51:42 -0400879 struct input_method *input_method =
880 container_of(listener, struct input_method, destroy_listener);
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200881
Derek Foreman0f299232015-05-08 17:08:41 -0500882 if (input_method->input)
Derek Foreman516d6032015-05-08 17:08:40 -0500883 deactivate_input_method(input_method);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200884
Kristian Høgsberg919cddb2013-07-08 19:03:57 -0400885 wl_global_destroy(input_method->input_method_global);
Rob Bradfordead3ef82013-07-24 16:57:32 +0100886 wl_list_remove(&input_method->destroy_listener.link);
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200887
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200888 free(input_method);
889}
890
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200891static void
892handle_keyboard_focus(struct wl_listener *listener, void *data)
893{
Kristian Høgsberg29139d42013-04-18 15:25:39 -0400894 struct weston_keyboard *keyboard = data;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200895 struct input_method *input_method =
Murray Calavera972d1af2015-06-09 20:29:28 +0000896 container_of(listener, struct input_method,
897 keyboard_focus_listener);
Kristian Høgsbergfe7aa902013-05-08 09:54:37 -0400898 struct weston_surface *surface = keyboard->focus;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200899
Derek Foreman0f299232015-05-08 17:08:41 -0500900 if (!input_method->input)
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200901 return;
902
Derek Foreman0f299232015-05-08 17:08:41 -0500903 if (!surface || input_method->input->surface != surface)
Derek Foreman516d6032015-05-08 17:08:40 -0500904 deactivate_input_method(input_method);
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200905}
906
907static void
908input_method_init_seat(struct weston_seat *seat)
909{
Derek Foreman1281a362015-07-31 16:55:32 -0500910 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
911
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200912 if (seat->input_method->focus_listener_initialized)
913 return;
914
Derek Foreman1281a362015-07-31 16:55:32 -0500915 if (keyboard) {
Murray Calavera972d1af2015-06-09 20:29:28 +0000916 seat->input_method->keyboard_focus_listener.notify =
917 handle_keyboard_focus;
Derek Foreman1281a362015-07-31 16:55:32 -0500918 wl_signal_add(&keyboard->focus_signal,
Murray Calavera972d1af2015-06-09 20:29:28 +0000919 &seat->input_method->keyboard_focus_listener);
Derek Foreman1281a362015-07-31 16:55:32 -0500920 keyboard->input_method_grab.interface =
Murray Calavera972d1af2015-06-09 20:29:28 +0000921 &input_method_context_grab;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200922 }
923
Derek Foremanddc2c972015-07-15 13:00:32 -0500924 seat->input_method->focus_listener_initialized = true;
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +0200925}
926
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300927static void launch_input_method(struct text_backend *text_backend);
928
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100929static void
Derek Foreman89dcea92015-06-25 15:49:49 -0500930respawn_input_method_process(struct text_backend *text_backend)
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200931{
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300932 uint32_t time;
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) {
Derek Foreman89dcea92015-06-25 15:49:49 -0500943 weston_log("input_method disconnected, giving up.\n");
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300944 return;
945 }
946
Derek Foreman89dcea92015-06-25 15:49:49 -0500947 weston_log("input_method disconnected, respawning...\n");
Eduardo Lima (Etrunko)27337002013-05-14 13:09:31 -0300948 launch_input_method(text_backend);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100949}
950
951static void
Derek Foreman89dcea92015-06-25 15:49:49 -0500952input_method_client_notifier(struct wl_listener *listener, void *data)
953{
954 struct text_backend *text_backend;
955
956 text_backend = container_of(listener, struct text_backend,
957 client_listener);
958
959 text_backend->input_method.client = NULL;
960 respawn_input_method_process(text_backend);
961}
962
963static void
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100964launch_input_method(struct text_backend *text_backend)
965{
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100966 if (!text_backend->input_method.path)
967 return;
968
Murray Calaveraf65f89b2015-06-09 20:28:06 +0000969 if (strcmp(text_backend->input_method.path, "") == 0)
970 return;
971
Murray Calavera972d1af2015-06-09 20:29:28 +0000972 text_backend->input_method.client =
Derek Foreman89dcea92015-06-25 15:49:49 -0500973 weston_client_start(text_backend->compositor,
974 text_backend->input_method.path);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100975
Derek Foreman89dcea92015-06-25 15:49:49 -0500976 if (!text_backend->input_method.client) {
Murray Calavera972d1af2015-06-09 20:29:28 +0000977 weston_log("not able to start %s\n",
978 text_backend->input_method.path);
Derek Foreman89dcea92015-06-25 15:49:49 -0500979 return;
980 }
981
982 text_backend->client_listener.notify = input_method_client_notifier;
983 wl_client_add_destroy_listener(text_backend->input_method.client,
984 &text_backend->client_listener);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100985}
986
987static void
Murray Calavera25881242015-06-10 21:15:30 +0000988text_backend_seat_created(struct text_backend *text_backend,
989 struct weston_seat *seat)
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100990{
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200991 struct input_method *input_method;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +0100992 struct weston_compositor *ec = seat->compositor;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200993
Bryce Harringtonde16d892014-11-20 22:21:57 -0800994 input_method = zalloc(sizeof *input_method);
995 if (input_method == NULL)
996 return;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +0200997
Philipp Brüschweilerb13b9ff2012-09-09 23:08:31 +0200998 input_method->seat = seat;
Derek Foreman0f299232015-05-08 17:08:41 -0500999 input_method->input = NULL;
Derek Foremanddc2c972015-07-15 13:00:32 -05001000 input_method->focus_listener_initialized = false;
Jan Arne Petersen620cd622012-09-09 23:08:32 +02001001 input_method->context = NULL;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001002 input_method->text_backend = text_backend;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +02001003
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +02001004 input_method->input_method_global =
Jonas Ådahlb57f4722015-11-17 16:00:30 +08001005 wl_global_create(ec->wl_display,
1006 &zwp_input_method_v1_interface, 1,
Kristian Høgsberg919cddb2013-07-08 19:03:57 -04001007 input_method, bind_input_method);
Philipp Brüschweilerf25602b2012-07-11 22:25:31 +02001008
Jan Arne Petersen1f17be42012-06-21 21:52:18 +02001009 input_method->destroy_listener.notify = input_method_notifier_destroy;
Kristian Høgsberg49124542013-05-06 22:27:40 -04001010 wl_signal_add(&seat->destroy_signal, &input_method->destroy_listener);
Jan Arne Petersene829adc2012-08-10 16:47:22 +02001011
1012 seat->input_method = input_method;
Jan Arne Petersen1f17be42012-06-21 21:52:18 +02001013}
Jan Arne Petersencd8cdcc2012-08-10 16:47:23 +02001014
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001015static void
Murray Calavera25881242015-06-10 21:15:30 +00001016handle_seat_created(struct wl_listener *listener, void *data)
1017{
1018 struct weston_seat *seat = data;
1019 struct text_backend *text_backend =
1020 container_of(listener, struct text_backend,
1021 seat_created_listener);
1022
1023 text_backend_seat_created(text_backend, seat);
1024}
1025
1026static void
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001027text_backend_configuration(struct text_backend *text_backend)
1028{
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -04001029 struct weston_config_section *section;
Derek Foremanc7210432014-08-21 11:32:38 -05001030 char *client;
Pekka Paalanen974c0942014-09-05 14:45:09 +03001031 int ret;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001032
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -04001033 section = weston_config_get_section(text_backend->compositor->config,
1034 "input-method", NULL, NULL);
Pekka Paalanen974c0942014-09-05 14:45:09 +03001035 ret = asprintf(&client, "%s/weston-keyboard",
1036 weston_config_get_libexec_dir());
1037 if (ret < 0)
1038 client = NULL;
Kristian Høgsberg00fd7b82013-05-23 21:45:51 -04001039 weston_config_section_get_string(section, "path",
1040 &text_backend->input_method.path,
Derek Foremanc7210432014-08-21 11:32:38 -05001041 client);
1042 free(client);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001043}
1044
Pekka Paalanenaa9536a2015-06-24 16:09:17 +03001045WL_EXPORT void
1046text_backend_destroy(struct text_backend *text_backend)
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001047{
Derek Foreman89dcea92015-06-25 15:49:49 -05001048 if (text_backend->input_method.client) {
1049 /* disable respawn */
1050 wl_list_remove(&text_backend->client_listener.link);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001051 wl_client_destroy(text_backend->input_method.client);
Derek Foreman89dcea92015-06-25 15:49:49 -05001052 }
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001053
1054 free(text_backend->input_method.path);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001055 free(text_backend);
1056}
1057
Pekka Paalanenaa9536a2015-06-24 16:09:17 +03001058WL_EXPORT struct text_backend *
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001059text_backend_init(struct weston_compositor *ec)
1060{
1061 struct text_backend *text_backend;
Murray Calavera25881242015-06-10 21:15:30 +00001062 struct weston_seat *seat;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001063
Bryce Harringtonde16d892014-11-20 22:21:57 -08001064 text_backend = zalloc(sizeof(*text_backend));
1065 if (text_backend == NULL)
Pekka Paalanenaa9536a2015-06-24 16:09:17 +03001066 return NULL;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001067
1068 text_backend->compositor = ec;
1069
Murray Calavera25881242015-06-10 21:15:30 +00001070 text_backend_configuration(text_backend);
1071
1072 wl_list_for_each(seat, &ec->seat_list, link)
1073 text_backend_seat_created(text_backend, seat);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001074 text_backend->seat_created_listener.notify = handle_seat_created;
1075 wl_signal_add(&ec->seat_created_signal,
1076 &text_backend->seat_created_listener);
1077
Jan Arne Petersen78d00e42013-04-18 16:47:24 +02001078 text_input_manager_create(ec);
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001079
Derek Foremanb4bacd22015-06-25 15:49:47 -05001080 launch_input_method(text_backend);
1081
Pekka Paalanenaa9536a2015-06-24 16:09:17 +03001082 return text_backend;
Jan Arne Petersen674fd1d2012-11-18 19:06:42 +01001083}