diff --git a/.config/waybar/base.jsonc##hostname.viking-mate b/.config/waybar/base.jsonc##hostname.viking-mate new file mode 100644 index 0000000..173954b --- /dev/null +++ b/.config/waybar/base.jsonc##hostname.viking-mate @@ -0,0 +1,207 @@ +{ + // Shared defaults & core module definitions (laptop host) + "layer": "bottom", + "position": "bottom", + "mod": "dock", + "exclusive": true, + "gtk-layer-shell": true, + "passthrough": false, + "fixed-center": true, + "height": 32, + "spacing": 8, + + // Hyprland + "hyprland/workspaces": { + "icon-size": 24, + "spacing": 10, + "all-outputs": true, + "on-scroll-up": "hyprctl dispatch workspace r+1", + "on-scroll-down": "hyprctl dispatch workspace r-1" + }, + "hyprland/window": { + "format": "{title}", + "max-length": 56, + "separate-outputs": false, + "tooltip": true + }, + + // System stats + "cpu": { "interval": 5, "format": " {usage}%", "tooltip": true, "on-click": "alacritty -e btop" }, + "memory": { "interval": 11, "format": " {percentage}%", "tooltip": true, "on-click": "alacritty -e btop" }, + "custom/temps": { + "exec-if": "command -v sensors >/dev/null", + "exec": "bash -lc \"sensors | awk '/Tctl|Tdie|Package id 0/{gsub(/\\+|°C/,\\\"\\\"); print int($2); exit}'\"", + "interval": 5, + "format": " {output}°C", + "tooltip": true, + "on-click": "alacritty -e watch -n 1 sensors" + }, + + // Disks (keep minimal on laptop) + "disk#root": { + "interval": 29, + "path": "/", + "format": " {percentage_used}%", + "tooltip": true, + "tooltip-format": "Root: {used} / {total} ({percentage_used}%)" + }, + + // Media + "mpris": { + "format": "{player_icon} {dynamic}", + "format-paused": "{status_icon} {dynamic}", + "dynamic-len": 40, + "ellipsis": "…", + "player-icons": { "default": "▶", "mpv": "🎵", "spotify": "" }, + "status-icons": { "paused": "⏸" }, + "on-click": "playerctl play-pause", + "on-click-right": "playerctl next", + "on-click-middle": "playerctl previous", + "on-scroll-up": "playerctl position 5+", + "on-scroll-down": "playerctl position 5-", + "tooltip": true + }, + + // Network / Audio / BT + "network": { + "format-wifi": " {essid} ({signalStrength}%)", + "format-ethernet": " {ifname}", + "format-disconnected": "󰌙 Disconnected", + "tooltip": true, + "tooltip-format": "{ifname} → {gwaddr}", + "on-click": "nm-connection-editor", + "on-click-right": "alacritty -e nmtui" + }, + "pulseaudio": { + "format": "{icon} {volume}%", + "format-muted": " Muted", + "scroll-step": 5, + "interval": 30, + "tooltip": true, + "on-click": "pavucontrol", + "on-click-right": "pactl set-sink-mute @DEFAULT_SINK@ toggle", + "format-icons": { "default": ["", ""] } + }, + "bluetooth": { + "format": " {status}", + "format-connected": " {device_alias} ({device_battery_percentage}%)", + "tooltip": true, + "on-click": "blueman-manager" + }, + + // Backlight (screen) + "backlight": { + "interval": 2, + "format": " {percent}%", + "on-scroll-up": "brightnessctl set +5%", + "on-scroll-down": "brightnessctl set 5%-", + "tooltip": true + }, + + // Power + "battery": { + "states": { "good": 95, "warning": 30, "critical": 20 }, + "format": "{icon} {capacity}%", + "format-alt": "{icon} {capacity}% ({time})", + "format-charging": " {capacity}%", + "format-full": " {capacity}%", + "tooltip": true, + "interval": 15, + "format-icons": ["󰁺","󰁼","󰁿","󰂂","󰁹"] + }, + "power-profiles-daemon": { + "format": " {profile}", + "tooltip": true, + "on-click": "bash -lc 'cur=$(powerprofilesctl get); case $cur in performance) nxt=balanced;; balanced) nxt=powersave;; *) nxt=performance;; esac; powerprofilesctl set $nxt; notify-send -a waybar \"Power Profile\" \"Switched to $nxt\"'" + }, + + // Hyprsunset (reusing your existing script wiring & daemon) + "custom/hyprsunset": { + "exec-if": "[ -x $HOME/.config/waybar/scripts/hyprsunset_toggle.sh ]", + "exec": "$HOME/.config/waybar/scripts/hyprsunset_toggle.sh --print", + "return-type": "json", + "interval": 60, + "signal": 5, + "format": "{text}", + "tooltip": true, + "on-click": "bash -lc '$HOME/.config/waybar/scripts/hyprsunset_toggle.sh --toggle-auto && pkill -SIGRTMIN+5 waybar'", + "on-click-right": "bash -lc '$HOME/.config/waybar/scripts/hyprsunset_toggle.sh --toggle && pkill -SIGRTMIN+5 waybar'", + "on-scroll-up": "bash -lc 't=$($HOME/.config/waybar/scripts/hyprsunset_toggle.sh --print | sed -n \"s/.* \\([0-9]\\+\\)K.*/\\1/p\"); [ -z \"$t\" ] && t=3800; t=$((t+200)); $HOME/.config/waybar/scripts/hyprsunset_toggle.sh --set $t && pkill -SIGRTMIN+5 waybar'", + "on-scroll-down": "bash -lc 't=$($HOME/.config/waybar/scripts/hyprsunset_toggle.sh --print | sed -n \"s/.* \\([0-9]\\+\\)K.*/\\1/p\"); [ -z \"$t\" ] && t=3800; t=$((t-200)); [ $t -lt 1000 ] && t=1000; $HOME/.config/waybar/scripts/hyprsunset_toggle.sh --set $t && pkill -SIGRTMIN+5 waybar'" + }, + + // Extra laptop customs (defined by scripts below) + "custom/wifi": { + "exec-if": "command -v nmcli >/dev/null", + "exec": "$HOME/.config/waybar/scripts/wifi_toggle.sh --print", + "return-type": "json", + "interval": 5, + "signal": 10, + "format": "{text}", + "tooltip": true, + "on-click": "bash -lc '$HOME/.config/waybar/scripts/wifi_toggle.sh --toggle && pkill -SIGRTMIN+10 waybar'" + }, + "custom/bt": { + "exec-if": "command -v bluetoothctl >/dev/null", + "exec": "$HOME/.config/waybar/scripts/bt_toggle.sh --print", + "return-type": "json", + "interval": 5, + "signal": 11, + "format": "{text}", + "tooltip": true, + "on-click": "bash -lc '$HOME/.config/waybar/scripts/bt_toggle.sh --toggle && pkill -SIGRTMIN+11 waybar'" + }, + "custom/airplane": { + "exec-if": "command -v rfkill >/dev/null", + "exec": "$HOME/.config/waybar/scripts/airplane_mode.sh --print", + "return-type": "json", + "interval": 7, + "signal": 12, + "format": "{text}", + "tooltip": true, + "on-click": "bash -lc '$HOME/.config/waybar/scripts/airplane_mode.sh --toggle && pkill -SIGRTMIN+12 waybar'" + }, + "custom/kbdlight": { + "exec-if": "command -v brightnessctl >/dev/null", + "exec": "$HOME/.config/waybar/scripts/kbdlight.sh --print", + "return-type": "json", + "interval": 4, + "signal": 13, + "format": "{text}", + "tooltip": true, + "on-scroll-up": "bash -lc '$HOME/.config/waybar/scripts/kbdlight.sh --inc && pkill -SIGRTMIN+13 waybar'", + "on-scroll-down": "bash -lc '$HOME/.config/waybar/scripts/kbdlight.sh --dec && pkill -SIGRTMIN+13 waybar'" + }, + "custom/batteryhealth": { + "exec-if": "command -v upower >/dev/null", + "exec": "$HOME/.config/waybar/scripts/battery_health.sh", + "return-type": "json", + "interval": 120, + "signal": 14, + "format": "{text}", + "tooltip": true + }, + + // Performance (same concept as desktop) + "custom/performance": { + "exec-if": "[ -x $HOME/.config/waybar/scripts/performance.sh ]", + "exec": "$HOME/.config/waybar/scripts/performance.sh", + "interval": 10, + "signal": 6, + "tooltip": true, + "on-click": "bash -lc '$HOME/.config/waybar/scripts/performance.sh toggle >/dev/null 2>&1; pkill -SIGRTMIN+6 waybar'", + "on-click-right": "bash -lc '$HOME/.config/waybar/scripts/performance.sh cycle >/dev/null 2>&1; pkill -SIGRTMIN+6 waybar'", + "format": "{text}" + }, + + // Tray / Clock / Privacy + "tray": { "icon-size": 18, "spacing": 4 }, + "clock": { + "format": "{:%R | %d.%m.%Y}", + "tooltip-format": "{calendar}", + "calendar": { "mode": "year", "mode-mon-col": 3, "weeks-pos": "right" }, + "actions": { "on-click-right": "mode", "on-scroll-up": "shift_up", "on-scroll-down": "shift_down" } + }, + "privacy": { "icon-size": 16, "tooltip": true } +} + diff --git a/.config/waybar/conf.d/laptop.jsonc##hostname.viking-mate b/.config/waybar/conf.d/laptop.jsonc##hostname.viking-mate new file mode 100644 index 0000000..4a5d30e --- /dev/null +++ b/.config/waybar/conf.d/laptop.jsonc##hostname.viking-mate @@ -0,0 +1,41 @@ +{ + "name": "bar-laptop", + "output": "eDP-1", // change if your panel isn't eDP-1 + "height": 32, + "spacing": 8, + + "modules-left": ["hyprland/workspaces", "hyprland/window"], + "modules-center": ["privacy", "mpris"], + "modules-right": [ + "group/sys", + "network", + "backlight", + "custom/kbdlight", + "pulseaudio", + "bluetooth", + "custom/wifi", + "custom/bt", + "custom/airplane", + "battery", + "custom/batteryhealth", + "power-profiles-daemon", + "custom/performance", + "custom/hyprsunset", + "tray", + "clock" + ], + + // Drawer for noisy stats to save width + "custom/sys": { "format": "", "tooltip": true }, + "group/sys": { + "orientation": "horizontal", + "drawer": { + "transition-duration": 300, + "children-class": "sys", + "click-to-reveal": true, + "transition-left-to-right": false + }, + "modules": ["custom/sys", "cpu", "memory", "custom/temps", "disk#root"] + } +} + diff --git a/.config/waybar/config.jsonc##hostname.viking-mate b/.config/waybar/config.jsonc##hostname.viking-mate new file mode 100644 index 0000000..ced45b9 --- /dev/null +++ b/.config/waybar/config.jsonc##hostname.viking-mate @@ -0,0 +1,4 @@ +[ + { "include": ["base.jsonc", "conf.d/laptop.jsonc"] } +] + diff --git a/.config/waybar/scripts/airplane_mode.sh b/.config/waybar/scripts/airplane_mode.sh new file mode 100755 index 0000000..13d5677 --- /dev/null +++ b/.config/waybar/scripts/airplane_mode.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +set -euo pipefail +is_blocked_all() { rfkill list | awk '/Soft blocked:/{c++;/yes/&&y++} END{exit !(c>0 && c==y)}'; } +print() { + if is_blocked_all; then + echo '{"text":"✈","class":"on","tooltip":"Airplane mode: ON (click to disable)"}' + else + echo '{"text":"✈","class":"off","tooltip":"Airplane mode: OFF (click to enable)"}' + fi +} +case "${1:---print}" in + --toggle) + if is_blocked_all; then rfkill unblock all; else rfkill block all; fi + ;; + --print) : ;; + *) echo "Usage: $0 [--toggle|--print]"; exit 1 ;; +esac +print + diff --git a/.config/waybar/scripts/battery_health.sh b/.config/waybar/scripts/battery_health.sh new file mode 100755 index 0000000..c0a9bc1 --- /dev/null +++ b/.config/waybar/scripts/battery_health.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +set -euo pipefail +bat="$(upower -e | grep -m1 BAT || true)" +if [ -z "$bat" ]; then + echo '{"text":" --","class":"no-battery","tooltip":"No battery found"}' + exit 0 +fi +info="$(upower -i "$bat")" +full=$(echo "$info" | awk -F: '/energy-full:/{gsub(/[^0-9.]/,"",$2); print $2; exit}') +design=$(echo "$info" | awk -F: '/energy-full-design:/{gsub(/[^0-9.]/,"",$2); print $2; exit}') +if [ -z "$full" ] || [ -z "$design" ] || [ "$design" = "0" ]; then + # Try charge-full fallback + full=$(echo "$info" | awk -F: '/charge-full:/{gsub(/[^0-9.]/,"",$2); print $2; exit}') + design=$(echo "$info" | awk -F: '/charge-full-design:/{gsub(/[^0-9.]/,"",$2); print $2; exit}') +fi +wear="--" +if [ -n "$full" ] && [ -n "$design" ] && [ "$design" != "0" ]; then + health=$(awk -v f="$full" -v d="$design" 'BEGIN{printf "%.0f", (f/d)*100}') + wear=$(( 100 - health )) + text="❤ ${health}%" +else + text="❤ --" +fi +cycles=$(echo "$info" | awk -F: '/cycle count:/{gsub(/[^0-9]/,"",$2); print $2; exit}') +vendor=$(echo "$info" | awk -F: '/vendor:/{gsub(/^ +/,"",$2); print $2; exit}') +model=$(echo "$info" | awk -F: '/model:/{gsub(/^ +/,"",$2); print $2; exit}') +tt="Battery health info\nWear: ${wear}%\nCycles: ${cycles:---}\nVendor: ${vendor:---}\nModel: ${model:---}" +printf '{"text":"%s","class":"battery-health","tooltip":"%s"}\n' "$text" "$(echo "$tt" | sed ':a;N;$!ba;s/\n/\\n/g')" + diff --git a/.config/waybar/scripts/bt_toggle.sh b/.config/waybar/scripts/bt_toggle.sh new file mode 100755 index 0000000..97a8608 --- /dev/null +++ b/.config/waybar/scripts/bt_toggle.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +set -euo pipefail +status() { bluetoothctl show 2>/dev/null | awk '/Powered:/ {print tolower($2); exit}'; } # yes/no +print() { + s="$(status)"; s="${s:-no}" + if [ "$s" = "yes" ]; then + echo '{"text":"","class":"on","tooltip":"Bluetooth: on (click to toggle)"}' + else + echo '{"text":"","class":"off","tooltip":"Bluetooth: off (click to toggle)"}' + fi +} +case "${1:---print}" in + --toggle) [ "$(status)" = "yes" ] && bluetoothctl power off || bluetoothctl power on ;; + --print) : ;; + *) echo "Usage: $0 [--toggle|--print]"; exit 1 ;; +esac +print + diff --git a/.config/waybar/scripts/kbdlight.sh b/.config/waybar/scripts/kbdlight.sh new file mode 100755 index 0000000..85c6763 --- /dev/null +++ b/.config/waybar/scripts/kbdlight.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +set -euo pipefail +dev() { brightnessctl --list 2>/dev/null | awk '/kbd_backlight/ {print $2; exit}'; } +get_vals() { + d="$(dev)"; [ -z "$d" ] && return 1 + cur="$(brightnessctl -d "$d" get)"; max="$(brightnessctl -d "$d" max)" + echo "$d;$cur;$max" +} +print() { + if vals="$(get_vals)"; then + IFS=';' read -r d cur max <<<"$vals" + [ "$max" -gt 0 ] || max=1 + pct=$(( cur * 100 / max )) + # show in steps if small range + steps=$(( max>10 ? 10 : max )) + step=$(( cur * steps / max )) + echo "{\"text\":\"⌨ ${pct}%\",\"class\":\"kbd $step/$steps\",\"tooltip\":\"Keyboard backlight: ${cur}/${max} (${pct}%)\\nScroll to adjust\"}" + else + echo '{"text":"⌨","class":"kbd none","tooltip":"No keyboard backlight device found"}' + fi +} +case "${1:---print}" in + --inc) if vals="$(get_vals)"; then IFS=';' read -r d cur max <<<"$vals"; brightnessctl -d "$d" set +1 >/dev/null; fi ;; + --dec) if vals="$(get_vals)"; then IFS=';' read -r d cur max <<<"$vals"; brightnessctl -d "$d" set 1- >/dev/null; fi ;; + --print) : ;; + *) echo "Usage: $0 [--inc|--dec|--print]"; exit 1 ;; +esac +print + diff --git a/.config/waybar/scripts/wifi_toggle.sh b/.config/waybar/scripts/wifi_toggle.sh new file mode 100755 index 0000000..8e69c85 --- /dev/null +++ b/.config/waybar/scripts/wifi_toggle.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +set -euo pipefail +status() { nmcli -t -f WIFI g | awk -F: '{print $1}'; } # enabled/disabled +print() { + s="$(status)" + if [ "$s" = "enabled" ]; then + echo '{"text":"","class":"on","tooltip":"Wi-Fi: enabled (click to toggle)"}' + else + echo '{"text":"","class":"off","tooltip":"Wi-Fi: disabled (click to toggle)"}' + fi +} +case "${1:---print}" in + --toggle) [ "$(status)" = "enabled" ] && nmcli radio wifi off || nmcli radio wifi on ;; + --print) : ;; + *) echo "Usage: $0 [--toggle|--print]"; exit 1 ;; +esac +print + diff --git a/.config/waybar/style.css b/.config/waybar/style.css new file mode 120000 index 0000000..46e9c4a --- /dev/null +++ b/.config/waybar/style.css @@ -0,0 +1 @@ +style.css##hostname.cn-arch \ No newline at end of file diff --git a/.config/waybar/style.css##hostname.cn-arch b/.config/waybar/style.css##hostname.cn-arch deleted file mode 100644 index a2e161e..0000000 --- a/.config/waybar/style.css##hostname.cn-arch +++ /dev/null @@ -1,181 +0,0 @@ -/* ========================= - Midnight-Ocean — Waybar GTK CSS - ========================= */ - -/* Palette */ -@define-color bg_main rgba(11, 27, 43, 0.85); -@define-color bg_main_tooltip rgba(11, 27, 43, 0.95); -@define-color bg_hover rgba(79, 132, 204, 0.3); -@define-color bg_active rgba(53, 107, 171, 0.7); -@define-color border_main rgba(79, 132, 204, 0.5); -@define-color content_main #FFFFFF; /* ← all text white */ -@define-color content_inactive rgba(255, 255, 255, 0.45); -@define-color warning_color #FFCC33; - -/* Reset & Font */ -* { - font-family: "Inconsolata Go Nerd Font"; - font-size: 14px; - text-shadow: none; - box-shadow: none; - border-radius: 0; - margin: 0; - padding: 0; - color: @content_main; -} - -/* Bar Background */ -window#waybar { - background: @bg_main; - border-top: 1px solid @border_main; -} - -/* Per-bar sizing nudges */ -window#waybar.bar-dp2 * { - font-size: 14px; -} -window#waybar.bar-dp1 * { - font-size: 14px; -} -window#waybar.bar-hdmi * { - font-size: 13px; -} - -/* Tooltips */ -tooltip { - background: @bg_main_tooltip; - border: 1px solid @border_main; - border-radius: 4px; - padding: 4px 6px; -} - -/* Module Spacing & Hover */ -.module { - padding: 0 6px; - margin: 0 2px; -} -.module:hover { - background: @bg_hover; -} - -/* HDMI: tighter modules to free center space */ -window#waybar.bar-hdmi .module { - padding: 0 4px; -} - -/* Collapse empty/noise modules */ -#mpris.empty, -#bluetooth.disconnected { - padding: 0; - margin: 0; - border: none; -} - -/* Separators */ -#cpu, -#memory, -#disk, -#disk-nvme0, -#disk-nvme1, -#network, -#pulseaudio, -#bluetooth, -#power-profiles-daemon, -#custom-alhp, -#custom-razer-mouse-battery, -#custom-hyprsunset { - /* ← new module gets a separator too */ - border-right: 1px solid @border_main; -} - -/* Workspaces */ -#workspaces { - margin: 0 2px; -} -#workspaces button { - padding: 4px 6px; - color: @content_inactive; -} -#workspaces button:hover { - background: @bg_hover; - color: @content_main; -} -#workspaces button.active { - background: @bg_active; - color: @content_main; - font-weight: 600; -} -#workspaces button.urgent { - background: rgba(255, 204, 51, 0.35); - color: @warning_color; -} - -/* Window title (hyprland/window): truncation via config max-length */ -#window { - min-width: 0; - font-weight: 500; - padding: 0 6px; -} - -/* MPRIS */ -#mpris { - min-width: 0; - padding: 0 6px; -} - -/* Tray & Clock */ -#tray, -#clock { - padding: 0 6px; -} -#tray > .passive { - opacity: 0.7; -} -#tray > .needs-attention { - color: @warning_color; -} - -/* Battery states */ -#battery.warning { - color: @warning_color; -} -#battery.critical { - color: @warning_color; -} -#battery.critical span { - color: @warning_color; -} - -/* Optional subtle accent for quick scanning (kept minimal; text still white overall) */ -#cpu, -#network, -#pulseaudio, -#bluetooth, -#mpris, -#custom-hyprsunset { - color: #dee6f7; /* very light tint; still reads as white on dark */ -} - -/* Drawer polish (DP-1) */ -#custom-sys { - padding: 0 8px; - font-weight: 600; -} -.sys { - padding: 0 6px; -} -.revealed .sys { - background: rgba(79, 132, 204, 0.12); -} - -/* Customs */ -#custom-alhp, -#custom-razer-mouse-battery, -#custom-hyprsunset { - padding: 0 6px; -} - -/* Network states */ -#network.disconnected { - color: @warning_color; -}