fix: defer setmon() after scene_surface creation to prevent segfault on window map

Root cause: applyrules() called setmon() which called resize(), but
resize() dereferences c->scene_surface->node before c->scene_surface
was created in mapnotify(). Fix by storing target monitor/tags in
pending_mon/pending_tags fields and calling setmon() after scene
nodes exist.

The crash affected all new windows, not just Firefox (which was
the first tested).
This commit is contained in:
2026-07-03 04:11:21 -04:00
parent f923ca83fd
commit 010e885cdf
2 changed files with 11 additions and 4 deletions
+4
View File
@@ -67,6 +67,10 @@ typedef struct Client {
bool can_fullscreen;
ClientRuleEffects rule_effects;
/* Deferred monitor/tags — set by applyrules, used by setmon in mapnotify */
Monitor *pending_mon;
uint32_t pending_tags;
/* COLD — wl_listeners (set up once, rarely touched after) */
struct wl_listener commit;
struct wl_listener map;
+7 -4
View File
@@ -492,7 +492,8 @@ static void applyrules(Client *c) {
}
c->isfloating |= client_is_float_type(c);
setmon(c, mon, newtags);
c->pending_mon = mon;
c->pending_tags = newtags;
}
static void client_arr_add(Client *c) {
@@ -956,10 +957,9 @@ static void commitnotify(struct wl_listener *listener, void *data) {
* a wrong monitor.
*/
applyrules(c);
if (c->mon) {
client_set_scale(client_surface(c), c->mon->wlr_output->scale);
if (c->pending_mon) {
client_set_scale(client_surface(c), c->pending_mon->wlr_output->scale);
}
setmon(c, nullptr, 0); /* Make sure to reapply rules in mapnotify() */
wlr_xdg_toplevel_set_wm_capabilities(
c->surface.xdg->toplevel, WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
@@ -2289,6 +2289,9 @@ static void mapnotify(struct wl_listener *listener, void *data) {
}
}
/* Deferred setmon — scene nodes now exist */
setmon(c, c->pending_mon, c->pending_tags);
if (c->isfullscreen)
setfullscreen(c, 1);
if (c->border_bg)