aboutsummaryrefslogtreecommitdiffstats
path: root/config/hypr
diff options
context:
space:
mode:
authorMartin Guzman <55927935+brockar@users.noreply.github.com>2026-01-21 16:18:43 -0300
committerGitHub <noreply@github.com>2026-01-21 16:18:43 -0300
commitc6198c1bedeffd08ec3f60f7ba3a41e6c5870885 (patch)
tree458c030873b4e70ff9eda0baed5df257434871f4 /config/hypr
parent7dedbe3d4a4560ac15987fdf8164dbbb1f4701bf (diff)
parent88a09344e8cc7cffe69a017eb752e8c6fa17ddcb (diff)
Merge pull request #927 from JaKooLit/development
Merge Development to main branch for release
Diffstat (limited to 'config/hypr')
-rw-r--r--config/hypr/UserConfigs/UserDecorations.conf14
-rwxr-xr-xconfig/hypr/UserScripts/RainbowBorders.bak.sh89
-rwxr-xr-xconfig/hypr/UserScripts/RainbowBorders.sh14
-rwxr-xr-xconfig/hypr/UserScripts/WallpaperEffects.sh40
-rwxr-xr-xconfig/hypr/UserScripts/WallpaperRandom.sh5
-rwxr-xr-xconfig/hypr/UserScripts/WallpaperSelect.sh47
-rwxr-xr-xconfig/hypr/UserScripts/Weather.sh46
-rwxr-xr-xconfig/hypr/UserScripts/WeatherWrap.sh26
-rw-r--r--config/hypr/configs/Keybinds.conf15
-rw-r--r--config/hypr/configs/Startup_Apps.conf27
-rw-r--r--config/hypr/configs/SystemSettings.conf5
-rw-r--r--config/hypr/configs/WindowRules-config-v3.conf65
-rw-r--r--config/hypr/configs/WindowRules-pre-53.conf4
-rw-r--r--config/hypr/configs/WindowRules.conf95
-rw-r--r--config/hypr/hyprlock-2k.conf183
-rwxr-xr-xconfig/hypr/initial-boot.sh3
-rwxr-xr-xconfig/hypr/scripts/ChangeLayout.sh31
-rwxr-xr-xconfig/hypr/scripts/DarkLight.sh15
-rwxr-xr-xconfig/hypr/scripts/Distro_update.sh2
-rwxr-xr-xconfig/hypr/scripts/Hypridle.sh3
-rwxr-xr-xconfig/hypr/scripts/KeyBinds.sh136
-rwxr-xr-xconfig/hypr/scripts/KeyHints.sh3
-rwxr-xr-xconfig/hypr/scripts/KeyboardLayout.sh119
-rwxr-xr-xconfig/hypr/scripts/KillActiveProcess.sh7
-rwxr-xr-xconfig/hypr/scripts/KooLsDotsUpdate.sh12
-rwxr-xr-xconfig/hypr/scripts/Kool_Quick_Settings.sh153
-rwxr-xr-xconfig/hypr/scripts/PortalHyprland.sh40
-rwxr-xr-xconfig/hypr/scripts/RofiSearch.sh15
-rwxr-xr-xconfig/hypr/scripts/ScreenShot.sh3
-rwxr-xr-xconfig/hypr/scripts/Sounds.sh17
-rwxr-xr-xconfig/hypr/scripts/SwitchKeyboardLayout.sh103
-rwxr-xr-xconfig/hypr/scripts/Tak0-Per-Window-Switch.sh20
-rwxr-xr-xconfig/hypr/scripts/ThemeChanger.sh145
-rwxr-xr-xconfig/hypr/scripts/TouchPad.sh48
-rwxr-xr-xconfig/hypr/scripts/Volume.sh132
-rwxr-xr-xconfig/hypr/scripts/WallustSwww.sh81
-rwxr-xr-xconfig/hypr/scripts/WaybarScripts.sh10
-rwxr-xr-xconfig/hypr/scripts/keybinds_parser.py245
-rwxr-xr-xconfig/hypr/scripts/sddm_wallpaper.sh51
-rwxr-xr-xconfig/hypr/scripts/update_WindowRules.sh60
-rw-r--r--config/hypr/v2.3.19 (renamed from config/hypr/v2.3.18)0
41 files changed, 1613 insertions, 516 deletions
diff --git a/config/hypr/UserConfigs/UserDecorations.conf b/config/hypr/UserConfigs/UserDecorations.conf
index 0b450904..f203fe5b 100644
--- a/config/hypr/UserConfigs/UserDecorations.conf
+++ b/config/hypr/UserConfigs/UserDecorations.conf
@@ -12,14 +12,14 @@ general {
border_size = 2
gaps_in = 2
gaps_out = 4
-
- col.active_border = $color12
+
+ col.active_border = $color12
col.inactive_border = $color10
}
decoration {
rounding = 10
-
+
active_opacity = 1.0
inactive_opacity = 0.9
fullscreen_opacity = 1.0
@@ -37,13 +37,13 @@ decoration {
color_inactive = $color10
}
-
blur {
- enabled = true
+ enabled = true
size = 6
- passes = 2
- ignore_opacity = true
+ passes = 3
new_optimizations = true
+ xray = true
+ ignore_opacity = true
special = true
popups = true
}
diff --git a/config/hypr/UserScripts/RainbowBorders.bak.sh b/config/hypr/UserScripts/RainbowBorders.bak.sh
new file mode 100755
index 00000000..67269b8a
--- /dev/null
+++ b/config/hypr/UserScripts/RainbowBorders.bak.sh
@@ -0,0 +1,89 @@
+#!/usr/bin/env bash
+# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
+# Smooth border cycling effect using Wallust palette or full rainbow
+
+# Possible values: "wallust_random", "rainbow", "gradient_flow"
+EFFECT_TYPE="gradient_flow"
+
+WALLUST_COLORS_SOURCE="$HOME/.config/hypr/wallust/wallust-hyprland.conf"
+
+WALLUST_COLORS=()
+
+# ---------- LOAD WALLUST COLORS ----------
+if [[ "$EFFECT_TYPE" == "wallust_random" || "$EFFECT_TYPE" == "gradient_flow" ]]; then
+ # Accept either hex (0xffRRGGBB) or rgb(r,g,b) and normalize to 0xffRRGGBB
+ mapfile -t WALLUST_COLORS < <(
+ grep -E '^\$color[0-9]+' "$WALLUST_COLORS_SOURCE" | awk '
+ function hex2(s){ return (length(s)==6 ? "0xff"s : ""); }
+ function rgb2(r,g,b){ return sprintf("0xff%02x%02x%02x", r, g, b); }
+ {
+ if (match($0, /0x([0-9a-fA-F]{8})/, m)) { print "0x" m[1]; next }
+ if (match($0, /#([0-9a-fA-F]{6})/, m)) { print hex2(m[1]); next }
+ if (match($0, /rgb\(([0-9]+),[ ]*([0-9]+),[ ]*([0-9]+)\)/, m)) {
+ print rgb2(m[1], m[2], m[3]); next
+ }
+ }'
+ )
+
+ if (( ${#WALLUST_COLORS[@]} == 0 )); then
+ # If wallust colors can't be loaded, fall back to random_hex
+ EFFECT_TYPE="rainbow"
+ fi
+fi
+
+# ---------- RANDOM WALLUST COLORS ----------
+function wallust_random() {
+ echo "${WALLUST_COLORS[RANDOM % ${#WALLUST_COLORS[@]}]}"
+}
+
+# ---------- RAINBOW COLORS ----------
+function random_hex() {
+ echo "0xff$(openssl rand -hex 3)"
+}
+
+# ---------- FLOW MODE ----------
+BASE_COLOR="${WALLUST_COLORS[10]}"
+GRAD1_COLOR="${WALLUST_COLORS[14]}"
+GRAD2_COLOR="${WALLUST_COLORS[13]}"
+GLOW_COLOR="${WALLUST_COLORS[15]}"
+
+MAX_POS=10
+GLOW_POS=0
+
+function gradient_flow_color() {
+ local pos=$1
+ local d=$(( pos - GLOW_POS ))
+
+ # wrap distance (-9..9)
+ if (( d > MAX_POS/2 )); then d=$((d - MAX_POS)); fi
+ if (( d < -MAX_POS/2 )); then d=$((d + MAX_POS)); fi
+
+ case "${d#-}" in
+ 0) echo "$GLOW_COLOR" ;;
+ 1) echo "$GRAD1_COLOR" ;;
+ 2) echo "$GRAD2_COLOR" ;;
+ *) echo "$BASE_COLOR" ;;
+ esac
+
+ if (( pos == MAX_POS - 1 )); then
+ GLOW_POS=$(( (GLOW_POS + 1) % MAX_POS ))
+ fi
+}
+
+# ---------- Main function ----------
+
+function get_color() {
+ if [[ "$EFFECT_TYPE" == "wallust_random" && ${#WALLUST_COLORS[@]} -gt 0 ]]; then
+ wallust_random
+ elif [[ "$EFFECT_TYPE" == "gradient_flow" && ${#WALLUST_COLORS[@]} -ge 16 ]]; then
+ gradient_flow_color "$1"
+ else
+ random_hex
+ fi
+}
+
+# border effect for ACTIVE window
+hyprctl keyword general:col.active_border $(get_color 0) $(get_color 1) $(get_color 2) $(get_color 3) $(get_color 4) $(get_color 5) $(get_color 6) $(get_color 7) $(get_color 8) $(get_color 9) 270deg
+
+# border effect for INACTIVE windows
+#hyprctl keyword general:col.inactive_border $(get_color 0) $(get_color 1) $(get_color 2) $(get_color 3) $(get_color 4) $(get_color 5) $(get_color 6) $(get_color 7) $(get_color 8) $(get_color 9) 270deg \ No newline at end of file
diff --git a/config/hypr/UserScripts/RainbowBorders.sh b/config/hypr/UserScripts/RainbowBorders.sh
deleted file mode 100755
index 0a7fd721..00000000
--- a/config/hypr/UserScripts/RainbowBorders.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env bash
-# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
-# for rainbow borders animation
-
-function random_hex() {
- random_hex=("0xff$(openssl rand -hex 3)")
- echo $random_hex
-}
-
-# rainbow colors only for active window
-hyprctl keyword general:col.active_border $(random_hex) $(random_hex) $(random_hex) $(random_hex) $(random_hex) $(random_hex) $(random_hex) $(random_hex) $(random_hex) $(random_hex) 270deg
-
-# rainbow colors for inactive window (uncomment to take effect)
-#hyprctl keyword general:col.inactive_border $(random_hex) $(random_hex) $(random_hex) $(random_hex) $(random_hex) $(random_hex) $(random_hex) $(random_hex) $(random_hex) $(random_hex) 270deg \ No newline at end of file
diff --git a/config/hypr/UserScripts/WallpaperEffects.sh b/config/hypr/UserScripts/WallpaperEffects.sh
index 89577efa..475969d6 100755
--- a/config/hypr/UserScripts/WallpaperEffects.sh
+++ b/config/hypr/UserScripts/WallpaperEffects.sh
@@ -106,43 +106,3 @@ fi
main
sleep 1
-
-if [[ -n "$choice" ]]; then
- # Resolve SDDM themes directory (standard and NixOS path)
- sddm_themes_dir=""
- if [ -d "/usr/share/sddm/themes" ]; then
- sddm_themes_dir="/usr/share/sddm/themes"
- elif [ -d "/run/current-system/sw/share/sddm/themes" ]; then
- sddm_themes_dir="/run/current-system/sw/share/sddm/themes"
- fi
-
- if [ -n "$sddm_themes_dir" ]; then
- sddm_simple="$sddm_themes_dir/simple_sddm_2"
-
- # Only prompt if theme exists and its Backgrounds directory is writable
- if [ -d "$sddm_simple" ] && [ -w "$sddm_simple/Backgrounds" ]; then
- # Check if yad is running to avoid multiple yad notification
- if pidof yad > /dev/null; then
- killall yad
- fi
-
- if yad --info --text="Set current wallpaper as SDDM background?\n\nNOTE: This only applies to SIMPLE SDDM v2 Theme" \
- --text-align=left \
- --title="SDDM Background" \
- --timeout=5 \
- --timeout-indicator=right \
- --button="yad-yes:0" \
- --button="yad-no:1" \
- ; then
-
- # Check if terminal exists
- if ! command -v "$terminal" &>/dev/null; then
- notify-send -i "$iDIR/ja.png" "Missing $terminal" "Install $terminal to enable setting of wallpaper background"
- exit 1
- fi
-
- exec "$SCRIPTSDIR/sddm_wallpaper.sh" --effects
- fi
- fi
- fi
-fi
diff --git a/config/hypr/UserScripts/WallpaperRandom.sh b/config/hypr/UserScripts/WallpaperRandom.sh
index 654d4bd3..8dd680d5 100755
--- a/config/hypr/UserScripts/WallpaperRandom.sh
+++ b/config/hypr/UserScripts/WallpaperRandom.sh
@@ -2,12 +2,13 @@
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# Script for Random Wallpaper ( CTRL ALT W)
-wallDIR="$HOME/Pictures/wallpapers"
+PICTURES_DIR="$(xdg-user-dir PICTURES 2>/dev/null || echo "$HOME/Pictures")"
+wallDIR="$PICTURES_DIR/wallpapers"
SCRIPTSDIR="$HOME/.config/hypr/scripts"
focused_monitor=$(hyprctl monitors -j | jq -r '.[] | select(.focused) | .name')
-PICS=($(find -L ${wallDIR} -type f \( -name "*.jpg" -o -name "*.jpeg" -o -name "*.png" -o -name "*.pnm" -o -name "*.tga" -o -name "*.tiff" -o -name "*.webp" -o -name "*.bmp" -o -name "*.farbfeld" -o -name "*.gif" \)))
+PICS=($(find -L "${wallDIR}" -type f \( -name "*.jpg" -o -name "*.jpeg" -o -name "*.png" -o -name "*.pnm" -o -name "*.tga" -o -name "*.tiff" -o -name "*.webp" -o -name "*.bmp" -o -name "*.farbfeld" -o -name "*.gif" \)))
RANDOMPICS=${PICS[ $RANDOM % ${#PICS[@]} ]}
diff --git a/config/hypr/UserScripts/WallpaperSelect.sh b/config/hypr/UserScripts/WallpaperSelect.sh
index 0029d3e5..316a7cd4 100755
--- a/config/hypr/UserScripts/WallpaperSelect.sh
+++ b/config/hypr/UserScripts/WallpaperSelect.sh
@@ -4,7 +4,8 @@
# WALLPAPERS PATH
terminal=kitty
-wallDIR="$HOME/Pictures/wallpapers"
+PICTURES_DIR="$(xdg-user-dir PICTURES 2>/dev/null || echo "$HOME/Pictures")"
+wallDIR="$PICTURES_DIR/wallpapers"
SCRIPTSDIR="$HOME/.config/hypr/scripts"
wallpaper_current="$HOME/.config/hypr/wallpaper_effects/.wallpaper_current"
@@ -98,49 +99,6 @@ menu() {
done
}
-# Offer SDDM Simple Wallpaper Option (only for non-video wallpapers)
-set_sddm_wallpaper() {
- sleep 1
-
- # Resolve SDDM themes directory (standard and NixOS path)
- local sddm_themes_dir=""
- if [ -d "/usr/share/sddm/themes" ]; then
- sddm_themes_dir="/usr/share/sddm/themes"
- elif [ -d "/run/current-system/sw/share/sddm/themes" ]; then
- sddm_themes_dir="/run/current-system/sw/share/sddm/themes"
- fi
-
- [ -z "$sddm_themes_dir" ] && return 0
-
- local sddm_simple="$sddm_themes_dir/simple_sddm_2"
-
- # Only prompt if theme exists and its Backgrounds directory is writable
- if [ -d "$sddm_simple" ] && [ -w "$sddm_simple/Backgrounds" ]; then
-
- # Check if yad is running to avoid multiple notifications
- if pidof yad >/dev/null; then
- killall yad
- fi
-
- if yad --info --text="Set current wallpaper as SDDM background?\n\nNOTE: This only applies to SIMPLE SDDM v2 Theme" \
- --text-align=left \
- --title="SDDM Background" \
- --timeout=5 \
- --timeout-indicator=right \
- --button="yes:0" \
- --button="no:1"; then
-
- # Check if terminal exists
- if ! command -v "$terminal" &>/dev/null; then
- notify-send -i "$iDIR/error.png" "Missing $terminal" "Install $terminal to enable setting of wallpaper background"
- exit 1
- fi
-
- exec "$SCRIPTSDIR/sddm_wallpaper.sh" --normal
-
- fi
- fi
-}
modify_startup_config() {
local selected_file="$1"
@@ -186,7 +144,6 @@ apply_image_wallpaper() {
"$SCRIPTSDIR/Refresh.sh"
sleep 1
- set_sddm_wallpaper
}
apply_video_wallpaper() {
diff --git a/config/hypr/UserScripts/Weather.sh b/config/hypr/UserScripts/Weather.sh
index ac9abc13..4588ed1d 100755
--- a/config/hypr/UserScripts/Weather.sh
+++ b/config/hypr/UserScripts/Weather.sh
@@ -2,16 +2,50 @@
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# weather info from wttr. https://github.com/chubin/wttr.in
# Remember to add city
+# Function to get current city from IP address with fallback
-city=""
+# Get your current location with your IP adress
+get_current_city() {
+ local city
+
+ # First try: ipinfo.io
+ local location_data=$(curl -fsS "https://ipinfo.io/json" 2>/dev/null)
+ if [ $? -eq 0 ] && [ -n "$location_data" ]; then
+ city=$(echo "$location_data" | grep -o '"city"[[:space:]]*:[[:space:]]*"[^"]*"' | cut -d'"' -f4)
+ if [ -n "$city" ]; then
+ echo "$city"
+ return 0
+ fi
+ fi
+
+ # Fallback: ipapi.co
+ city=$(curl -fsS "https://ipapi.co/json" 2>/dev/null | grep -o '"city"[[:space:]]*:[[:space:]]*"[^"]*"' | cut -d'"' -f4)
+ if [ -n "$city" ]; then
+ echo "$city"
+ return 0
+ fi
+
+ # Last resort: ipwho.is
+ city=$(curl -fsS "https://ipwho.is/" 2>/dev/null | grep -o '"city"[[:space:]]*:[[:space:]]*"[^"]*"' | cut -d'"' -f4)
+ if [ -n "$city" ]; then
+ echo "$city"
+ return 0
+ fi
+
+ # If all fail
+ echo "Unknown" >&2
+ return 1
+}
+city=$(get_current_city)
-# if city is blank, use https://ipapi.co/json to get location from IP
-if [ -z "$city" ]; then
- city=$(curl -fsS https://ipapi.co/json | grep city | cut -f4 -d'"')
+# If city is empty, that means the IP check failed, which means, we should use manual setting
+if [ -z "$city" ] || [ "$city" = "Unknown" ]; then
+ # SET YOUR MANUAL CITY HERE
+ city=" " # ← Change this to your preferred city
+ echo "Using manual city: $city" >&2
fi
-
# URL-encode city for safe use in URLs
encoded_city="$city"
if command -v python3 >/dev/null 2>&1; then
@@ -206,4 +240,4 @@ tooltip_json=$(json_escape "${weather[0]}: $temperature $cond_disp")
printf '{"text":"%s", "alt":"%s", "tooltip":"%s"}\n' "$text_json" "$alt_json" "$tooltip_json"
# Write a two-line cache with an actual newline between lines
-printf ' %s \n%s %s\n' "$temperature" "$condition" "${weather[1]}" > "$HOME/.cache/.weather_cache" \ No newline at end of file
+printf ' %s \n%s %s\n' "$temperature" "$condition" "${weather[1]}" > "$HOME/.cache/.weather_cache"
diff --git a/config/hypr/UserScripts/WeatherWrap.sh b/config/hypr/UserScripts/WeatherWrap.sh
index 10c125dc..5b266930 100755
--- a/config/hypr/UserScripts/WeatherWrap.sh
+++ b/config/hypr/UserScripts/WeatherWrap.sh
@@ -6,6 +6,30 @@ SCRIPT_DIR="$(dirname "$0")"
PY_SCRIPT="$SCRIPT_DIR/Weather.py"
BASH_FALLBACK="$SCRIPT_DIR/Weather.sh"
+# Function to check network connectivity
+check_network() {
+ # Try multiple methods to check network
+ if ping -c1 -W2 8.8.8.8 >/dev/null 2>&1; then
+ return 0
+ fi
+
+ if ping -c1 -W2 1.1.1.1 >/dev/null 2>&1; then
+ return 0
+ fi
+
+ if curl -s --connect-timeout 3 "https://ipinfo.io" >/dev/null 2>&1; then
+ return 0
+ fi
+
+ return 1
+}
+
+# If no network, return offline status immediately
+if ! check_network; then
+ echo '{"text":"󰖪", "alt":"Offline", "tooltip":"No network connection"}'
+ exit 0
+fi
+
run_fallback() {
if [ -f "$BASH_FALLBACK" ]; then
# Invoke via bash to avoid requiring +x and ensure consistent shell
@@ -30,4 +54,4 @@ else
echo "python3 not found in PATH — falling back to Weather.sh" >&2
run_fallback "$@"
exit $?
-fi \ No newline at end of file
+fi
diff --git a/config/hypr/configs/Keybinds.conf b/config/hypr/configs/Keybinds.conf
index 1ddbc81a..dea22719 100644
--- a/config/hypr/configs/Keybinds.conf
+++ b/config/hypr/configs/Keybinds.conf
@@ -23,6 +23,7 @@ bindd = $mainMod, Return, Open terminal, exec, $term
bindd = $mainMod, E, file manager, exec, $files
# FEATURES / EXTRAS
+bindd = $mainMod, T, Global theme switcher using Wallust, exec, $scriptsDir/ThemeChanger.sh #Global theme switcher
bindd = $mainMod, H, help / cheat sheet, exec, $scriptsDir/KeyHints.sh
bindd = $mainMod ALT, R, refresh bar and menus, exec, $scriptsDir/Refresh.sh
bindd = $mainMod ALT, E, emoji menu, exec, $scriptsDir/RofiEmoji.sh
@@ -43,7 +44,7 @@ bindd = $mainMod SHIFT, Return, DropDown terminal, exec, $scriptsDir/Droptermina
# Desktop zooming or magnifier
bindd = $mainMod ALT, mouse_down, zoom in, exec, hyprctl keyword cursor:zoom_factor "$(hyprctl getoption cursor:zoom_factor | awk 'NR==1 {factor = $2; if (factor < 1) {factor = 1}; print factor * 2.0}')"
-bindd = $mainMod ALT, mouse_up, zoom out, exec, hyprctl keyword cursor:zoom_factor "$(hyprctl getoption cursor:zoom_factor | awk 'NR==1 {factor = $2; if (factor < 1) {factor = 1}; print factor / 2.0}')"
+bindd = $mainMod ALT, mouse_up, zoom out, exec, hyprctl keyword cursor:zoom_factor "$(hyprctl getoption cursor:zoom_factor | awk 'NR==1 {factor = $2; if (factor < 1) {factor = 1}; print factor / 2.0}')"
# Waybar / Bar related
bindd = $mainMod CTRL ALT, B, toggle waybar on/off, exec, pkill -SIGUSR1 waybar
@@ -58,11 +59,11 @@ bindd = $mainMod SHIFT, M, online music, exec, $UserScripts/RofiBeats.sh
bindd = $mainMod, W, select wallpaper, exec, $UserScripts/WallpaperSelect.sh
bindd = $mainMod SHIFT, W, wallpaper effects, exec, $UserScripts/WallpaperEffects.sh
bindd = CTRL ALT, W, random wallpaper, exec, $UserScripts/WallpaperRandom.sh
-bindd = $mainMod CTRL, O, toggle active window opacity, exec, hyprctl setprop active opaque toggle
+bindd = $mainMod CTRL, O, toggle active window opacity, setprop, active opaque toggle
bindd = $mainMod SHIFT, K, search keybinds, exec, $scriptsDir/KeyBinds.sh
bindd = $mainMod SHIFT, A, animations menu, exec, $scriptsDir/Animations.sh
bindd = $mainMod SHIFT, O, change oh-my-zsh theme, exec, $UserScripts/ZshChangeTheme.sh
-bindlnd = ALT_L, SHIFT_L, switch keyboard layout globally, exec, $scriptsDir/SwitchKeyboardLayout.sh
+bindlnd = ALT_L, SHIFT_L, switch keyboard layout globally, exec, $scriptsDir/KeyboardLayout.sh switch
bindlnd = SHIFT_L, ALT_L, switch keyboard layout per-window, exec, $scriptsDir/Tak0-Per-Window-Switch.sh
bindd = $mainMod ALT, C, calculator, exec, $UserScripts/RofiCalc.sh
@@ -97,6 +98,8 @@ bindd = $mainMod, P, toggle pseudo (dwindle), pseudo,
# Works on either layout (Master or Dwindle)
bindd = $mainMod, M, set split ratio 0.3, exec, hyprctl dispatch splitratio 0.3
+# layout aware keybinds
+exec-once = $scriptsDir/ChangeLayout.sh init
# Cycle windows; if floating bring to top
@@ -106,6 +109,8 @@ bindd = ALT, tab, bring active to top, bringactivetotop
# Special Keys / Hot Keys
bindeld = , xf86audioraisevolume, volume up, exec, $scriptsDir/Volume.sh --inc
bindeld = , xf86audiolowervolume, volume down, exec, $scriptsDir/Volume.sh --dec
+bindeld = ALT, xf86audioraisevolume, volume up precise, exec, $scriptsDir/Volume.sh --inc-precise
+bindeld = ALT, xf86audiolowervolume, volume down precise, exec, $scriptsDir/Volume.sh --dec-precise
bindld = , xf86AudioMicMute, toggle mic mute, exec, $scriptsDir/Volume.sh --toggle-mic
bindld = , xf86audiomute, toggle mute, exec, $scriptsDir/Volume.sh --toggle
bindld = , xf86Sleep, sleep, exec, systemctl suspend
@@ -160,7 +165,7 @@ bindd = $mainMod CTRL, K, Move left into group, moveintogroup, l # Move active w
bindd = $mainMod CTRL, L, Move Right into group, moveintogroup, r # Move active window right into a group
bindd = $mainMod CTRL, H, Move active out of group, moveoutofgroup # Move active window out of group
-# Try to dynamically move in grouped window and when ungrouped
+# Try to dynamically move in grouped window and when ungrouped
# Not working for me DW 11/26/25 PR: https://github.com/JaKooLit/Hyprland-Dots/pull/872
#bindd = $mainMod, right, focus right, exec, bash -c 'if hyprctl activewindow -j | jq -e "((.grouped | type) == \"boolean\") or (.address == (.grouped[-1] // empty))" >/dev/null 2>&1; then hyprctl dispatch movefocus r; else hyprctl dispatch changegroupactive f; fi'
#bindd = $mainMod, left, focus left, exec, bash -c 'if hyprctl activewindow -j | jq -e "((.grouped | type) == \"boolean\") or (.address == (.grouped[0] // empty))" >/dev/null 2>&1; then hyprctl dispatch movefocus l; else hyprctl dispatch changegroupactive b; fi'
@@ -181,7 +186,7 @@ bindd = $mainMod, U, toggle special workspace, togglespecialworkspace,
# The following mappings use the key codes to better support various keyboard layouts
# 1 is code:10, 2 is code 11, etc
-# Switch workspaces with mainMod + [0-9]
+# Switch workspaces with mainMod + [0-9]
bindd = $mainMod, code:10, workspace 1, workspace, 1 # NOTE: code:10 = key 1
bindd = $mainMod, code:11, workspace 2, workspace, 2 # NOTE: code:11 = key 2
bindd = $mainMod, code:12, workspace 3, workspace, 3 # NOTE: code:12 = key 3
diff --git a/config/hypr/configs/Startup_Apps.conf b/config/hypr/configs/Startup_Apps.conf
index 0cfb6427..0cc5da11 100644
--- a/config/hypr/configs/Startup_Apps.conf
+++ b/config/hypr/configs/Startup_Apps.conf
@@ -1,35 +1,23 @@
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ #
# Commands and Apps to be executed at launch (vendor defaults)
-
$scriptsDir = $HOME/.config/hypr/scripts
$UserScripts = $HOME/.config/hypr/UserScripts
-
-$wallDIR=$HOME/Pictures/wallpapers
$lock = $scriptsDir/LockScreen.sh
$SwwwRandom = $UserScripts/WallpaperAutoChange.sh
$livewallpaper=""
+$wallDIR = $HOME/Pictures/wallpapers # change path manually here if needed
### wallpaper stuff ###
exec-once = swww-daemon --format xrgb
#exec-once = mpvpaper '*' -o "load-scripts=no no-audio --loop" $livewallpaper
-
# wallpaper random
#exec-once = $SwwwRandom $wallDIR # random wallpaper switcher every 30 minutes
### Startup ###
exec-once = dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP
exec-once = systemctl --user import-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP
-exec-once = $scriptsDir/KeybindsLayoutInit.sh
-
-# Drop Down terminal
-# See Bug#810 https://github.com/JaKooLit/Hyprland-Dots/issues/810#issuecomment-3351947644
exec-once = $HOME/.config/hypr/scripts/Dropterminal.sh kitty &
-
-
-# Polkit (Polkit Gnome / KDE)
exec-once = $scriptsDir/Polkit.sh
-
-# starup apps
exec-once = nm-applet --indicator
exec-once = nm-tray # For ubuntu
exec-once = swaync
@@ -38,23 +26,20 @@ exec-once = swaync
#exec-once = rog-control-center
exec-once = waybar
exec-once = qs -c overview # Quickshell Overview
+exec-once = hypridle
+exec-once = $scriptsDir/Hyprsunset.sh init
# Clipboard manager
exec-once = wl-paste --type text --watch cliphist store
exec-once = wl-paste --type image --watch cliphist store
-# Rainbow borders
-exec-once = $UserScripts/RainbowBorders.sh
+# Rainbow borders (disabled by default; use quick settings menu)
+#exec-once = $UserScripts/RainbowBorders.sh
-# hypridle for hyprlock
-exec-once = hypridle
-
-# Resume Hyprsunset if state is "on" from previous session
-exec-once = $scriptsDir/Hyprsunset.sh init
# Here are list of features available but disabled by default
# Persistent wallpaper
-# exec-once = swww-daemon --format xrgb && swww img $HOME/Pictures/wallpapers/mecha-nostalgia.png
+# exec-once = swww-daemon --format xrgb && swww img $wallDIR/mecha-nostalgia.png
# Gnome polkit for NixOS
#exec-once = $scriptsDir/Polkit-NixOS.sh
diff --git a/config/hypr/configs/SystemSettings.conf b/config/hypr/configs/SystemSettings.conf
index 44521156..f49960cd 100644
--- a/config/hypr/configs/SystemSettings.conf
+++ b/config/hypr/configs/SystemSettings.conf
@@ -93,6 +93,11 @@ misc {
enable_anr_dialog = true # Application not Responding (ANR)
anr_missed_pings = 15 # ANR Threshold default 1 is too low
allow_session_lock_restore = true # Prevent lockscreen crash when resume from suspend
+ # This only works with HL v0.53+
+ on_focus_under_fullscreen = 1
+ # 0 - Default, no change
+ # 1 - New focused window takes over fullscreen (Windows-like Alt-Tab)
+ # 2 - New focused window stays behind the fullscreen one
}
#opengl {
diff --git a/config/hypr/configs/WindowRules-config-v3.conf b/config/hypr/configs/WindowRules-config-v3.conf
index ba179461..6aab2590 100644
--- a/config/hypr/configs/WindowRules-config-v3.conf
+++ b/config/hypr/configs/WindowRules-config-v3.conf
@@ -2,10 +2,24 @@
# Vendor defaults for window rules and layerrules
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
-# NOTES: This is only for Hyprland > 0.52.1
-# note for ja: This should NOT be implemented on Debian and Ubuntu
+# NOTES: This is only for Hyprland >= 0.53
-# windowrule - tags - add apps under appropriate tag to use the same settings
+# Some samples on hwo to start apps on specific workspaces
+# windowrule = match:tag email*, workspace 1
+# windowrule = match:tag browser*, workspace 2
+# windowrule = match:tag projects*, workspace 3
+# windowrule = match:tag screenshare*, workspace 4 silent
+# windowrule = match:tag gamestore*, workspace 5
+# windowrule = match:class ^(virt-manager)$, workspace 6 silent
+# windowrule = match:class ^(.virt-manager-wrapped)$, workspace 6 silent
+# windowrule = match:tag im*, workspace 7
+# windowrule = match:class obsidian, workspace 8
+# windowrule = match:tag games*, workspace 8
+# windowrule = match:tag multimedia*, workspace 9 silent
+
+
+
+# TAGS - add apps under appropriate tag to use the same settings
# browser tags
windowrule = match:class ^([Ff]irefox|org.mozilla.firefox|[Ff]irefox-esr|[Ff]irefox-bin)$, tag +browser
windowrule = match:class ^([Gg]oogle-chrome(-beta|-dev|-unstable)?)$, tag +browser
@@ -14,7 +28,7 @@ windowrule = match:class ^([Cc]hromium)$, tag +browser
windowrule = match:class ^([Mm]icrosoft-edge(-stable|-beta|-dev|-unstable))$, tag +browser
windowrule = match:class ^(Brave-browser(-beta|-dev|-unstable)?)$, tag +browser
windowrule = match:class ^([Tt]horium-browser|[Cc]achy-browser)$, tag +browser
-windowrule = match:class ^(zen-alpha|zen)$, tag +browser
+windowrule = match:class ^(zen)$, tag +browser
# notif tags
windowrule = match:class ^(swaync-control-center|swaync-notification-window|swaync-client|class)$, tag +notif
@@ -30,11 +44,13 @@ windowrule = match:class ^(Alacritty|kitty|kitty-dropterm)$, tag +terminal
# email tags
windowrule = match:class ^([Tt]hunderbird|org.gnome.Evolution)$, tag +email
windowrule = match:class ^(eu.betterbird.Betterbird)$, tag +email
+windowrule = match:class ^(org.gnome.Evolution)$, tag +email
# project tags
windowrule = match:class ^(codium|codium-url-handler|VSCodium)$, tag +projects
windowrule = match:class ^(VSCode|code|code-url-handler)$, tag +projects
windowrule = match:class ^(jetbrains-.+)$, tag +projects
+windowrule = match:class ^(dev.zed.Zed|antigravity)$, tag +projects
# screenshare tags
windowrule = match:class ^(com.obsproject.Studio)$, tag +screenshare
@@ -43,7 +59,6 @@ windowrule = match:class ^(com.obsproject.Studio)$, tag +screenshare
windowrule = match:class ^([Dd]iscord|[Ww]ebCord|[Vv]esktop)$, tag +im
windowrule = match:class ^([Ff]erdium)$, tag +im
windowrule = match:class ^([Ww]hatsapp-for-linux)$, tag +im
-windowrule = match:class ^(ZapZap|com.rtosta.zapzap)$, tag +im
windowrule = match:class ^(org.telegram.desktop|io.github.tdesktop_x64.TDesktop)$, tag +im
windowrule = match:class ^(teams-for-linux)$, tag +im
windowrule = match:class ^(im.riot.Riot|Element)$, tag +im
@@ -79,10 +94,12 @@ windowrule = match:title (Kvantum Manager), tag +settings
windowrule = match:class ^(file-roller|org.gnome.FileRoller)$, tag +settings
windowrule = match:class ^(nm-applet|nm-connection-editor|blueman-manager)$, tag +settings
windowrule = match:class ^(pavucontrol|org.pulseaudio.pavucontrol|com.saivert.pwvucontrol)$, tag +settings
-windowrule = match:class ^(qt5ct|qt6ct|[Yy]ad)$, tag +settings
+windowrule = match:class ^(qt5ct|qt6ct)$, tag +settings
windowrule = match:class (xdg-desktop-portal-gtk), tag +settings
windowrule = match:class ^(org.kde.polkit-kde-authentication-agent-1)$, tag +settings
windowrule = match:class ^([Rr]ofi)$, tag +settings
+windowrule = match:class ^(btrfs-assistant)$, tag +settings
+windowrule = match:class ^(timeshift-gtk)$, tag +settings
# viewer tags
windowrule = match:class ^(gnome-system-monitor|org.gnome.SystemMonitor|io.missioncenter.MissionCenter)$, tag +viewer
@@ -153,23 +170,21 @@ windowrule = match:tag wallpaper, opacity 0.9 0.7
windowrule = match:class ^(gedit|org.gnome.TextEditor|mousepad)$, opacity 0.8 0.7
windowrule = match:class ^(deluge)$, opacity 0.9 0.8
windowrule = match:class ^(seahorse)$, opacity 0.9 0.8
-windowrule = match:title ^(Picture-in-Picture)$, opacity 0.95 0.75
# SIZE
windowrule = match:tag KooL_Cheat, size (monitor_w*0.65) (monitor_h*0.9)
windowrule = match:tag wallpaper, size (monitor_w*0.7) (monitor_h*0.7)
windowrule = match:tag settings, size (monitor_w*0.7) (monitor_h*0.7)
-windowrule = match:class ^([Ww]hatsapp-for-linux|ZapZap|com.rtosta.zapzap)$, size (monitor_w*0.6) (monitor_h*0.7)
windowrule = match:class ^([Ff]erdium)$, size (monitor_w*0.6) (monitor_h*0.7)
+windowrule = match:class (org.gnome.Calculator|qalculate-gtk), center on, size (monitor_w*0.25) (monitor_h*0.3)
-# PINNING
-windowrule = match:title ^(Picture-in-Picture)$, pin on, keep_aspect_ratio on
# BLUR & FULLSCREEN
windowrule = match:tag games, no_blur on, fullscreen 0
windowrule = match:tag games, fullscreen 0
-# This not gonna take the focus to the window that appears when hovering over some of the parts of the IntelliJ Products
+# This not gonna take the focus to the window that appears when
+# hovering over some of the parts of the IntelliJ Products
windowrule = match:class ^(jetbrains-*), no_initial_focus on
windowrule = match:title ^(wind.*)$, no_initial_focus on
@@ -178,3 +193,31 @@ layerrule = match:namespace rofi, blur on
layerrule = match:namespace notifications, blur on
layerrule = match:namespace quickshell:overview, blur on
layerrule = match:namespace quickshell:overview, ignore_alpha 0.5
+
+# Named rules for special cases
+windowrule {
+ name = Whatsapp-zapzap
+ match:class = ^([Ww]hatsapp-for-linux|ZapZap|com.rtosta.zapzap)$
+ size = (monitor_w*0.6) (monitor_h*0.7)
+ center = on
+}
+windowrule {
+ name = Picture-in-Picture
+ match:title = ^(Picture-in-Picture)$
+ float = on
+ move = 72% 7%
+ opacity = 0.95 0.75
+ pin = on
+ keep_aspect_ratio = on
+ size = (monitor_w*0.3) (monitor_h*0.3)
+}
+# Thunar copy progress dialog
+windowrule {
+ name = Thunar-Progress-bar
+ match:class = ^(thunar)$
+ match:title = ^(File Operation Progress)$
+ float = on
+ center = on
+ size = (monitor_w*0.26) (monitor_h*0.18)
+}
+
diff --git a/config/hypr/configs/WindowRules-pre-53.conf b/config/hypr/configs/WindowRules-pre-53.conf
index d1fb9315..8a5f99c7 100644
--- a/config/hypr/configs/WindowRules-pre-53.conf
+++ b/config/hypr/configs/WindowRules-pre-53.conf
@@ -4,8 +4,6 @@
# NOTES: This is only for Hyprland > 0.48
-# note for ja: This should NOT be implemented on Debian and Ubuntu
-
# windowrule - tags - add apps under appropriate tag to use the same settings
# browser tags
windowrule = tag +browser, class:^([Ff]irefox|org.mozilla.firefox|[Ff]irefox-esr|[Ff]irefox-bin)$
@@ -228,4 +226,4 @@ layerrule = ignorealpha 0.5, quickshell:overview
#layerrule = ignorezero, <rofi>
#layerrule = ignorezero, overview
-#layerrule = blur, overview \ No newline at end of file
+#layerrule = blur, overview
diff --git a/config/hypr/configs/WindowRules.conf b/config/hypr/configs/WindowRules.conf
index ba179461..d110cd4a 100644
--- a/config/hypr/configs/WindowRules.conf
+++ b/config/hypr/configs/WindowRules.conf
@@ -2,10 +2,24 @@
# Vendor defaults for window rules and layerrules
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
-# NOTES: This is only for Hyprland > 0.52.1
-# note for ja: This should NOT be implemented on Debian and Ubuntu
+# NOTES: This is only for Hyprland >= 0.53
-# windowrule - tags - add apps under appropriate tag to use the same settings
+# Some samples on hwo to start apps on specific workspaces
+# windowrule = match:tag email*, workspace 1
+# windowrule = match:tag browser*, workspace 2
+# windowrule = match:tag projects*, workspace 3
+# windowrule = match:tag screenshare*, workspace 4 silent
+# windowrule = match:tag gamestore*, workspace 5
+# windowrule = match:class ^(virt-manager)$, workspace 6 silent
+# windowrule = match:class ^(.virt-manager-wrapped)$, workspace 6 silent
+# windowrule = match:tag im*, workspace 7
+# windowrule = match:class obsidian, workspace 8
+# windowrule = match:tag games*, workspace 8
+# windowrule = match:tag multimedia*, workspace 9 silent
+
+
+
+# TAGS - add apps under appropriate tag to use the same settings
# browser tags
windowrule = match:class ^([Ff]irefox|org.mozilla.firefox|[Ff]irefox-esr|[Ff]irefox-bin)$, tag +browser
windowrule = match:class ^([Gg]oogle-chrome(-beta|-dev|-unstable)?)$, tag +browser
@@ -28,13 +42,15 @@ windowrule = match:class ^(nwg-displays|nwg-look)$, tag +KooL-Settings
windowrule = match:class ^(Alacritty|kitty|kitty-dropterm)$, tag +terminal
# email tags
-windowrule = match:class ^([Tt]hunderbird|org.gnome.Evolution)$, tag +email
+windowrule = match:class ^([Tt]hunderbird|org.mozilla.Thunderbird)$, tag +email
windowrule = match:class ^(eu.betterbird.Betterbird)$, tag +email
+windowrule = match:class ^(org.gnome.Evolution)$, tag +email
# project tags
windowrule = match:class ^(codium|codium-url-handler|VSCodium)$, tag +projects
windowrule = match:class ^(VSCode|code|code-url-handler)$, tag +projects
windowrule = match:class ^(jetbrains-.+)$, tag +projects
+windowrule = match:class ^(dev.zed.Zed|antigravity)$, tag +projects
# screenshare tags
windowrule = match:class ^(com.obsproject.Studio)$, tag +screenshare
@@ -43,7 +59,6 @@ windowrule = match:class ^(com.obsproject.Studio)$, tag +screenshare
windowrule = match:class ^([Dd]iscord|[Ww]ebCord|[Vv]esktop)$, tag +im
windowrule = match:class ^([Ff]erdium)$, tag +im
windowrule = match:class ^([Ww]hatsapp-for-linux)$, tag +im
-windowrule = match:class ^(ZapZap|com.rtosta.zapzap)$, tag +im
windowrule = match:class ^(org.telegram.desktop|io.github.tdesktop_x64.TDesktop)$, tag +im
windowrule = match:class ^(teams-for-linux)$, tag +im
windowrule = match:class ^(im.riot.Riot|Element)$, tag +im
@@ -79,10 +94,12 @@ windowrule = match:title (Kvantum Manager), tag +settings
windowrule = match:class ^(file-roller|org.gnome.FileRoller)$, tag +settings
windowrule = match:class ^(nm-applet|nm-connection-editor|blueman-manager)$, tag +settings
windowrule = match:class ^(pavucontrol|org.pulseaudio.pavucontrol|com.saivert.pwvucontrol)$, tag +settings
-windowrule = match:class ^(qt5ct|qt6ct|[Yy]ad)$, tag +settings
+windowrule = match:class ^(qt5ct|qt6ct)$, tag +settings
windowrule = match:class (xdg-desktop-portal-gtk), tag +settings
windowrule = match:class ^(org.kde.polkit-kde-authentication-agent-1)$, tag +settings
windowrule = match:class ^([Rr]ofi)$, tag +settings
+windowrule = match:class ^(btrfs-assistant)$, tag +settings
+windowrule = match:class ^(timeshift-gtk)$, tag +settings
# viewer tags
windowrule = match:class ^(gnome-system-monitor|org.gnome.SystemMonitor|io.missioncenter.MissionCenter)$, tag +viewer
@@ -92,53 +109,46 @@ windowrule = match:class ^(eog|org.gnome.Loupe)$, tag +viewer
# Some special override rules
windowrule = match:tag multimedia_video, no_blur on
windowrule = match:tag multimedia_video, opacity 1.0
+windowrule = match:tag multimedia, no_blur on
+windowrule = match:tag multimedia, opacity 1.0
# POSITION
-# windowrule = match:floating true, center on
windowrule = match:tag KooL_Cheat, center on
-windowrule = match:class ([Tt]hunar) match:title negative:(.*[Tt]hunar.*), center on
-windowrule = match:title ^(ROG Control)$, center on
windowrule = match:tag KooL-Settings, center on
+windowrule = match:title ^(ROG Control)$, center on
windowrule = match:title ^(Keybindings)$, center on
windowrule = match:class ^(pavucontrol|org.pulseaudio.pavucontrol|com.saivert.pwvucontrol)$, center on
-windowrule = match:class ^([Ww]hatsapp-for-linux|ZapZap|com.rtosta.zapzap)$, center on
windowrule = match:class ^([Ff]erdium)$, center on
-windowrule = match:title ^(Picture-in-Picture)$, move 72% 7%
# windowrule to avoid idle for fullscreen apps
windowrule = match:fullscreen true, idle_inhibit fullscreen
+windowrule = idle_inhibit fullscreen, match:fullscreen 1
+windowrule = idle_inhibit fullscreen, match:class ^(*)$
+windowrule = idle_inhibit fullscreen, match:title ^(*)$
# FLOAT
windowrule = match:tag KooL_Cheat, float on
-windowrule = match:tag wallpaper, float on
-windowrule = match:tag settings, float on
-windowrule = match:tag viewer, float on
-windowrule = match:tag KooL-Settings, float on
+windowrule = match:tag wallpaper, float on, center on
+windowrule = match:tag settings, float on, center on
+windowrule = match:tag viewer, float on, center on
+windowrule = match:tag KooL-Settings, float on, center on
windowrule = match:class ([Zz]oom|onedriver|onedriver-launcher), float on
-windowrule = match:class (org.gnome.Calculator) match:title (Calculator), float on
+windowrule = match:class (org.gnome.Calculator|qalculate-gtk), float on
windowrule = match:class ^(mpv|com.github.rafostar.Clapper)$, float on
windowrule = match:class ^([Qq]alculate-gtk)$, float on
windowrule = match:class ^([Ff]erdium)$, float on
-windowrule = match:title ^(Picture-in-Picture)$, float on
-# windowrule - ######### float popups and dialogue #######
+# popups and dialogue
windowrule = match:title ^(Authentication Required)$, float on, center on
windowrule = match:class (codium|codium-url-handler|VSCodium) match:title negative:(.*codium.*|.*VSCodium.*), float on
windowrule = match:class ^(com.heroicgameslauncher.hgl)$ match:title negative:(Heroic Games Launcher), float on
windowrule = match:class ^([Ss]team)$ match:title negative:^([Ss]team)$, float on
-windowrule = match:class ([Tt]hunar) match:title negative:(.*[Tt]hunar.*), float on
-
windowrule = match:title ^(Add Folder to Workspace)$, float on, size (monitor_w*0.7) (monitor_h*0.6), center on
-
windowrule = match:title ^(Save As)$, float on, size (monitor_w*0.7) (monitor_h*0.6), center on
-
windowrule = match:initial_title (Open Files), float on, size (monitor_w*0.7) (monitor_h*0.6)
-
windowrule = match:title ^(SDDM Background)$, float on, center on, size (monitor_w*0.16) (monitor_h*0.12)
-
-# YAD dialog for wallpaper confirmation
-windowrule = match:class ^(yad)$ match:title ^(YAD)$, float on, center on, size (monitor_w*0.2) (monitor_h*0.2)
-# END of float popups and dialogue #######
+windowrule = match:class ^(yad)$, float on, center on, size (monitor_w*0.2) (monitor_h*0.2)
+windowrule = match:class ^(hyprland-donate-screen)$, float on, center on
# OPACITY
windowrule = match:tag browser, opacity 0.99 0.8
@@ -169,7 +179,8 @@ windowrule = match:title ^(Picture-in-Picture)$, pin on, keep_aspect_ratio on
windowrule = match:tag games, no_blur on, fullscreen 0
windowrule = match:tag games, fullscreen 0
-# This not gonna take the focus to the window that appears when hovering over some of the parts of the IntelliJ Products
+# This not gonna take the focus to the window that appears when
+# hovering over some of the parts of the IntelliJ Products
windowrule = match:class ^(jetbrains-*), no_initial_focus on
windowrule = match:title ^(wind.*)$, no_initial_focus on
@@ -178,3 +189,31 @@ layerrule = match:namespace rofi, blur on
layerrule = match:namespace notifications, blur on
layerrule = match:namespace quickshell:overview, blur on
layerrule = match:namespace quickshell:overview, ignore_alpha 0.5
+
+# Named rules for special cases
+windowrule {
+ name = Whatsapp-zapzap
+ match:class = ^([Ww]hatsapp-for-linux|ZapZap|com.rtosta.zapzap)$
+ size = (monitor_w*0.6) (monitor_h*0.7)
+ center = on
+}
+windowrule {
+ name = Picture-in-Picture
+ match:title = ^(Picture-in-Picture)$
+ float = on
+ move = 72% 7%
+ opacity = 0.95 0.75
+ pin = on
+ keep_aspect_ratio = on
+ size = (monitor_w*0.3) (monitor_h*0.3)
+}
+# Thunar copy progress dialog
+windowrule {
+ name = Thunar-Progress-bar
+ match:class = ^(thunar)$
+ match:title = ^(File Operation Progress)$
+ float = on
+ center = on
+ size = (monitor_w*0.26) (monitor_h*0.18)
+}
+
diff --git a/config/hypr/hyprlock-2k.conf b/config/hypr/hyprlock-2k.conf
new file mode 100644
index 00000000..f359357f
--- /dev/null
+++ b/config/hypr/hyprlock-2k.conf
@@ -0,0 +1,183 @@
+# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ #
+# Hyprlock config for => 2k monitor resolutions
+# Original config submitted by https://github.com/SherLock707
+
+# Sourcing colors generated by wallust
+source = $HOME/.config/hypr/wallust/wallust-hyprland.conf
+$Scripts = $HOME/.config/hypr/scripts
+
+general {
+ grace = 1
+ fractional_scaling = 2
+ immediate_render = true
+}
+
+background {
+ monitor =
+ # NOTE: use only 1 path
+ #path = screenshot # screenshot of your desktop
+ #path = $HOME/.config/hypr/wallpaper_effects/.wallpaper_modified # by wallpaper effects
+ path = $HOME/.config/hypr/wallpaper_effects/.wallpaper_current # current wallpaper
+
+ color = rgb(0,0,0) # color will be rendered initially until path is available
+
+ # all these options are taken from hyprland, see https://wiki.hyprland.org/Configuring/Variables/#blur for explanations
+ blur_size = 3
+ blur_passes = 2 # 0 disables blurring
+ noise = 0.0117
+ contrast = 1.3000 # Vibrant!!!
+ brightness = 0.8000
+ vibrancy = 0.2100
+ vibrancy_darkness = 0.0
+}
+
+
+# Date
+label {
+ monitor =
+ text = cmd[update:18000000] echo "<b> "$(date +'%A, %-d %B')" </b>"
+ color = $color13
+ font_size = 64
+ font_family = Victor Mono Bold Italic
+ position = 0, -20
+ halign = center
+ valign = center
+}
+
+# Hour-Time (single horizontal time like 1080p variant)
+label {
+ monitor =
+# text = cmd[update:1000] echo "$(date +"%H:%M")" # 24h option
+ text = cmd[update:1000] echo "$(date +"%I:%M %p")" # AM/PM
+ #color = rgba(255, 185, 0, .8)
+ color = $color8
+ font_size = 173
+ font_family = JetBrainsMono Nerd Font ExtraBold
+ position = 0, -133
+ halign = center
+ valign = top
+}
+
+# Minute-Time (disabled; kept for reference)
+# label {
+# monitor =
+# text = cmd[update:1000] echo "$(date +"%M")"
+# #color = rgba(15, 10, 222, .8)
+# color = $color12
+# font_size = 240
+# font_family = JetBrainsMono Nerd Font ExtraBold
+# position = 0, -450
+# halign = center
+# valign = top
+# }
+
+# Seconds-Time (disabled; kept for reference)
+# label {
+# monitor =
+# text = cmd[update:1000] echo "$(date +"%S")"
+# # text = cmd[update:1000] echo "$(date +"%S %p")" #AM/PM
+# color = $color11
+# font_size = 50
+# font_family = JetBrainsMono Nerd Font ExtraBold
+# position = 0, -450
+# halign = center
+# valign = top
+# }
+
+# Put a picture of choice here. Default is the current wallpaper
+#image {
+# monitor =
+# #path = $HOME/.config/hypr/wallpaper_effects/.wallpaper_current
+# size = 160
+# rounding = -1
+# border_size = 0
+# border_color = $color11
+# rotate = 0
+# reload_time = -1
+# position = 0, 400
+# halign = center
+# valign = bottom
+#}
+
+# USER
+label {
+ monitor =
+ text =  $USER
+ color = $color9
+ font_size = 48
+ font_family = Victor Mono Bold Oblique
+ position = 0, 300
+ halign = center
+ valign = bottom
+}
+
+# INPUT FIELD
+input-field {
+ monitor =
+ size = 306, 93
+ outline_thickness = 2
+ dots_size = 0.2 # Scale of input-field height, 0.2 - 0.8
+ dots_spacing = 0.2 # Scale of dots' absolute size, 0.0 - 1.0
+ dots_center = true
+ outer_color = $color8
+ inner_color = rgba(255, 255, 255, 0.1)
+ capslock_color = rgb(255,255,255)
+ font_color = $color13
+ fade_on_empty = false
+ font_family = Victor Mono Bold Oblique
+ placeholder_text = <i><span foreground="##ffffff99">🔒 Type Password</span></i>
+ hide_input = false
+ position = 0, 100
+ halign = center
+ valign = bottom
+}
+
+# Keyboard LAYOUT
+label {
+ monitor =
+ text = $LAYOUT
+ color = $color8
+ font_size = 19
+ font_family = Victor Mono Bold Oblique
+ position = 0, 53
+ halign = center
+ valign = bottom
+}
+
+# uptime
+label {
+ monitor =
+ text = cmd[update:60000] echo "<b> "$(uptime -p || $Scripts/UptimeNixOS.sh)" </b>"
+ color = $color8
+ font_size = 32
+ font_family = Victor Mono Bold Oblique
+ position = 0, 0
+ halign = right
+ valign = bottom
+}
+
+# battery information
+label {
+ monitor =
+ text = cmd[update:1000] echo "<b> "$($Scripts/Battery.sh)" </b>"
+ color = $color8
+ font_size = 21
+ font_family = Victor Mono Bold Oblique
+ position = 0, 40
+ halign = right
+ valign = bottom
+}
+
+# weather edit the scripts for locations
+# weather scripts are located in ~/.config/hypr/UserScripts Weather.sh and/or Weather.py
+# see https://github.com/JaKooLit/Hyprland-Dots/wiki/TIPS#%EF%B8%8F-weather-app-related-for-waybar-and-hyprlock
+label {
+ monitor =
+ text = cmd[update:3600000] [ -f "$HOME/.cache/.weather_cache" ] && cat "$HOME/.cache/.weather_cache"
+ color = $color8
+ font_size = 19
+ font_family = Victor Mono Bold Oblique
+ position = 50, 0
+ halign = left
+ valign = bottom
+}
diff --git a/config/hypr/initial-boot.sh b/config/hypr/initial-boot.sh
index 1313f104..eeabdef5 100755
--- a/config/hypr/initial-boot.sh
+++ b/config/hypr/initial-boot.sh
@@ -49,9 +49,6 @@ if [ ! -f "$HOME/.config/hypr/.initial_startup_done" ]; then
# initiate kvantum theme
kvantummanager --set "$kvantum_theme" > /dev/null 2>&1 &
- # initiate the kb_layout (for some reason) waybar cant launch it
- "$scriptsDir/SwitchKeyboardLayout.sh" > /dev/null 2>&1 &
-
# waybar style
#if [ -L "$HOME/.config/waybar/config" ]; then
## ln -sf "$waybar_style" "$HOME/.config/waybar/style.css"
diff --git a/config/hypr/scripts/ChangeLayout.sh b/config/hypr/scripts/ChangeLayout.sh
index e2436b79..221f9637 100755
--- a/config/hypr/scripts/ChangeLayout.sh
+++ b/config/hypr/scripts/ChangeLayout.sh
@@ -6,19 +6,34 @@ notif="$HOME/.config/swaync/images/ja.png"
LAYOUT=$(hyprctl -j getoption general:layout | jq '.str' | sed 's/"//g')
+# Reverse layout value to reuse toggle logic. So layouts don't get swapped initially.
+if [ "$1" = "init" ]; then
+ if [ "$LAYOUT" = "master" ]; then
+ LAYOUT="dwindle"
+ else
+ LAYOUT="master"
+ fi
+fi
+
case $LAYOUT in
"master")
- hyprctl keyword general:layout dwindle
- # SUPER+J/K are global and managed by KeybindsLayoutInit.sh; only manage SUPER+O here
- hyprctl keyword bind SUPER,O,togglesplit
+ hyprctl keyword general:layout dwindle
+ hyprctl keyword unbind SUPER,J
+ hyprctl keyword unbind SUPER,K
+ hyprctl keyword bind SUPER,J,cyclenext
+ hyprctl keyword bind SUPER,K,cyclenext,prev
+ hyprctl keyword bind SUPER,O,togglesplit
notify-send -e -u low -i "$notif" " Dwindle Layout"
- ;;
+ ;;
"dwindle")
- hyprctl keyword general:layout master
- # Drop togglesplit binding on SUPER+O when switching back to master
- hyprctl keyword unbind SUPER,O
+ hyprctl keyword general:layout master
+ hyprctl keyword unbind SUPER,J
+ hyprctl keyword unbind SUPER,K
+ hyprctl keyword unbind SUPER,O
+ hyprctl keyword bind SUPER,J,layoutmsg,cyclenext
+ hyprctl keyword bind SUPER,K,layoutmsg,cycleprev
notify-send -e -u low -i "$notif" " Master Layout"
- ;;
+ ;;
*) ;;
esac
diff --git a/config/hypr/scripts/DarkLight.sh b/config/hypr/scripts/DarkLight.sh
index e473efb2..37016ec3 100755
--- a/config/hypr/scripts/DarkLight.sh
+++ b/config/hypr/scripts/DarkLight.sh
@@ -4,7 +4,8 @@
# Note: Scripts are looking for keywords Light or Dark except for wallpapers as the are in a separate directories
# Paths
-wallpaper_base_path="$HOME/Pictures/wallpapers/Dynamic-Wallpapers"
+PICTURES_DIR="$(xdg-user-dir PICTURES 2>/dev/null || echo "$HOME/Pictures")"
+wallpaper_base_path="$PICTURES_DIR/wallpapers/Dynamic-Wallpapers"
dark_wallpapers="$wallpaper_base_path/Dark"
light_wallpapers="$wallpaper_base_path/Light"
hypr_config_path="$HOME/.config/hypr"
@@ -19,6 +20,10 @@ kitty_conf="$HOME/.config/kitty/kitty.conf"
wallust_config="$HOME/.config/wallust/wallust.toml"
pallete_dark="dark16"
pallete_light="light16"
+qt5ct_dark="$HOME/.config/qt5ct/colors/Catppuccin-Mocha.conf"
+qt5ct_light="$HOME/.config/qt5ct/colors/Catppuccin-Latte.conf"
+qt6ct_dark="$HOME/.config/qt6ct/colors/Catppuccin-Mocha.conf"
+qt6ct_light="$HOME/.config/qt6ct/colors/Catppuccin-Latte.conf"
# intial kill process
for pid in waybar rofi swaync ags swaybg; do
@@ -43,6 +48,14 @@ else
# Logic for Light mode
wallpaper_path="$light_wallpapers"
fi
+# Select Qt color scheme templates for the upcoming mode
+if [ "$next_mode" = "Dark" ]; then
+ qt5ct_color_scheme="$qt5ct_dark"
+ qt6ct_color_scheme="$qt6ct_dark"
+else
+ qt5ct_color_scheme="$qt5ct_light"
+ qt6ct_color_scheme="$qt6ct_light"
+fi
# Function to update theme mode for the next cycle
update_theme_mode() {
diff --git a/config/hypr/scripts/Distro_update.sh b/config/hypr/scripts/Distro_update.sh
index 2b3376e3..917f303b 100755
--- a/config/hypr/scripts/Distro_update.sh
+++ b/config/hypr/scripts/Distro_update.sh
@@ -27,7 +27,7 @@ elif command -v dnf &> /dev/null; then
notify-send -i "$iDIR/ja.png" -u low 'Fedora system' 'has been updated.'
elif command -v apt &> /dev/null; then
# Debian-based (Debian, Ubuntu, etc.)
- kitty -T update sudo apt update && sudo apt upgrade -y
+ kitty -T update bash -c "sudo apt update && sudo apt upgrade -y"
notify-send -i "$iDIR/ja.png" -u low 'Debian/Ubuntu system' 'has been updated.'
elif command -v zypper &> /dev/null; then
# openSUSE-based
diff --git a/config/hypr/scripts/Hypridle.sh b/config/hypr/scripts/Hypridle.sh
index 6acff434..a9bb90d7 100755
--- a/config/hypr/scripts/Hypridle.sh
+++ b/config/hypr/scripts/Hypridle.sh
@@ -15,7 +15,8 @@ elif [[ "$1" == "toggle" ]]; then
if pgrep -x "$PROCESS" >/dev/null; then
pkill "$PROCESS"
else
- "$PROCESS"
+ "$PROCESS" >/dev/null 2>&1 &
+ disown
fi
else
echo "Usage: $0 {status|toggle}"
diff --git a/config/hypr/scripts/KeyBinds.sh b/config/hypr/scripts/KeyBinds.sh
index 4158b762..26ae832b 100755
--- a/config/hypr/scripts/KeyBinds.sh
+++ b/config/hypr/scripts/KeyBinds.sh
@@ -21,135 +21,19 @@ msg='☣️ NOTE ☣️: Clicking with Mouse or Pressing ENTER will have NO func
files=("$keybinds_conf" "$user_keybinds_conf")
[[ -f "$laptop_conf" ]] && files+=("$laptop_conf")
-# Parse binds/unbinds from files, detect overrides, and keep unique effective binds
-declare -A binding_map # combo -> bind line (effective)
-declare -A source_map # combo -> source file
-declare -A user_bind_map # combo -> user bind line
-declare -A unbound_user # combo -> 1 if explicitly unbound in user file
-declare -A seen_any_bind # combo -> 1 if any bind seen (for iteration)
-declare -A default_seen # combo -> 1 if default bind exists
-declare -a missing_unbind_suggestions_arr
+# Parse binds using the python script for speed
+# The last argument must be the user config for override logic to work correctly
+display_keybinds=$("$HOME/.config/hypr/scripts/keybinds_parser.py" "${files[@]}")
-normalize_combo() { echo "$1" | sed -E 's/[[:space:]]//g'; }
-
-extract_combo() {
- # arg: a bind/unbind line; returns "mods,key" via echo
- local s="$1"
- s="$(echo "$s" | sed -E 's/[[:space:]]+#.*$//')"
- if [[ "$s" =~ = ]]; then
- local rhs="${s#*=}"
- local mods="$(echo "$rhs" | awk -F',' '{gsub(/^[ \t]+|[ \t]+$/,"",$1); print $1}')"
- local key="$(echo "$rhs" | awk -F',' '{gsub(/^[ \t]+|[ \t]+$/,"",$2); print $2}')"
- echo "${mods},${key}"
- fi
-}
-
-for file in "${files[@]}"; do
- [[ ! -f "$file" ]] && continue
- while IFS= read -r line; do
- [[ -z "$line" || "$line" =~ ^[[:space:]]*# ]] && continue
-
- if [[ "$line" =~ ^[[:space:]]*bind[a-z]*[[:space:]]*= ]]; then
- combo_raw="$(extract_combo "$line")"
- [[ -z "$combo_raw" ]] && continue
- combo="$(normalize_combo "$combo_raw")"
- seen_any_bind["$combo"]=1
-
- if [[ "$file" != "$user_keybinds_conf" ]]; then
- default_seen["$combo"]=1
- fi
-
- # prefer user bind, else first seen
- if [[ -z "${source_map[$combo]}" ]]; then
- binding_map["$combo"]="$line"
- source_map["$combo"]="$file"
- fi
- if [[ "$file" == "$user_keybinds_conf" ]]; then
- user_bind_map["$combo"]="$line"
- binding_map["$combo"]="$line"
- source_map["$combo"]="$file"
- fi
-
- elif [[ "$line" =~ ^[[:space:]]*unbind[[:space:]]*= ]]; then
- combo_raw="$(extract_combo "$line")"
- [[ -z "$combo_raw" ]] && continue
- combo="$(normalize_combo "$combo_raw")"
- if [[ "$file" == "$user_keybinds_conf" ]]; then
- unbound_user["$combo"]=1
- fi
- fi
- done < "$file"
-done
-
-# Build raw_keybinds for display and collect missing unbind suggestions
-raw_keybinds=""
-for combo in "${!seen_any_bind[@]}"; do
- eff_line="${binding_map[$combo]}"
- src="${source_map[$combo]}"
- [[ -z "$eff_line" ]] && continue
- raw_keybinds+="$eff_line"$'\n'
-
- # If user overrides a default but didn't unbind in user file, suggest unbind
- if [[ "$src" == "$user_keybinds_conf" && -n "${default_seen[$combo]}" && -z "${unbound_user[$combo]}" ]]; then
- suggest="$(echo "$eff_line" | sed -E 's/^[[:space:]]*bind[a-z]*/unbind/')"
- missing_unbind_suggestions_arr+=("$suggest")
+# Check for suggestions file created by python script
+if [[ -f "/tmp/hypr_keybind_suggestions_file" ]]; then
+ suggestions_file=$(cat "/tmp/hypr_keybind_suggestions_file")
+ rm "/tmp/hypr_keybind_suggestions_file"
+ if [[ -n "$suggestions_file" && -f "$suggestions_file" ]]; then
+ count=$(wc -l < "$suggestions_file")
+ msg="$msg | Overrides missing unbind: $count (suggestions: $suggestions_file)"
fi
-done
-
-# If there are missing unbinds, write suggestions to a temp file and note in message
-if (( ${#missing_unbind_suggestions_arr[@]} > 0 )); then
- suggestions_file="$(mktemp -t hypr-unbind-suggestions.XXXX.conf)"
- printf '%s\n' "${missing_unbind_suggestions_arr[@]}" > "$suggestions_file"
- msg="$msg | Overrides missing unbind: ${#missing_unbind_suggestions_arr[@]} (suggestions: $suggestions_file)"
fi
-# check for any keybinds to display
-if [[ -z "$raw_keybinds" ]]; then
- echo "no keybinds found."
- exit 1
-fi
-
-# transform into a readable list: MODS+KEY — DESCRIPTION (for bindd) or DISPATCHER [PARAMS] (for bind)
-display_keybinds=$(echo "$raw_keybinds" | awk -F'=' '
- function trim(s){ gsub(/^[ \t]+|[ \t]+$/,"",s); return s }
- /^[[:space:]]*bind/ {
- binder=$1; gsub(/[ \t]/, "", binder);
- hasdesc = (index(binder, "d")>0);
-
- rhs=$2; rhs=trim(rhs);
- n=split(rhs, a, /[ \t]*,[ \t]*/);
-
- mods=trim(a[1]); key=(n>=2?trim(a[2]):"");
- desc=""; dispatcher=""; params="";
-
- if (hasdesc) {
- desc=(n>=3?trim(a[3]):"");
- dispatcher=(n>=4?trim(a[4]):"");
- start=5;
- } else {
- dispatcher=(n>=3?trim(a[3]):"");
- start=4;
- }
-
- for(i=start;i<=n;i++){ if(length(a[i])){ p=trim(a[i]); if(p!="") params = (params?params", ":"") p } }
-
- gsub(/\$mainMod/,"SUPER",mods);
- gsub(/[ \t]+/,"+",mods);
-
- combo = (mods && key) ? mods "+" key : (key?key:mods);
-
- if (hasdesc && desc != "") {
- print combo, " — ", desc;
- } else {
- if (dispatcher != "" && params != "")
- print combo, " — ", dispatcher, " ", params;
- else if (dispatcher != "")
- print combo, " — ", dispatcher;
- else
- print combo;
- }
- }
-')
-
# use rofi to display the keybinds
printf '%s\n' "$display_keybinds" | rofi -dmenu -i -config "$rofi_theme" -mesg "$msg"
diff --git a/config/hypr/scripts/KeyHints.sh b/config/hypr/scripts/KeyHints.sh
index 8a478039..5511cfed 100755
--- a/config/hypr/scripts/KeyHints.sh
+++ b/config/hypr/scripts/KeyHints.sh
@@ -34,6 +34,7 @@ GDK_BACKEND=$BACKEND yad \
" D" "Application Launcher" "(rofi-wayland)" \
" E" "Open File Manager" "(Thunar)" \
" S" "Google Search using rofi" "(rofi)" \
+" T" "Global theme switcher" "(rofi)" \
" Q" "close active window" "(not kill)" \
" Shift Q " "kills an active window" "(kill)" \
" ALT mouse scroll up/down " "Desktop Zoom" "Desktop Magnifier" \
@@ -69,4 +70,4 @@ GDK_BACKEND=$BACKEND yad \
" ALT E" "Rofi Emoticons" "Emoticon" \
" H" "Launch this Quick Cheat Sheet" "" \
"" "" "" \
-"More tips:" "https://github.com/JaKooLit/Hyprland-Dots/wiki" ""\ \ No newline at end of file
+"More tips:" "https://github.com/JaKooLit/Hyprland-Dots/wiki" ""\
diff --git a/config/hypr/scripts/KeyboardLayout.sh b/config/hypr/scripts/KeyboardLayout.sh
new file mode 100755
index 00000000..ec280826
--- /dev/null
+++ b/config/hypr/scripts/KeyboardLayout.sh
@@ -0,0 +1,119 @@
+#!/usr/bin/env bash
+# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
+# This is for changing kb_layouts. Set kb_layouts in "$HOME/.config/hypr/UserConfigs/UserSettings.conf"
+
+notif_icon="$HOME/.config/swaync/images/ja.png"
+SCRIPTSDIR="$HOME/.config/hypr/scripts"
+
+# Refined ignore list with patterns or specific device names
+ignore_patterns=(
+ "--(avrcp)"
+ "Bluetooth Speaker"
+ "Other Device
+ Name"
+)
+
+# Function to get keyboard names
+get_keyboard_names() {
+ hyprctl devices -j | jq -r '.keyboards[].name'
+}
+
+# Function to check if a device matches any ignore pattern
+is_ignored() {
+ local device_name=$1
+ for pattern in "${ignore_patterns[@]}"; do
+ if [[ "$device_name" == *"$pattern"* ]]; then
+ return 0 # Device matches ignore pattern
+ fi
+ done
+ return 1 # Device does not match any ignore pattern
+}
+
+# Function to get current layout info
+# Stores values in layout_mapping, variant_mapping and layout_index
+get_current_layout_info() {
+ local found_kb=false
+
+ # Read from the first non-ignored layout
+ while read -r name; do
+ if ! is_ignored "$name"; then
+ found_kb=true
+ local layout_mapping_str=$(hyprctl devices -j |
+ jq -r --arg name "$name" '.keyboards[] | select(.name==$name).layout')
+ IFS="," read -r -a layout_mapping <<<"$layout_mapping_str"
+
+ local variant_mapping_str=$(hyprctl devices -j |
+ jq -r --arg name "$name" '.keyboards[] | select(.name==$name).variant')
+ IFS="," read -r -a variant_mapping <<<"$variant_mapping_str"
+
+ layout_index=$(hyprctl devices -j |
+ jq -r --arg name "$name" '.keyboards[] | select(.name==$name).active_layout_index')
+ break
+ fi
+ done <<< "$(get_keyboard_names)"
+
+ $found_kb && return 0
+ return 1
+}
+
+# Function to change keyboard layout
+change_layout() {
+ local error_found=false
+
+ while read -r name; do
+ if is_ignored "$name"; then
+ echo "Skipping ignored device: $name"
+ continue
+ fi
+
+ echo "Switching layout for $name to $new_layout..."
+ hyprctl switchxkblayout "$name" "$next_index"
+ if [ $? -ne 0 ]; then
+ echo "Error while switching layout for $name." >&2
+ error_found=true
+ fi
+ done <<<"$(get_keyboard_names)"
+
+ $error_found && return 1
+ return 0
+}
+
+
+# Stores values in layout_mapping, variant_mapping and layout_index
+if ! get_current_layout_info; then
+ echo "Could not get current layout information." >&2
+ echo "There might not be any keyboards available, \
+ or some were unnecessarily set as ignored." >&2
+ notify-send -u low -t 2000 'kb_layout' " Error:" " Layout change failed"
+ echo "Exiting $0 $@" >&2
+ exit 1
+fi
+
+current_layout=${layout_mapping[$layout_index]}
+current_variant=${variant_mapping[$layout_index]}
+
+if [[ "$1" == "status" ]]; then
+ echo "$current_layout${current_variant:+($current_variant)}"
+elif [[ "$1" == "switch" ]]; then
+ echo "Current layout: $current_layout($current_variant)"
+
+ layout_count=${#layout_mapping[@]}
+ echo "Number of layouts: $layout_count"
+
+ next_index=$(( (layout_index + 1) % layout_count ))
+ new_layout="${layout_mapping[$next_index]}"
+ new_variant="${variant_mapping[$next_index]}"
+ echo "Next layout: $new_layout"
+
+ # Execute layout change and notify
+ if ! change_layout; then
+ notify-send -u low -t 2000 'kb_layout' " Error:" " Layout change failed"
+ echo "Layout change failed." >&2
+ exit 1
+ else
+ notify-send -u low -i "$notif_icon" " kb_layout: $new_layout${new_variant:+($new_variant)}"
+ echo "Layout change notification sent."
+ fi
+else
+ echo "Usage: $0 {status|switch}"
+fi
diff --git a/config/hypr/scripts/KillActiveProcess.sh b/config/hypr/scripts/KillActiveProcess.sh
index 2bc108f2..d9d26bb3 100755
--- a/config/hypr/scripts/KillActiveProcess.sh
+++ b/config/hypr/scripts/KillActiveProcess.sh
@@ -7,5 +7,10 @@
# Get id of an active window
active_pid=$(hyprctl activewindow | grep -o 'pid: [0-9]*' | cut -d' ' -f2)
+if [[ -z "$active_pid" || ! "$active_pid" =~ ^[0-9]+$ ]]; then
+ notify-send -u low -i "$HOME/.config/swaync/images/error.png" "Kill Active Window" "No active window PID found."
+ exit 1
+fi
+
# Close active window
-kill $active_pid \ No newline at end of file
+kill "$active_pid"
diff --git a/config/hypr/scripts/KooLsDotsUpdate.sh b/config/hypr/scripts/KooLsDotsUpdate.sh
index 51277ab1..a49f5430 100755
--- a/config/hypr/scripts/KooLsDotsUpdate.sh
+++ b/config/hypr/scripts/KooLsDotsUpdate.sh
@@ -5,12 +5,12 @@
# Local Paths
local_dir="$HOME/.config/hypr"
iDIR="$HOME/.config/swaync/images/"
-local_version=$(ls $local_dir/v* 2>/dev/null | sort -V | tail -n 1 | sed 's/.*v\(.*\)/\1/')
+local_version=$(find "$local_dir" -maxdepth 1 -name 'v*' -printf '%f\n' 2>/dev/null | sort -V | tail -n 1 | sed 's/^v//')
KooL_Dots_DIR="$HOME/Hyprland-Dots"
# exit if cannot find local version
if [ -z "$local_version" ]; then
- notify-send -i "$iDIR/error.png" "ERROR "!?!?!!"" "Unable to find KooL's dots version . exiting.... "
+ notify-send -i "$iDIR/error.png" 'ERROR !?!?!!' "Unable to find KooL's dots version. Exiting."
exit 1
fi
@@ -19,7 +19,7 @@ branch="main"
github_url="https://github.com/JaKooLit/Hyprland-Dots/tree/$branch/config/hypr/"
# Fetch the version from GitHub URL - KooL's dots
-github_version=$(curl -s $github_url | grep -o 'v[0-9]\+\.[0-9]\+\.[0-9]\+' | sort -V | tail -n 1 | sed 's/v//')
+github_version=$(curl -s "$github_url" | grep -o 'v[0-9]\+\.[0-9]\+\.[0-9]\+' | sort -V | tail -n 1 | sed 's/v//')
# Cant find GitHub URL - KooL's dots version
if [ -z "$github_version" ]; then
@@ -39,13 +39,13 @@ else
case "$response" in
"action1")
- if [ -d $KooL_Dots_DIR ]; then
+ if [ -d "$KooL_Dots_DIR" ]; then
if ! command -v kitty &> /dev/null; then
notify-send -i "$iDIR/error.png" "E-R-R-O-R" "Kitty terminal not found. Please install Kitty terminal."
exit 1
fi
kitty -e bash -c "
- cd $KooL_Dots_DIR &&
+ cd \"$KooL_Dots_DIR\" &&
git stash &&
git pull &&
./copy.sh &&
@@ -59,7 +59,7 @@ else
fi
kitty -e bash -c "
git clone --depth=1 https://github.com/JaKooLit/Hyprland-Dots.git $KooL_Dots_DIR &&
- cd $KooL_Dots_DIR &&
+ cd \"$KooL_Dots_DIR\" &&
chmod +x copy.sh &&
./copy.sh &&
notify-send -u critical -i "$iDIR/ja.png" 'Update Completed:' 'Kindly log out and relogin to take effect'
diff --git a/config/hypr/scripts/Kool_Quick_Settings.sh b/config/hypr/scripts/Kool_Quick_Settings.sh
index 8ab71ba2..0cd58f48 100755
--- a/config/hypr/scripts/Kool_Quick_Settings.sh
+++ b/config/hypr/scripts/Kool_Quick_Settings.sh
@@ -22,7 +22,154 @@ UserScripts="$HOME/.config/hypr/UserScripts"
# Function to show info notification
show_info() {
- notify-send -i "$iDIR/info.png" "Info" "$1"
+ if [[ -f "$iDIR/info.png" ]]; then
+ notify-send -i "$iDIR/info.png" "Info" "$1"
+ else
+ notify-send "Info" "$1"
+ fi
+}
+# Function to toggle Rainbow Borders script availability and refresh UI components
+toggle_rainbow_borders() {
+ local rainbow_script="$UserScripts/RainbowBorders.sh"
+ local disabled_sh_bak="${rainbow_script}.bak" # RainbowBorders.sh.bak
+ local disabled_bak_sh="$UserScripts/RainbowBorders.bak.sh" # RainbowBorders.bak.sh (created by copy.sh when disabled)
+ local refresh_script="$scriptsDir/Refresh.sh"
+ local status=""
+
+ # If both disabled variants exist, keep the newer one to avoid ambiguity
+ if [[ -f "$disabled_sh_bak" && -f "$disabled_bak_sh" ]]; then
+ if [[ "$disabled_sh_bak" -nt "$disabled_bak_sh" ]]; then
+ rm -f "$disabled_bak_sh"
+ else
+ rm -f "$disabled_sh_bak"
+ fi
+ fi
+
+ if [[ -f "$rainbow_script" ]]; then
+ # Currently enabled -> disable to canonical .sh.bak
+ if mv "$rainbow_script" "$disabled_sh_bak"; then
+ status="disabled"
+ if command -v hyprctl &>/dev/null; then
+ hyprctl reload >/dev/null 2>&1 || true
+ fi
+ fi
+ elif [[ -f "$disabled_sh_bak" ]]; then
+ # Disabled (.sh.bak) -> enable
+ if mv "$disabled_sh_bak" "$rainbow_script"; then
+ status="enabled"
+ fi
+ elif [[ -f "$disabled_bak_sh" ]]; then
+ # Disabled (.bak.sh) -> enable (normalize to .sh)
+ if mv "$disabled_bak_sh" "$rainbow_script"; then
+ status="enabled"
+ fi
+ else
+ show_info "RainbowBorders script not found in $UserScripts (checked .sh, .sh.bak, .bak.sh)."
+ return
+ fi
+
+ # Run refresh if available, otherwise apply borders directly
+ if [[ -x "$refresh_script" ]]; then
+ "$refresh_script" >/dev/null 2>&1 &
+ elif [[ "$current" != "disabled" && -x "$rainbow_script" ]]; then
+ "$rainbow_script" >/dev/null 2>&1 &
+ fi
+
+ if [[ -n "$status" ]]; then
+ show_info "Rainbow Borders ${status}."
+ fi
+}
+
+# Submenu to choose Rainbow Borders mode (disable, wallust_random, rainbow, gradient_flow)
+rainbow_borders_menu() {
+ local rainbow_script="$UserScripts/RainbowBorders.sh"
+ local disabled_sh_bak="${rainbow_script}.bak"
+ local disabled_bak_sh="$UserScripts/RainbowBorders.bak.sh"
+ local refresh_script="$scriptsDir/Refresh.sh"
+
+ # Determine current mode/status (internal)
+ local current="disabled"
+ if [[ -f "$rainbow_script" ]]; then
+ current=$(grep -E '^EFFECT_TYPE=' "$rainbow_script" 2>/dev/null | sed -E 's/^EFFECT_TYPE="?([^"]*)"?/\1/')
+ [[ -z "$current" ]] && current="unknown"
+ fi
+
+ # Map internal mode to friendly display
+ local current_display="$current"
+ case "$current" in
+ wallust_random) current_display="Wallust Color" ;;
+ rainbow) current_display="Original Rainbow" ;;
+ gradient_flow) current_display="Gradient Flow" ;;
+ disabled) current_display="Disabled" ;;
+ esac
+
+
+ # Build options and prompt
+ local options="Disable Rainbow Borders\nWallust Color\nOriginal Rainbow\nGradient Flow"
+ local choice
+ choice=$(printf "%b" "$options" | rofi -i -dmenu -config "$rofi_theme" -mesg "Rainbow Borders: current = $current_display")
+
+ [[ -z "$choice" ]] && return
+
+ local previous="$current"
+
+ case "$choice" in
+ "Disable Rainbow Borders")
+ if [[ -f "$rainbow_script" ]]; then
+ mv "$rainbow_script" "$disabled_sh_bak"
+ fi
+ current="disabled"
+ if command -v hyprctl &>/dev/null; then
+ hyprctl reload >/dev/null 2>&1 || true
+ fi
+ ;;
+ "Wallust Color"|"Original Rainbow"|"Gradient Flow")
+ local mode=""
+ case "$choice" in
+ "Wallust Color") mode="wallust_random" ;;
+ "Original Rainbow") mode="rainbow" ;;
+ "Gradient Flow") mode="gradient_flow" ;;
+ esac
+ # Ensure script is enabled
+ if [[ ! -f "$rainbow_script" ]]; then
+ if [[ -f "$disabled_sh_bak" ]]; then
+ mv "$disabled_sh_bak" "$rainbow_script"
+ elif [[ -f "$disabled_bak_sh" ]]; then
+ mv "$disabled_bak_sh" "$rainbow_script"
+ else
+ show_info "RainbowBorders script not found in $UserScripts."
+ return
+ fi
+ fi
+
+ # Update EFFECT_TYPE in place; insert if missing
+ if grep -q '^EFFECT_TYPE=' "$rainbow_script" 2>/dev/null; then
+ sed -i 's/^EFFECT_TYPE=.*/EFFECT_TYPE="'"$mode"'"/' "$rainbow_script"
+ else
+ if head -n1 "$rainbow_script" | grep -q '^#!'; then
+ sed -i '1a EFFECT_TYPE="'"$mode"'"' "$rainbow_script"
+ else
+ sed -i '1i EFFECT_TYPE="'"$mode"'"' "$rainbow_script"
+ fi
+ fi
+ # Set current to chosen mode
+ current="$mode"
+ ;;
+ *)
+ return ;;
+ esac
+
+ # Run refresh if available
+ if [[ -x "$refresh_script" ]]; then
+ "$refresh_script" >/dev/null 2>&1 &
+ fi
+
+ # Apply mode immediately (in case refresh doesn't trigger it)
+ if [[ "$current" != "disabled" && -x "$rainbow_script" ]]; then
+ "$rainbow_script" >/dev/null 2>&1 &
+ fi
+
+ # No notifications; mode is shown in the menu
}
# Function to display the menu options without numbers
@@ -44,6 +191,7 @@ Edit System Default Startup Apps
Edit System Default Window Rules
Edit System Default Settings
--- UTILITIES ---
+Set SDDM Wallpaper
Choose Kitty Terminal Theme
Configure Monitors (nwg-displays)
Configure Workspace Rules (nwg-displays)
@@ -56,6 +204,7 @@ Choose Rofi Themes
Search for Keybinds
Toggle Game Mode
Switch Dark-Light Theme
+Rainbow Borders Mode
EOF
}
@@ -78,6 +227,7 @@ main() {
"Edit System Default Startup Apps") file="$configs/Startup_Apps.conf" ;;
"Edit System Default Window Rules") file="$configs/WindowRules.conf" ;;
"Edit System Default Settings") file="$configs/SystemSettings.conf" ;;
+ "Set SDDM Wallpaper") $scriptsDir/sddm_wallpaper.sh --normal ;;
"Choose Kitty Terminal Theme") $scriptsDir/Kitty_themes.sh ;;
"Configure Monitors (nwg-displays)")
if ! command -v nwg-displays &>/dev/null; then
@@ -115,6 +265,7 @@ main() {
"Search for Keybinds") $scriptsDir/KeyBinds.sh ;;
"Toggle Game Mode") $scriptsDir/GameMode.sh ;;
"Switch Dark-Light Theme") $scriptsDir/DarkLight.sh ;;
+ "Rainbow Borders Mode") rainbow_borders_menu ;;
*) return ;; # Do nothing for invalid choices
esac
diff --git a/config/hypr/scripts/PortalHyprland.sh b/config/hypr/scripts/PortalHyprland.sh
index 21cb7db4..653e9b58 100755
--- a/config/hypr/scripts/PortalHyprland.sh
+++ b/config/hypr/scripts/PortalHyprland.sh
@@ -2,15 +2,39 @@
# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
# For manually starting xdg-desktop-portal-hyprland
+set -euo pipefail
+
+kill_quietly() {
+ killall -q "$1" 2>/dev/null || true
+}
+
+start_portal_binary() {
+ local description="$1"
+ shift
+ for candidate in "$@"; do
+ if [[ -x "$candidate" ]]; then
+ "$candidate" &
+ return 0
+ fi
+ done
+ echo "Warning: no $description binary found (checked: $*)" >&2
+ return 1
+}
+
sleep 1
-killall xdg-desktop-portal-hyprland
-killall xdg-desktop-portal-wlr
-killall xdg-desktop-portal-gnome
-killall xdg-desktop-portal
+kill_quietly xdg-desktop-portal-hyprland
+kill_quietly xdg-desktop-portal-wlr
+kill_quietly xdg-desktop-portal-gnome
+kill_quietly xdg-desktop-portal
sleep 1
-/usr/lib/xdg-desktop-portal-hyprland &
-/usr/libexec/xdg-desktop-portal-hyprland &
+
+start_portal_binary "xdg-desktop-portal-hyprland" \
+ /usr/lib/xdg-desktop-portal-hyprland \
+ /usr/libexec/xdg-desktop-portal-hyprland
+
sleep 2
-/usr/lib/xdg-desktop-portal &
-/usr/libexec/xdg-desktop-portal &
+
+start_portal_binary "xdg-desktop-portal" \
+ /usr/lib/xdg-desktop-portal \
+ /usr/libexec/xdg-desktop-portal
diff --git a/config/hypr/scripts/RofiSearch.sh b/config/hypr/scripts/RofiSearch.sh
index 8ef12c46..dfeb19ac 100755
--- a/config/hypr/scripts/RofiSearch.sh
+++ b/config/hypr/scripts/RofiSearch.sh
@@ -4,6 +4,10 @@
# Define the path to the config file
config_file=$HOME/.config/hypr/UserConfigs/01-UserDefaults.conf
+if ! command -v jq >/dev/null 2>&1; then
+ notify-send -u low "Rofi Search" "jq is required for URL encoding. Please install jq."
+ exit 1
+fi
# Check if the config file exists
if [[ ! -f "$config_file" ]]; then
@@ -32,5 +36,12 @@ if pgrep -x "rofi" >/dev/null; then
pkill rofi
fi
-# Open Rofi and pass the selected query to xdg-open for Google search
-echo "" | rofi -dmenu -config "$rofi_theme" -mesg "$msg" | xargs -I{} xdg-open $Search_Engine \ No newline at end of file
+# Open Rofi and pass the selected query to xdg-open for the configured search engine
+query=$(printf '' | rofi -dmenu -config "$rofi_theme" -mesg "$msg")
+
+if [[ -z "$query" ]]; then
+ exit 0
+fi
+
+encoded_query=$(printf '%s' "$query" | jq -sRr @uri)
+xdg-open "${Search_Engine}${encoded_query}" >/dev/null 2>&1 &
diff --git a/config/hypr/scripts/ScreenShot.sh b/config/hypr/scripts/ScreenShot.sh
index 0ef70964..3d578a51 100755
--- a/config/hypr/scripts/ScreenShot.sh
+++ b/config/hypr/scripts/ScreenShot.sh
@@ -4,7 +4,8 @@
# variables
time=$(date "+%d-%b_%H-%M-%S")
-dir="$(xdg-user-dir PICTURES)/Screenshots"
+PICTURES_DIR="$(xdg-user-dir PICTURES 2>/dev/null || echo "$HOME/Pictures")"
+dir="$PICTURES_DIR/Screenshots"
file="Screenshot_${time}_${RANDOM}.png"
iDIR="$HOME/.config/swaync/icons"
diff --git a/config/hypr/scripts/Sounds.sh b/config/hypr/scripts/Sounds.sh
index b372d714..e92248da 100755
--- a/config/hypr/scripts/Sounds.sh
+++ b/config/hypr/scripts/Sounds.sh
@@ -73,5 +73,18 @@ if ! test -f "$sound_file"; then
fi
fi
-# pipewire priority, fallback pulseaudio
-pw-play "$sound_file" || pa-play "$sound_file" \ No newline at end of file
+# Play the sound: prefer PipeWire, then PulseAudio, then ALSA
+if command -v pw-play >/dev/null 2>&1; then
+ pw-play "$sound_file" && exit 0
+fi
+
+if command -v paplay >/dev/null 2>&1; then
+ paplay "$sound_file" && exit 0
+fi
+
+if command -v aplay >/dev/null 2>&1; then
+ aplay "$sound_file" && exit 0
+fi
+
+echo "Error: No suitable audio player (pw-play/paplay/aplay) found."
+exit 1
diff --git a/config/hypr/scripts/SwitchKeyboardLayout.sh b/config/hypr/scripts/SwitchKeyboardLayout.sh
deleted file mode 100755
index 34d008a1..00000000
--- a/config/hypr/scripts/SwitchKeyboardLayout.sh
+++ /dev/null
@@ -1,103 +0,0 @@
-#!/usr/bin/env bash
-# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ ##
-# This is for changing kb_layouts. Set kb_layouts in $settings_file
-
-layout_file="$HOME/.cache/kb_layout"
-settings_file="$HOME/.config/hypr/configs/SystemSettings.conf"
-notif_icon="$HOME/.config/swaync/images/ja.png"
-
-# Refined ignore list with patterns or specific device names
-ignore_patterns=(
- "--(avrcp)"
- "Bluetooth Speaker"
- "Other Device
- Name"
-)
-
-# Create layout file with default layout if it does not exist
-if [ ! -f "$layout_file" ]; then
- echo "Creating layout file..."
- default_layout=$(grep 'kb_layout = ' "$settings_file" | cut -d '=' -f 2 | tr -d '[:space:]' | cut -d ',' -f 1 2>/dev/null)
- default_layout=${default_layout:-"us"} # Default to 'us' layout
- echo "$default_layout" >"$layout_file"
- echo "Default layout set to $default_layout"
-fi
-
-current_layout=$(cat "$layout_file")
-echo "Current layout: $current_layout"
-
-# Read available layouts from settings file
-if [ -f "$settings_file" ]; then
- kb_layout_line=$(grep 'kb_layout = ' "$settings_file" | cut -d '=' -f 2)
- # Remove leading and trailing spaces around each layout
- kb_layout_line=$(echo "$kb_layout_line" | tr -d '[:space:]')
- IFS=',' read -r -a layout_mapping <<<"$kb_layout_line"
-else
- echo "Settings file not found!"
- exit 1
-fi
-
-layout_count=${#layout_mapping[@]}
-echo "Number of layouts: $layout_count"
-
-# Find current layout index and calculate next layout
-for ((i = 0; i < layout_count; i++)); do
- if [ "$current_layout" == "${layout_mapping[i]}" ]; then
- current_index=$i
- break
- fi
-done
-
-next_index=$(((current_index + 1) % layout_count))
-new_layout="${layout_mapping[next_index]}"
-echo "Next layout: $new_layout"
-
-# Function to get keyboard names
-get_keyboard_names() {
- hyprctl devices -j | jq -r '.keyboards[].name'
-}
-
-# Function to check if a device matches any ignore pattern
-is_ignored() {
- local device_name=$1
- for pattern in "${ignore_patterns[@]}"; do
- if [[ "$device_name" == *"$pattern"* ]]; then
- return 0 # Device matches ignore pattern
- fi
- done
- return 1 # Device does not match any ignore pattern
-}
-
-# Function to change keyboard layout
-change_layout() {
- local error_found=false
-
- while read -r name; do
- if is_ignored "$name"; then
- echo "Skipping ignored device: $name"
- continue
- fi
-
- echo "Switching layout for $name to $new_layout..."
- hyprctl switchxkblayout "$name" "$next_index"
- if [ $? -ne 0 ]; then
- echo "Error while switching layout for $name." >&2
- error_found=true
- fi
- done <<<"$(get_keyboard_names)"
-
- $error_found && return 1
- return 0
-}
-
-# Execute layout change and notify
-if ! change_layout; then
- notify-send -u low -t 2000 'kb_layout' " Error:" " Layout change failed"
- echo "Layout change failed." >&2
- exit 1
-else
- notify-send -u low -i "$notif_icon" " kb_layout: $new_layout"
- echo "Layout change notification sent."
-fi
-
-echo "$new_layout" >"$layout_file"
diff --git a/config/hypr/scripts/Tak0-Per-Window-Switch.sh b/config/hypr/scripts/Tak0-Per-Window-Switch.sh
index 7879fb85..7cec89a6 100755
--- a/config/hypr/scripts/Tak0-Per-Window-Switch.sh
+++ b/config/hypr/scripts/Tak0-Per-Window-Switch.sh
@@ -17,6 +17,7 @@ MAP_FILE="$HOME/.cache/kb_layout_per_window"
CFG_FILE="$HOME/.config/hypr/configs/SystemSettings.conf"
ICON="$HOME/.config/swaync/images/ja.png"
SCRIPT_NAME="$(basename "$0")"
+LISTENER_PIDFILE="$HOME/.cache/kb_layout_per_window.listener.pid"
# Ensure map file exists
touch "$MAP_FILE"
@@ -99,7 +100,7 @@ subscribe() {
local SOCKET2="$XDG_RUNTIME_DIR/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock"
[[ -S "$SOCKET2" ]] || {
echo "Error: Hyprland socket not found." >&2
- exit 1
+ return 1
}
socat -u UNIX-CONNECT:"$SOCKET2" - | while read -r line; do
@@ -108,9 +109,20 @@ subscribe() {
}
# Ensure only one listener
-if ! pgrep -f "$SCRIPT_NAME.*--listener" >/dev/null; then
- subscribe --listener &
-fi
+start_listener_once() {
+ if [[ -f "$LISTENER_PIDFILE" ]]; then
+ local existing_pid
+ existing_pid=$(cat "$LISTENER_PIDFILE" 2>/dev/null || true)
+ if [[ -n "$existing_pid" ]] && kill -0 "$existing_pid" 2>/dev/null; then
+ return
+ fi
+ fi
+
+ subscribe &
+ echo $! >"$LISTENER_PIDFILE"
+}
+
+start_listener_once
# CLI
case "$1" in
diff --git a/config/hypr/scripts/ThemeChanger.sh b/config/hypr/scripts/ThemeChanger.sh
new file mode 100755
index 00000000..19ee3298
--- /dev/null
+++ b/config/hypr/scripts/ThemeChanger.sh
@@ -0,0 +1,145 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+# SPDX-FileCopyrightText: 2025-present Ahum Maitra theahummaitra@gmail.com
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+# Repository url : https://github.com/TheAhumMaitra/cautious-waddle
+
+require() {
+ command -v "$1" >/dev/null 2>&1 || {
+ printf '%s\n' "Missing dependency: $1" >&2
+ exit 127
+ }
+}
+
+require wallust
+require rofi
+
+# notify-send is optional
+have_notify() { command -v notify-send >/dev/null 2>&1; }
+
+# Prompt for theme; guard -e on cancel
+set +e
+choice="$(wallust theme list \
+ | sed -e '1d' -e 's/^- //' \
+ | rofi -dmenu -i -p 'Select Global Theme')"
+prompt_status=$?
+set -e
+
+# Exit cleanly on cancel or empty selection
+if (( prompt_status != 0 )) || [[ -z "${choice}" ]]; then
+ exit 0
+fi
+
+# Record time before applying so we can wait for fresh template outputs
+start_ts=$(date +%s)
+
+# Apply the theme and report result
+if wallust theme -- "${choice}"; then
+ have_notify && notify-send -a ThemeChanger \
+ -h string:x-dunst-stack-tag:themechanger \
+ "Global theme changed" "Selected: ${choice}"
+
+ # Wait until template targets exist, are newer than start_ts, and are stable (size/mtime stops changing)
+ # Ensure Ghostty directory exists so Wallust can write target even if Ghostty isn't installed
+ mkdir -p "$HOME/.config/ghostty" || true
+
+ targets=(
+ "$HOME/.config/waybar/wallust/colors-waybar.css"
+ "$HOME/.config/rofi/wallust/colors-rofi.rasi"
+ "$HOME/.config/kitty/kitty-themes/01-Wallust.conf"
+ "$HOME/.config/hypr/wallust/wallust-hyprland.conf"
+ "$HOME/.config/ghostty/wallust.conf"
+ )
+
+ # Normalize Ghostty palette syntax in case upstream templates or older targets used ':'
+ ghostty_conf="$HOME/.config/ghostty/wallust.conf"
+ if [ -f "$ghostty_conf" ]; then
+ sed -i -E 's/^(\s*palette\s*=\s*)([0-9]{1,2}):/\1\2=/' "$ghostty_conf" 2>/dev/null || true
+ fi
+
+ # Phase 1: appearance + freshness
+ for _ in $(seq 1 100); do # up to ~10s
+ ok=1
+ for f in "${targets[@]}"; do
+ [ -s "$f" ] || { ok=0; break; }
+ mtime=$(stat -c %Y "$f" 2>/dev/null || echo 0)
+ [ "$mtime" -ge "$start_ts" ] || { ok=0; break; }
+ done
+ [ $ok -eq 1 ] && break
+ sleep 0.1
+ done
+
+ # Phase 2: stability (avoid reading half-written files)
+ if [ $ok -eq 1 ]; then
+ for _ in 1 2 3; do
+ sizes_a=(); mtimes_a=()
+ for f in "${targets[@]}"; do
+ sizes_a+=("$(stat -c %s "$f" 2>/dev/null || echo 0)")
+ mtimes_a+=("$(stat -c %Y "$f" 2>/dev/null || echo 0)")
+ done
+ sleep 0.15
+ sizes_b=(); mtimes_b=()
+ for f in "${targets[@]}"; do
+ sizes_b+=("$(stat -c %s "$f" 2>/dev/null || echo 0)")
+ mtimes_b+=("$(stat -c %Y "$f" 2>/dev/null || echo 0)")
+ done
+ if [ "${sizes_a[*]}" = "${sizes_b[*]}" ] && [ "${mtimes_a[*]}" = "${mtimes_b[*]}" ]; then
+ break
+ fi
+ done
+ else
+ # As a safety net, wait a bit to avoid racing rofi reload against template writes
+ sleep 0.5
+ fi
+
+ # Small cushion before refresh to mirror wallpaper flow
+ sleep 0.2
+ # Normalize Rofi selection colors to use the palette's accent (color12)
+ rofi_colors="$HOME/.config/rofi/wallust/colors-rofi.rasi"
+ if [ -f "$rofi_colors" ]; then
+ accent_hex=$(sed -n 's/^\s*color12:\s*\(#[0-9A-Fa-f]\{6\}\).*/\1/p' "$rofi_colors" | head -n1)
+ [ -z "$accent_hex" ] && accent_hex=$(sed -n 's/^\s*color13:\s*\(#[0-9A-Fa-f]\{6\}\).*/\1/p' "$rofi_colors" | head -n1)
+ if [ -n "$accent_hex" ]; then
+ sed -i -E "s|^(\s*selected-normal-background:\s*).*$|\1$accent_hex;|" "$rofi_colors"
+ sed -i -E "s|^(\s*selected-active-background:\s*).*$|\1$accent_hex;|" "$rofi_colors"
+ sed -i -E "s|^(\s*selected-urgent-background:\s*).*$|\1$accent_hex;|" "$rofi_colors"
+ sed -i -E "s|^(\s*selected-normal-foreground:\s*).*$|\1#000000;|" "$rofi_colors"
+ sed -i -E "s|^(\s*selected-active-foreground:\s*).*$|\1#000000;|" "$rofi_colors"
+ sed -i -E "s|^(\s*selected-urgent-foreground:\s*).*$|\1#000000;|" "$rofi_colors"
+ fi
+ fi
+
+ # Reload Hyprland so new border colors from wallust-hyprland.conf take effect
+ if command -v hyprctl >/dev/null 2>&1; then
+ hyprctl reload >/dev/null 2>&1 || true
+ fi
+
+ # Refresh bars/menus after files are ready
+ if [ -x "$HOME/.config/hypr/scripts/Refresh.sh" ]; then
+ "$HOME/.config/hypr/scripts/Refresh.sh" >/dev/null 2>&1 || true
+ else
+ if command -v waybar-msg >/dev/null 2>&1; then
+ waybar-msg cmd reload >/dev/null 2>&1 || true
+ else
+ pkill -SIGUSR2 waybar >/dev/null 2>&1 || true
+ fi
+ fi
+
+ # Ask kitty to reload its config so the new 01-Wallust.conf is picked up
+ if pidof kitty >/dev/null; then
+ for pid in $(pidof kitty); do kill -SIGUSR1 "$pid" 2>/dev/null || true; done
+ fi
+
+ # Ask ghostty to reload its config so the updated wallust.conf is applied
+ if pidof ghostty >/dev/null; then
+ for pid in $(pidof ghostty); do kill -SIGUSR2 "$pid" 2>/dev/null || true; done
+ fi
+else
+ have_notify && notify-send -u critical -a ThemeChanger \
+ -h string:x-dunst-stack-tag:themechanger \
+ "Failed to apply theme" "${choice}"
+ exit 1
+fi
diff --git a/config/hypr/scripts/TouchPad.sh b/config/hypr/scripts/TouchPad.sh
index 030c36de..f14165a0 100755
--- a/config/hypr/scripts/TouchPad.sh
+++ b/config/hypr/scripts/TouchPad.sh
@@ -5,28 +5,50 @@
# use hyprctl devices to get your system touchpad device name
# source https://github.com/hyprwm/Hyprland/discussions/4283?sort=new#discussioncomment-8648109
+set -euo pipefail
+
notif="$HOME/.config/swaync/images/ja.png"
+laptops_conf="$HOME/.config/hypr/UserConfigs/Laptops.conf"
+
+touchpad_device="${TOUCHPAD_DEVICE:-}"
+if [[ -z "$touchpad_device" && -f "$laptops_conf" ]]; then
+ touchpad_device="$(
+ awk -F= '/^\$Touchpad_Device/ {
+ gsub(/[[:space:]]*/, "", $1);
+ gsub(/^[[:space:]]+|[[:space:]]+$/, "", $2);
+ print $2;
+ exit
+ }' "$laptops_conf"
+ )"
+fi
+
+if [[ -z "$touchpad_device" ]]; then
+ notify-send -u low -i "$notif" " Touchpad" " Device name not set (check Laptops.conf)"
+ exit 1
+fi
-export STATUS_FILE="$XDG_RUNTIME_DIR/touchpad.status"
+touchpad_keyword="${TOUCHPAD_KEYWORD:-device:${touchpad_device}:enabled}"
+status_file="${XDG_RUNTIME_DIR:-/tmp}/touchpad.status"
enable_touchpad() {
- printf "true" >"$STATUS_FILE"
- notify-send -u low -i $notif " Enabling" " touchpad"
- hyprctl keyword '$TOUCHPAD_ENABLED' "true" -r
+ printf "true" >"$status_file"
+ notify-send -u low -i "$notif" " Enabling" " touchpad"
+ hyprctl keyword "$touchpad_keyword" true -r
}
disable_touchpad() {
- printf "false" >"$STATUS_FILE"
- notify-send -u low -i $notif " Disabling" " touchpad"
- hyprctl keyword '$TOUCHPAD_ENABLED' "false" -r
+ printf "false" >"$status_file"
+ notify-send -u low -i "$notif" " Disabling" " touchpad"
+ hyprctl keyword "$touchpad_keyword" false -r
}
-if ! [ -f "$STATUS_FILE" ]; then
- enable_touchpad
-else
- if [ $(cat "$STATUS_FILE") = "true" ]; then
+current_state="false"
+if [[ -f "$status_file" ]]; then
+ current_state="$(<"$status_file")"
+fi
+
+if [[ "$current_state" == "true" ]]; then
disable_touchpad
- elif [ $(cat "$STATUS_FILE") = "false" ]; then
+else
enable_touchpad
- fi
fi
diff --git a/config/hypr/scripts/Volume.sh b/config/hypr/scripts/Volume.sh
index 4c82f543..e1034a68 100755
--- a/config/hypr/scripts/Volume.sh
+++ b/config/hypr/scripts/Volume.sh
@@ -7,8 +7,14 @@ sDIR="$HOME/.config/hypr/scripts"
# Get Volume
get_volume() {
+ if [[ "$(pamixer --get-mute)" == "true" ]]; then
+ echo "Muted"
+ return
+ fi
+
+ local volume
volume=$(pamixer --get-volume)
- if [[ "$volume" -eq "0" ]]; then
+ if [[ "$volume" -eq 0 ]]; then
echo "Muted"
else
echo "$volume %"
@@ -17,12 +23,15 @@ get_volume() {
# Get icons
get_icon() {
- current=$(get_volume)
- if [[ "$current" == "Muted" ]]; then
+ if [[ "$(pamixer --get-mute)" == "true" ]]; then
echo "$iDIR/volume-mute.png"
- elif [[ "${current%\%}" -le 30 ]]; then
+ return
+ fi
+
+ current=$(pamixer --get-volume)
+ if [[ "$current" -le 30 ]]; then
echo "$iDIR/volume-low.png"
- elif [[ "${current%\%}" -le 60 ]]; then
+ elif [[ "$current" -le 60 ]]; then
echo "$iDIR/volume-mid.png"
else
echo "$iDIR/volume-high.png"
@@ -31,11 +40,18 @@ get_icon() {
# Notify
notify_user() {
- if [[ "$(get_volume)" == "Muted" ]]; then
- notify-send -e -h string:x-canonical-private-synchronous:volume_notif -h boolean:SWAYNC_BYPASS_DND:true -u low -i "$(get_icon)" " Volume:" " Muted"
+ local muted="$(pamixer --get-mute)"
+ local level="$(pamixer --get-volume)"
+
+ if [[ "$muted" == "true" || "$level" -eq 0 ]]; then
+ notify-send -e -h string:x-canonical-private-synchronous:volume_notif \
+ -h boolean:SWAYNC_BYPASS_DND:true -u low -i "$(get_icon)" \
+ " Volume:" " Muted"
else
- notify-send -e -h int:value:"$(get_volume | sed 's/%//')" -h string:x-canonical-private-synchronous:volume_notif -h boolean:SWAYNC_BYPASS_DND:true -u low -i "$(get_icon)" " Volume Level:" " $(get_volume)" &&
- "$sDIR/Sounds.sh" --volume
+ notify-send -e -h int:value:"$level" -h string:x-canonical-private-synchronous:volume_notif \
+ -h boolean:SWAYNC_BYPASS_DND:true -u low -i "$(get_icon)" \
+ " Volume Level:" " ${level}%" &&
+ "$sDIR/Sounds.sh" --volume
fi
}
@@ -44,7 +60,7 @@ inc_volume() {
if [ "$(pamixer --get-mute)" == "true" ]; then
toggle_mute
else
- pamixer -i 5 --allow-boost --set-limit 150 && notify_user
+ pamixer -i "$1" --allow-boost --set-limit 150 && notify_user
fi
}
@@ -53,7 +69,7 @@ dec_volume() {
if [ "$(pamixer --get-mute)" == "true" ]; then
toggle_mute
else
- pamixer -d 5 && notify_user
+ pamixer -d "$1" && notify_user
fi
}
@@ -71,13 +87,14 @@ toggle_mic() {
if [ "$(pamixer --default-source --get-mute)" == "false" ]; then
pamixer --default-source -m && notify-send -e -u low -h boolean:SWAYNC_BYPASS_DND:true -i "$iDIR/microphone-mute.png" " Microphone:" " Switched OFF"
elif [ "$(pamixer --default-source --get-mute)" == "true" ]; then
- pamixer -u --default-source u && notify-send -e -u low -h boolean:SWAYNC_BYPASS_DND:true -i "$iDIR/microphone.png" " Microphone:" " Switched ON"
+ pamixer --default-source -u && notify-send -e -u low -h boolean:SWAYNC_BYPASS_DND:true -i "$iDIR/microphone.png" " Microphone:" " Switched ON"
fi
}
# Get Mic Icon
get_mic_icon() {
- current=$(pamixer --default-source --get-volume)
- if [[ "$current" -eq "0" ]]; then
+ local muted="$(pamixer --default-source --get-mute)"
+ local current="$(pamixer --default-source --get-volume)"
+ if [[ "$muted" == "true" || "$current" -eq "0" ]]; then
echo "$iDIR/microphone-mute.png"
else
echo "$iDIR/microphone.png"
@@ -86,8 +103,14 @@ get_mic_icon() {
# Get Microphone Volume
get_mic_volume() {
+ if [[ "$(pamixer --default-source --get-mute)" == "true" ]]; then
+ echo "Muted"
+ return
+ fi
+
+ local volume
volume=$(pamixer --default-source --get-volume)
- if [[ "$volume" -eq "0" ]]; then
+ if [[ "$volume" -eq 0 ]]; then
echo "Muted"
else
echo "$volume %"
@@ -96,9 +119,21 @@ get_mic_volume() {
# Notify for Microphone
notify_mic_user() {
- volume=$(get_mic_volume)
- icon=$(get_mic_icon)
- notify-send -e -h int:value:"$volume" -h "string:x-canonical-private-synchronous:volume_notif" -h boolean:SWAYNC_BYPASS_DND:true -u low -i "$icon" " Mic Level:" " $volume"
+ local muted="$(pamixer --default-source --get-mute)"
+ local level="$(pamixer --default-source --get-volume)"
+ local icon message
+
+ if [[ "$muted" == "true" || "$level" -eq 0 ]]; then
+ icon="$iDIR/microphone-mute.png"
+ notify-send -e -h "string:x-canonical-private-synchronous:volume_notif" \
+ -h boolean:SWAYNC_BYPASS_DND:true -u low -i "$icon" \
+ " Mic Level:" " Muted"
+ else
+ icon="$iDIR/microphone.png"
+ notify-send -e -h int:value:"$level" -h "string:x-canonical-private-synchronous:volume_notif" \
+ -h boolean:SWAYNC_BYPASS_DND:true -u low -i "$icon" \
+ " Mic Level:" " ${level}%"
+ fi
}
# Increase MIC Volume
@@ -113,31 +148,48 @@ inc_mic_volume() {
# Decrease MIC Volume
dec_mic_volume() {
if [ "$(pamixer --default-source --get-mute)" == "true" ]; then
- toggle-mic
+ toggle_mic
else
pamixer --default-source -d 5 && notify_mic_user
fi
}
# Execute accordingly
-if [[ "$1" == "--get" ]]; then
- get_volume
-elif [[ "$1" == "--inc" ]]; then
- inc_volume
-elif [[ "$1" == "--dec" ]]; then
- dec_volume
-elif [[ "$1" == "--toggle" ]]; then
- toggle_mute
-elif [[ "$1" == "--toggle-mic" ]]; then
- toggle_mic
-elif [[ "$1" == "--get-icon" ]]; then
- get_icon
-elif [[ "$1" == "--get-mic-icon" ]]; then
- get_mic_icon
-elif [[ "$1" == "--mic-inc" ]]; then
- inc_mic_volume
-elif [[ "$1" == "--mic-dec" ]]; then
- dec_mic_volume
-else
- get_volume
-fi \ No newline at end of file
+case "$1" in
+"--get")
+ get_volume
+ ;;
+"--inc")
+ inc_volume 5
+ ;;
+"--inc-precise")
+ inc_volume 1
+ ;;
+"--dec")
+ dec_volume 5
+ ;;
+"--dec-precise")
+ dec_volume 1
+ ;;
+"--toggle")
+ toggle_mute
+ ;;
+"--toggle-mic")
+ toggle_mic
+ ;;
+"--get-icon")
+ get_icon
+ ;;
+"--get-mic-icon")
+ get_mic_icon
+ ;;
+"--mic-inc")
+ inc_mic_volume
+ ;;
+"--mic-dec")
+ dec_mic_volume
+ ;;
+*)
+ get_volume
+ ;;
+esac
diff --git a/config/hypr/scripts/WallustSwww.sh b/config/hypr/scripts/WallustSwww.sh
index 657f41ab..63911036 100755
--- a/config/hypr/scripts/WallustSwww.sh
+++ b/config/hypr/scripts/WallustSwww.sh
@@ -10,6 +10,27 @@ passed_path="${1:-}"
cache_dir="$HOME/.cache/swww/"
rofi_link="$HOME/.config/rofi/.current_wallpaper"
wallpaper_current="$HOME/.config/hypr/wallpaper_effects/.wallpaper_current"
+read_cached_wallpaper() {
+ local cache_file="$1"
+ if [[ -f "$cache_file" ]]; then
+ awk 'NF && $0 !~ /^filter/ {print; exit}' "$cache_file"
+ fi
+}
+
+read_wallpaper_from_query() {
+ local monitor="$1"
+ swww query | awk -v mon="$monitor" '
+ /^Monitor/ {
+ cur=$2
+ gsub(":", "", cur)
+ }
+ /image:/ && cur==mon {
+ sub(/^.*image: /,"")
+ print
+ exit
+ }
+ '
+}
# Helper: get focused monitor name (prefer JSON)
get_focused_monitor() {
@@ -39,8 +60,11 @@ else
if [[ -f "$cache_file" ]]; then
# The first non-filter line is the original wallpaper path
- # wallpaper_path="$(grep -v 'Lanczos3' "$cache_file" | head -n 1)"
- wallpaper_path=$(swww query | grep $current_monitor | awk '{print $9}')
+ wallpaper_path="$(read_cached_wallpaper "$cache_file")"
+ fi
+
+ if [[ -z "$wallpaper_path" ]]; then
+ wallpaper_path="$(read_wallpaper_from_query "$current_monitor")"
fi
fi
@@ -54,6 +78,59 @@ ln -sf "$wallpaper_path" "$rofi_link" || true
mkdir -p "$(dirname "$wallpaper_current")"
cp -f "$wallpaper_path" "$wallpaper_current" || true
+# Ensure Ghostty directory exists so Wallust can write target even if Ghostty isn't installed
+mkdir -p "$HOME/.config/ghostty" || true
+wait_for_templates() {
+ local start_ts="$1"
+ shift
+ local files=("$@")
+ for _ in {1..50}; do
+ local ready=true
+ for file in "${files[@]}"; do
+ if [[ ! -s "$file" ]]; then
+ ready=false
+ break
+ fi
+ local mtime
+ mtime=$(stat -c %Y "$file" 2>/dev/null || echo 0)
+ if (( mtime < start_ts )); then
+ ready=false
+ break
+ fi
+ done
+ $ready && return 0
+ sleep 0.1
+ done
+ return 1
+}
+
# Run wallust (silent) to regenerate templates defined in ~/.config/wallust/wallust.toml
# -s is used in this repo to keep things quiet and avoid extra prompts
+start_ts=$(date +%s)
wallust run -s "$wallpaper_path" || true
+wallust_targets=(
+ "$HOME/.config/waybar/wallust/colors-waybar.css"
+ "$HOME/.config/rofi/wallust/colors-rofi.rasi"
+)
+wait_for_templates "$start_ts" "${wallust_targets[@]}" || true
+
+# Normalize Ghostty palette syntax in case ':' was used by older files
+if [ -f "$HOME/.config/ghostty/wallust.conf" ]; then
+ sed -i -E 's/^(\s*palette\s*=\s*)([0-9]{1,2}):/\1\2=/' "$HOME/.config/ghostty/wallust.conf" 2>/dev/null || true
+fi
+
+# Light wait for Ghostty colors file to be present then signal Ghostty to reload (SIGUSR2)
+for _ in 1 2 3; do
+ [ -s "$HOME/.config/ghostty/wallust.conf" ] && break
+ sleep 0.1
+done
+if pidof ghostty >/dev/null; then
+ for pid in $(pidof ghostty); do kill -SIGUSR2 "$pid" 2>/dev/null || true; done
+fi
+
+# Prompt Waybar to reload colors
+if command -v waybar-msg >/dev/null 2>&1; then
+ waybar-msg cmd reload >/dev/null 2>&1 || true
+elif pidof waybar >/dev/null; then
+ killall -SIGUSR2 waybar 2>/dev/null || true
+fi
diff --git a/config/hypr/scripts/WaybarScripts.sh b/config/hypr/scripts/WaybarScripts.sh
index d2205c42..54f7a4b4 100755
--- a/config/hypr/scripts/WaybarScripts.sh
+++ b/config/hypr/scripts/WaybarScripts.sh
@@ -24,6 +24,14 @@ if [[ -z "$term" ]]; then
fi
# Execute accordingly based on the passed argument
+launch_files() {
+ if [[ -z "$files" ]]; then
+ notify-send -u low -i "$HOME/.config/swaync/images/error.png" "Waybar: files" "Set \$files in 01-UserDefaults.conf or install a default file manager."
+ return 1
+ fi
+ eval "$files &"
+}
+
if [[ "$1" == "--btop" ]]; then
$term --title btop sh -c 'btop'
elif [[ "$1" == "--nvtop" ]]; then
@@ -33,7 +41,7 @@ elif [[ "$1" == "--nmtui" ]]; then
elif [[ "$1" == "--term" ]]; then
$term &
elif [[ "$1" == "--files" ]]; then
- $files &
+ launch_files
else
echo "Usage: $0 [--btop | --nvtop | --nmtui | --term]"
echo "--btop : Open btop in a new term"
diff --git a/config/hypr/scripts/keybinds_parser.py b/config/hypr/scripts/keybinds_parser.py
new file mode 100755
index 00000000..d12e3854
--- /dev/null
+++ b/config/hypr/scripts/keybinds_parser.py
@@ -0,0 +1,245 @@
+#!/usr/bin/env python3
+import sys
+import re
+import os
+
+def normalize_combo(combo):
+ return combo.replace(" ", "").replace("\t", "")
+
+def extract_combo(line):
+ # Remove comments and whitespace
+ line = re.sub(r'\s*#.*$', '', line).strip()
+
+ if '=' not in line:
+ return None
+
+ try:
+ rhs = line.split('=', 1)[1]
+ parts = [p.strip() for p in rhs.split(',')]
+ if len(parts) < 2:
+ return None
+
+ mods = parts[0]
+ key = parts[1]
+ return f"{mods},{key}"
+ except Exception:
+ return None
+
+def parse_files(files):
+ # Data structures to match original logic
+ binding_map = {} # combo -> effective line
+ source_map = {} # combo -> source file
+ user_bind_map = {} # combo -> user bind line
+ unbound_user = {} # combo -> True if explicitly unbound in user file
+ seen_any_bind = {} # combo -> True if seen
+ default_seen = {} # combo -> True if default bind exists
+
+ # We assume the last file in the list is the user config (UserKeybinds.conf)
+ # This matches the bash script logic where user_keybinds_conf is passed last
+ if not files:
+ return [], []
+
+ user_conf_path = files[-1] if len(files) > 1 else None
+
+ for file_path in files:
+ if not os.path.exists(file_path):
+ continue
+
+ try:
+ with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
+ for line in f:
+ line = line.rstrip('\n')
+ if not line or line.strip().startswith('#'):
+ continue
+
+ is_bind = re.match(r'^\s*bind[a-z]*\s*=', line)
+ is_unbind = re.match(r'^\s*unbind\s*=', line)
+
+ if is_bind:
+ combo_raw = extract_combo(line)
+ if not combo_raw:
+ continue
+ combo = normalize_combo(combo_raw)
+ seen_any_bind[combo] = True
+
+ is_user_file = (file_path == user_conf_path)
+
+ if not is_user_file:
+ default_seen[combo] = True
+
+ # prefer user bind, else first seen
+ if combo not in source_map:
+ binding_map[combo] = line
+ source_map[combo] = file_path
+
+ if is_user_file:
+ user_bind_map[combo] = line
+ binding_map[combo] = line
+ source_map[combo] = file_path
+
+ elif is_unbind:
+ combo_raw = extract_combo(line)
+ if not combo_raw:
+ continue
+ combo = normalize_combo(combo_raw)
+
+ if file_path == user_conf_path:
+ unbound_user[combo] = True
+
+ # If unbind is found, we should remove the bind from our map
+ # so it doesn't show up in the menu.
+ if combo in binding_map:
+ del binding_map[combo]
+ if combo in source_map:
+ del source_map[combo]
+
+ except Exception as e:
+ # Silently ignore read errors to mimic bash behavior or log to stderr
+ sys.stderr.write(f"Error reading {file_path}: {e}\n")
+ continue
+
+ # Build results
+ raw_keybinds = []
+ missing_unbind_suggestions = []
+
+ for combo in seen_any_bind:
+ eff_line = binding_map.get(combo)
+ src = source_map.get(combo)
+
+ if not eff_line:
+ continue
+
+ raw_keybinds.append(eff_line)
+
+ # Check for missing unbind suggestions
+ # If user overrides a default but didn't unbind in user file
+ if (src == user_conf_path and
+ combo in default_seen and
+ combo not in unbound_user):
+
+ # Create suggestion: replace 'bind' with 'unbind'
+ suggest = re.sub(r'^\s*bind[a-z]*', 'unbind', eff_line)
+ missing_unbind_suggestions.append(suggest)
+
+ return raw_keybinds, missing_unbind_suggestions
+
+def format_for_rofi(raw_binds):
+ formatted_lines = []
+
+ for line in raw_binds:
+ # line is like "bind = MODS, KEY, DISPATCHER, PARAMS" or "bindd = ..."
+ # Parsing logic from awk script:
+
+ # 1. Cleaner binder
+ match = re.match(r'^\s*(bind[a-z]*)\s*=(.*)', line)
+ if not match:
+ continue
+
+ binder = match.group(1).replace(" ", "").replace("\t", "")
+ rhs = match.group(2).strip()
+
+ # "bind" ends in d, but doesn't have a description. "bindd" does.
+ # Original script logic `index(binder, "d")>0` was likely buggy for "bind".
+ # We'll assume strict check for bindd or similar if needed,
+ # but avoiding "bind" having a description is crucial for correct output.
+ has_desc = 'd' in binder and binder != 'bind'
+
+ # Split by comma regex (handling spaces)
+ parts = [p.strip() for p in rhs.split(',')]
+
+ if len(parts) < 2:
+ continue
+
+ mods = parts[0]
+ key = parts[1]
+
+ desc = ""
+ dispatcher = ""
+ params = ""
+
+ start_idx = 0
+
+ if has_desc:
+ desc = parts[2] if len(parts) >= 3 else ""
+ dispatcher = parts[3] if len(parts) >= 4 else ""
+ start_idx = 4
+ else:
+ dispatcher = parts[2] if len(parts) >= 3 else ""
+ start_idx = 3
+
+ # Collect params
+ remaining_parts = []
+ if start_idx < len(parts):
+ for i in range(start_idx, len(parts)):
+ if parts[i]:
+ remaining_parts.append(parts[i])
+
+ if remaining_parts:
+ params = ", ".join(remaining_parts)
+
+ # Formatting mods
+ mods = mods.replace("$mainMod", "SUPER")
+ mods = re.sub(r'[ \t]+', '+', mods)
+
+ # Build combo string
+ if mods and key:
+ combo_str = f"{mods}+{key}"
+ elif key:
+ combo_str = key
+ else:
+ combo_str = mods
+
+ # Final Print Format
+ if has_desc and desc:
+ formatted_lines.append(f"{combo_str} — {desc}")
+ elif dispatcher:
+ if params:
+ formatted_lines.append(f"{combo_str} — {dispatcher} {params}")
+ else:
+ formatted_lines.append(f"{combo_str} — {dispatcher}")
+ else:
+ formatted_lines.append(combo_str)
+
+ return formatted_lines
+
+def main():
+ if len(sys.argv) < 2:
+ # No files provided
+ sys.exit(0)
+
+ config_files = sys.argv[1:]
+
+ binds, suggestions = parse_files(config_files)
+
+ if not binds:
+ print("no keybinds found.")
+ sys.exit(1)
+
+ formatted = format_for_rofi(binds)
+
+ for line in formatted:
+ print(line)
+
+ # Handle suggestions (print to stderr or a specific file if needed,
+ # but the original script assigns it to a variable 'msg'.
+ # To pass this back to bash, we might need a separate mechanism or just print to a known file.)
+ if suggestions:
+ import tempfile
+ try:
+ with tempfile.NamedTemporaryFile(mode='w', delete=False, prefix='hypr-unbind-suggestions-', suffix='.conf') as tf:
+ tf.write('\n'.join(suggestions) + '\n')
+ # We print a special marker line to stdout that the bash script can capture?
+ # Or better, just print to stderr and let the user ignore it,
+ # OR, since the original script specifically puts it in the Rofi message,
+ # we can print a special string at the END of stdout or to a side channel.
+
+ # Let's decide to print the valid keybinds to stdout (for rofi).
+ # And print the suggestion file path to a known location or specific fd if possible.
+ # Simplest: Write to a fixed temp file location that the bash script checks.
+ with open("/tmp/hypr_keybind_suggestions_file", "w") as sf:
+ sf.write(tf.name)
+ except Exception:
+ pass
+
+if __name__ == "__main__":
+ main()
diff --git a/config/hypr/scripts/sddm_wallpaper.sh b/config/hypr/scripts/sddm_wallpaper.sh
index 9dca2f72..17640f40 100755
--- a/config/hypr/scripts/sddm_wallpaper.sh
+++ b/config/hypr/scripts/sddm_wallpaper.sh
@@ -6,7 +6,8 @@
# variables
terminal=kitty
-wallDIR="$HOME/Pictures/wallpapers"
+PICTURES_DIR="$(xdg-user-dir PICTURES 2>/dev/null || echo "$HOME/Pictures")"
+wallDIR="$PICTURES_DIR/wallpapers"
SCRIPTSDIR="$HOME/.config/hypr/scripts"
wallpaper_current="$HOME/.config/hypr/wallpaper_effects/.wallpaper_current"
wallpaper_modified="$HOME/.config/hypr/wallpaper_effects/.wallpaper_modified"
@@ -20,6 +21,10 @@ sddm_simple="$sddm_themes_dir/simple_sddm_2"
# rofi-wallust-sddm colors path
rofi_wallust="$HOME/.config/rofi/wallust/colors-rofi.rasi"
sddm_theme_conf="$sddm_simple/theme.conf"
+if [[ ! -f "$rofi_wallust" ]]; then
+ notify-send -i "$iDIR/error.png" "SDDM" "Wallust colors file not found ($rofi_wallust). Aborting."
+ exit 1
+fi
# Directory for swaync
iDIR="$HOME/.config/swaync/images"
@@ -33,15 +38,45 @@ elif [[ "$1" == "--effects" ]]; then
mode="effects"
fi
+# Abort if SDDM is not running (avoid errors on non-SDDM systems)
+if command -v systemctl >/dev/null 2>&1; then
+ if ! systemctl is-active --quiet sddm; then
+ notify-send -i "$iDIR/error.png" "SDDM" "SDDM is not running. Skipping SDDM wallpaper update."
+ exit 0
+ fi
+elif ! pidof sddm >/dev/null 2>&1; then
+ notify-send -i "$iDIR/error.png" "SDDM" "SDDM is not running. Skipping SDDM wallpaper update."
+ exit 0
+fi
+
# Extract colors from rofi wallust config
-color0=$(grep -oP 'color1:\s*\K#[A-Fa-f0-9]+' "$rofi_wallust")
-color1=$(grep -oP 'color0:\s*\K#[A-Fa-f0-9]+' "$rofi_wallust")
-color7=$(grep -oP 'color14:\s*\K#[A-Fa-f0-9]+' "$rofi_wallust")
-color10=$(grep -oP 'color10:\s*\K#[A-Fa-f0-9]+' "$rofi_wallust")
-color12=$(grep -oP 'color12:\s*\K#[A-Fa-f0-9]+' "$rofi_wallust")
-color13=$(grep -oP 'color13:\s*\K#[A-Fa-f0-9]+' "$rofi_wallust")
-foreground=$(grep -oP 'foreground:\s*\K#[A-Fa-f0-9]+' "$rofi_wallust")
+extract_color() {
+ local key="$1"
+ local value
+ value=$(grep -oP "$key:\s*\K#[A-Fa-f0-9]+" "$rofi_wallust" | head -n1)
+ echo "$value"
+}
+
+color0=$(extract_color "color1")
+color1=$(extract_color "color0")
+color7=$(extract_color "color14")
+color10=$(extract_color "color10")
+color12=$(extract_color "color12")
+color13=$(extract_color "color13")
+foreground=$(extract_color "foreground")
+
+missing_colors=()
+for var in color0 color1 color7 color10 color12 color13 foreground; do
+ if [[ -z "${!var}" ]]; then
+ missing_colors+=("$var")
+ fi
+done
+
+if [[ ${#missing_colors[@]} -gt 0 ]]; then
+ notify-send -i "$iDIR/error.png" "SDDM" "Missing color(s): ${missing_colors[*]}. Run Wallust first."
+ exit 1
+fi
#background-color=$(grep -oP 'background:\s*\K#[A-Fa-f0-9]+' "$rofi_wallust")
# wallpaper to use
diff --git a/config/hypr/scripts/update_WindowRules.sh b/config/hypr/scripts/update_WindowRules.sh
new file mode 100755
index 00000000..8b4262ba
--- /dev/null
+++ b/config/hypr/scripts/update_WindowRules.sh
@@ -0,0 +1,60 @@
+#!/usr/bin/env bash
+# Script to update WindowRules config if Hyprland version is >= 0.53
+
+CONFIGS_DIR="$HOME/.config/hypr/configs"
+TARGET_FILE="$CONFIGS_DIR/WindowRules.conf"
+V3_FILE="$CONFIGS_DIR/WindowRules-config-v3.conf"
+
+if [[ ! -f "$V3_FILE" ]]; then
+ echo "Error: Source configuration file not found: $V3_FILE"
+ exit 1
+fi
+
+get_hyprland_version() {
+ local ver="0.0.0"
+ local raw_ver=""
+
+ if command -v hyprctl &>/dev/null; then
+ raw_ver=$(hyprctl version 2>/dev/null | grep "Tag:" | cut -d 'v' -f2)
+ fi
+
+ if [ -z "$raw_ver" ] && command -v Hyprland &>/dev/null; then
+ raw_ver=$(Hyprland --version 2>/dev/null | grep "Tag:" | cut -d 'v' -f2 | awk '{print $1}')
+ fi
+
+ if [ -n "$raw_ver" ]; then
+ ver=$(echo "$raw_ver" | grep -oE '^[0-9]+\.[0-9]+(\.[0-9]+)?')
+ fi
+
+ if [ -z "$ver" ]; then
+ echo "0.0.0"
+ else
+ echo "$ver"
+ fi
+}
+
+VERSION=$(get_hyprland_version)
+REQUIRED_VER="0.53"
+
+# Check if version >= REQUIRED_VER
+SMALLEST=$(printf '%s\n' "$REQUIRED_VER" "$VERSION" | sort -V | head -n1)
+
+if [ "$SMALLEST" = "$REQUIRED_VER" ]; then
+ echo "Version $VERSION >= $REQUIRED_VER. Updating WindowRules config..."
+ # Backup existing config if it exists
+ if [ -f "$TARGET_FILE" ]; then
+ echo "Backing up existing WindowRules.conf to WindowRules.conf.bak"
+ mv "$TARGET_FILE" "$TARGET_FILE.bak"
+ fi
+ cp "$V3_FILE" "$TARGET_FILE"
+
+ if command -v hyprctl &>/dev/null; then
+ if hyprctl instances &>/dev/null; then
+ echo "Reloading Hyprland..."
+ hyprctl reload
+ fi
+ fi
+else
+ echo "Version $VERSION < $REQUIRED_VER. No update needed."
+fi
+
diff --git a/config/hypr/v2.3.18 b/config/hypr/v2.3.19
index 31b3414d..31b3414d 100644
--- a/config/hypr/v2.3.18
+++ b/config/hypr/v2.3.19
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage