From 80ed79a0d30e77e8e4d85a196f362869de7f0520 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Thu, 16 Nov 2023 14:09:55 +0100 Subject: [PATCH] wayland: Add default event interface handling seat events This is implemented at the MetaWaylandSeat level, and it governs focus and event delivery for all devices, falling through each of the MetaWaylandPointer/MetaWaylandKeyboard/etc components. Part-of: --- src/wayland/meta-wayland-pointer.c | 19 +++- src/wayland/meta-wayland-pointer.h | 2 + src/wayland/meta-wayland-seat.c | 155 ++++++++++++++++++++++++++++- src/wayland/meta-wayland-seat.h | 10 ++ 4 files changed, 178 insertions(+), 8 deletions(-) diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c index 4103b62bf..06e3cf713 100644 --- a/src/wayland/meta-wayland-pointer.c +++ b/src/wayland/meta-wayland-pointer.c @@ -303,6 +303,9 @@ sync_focus_surface (MetaWaylandPointer *pointer) { MetaBackend *backend = backend_from_pointer (pointer); ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend)); + MetaWaylandInputDevice *input_device = META_WAYLAND_INPUT_DEVICE (pointer); + MetaWaylandSeat *seat = meta_wayland_input_device_get_seat (input_device); + MetaWaylandInput *input; if (clutter_stage_get_grab_actor (stage) != NULL) { @@ -310,8 +313,8 @@ sync_focus_surface (MetaWaylandPointer *pointer) return; } - const MetaWaylandPointerGrabInterface *interface = pointer->grab->interface; - interface->focus (pointer->grab, pointer->current); + input = meta_wayland_seat_get_input (seat); + meta_wayland_input_invalidate_focus (input, pointer->device, NULL); } static void @@ -460,9 +463,6 @@ default_grab_focus (MetaWaylandPointerGrab *grab, if (clutter_stage_get_grab_actor (stage) != NULL) return; - if (pointer->button_count > 0) - return; - if (surface) { MetaWindow *window = NULL; @@ -1550,3 +1550,12 @@ meta_wayland_pointer_get_current_surface (MetaWaylandPointer *pointer) { return pointer->current; } + +MetaWaylandSurface * +meta_wayland_pointer_get_implicit_grab_surface (MetaWaylandPointer *pointer) +{ + if (pointer->button_count > 0) + return pointer->focus_surface; + + return NULL; +} diff --git a/src/wayland/meta-wayland-pointer.h b/src/wayland/meta-wayland-pointer.h index 9a64bad1b..5e64fe623 100644 --- a/src/wayland/meta-wayland-pointer.h +++ b/src/wayland/meta-wayland-pointer.h @@ -164,3 +164,5 @@ MetaWaylandSurface * meta_wayland_pointer_get_current_surface (MetaWaylandPointe void meta_wayland_pointer_focus_surface (MetaWaylandPointer *pointer, MetaWaylandSurface *surface); + +MetaWaylandSurface * meta_wayland_pointer_get_implicit_grab_surface (MetaWaylandPointer *pointer); diff --git a/src/wayland/meta-wayland-seat.c b/src/wayland/meta-wayland-seat.c index 35a389324..b3088a111 100644 --- a/src/wayland/meta-wayland-seat.c +++ b/src/wayland/meta-wayland-seat.c @@ -26,6 +26,9 @@ #include "wayland/meta-wayland-tablet-seat.h" #include "wayland/meta-wayland-versions.h" +static gboolean meta_wayland_seat_handle_event_internal (MetaWaylandSeat *seat, + const ClutterEvent *event); + #define CAPABILITY_ENABLED(prev, cur, capability) ((cur & (capability)) && !(prev & (capability))) #define CAPABILITY_DISABLED(prev, cur, capability) ((prev & (capability)) && !(cur & (capability))) @@ -189,6 +192,79 @@ meta_wayland_seat_devices_updated (ClutterSeat *clutter_seat, meta_wayland_seat_update_capabilities (seat, clutter_seat); } +static MetaWaylandSurface * +default_get_focus_surface (MetaWaylandEventHandler *handler, + ClutterInputDevice *device, + ClutterEventSequence *sequence, + gpointer user_data) +{ + MetaWaylandSeat *seat = user_data; + + return meta_wayland_seat_get_current_surface (seat, + device, + sequence); +} + +static void +default_focus (MetaWaylandEventHandler *handler, + ClutterInputDevice *device, + ClutterEventSequence *sequence, + MetaWaylandSurface *surface, + gpointer user_data) +{ + MetaWaylandSeat *seat = user_data; + ClutterInputCapabilities caps; + + caps = clutter_input_device_get_capabilities (device); + + if (caps & + (CLUTTER_INPUT_CAPABILITY_KEYBOARD | + CLUTTER_INPUT_CAPABILITY_TABLET_PAD)) + { + if (meta_wayland_seat_has_keyboard (seat)) + meta_wayland_keyboard_set_focus (seat->keyboard, surface); + + meta_wayland_data_device_set_keyboard_focus (&seat->data_device); + meta_wayland_data_device_primary_set_keyboard_focus (&seat->primary_data_device); + meta_wayland_tablet_seat_set_pad_focus (seat->tablet_seat, surface); + meta_wayland_text_input_set_focus (seat->text_input, surface); + } + + if (caps & CLUTTER_INPUT_CAPABILITY_TABLET_TOOL) + { + meta_wayland_tablet_seat_focus_surface (seat->tablet_seat, + device, + surface); + } + + if (caps & + (CLUTTER_INPUT_CAPABILITY_POINTER | + CLUTTER_INPUT_CAPABILITY_TOUCHPAD | + CLUTTER_INPUT_CAPABILITY_TRACKBALL | + CLUTTER_INPUT_CAPABILITY_TRACKPOINT)) + meta_wayland_pointer_focus_surface (seat->pointer, surface); +} + +static gboolean +default_handle_event (MetaWaylandEventHandler *handler, + const ClutterEvent *event, + gpointer user_data) +{ + MetaWaylandSeat *seat = user_data; + + return meta_wayland_seat_handle_event_internal (seat, event); +} + +static const MetaWaylandEventInterface default_event_interface = { + .get_focus_surface = default_get_focus_surface, + .focus = default_focus, + .motion = default_handle_event, + .press = default_handle_event, + .release = default_handle_event, + .key = default_handle_event, + .other = default_handle_event, +}; + static MetaWaylandSeat * meta_wayland_seat_new (MetaWaylandCompositor *compositor, struct wl_display *display) @@ -229,6 +305,11 @@ meta_wayland_seat_new (MetaWaylandCompositor *compositor, seat->tablet_seat = meta_wayland_tablet_manager_ensure_seat (compositor->tablet_manager, seat); + seat->input_handler = meta_wayland_input_new (seat); + seat->default_handler = + meta_wayland_input_attach_event_handler (seat->input_handler, + &default_event_interface, seat); + return seat; } @@ -244,6 +325,8 @@ meta_wayland_seat_free (MetaWaylandSeat *seat) { ClutterSeat *clutter_seat; + g_clear_object (&seat->input_handler); + clutter_seat = clutter_backend_get_default_seat (clutter_get_default_backend ()); g_signal_handlers_disconnect_by_data (clutter_seat, seat); meta_wayland_seat_set_capabilities (seat, 0); @@ -375,9 +458,9 @@ meta_wayland_seat_update (MetaWaylandSeat *seat, } } -gboolean -meta_wayland_seat_handle_event (MetaWaylandSeat *seat, - const ClutterEvent *event) +static gboolean +meta_wayland_seat_handle_event_internal (MetaWaylandSeat *seat, + const ClutterEvent *event) { ClutterEventType event_type; @@ -590,5 +673,71 @@ meta_wayland_seat_is_grabbed (MetaWaylandSeat *seat) meta_wayland_keyboard_is_grabbed (seat->keyboard)) return TRUE; + if (!meta_wayland_input_is_current_handler (seat->input_handler, + seat->default_handler)) + return TRUE; + return FALSE; } + +gboolean +meta_wayland_seat_handle_event (MetaWaylandSeat *seat, + const ClutterEvent *event) +{ + return meta_wayland_input_handle_event (seat->input_handler, event); +} + +MetaWaylandInput * +meta_wayland_seat_get_input (MetaWaylandSeat *seat) +{ + return seat->input_handler; +} + +MetaWaylandSurface * +meta_wayland_seat_get_current_surface (MetaWaylandSeat *seat, + ClutterInputDevice *device, + ClutterEventSequence *sequence) +{ + if (sequence) + { + return meta_wayland_touch_get_surface (seat->touch, sequence); + } + else + { + ClutterInputCapabilities caps; + + caps = clutter_input_device_get_capabilities (device); + + if (caps & + (CLUTTER_INPUT_CAPABILITY_KEYBOARD | + CLUTTER_INPUT_CAPABILITY_TABLET_PAD)) + return seat->input_focus; + + if (caps & CLUTTER_INPUT_CAPABILITY_TABLET_TOOL) + { + return meta_wayland_tablet_seat_get_current_surface (seat->tablet_seat, + device); + } + + if (caps & + (CLUTTER_INPUT_CAPABILITY_POINTER | + CLUTTER_INPUT_CAPABILITY_TOUCHPAD | + CLUTTER_INPUT_CAPABILITY_TRACKBALL | + CLUTTER_INPUT_CAPABILITY_TRACKPOINT)) + { + MetaWaylandSurface *implicit_grab_surface; + + implicit_grab_surface = + meta_wayland_pointer_get_implicit_grab_surface (seat->pointer); + + if (implicit_grab_surface && + meta_wayland_input_is_current_handler (seat->input_handler, + seat->default_handler)) + return implicit_grab_surface; + else + return meta_wayland_pointer_get_current_surface (seat->pointer); + } + } + + return NULL; +} diff --git a/src/wayland/meta-wayland-seat.h b/src/wayland/meta-wayland-seat.h index c4a012b60..807efa75a 100644 --- a/src/wayland/meta-wayland-seat.h +++ b/src/wayland/meta-wayland-seat.h @@ -24,6 +24,7 @@ #include "clutter/clutter.h" #include "wayland/meta-wayland-data-device.h" #include "wayland/meta-wayland-data-device-primary.h" +#include "wayland/meta-wayland-input.h" #include "wayland/meta-wayland-input-device.h" #include "wayland/meta-wayland-keyboard.h" #include "wayland/meta-wayland-pointer.h" @@ -49,6 +50,9 @@ struct _MetaWaylandSeat MetaWaylandTextInput *text_input; + MetaWaylandInput *input_handler; + MetaWaylandEventHandler *default_handler; + MetaWaylandSurface *input_focus; gulong input_focus_destroy_id; @@ -88,3 +92,9 @@ gboolean meta_wayland_seat_has_touch (MetaWaylandSeat *seat); MetaWaylandCompositor * meta_wayland_seat_get_compositor (MetaWaylandSeat *seat); gboolean meta_wayland_seat_is_grabbed (MetaWaylandSeat *seat); + +MetaWaylandInput * meta_wayland_seat_get_input (MetaWaylandSeat *seat); + +MetaWaylandSurface * meta_wayland_seat_get_current_surface (MetaWaylandSeat *seat, + ClutterInputDevice *device, + ClutterEventSequence *sequence);