aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md24
-rw-r--r--SPEC.md22
-rwxr-xr-xbin/wb-icon2
-rw-r--r--config.jsonc14
-rwxr-xr-xinstall.sh15
-rw-r--r--modules/custom/mail.jsonc27
-rw-r--r--styles/modules.css30
-rw-r--r--styles/pills.css8
8 files changed, 111 insertions, 31 deletions
diff --git a/README.md b/README.md
index d7f995e..f44d04e 100644
--- a/README.md
+++ b/README.md
@@ -4,19 +4,23 @@ Two waybar bars for DP-3: pill clusters, icons from the desktop's own icon
theme instead of font glyphs, and colours driven by
[unified-desktop-theme](../unified-desktop-theme).
- top [📅 Wed 15/09] [🕑 14:32] [●●] [S] [●] [🔊] [tray] [⏻] [🇮🇹]
- bottom [1..8] [ open windows ]
+ DP-3 [📅 Wed 15/09] [🕑 14:32] [●] [S] [●] [✉ 9] [🔊] [tray] [⏻] [🇮🇹]
+ DP-1 [1..8] [ open windows ]
Each bracket is a pill. Pills group into clusters with gaps between them, so
the bars read as a few objects rather than one strip. Hover cross-fades
background and text over 0.3s; taskbar buttons underline in the accent.
-DP-3 is rotated, so a bar there is 1080px wide rather than 1920, and one bar
-holding everything was too crowded. Status sits on top, the desktop itself
-(workspaces and open windows) along the bottom. Both bars are one waybar
+DP-3 is rotated, so a bar there is only 1080px wide, which is why it carries
+status alone. The desktop itself, the workspaces and the window list, sits on
+DP-1 where there are 2560px to spread them across. Both bars are one waybar
process reading one stylesheet: waybar takes a top-level array of bars, so
they cannot drift apart.
+This replaces the stock bar. Hyprland starts it from
+`~/.config/hypr/sections/autostart.lua`; `~/.config/waybar/` is left on disk
+but nothing reads it.
+
## Install
./install.sh
@@ -74,11 +78,11 @@ their national colours.
| Bar | Cluster | Modules |
| --- | --- | --- |
-| top | left | date, time, VM dots |
-| top | centre | launcher |
-| top | right | privacy dots, volume drawer, tray, presentation mode, language |
-| bottom | left | workspaces |
-| bottom | right | open windows |
+| DP-3 | left | date, time, VM dots |
+| DP-3 | centre | launcher |
+| DP-3 | right | privacy dots, mail, volume drawer, tray, presentation mode, language |
+| DP-1 | left | workspaces |
+| DP-1 | right | open windows |
No battery, temperature, CPU, memory or backlight: this is a desktop.
diff --git a/SPEC.md b/SPEC.md
index 16a701b..7d151d1 100644
--- a/SPEC.md
+++ b/SPEC.md
@@ -23,17 +23,22 @@ pointed at DP-3.
## Layout
- top [📅 Wed 15/09] [🕑 14:32] [●●] [S] [●] [🔊] [tray] [⏻] [🇮🇹]
- date time vm launcher priv vol tray present lang
+ DP-3 [📅 Wed 15/09] [🕑 14:32] [●] [S] [●] [✉ 9] [🔊] [tray] [⏻] [🇮🇹]
+ date time vm launcher priv mail vol tray present lang
- bottom [1..8] [ open windows ]
- workspaces taskbar
+ DP-1 [1..8] [ open windows ]
+ workspaces taskbar
-DP-3 is rotated, so a bar there is 1080px wide rather than 1920. One bar
-holding every module was too crowded at that width, so status sits on top and
-the desktop itself along the bottom. Both are one waybar process reading one
+DP-3 is rotated, so a bar there is only 1080px wide. One bar holding every
+module was too crowded at that width, so status stays on DP-3 alone and the
+desktop itself, the workspaces and the window list, moved to DP-1 where there
+are 2560px to spread them across. Both are one waybar process reading one
stylesheet: waybar takes a top-level array of bars.
+This replaces the stock bar rather than sitting beside it. Hyprland starts it
+from `~/.config/hypr/sections/autostart.lua`, which used to launch a bare
+`waybar`; `~/.config/waybar/` is left on disk but nothing reads it.
+
Each bracket is one pill. Neighbouring pills in a cluster share a background
and weld together with asymmetric corner radii; clusters are separated by
transparent gaps, so the bar reads as groups rather than a continuous strip.
@@ -50,7 +55,8 @@ transparent gaps, so the bar reads as groups rather than a continuous strip.
| center | `wlr/taskbar` | `icon-theme` config key | Per-window application icons. |
| right | `group/wireplumber` | `image` module | Drawer group kept as it is today. |
| right | `tray` | application-provided | |
-| right | `custom/presentation` | CSS, keyed on the module's class | Presentation mode, the same `statusctl`-backed module the DP-1 bar runs. It already emits an empty text and a state class, so the icon is chosen in CSS and the glyphs are simply dropped. |
+| right | `custom/mail` | CSS, plus the count as text | Unread mail, the same notmuch watcher the stock bar ran. The envelope is a CSS background; the count stays text, because it is content rather than decoration, exactly like the clock. |
+| right | `custom/presentation` | CSS, keyed on the module's class | Presentation mode, the same `statusctl`-backed module the stock bar ran. It already emits an empty text and a state class, so the icon is chosen in CSS and the glyphs are simply dropped. |
| right | `image#lang` | `flag-it.svg` / `flag-gb.svg`, shipped here | An `image` module: `hyprland/language` styles as `#language` only, with no per-language class, so a flag cannot be selected in CSS. |
Dropped from the current bar: `custom/breaktimer`, `custom/mail`,
diff --git a/bin/wb-icon b/bin/wb-icon
index b8f91cc..9e011b9 100755
--- a/bin/wb-icon
+++ b/bin/wb-icon
@@ -119,10 +119,12 @@ def selftest():
"x-office-presentation", # on
"dialog-warning", # no state file
]
+ mail_icons = ["mail-unread"]
names = sorted(
{n for group in ICONS.values() for n in group.values()}
| set(workspace_icons) | set(clock_icons) | set(presentation_icons)
+ | set(mail_icons)
)
missing = [n for n in names if not lookup(n)]
for n in names:
diff --git a/config.jsonc b/config.jsonc
index a7c5ff9..1d94a39 100644
--- a/config.jsonc
+++ b/config.jsonc
@@ -1,13 +1,13 @@
-// waybar-theme-udt: two bars on DP-3.
+// waybar-theme-udt: the status bar on DP-3, the desktop bar on DP-1.
// Copyright (C) 2026 Danilo M. <danix@danix.xyz>
// Licensed under the GNU General Public License v2 only.
//
// A top-level array is how waybar takes more than one bar. Both bars are one
// process reading one stylesheet, so the pills stay consistent between them.
//
-// DP-3 is rotated, so the bar is 1080px rather than 1920: one bar holding
-// everything was too crowded at that width. Status lives on top, the desktop
-// (workspaces and open windows) along the bottom.
+// DP-3 is rotated and only 1080px wide, which is why it carries status alone.
+// The desktop itself, the workspaces and the window list, sits on DP-1 where
+// there are 2560px to spread them across.
//
// One file per module, included explicitly: wildcard `include` has been broken
// since waybar v0.14.0, so every module file has to be listed by name.
@@ -18,6 +18,7 @@
"$HOME/.config/waybar-udt/modules/custom/vmdot.jsonc",
"$HOME/.config/waybar-udt/modules/image/launcher.jsonc",
"$HOME/.config/waybar-udt/modules/custom/privacy_dots.jsonc",
+ "$HOME/.config/waybar-udt/modules/custom/mail.jsonc",
"$HOME/.config/waybar-udt/modules/image/volume.jsonc",
"$HOME/.config/waybar-udt/modules/extras/tray.jsonc",
"$HOME/.config/waybar-udt/modules/custom/presentation.jsonc",
@@ -34,6 +35,7 @@
],
"modules-right": [
"custom/privacy_dots",
+ "custom/mail",
"group/volume",
"tray",
"custom/presentation",
@@ -64,8 +66,8 @@
],
"layer": "top",
- "output": "DP-3",
- "position": "bottom",
+ "output": "DP-1",
+ "position": "top",
"height": 0,
"width": 0,
"margin": 0,
diff --git a/install.sh b/install.sh
index ad75744..cd64844 100755
--- a/install.sh
+++ b/install.sh
@@ -3,10 +3,13 @@
# Copyright (C) 2026 Danilo M. <danix@danix.xyz>
# Licensed under the GNU General Public License v2 only.
#
-# This installs a SECOND bar, at ~/.config/waybar-udt/. The existing bar at
-# ~/.config/waybar/ is left alone, so DP-1 keeps working while this one is
-# tried on DP-3. Nothing is started: the command to run it is printed at the
-# end.
+# Installs to ~/.config/waybar-udt/, which is a separate config directory from
+# the stock ~/.config/waybar/: that one is left on disk untouched, so its
+# modules and scripts stay available to go back to.
+#
+# Nothing is started here. Hyprland launches the bar on login from
+# ~/.config/hypr/sections/autostart.lua; the command is printed at the end for
+# starting it by hand.
set -euo pipefail
repo="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
@@ -86,7 +89,7 @@ ln -sfn "$repo/config.jsonc" "$target/config.jsonc"
for f in modules/clock.jsonc \
modules/hyprland/workspaces.jsonc \
modules/custom/vmdot.jsonc modules/custom/privacy_dots.jsonc \
- modules/custom/presentation.jsonc \
+ modules/custom/presentation.jsonc modules/custom/mail.jsonc \
modules/extras/taskbar.jsonc modules/extras/tray.jsonc \
modules/image/volume.jsonc modules/image/language.jsonc; do
ln -sfn "$repo/$f" "$target/$f"
@@ -146,4 +149,4 @@ ln -sfn "$repo/bin/wb-lang" "$HOME/bin/wb-lang"
echo
echo "installed to $target"
echo "run it with: waybar -c $target/config.jsonc -s $target/styles/style.css"
-echo "your existing bar on DP-1 is untouched."
+echo "hyprland starts it on login; see ~/.config/hypr/sections/autostart.lua"
diff --git a/modules/custom/mail.jsonc b/modules/custom/mail.jsonc
new file mode 100644
index 0000000..65cd9e8
--- /dev/null
+++ b/modules/custom/mail.jsonc
@@ -0,0 +1,27 @@
+// Unread mail, the same watcher the DP-1 bar runs.
+//
+// The count is read from the local notmuch index rather than polled from the
+// Gmail API, so it drops the moment mail is read in qtmaildir and rises the
+// moment mbsync commits. No "interval": the script runs in continuous mode,
+// printing one JSON line per notmuch commit, and waybar owns the watcher
+// process, which is why there is no daemon to supervise.
+//
+// The envelope is a CSS background rather than the DP-1 bar's glyph, but the
+// count stays text: it is the content, not decoration, exactly like the clock.
+//
+// The format keeps a trailing space so it is never empty. The script emits
+// {"text":""} with class "empty" when nothing is unread, and waybar draws no
+// widget at all for a custom module whose formatted output is empty: not an
+// empty pill, no pill. The space keeps the envelope on the bar at zero unread.
+//
+// See ~/Programming/GIT/quickshell/desktop/modules/mail/README.md
+{
+ "custom/mail": {
+ "format": "{} ",
+ "return-type": "json",
+ "exec": "$HOME/Programming/GIT/quickshell/desktop/modules/mail/waybar-mail.sh",
+ "on-click": "qs -p $HOME/Programming/GIT/quickshell/desktop ipc call drawer open mail",
+ "on-click-right": "$HOME/bin/mailsync.sh",
+ "tooltip": false
+ }
+}
diff --git a/styles/modules.css b/styles/modules.css
index 4d3d38e..9044455 100644
--- a/styles/modules.css
+++ b/styles/modules.css
@@ -106,6 +106,36 @@
min-width: 22px;
}
+/* ------------------------------------------------------ *
+ * Mail: envelope icon, unread count as text. *
+ * *
+ * The count is content rather than decoration, so it stays *
+ * text like the clock. The state comes from the watcher's *
+ * class: nothing unread is dim, a dead watcher is loud. *
+ * ------------------------------------------------------ */
+
+#custom-mail {
+ background-image: url("@ICONS@/actions/22/mail-unread.svg");
+ background-repeat: no-repeat;
+ background-position: 10px center;
+ background-size: 16px 16px;
+ padding-left: 32px;
+ min-height: 16px;
+}
+
+#custom-mail.empty {
+ color: @main-fg;
+ opacity: 0.45;
+}
+
+#custom-mail.unread {
+ color: @main-fg;
+}
+
+#custom-mail.error {
+ color: @critical;
+}
+
/* ------------------------------------------- *
* Dots: coloured by their scripts, not by CSS. *
* ------------------------------------------- */
diff --git a/styles/pills.css b/styles/pills.css
index 40c6629..93a8855 100644
--- a/styles/pills.css
+++ b/styles/pills.css
@@ -19,6 +19,7 @@
#custom-vmdot,
#taskbar,
#custom-privacy_dots,
+#custom-mail,
#volume,
#tray,
#custom-presentation,
@@ -38,6 +39,7 @@
#clock.time:hover,
#custom-vmdot:hover,
#custom-privacy_dots:hover,
+#custom-mail:hover,
#volume:hover,
#tray:hover,
#custom-presentation:hover,
@@ -78,11 +80,15 @@
margin-left: 6px;
}
-/* Right: privacy | volume | tray | presentation | language */
+/* Right: privacy | mail | volume | tray | presentation | language */
#custom-privacy_dots {
margin-right: 6px;
}
+#custom-mail {
+ margin-right: 6px;
+}
+
#volume {
margin-right: 6px;
}