xwayland: listen to drag focus destroy signal

The wlr_drag takes care of resetting the focused wlr_surface when
it's destroyed, however we store the wlr_xwayland_surface, which
may be destroyed before.
This commit is contained in:
Simon Ser 2024-12-05 20:21:56 +01:00
parent 9649fbe443
commit c7acfe906b
3 changed files with 40 additions and 15 deletions

View file

@ -149,6 +149,7 @@ struct wlr_xwm {
struct wl_listener seat_drag_drop;
struct wl_listener seat_drag_destroy;
struct wl_listener seat_drag_source_destroy;
struct wl_listener drag_focus_destroy;
};
struct wlr_xwm *xwm_create(struct wlr_xwayland *wlr_xwayland, int wm_fd);

View file

@ -234,6 +234,37 @@ int xwm_handle_selection_client_message(struct wlr_xwm *xwm,
}
}
static void xwm_set_drag_focus(struct wlr_xwm *xwm, struct wlr_xwayland_surface *focus);
static void drag_focus_handle_destroy(struct wl_listener *listener, void *data) {
struct wlr_xwm *xwm = wl_container_of(listener, xwm, drag_focus_destroy);
xwm_set_drag_focus(xwm, NULL);
}
static void xwm_set_drag_focus(struct wlr_xwm *xwm, struct wlr_xwayland_surface *focus) {
if (focus == xwm->drag_focus) {
return;
}
if (xwm->drag_focus != NULL) {
wlr_data_source_dnd_action(xwm->drag->source,
WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE);
xwm_dnd_send_leave(xwm);
}
wl_list_remove(&xwm->drag_focus_destroy.link);
wl_list_init(&xwm->drag_focus_destroy.link);
xwm->drag_focus = focus;
if (xwm->drag_focus != NULL) {
xwm->drag_focus_destroy.notify = drag_focus_handle_destroy;
wl_signal_add(&xwm->drag_focus->events.destroy, &xwm->drag_focus_destroy);
xwm_dnd_send_enter(xwm);
}
}
static void seat_handle_drag_focus(struct wl_listener *listener, void *data) {
struct wlr_drag *drag = data;
struct wlr_xwm *xwm = wl_container_of(listener, xwm, seat_drag_focus);
@ -250,21 +281,7 @@ static void seat_handle_drag_focus(struct wl_listener *listener, void *data) {
}
}
if (focus == xwm->drag_focus) {
return;
}
if (xwm->drag_focus != NULL) {
wlr_data_source_dnd_action(drag->source,
WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE);
xwm_dnd_send_leave(xwm);
}
xwm->drag_focus = focus;
if (xwm->drag_focus != NULL) {
xwm_dnd_send_enter(xwm);
}
xwm_set_drag_focus(xwm, focus);
}
static void seat_handle_drag_motion(struct wl_listener *listener, void *data) {
@ -316,10 +333,15 @@ static void seat_handle_drag_source_destroy(struct wl_listener *listener,
wl_list_remove(&xwm->seat_drag_source_destroy.link);
wl_list_init(&xwm->seat_drag_source_destroy.link);
wl_list_remove(&xwm->drag_focus_destroy.link);
wl_list_init(&xwm->drag_focus_destroy.link);
xwm->drag_focus = NULL;
}
void xwm_seat_handle_start_drag(struct wlr_xwm *xwm, struct wlr_drag *drag) {
wl_list_remove(&xwm->drag_focus_destroy.link);
wl_list_init(&xwm->drag_focus_destroy.link);
xwm->drag = drag;
xwm->drag_focus = NULL;
@ -341,6 +363,7 @@ void xwm_seat_handle_start_drag(struct wlr_xwm *xwm, struct wlr_drag *drag) {
void xwm_seat_unlink_drag_handlers(struct wlr_xwm *xwm) {
wl_list_remove(&xwm->seat_drag_source_destroy.link);
wl_list_remove(&xwm->drag_focus_destroy.link);
if (!xwm->drag) {
return;

View file

@ -2265,6 +2265,7 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *xwayland, int wm_fd) {
wl_list_init(&xwm->unpaired_surfaces);
wl_list_init(&xwm->pending_startup_ids);
wl_list_init(&xwm->seat_drag_source_destroy.link);
wl_list_init(&xwm->drag_focus_destroy.link);
xwm->ping_timeout = 10000;