Compare commits

7 Commits

Author SHA1 Message Date
nvrl 9365615f06 updated waybar config 2026-04-04 05:10:21 +02:00
nvrl f910af8dce removed splash and increased refresh intervals 2026-04-02 18:47:11 +02:00
nvrl 74945d45e9 updated hyprlock 2026-04-02 13:46:16 +02:00
nvrl eadaaa5d52 updated themes, waybar 2026-04-02 13:10:37 +02:00
nvrl 70842dc108 changen clock color 2026-04-01 17:44:08 +02:00
nvrl 1e811035a5 updated waybar + hypr rules 2026-03-31 10:20:16 +02:00
nvrl 9dda38ceee fire/ice theme 2026-03-24 23:47:28 +01:00
29 changed files with 450 additions and 1146 deletions
+5
View File
@@ -104,3 +104,8 @@ ipc_socket = true
## Import additional configuration files. ## Import additional configuration files.
import = ["~/.config/alacritty/colors.toml", "~/.config/alacritty/fonts.toml"] import = ["~/.config/alacritty/colors.toml", "~/.config/alacritty/fonts.toml"]
[[keyboard.bindings]]
key = "Return"
mods = "Shift"
chars = "\u001B\r"
+2 -2
View File
@@ -1,10 +1,10 @@
[global] [global]
corner_radius = 4 corner_radius = 4
transparency = 90 transparency = 90
frame_color = "#94e2d5" frame_color = "#f38ba8"
frame_width = 1 frame_width = 1
separator_color= frame separator_color= frame
highlight = "#89b4fa" highlight = "#89dceb"
[urgency_low] [urgency_low]
background = "#1e1e2e" background = "#1e1e2e"
+20 -5
View File
@@ -1,13 +1,28 @@
include=~/.config/fuzzel/catppuccin-fuzzel/themes/catppuccin-mocha/mauve.ini include=~/.config/fuzzel/catppuccin-fuzzel/themes/catppuccin-mocha/red.ini
include=~/.config/fuzzel/catppuccin-fuzzel/themes/catppuccin-mocha/red.ini
[main] [main]
font=FiraCode Nerd Font:size=14 font=FiraCode Nerd Font:size=14
terminal=alacritty terminal=alacritty
dpi-aware=no dpi-aware=no
prompt="> "
icon-theme=Papirus-Dark width=45
show-actions=yes lines=8
horizontal-pad=20
vertical-pad=20
inner-pad=10
prompt=" "
show-actions=no
layer=overlay
[border] [border]
radius=4 radius=12
width=2 width=2
[colors]
background=1e1e2e80
# Matches the background so the counter becomes invisible for a cleaner look
counter=1e1e2eff
border=f38ba8ff
+103 -48
View File
@@ -7,38 +7,35 @@ $font = JetBrainsMono Nerd Font
# GENERAL # GENERAL
general { general {
hide_cursor = true hide_cursor = true
no_fade_in = false
grace = 0
disable_loading_bar = true
} }
# BACKGROUND # BACKGROUND
background { background {
monitor = monitor =
path = $HOME/Pictures/mandelbrot.png path = $HOME/Pictures/reze/reze.png
blur_passes = 0 blur_passes = 3
blur_size = 7
noise = 0.0117
contrast = 0.8916
brightness = 0.8172
vibrancy = 0.1696
vibrancy_darkness = 0.0
color = $base color = $base
} }
# LAYOUT
label {
monitor =
text = Layout: $LAYOUT
color = $text
font_size = 25
font_family = $font
position = 30, -30
halign = left
valign = top
}
# TIME # TIME
label { label {
monitor = monitor =
text = $TIME text = $TIME
color = $text color = $text
font_size = 90 font_size = 120
font_family = $font font_family = $font
position = -30, 0 position = 0, 300
halign = right halign = center
valign = top valign = center
} }
# DATE # DATE
@@ -46,46 +43,34 @@ label {
monitor = monitor =
text = cmd[update:43200000] date +"%A, %d %B %Y" text = cmd[update:43200000] date +"%A, %d %B %Y"
color = $text color = $text
font_size = 25 font_size = 30
font_family = $font font_family = $font
position = -30, -150 position = 0, 200
halign = right
valign = top
}
# FINGERPRINT
{
monitor = "";
text = "$FPRINTPROMPT";
color = "$text";
font_size = 14;
font_family = $font;
position = "0, -107";
halign = "center";
valign = "center";
}
# USER AVATAR
image {
monitor =
path = $HOME/.face
size = 100
border_color = $accent
position = 0, 75
halign = center halign = center
valign = center valign = center
} }
# INPUT FIELD # USER AVATAR (Center)
image {
monitor =
path = $HOME/.face
size = 120
border_color = rgba(255, 255, 255, 0.1)
position = 0, 50
halign = center
valign = center
}
# INPUT FIELD (Center)
input-field { input-field {
monitor = monitor =
size = 300, 60 size = 300, 60
outline_thickness = 4 outline_thickness = 2
dots_size = 0.2 dots_size = 0.2
dots_spacing = 0.2 dots_spacing = 0.2
dots_center = true dots_center = true
outer_color = $accent outer_color = rgba(255, 255, 255, 0.1)
inner_color = $surface0 inner_color = rgba(0, 0, 0, 0.2)
font_color = $text font_color = $text
fade_on_empty = false fade_on_empty = false
placeholder_text = <span foreground="##$textAlpha"><i>󰌾 Logged in as </i><span foreground="##$accentAlpha">$USER</span></span> placeholder_text = <span foreground="##$textAlpha"><i>󰌾 Logged in as </i><span foreground="##$accentAlpha">$USER</span></span>
@@ -94,7 +79,77 @@ input-field {
fail_color = $red fail_color = $red
fail_text = <i>$FAIL <b>($ATTEMPTS)</b></i> fail_text = <i>$FAIL <b>($ATTEMPTS)</b></i>
capslock_color = $yellow capslock_color = $yellow
position = 0, -47 position = 0, -60
halign = center halign = center
valign = center valign = center
} }
# --- MUSIC DASHBOARD (TOP RIGHT) ---
# ALBUM ART (At the very top right, 80px high, adjusted -3px for perfect alignment)
image {
monitor =
path = /tmp/hyprlock_art.png
size = 80
rounding = 15
border_color = rgba(255, 255, 255, 0.1)
reload_time = 2
reload_cmd = ~/.config/hypr/scripts/album_art.sh
position = -20, -17
halign = right
valign = top
}
# MUSIC TEXT BOX (To the left of the image, same height)
shape {
monitor =
size = 300, 80
color = rgba(0, 0, 0, 0.3)
rounding = 15
border_size = 1
border_color = rgba(255, 255, 255, 0.1)
position = -110, -20
halign = right
valign = top
}
# MUSIC TEXT (Right aligned and vertically centered inside the 80px box)
label {
monitor =
text = cmd[update:1000] ~/.config/hypr/scripts/songdetail.sh
color = $text
font_size = 14
font_family = $font
position = -125, -37
halign = right
valign = top
text_align = right
}
# --- STATUS DASHBOARD (BOTTOM RIGHT) ---
# SYSTEM INFO BOX (Vertical stack container)
shape {
monitor =
size = 300, 100
color = rgba(0, 0, 0, 0.3)
rounding = 15
border_size = 1
border_color = rgba(255, 255, 255, 0.1)
position = -20, 20
halign = right
valign = bottom
}
# SYSTEM INFO TEXT (3 lines, top of each other, right aligned)
label {
monitor =
text = cmd[update:5000] ~/.config/hypr/scripts/status_info.sh
color = $text
font_size = 14
font_family = $font
position = -35, 35
halign = right
valign = bottom
text_align = right
}
+4 -2
View File
@@ -1,5 +1,7 @@
wallpaper { wallpaper {
monitor = monitor =
path = ~/Pictures/mandelbrot.png path = ~/Pictures/reze/reze.png
fit_mode = fill fit_mode = cover
} }
splash = false
+4 -4
View File
@@ -77,10 +77,10 @@ bindm = $mainMod, mouse:272, movewindow
bindm = $mainMod, mouse:273, resizewindow bindm = $mainMod, mouse:273, resizewindow
# Laptop multimedia keys for volume and LCD brightness # Laptop multimedia keys for volume and LCD brightness
bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume -l 1.0 @DEFAULT_AUDIO_SINK@ 5%+ bindel = ,XF86AudioRaiseVolume, exec, fluxo-rs vol up 5
bindel = ,XF86AudioLowerVolume, exec, wpctl set-volume -l 1.0 @DEFAULT_AUDIO_SINK@ 5%- bindel = ,XF86AudioLowerVolume, exec, fluxo-rs vol down 5
bindel = ,XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle bindel = ,XF86AudioMute, exec, fluxo-rs vol mute
bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle bindel = ,XF86AudioMicMute, exec, fluxo-rs mic mute
bindel = ,XF86MonBrightnessUp, exec, brightnessctl set 5%+ bindel = ,XF86MonBrightnessUp, exec, brightnessctl set 5%+
bindel = ,XF86MonBrightnessDown, exec, brightnessctl set 5%- bindel = ,XF86MonBrightnessDown, exec, brightnessctl set 5%-
+34 -13
View File
@@ -12,8 +12,7 @@ general {
border_size = 3 border_size = 3
# https://wiki.hyprland.org/Configuring/Variables/#variable-types for info about colors # https://wiki.hyprland.org/Configuring/Variables/#variable-types for info about colors
# col.active_border = rgba(cba6f7ee) rgba(f38ba8ee) 45deg col.active_border = $mauve $lavender 45deg
col.active_border = rgb($mauveAlpha) rgb($blueAlpha) 30deg
col.inactive_border = rgb($surface2Alpha) col.inactive_border = rgb($surface2Alpha)
# Set to true enable resizing windows by clicking and dragging on borders and gaps # Set to true enable resizing windows by clicking and dragging on borders and gaps
@@ -27,8 +26,8 @@ general {
# https://wiki.hyprland.org/Configuring/Variables/#decoration # https://wiki.hyprland.org/Configuring/Variables/#decoration
decoration { decoration {
rounding = 4 rounding = 12
rounding_power = 1 rounding_power = 3
# Change transparency of focused and unfocused windows # Change transparency of focused and unfocused windows
active_opacity = 1.0 active_opacity = 1.0
@@ -101,13 +100,35 @@ misc {
} }
group { group {
groupbar { # The border around the grouped windows
font_size = 14 col.border_active = $mauve $lavender 45deg
text_color = $text col.border_inactive = $surface1
text_color_inactive = $text
col.active = $maroon groupbar {
col.inactive = $surface2 font_family = JetBrainsMono Nerd Font
} font_size = 11
col.border_active = $maroon $teal 30deg
col.border_inactive = $surface2 # Increase the height so the text has room to breathe
height = 24
# Disable the default 3D gradient for a modern flat look
gradients = false
# --- Active Tab ---
# Bright background with very dark text for perfect readability
col.active = $mauve
text_color = $crust
# --- Inactive Tab ---
# Dark surface background with dimmed, soft text
col.inactive = $surface0
text_color_inactive = $subtext0
height = 1
font_size = 11
# about half the indicator height
text_offset = -7
# Make the indicator tall enough to render text inside
indicator_height = 15
}
} }
+12
View File
@@ -75,3 +75,15 @@ windowrule = no_blur 1, match:class $steam, match:title negative:^(Steam)$
# Allow tearing for games started with Gamescope # Allow tearing for games started with Gamescope
windowrule = immediate 1, match:class $gamescope windowrule = immediate 1, match:class $gamescope
# Layer rules
# waybar blur
layerrule = blur on, match:namespace bottom
layerrule = blur on, match:namespace top
layerrule = ignore_alpha 0.5, match:namespace bottom
layerrule = ignore_alpha 0.5, match:namespace top
# launcher blur
layerrule = blur on, match:namespace launcher
layerrule = ignore_alpha 0.5, match:namespace launcher
+11
View File
@@ -0,0 +1,11 @@
#!/bin/bash
url=$(playerctl metadata mpris:artUrl 2>/dev/null)
if [[ "$url" == file://* ]]; then
cp "${url#file://}" /tmp/hyprlock_art.png
echo "/tmp/hyprlock_art.png"
elif [[ "$url" == http* ]]; then
curl -s "$url" -o /tmp/hyprlock_art.png
echo "/tmp/hyprlock_art.png"
else
echo "$HOME/.config/hypr/catppuccin-hyprland/assets/mocha.webp"
fi
+13
View File
@@ -0,0 +1,13 @@
#!/bin/bash
status=$(playerctl status 2>/dev/null)
if [ "$status" = "Playing" ] || [ "$status" = "Paused" ]; then
title=$(playerctl metadata title | sed 's/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g')
artist=$(playerctl metadata artist | sed 's/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g')
if [ ${#title} -gt 25 ]; then title="${title:0:22}..."; fi
if [ ${#artist} -gt 25 ]; then artist="${artist:0:22}..."; fi
echo "<span weight='bold' foreground='#cba6f7'>$title</span>"
echo "<span foreground='#bac2de' size='small'>$artist</span>"
else
echo "<span weight='bold' foreground='#cdd6f4'>No Media</span>"
echo "<span size='small' foreground='#a6adc8'>Idling</span>"
fi
+14
View File
@@ -0,0 +1,14 @@
#!/bin/bash
# 1. Network
net=$(nmcli -t -f active,ssid dev wifi | grep '^yes' | cut -d: -f2 || echo 'Offline')
if [ ${#net} -gt 15 ]; then net="${net:0:12}..."; fi
# 2. Battery
bat_cap=$(cat /sys/class/power_supply/BAT0/capacity)
bat_stat=$(cat /sys/class/power_supply/BAT0/status)
if [ "$bat_stat" = "Charging" ]; then icon="󰂄"; else icon="󰁹"; fi
# 3. Load
cpu=$(top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1}' | cut -d. -f1)
# Output 3 lines for the vertical stack
echo "󰖩 $net"
echo "$icon $bat_cap% ($bat_stat)"
echo "󰍛 Load: $cpu%"
+1
View File
@@ -17,6 +17,7 @@ x-scheme-handler/unknown=google-chrome.desktop
application/vnd.openxmlformats-officedocument.wordprocessingml.document=libreoffice-writer.desktop application/vnd.openxmlformats-officedocument.wordprocessingml.document=libreoffice-writer.desktop
x-scheme-handler/ror2mm=r2modman.desktop x-scheme-handler/ror2mm=r2modman.desktop
image/webp=feh.desktop image/webp=feh.desktop
x-scheme-handler/claude-cli=claude-code-url-handler.desktop
[Added Associations] [Added Associations]
application/pdf=org.pwmt.zathura-pdf-poppler.desktop; application/pdf=org.pwmt.zathura-pdf-poppler.desktop;
+84 -73
View File
@@ -4,7 +4,7 @@
"name": "top", "name": "top",
"layer": "top", "layer": "top",
"position": "top", "position": "top",
"height": 34, "height": 39,
"spacing": 4, "spacing": 4,
"margin-top": 6, "margin-top": 6,
"margin-left": 10, "margin-left": 10,
@@ -15,7 +15,7 @@
"hyprland/window" "hyprland/window"
], ],
"modules-center": [ "modules-center": [
"clock" "group/center"
], ],
"modules-right": [ "modules-right": [
"tray", "tray",
@@ -34,28 +34,44 @@
}, },
"clock": { "clock": {
"format": "{:%a %d %b %H:%M}", "format": "{:%a %d %b %H:%M}",
"on-click-right": "xdg-open https://calendar.proton.me/u/0/month &> /dev/null & disown",
"tooltip": false "tooltip": false
}, },
"custom/mpris": {
"format": "{}",
"return-type": "json",
"exec": "fluxo-rs mpris",
"on-click": "playerctl play-pause",
"signal": 11,
"interval": 0
},
"tray": { "tray": {
"icon-size": 18, "icon-size": 18,
"spacing": 10 "spacing": 10
}, },
"group/center": {
"orientation": "horizontal",
"modules": [
"custom/mpris",
"clock"
// "custom/dnd"
]
},
"custom/gamemode": { "custom/gamemode": {
"format": "{}", "format": "{}",
"return-type": "json", "return-type": "json",
"exec": "~/.config/waybar/fluxo-rs/target/release/fluxo-rs game", "exec": "fluxo-rs game",
"on-click": "~/.config/hypr/scripts/gamemode.sh & disown", "on-click": "~/.config/hypr/scripts/gamemode.sh",
"interval": 1 "signal": 7,
"interval": 5
}, },
// --- Fluxo-rs Power ---
"custom/power_status": { "custom/power_status": {
"format": "{} ", "format": "{} ",
"return-type": "json", "return-type": "json",
"exec": "~/.config/waybar/fluxo-rs/target/release/fluxo-rs power", "exec": "fluxo-rs power",
"on-click": "~/.config/hypr/scripts/powermenu.sh & disown", "on-click": "~/.config/hypr/scripts/powermenu.sh & disown",
"signal": 10,
"interval": 5 "interval": 5
} }
}, },
@@ -63,19 +79,25 @@
"name": "bottom", "name": "bottom",
"layer": "top", "layer": "top",
"position": "bottom", "position": "bottom",
"height": 34, "height": 35,
"spacing": 4, "spacing": 4,
"margin-bottom": 6, "margin-bottom": 6,
"margin-left": 10, "margin-left": 10,
"margin-right": 10, "margin-right": 10,
"modules-left": [ "modules-left": [
"custom/sys", "group/hardware"
"custom/cpu",
"custom/mem",
"custom/network",
"custom/disk-root"
], ],
"group/hardware": {
"orientation": "horizontal",
"modules": [
"custom/sys",
"custom/cpu",
"custom/mem",
"custom/disk-root",
"custom/network"
]
},
"modules-center": [ "modules-center": [
], ],
"modules-right": [ "modules-right": [
@@ -88,101 +110,90 @@
"custom/sys": { "custom/sys": {
"format": "{}", "format": "{}",
"return-type": "json", "return-type": "json",
"exec": "~/.config/waybar/fluxo-rs/target/release/fluxo-rs sys", "exec": "fluxo-rs sys",
"interval": 5 "signal": 5,
"interval": 1
}, },
"custom/cpu": { "custom/cpu": {
"format": "{}", "format": "{}",
"return-type": "json", "return-type": "json",
"exec": "~/.config/waybar/fluxo-rs/target/release/fluxo-rs cpu", "exec": "fluxo-rs cpu",
"on-click": "zenmonitor & disown", "on-click": "zenmonitor & disown",
"interval": 3 "signal": 2,
"interval": 1
}, },
"custom/mem": { "custom/mem": {
"format": "{}", "format": "{}",
"return-type": "json", "return-type": "json",
"exec": "~/.config/waybar/fluxo-rs/target/release/fluxo-rs mem", "exec": "fluxo-rs mem",
"interval": 3 "signal": 3,
"interval": 1
},
"custom/gpu": {
"format": "{}",
"return-type": "json",
"exec": "fluxo-rs gpu",
"signal": 4,
"interval": 1
}, },
"custom/network": { "custom/network": {
"format": "{}", "format": "{}",
"return-type": "json", "return-type": "json",
"exec": "~/.config/waybar/fluxo-rs/target/release/fluxo-rs net", "exec": "fluxo-rs net",
"interval": 2 "signal": 1,
"interval": 1
}, },
// --- Fluxo-rs Utilities ---
"custom/disk-root": { "custom/disk-root": {
"format": "{}", "format": "{}",
"return-type": "json", "return-type": "json",
"exec": "~/.config/waybar/fluxo-rs/target/release/fluxo-rs disk /", "exec": "fluxo-rs disk /",
"interval": 30 "signal": 6,
"interval": 1
}, },
// --- Fluxo-rs Audio & BT --- // --- Fluxo-rs Audio & BT ---
"custom/volume": { "custom/volume": {
"format": "{}", "format": "{}",
"return-type": "json", "return-type": "json",
"exec": "~/.config/waybar/fluxo-rs/target/release/fluxo-rs vol", "exec": "fluxo-rs vol",
"on-click": "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle", "on-click": "fluxo-rs vol mute",
"on-scroll-up": "wpctl set-volume -l 1.0 @DEFAULT_AUDIO_SINK@ 5%+", "on-scroll-up": "fluxo-rs vol up 5",
"on-scroll-down": "wpctl set-volume -l 1.0 @DEFAULT_AUDIO_SINK@ 5%-", "on-scroll-down": "fluxo-rs vol down 5",
"on-click-right": "~/.config/waybar/fluxo-rs/target/release/fluxo-rs vol --cycle", "on-click-right": "fluxo-rs vol cycle",
"on-click-middle": "pavucontrol", "on-click-middle": "pavucontrol",
"signal": 8,
"interval": 1 "interval": 1
}, },
"custom/mic": { "custom/mic": {
"format": "{}", "format": "{}",
"return-type": "json", "return-type": "json",
"exec": "~/.config/waybar/fluxo-rs/target/release/fluxo-rs mic", "exec": "fluxo-rs mic",
"on-click": "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle", "on-click": "fluxo-rs mic mute",
"on-scroll-up": "wpctl set-volume @DEFAULT_AUDIO_SOURCE@ 5%+", "on-scroll-up": "fluxo-rs mic up 5",
"on-scroll-down": "wpctl set-volume @DEFAULT_AUDIO_SOURCE@ 5%-", "on-scroll-down": "fluxo-rs mic down 5",
"on-click-right": "~/.config/waybar/fluxo-rs/target/release/fluxo-rs mic --cycle", "on-click-right": "fluxo-rs mic cycle",
"on-click-middle": "pavucontrol", "on-click-middle": "pavucontrol",
"signal": 8,
"interval": 1 "interval": 1
}, },
"custom/bluetooth-audio": { "custom/bluetooth-audio": {
"format": "{}", "format": "{}",
"return-type": "json", "return-type": "json",
"exec": "~/.config/waybar/fluxo-rs/target/release/fluxo-rs bt", "exec": "fluxo-rs bt",
"on-click": "~/.config/waybar/fluxo-rs/target/release/fluxo-rs bt menu", "on-click": "fluxo-rs bt menu",
"on-click-right": "~/.config/waybar/fluxo-rs/target/release/fluxo-rs bt disconnect", "on-click-right": "fluxo-rs bt cycle_mode",
"interval": 3 "signal": 9,
"interval": 1,
"tooltip": true
},
"custom/dnd": {
"format": "{}",
"return-type": "json",
"exec": "fluxo-rs dnd",
"on-click": "fluxo-rs dnd toggle",
"signal": 14,
"interval": 0
} }
// --- Commented Out Modules ---
/*
"custom/gpu": {
"format": "{}",
"return-type": "json",
"exec": "~/.config/waybar/fluxo-rs/target/release/fluxo-rs gpu",
"on-click": "lact gui & disown",
"interval": 3
},
"custom/btrfs": {
"format": "{}",
"return-type": "json",
"exec": "~/.config/waybar/fluxo-rs/target/release/fluxo-rs pool",
"interval": 30
},
"custom/pixelbuds_pro": {
"format": "{}",
"return-type": "json",
"exec": "~/.config/waybar/fluxo-rs/target/release/fluxo-rs buds",
"on-click": "~/.config/waybar/fluxo-rs/target/release/fluxo-rs buds connect & disown",
"on-click-right": "~/.config/waybar/fluxo-rs/target/release/fluxo-rs buds cycle_anc & disown",
"interval": 5
},
"custom/gpu-screen-recorder": {
"format": "{}",
"return-type": "json",
"exec": "~/.config/waybar/scripts/gpu-screen-recorder-status.sh",
"on-click-right": "~/.config/hypr/scripts/replay-ctrl.sh save & disown",
"on-click-middle": "nautilus ~/Videos/replay & disown",
"on-click": "~/.config/waybar/scripts/toggle-replay.sh & disown",
"interval": 1
}
*/
} }
] ]
-202
View File
@@ -1,202 +0,0 @@
// ~/.config/waybar/config.jsonc
{
"layer": "top",
"position": "top",
"height": 36,
"modules-left": [
"hyprland/workspaces"
],
"modules-center": [
],
"modules-right": [
// "custom/bluetooth-audio",
// "custom/pixelbuds_pro",
"custom/mem",
"custom/cpu",
"custom/gpu",
"custom/disk-root",
"custom/disk-gdrive",
"custom/disk-data",
"custom/disk-games",
// "network",
"custom/audio-output",
"wireplumber",
"tray",
"custom/gpu-screen-recorder",
"custom/gamemode",
"clock"
],
"hyprland/workspaces": {
"format": "{icon}",
"on-click": "activate"
},
"hyprland/window": {
"format": "{}",
"max-length": 35
},
"clock": {
"format": "{:%a %d %b %H:%M}",
"format-alt": false,
"on-click-right": "xdg-open https://calendar.proton.me/u/0/month &> /dev/null & disown",
"tooltip": false,
},
"cpu": {
"format": "CPU: {usage}%",
"tooltip": true,
"interval": 1
},
"memory": {
"format": "MEM: {used}/{total}GB",
"interval": 3
},
"network": {
"format-wifi": "{essid} ({signalStrength}%): {ipaddr}",
"format-ethernet": "{ifname}: {ipaddr}",
"format-disconnected": "Disconnected",
"tooltip-format": "{ifname} via {gwaddr}"
},
"wireplumber": {
"format": "{volume}% {icon}",
"format-muted": "--- ",
"format-icons": {
"headphone": "",
"hands-free": "",
"default": ["", "", ""]
},
"on-click": "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle",
"on-click-right": "~/.config/waybar/scripts/audio.sh cycle",
"on-click-middle": "pavucontrol",
"scroll-step": 1
},
"custom/bluetooth-audio": {
"format": "{}",
"return-type": "json",
"exec": "~/.config/waybar/scripts/bluetooth_audio.sh",
"interval": 3,
"on-click": "~/.config/waybar/scripts/bluetooth_audio.sh disconnect & disown"
},
"pulseaudio": {
"format": "{icon} {volume}%",
"format-muted": " Muted",
"format-icons": {
"headphone": "",
"hands-free": "",
"headset": "",
"phone": "",
"portable": "",
"car": "",
"default": ["", ""]
},
"on-click": "pavucontrol & disown"
},
"tray": {
"icon-size": 18,
"spacing": 10
},
"custom/power": {
"format": "",
"tooltip": false,
"on-click": "~/.config/hypr/scripts/powermenu.sh & disown"
},
"custom/tlp": {
"format": "{}",
"exec": "~/.config/waybar/scripts/tlp-profile.sh",
"return-type": "json",
"interval": 5
},
"battery": {
"states": {
"warning": 30,
"critical": 15
},
"format": "{capacity}%",
"format-charging": "{capacity}%",
"format-plugged": "{capacity}%",
"format-alt": "{time} {icon}",
"format-full": "{capacity}%",
"format-icons": ["", "", "", "", ""]
},
"custom/pixelbuds_pro": {
"format": "{}",
"return-type": "json",
"exec": "~/.config/waybar/scripts/pixelbuds_pro_control.sh",
"interval": 5,
"on-click": "~/.config/waybar/scripts/pixelbuds_pro_control.sh connect & disown",
"on-click-right": "~/.config/waybar/scripts/pixelbuds_pro_control.sh cycle_anc & disown"
},
"custom/audio-output": {
"format": "{}",
"return-type": "json",
"exec": "/home/narl/.config/waybar/scripts/audio.sh show",
"on-click": "/home/narl/.config/waybar/scripts/audio.sh cycle & disown",
"interval": 1
},
"custom/gamemode": {
"format": "{}",
"return-type": "json",
"exec": "~/.config/waybar/scripts/gamemode_status.sh",
"on-click": "~/.config/hypr/scripts/gamemode.sh & disown",
"interval": 1
},
"custom/gpu-screen-recorder": {
"format": "{}",
"return-type": "json",
"exec": "~/.config/waybar/scripts/gpu-screen-recorder-status.sh",
"on-click-right": "~/.config/hypr/scripts/replay-ctrl.sh save & disown",
"on-click-middle": "nautilus ~/Videos/replay & disown",
"on-click": "~/.config/waybar/scripts/toggle-replay.sh & disown",
"interval": 1
},
"custom/gpu": {
"format": "{}",
"return-type": "json",
"exec": "~/.config/waybar/scripts/gpu_info.sh",
"on-click": "lact gui & disown",
"interval": 3
},
"custom/cpu": {
"format": "{}",
"return-type": "json",
"exec": "~/.config/waybar/scripts/cpu_info.sh",
"on-click": "zenmonitor & disown",
"interval": 3
},
"custom/mem": {
"format": "{}",
"return-type": "json",
"exec": "~/.config/waybar/scripts/memory.sh",
"interval": 3
},
"custom/btrfs": {
"format": "{}",
"exec": "~/.config/waybar/scripts/btrfs.sh",
"return-type": "json",
"interval": 30
},
"custom/disk-root": {
"format": "{}",
"return-type": "json",
"exec": "~/.config/waybar/scripts/disk_info.sh /",
"interval": 30
},
"custom/disk-gdrive": {
"format": "{}",
"return-type": "json",
"exec": "~/.config/waybar/scripts/disk_info.sh ~/gdrive",
"interval": 30
},
"custom/disk-data": {
"format": "{}",
"return-type": "json",
"exec": "~/.config/waybar/scripts/disk_info.sh ~/data",
"interval": 30
},
"custom/disk-games": {
"format": "{}",
"return-type": "json",
"exec": "~/.config/waybar/scripts/disk_info.sh ~/games",
"interval": 30
}
}
-40
View File
@@ -1,40 +0,0 @@
#!/bin/bash
DEFAULT_SINK=$(pactl info | grep 'Default Sink' | cut -d ' ' -f3)
DESCRIPTION=$(pactl list sinks | grep -A2 "Name: $DEFAULT_SINK" | grep "Description:" | cut -d ' ' -f2-)
case $1 in
cycle)
SINKS=($(pactl list short sinks | awk '{print $2}'))
NUM_SINKS=${#SINKS[@]}
CURRENT_SINK=$(pactl info | grep 'Default Sink' | cut -d ' ' -f3)
for i in "${!SINKS[@]}"; do
if [[ "${SINKS[$i]}" == "$CURRENT_SINK" ]]; then
NEXT_INDEX=$(( (i + 1) % NUM_SINKS ))
pactl set-default-sink "${SINKS[$NEXT_INDEX]}"
exit 0
fi
done
;;
show)
TEXT=$(echo "$DESCRIPTION" | cut -c -20)
if [ -z "$DESCRIPTION" ]; then
DESCRIPTION=$DEFAULT_SINK
fi
CLASS=""
case $(pactl get-sink-mute @DEFAULT_SINK@ | awk '{print $2}') in
yes)
CLASS="muted"
;;
no)
CLASS="unmuted"
;;
esac
printf '{"text": "%s", "tooltip": "%s", "class": "%s"}' "$TEXT" "$DESCRIPTION" "$CLASS"
;;
*)
echo "usage audio.sh {cycle|show}"
;;
esac
-118
View File
@@ -1,118 +0,0 @@
#!/bin/bash
bt-audio-info() {
# Check if a MAC address was provided as the first argument.
if [ -z "$1" ]; then
echo "Usage: $0 <MAC_ADDRESS>"
echo "Example: $0 00:11:22:33:AA:BB"
exit 1
fi
MAC_ADDRESS="$1"
# --- Main Logic ---
# Construct the PipeWire sink name from the MAC address.
# The format is typically: bluez_output.XX_XX_XX_XX_XX_XX.a2dp_sink
# We replace colons with underscores for the format.
SINK_IDENTIFIER="bluez_output.$(echo "$MAC_ADDRESS" | tr ':' '_')"
# Use pactl to get the full details for all sinks, then find the one
# that contains our device's identifier. We use awk to print the
# entire block of text for that specific sink.
# We check for a partial match on the sink identifier because the profile
# (e.g., .a2dp_sink) can change.
sink_info=$(pactl list sinks | awk -v id="$SINK_IDENTIFIER" '/Sink #/ {p=0} $0 ~ "Name: " id {p=1} p')
# If sink_info is empty, the device might not be an audio sink or isn't connected.
if [ -z "$sink_info" ]; then
echo "Error: Could not find an active audio sink for MAC ${MAC_ADDRESS}"
echo "Please ensure the device is connected and is an audio output device."
exit 1
fi
# Get the full block of info for the device from bluetoothctl.
device_info=$(bluetoothctl info "$MAC_ADDRESS")
# --- Parse Information ---
# Parse bluetoothctl output for general device details.
alias=$(echo "$device_info" | rg "Alias:" | cut -d ' ' -f 2-)
trusted=$(echo "$device_info" | rg "Trusted:" | awk '{print $2}')
battery_raw=$(echo "$device_info" | rg "Battery Percentage:" | awk -F'[()]' '{print $2}')
# Parse pactl output for audio-specific details.
volume=$(echo "$sink_info" | rg "Volume:" | head -n1 | awk '{print $5}')
codec=$(echo "$sink_info" | rg -e 'bluetooth.codec|api.bluez5.codec' | awk -F'"' '{print $2}')
# --- Build and Display Compact Output ---
# Build the output string with all the information.
output_string="${alias} | MAC: ${MAC_ADDRESS}\n"
output_string+="Trusted: ${trusted}"
# Append battery info if available, otherwise show N/A.
if [ -n "$battery_raw" ]; then
output_string+=" | Bat: ${battery_raw}%"
else
output_string+=" | Bat: N/A"
fi
output_string+=" | Vol: ${volume} | Codec: ${codec:-N/A}"
# Print the final, single-line string.
echo "$output_string"
}
# Find the MAC address of the first connected device that is an audio sink
find_audio_device() {
default_sink_name=$(pactl get-default-sink)
# Check if the default sink is a Bluetooth device. Their names typically
# start with "bluez_output.". If not, print a message and exit.
if [[ "$default_sink_name" == bluez_output* ]]; then
# Extract the MAC address from the sink name.
# The format is bluez_output.XX_XX_XX_XX_XX_XX.profile
# We extract the middle part and replace underscores with colons.
mac_with_underscores=$(echo "$default_sink_name" | cut -d '.' -f 2)
mac=$(echo "$mac_with_underscores" | tr '_' ':')
echo "$mac"
return
fi
# else look for the first bluetooth device that provides a sink
bluetoothctl devices Connected | rg '^Device ' | awk '{print $2}' | while read -r mac;
do
# Check if the device provides the "Audio Sink" service
if bluetoothctl info "$mac" | rg -q "0000110b-0000-1000-8000-00805f9b34fb"; then
echo "$mac"
# If you only want the first audio device found, you can 'break' or 'exit' here.
break
fi
done
}
# If the script is called with "disconnect"
if [ "$1" == "disconnect" ]; then
device_mac=$(find_audio_device)
if [ -n "$device_mac" ]; then
bluetoothctl disconnect "$device_mac"
fi
echo "{}"
exit 0
fi
# Main logic to display the device name
device_mac=$(find_audio_device)
if [ -n "$device_mac" ]; then
# Get the device alias (name)
device_name=$(bluetoothctl info "$device_mac" | rg "Alias:" | cut -d ' ' -f 2-)
# Output in Waybar's JSON format
tooltip=$(bt-audio-info $device_mac)
echo "{\"text\": \"$device_name <span size='large'>󰂰</span>\", \"tooltip\": \"$tooltip\"}"
else
# Output empty string when no device is connected
echo "{}"
fi
-45
View File
@@ -1,45 +0,0 @@
#!/bin/bash
# Get BTRFS filesystems
btrfs_filesystems=$(df -hT | grep btrfs)
# Initialize variables
total_used=0
total_size=0
# Process each BTRFS filesystem
while read -r line; do
size_str=$(echo "$line" | awk '{print $3}')
used_str=$(echo "$line" | awk '{print $4}')
size=$(echo "$size_str" | sed 's/[GT]//')
used=$(echo "$used_str" | sed 's/[GT]//')
if [[ $size_str == *T ]]; then
size=$(awk -v s="$size" 'BEGIN {print s*1024}')
fi
if [[ $used_str == *T ]]; then
used=$(awk -v u="$used" 'BEGIN {print u*1024}')
fi
total_size=$(awk -v total="$total_size" -v size="$size" 'BEGIN {print total+size}')
total_used=$(awk -v total="$total_used" -v used="$used" 'BEGIN {print total+used}')
done <<< "$btrfs_filesystems"
# Calculate usage percentage
usage_percentage=$(awk -v used="$total_used" -v total="$total_size" 'BEGIN {printf "%.0f", (used/total)*100}')
# Set class based on usage
if [ "$usage_percentage" -gt 95 ]; then
class="max"
elif [ "$usage_percentage" -gt 80 ]; then
class="high"
else
class="normal"
fi
text="$(printf "%.0f" $total_used)G / $(printf "%.0f" $total_size)G"
# Manually construct the JSON output
echo "{\"text\": \"$text\", \"tooltip\": \"\", \"class\": \"$class\"}"
-22
View File
@@ -1,22 +0,0 @@
#!/bin/bash
USAGE=$(mpstat 1 1 | awk '/Average:/ {print 100 - $12}')
TEMP=$(cat /sys/class/hwmon/hwmon6/temp1_input)
TEXT="$(printf "%.1f" $(echo "$USAGE"))% $(printf "%.1f" $(echo "scale=2; $TEMP"/1000 | bc -l))C"
CPU=$(lscpu | grep 'Model name' | awk -F': ' '{print $2}' | sed 's/^[ \t]*//')
# TOOLTIP=$(ps -eo %cpu,comm --sort=-%cpu | head -n 6 | sed '1d' | awk '{output = output sprintf("%.1f%%\t%s\\n", $1, $2)} END {printf "%s", output}')
# TOOLTIP=$(ps -eo %cpu,comm --sort=-%cpu | head -n 6 | sed '1d' | awk -v ncores=$(nproc) '{printf "%.1f%%\t%s\n", $1/ncores, $2}')
# TOOLTIP=$(ps -eo %cpu,comm --sort=-%cpu | head -n 6 | sed '1d' | awk -v ncores=$(nproc) '{printf "%.1f%%\t%s\\n", $1/ncores, $2}')
# TOOLTIP=$(top -b -n 1 | sed '1,7d' | head -n 5 | awk '{output = output sprintf("%.1f%%\t%s\\n", $9, $12)} END {printf "%s", output}')
CLASS=""
if (( $(echo "$USAGE > 95" | bc -l) )); then
CLASS="max"
elif (( $(echo "$USAGE > 75" | bc -l) )); then
CLASS="high"
else
CLASS="normal"
fi
# echo "{\"text\":\"CPU: $TEXT\", \"tooltip\": \"$TOOLTIP\", \"class\":\"$CLASS\"}"
echo "{\"text\":\"CPU: $TEXT\", \"class\":\"$CLASS\"}"
-45
View File
@@ -1,45 +0,0 @@
#!/bin/bash
DEFAULT_SOURCE=$(pactl info | grep 'Default Source' | cut -d ' ' -f3)
DESCRIPTION=$(pactl list sources | grep -A2 "Name: $DEFAULT_SOURCE" | grep "Description:" | cut -d ' ' -f2-)
case $1 in
cycle)
# Filter out monitor sources
SOURCES=($(pactl list short sources | awk '{print $2}' | grep -v ".monitor"))
NUM_SOURCES=${#SOURCES[@]}
CURRENT_SOURCE=$(pactl info | grep 'Default Source' | cut -d ' ' -f3)
for i in "${!SOURCES[@]}"; do
if [[ "${SOURCES[$i]}" == "$CURRENT_SOURCE" ]]; then
NEXT_INDEX=$(( (i + 1) % NUM_SOURCES ))
pactl set-default-source "${SOURCES[$NEXT_INDEX]}"
exit 0
fi
done
# If current source was a monitor or not in list, just pick the first one
if [ $NUM_SOURCES -gt 0 ]; then
pactl set-default-source "${SOURCES[0]}"
fi
;;
show)
TEXT=$(echo "$DESCRIPTION" | cut -c -20)
if [ -z "$DESCRIPTION" ]; then
DESCRIPTION=$DEFAULT_SOURCE
fi
CLASS=""
case $(pactl get-source-mute @DEFAULT_SOURCE@ | awk '{print $2}') in
yes)
CLASS="muted"
;;
no)
CLASS="unmuted"
;;
esac
printf '{"text": "%s", "tooltip": "%s", "class": "%s"}' "$TEXT" "$DESCRIPTION" "$CLASS"
;;
*)
echo "usage cycle_input.sh {cycle|show}"
;;
esac
-31
View File
@@ -1,31 +0,0 @@
#!/bin/sh
if [ -z "$1" ]; then
echo "Usage: $0 <mountpoint>"
exit 1
fi
MOUNTPOINT=$1
# Get disk usage info
USED=$(df -h --output=used "$MOUNTPOINT" | sed '1d' | awk '{print $1}')
TOTAL=$(df -h --output=size "$MOUNTPOINT" | sed '1d' | awk '{print $1}')
PERCENTAGE=$(df --output=pcent "$MOUNTPOINT" | sed '1d' | tr -d '%' | awk '{print $1}')
# Set class based on usage
CLASS="normal"
if [ "$PERCENTAGE" -gt 95 ]; then
CLASS="max"
elif [ "$PERCENTAGE" -gt 80 ]; then
CLASS="high"
fi
# Create tooltip with more details
TOOLTIP=$(df -h "$MOUNTPOINT" | sed '1d' | awk '{printf "Used: %s\nTotal: %s\nFree: %s", $3, $2, $4}')
# Output JSON for Waybar using jq
jq -n -c \
--arg text "$1 $USED/$TOTAL" \
--arg tooltip "$TOOLTIP" \
--arg class "$CLASS" \
'{"text": $text, "tooltip": $tooltip, "class": $class}'
-10
View File
@@ -1,10 +0,0 @@
#!/usr/bin/env sh
FORMAT_ACTIVATED="<span size='large'>󰊖</span>"
FORMAT_DEACTIVATED="<span size='large'></span>"
HYPRGAMEMODE=$(hyprctl getoption animations:enabled | awk 'NR==1{print $2}')
if [ "$HYPRGAMEMODE" = 1 ] ; then
printf "{\"text\": \"$FORMAT_DEACTIVATED\", \"tooltip\": \"Gamemode deactivated\"}"
else
printf "{\"text\": \"$FORMAT_ACTIVATED\", \"tooltip\": \"Gamemode activated\", \"class\": \"active\"}"
fi
-22
View File
@@ -1,22 +0,0 @@
#!/bin/bash
USAGE=$(cat /sys/class/drm/card1/device/gpu_busy_percent)
MEM_USED=$(cat /sys/class/drm/card1/device/mem_info_vram_used)
MEM_TOTAL=$(cat /sys/class/drm/card1/device/mem_info_vram_total)
EDGE_TEMP=$(cat /sys/class/drm/card1/device/hwmon/hwmon2/temp1_input)
JUNC_TEMP=$(cat /sys/class/drm/card1/device/hwmon/hwmon2/temp2_input)
MEM_TEMP=$(cat /sys/class/drm/card1/device/hwmon/hwmon2/temp3_input)
GPU=$(/opt/rocm/bin/rocm-smi --showproductname | grep "Card Series" | awk -F':' '{print $3}' | xargs)
TEXT="$USAGE% $(printf "%.1f" $(echo "scale=2; $MEM_USED/1024/1024/1024" | bc -l))/$(printf "%.1f" $(echo "scale=2; $MEM_TOTAL/1024/1024/1024" | bc -l))GB $(printf "%.1f" $(echo "scale=2; $EDGE_TEMP/1000" | bc -l))/$(printf "%.1f" $(echo "scale=2; $MEM_TEMP/1000" | bc -l))C"
RATIO=$(echo "$MEM_USED/ $MEM_TOTAL" | bc -l)
CLASS=""
if (( $(echo "$USAGE > 95" | bc -l) )); then
CLASS="max"
elif (( $(echo "$USAGE > 75" | bc -l) )); then
CLASS="high"
else
CLASS="normal"
fi
echo "{\"text\":\"GPU: $TEXT\", \"tooltip\": \"$GPU\", \"class\":\"$CLASS\"}"
-19
View File
@@ -1,19 +0,0 @@
#!/bin/sh
# TOOLTIP=$(ps -eo rss,comm --sort=-rss | head -n 6 | sed '1d' | awk '{output = output sprintf("%.2f GB\t%s\\n", $1/1024/1024, $2)} END {printf "%s", output}')
TOTAL=$(awk '/MemTotal/ {printf "%.2f\n", $2/1024/1024}' /proc/meminfo)
USED=$(awk '/MemTotal/ {total=$2} /MemAvailable/ {available=$2} END {printf "%.2f\n", (total-available)/1024/1024}' /proc/meminfo)
RATIO=$(echo "$USED/ $TOTAL" | bc -l)
CLASS=""
if (( $(echo "$RATIO> 95" | bc -l) )); then
CLASS="max"
elif (( $(echo "$RATIO> 75" | bc -l) )); then
CLASS="high"
else
CLASS="normal"
fi
# printf '{"text": "%s/%sGB", "tooltip": "%s", "class": "%s"}' "$USED" "$TOTAL" "$TOOLTIP" "$CLASS"
printf '{"text": "%s/%sGB", "class": "%s"}' "$USED" "$TOTAL" "$CLASS"
-71
View File
@@ -1,71 +0,0 @@
#!/bin/bash
# Path for the temporary file to store previous stats
STATS_FILE="/tmp/waybar_net_stats"
# Find the primary default network interface by sorting routing metrics.
# This correctly prioritizes a VPN connection when it's active.
INTERFACE_INFO=$(ip route list | grep '^default' | sort -k 9 -n | head -n1)
INTERFACE=$(echo "$INTERFACE_INFO" | awk '{print $5}')
# Exit if no active interface is found
if [ -z "$INTERFACE" ]; then
echo "{\"text\": \"No connection\"}"
exit 0
fi
# Get the IP address for the interface
IP_ADDR=$(ip -4 addr show "$INTERFACE" | grep -oP 'inet \K[\d.]+')
# Get current time and byte counts
TIME_NOW=$(date +%s)
RX_BYTES_NOW=$(cat "/sys/class/net/$INTERFACE/statistics/rx_bytes")
TX_BYTES_NOW=$(cat "/sys/class/net/$INTERFACE/statistics/tx_bytes")
# Initialize speeds to 0
RX_MBPS="0.00"
TX_MBPS="0.00"
# Read previous values if the stats file exists
if [ -f "$STATS_FILE" ]; then
# shellcheck source=/dev/null
# Use a lock to ensure we don't source while another instance is writing
{
flock -s 200 || exit 1
source "$STATS_FILE" 2>/dev/null
} 200>"$STATS_FILE.lock"
fi
# Calculate speed if we have previous data and time has passed
if [ -n "$PREV_TIME" ] && [ -n "$PREV_RX_BYTES" ] && [ -n "$PREV_TX_BYTES" ] && [ "$TIME_NOW" -gt "$PREV_TIME" ]; then
TIME_DIFF=$((TIME_NOW - PREV_TIME))
RX_BPS=$(( (RX_BYTES_NOW - PREV_RX_BYTES) / TIME_DIFF ))
TX_BPS=$(( (TX_BYTES_NOW - PREV_TX_BYTES) / TIME_DIFF ))
# Using printf for better formatting (forces two decimal places)
RX_MBPS=$(printf "%.2f" "$(echo "$RX_BPS / 1024 / 1024" | bc -l)")
TX_MBPS=$(printf "%.2f" "$(echo "$TX_BPS / 1024 / 1024" | bc -l)")
fi
# Save current values for the next run safely using a lock
# We use a subshell with flock to ensure atomic updates and prevent race conditions
(
flock -x 200 || exit 1
echo "PREV_TIME=$TIME_NOW" > "$STATS_FILE"
echo "PREV_RX_BYTES=$RX_BYTES_NOW" >> "$STATS_FILE"
echo "PREV_TX_BYTES=$TX_BYTES_NOW" >> "$STATS_FILE"
) 200>"$STATS_FILE.lock"
# Format the main output string
OUTPUT_TEXT="$INTERFACE ($IP_ADDR):  ${RX_MBPS} MB/s  ${TX_MBPS} MB/s"
# Prepend a VPN icon if a common VPN interface is active
case "$INTERFACE" in
tun*|wg*|ppp*|pvpn*)
OUTPUT_TEXT="$OUTPUT_TEXT"
;;
esac
# Output JSON for Waybar
echo "{\"text\": \"$OUTPUT_TEXT\"}"
-126
View File
@@ -1,126 +0,0 @@
#!/bin/bash
# --- CONFIGURATION ---
# Your Pixel Buds Pro's MAC Address
MAC_ADDRESS="B4:23:A2:09:D3:53"
# --- END CONFIGURATION ---
not_connected() {
printf "{\"text\": \"<span size='large'></span>\", \"tooltip\": \"Pixel Buds Pro 2 not connected\", \"class\": \"disconnected\"}\n"
exit
}
# This function gets the current status and formats it for Waybar.
get_status() {
# Get all info from pbpctrl in one go. Redirect errors to null.
battery_output=$(pbpctrl show battery 2>/dev/null)
# Fallback: If pbpctrl fails or returns 'unknown', hide the module.
if [[ $? -ne 0 || -z "$battery_output" ]]; then
not_connected
fi
# --- PARSE BATTERY INFO ---
left_bud=$(echo "$battery_output" | grep "left bud:" | awk '{print $3}')
right_bud=$(echo "$battery_output" | grep "right bud:" | awk '{print $3}')
if ([[ "$left_bud" == "unknown" ]] && [[ "$right_bud" == "unknown" ]]) || \
[[ -z "$left_bud" && -z "$right_bud" ]]; then
echo "{}"
exit
fi
if [[ "$left_bud" == "unknown" ]]; then
left_display="L: ---"
else
left_display="L: $left_bud"
fi
if [[ "$right_bud" == "unknown" ]]; then
right_display="R: ---"
else
right_display="R: $right_bud"
fi
# --- PARSE ANC INFO ---
current_mode=$(pbpctrl get anc 2>/dev/null)
case "$current_mode" in
"active")
anc_icon="ANC"
class="anc-active"
;;
"aware")
anc_icon="Aware"
class="anc-aware"
;;
"off")
anc_icon="Off"
class="anc-off"
;;
*)
anc_icon="?"
class="anc-unknown"
;;
esac
# --- FORMAT OUTPUT ---
printf '{"text": "%s | %s | %s", "tooltip": "Pixel Buds Pro 2", "class": "%s"}\n' \
"$left_display" "$right_display" "$anc_icon" "$class"
exit
}
status() {
# First, check if the device is connected using bluetoothctl.
if bluetoothctl info "$MAC_ADDRESS" | grep -q "Connected: yes"; then
# --- DEVICE IS CONNECTED ---
get_status
else
# --- DEVICE IS NOT CONNECTED ---
not_connected
fi
}
# Handle click actions passed from Waybar.
case "$1" in
cycle_anc)
current_mode=$(pbpctrl get anc 2>/dev/null)
next_mode="active"
case "$current_mode" in
active)
next_mode="aware"
;;
aware)
next_mode="off"
;;
off)
next_mode="active"
;;
esac
pbpctrl set anc "$next_mode"
sleep 0.1
exit
;;
connect)
if bluetoothctl info "$MAC_ADDRESS" | grep -q "Connected: yes"; then
notify-send "Pixel Buds Pro 2 are already connected"
exit
else
bluetoothctl connect "$MAC_ADDRESS"
exit
fi
;;
disconnect)
if bluetoothctl info "$MAC_ADDRESS" | grep -q "Connected: yes"; then
bluetoothctl disconnect "$MAC_ADDRESS"
exit
else
notify-send "Pixel Buds Pro 2 aren't connected"
exit
fi
;;
*)
status
exit
;;
esac
-54
View File
@@ -1,54 +0,0 @@
#!/bin/bash
# --- Configuration ---
CRITICAL_THRESHOLD=15
WARNING_THRESHOLD=50
# ---------------------
# Get the battery path from upower
battery_path=$(upower -e | grep 'BAT')
# Handle case where no battery is found
if [ -z "$battery_path" ]; then
# Check if we are on AC power anyway
if [[ $(tlp-stat -s | grep "Power source" | awk '{print $4}') == "AC" ]]; then
printf '{"text": "", "tooltip": "AC Power (No Battery)", "class": "ac"}\n'
else
printf '{"text": "", "tooltip": "Error: Battery not found", "class": "unknown"}\n'
fi
exit 0
fi
# Get battery percentage and state
percentage=$(upower -i "$battery_path" | grep "percentage" | awk '{print $2}' | tr -d '%')
state=$(upower -i "$battery_path" | grep "state" | awk '{print $2}')
tlp_profile=$(tlp-stat -s | grep "Power source" | awk '{print $4}')
# Set icon, class, and tooltip based on state and percentage
if [ "$state" == "charging" ] || [ "$tlp_profile" == "AC" ]; then
icon=""
class="charging"
tooltip="TLP: AC | Charging at ${percentage}%"
elif [ "$state" == "discharging" ]; then
tooltip="TLP: Battery | Discharging at ${percentage}%"
if [ "$percentage" -le "$CRITICAL_THRESHOLD" ]; then
icon="" # Very low
class="critical"
elif [ "$percentage" -le "$WARNING_THRESHOLD" ]; then
icon="" # Low
class="warning"
elif [ "$percentage" -le 85 ]; then
icon="" # Healthy
class="bat"
else
icon="" # Full
class="bat"
fi
else # Fallback for "fully-charged", "pending-charge", etc.
icon=""
class="charging"
tooltip="TLP: AC | Fully Charged at ${percentage}%"
fi
# Output JSON for Waybar
printf '{"text": "%s%% %s", "tooltip": "%s", "class": "%s"}\n' "$percentage" "$icon" "$tooltip" "$class"
-37
View File
@@ -1,37 +0,0 @@
#!/bin/bash
TYPE=$1 # "mic" for source, empty for sink
if [ "$TYPE" == "mic" ]; then
TARGET="@DEFAULT_AUDIO_SOURCE@"
else
TARGET="@DEFAULT_AUDIO_SINK@"
fi
# Get volume and mute status from wpctl
OUTPUT=$(wpctl get-volume $TARGET)
VOLUME_RAW=$(echo "$OUTPUT" | awk '{print $2}')
VOLUME=$(echo "$VOLUME_RAW * 100 / 1" | bc)
MUTE=$(echo "$OUTPUT" | grep -c "MUTED")
if [ "$MUTE" -eq 1 ]; then
if [ "$TYPE" == "mic" ]; then
ICON=""
else
ICON=""
fi
printf '{"text": "%s", "class": "muted", "percentage": %d}' "$ICON" "$VOLUME"
else
if [ "$TYPE" == "mic" ]; then
ICON=""
else
if [ "$VOLUME" -le 30 ]; then
ICON=""
elif [ "$VOLUME" -le 60 ]; then
ICON=""
else
ICON=""
fi
fi
printf '{"text": "%d%% %s", "class": "unmuted", "percentage": %d}' "$VOLUME" "$ICON" "$VOLUME"
fi
-64
View File
@@ -1,64 +0,0 @@
import subprocess
import json
import sys
def get_wpctl_status(target):
try:
output = subprocess.check_output(["wpctl", "get-volume", target], text=True)
parts = output.strip().split()
if len(parts) < 2:
return 0, False
vol = int(float(parts[1]) * 100)
muted = "[MUTED]" in output
return vol, muted
except:
return 0, False
def get_pactl_description(target_type):
try:
cmd_info = ["pactl", "info"]
info = subprocess.check_output(cmd_info, text=True)
search_key = "Default Sink" if target_type == "sink" else "Default Source"
default_dev = next(line.split(": ")[1] for line in info.splitlines() if search_key in line)
cmd_list = ["pactl", "list", "sinks" if target_type == "sink" else "sources"]
output = subprocess.check_output(cmd_list, text=True)
blocks = output.split("\n\n")
for block in blocks:
if f"Name: {default_dev}" in block:
for line in block.splitlines():
if "Description:" in line:
desc = line.split(": ")[1].strip()
# Add a small hint if it is a monitor, though cycle_input should prevent it
if ".monitor" in default_dev:
return "Monitor: " + desc[:11]
return desc[:20]
except:
pass
return "Unknown"
try:
target_type = sys.argv[1] if len(sys.argv) > 1 else "sink"
target = "@DEFAULT_AUDIO_SINK@" if target_type == "sink" else "@DEFAULT_AUDIO_SOURCE@"
vol, muted = get_wpctl_status(target)
name = get_pactl_description(target_type)
if muted:
icon = "" if target_type == "sink" else ""
text = f"{name} {icon}"
cls = "muted"
else:
if target_type == "sink":
if vol <= 30: icon = ""
elif vol <= 60: icon = ""
else: icon = ""
else:
icon = ""
text = f"{name} {vol}% {icon}"
cls = "unmuted"
print(json.dumps({"text": text, "class": cls, "percentage": vol}))
except Exception as e:
print(json.dumps({"text": "Error", "class": "error"}))
+143 -93
View File
@@ -4,13 +4,11 @@
/* --- Global Reset --- */ /* --- Global Reset --- */
* { * {
border: none; border: none;
border-radius: 0; border-radius: 12px;
min-height: 0; min-height: 0;
font-family: font-family: JetBrainsMono Nerd Font, sans-serif;
JetBrainsMono Nerd Font, font-size: 12px;
monospace; transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
font-size: 13px;
transition: all 0.2s ease;
} }
/* --- Bar Background (Floating Island Style) --- */ /* --- Bar Background (Floating Island Style) --- */
@@ -19,32 +17,6 @@ window#waybar {
color: @text; color: @text;
} }
/* --- Shared Island Styling --- */
#workspaces,
#window,
#clock,
#tray,
#custom-sys,
#custom-cpu,
#custom-gpu,
#custom-mem,
#custom-network,
#custom-btrfs,
#custom-disk-root,
#custom-pixelbuds_pro,
#custom-bluetooth-audio,
#custom-volume,
#custom-mic,
#custom-gamemode,
#custom-gpu-screen-recorder,
#custom-power_status {
background-color: alpha(@surface0, 0.95);
margin: 4px 2px;
padding: 0 12px;
border-radius: 5px;
border: 1px solid alpha(@surface1, 0.5);
}
/* --- Top Bar Special Handling --- */ /* --- Top Bar Special Handling --- */
window#waybar.top { window#waybar.top {
margin-top: 6px; margin-top: 6px;
@@ -55,33 +27,67 @@ window#waybar.bottom {
margin-bottom: 6px; margin-bottom: 6px;
} }
/* --- Shared Island Styling --- */
#workspaces,
#window,
#tray,
#hardware,
#custom-bluetooth-audio,
#custom-volume,
#custom-buds,
#custom-mic,
#custom-dnd,
#custom-gamemode,
#custom-power_status {
background-color: alpha(@surface0, 0.8);
margin: 4px 6px;
padding: 4px 16px;
border: 1px solid alpha(@surface1, 0.5);
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.15);
color: @text; /* Unifies all standard text to the soft Catppuccin white */
}
/* --- Workspaces --- */ /* --- Workspaces --- */
#workspaces {
padding: 2px 8px;
}
#workspaces button { #workspaces button {
padding: 0 8px; padding: 0;
margin: 4px 2px; margin: 4px;
border-radius: 5px; min-width: 12px;
color: @subtext0; min-height: 12px;
background-color: transparent; background-color: @subtext0; /* Subtle dark gray for inactive */
color: transparent;
border-radius: 12px;
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
} }
#workspaces button.active { #workspaces button.active {
color: @blue; min-width: 30px;
background-color: @surface1; background-color: @mauve; /* Signature Catppuccin accent */
}
#workspaces button.active:hover { min-width: 30px; background-color: @mauve; }
#workspaces button:hover {
background-color: @lavender;
min-width: 20px;
} }
#workspaces button.urgent { #workspaces button.urgent {
color: @red; background-color: @red;
}
#workspaces button:hover {
background-color: @surface2;
color: @text;
} }
/* --- Clock (Centered Pill) --- */ /* --- Clock (Centered Pill) --- */
#clock { #center {
color: @mauve; background: linear-gradient(45deg, @mauve, @lavender); /* Cohesive pastel gradient */
font-weight: bold; color: @surface0;
font-weight: 900;
margin: 4px 6px;
padding: 4px 20px;
border-radius: 12px;
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.15);
} }
/* --- Power Status --- */ /* --- Power Status --- */
@@ -90,86 +96,130 @@ window#waybar.bottom {
} }
#custom-power_status.charging { #custom-power_status.charging {
color: @green; color: @green;
border-color: @green;
}
#custom-power_status.bat {
color: @yellow;
} }
#custom-power_status.warning { #custom-power_status.warning {
color: @peach; color: @peach;
} }
#custom-power_status.critical { #custom-power_status.critical {
color: @red; color: @red;
border-color: @red;
animation: blink 1s infinite alternate; animation: blink 1s infinite alternate;
} }
@keyframes blink { @keyframes blink {
to { to {
background-color: alpha(@red, 0.4); color: @base;
background-color: @red;
} }
} }
/* --- Hardware Metrics (Left Bottom) --- */ /* --- Hardware Group (Left Bottom) --- */
#custom-sys { #hardware {
color: @teal; border-radius: 24px;
} padding: 4px 10px;
#custom-cpu {
color: @blue;
}
#custom-mem {
color: @lavender;
}
#custom-network {
color: @sapphire;
} }
#custom-cpu.high, /* Strip backgrounds and borders from the items inside the group */
#custom-mem.high { #custom-cpu,
color: @yellow; #custom-mem,
#custom-network
#custom-sys,
#custom-gpu,
#custom-disk-root,
#custom-mpris,
#clock,
#custom-dnd {
background-color: transparent;
border: none;
box-shadow: none;
margin: 0;
padding: 0 8px;
} }
#custom-cpu.max,
#custom-mem.max { /* Subtle vertical separator line between them */
color: @red; #custom-cpu,
#custom-mem,
#custom-sys,
#custom-gpu,
#custom-disk-root,
#custom-mpris
/* #clock */ {
border-right: 1px solid alpha(@surface1, 0.5);
border-radius: 0;
} }
#custom-network {
padding-left: 8px;
color: @mauve;
}
/* Hardware Semantic Alerts */
.normal { color: @mauve; }
.high { color: @peach; }
.max { color: @red; }
/* Stale Data Warning (Module in backoff/failure state) */
/* .warning {
color: @peach;
opacity: 0.6;
} */
/* --- Center Bottom Utilities --- */ /* --- Center Bottom Utilities --- */
#custom-gamemode {
color: @yellow;
}
#custom-gamemode.active { #custom-gamemode.active {
color: @red; color: @mauve; /* Matches the workspace accent */
border-color: @red; /* padding-left: 9px; */
padding-left: 9px;
} }
/* --- Right Bottom Controls --- */ /* --- Right Bottom Controls Semantic Alerts --- */
#custom-disk-root {
color: @sky;
}
#custom-volume {
color: @mauve;
}
#custom-mic {
color: @flamingo;
}
#custom-volume.muted, #custom-volume.muted,
#custom-mic.muted { #custom-mic.muted {
color: @overlay0; color: @overlay1; /* Dims when muted */
} }
#custom-bluetooth-audio {
color: @blue; #custom-bluetooth-audio.disabled {
color: @overlay1; /* Green for active ANC */
} }
#custom-bluetooth-audio.connected {
color: @blue; /* Green for active ANC */
}
#custom-bluetooth-audio.anc-off {
color: @blue; /* Green for active ANC */
}
#custom-bluetooth-audio.anc-active {
color: @blue; /* Green for active ANC */
}
#custom-bluetooth-audio.anc-aware {
color: @blue; /* Yellow for transparency mode */
}
#custom-bluetooth-audio.disconnected {
color: @text; /* Gray when off */
}
/* --- Hover States --- */
#custom-volume:hover,
#custom-buds:hover,
#custom-mic:hover,
#custom-bluetooth-audio:hover,
#custom-power_status:hover {
background-color: @surface1;
color: @mauve; /* Subtle accent color on hover instead of jarring borders */
}
/* --- Tooltip --- */ /* --- Tooltip --- */
tooltip { tooltip {
background-color: alpha(@base, 0.95); background-color: alpha(@base, 0.9);
border: 1px solid @surface1; border: 1px solid @surface1;
border-radius: 5px; border-radius: 8px;
} }
tooltip label { tooltip label {
color: @text; color: @text;
padding: 8px; padding: 8px;
} }