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
This commit is contained in:
Robert Mader 2019-07-15 13:46:00 +02:00
parent 7275cf60bd
commit 5cfea4fee3

View File

@ -21,9 +21,13 @@
#include "wayland/meta-wayland-dnd-surface.h" #include "wayland/meta-wayland-dnd-surface.h"
#include "compositor/meta-feedback-actor-private.h"
struct _MetaWaylandSurfaceRoleDND struct _MetaWaylandSurfaceRoleDND
{ {
MetaWaylandActorSurface parent; MetaWaylandActorSurface parent;
int32_t pending_offset_x;
int32_t pending_offset_y;
}; };
G_DEFINE_TYPE (MetaWaylandSurfaceRoleDND, G_DEFINE_TYPE (MetaWaylandSurfaceRoleDND,
@ -45,14 +49,57 @@ dnd_surface_commit (MetaWaylandSurfaceRole *surface_role,
{ {
MetaWaylandSurface *surface = MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role); meta_wayland_surface_role_get_surface (surface_role);
MetaWaylandSurfaceRoleDND *surface_role_dnd =
META_WAYLAND_SURFACE_ROLE_DND (surface_role);
MetaWaylandSurfaceRoleClass *surface_role_class = MetaWaylandSurfaceRoleClass *surface_role_class =
META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_surface_role_dnd_parent_class); META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_surface_role_dnd_parent_class);
meta_wayland_surface_queue_pending_state_frame_callbacks (surface, pending); 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); 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 static void
meta_wayland_surface_role_dnd_init (MetaWaylandSurfaceRoleDND *role) 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 = MetaWaylandSurfaceRoleClass *surface_role_class =
META_WAYLAND_SURFACE_ROLE_CLASS (klass); 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->assigned = dnd_surface_assigned;
surface_role_class->commit = dnd_surface_commit; surface_role_class->commit = dnd_surface_commit;
actor_surface_class->sync_actor_state = dnd_subsurface_sync_actor_state;
} }