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