* add the request_keyboard_input request to signal that the input method wants to receive keyboard events * add key and modifier events * keyboard events are grabbed with wl_keyboard_grab and relayed to the input method --- protocol/text.xml | 28 +++++++++++ src/compositor.c | 15 +++--- src/compositor.h | 8 +++- src/shell.c | 10 ++-- src/text-backend.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 5 Dateien geändert, 180 Zeilen hinzugefügt(+), 17 Zeilen entfernt(-)
diff --git a/protocol/text.xml b/protocol/text.xml index a14277a..e51057a 100644 --- a/protocol/text.xml +++ b/protocol/text.xml @@ -48,5 +48,33 @@ <arg name="text" type="string"/> <arg name="index" type="uint"/> </request> + + <request name="request_keyboard_input"> + <arg name="request_p" type="uint" description="0: false, 1: true"/> + </request> + + <event name="key"> + <description summary="key event"> + A key was pressed or released. + </description> + + <arg name="serial" type="uint"/> + <arg name="time" type="uint"/> + <arg name="key" type="uint"/> + <arg name="state" type="uint"/> + </event> + + <event name="modifiers"> + <description summary="modifier and group state"> + Notifies clients that the modifier and/or group state has + changed, and it should update its local state. + </description> + + <arg name="serial" type="uint"/> + <arg name="mods_depressed" type="uint"/> + <arg name="mods_latched" type="uint"/> + <arg name="mods_locked" type="uint"/> + <arg name="group" type="uint"/> + </event> </interface> </protocol> diff --git a/src/compositor.c b/src/compositor.c index 678e0bd..e28ee4b 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -646,7 +646,7 @@ weston_surface_unmap(struct weston_surface *surface) wl_list_for_each(seat, &surface->compositor->seat_list, link) { if (seat->seat.keyboard && seat->seat.keyboard->focus == &surface->surface) - wl_keyboard_set_focus(seat->seat.keyboard, NULL); + keyboard_set_focus(seat->compositor, seat->seat.keyboard, NULL); if (seat->seat.pointer && seat->seat.pointer->focus == &surface->surface) wl_pointer_set_focus(seat->seat.pointer, @@ -1686,7 +1686,7 @@ weston_surface_activate(struct weston_surface *surface, struct weston_compositor *compositor = seat->compositor; if (seat->seat.keyboard) { - wl_keyboard_set_focus(seat->seat.keyboard, &surface->surface); + keyboard_set_focus(seat->compositor, seat->seat.keyboard, &surface->surface); wl_data_device_set_keyboard_focus(&seat->seat); } @@ -1959,7 +1959,7 @@ notify_keyboard_focus_in(struct wl_seat *seat, struct wl_array *keys, if (surface) { wl_list_remove(&ws->saved_kbd_focus_listener.link); - wl_keyboard_set_focus(ws->seat.keyboard, surface); + keyboard_set_focus(ws->compositor, ws->seat.keyboard, surface); ws->saved_kbd_focus = NULL; } } @@ -1991,7 +1991,7 @@ notify_keyboard_focus_out(struct wl_seat *seat) &ws->saved_kbd_focus_listener); } - wl_keyboard_set_focus(ws->seat.keyboard, NULL); + keyboard_set_focus(ws->compositor, ws->seat.keyboard, NULL); /* FIXME: We really need keyboard grab cancel here to * let the grab shut down properly. As it is we leak * the grab data. */ @@ -2293,8 +2293,9 @@ seat_get_keyboard(struct wl_client *client, struct wl_resource *resource, if (seat->seat.keyboard->focus && seat->seat.keyboard->focus->resource.client == client) { - wl_keyboard_set_focus(seat->seat.keyboard, - seat->seat.keyboard->focus); + keyboard_set_focus(seat->compositor, + seat->seat.keyboard, + seat->seat.keyboard->focus); } } @@ -3044,7 +3045,7 @@ weston_compositor_init(struct weston_compositor *ec, screenshooter_create(ec); text_cursor_position_notifier_create(ec); - input_method_create(ec); + ec->input_method = input_method_create(ec); wl_data_device_manager_init(ec->wl_display); diff --git a/src/compositor.h b/src/compositor.h index 0d49dec..34c4778 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -289,6 +289,8 @@ struct weston_compositor { /* There can be more than one, but not right now... */ struct weston_seat *seat; + struct input_method *input_method; + struct weston_layer fade_layer; struct weston_layer cursor_layer; @@ -708,7 +710,7 @@ clipboard_create(struct weston_seat *seat); void text_cursor_position_notifier_create(struct weston_compositor *ec); -void +struct input_method * input_method_create(struct weston_compositor *ec); struct weston_process; @@ -761,4 +763,8 @@ backend_init(struct wl_display *display, int argc, char *argv[], int weston_output_switch_mode(struct weston_output *output, struct weston_mode *mode); +void +keyboard_set_focus(struct weston_compositor *compositor, struct wl_keyboard *keyboard, + struct wl_surface *surface); + #endif diff --git a/src/shell.c b/src/shell.c index 66c9d64..6504631 100644 --- a/src/shell.c +++ b/src/shell.c @@ -421,8 +421,9 @@ pop_focus_state(struct desktop_shell *shell, struct workspace *ws) wl_list_for_each_safe(state, next, &ws->focus_list, link) { if (state->keyboard_focus) - wl_keyboard_set_focus(state->seat->seat.keyboard, - &state->keyboard_focus->surface); + keyboard_set_focus(shell->compositor, + state->seat->seat.keyboard, + &state->keyboard_focus->surface); focus_state_destroy(state); } @@ -445,7 +446,8 @@ push_focus_state(struct desktop_shell *shell, struct workspace *ws) wl_list_insert(&ws->focus_list, &state->link); - wl_keyboard_set_focus(seat->seat.keyboard, NULL); + keyboard_set_focus(shell->compositor, + seat->seat.keyboard, NULL); } } } @@ -3046,7 +3048,7 @@ switcher_binding(struct wl_seat *seat, uint32_t time, uint32_t key, lower_fullscreen_layer(switcher->shell); switcher->grab.interface = &switcher_grab; wl_keyboard_start_grab(seat->keyboard, &switcher->grab); - wl_keyboard_set_focus(seat->keyboard, NULL); + keyboard_set_focus(shell->compositor, seat->keyboard, NULL); switcher_next(switcher); } diff --git a/src/text-backend.c b/src/text-backend.c index e4dea8f..8681a95 100644 --- a/src/text-backend.c +++ b/src/text-backend.c @@ -20,10 +20,13 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <stdbool.h> #include <stdlib.h> +#include <string.h> #include "compositor.h" #include "text-server-protocol.h" +#include "log.h" struct input_method; @@ -33,6 +36,8 @@ struct text_model { struct wl_list link; struct input_method *input_method; + struct wl_keyboard_grab grab; + struct wl_surface *surface; }; struct input_method { @@ -44,15 +49,23 @@ struct input_method { struct weston_compositor *ec; struct wl_list models; struct text_model *active_model; + + bool request_keyboard_input_p; }; static void deactivate_text_model(struct text_model *text_model) { + struct wl_keyboard_grab *grab = &text_model->grab; + if (grab->keyboard && (grab->keyboard->grab == grab)) { + wl_keyboard_end_grab(grab->keyboard); + weston_log("end keyboard grab\n"); + } if (text_model->input_method->active_model == text_model) { text_model->input_method->active_model = NULL; - wl_signal_emit(&text_model->input_method->ec->hide_input_panel_signal, text_model->input_method->ec); + wl_signal_emit(&text_model->input_method->ec->hide_input_panel_signal, + text_model->input_method->ec); } } @@ -83,6 +96,40 @@ text_model_set_cursor_index(struct wl_client *client, } static void +text_model_key(struct wl_keyboard_grab *grab, + uint32_t time, uint32_t key, uint32_t state_w) +{ + struct text_model *text_model = container_of(grab, struct text_model, grab); + + uint32_t serial = wl_display_next_serial(text_model->input_method->ec->wl_display); + if (text_model->input_method->input_method_binding) { + input_method_send_key(text_model->input_method->input_method_binding, + serial, time, key, state_w); + } +} + +static void +text_model_modifier(struct wl_keyboard_grab *grab, uint32_t serial, + uint32_t mods_depressed, uint32_t mods_latched, + uint32_t mods_locked, uint32_t group) +{ + struct text_model *text_model = container_of(grab, struct text_model, grab); + + uint32_t new_serial = wl_display_next_serial(text_model->input_method->ec->wl_display); + if (text_model->input_method->input_method_binding) { + input_method_send_modifiers(text_model->input_method->input_method_binding, + new_serial, mods_depressed, mods_latched, + mods_locked, group); + } +} + +static const struct wl_keyboard_grab_interface text_model_grab = { + text_model_key, + text_model_modifier, +}; + + +static void text_model_activate(struct wl_client *client, struct wl_resource *resource) { @@ -90,7 +137,19 @@ text_model_activate(struct wl_client *client, text_model->input_method->active_model = text_model; - wl_signal_emit(&text_model->input_method->ec->show_input_panel_signal, text_model->input_method->ec); + wl_signal_emit(&text_model->input_method->ec->show_input_panel_signal, + text_model->input_method->ec); + + if (text_model->input_method->input_method_binding && + text_model->input_method->request_keyboard_input_p) { + struct wl_seat *seat = &text_model->input_method->ec->seat->seat; + + if (seat->keyboard->grab != &seat->keyboard->default_grab) { + wl_keyboard_end_grab(seat->keyboard); + } + wl_keyboard_start_grab(seat->keyboard, &text_model->grab); + weston_log("start keyboard grab\n"); + } } static void @@ -162,6 +221,9 @@ static void text_model_manager_create_text_model(struct wl_client *client, text_model->resource.data = text_model; text_model->input_method = input_method; + text_model->surface = container_of(surface, struct wl_surface, resource); + + text_model->grab.interface = &text_model_grab; wl_client_add_resource(client, &text_model->resource); @@ -196,21 +258,66 @@ input_method_commit_string(struct wl_client *client, struct input_method *input_method = resource->data; if (input_method->active_model) { - text_model_send_commit_string(&input_method->active_model->resource, text, index); + text_model_send_commit_string(&input_method->active_model->resource, + text, index); + } +} + +static void +input_method_request_keyboard_input(struct wl_client *client, + struct wl_resource *resource, + uint32_t request_p) +{ + + struct input_method *input_method = resource->data; + + weston_log("request keyboard!\n"); + if ((input_method->request_keyboard_input_p != (bool) request_p) + && input_method->active_model) { + if (request_p) { + struct wl_seat *seat = &input_method->ec->seat->seat; + + wl_keyboard_start_grab(seat->keyboard, + &input_method->active_model->grab); + } else { + struct wl_keyboard_grab *grab = &input_method->active_model->grab; + if (grab->keyboard && grab->keyboard->grab == grab) { + wl_keyboard_end_grab(grab->keyboard); + } + } } + + input_method->request_keyboard_input_p = request_p; } static const struct input_method_interface input_method_implementation = { - input_method_commit_string + input_method_commit_string, + input_method_request_keyboard_input }; static void +clear_input_method_data(struct input_method *input_method) +{ + input_method->request_keyboard_input_p = false; +} + +static void unbind_input_method(struct wl_resource *resource) { struct input_method *input_method = resource->data; + if (input_method->active_model) { + struct wl_keyboard_grab *grab = &input_method->active_model->grab; + if (grab->keyboard && (grab->keyboard->grab == grab)) { + wl_keyboard_end_grab(grab->keyboard); + weston_log("end keyboard grab\n"); + } + } + input_method->input_method_binding = NULL; free(resource); + + clear_input_method_data(input_method); } static void @@ -249,15 +356,17 @@ input_method_notifier_destroy(struct wl_listener *listener, void *data) free(input_method); } -void +WL_EXPORT struct input_method * input_method_create(struct weston_compositor *ec) { + struct input_method *input_method; input_method = calloc(1, sizeof *input_method); input_method->ec = ec; input_method->active_model = NULL; + clear_input_method_data(input_method); wl_list_init(&input_method->models); @@ -273,4 +382,21 @@ input_method_create(struct weston_compositor *ec) input_method->destroy_listener.notify = input_method_notifier_destroy; wl_signal_add(&ec->destroy_signal, &input_method->destroy_listener); + + return input_method; +} + +WL_EXPORT void +keyboard_set_focus(struct weston_compositor *compositor, + struct wl_keyboard *keyboard, + struct wl_surface *surface) +{ + if (compositor->input_method) { + struct text_model *active_model = + compositor->input_method->active_model; + if (active_model && active_model->surface != surface) { + deactivate_text_model(active_model); + } + } + wl_keyboard_set_focus(keyboard, surface); } -- 1.7.11.1 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel