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 uint32_t input_panel_visible;
47 struct text_model_factory {
48 struct wl_global *text_model_factory_global;
49 struct wl_listener destroy_listener;
51 struct weston_compositor *ec;
55 struct wl_resource *input_method_binding;
56 struct wl_global *input_method_global;
57 struct wl_listener destroy_listener;
59 struct weston_seat *seat;
60 struct text_model *model;
64 struct wl_listener keyboard_focus_listener;
66 int focus_listener_initialized;
68 struct input_method_context *context;
70 struct text_backend *text_backend;
73 struct input_method_context {
74 struct wl_resource resource;
76 struct text_model *model;
77 struct input_method *input_method;
81 struct wl_resource *keyboard;
85 struct weston_compositor *compositor;
89 struct wl_resource *binding;
90 struct weston_process process;
91 struct wl_client *client;
94 struct wl_listener seat_created_listener;
95 struct wl_listener destroy_listener;
98 static void input_method_context_create(struct text_model *model,
99 struct input_method *input_method,
101 static void input_method_context_end_keyboard_grab(struct input_method_context *context);
103 static void input_method_init_seat(struct weston_seat *seat);
106 deactivate_text_model(struct text_model *text_model,
107 struct input_method *input_method)
109 struct weston_compositor *ec = text_model->ec;
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);
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);
127 destroy_text_model(struct wl_resource *resource)
129 struct text_model *text_model =
130 container_of(resource, struct text_model, resource);
131 struct input_method *input_method, *next;
133 wl_list_for_each_safe(input_method, next, &text_model->input_methods, link)
134 deactivate_text_model(text_model, input_method);
140 text_model_set_surrounding_text(struct wl_client *client,
141 struct wl_resource *resource,
146 struct text_model *text_model = resource->data;
147 struct input_method *input_method, *next;
149 wl_list_for_each_safe(input_method, next, &text_model->input_methods, link) {
150 if (!input_method->context)
152 input_method_context_send_surrounding_text(&input_method->context->resource,
160 text_model_activate(struct wl_client *client,
161 struct wl_resource *resource,
163 struct wl_resource *seat,
164 struct wl_resource *surface)
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;
172 if (old == text_model)
176 deactivate_text_model(old,
177 weston_seat->input_method);
180 input_method->model = text_model;
181 wl_list_insert(&text_model->input_methods, &input_method->link);
182 input_method_init_seat(weston_seat);
184 text_model->surface = surface->data;
186 input_method_context_create(text_model, input_method, serial);
188 if (text_model->input_panel_visible)
189 wl_signal_emit(&ec->show_input_panel_signal, ec);
191 text_model_send_enter(&text_model->resource, &text_model->surface->resource);
195 text_model_deactivate(struct wl_client *client,
196 struct wl_resource *resource,
197 struct wl_resource *seat)
199 struct text_model *text_model = resource->data;
200 struct weston_seat *weston_seat = seat->data;
202 deactivate_text_model(text_model,
203 weston_seat->input_method);
207 text_model_reset(struct wl_client *client,
208 struct wl_resource *resource,
211 struct text_model *text_model = resource->data;
212 struct input_method *input_method, *next;
214 wl_list_for_each_safe(input_method, next, &text_model->input_methods, link) {
215 if (!input_method->context)
217 input_method_context_send_reset(&input_method->context->resource, serial);
222 text_model_set_micro_focus(struct wl_client *client,
223 struct wl_resource *resource,
232 text_model_set_content_type(struct wl_client *client,
233 struct wl_resource *resource,
237 struct text_model *text_model = resource->data;
238 struct input_method *input_method, *next;
240 wl_list_for_each_safe(input_method, next, &text_model->input_methods, link) {
241 if (!input_method->context)
243 input_method_context_send_content_type(&input_method->context->resource, hint, purpose);
248 text_model_invoke_action(struct wl_client *client,
249 struct wl_resource *resource,
253 struct text_model *text_model = resource->data;
254 struct input_method *input_method, *next;
256 wl_list_for_each_safe(input_method, next, &text_model->input_methods, link) {
257 if (!input_method->context)
259 input_method_context_send_invoke_action(&input_method->context->resource, button, index);
264 text_model_commit(struct wl_client *client,
265 struct wl_resource *resource)
267 struct text_model *text_model = resource->data;
268 struct input_method *input_method, *next;
270 wl_list_for_each_safe(input_method, next, &text_model->input_methods, link) {
271 if (!input_method->context)
273 input_method_context_send_commit(&input_method->context->resource);
278 text_model_show_input_panel(struct wl_client *client,
279 struct wl_resource *resource)
281 struct text_model *text_model = resource->data;
282 struct weston_compositor *ec = text_model->ec;
284 text_model->input_panel_visible = 1;
286 if (!wl_list_empty(&text_model->input_methods))
287 wl_signal_emit(&ec->show_input_panel_signal, ec);
291 text_model_hide_input_panel(struct wl_client *client,
292 struct wl_resource *resource)
294 struct text_model *text_model = resource->data;
295 struct weston_compositor *ec = text_model->ec;
297 text_model->input_panel_visible = 0;
299 if (!wl_list_empty(&text_model->input_methods))
300 wl_signal_emit(&ec->hide_input_panel_signal, ec);
304 text_model_set_preferred_language(struct wl_client *client,
305 struct wl_resource *resource,
306 const char *language)
308 struct text_model *text_model = resource->data;
309 struct input_method *input_method, *next;
311 wl_list_for_each_safe(input_method, next, &text_model->input_methods, link) {
312 if (!input_method->context)
314 input_method_context_send_preferred_language(&input_method->context->resource,
319 static const struct text_model_interface text_model_implementation = {
320 text_model_set_surrounding_text,
322 text_model_deactivate,
324 text_model_set_micro_focus,
325 text_model_set_content_type,
326 text_model_invoke_action,
328 text_model_show_input_panel,
329 text_model_hide_input_panel,
330 text_model_set_preferred_language
333 static void text_model_factory_create_text_model(struct wl_client *client,
334 struct wl_resource *resource,
337 struct text_model_factory *text_model_factory = resource->data;
338 struct text_model *text_model;
340 text_model = calloc(1, sizeof *text_model);
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;
347 text_model->resource.data = text_model;
348 text_model->resource.destroy = destroy_text_model;
350 text_model->ec = text_model_factory->ec;
352 wl_list_init(&text_model->input_methods);
354 wl_client_add_resource(client, &text_model->resource);
357 static const struct text_model_factory_interface text_model_factory_implementation = {
358 text_model_factory_create_text_model
362 bind_text_model_factory(struct wl_client *client,
367 struct text_model_factory *text_model_factory = data;
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);
377 text_model_factory_notifier_destroy(struct wl_listener *listener, void *data)
379 struct text_model_factory *text_model_factory =
380 container_of(listener, struct text_model_factory, destroy_listener);
382 wl_display_remove_global(text_model_factory->ec->wl_display,
383 text_model_factory->text_model_factory_global);
385 free(text_model_factory);
389 text_model_factory_create(struct weston_compositor *ec)
391 struct text_model_factory *text_model_factory;
393 text_model_factory = calloc(1, sizeof *text_model_factory);
395 text_model_factory->ec = ec;
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);
402 text_model_factory->destroy_listener.notify = text_model_factory_notifier_destroy;
403 wl_signal_add(&ec->destroy_signal, &text_model_factory->destroy_listener);
407 input_method_context_destroy(struct wl_client *client,
408 struct wl_resource *resource)
410 wl_resource_destroy(resource);
414 input_method_context_commit_string(struct wl_client *client,
415 struct wl_resource *resource,
419 struct input_method_context *context = resource->data;
421 text_model_send_commit_string(&context->model->resource, serial, text);
425 input_method_context_preedit_string(struct wl_client *client,
426 struct wl_resource *resource,
431 struct input_method_context *context = resource->data;
433 text_model_send_preedit_string(&context->model->resource, serial, text, commit);
437 input_method_context_preedit_styling(struct wl_client *client,
438 struct wl_resource *resource,
444 struct input_method_context *context = resource->data;
446 text_model_send_preedit_styling(&context->model->resource, serial, index, length, style);
450 input_method_context_preedit_cursor(struct wl_client *client,
451 struct wl_resource *resource,
455 struct input_method_context *context = resource->data;
457 text_model_send_preedit_cursor(&context->model->resource, serial, cursor);
461 input_method_context_delete_surrounding_text(struct wl_client *client,
462 struct wl_resource *resource,
467 struct input_method_context *context = resource->data;
469 text_model_send_delete_surrounding_text(&context->model->resource, serial, index, length);
473 input_method_context_cursor_position(struct wl_client *client,
474 struct wl_resource *resource,
479 struct input_method_context *context = resource->data;
481 text_model_send_cursor_position(&context->model->resource, serial, index, anchor);
485 input_method_context_modifiers_map(struct wl_client *client,
486 struct wl_resource *resource,
487 struct wl_array *map)
489 struct input_method_context *context = resource->data;
491 text_model_send_modifiers_map(&context->model->resource, map);
495 input_method_context_keysym(struct wl_client *client,
496 struct wl_resource *resource,
503 struct input_method_context *context = resource->data;
505 text_model_send_keysym(&context->model->resource, serial, time,
506 sym, state, modifiers);
510 unbind_keyboard(struct wl_resource *resource)
512 struct input_method_context *context = resource->data;
514 input_method_context_end_keyboard_grab(context);
515 context->keyboard = NULL;
521 input_method_context_grab_key(struct wl_keyboard_grab *grab,
522 uint32_t time, uint32_t key, uint32_t state_w)
524 struct weston_keyboard *keyboard = (struct weston_keyboard *)grab->keyboard;
525 struct wl_display *display;
528 if (!keyboard->input_method_resource)
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);
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)
542 struct weston_keyboard *keyboard = (struct weston_keyboard *)grab->keyboard;
544 if (!keyboard->input_method_resource)
547 wl_keyboard_send_modifiers(keyboard->input_method_resource,
548 serial, mods_depressed, mods_latched,
552 static const struct wl_keyboard_grab_interface input_method_context_grab = {
553 input_method_context_grab_key,
554 input_method_context_grab_modifier,
558 input_method_context_grab_keyboard(struct wl_client *client,
559 struct wl_resource *resource,
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;
567 cr = wl_client_add_object(client, &wl_keyboard_interface,
569 cr->destroy = unbind_keyboard;
571 context->keyboard = cr;
573 wl_keyboard_send_keymap(cr, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
574 seat->xkb_info.keymap_fd,
575 seat->xkb_info.keymap_size);
577 if (keyboard->keyboard.grab != &keyboard->keyboard.default_grab) {
578 wl_keyboard_end_grab(&keyboard->keyboard);
580 wl_keyboard_start_grab(&keyboard->keyboard, &keyboard->input_method_grab);
581 keyboard->input_method_resource = cr;
585 input_method_context_key(struct wl_client *client,
586 struct wl_resource *resource,
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;
597 default_grab->interface->key(default_grab, time, key, state_w);
601 input_method_context_modifiers(struct wl_client *client,
602 struct wl_resource *resource,
604 uint32_t mods_depressed,
605 uint32_t mods_latched,
606 uint32_t mods_locked,
609 struct input_method_context *context = resource->data;
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;
615 default_grab->interface->modifiers(default_grab,
616 serial, mods_depressed,
617 mods_latched, mods_locked,
622 input_method_context_language(struct wl_client *client,
623 struct wl_resource *resource,
625 const char *language)
627 struct input_method_context *context = resource->data;
629 text_model_send_language(&context->model->resource, serial, language);
633 input_method_context_text_direction(struct wl_client *client,
634 struct wl_resource *resource,
638 struct input_method_context *context = resource->data;
640 text_model_send_text_direction(&context->model->resource, serial, direction);
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
662 destroy_input_method_context(struct wl_resource *resource)
664 struct input_method_context *context = resource->data;
666 if (context->keyboard) {
667 wl_resource_destroy(context->keyboard);
674 input_method_context_create(struct text_model *model,
675 struct input_method *input_method,
678 struct input_method_context *context;
680 if (!input_method->input_method_binding)
683 context = calloc(1, sizeof *context);
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);
695 context->model = model;
696 context->input_method = input_method;
697 input_method->context = context;
699 wl_client_add_resource(input_method->input_method_binding->client, &context->resource);
701 input_method_send_activate(input_method->input_method_binding, &context->resource, serial);
705 input_method_context_end_keyboard_grab(struct input_method_context *context)
707 struct wl_keyboard_grab *grab = &context->input_method->seat->keyboard.input_method_grab;
708 struct weston_keyboard *keyboard = (struct weston_keyboard *)grab->keyboard;
713 if (grab->keyboard->grab == grab)
714 wl_keyboard_end_grab(grab->keyboard);
716 keyboard->input_method_resource = NULL;
720 unbind_input_method(struct wl_resource *resource)
722 struct input_method *input_method = resource->data;
723 struct text_backend *text_backend = input_method->text_backend;
725 input_method->input_method_binding = NULL;
726 input_method->context = NULL;
728 text_backend->input_method.binding = NULL;
734 bind_input_method(struct wl_client *client,
739 struct input_method *input_method = data;
740 struct text_backend *text_backend = input_method->text_backend;
741 struct wl_resource *resource;
743 resource = wl_client_add_object(client, &input_method_interface,
747 if (input_method->input_method_binding == NULL) {
748 resource->destroy = unbind_input_method;
749 input_method->input_method_binding = resource;
751 text_backend->input_method.binding = resource;
755 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
756 "interface object already bound");
757 wl_resource_destroy(resource);
761 input_method_notifier_destroy(struct wl_listener *listener, void *data)
763 struct input_method *input_method =
764 container_of(listener, struct input_method, destroy_listener);
766 if (input_method->model)
767 deactivate_text_model(input_method->model, input_method);
769 wl_display_remove_global(input_method->seat->compositor->wl_display,
770 input_method->input_method_global);
776 handle_keyboard_focus(struct wl_listener *listener, void *data)
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;
783 if (!input_method->model)
786 if (!surface || input_method->model->surface != surface)
787 deactivate_text_model(input_method->model,
792 input_method_init_seat(struct weston_seat *seat)
794 if (seat->input_method->focus_listener_initialized)
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;
803 seat->input_method->focus_listener_initialized = 1;
807 handle_input_method_sigchld(struct weston_process *process, int status)
809 struct text_backend *text_backend =
810 container_of(process, struct text_backend, input_method.process);
812 text_backend->input_method.process.pid = 0;
813 text_backend->input_method.client = NULL;
817 launch_input_method(struct text_backend *text_backend)
819 if (text_backend->input_method.binding)
822 if (!text_backend->input_method.path)
825 if (text_backend->input_method.process.pid != 0)
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);
833 if (!text_backend->input_method.client)
834 weston_log("not able to start %s\n", text_backend->input_method.path);
838 handle_seat_created(struct wl_listener *listener,
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;
848 input_method = calloc(1, sizeof *input_method);
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;
856 input_method->input_method_global =
857 wl_display_add_global(ec->wl_display,
858 &input_method_interface,
859 input_method, bind_input_method);
861 input_method->destroy_listener.notify = input_method_notifier_destroy;
862 wl_signal_add(&seat->seat.destroy_signal, &input_method->destroy_listener);
864 seat->input_method = input_method;
866 launch_input_method(text_backend);
870 text_backend_configuration(struct text_backend *text_backend)
875 struct config_key input_method_keys[] = {
876 { "path", CONFIG_KEY_STRING, &path }
879 struct config_section cs[] = {
880 { "input-method", input_method_keys, ARRAY_LENGTH(input_method_keys), NULL }
883 config_file = config_file_path("weston.ini");
884 parse_config_file(config_file, cs, ARRAY_LENGTH(cs), text_backend);
888 text_backend->input_method.path = path;
890 text_backend->input_method.path = strdup(LIBEXECDIR "/weston-keyboard");
894 text_backend_notifier_destroy(struct wl_listener *listener, void *data)
896 struct text_backend *text_backend =
897 container_of(listener, struct text_backend, destroy_listener);
899 if (text_backend->input_method.client)
900 wl_client_destroy(text_backend->input_method.client);
902 free(text_backend->input_method.path);
909 text_backend_init(struct weston_compositor *ec)
911 struct text_backend *text_backend;
913 text_backend = calloc(1, sizeof(*text_backend));
915 text_backend->compositor = ec;
917 text_backend->seat_created_listener.notify = handle_seat_created;
918 wl_signal_add(&ec->seat_created_signal,
919 &text_backend->seat_created_listener);
921 text_backend->destroy_listener.notify = text_backend_notifier_destroy;
922 wl_signal_add(&ec->destroy_signal, &text_backend->destroy_listener);
924 text_backend_configuration(text_backend);
926 text_model_factory_create(ec);