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.
---
 desktop-shell/shell.c |  16 +++--
 src/compositor.h      |  11 ++-
 src/input.c           | 186 ++++++++++++++++++++++++++++++++++++++++----------
 3 files changed, 169 insertions(+), 44 deletions(-)

diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index 6044cc9..4d7a484 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -3209,6 +3209,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;
 
@@ -3220,7 +3221,8 @@ 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) {
+       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);
@@ -3238,10 +3240,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,
@@ -3265,7 +3268,10 @@ popup_grab_axis(struct weston_pointer_grab *grab,
        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);
 }
diff --git a/src/compositor.h b/src/compositor.h
index b98119e..4d5b0e1 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -329,12 +329,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 cbe9911..3338fdb 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);
 }
@@ -401,25 +496,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
@@ -506,8 +617,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);
@@ -664,8 +774,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 = pointer->seat->keyboard;
        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;
@@ -677,21 +789,24 @@ 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) {
+               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);
 
@@ -701,10 +816,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,
@@ -1805,9 +1919,11 @@ seat_get_pointer(struct wl_client *client, struct 
wl_resource *resource,
                 uint32_t id)
 {
        struct weston_seat *seat = wl_resource_get_user_data(resource);
+       struct weston_pointer *pointer = seat->pointer;
        struct wl_resource *cr;
+       struct weston_pointer_client *pointer_client;
 
-       if (!seat->pointer)
+       if (!pointer)
                return;
 
         cr = wl_resource_create(client, &wl_pointer_interface,
@@ -1816,13 +1932,12 @@ seat_get_pointer(struct wl_client *client, struct 
wl_resource *resource,
                wl_client_post_no_memory(client);
                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(&seat->pointer->resource_list, wl_resource_get_link(cr));
        wl_resource_set_implementation(cr, &pointer_interface, seat->pointer,
-                                      unbind_resource);
+                                      unbind_pointer_client_resource);
+
+       pointer_client = weston_pointer_ensure_pointer_client(pointer, client);
+       wl_list_insert(&pointer_client->pointer_resources,
+                      wl_resource_get_link(cr));
 
        if (seat->pointer->focus && seat->pointer->focus->surface->resource &&
            wl_resource_get_client(seat->pointer->focus->surface->resource) == 
client) {
@@ -1833,9 +1948,6 @@ seat_get_pointer(struct wl_client *client, struct 
wl_resource *resource,
                                              seat->pointer->y,
                                              &sx, &sy);
 
-               wl_list_remove(wl_resource_get_link(cr));
-               wl_list_insert(&seat->pointer->focus_resource_list,
-                              wl_resource_get_link(cr));
                wl_pointer_send_enter(cr,
                                      seat->pointer->focus_serial,
                                      seat->pointer->focus->surface->resource,
-- 
2.1.0

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to