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,