summaryrefslogtreecommitdiff
path: root/dotfiles/hyprland/.local/bin
diff options
context:
space:
mode:
Diffstat (limited to 'dotfiles/hyprland/.local/bin')
-rwxr-xr-xdotfiles/hyprland/.local/bin/cycle-layout29
-rwxr-xr-xdotfiles/hyprland/.local/bin/layout-navigate59
-rwxr-xr-xdotfiles/hyprland/.local/bin/pinentry-fuzzel107
-rwxr-xr-xdotfiles/hyprland/.local/bin/set-theme124
-rwxr-xr-xdotfiles/hyprland/.local/bin/toggle-scratchpad29
-rwxr-xr-xdotfiles/hyprland/.local/bin/waybar-layout36
-rwxr-xr-xdotfiles/hyprland/.local/bin/waybar-netspeed67
7 files changed, 451 insertions, 0 deletions
diff --git a/dotfiles/hyprland/.local/bin/cycle-layout b/dotfiles/hyprland/.local/bin/cycle-layout
new file mode 100755
index 0000000..ebfd2e0
--- /dev/null
+++ b/dotfiles/hyprland/.local/bin/cycle-layout
@@ -0,0 +1,29 @@
+#!/bin/sh
+# Cycle through Hyprland layouts
+# Cycle: master -> hy3 (tab/monocle) -> scrolling -> floating -> master
+
+LAYOUT=$(hyprctl getoption general:layout -j | jq -r '.str')
+FLOATING=$(hyprctl activewindow -j 2>/dev/null | jq -r '.floating // false')
+
+# Check if we're in "all floating" mode by checking layout
+case "$LAYOUT" in
+ master)
+ hyprctl keyword general:layout hy3
+ # Create tab group for monocle behavior
+ hyprctl dispatch hy3:changegroup tab
+ ;;
+ hy3)
+ hyprctl keyword general:layout scrolling
+ ;;
+ scrolling)
+ # Switch to master but float all windows
+ hyprctl keyword general:layout master
+ hyprctl dispatch workspaceopt allfloat
+ ;;
+ *)
+ # Return to master tiled
+ hyprctl dispatch workspaceopt allfloat
+ hyprctl keyword general:layout master
+ hyprctl keyword master:orientation left
+ ;;
+esac
diff --git a/dotfiles/hyprland/.local/bin/layout-navigate b/dotfiles/hyprland/.local/bin/layout-navigate
new file mode 100755
index 0000000..4fc02c2
--- /dev/null
+++ b/dotfiles/hyprland/.local/bin/layout-navigate
@@ -0,0 +1,59 @@
+#!/bin/sh
+# Layout-aware navigation for Hyprland
+# Usage: layout-navigate <direction> [move]
+# direction: next|prev
+# move: if present, move window instead of focus
+
+DIR="$1"
+MOVE="$2"
+LAYOUT=$(hyprctl getoption general:layout -j | jq -r '.str')
+
+case "$LAYOUT" in
+ scrolling)
+ # Swap directions: J (next) goes left, K (prev) goes right
+ if [ "$MOVE" = "move" ]; then
+ if [ "$DIR" = "next" ]; then
+ hyprctl dispatch layoutmsg movewindowto l
+ else
+ hyprctl dispatch layoutmsg movewindowto r
+ fi
+ else
+ if [ "$DIR" = "next" ]; then
+ hyprctl dispatch layoutmsg focus l
+ else
+ hyprctl dispatch layoutmsg focus r
+ fi
+ fi
+ ;;
+ hy3)
+ if [ "$MOVE" = "move" ]; then
+ if [ "$DIR" = "next" ]; then
+ hyprctl dispatch hy3:movewindow r
+ else
+ hyprctl dispatch hy3:movewindow l
+ fi
+ else
+ if [ "$DIR" = "next" ]; then
+ hyprctl dispatch hy3:movefocus r
+ else
+ hyprctl dispatch hy3:movefocus l
+ fi
+ fi
+ ;;
+ *)
+ # master, dwindle, etc.
+ if [ "$MOVE" = "move" ]; then
+ if [ "$DIR" = "next" ]; then
+ hyprctl dispatch layoutmsg swapnext
+ else
+ hyprctl dispatch layoutmsg swapprev
+ fi
+ else
+ if [ "$DIR" = "next" ]; then
+ hyprctl dispatch layoutmsg cyclenext
+ else
+ hyprctl dispatch layoutmsg cycleprev
+ fi
+ fi
+ ;;
+esac
diff --git a/dotfiles/hyprland/.local/bin/pinentry-fuzzel b/dotfiles/hyprland/.local/bin/pinentry-fuzzel
new file mode 100755
index 0000000..4cbe6b7
--- /dev/null
+++ b/dotfiles/hyprland/.local/bin/pinentry-fuzzel
@@ -0,0 +1,107 @@
+#!/bin/sh
+
+ENABLE_LOGGING="TRUE"
+logger() {
+ if [ "$ENABLE_LOGGING" == "TRUE" ]; then
+ /usr/bin/logger -t "${0} [$]" "$@";
+ fi
+}
+
+# Decode URL-encoded characters (%0A = newline, %20 = space, etc.)
+decode() {
+ printf '%b' "$(echo "$1" | sed 's/%\([0-9A-Fa-f][0-9A-Fa-f]\)/\\x\1/g')"
+}
+
+# Base command and misc variables
+DESC=""
+PROMPT=""
+COUNTFILE="/tmp/pinentry-fuzzel-count-$$"
+
+# Check if this is a repeat prompt (within 5 seconds of last)
+LASTFILE="/tmp/pinentry-fuzzel-last"
+NOW=$(date +%s)
+if [ -f "$LASTFILE" ]; then
+ LAST=$(cat "$LASTFILE")
+ if [ $((NOW - LAST)) -lt 5 ]; then
+ REPEAT=1
+ else
+ REPEAT=0
+ fi
+else
+ REPEAT=0
+fi
+echo "$NOW" > "$LASTFILE"
+
+echo "OK Please go ahead"
+while read cmd rest; do
+ logger "RAW=< ${cmd} ${rest} >"
+ logger "cmd=<${cmd}> rest=<${rest}>"
+
+ case $cmd in
+ GETINFO)
+ case "$rest" in
+ flavor)
+ echo "D fuzzel"
+ echo "OK"
+ ;;
+ version)
+ echo "D 0.1"
+ echo "OK"
+ ;;
+ ttyinfo)
+ echo "D - - -"
+ echo "OK"
+ ;;
+ pid)
+ echo "D $$"
+ echo "OK"
+ ;;
+ esac
+ ;;
+
+ SETDESC)
+ DESC=$(decode "$rest")
+ echo "OK"
+ ;;
+
+ SETERROR)
+ logger "ERROR $rest"
+ # Silently acknowledge errors (e.g., empty passphrase on escape)
+ echo "OK"
+ ;;
+
+ SETPROMPT)
+ PROMPT=$(decode "$rest")
+ # Remove trailing colon if present (we add our own)
+ PROMPT="${PROMPT%:}"
+ echo "OK"
+ ;;
+
+ GETPIN | getpin)
+ if [ "$REPEAT" -eq 0 ]; then
+ LABEL="password: "
+ else
+ LABEL="reenter: "
+ fi
+ PASS=$(fuzzel --prompt "$LABEL" --width 25 --lines 0 --cache /dev/null --password --dmenu)
+ if [ -z "$PASS" ]; then
+ # User cancelled - return error to GPG
+ rm -f "$LASTFILE"
+ echo "ERR 83886179 Operation cancelled"
+ else
+ echo "D $PASS"
+ echo "OK"
+ fi
+ ;;
+
+ BYE|bye)
+ echo "OK closing connection"
+ logger "EXITING"
+ exit 0
+ ;;
+
+ *)
+ echo "OK"
+ ;;
+ esac
+done
diff --git a/dotfiles/hyprland/.local/bin/set-theme b/dotfiles/hyprland/.local/bin/set-theme
new file mode 100755
index 0000000..338aab9
--- /dev/null
+++ b/dotfiles/hyprland/.local/bin/set-theme
@@ -0,0 +1,124 @@
+#!/bin/sh
+# Theme switcher for Hyprland desktop
+# Usage: set-theme <theme-name>
+# set-theme --toggle
+# set-theme --current
+# Available themes: dupre, hudson
+
+THEME_DIR="$HOME/.config/themes"
+CURRENT_FILE="$HOME/.config/current-theme"
+
+# Get current theme
+get_current() {
+ if [ -f "$CURRENT_FILE" ]; then
+ cat "$CURRENT_FILE"
+ else
+ echo "hudson" # default
+ fi
+}
+
+# List available themes
+list_themes() {
+ for dir in "$THEME_DIR"/*/; do
+ basename "$dir"
+ done
+}
+
+# Apply a theme
+apply_theme() {
+ theme="$1"
+
+ if [ ! -d "$THEME_DIR/$theme" ]; then
+ echo "Error: Theme '$theme' not found in $THEME_DIR"
+ echo "Available themes: $(list_themes | tr '\n' ' ')"
+ exit 1
+ fi
+
+ echo "Applying theme: $theme"
+
+ # Copy configs that don't support sourcing
+ cp "$THEME_DIR/$theme/foot.ini" "$HOME/.config/foot/foot.ini"
+ cp "$THEME_DIR/$theme/fuzzel.ini" "$HOME/.config/fuzzel/fuzzel.ini"
+ cp "$THEME_DIR/$theme/waybar.css" "$HOME/.config/waybar/style.css"
+ cp "$THEME_DIR/$theme/dunstrc" "$HOME/.config/dunst/dunstrc"
+ cp "$THEME_DIR/$theme/hyprlock.conf" "$HOME/.config/hypr/hyprlock.conf"
+ cp "$THEME_DIR/$theme/Xresources" "$HOME/.Xresources"
+
+ # Apply Xresources (for X11 apps and Emacs)
+ xrdb -merge "$HOME/.Xresources" 2>/dev/null
+
+ # Apply Hyprland colors directly via hyprctl
+ case "$theme" in
+ dupre)
+ hyprctl keyword general:col.active_border "rgba(d7af5fff)"
+ hyprctl keyword general:col.inactive_border "rgba(474544ff)"
+ ;;
+ hudson)
+ hyprctl keyword general:col.active_border "rgba(daa520ff)"
+ hyprctl keyword general:col.inactive_border "rgba(444444ff)"
+ ;;
+ esac
+
+ # Save current theme
+ echo "$theme" > "$CURRENT_FILE"
+
+ # Reload applications
+ killall -SIGUSR2 waybar 2>/dev/null
+ pkill dunst && dunst &
+
+ # Notify user
+ notify-send "Theme" "Switched to $theme" -t 2000
+
+ echo "Theme '$theme' applied. Open new terminals to see changes."
+}
+
+# Toggle between themes
+toggle_theme() {
+ current=$(get_current)
+ case "$current" in
+ dupre) apply_theme "hudson" ;;
+ hudson) apply_theme "dupre" ;;
+ *) apply_theme "dupre" ;;
+ esac
+}
+
+# Show picker with fuzzel
+pick_theme() {
+ themes=$(list_themes)
+ current=$(get_current)
+ selected=$(echo "$themes" | fuzzel --dmenu --prompt "Theme (current: $current): ")
+ if [ -n "$selected" ]; then
+ apply_theme "$selected"
+ fi
+}
+
+# Main
+case "$1" in
+ --toggle|-t)
+ toggle_theme
+ ;;
+ --current|-c)
+ get_current
+ ;;
+ --list|-l)
+ list_themes
+ ;;
+ --pick|-p)
+ pick_theme
+ ;;
+ --help|-h)
+ echo "Usage: set-theme <theme-name>"
+ echo " set-theme --toggle Toggle between themes"
+ echo " set-theme --current Show current theme"
+ echo " set-theme --list List available themes"
+ echo " set-theme --pick Pick theme with fuzzel"
+ echo ""
+ echo "Available themes: $(list_themes | tr '\n' ' ')"
+ ;;
+ "")
+ pick_theme
+ ;;
+ *)
+ apply_theme "$1"
+ ;;
+esac
diff --git a/dotfiles/hyprland/.local/bin/toggle-scratchpad b/dotfiles/hyprland/.local/bin/toggle-scratchpad
new file mode 100755
index 0000000..bb10ef7
--- /dev/null
+++ b/dotfiles/hyprland/.local/bin/toggle-scratchpad
@@ -0,0 +1,29 @@
+#!/bin/sh
+# Toggle a special workspace from waybar click
+# Tracks state to handle focus-loss auto-close issue
+# Usage: toggle-scratchpad <name>
+
+NAME="$1"
+if [ -z "$NAME" ]; then
+ echo "Usage: toggle-scratchpad <name>"
+ exit 1
+fi
+
+STATEFILE="/tmp/scratchpad-$NAME-open"
+NOW=$(date +%s)
+
+# If state file exists and recent, scratchpad was open and just closed by focus loss
+# Don't reopen it - user intended to close
+if [ -f "$STATEFILE" ]; then
+ LAST=$(cat "$STATEFILE")
+ AGE=$((NOW - LAST))
+ rm -f "$STATEFILE"
+ if [ "$AGE" -lt 2 ]; then
+ # Was just open, user clicked to close - don't reopen
+ exit 0
+ fi
+fi
+
+# Opening the scratchpad - mark timestamp
+echo "$NOW" > "$STATEFILE"
+hyprctl dispatch togglespecialworkspace "$NAME"
diff --git a/dotfiles/hyprland/.local/bin/waybar-layout b/dotfiles/hyprland/.local/bin/waybar-layout
new file mode 100755
index 0000000..6c45877
--- /dev/null
+++ b/dotfiles/hyprland/.local/bin/waybar-layout
@@ -0,0 +1,36 @@
+#!/bin/sh
+# Hyprland layout indicator for waybar
+# Shows current layout with nerd font icons
+# Layouts: master -> tab group (monocle) -> scrolling -> floating
+
+# Get current layout
+LAYOUT=$(hyprctl getoption general:layout -j | jq -r '.str')
+
+# Check if workspace has allfloat enabled
+ALLFLOAT=$(hyprctl activeworkspace -j | jq -r '.hasfullscreenwindow')
+
+# Check if active window is floating
+FLOATING=$(hyprctl activewindow -j 2>/dev/null | jq -r '.floating // false')
+
+# Check workspace rules for allfloat
+WSRULES=$(hyprctl activeworkspace -j | jq -r '.rules // []')
+
+# Determine icon and tooltip
+if [ "$LAYOUT" = "master" ] && echo "$WSRULES" | grep -q "allfloat"; then
+ ICON="󰖲"
+ TOOLTIP="Floating"
+elif [ "$LAYOUT" = "scrolling" ]; then
+ ICON="󰯍"
+ TOOLTIP="Scrolling"
+elif [ "$LAYOUT" = "hy3" ]; then
+ ICON="󰖯"
+ TOOLTIP="Tab Group (Monocle)"
+elif [ "$LAYOUT" = "master" ]; then
+ ICON="󰕰"
+ TOOLTIP="Master"
+else
+ ICON="󰕰"
+ TOOLTIP="$LAYOUT"
+fi
+
+echo "{\"text\": \"<span size='large'>$ICON</span>\", \"tooltip\": \"$TOOLTIP\"}"
diff --git a/dotfiles/hyprland/.local/bin/waybar-netspeed b/dotfiles/hyprland/.local/bin/waybar-netspeed
new file mode 100755
index 0000000..97e8e5e
--- /dev/null
+++ b/dotfiles/hyprland/.local/bin/waybar-netspeed
@@ -0,0 +1,67 @@
+#!/bin/sh
+# Network status indicator for waybar
+# Shows: WiFi icon (signal strength) + SSID, or Ethernet icon + interface
+# Tooltip: upload/download speeds
+
+INTERFACE=$(ip route | awk '/default/ {print $5; exit}')
+
+if [ -z "$INTERFACE" ]; then
+ echo '{"text": "󰤭 Disconnected", "tooltip": "No network connection", "class": "disconnected"}'
+ exit 0
+fi
+
+# Measure network speed (requires 1 second delay)
+RX1=$(cat /sys/class/net/$INTERFACE/statistics/rx_bytes)
+TX1=$(cat /sys/class/net/$INTERFACE/statistics/tx_bytes)
+sleep 1
+RX2=$(cat /sys/class/net/$INTERFACE/statistics/rx_bytes)
+TX2=$(cat /sys/class/net/$INTERFACE/statistics/tx_bytes)
+
+RX_RATE=$((RX2 - RX1))
+TX_RATE=$((TX2 - TX1))
+
+format_speed() {
+ local bytes=$1
+ if [ $bytes -ge 1073741824 ]; then
+ printf "%.2f GB/s" $(echo "scale=2; $bytes / 1073741824" | bc)
+ elif [ $bytes -ge 1048576 ]; then
+ printf "%.2f MB/s" $(echo "scale=2; $bytes / 1048576" | bc)
+ elif [ $bytes -ge 1024 ]; then
+ printf "%.2f KB/s" $(echo "scale=2; $bytes / 1024" | bc)
+ else
+ printf "%d B/s" $bytes
+ fi
+}
+
+UP=$(format_speed $TX_RATE)
+DOWN=$(format_speed $RX_RATE)
+
+# Determine connection type and get appropriate icon/label
+if [ -d "/sys/class/net/$INTERFACE/wireless" ]; then
+ # WiFi connection
+ LABEL=$(iwgetid -r 2>/dev/null || echo "WiFi")
+
+ # Get signal strength in percentage
+ SIGNAL=$(awk 'NR==3 {print int($3 * 100 / 70)}' /proc/net/wireless 2>/dev/null)
+
+ # Select icon based on signal strength
+ if [ -z "$SIGNAL" ] || [ "$SIGNAL" -le 0 ]; then
+ ICON="󰤯" # No signal
+ elif [ "$SIGNAL" -le 25 ]; then
+ ICON="󰤟" # Weak
+ elif [ "$SIGNAL" -le 50 ]; then
+ ICON="󰤢" # Fair
+ elif [ "$SIGNAL" -le 75 ]; then
+ ICON="󰤥" # Good
+ else
+ ICON="󰤨" # Excellent
+ fi
+else
+ # Ethernet connection
+ ICON="󰈀"
+ LABEL="$INTERFACE"
+fi
+
+TOOLTIP="Up: $UP\nDown: $DOWN"
+
+echo "{\"text\": \"<span size='large'>$ICON</span> $LABEL\", \"tooltip\": \"$TOOLTIP\", \"class\": \"connected\"}"