aboutsummaryrefslogtreecommitdiff
path: root/dotfiles
diff options
context:
space:
mode:
Diffstat (limited to 'dotfiles')
-rw-r--r--dotfiles/hyprland/.config/waybar/config8
-rw-r--r--dotfiles/hyprland/.config/waybar/style.css6
-rwxr-xr-xdotfiles/hyprland/.local/bin/airplane-mode110
-rwxr-xr-xdotfiles/hyprland/.local/bin/waybar-airplane33
4 files changed, 157 insertions, 0 deletions
diff --git a/dotfiles/hyprland/.config/waybar/config b/dotfiles/hyprland/.config/waybar/config
index 2ae43fe..97fb3b7 100644
--- a/dotfiles/hyprland/.config/waybar/config
+++ b/dotfiles/hyprland/.config/waybar/config
@@ -18,6 +18,7 @@
"custom/netspeed",
"pulseaudio",
"custom/touchpad",
+ "custom/airplane",
"idle_inhibitor",
"custom/pocketbook",
"tray",
@@ -149,6 +150,13 @@
"on-click": "toggle-touchpad"
},
+ "custom/airplane": {
+ "exec": "waybar-airplane",
+ "return-type": "json",
+ "signal": 10,
+ "on-click": "airplane-mode"
+ },
+
"idle_inhibitor": {
"format": "<span size='large'>{icon}</span>",
"format-icons": {
diff --git a/dotfiles/hyprland/.config/waybar/style.css b/dotfiles/hyprland/.config/waybar/style.css
index 3a849c5..cd158d0 100644
--- a/dotfiles/hyprland/.config/waybar/style.css
+++ b/dotfiles/hyprland/.config/waybar/style.css
@@ -77,6 +77,7 @@ window#waybar {
#custom-worldclock,
#custom-layout,
#custom-touchpad,
+#custom-airplane,
#window {
padding: 0.45rem;
margin: 0.3rem;
@@ -98,6 +99,7 @@ window#waybar {
#pulseaudio:hover,
#sysmonitor:hover,
#custom-touchpad:hover,
+#custom-airplane:hover,
#custom-layout:hover {
background-color: #474544;
border-radius: 1rem;
@@ -112,6 +114,10 @@ window#waybar {
color: #d47c59;
}
+#custom-airplane.active {
+ color: #d7af5f;
+}
+
#temperature.warning {
color: #d7af5f;
}
diff --git a/dotfiles/hyprland/.local/bin/airplane-mode b/dotfiles/hyprland/.local/bin/airplane-mode
new file mode 100755
index 0000000..4f5ed9c
--- /dev/null
+++ b/dotfiles/hyprland/.local/bin/airplane-mode
@@ -0,0 +1,110 @@
+#!/bin/sh
+# airplane-mode — toggle a low-power "airplane" state for a laptop.
+#
+# Engage: record the current state of each lever, then apply low-power values:
+# - wifi off (nmcli; bluetooth is left alone, on purpose — earbuds)
+# - CPU energy-performance preference -> power (intel_pstate, via sysfs)
+# - display brightness dimmed
+# - stop network-only services (VPNs, sync, discovery, inbound SSH)
+# Disengage: read the recorded state and restore exactly what was there. A
+# lever already in its low-power position before engaging (e.g. wifi already
+# off, a service already stopped) is left untouched on disengage.
+#
+# State lives at $XDG_RUNTIME_DIR/airplane-state as key=value lines. The
+# waybar-airplane indicator reads `mode` from it.
+#
+# Env knobs (defaults are the real system; tests override them):
+# AIRPLANE_EPP_GLOB glob of EPP sysfs files
+# AIRPLANE_BRIGHTNESS_LOW brightnessctl target while engaged
+# AIRPLANE_SYSTEM_SERVICES system units to stop (sudo)
+# AIRPLANE_USER_SERVICES --user units to stop
+
+STATE_FILE="${XDG_RUNTIME_DIR:-/tmp}/airplane-state"
+SUDO="${AIRPLANE_SUDO:-sudo}"
+EPP_GLOB="${AIRPLANE_EPP_GLOB:-/sys/devices/system/cpu/cpu*/cpufreq/energy_performance_preference}"
+BRIGHTNESS_LOW="${AIRPLANE_BRIGHTNESS_LOW:-35%}"
+SYSTEM_SERVICES="${AIRPLANE_SYSTEM_SERVICES:-tailscaled.service proton.VPN.service avahi-daemon.service cups.service wsdd.service geoclue.service sshd.service fail2ban.service}"
+USER_SERVICES="${AIRPLANE_USER_SERVICES:-syncthing.service}"
+
+read_key() { sed -n "s/^$1=//p" "$STATE_FILE" 2>/dev/null | head -n1; }
+
+set_epp() {
+ # Write $1 to every EPP file. Needs root; glob expands inside the subshell.
+ $SUDO sh -c "for f in $EPP_GLOB; do [ -e \"\$f\" ] && echo $1 > \"\$f\"; done" 2>/dev/null
+}
+
+first_epp() {
+ for f in $EPP_GLOB; do
+ [ -e "$f" ] && { cat "$f"; return; }
+ done
+}
+
+engage() {
+ # --- record current state ---
+ wifi_was=$(nmcli radio wifi 2>/dev/null)
+ epp_was=$(first_epp)
+ bright_was=$(brightnessctl get 2>/dev/null)
+
+ stopped_system=""
+ for s in $SYSTEM_SERVICES; do
+ if systemctl is-active --quiet "$s" 2>/dev/null; then
+ $SUDO systemctl stop "$s" 2>/dev/null && stopped_system="$stopped_system $s"
+ fi
+ done
+ stopped_user=""
+ for s in $USER_SERVICES; do
+ if systemctl --user is-active --quiet "$s" 2>/dev/null; then
+ systemctl --user stop "$s" 2>/dev/null && stopped_user="$stopped_user $s"
+ fi
+ done
+
+ # --- apply low-power settings ---
+ nmcli radio wifi off 2>/dev/null
+ set_epp power
+ brightnessctl set "$BRIGHTNESS_LOW" >/dev/null 2>&1
+
+ # --- persist what we recorded ---
+ {
+ echo "mode=on"
+ echo "wifi=$wifi_was"
+ echo "epp=$epp_was"
+ echo "brightness=$bright_was"
+ echo "stopped_system=$stopped_system"
+ echo "stopped_user=$stopped_user"
+ } > "$STATE_FILE"
+
+ notify info "Airplane mode" "ON — wifi off, low power" 2>/dev/null
+}
+
+disengage() {
+ wifi_was=$(read_key wifi)
+ epp_was=$(read_key epp)
+ bright_was=$(read_key brightness)
+ stopped_system=$(read_key stopped_system)
+ stopped_user=$(read_key stopped_user)
+
+ # Only restore a lever that was NOT already in its low-power state.
+ [ "$wifi_was" = "enabled" ] && nmcli radio wifi on 2>/dev/null
+ [ -n "$epp_was" ] && set_epp "$epp_was"
+ [ -n "$bright_was" ] && brightnessctl set "$bright_was" >/dev/null 2>&1
+
+ for s in $stopped_system; do
+ $SUDO systemctl start "$s" 2>/dev/null
+ done
+ for s in $stopped_user; do
+ systemctl --user start "$s" 2>/dev/null
+ done
+
+ echo "mode=off" > "$STATE_FILE"
+ notify info "Airplane mode" "OFF — settings restored" 2>/dev/null
+}
+
+case "$(read_key mode)" in
+ on) disengage ;;
+ *) engage ;;
+esac
+
+# Refresh the waybar indicator immediately (custom/airplane listens on signal 10).
+pkill -RTMIN+10 waybar 2>/dev/null
+
+exit 0
diff --git a/dotfiles/hyprland/.local/bin/waybar-airplane b/dotfiles/hyprland/.local/bin/waybar-airplane
new file mode 100755
index 0000000..21f869c
--- /dev/null
+++ b/dotfiles/hyprland/.local/bin/waybar-airplane
@@ -0,0 +1,33 @@
+#!/bin/sh
+# Airplane-mode indicator for waybar.
+# Reads the state file the airplane-mode toggle maintains; emits one JSON line
+# (text + tooltip + class) for the custom/airplane module. The file holds
+# key=value lines; only `mode` (on/off) matters here. Anything other than
+# "on" reads as off, so a missing or garbled state file fails safe (airplane
+# mode shown as inactive — i.e. radios assumed on).
+#
+# Laptop-only: airplane mode is meaningless on a desktop, so the module hides
+# itself (emits nothing → waybar drops it) on machines with no battery.
+
+STATE_FILE="${XDG_RUNTIME_DIR:-/tmp}/airplane-state"
+PS_DIR="${AIRPLANE_POWER_SUPPLY_DIR:-/sys/class/power_supply}"
+
+# Laptop check: a battery present means this is a portable machine.
+is_laptop() {
+ for b in "$PS_DIR"/BAT*; do
+ [ -e "$b" ] && return 0
+ done
+ return 1
+}
+
+is_laptop || exit 0
+
+mode=$(sed -n 's/^mode=//p' "$STATE_FILE" 2>/dev/null | head -n1)
+
+# Same clear plane glyph in both states; the class drives the color (gold when
+# engaged, default gray when not) so there's no slash to obscure the wings.
+if [ "$mode" = "on" ]; then
+ echo "{\"text\": \"<span size='large'></span>\", \"tooltip\": \"Airplane mode ON — wifi off, low power\", \"class\": \"active\"}"
+else
+ echo "{\"text\": \"<span size='large'></span>\", \"tooltip\": \"Airplane mode OFF\", \"class\": \"inactive\"}"
+fi