From c1d157e13692a521375dce3b47bd6b9257247cfc Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Tue, 10 May 2016 17:29:57 +0200 Subject: [PATCH] wayland: Add focus management to pads All pads will share the same focus than the keyboard, so this means that: - The focus changes in-sync for keyboard and all pad devices, and - Newly plugged pads will be immediately focused on that same surface --- src/wayland/meta-wayland-seat.c | 15 +++-- src/wayland/meta-wayland-tablet-pad.c | 88 ++++++++++++++++++++++++++ src/wayland/meta-wayland-tablet-seat.c | 35 ++++++++++ src/wayland/meta-wayland-tablet-seat.h | 3 + 4 files changed, 137 insertions(+), 4 deletions(-) diff --git a/src/wayland/meta-wayland-seat.c b/src/wayland/meta-wayland-seat.c index 9a7fa2e92..a235a81ec 100644 --- a/src/wayland/meta-wayland-seat.c +++ b/src/wayland/meta-wayland-seat.c @@ -26,6 +26,7 @@ #include "meta-wayland-private.h" #include "meta-wayland-versions.h" #include "meta-wayland-data-device.h" +#include "meta-wayland-tablet-seat.h" #define CAPABILITY_ENABLED(prev, cur, capability) ((cur & (capability)) && !(prev & (capability))) #define CAPABILITY_DISABLED(prev, cur, capability) ((prev & (capability)) && !(cur & (capability))) @@ -369,11 +370,17 @@ void meta_wayland_seat_set_input_focus (MetaWaylandSeat *seat, MetaWaylandSurface *surface) { - if ((seat->capabilities & WL_SEAT_CAPABILITY_KEYBOARD) == 0) - return; + MetaWaylandTabletSeat *tablet_seat; + MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - meta_wayland_keyboard_set_focus (&seat->keyboard, surface); - meta_wayland_data_device_set_keyboard_focus (&seat->data_device); + if ((seat->capabilities & WL_SEAT_CAPABILITY_KEYBOARD) != 0) + { + meta_wayland_keyboard_set_focus (&seat->keyboard, surface); + meta_wayland_data_device_set_keyboard_focus (&seat->data_device); + } + + tablet_seat = meta_wayland_tablet_manager_ensure_seat (compositor->tablet_manager, seat); + meta_wayland_tablet_seat_set_pad_focus (tablet_seat, surface); } gboolean diff --git a/src/wayland/meta-wayland-tablet-pad.c b/src/wayland/meta-wayland-tablet-pad.c index c83169ff6..0b4a2283f 100644 --- a/src/wayland/meta-wayland-tablet-pad.c +++ b/src/wayland/meta-wayland-tablet-pad.c @@ -32,6 +32,8 @@ #include "meta-surface-actor-wayland.h" #include "meta-wayland-private.h" +#include "meta-wayland-tablet-seat.h" +#include "meta-wayland-tablet.h" #include "meta-wayland-tablet-pad.h" #include "meta-wayland-tablet-pad-group.h" #include "meta-wayland-tablet-pad-ring.h" @@ -295,8 +297,94 @@ meta_wayland_tablet_pad_update_groups_focus (MetaWaylandTabletPad *pad) meta_wayland_tablet_pad_group_sync_focus (l->data); } +static void +meta_wayland_tablet_pad_broadcast_enter (MetaWaylandTabletPad *pad, + uint32_t serial, + MetaWaylandTablet *tablet, + MetaWaylandSurface *surface) +{ + struct wl_resource *resource, *tablet_resource; + struct wl_client *client; + + client = wl_resource_get_client (pad->focus_surface->resource); + tablet_resource = meta_wayland_tablet_lookup_resource (tablet, client); + + wl_resource_for_each (resource, &pad->focus_resource_list) + { + zwp_tablet_pad_v2_send_enter (resource, serial, + tablet_resource, + surface->resource); + } +} + +static void +meta_wayland_tablet_pad_broadcast_leave (MetaWaylandTabletPad *pad, + uint32_t serial, + MetaWaylandSurface *surface) +{ + struct wl_resource *resource; + + wl_resource_for_each (resource, &pad->focus_resource_list) + { + zwp_tablet_pad_v2_send_leave (resource, serial, + surface->resource); + } +} + void meta_wayland_tablet_pad_set_focus (MetaWaylandTabletPad *pad, MetaWaylandSurface *surface) { + MetaWaylandTablet *tablet; + + if (pad->focus_surface == surface) + return; + + g_hash_table_remove_all (pad->feedback); + + if (pad->focus_surface != NULL) + { + struct wl_client *client = wl_resource_get_client (pad->focus_surface->resource); + struct wl_list *focus_resources = &pad->focus_resource_list; + + if (!wl_list_empty (focus_resources)) + { + struct wl_display *display = wl_client_get_display (client); + uint32_t serial = wl_display_next_serial (display); + + meta_wayland_tablet_pad_broadcast_leave (pad, serial, + pad->focus_surface); + move_resources (&pad->resource_list, &pad->focus_resource_list); + } + + wl_list_remove (&pad->focus_surface_listener.link); + pad->focus_surface = NULL; + } + + tablet = meta_wayland_tablet_seat_lookup_paired_tablet (pad->tablet_seat, + pad); + + if (tablet != NULL && surface != NULL) + { + struct wl_client *client; + + pad->focus_surface = surface; + wl_resource_add_destroy_listener (pad->focus_surface->resource, + &pad->focus_surface_listener); + + client = wl_resource_get_client (pad->focus_surface->resource); + move_resources_for_client (&pad->focus_resource_list, + &pad->resource_list, client); + + if (!wl_list_empty (&pad->focus_resource_list)) + { + struct wl_display *display = wl_client_get_display (client); + + pad->focus_serial = wl_display_next_serial (display); + meta_wayland_tablet_pad_broadcast_enter (pad, pad->focus_serial, + tablet, pad->focus_surface); + } + } + + meta_wayland_tablet_pad_update_groups_focus (pad); } diff --git a/src/wayland/meta-wayland-tablet-seat.c b/src/wayland/meta-wayland-tablet-seat.c index 7b9a07e37..3bf42c5cf 100644 --- a/src/wayland/meta-wayland-tablet-seat.c +++ b/src/wayland/meta-wayland-tablet-seat.c @@ -36,6 +36,11 @@ #include "meta-wayland-tablet-tool.h" #include "meta-wayland-tablet-pad.h" +#ifdef HAVE_NATIVE_BACKEND +#include +#include "backends/native/meta-backend-native.h" +#endif + static void unbind_resource (struct wl_resource *resource) { @@ -199,13 +204,28 @@ static void meta_wayland_tablet_seat_device_added (MetaWaylandTabletSeat *tablet_seat, ClutterInputDevice *device) { + MetaWaylandSurface *pad_focus = tablet_seat->seat->keyboard.focus_surface; + if (is_tablet_device (device)) { MetaWaylandTablet *tablet; + GList *pads, *l; tablet = meta_wayland_tablet_new (device, tablet_seat); g_hash_table_insert (tablet_seat->tablets, device, tablet); broadcast_tablet_added (tablet_seat, device); + + /* Because the insertion order is undefined, there might be already + * pads that are logically paired to this tablet. Look those up and + * refocus them. + */ + pads = meta_wayland_tablet_seat_lookup_paired_pads (tablet_seat, + tablet); + + for (l = pads; l; l = l->next) + meta_wayland_tablet_pad_set_focus (l->data, pad_focus); + + g_list_free (pads); } else if (is_pad_device (device)) { @@ -214,6 +234,8 @@ meta_wayland_tablet_seat_device_added (MetaWaylandTabletSeat *tablet_seat, pad = meta_wayland_tablet_pad_new (device, tablet_seat); g_hash_table_insert (tablet_seat->pads, device, pad); broadcast_pad_added (tablet_seat, device); + + meta_wayland_tablet_pad_set_focus (pad, pad_focus); } } @@ -524,3 +546,16 @@ meta_wayland_tablet_seat_lookup_paired_pads (MetaWaylandTabletSeat *tablet_seat, return pads; } + +void +meta_wayland_tablet_seat_set_pad_focus (MetaWaylandTabletSeat *tablet_seat, + MetaWaylandSurface *surface) +{ + MetaWaylandTabletPad *pad; + GHashTableIter iter; + + g_hash_table_iter_init (&iter, tablet_seat->pads); + + while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &pad)) + meta_wayland_tablet_pad_set_focus (pad, surface); +} diff --git a/src/wayland/meta-wayland-tablet-seat.h b/src/wayland/meta-wayland-tablet-seat.h index 98ce4a956..e923f936e 100644 --- a/src/wayland/meta-wayland-tablet-seat.h +++ b/src/wayland/meta-wayland-tablet-seat.h @@ -69,6 +69,9 @@ void meta_wayland_tablet_seat_notify_tool (MetaWayland MetaWaylandTabletTool *tool, struct wl_client *client); +void meta_wayland_tablet_seat_set_pad_focus (MetaWaylandTabletSeat *tablet_seat, + MetaWaylandSurface *surface); + MetaWaylandTablet *meta_wayland_tablet_seat_lookup_paired_tablet (MetaWaylandTabletSeat *tablet_seat, MetaWaylandTabletPad *pad); GList *meta_wayland_tablet_seat_lookup_paired_pads (MetaWaylandTabletSeat *tablet_seat,