aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-10-19 09:52:58 +0200
committerDanilo M. <danix@danix.xyz>2026-10-19 09:52:58 +0200
commit96b359b8f9c7dbfea7ac4f2ff367a0385d72622c (patch)
treecc83091499a3471c8539db4204ecef9695a02671
parent10868cab37e7dadf247d5da78f5eb5e69bcb6c9d (diff)
downloadquickshell-96b359b8f9c7dbfea7ac4f2ff367a0385d72622c.tar.gz
quickshell-96b359b8f9c7dbfea7ac4f2ff367a0385d72622c.zip
notifications: play a sound for a new balloon
pw-play, once per new or replaced notification, only when the balloon would show: the drawer, snooze, mute and DND that withhold the balloon silence it too. A restart records the queue without playing it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
-rw-r--r--notifications/Balloons.qml34
1 files changed, 34 insertions, 0 deletions
diff --git a/notifications/Balloons.qml b/notifications/Balloons.qml
index b02099c..1b3cce8 100644
--- a/notifications/Balloons.qml
+++ b/notifications/Balloons.qml
@@ -13,6 +13,7 @@ import Quickshell
import Quickshell.Io
import Quickshell.Wayland
import QtQuick
+import "NotifyConfig.js" as NC
// The balloon stack, in the corner and on the screen notifyd's config.json
// names (bottom-right of DP-1 by default), over conky.
@@ -37,6 +38,39 @@ Scope {
// (reloading icons, resetting hover) four times a second.
readonly property var live: Notify.queue || []
+ // A sound per new or replaced notification (replace keeps the id and
+ // changes created), played only when its balloon would show now: the
+ // same drawer, snooze, mute and DND checks as NotificationBalloon. The
+ // first read after a start only records what is there, so a restart is
+ // silent. seen is rebuilt from the queue each time, so it never grows.
+ property var seen: ({})
+ property bool primed: false
+ Connections {
+ target: Notify
+ function onQueueChanged() {
+ const next = {};
+ let file = "";
+ for (const n of Notify.queue || []) {
+ const key = n.id + ":" + n.created;
+ next[key] = true;
+ if (!root.primed || root.seen[key] || file !== "") continue;
+ if (Notify.drawerOpen || Notify.snoozeUntil > Date.now()) continue;
+ if (NC.withheld(Notify.config, n, Notify.dnd)) continue;
+ file = NC.soundFor(Notify.config, n);
+ }
+ root.seen = next;
+ root.primed = true;
+ if (file !== "") {
+ // ponytail: one player, a new sound cuts the last; a queue of
+ // sounds if bursts ever need every one heard.
+ player.command = ["pw-play", file];
+ player.running = false;
+ player.running = true;
+ }
+ }
+ }
+ Process { id: player }
+
// The window border gradient, from the same file Hyprland reads, so the
// balloons wear the windows' border. udt-accent writes it as Hyprland
// colours, `rgb(rrggbb)` or `rgba(rrggbbaa)`; Qt wants `#aarrggbb`. The