diff --git a/.config/waybar/base.jsonc##hostname.cn-arch b/.config/waybar/base.jsonc##hostname.cn-arch
new file mode 100644
index 0000000..660f230
--- /dev/null
+++ b/.config/waybar/base.jsonc##hostname.cn-arch
@@ -0,0 +1,196 @@
+{
+ // Shared defaults & module definitions
+ "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": 26,
+ "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": 70,
+ "separate-outputs": false,
+ "tooltip": true,
+ },
+ // System
+ "cpu": {
+ "interval": 5,
+ "format": " {usage}%",
+ "tooltip": true,
+ "on-click": "alacritty -e btop",
+ },
+ "memory": {
+ "interval": 11,
+ "format": " {percentage}%",
+ "tooltip": true,
+ "on-click": "alacritty -e btop",
+ },
+ "disk#nvme0": {
+ "interval": 29,
+ "path": "/",
+ "format": " {percentage_used}%",
+ "tooltip": true,
+ "tooltip-format": "Root: {used} / {total} ({percentage_used}%)",
+ "on-click": "alacritty -e bash -lc \"df -hT /; echo; sudo btrfs filesystem usage -T / 2>/dev/null || true; read -n1 -r -p 'Press any key...'\"",
+ },
+ "disk#nvme1": {
+ "interval": 29,
+ "path": "/home/cnachtigall/data",
+ "format": " {percentage_used}%",
+ "tooltip": true,
+ "tooltip-format": "Data: {used} / {total} ({percentage_used}%)",
+ "on-click": "alacritty -e bash -lc \"df -hT /home/cnachtigall/data; echo; sudo btrfs filesystem usage -T /home/cnachtigall/data 2>/dev/null || true; read -n1 -r -p 'Press any key...'\"",
+ },
+ // Media
+ "mpris": {
+ "format": "{player_icon} {dynamic}",
+ "format-paused": "{status_icon} {dynamic}",
+ "dynamic-len": 50,
+ "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",
+ "on-click-middle": "bash -lc \"next=$(pactl list short sinks | awk '{print \\$1}' | awk -v cur=$(pactl get-default-sink) '\\$0!=cur{print; exit}'); if [ -n \\\"$next\\\" ]; then pactl set-default-sink $next; notify-send -a waybar 'Audio' 'Switched default sink to '$next; fi\"",
+ "format-icons": {
+ "alsa_output.usb-SteelSeries_Arctis_7_-00.analog-stereo": "",
+ "alsa_output.pci-0000_0a_00.4.iec958-stereo": "",
+ "bluez_output.50_5E_5C_2D_F3_B2.1": "",
+ "default": ["", ""],
+ },
+ },
+ "bluetooth": {
+ "format": " {status}",
+ "format-connected": " {device_alias} ({device_battery_percentage}%)",
+ "tooltip": true,
+ "on-click": "blueman-manager",
+ },
+ // 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\"'",
+ },
+ // Customs
+ "custom/alhp": {
+ "exec-if": "[ -x $HOME/.config/waybar/scripts/alhp.sh ]",
+ "exec": "$HOME/.config/waybar/scripts/alhp.sh",
+ "return-type": "json",
+ "interval": 60,
+ "signal": 3,
+ "format": "{text}",
+ "tooltip": true,
+ "on-click": "pkill -SIGRTMIN+3 waybar",
+ },
+ "custom/razer-mouse-battery": {
+ "exec-if": "[ -x $HOME/.config/waybar/scripts/razer_basilisk_v3_pro_battery_info.sh ]",
+ "exec": "$HOME/.config/waybar/scripts/razer_basilisk_v3_pro_battery_info.sh",
+ "return-type": "json",
+ "interval": 30,
+ "signal": 4,
+ "format": "{text}",
+ "tooltip": true,
+ "on-click": "pkill -SIGRTMIN+4 waybar",
+ },
+ "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",
+ },
+ "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,
+ // Left click: toggle AUTO on/off (your ask)
+ "on-click": "bash -lc '$HOME/.config/waybar/scripts/hyprsunset_toggle.sh --toggle-auto && pkill -SIGRTMIN+5 waybar'",
+ // Right click: manual on/off (doesn’t touch auto flag)
+ "on-click-right": "bash -lc '$HOME/.config/waybar/scripts/hyprsunset_toggle.sh --toggle && pkill -SIGRTMIN+5 waybar'",
+ // Scroll: fine tune manual temp (useful when AUTO is OFF)
+ "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)); if [ $t -lt 1000 ]; then t=1000; fi; $HOME/.config/waybar/scripts/hyprsunset_toggle.sh --set $t && pkill -SIGRTMIN+5 waybar'",
+ },
+ // 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/config.jsonc##hostname.cn-arch b/.config/waybar/config.jsonc##hostname.cn-arch
index 8adbeac..70a4827 100644
--- a/.config/waybar/config.jsonc##hostname.cn-arch
+++ b/.config/waybar/config.jsonc##hostname.cn-arch
@@ -1,135 +1,11 @@
-{
- "layer": "bottom",
- "output": [
- "DP-1",
- "DP-2",
- "HDMI-A-2"
- ],
- "position": "bottom",
- "mod": "dock",
- "exclusive": true,
- "gtk-layer-shell": true,
- "passthrough": false,
- "height": 32,
- "modules-left": [
- "hyprland/workspaces"
- ],
- "modules-center": [
- "privacy"
- ],
- "modules-right": [
- "cpu",
- "memory",
- "disk",
- "network",
- "pulseaudio",
- "bluetooth",
- "battery",
- "custom/alhp",
- "custom/razer-mouse-battery",
- "tray",
- "clock",
- ],
- "hyprland/workspaces": {
- "icon-size": 28,
- "spacing": 12,
- "on-scroll-up": "hyprctl dispatch workspace r+1",
- "on-scroll-down": "hyprctl dispatch workspace r-1",
+[
+ {
+ "include": ["base.jsonc", "conf.d/dp2.jsonc"],
},
- "cpu": {
- "interval": 5,
- "format": " {usage}%",
+ {
+ "include": ["base.jsonc", "conf.d/dp1.jsonc"],
},
- "memory": {
- "interval": 10,
- "format": " {percentage}%",
- "tooltip": true,
+ {
+ "include": ["base.jsonc", "conf.d/hdmi.jsonc"],
},
- "disk": {
- "interval": 30,
- "format": " {percentage_used}%",
- "tooltip": true,
- },
- "mpris": {
- "format": "{player_icon} {dynamic}",
- "format-paused": "{status_icon} {dynamic}",
- "dynamic-len": 50,
- "ellipsis": "…",
- "player-icons": {
- "default": "▶",
- "mpv": "🎵",
- },
- "status-icons": {
- "paused": "⏸",
- },
- },
- "network": {
- "format-wifi": " {essid} ({signalStrength}%)",
- "format-ethernet": " {ifname}",
- "format-disconnected": " Disconnected",
- "tooltip": true,
- "tooltip-format": "{ifname} via {gwaddr}",
- },
- "pulseaudio": {
- "format": "{icon} {volume}%",
- "format-muted": " Muted",
- "scroll-step": 5,
- "on-click": "pavucontrol",
- "interval": 30,
- "format-icons": {
- // match these to the sink NAMES you see in `pactl list sinks`
- "alsa_output.usb-SteelSeries_Arctis_7_-00.analog-stereo": "", // SteelSeries headset
- "alsa_output.pci-0000_0a_00.4.iec958-stereo": "", // speaker icon for your soundbar
- "bluez_output.50_5E_5C_2D_F3_B2.1": "", // Bluetooth earbud icon
- "default": [
- "",
- ""
- ], // fallback (low/hi)
- },
- },
- "bluetooth": {
- "format": " {status}",
- "format-connected": " {device_alias} ({device_battery_percentage}%)",
- },
- "battery": {
- "states": {
- "good": 95,
- "warning": 30,
- "critical": 20,
- },
- "format": "{icon} {capacity}%",
- "format-charging": " {capacity}%",
- },
- "custom/alhp": {
- "exec": "$HOME/.config/waybar/scripts/alhp.sh",
- "return-type": "json",
- "interval": 60,
- "format": "{text}",
- "tooltip": true,
- },
- "custom/razer-mouse-battery": {
- "exec": "$HOME/.config/waybar/scripts/razer_basilisk_v3_pro_battery_info.sh",
- "return-type": "json",
- "interval": 10,
- "format": "{text}",
- "tooltip": true,
- },
- "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",
- },
- },
-}
+]
diff --git a/.config/waybar/config.jsonc##hostname.cn-mate b/.config/waybar/config.jsonc##hostname.cn-mate
deleted file mode 100644
index 99c6eca..0000000
--- a/.config/waybar/config.jsonc##hostname.cn-mate
+++ /dev/null
@@ -1,201 +0,0 @@
-{
- "layer": "bottom",
- "position": "bottom",
- "mod": "dock",
- "exclusive": true,
- "gtk-layer-shell": true,
- "passthrough": false,
- "height": 30,
- "modules-left": [
- "wlr/workspaces"
- ],
- "modules-center": [
- "mpris",
- "privacy"
- ],
- "modules-right": [
- "custom/alhp",
- "cpu",
- "memory",
- "disk",
- "bluetooth",
- "pulseaudio",
- "network",
- "battery",
- "tray",
- "clock"
- ],
- "wlr/workspaces": {
- "icon-size": 32,
- "spacing": 16,
- "on-scroll-up": "hyprctl dispatch workspace r+1",
- "on-scroll-down": "hyprctl dispatch workspace r-1"
- },
- "cpu": {
- "interval": 5,
- "format": " {usage}%",
- "max-length": 10
- },
- "disk": {
- "interval": 30,
- "format": " {percentage_used}%",
- "path": "/",
- "tooltip": true,
- "unit": "GB",
- "tooltip-format": "Available {free} of {total}"
- },
- "memory": {
- "interval": 10,
- "format": " {percentage}%",
- "max-length": 10,
- "tooltip": true,
- "tooltip-format": "RAM - {used:0.1f}GiB used"
- },
- "tray": {
- "icon-size": 18,
- "spacing": 3
- },
- "clock": {
- "format": "{:%R | %d.%m.%Y}",
- "tooltip-format": "{calendar}",
- "calendar": {
- "mode": "year",
- "mode-mon-col": 3,
- "weeks-pos": "right",
- "on-scroll": 1,
- "on-click-right": "mode",
- "format": {
- "months": "{}",
- "days": "{}",
- "weeks": "W{}",
- "weekdays": "{}",
- "today": "{}"
- }
- },
- "actions": {
- "on-click-right": "mode",
- "on-click-forward": "tz_up",
- "on-click-backward": "tz_down",
- "on-scroll-up": "shift_up",
- "on-scroll-down": "shift_down"
- }
- },
- "network": {
- "format-wifi": "{essid} ({signalStrength}%) {icon}",
- "format-ethernet": "{ifname}",
- "format-disconnected": "",
- "tooltip-format": "{ifname} via {gwaddr} ",
- "tooltip-format-wifi": "{essid} ({signalStrength}%) ",
- "tooltip-format-ethernet": "{ifname} ",
- "tooltip-format-disconnected": "Disconnected",
- "format-icons": [
- " ",
- " ",
- " ",
- " ",
- " "
- ]
- },
- "battery": {
- "states": {
- "good": 95,
- "warning": 30,
- "critical": 20
- },
- "format": "{icon} {capacity}%",
- "format-charging": " {capacity}%",
- "format-plugged": " {capacity}%",
- "format-alt": "{time} {icon}",
- "format-icons": [
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- ""
- ]
- },
- "pulseaudio": {
- "format": "{volume}% {icon} ",
- "format-bluetooth": "{volume}% {icon} ",
- "format-muted": " ",
- "format-icons": {
- "alsa_output.pci-0000_00_1f.3.analog-stereo": "",
- "alsa_output.pci-0000_00_1f.3.analog-stereo-muted": "",
- "headphone": "",
- "hands-free": "",
- "headset": "\uF025",
- "phone": "",
- "phone-muted": "",
- "portable": "",
- "car": "",
- "default": [
- "",
- ""
- ]
- },
- "scroll-step": 5,
- "on-click": "pwvucontrol",
- "ignored-sinks": [
- "Easy Effects Sink"
- ]
- },
- "privacy": {
- "icon-spacing": 4,
- "icon-size": 14,
- "transition-duration": 250,
- "modules": [
- {
- "type": "screenshare",
- "tooltip": true,
- "tooltip-icon-size": 12
- },
- {
- "type": "audio-out",
- "tooltip": true,
- "tooltip-icon-size": 12
- },
- {
- "type": "audio-in",
- "tooltip": true,
- "tooltip-icon-size": 12
- }
- ]
- },
- "mpris": {
- "format": "{player_icon} {dynamic}",
- "format-paused": "{status_icon} {dynamic}",
- "dynamic-len": 50,
- "ellipsis": "…",
- "player-icons": {
- "default": "▶",
- "mpv": "🎵"
- },
- "status-icons": {
- "paused": "⏸"
- }
- },
- "bluetooth": {
- "format": " {status}",
- "on-click": "overskride",
- "format-connected": " {device_alias}",
- "format-connected-battery": " {device_alias} {device_battery_percentage}%",
- "tooltip-format": "{controller_alias}\t{controller_address}\n\n{num_connections} connected",
- "tooltip-format-connected": "{controller_alias}\t{controller_address}\n\n{num_connections} connected\n\n{device_enumerate}",
- "tooltip-format-enumerate-connected": "{device_alias}\t{device_address}",
- "tooltip-format-enumerate-connected-battery": "{device_alias}\t{device_address}\t{device_battery_percentage}%"
- },
- "custom/alhp": {
- "id": "custom-alhp",
- "exec": "$HOME/.config/waybar/scripts/alhp.sh",
- "return-type": "json",
- "interval": 60,
- "tooltip": true,
- "format": "{text}",
- }
-}
diff --git a/.config/waybar/scripts/hyprsunset_daemon.sh b/.config/waybar/scripts/hyprsunset_daemon.sh
new file mode 100755
index 0000000..e16404f
--- /dev/null
+++ b/.config/waybar/scripts/hyprsunset_daemon.sh
@@ -0,0 +1,136 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+CONF="${XDG_CONFIG_HOME:-$HOME/.config}/hyprsunset/config"
+STATE_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/hyprsunset"
+LOG_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/hyprsunset"
+AUTO_FILE="$STATE_DIR/auto" # "1" = automation ON, "0" = OFF
+TEMP_FILE="$STATE_DIR/temp" # last manual/night temp persisted
+MODE_FILE="$STATE_DIR/mode" # "day" or "night"
+mkdir -p "$STATE_DIR" "$LOG_DIR"
+
+# Defaults
+LAT="52.5200"; LON="13.4050"
+TEMP_DAY=6500; TEMP_NIGHT=3800
+RAMP_DOWN_MIN=45; RAMP_UP_MIN=35
+STEP_K=100
+FALLBACK_SUNSET="20:30"; FALLBACK_SUNRISE="06:30"
+
+# Load config
+[ -r "$CONF" ] && source "$CONF"
+
+cmd() { hyprctl dispatch exec "$1" >/dev/null 2>&1 || true; }
+start_hyprsunset() {
+ local t="$1"
+ echo -n "$t" > "$TEMP_FILE"
+ cmd "hyprsunset -t $t"
+}
+stop_hyprsunset() {
+ cmd "hyprsunset -x"
+ pkill -x hyprsunset >/dev/null 2>&1 || true
+}
+
+# Compute ramp steps between a and b over minutes, step size STEP_K
+ramp_between() {
+ local from="$1" to="$2" minutes="$3"
+ local step="${STEP_K}"
+ local delta=$(( to - from ))
+ local sign=1
+ (( delta < 0 )) && sign=-1
+ local steps=$(( (delta*sign + step - 1) / step )) # ceil
+ [ "$steps" -lt 1 ] && steps=1
+ local sleep_s=$(( (minutes*60) / steps ))
+ local t="$from"
+ for ((i=1;i<=steps;i++)); do
+ t=$(( from + sign*i*step ))
+ # clamp
+ (( sign == 1 && t > to )) && t="$to"
+ (( sign == -1 && t < to )) && t="$to"
+ start_hyprsunset "$t"
+ sleep "$sleep_s"
+ done
+}
+
+now_hhmm() { date +%H:%M; }
+sec_until() {
+ # returns seconds until HH:MM tomorrow/ today
+ local target="$1"
+ local now_s=$(date +%s)
+ local tgt_s=$(date -d "$(date +%F) $target" +%s)
+ if (( tgt_s <= now_s )); then
+ tgt_s=$(( tgt_s + 86400 ))
+ fi
+ echo $(( tgt_s - now_s ))
+}
+
+have_sunwait() { command -v sunwait >/dev/null 2>&1; }
+
+# Initialize state defaults if missing
+[ -r "$AUTO_FILE" ] || echo -n "1" > "$AUTO_FILE" # default: automation ON
+[ -r "$TEMP_FILE" ] || echo -n "$TEMP_NIGHT" > "$TEMP_FILE"
+[ -r "$MODE_FILE" ] || echo -n "day" > "$MODE_FILE"
+
+log() { printf "[hyprsunset] %s\n" "$*" >&2; }
+
+while :; do
+ # If automation is OFF, just sleep and retry
+ if [ "$(cat "$AUTO_FILE" 2>/dev/null || echo 1)" != "1" ]; then
+ sleep 30
+ continue
+ fi
+
+ if have_sunwait; then
+ # Use sunwait to block until the next event
+ # Decide current solar state quickly
+ # sunwait 'day' exits 0 if sun is up; 'night' if down
+ if sunwait day "$LAT" "$LON" >/dev/null 2>&1; then
+ echo -n "day" > "$MODE_FILE"
+ # Wait for sunset, then ramp down
+ log "waiting for SUNSET via sunwait…"
+ sunwait set "$LAT" "$LON" >/dev/null 2>&1
+ [ "$(cat "$AUTO_FILE")" = "1" ] || continue
+ log "SUNSET reached → ramp down ${TEMP_DAY}→${TEMP_NIGHT} over ${RAMP_DOWN_MIN}m"
+ ramp_between "$TEMP_DAY" "$TEMP_NIGHT" "$RAMP_DOWN_MIN"
+ echo -n "night" > "$MODE_FILE"
+ # Stay in night until sunrise
+ log "waiting for SUNRISE via sunwait…"
+ sunwait rise "$LAT" "$LON" >/dev/null 2>&1
+ [ "$(cat "$AUTO_FILE")" = "1" ] || continue
+ log "SUNRISE reached → ramp up ${TEMP_NIGHT}→${TEMP_DAY} over ${RAMP_UP_MIN}m"
+ ramp_between "$TEMP_NIGHT" "$TEMP_DAY" "$RAMP_UP_MIN"
+ echo -n "day" > "$MODE_FILE"
+ else
+ echo -n "night" > "$MODE_FILE"
+ # We are in night → ramp to night if not already, then wait sunrise
+ log "night now → ensure at night temp, then wait SUNRISE"
+ start_hyprsunset "$TEMP_NIGHT"
+ sunwait rise "$LAT" "$LON" >/dev/null 2>&1
+ [ "$(cat "$AUTO_FILE")" = "1" ] || continue
+ log "SUNRISE → ramp up ${TEMP_NIGHT}→${TEMP_DAY} over ${RAMP_UP_MIN}m"
+ ramp_between "$TEMP_NIGHT" "$TEMP_DAY" "$RAMP_UP_MIN"
+ echo -n "day" > "$MODE_FILE"
+ fi
+ else
+ # Fallback fixed schedule
+ cur="$(now_hhmm)"
+ # If day now (before fallback sunset), wait sunset
+ if [[ "$cur" < "$FALLBACK_SUNSET" && "$cur" > "$FALLBACK_SUNRISE" ]]; then
+ echo -n "day" > "$MODE_FILE"
+ secs=$(sec_until "$FALLBACK_SUNSET")
+ log "fallback: waiting $secs s until sunset ${FALLBACK_SUNSET}"
+ sleep "$secs"
+ [ "$(cat "$AUTO_FILE")" = "1" ] || continue
+ ramp_between "$TEMP_DAY" "$TEMP_NIGHT" "$RAMP_DOWN_MIN"
+ echo -n "night" > "$MODE_FILE"
+ else
+ echo -n "night" > "$MODE_FILE"
+ secs=$(sec_until "$FALLBACK_SUNRISE")
+ log "fallback: waiting $secs s until sunrise ${FALLBACK_SUNRISE}"
+ sleep "$secs"
+ [ "$(cat "$AUTO_FILE")" = "1" ] || continue
+ ramp_between "$TEMP_NIGHT" "$TEMP_DAY" "$RAMP_UP_MIN"
+ echo -n "day" > "$MODE_FILE"
+ fi
+ fi
+done
+
diff --git a/.config/waybar/scripts/hyprsunset_toggle.sh b/.config/waybar/scripts/hyprsunset_toggle.sh
new file mode 100755
index 0000000..deca346
--- /dev/null
+++ b/.config/waybar/scripts/hyprsunset_toggle.sh
@@ -0,0 +1,89 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+CONF="${XDG_CONFIG_HOME:-$HOME/.config}/hyprsunset/config"
+STATE_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/hyprsunset"
+AUTO_FILE="$STATE_DIR/auto" # "1"=auto on, "0"=auto off
+TEMP_FILE="$STATE_DIR/temp" # last set temp (manual/night)
+MODE_FILE="$STATE_DIR/mode" # "day"/"night" (best effort)
+mkdir -p "$STATE_DIR"
+
+# Defaults (overridden by CONF)
+DEFAULT_TEMP=5500
+TEMP_DAY=6500
+TEMP_NIGHT=2500
+[ -r "$CONF" ] && source "$CONF"
+[ -r "$TEMP_FILE" ] || echo -n "${TEMP_NIGHT:-$DEFAULT_TEMP}" > "$TEMP_FILE"
+[ -r "$AUTO_FILE" ] || echo -n "1" > "$AUTO_FILE"
+[ -r "$MODE_FILE" ] || echo -n "day" > "$MODE_FILE"
+
+is_running() { pgrep -x hyprsunset >/dev/null 2>&1; }
+cur_temp() {
+ if is_running; then
+ pid="$(pgrep -x hyprsunset | head -n1 || true)"
+ if [ -n "${pid:-}" ] && [ -r "/proc/$pid/cmdline" ]; then
+ t="$(tr '\0' ' ' < "/proc/$pid/cmdline" | sed -n 's/.*-t \([0-9]\+\).*/\1/p')"
+ [ -n "$t" ] && { echo "$t"; return; }
+ fi
+ fi
+ cat "$TEMP_FILE"
+}
+set_temp() {
+ local t="$1"
+ echo -n "$t" > "$TEMP_FILE"
+ hyprctl dispatch exec "hyprsunset -t $t" >/dev/null 2>&1 || true
+}
+disable() {
+ hyprctl dispatch exec "hyprsunset -x" >/dev/null 2>&1 || true
+ pkill -x hyprsunset >/dev/null 2>&1 || true
+}
+print_json() {
+ local auto="$(cat "$AUTO_FILE")"
+ local t="$(cur_temp)"
+ local mode="$(cat "$MODE_FILE" 2>/dev/null || echo "day")"
+ if [ "$auto" = "1" ]; then
+ printf '{"text":" %sK","class":"auto %s","tooltip":"Hyprsunset Auto (%s) — %sK\\nLeft-click: Toggle auto OFF\\nRight-click: Toggle manual on/off\\nScroll: +/- 200K (manual)"}\n' "$t" "$mode" "$mode" "$t"
+ else
+ if is_running; then
+ printf '{"text":" %sK","class":"manual on","tooltip":"Hyprsunset Manual ON — %sK\\nLeft-click: Toggle auto ON\\nRight-click: Turn OFF\\nScroll: +/- 200K"}\n' "$t" "$t"
+ else
+ local last="$(cat "$TEMP_FILE")"
+ printf '{"text":" Off","class":"manual off","tooltip":"Hyprsunset Manual OFF — last %sK\\nLeft-click: Toggle auto ON\\nRight-click: Turn ON (%sK)\\nScroll: +/- 200K"}\n' "$last" "$last"
+ fi
+ fi
+}
+
+case "${1:---print}" in
+ --print) print_json ;;
+ --auto-on) echo -n "1" > "$AUTO_FILE" ; print_json ;;
+ --auto-off) echo -n "0" > "$AUTO_FILE" ; print_json ;;
+ --toggle-auto)
+ if [ "$(cat "$AUTO_FILE")" = "1" ]; then
+ # Turning auto OFF → restore last manual temp and keep running
+ echo -n "0" > "$AUTO_FILE"
+ set_temp "$(cat "$TEMP_FILE")"
+ else
+ # Turning auto ON → let daemon steer; ensure hyprsunset is running at current temp (keeps smoothness)
+ echo -n "1" > "$AUTO_FILE"
+ set_temp "$(cur_temp)"
+ fi
+ print_json
+ ;;
+ --toggle)
+ # Manual on/off (does not change auto flag)
+ if is_running; then
+ disable
+ else
+ set_temp "$(cat "$TEMP_FILE")"
+ fi
+ print_json
+ ;;
+ --set)
+ t="${2:-$DEFAULT_TEMP}"
+ echo -n "$t" > "$TEMP_FILE"
+ set_temp "$t"
+ print_json
+ ;;
+ *) echo "Usage: $0 [--print|--toggle-auto|--auto-on|--auto-off|--toggle|--set TEMP]" >&2; exit 1 ;;
+esac
+
diff --git a/.config/waybar/style.css##hostname.cn-arch b/.config/waybar/style.css##hostname.cn-arch
index 8039625..a2e161e 100644
--- a/.config/waybar/style.css##hostname.cn-arch
+++ b/.config/waybar/style.css##hostname.cn-arch
@@ -1,11 +1,15 @@
+/* =========================
+ 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 #CAD3E8;
-@define-color content_inactive rgba(202, 211, 232, 0.4);
+@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 */
@@ -17,15 +21,26 @@
border-radius: 0;
margin: 0;
padding: 0;
+ color: @content_main;
}
/* Bar Background */
window#waybar {
background: @bg_main;
- color: @content_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;
@@ -43,43 +58,124 @@ tooltip {
background: @bg_hover;
}
-/* Separator Border */
+/* 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-razer-mouse-battery,
+#custom-hyprsunset {
+ /* ← new module gets a separator too */
border-right: 1px solid @border_main;
}
-/* Workspaces Buttons */
+/* 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;
-}
-#workspaces button.focused {
- background: @bg_hover;
- color: @content_main;
+ font-weight: 600;
}
#workspaces button.urgent {
background: rgba(255, 204, 51, 0.35);
color: @warning_color;
}
-/* Tray & Clock Padding */
+/* 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;
+}
-/* Critical Battery 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;
+}
diff --git a/.config/waybar/style.css##hostname.cn-mate b/.config/waybar/style.css##hostname.cn-mate
deleted file mode 100644
index bee802b..0000000
--- a/.config/waybar/style.css##hostname.cn-mate
+++ /dev/null
@@ -1,208 +0,0 @@
-
-/*base background color*/
-@define-color bg_main rgba(25, 25, 25, 0.65);
-@define-color bg_main_tooltip rgba(0, 0, 0, 0.7);
-
-
-/*base background color of selections */
-@define-color bg_hover rgba(200, 200, 200, 0.3);
-/*base background color of active elements */
-@define-color bg_active rgba(100, 100, 100, 0.5);
-
-/*base border color*/
-@define-color border_main rgba(255, 255, 255, 0.2);
-
-/*text color for entries, views and content in general */
-@define-color content_main white;
-/*text color for entries that are unselected */
-@define-color content_inactive rgba(255, 255, 255, 0.25);
-
-* {
- text-shadow: none;
- box-shadow: none;
- border: none;
- border-radius: 0;
- font-family: "Inconsolata Go Nerd Font";
- font-size: 14px;
-}
-
-window#waybar {
- background: @bg_main;
- border-top: 1px solid @border_main;
- color: @content_main;
-}
-
-tooltip {
- font-size: 14px;
- background: @bg_main_tooltip;
- border-radius: 5px;
- border-width: 1px;
- border-style: solid;
- border-color: @border_main;
-}
-tooltip label{
- color: @content_main;
-}
-
-.module {
- margin-left: 2px;
- margin-right: 2px;
-}
-
-#workspaces {
- color: transparent;
- margin-right: 1.5px;
- margin-left: 1.5px;
-}
-#workspaces button {
- padding: 3px;
- color: @content_inactive;
-}
-#workspaces button.active {
- color: whitesmoke;
- background: @bg_active;
-}
-#workspaces button.focused {
- color: @bg_active;
-}
-#workspaces button.urgent {
- background: rgba(255, 200, 0, 0.35);
- color: @warning_color;
-}
-#workspaces button:hover {
- background: @bg_hover;
- color: @content_main;
-}
-
-#cpu, #disk, #memory {
- border-bottom: 1px solid grey;
- padding-right: 5px;
- padding-left: 5px;
-}
-
-#tray{
- padding-left: 5px;
- padding-right: 5px;
-}
-#tray > .passive {
- border-bottom: none;
-}
-#tray > .active {
-
-}
-#tray > .needs-attention {
- border-bottom: 3px solid @warning_color;
-}
-#tray > widget {
- transition: all 0.25s cubic-bezier(0.165, 0.84, 0.44, 1);
-}
-#tray > widget:hover {
- background: @bg_hover;
-}
-
-#pulseaudio {
- border-bottom: 1px solid grey;
- padding-right: 5px;
- padding-left: 5px;
- transition: all 0.25s cubic-bezier(0.165, 0.84, 0.44, 1);
-}
-#pulseaudio:hover {
- background: @bg_hover;
-}
-
-#network {
- border-bottom: 1px solid grey;
- padding-right: 5px;
- padding-left: 5px;
-}
-
-#clock {
- padding-right: 5px;
- padding-left: 5px;
- transition: all 0.25s cubic-bezier(0.165, 0.84, 0.44, 1);
-}
-#clock:hover {
- background: @bg_hover;
-}
-
-#privacy {
-}
-#privacy-item {
- padding-left: 5px;
- padding-right: 5px;
-}
-#privacy-item.screenshare {
- background: #850404;
-}
-#privacy-item.audio-in {
- background: #6c045e;
-}
-#privacy-item.audio-out {
- background: #02605b;
-}
-
-#mpris {
- padding-left: 5px;
- padding-right: 5px;
-}
-#mpris.playing {
-}
-#mpris.paused {
-}
-#mpris.stopped {
-}
-#mpris.firefox {
- border-bottom: 1px solid #fd8728;
-}
-#mpris.spotify {
- border-bottom: 1px solid #17d860;
-}
-#mpris.mpv {
- border-bottom: 1px solid #420042;
-}
-#mpris.chromium {
- border-bottom: 1px solid #1a73e8;
-}
-
-#bluetooth {
- padding-right: 5px;
- padding-left: 5px;
-}
-#bluetooth.disabled {
- border-bottom: 1px solid grey;
-}
-#bluetooth.off {
- border-bottom: 1px solid grey;
-}
-#bluetooth.on {
- border-bottom: 1px solid #0059fd;
-}
-#bluetooth.connected {
- border-bottom: 1px solid #00b7fa;
-}
-#bluetooth.discoverable {
-}
-#bluetooth.discovering {
-}
-#bluetooth.pairable {
-}
-#bluetooth.no-controller {
- background: darkred;
-}
-
-#custom-alhp {
- padding-left: 5px;
- padding-right: 5px;
-}
-#custom-alhp.good {
- border-bottom: 1px solid #adff2f;
-}
-#custom-alhp.stale {
- border-bottom: 1px solid #f6ac00;
-}
-#custom-alhp.bad {
- border-bottom: 1px solid #ff4500;
-}
-#custom-alhp.down {
- border-bottom: 1px solid #800000;
-}