wayland/xdg-toplevel-drag: Add the protocol implementation
- For already mapped windows, the window drag session is started straight away; - For about-to-be-mapped window (ie: undocking window use case): - The "shown" signal for the dragged window triggers the actual MetaWindowDrag once it's mapped. - MetaWindowWayland now handles the case of toplevel-drag and position the window about to be mapped according to the toplevel-drag parameters. - While attached to a toplevel-drag, the window state is updated to: - Actor's "reactive" state is set to false, which in practice excludes it from the possible drag target list; - WindowActor's "tied to drag" state is set to true, which results in initial placement constraints to be skipped, so newly created (detached) windows can be freely dragged around. - Toplevel drag session ends upon: - dnd drop and cancellation. - xdg_toplevel_drag_v1 object destruction (client-side). - data source destruction. 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 - [ ] Disable visibility change animations - [ ] 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
1cb46f203c
commit
66cfbf03c9
@ -697,6 +697,8 @@ if have_wayland
|
||||
'wayland/meta-wayland-tablet-tool.h',
|
||||
'wayland/meta-wayland-text-input.c',
|
||||
'wayland/meta-wayland-text-input.h',
|
||||
'wayland/meta-wayland-toplevel-drag.c',
|
||||
'wayland/meta-wayland-toplevel-drag.h',
|
||||
'wayland/meta-wayland-touch.c',
|
||||
'wayland/meta-wayland-touch.h',
|
||||
'wayland/meta-wayland-transaction.c',
|
||||
@ -1118,6 +1120,7 @@ if have_wayland
|
||||
['xdg-foreign', 'unstable', 'v2', ],
|
||||
['xdg-output', 'unstable', 'v1', ],
|
||||
['xdg-shell', 'stable', ],
|
||||
['xdg-toplevel-drag', 'staging', 'v1'],
|
||||
['xwayland-keyboard-grab', 'unstable', 'v1', ],
|
||||
['linux-drm-syncobj-v1', 'private', ],
|
||||
['color-management-v1', 'private', ],
|
||||
|
@ -43,6 +43,7 @@
|
||||
#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"
|
||||
|
||||
#define ROOTWINDOW_DROP_MIME "application/x-rootwindow-drop"
|
||||
|
||||
@ -343,6 +344,12 @@ meta_wayland_drag_grab_get_origin (MetaWaylandDragGrab *drag_grab)
|
||||
return drag_grab->drag_origin;
|
||||
}
|
||||
|
||||
MetaWaylandDataSource *
|
||||
meta_wayland_drag_grab_get_data_source (MetaWaylandDragGrab *drag_grab)
|
||||
{
|
||||
return drag_grab->drag_data_source;
|
||||
}
|
||||
|
||||
static void
|
||||
data_source_update_user_dnd_action (MetaWaylandDataSource *source,
|
||||
ClutterModifierType modifiers)
|
||||
|
@ -98,3 +98,6 @@ ClutterInputDevice * meta_wayland_drag_grab_get_device (MetaWaylandDragGrab *
|
||||
ClutterEventSequence **sequence);
|
||||
|
||||
MetaWaylandSurface * meta_wayland_drag_grab_get_origin (MetaWaylandDragGrab *drag_grab);
|
||||
|
||||
MetaWaylandDataSource *
|
||||
meta_wayland_drag_grab_get_data_source (MetaWaylandDragGrab *drag_grab);
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
#include "wayland/meta-wayland-data-source.h"
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
#include "wayland/meta-wayland-toplevel-drag.h"
|
||||
|
||||
#define ALL_ACTIONS (WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY | \
|
||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE | \
|
||||
@ -44,6 +45,7 @@ typedef struct _MetaWaylandDataSourcePrivate
|
||||
enum wl_data_device_manager_dnd_action user_dnd_action;
|
||||
enum wl_data_device_manager_dnd_action current_dnd_action;
|
||||
MetaWaylandSeat *seat;
|
||||
MetaWaylandToplevelDrag *toplevel_drag;
|
||||
guint actions_set : 1;
|
||||
guint in_ask : 1;
|
||||
guint drop_performed : 1;
|
||||
@ -614,3 +616,22 @@ meta_wayland_data_source_get_compositor (MetaWaylandDataSource *source)
|
||||
|
||||
return priv->compositor;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_source_set_toplevel_drag (MetaWaylandDataSource *source,
|
||||
MetaWaylandToplevelDrag *toplevel_drag)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
priv->toplevel_drag = toplevel_drag;
|
||||
}
|
||||
|
||||
MetaWaylandToplevelDrag *
|
||||
meta_wayland_data_source_get_toplevel_drag (MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
return priv->toplevel_drag;
|
||||
}
|
||||
|
@ -110,3 +110,10 @@ gboolean meta_wayland_data_source_get_drop_performed (MetaWaylandDataSource *sou
|
||||
|
||||
void meta_wayland_data_source_notify_drop_performed (MetaWaylandDataSource *source);
|
||||
void meta_wayland_data_source_notify_finish (MetaWaylandDataSource *source);
|
||||
|
||||
void
|
||||
meta_wayland_data_source_set_toplevel_drag (MetaWaylandDataSource *source,
|
||||
MetaWaylandToplevelDrag *toplevel_drag);
|
||||
|
||||
MetaWaylandToplevelDrag *
|
||||
meta_wayland_data_source_get_toplevel_drag (MetaWaylandDataSource *source);
|
||||
|
435
src/wayland/meta-wayland-toplevel-drag.c
Normal file
435
src/wayland/meta-wayland-toplevel-drag.c
Normal file
@ -0,0 +1,435 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Igalia, S.L.
|
||||
*
|
||||
* Author: Nick Yamane <nickdiego@igalia.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "clutter-mutter.h"
|
||||
#include "config.h"
|
||||
|
||||
#include "meta-wayland-toplevel-drag.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "compositor/compositor-private.h"
|
||||
#include "compositor/meta-window-drag.h"
|
||||
#include "core/window-private.h"
|
||||
#include "meta/meta-debug.h"
|
||||
#include "meta/meta-enums.h"
|
||||
#include "meta/meta-wayland-surface.h"
|
||||
#include "meta/types.h"
|
||||
#include "meta/window.h"
|
||||
#include "wayland/meta-wayland-data-device.h"
|
||||
#include "wayland/meta-wayland-data-source.h"
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
#include "wayland/meta-wayland-seat.h"
|
||||
#include "wayland/meta-wayland-surface-private.h"
|
||||
#include "wayland/meta-wayland-types.h"
|
||||
#include "wayland/meta-wayland-versions.h"
|
||||
#include "wayland/meta-wayland-xdg-shell.h"
|
||||
|
||||
#include "xdg-toplevel-drag-v1-server-protocol.h"
|
||||
|
||||
static void
|
||||
xdg_toplevel_drag_destructor (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandToplevelDrag *toplevel_drag = wl_resource_get_user_data (resource);
|
||||
g_assert (toplevel_drag);
|
||||
meta_topic (META_DEBUG_WAYLAND, "Destroying xdg_toplevel_drag#%u",
|
||||
wl_resource_get_id (resource));
|
||||
|
||||
meta_wayland_toplevel_drag_end (toplevel_drag);
|
||||
g_free (toplevel_drag);
|
||||
}
|
||||
|
||||
static void
|
||||
on_dragged_window_unmanaging (MetaWindow *window,
|
||||
MetaWaylandToplevelDrag *toplevel_drag)
|
||||
{
|
||||
meta_topic (META_DEBUG_WAYLAND, "Dragged window destroyed.");
|
||||
g_clear_signal_handler (&toplevel_drag->window_unmanaging_handler_id, window);
|
||||
g_clear_signal_handler (&toplevel_drag->window_shown_handler_id, window);
|
||||
toplevel_drag->dragged_surface = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
on_window_drag_ended (MetaWindowDrag *window_drag,
|
||||
MetaWaylandToplevelDrag *toplevel_drag)
|
||||
{
|
||||
meta_topic (META_DEBUG_WAYLAND, "Window drag ended.");
|
||||
g_clear_signal_handler (&toplevel_drag->drag_ended_handler_id, window_drag);
|
||||
toplevel_drag->window_drag = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
on_data_source_destroyed (MetaWaylandDataSource *data_source,
|
||||
MetaWaylandToplevelDrag *toplevel_drag)
|
||||
{
|
||||
meta_topic (META_DEBUG_WAYLAND,
|
||||
"Data source destroyed before xdg_toplevel_drag#%d",
|
||||
wl_resource_get_id (toplevel_drag->resource));
|
||||
|
||||
g_clear_signal_handler (&toplevel_drag->source_destroyed_handler_id,
|
||||
data_source);
|
||||
meta_wayland_toplevel_drag_end (toplevel_drag);
|
||||
}
|
||||
|
||||
static void
|
||||
add_window_geometry_origin (MetaWaylandSurface *dragged_surface,
|
||||
int *x_offset,
|
||||
int *y_offset)
|
||||
{
|
||||
MtkRectangle toplevel_geometry;
|
||||
toplevel_geometry = meta_wayland_xdg_surface_get_window_geometry (
|
||||
META_WAYLAND_XDG_SURFACE (dragged_surface->role));
|
||||
|
||||
if (x_offset)
|
||||
*x_offset = *x_offset + toplevel_geometry.x;
|
||||
if (y_offset)
|
||||
*y_offset = *y_offset + toplevel_geometry.y;
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_toplevel_drag_destroy (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy (resource);
|
||||
}
|
||||
|
||||
static MetaWaylandSurface *
|
||||
surface_from_xdg_toplevel_resource (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurfaceRole *surface_role = wl_resource_get_user_data (resource);
|
||||
|
||||
if (!META_IS_WAYLAND_SURFACE_ROLE (surface_role))
|
||||
return NULL;
|
||||
|
||||
return meta_wayland_surface_role_get_surface (surface_role);
|
||||
}
|
||||
|
||||
static void
|
||||
start_window_drag (MetaWindow *dragged_window,
|
||||
MetaWaylandToplevelDrag *toplevel_drag,
|
||||
graphene_point_t *offset_hint)
|
||||
{
|
||||
MetaWaylandSeat *seat;
|
||||
MetaWaylandDragGrab *drag_grab;
|
||||
MetaSurfaceActor *surface_actor;
|
||||
MetaContext *context;
|
||||
MetaBackend *backend;
|
||||
ClutterInputDevice *device;
|
||||
ClutterEventSequence *sequence;
|
||||
ClutterActor *stage, *grab_actor;
|
||||
MetaCompositor *compositor;
|
||||
uint32_t timestamp;
|
||||
gboolean started;
|
||||
|
||||
g_assert (toplevel_drag);
|
||||
g_assert (toplevel_drag->data_source);
|
||||
g_assert (toplevel_drag->dragged_surface);
|
||||
|
||||
seat = meta_wayland_data_source_get_seat (toplevel_drag->data_source);
|
||||
if (!seat)
|
||||
return;
|
||||
|
||||
drag_grab = meta_wayland_data_device_get_current_grab (&seat->data_device);
|
||||
if (!drag_grab ||
|
||||
toplevel_drag->data_source != meta_wayland_drag_grab_get_data_source (drag_grab))
|
||||
{
|
||||
meta_topic (META_DEBUG_WAYLAND, "No drag grab found, earlying out.");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Disable events on the dragged surface, so drag enter and leave events
|
||||
* can be detected for other surfaces. */
|
||||
surface_actor = meta_wayland_surface_get_actor (toplevel_drag->dragged_surface);
|
||||
clutter_actor_set_reactive (CLUTTER_ACTOR (surface_actor), FALSE);
|
||||
|
||||
meta_topic (META_DEBUG_WAYLAND, "Starting window drag. window=%s offset=(%.0f, %.0f)",
|
||||
dragged_window->desc,
|
||||
(offset_hint ? offset_hint->x : -1),
|
||||
(offset_hint ? offset_hint->y : -1));
|
||||
|
||||
device = meta_wayland_drag_grab_get_device (drag_grab, &sequence);
|
||||
timestamp = meta_display_get_current_time_roundtrip (dragged_window->display);
|
||||
|
||||
/* Re-use the current wayland input's grab actor for the newly started
|
||||
* window drag session. */
|
||||
context = meta_display_get_context (dragged_window->display);
|
||||
backend = meta_context_get_backend (context);
|
||||
stage = meta_backend_get_stage (backend);
|
||||
grab_actor = clutter_stage_get_grab_actor (CLUTTER_STAGE (stage));
|
||||
|
||||
compositor = dragged_window->display->compositor;
|
||||
started = meta_compositor_drag_window (compositor, dragged_window,
|
||||
META_GRAB_OP_MOVING_UNCONSTRAINED, device,
|
||||
sequence, timestamp, offset_hint, grab_actor);
|
||||
if (!started)
|
||||
return;
|
||||
|
||||
toplevel_drag->window_drag = meta_compositor_get_current_window_drag (compositor);
|
||||
toplevel_drag->drag_ended_handler_id =
|
||||
g_signal_connect (toplevel_drag->window_drag,
|
||||
"ended",
|
||||
G_CALLBACK (on_window_drag_ended),
|
||||
toplevel_drag);
|
||||
}
|
||||
|
||||
static void
|
||||
on_dragged_window_shown (MetaWindow *window,
|
||||
MetaWaylandToplevelDrag *toplevel_drag)
|
||||
{
|
||||
g_assert (window->mapped);
|
||||
g_clear_signal_handler (&toplevel_drag->window_shown_handler_id, window);
|
||||
if (toplevel_drag->data_source && toplevel_drag->dragged_surface)
|
||||
start_window_drag (window, toplevel_drag, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_toplevel_drag_attach (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *toplevel,
|
||||
int32_t x_offset,
|
||||
int32_t y_offset)
|
||||
{
|
||||
MetaWaylandSurface *dragged_surface;
|
||||
MetaWindow *dragged_window;
|
||||
float screen_x, screen_y;
|
||||
MetaWaylandToplevelDrag *toplevel_drag = wl_resource_get_user_data (resource);
|
||||
|
||||
/* Toplevel drag becomes inert if the associated data source is destroyed */
|
||||
if (!toplevel_drag->data_source)
|
||||
return;
|
||||
|
||||
dragged_surface = surface_from_xdg_toplevel_resource (toplevel);
|
||||
dragged_window = meta_wayland_surface_get_window (dragged_surface);
|
||||
g_return_if_fail (dragged_window != NULL);
|
||||
|
||||
if (toplevel_drag->dragged_surface != NULL)
|
||||
{
|
||||
wl_resource_post_error (
|
||||
resource, XDG_TOPLEVEL_DRAG_V1_ERROR_TOPLEVEL_ATTACHED,
|
||||
"toplevel drag already has a surface attached");
|
||||
return;
|
||||
}
|
||||
|
||||
meta_topic (META_DEBUG_WAYLAND,
|
||||
"Attaching xdg_toplevel#%u to xdg_toplevel_drag#%u "
|
||||
"data_source#%p window=%s drag_offset=(%d, %d)",
|
||||
wl_resource_get_id (toplevel), wl_resource_get_id (resource),
|
||||
toplevel_drag->data_source, dragged_window->desc, x_offset, y_offset);
|
||||
|
||||
toplevel_drag->dragged_surface = dragged_surface;
|
||||
toplevel_drag->x_offset = x_offset;
|
||||
toplevel_drag->y_offset = y_offset;
|
||||
toplevel_drag->window_unmanaging_handler_id =
|
||||
g_signal_connect (dragged_window,
|
||||
"unmanaging",
|
||||
G_CALLBACK (on_dragged_window_unmanaging),
|
||||
toplevel_drag);
|
||||
|
||||
if (dragged_window->mapped)
|
||||
{
|
||||
/* {x,y}_offset values are relative to the toplevel geometry. */
|
||||
add_window_geometry_origin (dragged_surface, &x_offset, &y_offset);
|
||||
meta_wayland_surface_get_absolute_coordinates (dragged_surface,
|
||||
(float) x_offset,
|
||||
(float) y_offset,
|
||||
&screen_x, &screen_y);
|
||||
start_window_drag (dragged_window, toplevel_drag,
|
||||
&GRAPHENE_POINT_INIT (screen_x, screen_y));
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_topic (META_DEBUG_WAYLAND, "Window not mapped yet, monitoring.");
|
||||
toplevel_drag->window_shown_handler_id =
|
||||
g_signal_connect (dragged_window,
|
||||
"shown",
|
||||
G_CALLBACK (on_dragged_window_shown),
|
||||
toplevel_drag);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct xdg_toplevel_drag_v1_interface meta_wayland_toplevel_drag_interface = {
|
||||
.destroy = xdg_toplevel_drag_destroy,
|
||||
.attach = xdg_toplevel_drag_attach,
|
||||
};
|
||||
|
||||
static void
|
||||
xdg_toplevel_drag_manager_destroy (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy (resource);
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_toplevel_drag_manager_get_toplevel_drag (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
uint32_t toplevel_drag_id,
|
||||
struct wl_resource *data_source_resource)
|
||||
{
|
||||
MetaWaylandDataSource *data_source;
|
||||
MetaWaylandToplevelDrag *toplevel_drag;
|
||||
struct wl_resource *toplevel_drag_resource;
|
||||
|
||||
data_source = wl_resource_get_user_data (data_source_resource);
|
||||
toplevel_drag = meta_wayland_data_source_get_toplevel_drag (data_source);
|
||||
|
||||
if (toplevel_drag)
|
||||
{
|
||||
wl_resource_post_error (
|
||||
resource, XDG_TOPLEVEL_DRAG_MANAGER_V1_ERROR_INVALID_SOURCE,
|
||||
"toplevel drag resource already exists on data source");
|
||||
return;
|
||||
}
|
||||
|
||||
toplevel_drag_resource = wl_resource_create (client,
|
||||
&xdg_toplevel_drag_v1_interface,
|
||||
wl_resource_get_version (resource),
|
||||
toplevel_drag_id);
|
||||
|
||||
toplevel_drag = g_new0 (MetaWaylandToplevelDrag, 1);
|
||||
toplevel_drag->resource = toplevel_drag_resource;
|
||||
toplevel_drag->data_source = data_source;
|
||||
toplevel_drag->source_destroyed_handler_id =
|
||||
g_signal_connect (data_source,
|
||||
"destroy",
|
||||
G_CALLBACK (on_data_source_destroyed),
|
||||
toplevel_drag);
|
||||
meta_wayland_data_source_set_toplevel_drag (data_source,
|
||||
toplevel_drag);
|
||||
|
||||
wl_resource_set_implementation (toplevel_drag_resource,
|
||||
&meta_wayland_toplevel_drag_interface,
|
||||
toplevel_drag,
|
||||
xdg_toplevel_drag_destructor);
|
||||
}
|
||||
|
||||
static const struct xdg_toplevel_drag_manager_v1_interface meta_wayland_toplevel_drag_manager_interface = {
|
||||
.destroy = xdg_toplevel_drag_manager_destroy,
|
||||
.get_xdg_toplevel_drag = xdg_toplevel_drag_manager_get_toplevel_drag,
|
||||
};
|
||||
|
||||
static void
|
||||
xdg_toplevel_drag_bind (struct wl_client *client,
|
||||
void *data,
|
||||
uint32_t version,
|
||||
uint32_t id)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = wl_resource_create (client,
|
||||
&xdg_toplevel_drag_manager_v1_interface,
|
||||
version,
|
||||
id);
|
||||
wl_resource_set_implementation (resource,
|
||||
&meta_wayland_toplevel_drag_manager_interface,
|
||||
data,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_init_toplevel_drag (MetaWaylandCompositor *compositor)
|
||||
{
|
||||
if (wl_global_create (compositor->wayland_display,
|
||||
&xdg_toplevel_drag_manager_v1_interface,
|
||||
META_XDG_TOPLEVEL_DRAG_VERSION,
|
||||
compositor,
|
||||
xdg_toplevel_drag_bind) == NULL)
|
||||
g_error ("Failed to register a global xdg_toplevel_drag object");
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_toplevel_drag_calc_origin_for_dragged_window (MetaWaylandToplevelDrag *toplevel_drag,
|
||||
MtkRectangle *bounds_out)
|
||||
{
|
||||
MetaWaylandSeat *seat;
|
||||
MetaWaylandDragGrab *drag_grab;
|
||||
ClutterInputDevice *device;
|
||||
ClutterEventSequence *sequence;
|
||||
graphene_point_t coords;
|
||||
|
||||
g_assert (toplevel_drag);
|
||||
g_assert (bounds_out);
|
||||
|
||||
seat = meta_wayland_data_source_get_seat (toplevel_drag->data_source);
|
||||
if (!seat)
|
||||
return FALSE;
|
||||
|
||||
drag_grab = meta_wayland_data_device_get_current_grab (&seat->data_device);
|
||||
if (!drag_grab)
|
||||
return FALSE;
|
||||
|
||||
device = meta_wayland_drag_grab_get_device (drag_grab, &sequence);
|
||||
clutter_seat_query_state (clutter_input_device_get_seat (device),
|
||||
device, sequence, &coords, NULL);
|
||||
|
||||
meta_topic (META_DEBUG_WAYLAND,
|
||||
"Calculated position for the dragged window. "
|
||||
"offset=(%d, %d) new_origin=(%.0f, %.0f)",
|
||||
toplevel_drag->x_offset, toplevel_drag->y_offset, coords.x, coords.y);
|
||||
bounds_out->x = (int) coords.x - toplevel_drag->x_offset;
|
||||
bounds_out->y = (int) coords.y - toplevel_drag->y_offset;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_toplevel_drag_end (MetaWaylandToplevelDrag *toplevel_drag)
|
||||
{
|
||||
MetaWindow *window;
|
||||
MetaWindowActor *window_actor;
|
||||
MetaSurfaceActor *surface_actor;
|
||||
|
||||
g_return_if_fail (toplevel_drag != NULL);
|
||||
meta_topic (META_DEBUG_WAYLAND, "Ending toplevel drag.");
|
||||
|
||||
if (toplevel_drag->window_drag)
|
||||
{
|
||||
window = meta_window_drag_get_window (toplevel_drag->window_drag);
|
||||
g_clear_signal_handler (&toplevel_drag->drag_ended_handler_id,
|
||||
toplevel_drag->window_drag);
|
||||
meta_window_drag_end (toplevel_drag->window_drag);
|
||||
|
||||
window_actor = meta_window_actor_from_window (window);
|
||||
if (window_actor)
|
||||
meta_window_actor_set_tied_to_drag (window_actor, FALSE);
|
||||
toplevel_drag->window_drag = NULL;
|
||||
}
|
||||
|
||||
if (toplevel_drag->dragged_surface)
|
||||
{
|
||||
surface_actor = meta_wayland_surface_get_actor (toplevel_drag->dragged_surface);
|
||||
if (surface_actor)
|
||||
clutter_actor_set_reactive (CLUTTER_ACTOR (surface_actor), TRUE);
|
||||
|
||||
window = meta_wayland_surface_get_window (toplevel_drag->dragged_surface);
|
||||
if (window)
|
||||
{
|
||||
g_clear_signal_handler (&toplevel_drag->window_unmanaging_handler_id, window);
|
||||
g_clear_signal_handler (&toplevel_drag->window_shown_handler_id, window);
|
||||
}
|
||||
toplevel_drag->dragged_surface = NULL;
|
||||
}
|
||||
|
||||
if (toplevel_drag->data_source)
|
||||
{
|
||||
g_clear_signal_handler (&toplevel_drag->source_destroyed_handler_id,
|
||||
toplevel_drag->data_source);
|
||||
meta_wayland_data_source_set_toplevel_drag (toplevel_drag->data_source, NULL);
|
||||
toplevel_drag->data_source = NULL;
|
||||
}
|
||||
}
|
54
src/wayland/meta-wayland-toplevel-drag.h
Normal file
54
src/wayland/meta-wayland-toplevel-drag.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Igalia, S.L.
|
||||
*
|
||||
* Author: Nick Yamane <nickdiego@igalia.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "compositor/meta-window-drag.h"
|
||||
#include "mtk/mtk.h"
|
||||
#include "wayland/meta-wayland-types.h"
|
||||
#include "wayland/meta-wayland-data-source.h"
|
||||
|
||||
struct _MetaWaylandToplevelDrag
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
MetaWaylandDataSource *data_source;
|
||||
MetaWaylandSurface *dragged_surface;
|
||||
int32_t x_offset, y_offset;
|
||||
|
||||
MetaWindowDrag *window_drag;
|
||||
gulong window_unmanaging_handler_id;
|
||||
gulong window_shown_handler_id;
|
||||
gulong drag_ended_handler_id;
|
||||
gulong source_destroyed_handler_id;
|
||||
};
|
||||
|
||||
void
|
||||
meta_wayland_init_toplevel_drag (MetaWaylandCompositor *compositor);
|
||||
|
||||
gboolean
|
||||
meta_wayland_toplevel_drag_calc_origin_for_dragged_window (MetaWaylandToplevelDrag *drag,
|
||||
MtkRectangle *bounds_out);
|
||||
|
||||
void
|
||||
meta_wayland_toplevel_drag_end (MetaWaylandToplevelDrag *drag);
|
@ -75,3 +75,5 @@ typedef struct _MetaWaylandClient MetaWaylandClient;
|
||||
typedef struct _MetaWaylandDrmLeaseManager MetaWaylandDrmLeaseManager;
|
||||
|
||||
typedef struct _MetaWaylandXdgSessionManager MetaWaylandXdgSessionManager;
|
||||
|
||||
typedef struct _MetaWaylandToplevelDrag MetaWaylandToplevelDrag;
|
||||
|
@ -62,3 +62,4 @@
|
||||
#define META_WP_DRM_LEASE_DEVICE_V1_VERSION 1
|
||||
#define META_XDG_SESSION_MANAGER_V1_VERSION 1
|
||||
#define META_WP_SYSTEM_BELL_V1_VERSION 1
|
||||
#define META_XDG_TOPLEVEL_DRAG_VERSION 1
|
||||
|
Loading…
x
Reference in New Issue
Block a user