swc

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/swc
Log | Files | Refs | README | LICENSE

commit 600a87459ff518879ffb1023ed4a5e385bfadbae
parent 97069f84283298fd546b7300d7dc78989553f14a
Author: Michael Forney <mforney@mforney.org>
Date:   Fri,  9 Nov 2018 16:02:22 -0800

input: Send keyboard/pointer events for each instance a client has bound

Some clients (like firefox) may bind multiple wl_keyboard instances,
and expect key press events on each one.

Diffstat:
Mlibswc/input.c | 53+++++++++++++++++++++++++++++------------------------
Mlibswc/input.h | 8++++----
Mlibswc/keyboard.c | 38++++++++++++++++++--------------------
Mlibswc/pointer.c | 36++++++++++++++++++++++--------------
Mlibswc/seat.c | 6++----
5 files changed, 75 insertions(+), 66 deletions(-)

diff --git a/libswc/input.c b/libswc/input.c @@ -30,19 +30,23 @@ static inline void focus(struct input_focus *input_focus, struct compositor_view *view) { - struct wl_resource *resource = NULL; + struct wl_client *client = NULL; + struct wl_resource *resource, *tmp; if (view) { - struct wl_client *client; - client = wl_resource_get_client(view->surface->resource); - resource = wl_resource_find_for_client(&input_focus->resources, client); + wl_resource_for_each_safe (resource, tmp, &input_focus->inactive) { + if (wl_resource_get_client(resource) == client) { + wl_list_remove(wl_resource_get_link(resource)); + wl_list_insert(&input_focus->active, wl_resource_get_link(resource)); + } + } wl_signal_add(&view->destroy_signal, &input_focus->view_destroy_listener); } + input_focus->client = client; input_focus->view = view; - input_focus->resource = resource; - input_focus->handler->enter(input_focus->handler, resource, view); + input_focus->handler->enter(input_focus->handler, &input_focus->active, view); } static inline void @@ -50,7 +54,9 @@ unfocus(struct input_focus *input_focus) { if (input_focus->view) wl_list_remove(&input_focus->view_destroy_listener.link); - input_focus->handler->leave(input_focus->handler, input_focus->resource, input_focus->view); + input_focus->handler->leave(input_focus->handler, &input_focus->active, input_focus->view); + wl_list_insert_list(&input_focus->inactive, &input_focus->active); + wl_list_init(&input_focus->active); } static void @@ -58,19 +64,23 @@ handle_focus_view_destroy(struct wl_listener *listener, void *data) { struct input_focus *input_focus = wl_container_of(listener, input_focus, view_destroy_listener); - input_focus->resource = NULL; + /* XXX: Should this call unfocus? */ + wl_list_insert_list(&input_focus->inactive, &input_focus->active); + wl_list_init(&input_focus->active); + input_focus->client = NULL; input_focus->view = NULL; } bool input_focus_initialize(struct input_focus *input_focus, struct input_focus_handler *handler) { - input_focus->resource = NULL; + input_focus->client = NULL; input_focus->view = NULL; input_focus->view_destroy_listener.notify = &handle_focus_view_destroy; input_focus->handler = handler; - wl_list_init(&input_focus->resources); + wl_list_init(&input_focus->active); + wl_list_init(&input_focus->inactive); wl_signal_init(&input_focus->event_signal); return true; @@ -85,29 +95,24 @@ input_focus_finalize(struct input_focus *input_focus) void input_focus_add_resource(struct input_focus *input_focus, struct wl_resource *resource) { - /* If this new input resource corresponds to our focus, set it as our focus. */ - if (input_focus->view) { - struct wl_client *client, *surface_client; + struct wl_list resources, *target = &input_focus->inactive; - client = wl_resource_get_client(resource); - surface_client = wl_resource_get_client(input_focus->view->surface->resource); + wl_list_init(&resources); + wl_list_insert(&resources, wl_resource_get_link(resource)); - if (client == surface_client) { - input_focus->handler->enter(input_focus->handler, resource, input_focus->view); - input_focus->resource = resource; - } + /* If this new input resource corresponds to the focused client, send an enter event. */ + if (wl_resource_get_client(resource) == input_focus->client) { + input_focus->handler->enter(input_focus->handler, &resources, input_focus->view); + target = &input_focus->active; } - wl_list_insert(&input_focus->resources, wl_resource_get_link(resource)); + wl_list_insert_list(target, &resources); } void input_focus_remove_resource(struct input_focus *input_focus, struct wl_resource *resource) { - if (resource == input_focus->resource) - input_focus->resource = NULL; - - remove_resource(resource); + wl_list_remove(wl_resource_get_link(resource)); } void diff --git a/libswc/input.h b/libswc/input.h @@ -38,17 +38,17 @@ struct input_focus_event_data { }; struct input_focus_handler { - void (*enter)(struct input_focus_handler *handler, struct wl_resource *resource, struct compositor_view *view); - void (*leave)(struct input_focus_handler *handler, struct wl_resource *resource, struct compositor_view *view); + void (*enter)(struct input_focus_handler *handler, struct wl_list *resources, struct compositor_view *view); + void (*leave)(struct input_focus_handler *handler, struct wl_list *resources, struct compositor_view *view); }; struct input_focus { - struct wl_resource *resource; + struct wl_client *client; struct compositor_view *view; struct wl_listener view_destroy_listener; struct input_focus_handler *handler; - struct wl_list resources; + struct wl_list active, inactive; struct wl_signal event_signal; }; diff --git a/libswc/keyboard.c b/libswc/keyboard.c @@ -44,34 +44,36 @@ static const int repeat_delay = 500, repeat_rate = 40; static const char keymap_file_template[] = "swc-xkb-keymap-XXXXXX"; static void -enter(struct input_focus_handler *handler, struct wl_resource *resource, struct compositor_view *view) +enter(struct input_focus_handler *handler, struct wl_list *resources, struct compositor_view *view) { struct keyboard *keyboard = wl_container_of(handler, keyboard, focus_handler); struct keyboard_modifier_state *state = &keyboard->modifier_state; + struct wl_resource *resource; uint32_t serial; - if (!resource) - return; serial = wl_display_next_serial(swc.display); - wl_keyboard_send_modifiers(resource, serial, state->depressed, state->locked, state->latched, state->group); - wl_keyboard_send_enter(resource, serial, view->surface->resource, &keyboard->client_keys); + wl_resource_for_each (resource, resources) { + wl_keyboard_send_modifiers(resource, serial, state->depressed, state->locked, state->latched, state->group); + wl_keyboard_send_enter(resource, serial, view->surface->resource, &keyboard->client_keys); + } } static void -leave(struct input_focus_handler *handler, struct wl_resource *resource, struct compositor_view *view) +leave(struct input_focus_handler *handler, struct wl_list *resources, struct compositor_view *view) { + struct wl_resource *resource; uint32_t serial; - if (!resource) - return; serial = wl_display_next_serial(swc.display); - wl_keyboard_send_leave(resource, serial, view->surface->resource); + wl_resource_for_each (resource, resources) + wl_keyboard_send_leave(resource, serial, view->surface->resource); } static bool client_handle_key(struct keyboard *keyboard, uint32_t time, struct key *key, uint32_t state) { uint32_t *value; + struct wl_resource *resource; if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { if (!(value = wl_array_add(&keyboard->client_keys, sizeof(*value)))) @@ -87,27 +89,23 @@ client_handle_key(struct keyboard *keyboard, uint32_t time, struct key *key, uin } } - if (keyboard->focus.resource) - wl_keyboard_send_key(keyboard->focus.resource, key->press.serial, time, key->press.value, state); - + wl_resource_for_each (resource, &keyboard->focus.active) + wl_keyboard_send_key(resource, key->press.serial, time, key->press.value, state); return true; } static bool client_handle_modifiers(struct keyboard *keyboard, const struct keyboard_modifier_state *state) { - struct wl_client *client; - struct wl_display *display; + struct wl_resource *resource; uint32_t serial; - if (!keyboard->focus.resource) + if (wl_list_empty(&keyboard->focus.active)) return false; - client = wl_resource_get_client(keyboard->focus.resource); - display = wl_client_get_display(client); - serial = wl_display_next_serial(display); - wl_keyboard_send_modifiers(keyboard->focus.resource, serial, state->depressed, state->locked, state->latched, state->group); - + serial = wl_display_next_serial(swc.display); + wl_resource_for_each (resource, &keyboard->focus.active) + wl_keyboard_send_modifiers(resource, serial, state->depressed, state->locked, state->latched, state->group); return true; } diff --git a/libswc/pointer.c b/libswc/pointer.c @@ -35,31 +35,33 @@ #include <wld/wld.h> static void -enter(struct input_focus_handler *handler, struct wl_resource *resource, struct compositor_view *view) +enter(struct input_focus_handler *handler, struct wl_list *resources, struct compositor_view *view) { struct pointer *pointer = wl_container_of(handler, pointer, focus_handler); + struct wl_resource *resource; uint32_t serial; wl_fixed_t surface_x, surface_y; - if (!resource) { + if (wl_list_empty(resources)) { pointer_set_cursor(pointer, cursor_left_ptr); return; } serial = wl_display_next_serial(swc.display); surface_x = pointer->x - wl_fixed_from_int(view->base.geometry.x); surface_y = pointer->y - wl_fixed_from_int(view->base.geometry.y); - wl_pointer_send_enter(resource, serial, view->surface->resource, surface_x, surface_y); + wl_resource_for_each (resource, resources) + wl_pointer_send_enter(resource, serial, view->surface->resource, surface_x, surface_y); } static void -leave(struct input_focus_handler *handler, struct wl_resource *resource, struct compositor_view *view) +leave(struct input_focus_handler *handler, struct wl_list *resources, struct compositor_view *view) { + struct wl_resource *resource; uint32_t serial; - if (!resource) - return; serial = wl_display_next_serial(swc.display); - wl_pointer_send_leave(resource, serial, view->surface->resource); + wl_resource_for_each (resource, resources) + wl_pointer_send_leave(resource, serial, view->surface->resource); } static void @@ -169,11 +171,13 @@ static bool client_handle_button(struct pointer_handler *handler, uint32_t time, struct button *button, uint32_t state) { struct pointer *pointer = wl_container_of(handler, pointer, client_handler); + struct wl_resource *resource; - if (!pointer->focus.resource) + if (wl_list_empty(&pointer->focus.active)) return false; - wl_pointer_send_button(pointer->focus.resource, button->press.serial, time, button->press.value, state); + wl_resource_for_each (resource, &pointer->focus.active) + wl_pointer_send_button(resource, button->press.serial, time, button->press.value, state); return true; } @@ -181,11 +185,13 @@ static bool client_handle_axis(struct pointer_handler *handler, uint32_t time, uint32_t axis, wl_fixed_t amount) { struct pointer *pointer = wl_container_of(handler, pointer, client_handler); + struct wl_resource *resource; - if (!pointer->focus.resource) + if (wl_list_empty(&pointer->focus.active)) return false; - wl_pointer_send_axis(pointer->focus.resource, time, axis, amount); + wl_resource_for_each (resource, &pointer->focus.active) + wl_pointer_send_axis(resource, time, axis, amount); return true; } @@ -193,14 +199,16 @@ static bool client_handle_motion(struct pointer_handler *handler, uint32_t time, wl_fixed_t x, wl_fixed_t y) { struct pointer *pointer = wl_container_of(handler, pointer, client_handler); + struct wl_resource *resource; wl_fixed_t sx, sy; - if (!pointer->focus.resource) + if (wl_list_empty(&pointer->focus.active)) return false; sx = x - wl_fixed_from_int(pointer->focus.view->base.geometry.x); sy = y - wl_fixed_from_int(pointer->focus.view->base.geometry.y); - wl_pointer_send_motion(pointer->focus.resource, time, sx, sy); + wl_resource_for_each (resource, &pointer->focus.active) + wl_pointer_send_motion(resource, time, sx, sy); return true; } @@ -298,7 +306,7 @@ set_cursor(struct wl_client *client, struct wl_resource *resource, struct pointer *pointer = wl_resource_get_user_data(resource); struct surface *surface; - if (!pointer->focus.resource || client != wl_resource_get_client(pointer->focus.resource)) + if (client != pointer->focus.client) return; if (pointer->cursor.surface) { diff --git a/libswc/seat.c b/libswc/seat.c @@ -102,10 +102,8 @@ handle_data_device_event(struct wl_listener *listener, void *data) if (ev->type != DATA_DEVICE_EVENT_SELECTION_CHANGED) return; - if (seat.keyboard.focus.resource) { - struct wl_client *client = wl_resource_get_client(seat.keyboard.focus.resource); - data_device_offer_selection(&seat.data_device, client); - } + if (seat.keyboard.focus.client) + data_device_offer_selection(&seat.data_device, seat.keyboard.focus.client); } static struct wl_listener data_device_listener = {