================================================================================ EVIDENCE: Task 5 — wlr_fractional_scale_manager_v1 propagation chain ================================================================================ Goal: Verify that scale-change notifications reach surfaces when any output configuration changes (wlr-randr, hotplug, layout rejig, etc.). ================================================================================ PATH 1 (direct): outputmgrapplyortest() → updatemons() ================================================================================ File: src/peachwm.c Function: outputmgrapplyortest() (line 2553) Call site: line 2612 — updatemons(nullptr, nullptr); Triggered by: - outputmgrapply() (line 2548 — from wlr_output_manager config apply) - outputmgrtest() (line 2615 — from wlr_output_manager test) This path fires when a client (e.g. wlr-randr) sends a new output configuration. After committing the per-head state and sending the success/failure response, updatemons() is called unconditionally. CONFIRMED ✅ — updatemons(nullptr, nullptr) at line 2612. ================================================================================ PATH 2 (indirect): output_layout.change signal → updatemons() ================================================================================ Listener declaration: line 364 static struct wl_listener layout_change = {.notify = updatemons}; Signal wiring: line 3691 wl_signal_add(&output_layout->events.change, &layout_change); This path fires when the output layout changes via any other route (e.g. hotplug, wlr_output_layout_add call inside updatemons itself). It is the "belt" to the "suspenders" of Path 1. Note: outputmgrapplyortest() calls wlr_output_layout_add() at line 2600, which itself triggers output_layout.change — so Path 2 also fires during Path 1. updatemons() is idempotent (no ill effect from running twice in a single event cycle). CONFIRMED ✅ — layout_change.notify = updatemons at line 364, wired at line 3691. ================================================================================ SCALE RE-NOTIFICATION HOOK (inside updatemons) ================================================================================ File: src/peachwm.c Function: updatemons() (line 4101) Hook: lines 4168–4201 For each enabled monitor: [clients loop, line 4170] wl_list_for_each(c, &clients, link) { if (c->mon != m) continue; client_update_scale(c); // ← task 4 hook if (!client_is_x11(c) && c->surface.xdg) { struct wlr_xdg_popup *popup; wl_list_for_each(popup, &c->surface.xdg->popups, link) wlr_fractional_scale_v1_notify_scale( popup->base->surface, (double)m->wlr_output->scale); } } [layers loop, line 4181] for (int i = 0; i < 4; i++) { LayerSurface *l; wl_list_for_each(l, &m->layers[i], link) { layersurface_update_scale(l); // ← task 4 hook { struct wlr_scene_node *popup_node; wl_list_for_each(popup_node, &l->popups->children, link) { if (popup_node->type != WLR_SCENE_NODE_BUFFER) continue; struct wlr_scene_buffer *sb = wlr_scene_buffer_from_node(popup_node); struct wlr_scene_surface *ss = wlr_scene_surface_try_from_buffer(sb); if (ss && ss->surface) wlr_fractional_scale_v1_notify_scale( ss->surface, (double)m->wlr_output->scale); } } } } This covers both regular xdg-toplevel clients and layer-shell surfaces (bars, backgrounds, OSDs), including their XDG popups. CONFIRMED ✅ — scale re-notification hook present and complete. ================================================================================ VERDICT: PROPAGATION CHAIN CONFIRMED ✅ ================================================================================ outputmgrapplyortest() → updatemons() [direct: line 2612] layout_change signal → updatemons() [indirect: lines 364, 3691] updatemons() → client_update_scale(), layersurface_update_scale(), wlr_fractional_scale_v1_notify_scale() [lines 4168–4201] No code changes required. The chain is complete. Scale-change notifications will reach every surface (clients + layers + popups) whenever output configuration changes through ANY path. Test: wlr-randr --output DP-1 --scale 2 # triggers Path 1 via config apply # which calls updatemons, which re-notifies every surface on that output. # Also triggers Path 2 via wlr_output_layout_add calling events.change. ================================================================================