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