diff options
Diffstat (limited to 'dotfiles/hyprland/.local')
| -rwxr-xr-x | dotfiles/hyprland/.local/bin/cycle-layout | 29 | ||||
| -rwxr-xr-x | dotfiles/hyprland/.local/bin/layout-navigate | 59 | ||||
| -rwxr-xr-x | dotfiles/hyprland/.local/bin/pinentry-fuzzel | 107 | ||||
| -rwxr-xr-x | dotfiles/hyprland/.local/bin/set-theme | 124 | ||||
| -rwxr-xr-x | dotfiles/hyprland/.local/bin/toggle-scratchpad | 29 | ||||
| -rwxr-xr-x | dotfiles/hyprland/.local/bin/waybar-layout | 36 | ||||
| -rwxr-xr-x | dotfiles/hyprland/.local/bin/waybar-netspeed | 67 |
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\"}" |
