diff options
| author | Danilo M. <danix@danix.xyz> | 2026-09-15 14:06:08 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-09-15 14:06:08 +0200 |
| commit | ee860b6a3e955bc0d625af18168dd079e93ca9e0 (patch) | |
| tree | 86fb62453990ff27145190a53716ec0b3ee55122 /docs/superpowers | |
| parent | 18b2cffb1b7e6f8e35152898011c71288e871422 (diff) | |
| download | quickshell-ee860b6a3e955bc0d625af18168dd079e93ca9e0.tar.gz quickshell-ee860b6a3e955bc0d625af18168dd079e93ca9e0.zip | |
docs: fix the expire_timeout direction in the spec and plan
The freedesktop spec says -1 means the server decides and 0 means never; the
spec and plan had them reversed, which the shipped code inherited and the
live handover test caught. Corrected to match the spec, libnotify's -1
default and dunst.
Diffstat (limited to 'docs/superpowers')
| -rw-r--r-- | docs/superpowers/plans/2026-09-15-notifyd.md | 24 | ||||
| -rw-r--r-- | docs/superpowers/specs/2026-09-15-notification-daemon-design.md | 23 |
2 files changed, 27 insertions, 20 deletions
diff --git a/docs/superpowers/plans/2026-09-15-notifyd.md b/docs/superpowers/plans/2026-09-15-notifyd.md index 9a017d8..afb938f 100644 --- a/docs/superpowers/plans/2026-09-15-notifyd.md +++ b/docs/superpowers/plans/2026-09-15-notifyd.md @@ -140,10 +140,10 @@ func TestEffectiveTimeoutMS(t *testing.T) { u Urgency want int64 }{ - {"zero uses low default", 0, Low, 10_000}, - {"zero uses normal default", 0, Normal, 10_000}, - {"zero critical never", 0, Critical, 0}, - {"minus one never", -1, Normal, 0}, + {"minus one uses low default", -1, Low, 10_000}, + {"minus one uses normal default", -1, Normal, 10_000}, + {"minus one critical never", -1, Critical, 0}, + {"zero never", 0, Normal, 0}, {"explicit wins", 3_000, Normal, 3_000}, {"sub second exact", 1, Normal, 1}, } @@ -228,8 +228,9 @@ const ( Critical Urgency = "critical" ) -// DefaultTimeoutMS is the balloon lifetime for an urgency when the client sends -// expire_timeout 0. Critical never expires, which is 0 here. +// DefaultTimeoutMS is the balloon lifetime for an urgency when the client +// leaves the choice to the server (expire_timeout -1). Critical never expires, +// which is 0 here. func DefaultTimeoutMS(u Urgency) int64 { switch u { case Low, Normal: @@ -239,14 +240,17 @@ func DefaultTimeoutMS(u Urgency) int64 { } } -// EffectiveTimeoutMS resolves the client's expire_timeout: 0 means the urgency -// default, -1 means never, anything positive is milliseconds and wins. +// EffectiveTimeoutMS resolves the client's expire_timeout per the freedesktop +// spec: -1 means the server decides (the urgency default), 0 means never, and +// anything positive is milliseconds and wins. The spec is precise about the +// direction and libnotify's default is -1, so getting it backwards would make +// every plain notify-send immortal. func EffectiveTimeoutMS(expire int32, u Urgency) int64 { switch { case expire == -1: - return 0 - case expire == 0: return DefaultTimeoutMS(u) + case expire == 0: + return 0 default: return int64(expire) } diff --git a/docs/superpowers/specs/2026-09-15-notification-daemon-design.md b/docs/superpowers/specs/2026-09-15-notification-daemon-design.md index fa287e1..4e2806a 100644 --- a/docs/superpowers/specs/2026-09-15-notification-daemon-design.md +++ b/docs/superpowers/specs/2026-09-15-notification-daemon-design.md @@ -60,10 +60,12 @@ closed by a `CloseNotification` call. All of this is in the daemon and is independent of any renderer. **Timeout, and the two lifetimes.** `expire_timeout` from `Notify` is honoured -exactly as the notification's balloon lifetime: `0` means use the urgency -default, `-1` means never expire, any positive value is milliseconds. The -urgency defaults are `10s` for low, `10s` for normal and never for critical, -matching the running dunst. `ronema` relies on `-t 0` meaning never and `-t 1` +exactly as the notification's balloon lifetime, in the spec's direction: `-1` +means the server decides, so it takes the urgency default; `0` means never; any +positive value is milliseconds and wins. The urgency defaults are `10s` for +low, `10s` for normal and never for critical, matching the running dunst. +libnotify sends `-1` by default, so a plain `notify-send` gets the urgency +default, and `dunst` agrees. `ronema` relies on `-t 0` meaning never and `-t 1` meaning effectively immediate; both work unchanged. At expiry the daemon emits `NotificationClosed(id, 1)` and the balloon goes, @@ -122,15 +124,16 @@ A live notification is one object: "urgency": "normal", "icon": "/home/you/.local/share/icons/.../mail-unread-multiple.svg", "actions": [["default", "open"]], - "created": 1758000000, - "expires": 1758000010 + "created": 1758000000000, + "expires": 1758000010000 } `app`, `summary` and `body` are markup. `icon` is an absolute path or empty. -`actions` is the spec's key and label pairs. `expires` is an epoch second, or -`0` for a notification that never expires; a value in the past means the -balloon has gone and the entry is inert. The history objects are the same -shape. +`actions` is the spec's key and label pairs. `created` and `expires` are epoch +milliseconds, so a sub-second timeout (`ronema` sends `-t 1`) is exact rather +than rounding to zero, which would read as never. `expires` is `0` for a +notification that never expires; a value in the past means the balloon has gone +and the entry is inert. The history objects are the same shape. `queue.json` is capped at 20; an arrival beyond the cap pushes the oldest into history. |
