diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 37de1223..2256fff1 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -64,6 +64,12 @@ struct sway_drag_icon { struct wl_listener destroy; }; +struct sway_drag { + struct sway_seat *seat; + struct wlr_drag *wlr_drag; + struct wl_listener destroy; +}; + struct sway_seat { struct wlr_seat *wlr_seat; struct sway_cursor *cursor; diff --git a/sway/input/seat.c b/sway/input/seat.c index aa56394a..a54bc2e7 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -402,6 +402,31 @@ static void drag_icon_handle_destroy(struct wl_listener *listener, void *data) { free(icon); } +static void drag_handle_destroy(struct wl_listener *listener, void *data) { + struct sway_drag *drag = wl_container_of(listener, drag, destroy); + + // Focus enter isn't sent during drag, so refocus the focused node, layer + // surface or unmanaged surface. + struct sway_seat *seat = drag->seat; + struct sway_node *focus = seat_get_focus(seat); + if (focus) { + seat_set_focus(seat, NULL); + seat_set_focus(seat, focus); + } else if (seat->focused_layer) { + struct wlr_layer_surface_v1 *layer = seat->focused_layer; + seat_set_focus_layer(seat, NULL); + seat_set_focus_layer(seat, layer); + } else { + struct wlr_surface *unmanaged = seat->wlr_seat->keyboard_state.focused_surface; + seat_set_focus_surface(seat, NULL, false); + seat_set_focus_surface(seat, unmanaged, false); + } + + drag->wlr_drag->data = NULL; + wl_list_remove(&drag->destroy.link); + free(drag); +} + static void handle_request_start_drag(struct wl_listener *listener, void *data) { struct sway_seat *seat = wl_container_of(listener, seat, request_start_drag); @@ -431,6 +456,19 @@ static void handle_request_start_drag(struct wl_listener *listener, static void handle_start_drag(struct wl_listener *listener, void *data) { struct sway_seat *seat = wl_container_of(listener, seat, start_drag); struct wlr_drag *wlr_drag = data; + + struct sway_drag *drag = calloc(1, sizeof(struct sway_drag)); + if (drag == NULL) { + sway_log(SWAY_ERROR, "Allocation failed"); + return; + } + drag->seat = seat; + drag->wlr_drag = wlr_drag; + wlr_drag->data = drag; + + drag->destroy.notify = drag_handle_destroy; + wl_signal_add(&wlr_drag->events.destroy, &drag->destroy); + struct wlr_drag_icon *wlr_drag_icon = wlr_drag->icon; if (wlr_drag_icon == NULL) { return;