From 35ab453360ddcd99d47df519cbdf0983e4f82f07 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 6 Dec 2024 16:42:26 +0100 Subject: [PATCH] data-device: reset focused surface when destroyed The surface may be destroyed before the struct wlr_seat_client. Spotted by Consolatis. (cherry picked from commit 71943b3b1ea0ea4584337a145746026567c51a89) --- include/wlr/types/wlr_data_device.h | 1 + types/data_device/wlr_drag.c | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/include/wlr/types/wlr_data_device.h b/include/wlr/types/wlr_data_device.h index 85d661a77..b0fa9fd95 100644 --- a/include/wlr/types/wlr_data_device.h +++ b/include/wlr/types/wlr_data_device.h @@ -126,6 +126,7 @@ struct wlr_drag { struct wl_listener source_destroy; struct wl_listener seat_client_destroy; + struct wl_listener focus_destroy; struct wl_listener icon_destroy; void *data; diff --git a/types/data_device/wlr_drag.c b/types/data_device/wlr_drag.c index 9ccd53c94..6338a4388 100644 --- a/types/data_device/wlr_drag.c +++ b/types/data_device/wlr_drag.c @@ -19,6 +19,14 @@ static void drag_handle_seat_client_destroy(struct wl_listener *listener, wl_list_remove(&drag->seat_client_destroy.link); } +static void drag_set_focus(struct wlr_drag *drag, + struct wlr_surface *surface, double sx, double sy); + +static void drag_handle_focus_destroy(struct wl_listener *listener, void *data) { + struct wlr_drag *drag = wl_container_of(listener, drag, focus_destroy); + drag_set_focus(drag, NULL, 0, 0); +} + static void drag_set_focus(struct wlr_drag *drag, struct wlr_surface *surface, double sx, double sy) { if (drag->focus == surface) { @@ -48,9 +56,12 @@ static void drag_set_focus(struct wlr_drag *drag, } drag->focus_client = NULL; - drag->focus = NULL; } + wl_list_remove(&drag->focus_destroy.link); + wl_list_init(&drag->focus_destroy.link); + drag->focus = NULL; + if (!surface) { goto out; } @@ -99,6 +110,8 @@ static void drag_set_focus(struct wlr_drag *drag, drag->focus = surface; drag->focus_client = focus_client; + drag->focus_destroy.notify = drag_handle_focus_destroy; + wl_signal_add(&surface->events.destroy, &drag->focus_destroy); drag->seat_client_destroy.notify = drag_handle_seat_client_destroy; wl_signal_add(&focus_client->events.destroy, &drag->seat_client_destroy); @@ -150,6 +163,7 @@ static void drag_destroy(struct wlr_drag *drag) { if (drag->source) { wl_list_remove(&drag->source_destroy.link); } + wl_list_remove(&drag->focus_destroy.link); if (drag->icon != NULL) { drag_icon_destroy(drag->icon); @@ -410,6 +424,8 @@ struct wlr_drag *wlr_drag_create(struct wlr_seat_client *seat_client, wl_signal_init(&drag->events.drop); wl_signal_init(&drag->events.destroy); + wl_list_init(&drag->focus_destroy.link); + drag->seat = seat_client->seat; drag->seat_client = seat_client;