From 1cb46f203cd2b0b0644d3aa323ecb007fab5b7d2 Mon Sep 17 00:00:00 2001 From: Nick Diego Yamane Date: Thu, 21 Nov 2024 10:53:11 -0300 Subject: [PATCH] wayland/xdg-toplevel-drag: Support non-grabbing mode in MetaWindowDrag - This adds a new ClutterActor parameter to meta_compositor_drag_window and meta_window_drag_begin such that it's possible to inject an external grab actor, which is then used to implement a "non-grabbing" mode that allow a MetaWindowDrag to be used in conjunction, for example, with a Wayland drag-and-drop session; - This new API is going to be used to implement the toplevel drag protocol in a subsequent commit. Signed-off-by: Nick Diego Yamane Part-of: --- src/compositor/compositor-private.h | 3 +- src/compositor/compositor.c | 6 ++- src/compositor/meta-window-drag.c | 75 ++++++++++++++++++++--------- src/compositor/meta-window-drag.h | 3 +- src/core/window.c | 2 +- 5 files changed, 61 insertions(+), 28 deletions(-) diff --git a/src/compositor/compositor-private.h b/src/compositor/compositor-private.h index e9b11f1b4..b1f465c01 100644 --- a/src/compositor/compositor-private.h +++ b/src/compositor/compositor-private.h @@ -79,7 +79,8 @@ gboolean meta_compositor_drag_window (MetaCompositor *compositor, ClutterInputDevice *device, ClutterEventSequence *sequence, uint32_t timestamp, - graphene_point_t *pos_hint); + graphene_point_t *pos_hint, + ClutterActor *grab_actor); MetaWindowDrag * meta_compositor_get_current_window_drag (MetaCompositor *compositor); diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c index 7b3ca5111..e0b44a47e 100644 --- a/src/compositor/compositor.c +++ b/src/compositor/compositor.c @@ -1587,7 +1587,8 @@ meta_compositor_drag_window (MetaCompositor *compositor, ClutterInputDevice *device, ClutterEventSequence *sequence, uint32_t timestamp, - graphene_point_t *pos_hint) + graphene_point_t *pos_hint, + ClutterActor *grab_actor) { MetaCompositorPrivate *priv = meta_compositor_get_instance_private (compositor); @@ -1603,7 +1604,8 @@ meta_compositor_drag_window (MetaCompositor *compositor, priv->current_drag = g_steal_pointer (&window_drag); - if (!meta_window_drag_begin (priv->current_drag, device, sequence, timestamp)) + if (!meta_window_drag_begin (priv->current_drag, device, + sequence, timestamp, grab_actor)) { g_clear_object (&priv->current_drag); return FALSE; diff --git a/src/compositor/meta-window-drag.c b/src/compositor/meta-window-drag.c index 04391b613..2d1412330 100644 --- a/src/compositor/meta-window-drag.c +++ b/src/compositor/meta-window-drag.c @@ -79,6 +79,7 @@ struct _MetaWindowDrag { gulong unmanaged_id; gulong size_changed_id; + gulong event_handler_id; guint tile_preview_timeout_id; guint preview_tile_mode : 2; @@ -175,14 +176,24 @@ hide_tile_preview (MetaWindowDrag *window_drag) meta_compositor_hide_tile_preview (window->display->compositor); } +static gboolean +owns_grab_actor (MetaWindowDrag *window_drag) +{ + g_assert (META_IS_WINDOW_DRAG (window_drag)); + return window_drag->grab != NULL; +} + static void meta_window_drag_finalize (GObject *object) { MetaWindowDrag *window_drag = META_WINDOW_DRAG (object); hide_tile_preview (window_drag); - g_clear_pointer (&window_drag->handler, clutter_actor_destroy); - g_clear_object (&window_drag->grab); + if (owns_grab_actor (window_drag)) + { + g_clear_pointer (&window_drag->handler, clutter_actor_destroy); + g_clear_object (&window_drag->grab); + } g_clear_object (&window_drag->effective_grab_window); G_OBJECT_CLASS (meta_window_drag_parent_class)->finalize (object); @@ -387,7 +398,11 @@ meta_window_drag_end (MetaWindowDrag *window_drag) meta_window_grab_op_ended (grab_window, grab_op); - clutter_grab_dismiss (window_drag->grab); + if (owns_grab_actor (window_drag)) + clutter_grab_dismiss (window_drag->grab); + else + g_clear_signal_handler (&window_drag->event_handler_id, + window_drag->handler); g_clear_signal_handler (&window_drag->unmanaged_id, grab_window); g_clear_signal_handler (&window_drag->size_changed_id, grab_window); @@ -1780,7 +1795,8 @@ gboolean meta_window_drag_begin (MetaWindowDrag *window_drag, ClutterInputDevice *device, ClutterEventSequence *sequence, - uint32_t timestamp) + uint32_t timestamp, + ClutterActor *grab_actor) { MetaWindow *window = window_drag->window, *grab_window = NULL; MetaDisplay *display = meta_window_get_display (window); @@ -1845,26 +1861,39 @@ meta_window_drag_begin (MetaWindowDrag *window_drag, stage = meta_backend_get_stage (backend); - window_drag->handler = clutter_actor_new (); - clutter_actor_hide (window_drag->handler); - clutter_actor_set_name (window_drag->handler, - "Window drag helper"); - clutter_actor_set_accessible_name (window_drag->handler, - "Window drag helper"); - g_signal_connect_swapped (window_drag->handler, "event", - G_CALLBACK (on_window_drag_event), window_drag); - clutter_actor_add_child (stage, window_drag->handler); - - window_drag->grab = clutter_stage_grab (CLUTTER_STAGE (stage), - window_drag->handler); - - if ((clutter_grab_get_seat_state (window_drag->grab) & - CLUTTER_GRAB_STATE_POINTER) == 0 && - !meta_grab_op_is_keyboard (grab_op)) + if (grab_actor) { - meta_topic (META_DEBUG_WINDOW_OPS, - "Pointer grab failed on a pointer grab op"); - return FALSE; + meta_topic (META_DEBUG_WINDOW_OPS, "Reusing grab actor %p.", grab_actor); + window_drag->handler = grab_actor; + window_drag->event_handler_id = + g_signal_connect_swapped (window_drag->handler, "event", + G_CALLBACK (on_window_drag_event), window_drag); + } + else + { + meta_topic (META_DEBUG_WINDOW_OPS, "Creating a new grab."); + window_drag->handler = clutter_actor_new (); + clutter_actor_hide (window_drag->handler); + clutter_actor_set_name (window_drag->handler, + "Window drag helper"); + clutter_actor_set_accessible_name (window_drag->handler, + "Window drag helper"); + window_drag->event_handler_id = + g_signal_connect_swapped (window_drag->handler, "event", + G_CALLBACK (on_window_drag_event), window_drag); + clutter_actor_add_child (stage, window_drag->handler); + + window_drag->grab = clutter_stage_grab (CLUTTER_STAGE (stage), + window_drag->handler); + + if ((clutter_grab_get_seat_state (window_drag->grab) & + CLUTTER_GRAB_STATE_POINTER) == 0 && + !meta_grab_op_is_keyboard (grab_op)) + { + meta_topic (META_DEBUG_WINDOW_OPS, + "Pointer grab failed on a pointer grab op"); + return FALSE; + } } /* Temporarily release the passive key grabs on the window */ diff --git a/src/compositor/meta-window-drag.h b/src/compositor/meta-window-drag.h index 5fac435b7..c6b51f808 100644 --- a/src/compositor/meta-window-drag.h +++ b/src/compositor/meta-window-drag.h @@ -32,7 +32,8 @@ MetaWindowDrag * meta_window_drag_new (MetaWindow *window, gboolean meta_window_drag_begin (MetaWindowDrag *drag, ClutterInputDevice *device, ClutterEventSequence *sequence, - uint32_t timestamp); + uint32_t timestamp, + ClutterActor *grab_actor); void meta_window_drag_end (MetaWindowDrag *drag); diff --git a/src/core/window.c b/src/core/window.c index 50f4d6aba..bf9bfd332 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -6149,7 +6149,7 @@ meta_window_begin_grab_op (MetaWindow *window, window, op, device, sequence, timestamp, - pos_hint); + pos_hint, NULL); } MetaStackLayer