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: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2308>
This commit is contained in:
Jonas Dreßler 2022-02-23 16:09:28 +01:00 committed by Marge Bot
parent 8a11069dca
commit 672696f823
5 changed files with 53 additions and 52 deletions

View File

@ -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 */

View File

@ -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);
}

View File

@ -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;

View File

@ -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);

View File

@ -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 */