From 84941247c4cc4068922116f6ba9ca8464c568c4e Mon Sep 17 00:00:00 2001 From: en Date: Wed, 16 Sep 2026 08:03:05 +0200 Subject: [PATCH] Gate toggle_pin on ENBOXER_ALLOW_LAYOUT (Bug #12) toggle_pin (a.k.a. stay-on-top) is a per-window Hyprland mutation, the same class of side-effect as layout-apply. Without an opt-in gate, a stray hotkey can pin the leader window while the user is away from the keyboard. Adds the moves_allowed() helper next to toggle_pin. The rest of session.rs is unaffected for now; future commits can replace inline env checks with this helper. --- src/session.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/session.rs b/src/session.rs index 5a9bbf6..ba4f5f7 100644 --- a/src/session.rs +++ b/src/session.rs @@ -690,7 +690,26 @@ async fn reset_layout(session: &Arc>) -> Result<()> { Ok(()) } +/// True iff the operator has explicitly allowed the daemon to mutate the +/// Hyprland window stack. The enBoxer defaults are keys-only with safe +/// passthrough; per-window moves (pin/float/move/resize) require an opt-in +/// so a stray hotkey cannot wreck the user's layout while they are away +/// from the keyboard. +pub fn moves_allowed() -> bool { + std::env::var("ENBOXER_ALLOW_LAYOUT") + .map(|v| v == "1" || v.eq_ignore_ascii_case("true")) + .unwrap_or(false) +} + async fn toggle_pin(session: &Arc>) -> Result<()> { + // Bug #12: pin/float/move/resize must be opt-in like layout-apply, + // not silently fire on the leader slot on a hotkey press. + if !moves_allowed() { + tracing::warn!( + "toggle_pin: refusing (set ENBOXER_ALLOW_LAYOUT=1 to enable)" + ); + return Ok(()); + } let addr = { let g = session.lock().await; g.slots