From 672696f82396c4229ddd76c4a718697ef0c85f4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= Date: Wed, 23 Feb 2022 16:09:28 +0100 Subject: [PATCH] dnd: Notify about events during compositor grab from event filter Since the introduction of ClutterGrabs, MetaDnd now no longer gets notified about input events on the stage during grabs (for example while the alt-tab popup is shown) and thus can't move the grab feedback actor anymore. To fix this, forward events to MetaDnD directly from meta_display_handle_event() when a ClutterGrab is in effect. Part-of: --- src/backends/meta-dnd-private.h | 3 + src/compositor/meta-dnd.c | 92 ++++++++++++-------------- src/core/events.c | 6 ++ src/wayland/meta-wayland-data-device.c | 2 +- src/wayland/meta-wayland-data-device.h | 2 +- 5 files changed, 53 insertions(+), 52 deletions(-) diff --git a/src/backends/meta-dnd-private.h b/src/backends/meta-dnd-private.h index 0cfb3d788..a4cb37220 100644 --- a/src/backends/meta-dnd-private.h +++ b/src/backends/meta-dnd-private.h @@ -36,6 +36,9 @@ void meta_dnd_init_xdnd (MetaX11Display *x11_display); #ifdef HAVE_WAYLAND void meta_dnd_wayland_handle_begin_modal (MetaCompositor *compositor); void meta_dnd_wayland_handle_end_modal (MetaCompositor *compositor); + +void meta_dnd_wayland_maybe_handle_event (MetaDnd *dnd, + const ClutterEvent *event); #endif #endif /* META_DND_PRIVATE_H */ diff --git a/src/compositor/meta-dnd.c b/src/compositor/meta-dnd.c index 8461690a2..0edc797e7 100644 --- a/src/compositor/meta-dnd.c +++ b/src/compositor/meta-dnd.c @@ -46,10 +46,7 @@ typedef struct _MetaDndPrivate MetaDndPrivate; struct _MetaDndPrivate { #ifdef HAVE_WAYLAND - gulong handler_id[3]; - - MetaCompositor *compositor; - MetaWaylandCompositor *wl_compositor; + gboolean dnd_during_modal; #else /* to avoid warnings (g_type_class_add_private: assertion `private_size > 0' failed) */ gchar dummy; @@ -230,54 +227,73 @@ meta_dnd_handle_xdnd_event (MetaBackend *backend, #ifdef HAVE_WAYLAND static void -meta_dnd_wayland_on_motion_event (ClutterActor *actor, - ClutterEvent *event, - MetaDnd *dnd) +meta_dnd_wayland_on_motion_event (MetaDnd *dnd, + const ClutterEvent *event) { - MetaDndPrivate *priv = meta_dnd_get_instance_private (dnd); MetaWaylandDragGrab *current_grab; gfloat event_x, event_y; + MetaWaylandCompositor *wl_compositor = meta_wayland_compositor_get_default (); g_return_if_fail (event != NULL); clutter_event_get_coords (event, &event_x, &event_y); meta_dnd_notify_dnd_position_change (dnd, (int)event_x, (int)event_y); - current_grab = meta_wayland_data_device_get_current_grab (&priv->wl_compositor->seat->data_device); + current_grab = meta_wayland_data_device_get_current_grab (&wl_compositor->seat->data_device); if (current_grab) meta_wayland_drag_grab_update_feedback_actor (current_grab, event); } static void -meta_dnd_wayland_end_notify (ClutterActor *actor, - ClutterEvent *event, - MetaDnd *dnd) +meta_dnd_wayland_end_notify (MetaDnd *dnd) { MetaDndPrivate *priv = meta_dnd_get_instance_private (dnd); + MetaWaylandCompositor *wl_compositor = meta_wayland_compositor_get_default (); - meta_wayland_data_device_end_drag (&priv->wl_compositor->seat->data_device); - meta_dnd_wayland_handle_end_modal (priv->compositor); + meta_wayland_data_device_end_drag (&wl_compositor->seat->data_device); + + priv->dnd_during_modal = FALSE; + + meta_dnd_notify_dnd_leave (dnd); } static void -meta_dnd_wayland_on_button_released (ClutterActor *actor, - ClutterEvent *event, - MetaDnd *dnd) +meta_dnd_wayland_on_button_released (MetaDnd *dnd, + const ClutterEvent *event) { - meta_dnd_wayland_end_notify (actor, event, dnd); + meta_dnd_wayland_end_notify (dnd); } static void -meta_dnd_wayland_on_key_pressed (ClutterActor *actor, - ClutterEvent *event, - MetaDnd *dnd) +meta_dnd_wayland_on_key_pressed (MetaDnd *dnd, + const ClutterEvent *event) { guint key = clutter_event_get_key_symbol (event); if (key != CLUTTER_KEY_Escape) return; - meta_dnd_wayland_end_notify (actor, event, dnd); + meta_dnd_wayland_end_notify (dnd); +} + +void +meta_dnd_wayland_maybe_handle_event (MetaDnd *dnd, + const ClutterEvent *event) +{ + MetaWaylandCompositor *wl_compositor = meta_wayland_compositor_get_default (); + MetaDndPrivate *priv = meta_dnd_get_instance_private (dnd); + + if (!meta_wayland_data_device_get_current_grab (&wl_compositor->seat->data_device)) + return; + + g_warn_if_fail (priv->dnd_during_modal); + + if (event->type == CLUTTER_MOTION) + meta_dnd_wayland_on_motion_event (dnd, event); + else if (event->type == CLUTTER_BUTTON_RELEASE) + meta_dnd_wayland_on_button_released (dnd, event); + else if (event->type == CLUTTER_KEY_PRESS) + meta_dnd_wayland_on_key_pressed (dnd, event); } void @@ -287,28 +303,10 @@ meta_dnd_wayland_handle_begin_modal (MetaCompositor *compositor) MetaDnd *dnd = meta_backend_get_dnd (meta_get_backend ()); MetaDndPrivate *priv = meta_dnd_get_instance_private (dnd); - if (priv->handler_id[0] == 0 && + if (!priv->dnd_during_modal && meta_wayland_data_device_get_current_grab (&wl_compositor->seat->data_device) != NULL) { - ClutterStage *stage = meta_compositor_get_stage (compositor); - - priv->compositor = compositor; - priv->wl_compositor = wl_compositor; - - priv->handler_id[0] = g_signal_connect (stage, - "motion-event", - G_CALLBACK (meta_dnd_wayland_on_motion_event), - dnd); - - priv->handler_id[1] = g_signal_connect (stage, - "button-release-event", - G_CALLBACK (meta_dnd_wayland_on_button_released), - dnd); - - priv->handler_id[2] = g_signal_connect (stage, - "key-press-event", - G_CALLBACK (meta_dnd_wayland_on_key_pressed), - dnd); + priv->dnd_during_modal = TRUE; meta_dnd_notify_dnd_enter (dnd); } @@ -319,17 +317,11 @@ meta_dnd_wayland_handle_end_modal (MetaCompositor *compositor) { MetaDnd *dnd = meta_backend_get_dnd (meta_get_backend ()); MetaDndPrivate *priv = meta_dnd_get_instance_private (dnd); - ClutterStage *stage = meta_compositor_get_stage (compositor); - unsigned int i; - if (!priv->compositor) + if (!priv->dnd_during_modal) return; - for (i = 0; i < G_N_ELEMENTS (priv->handler_id); i++) - g_clear_signal_handler (&priv->handler_id[i], stage); - - priv->compositor = NULL; - priv->wl_compositor = NULL; + priv->dnd_during_modal = FALSE; meta_dnd_notify_dnd_leave (dnd); } diff --git a/src/core/events.c b/src/core/events.c index 853c86f77..49c70194f 100644 --- a/src/core/events.c +++ b/src/core/events.c @@ -25,6 +25,7 @@ #include "core/events.h" #include "backends/meta-cursor-tracker-private.h" +#include "backends/meta-dnd-private.h" #include "backends/meta-idle-manager.h" #include "backends/x11/meta-backend-x11.h" #include "backends/x11/meta-input-device-x11.h" @@ -426,6 +427,11 @@ meta_display_handle_event (MetaDisplay *display, if (stage_has_grab (display)) { +#ifdef HAVE_WAYLAND + if (wayland_compositor) + meta_dnd_wayland_maybe_handle_event (meta_backend_get_dnd (backend), event); +#endif + bypass_wayland = TRUE; bypass_clutter = FALSE; goto out; diff --git a/src/wayland/meta-wayland-data-device.c b/src/wayland/meta-wayland-data-device.c index 2f3c154a1..c8cf8f5c4 100644 --- a/src/wayland/meta-wayland-data-device.c +++ b/src/wayland/meta-wayland-data-device.c @@ -304,7 +304,7 @@ meta_wayland_drag_grab_get_focus (MetaWaylandDragGrab *drag_grab) void meta_wayland_drag_grab_update_feedback_actor (MetaWaylandDragGrab *drag_grab, - ClutterEvent *event) + const ClutterEvent *event) { meta_feedback_actor_update (META_FEEDBACK_ACTOR (drag_grab->feedback_actor), event); diff --git a/src/wayland/meta-wayland-data-device.h b/src/wayland/meta-wayland-data-device.h index 840893389..6081433ee 100644 --- a/src/wayland/meta-wayland-data-device.h +++ b/src/wayland/meta-wayland-data-device.h @@ -86,6 +86,6 @@ void meta_wayland_drag_grab_set_focus (MetaWaylandDragGrab MetaWaylandSurface * meta_wayland_drag_grab_get_focus (MetaWaylandDragGrab *drag_grab); void meta_wayland_drag_grab_update_feedback_actor (MetaWaylandDragGrab *drag_grab, - ClutterEvent *event); + const ClutterEvent *event); #endif /* META_WAYLAND_DATA_DEVICE_H */