// Copyright (C) 2026 Danilo M. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as // published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. package notify import "github.com/godbus/dbus/v5" // Urgency is the freedesktop urgency level. type Urgency string const ( Low Urgency = "low" Normal Urgency = "normal" Critical Urgency = "critical" ) // 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: return 10_000 default: return 0 } } // 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 DefaultTimeoutMS(u) case expire == 0: return 0 default: return int64(expire) } } // UrgencyFromHints reads the urgency byte: 0 low, 1 normal, 2 critical. A // missing or malformed value is normal, the same default libnotify uses. func UrgencyFromHints(hints map[string]dbus.Variant) Urgency { v, ok := hints["urgency"] if !ok { return Normal } switch n := v.Value().(type) { case uint8: switch n { case 0: return Low case 2: return Critical } case int32: switch n { case 0: return Low case 2: return Critical } } return Normal } // StackTagFromHints reads the dunst stack tag, then the danix spelling. Both // mean the same thing and dunst wins when a client sends both. func StackTagFromHints(hints map[string]dbus.Variant) string { for _, key := range []string{"x-dunst-stack-tag", "x-danix-stack-tag"} { if v, ok := hints[key]; ok { if s, ok := v.Value().(string); ok && s != "" { return s } } } return "" } // ParseActions turns the spec's flat [key, label, key, label] array into pairs. func ParseActions(flat []string) [][2]string { out := make([][2]string, 0, len(flat)/2) for i := 0; i+1 < len(flat); i += 2 { out = append(out, [2]string{flat[i], flat[i+1]}) } return out }