From 5cfea4fee322508563844d8e7761719b1c3083eb Mon Sep 17 00:00:00 2001 From: Robert Mader Date: Mon, 15 Jul 2019 13:46:00 +0200 Subject: [PATCH] wayland/dnd-surface: Apply surface offset The surface offset allows an application to move itself in relative coordinates to its previous position. It is rather ill defined and partly incompatible with other functionality, which is why we ignore it generally. For dnd-surfaces though, it is the de-facto standard for applications to properly position the dnd-icon below the cursor. Therefore apply the offset on actor sync by setting the feedback actor anchor. https://gitlab.gnome.org/GNOME/mutter/merge_requests/684 --- src/wayland/meta-wayland-dnd-surface.c | 51 ++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/wayland/meta-wayland-dnd-surface.c b/src/wayland/meta-wayland-dnd-surface.c index ae60f53e8..c83bb0c52 100644 --- a/src/wayland/meta-wayland-dnd-surface.c +++ b/src/wayland/meta-wayland-dnd-surface.c @@ -21,9 +21,13 @@ #include "wayland/meta-wayland-dnd-surface.h" +#include "compositor/meta-feedback-actor-private.h" + struct _MetaWaylandSurfaceRoleDND { MetaWaylandActorSurface parent; + int32_t pending_offset_x; + int32_t pending_offset_y; }; G_DEFINE_TYPE (MetaWaylandSurfaceRoleDND, @@ -45,14 +49,57 @@ dnd_surface_commit (MetaWaylandSurfaceRole *surface_role, { MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (surface_role); + MetaWaylandSurfaceRoleDND *surface_role_dnd = + META_WAYLAND_SURFACE_ROLE_DND (surface_role); MetaWaylandSurfaceRoleClass *surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_surface_role_dnd_parent_class); meta_wayland_surface_queue_pending_state_frame_callbacks (surface, pending); + surface_role_dnd->pending_offset_x = pending->dx; + surface_role_dnd->pending_offset_y = pending->dy; + surface_role_class->commit (surface_role, pending); } +static void +dnd_subsurface_sync_actor_state (MetaWaylandActorSurface *actor_surface) +{ + MetaSurfaceActor *surface_actor = + meta_wayland_actor_surface_get_actor (actor_surface); + MetaFeedbackActor *feedback_actor = + META_FEEDBACK_ACTOR (clutter_actor_get_parent (CLUTTER_ACTOR (surface_actor))); + MetaWaylandSurfaceRole *surface_role = + META_WAYLAND_SURFACE_ROLE (actor_surface); + MetaWaylandSurfaceRoleDND *surface_role_dnd = + META_WAYLAND_SURFACE_ROLE_DND (surface_role); + MetaWaylandSurface *surface = + meta_wayland_surface_role_get_surface (surface_role); + MetaWaylandActorSurfaceClass *actor_surface_class = + META_WAYLAND_ACTOR_SURFACE_CLASS (meta_wayland_surface_role_dnd_parent_class); + float geometry_scale; + float actor_scale; + float anchor_x; + float anchor_y; + float new_anchor_x; + float new_anchor_y; + + g_return_if_fail (META_IS_FEEDBACK_ACTOR (feedback_actor)); + + geometry_scale = + meta_wayland_actor_surface_get_geometry_scale (actor_surface); + actor_scale = geometry_scale / surface->scale; + + meta_feedback_actor_get_anchor (feedback_actor, &anchor_x, &anchor_y); + new_anchor_x = anchor_x - surface_role_dnd->pending_offset_x / actor_scale; + new_anchor_y = anchor_y - surface_role_dnd->pending_offset_y / actor_scale; + meta_feedback_actor_set_anchor (feedback_actor, + new_anchor_x, + new_anchor_y); + + actor_surface_class->sync_actor_state (actor_surface); +} + static void meta_wayland_surface_role_dnd_init (MetaWaylandSurfaceRoleDND *role) { @@ -63,7 +110,11 @@ meta_wayland_surface_role_dnd_class_init (MetaWaylandSurfaceRoleDNDClass *klass) { MetaWaylandSurfaceRoleClass *surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (klass); + MetaWaylandActorSurfaceClass *actor_surface_class = + META_WAYLAND_ACTOR_SURFACE_CLASS (klass); surface_role_class->assigned = dnd_surface_assigned; surface_role_class->commit = dnd_surface_commit; + + actor_surface_class->sync_actor_state = dnd_subsurface_sync_actor_state; }