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.
27 #include "compositor.h"
28 #include "text-server-protocol.h"
29 #include "input-method-server-protocol.h"
32 struct input_method_context;
36 struct wl_resource resource;
38 struct weston_compositor *ec;
40 struct wl_list input_methods;
42 struct wl_surface *surface;
44 pixman_box32_t cursor_rectangle;
46 uint32_t input_panel_visible;
49 struct text_input_manager {
50 struct wl_global *text_input_manager_global;
51 struct wl_listener destroy_listener;
53 struct weston_compositor *ec;
57 struct wl_resource *input_method_binding;
58 struct wl_global *input_method_global;
59 struct wl_listener destroy_listener;
61 struct weston_seat *seat;
62 struct text_input *model;
66 struct wl_listener keyboard_focus_listener;
68 int focus_listener_initialized;
70 struct input_method_context *context;
72 struct text_backend *text_backend;
75 struct input_method_context {
76 struct wl_resource resource;
78 struct text_input *model;
79 struct input_method *input_method;
83 struct wl_resource *keyboard;
87 struct weston_compositor *compositor;
91 struct wl_resource *binding;
92 struct weston_process process;
93 struct wl_client *client;
96 struct wl_listener seat_created_listener;
97 struct wl_listener destroy_listener;
100 static void input_method_context_create(struct text_input *model,
101 struct input_method *input_method);
102 static void input_method_context_end_keyboard_grab(struct input_method_context *context);
104 static void input_method_init_seat(struct weston_seat *seat);
107 deactivate_text_input(struct text_input *text_input,
108 struct input_method *input_method)
110 struct weston_compositor *ec = text_input->ec;
112 if (input_method->model == text_input) {
113 if (input_method->context && input_method->input_method_binding) {
114 input_method_context_end_keyboard_grab(input_method->context);
115 wl_input_method_send_deactivate(input_method->input_method_binding,
116 &input_method->context->resource);
119 wl_list_remove(&input_method->link);
120 input_method->model = NULL;
121 input_method->context = NULL;
122 wl_signal_emit(&ec->hide_input_panel_signal, ec);
123 wl_text_input_send_leave(&text_input->resource);
128 destroy_text_input(struct wl_resource *resource)
130 struct text_input *text_input =
131 container_of(resource, struct text_input, resource);
132 struct input_method *input_method, *next;
134 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link)
135 deactivate_text_input(text_input, input_method);
141 text_input_set_surrounding_text(struct wl_client *client,
142 struct wl_resource *resource,
147 struct text_input *text_input = resource->data;
148 struct input_method *input_method, *next;
150 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
151 if (!input_method->context)
153 wl_input_method_context_send_surrounding_text(&input_method->context->resource,
161 text_input_activate(struct wl_client *client,
162 struct wl_resource *resource,
163 struct wl_resource *seat,
164 struct wl_resource *surface)
166 struct text_input *text_input = resource->data;
167 struct weston_seat *weston_seat = seat->data;
168 struct input_method *input_method = weston_seat->input_method;
169 struct text_input *old = weston_seat->input_method->model;
170 struct weston_compositor *ec = text_input->ec;
172 if (old == text_input)
176 deactivate_text_input(old,
177 weston_seat->input_method);
180 input_method->model = text_input;
181 wl_list_insert(&text_input->input_methods, &input_method->link);
182 input_method_init_seat(weston_seat);
184 text_input->surface = surface->data;
186 input_method_context_create(text_input, input_method);
188 if (text_input->input_panel_visible) {
189 wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
190 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
193 wl_text_input_send_enter(&text_input->resource, &text_input->surface->resource);
197 text_input_deactivate(struct wl_client *client,
198 struct wl_resource *resource,
199 struct wl_resource *seat)
201 struct text_input *text_input = resource->data;
202 struct weston_seat *weston_seat = seat->data;
204 deactivate_text_input(text_input,
205 weston_seat->input_method);
209 text_input_reset(struct wl_client *client,
210 struct wl_resource *resource)
212 struct text_input *text_input = resource->data;
213 struct input_method *input_method, *next;
215 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
216 if (!input_method->context)
218 wl_input_method_context_send_reset(&input_method->context->resource);
223 text_input_set_cursor_rectangle(struct wl_client *client,
224 struct wl_resource *resource,
230 struct text_input *text_input = resource->data;
231 struct weston_compositor *ec = text_input->ec;
233 text_input->cursor_rectangle.x1 = x;
234 text_input->cursor_rectangle.y1 = y;
235 text_input->cursor_rectangle.x2 = x + width;
236 text_input->cursor_rectangle.y2 = y + height;
238 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
242 text_input_set_content_type(struct wl_client *client,
243 struct wl_resource *resource,
247 struct text_input *text_input = resource->data;
248 struct input_method *input_method, *next;
250 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
251 if (!input_method->context)
253 wl_input_method_context_send_content_type(&input_method->context->resource, hint, purpose);
258 text_input_invoke_action(struct wl_client *client,
259 struct wl_resource *resource,
263 struct text_input *text_input = resource->data;
264 struct input_method *input_method, *next;
266 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
267 if (!input_method->context)
269 wl_input_method_context_send_invoke_action(&input_method->context->resource, button, index);
274 text_input_commit_state(struct wl_client *client,
275 struct wl_resource *resource,
278 struct text_input *text_input = resource->data;
279 struct input_method *input_method, *next;
281 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
282 if (!input_method->context)
284 wl_input_method_context_send_commit_state(&input_method->context->resource, serial);
289 text_input_show_input_panel(struct wl_client *client,
290 struct wl_resource *resource)
292 struct text_input *text_input = resource->data;
293 struct weston_compositor *ec = text_input->ec;
295 text_input->input_panel_visible = 1;
297 if (!wl_list_empty(&text_input->input_methods)) {
298 wl_signal_emit(&ec->show_input_panel_signal, text_input->surface);
299 wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle);
304 text_input_hide_input_panel(struct wl_client *client,
305 struct wl_resource *resource)
307 struct text_input *text_input = resource->data;
308 struct weston_compositor *ec = text_input->ec;
310 text_input->input_panel_visible = 0;
312 if (!wl_list_empty(&text_input->input_methods))
313 wl_signal_emit(&ec->hide_input_panel_signal, ec);
317 text_input_set_preferred_language(struct wl_client *client,
318 struct wl_resource *resource,
319 const char *language)
321 struct text_input *text_input = resource->data;
322 struct input_method *input_method, *next;
324 wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) {
325 if (!input_method->context)
327 wl_input_method_context_send_preferred_language(&input_method->context->resource,
332 static const struct wl_text_input_interface text_input_implementation = {
334 text_input_deactivate,
335 text_input_show_input_panel,
336 text_input_hide_input_panel,
338 text_input_set_surrounding_text,
339 text_input_set_content_type,
340 text_input_set_cursor_rectangle,
341 text_input_set_preferred_language,
342 text_input_commit_state,
343 text_input_invoke_action
346 static void text_input_manager_create_text_input(struct wl_client *client,
347 struct wl_resource *resource,
350 struct text_input_manager *text_input_manager = resource->data;
351 struct text_input *text_input;
353 text_input = calloc(1, sizeof *text_input);
355 text_input->resource.object.id = id;
356 text_input->resource.object.interface = &wl_text_input_interface;
357 text_input->resource.object.implementation =
358 (void (**)(void)) &text_input_implementation;
360 text_input->resource.data = text_input;
361 text_input->resource.destroy = destroy_text_input;
363 text_input->ec = text_input_manager->ec;
365 wl_list_init(&text_input->input_methods);
367 wl_client_add_resource(client, &text_input->resource);
370 static const struct wl_text_input_manager_interface text_input_manager_implementation = {
371 text_input_manager_create_text_input
375 bind_text_input_manager(struct wl_client *client,
380 struct text_input_manager *text_input_manager = data;
382 /* No checking for duplicate binding necessary.
383 * No events have to be sent, so we don't need the return value. */
384 wl_client_add_object(client, &wl_text_input_manager_interface,
385 &text_input_manager_implementation,
386 id, text_input_manager);
390 text_input_manager_notifier_destroy(struct wl_listener *listener, void *data)
392 struct text_input_manager *text_input_manager =
393 container_of(listener, struct text_input_manager, destroy_listener);
395 wl_display_remove_global(text_input_manager->ec->wl_display,
396 text_input_manager->text_input_manager_global);
398 free(text_input_manager);
402 text_input_manager_create(struct weston_compositor *ec)
404 struct text_input_manager *text_input_manager;
406 text_input_manager = calloc(1, sizeof *text_input_manager);
408 text_input_manager->ec = ec;
410 text_input_manager->text_input_manager_global =
411 wl_display_add_global(ec->wl_display,
412 &wl_text_input_manager_interface,
413 text_input_manager, bind_text_input_manager);
415 text_input_manager->destroy_listener.notify = text_input_manager_notifier_destroy;
416 wl_signal_add(&ec->destroy_signal, &text_input_manager->destroy_listener);
420 input_method_context_destroy(struct wl_client *client,
421 struct wl_resource *resource)
423 wl_resource_destroy(resource);
427 input_method_context_commit_string(struct wl_client *client,
428 struct wl_resource *resource,
432 struct input_method_context *context = resource->data;
434 wl_text_input_send_commit_string(&context->model->resource, serial, text);
438 input_method_context_preedit_string(struct wl_client *client,
439 struct wl_resource *resource,
444 struct input_method_context *context = resource->data;
446 wl_text_input_send_preedit_string(&context->model->resource, serial, text, commit);
450 input_method_context_preedit_styling(struct wl_client *client,
451 struct wl_resource *resource,
456 struct input_method_context *context = resource->data;
458 wl_text_input_send_preedit_styling(&context->model->resource, index, length, style);
462 input_method_context_preedit_cursor(struct wl_client *client,
463 struct wl_resource *resource,
466 struct input_method_context *context = resource->data;
468 wl_text_input_send_preedit_cursor(&context->model->resource, cursor);
472 input_method_context_delete_surrounding_text(struct wl_client *client,
473 struct wl_resource *resource,
477 struct input_method_context *context = resource->data;
479 wl_text_input_send_delete_surrounding_text(&context->model->resource, index, length);
483 input_method_context_cursor_position(struct wl_client *client,
484 struct wl_resource *resource,
488 struct input_method_context *context = resource->data;
490 wl_text_input_send_cursor_position(&context->model->resource, index, anchor);
494 input_method_context_modifiers_map(struct wl_client *client,
495 struct wl_resource *resource,
496 struct wl_array *map)
498 struct input_method_context *context = resource->data;
500 wl_text_input_send_modifiers_map(&context->model->resource, map);
504 input_method_context_keysym(struct wl_client *client,
505 struct wl_resource *resource,
512 struct input_method_context *context = resource->data;
514 wl_text_input_send_keysym(&context->model->resource, serial, time,
515 sym, state, modifiers);
519 unbind_keyboard(struct wl_resource *resource)
521 struct input_method_context *context = resource->data;
523 input_method_context_end_keyboard_grab(context);
524 context->keyboard = NULL;
530 input_method_context_grab_key(struct weston_keyboard_grab *grab,
531 uint32_t time, uint32_t key, uint32_t state_w)
533 struct weston_keyboard *keyboard = grab->keyboard;
534 struct wl_display *display;
537 if (!keyboard->input_method_resource)
540 display = wl_client_get_display(keyboard->input_method_resource->client);
541 serial = wl_display_next_serial(display);
542 wl_keyboard_send_key(keyboard->input_method_resource,
543 serial, time, key, state_w);
547 input_method_context_grab_modifier(struct weston_keyboard_grab *grab, uint32_t serial,
548 uint32_t mods_depressed, uint32_t mods_latched,
549 uint32_t mods_locked, uint32_t group)
551 struct weston_keyboard *keyboard = grab->keyboard;
553 if (!keyboard->input_method_resource)
556 wl_keyboard_send_modifiers(keyboard->input_method_resource,
557 serial, mods_depressed, mods_latched,
561 static const struct weston_keyboard_grab_interface input_method_context_grab = {
562 input_method_context_grab_key,
563 input_method_context_grab_modifier,
567 input_method_context_grab_keyboard(struct wl_client *client,
568 struct wl_resource *resource,
571 struct input_method_context *context = resource->data;
572 struct wl_resource *cr;
573 struct weston_seat *seat = context->input_method->seat;
574 struct weston_keyboard *keyboard = &seat->keyboard;
576 cr = wl_client_add_object(client, &wl_keyboard_interface,
578 cr->destroy = unbind_keyboard;
580 context->keyboard = cr;
582 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
583 seat->xkb_info.keymap_fd,
584 seat->xkb_info.keymap_size);
586 if (keyboard->grab != &keyboard->default_grab) {
587 weston_keyboard_end_grab(keyboard);
589 weston_keyboard_start_grab(keyboard, &keyboard->input_method_grab);
590 keyboard->input_method_resource = cr;
594 input_method_context_key(struct wl_client *client,
595 struct wl_resource *resource,
601 struct input_method_context *context = resource->data;
602 struct weston_seat *seat = context->input_method->seat;
603 struct weston_keyboard *keyboard = seat->seat.keyboard;
604 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
606 default_grab->interface->key(default_grab, time, key, state_w);
610 input_method_context_modifiers(struct wl_client *client,
611 struct wl_resource *resource,
613 uint32_t mods_depressed,
614 uint32_t mods_latched,
615 uint32_t mods_locked,
618 struct input_method_context *context = resource->data;
620 struct weston_seat *seat = context->input_method->seat;
621 struct weston_keyboard *keyboard = seat->seat.keyboard;
622 struct weston_keyboard_grab *default_grab = &keyboard->default_grab;
624 default_grab->interface->modifiers(default_grab,
625 serial, mods_depressed,
626 mods_latched, mods_locked,
631 input_method_context_language(struct wl_client *client,
632 struct wl_resource *resource,
634 const char *language)
636 struct input_method_context *context = resource->data;
638 wl_text_input_send_language(&context->model->resource, serial, language);
642 input_method_context_text_direction(struct wl_client *client,
643 struct wl_resource *resource,
647 struct input_method_context *context = resource->data;
649 wl_text_input_send_text_direction(&context->model->resource, serial, direction);
653 static const struct wl_input_method_context_interface input_method_context_implementation = {
654 input_method_context_destroy,
655 input_method_context_commit_string,
656 input_method_context_preedit_string,
657 input_method_context_preedit_styling,
658 input_method_context_preedit_cursor,
659 input_method_context_delete_surrounding_text,
660 input_method_context_cursor_position,
661 input_method_context_modifiers_map,
662 input_method_context_keysym,
663 input_method_context_grab_keyboard,
664 input_method_context_key,
665 input_method_context_modifiers,
666 input_method_context_language,
667 input_method_context_text_direction
671 destroy_input_method_context(struct wl_resource *resource)
673 struct input_method_context *context = resource->data;
675 if (context->keyboard) {
676 wl_resource_destroy(context->keyboard);
683 input_method_context_create(struct text_input *model,
684 struct input_method *input_method)
686 struct input_method_context *context;
688 if (!input_method->input_method_binding)
691 context = calloc(1, sizeof *context);
695 context->resource.destroy = destroy_input_method_context;
696 context->resource.object.id = 0;
697 context->resource.object.interface = &wl_input_method_context_interface;
698 context->resource.object.implementation =
699 (void (**)(void)) &input_method_context_implementation;
700 context->resource.data = context;
701 wl_signal_init(&context->resource.destroy_signal);
703 context->model = model;
704 context->input_method = input_method;
705 input_method->context = context;
707 wl_client_add_resource(input_method->input_method_binding->client, &context->resource);
709 wl_input_method_send_activate(input_method->input_method_binding, &context->resource);
713 input_method_context_end_keyboard_grab(struct input_method_context *context)
715 struct weston_keyboard_grab *grab = &context->input_method->seat->keyboard.input_method_grab;
716 struct weston_keyboard *keyboard = grab->keyboard;
721 if (grab->keyboard->grab == grab)
722 weston_keyboard_end_grab(grab->keyboard);
724 keyboard->input_method_resource = NULL;
728 unbind_input_method(struct wl_resource *resource)
730 struct input_method *input_method = resource->data;
731 struct text_backend *text_backend = input_method->text_backend;
733 input_method->input_method_binding = NULL;
734 input_method->context = NULL;
736 text_backend->input_method.binding = NULL;
742 bind_input_method(struct wl_client *client,
747 struct input_method *input_method = data;
748 struct text_backend *text_backend = input_method->text_backend;
749 struct wl_resource *resource;
751 resource = wl_client_add_object(client, &wl_input_method_interface,
755 if (input_method->input_method_binding != NULL) {
756 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
757 "interface object already bound");
758 wl_resource_destroy(resource);
762 if (text_backend->input_method.client != client) {
763 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
764 "permission to bind desktop_shell denied");
765 wl_resource_destroy(resource);
769 resource->destroy = unbind_input_method;
770 input_method->input_method_binding = resource;
772 text_backend->input_method.binding = resource;
776 input_method_notifier_destroy(struct wl_listener *listener, void *data)
778 struct input_method *input_method =
779 container_of(listener, struct input_method, destroy_listener);
781 if (input_method->model)
782 deactivate_text_input(input_method->model, input_method);
784 wl_display_remove_global(input_method->seat->compositor->wl_display,
785 input_method->input_method_global);
791 handle_keyboard_focus(struct wl_listener *listener, void *data)
793 struct weston_keyboard *keyboard = data;
794 struct input_method *input_method =
795 container_of(listener, struct input_method, keyboard_focus_listener);
796 struct wl_surface *surface = keyboard->focus;
798 if (!input_method->model)
801 if (!surface || input_method->model->surface != surface)
802 deactivate_text_input(input_method->model,
807 input_method_init_seat(struct weston_seat *seat)
809 if (seat->input_method->focus_listener_initialized)
812 if (seat->has_keyboard) {
813 seat->input_method->keyboard_focus_listener.notify = handle_keyboard_focus;
814 wl_signal_add(&seat->seat.keyboard->focus_signal, &seat->input_method->keyboard_focus_listener);
815 seat->keyboard.input_method_grab.interface = &input_method_context_grab;
818 seat->input_method->focus_listener_initialized = 1;
822 handle_input_method_sigchld(struct weston_process *process, int status)
824 struct text_backend *text_backend =
825 container_of(process, struct text_backend, input_method.process);
827 text_backend->input_method.process.pid = 0;
828 text_backend->input_method.client = NULL;
832 launch_input_method(struct text_backend *text_backend)
834 if (text_backend->input_method.binding)
837 if (!text_backend->input_method.path)
840 if (text_backend->input_method.process.pid != 0)
843 text_backend->input_method.client = weston_client_launch(text_backend->compositor,
844 &text_backend->input_method.process,
845 text_backend->input_method.path,
846 handle_input_method_sigchld);
848 if (!text_backend->input_method.client)
849 weston_log("not able to start %s\n", text_backend->input_method.path);
853 handle_seat_created(struct wl_listener *listener,
856 struct weston_seat *seat = data;
857 struct text_backend *text_backend =
858 container_of(listener, struct text_backend,
859 seat_created_listener);
860 struct input_method *input_method;
861 struct weston_compositor *ec = seat->compositor;
863 input_method = calloc(1, sizeof *input_method);
865 input_method->seat = seat;
866 input_method->model = NULL;
867 input_method->focus_listener_initialized = 0;
868 input_method->context = NULL;
869 input_method->text_backend = text_backend;
871 input_method->input_method_global =
872 wl_display_add_global(ec->wl_display,
873 &wl_input_method_interface,
874 input_method, bind_input_method);
876 input_method->destroy_listener.notify = input_method_notifier_destroy;
877 wl_signal_add(&seat->seat.destroy_signal, &input_method->destroy_listener);
879 seat->input_method = input_method;
881 launch_input_method(text_backend);
885 text_backend_configuration(struct text_backend *text_backend)
890 struct config_key input_method_keys[] = {
891 { "path", CONFIG_KEY_STRING, &path }
894 struct config_section cs[] = {
895 { "input-method", input_method_keys, ARRAY_LENGTH(input_method_keys), NULL }
898 config_file = config_file_path("weston.ini");
899 parse_config_file(config_file, cs, ARRAY_LENGTH(cs), text_backend);
903 text_backend->input_method.path = path;
905 text_backend->input_method.path = strdup(LIBEXECDIR "/weston-keyboard");
909 text_backend_notifier_destroy(struct wl_listener *listener, void *data)
911 struct text_backend *text_backend =
912 container_of(listener, struct text_backend, destroy_listener);
914 if (text_backend->input_method.client)
915 wl_client_destroy(text_backend->input_method.client);
917 free(text_backend->input_method.path);
924 text_backend_init(struct weston_compositor *ec)
926 struct text_backend *text_backend;
928 text_backend = calloc(1, sizeof(*text_backend));
930 text_backend->compositor = ec;
932 text_backend->seat_created_listener.notify = handle_seat_created;
933 wl_signal_add(&ec->seat_created_signal,
934 &text_backend->seat_created_listener);
936 text_backend->destroy_listener.notify = text_backend_notifier_destroy;
937 wl_signal_add(&ec->destroy_signal, &text_backend->destroy_listener);
939 text_backend_configuration(text_backend);
941 text_input_manager_create(ec);