From: Derek Foreman Date: Fri, 8 May 2015 22:08:40 +0000 (-0500) Subject: text: Fix text-input for multi-seat X-Git-Tag: 1.7.92~9 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=516d603515de3df40a04b722cf4851209e9d5588;p=platform%2Fupstream%2Fweston.git text: Fix text-input for multi-seat Multi-seat configurations currently break the text-backend, crashing weston. This is an attempt to clean up any crashes and have somewhat sensible input panel behavior with multi-seat. Store a link to the manager that created a text_input, use this to ensure that only a single panel gets popped up at a time, since there is only one manager. Replace deactivate_text_input with deactivate_input_method: multiple input methods may focus the same text_input, so deactivating a text_input is weird in multi-seat and confusing to perform. In destroy_input_method_context set the context's input_method's context pointer to NULL to prevent a dangling pointer. Reviewed-by: Jan Arne Petersen Reviewed-by: Bryce Harrington Signed-off-by: Derek Foreman --- diff --git a/src/text-backend.c b/src/text-backend.c index 4dc7179..65b4e5e 100644 --- a/src/text-backend.c +++ b/src/text-backend.c @@ -33,6 +33,7 @@ #include "text-server-protocol.h" #include "input-method-server-protocol.h" +struct text_input_manager; struct input_method; struct input_method_context; struct text_backend; @@ -49,12 +50,16 @@ struct text_input { pixman_box32_t cursor_rectangle; bool input_panel_visible; + + struct text_input_manager *manager; }; struct text_input_manager { struct wl_global *text_input_manager_global; struct wl_listener destroy_listener; + struct text_input *current_panel; + struct weston_compositor *ec; }; @@ -113,25 +118,28 @@ static void input_method_init_seat(struct weston_seat *seat); static void -deactivate_text_input(struct text_input *text_input, - struct input_method *input_method) +deactivate_input_method(struct input_method *input_method) { + struct text_input *text_input = input_method->model; struct weston_compositor *ec = text_input->ec; - if (input_method->model == text_input) { - if (input_method->context && input_method->input_method_binding) { - input_method_context_end_keyboard_grab(input_method->context); - wl_input_method_send_deactivate(input_method->input_method_binding, - input_method->context->resource); - input_method->context->model = NULL; - } - - wl_list_remove(&input_method->link); - input_method->model = NULL; - input_method->context = NULL; + if (input_method->context && input_method->input_method_binding) { + input_method_context_end_keyboard_grab(input_method->context); + wl_input_method_send_deactivate(input_method->input_method_binding, + input_method->context->resource); + } + + wl_list_remove(&input_method->link); + input_method->model = NULL; + input_method->context = NULL; + + if (wl_list_empty(&text_input->input_methods) && + text_input->input_panel_visible) { wl_signal_emit(&ec->hide_input_panel_signal, ec); - wl_text_input_send_leave(text_input->resource); + text_input->input_panel_visible = false; + text_input->manager->current_panel = NULL; } + wl_text_input_send_leave(text_input->resource); } static void @@ -141,7 +149,7 @@ destroy_text_input(struct wl_resource *resource) struct input_method *input_method, *next; wl_list_for_each_safe(input_method, next, &text_input->input_methods, link) - deactivate_text_input(text_input, input_method); + deactivate_input_method(input_method); free(text_input); } @@ -175,16 +183,14 @@ text_input_activate(struct wl_client *client, struct text_input *text_input = wl_resource_get_user_data(resource); struct weston_seat *weston_seat = wl_resource_get_user_data(seat); struct input_method *input_method = weston_seat->input_method; - struct text_input *old = weston_seat->input_method->model; struct weston_compositor *ec = text_input->ec; + struct text_input *current; - if (old == text_input) + if (input_method->model == text_input) return; - if (old) { - deactivate_text_input(old, - weston_seat->input_method); - } + if (input_method->model) + deactivate_input_method(input_method); input_method->model = text_input; wl_list_insert(&text_input->input_methods, &input_method->link); @@ -194,9 +200,18 @@ text_input_activate(struct wl_client *client, input_method_context_create(text_input, input_method); + current = text_input->manager->current_panel; + + if (current && current != text_input) { + current->input_panel_visible = false; + wl_signal_emit(&ec->hide_input_panel_signal, ec); + text_input->manager->current_panel = NULL; + } + if (text_input->input_panel_visible) { wl_signal_emit(&ec->show_input_panel_signal, text_input->surface); wl_signal_emit(&ec->update_input_panel_signal, &text_input->cursor_rectangle); + text_input->manager->current_panel = text_input; } wl_text_input_send_enter(text_input->resource, text_input->surface->resource); @@ -207,11 +222,10 @@ text_input_deactivate(struct wl_client *client, struct wl_resource *resource, struct wl_resource *seat) { - struct text_input *text_input = wl_resource_get_user_data(resource); struct weston_seat *weston_seat = wl_resource_get_user_data(seat); - deactivate_text_input(text_input, - weston_seat->input_method); + if (weston_seat->input_method->model) + deactivate_input_method(weston_seat->input_method); } static void @@ -318,8 +332,11 @@ text_input_hide_input_panel(struct wl_client *client, text_input->input_panel_visible = false; - if (!wl_list_empty(&text_input->input_methods)) + if (!wl_list_empty(&text_input->input_methods) && + text_input == text_input->manager->current_panel) { + text_input->manager->current_panel = NULL; wl_signal_emit(&ec->hide_input_panel_signal, ec); + } } static void @@ -370,6 +387,7 @@ static void text_input_manager_create_text_input(struct wl_client *client, text_input, destroy_text_input); text_input->ec = text_input_manager->ec; + text_input->manager = text_input_manager; wl_list_init(&text_input->input_methods); }; @@ -719,6 +737,9 @@ destroy_input_method_context(struct wl_resource *resource) wl_resource_destroy(context->keyboard); } + if (context->input_method && context->input_method->context == context) + context->input_method->context = NULL; + free(context); } @@ -823,7 +844,7 @@ input_method_notifier_destroy(struct wl_listener *listener, void *data) container_of(listener, struct input_method, destroy_listener); if (input_method->model) - deactivate_text_input(input_method->model, input_method); + deactivate_input_method(input_method); wl_global_destroy(input_method->input_method_global); wl_list_remove(&input_method->destroy_listener.link); @@ -843,8 +864,7 @@ handle_keyboard_focus(struct wl_listener *listener, void *data) return; if (!surface || input_method->model->surface != surface) - deactivate_text_input(input_method->model, - input_method); + deactivate_input_method(input_method); } static void