From 0111f0de144953b0f8b54a457571c7bddaf83cad Mon Sep 17 00:00:00 2001 From: Nick Diego Yamane Date: Thu, 21 Nov 2024 11:50:58 -0300 Subject: [PATCH] wayland/xdg-toplevel-drag: Plumb xdg-toplevel-drag to core/compositor - Event stream adaptations. When there is a toplevel-drag in place, do: - Send wl_data_source.dnd_finished and end the session successfully - Send wl_data_source.cancelled and end the MetaWindowDrag when ESC key is pressed. - Modify MetaWaylandDataDevice such that, when a toplevel-drag is running, it does: - Propagate motion events, so that they can be processed further by MetaWindowDrag. - Ends the associated MetaWindowDrag upon release event. - Hook up the window mapping process in MetaWindowWayand, such that: - the initial position of the window attached to the ongoing toplevel-drag instance can be calculated and set. - the appropriate gravity and flags can be set when calling MetaWindow's meta_window_move_resize_internal, which allows it for example to be moved freely (unconstrained) as per current dragging cursor. Status: - [x] Basic window drag triggering - [x] Exclude the dragged window from event targets - [x] Event forwarding (window drag vs wayland grabs) - [x] Offset calc relative to toplevel geometry - [x] Attach already mapped windows - [x] Properly support not-yet-mapped windows - [x] Disable visibility change animations - [x] Dnd events stream adaptations Signed-off-by: Nick Diego Yamane Part-of: --- src/wayland/meta-wayland-data-device.c | 45 ++++++++++++++++++++++++-- src/wayland/meta-wayland-data-device.h | 3 ++ src/wayland/meta-window-wayland.c | 35 ++++++++++++++++++++ 3 files changed, 81 insertions(+), 2 deletions(-) diff --git a/src/wayland/meta-wayland-data-device.c b/src/wayland/meta-wayland-data-device.c index c05686484..270ada302 100644 --- a/src/wayland/meta-wayland-data-device.c +++ b/src/wayland/meta-wayland-data-device.c @@ -36,14 +36,20 @@ #include "backends/meta-dnd-private.h" #include "compositor/meta-dnd-actor-private.h" +#include "compositor/meta-surface-actor.h" +#include "compositor/meta-window-drag.h" #include "core/meta-selection-private.h" +#include "meta/meta-debug.h" #include "meta/meta-selection-source-memory.h" +#include "meta/meta-wayland-surface.h" #include "wayland/meta-selection-source-wayland-private.h" +#include "wayland/meta-wayland-data-source.h" #include "wayland/meta-wayland-dnd-surface.h" #include "wayland/meta-wayland-pointer.h" #include "wayland/meta-wayland-private.h" #include "wayland/meta-wayland-seat.h" #include "wayland/meta-wayland-toplevel-drag.h" +#include "wayland/meta-wayland-types.h" #define ROOTWINDOW_DROP_MIME "application/x-rootwindow-drop" @@ -510,6 +516,12 @@ data_device_update_position (MetaWaylandDragGrab *drag_grab, meta_wayland_surface_set_main_monitor (drag_grab->drag_surface, monitor); } +static gboolean +is_dragging_window (MetaWaylandSeat *seat) +{ + return meta_wayland_data_device_get_toplevel_drag (&seat->data_device) != NULL; +} + static gboolean drag_grab_motion (MetaWaylandEventHandler *handler, const ClutterEvent *event, @@ -540,7 +552,7 @@ drag_grab_motion (MetaWaylandEventHandler *handler, meta_dnd_wayland_on_motion_event (meta_backend_get_dnd (backend), event); - return CLUTTER_EVENT_STOP; + return !is_dragging_window (drag_grab->seat); } static gboolean @@ -551,6 +563,7 @@ drag_grab_release (MetaWaylandEventHandler *handler, MetaWaylandDragGrab *drag_grab = user_data; MetaWaylandSeat *seat = drag_grab->seat; MetaWaylandDataSource *source = drag_grab->drag_data_source; + MetaWaylandToplevelDrag *toplevel_drag; gboolean success; if (drag_grab->device != clutter_event_get_device (event) || @@ -565,12 +578,22 @@ drag_grab_release (MetaWaylandEventHandler *handler, CLUTTER_BUTTON5_MASK)) > 1) return CLUTTER_EVENT_STOP; + toplevel_drag = meta_wayland_data_device_get_toplevel_drag (&seat->data_device); + if (toplevel_drag) + { + meta_topic (META_DEBUG_WAYLAND, "Will end xdg_toplevel_drag#%u.", + wl_resource_get_id (toplevel_drag->resource)); + meta_wayland_data_source_notify_drop_performed (source); + meta_wayland_toplevel_drag_end (toplevel_drag); + } + if (drag_grab->drag_focus && source && meta_wayland_data_source_has_target (source) && meta_wayland_data_source_get_current_action (source)) { meta_wayland_surface_drag_dest_drop (drag_grab->drag_focus); - meta_wayland_data_source_notify_drop_performed (source); + if (!meta_wayland_data_source_get_drop_performed (source)) + meta_wayland_data_source_notify_drop_performed (source); meta_wayland_data_source_update_in_ask (source); success = TRUE; @@ -609,11 +632,20 @@ drag_grab_key (MetaWaylandEventHandler *handler, const ClutterEvent *event, gpointer user_data) { + MetaWaylandToplevelDrag *toplevel_drag; MetaWaylandDragGrab *drag_grab = user_data; ClutterModifierType modifiers; if (clutter_event_get_key_symbol (event) == CLUTTER_KEY_Escape) { + toplevel_drag = meta_wayland_data_device_get_toplevel_drag (&drag_grab->seat->data_device); + if (toplevel_drag) + { + meta_topic (META_DEBUG_WAYLAND, "Will cancel xdg_toplevel_drag#%u.", + wl_resource_get_id (toplevel_drag->resource)); + meta_wayland_toplevel_drag_end (toplevel_drag); + } + meta_wayland_data_device_set_dnd_source (&drag_grab->seat->data_device, NULL); unset_selection_source (&drag_grab->seat->data_device, META_SELECTION_DND); @@ -1309,3 +1341,12 @@ meta_wayland_data_device_unset_dnd_selection (MetaWaylandDataDevice *data_device { unset_selection_source (data_device, META_SELECTION_DND); } + +MetaWaylandToplevelDrag * +meta_wayland_data_device_get_toplevel_drag (MetaWaylandDataDevice *data_device) +{ + if (!data_device->current_grab || !data_device->current_grab->drag_data_source) + return NULL; + + return meta_wayland_data_source_get_toplevel_drag (data_device->current_grab->drag_data_source); +} diff --git a/src/wayland/meta-wayland-data-device.h b/src/wayland/meta-wayland-data-device.h index 3e9b791ca..9de22037a 100644 --- a/src/wayland/meta-wayland-data-device.h +++ b/src/wayland/meta-wayland-data-device.h @@ -87,6 +87,9 @@ void meta_wayland_data_device_start_drag (MetaWaylandDataDevice *data_ void meta_wayland_data_device_end_drag (MetaWaylandDataDevice *data_device); +MetaWaylandToplevelDrag * +meta_wayland_data_device_get_toplevel_drag (MetaWaylandDataDevice *data_device); + void meta_wayland_drag_grab_set_focus (MetaWaylandDragGrab *drag_grab, MetaWaylandSurface *surface); MetaWaylandSurface * diff --git a/src/wayland/meta-window-wayland.c b/src/wayland/meta-window-wayland.c index 2171f4600..27bc74337 100644 --- a/src/wayland/meta-window-wayland.c +++ b/src/wayland/meta-window-wayland.c @@ -39,6 +39,7 @@ #include "wayland/meta-wayland-actor-surface.h" #include "wayland/meta-wayland-private.h" #include "wayland/meta-wayland-surface-private.h" +#include "wayland/meta-wayland-toplevel-drag.h" #include "wayland/meta-wayland-window-configuration.h" #include "wayland/meta-wayland-xdg-shell.h" @@ -732,6 +733,21 @@ on_window_shown (MetaWindow *window) meta_compositor_sync_updates_frozen (window->display->compositor, window); } +static MetaWaylandToplevelDrag * +get_toplevel_drag (MetaWindow *window) +{ + MetaWaylandToplevelDrag *toplevel_drag; + MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window); + MetaDisplay *display = meta_window_get_display (window); + MetaContext *context = meta_display_get_context (display); + MetaWaylandCompositor *compositor = meta_context_get_wayland_compositor (context); + + toplevel_drag = meta_wayland_data_device_get_toplevel_drag (&compositor->seat->data_device); + if (!toplevel_drag || toplevel_drag->dragged_surface != wl_window->surface) + return NULL; + return toplevel_drag; +} + static void meta_window_wayland_init (MetaWindowWayland *wl_window) { @@ -1179,6 +1195,8 @@ meta_window_wayland_finish_move_resize (MetaWindow *window, gboolean is_client_resize; MetaWindowDrag *window_drag; MtkRectangle frame_rect; + MetaWindowActor *window_actor; + MetaWaylandToplevelDrag *toplevel_drag; /* new_geom is in the logical pixel coordinate space, but MetaWindow wants its * rects to represent what in turn will end up on the stage, i.e. we need to @@ -1263,6 +1281,14 @@ meta_window_wayland_finish_move_resize (MetaWindow *window, calculate_position (acked_configuration, &new_geom, &rect); } + toplevel_drag = get_toplevel_drag (window); + if (toplevel_drag && !is_window_being_resized && !window->mapped && + rect.width > 0 && rect.height > 0) + { + meta_wayland_toplevel_drag_calc_origin_for_dragged_window (toplevel_drag, + &rect); + } + rect.x += dx; rect.y += dy; @@ -1295,6 +1321,15 @@ meta_window_wayland_finish_move_resize (MetaWindow *window, gravity = meta_resize_gravity_from_grab_op (meta_window_drag_get_grab_op (window_drag)); else gravity = META_GRAVITY_STATIC; + + /* Force unconstrained move + northwest gravity when running toplevel drags */ + if (toplevel_drag && surface == toplevel_drag->dragged_surface) + { + gravity = META_GRAVITY_NORTH_WEST; + window_actor = meta_window_actor_from_window (window); + meta_window_actor_set_tied_to_drag (window_actor, TRUE); + } + meta_window_move_resize_internal (window, flags, META_PLACE_FLAG_NONE,