From 2cbf293b0551357ae36757788e385e391f971386 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jonas=20=C3=85dahl?= Date: Wed, 22 Jul 2015 12:05:38 +0800 Subject: [PATCH] input: Keep per client pointer resources in their own structs MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Keep all per client wl_pointer resources in a new struct called 'weston_pointer_client'. When focus changes, instead of moving a list of resources between different lists, just change the focused pointer client. The intention with this is to make it easier to add wl_pointer extensions that share the same focus as the corresponding wl_pointer. Signed-off-by: Jonas Ådahl Reviewed-by: Peter Hutterer --- desktop-shell/shell.c | 14 ++-- src/compositor.h | 11 ++- src/input.c | 187 ++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 170 insertions(+), 42 deletions(-) diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c index d58a830..780902d 100644 --- a/desktop-shell/shell.c +++ b/desktop-shell/shell.c @@ -3145,6 +3145,7 @@ popup_grab_motion(struct weston_pointer_grab *grab, uint32_t time, { struct weston_pointer *pointer = grab->pointer; struct wl_resource *resource; + struct wl_list *resource_list; wl_fixed_t x, y; wl_fixed_t sx, sy; @@ -3156,7 +3157,11 @@ popup_grab_motion(struct weston_pointer_grab *grab, uint32_t time, weston_pointer_move(pointer, event); - wl_resource_for_each(resource, &pointer->focus_resource_list) { + if (!pointer->focus_client) + return; + + resource_list = &pointer->focus_client->pointer_resources; + wl_resource_for_each(resource, resource_list) { weston_view_from_global_fixed(pointer->focus, pointer->x, pointer->y, &sx, &sy); @@ -3174,10 +3179,11 @@ popup_grab_button(struct weston_pointer_grab *grab, struct wl_display *display = shseat->seat->compositor->wl_display; enum wl_pointer_button_state state = state_w; uint32_t serial; - struct wl_list *resource_list; + struct wl_list *resource_list = NULL; - resource_list = &grab->pointer->focus_resource_list; - if (!wl_list_empty(resource_list)) { + if (grab->pointer->focus_client) + resource_list = &grab->pointer->focus_client->pointer_resources; + if (resource_list && !wl_list_empty(resource_list)) { serial = wl_display_get_serial(display); wl_resource_for_each(resource, resource_list) { wl_pointer_send_button(resource, serial, diff --git a/src/compositor.h b/src/compositor.h index 44d9f86..203c2fd 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -327,12 +327,19 @@ struct weston_data_source { void (*cancel)(struct weston_data_source *source); }; +struct weston_pointer_client { + struct wl_list link; + struct wl_client *client; + struct wl_list pointer_resources; +}; + struct weston_pointer { struct weston_seat *seat; - struct wl_list resource_list; - struct wl_list focus_resource_list; + struct wl_list pointer_clients; + struct weston_view *focus; + struct weston_pointer_client *focus_client; uint32_t focus_serial; struct wl_listener focus_view_listener; struct wl_listener focus_resource_listener; diff --git a/src/input.c b/src/input.c index 86f96b5..1cc2540 100644 --- a/src/input.c +++ b/src/input.c @@ -45,6 +45,95 @@ empty_region(pixman_region32_t *region) pixman_region32_init(region); } +static struct weston_pointer_client * +weston_pointer_client_create(struct wl_client *client) +{ + struct weston_pointer_client *pointer_client; + + pointer_client = zalloc(sizeof *pointer_client); + if (!pointer_client) + return NULL; + + pointer_client->client = client; + wl_list_init(&pointer_client->pointer_resources); + + return pointer_client; +} + +static void +weston_pointer_client_destroy(struct weston_pointer_client *pointer_client) +{ + free(pointer_client); +} + +static bool +weston_pointer_client_is_empty(struct weston_pointer_client *pointer_client) +{ + return wl_list_empty(&pointer_client->pointer_resources); +} + +static struct weston_pointer_client * +weston_pointer_get_pointer_client(struct weston_pointer *pointer, + struct wl_client *client) +{ + struct weston_pointer_client *pointer_client; + + wl_list_for_each(pointer_client, &pointer->pointer_clients, link) { + if (pointer_client->client == client) + return pointer_client; + } + + return NULL; +} + +static struct weston_pointer_client * +weston_pointer_ensure_pointer_client(struct weston_pointer *pointer, + struct wl_client *client) +{ + struct weston_pointer_client *pointer_client; + + pointer_client = weston_pointer_get_pointer_client(pointer, client); + if (pointer_client) + return pointer_client; + + pointer_client = weston_pointer_client_create(client); + wl_list_insert(&pointer->pointer_clients, &pointer_client->link); + + if (pointer->focus && + pointer->focus->surface->resource && + wl_resource_get_client(pointer->focus->surface->resource) == client) { + pointer->focus_client = pointer_client; + } + + return pointer_client; +} + +static void +weston_pointer_cleanup_pointer_client(struct weston_pointer *pointer, + struct weston_pointer_client *pointer_client) +{ + if (weston_pointer_client_is_empty(pointer_client)) { + if (pointer->focus_client == pointer_client) + pointer->focus_client = NULL; + wl_list_remove(&pointer_client->link); + weston_pointer_client_destroy(pointer_client); + } +} + +static void +unbind_pointer_client_resource(struct wl_resource *resource) +{ + struct weston_pointer *pointer = wl_resource_get_user_data(resource); + struct wl_client *client = wl_resource_get_client(resource); + struct weston_pointer_client *pointer_client; + + pointer_client = weston_pointer_get_pointer_client(pointer, client); + assert(pointer_client); + + wl_list_remove(wl_resource_get_link(resource)); + weston_pointer_cleanup_pointer_client(pointer, pointer_client); +} + static void unbind_resource(struct wl_resource *resource) { wl_list_remove(wl_resource_get_link(resource)); @@ -184,8 +273,9 @@ default_grab_pointer_motion(struct weston_pointer_grab *grab, uint32_t time, weston_pointer_move(pointer, event); - if (old_sx != pointer->sx || old_sy != pointer->sy) { - resource_list = &pointer->focus_resource_list; + if (pointer->focus_client && + (old_sx != pointer->sx || old_sy != pointer->sy)) { + resource_list = &pointer->focus_client->pointer_resources; wl_resource_for_each(resource, resource_list) { wl_pointer_send_motion(resource, time, pointer->sx, pointer->sy); @@ -205,10 +295,12 @@ default_grab_pointer_button(struct weston_pointer_grab *grab, enum wl_pointer_button_state state = state_w; struct wl_display *display = compositor->wl_display; wl_fixed_t sx, sy; - struct wl_list *resource_list; + struct wl_list *resource_list = NULL; - resource_list = &pointer->focus_resource_list; - if (!wl_list_empty(resource_list)) { + if (pointer->focus_client) + resource_list = &pointer->focus_client->pointer_resources; + if (resource_list && !wl_list_empty(resource_list)) { + resource_list = &pointer->focus_client->pointer_resources; serial = wl_display_next_serial(display); wl_resource_for_each(resource, resource_list) wl_pointer_send_button(resource, @@ -246,7 +338,10 @@ weston_pointer_send_axis(struct weston_pointer *pointer, struct wl_resource *resource; struct wl_list *resource_list; - resource_list = &pointer->focus_resource_list; + if (!pointer->focus_client) + return; + + resource_list = &pointer->focus_client->pointer_resources; wl_resource_for_each(resource, resource_list) wl_pointer_send_axis(resource, time, axis, value); } @@ -407,25 +502,41 @@ send_modifiers_to_client_in_list(struct wl_client *client, } } -static struct wl_resource * -find_resource_for_surface(struct wl_list *list, struct weston_surface *surface) +static struct weston_pointer_client * +find_pointer_client_for_surface(struct weston_pointer *pointer, + struct weston_surface *surface) { + struct wl_client *client; + if (!surface) return NULL; if (!surface->resource) return NULL; - return wl_resource_find_for_client(list, wl_resource_get_client(surface->resource)); + client = wl_resource_get_client(surface->resource); + return weston_pointer_get_pointer_client(pointer, client); } -static struct wl_resource * -find_resource_for_view(struct wl_list *list, struct weston_view *view) +static struct weston_pointer_client * +find_pointer_client_for_view(struct weston_pointer *pointer, struct weston_view *view) { if (!view) return NULL; - return find_resource_for_surface(list, view->surface); + return find_pointer_client_for_surface(pointer, view->surface); +} + +static struct wl_resource * +find_resource_for_surface(struct wl_list *list, struct weston_surface *surface) +{ + if (!surface) + return NULL; + + if (!surface->resource) + return NULL; + + return wl_resource_find_for_client(list, wl_resource_get_client(surface->resource)); } static void @@ -513,8 +624,7 @@ weston_pointer_create(struct weston_seat *seat) if (pointer == NULL) return NULL; - wl_list_init(&pointer->resource_list); - wl_list_init(&pointer->focus_resource_list); + wl_list_init(&pointer->pointer_clients); weston_pointer_set_default_grab(pointer, seat->compositor->default_pointer_grab); wl_list_init(&pointer->focus_resource_listener.link); @@ -694,8 +804,10 @@ weston_pointer_set_focus(struct weston_pointer *pointer, struct weston_view *view, wl_fixed_t sx, wl_fixed_t sy) { + struct weston_pointer_client *pointer_client; struct weston_keyboard *kbd = weston_seat_get_keyboard(pointer->seat); struct wl_resource *resource; + struct wl_resource *surface_resource; struct wl_display *display = pointer->seat->compositor->wl_display; uint32_t serial; struct wl_list *focus_resource_list; @@ -707,21 +819,23 @@ weston_pointer_set_focus(struct weston_pointer *pointer, pointer->sx != sx || pointer->sy != sy) refocus = 1; - focus_resource_list = &pointer->focus_resource_list; - - if (!wl_list_empty(focus_resource_list) && refocus) { - serial = wl_display_next_serial(display); - wl_resource_for_each(resource, focus_resource_list) { - wl_pointer_send_leave(resource, serial, - pointer->focus->surface->resource); + if (pointer->focus_client && refocus) { + focus_resource_list = &pointer->focus_client->pointer_resources; + if (!wl_list_empty(focus_resource_list)) { + serial = wl_display_next_serial(display); + surface_resource = pointer->focus->surface->resource; + wl_resource_for_each(resource, focus_resource_list) { + wl_pointer_send_leave(resource, serial, + surface_resource); + } } - move_resources(&pointer->resource_list, focus_resource_list); + pointer->focus_client = NULL; } - if (find_resource_for_view(&pointer->resource_list, view) && refocus) { - struct wl_client *surface_client = - wl_resource_get_client(view->surface->resource); + pointer_client = find_pointer_client_for_view(pointer, view); + if (pointer_client && refocus) { + struct wl_client *surface_client = pointer_client->client; serial = wl_display_next_serial(display); @@ -731,10 +845,9 @@ weston_pointer_set_focus(struct weston_pointer *pointer, serial, kbd); - move_resources_for_client(focus_resource_list, - &pointer->resource_list, - surface_client); + pointer->focus_client = pointer_client; + focus_resource_list = &pointer->focus_client->pointer_resources; wl_resource_for_each(resource, focus_resource_list) { wl_pointer_send_enter(resource, serial, @@ -1818,6 +1931,7 @@ seat_get_pointer(struct wl_client *client, struct wl_resource *resource, */ struct weston_pointer *pointer = seat->pointer_state; struct wl_resource *cr; + struct weston_pointer_client *pointer_client; if (!pointer) return; @@ -1829,12 +1943,16 @@ seat_get_pointer(struct wl_client *client, struct wl_resource *resource, return; } - /* May be moved to focused list later by either - * weston_pointer_set_focus or directly if this client is already - * focused */ - wl_list_insert(&pointer->resource_list, wl_resource_get_link(cr)); + pointer_client = weston_pointer_ensure_pointer_client(pointer, client); + if (!pointer_client) { + wl_client_post_no_memory(client); + return; + } + + wl_list_insert(&pointer_client->pointer_resources, + wl_resource_get_link(cr)); wl_resource_set_implementation(cr, &pointer_interface, pointer, - unbind_resource); + unbind_pointer_client_resource); if (pointer->focus && pointer->focus->surface->resource && wl_resource_get_client(pointer->focus->surface->resource) == client) { @@ -1845,9 +1963,6 @@ seat_get_pointer(struct wl_client *client, struct wl_resource *resource, pointer->y, &sx, &sy); - wl_list_remove(wl_resource_get_link(cr)); - wl_list_insert(&pointer->focus_resource_list, - wl_resource_get_link(cr)); wl_pointer_send_enter(cr, pointer->focus_serial, pointer->focus->surface->resource, -- 2.7.4