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 <nickdiego@igalia.com> Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4107>
This commit is contained in:
parent
66cfbf03c9
commit
0111f0de14
@ -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);
|
||||
}
|
||||
|
@ -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 *
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user