From 8a4c71cb7c7fa0bdad8767051fa3b06df8309d12 Mon Sep 17 00:00:00 2001 From: Helmut Januschka Date: Thu, 11 Jun 2026 23:28:40 +0200 Subject: [PATCH] input/seatop_down: update touch drag focus while dragging The touch drag grab in wlroots only sends wl_data_device.enter from wlr_seat_touch_point_focus() and only sends wl_data_device.motion when the drag has a focused surface. Sway never called it, so touch-initiated drags never delivered enter/motion to drop targets and the source was cancelled instead of dropped on touch up. While a touch drag is active for the moving touch point, re-pick the surface under the finger and update the touch point focus before notifying motion, mirroring what pointer drags get implicitly via wlr_seat_pointer_notify_enter(). --- sway/input/seatop_down.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/sway/input/seatop_down.c b/sway/input/seatop_down.c index f64e5a4f2..9a3b7ddbb 100644 --- a/sway/input/seatop_down.c +++ b/sway/input/seatop_down.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include "sway/input/cursor.h" @@ -41,6 +42,32 @@ static void handle_touch_motion(struct sway_seat *seat, return; // Probably not a point_event from this seatop_down } + // If this touch point is driving an active drag-and-drop session, + // keep the drag focus in sync with the surface under the touch + // point, like pointer drags do via wlr_seat_pointer_notify_enter(). + // The drag grab in wlroots only sends wl_data_device.enter from + // wlr_seat_touch_point_focus() and only sends wl_data_device.motion + // when the drag has a focused surface. + struct wlr_drag *drag = seat->wlr_seat->drag; + if (drag != NULL && drag->grab_type == WLR_DRAG_GRAB_KEYBOARD_TOUCH && + drag->touch_id == event->touch_id) { + double sx, sy; + struct wlr_surface *surface = NULL; + node_at_coords(seat, lx, ly, &surface, &sx, &sy); + if (surface != NULL) { + wlr_seat_touch_point_focus(seat->wlr_seat, surface, + event->time_msec, event->touch_id, sx, sy); + wlr_seat_touch_notify_motion(seat->wlr_seat, + event->time_msec, event->touch_id, sx, sy); + } else { + wlr_seat_touch_notify_clear_focus(seat->wlr_seat, + event->time_msec, event->touch_id); + wlr_seat_touch_point_clear_focus(seat->wlr_seat, + event->time_msec, event->touch_id); + } + return; + } + double moved_x = lx - point_event->ref_lx; double moved_y = ly - point_event->ref_ly; double sx = point_event->ref_con_lx + moved_x;