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);
126 wl_list_remove(&input_method->link);
127 input_method->model = NULL;
128 input_method->context = NULL;
129 wl_signal_emit(&ec->hide_input_panel_signal, ec);
130 wl_text_input_send_leave(text_input->resource);
135 destroy_text_input(struct wl_resource *resource)
137 struct text_input *text_input = wl_resource_get_user_data(resource);
138 struct input_method *input_method, *next;
140 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link)
141 deactivate_text_input(text_input, input_method);
147 text_input_set_surrounding_text(struct wl_client *client,
148 struct wl_resource *resource,
153 struct text_input *text_input = wl_resource_get_user_data(resource);
154 struct input_method *input_method, *next;
156 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
157 if (!input_method->context)
159 wl_input_method_context_send_surrounding_text(input_method->context->resource,
167 text_input_activate(struct wl_client *client,
168 struct wl_resource *resource,
169 struct wl_resource *seat,
170 struct wl_resource *surface)
172 struct text_input *text_input = wl_resource_get_user_data(resource);
173 struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
174 struct input_method *input_method = weston_seat->input_method;
175 struct text_input *old = weston_seat->input_method->model;
176 struct weston_compositor *ec = text_input->ec;
178 if (old == text_input)
182 deactivate_text_input(old,
183 weston_seat->input_method);
186 input_method->model = text_input;
187 wl_list_insert(&text_input->input_methods, &input_method->link);
188 input_method_init_seat(weston_seat);
190 text_input->surface = wl_resource_get_user_data(surface);
192 input_method_context_create(text_input, input_method);
194 if (text_input->input_panel_visible) {
195 wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
196 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
199 wl_text_input_send_enter(text_input->resource, text_input->surface->resource);
203 text_input_deactivate(struct wl_client *client,
204 struct wl_resource *resource,
205 struct wl_resource *seat)
207 struct text_input *text_input = wl_resource_get_user_data(resource);
208 struct weston_seat *weston_seat = wl_resource_get_user_data(seat);
210 deactivate_text_input(text_input,
211 weston_seat->input_method);
215 text_input_reset(struct wl_client *client,
216 struct wl_resource *resource)
218 struct text_input *text_input = wl_resource_get_user_data(resource);
219 struct input_method *input_method, *next;
221 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
222 if (!input_method->context)
224 wl_input_method_context_send_reset(input_method->context->resource);
229 text_input_set_cursor_rectangle(struct wl_client *client,
230 struct wl_resource *resource,
236 struct text_input *text_input = wl_resource_get_user_data(resource);
237 struct weston_compositor *ec = text_input->ec;
239 text_input->cursor_rectangle.x1 = x;
240 text_input->cursor_rectangle.y1 = y;
241 text_input->cursor_rectangle.x2 = x + width;
242 text_input->cursor_rectangle.y2 = y + height;
244 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
248 text_input_set_content_type(struct wl_client *client,
249 struct wl_resource *resource,
253 struct text_input *text_input = wl_resource_get_user_data(resource);
254 struct input_method *input_method, *next;
256 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
257 if (!input_method->context)
259 wl_input_method_context_send_content_type(input_method->context->resource, hint, purpose);
264 text_input_invoke_action(struct wl_client *client,
265 struct wl_resource *resource,
269 struct text_input *text_input = wl_resource_get_user_data(resource);
270 struct input_method *input_method, *next;
272 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
273 if (!input_method->context)
275 wl_input_method_context_send_invoke_action(input_method->context->resource, button, index);
280 text_input_commit_state(struct wl_client *client,
281 struct wl_resource *resource,
284 struct text_input *text_input = wl_resource_get_user_data(resource);
285 struct input_method *input_method, *next;
287 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
288 if (!input_method->context)
290 wl_input_method_context_send_commit_state(input_method->context->resource, serial);
295 text_input_show_input_panel(struct wl_client *client,
296 struct wl_resource *resource)
298 struct text_input *text_input = wl_resource_get_user_data(resource);
299 struct weston_compositor *ec = text_input->ec;
301 text_input->input_panel_visible = 1;
303 if (!wl_list_empty(&text_input->input_methods)) {
304 wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
305 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
310 text_input_hide_input_panel(struct wl_client *client,
311 struct wl_resource *resource)
313 struct text_input *text_input = wl_resource_get_user_data(resource);
314 struct weston_compositor *ec = text_input->ec;
316 text_input->input_panel_visible = 0;
318 if (!wl_list_empty(&text_input->input_methods))
319 wl_signal_emit(&ec->hide_input_panel_signal, ec);
323 text_input_set_preferred_language(struct wl_client *client,
324 struct wl_resource *resource,
325 const char *language)
327 struct text_input *text_input = wl_resource_get_user_data(resource);
328 struct input_method *input_method, *next;
330 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
331 if (!input_method->context)
333 wl_input_method_context_send_preferred_language(input_method->context->resource,
338 static const struct wl_text_input_interface text_input_implementation = {
340 text_input_deactivate,
341 text_input_show_input_panel,
342 text_input_hide_input_panel,
344 text_input_set_surrounding_text,
345 text_input_set_content_type,
346 text_input_set_cursor_rectangle,
347 text_input_set_preferred_language,
348 text_input_commit_state,
349 text_input_invoke_action
352 static void text_input_manager_create_text_input(struct wl_client *client,
353 struct wl_resource *resource,
356 struct text_input_manager *text_input_manager = wl_resource_get_user_data(resource);
357 struct text_input *text_input;
359 text_input = calloc(1, sizeof *text_input);
361 text_input->resource =
362 wl_resource_create(client, &wl_text_input_interface, 1, id);
363 wl_resource_set_implementation(text_input->resource,
364 &text_input_implementation,
365 text_input, destroy_text_input);
367 text_input->ec = text_input_manager->ec;
369 wl_list_init(&text_input->input_methods);
372 static const struct wl_text_input_manager_interface text_input_manager_implementation = {
373 text_input_manager_create_text_input
377 bind_text_input_manager(struct wl_client *client,
382 struct text_input_manager *text_input_manager = data;
383 struct wl_resource *resource;
385 /* No checking for duplicate binding necessary. */
387 wl_resource_create(client,
388 &wl_text_input_manager_interface, 1, id);
390 wl_resource_set_implementation(resource,
391 &text_input_manager_implementation,
392 text_input_manager, NULL);
396 text_input_manager_notifier_destroy(struct wl_listener *listener, void *data)
398 struct text_input_manager *text_input_manager =
399 container_of(listener, struct text_input_manager, destroy_listener);
401 wl_global_destroy(text_input_manager->text_input_manager_global);
403 free(text_input_manager);
407 text_input_manager_create(struct weston_compositor *ec)
409 struct text_input_manager *text_input_manager;
411 text_input_manager = calloc(1, sizeof *text_input_manager);
413 text_input_manager->ec = ec;
415 text_input_manager->text_input_manager_global =
416 wl_global_create(ec->wl_display,
417 &wl_text_input_manager_interface, 1,
418 text_input_manager, bind_text_input_manager);
420 text_input_manager->destroy_listener.notify = text_input_manager_notifier_destroy;
421 wl_signal_add(&ec->destroy_signal, &text_input_manager->destroy_listener);
425 input_method_context_destroy(struct wl_client *client,
426 struct wl_resource *resource)
428 wl_resource_destroy(resource);
432 input_method_context_commit_string(struct wl_client *client,
433 struct wl_resource *resource,
437 struct input_method_context *context =
438 wl_resource_get_user_data(resource);
440 wl_text_input_send_commit_string(context->model->resource, serial, text);
444 input_method_context_preedit_string(struct wl_client *client,
445 struct wl_resource *resource,
450 struct input_method_context *context =
451 wl_resource_get_user_data(resource);
453 wl_text_input_send_preedit_string(context->model->resource, serial, text, commit);
457 input_method_context_preedit_styling(struct wl_client *client,
458 struct wl_resource *resource,
463 struct input_method_context *context =
464 wl_resource_get_user_data(resource);
466 wl_text_input_send_preedit_styling(context->model->resource, index, length, style);
470 input_method_context_preedit_cursor(struct wl_client *client,
471 struct wl_resource *resource,
474 struct input_method_context *context =
475 wl_resource_get_user_data(resource);
477 wl_text_input_send_preedit_cursor(context->model->resource, cursor);
481 input_method_context_delete_surrounding_text(struct wl_client *client,
482 struct wl_resource *resource,
486 struct input_method_context *context =
487 wl_resource_get_user_data(resource);
489 wl_text_input_send_delete_surrounding_text(context->model->resource, index, length);
493 input_method_context_cursor_position(struct wl_client *client,
494 struct wl_resource *resource,
498 struct input_method_context *context =
499 wl_resource_get_user_data(resource);
501 wl_text_input_send_cursor_position(context->model->resource, index, anchor);
505 input_method_context_modifiers_map(struct wl_client *client,
506 struct wl_resource *resource,
507 struct wl_array *map)
509 struct input_method_context *context =
510 wl_resource_get_user_data(resource);
512 wl_text_input_send_modifiers_map(context->model->resource, map);
516 input_method_context_keysym(struct wl_client *client,
517 struct wl_resource *resource,
524 struct input_method_context *context =
525 wl_resource_get_user_data(resource);
527 wl_text_input_send_keysym(context->model->resource, serial, time,
528 sym, state, modifiers);
532 unbind_keyboard(struct wl_resource *resource)
534 struct input_method_context *context =
535 wl_resource_get_user_data(resource);
537 input_method_context_end_keyboard_grab(context);
538 context->keyboard = NULL;
542 input_method_context_grab_key(struct weston_keyboard_grab *grab,
543 uint32_t time, uint32_t key, uint32_t state_w)
545 struct weston_keyboard *keyboard = grab->keyboard;
546 struct wl_display *display;
549 if (!keyboard->input_method_resource)
552 display = wl_client_get_display(wl_resource_get_client(keyboard->input_method_resource));
553 serial = wl_display_next_serial(display);
554 wl_keyboard_send_key(keyboard->input_method_resource,
555 serial, time, key, state_w);
559 input_method_context_grab_modifier(struct weston_keyboard_grab *grab, uint32_t serial,
560 uint32_t mods_depressed, uint32_t mods_latched,
561 uint32_t mods_locked, uint32_t group)
563 struct weston_keyboard *keyboard = grab->keyboard;
565 if (!keyboard->input_method_resource)
568 wl_keyboard_send_modifiers(keyboard->input_method_resource,
569 serial, mods_depressed, mods_latched,
574 input_method_context_grab_cancel(struct weston_keyboard_grab *grab)
576 weston_keyboard_end_grab(grab->keyboard);
579 static const struct weston_keyboard_grab_interface input_method_context_grab = {
580 input_method_context_grab_key,
581 input_method_context_grab_modifier,
582 input_method_context_grab_cancel,
586 input_method_context_grab_keyboard(struct wl_client *client,
587 struct wl_resource *resource,
590 struct input_method_context *context = wl_resource_get_user_data(resource);
591 struct wl_resource *cr;
592 struct weston_seat *seat = context->input_method->seat;
593 struct weston_keyboard *keyboard = seat->keyboard;
595 cr = wl_resource_create(client, &wl_keyboard_interface, 1, id);
596 wl_resource_set_implementation(cr, NULL, context, unbind_keyboard);
598 context->keyboard = cr;
600 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
601 keyboard->xkb_info->keymap_fd,
602 keyboard->xkb_info->keymap_size);
604 if (keyboard->grab != &keyboard->default_grab) {
605 weston_keyboard_end_grab(keyboard);
607 weston_keyboard_start_grab(keyboard, &keyboard->input_method_grab);
608 keyboard->input_method_resource = cr;
612 input_method_context_key(struct wl_client *client,
613 struct wl_resource *resource,
619 struct input_method_context *context = wl_resource_get_user_data(resource);
620 struct weston_seat *seat = context->input_method->seat;
621 struct weston_keyboard *keyboard = seat->keyboard;
622 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
624 default_grab->interface->key(default_grab, time, key, state_w);
628 input_method_context_modifiers(struct wl_client *client,
629 struct wl_resource *resource,
631 uint32_t mods_depressed,
632 uint32_t mods_latched,
633 uint32_t mods_locked,
636 struct input_method_context *context = wl_resource_get_user_data(resource);
638 struct weston_seat *seat = context->input_method->seat;
639 struct weston_keyboard *keyboard = seat->keyboard;
640 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
642 default_grab->interface->modifiers(default_grab,
643 serial, mods_depressed,
644 mods_latched, mods_locked,
649 input_method_context_language(struct wl_client *client,
650 struct wl_resource *resource,
652 const char *language)
654 struct input_method_context *context = wl_resource_get_user_data(resource);
656 wl_text_input_send_language(context->model->resource, serial, language);
660 input_method_context_text_direction(struct wl_client *client,
661 struct wl_resource *resource,
665 struct input_method_context *context = wl_resource_get_user_data(resource);
667 wl_text_input_send_text_direction(context->model->resource, serial, direction);
671 static const struct wl_input_method_context_interface input_method_context_implementation = {
672 input_method_context_destroy,
673 input_method_context_commit_string,
674 input_method_context_preedit_string,
675 input_method_context_preedit_styling,
676 input_method_context_preedit_cursor,
677 input_method_context_delete_surrounding_text,
678 input_method_context_cursor_position,
679 input_method_context_modifiers_map,
680 input_method_context_keysym,
681 input_method_context_grab_keyboard,
682 input_method_context_key,
683 input_method_context_modifiers,
684 input_method_context_language,
685 input_method_context_text_direction
689 destroy_input_method_context(struct wl_resource *resource)
691 struct input_method_context *context = wl_resource_get_user_data(resource);
693 if (context->keyboard) {
694 wl_resource_destroy(context->keyboard);
701 input_method_context_create(struct text_input *model,
702 struct input_method *input_method)
704 struct input_method_context *context;
705 struct wl_resource *binding;
707 if (!input_method->input_method_binding)
710 context = calloc(1, sizeof *context);
714 binding = input_method->input_method_binding;
716 wl_resource_create(wl_resource_get_client(binding),
717 &wl_input_method_context_interface, 1, 0);
718 wl_resource_set_implementation(context->resource,
719 &input_method_context_implementation,
720 context, destroy_input_method_context);
722 context->model = model;
723 context->input_method = input_method;
724 input_method->context = context;
727 wl_input_method_send_activate(binding, context->resource);
731 input_method_context_end_keyboard_grab(struct input_method_context *context)
733 struct weston_keyboard_grab *grab =
734 &context->input_method->seat->keyboard->input_method_grab;
735 struct weston_keyboard *keyboard = grab->keyboard;
740 if (grab->keyboard->grab == grab)
741 weston_keyboard_end_grab(grab->keyboard);
743 keyboard->input_method_resource = NULL;
747 unbind_input_method(struct wl_resource *resource)
749 struct input_method *input_method = wl_resource_get_user_data(resource);
750 struct text_backend *text_backend = input_method->text_backend;
752 input_method->input_method_binding = NULL;
753 input_method->context = NULL;
755 text_backend->input_method.binding = NULL;
759 bind_input_method(struct wl_client *client,
764 struct input_method *input_method = data;
765 struct text_backend *text_backend = input_method->text_backend;
766 struct wl_resource *resource;
769 wl_resource_create(client, &wl_input_method_interface, 1, id);
771 if (input_method->input_method_binding != NULL) {
772 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
773 "interface object already bound");
774 wl_resource_destroy(resource);
778 if (text_backend->input_method.client != client) {
779 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
780 "permission to bind input_method denied");
781 wl_resource_destroy(resource);
785 wl_resource_set_implementation(resource, NULL, input_method,
786 unbind_input_method);
787 input_method->input_method_binding = resource;
789 text_backend->input_method.binding = resource;
793 input_method_notifier_destroy(struct wl_listener *listener, void *data)
795 struct input_method *input_method =
796 container_of(listener, struct input_method, destroy_listener);
798 if (input_method->model)
799 deactivate_text_input(input_method->model, input_method);
801 wl_global_destroy(input_method->input_method_global);
802 wl_list_remove(&input_method->destroy_listener.link);
808 handle_keyboard_focus(struct wl_listener *listener, void *data)
810 struct weston_keyboard *keyboard = data;
811 struct input_method *input_method =
812 container_of(listener, struct input_method, keyboard_focus_listener);
813 struct weston_surface *surface = keyboard->focus;
815 if (!input_method->model)
818 if (!surface || input_method->model->surface != surface)
819 deactivate_text_input(input_method->model,
824 input_method_init_seat(struct weston_seat *seat)
826 if (seat->input_method->focus_listener_initialized)
829 if (seat->keyboard) {
830 seat->input_method->keyboard_focus_listener.notify = handle_keyboard_focus;
831 wl_signal_add(&seat->keyboard->focus_signal, &seat->input_method->keyboard_focus_listener);
832 seat->keyboard->input_method_grab.interface = &input_method_context_grab;
835 seat->input_method->focus_listener_initialized = 1;
838 static void launch_input_method(struct text_backend *text_backend);
841 handle_input_method_sigchld(struct weston_process *process, int status)
844 struct text_backend *text_backend =
845 container_of(process, struct text_backend, input_method.process);
847 text_backend->input_method.process.pid = 0;
848 text_backend->input_method.client = NULL;
850 /* if input_method dies more than 5 times in 10 seconds, give up */
851 time = weston_compositor_get_time();
852 if (time - text_backend->input_method.deathstamp > 10000) {
853 text_backend->input_method.deathstamp = time;
854 text_backend->input_method.deathcount = 0;
857 text_backend->input_method.deathcount++;
858 if (text_backend->input_method.deathcount > 5) {
859 weston_log("input_method died, giving up.\n");
863 weston_log("input_method died, respawning...\n");
864 launch_input_method(text_backend);
868 launch_input_method(struct text_backend *text_backend)
870 if (text_backend->input_method.binding)
873 if (!text_backend->input_method.path)
876 if (text_backend->input_method.process.pid != 0)
879 text_backend->input_method.client = weston_client_launch(text_backend->compositor,
880 &text_backend->input_method.process,
881 text_backend->input_method.path,
882 handle_input_method_sigchld);
884 if (!text_backend->input_method.client)
885 weston_log("not able to start %s\n", text_backend->input_method.path);
889 handle_seat_created(struct wl_listener *listener,
892 struct weston_seat *seat = data;
893 struct text_backend *text_backend =
894 container_of(listener, struct text_backend,
895 seat_created_listener);
896 struct input_method *input_method;
897 struct weston_compositor *ec = seat->compositor;
899 input_method = calloc(1, sizeof *input_method);
901 input_method->seat = seat;
902 input_method->model = NULL;
903 input_method->focus_listener_initialized = 0;
904 input_method->context = NULL;
905 input_method->text_backend = text_backend;
907 input_method->input_method_global =
908 wl_global_create(ec->wl_display, &wl_input_method_interface, 1,
909 input_method, bind_input_method);
911 input_method->destroy_listener.notify = input_method_notifier_destroy;
912 wl_signal_add(&seat->destroy_signal, &input_method->destroy_listener);
914 seat->input_method = input_method;
916 launch_input_method(text_backend);
920 text_backend_configuration(struct text_backend *text_backend)
922 struct weston_config_section *section;
924 section = weston_config_get_section(text_backend->compositor->config,
925 "input-method", NULL, NULL);
926 weston_config_section_get_string(section, "path",
927 &text_backend->input_method.path,
928 LIBEXECDIR "/weston-keyboard");
932 text_backend_notifier_destroy(struct wl_listener *listener, void *data)
934 struct text_backend *text_backend =
935 container_of(listener, struct text_backend, destroy_listener);
937 if (text_backend->input_method.client)
938 wl_client_destroy(text_backend->input_method.client);
940 free(text_backend->input_method.path);
947 text_backend_init(struct weston_compositor *ec)
949 struct text_backend *text_backend;
951 text_backend = calloc(1, sizeof(*text_backend));
953 text_backend->compositor = ec;
955 text_backend->seat_created_listener.notify = handle_seat_created;
956 wl_signal_add(&ec->seat_created_signal,
957 &text_backend->seat_created_listener);
959 text_backend->destroy_listener.notify = text_backend_notifier_destroy;
960 wl_signal_add(&ec->destroy_signal, &text_backend->destroy_listener);
962 text_backend_configuration(text_backend);
964 text_input_manager_create(ec);