1 /*
2  * Copyright © 2012 Openismus GmbH
3  * Copyright © 2012 Intel Corporation
4  *
5  * 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:
12  *
13  * 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.
25  */
26 
27 #include "config.h"
28 
29 #include <stdbool.h>
30 #include <stdlib.h>
31 #include <stdint.h>
32 #include <string.h>
33 #include <unistd.h>
34 #include <time.h>
35 
36 #include <libweston/libweston.h>
37 #include "weston.h"
38 #include "text-input-unstable-v1-server-protocol.h"
39 #include "input-method-unstable-v1-server-protocol.h"
40 #include "shared/helpers.h"
41 #include "shared/timespec-util.h"
42 
43 struct text_input_manager;
44 struct input_method;
45 struct input_method_context;
46 struct text_backend;
47 
48 struct text_input {
49 	struct wl_resource *resource;
50 
51 	struct weston_compositor *ec;
52 
53 	struct wl_list input_methods;
54 
55 	struct weston_surface *surface;
56 
57 	pixman_box32_t cursor_rectangle;
58 
59 	bool input_panel_visible;
60 
61 	struct text_input_manager *manager;
62 };
63 
64 struct text_input_manager {
65 	struct wl_global *text_input_manager_global;
66 	struct wl_listener destroy_listener;
67 
68 	struct text_input *current_text_input;
69 
70 	struct weston_compositor *ec;
71 };
72 
73 struct input_method {
74 	struct wl_resource *input_method_binding;
75 	struct wl_global *input_method_global;
76 	struct wl_listener destroy_listener;
77 
78 	struct weston_seat *seat;
79 	struct text_input *input;
80 
81 	struct wl_list link;
82 
83 	struct wl_listener keyboard_focus_listener;
84 
85 	bool focus_listener_initialized;
86 
87 	struct input_method_context *context;
88 
89 	struct text_backend *text_backend;
90 };
91 
92 struct input_method_context {
93 	struct wl_resource *resource;
94 
95 	struct text_input *input;
96 	struct input_method *input_method;
97 
98 	struct wl_resource *keyboard;
99 };
100 
101 struct text_backend {
102 	struct weston_compositor *compositor;
103 
104 	struct {
105 		char *path;
106 		struct wl_client *client;
107 
108 		unsigned deathcount;
109 		struct timespec deathstamp;
110 	} input_method;
111 
112 	struct wl_listener client_listener;
113 	struct wl_listener seat_created_listener;
114 };
115 
116 static void
117 input_method_context_create(struct text_input *input,
118 			    struct input_method *input_method);
119 static void
120 input_method_context_end_keyboard_grab(struct input_method_context *context);
121 
122 static void
123 input_method_init_seat(struct weston_seat *seat);
124 
125 static void
deactivate_input_method(struct input_method * input_method)126 deactivate_input_method(struct input_method *input_method)
127 {
128 	struct text_input *text_input = input_method->input;
129 	struct weston_compositor *ec = text_input->ec;
130 
131 	if (input_method->context && input_method->input_method_binding) {
132 		input_method_context_end_keyboard_grab(input_method->context);
133 		zwp_input_method_v1_send_deactivate(
134 			input_method->input_method_binding,
135 			input_method->context->resource);
136 		input_method->context->input = NULL;
137 	}
138 
139 	wl_list_remove(&input_method->link);
140 	input_method->input = NULL;
141 	input_method->context = NULL;
142 
143 	if (wl_list_empty(&text_input->input_methods) &&
144 	    text_input->input_panel_visible &&
145 	    text_input->manager->current_text_input == text_input) {
146 		wl_signal_emit(&ec->hide_input_panel_signal, ec);
147 		text_input->input_panel_visible = false;
148 	}
149 
150 	if (text_input->manager->current_text_input == text_input)
151 		text_input->manager->current_text_input = NULL;
152 
153 	zwp_text_input_v1_send_leave(text_input->resource);
154 }
155 
156 static void
destroy_text_input(struct wl_resource * resource)157 destroy_text_input(struct wl_resource *resource)
158 {
159 	struct text_input *text_input = wl_resource_get_user_data(resource);
160 	struct input_method *input_method, *next;
161 
162 	wl_list_for_each_safe(input_method, next,
163 			      &text_input->input_methods, link)
164 		deactivate_input_method(input_method);
165 
166 	free(text_input);
167 }
168 
169 static void
text_input_set_surrounding_text(struct wl_client * client,struct wl_resource * resource,const char * text,uint32_t cursor,uint32_t anchor)170 text_input_set_surrounding_text(struct wl_client *client,
171 				struct wl_resource *resource,
172 				const char *text,
173 				uint32_t cursor,
174 				uint32_t anchor)
175 {
176 	struct text_input *text_input = wl_resource_get_user_data(resource);
177 	struct input_method *input_method, *next;
178 
179 	wl_list_for_each_safe(input_method, next,
180 			      &text_input->input_methods, link) {
181 		if (!input_method->context)
182 			continue;
183 		zwp_input_method_context_v1_send_surrounding_text(
184 			input_method->context->resource, text, cursor, anchor);
185 	}
186 }
187 
188 static void
text_input_activate(struct wl_client * client,struct wl_resource * resource,struct wl_resource * seat,struct wl_resource * surface)189 text_input_activate(struct wl_client *client,
190 		    struct wl_resource *resource,
191 		    struct wl_resource *seat,
192 		    struct wl_resource *surface)
193 {
194 	struct text_input *text_input = wl_resource_get_user_data(resource);
195 	struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
196 	struct input_method *input_method;
197 	struct weston_compositor *ec = text_input->ec;
198 	struct text_input *current;
199 
200 	if (!weston_seat)
201 		return;
202 
203 	input_method = weston_seat->input_method;
204 	if (input_method->input == text_input)
205 		return;
206 
207 	if (input_method->input)
208 		deactivate_input_method(input_method);
209 
210 	input_method->input = text_input;
211 	wl_list_insert(&text_input->input_methods, &input_method->link);
212 	input_method_init_seat(weston_seat);
213 
214 	text_input->surface = wl_resource_get_user_data(surface);
215 
216 	input_method_context_create(text_input, input_method);
217 
218 	current = text_input->manager->current_text_input;
219 
220 	if (current && current != text_input) {
221 		current->input_panel_visible = false;
222 		wl_signal_emit(&ec->hide_input_panel_signal, ec);
223 	}
224 
225 	if (text_input->input_panel_visible) {
226 		wl_signal_emit(&ec->show_input_panel_signal,
227 			       text_input->surface);
228 		wl_signal_emit(&ec->update_input_panel_signal,
229 			       &text_input->cursor_rectangle);
230 	}
231 	text_input->manager->current_text_input = text_input;
232 
233 	zwp_text_input_v1_send_enter(text_input->resource,
234 				     text_input->surface->resource);
235 }
236 
237 static void
text_input_deactivate(struct wl_client * client,struct wl_resource * resource,struct wl_resource * seat)238 text_input_deactivate(struct wl_client *client,
239 		      struct wl_resource *resource,
240 		      struct wl_resource *seat)
241 {
242 	struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
243 
244 	if (weston_seat && weston_seat->input_method->input)
245 		deactivate_input_method(weston_seat->input_method);
246 }
247 
248 static void
text_input_reset(struct wl_client * client,struct wl_resource * resource)249 text_input_reset(struct wl_client *client,
250 		 struct wl_resource *resource)
251 {
252 	struct text_input *text_input = wl_resource_get_user_data(resource);
253 	struct input_method *input_method, *next;
254 
255 	wl_list_for_each_safe(input_method, next,
256 			      &text_input->input_methods, link) {
257 		if (!input_method->context)
258 			continue;
259 		zwp_input_method_context_v1_send_reset(
260 			input_method->context->resource);
261 	}
262 }
263 
264 static void
text_input_set_cursor_rectangle(struct wl_client * client,struct wl_resource * resource,int32_t x,int32_t y,int32_t width,int32_t height)265 text_input_set_cursor_rectangle(struct wl_client *client,
266 				struct wl_resource *resource,
267 				int32_t x,
268 				int32_t y,
269 				int32_t width,
270 				int32_t height)
271 {
272 	struct text_input *text_input = wl_resource_get_user_data(resource);
273 	struct weston_compositor *ec = text_input->ec;
274 
275 	text_input->cursor_rectangle.x1 = x;
276 	text_input->cursor_rectangle.y1 = y;
277 	text_input->cursor_rectangle.x2 = x + width;
278 	text_input->cursor_rectangle.y2 = y + height;
279 
280 	wl_signal_emit(&ec->update_input_panel_signal,
281 		       &text_input->cursor_rectangle);
282 }
283 
284 static void
text_input_set_content_type(struct wl_client * client,struct wl_resource * resource,uint32_t hint,uint32_t purpose)285 text_input_set_content_type(struct wl_client *client,
286 			    struct wl_resource *resource,
287 			    uint32_t hint,
288 			    uint32_t purpose)
289 {
290 	struct text_input *text_input = wl_resource_get_user_data(resource);
291 	struct input_method *input_method, *next;
292 
293 	wl_list_for_each_safe(input_method, next,
294 			      &text_input->input_methods, link) {
295 		if (!input_method->context)
296 			continue;
297 		zwp_input_method_context_v1_send_content_type(
298 			input_method->context->resource, hint, purpose);
299 	}
300 }
301 
302 static void
text_input_invoke_action(struct wl_client * client,struct wl_resource * resource,uint32_t button,uint32_t index)303 text_input_invoke_action(struct wl_client *client,
304 			 struct wl_resource *resource,
305 			 uint32_t button,
306 			 uint32_t index)
307 {
308 	struct text_input *text_input = wl_resource_get_user_data(resource);
309 	struct input_method *input_method, *next;
310 
311 	wl_list_for_each_safe(input_method, next,
312 			      &text_input->input_methods, link) {
313 		if (!input_method->context)
314 			continue;
315 		zwp_input_method_context_v1_send_invoke_action(
316 			input_method->context->resource, button, index);
317 	}
318 }
319 
320 static void
text_input_commit_state(struct wl_client * client,struct wl_resource * resource,uint32_t serial)321 text_input_commit_state(struct wl_client *client,
322 			struct wl_resource *resource,
323 			uint32_t serial)
324 {
325 	struct text_input *text_input = wl_resource_get_user_data(resource);
326 	struct input_method *input_method, *next;
327 
328 	wl_list_for_each_safe(input_method, next,
329 			      &text_input->input_methods, link) {
330 		if (!input_method->context)
331 			continue;
332 		zwp_input_method_context_v1_send_commit_state(
333 			input_method->context->resource, serial);
334 	}
335 }
336 
337 static void
text_input_show_input_panel(struct wl_client * client,struct wl_resource * resource)338 text_input_show_input_panel(struct wl_client *client,
339 			    struct wl_resource *resource)
340 {
341 	struct text_input *text_input = wl_resource_get_user_data(resource);
342 	struct weston_compositor *ec = text_input->ec;
343 
344 	text_input->input_panel_visible = true;
345 
346 	if (!wl_list_empty(&text_input->input_methods) &&
347 	    text_input == text_input->manager->current_text_input) {
348 		wl_signal_emit(&ec->show_input_panel_signal,
349 			       text_input->surface);
350 		wl_signal_emit(&ec->update_input_panel_signal,
351 			       &text_input->cursor_rectangle);
352 	}
353 }
354 
355 static void
text_input_hide_input_panel(struct wl_client * client,struct wl_resource * resource)356 text_input_hide_input_panel(struct wl_client *client,
357 			    struct wl_resource *resource)
358 {
359 	struct text_input *text_input = wl_resource_get_user_data(resource);
360 	struct weston_compositor *ec = text_input->ec;
361 
362 	text_input->input_panel_visible = false;
363 
364 	if (!wl_list_empty(&text_input->input_methods) &&
365 	    text_input == text_input->manager->current_text_input)
366 		wl_signal_emit(&ec->hide_input_panel_signal, ec);
367 }
368 
369 static void
text_input_set_preferred_language(struct wl_client * client,struct wl_resource * resource,const char * language)370 text_input_set_preferred_language(struct wl_client *client,
371 				  struct wl_resource *resource,
372 				  const char *language)
373 {
374 	struct text_input *text_input = wl_resource_get_user_data(resource);
375 	struct input_method *input_method, *next;
376 
377 	wl_list_for_each_safe(input_method, next,
378 			      &text_input->input_methods, link) {
379 		if (!input_method->context)
380 			continue;
381 		zwp_input_method_context_v1_send_preferred_language(
382 			input_method->context->resource, language);
383 	}
384 }
385 
386 static const struct zwp_text_input_v1_interface text_input_implementation = {
387 	text_input_activate,
388 	text_input_deactivate,
389 	text_input_show_input_panel,
390 	text_input_hide_input_panel,
391 	text_input_reset,
392 	text_input_set_surrounding_text,
393 	text_input_set_content_type,
394 	text_input_set_cursor_rectangle,
395 	text_input_set_preferred_language,
396 	text_input_commit_state,
397 	text_input_invoke_action
398 };
399 
text_input_manager_create_text_input(struct wl_client * client,struct wl_resource * resource,uint32_t id)400 static void text_input_manager_create_text_input(struct wl_client *client,
401 						 struct wl_resource *resource,
402 						 uint32_t id)
403 {
404 	struct text_input_manager *text_input_manager =
405 		wl_resource_get_user_data(resource);
406 	struct text_input *text_input;
407 
408 	text_input = zalloc(sizeof *text_input);
409 	if (text_input == NULL)
410 		return;
411 
412 	text_input->resource =
413 		wl_resource_create(client, &zwp_text_input_v1_interface, 1, id);
414 	wl_resource_set_implementation(text_input->resource,
415 				       &text_input_implementation,
416 				       text_input, destroy_text_input);
417 
418 	text_input->ec = text_input_manager->ec;
419 	text_input->manager = text_input_manager;
420 
421 	wl_list_init(&text_input->input_methods);
422 };
423 
424 static const struct zwp_text_input_manager_v1_interface manager_implementation = {
425 	text_input_manager_create_text_input
426 };
427 
428 static void
bind_text_input_manager(struct wl_client * client,void * data,uint32_t version,uint32_t id)429 bind_text_input_manager(struct wl_client *client,
430 			void *data,
431 			uint32_t version,
432 			uint32_t id)
433 {
434 	struct text_input_manager *text_input_manager = data;
435 	struct wl_resource *resource;
436 
437 	/* No checking for duplicate binding necessary.  */
438 	resource =
439 		wl_resource_create(client,
440 				   &zwp_text_input_manager_v1_interface, 1, id);
441 	if (resource)
442 		wl_resource_set_implementation(resource,
443 					       &manager_implementation,
444 					       text_input_manager, NULL);
445 }
446 
447 static void
text_input_manager_notifier_destroy(struct wl_listener * listener,void * data)448 text_input_manager_notifier_destroy(struct wl_listener *listener, void *data)
449 {
450 	struct text_input_manager *text_input_manager =
451 		container_of(listener,
452 			     struct text_input_manager,
453 			     destroy_listener);
454 
455 	wl_list_remove(&text_input_manager->destroy_listener.link);
456 	wl_global_destroy(text_input_manager->text_input_manager_global);
457 
458 	free(text_input_manager);
459 }
460 
461 static void
text_input_manager_create(struct weston_compositor * ec)462 text_input_manager_create(struct weston_compositor *ec)
463 {
464 	struct text_input_manager *text_input_manager;
465 
466 	text_input_manager = zalloc(sizeof *text_input_manager);
467 	if (text_input_manager == NULL)
468 		return;
469 
470 	text_input_manager->ec = ec;
471 
472 	text_input_manager->text_input_manager_global =
473 		wl_global_create(ec->wl_display,
474 				 &zwp_text_input_manager_v1_interface, 1,
475 				 text_input_manager, bind_text_input_manager);
476 
477 	text_input_manager->destroy_listener.notify =
478 		text_input_manager_notifier_destroy;
479 	wl_signal_add(&ec->destroy_signal,
480 		      &text_input_manager->destroy_listener);
481 }
482 
483 static void
input_method_context_destroy(struct wl_client * client,struct wl_resource * resource)484 input_method_context_destroy(struct wl_client *client,
485 			     struct wl_resource *resource)
486 {
487 	wl_resource_destroy(resource);
488 }
489 
490 static void
input_method_context_commit_string(struct wl_client * client,struct wl_resource * resource,uint32_t serial,const char * text)491 input_method_context_commit_string(struct wl_client *client,
492 				   struct wl_resource *resource,
493 				   uint32_t serial,
494 				   const char *text)
495 {
496 	struct input_method_context *context =
497 		wl_resource_get_user_data(resource);
498 
499 	if (context->input)
500 		zwp_text_input_v1_send_commit_string(context->input->resource,
501 						     serial, text);
502 }
503 
504 static void
input_method_context_preedit_string(struct wl_client * client,struct wl_resource * resource,uint32_t serial,const char * text,const char * commit)505 input_method_context_preedit_string(struct wl_client *client,
506 				    struct wl_resource *resource,
507 				    uint32_t serial,
508 				    const char *text,
509 				    const char *commit)
510 {
511 	struct input_method_context *context =
512 		wl_resource_get_user_data(resource);
513 
514 	if (context->input)
515 		zwp_text_input_v1_send_preedit_string(context->input->resource,
516 						      serial, text, commit);
517 }
518 
519 static void
input_method_context_preedit_styling(struct wl_client * client,struct wl_resource * resource,uint32_t index,uint32_t length,uint32_t style)520 input_method_context_preedit_styling(struct wl_client *client,
521 				     struct wl_resource *resource,
522 				     uint32_t index,
523 				     uint32_t length,
524 				     uint32_t style)
525 {
526 	struct input_method_context *context =
527 		wl_resource_get_user_data(resource);
528 
529 	if (context->input)
530 		zwp_text_input_v1_send_preedit_styling(context->input->resource,
531 						       index, length, style);
532 }
533 
534 static void
input_method_context_preedit_cursor(struct wl_client * client,struct wl_resource * resource,int32_t cursor)535 input_method_context_preedit_cursor(struct wl_client *client,
536 				    struct wl_resource *resource,
537 				    int32_t cursor)
538 {
539 	struct input_method_context *context =
540 		wl_resource_get_user_data(resource);
541 
542 	if (context->input)
543 		zwp_text_input_v1_send_preedit_cursor(context->input->resource,
544 						      cursor);
545 }
546 
547 static void
input_method_context_delete_surrounding_text(struct wl_client * client,struct wl_resource * resource,int32_t index,uint32_t length)548 input_method_context_delete_surrounding_text(struct wl_client *client,
549 					     struct wl_resource *resource,
550 					     int32_t index,
551 					     uint32_t length)
552 {
553 	struct input_method_context *context =
554 		wl_resource_get_user_data(resource);
555 
556 	if (context->input)
557 		zwp_text_input_v1_send_delete_surrounding_text(
558 			context->input->resource, index, length);
559 }
560 
561 static void
input_method_context_cursor_position(struct wl_client * client,struct wl_resource * resource,int32_t index,int32_t anchor)562 input_method_context_cursor_position(struct wl_client *client,
563 				     struct wl_resource *resource,
564 				     int32_t index,
565 				     int32_t anchor)
566 {
567 	struct input_method_context *context =
568 		wl_resource_get_user_data(resource);
569 
570 	if (context->input)
571 		zwp_text_input_v1_send_cursor_position(context->input->resource,
572 						       index, anchor);
573 }
574 
575 static void
input_method_context_modifiers_map(struct wl_client * client,struct wl_resource * resource,struct wl_array * map)576 input_method_context_modifiers_map(struct wl_client *client,
577 				   struct wl_resource *resource,
578 				   struct wl_array *map)
579 {
580 	struct input_method_context *context =
581 		wl_resource_get_user_data(resource);
582 
583 	if (context->input)
584 		zwp_text_input_v1_send_modifiers_map(context->input->resource,
585 						     map);
586 }
587 
588 static void
input_method_context_keysym(struct wl_client * client,struct wl_resource * resource,uint32_t serial,uint32_t time,uint32_t sym,uint32_t state,uint32_t modifiers)589 input_method_context_keysym(struct wl_client *client,
590 			    struct wl_resource *resource,
591 			    uint32_t serial,
592 			    uint32_t time,
593 			    uint32_t sym,
594 			    uint32_t state,
595 			    uint32_t modifiers)
596 {
597 	struct input_method_context *context =
598 		wl_resource_get_user_data(resource);
599 
600 	if (context->input)
601 		zwp_text_input_v1_send_keysym(context->input->resource,
602 					      serial, time,
603 					      sym, state, modifiers);
604 }
605 
606 static void
unbind_keyboard(struct wl_resource * resource)607 unbind_keyboard(struct wl_resource *resource)
608 {
609 	struct input_method_context *context =
610 		wl_resource_get_user_data(resource);
611 
612 	input_method_context_end_keyboard_grab(context);
613 	context->keyboard = NULL;
614 }
615 
616 static void
input_method_context_grab_key(struct weston_keyboard_grab * grab,const struct timespec * time,uint32_t key,uint32_t state_w)617 input_method_context_grab_key(struct weston_keyboard_grab *grab,
618 			      const struct timespec *time, uint32_t key,
619 			      uint32_t state_w)
620 {
621 	struct weston_keyboard *keyboard = grab->keyboard;
622 	struct wl_display *display;
623 	uint32_t serial;
624 	uint32_t msecs;
625 
626 	if (!keyboard->input_method_resource)
627 		return;
628 
629 	display = wl_client_get_display(
630 		wl_resource_get_client(keyboard->input_method_resource));
631 	serial = wl_display_next_serial(display);
632 	msecs = timespec_to_msec(time);
633 	wl_keyboard_send_key(keyboard->input_method_resource,
634 			     serial, msecs, key, state_w);
635 }
636 
637 static void
input_method_context_grab_modifier(struct weston_keyboard_grab * grab,uint32_t serial,uint32_t mods_depressed,uint32_t mods_latched,uint32_t mods_locked,uint32_t group)638 input_method_context_grab_modifier(struct weston_keyboard_grab *grab,
639 				   uint32_t serial,
640 				   uint32_t mods_depressed,
641 				   uint32_t mods_latched,
642 				   uint32_t mods_locked,
643 				   uint32_t group)
644 {
645 	struct weston_keyboard *keyboard = grab->keyboard;
646 
647 	if (!keyboard->input_method_resource)
648 		return;
649 
650 	wl_keyboard_send_modifiers(keyboard->input_method_resource,
651 				   serial, mods_depressed, mods_latched,
652 				   mods_locked, group);
653 }
654 
655 static void
input_method_context_grab_cancel(struct weston_keyboard_grab * grab)656 input_method_context_grab_cancel(struct weston_keyboard_grab *grab)
657 {
658 	weston_keyboard_end_grab(grab->keyboard);
659 }
660 
661 static const struct weston_keyboard_grab_interface input_method_context_grab = {
662 	input_method_context_grab_key,
663 	input_method_context_grab_modifier,
664 	input_method_context_grab_cancel,
665 };
666 
667 static void
input_method_context_grab_keyboard(struct wl_client * client,struct wl_resource * resource,uint32_t id)668 input_method_context_grab_keyboard(struct wl_client *client,
669 				   struct wl_resource *resource,
670 				   uint32_t id)
671 {
672 	struct input_method_context *context =
673 		wl_resource_get_user_data(resource);
674 	struct wl_resource *cr;
675 	struct weston_seat *seat = context->input_method->seat;
676 	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
677 
678 	cr = wl_resource_create(client, &wl_keyboard_interface, 1, id);
679 	wl_resource_set_implementation(cr, NULL, context, unbind_keyboard);
680 
681 	context->keyboard = cr;
682 
683 	weston_keyboard_send_keymap(keyboard, cr);
684 
685 	if (keyboard->grab != &keyboard->default_grab) {
686 		weston_keyboard_end_grab(keyboard);
687 	}
688 	weston_keyboard_start_grab(keyboard, &keyboard->input_method_grab);
689 	keyboard->input_method_resource = cr;
690 }
691 
692 static void
input_method_context_key(struct wl_client * client,struct wl_resource * resource,uint32_t serial,uint32_t time,uint32_t key,uint32_t state_w)693 input_method_context_key(struct wl_client *client,
694 			 struct wl_resource *resource,
695 			 uint32_t serial,
696 			 uint32_t time,
697 			 uint32_t key,
698 			 uint32_t state_w)
699 {
700 	struct input_method_context *context =
701 		wl_resource_get_user_data(resource);
702 	struct weston_seat *seat = context->input_method->seat;
703 	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
704 	struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
705 	struct timespec ts;
706 
707 	timespec_from_msec(&ts, time);
708 
709 	default_grab->interface->key(default_grab, &ts, key, state_w);
710 }
711 
712 static void
input_method_context_modifiers(struct wl_client * client,struct wl_resource * resource,uint32_t serial,uint32_t mods_depressed,uint32_t mods_latched,uint32_t mods_locked,uint32_t group)713 input_method_context_modifiers(struct wl_client *client,
714 			       struct wl_resource *resource,
715 			       uint32_t serial,
716 			       uint32_t mods_depressed,
717 			       uint32_t mods_latched,
718 			       uint32_t mods_locked,
719 			       uint32_t group)
720 {
721 	struct input_method_context *context =
722 		wl_resource_get_user_data(resource);
723 
724 	struct weston_seat *seat = context->input_method->seat;
725 	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
726 	struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
727 
728 	default_grab->interface->modifiers(default_grab,
729 					   serial, mods_depressed,
730 					   mods_latched, mods_locked,
731 					   group);
732 }
733 
734 static void
input_method_context_language(struct wl_client * client,struct wl_resource * resource,uint32_t serial,const char * language)735 input_method_context_language(struct wl_client *client,
736 			      struct wl_resource *resource,
737 			      uint32_t serial,
738 			      const char *language)
739 {
740 	struct input_method_context *context =
741 		wl_resource_get_user_data(resource);
742 
743 	if (context->input)
744 		zwp_text_input_v1_send_language(context->input->resource,
745 						serial, language);
746 }
747 
748 static void
input_method_context_text_direction(struct wl_client * client,struct wl_resource * resource,uint32_t serial,uint32_t direction)749 input_method_context_text_direction(struct wl_client *client,
750 				    struct wl_resource *resource,
751 				    uint32_t serial,
752 				    uint32_t direction)
753 {
754 	struct input_method_context *context =
755 		wl_resource_get_user_data(resource);
756 
757 	if (context->input)
758 		zwp_text_input_v1_send_text_direction(context->input->resource,
759 						      serial, direction);
760 }
761 
762 
763 static const struct zwp_input_method_context_v1_interface context_implementation = {
764 	input_method_context_destroy,
765 	input_method_context_commit_string,
766 	input_method_context_preedit_string,
767 	input_method_context_preedit_styling,
768 	input_method_context_preedit_cursor,
769 	input_method_context_delete_surrounding_text,
770 	input_method_context_cursor_position,
771 	input_method_context_modifiers_map,
772 	input_method_context_keysym,
773 	input_method_context_grab_keyboard,
774 	input_method_context_key,
775 	input_method_context_modifiers,
776 	input_method_context_language,
777 	input_method_context_text_direction
778 };
779 
780 static void
destroy_input_method_context(struct wl_resource * resource)781 destroy_input_method_context(struct wl_resource *resource)
782 {
783 	struct input_method_context *context =
784 		wl_resource_get_user_data(resource);
785 
786 	if (context->keyboard)
787 		wl_resource_destroy(context->keyboard);
788 
789 	if (context->input_method && context->input_method->context == context)
790 		context->input_method->context = NULL;
791 
792 	free(context);
793 }
794 
795 static void
input_method_context_create(struct text_input * input,struct input_method * input_method)796 input_method_context_create(struct text_input *input,
797 			    struct input_method *input_method)
798 {
799 	struct input_method_context *context;
800 	struct wl_resource *binding;
801 
802 	if (!input_method->input_method_binding)
803 		return;
804 
805 	context = zalloc(sizeof *context);
806 	if (context == NULL)
807 		return;
808 
809 	binding = input_method->input_method_binding;
810 	context->resource =
811 		wl_resource_create(wl_resource_get_client(binding),
812 				   &zwp_input_method_context_v1_interface,
813 				   1, 0);
814 	wl_resource_set_implementation(context->resource,
815 				       &context_implementation,
816 				       context, destroy_input_method_context);
817 
818 	context->input = input;
819 	context->input_method = input_method;
820 	input_method->context = context;
821 
822 
823 	zwp_input_method_v1_send_activate(binding, context->resource);
824 }
825 
826 static void
input_method_context_end_keyboard_grab(struct input_method_context * context)827 input_method_context_end_keyboard_grab(struct input_method_context *context)
828 {
829 	struct weston_keyboard_grab *grab;
830 	struct weston_keyboard *keyboard;
831 
832 	keyboard = weston_seat_get_keyboard(context->input_method->seat);
833 	if (!keyboard)
834 		return;
835 
836 	grab = &keyboard->input_method_grab;
837 	keyboard = grab->keyboard;
838 	if (!keyboard)
839 		return;
840 
841 	if (keyboard->grab == grab)
842 		weston_keyboard_end_grab(keyboard);
843 
844 	keyboard->input_method_resource = NULL;
845 }
846 
847 static void
unbind_input_method(struct wl_resource * resource)848 unbind_input_method(struct wl_resource *resource)
849 {
850 	struct input_method *input_method = wl_resource_get_user_data(resource);
851 
852 	input_method->input_method_binding = NULL;
853 	input_method->context = NULL;
854 }
855 
856 static void
bind_input_method(struct wl_client * client,void * data,uint32_t version,uint32_t id)857 bind_input_method(struct wl_client *client,
858 		  void *data,
859 		  uint32_t version,
860 		  uint32_t id)
861 {
862 	struct input_method *input_method = data;
863 	struct text_backend *text_backend = input_method->text_backend;
864 	struct wl_resource *resource;
865 
866 	resource =
867 		wl_resource_create(client,
868 				   &zwp_input_method_v1_interface, 1, id);
869 
870 	if (input_method->input_method_binding != NULL) {
871 		wl_resource_post_error(resource,
872 				       WL_DISPLAY_ERROR_INVALID_OBJECT,
873 				       "interface object already bound");
874 		return;
875 	}
876 
877 	if (text_backend->input_method.client != client) {
878 		wl_resource_post_error(resource,
879 				       WL_DISPLAY_ERROR_INVALID_OBJECT,
880 				       "permission to bind "
881 				       "input_method denied");
882 		return;
883 	}
884 
885 	wl_resource_set_implementation(resource, NULL, input_method,
886 				       unbind_input_method);
887 	input_method->input_method_binding = resource;
888 }
889 
890 static void
input_method_notifier_destroy(struct wl_listener * listener,void * data)891 input_method_notifier_destroy(struct wl_listener *listener, void *data)
892 {
893 	struct input_method *input_method =
894 		container_of(listener, struct input_method, destroy_listener);
895 
896 	if (input_method->input)
897 		deactivate_input_method(input_method);
898 
899 	wl_global_destroy(input_method->input_method_global);
900 	wl_list_remove(&input_method->destroy_listener.link);
901 
902 	free(input_method);
903 }
904 
905 static void
handle_keyboard_focus(struct wl_listener * listener,void * data)906 handle_keyboard_focus(struct wl_listener *listener, void *data)
907 {
908 	struct weston_keyboard *keyboard = data;
909 	struct input_method *input_method =
910 		container_of(listener, struct input_method,
911 			     keyboard_focus_listener);
912 	struct weston_surface *surface = keyboard->focus;
913 
914 	if (!input_method->input)
915 		return;
916 
917 	if (!surface || input_method->input->surface != surface)
918 		deactivate_input_method(input_method);
919 }
920 
921 static void
input_method_init_seat(struct weston_seat * seat)922 input_method_init_seat(struct weston_seat *seat)
923 {
924 	struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
925 
926 	if (seat->input_method->focus_listener_initialized)
927 		return;
928 
929 	if (keyboard) {
930 		seat->input_method->keyboard_focus_listener.notify =
931 			handle_keyboard_focus;
932 		wl_signal_add(&keyboard->focus_signal,
933 			      &seat->input_method->keyboard_focus_listener);
934 		keyboard->input_method_grab.interface =
935 			&input_method_context_grab;
936 	}
937 
938 	seat->input_method->focus_listener_initialized = true;
939 }
940 
941 static void launch_input_method(struct text_backend *text_backend);
942 
943 static void
respawn_input_method_process(struct text_backend * text_backend)944 respawn_input_method_process(struct text_backend *text_backend)
945 {
946 	struct timespec time;
947 	int64_t tdiff;
948 
949 	/* if input_method dies more than 5 times in 10 seconds, give up */
950 	weston_compositor_get_time(&time);
951 	tdiff = timespec_sub_to_msec(&time,
952 				     &text_backend->input_method.deathstamp);
953 	if (tdiff > 10000) {
954 		text_backend->input_method.deathstamp = time;
955 		text_backend->input_method.deathcount = 0;
956 	}
957 
958 	text_backend->input_method.deathcount++;
959 	if (text_backend->input_method.deathcount > 5) {
960 		weston_log("input_method disconnected, giving up.\n");
961 		return;
962 	}
963 
964 	weston_log("input_method disconnected, respawning...\n");
965 	launch_input_method(text_backend);
966 }
967 
968 static void
input_method_client_notifier(struct wl_listener * listener,void * data)969 input_method_client_notifier(struct wl_listener *listener, void *data)
970 {
971 	struct text_backend *text_backend;
972 
973 	text_backend = container_of(listener, struct text_backend,
974 				    client_listener);
975 
976 	text_backend->input_method.client = NULL;
977 	respawn_input_method_process(text_backend);
978 }
979 
980 static void
launch_input_method(struct text_backend * text_backend)981 launch_input_method(struct text_backend *text_backend)
982 {
983 	if (!text_backend->input_method.path)
984 		return;
985 
986 	if (strcmp(text_backend->input_method.path, "") == 0)
987 		return;
988 
989 	text_backend->input_method.client =
990 		weston_client_start(text_backend->compositor,
991 				    text_backend->input_method.path);
992 
993 	if (!text_backend->input_method.client) {
994 		weston_log("not able to start %s\n",
995 			   text_backend->input_method.path);
996 		return;
997 	}
998 
999 	text_backend->client_listener.notify = input_method_client_notifier;
1000 	wl_client_add_destroy_listener(text_backend->input_method.client,
1001 				       &text_backend->client_listener);
1002 }
1003 
1004 static void
text_backend_seat_created(struct text_backend * text_backend,struct weston_seat * seat)1005 text_backend_seat_created(struct text_backend *text_backend,
1006 			  struct weston_seat *seat)
1007 {
1008 	struct input_method *input_method;
1009 	struct weston_compositor *ec = seat->compositor;
1010 
1011 	input_method = zalloc(sizeof *input_method);
1012 	if (input_method == NULL)
1013 		return;
1014 
1015 	input_method->seat = seat;
1016 	input_method->input = NULL;
1017 	input_method->focus_listener_initialized = false;
1018 	input_method->context = NULL;
1019 	input_method->text_backend = text_backend;
1020 
1021 	input_method->input_method_global =
1022 		wl_global_create(ec->wl_display,
1023 				 &zwp_input_method_v1_interface, 1,
1024 				 input_method, bind_input_method);
1025 
1026 	input_method->destroy_listener.notify = input_method_notifier_destroy;
1027 	wl_signal_add(&seat->destroy_signal, &input_method->destroy_listener);
1028 
1029 	seat->input_method = input_method;
1030 }
1031 
1032 static void
handle_seat_created(struct wl_listener * listener,void * data)1033 handle_seat_created(struct wl_listener *listener, void *data)
1034 {
1035 	struct weston_seat *seat = data;
1036 	struct text_backend *text_backend =
1037 		container_of(listener, struct text_backend,
1038 			     seat_created_listener);
1039 
1040 	text_backend_seat_created(text_backend, seat);
1041 }
1042 
1043 static void
text_backend_configuration(struct text_backend * text_backend)1044 text_backend_configuration(struct text_backend *text_backend)
1045 {
1046 	struct weston_config *config = wet_get_config(text_backend->compositor);
1047 	struct weston_config_section *section;
1048 	char *client;
1049 
1050 	section = weston_config_get_section(config,
1051 					    "input-method", NULL, NULL);
1052 	client = wet_get_libexec_path("weston-keyboard");
1053 	weston_config_section_get_string(section, "path",
1054 					 &text_backend->input_method.path,
1055 					 client);
1056 	free(client);
1057 }
1058 
1059 WL_EXPORT void
text_backend_destroy(struct text_backend * text_backend)1060 text_backend_destroy(struct text_backend *text_backend)
1061 {
1062 	wl_list_remove(&text_backend->seat_created_listener.link);
1063 
1064 	if (text_backend->input_method.client) {
1065 		/* disable respawn */
1066 		wl_list_remove(&text_backend->client_listener.link);
1067 		wl_client_destroy(text_backend->input_method.client);
1068 	}
1069 
1070 	free(text_backend->input_method.path);
1071 	free(text_backend);
1072 }
1073 
1074 WL_EXPORT struct text_backend *
text_backend_init(struct weston_compositor * ec)1075 text_backend_init(struct weston_compositor *ec)
1076 {
1077 	struct text_backend *text_backend;
1078 	struct weston_seat *seat;
1079 
1080 	text_backend = zalloc(sizeof(*text_backend));
1081 	if (text_backend == NULL)
1082 		return NULL;
1083 
1084 	text_backend->compositor = ec;
1085 
1086 	text_backend_configuration(text_backend);
1087 
1088 	wl_list_for_each(seat, &ec->seat_list, link)
1089 		text_backend_seat_created(text_backend, seat);
1090 	text_backend->seat_created_listener.notify = handle_seat_created;
1091 	wl_signal_add(&ec->seat_created_signal,
1092 		      &text_backend->seat_created_listener);
1093 
1094 	text_input_manager_create(ec);
1095 
1096 	launch_input_method(text_backend);
1097 
1098 	return text_backend;
1099 }
1100