config: deserialize cursor_hide with defaults for missing fields

Serde ignores unknown fields but errors on missing ones, so adding a
fifth trigger later would make every existing cursor_hide file fail to
deserialize. get_entry would then substitute the struct default and
Config::load swallows the error — its warn! loop is behind
cfg!(debug_assertions) — silently resetting everyone's settings on
upgrade. That is the exact failure this key was grouped to avoid.

It also has a present-day effect: the migration shim cannot tell "absent"
from "present but unparseable", so a partial hand-written cursor_hide was
treated as absent and overwritten — and hand-editing is what the shim's
audience does.

Drafted with Claude (Anthropic); reviewed and tested by the committer.
This commit is contained in:
Niklas Herder 2026-09-12 09:47:19 +02:00 • committed by Victoria Brekenfeld
parent 295eaa8f63
commit 7596cf7f2f

View file

@ -212,7 +212,10 @@ pub enum HideDecision {
/// When the cursor hides itself. Every trigger is revealed by pointer input, so /// When the cursor hides itself. Every trigger is revealed by pointer input, so
/// these differ only in what arms the hide and after how long. /// these differ only in what arms the hide and after how long.
// `default`: a trigger added later must not make every existing file fail to
// deserialize, which `get_entry` would swallow as "reset everyone to defaults".
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
#[serde(default)]
pub struct CursorHideConfig { pub struct CursorHideConfig {
/// Seconds of pointer inactivity before hiding, anywhere. `None` disables. /// Seconds of pointer inactivity before hiding, anywhere. `None` disables.
pub idle_timeout: Option<u32>, pub idle_timeout: Option<u32>,