[mutter] dnd: Notify about events during compositor grab from event filter



commit 672696f82396c4229ddd76c4a718697ef0c85f4b
Author: Jonas Dreßler <verdre v0yd nl>
Date:   Wed Feb 23 16:09:28 2022 +0100

    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>

 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 0cfb3d7886..a4cb372207 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 8461690a26..0edc797e70 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,85 +227,86 @@ 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 (&wl_compositor->seat->data_device);
+
+  priv->dnd_during_modal = FALSE;
 
-  meta_wayland_data_device_end_drag (&priv->wl_compositor->seat->data_device);
-  meta_dnd_wayland_handle_end_modal (priv->compositor);
+  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_handle_begin_modal (MetaCompositor *compositor)
+meta_dnd_wayland_maybe_handle_event (MetaDnd            *dnd,
+                                     const ClutterEvent *event)
 {
   MetaWaylandCompositor *wl_compositor = meta_wayland_compositor_get_default ();
-  MetaDnd *dnd = meta_backend_get_dnd (meta_get_backend ());
   MetaDndPrivate *priv = meta_dnd_get_instance_private (dnd);
 
-  if (priv->handler_id[0] == 0 &&
-      meta_wayland_data_device_get_current_grab (&wl_compositor->seat->data_device) != NULL)
-    {
-      ClutterStage *stage = meta_compositor_get_stage (compositor);
+  if (!meta_wayland_data_device_get_current_grab (&wl_compositor->seat->data_device))
+    return;
 
-      priv->compositor = compositor;
-      priv->wl_compositor = wl_compositor;
+  g_warn_if_fail (priv->dnd_during_modal);
 
-      priv->handler_id[0] = g_signal_connect (stage,
-                                              "motion-event",
-                                              G_CALLBACK (meta_dnd_wayland_on_motion_event),
-                                              dnd);
+  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);
+}
 
-      priv->handler_id[1] = g_signal_connect (stage,
-                                              "button-release-event",
-                                              G_CALLBACK (meta_dnd_wayland_on_button_released),
-                                              dnd);
+void
+meta_dnd_wayland_handle_begin_modal (MetaCompositor *compositor)
+{
+  MetaWaylandCompositor *wl_compositor = meta_wayland_compositor_get_default ();
+  MetaDnd *dnd = meta_backend_get_dnd (meta_get_backend ());
+  MetaDndPrivate *priv = meta_dnd_get_instance_private (dnd);
 
-      priv->handler_id[2] = g_signal_connect (stage,
-                                              "key-press-event",
-                                              G_CALLBACK (meta_dnd_wayland_on_key_pressed),
-                                              dnd);
+  if (!priv->dnd_during_modal &&
+      meta_wayland_data_device_get_current_grab (&wl_compositor->seat->data_device) != NULL)
+    {
+      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 853c86f772..49c70194fc 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 2f3c154a1d..c8cf8f5c4b 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 8408933894..6081433ee0 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 */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]