2 * Copyright © 2012 Openismus GmbH
3 * Copyright © 2012 Intel Corporation
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.
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.
31 #include "compositor.h"
32 #include "text-server-protocol.h"
33 #include "input-method-server-protocol.h"
36 struct input_method_context;
40 struct wl_resource *resource;
42 struct weston_compositor *ec;
44 struct wl_list input_methods;
46 struct weston_surface *surface;
48 pixman_box32_t cursor_rectangle;
50 uint32_t input_panel_visible;
53 struct text_input_manager {
54 struct wl_global *text_input_manager_global;
55 struct wl_listener destroy_listener;
57 struct weston_compositor *ec;
61 struct wl_resource *input_method_binding;
62 struct wl_global *input_method_global;
63 struct wl_listener destroy_listener;
65 struct weston_seat *seat;
66 struct text_input *model;
70 struct wl_listener keyboard_focus_listener;
72 int focus_listener_initialized;
74 struct input_method_context *context;
76 struct text_backend *text_backend;
79 struct input_method_context {
80 struct wl_resource *resource;
82 struct text_input *model;
83 struct input_method *input_method;
87 struct wl_resource *keyboard;
91 struct weston_compositor *compositor;
95 struct wl_resource *binding;
96 struct weston_process process;
97 struct wl_client *client;
103 struct wl_listener seat_created_listener;
104 struct wl_listener destroy_listener;
107 static void input_method_context_create(struct text_input *model,
108 struct input_method *input_method);
109 static void input_method_context_end_keyboard_grab(struct input_method_context *context);
111 static void input_method_init_seat(struct weston_seat *seat);
114 deactivate_text_input(struct text_input *text_input,
115 struct input_method *input_method)
117 struct weston_compositor *ec = text_input->ec;
119 if (input_method->model == text_input) {
120 if (input_method->context && input_method->input_method_binding) {
121 input_method_context_end_keyboard_grab(input_method->context);
122 wl_input_method_send_deactivate(input_method->input_method_binding,
123 input_method->context->resource);
124 input_method->context->model = NULL;
127 wl_list_remove(&input_method->link);
128 input_method->model = NULL;
129 input_method->context = NULL;
130 wl_signal_emit(&ec->hide_input_panel_signal, ec);
131 wl_text_input_send_leave(text_input->resource);
136 destroy_text_input(struct wl_resource *resource)
138 struct text_input *text_input = wl_resource_get_user_data(resource);
139 struct input_method *input_method, *next;
141 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link)
142 deactivate_text_input(text_input, input_method);
148 text_input_set_surrounding_text(struct wl_client *client,
149 struct wl_resource *resource,
154 struct text_input *text_input = wl_resource_get_user_data(resource);
155 struct input_method *input_method, *next;
157 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
158 if (!input_method->context)
160 wl_input_method_context_send_surrounding_text(input_method->context->resource,
168 text_input_activate(struct wl_client *client,
169 struct wl_resource *resource,
170 struct wl_resource *seat,
171 struct wl_resource *surface)
173 struct text_input *text_input = wl_resource_get_user_data(resource);
174 struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
175 struct input_method *input_method = weston_seat->input_method;
176 struct text_input *old = weston_seat->input_method->model;
177 struct weston_compositor *ec = text_input->ec;
179 if (old == text_input)
183 deactivate_text_input(old,
184 weston_seat->input_method);
187 input_method->model = text_input;
188 wl_list_insert(&text_input->input_methods, &input_method->link);
189 input_method_init_seat(weston_seat);
191 text_input->surface = wl_resource_get_user_data(surface);
193 input_method_context_create(text_input, input_method);
195 if (text_input->input_panel_visible) {
196 wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
197 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
200 wl_text_input_send_enter(text_input->resource, text_input->surface->resource);
204 text_input_deactivate(struct wl_client *client,
205 struct wl_resource *resource,
206 struct wl_resource *seat)
208 struct text_input *text_input = wl_resource_get_user_data(resource);
209 struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
211 deactivate_text_input(text_input,
212 weston_seat->input_method);
216 text_input_reset(struct wl_client *client,
217 struct wl_resource *resource)
219 struct text_input *text_input = wl_resource_get_user_data(resource);
220 struct input_method *input_method, *next;
222 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
223 if (!input_method->context)
225 wl_input_method_context_send_reset(input_method->context->resource);
230 text_input_set_cursor_rectangle(struct wl_client *client,
231 struct wl_resource *resource,
237 struct text_input *text_input = wl_resource_get_user_data(resource);
238 struct weston_compositor *ec = text_input->ec;
240 text_input->cursor_rectangle.x1 = x;
241 text_input->cursor_rectangle.y1 = y;
242 text_input->cursor_rectangle.x2 = x + width;
243 text_input->cursor_rectangle.y2 = y + height;
245 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
249 text_input_set_content_type(struct wl_client *client,
250 struct wl_resource *resource,
254 struct text_input *text_input = wl_resource_get_user_data(resource);
255 struct input_method *input_method, *next;
257 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
258 if (!input_method->context)
260 wl_input_method_context_send_content_type(input_method->context->resource, hint, purpose);
265 text_input_invoke_action(struct wl_client *client,
266 struct wl_resource *resource,
270 struct text_input *text_input = wl_resource_get_user_data(resource);
271 struct input_method *input_method, *next;
273 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
274 if (!input_method->context)
276 wl_input_method_context_send_invoke_action(input_method->context->resource, button, index);
281 text_input_commit_state(struct wl_client *client,
282 struct wl_resource *resource,
285 struct text_input *text_input = wl_resource_get_user_data(resource);
286 struct input_method *input_method, *next;
288 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
289 if (!input_method->context)
291 wl_input_method_context_send_commit_state(input_method->context->resource, serial);
296 text_input_show_input_panel(struct wl_client *client,
297 struct wl_resource *resource)
299 struct text_input *text_input = wl_resource_get_user_data(resource);
300 struct weston_compositor *ec = text_input->ec;
302 text_input->input_panel_visible = 1;
304 if (!wl_list_empty(&text_input->input_methods)) {
305 wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
306 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
311 text_input_hide_input_panel(struct wl_client *client,
312 struct wl_resource *resource)
314 struct text_input *text_input = wl_resource_get_user_data(resource);
315 struct weston_compositor *ec = text_input->ec;
317 text_input->input_panel_visible = 0;
319 if (!wl_list_empty(&text_input->input_methods))
320 wl_signal_emit(&ec->hide_input_panel_signal, ec);
324 text_input_set_preferred_language(struct wl_client *client,
325 struct wl_resource *resource,
326 const char *language)
328 struct text_input *text_input = wl_resource_get_user_data(resource);
329 struct input_method *input_method, *next;
331 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
332 if (!input_method->context)
334 wl_input_method_context_send_preferred_language(input_method->context->resource,
339 static const struct wl_text_input_interface text_input_implementation = {
341 text_input_deactivate,
342 text_input_show_input_panel,
343 text_input_hide_input_panel,
345 text_input_set_surrounding_text,
346 text_input_set_content_type,
347 text_input_set_cursor_rectangle,
348 text_input_set_preferred_language,
349 text_input_commit_state,
350 text_input_invoke_action
353 static void text_input_manager_create_text_input(struct wl_client *client,
354 struct wl_resource *resource,
357 struct text_input_manager *text_input_manager = wl_resource_get_user_data(resource);
358 struct text_input *text_input;
360 text_input = calloc(1, sizeof *text_input);
362 text_input->resource =
363 wl_resource_create(client, &wl_text_input_interface, 1, id);
364 wl_resource_set_implementation(text_input->resource,
365 &text_input_implementation,
366 text_input, destroy_text_input);
368 text_input->ec = text_input_manager->ec;
370 wl_list_init(&text_input->input_methods);
373 static const struct wl_text_input_manager_interface text_input_manager_implementation = {
374 text_input_manager_create_text_input
378 bind_text_input_manager(struct wl_client *client,
383 struct text_input_manager *text_input_manager = data;
384 struct wl_resource *resource;
386 /* No checking for duplicate binding necessary. */
388 wl_resource_create(client,
389 &wl_text_input_manager_interface, 1, id);
391 wl_resource_set_implementation(resource,
392 &text_input_manager_implementation,
393 text_input_manager, NULL);
397 text_input_manager_notifier_destroy(struct wl_listener *listener, void *data)
399 struct text_input_manager *text_input_manager =
400 container_of(listener, struct text_input_manager, destroy_listener);
402 wl_global_destroy(text_input_manager->text_input_manager_global);
404 free(text_input_manager);
408 text_input_manager_create(struct weston_compositor *ec)
410 struct text_input_manager *text_input_manager;
412 text_input_manager = calloc(1, sizeof *text_input_manager);
414 text_input_manager->ec = ec;
416 text_input_manager->text_input_manager_global =
417 wl_global_create(ec->wl_display,
418 &wl_text_input_manager_interface, 1,
419 text_input_manager, bind_text_input_manager);
421 text_input_manager->destroy_listener.notify = text_input_manager_notifier_destroy;
422 wl_signal_add(&ec->destroy_signal, &text_input_manager->destroy_listener);
426 input_method_context_destroy(struct wl_client *client,
427 struct wl_resource *resource)
429 wl_resource_destroy(resource);
433 input_method_context_commit_string(struct wl_client *client,
434 struct wl_resource *resource,
438 struct input_method_context *context =
439 wl_resource_get_user_data(resource);
442 wl_text_input_send_commit_string(context->model->resource,
447 input_method_context_preedit_string(struct wl_client *client,
448 struct wl_resource *resource,
453 struct input_method_context *context =
454 wl_resource_get_user_data(resource);
457 wl_text_input_send_preedit_string(context->model->resource,
458 serial, text, commit);
462 input_method_context_preedit_styling(struct wl_client *client,
463 struct wl_resource *resource,
468 struct input_method_context *context =
469 wl_resource_get_user_data(resource);
472 wl_text_input_send_preedit_styling(context->model->resource,
473 index, length, style);
477 input_method_context_preedit_cursor(struct wl_client *client,
478 struct wl_resource *resource,
481 struct input_method_context *context =
482 wl_resource_get_user_data(resource);
485 wl_text_input_send_preedit_cursor(context->model->resource,
490 input_method_context_delete_surrounding_text(struct wl_client *client,
491 struct wl_resource *resource,
495 struct input_method_context *context =
496 wl_resource_get_user_data(resource);
499 wl_text_input_send_delete_surrounding_text(context->model->resource,
504 input_method_context_cursor_position(struct wl_client *client,
505 struct wl_resource *resource,
509 struct input_method_context *context =
510 wl_resource_get_user_data(resource);
513 wl_text_input_send_cursor_position(context->model->resource,
518 input_method_context_modifiers_map(struct wl_client *client,
519 struct wl_resource *resource,
520 struct wl_array *map)
522 struct input_method_context *context =
523 wl_resource_get_user_data(resource);
526 wl_text_input_send_modifiers_map(context->model->resource, map);
530 input_method_context_keysym(struct wl_client *client,
531 struct wl_resource *resource,
538 struct input_method_context *context =
539 wl_resource_get_user_data(resource);
542 wl_text_input_send_keysym(context->model->resource,
543 serial, time, sym, state, modifiers);
547 unbind_keyboard(struct wl_resource *resource)
549 struct input_method_context *context =
550 wl_resource_get_user_data(resource);
552 input_method_context_end_keyboard_grab(context);
553 context->keyboard = NULL;
557 input_method_context_grab_key(struct weston_keyboard_grab *grab,
558 uint32_t time, uint32_t key, uint32_t state_w)
560 struct weston_keyboard *keyboard = grab->keyboard;
561 struct wl_display *display;
564 if (!keyboard->input_method_resource)
567 display = wl_client_get_display(wl_resource_get_client(keyboard->input_method_resource));
568 serial = wl_display_next_serial(display);
569 wl_keyboard_send_key(keyboard->input_method_resource,
570 serial, time, key, state_w);
574 input_method_context_grab_modifier(struct weston_keyboard_grab *grab, uint32_t serial,
575 uint32_t mods_depressed, uint32_t mods_latched,
576 uint32_t mods_locked, uint32_t group)
578 struct weston_keyboard *keyboard = grab->keyboard;
580 if (!keyboard->input_method_resource)
583 wl_keyboard_send_modifiers(keyboard->input_method_resource,
584 serial, mods_depressed, mods_latched,
589 input_method_context_grab_cancel(struct weston_keyboard_grab *grab)
591 weston_keyboard_end_grab(grab->keyboard);
594 static const struct weston_keyboard_grab_interface input_method_context_grab = {
595 input_method_context_grab_key,
596 input_method_context_grab_modifier,
597 input_method_context_grab_cancel,
601 input_method_context_grab_keyboard(struct wl_client *client,
602 struct wl_resource *resource,
605 struct input_method_context *context = wl_resource_get_user_data(resource);
606 struct wl_resource *cr;
607 struct weston_seat *seat = context->input_method->seat;
608 struct weston_keyboard *keyboard = seat->keyboard;
610 cr = wl_resource_create(client, &wl_keyboard_interface, 1, id);
611 wl_resource_set_implementation(cr, NULL, context, unbind_keyboard);
613 context->keyboard = cr;
615 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
616 keyboard->xkb_info->keymap_fd,
617 keyboard->xkb_info->keymap_size);
619 if (keyboard->grab != &keyboard->default_grab) {
620 weston_keyboard_end_grab(keyboard);
622 weston_keyboard_start_grab(keyboard, &keyboard->input_method_grab);
623 keyboard->input_method_resource = cr;
627 input_method_context_key(struct wl_client *client,
628 struct wl_resource *resource,
634 struct input_method_context *context = wl_resource_get_user_data(resource);
635 struct weston_seat *seat = context->input_method->seat;
636 struct weston_keyboard *keyboard = seat->keyboard;
637 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
639 default_grab->interface->key(default_grab, time, key, state_w);
643 input_method_context_modifiers(struct wl_client *client,
644 struct wl_resource *resource,
646 uint32_t mods_depressed,
647 uint32_t mods_latched,
648 uint32_t mods_locked,
651 struct input_method_context *context = wl_resource_get_user_data(resource);
653 struct weston_seat *seat = context->input_method->seat;
654 struct weston_keyboard *keyboard = seat->keyboard;
655 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
657 default_grab->interface->modifiers(default_grab,
658 serial, mods_depressed,
659 mods_latched, mods_locked,
664 input_method_context_language(struct wl_client *client,
665 struct wl_resource *resource,
667 const char *language)
669 struct input_method_context *context = wl_resource_get_user_data(resource);
672 wl_text_input_send_language(context->model->resource,
677 input_method_context_text_direction(struct wl_client *client,
678 struct wl_resource *resource,
682 struct input_method_context *context = wl_resource_get_user_data(resource);
685 wl_text_input_send_text_direction(context->model->resource,
690 static const struct wl_input_method_context_interface input_method_context_implementation = {
691 input_method_context_destroy,
692 input_method_context_commit_string,
693 input_method_context_preedit_string,
694 input_method_context_preedit_styling,
695 input_method_context_preedit_cursor,
696 input_method_context_delete_surrounding_text,
697 input_method_context_cursor_position,
698 input_method_context_modifiers_map,
699 input_method_context_keysym,
700 input_method_context_grab_keyboard,
701 input_method_context_key,
702 input_method_context_modifiers,
703 input_method_context_language,
704 input_method_context_text_direction
708 destroy_input_method_context(struct wl_resource *resource)
710 struct input_method_context *context = wl_resource_get_user_data(resource);
712 if (context->keyboard) {
713 wl_resource_destroy(context->keyboard);
720 input_method_context_create(struct text_input *model,
721 struct input_method *input_method)
723 struct input_method_context *context;
724 struct wl_resource *binding;
726 if (!input_method->input_method_binding)
729 context = calloc(1, sizeof *context);
733 binding = input_method->input_method_binding;
735 wl_resource_create(wl_resource_get_client(binding),
736 &wl_input_method_context_interface, 1, 0);
737 wl_resource_set_implementation(context->resource,
738 &input_method_context_implementation,
739 context, destroy_input_method_context);
741 context->model = model;
742 context->input_method = input_method;
743 input_method->context = context;
746 wl_input_method_send_activate(binding, context->resource);
750 input_method_context_end_keyboard_grab(struct input_method_context *context)
752 struct weston_keyboard_grab *grab =
753 &context->input_method->seat->keyboard->input_method_grab;
754 struct weston_keyboard *keyboard = grab->keyboard;
759 if (grab->keyboard->grab == grab)
760 weston_keyboard_end_grab(grab->keyboard);
762 keyboard->input_method_resource = NULL;
766 unbind_input_method(struct wl_resource *resource)
768 struct input_method *input_method = wl_resource_get_user_data(resource);
769 struct text_backend *text_backend = input_method->text_backend;
771 input_method->input_method_binding = NULL;
772 input_method->context = NULL;
774 text_backend->input_method.binding = NULL;
778 bind_input_method(struct wl_client *client,
783 struct input_method *input_method = data;
784 struct text_backend *text_backend = input_method->text_backend;
785 struct wl_resource *resource;
788 wl_resource_create(client, &wl_input_method_interface, 1, id);
790 if (input_method->input_method_binding != NULL) {
791 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
792 "interface object already bound");
793 wl_resource_destroy(resource);
797 if (text_backend->input_method.client != client) {
798 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
799 "permission to bind input_method denied");
800 wl_resource_destroy(resource);
804 wl_resource_set_implementation(resource, NULL, input_method,
805 unbind_input_method);
806 input_method->input_method_binding = resource;
808 text_backend->input_method.binding = resource;
812 input_method_notifier_destroy(struct wl_listener *listener, void *data)
814 struct input_method *input_method =
815 container_of(listener, struct input_method, destroy_listener);
817 if (input_method->model)
818 deactivate_text_input(input_method->model, input_method);
820 wl_global_destroy(input_method->input_method_global);
821 wl_list_remove(&input_method->destroy_listener.link);
827 handle_keyboard_focus(struct wl_listener *listener, void *data)
829 struct weston_keyboard *keyboard = data;
830 struct input_method *input_method =
831 container_of(listener, struct input_method, keyboard_focus_listener);
832 struct weston_surface *surface = keyboard->focus;
834 if (!input_method->model)
837 if (!surface || input_method->model->surface != surface)
838 deactivate_text_input(input_method->model,
843 input_method_init_seat(struct weston_seat *seat)
845 if (seat->input_method->focus_listener_initialized)
848 if (seat->keyboard) {
849 seat->input_method->keyboard_focus_listener.notify = handle_keyboard_focus;
850 wl_signal_add(&seat->keyboard->focus_signal, &seat->input_method->keyboard_focus_listener);
851 seat->keyboard->input_method_grab.interface = &input_method_context_grab;
854 seat->input_method->focus_listener_initialized = 1;
857 static void launch_input_method(struct text_backend *text_backend);
860 handle_input_method_sigchld(struct weston_process *process, int status)
863 struct text_backend *text_backend =
864 container_of(process, struct text_backend, input_method.process);
866 text_backend->input_method.process.pid = 0;
867 text_backend->input_method.client = NULL;
869 /* if input_method dies more than 5 times in 10 seconds, give up */
870 time = weston_compositor_get_time();
871 if (time - text_backend->input_method.deathstamp > 10000) {
872 text_backend->input_method.deathstamp = time;
873 text_backend->input_method.deathcount = 0;
876 text_backend->input_method.deathcount++;
877 if (text_backend->input_method.deathcount > 5) {
878 weston_log("input_method died, giving up.\n");
882 weston_log("input_method died, respawning...\n");
883 launch_input_method(text_backend);
887 launch_input_method(struct text_backend *text_backend)
889 if (text_backend->input_method.binding)
892 if (!text_backend->input_method.path)
895 if (text_backend->input_method.process.pid != 0)
898 text_backend->input_method.client = weston_client_launch(text_backend->compositor,
899 &text_backend->input_method.process,
900 text_backend->input_method.path,
901 handle_input_method_sigchld);
903 if (!text_backend->input_method.client)
904 weston_log("not able to start %s\n", text_backend->input_method.path);
908 handle_seat_created(struct wl_listener *listener,
911 struct weston_seat *seat = data;
912 struct text_backend *text_backend =
913 container_of(listener, struct text_backend,
914 seat_created_listener);
915 struct input_method *input_method;
916 struct weston_compositor *ec = seat->compositor;
918 input_method = calloc(1, sizeof *input_method);
920 input_method->seat = seat;
921 input_method->model = NULL;
922 input_method->focus_listener_initialized = 0;
923 input_method->context = NULL;
924 input_method->text_backend = text_backend;
926 input_method->input_method_global =
927 wl_global_create(ec->wl_display, &wl_input_method_interface, 1,
928 input_method, bind_input_method);
930 input_method->destroy_listener.notify = input_method_notifier_destroy;
931 wl_signal_add(&seat->destroy_signal, &input_method->destroy_listener);
933 seat->input_method = input_method;
935 launch_input_method(text_backend);
939 text_backend_configuration(struct text_backend *text_backend)
941 struct weston_config_section *section;
943 section = weston_config_get_section(text_backend->compositor->config,
944 "input-method", NULL, NULL);
945 weston_config_section_get_string(section, "path",
946 &text_backend->input_method.path,
947 LIBEXECDIR "/weston-keyboard");
951 text_backend_notifier_destroy(struct wl_listener *listener, void *data)
953 struct text_backend *text_backend =
954 container_of(listener, struct text_backend, destroy_listener);
956 if (text_backend->input_method.client)
957 wl_client_destroy(text_backend->input_method.client);
959 free(text_backend->input_method.path);
966 text_backend_init(struct weston_compositor *ec)
968 struct text_backend *text_backend;
970 text_backend = calloc(1, sizeof(*text_backend));
972 text_backend->compositor = ec;
974 text_backend->seat_created_listener.notify = handle_seat_created;
975 wl_signal_add(&ec->seat_created_signal,
976 &text_backend->seat_created_listener);
978 text_backend->destroy_listener.notify = text_backend_notifier_destroy;
979 wl_signal_add(&ec->destroy_signal, &text_backend->destroy_listener);
981 text_backend_configuration(text_backend);
983 text_input_manager_create(ec);