From 467805da202e76f472b8db2d522fe225e3c0ecaa Mon Sep 17 00:00:00 2001 From: lkn Date: Tue, 23 Jun 2026 17:32:10 +0200 Subject: [PATCH] render DnD drag icon surface following cursor When a client starts a drag with an icon surface, create a wlr_scene_subsurface_tree in the overlay layer and position it at the cursor. Update position on drag motion, destroy on end. --- src/backend/wayland/wl_dnd.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/backend/wayland/wl_dnd.c b/src/backend/wayland/wl_dnd.c index 678f3e4..d8a40e3 100644 --- a/src/backend/wayland/wl_dnd.c +++ b/src/backend/wayland/wl_dnd.c @@ -7,12 +7,14 @@ #include #include #include +#include #include "wl_types.h" #include /* Currently active external wlr_drag (NULL if none). */ struct wlr_drag *wl_current_drag = NULL; +static struct wlr_scene_tree *drag_icon_tree = NULL; void handle_drag_motion(struct wl_listener *listener, void *data); void handle_drag_drop(struct wl_listener *listener, void *data); @@ -35,6 +37,17 @@ handle_seat_request_start_drag(struct wl_listener *listener, void *data) wl_signal_add(&ev->drag->events.motion, &wl_drag_motion_listener); wl_signal_add(&ev->drag->events.drop, &wl_drag_drop_listener); wl_signal_add(&ev->drag->events.destroy, &wl_drag_destroy_listener); + + /* Render the drag icon surface if provided */ + if (ev->drag->icon && ev->drag->icon->surface && wl_state.scene) { + struct wlr_scene_tree *parent = wl_state.level_trees[WL_LAYER_OVERLAY] + ? wl_state.level_trees[WL_LAYER_OVERLAY] : &wl_state.scene->tree; + drag_icon_tree = wlr_scene_subsurface_tree_create(parent, + ev->drag->icon->surface); + if (drag_icon_tree) + wlr_scene_node_set_position(&drag_icon_tree->node, + (int)wl_state.pointer_x, (int)wl_state.pointer_y); + } } void @@ -47,6 +60,11 @@ handle_drag_motion(struct wl_listener *listener, void *data) if (!wl_current_drag) return; + /* Update drag icon position */ + if (drag_icon_tree) + wlr_scene_node_set_position(&drag_icon_tree->node, + (int)wl_state.pointer_x, (int)wl_state.pointer_y); + /* Hit-test at current pointer position */ struct wl_frame_buf *fb = frame_buf_hit(wl_state.pointer_x, wl_state.pointer_y); @@ -140,5 +158,9 @@ handle_drag_destroy(struct wl_listener *listener, void *data) (void)listener; (void)data; wwarning("wl_backend: external DND finished"); + if (drag_icon_tree) { + wlr_scene_node_destroy(&drag_icon_tree->node); + drag_icon_tree = NULL; + } wl_current_drag = NULL; }