diff --git a/bazzite/waybar/config.jsonc b/bazzite/waybar/config.jsonc
index 6b3918c..bc19250 100644
--- a/bazzite/waybar/config.jsonc
+++ b/bazzite/waybar/config.jsonc
@@ -1,214 +1,160 @@
// -*- mode: jsonc -*-
{
- // "layer": "top", // Waybar at top layer
- // "position": "bottom", // Waybar position (top|bottom|left|right)
- "height": 30, // Waybar height (to be removed for auto height)
- // "width": 1280, // Waybar width
- "spacing": 4, // Gaps between modules (4px)
- // Choose the order of the modules
+ "layer": "top",
+ "height": 32,
+ "spacing": 8,
+
"modules-left": [
- "sway/workspaces",
- "sway/mode",
- "sway/scratchpad"
+ "niri/workspaces"
],
"modules-center": [
- "sway/window"
+ "niri/window"
],
"modules-right": [
+ "privacy",
+ "custom/mail",
"idle_inhibitor",
+ "custom/weather",
"pulseaudio",
"network",
"power-profiles-daemon",
"cpu",
"memory",
"temperature",
- "backlight",
- "sway/language",
- "battery",
+ "custom/gpu",
+ "disk",
+ "niri/language",
"clock",
"tray"
],
- // Modules configuration
- // "sway/workspaces": {
- // "disable-scroll": true,
- // "all-outputs": true,
- // "warp-on-scroll": false,
- // "format": "{name}: {icon}",
- // "format-icons": {
- // "1": "",
- // "2": "",
- // "3": "",
- // "4": "",
- // "5": "",
- // "urgent": "",
- // "focused": "",
- // "default": ""
- // }
- // },
- "keyboard-state": {
- "numlock": true,
- "capslock": true,
- "format": "{name} {icon}",
- "format-icons": {
- "locked": "",
- "unlocked": ""
- }
+
+ "niri/workspaces": {
+ "format": "{index}"
},
- "sway/mode": {
- "format": "{}"
+
+ "niri/window": {
+ "format": "{}",
+ "max-length": 50
},
- "sway/scratchpad": {
- "format": "{icon} {count}",
- "show-empty": false,
- "format-icons": ["", ""],
+
+ "niri/language": {
+ "format": "{short}"
+ },
+
+ "privacy": {
+ "icon-spacing": 4,
+ "icon-size": 16,
+ "transition-duration": 250,
+ "modules": [
+ { "type": "screenshare" },
+ { "type": "audio-in" },
+ { "type": "audio-out" }
+ ]
+ },
+
+ "custom/mail": {
+ "format": "{}",
+ "return-type": "json",
+ "exec": "python3 ~/.config/waybar/scripts/mail.py",
+ "interval": 60,
"tooltip": true,
- "tooltip-format": "{app}: {title}"
- },
- "mpd": {
- "format": "{stateIcon} {consumeIcon}{randomIcon}{repeatIcon}{singleIcon}{artist} - {album} - {title} ({elapsedTime:%M:%S}/{totalTime:%M:%S}) ⸨{songPosition}|{queueLength}⸩ {volume}% ",
- "format-disconnected": "Disconnected ",
- "format-stopped": "{consumeIcon}{randomIcon}{repeatIcon}{singleIcon}Stopped ",
- "unknown-tag": "N/A",
- "interval": 5,
- "consume-icons": {
- "on": " "
- },
- "random-icons": {
- "off": " ",
- "on": " "
- },
- "repeat-icons": {
- "on": " "
- },
- "single-icons": {
- "on": "1 "
- },
- "state-icons": {
- "paused": "",
- "playing": ""
- },
- "tooltip-format": "MPD (connected)",
- "tooltip-format-disconnected": "MPD (disconnected)"
+ "on-click": "flatpak run org.mozilla.Thunderbird"
},
+
"idle_inhibitor": {
"format": "{icon}",
"format-icons": {
- "activated": "",
- "deactivated": ""
+ "activated": "",
+ "deactivated": ""
}
},
- "tray": {
- // "icon-size": 21,
- "spacing": 10,
- // "icons": {
- // "blueman": "bluetooth",
- // "TelegramDesktop": "$HOME/.local/share/icons/hicolor/16x16/apps/telegram.png"
- // }
+
+ "custom/weather": {
+ "format": "{}",
+ "return-type": "json",
+ "exec": "~/.config/waybar/scripts/weather.sh",
+ "interval": 900,
+ "tooltip": true
},
+
+ "custom/gpu": {
+ "format": " {}",
+ "return-type": "json",
+ "exec": "~/.config/waybar/scripts/gpu.sh",
+ "interval": 5,
+ "tooltip": true
+ },
+
+ "disk": {
+ "format": "{percentage_used}% ",
+ "path": "/",
+ "tooltip-format": "{used} / {total} ({percentage_used}%)"
+ },
+
+ "tray": {
+ "spacing": 10
+ },
+
"clock": {
- // "timezone": "America/New_York",
"tooltip-format": "{:%Y %B}\n{calendar}",
+ "format": "{:%H:%M}",
"format-alt": "{:%Y-%m-%d}"
},
+
"cpu": {
- "format": "{usage}% ",
+ "format": "{usage}% ",
"tooltip": false
},
+
"memory": {
- "format": "{}% "
+ "format": "{}% "
},
+
"temperature": {
- // "thermal-zone": 2,
- // "hwmon-path": "/sys/class/hwmon/hwmon2/temp1_input",
"critical-threshold": 80,
- // "format-critical": "{temperatureC}°C {icon}",
"format": "{temperatureC}°C {icon}",
- "format-icons": ["", "", ""]
- },
- "backlight": {
- // "device": "acpi_video1",
- "format": "{percent}% {icon}",
- "format-icons": ["🌑", "🌘", "🌗", "🌖", "🌕"]
- },
- "battery": {
- "states": {
- // "good": 95,
- "warning": 30,
- "critical": 15
- },
- "format": "{capacity}% {icon}",
- "format-full": "{capacity}% {icon}",
- "format-charging": "{capacity}% ",
- "format-plugged": "{capacity}% ",
- "format-alt": "{time} {icon}",
- // "format-good": "", // An empty format will hide the module
- // "format-full": "",
- "format-icons": ["", "", "", "", ""]
- },
- "battery#bat2": {
- "bat": "BAT2"
- },
- "power-profiles-daemon": {
- "format": "{icon}",
- "tooltip-format": "Power profile: {profile}\nDriver: {driver}",
- "tooltip": true,
- "format-icons": {
- "default": "",
- "performance": "",
- "balanced": "",
- "power-saver": ""
- }
+ "format-icons": ["", "", ""]
},
+
"network": {
- // "interface": "wlp2*", // (Optional) To force the use of this interface
- "format-wifi": "{essid} ({signalStrength}%) ",
- "format-ethernet": "{ipaddr}/{cidr} ",
- "tooltip-format": "{ifname} via {gwaddr} ",
- "format-linked": "{ifname} (No IP) ",
- "format-disconnected": "Disconnected ⚠",
- "format-alt": "{ifname}: {ipaddr}/{cidr}"
+ "format-wifi": "{icon}",
+ "format-ethernet": "",
+ "format-icons": ["", "", "", "", ""],
+ "tooltip-format-wifi": "{essid} ({signalStrength}%)\n{ipaddr}/{cidr}",
+ "tooltip-format-ethernet": "{ifname}\n{ipaddr}/{cidr}",
+ "format-linked": "{ifname} (No IP) ",
+ "format-disconnected": "",
+ "on-click": ""
},
+
"pulseaudio": {
- // "scroll-step": 1, // %, can be a float
"format": "{volume}% {icon} {format_source}",
- "format-bluetooth": "{volume}% {icon} {format_source}",
- "format-bluetooth-muted": " {icon} {format_source}",
- "format-muted": " {format_source}",
- "format-source": "{volume}% ",
- "format-source-muted": "",
+ "format-bluetooth": "{volume}% {icon} {format_source}",
+ "format-bluetooth-muted": " {icon} {format_source}",
+ "format-muted": " {format_source}",
+ "format-source": "{volume}% ",
+ "format-source-muted": "",
"format-icons": {
- "headphone": "",
- "hands-free": "",
- "headset": "",
- "phone": "",
- "portable": "",
- "car": "",
- "default": ["", "", ""]
+ "headphone": "",
+ "hands-free": "",
+ "headset": "",
+ "phone": "",
+ "portable": "",
+ "car": "",
+ "default": ["", "", ""]
},
"on-click": "pavucontrol"
},
- "custom/media": {
- "format": "{icon} {text}",
- "return-type": "json",
- "max-length": 40,
+
+ "power-profiles-daemon": {
+ "format": "{icon}",
+ "tooltip-format": "Power profile: {profile}\nDriver: {driver}",
+ "tooltip": true,
"format-icons": {
- "spotify": "",
- "default": "🎜"
- },
- "escape": true,
- "exec": "$HOME/.config/waybar/mediaplayer.py 2> /dev/null" // Script in resources folder
- // "exec": "$HOME/.config/waybar/mediaplayer.py --player spotify 2> /dev/null" // Filter player based on name
- },
- "custom/power": {
- "format" : "⏻ ",
- "tooltip": false,
- "menu": "on-click",
- "menu-file": "$HOME/.config/waybar/power_menu.xml", // Menu file in resources folder
- "menu-actions": {
- "shutdown": "shutdown",
- "reboot": "reboot",
- "suspend": "systemctl suspend",
- "hibernate": "systemctl hibernate"
- }
+ "default": "",
+ "performance": "",
+ "balanced": "",
+ "power-saver": ""
+ }
}
}
diff --git a/bazzite/waybar/scripts/gpu.sh b/bazzite/waybar/scripts/gpu.sh
new file mode 100644
index 0000000..420f528
--- /dev/null
+++ b/bazzite/waybar/scripts/gpu.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+data=$(nvidia-smi --query-gpu=utilization.gpu,temperature.gpu --format=csv,noheader,nounits 2>/dev/null)
+if [ -z "$data" ]; then
+ echo '{"text": "N/A", "tooltip": "nvidia-smi not available"}'
+ exit 0
+fi
+usage=$(echo "$data" | cut -d',' -f1 | tr -d ' ')
+temp=$(echo "$data" | cut -d',' -f2 | tr -d ' ')
+echo "{\"text\": \"${usage}% ${temp}°C\", \"tooltip\": \"GPU: ${usage}%\\nTemp: ${temp}°C\", \"class\": \"\"}"
diff --git a/bazzite/waybar/scripts/mail.py b/bazzite/waybar/scripts/mail.py
new file mode 100644
index 0000000..d249345
--- /dev/null
+++ b/bazzite/waybar/scripts/mail.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python3
+import glob
+import json
+import sqlite3
+import os
+
+profile_dirs = glob.glob(
+ os.path.expanduser("~/.var/app/org.mozilla.Thunderbird/.thunderbird/*.default-esr")
+) or glob.glob(
+ os.path.expanduser("~/.thunderbird/*.default-esr")
+)
+
+if not profile_dirs:
+ print(json.dumps({"text": "", "tooltip": "No Thunderbird profile found"}))
+ exit()
+
+db_path = os.path.join(profile_dirs[0], "global-messages-db.sqlite")
+if not os.path.exists(db_path):
+ print(json.dumps({"text": "", "tooltip": "No message database"}))
+ exit()
+
+try:
+ conn = sqlite3.connect(f"file:{db_path}?mode=ro&nolock=1", uri=True)
+ cursor = conn.cursor()
+ cursor.execute(
+ "SELECT COUNT(*) FROM messages WHERE jsonAttributes LIKE '%\"read\":false%' OR jsonAttributes LIKE '%\"read\": false%'"
+ )
+ count = cursor.fetchone()[0]
+ conn.close()
+except Exception:
+ # fallback: try folderStatus
+ try:
+ conn = sqlite3.connect(f"file:{db_path}?mode=ro&nolock=1", uri=True)
+ cursor = conn.cursor()
+ cursor.execute("SELECT SUM(numNewMessages) FROM folderlocations WHERE numNewMessages > 0")
+ row = cursor.fetchone()
+ count = row[0] if row and row[0] else 0
+ conn.close()
+ except Exception:
+ count = 0
+
+if count > 0:
+ print(json.dumps({"text": f" {count}", "tooltip": f"{count} unread emails", "class": "unread"}))
+else:
+ print(json.dumps({"text": "", "tooltip": "No unread emails"}))
diff --git a/bazzite/waybar/scripts/weather.sh b/bazzite/waybar/scripts/weather.sh
new file mode 100644
index 0000000..e37ecd7
--- /dev/null
+++ b/bazzite/waybar/scripts/weather.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+weather=$(curl -s "wttr.in/?format=%c%t" 2>/dev/null)
+if [ -z "$weather" ] || echo "$weather" | grep -q "Unknown"; then
+ echo '{"text": "N/A", "tooltip": "Weather unavailable"}'
+ exit 0
+fi
+tooltip=$(curl -s "wttr.in/?format=%l:+%C+%t+%w+%h" 2>/dev/null)
+echo "{\"text\": \"${weather}\", \"tooltip\": \"${tooltip}\"}"
diff --git a/bazzite/waybar/style.css b/bazzite/waybar/style.css
index e031037..18ba1a2 100644
--- a/bazzite/waybar/style.css
+++ b/bazzite/waybar/style.css
@@ -1,12 +1,40 @@
+/* Catppuccin Latte */
+@define-color rosewater #dc8a78;
+@define-color flamingo #dd7878;
+@define-color pink #ea76cb;
+@define-color mauve #8839ef;
+@define-color red #d20f39;
+@define-color maroon #e64553;
+@define-color peach #fe640b;
+@define-color yellow #df8e1d;
+@define-color green #40a02b;
+@define-color teal #179299;
+@define-color sky #04a5e5;
+@define-color sapphire #209fb5;
+@define-color blue #1e66f5;
+@define-color lavender #7287fd;
+@define-color text #4c4f69;
+@define-color subtext1 #5c5f77;
+@define-color subtext0 #6c6f85;
+@define-color overlay2 #7c7f93;
+@define-color overlay1 #8c8fa1;
+@define-color overlay0 #9ca0b0;
+@define-color surface2 #acb0be;
+@define-color surface1 #bcc0cc;
+@define-color surface0 #ccd0da;
+@define-color base #eff1f5;
+@define-color mantle #e6e9ef;
+@define-color crust #dce0e8;
+
* {
- font-family: 'Noto Sans Mono', 'Font Awesome 6 Free', 'Font Awesome 6 Brands', monospace;
- font-size: 13px;
+ font-family: 'JetBrainsMono Nerd Font', 'Noto Sans Mono', monospace;
+ font-size: 15px;
+ font-weight: bold;
}
window#waybar {
- background-color: rgba(43, 48, 59, 0.5);
- border-bottom: 3px solid rgba(100, 114, 125, 0.5);
- color: #ffffff;
+ background-color: #1e1e2e;
+ color: @text;
transition-property: background-color;
transition-duration: .5s;
}
@@ -15,86 +43,56 @@ window#waybar.hidden {
opacity: 0.2;
}
-/*
-window#waybar.empty {
- background-color: transparent;
-}
-window#waybar.solo {
- background-color: #FFFFFF;
-}
-*/
-
-window#waybar.termite {
- background-color: #3F3F3F;
-}
-
-window#waybar.chromium {
- background-color: #000000;
- border: none;
-}
-
button {
- /* Use box-shadow instead of border so the text isn't offset */
box-shadow: inset 0 -3px transparent;
- /* Avoid rounded borders under each button name */
border: none;
border-radius: 0;
}
-/* https://github.com/Alexays/Waybar/wiki/FAQ#the-workspace-buttons-have-a-strange-hover-effect */
button:hover {
background: inherit;
- box-shadow: inset 0 -3px #ffffff;
-}
-
-/* you can set a style on hover for any module like this */
-#pulseaudio:hover {
- background-color: #a37800;
+ box-shadow: inset 0 -2px @blue;
}
+/* Workspaces */
#workspaces button {
- padding: 0 5px;
+ padding: 0 6px;
background-color: transparent;
- color: #ffffff;
+ color: #a6adc8;
}
#workspaces button:hover {
- background: rgba(0, 0, 0, 0.2);
+ background: alpha(@surface0, 0.5);
}
-#workspaces button.focused {
- background-color: #64727D;
- box-shadow: inset 0 -3px #ffffff;
+#workspaces button.active {
+ color: #cdd6f4;
+ box-shadow: inset 0 -2px @blue;
}
#workspaces button.urgent {
- background-color: #eb4d4b;
-}
-
-#mode {
- background-color: #64727D;
- box-shadow: inset 0 -3px #ffffff;
+ background-color: alpha(@red, 0.2);
+ color: @red;
}
+/* Common module styling */
#clock,
-#battery,
#cpu,
#memory,
#disk,
#temperature,
-#backlight,
#network,
#pulseaudio,
#wireplumber,
-#custom-media,
#tray,
-#mode,
#idle_inhibitor,
-#scratchpad,
#power-profiles-daemon,
-#mpd {
+#language,
+#custom-gpu,
+#custom-weather,
+#privacy {
padding: 0 10px;
- color: #ffffff;
+ color: @text;
}
#window,
@@ -102,139 +100,135 @@ button:hover {
margin: 0 4px;
}
-/* If workspaces is the leftmost module, omit left margin */
-.modules-left > widget:first-child > #workspaces {
- margin-left: 0;
-}
-
-/* If workspaces is the rightmost module, omit right margin */
-.modules-right > widget:last-child > #workspaces {
- margin-right: 0;
+#window {
+ color: #cdd6f4;
}
+/* Clock */
#clock {
- background-color: #64727D;
-}
-
-#battery {
- background-color: #ffffff;
- color: #000000;
-}
-
-#battery.charging, #battery.plugged {
- color: #ffffff;
- background-color: #26A65B;
-}
-
-@keyframes blink {
- to {
- background-color: #ffffff;
- color: #000000;
- }
-}
-
-/* Using steps() instead of linear as a timing function to limit cpu usage */
-#battery.critical:not(.charging) {
- background-color: #f53c3c;
- color: #ffffff;
- animation-name: blink;
- animation-duration: 0.5s;
- animation-timing-function: steps(12);
- animation-iteration-count: infinite;
- animation-direction: alternate;
-}
-
-#power-profiles-daemon {
- padding-right: 15px;
-}
-
-#power-profiles-daemon.performance {
- background-color: #f53c3c;
- color: #ffffff;
-}
-
-#power-profiles-daemon.balanced {
- background-color: #2980b9;
- color: #ffffff;
-}
-
-#power-profiles-daemon.power-saver {
- background-color: #2ecc71;
- color: #000000;
-}
-
-label:focus {
- background-color: #000000;
+ color: @blue;
+ font-weight: bold;
}
+/* CPU */
#cpu {
- background-color: #2ecc71;
- color: #000000;
+ color: @green;
}
+/* Memory */
#memory {
- background-color: #9b59b6;
-}
-
-#disk {
- background-color: #964B00;
-}
-
-#backlight {
- background-color: #90b1b1;
-}
-
-#network {
- background-color: #2980b9;
-}
-
-#network.disconnected {
- background-color: #f53c3c;
-}
-
-#pulseaudio {
- background-color: #f1c40f;
- color: #000000;
-}
-
-#pulseaudio.muted {
- background-color: #90b1b1;
- color: #2a5c45;
-}
-
-#wireplumber {
- background-color: #fff0f5;
- color: #000000;
-}
-
-#wireplumber.muted {
- background-color: #f53c3c;
-}
-
-#custom-media {
- background-color: #66cc99;
- color: #2a5c45;
- min-width: 100px;
-}
-
-#custom-media.custom-spotify {
- background-color: #66cc99;
-}
-
-#custom-media.custom-vlc {
- background-color: #ffa000;
+ color: @mauve;
}
+/* Temperature */
#temperature {
- background-color: #f0932b;
+ color: @peach;
}
#temperature.critical {
- background-color: #eb4d4b;
+ color: @red;
}
+/* Network */
+#network {
+ color: @sapphire;
+ font-size: 20px;
+}
+
+#network.disconnected {
+ color: @red;
+}
+
+/* Pulseaudio */
+#pulseaudio {
+ color: @yellow;
+}
+
+#pulseaudio.muted {
+ color: @overlay1;
+}
+
+/* Language */
+#language {
+ color: @teal;
+ font-weight: bold;
+}
+
+/* Idle inhibitor */
+#idle_inhibitor {
+ color: @overlay1;
+}
+
+#idle_inhibitor.activated {
+ color: @peach;
+}
+
+/* Power profiles */
+#power-profiles-daemon {
+ color: @subtext0;
+}
+
+#power-profiles-daemon.performance {
+ color: @red;
+}
+
+#power-profiles-daemon.balanced {
+ color: @blue;
+}
+
+#power-profiles-daemon.power-saver {
+ color: @green;
+}
+
+/* Mail */
+#custom-mail {
+ color: @lavender;
+}
+
+#custom-mail.unread {
+ color: @red;
+}
+
+/* Disk */
+#disk {
+ color: @flamingo;
+}
+
+/* GPU */
+#custom-gpu {
+ color: @green;
+}
+
+/* Weather */
+#custom-weather {
+ color: @sky;
+}
+
+/* Privacy */
+#privacy {
+ padding: 0;
+}
+
+#privacy-item {
+ padding: 0 5px;
+ color: @base;
+}
+
+#privacy-item.screenshare {
+ background-color: @peach;
+}
+
+#privacy-item.audio-in {
+ background-color: @red;
+}
+
+#privacy-item.audio-out {
+ background-color: @blue;
+}
+
+/* Tray */
#tray {
- background-color: #2980b9;
+ color: @text;
}
#tray > .passive {
@@ -243,84 +237,5 @@ label:focus {
#tray > .needs-attention {
-gtk-icon-effect: highlight;
- background-color: #eb4d4b;
-}
-
-#idle_inhibitor {
- background-color: #2d3436;
-}
-
-#idle_inhibitor.activated {
- background-color: #ecf0f1;
- color: #2d3436;
-}
-
-#mpd {
- background-color: #66cc99;
- color: #2a5c45;
-}
-
-#mpd.disconnected {
- background-color: #f53c3c;
-}
-
-#mpd.stopped {
- background-color: #90b1b1;
-}
-
-#mpd.paused {
- background-color: #51a37a;
-}
-
-#language {
- background: #00b093;
- color: #740864;
- padding: 0 5px;
- margin: 0 5px;
- min-width: 16px;
-}
-
-#keyboard-state {
- background: #97e1ad;
- color: #000000;
- padding: 0 0px;
- margin: 0 5px;
- min-width: 16px;
-}
-
-#keyboard-state > label {
- padding: 0 5px;
-}
-
-#keyboard-state > label.locked {
- background: rgba(0, 0, 0, 0.2);
-}
-
-#scratchpad {
- background: rgba(0, 0, 0, 0.2);
-}
-
-#scratchpad.empty {
- background-color: transparent;
-}
-
-#privacy {
- padding: 0;
-}
-
-#privacy-item {
- padding: 0 5px;
- color: white;
-}
-
-#privacy-item.screenshare {
- background-color: #cf5700;
-}
-
-#privacy-item.audio-in {
- background-color: #1ca000;
-}
-
-#privacy-item.audio-out {
- background-color: #0069d4;
+ color: @red;
}