text: Add language and text-direction to protocol
[profile/ivi/weston-ivi-shell.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 <stdlib.h>
25 #include <string.h>
26
27 #include "compositor.h"
28 #include "text-server-protocol.h"
29 #include "input-method-server-protocol.h"
30
31 struct input_method;
32 struct input_method_context;
33 struct text_backend;
34
35 struct text_model {
36         struct wl_resource resource;
37
38         struct weston_compositor *ec;
39
40         struct wl_list input_methods;
41
42         struct wl_surface *surface;
43
44         uint32_t input_panel_visible;
45 };
46
47 struct text_model_factory {
48         struct wl_global *text_model_factory_global;
49         struct wl_listener destroy_listener;
50
51         struct weston_compositor *ec;
52 };
53
54 struct input_method {
55         struct wl_resource *input_method_binding;
56         struct wl_global *input_method_global;
57         struct wl_listener destroy_listener;
58
59         struct weston_seat *seat;
60         struct text_model *model;
61
62         struct wl_list link;
63
64         struct wl_listener keyboard_focus_listener;
65
66         int focus_listener_initialized;
67
68         struct input_method_context *context;
69
70         struct text_backend *text_backend;
71 };
72
73 struct input_method_context {
74         struct wl_resource resource;
75
76         struct text_model *model;
77         struct input_method *input_method;
78
79         struct wl_list link;
80
81         struct wl_resource *keyboard;
82 };
83
84 struct text_backend {
85         struct weston_compositor *compositor;
86
87         struct {
88                 char *path;
89                 struct wl_resource *binding;
90                 struct weston_process process;
91                 struct wl_client *client;
92         } input_method;
93
94         struct wl_listener seat_created_listener;
95         struct wl_listener destroy_listener;
96 };
97
98 static void input_method_context_create(struct text_model *model,
99                                         struct input_method *input_method,
100                                         uint32_t serial);
101 static void input_method_context_end_keyboard_grab(struct input_method_context *context);
102
103 static void input_method_init_seat(struct weston_seat *seat);
104
105 static void
106 deactivate_text_model(struct text_model *text_model,
107                       struct input_method *input_method)
108 {
109         struct weston_compositor *ec = text_model->ec;
110
111         if (input_method->model == text_model) {
112                 if (input_method->context && input_method->input_method_binding) {
113                         input_method_context_end_keyboard_grab(input_method->context);
114                         input_method_send_deactivate(input_method->input_method_binding,
115                                                      &input_method->context->resource);
116                 }
117
118                 wl_list_remove(&input_method->link);
119                 input_method->model = NULL;
120                 input_method->context = NULL;
121                 wl_signal_emit(&ec->hide_input_panel_signal, ec);
122                 text_model_send_leave(&text_model->resource);
123         }
124 }
125
126 static void
127 destroy_text_model(struct wl_resource *resource)
128 {
129         struct text_model *text_model =
130                 container_of(resource, struct text_model, resource);
131         struct input_method *input_method, *next;
132
133         wl_list_for_each_safe(input_method, next, &text_model->input_methods, link)
134                 deactivate_text_model(text_model, input_method);
135
136         free(text_model);
137 }
138
139 static void
140 text_model_set_surrounding_text(struct wl_client *client,
141                                 struct wl_resource *resource,
142                                 const char *text,
143                                 uint32_t cursor,
144                                 uint32_t anchor)
145 {
146         struct text_model *text_model = resource->data;
147         struct input_method *input_method, *next;
148
149         wl_list_for_each_safe(input_method, next, &text_model->input_methods, link) {
150                 if (!input_method->context)
151                         continue;
152                 input_method_context_send_surrounding_text(&input_method->context->resource,
153                                                            text,
154                                                            cursor,
155                                                            anchor);
156         }
157 }
158
159 static void
160 text_model_activate(struct wl_client *client,
161                     struct wl_resource *resource,
162                     uint32_t serial,
163                     struct wl_resource *seat,
164                     struct wl_resource *surface)
165 {
166         struct text_model *text_model = resource->data;
167         struct weston_seat *weston_seat = seat->data;
168         struct input_method *input_method = weston_seat->input_method;
169         struct text_model *old = weston_seat->input_method->model;
170         struct weston_compositor *ec = text_model->ec;
171
172         if (old == text_model)
173                 return;
174
175         if (old) {
176                 deactivate_text_model(old,
177                                       weston_seat->input_method);
178         }
179
180         input_method->model = text_model;
181         wl_list_insert(&text_model->input_methods, &input_method->link);
182         input_method_init_seat(weston_seat);
183
184         text_model->surface = surface->data;
185
186         input_method_context_create(text_model, input_method, serial);
187
188         if (text_model->input_panel_visible)
189                 wl_signal_emit(&ec->show_input_panel_signal, ec);
190
191         text_model_send_enter(&text_model->resource, &text_model->surface->resource);
192 }
193
194 static void
195 text_model_deactivate(struct wl_client *client,
196                       struct wl_resource *resource,
197                       struct wl_resource *seat)
198 {
199         struct text_model *text_model = resource->data;
200         struct weston_seat *weston_seat = seat->data;
201
202         deactivate_text_model(text_model,
203                               weston_seat->input_method);
204 }
205
206 static void
207 text_model_reset(struct wl_client *client,
208                  struct wl_resource *resource,
209                  uint32_t serial)
210 {
211         struct text_model *text_model = resource->data;
212         struct input_method *input_method, *next;
213
214         wl_list_for_each_safe(input_method, next, &text_model->input_methods, link) {
215                 if (!input_method->context)
216                         continue;
217                 input_method_context_send_reset(&input_method->context->resource, serial);
218         }
219 }
220
221 static void
222 text_model_set_micro_focus(struct wl_client *client,
223                            struct wl_resource *resource,
224                            int32_t x,
225                            int32_t y,
226                            int32_t width,
227                            int32_t height)
228 {
229 }
230
231 static void
232 text_model_set_content_type(struct wl_client *client,
233                             struct wl_resource *resource,
234                             uint32_t hint,
235                             uint32_t purpose)
236 {
237         struct text_model *text_model = resource->data;
238         struct input_method *input_method, *next;
239
240         wl_list_for_each_safe(input_method, next, &text_model->input_methods, link) {
241                 if (!input_method->context)
242                         continue;
243                 input_method_context_send_content_type(&input_method->context->resource, hint, purpose);
244         }
245 }
246
247 static void
248 text_model_invoke_action(struct wl_client *client,
249                          struct wl_resource *resource,
250                          uint32_t button,
251                          uint32_t index)
252 {
253         struct text_model *text_model = resource->data;
254         struct input_method *input_method, *next;
255
256         wl_list_for_each_safe(input_method, next, &text_model->input_methods, link) {
257                 if (!input_method->context)
258                         continue;
259                 input_method_context_send_invoke_action(&input_method->context->resource, button, index);
260         }
261 }
262
263 static void
264 text_model_commit(struct wl_client *client,
265                   struct wl_resource *resource)
266 {
267         struct text_model *text_model = resource->data;
268         struct input_method *input_method, *next;
269
270         wl_list_for_each_safe(input_method, next, &text_model->input_methods, link) {
271                 if (!input_method->context)
272                         continue;
273                 input_method_context_send_commit(&input_method->context->resource);
274         }
275 }
276
277 static void
278 text_model_show_input_panel(struct wl_client *client,
279                             struct wl_resource *resource)
280 {
281         struct text_model *text_model = resource->data;
282         struct weston_compositor *ec = text_model->ec;
283
284         text_model->input_panel_visible = 1;
285
286         if (!wl_list_empty(&text_model->input_methods))
287                 wl_signal_emit(&ec->show_input_panel_signal, ec);
288 }
289
290 static void
291 text_model_hide_input_panel(struct wl_client *client,
292                             struct wl_resource *resource)
293 {
294         struct text_model *text_model = resource->data;
295         struct weston_compositor *ec = text_model->ec;
296
297         text_model->input_panel_visible = 0;
298
299         if (!wl_list_empty(&text_model->input_methods))
300                 wl_signal_emit(&ec->hide_input_panel_signal, ec);
301 }
302
303 static void
304 text_model_set_preferred_language(struct wl_client *client,
305                                   struct wl_resource *resource,
306                                   const char *language)
307 {
308         struct text_model *text_model = resource->data;
309         struct input_method *input_method, *next;
310
311         wl_list_for_each_safe(input_method, next, &text_model->input_methods, link) {
312                 if (!input_method->context)
313                         continue;
314                 input_method_context_send_preferred_language(&input_method->context->resource,
315                                                              language);
316         }
317 }
318
319 static const struct text_model_interface text_model_implementation = {
320         text_model_set_surrounding_text,
321         text_model_activate,
322         text_model_deactivate,
323         text_model_reset,
324         text_model_set_micro_focus,
325         text_model_set_content_type,
326         text_model_invoke_action,
327         text_model_commit,
328         text_model_show_input_panel,
329         text_model_hide_input_panel,
330         text_model_set_preferred_language
331 };
332
333 static void text_model_factory_create_text_model(struct wl_client *client,
334                                                  struct wl_resource *resource,
335                                                  uint32_t id)
336 {
337         struct text_model_factory *text_model_factory = resource->data;
338         struct text_model *text_model;
339
340         text_model = calloc(1, sizeof *text_model);
341
342         text_model->resource.object.id = id;
343         text_model->resource.object.interface = &text_model_interface;
344         text_model->resource.object.implementation =
345                 (void (**)(void)) &text_model_implementation;
346
347         text_model->resource.data = text_model;
348         text_model->resource.destroy = destroy_text_model;
349
350         text_model->ec = text_model_factory->ec;
351
352         wl_list_init(&text_model->input_methods);
353
354         wl_client_add_resource(client, &text_model->resource);
355 };
356
357 static const struct text_model_factory_interface text_model_factory_implementation = {
358         text_model_factory_create_text_model
359 };
360
361 static void
362 bind_text_model_factory(struct wl_client *client,
363                         void *data,
364                         uint32_t version,
365                         uint32_t id)
366 {
367         struct text_model_factory *text_model_factory = data;
368
369         /* No checking for duplicate binding necessary.
370          * No events have to be sent, so we don't need the return value. */
371         wl_client_add_object(client, &text_model_factory_interface,
372                              &text_model_factory_implementation,
373                              id, text_model_factory);
374 }
375
376 static void
377 text_model_factory_notifier_destroy(struct wl_listener *listener, void *data)
378 {
379         struct text_model_factory *text_model_factory =
380                 container_of(listener, struct text_model_factory, destroy_listener);
381
382         wl_display_remove_global(text_model_factory->ec->wl_display,
383                                  text_model_factory->text_model_factory_global);
384
385         free(text_model_factory);
386 }
387
388 static void
389 text_model_factory_create(struct weston_compositor *ec)
390 {
391         struct text_model_factory *text_model_factory;
392
393         text_model_factory = calloc(1, sizeof *text_model_factory);
394
395         text_model_factory->ec = ec;
396
397         text_model_factory->text_model_factory_global =
398                 wl_display_add_global(ec->wl_display,
399                                       &text_model_factory_interface,
400                                       text_model_factory, bind_text_model_factory);
401
402         text_model_factory->destroy_listener.notify = text_model_factory_notifier_destroy;
403         wl_signal_add(&ec->destroy_signal, &text_model_factory->destroy_listener);
404 }
405
406 static void
407 input_method_context_destroy(struct wl_client *client,
408                              struct wl_resource *resource)
409 {
410         wl_resource_destroy(resource);
411 }
412
413 static void
414 input_method_context_commit_string(struct wl_client *client,
415                                    struct wl_resource *resource,
416                                    uint32_t serial,
417                                    const char *text)
418 {
419         struct input_method_context *context = resource->data;
420
421         text_model_send_commit_string(&context->model->resource, serial, text);
422 }
423
424 static void
425 input_method_context_preedit_string(struct wl_client *client,
426                                     struct wl_resource *resource,
427                                     uint32_t serial,
428                                     const char *text,
429                                     const char *commit)
430 {
431         struct input_method_context *context = resource->data;
432
433         text_model_send_preedit_string(&context->model->resource, serial, text, commit);
434 }
435
436 static void
437 input_method_context_preedit_styling(struct wl_client *client,
438                                      struct wl_resource *resource,
439                                      uint32_t serial,
440                                      uint32_t index,
441                                      uint32_t length,
442                                      uint32_t style)
443 {
444         struct input_method_context *context = resource->data;
445
446         text_model_send_preedit_styling(&context->model->resource, serial, index, length, style);
447 }
448
449 static void
450 input_method_context_preedit_cursor(struct wl_client *client,
451                                     struct wl_resource *resource,
452                                     uint32_t serial,
453                                     int32_t cursor)
454 {
455         struct input_method_context *context = resource->data;
456
457         text_model_send_preedit_cursor(&context->model->resource, serial, cursor);
458 }
459
460 static void
461 input_method_context_delete_surrounding_text(struct wl_client *client,
462                                              struct wl_resource *resource,
463                                              uint32_t serial,
464                                              int32_t index,
465                                              uint32_t length)
466 {
467         struct input_method_context *context = resource->data;
468
469         text_model_send_delete_surrounding_text(&context->model->resource, serial, index, length);
470 }
471
472 static void
473 input_method_context_cursor_position(struct wl_client *client,
474                                      struct wl_resource *resource,
475                                      uint32_t serial,
476                                      int32_t index,
477                                      int32_t anchor)
478 {
479         struct input_method_context *context = resource->data;
480
481         text_model_send_cursor_position(&context->model->resource, serial, index, anchor);
482 }
483
484 static void
485 input_method_context_modifiers_map(struct wl_client *client,
486                                    struct wl_resource *resource,
487                                    struct wl_array *map)
488 {
489         struct input_method_context *context = resource->data;
490
491         text_model_send_modifiers_map(&context->model->resource, map);
492 }
493
494 static void
495 input_method_context_keysym(struct wl_client *client,
496                             struct wl_resource *resource,
497                             uint32_t serial,
498                             uint32_t time,
499                             uint32_t sym,
500                             uint32_t state,
501                             uint32_t modifiers)
502 {
503         struct input_method_context *context = resource->data;
504
505         text_model_send_keysym(&context->model->resource, serial, time,
506                                sym, state, modifiers);
507 }
508
509 static void
510 unbind_keyboard(struct wl_resource *resource)
511 {
512         struct input_method_context *context = resource->data;
513
514         input_method_context_end_keyboard_grab(context);
515         context->keyboard = NULL;
516
517         free(resource);
518 }
519
520 static void
521 input_method_context_grab_key(struct wl_keyboard_grab *grab,
522                               uint32_t time, uint32_t key, uint32_t state_w)
523 {
524         struct weston_keyboard *keyboard = (struct weston_keyboard *)grab->keyboard;
525         struct wl_display *display;
526         uint32_t serial;
527
528         if (!keyboard->input_method_resource)
529                 return;
530
531         display = wl_client_get_display(keyboard->input_method_resource->client);
532         serial = wl_display_next_serial(display);
533         wl_keyboard_send_key(keyboard->input_method_resource,
534                              serial, time, key, state_w);
535 }
536
537 static void
538 input_method_context_grab_modifier(struct wl_keyboard_grab *grab, uint32_t serial,
539                                    uint32_t mods_depressed, uint32_t mods_latched,
540                                    uint32_t mods_locked, uint32_t group)
541 {
542         struct weston_keyboard *keyboard = (struct weston_keyboard *)grab->keyboard;
543
544         if (!keyboard->input_method_resource)
545                 return;
546
547         wl_keyboard_send_modifiers(keyboard->input_method_resource,
548                                    serial, mods_depressed, mods_latched,
549                                    mods_locked, group);
550 }
551
552 static const struct wl_keyboard_grab_interface input_method_context_grab = {
553         input_method_context_grab_key,
554         input_method_context_grab_modifier,
555 };
556
557 static void
558 input_method_context_grab_keyboard(struct wl_client *client,
559                                    struct wl_resource *resource,
560                                    uint32_t id)
561 {
562         struct input_method_context *context = resource->data;
563         struct wl_resource *cr;
564         struct weston_seat *seat = context->input_method->seat;
565         struct weston_keyboard *keyboard = &seat->keyboard;
566
567         cr = wl_client_add_object(client, &wl_keyboard_interface,
568                                   NULL, id, context);
569         cr->destroy = unbind_keyboard;
570
571         context->keyboard = cr;
572
573         wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
574                                 seat->xkb_info.keymap_fd,
575                                 seat->xkb_info.keymap_size);
576
577         if (keyboard->keyboard.grab != &keyboard->keyboard.default_grab) {
578                 wl_keyboard_end_grab(&keyboard->keyboard);
579         }
580         wl_keyboard_start_grab(&keyboard->keyboard, &keyboard->input_method_grab);
581         keyboard->input_method_resource = cr;
582 }
583
584 static void
585 input_method_context_key(struct wl_client *client,
586                          struct wl_resource *resource,
587                          uint32_t serial,
588                          uint32_t time,
589                          uint32_t key,
590                          uint32_t state_w)
591 {
592         struct input_method_context *context = resource->data;
593         struct weston_seat *seat = context->input_method->seat;
594         struct wl_keyboard *keyboard = seat->seat.keyboard;
595         struct wl_keyboard_grab *default_grab = &keyboard->default_grab;
596
597         default_grab->interface->key(default_grab, time, key, state_w);
598 }
599
600 static void
601 input_method_context_modifiers(struct wl_client *client,
602                                struct wl_resource *resource,
603                                uint32_t serial,
604                                uint32_t mods_depressed,
605                                uint32_t mods_latched,
606                                uint32_t mods_locked,
607                                uint32_t group)
608 {
609         struct input_method_context *context = resource->data;
610
611         struct weston_seat *seat = context->input_method->seat;
612         struct wl_keyboard *keyboard = seat->seat.keyboard;
613         struct wl_keyboard_grab *default_grab = &keyboard->default_grab;
614
615         default_grab->interface->modifiers(default_grab,
616                                            serial, mods_depressed,
617                                            mods_latched, mods_locked,
618                                            group);
619 }
620
621 static void
622 input_method_context_language(struct wl_client *client,
623                               struct wl_resource *resource,
624                               uint32_t serial,
625                               const char *language)
626 {
627         struct input_method_context *context = resource->data;
628
629         text_model_send_language(&context->model->resource, serial, language);
630 }
631
632 static void
633 input_method_context_text_direction(struct wl_client *client,
634                                     struct wl_resource *resource,
635                                     uint32_t serial,
636                                     uint32_t direction)
637 {
638         struct input_method_context *context = resource->data;
639
640         text_model_send_text_direction(&context->model->resource, serial, direction);
641 }
642
643
644 static const struct input_method_context_interface input_method_context_implementation = {
645         input_method_context_destroy,
646         input_method_context_commit_string,
647         input_method_context_preedit_string,
648         input_method_context_preedit_styling,
649         input_method_context_preedit_cursor,
650         input_method_context_delete_surrounding_text,
651         input_method_context_cursor_position,
652         input_method_context_modifiers_map,
653         input_method_context_keysym,
654         input_method_context_grab_keyboard,
655         input_method_context_key,
656         input_method_context_modifiers,
657         input_method_context_language,
658         input_method_context_text_direction
659 };
660
661 static void
662 destroy_input_method_context(struct wl_resource *resource)
663 {
664         struct input_method_context *context = resource->data;
665
666         if (context->keyboard) {
667                 wl_resource_destroy(context->keyboard);
668         }
669
670         free(context);
671 }
672
673 static void
674 input_method_context_create(struct text_model *model,
675                             struct input_method *input_method,
676                             uint32_t serial)
677 {
678         struct input_method_context *context;
679
680         if (!input_method->input_method_binding)
681                 return;
682
683         context = calloc(1, sizeof *context);
684         if (context == NULL)
685                 return;
686
687         context->resource.destroy = destroy_input_method_context;
688         context->resource.object.id = 0;
689         context->resource.object.interface = &input_method_context_interface;
690         context->resource.object.implementation =
691                 (void (**)(void)) &input_method_context_implementation;
692         context->resource.data = context;
693         wl_signal_init(&context->resource.destroy_signal);
694
695         context->model = model;
696         context->input_method = input_method;
697         input_method->context = context;
698
699         wl_client_add_resource(input_method->input_method_binding->client, &context->resource);
700
701         input_method_send_activate(input_method->input_method_binding, &context->resource, serial);
702 }
703
704 static void
705 input_method_context_end_keyboard_grab(struct input_method_context *context)
706 {
707         struct wl_keyboard_grab *grab = &context->input_method->seat->keyboard.input_method_grab;
708         struct weston_keyboard *keyboard = (struct weston_keyboard *)grab->keyboard;
709
710         if (!grab->keyboard)
711                 return;
712
713         if (grab->keyboard->grab == grab)
714                 wl_keyboard_end_grab(grab->keyboard);
715
716         keyboard->input_method_resource = NULL;
717 }
718
719 static void
720 unbind_input_method(struct wl_resource *resource)
721 {
722         struct input_method *input_method = resource->data;
723         struct text_backend *text_backend = input_method->text_backend;
724
725         input_method->input_method_binding = NULL;
726         input_method->context = NULL;
727
728         text_backend->input_method.binding = NULL;
729
730         free(resource);
731 }
732
733 static void
734 bind_input_method(struct wl_client *client,
735                   void *data,
736                   uint32_t version,
737                   uint32_t id)
738 {
739         struct input_method *input_method = data;
740         struct text_backend *text_backend = input_method->text_backend;
741         struct wl_resource *resource;
742
743         resource = wl_client_add_object(client, &input_method_interface,
744                                         NULL,
745                                         id, input_method);
746
747         if (input_method->input_method_binding == NULL) {
748                 resource->destroy = unbind_input_method;
749                 input_method->input_method_binding = resource;
750
751                 text_backend->input_method.binding = resource;
752                 return;
753         }
754
755         wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
756                                "interface object already bound");
757         wl_resource_destroy(resource);
758 }
759
760 static void
761 input_method_notifier_destroy(struct wl_listener *listener, void *data)
762 {
763         struct input_method *input_method =
764                 container_of(listener, struct input_method, destroy_listener);
765
766         if (input_method->model)
767                 deactivate_text_model(input_method->model, input_method);
768
769         wl_display_remove_global(input_method->seat->compositor->wl_display,
770                                  input_method->input_method_global);
771
772         free(input_method);
773 }
774
775 static void
776 handle_keyboard_focus(struct wl_listener *listener, void *data)
777 {
778         struct wl_keyboard *keyboard = data;
779         struct input_method *input_method =
780                 container_of(listener, struct input_method, keyboard_focus_listener);
781         struct wl_surface *surface = keyboard->focus;
782
783         if (!input_method->model)
784                 return;
785
786         if (!surface || input_method->model->surface != surface)
787                 deactivate_text_model(input_method->model,
788                                       input_method);
789 }
790
791 static void
792 input_method_init_seat(struct weston_seat *seat)
793 {
794         if (seat->input_method->focus_listener_initialized)
795                 return;
796
797         if (seat->has_keyboard) {
798                 seat->input_method->keyboard_focus_listener.notify = handle_keyboard_focus;
799                 wl_signal_add(&seat->seat.keyboard->focus_signal, &seat->input_method->keyboard_focus_listener);
800                 seat->keyboard.input_method_grab.interface = &input_method_context_grab;
801         }
802
803         seat->input_method->focus_listener_initialized = 1;
804 }
805
806 static void
807 handle_input_method_sigchld(struct weston_process *process, int status)
808 {
809         struct text_backend *text_backend =
810                 container_of(process, struct text_backend, input_method.process);
811
812         text_backend->input_method.process.pid = 0;
813         text_backend->input_method.client = NULL;
814 }
815
816 static void
817 launch_input_method(struct text_backend *text_backend)
818 {
819         if (text_backend->input_method.binding)
820                 return;
821
822         if (!text_backend->input_method.path)
823                 return;
824
825         if (text_backend->input_method.process.pid != 0)
826                 return;
827
828         text_backend->input_method.client = weston_client_launch(text_backend->compositor,
829                                                                 &text_backend->input_method.process,
830                                                                 text_backend->input_method.path,
831                                                                 handle_input_method_sigchld);
832
833         if (!text_backend->input_method.client)
834                 weston_log("not able to start %s\n", text_backend->input_method.path);
835 }
836
837 static void
838 handle_seat_created(struct wl_listener *listener,
839                     void *data)
840 {
841         struct weston_seat *seat = data;
842         struct text_backend *text_backend =
843                 container_of(listener, struct text_backend,
844                              seat_created_listener);
845         struct input_method *input_method;
846         struct weston_compositor *ec = seat->compositor;
847
848         input_method = calloc(1, sizeof *input_method);
849
850         input_method->seat = seat;
851         input_method->model = NULL;
852         input_method->focus_listener_initialized = 0;
853         input_method->context = NULL;
854         input_method->text_backend = text_backend;
855
856         input_method->input_method_global =
857                 wl_display_add_global(ec->wl_display,
858                                       &input_method_interface,
859                                       input_method, bind_input_method);
860
861         input_method->destroy_listener.notify = input_method_notifier_destroy;
862         wl_signal_add(&seat->seat.destroy_signal, &input_method->destroy_listener);
863
864         seat->input_method = input_method;
865
866         launch_input_method(text_backend);
867 }
868
869 static void
870 text_backend_configuration(struct text_backend *text_backend)
871 {
872         char *config_file;
873         char *path = NULL;
874
875         struct config_key input_method_keys[] = {
876                 { "path", CONFIG_KEY_STRING, &path }
877         };
878
879         struct config_section cs[] = {
880                 { "input-method", input_method_keys, ARRAY_LENGTH(input_method_keys), NULL }
881         };
882
883         config_file = config_file_path("weston.ini");
884         parse_config_file(config_file, cs, ARRAY_LENGTH(cs), text_backend);
885         free(config_file);
886
887         if (path)
888                 text_backend->input_method.path = path;
889         else
890                 text_backend->input_method.path = strdup(LIBEXECDIR "/weston-keyboard");
891 }
892
893 static void
894 text_backend_notifier_destroy(struct wl_listener *listener, void *data)
895 {
896         struct text_backend *text_backend =
897                 container_of(listener, struct text_backend, destroy_listener);
898
899         if (text_backend->input_method.client)
900                 wl_client_destroy(text_backend->input_method.client);
901
902         free(text_backend->input_method.path);
903
904         free(text_backend);
905 }
906
907
908 WL_EXPORT int
909 text_backend_init(struct weston_compositor *ec)
910 {
911         struct text_backend *text_backend;
912
913         text_backend = calloc(1, sizeof(*text_backend));
914
915         text_backend->compositor = ec;
916
917         text_backend->seat_created_listener.notify = handle_seat_created;
918         wl_signal_add(&ec->seat_created_signal,
919                       &text_backend->seat_created_listener);
920
921         text_backend->destroy_listener.notify = text_backend_notifier_destroy;
922         wl_signal_add(&ec->destroy_signal, &text_backend->destroy_listener);
923
924         text_backend_configuration(text_backend);
925
926         text_model_factory_create(ec);
927
928         return 0;
929 }