pass the object to LISTEN_STATIC handlers

wlroots 482d6e53 stopped passing the surface to the idle inhibitor
destroy and surface commit signals, which made destroyidleinhibitor()
and commitpopup() dereference NULL. Store the object in the listener
instead.
This commit is contained in:
Guido Cella
2026-10-27 23:33:14 +01:00
parent 7622bd3187
commit 2d16962424
+15 -8
View File
@@ -83,7 +83,7 @@
#define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags])) #define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags]))
#define TAGMASK ((1u << TAGCOUNT) - 1) #define TAGMASK ((1u << TAGCOUNT) - 1)
#define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L))) #define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L)))
#define LISTEN_STATIC(E, H) do { struct wl_listener *_l = ecalloc(1, sizeof(*_l)); _l->notify = (H); wl_signal_add((E), _l); } while (0) #define LISTEN_STATIC(E, H, D) do { StaticListener *_l = ecalloc(1, sizeof(*_l)); _l->listener.notify = (H); _l->data = (D); wl_signal_add((E), &_l->listener); } while (0)
/* enums */ /* enums */
enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */
@@ -263,6 +263,12 @@ typedef struct {
struct wl_listener destroy; struct wl_listener destroy;
} SessionLock; } SessionLock;
typedef struct {
/* Must keep this field first */
struct wl_listener listener;
void *data;
} StaticListener;
/* function declarations */ /* function declarations */
static void applybounds(Client *c, struct wlr_box *bbox); static void applybounds(Client *c, struct wlr_box *bbox);
static void applygeom(Client *c); static void applygeom(Client *c);
@@ -1048,8 +1054,8 @@ commitnotify(struct wl_listener *listener, void *data)
void void
commitpopup(struct wl_listener *listener, void *data) commitpopup(struct wl_listener *listener, void *data)
{ {
struct wlr_surface *surface = data; StaticListener *sl = wl_container_of(listener, sl, listener);
struct wlr_xdg_popup *popup = wlr_xdg_popup_try_from_wlr_surface(surface); struct wlr_xdg_popup *popup = sl->data;
LayerSurface *l = NULL; LayerSurface *l = NULL;
Client *c = NULL; Client *c = NULL;
struct wlr_box box; struct wlr_box box;
@@ -1092,7 +1098,7 @@ void
createidleinhibitor(struct wl_listener *listener, void *data) createidleinhibitor(struct wl_listener *listener, void *data)
{ {
struct wlr_idle_inhibitor_v1 *idle_inhibitor = data; struct wlr_idle_inhibitor_v1 *idle_inhibitor = data;
LISTEN_STATIC(&idle_inhibitor->events.destroy, destroyidleinhibitor); LISTEN_STATIC(&idle_inhibitor->events.destroy, destroyidleinhibitor, idle_inhibitor);
checkidleinhibitor(NULL); checkidleinhibitor(NULL);
} }
@@ -1366,7 +1372,7 @@ createpopup(struct wl_listener *listener, void *data)
/* This event is raised when a client (either xdg-shell or layer-shell) /* This event is raised when a client (either xdg-shell or layer-shell)
* creates a new popup. */ * creates a new popup. */
struct wlr_xdg_popup *popup = data; struct wlr_xdg_popup *popup = data;
LISTEN_STATIC(&popup->base->surface->events.commit, commitpopup); LISTEN_STATIC(&popup->base->surface->events.commit, commitpopup, popup);
} }
void void
@@ -1429,9 +1435,10 @@ destroydragicon(struct wl_listener *listener, void *data)
void void
destroyidleinhibitor(struct wl_listener *listener, void *data) destroyidleinhibitor(struct wl_listener *listener, void *data)
{ {
/* `data` is the wlr_surface of the idle inhibitor being destroyed, StaticListener *sl = wl_container_of(listener, sl, listener);
* at this point the idle inhibitor is still in the list of the manager */ struct wlr_idle_inhibitor_v1 *idle_inhibitor = sl->data;
checkidleinhibitor(wlr_surface_get_root_surface(data)); /* At this point the idle inhibitor is still in the list of the manager */
checkidleinhibitor(wlr_surface_get_root_surface(idle_inhibitor->surface));
wl_list_remove(&listener->link); wl_list_remove(&listener->link);
free(listener); free(listener);
} }