From 339a78718dad817bbdfc7ba7056fc0371c89d9aa Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Wed, 16 Apr 2014 15:11:10 -0400 Subject: [PATCH] pointer/keyboard: Support more than one focused resource Sophisticated clients, like those using ClutterGtk, will have more than one focused resource per client, as both Clutter and GDK will ask for a wl_pointer / wl_keyboard. Support this naturally using the same "hack" as Weston: multiple resource lists, where we move elements from one to the other. --- src/wayland/meta-wayland-keyboard.c | 102 ++++++++++++++++++---------- src/wayland/meta-wayland-keyboard.h | 2 +- src/wayland/meta-wayland-pointer.c | 80 ++++++++++++++-------- src/wayland/meta-wayland-pointer.h | 2 +- src/wayland/meta-wayland-seat.c | 21 +++--- 5 files changed, 135 insertions(+), 72 deletions(-) diff --git a/src/wayland/meta-wayland-keyboard.c b/src/wayland/meta-wayland-keyboard.c index cb227a9c7..08e09341c 100644 --- a/src/wayland/meta-wayland-keyboard.c +++ b/src/wayland/meta-wayland-keyboard.c @@ -211,7 +211,6 @@ keyboard_handle_focus_surface_destroy (struct wl_listener *listener, void *data) MetaWaylandKeyboard *keyboard = wl_container_of (listener, keyboard, focus_surface_listener); keyboard->focus_surface = NULL; - keyboard->focus_resource = NULL; } static gboolean @@ -220,34 +219,47 @@ default_grab_key (MetaWaylandKeyboardGrab *grab, { MetaWaylandKeyboard *keyboard = grab->keyboard; struct wl_resource *resource; - uint32_t serial; + struct wl_list *l; - resource = keyboard->focus_resource; - if (resource) + l = &keyboard->focus_resource_list; + if (!wl_list_empty (l)) { struct wl_client *client = wl_resource_get_client (keyboard->focus_surface->resource); struct wl_display *display = wl_client_get_display (client); - serial = wl_display_next_serial (display); - wl_keyboard_send_key (resource, serial, time, key, state); + uint32_t serial = wl_display_next_serial (display); + + wl_resource_for_each (resource, l) + { + wl_keyboard_send_key (resource, serial, time, key, state); + } + + return TRUE; } - return resource != NULL; + return FALSE; } -static struct wl_resource * -find_resource_for_surface (struct wl_list *list, MetaWaylandSurface *surface) +static void +move_resources (struct wl_list *destination, struct wl_list *source) { - struct wl_client *client; + wl_list_insert_list (destination, source); + wl_list_init (source); +} - if (!surface) - return NULL; - - if (!surface->resource) - return NULL; - - client = wl_resource_get_client (surface->resource); - - return wl_resource_find_for_client (list, client); +static void +move_resources_for_client (struct wl_list *destination, + struct wl_list *source, + struct wl_client *client) +{ + struct wl_resource *resource, *tmp; + wl_resource_for_each_safe (resource, tmp, source) + { + if (wl_resource_get_client (resource) == client) + { + wl_list_remove (wl_resource_get_link (resource)); + wl_list_insert (destination, wl_resource_get_link (resource)); + } + } } static void @@ -256,10 +268,13 @@ default_grab_modifiers (MetaWaylandKeyboardGrab *grab, uint32_t serial, uint32_t mods_locked, uint32_t group) { MetaWaylandKeyboard *keyboard = grab->keyboard; + struct wl_resource *resource; + struct wl_list *l; - if (keyboard->focus_resource) + l = &keyboard->focus_resource_list; + wl_resource_for_each (resource, l) { - wl_keyboard_send_modifiers (keyboard->focus_resource, serial, mods_depressed, + wl_keyboard_send_modifiers (resource, serial, mods_depressed, mods_latched, mods_locked, group); } } @@ -278,6 +293,7 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard, keyboard->xkb_info.keymap_fd = -1; wl_list_init (&keyboard->resource_list); + wl_list_init (&keyboard->focus_resource_list); wl_array_init (&keyboard->keys); keyboard->focus_surface_listener.notify = keyboard_handle_focus_surface_destroy; @@ -418,19 +434,27 @@ void meta_wayland_keyboard_set_focus (MetaWaylandKeyboard *keyboard, MetaWaylandSurface *surface) { - if (keyboard->focus_surface == surface && keyboard->focus_resource != NULL) + if (keyboard->focus_surface == surface && !wl_list_empty (&keyboard->focus_resource_list)) return; if (keyboard->focus_surface != NULL) { - if (keyboard->focus_resource) + struct wl_resource *resource; + struct wl_list *l; + + l = &keyboard->focus_resource_list; + if (!wl_list_empty (l)) { struct wl_client *client = wl_resource_get_client (keyboard->focus_surface->resource); struct wl_display *display = wl_client_get_display (client); uint32_t serial = wl_display_next_serial (display); - wl_keyboard_send_leave (keyboard->focus_resource, serial, keyboard->focus_surface->resource); - keyboard->focus_resource = NULL; + wl_resource_for_each (resource, l) + { + wl_keyboard_send_leave (resource, serial, keyboard->focus_surface->resource); + } + + move_resources (&keyboard->resource_list, &keyboard->focus_resource_list); } wl_list_remove (&keyboard->focus_surface_listener.link); @@ -439,24 +463,34 @@ meta_wayland_keyboard_set_focus (MetaWaylandKeyboard *keyboard, if (surface != NULL) { + struct wl_resource *resource; + struct wl_list *l; + keyboard->focus_surface = surface; wl_resource_add_destroy_listener (keyboard->focus_surface->resource, &keyboard->focus_surface_listener); - keyboard->focus_resource = find_resource_for_surface (&keyboard->resource_list, surface); - if (keyboard->focus_resource) + move_resources_for_client (&keyboard->focus_resource_list, + &keyboard->resource_list, + wl_resource_get_client (keyboard->focus_surface->resource)); + + l = &keyboard->focus_resource_list; + if (!wl_list_empty (l)) { struct wl_client *client = wl_resource_get_client (keyboard->focus_surface->resource); struct wl_display *display = wl_client_get_display (client); struct xkb_state *state = keyboard->xkb_info.state; uint32_t serial = wl_display_next_serial (display); - wl_keyboard_send_modifiers (keyboard->focus_resource, serial, - xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED), - xkb_state_serialize_mods (state, XKB_STATE_MODS_LATCHED), - xkb_state_serialize_mods (state, XKB_STATE_MODS_LOCKED), - xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_EFFECTIVE)); - wl_keyboard_send_enter (keyboard->focus_resource, serial, keyboard->focus_surface->resource, - &keyboard->keys); + wl_resource_for_each (resource, l) + { + wl_keyboard_send_modifiers (resource, serial, + xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED), + xkb_state_serialize_mods (state, XKB_STATE_MODS_LATCHED), + xkb_state_serialize_mods (state, XKB_STATE_MODS_LOCKED), + xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_EFFECTIVE)); + wl_keyboard_send_enter (resource, serial, keyboard->focus_surface->resource, + &keyboard->keys); + } keyboard->focus_serial = serial; } diff --git a/src/wayland/meta-wayland-keyboard.h b/src/wayland/meta-wayland-keyboard.h index f67d02f67..38011c980 100644 --- a/src/wayland/meta-wayland-keyboard.h +++ b/src/wayland/meta-wayland-keyboard.h @@ -78,10 +78,10 @@ typedef struct struct _MetaWaylandKeyboard { struct wl_list resource_list; + struct wl_list focus_resource_list; MetaWaylandSurface *focus_surface; struct wl_listener focus_surface_listener; - struct wl_resource *focus_resource; uint32_t focus_serial; MetaWaylandKeyboardGrab *grab; diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c index 7ed2255f7..f5535a6b1 100644 --- a/src/wayland/meta-wayland-pointer.c +++ b/src/wayland/meta-wayland-pointer.c @@ -60,7 +60,6 @@ pointer_handle_focus_surface_destroy (struct wl_listener *listener, void *data) MetaWaylandPointer *pointer = wl_container_of (listener, pointer, focus_surface_listener); pointer->focus_surface = NULL; - pointer->focus_resource = NULL; } static void @@ -81,9 +80,10 @@ default_grab_motion (MetaWaylandPointerGrab *grab, { MetaWaylandPointer *pointer = grab->pointer; struct wl_resource *resource; + struct wl_list *l; - resource = pointer->focus_resource; - if (resource) + l = &pointer->focus_resource_list; + wl_resource_for_each(resource, l) { wl_fixed_t sx, sy; @@ -100,12 +100,13 @@ default_grab_button (MetaWaylandPointerGrab *grab, { MetaWaylandPointer *pointer = grab->pointer; struct wl_resource *resource; + struct wl_list *l; ClutterEventType event_type; event_type = clutter_event_type (event); - resource = pointer->focus_resource; - if (resource) + l = &grab->pointer->focus_resource_list; + wl_resource_for_each(resource, l) { struct wl_client *client = wl_resource_get_client (pointer->focus_surface->resource); struct wl_display *display = wl_client_get_display (client); @@ -256,6 +257,7 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer) memset (pointer, 0, sizeof *pointer); wl_list_init (&pointer->resource_list); + wl_list_init (&pointer->focus_resource_list); pointer->focus_surface_listener.notify = pointer_handle_focus_surface_destroy; @@ -288,37 +290,54 @@ meta_wayland_pointer_release (MetaWaylandPointer *pointer) /* Do nothing. */ } -static struct wl_resource * -find_resource_for_surface (struct wl_list *list, MetaWaylandSurface *surface) +static void +move_resources (struct wl_list *destination, struct wl_list *source) { - struct wl_client *client; + wl_list_insert_list (destination, source); + wl_list_init (source); +} - if (!surface) - return NULL; - - g_assert (surface->resource); - client = wl_resource_get_client (surface->resource); - - return wl_resource_find_for_client (list, client); +static void +move_resources_for_client (struct wl_list *destination, + struct wl_list *source, + struct wl_client *client) +{ + struct wl_resource *resource, *tmp; + wl_resource_for_each_safe (resource, tmp, source) + { + if (wl_resource_get_client (resource) == client) + { + wl_list_remove (wl_resource_get_link (resource)); + wl_list_insert (destination, wl_resource_get_link (resource)); + } + } } void meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer, MetaWaylandSurface *surface) { - if (pointer->focus_surface == surface && pointer->focus_resource != NULL) + if (pointer->focus_surface == surface && !wl_list_empty (&pointer->focus_resource_list)) return; if (pointer->focus_surface) { - if (pointer->focus_resource) + struct wl_resource *resource; + struct wl_list *l; + + l = &pointer->focus_resource_list; + if (!wl_list_empty (l)) { struct wl_client *client = wl_resource_get_client (pointer->focus_surface->resource); struct wl_display *display = wl_client_get_display (client); uint32_t serial = wl_display_next_serial (display); - wl_pointer_send_leave (pointer->focus_resource, serial, pointer->focus_surface->resource); - pointer->focus_resource = NULL; + wl_resource_for_each (resource, l) + { + wl_pointer_send_leave (resource, serial, pointer->focus_surface->resource); + } + + move_resources (&pointer->resource_list, &pointer->focus_resource_list); } wl_list_remove (&pointer->focus_surface_listener.link); @@ -327,6 +346,9 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer, if (surface != NULL) { + struct wl_resource *resource; + struct wl_list *l; + pointer->focus_surface = surface; wl_resource_add_destroy_listener (pointer->focus_surface->resource, &pointer->focus_surface_listener); @@ -336,19 +358,24 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer, wl_fixed_to_int (pointer->x), wl_fixed_to_int (pointer->y)); - pointer->focus_resource = find_resource_for_surface (&pointer->resource_list, surface); - if (pointer->focus_resource) + move_resources_for_client (&pointer->focus_resource_list, + &pointer->resource_list, + wl_resource_get_client (pointer->focus_surface->resource)); + + l = &pointer->focus_resource_list; + if (!wl_list_empty (l)) { struct wl_client *client = wl_resource_get_client (pointer->focus_surface->resource); struct wl_display *display = wl_client_get_display (client); uint32_t serial = wl_display_next_serial (display); - { - wl_fixed_t sx, sy; + wl_resource_for_each (resource, l) + { + wl_fixed_t sx, sy; - meta_wayland_pointer_get_relative_coordinates (pointer, pointer->focus_surface, &sx, &sy); - wl_pointer_send_enter (pointer->focus_resource, serial, pointer->focus_surface->resource, sx, sy); - } + meta_wayland_pointer_get_relative_coordinates (pointer, pointer->focus_surface, &sx, &sy); + wl_pointer_send_enter (resource, serial, pointer->focus_surface->resource, sx, sy); + } pointer->focus_serial = serial; } @@ -419,7 +446,6 @@ static void popup_grab_button (MetaWaylandPointerGrab *grab, const ClutterEvent *event) { - MetaWaylandPopupGrab *popup_grab = (MetaWaylandPopupGrab*)grab; MetaWaylandPointer *pointer = grab->pointer; if (pointer->focus_surface) diff --git a/src/wayland/meta-wayland-pointer.h b/src/wayland/meta-wayland-pointer.h index 98b536cb5..43c82fbb4 100644 --- a/src/wayland/meta-wayland-pointer.h +++ b/src/wayland/meta-wayland-pointer.h @@ -45,10 +45,10 @@ struct _MetaWaylandPointerGrab struct _MetaWaylandPointer { struct wl_list resource_list; + struct wl_list focus_resource_list; MetaWaylandSurface *focus_surface; struct wl_listener focus_surface_listener; - struct wl_resource *focus_resource; guint32 focus_serial; guint32 click_serial; diff --git a/src/wayland/meta-wayland-seat.c b/src/wayland/meta-wayland-seat.c index 24280d39a..3484d0879 100644 --- a/src/wayland/meta-wayland-seat.c +++ b/src/wayland/meta-wayland-seat.c @@ -301,13 +301,12 @@ static void handle_scroll_event (MetaWaylandSeat *seat, const ClutterEvent *event) { + struct wl_resource *resource; + struct wl_list *l; wl_fixed_t x_value = 0, y_value = 0; notify_motion (seat, event); - if (!seat->pointer.focus_resource) - return; - if (clutter_event_is_pointer_emulated (event)) return; @@ -342,12 +341,16 @@ handle_scroll_event (MetaWaylandSeat *seat, return; } - if (x_value) - wl_pointer_send_axis (seat->pointer.focus_resource, clutter_event_get_time (event), - WL_POINTER_AXIS_HORIZONTAL_SCROLL, x_value); - if (y_value) - wl_pointer_send_axis (seat->pointer.focus_resource, clutter_event_get_time (event), - WL_POINTER_AXIS_VERTICAL_SCROLL, y_value); + l = &seat->pointer.focus_resource_list; + wl_resource_for_each (resource, l) + { + if (x_value) + wl_pointer_send_axis (resource, clutter_event_get_time (event), + WL_POINTER_AXIS_HORIZONTAL_SCROLL, x_value); + if (y_value) + wl_pointer_send_axis (resource, clutter_event_get_time (event), + WL_POINTER_AXIS_VERTICAL_SCROLL, y_value); + } } static int