aboutsummaryrefslogtreecommitdiffstats
path: root/notifications/Balloons.qml
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-10-06 10:02:41 +0200
committerDanilo M. <danix@danix.xyz>2026-10-06 10:02:41 +0200
commit595d42fbd4ee206d2b16d033e1be337f9c97eee7 (patch)
treee59353ad2d43392cd8e1cf9d212140479388a450 /notifications/Balloons.qml
parent87ed521bad8774899f5080f937665b110f44ac27 (diff)
downloadquickshell-595d42fbd4ee206d2b16d033e1be337f9c97eee7.tar.gz
quickshell-595d42fbd4ee206d2b16d033e1be337f9c97eee7.zip
feat(notifications): window border on the balloons
The balloons now wear the Hyprland window border: 2px, the udt gradient read from ~/.cache/udt/udt-border.lua (the file look_and_feel.lua reads, watched so a wallpaper change follows), rotating, with the windows' corners. A Rectangle border takes one colour and its radius is circular, while the windows use rounding 15 at rounding_power 4, a superellipse. So the body and the border are both drawn by a Shape from an SVG path whose corners are the cubic fit to |x|^4 + |y|^4 = 1, and the border is a ring filled odd-even, which keeps the translucent body from showing the gradient through. One angle drives every balloon, so they turn together, and the animation runs only while the stack is mapped. Hyprland's borderangle (speed 30) reads as 3s a turn, which looked slow on a balloon that size, so the turn is 1.5s, tuned by eye. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'notifications/Balloons.qml')
-rw-r--r--notifications/Balloons.qml39
1 files changed, 38 insertions, 1 deletions
diff --git a/notifications/Balloons.qml b/notifications/Balloons.qml
index 3676e67..d22e4a1 100644
--- a/notifications/Balloons.qml
+++ b/notifications/Balloons.qml
@@ -10,6 +10,7 @@
// GNU General Public License for more details.
import Quickshell
+import Quickshell.Io
import Quickshell.Wayland
import QtQuick
@@ -35,6 +36,37 @@ Scope {
// (reloading icons, resetting hover) four times a second.
readonly property var live: Notify.queue || []
+ // 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
+ // fallback is the triple look_and_feel.lua falls back to.
+ property var borderColors: ["#c6a0f6", "#b7bdf8", "#8aadf4"]
+ FileView {
+ path: `${Quickshell.env("HOME")}/.cache/udt/udt-border.lua`
+ watchChanges: true
+ onFileChanged: reload()
+ onLoaded: {
+ const re = /rgba?\(([0-9a-fA-F]{6})([0-9a-fA-F]{2})?\)/g;
+ const out = [];
+ let m;
+ while ((m = re.exec(text())) !== null) out.push("#" + (m[2] ?? "") + m[1]);
+ if (out.length > 0) root.borderColors = out;
+ }
+ }
+
+ // Hyprland's borderangle is speed 30, linear, loop, which reads as 3s a
+ // turn, but on a balloon that size looked slow next to the windows, so
+ // the turn is tuned by eye rather than taken from the config. One angle for every balloon, so they turn together like the
+ // windows do, and only while the stack is mapped.
+ property real borderAngle: 0
+ NumberAnimation on borderAngle {
+ from: 0
+ to: 2 * Math.PI
+ duration: 1500
+ loops: Animation.Infinite
+ running: win.visible
+ }
+
PanelWindow {
id: win
@@ -65,7 +97,12 @@ Scope {
Repeater {
model: root.live
- NotificationBalloon { notification: modelData; now: root.now }
+ NotificationBalloon {
+ notification: modelData
+ now: root.now
+ borderColors: root.borderColors
+ borderAngle: root.borderAngle
+ }
}
}
}