diff options
Diffstat (limited to 'config/hypr/scripts')
79 files changed, 3855 insertions, 406 deletions
diff --git a/config/hypr/scripts/Add-override-Hyprland-Portal.sh b/config/hypr/scripts/Add-override-Hyprland-Portal.sh index 1f321d51..b8a10ba4 100755 --- a/config/hypr/scripts/Add-override-Hyprland-Portal.sh +++ b/config/hypr/scripts/Add-override-Hyprland-Portal.sh @@ -14,7 +14,7 @@ SCRIPT_NAME="$(basename "$0")" DRY_RUN=0 ACTION="apply" -OVERRIDE_DIR="$HOME/.config/systemd/user/xdg-desktop-portal.service.d" +OVERRIDE_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user/xdg-desktop-portal.service.d" OVERRIDE_FILE="$OVERRIDE_DIR/override.conf" PORTAL_UNITS=( "xdg-desktop-portal.service" diff --git a/config/hypr/scripts/AirplaneMode.sh b/config/hypr/scripts/AirplaneMode.sh index 21aa04a8..17a8d9ac 100755 --- a/config/hypr/scripts/AirplaneMode.sh +++ b/config/hypr/scripts/AirplaneMode.sh @@ -7,7 +7,7 @@ # ================================================== # Airplane Mode. Turning on or off all wifi using rfkill. -notif="$HOME/.config/swaync/images/ja.png" +notif="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/images/ja.png" # Check if any wireless device is blocked wifi_blocked=$(rfkill list wifi | grep -o "Soft blocked: yes") diff --git a/config/hypr/scripts/Animations.sh b/config/hypr/scripts/Animations.sh index 5fb77750..ae93429b 100755 --- a/config/hypr/scripts/Animations.sh +++ b/config/hypr/scripts/Animations.sh @@ -13,22 +13,44 @@ if pidof rofi > /dev/null; then fi # Variables -iDIR="$HOME/.config/swaync/images" -SCRIPTSDIR="$HOME/.config/hypr/scripts" -animations_dir="$HOME/.config/hypr/animations" -UserConfigs="$HOME/.config/hypr/UserConfigs" -rofi_theme="$HOME/.config/rofi/config-Animations.rasi" -msg='❗NOTE:❗ This will copy animations into UserAnimations.conf' +iDIR="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/images" +SCRIPTSDIR="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts" +animations_dir="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/animations" +UserConfigs="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/UserConfigs" +rofi_theme="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/config-Animations.rasi" +config_home="${XDG_CONFIG_HOME:-$HOME/.config}" +hypr_dir="$config_home/hypr" +lua_entry="$hypr_dir/hyprland.lua" +legacy_lua_entry="$config_home/hyprland.lua" + +# Detect active Hyprland config mode (Lua entrypoint vs legacy .conf includes) +if [[ -f "$lua_entry" || -f "$legacy_lua_entry" ]]; then + hypr_config_mode="lua" + animation_ext="lua" + target_animation_file="$UserConfigs/user_animations.lua" + msg='❗NOTE:❗ This will copy animations into user_animations.lua' +else + hypr_config_mode="conf" + animation_ext="conf" + target_animation_file="$UserConfigs/UserAnimations.conf" + msg='❗NOTE:❗ This will copy animations into UserAnimations.conf' +fi + # list of animation files, sorted alphabetically with numbers first -animations_list=$(find -L "$animations_dir" -maxdepth 1 -type f | sed 's/.*\///' | sed 's/\.conf$//' | sort -V) +animations_list=$(find -L "$animations_dir" -maxdepth 1 -type f -name "*.${animation_ext}" | sed 's/.*\///' | sed "s/\.${animation_ext}$//" | sort -V) + +if [[ -z "$animations_list" ]]; then + notify-send -u normal -i "$iDIR/ja.png" "No animation presets found" "Expected *.${animation_ext} in $animations_dir" + exit 0 +fi # Rofi Menu -chosen_file=$(echo "$animations_list" | rofi -i -dmenu -config $rofi_theme -mesg "$msg") +chosen_file=$(echo "$animations_list" | rofi -i -dmenu -config "$rofi_theme" -mesg "$msg") # Check if a file was selected if [[ -n "$chosen_file" ]]; then - full_path="$animations_dir/$chosen_file.conf" - cp "$full_path" "$UserConfigs/UserAnimations.conf" + full_path="$animations_dir/$chosen_file.$animation_ext" + cp "$full_path" "$target_animation_file" notify-send -u low -i "$iDIR/ja.png" "$chosen_file" "Hyprland Animation Loaded" fi diff --git a/config/hypr/scripts/ApplyThemeMode.sh b/config/hypr/scripts/ApplyThemeMode.sh new file mode 100755 index 00000000..f0b45aaf --- /dev/null +++ b/config/hypr/scripts/ApplyThemeMode.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +# ================================================== +# KoolDots (2026) +# Project URL: https://github.com/LinuxBeginnings +# License: GNU GPLv3 +# SPDX-License-Identifier: GPL-3.0-or-later +# ================================================== +# Re-apply saved Dark/Light mode on startup without toggling. + +SCRIPTSDIR="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts" +"$SCRIPTSDIR/DarkLight.sh" --apply-current --preserve-wallpaper --no-notify diff --git a/config/hypr/scripts/Brightness.sh b/config/hypr/scripts/Brightness.sh index bf0f4bf1..d3f221bf 100755 --- a/config/hypr/scripts/Brightness.sh +++ b/config/hypr/scripts/Brightness.sh @@ -7,7 +7,7 @@ # ================================================== # Script for Monitor backlights (if supported) using brightnessctl -iDIR="$HOME/.config/swaync/icons" +iDIR="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/icons" notification_timeout=1000 step=10 # INCREASE/DECREASE BY THIS VALUE diff --git a/config/hypr/scripts/BrightnessKbd.sh b/config/hypr/scripts/BrightnessKbd.sh index 5bd09a78..ae24b2b2 100755 --- a/config/hypr/scripts/BrightnessKbd.sh +++ b/config/hypr/scripts/BrightnessKbd.sh @@ -7,7 +7,7 @@ # ================================================== # Script for keyboard backlights (if supported) using brightnessctl -iDIR="$HOME/.config/swaync/icons" +iDIR="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/icons" # Get keyboard brightness get_kbd_backlight() { diff --git a/config/hypr/scripts/ChangeBlur.sh b/config/hypr/scripts/ChangeBlur.sh index 10b5914e..ca1be5ad 100755 --- a/config/hypr/scripts/ChangeBlur.sh +++ b/config/hypr/scripts/ChangeBlur.sh @@ -7,7 +7,7 @@ # ================================================== # Script for changing blurs on the fly -notif="$HOME/.config/swaync/images" +notif="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/images" STATE=$(hyprctl -j getoption decoration:blur:passes | jq ".int") diff --git a/config/hypr/scripts/ChangeLayout.sh b/config/hypr/scripts/ChangeLayout.sh index 3c81bcbe..4e241e85 100755 --- a/config/hypr/scripts/ChangeLayout.sh +++ b/config/hypr/scripts/ChangeLayout.sh @@ -5,36 +5,168 @@ # License: GNU GPLv3 # SPDX-License-Identifier: GPL-3.0-or-later # ================================================== -# for changing Hyprland Layouts (master, dwindle, scrolling, monocle) on the fly - -notif="$HOME/.config/swaync/images/ja.png" +# Switch Hyprland layouts per active monitor/workspace. +# This avoids global layout mutations and keeps workspace-specific rules intact. +notif="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/images/ja.png" +persist_layout_script="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts/PersistWorkspaceLayout.sh" layouts=(master dwindle scrolling monocle) quiet_mode=0 +normalize_layout() { + case "$1" in + master | dwindle | scrolling | monocle) + printf '%s\n' "$1" + ;; + *) + printf '\n' + ;; + esac +} + +wait_for_layout() { + local target="$1" + local actual="" + local attempt + + for attempt in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do + actual="$(get_layout)" + if [[ "$actual" == "$target" ]]; then + printf '%s\n' "$actual" + return 0 + fi + sleep 0.03 + done + + printf '%s\n' "$actual" + return 1 +} + +persist_current_workspace_layout() { + local target_layout="$1" + + if [[ ! -x "$persist_layout_script" ]]; then + return 0 + fi + + "$persist_layout_script" --quiet --layout "$target_layout" >/dev/null 2>&1 || true +} + +get_active_workspace_json() { + hyprctl -j activeworkspace 2>/dev/null || printf '{}' +} + get_layout() { - hyprctl -j getoption general:layout | jq -r '.str' + local ws_json layout + + ws_json="$(get_active_workspace_json)" + layout="$(jq -r '.tiledLayout // .tiled_layout // .layout // empty' <<<"$ws_json" 2>/dev/null || true)" + layout="$(normalize_layout "$layout")" + + if [[ -z "$layout" ]]; then + layout="$(hyprctl -j getoption general:layout 2>/dev/null | jq -r '.str // empty' 2>/dev/null || true)" + layout="$(normalize_layout "$layout")" + fi + + if [[ -z "$layout" ]]; then + layout="dwindle" + fi + + printf '%s\n' "$layout" } -set_hypr_layout() { +get_workspace_selector() { + local ws_json="$1" + local ws_id ws_name + + ws_id="$(jq -r '.id // empty' <<<"$ws_json" 2>/dev/null || true)" + ws_name="$(jq -r '.name // empty' <<<"$ws_json" 2>/dev/null || true)" + + if [[ "$ws_id" =~ ^[0-9]+$ ]] && ((ws_id > 0)); then + printf '%s\n' "$ws_id" + return 0 + fi + + if [[ -n "$ws_name" && "$ws_name" != "null" ]]; then + if [[ "$ws_name" == name:* || "$ws_name" == special:* ]]; then + printf '%s\n' "$ws_name" + else + printf 'name:%s\n' "$ws_name" + fi + return 0 + fi + + return 1 +} + +get_workspace_label() { + local ws_json="$1" + local ws_name ws_id + + ws_name="$(jq -r '.name // empty' <<<"$ws_json" 2>/dev/null || true)" + ws_id="$(jq -r '.id // empty' <<<"$ws_json" 2>/dev/null || true)" + + if [[ -n "$ws_name" && "$ws_name" != "null" ]]; then + printf '%s\n' "$ws_name" + return + fi + + if [[ -n "$ws_id" && "$ws_id" != "null" ]]; then + printf '%s\n' "$ws_id" + return + fi + + printf 'current\n' +} + +get_monitor_name() { + local ws_json="$1" + jq -r '.monitor // empty' <<<"$ws_json" 2>/dev/null || true +} + +escape_lua_string() { + local value="$1" + value="${value//\\/\\\\}" + value="${value//\"/\\\"}" + printf '%s' "$value" +} + +is_ok_output() { + local output="$1" + local normalized + + normalized="$(printf '%s\n' "$output" | tr -d '\r' | sed '/^[[:space:]]*$/d')" + [[ -z "$normalized" || "$normalized" == "ok" ]] +} + +set_workspace_layout_rule() { local target="$1" - local output + local ws_json workspace_selector monitor_name output + local ws_escaped monitor_escaped target_escaped + + ws_json="$(get_active_workspace_json)" + workspace_selector="$(get_workspace_selector "$ws_json" || true)" + monitor_name="$(get_monitor_name "$ws_json")" - output="$(hyprctl keyword general:layout "$target" 2>&1)" + if [[ -z "$workspace_selector" || -z "$monitor_name" ]]; then + echo "Unable to resolve active workspace context" >&2 + return 1 + fi + + output="$(hyprctl keyword workspace "${workspace_selector}, monitor:${monitor_name}, layout:${target}" 2>&1 || true)" if grep -q "keyword can't work with non-legacy parsers" <<<"$output"; then - output="$(hyprctl eval "hl.config({ general = { layout = \"${target}\" } })" 2>&1)" + ws_escaped="$(escape_lua_string "$workspace_selector")" + monitor_escaped="$(escape_lua_string "$monitor_name")" + target_escaped="$(escape_lua_string "$target")" + output="$(hyprctl eval "hl.workspace_rule({ workspace = \"${ws_escaped}\", monitor = \"${monitor_escaped}\", layout = \"${target_escaped}\" })" 2>&1 || true)" fi - if ! grep -q "^ok$" <<<"$output"; then + if ! is_ok_output "$output"; then echo "$output" >&2 return 1 fi } -hypr_keyword() { - hyprctl keyword "$@" >/dev/null 2>&1 || true -} - next_layout() { local current="$1" local i @@ -49,65 +181,24 @@ next_layout() { set_layout() { local target="$1" + local ws_json workspace_label monitor_name actual - if ! set_hypr_layout "$target"; then + ws_json="$(get_active_workspace_json)" + workspace_label="$(get_workspace_label "$ws_json")" + monitor_name="$(get_monitor_name "$ws_json")" + + if ! set_workspace_layout_rule "$target"; then if [[ "$quiet_mode" -eq 0 ]]; then notify-send -e -u critical -i "$notif" " Layout switch failed: $target" fi return 1 fi - hypr_keyword unbind SUPER,j - hypr_keyword unbind SUPER,k - hypr_keyword bind SUPER,j,cyclenext - hypr_keyword bind SUPER,k,cyclenext,prev - hypr_keyword unbind SUPER,left - hypr_keyword unbind SUPER,right - hypr_keyword unbind SUPER,up - hypr_keyword unbind SUPER,down - hypr_keyword unbind SUPER,O - - case "$target" in - "dwindle") - hypr_keyword bind SUPER,left,cyclenext,prev - hypr_keyword bind SUPER,up,cyclenext,prev - hypr_keyword bind SUPER,right,cyclenext - hypr_keyword bind SUPER,down,cyclenext - hypr_keyword bind SUPER,O,layoutmsg,togglesplit - ;; - "scrolling") - hypr_keyword bind SUPER,left,cyclenext,prev - hypr_keyword bind SUPER,up,cyclenext,prev - hypr_keyword bind SUPER,right,cyclenext - hypr_keyword bind SUPER,down,cyclenext - ;; - "monocle") - hypr_keyword bind SUPER,left,layoutmsg,cycleprev - hypr_keyword bind SUPER,up,layoutmsg,cycleprev - hypr_keyword bind SUPER,right,layoutmsg,cyclenext - hypr_keyword bind SUPER,down,layoutmsg,cyclenext - ;; - "master") - hypr_keyword bind SUPER,left,movefocus,l - hypr_keyword bind SUPER,right,movefocus,r - hypr_keyword bind SUPER,up,movefocus,u - hypr_keyword bind SUPER,down,movefocus,d - ;; - *) - hypr_keyword bind SUPER,left,movefocus,l - hypr_keyword bind SUPER,right,movefocus,r - hypr_keyword bind SUPER,up,movefocus,u - hypr_keyword bind SUPER,down,movefocus,d - echo "Unknown layout: $target" >&2 - return 1 - ;; - esac - - local actual - actual="$(get_layout)" + actual="$(wait_for_layout "$target")" if [[ "$actual" == "$target" ]]; then + persist_current_workspace_layout "$target" if [[ "$quiet_mode" -eq 0 ]]; then - notify-send -e -u low -i "$notif" " ${actual^} Layout" + notify-send -e -u low -i "$notif" " ${actual^} Layout · WS ${workspace_label}${monitor_name:+ @ ${monitor_name}}" fi else if [[ "$quiet_mode" -eq 0 ]]; then @@ -127,16 +218,20 @@ arg="${1:-toggle}" case "$arg" in init) - set_layout "$current" + # No startup keybind rebinding required anymore. + exit 0 + ;; +current | status | get) + printf '%s\n' "$current" ;; -toggle|next) +toggle | next) set_layout "$(next_layout "$current")" ;; -master|dwindle|scrolling|monocle) +master | dwindle | scrolling | monocle) set_layout "$arg" ;; *) - echo "Usage: $(basename "$0") [--quiet|--no-notify] [toggle|next|init|master|dwindle|scrolling|monocle]" >&2 + echo "Usage: $(basename "$0") [--quiet|--no-notify] [toggle|next|init|current|master|dwindle|scrolling|monocle]" >&2 exit 1 ;; esac diff --git a/config/hypr/scripts/ChangeStarshipPrompt.sh b/config/hypr/scripts/ChangeStarshipPrompt.sh new file mode 100755 index 00000000..44e50936 --- /dev/null +++ b/config/hypr/scripts/ChangeStarshipPrompt.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash +# ================================================== +# KoolDots (2026) +# Project URL: https://github.com/LinuxBeginnings +# License: GNU GPLv3 +# SPDX-License-Identifier: GPL-3.0-or-later +# ================================================== +# Switch Starship prompt configs via Rofi. + +CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" +STARSHIP_DIR="$CONFIG_HOME/starship" +HYPR_STARSHIP_DIR="$CONFIG_HOME/hypr/starship" +STARSHIP_CONFIG="$CONFIG_HOME/starship.toml" +BACKUP_FILE="$STARSHIP_CONFIG.original" +ROFI_THEME="$CONFIG_HOME/rofi/config-starship.rasi" +RESTORE_LABEL="Retore orignal prompt" + +if ! command -v starship >/dev/null 2>&1; then + echo "starship is not installed" + exit 1 +fi + +if [[ ! -f "$ROFI_THEME" ]]; then + echo "Rofi theme not found: $ROFI_THEME" + exit 1 +fi + +if [[ ! -d "$STARSHIP_DIR" ]]; then + echo "Starship config directory not found: $STARSHIP_DIR" + exit 1 +fi + +mapfile -t available_prompts < <(find "$STARSHIP_DIR" -maxdepth 1 -type f -name "*.toml" -printf "%f\n" 2>/dev/null | sort -V) + +if [[ ${#available_prompts[@]} -eq 0 ]]; then + echo "No Starship prompt files found in $STARSHIP_DIR" + exit 1 +fi + +rofi_options=("${available_prompts[@]}") +if [[ -f "$BACKUP_FILE" ]]; then + rofi_options+=("$RESTORE_LABEL") +fi + +selection="$(printf '%s\n' "${rofi_options[@]}" | rofi -dmenu -i -p "Select Starship Prompt" -mesg "Select Starship Prompt" -theme "$ROFI_THEME")" + +if [[ -z "$selection" ]]; then + exit 0 +fi + +if [[ "$selection" == "$RESTORE_LABEL" ]]; then + if [[ -f "$BACKUP_FILE" ]]; then + if [[ -L "$STARSHIP_CONFIG" ]]; then + rm -f "$STARSHIP_CONFIG" + fi + cp -f "$BACKUP_FILE" "$STARSHIP_CONFIG" + else + echo "Backup not found: $BACKUP_FILE" + fi + exit 0 +fi + +selected_path="$STARSHIP_DIR/$selection" +if [[ ! -f "$selected_path" && -f "$HYPR_STARSHIP_DIR/$selection" ]]; then + selected_path="$HYPR_STARSHIP_DIR/$selection" +fi + +if [[ ! -f "$selected_path" ]]; then + echo "Selected prompt not found: $selection" + exit 1 +fi + +if [[ -f "$STARSHIP_CONFIG" && ! -L "$STARSHIP_CONFIG" ]]; then + cp -f "$STARSHIP_CONFIG" "$BACKUP_FILE" + rm -f "$STARSHIP_CONFIG" +fi + +ln -sfn "$selected_path" "$STARSHIP_CONFIG" diff --git a/config/hypr/scripts/ClipManager.sh b/config/hypr/scripts/ClipManager.sh index e3fbd066..19e15fd6 100755 --- a/config/hypr/scripts/ClipManager.sh +++ b/config/hypr/scripts/ClipManager.sh @@ -8,7 +8,7 @@ # Clipboard Manager. This script uses cliphist, rofi, and wl-copy. # Variables -rofi_theme="$HOME/.config/rofi/config-clipboard.rasi" +rofi_theme="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/config-clipboard.rasi" msg='👀 **note** CTRL DEL = cliphist del (entry) or ALT DEL - cliphist wipe (all)' # Actions: # CTRL Del to delete an entry diff --git a/config/hypr/scripts/DarkLight.sh b/config/hypr/scripts/DarkLight.sh index 5b1cc3e7..16f1a4ef 100755 --- a/config/hypr/scripts/DarkLight.sh +++ b/config/hypr/scripts/DarkLight.sh @@ -13,24 +13,79 @@ 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" -swaync_style="$HOME/.config/swaync/style.css" -ags_style="$HOME/.config/ags/user/style.css" -SCRIPTSDIR="$HOME/.config/hypr/scripts" +hypr_config_path="${XDG_CONFIG_HOME:-$HOME/.config}/hypr" +swaync_style="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/style.css" +ags_style="${XDG_CONFIG_HOME:-$HOME/.config}/ags/user/style.css" +SCRIPTSDIR="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts" # shellcheck source=/dev/null . "$SCRIPTSDIR/WallpaperCmd.sh" -notif="$HOME/.config/swaync/images/bell.png" -wallust_rofi="$HOME/.config/wallust/templates/colors-rofi.rasi" +notif="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/images/bell.png" +wallust_rofi="${XDG_CONFIG_HOME:-$HOME/.config}/wallust/templates/colors-rofi.rasi" +theme_state_dir="${XDG_STATE_HOME:-$HOME/.local/state}/hypr" +theme_state_file="$theme_state_dir/theme_mode" +legacy_theme_state_file="$HOME/.cache/.theme_mode" -kitty_conf="$HOME/.config/kitty/kitty.conf" +kitty_conf="${XDG_CONFIG_HOME:-$HOME/.config}/kitty/kitty.conf" -wallust_config="$HOME/.config/wallust/wallust.toml" +wallust_config="${XDG_CONFIG_HOME:-$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" +qt5ct_dark="${XDG_CONFIG_HOME:-$HOME/.config}/qt5ct/colors/Catppuccin-Mocha.conf" +qt5ct_light="${XDG_CONFIG_HOME:-$HOME/.config}/qt5ct/colors/Catppuccin-Latte.conf" +qt6ct_dark="${XDG_CONFIG_HOME:-$HOME/.config}/qt6ct/colors/Catppuccin-Mocha.conf" +qt6ct_light="${XDG_CONFIG_HOME:-$HOME/.config}/qt6ct/colors/Catppuccin-Latte.conf" +apply_saved_mode=0 +notify_enabled=1 +preserve_wallpaper=0 +forced_mode="" + +normalize_mode() { + case "$1" in + Dark|Light) printf '%s' "$1" ;; + *) printf '' ;; + esac +} + +read_saved_mode() { + local mode="" + if [ -f "$theme_state_file" ]; then + mode="$(normalize_mode "$(tr -d '\r\n' < "$theme_state_file")")" + fi + if [ -z "$mode" ] && [ -f "$legacy_theme_state_file" ]; then + mode="$(normalize_mode "$(tr -d '\r\n' < "$legacy_theme_state_file")")" + fi + [ -n "$mode" ] && printf '%s' "$mode" || printf 'Dark' +} + +while [ $# -gt 0 ]; do + case "$1" in + --apply-current) + apply_saved_mode=1 + ;; + --mode) + shift + forced_mode="$(normalize_mode "${1:-}")" + ;; + --no-notify) + notify_enabled=0 + ;; + --preserve-wallpaper) + preserve_wallpaper=1 + ;; + --help) + cat <<'EOF' +Usage: DarkLight.sh [--apply-current] [--mode Dark|Light] [--no-notify] [--preserve-wallpaper] + (no args) Toggle between Dark and Light and persist selection + --apply-current Re-apply saved mode (defaults to Dark when unset) + --mode <mode> Force target mode to Dark or Light + --no-notify Suppress notifications + --preserve-wallpaper Keep current wallpaper instead of choosing random Dynamic-Wallpapers image +EOF + exit 0 + ;; + esac + shift +done # intial kill process for pid in waybar rofi swaync ags swaybg; do @@ -45,28 +100,33 @@ done swww="$WWW_CMD img" effect="--transition-bezier .43,1.19,1,.4 --transition-fps 60 --transition-type grow --transition-pos 0.925,0.977 --transition-duration 2" -# Determine current theme mode -if [ "$(cat $HOME/.cache/.theme_mode)" = "Light" ]; then +# Determine target theme mode +saved_mode="$(read_saved_mode)" +if [ -n "$forced_mode" ]; then + next_mode="$forced_mode" +elif [ "$apply_saved_mode" -eq 1 ]; then + next_mode="$saved_mode" +elif [ "$saved_mode" = "Light" ]; then next_mode="Dark" - # Logic for Dark mode - wallpaper_path="$dark_wallpapers" else next_mode="Light" - # Logic for Light mode - wallpaper_path="$light_wallpapers" fi # Select Qt color scheme templates for the upcoming mode if [ "$next_mode" = "Dark" ]; then + wallpaper_path="$dark_wallpapers" qt5ct_color_scheme="$qt5ct_dark" qt6ct_color_scheme="$qt6ct_dark" else + wallpaper_path="$light_wallpapers" qt5ct_color_scheme="$qt5ct_light" qt6ct_color_scheme="$qt6ct_light" fi # Function to update theme mode for the next cycle update_theme_mode() { - echo "$next_mode" > "$HOME/.cache/.theme_mode" + mkdir -p "$theme_state_dir" "$HOME/.cache" + echo "$next_mode" > "$theme_state_file" + echo "$next_mode" > "$legacy_theme_state_file" } # Function to notify user @@ -84,8 +144,8 @@ fi # Function to set Waybar style set_waybar_style() { theme="$1" - waybar_styles="$HOME/.config/waybar/style" - waybar_style_link="$HOME/.config/waybar/style.css" + waybar_styles="${XDG_CONFIG_HOME:-$HOME/.config}/waybar/style" + waybar_style_link="${XDG_CONFIG_HOME:-$HOME/.config}/waybar/style.css" style_prefix="\\[${theme}\\].*\\.css$" style_file=$(find -L "$waybar_styles" -maxdepth 1 -type f -regex ".*$style_prefix" | shuf -n 1) @@ -99,7 +159,7 @@ set_waybar_style() { # Call the function after determining the mode set_waybar_style "$next_mode" -notify_user "$next_mode" +[ "$notify_enabled" -eq 1 ] && notify_user "$next_mode" # swaync color change @@ -140,29 +200,31 @@ for pid_kitty in $(pidof kitty); do done # Set Dynamic Wallpaper for Dark or Light Mode -if [ "$next_mode" = "Dark" ]; then - next_wallpaper="$(find -L "${dark_wallpapers}" -type f \( -iname "*.jpg" -o -iname "*.png" \) -print0 | shuf -n1 -z | xargs -0)" -else - next_wallpaper="$(find -L "${light_wallpapers}" -type f \( -iname "*.jpg" -o -iname "*.png" \) -print0 | shuf -n1 -z | xargs -0)" -fi +if [ "$preserve_wallpaper" -eq 0 ]; then + if [ "$next_mode" = "Dark" ]; then + next_wallpaper="$(find -L "${dark_wallpapers}" -type f \( -iname "*.jpg" -o -iname "*.png" \) -print0 | shuf -n1 -z | xargs -0)" + else + next_wallpaper="$(find -L "${light_wallpapers}" -type f \( -iname "*.jpg" -o -iname "*.png" \) -print0 | shuf -n1 -z | xargs -0)" + fi -# Update wallpaper using swww command -$swww "${next_wallpaper}" $effect + # Update wallpaper using swww command + $swww "${next_wallpaper}" $effect +fi # Set Kvantum Manager theme & QT5/QT6 settings if [ "$next_mode" = "Dark" ]; then kvantum_theme="catppuccin-mocha-blue" - #qt5ct_color_scheme="$HOME/.config/qt5ct/colors/Catppuccin-Mocha.conf" - #qt6ct_color_scheme="$HOME/.config/qt6ct/colors/Catppuccin-Mocha.conf" + #qt5ct_color_scheme="${XDG_CONFIG_HOME:-$HOME/.config}/qt5ct/colors/Catppuccin-Mocha.conf" + #qt6ct_color_scheme="${XDG_CONFIG_HOME:-$HOME/.config}/qt6ct/colors/Catppuccin-Mocha.conf" else kvantum_theme="catppuccin-latte-blue" - #qt5ct_color_scheme="$HOME/.config/qt5ct/colors/Catppuccin-Latte.conf" - #qt6ct_color_scheme="$HOME/.config/qt6ct/colors/Catppuccin-Latte.conf" + #qt5ct_color_scheme="${XDG_CONFIG_HOME:-$HOME/.config}/qt5ct/colors/Catppuccin-Latte.conf" + #qt6ct_color_scheme="${XDG_CONFIG_HOME:-$HOME/.config}/qt6ct/colors/Catppuccin-Latte.conf" fi -sed -i "s|^color_scheme_path=.*$|color_scheme_path=$qt5ct_color_scheme|" "$HOME/.config/qt5ct/qt5ct.conf" -sed -i "s|^color_scheme_path=.*$|color_scheme_path=$qt6ct_color_scheme|" "$HOME/.config/qt6ct/qt6ct.conf" +sed -i "s|^color_scheme_path=.*$|color_scheme_path=$qt5ct_color_scheme|" "${XDG_CONFIG_HOME:-$HOME/.config}/qt5ct/qt5ct.conf" +sed -i "s|^color_scheme_path=.*$|color_scheme_path=$qt6ct_color_scheme|" "${XDG_CONFIG_HOME:-$HOME/.config}/qt6ct/qt6ct.conf" kvantummanager --set "$kvantum_theme" @@ -234,8 +296,8 @@ set_custom_gtk_theme() { gsettings set $icon_setting "$selected_icon" ## QT5ct icon_theme - sed -i "s|^icon_theme=.*$|icon_theme=$selected_icon|" "$HOME/.config/qt5ct/qt5ct.conf" - sed -i "s|^icon_theme=.*$|icon_theme=$selected_icon|" "$HOME/.config/qt6ct/qt6ct.conf" + sed -i "s|^icon_theme=.*$|icon_theme=$selected_icon|" "${XDG_CONFIG_HOME:-$HOME/.config}/qt5ct/qt5ct.conf" + sed -i "s|^icon_theme=.*$|icon_theme=$selected_icon|" "${XDG_CONFIG_HOME:-$HOME/.config}/qt6ct/qt6ct.conf" # Flatpak GTK apps (icons) if command -v flatpak &> /dev/null; then @@ -268,7 +330,7 @@ ${SCRIPTSDIR}/Refresh.sh sleep 0.5 # Display notifications for theme and icon changes -notify-send -u low -i "$notif" " Themes switched to:" " $next_mode Mode" +[ "$notify_enabled" -eq 1 ] && notify-send -u low -i "$notif" " Themes switched to:" " $next_mode Mode" exit 0 diff --git a/config/hypr/scripts/Distro_update.sh b/config/hypr/scripts/Distro_update.sh index b9bcae71..20a710ee 100755 --- a/config/hypr/scripts/Distro_update.sh +++ b/config/hypr/scripts/Distro_update.sh @@ -8,7 +8,7 @@ # Simple bash script to check and will try to update your system # Local Paths -iDIR="$HOME/.config/swaync/images" +iDIR="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/images" # Check for required tools (kitty) if ! command -v kitty &> /dev/null; then diff --git a/config/hypr/scripts/Dropterminal.sh b/config/hypr/scripts/Dropterminal.sh index 21349d4a..8c301f68 100755 --- a/config/hypr/scripts/Dropterminal.sh +++ b/config/hypr/scripts/Dropterminal.sh @@ -24,7 +24,7 @@ LOCK_FILE="/tmp/dropdown_terminal_lock" LAST_TOGGLE_FILE="/tmp/dropdown_terminal_last_toggle" MIN_TOGGLE_INTERVAL_MS=250 DROPDOWN_KITTY_CLASS="kitty-dropterm" -CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" +CONFIG_HOME="${XDG_CONFIG_HOME:-${XDG_CONFIG_HOME:-$HOME/.config}}" HYPR_DIR="$CONFIG_HOME/hypr" LUA_ENTRY="$HYPR_DIR/hyprland.lua" LEGACY_LUA_ENTRY="$CONFIG_HOME/hyprland.lua" diff --git a/config/hypr/scripts/ExternalBrightness.sh b/config/hypr/scripts/ExternalBrightness.sh index 59081e1d..f3bf2487 100755 --- a/config/hypr/scripts/ExternalBrightness.sh +++ b/config/hypr/scripts/ExternalBrightness.sh @@ -18,7 +18,7 @@ cache_file="/tmp/external_brightness_displays.cache" cache_ttl=300 # 5 minutes # Detect active Hyprland config mode (Lua entrypoint vs legacy .conf includes) -config_home="${XDG_CONFIG_HOME:-$HOME/.config}" +config_home="${XDG_CONFIG_HOME:-${XDG_CONFIG_HOME:-$HOME/.config}}" hypr_dir="$config_home/hypr" lua_entry="$hypr_dir/hyprland.lua" legacy_lua_entry="$config_home/hyprland.lua" diff --git a/config/hypr/scripts/Float-all-Windows.sh b/config/hypr/scripts/Float-all-Windows.sh index 25fdc465..1f754ec5 100755 --- a/config/hypr/scripts/Float-all-Windows.sh +++ b/config/hypr/scripts/Float-all-Windows.sh @@ -7,7 +7,7 @@ # ================================================== # Detect active Hyprland config mode (Lua entrypoint vs legacy .conf includes) -config_home="${XDG_CONFIG_HOME:-$HOME/.config}" +config_home="${XDG_CONFIG_HOME:-${XDG_CONFIG_HOME:-$HOME/.config}}" hypr_dir="$config_home/hypr" lua_entry="$hypr_dir/hyprland.lua" legacy_lua_entry="$config_home/hyprland.lua" diff --git a/config/hypr/scripts/GameMode.sh b/config/hypr/scripts/GameMode.sh index b104179e..c3a02948 100755 --- a/config/hypr/scripts/GameMode.sh +++ b/config/hypr/scripts/GameMode.sh @@ -7,13 +7,13 @@ # ================================================== # Game Mode. Turning off all animations -notif="$HOME/.config/swaync/images/ja.png" -SCRIPTSDIR="$HOME/.config/hypr/scripts" +notif="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/images/ja.png" +SCRIPTSDIR="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts" # shellcheck source=/dev/null . "$SCRIPTSDIR/WallpaperCmd.sh" # Detect active Hyprland config mode (Lua entrypoint vs legacy .conf includes) -config_home="${XDG_CONFIG_HOME:-$HOME/.config}" +config_home="${XDG_CONFIG_HOME:-${XDG_CONFIG_HOME:-$HOME/.config}}" hypr_dir="$config_home/hypr" lua_entry="$hypr_dir/hyprland.lua" legacy_lua_entry="$config_home/hyprland.lua" diff --git a/config/hypr/scripts/Ghostty_themes.sh b/config/hypr/scripts/Ghostty_themes.sh index c3fcd792..7eef6c1c 100755 --- a/config/hypr/scripts/Ghostty_themes.sh +++ b/config/hypr/scripts/Ghostty_themes.sh @@ -7,14 +7,14 @@ # ================================================== # Ghostty theme selector -config_file="$HOME/.config/ghostty/config" -iDIR="$HOME/.config/swaync/images" -rofi_theme_primary="$HOME/.config/rofi/config-ghostty-theme.rasi" -rofi_theme_fallback="$HOME/.config/rofi/config-edit.rasi" -wallust_include_path="$HOME/.config/ghostty/wallust.conf" +config_file="${XDG_CONFIG_HOME:-$HOME/.config}/ghostty/config" +iDIR="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/images" +rofi_theme_primary="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/config-ghostty-theme.rasi" +rofi_theme_fallback="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/config-edit.rasi" +wallust_include_path="${XDG_CONFIG_HOME:-$HOME/.config}/ghostty/wallust.conf" wallust_option_label="Set by wallpaper" default_option_label="Default - no color" -wallust_refresh_script="$HOME/.config/hypr/scripts/WallustSwww.sh" +wallust_refresh_script="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts/WallustSwww.sh" notify_user() { local icon="$1" diff --git a/config/hypr/scripts/HyprLayoutModule.sh b/config/hypr/scripts/HyprLayoutModule.sh index 22f12920..14e3b524 100755 --- a/config/hypr/scripts/HyprLayoutModule.sh +++ b/config/hypr/scripts/HyprLayoutModule.sh @@ -9,8 +9,8 @@ IFS=$'\n\t' -SCRIPTSDIR="$HOME/.config/hypr/scripts" -rofi_config="$HOME/.config/rofi/config-waybar-layout.rasi" +SCRIPTSDIR="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts" +rofi_config="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/config-layout.rasi" change_layout="${SCRIPTSDIR}/ChangeLayout.sh" layouts=(dwindle scrolling monocle master) @@ -35,7 +35,17 @@ layout_name() { } get_layout() { - hyprctl -j getoption general:layout 2>/dev/null | jq -r '.str // "unknown"' 2>/dev/null + local layout + + if [[ -x "$change_layout" ]]; then + layout="$("$change_layout" --quiet current 2>/dev/null || true)" + if [[ -n "$layout" ]]; then + printf '%s\n' "$layout" + return + fi + fi + + hyprctl -j activeworkspace 2>/dev/null | jq -r '.tiledLayout // .tiled_layout // "unknown"' 2>/dev/null } next_layout() { @@ -68,7 +78,7 @@ show_status() { current="$(get_layout)" icon="$(layout_icon "$current")" name="$(layout_name "$current")" - tooltip="Hyprland layout: ${name} (${icon})\n\nLeft click: Select layout\nRight click: Cycle layout\n\nOptions:\n🄳 Dwindle\n🅂 Scrolling\n🄼 Monocle\nⓜ Master" + tooltip="Workspace layout: ${name} (${icon})\n\nLeft click: Select layout for active workspace\nRight click: Cycle active workspace layout\n\nOptions:\n🄳 Dwindle\n🅂 Scrolling\n🄼 Monocle\nⓜ Master" printf '{"text":"%s","tooltip":"%s","class":"%s"}\n' "$icon" "$tooltip" "$current" } @@ -97,7 +107,7 @@ show_menu() { return 0 fi - choice="$(printf '%s\n' "${options[@]}" | rofi -i -dmenu -p "Layout" -mesg "Left click selects • Right click cycles" -selected-row "$default_row" -config "$rofi_config")" + choice="$(printf '%s\n' "${options[@]}" | rofi -i -dmenu -p "Workspace layout" -mesg "Select layout for this workspace" -selected-row "$default_row" -config "$rofi_config")" [[ -z "$choice" ]] && exit 0 case "$choice" in diff --git a/config/hypr/scripts/HyprlockWallpaperSelect.sh b/config/hypr/scripts/HyprlockWallpaperSelect.sh new file mode 100755 index 00000000..a139ca36 --- /dev/null +++ b/config/hypr/scripts/HyprlockWallpaperSelect.sh @@ -0,0 +1,358 @@ +#!/usr/bin/env bash +# ================================================== +# KoolDots (2026) +# Project URL: https://github.com/LinuxBeginnings +# License: GNU GPLv3 +# SPDX-License-Identifier: GPL-3.0-or-later +# ================================================== +# Hyprlock wallpaper selector (images + video fallback) + +PICTURES_DIR="$(xdg-user-dir PICTURES 2>/dev/null || echo "$HOME/Pictures")" +wallDIR="$PICTURES_DIR/wallpapers" +scriptsDir="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts" +iDIR="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/images" +# shellcheck source=/dev/null +. "$scriptsDir/WallpaperCmd.sh" 2>/dev/null || true + +rofi_theme="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/config-wallpaper.rasi" +lock_cache_dir="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/wallpaper_effects" +lock_wallpaper_link="$lock_cache_dir/.hyprlock_current" +lock_wallpaper_current="$lock_cache_dir/.wallpaper_current" +video_cache_dir="$HOME/.cache/hyprlock_preview" +find_notify_send() { + local candidate="" + if candidate="$(command -v notify-send 2>/dev/null)"; then + [ -n "$candidate" ] && [ -x "$candidate" ] && { printf '%s\n' "$candidate"; return 0; } + fi + for candidate in /usr/bin/notify-send /usr/sbin/notify-send /bin/notify-send /sbin/notify-send; do + [ -x "$candidate" ] && { printf '%s\n' "$candidate"; return 0; } + done + return 1 +} + +NOTIFY_SEND_BIN="$(find_notify_send || true)" + +notify_err() { + if [ -n "$NOTIFY_SEND_BIN" ]; then + if [ -f "$iDIR/error.png" ]; then + "$NOTIFY_SEND_BIN" -i "$iDIR/error.png" "Hyprlock Wallpaper" "$1" + else + "$NOTIFY_SEND_BIN" "Hyprlock Wallpaper" "$1" + fi + fi +} + +notify_ok() { + if [ -n "$NOTIFY_SEND_BIN" ]; then + if [ -f "$iDIR/ja.png" ]; then + "$NOTIFY_SEND_BIN" -i "$iDIR/ja.png" "Hyprlock Wallpaper" "$1" + else + "$NOTIFY_SEND_BIN" "Hyprlock Wallpaper" "$1" + fi + fi +} + +if ! command -v rofi >/dev/null 2>&1; then + notify_err "rofi not found" + exit 1 +fi +if ! command -v hyprctl >/dev/null 2>&1; then + notify_err "hyprctl not found" + exit 1 +fi +if ! command -v jq >/dev/null 2>&1; then + notify_err "jq not found" + exit 1 +fi +if ! command -v bc >/dev/null 2>&1; then + notify_err "bc not found" + exit 1 +fi +read_wallpaper_from_query() { + local monitor="$1" + [ -n "$monitor" ] || return 1 + "$WWW_CMD" query 2>/dev/null | awk -v mon="$monitor" ' + { + line=$0 + sub(/^Monitor[[:space:]]+/, "", line) + sub(/^:[[:space:]]*/, "", line) + mon_name=line + sub(/:.*/, "", mon_name) + gsub(/^[[:space:]]+|[[:space:]]+$/, "", mon_name) + if (mon_name != mon) next + + path=line + sub(/^.*image:[[:space:]]*/, "", path) + gsub(/^[[:space:]]+|[[:space:]]+$/, "", path) + if (path != line && length(path) > 0) { + print path + exit + } + } + ' +} + +read_cached_wallpaper() { + local cache_file="$1" + [ -f "$cache_file" ] || return 1 + awk 'NF && $0 !~ /^filter/ {print; exit}' "$cache_file" +} + +read_wallpaper_from_cache() { + local monitor="$1" + local cache_root="${WWW_CACHE_DIR:-$HOME/.cache/awww}" + local cache_file="$cache_root/$monitor" + local fallback_cache="" + local path="" + + case "$cache_root" in + "$HOME/.cache/awww") + fallback_cache="$HOME/.cache/swww/$monitor" + ;; + "$HOME/.cache/swww") + fallback_cache="$HOME/.cache/awww/$monitor" + ;; + esac + + path="$(read_cached_wallpaper "$cache_file" 2>/dev/null || true)" + if [ -z "$path" ] && [ -n "$fallback_cache" ]; then + path="$(read_cached_wallpaper "$fallback_cache" 2>/dev/null || true)" + fi + + [ -n "$path" ] && [ -f "$path" ] || return 1 + printf '%s\n' "$path" +} + +get_active_workspace_monitor() { + hyprctl activeworkspace -j 2>/dev/null | jq -r '.monitor // empty' | head -n1 +} + +monitor_exists() { + local monitor="$1" + [ -n "$monitor" ] || return 1 + hyprctl monitors -j 2>/dev/null | jq -r --arg mon "$monitor" '.[] | select(.name == $mon) | .name' | grep -qx "$monitor" +} + +focused_monitor="" +requested_monitor="${1:-${HYPRLOCK_TARGET_MONITOR:-}}" +if monitor_exists "$requested_monitor"; then + focused_monitor="$requested_monitor" +fi +if [[ -z "$focused_monitor" ]]; then + workspace_monitor="$(get_active_workspace_monitor)" + if monitor_exists "$workspace_monitor"; then + focused_monitor="$workspace_monitor" + fi +fi +if [[ -z "$focused_monitor" ]]; then + focused_monitor=$(hyprctl monitors -j | jq -r '.[] | select(.focused) | .name' | head -n1) +fi +if [[ -z "$focused_monitor" ]]; then + notify_err "Could not detect target monitor" + exit 1 +fi + +per_monitor_rofi_link="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/.current_wallpaper_${focused_monitor}" +per_monitor_wallpaper_current="$lock_cache_dir/.wallpaper_current_${focused_monitor}" + +scale_factor=$(hyprctl monitors -j | jq -r --arg mon "$focused_monitor" '.[] | select(.name == $mon) | .scale') +monitor_height=$(hyprctl monitors -j | jq -r --arg mon "$focused_monitor" '.[] | select(.name == $mon) | .height') +icon_size=$(echo "scale=1; ($monitor_height * 3) / ($scale_factor * 150)" | bc) +adjusted_icon_size=$(echo "$icon_size" | awk '{if ($1 < 15) $1 = 20; if ($1 > 25) $1 = 25; print $1}') +rofi_override="element-icon{size:${adjusted_icon_size}%;}" + +mapfile -d '' PICS < <(find -L "${wallDIR}" -type f \( \ + -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" -o -iname "*.gif" -o \ + -iname "*.bmp" -o -iname "*.tiff" -o -iname "*.webp" -o \ + -iname "*.mp4" -o -iname "*.mkv" -o -iname "*.mov" -o -iname "*.webm" \) -print0) + +if [ "${#PICS[@]}" -eq 0 ]; then + notify_err "No wallpapers found in $wallDIR" + exit 1 +fi + +RANDOM_PIC="${PICS[$((RANDOM % ${#PICS[@]}))]}" +RANDOM_PIC_NAME="Random: $(basename "$RANDOM_PIC")" + +current_lock_path="" +if [ -L "$lock_wallpaper_link" ]; then + current_lock_path="$(readlink -f "$lock_wallpaper_link" 2>/dev/null || true)" +elif [ -f "$lock_wallpaper_link" ]; then + current_lock_path="$lock_wallpaper_link" +fi +current_lock_name="" +if [ -n "$current_lock_path" ]; then + current_lock_name="Current: $(basename "$current_lock_path")" +fi + +current_monitor_path="" +if [ -n "${WWW_CMD:-}" ] && command -v "$WWW_CMD" >/dev/null 2>&1; then + current_monitor_path="$(read_wallpaper_from_query "$focused_monitor")" +fi +if [ -z "$current_monitor_path" ] && [ -L "$per_monitor_rofi_link" ]; then + current_monitor_path="$(readlink -f "$per_monitor_rofi_link" 2>/dev/null || true)" +fi +if [ -z "$current_monitor_path" ] && [ -f "$per_monitor_rofi_link" ]; then + current_monitor_path="$per_monitor_rofi_link" +fi +if [ -z "$current_monitor_path" ] && [ -f "$per_monitor_wallpaper_current" ]; then + current_monitor_path="$per_monitor_wallpaper_current" +fi +if [ -z "$current_monitor_path" ]; then + current_monitor_path="$(read_wallpaper_from_cache "$focused_monitor" 2>/dev/null || true)" +fi +if [ -n "$current_monitor_path" ] && [ ! -f "$current_monitor_path" ]; then + current_monitor_path="" +fi +current_monitor_name="" +if [ -n "$current_monitor_path" ]; then + current_monitor_name="Current monitor: $(basename "$current_monitor_path")" +fi + +rofi_command="rofi -i -show -dmenu -config $rofi_theme -theme-str $rofi_override" + +menu() { + IFS=$'\n' sorted_options=($(sort <<<"${PICS[*]}")) + printf "%s\x00icon\x1f%s\n" "$RANDOM_PIC_NAME" "$RANDOM_PIC" + if [ -n "$current_monitor_name" ]; then + printf "%s\x00icon\x1f%s\n" "$current_monitor_name" "$current_monitor_path" + fi + if [ -n "$current_lock_name" ]; then + printf "%s\x00icon\x1f%s\n" "$current_lock_name" "$current_lock_path" + fi + for pic_path in "${sorted_options[@]}"; do + pic_name=$(basename "$pic_path") + if [[ "$pic_name" =~ \.gif$ ]]; then + cache_gif_image="$HOME/.cache/gif_preview/${pic_name}.png" + if [[ ! -f "$cache_gif_image" ]]; then + mkdir -p "$HOME/.cache/gif_preview" + magick "$pic_path[0]" -resize 1920x1080 "$cache_gif_image" + fi + printf "%s\x00icon\x1f%s\n" "$pic_name" "$cache_gif_image" + elif [[ "$pic_name" =~ \.(mp4|mkv|mov|webm|MP4|MKV|MOV|WEBM)$ ]]; then + cache_preview_image="$HOME/.cache/video_preview/${pic_name}.png" + if [[ ! -f "$cache_preview_image" ]]; then + mkdir -p "$HOME/.cache/video_preview" + ffmpeg -v error -y -i "$pic_path" -ss 00:00:01.000 -vframes 1 "$cache_preview_image" + fi + printf "%s\x00icon\x1f%s\n" "$pic_name" "$cache_preview_image" + else + printf "%s\x00icon\x1f%s\n" "$pic_name" "$pic_path" + fi + done +} + +update_hyprlock_config() { + local conf="$1" + local path="$2" + [ -f "$conf" ] || return 0 + + if grep -qE '^[[:space:]]*path[[:space:]]*=' "$conf"; then + sed -i -E "s|^[[:space:]]*path[[:space:]]*=.*| path = $path|" "$conf" + elif grep -qE '^[[:space:]]*background[[:space:]]*{' "$conf"; then + sed -i -E "/^[[:space:]]*background[[:space:]]*{/a\\ path = $path" "$conf" + else + printf "\nbackground {\n path = %s\n}\n" "$path" >>"$conf" + fi +} + +set_hyprlock_wallpaper() { + local selected_file="$1" + local target_monitor="${2:-$focused_monitor}" + local final_path="$selected_file" + + if [ ! -f "$selected_file" ]; then + notify_err "Failed for $target_monitor: selected file not found" + return 1 + fi + + if [[ "$selected_file" =~ \.(mp4|mkv|mov|webm|MP4|MKV|MOV|WEBM)$ ]]; then + if ! command -v ffmpeg >/dev/null 2>&1; then + notify_err "Failed for $target_monitor: ffmpeg not found for video preview" + return 1 + fi + mkdir -p "$video_cache_dir" + local video_name + video_name="$(basename "$selected_file")" + final_path="$video_cache_dir/${video_name}.png" + if ! ffmpeg -v error -y -i "$selected_file" -ss 00:00:01.000 -vframes 1 "$final_path"; then + notify_err "Failed for $target_monitor: could not generate video preview" + return 1 + fi + fi + + mkdir -p "$lock_cache_dir" + if ! ln -sf "$final_path" "$lock_wallpaper_link"; then + notify_err "Failed for $target_monitor: could not update hyprlock wallpaper link" + return 1 + fi + if ! cp -f "$final_path" "$lock_wallpaper_current"; then + notify_err "Failed for $target_monitor: could not update lock fallback wallpaper" + return 1 + fi + + update_hyprlock_config "${XDG_CONFIG_HOME:-$HOME/.config}/hypr/hyprlock.conf" "$lock_wallpaper_link" + update_hyprlock_config "${XDG_CONFIG_HOME:-$HOME/.config}/hypr/hyprlock-2k.conf" "$lock_wallpaper_link" + update_hyprlock_config "${XDG_CONFIG_HOME:-$HOME/.config}/hypr/hyprlock-1080p.conf" "$lock_wallpaper_link" + + pkill -USR1 hyprlock 2>/dev/null || true + + local resolved_path="" + if [ -L "$lock_wallpaper_link" ]; then + resolved_path="$(readlink -f "$lock_wallpaper_link" 2>/dev/null || true)" + elif [ -f "$lock_wallpaper_link" ]; then + resolved_path="$lock_wallpaper_link" + fi + + if [ -z "$resolved_path" ] || [ ! -f "$resolved_path" ]; then + notify_err "Failed for $target_monitor: hyprlock wallpaper was not applied" + return 1 + fi + + notify_ok "Set for $target_monitor: $(basename "$resolved_path")" + return 0 +} + +main() { + choice=$(menu | $rofi_command) + choice=$(echo "$choice" | xargs) + + if [[ -z "$choice" ]]; then + exit 0 + fi + + if [[ "$choice" == "$RANDOM_PIC_NAME" ]]; then + set_hyprlock_wallpaper "$RANDOM_PIC" "$focused_monitor" || exit 1 + return + fi + if [[ "$choice" == "$current_monitor_name" && -n "$current_monitor_path" ]]; then + set_hyprlock_wallpaper "$current_monitor_path" "$focused_monitor" || exit 1 + return + fi + + if [[ "$choice" == "$current_lock_name" && -n "$current_lock_path" ]]; then + set_hyprlock_wallpaper "$current_lock_path" "$focused_monitor" || exit 1 + return + fi + + if [[ -f "$choice" ]]; then + set_hyprlock_wallpaper "$choice" "$focused_monitor" || exit 1 + return + fi + + choice_basename=$(basename "$choice" | sed 's/\(.*\)\.[^.]*$/\1/') + selected_file=$(find "$wallDIR" -iname "$choice_basename.*" -print -quit) + + if [[ -z "$selected_file" ]]; then + notify_err "Selected choice not found: $choice" + exit 1 + fi + + set_hyprlock_wallpaper "$selected_file" "$focused_monitor" || exit 1 +} + +if pidof rofi >/dev/null; then + pkill rofi +fi + +main diff --git a/config/hypr/scripts/JavaManager.sh b/config/hypr/scripts/JavaManager.sh index 728c69a3..8f8f5612 100755 --- a/config/hypr/scripts/JavaManager.sh +++ b/config/hypr/scripts/JavaManager.sh @@ -201,7 +201,7 @@ generate_list() { } # --- 6. rofi --- -THEME="$HOME/.config/rofi/config.rasi" +THEME="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/config.rasi" SELECTION=$(generate_list | rofi -dmenu -i \ -p " Java" \ diff --git a/config/hypr/scripts/KeyBinds.sh b/config/hypr/scripts/KeyBinds.sh index 1005e797..aff7b808 100755 --- a/config/hypr/scripts/KeyBinds.sh +++ b/config/hypr/scripts/KeyBinds.sh @@ -16,7 +16,7 @@ if pidof rofi > /dev/null; then fi # define the config files -config_home="${XDG_CONFIG_HOME:-$HOME/.config}" +config_home="${XDG_CONFIG_HOME:-${XDG_CONFIG_HOME:-$HOME/.config}}" hypr_dir="$config_home/hypr" keybinds_conf="$hypr_dir/configs/Keybinds.conf" user_keybinds_conf="$hypr_dir/UserConfigs/UserKeybinds.conf" @@ -26,7 +26,7 @@ lua_user_keybinds="$hypr_dir/UserConfigs/user_keybinds.lua" lua_system_keybinds="$hypr_dir/configs/system_keybinds.lua" lua_legacy_system_keybinds="$hypr_dir/UserConfigs/system_keybinds.lua" lua_overrides="$hypr_dir/UserConfigs/user_overrides.lua" -rofi_theme="$HOME/.config/rofi/config-keybinds.rasi" +rofi_theme="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/config-keybinds.rasi" msg='☣️ NOTE ☣️: Clicking with Mouse or Pressing ENTER will have NO function' # detect active Hyprland config mode (Lua entrypoint vs legacy .conf includes) @@ -55,7 +55,7 @@ fi # 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[@]}") +display_keybinds=$("${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts/keybinds_parser.py" "${files[@]}") # Check for suggestions file created by python script if [[ -f "/tmp/hypr_keybind_suggestions_file" ]]; then diff --git a/config/hypr/scripts/KeyHints.sh b/config/hypr/scripts/KeyHints.sh index a9f6660a..08415dab 100755 --- a/config/hypr/scripts/KeyHints.sh +++ b/config/hypr/scripts/KeyHints.sh @@ -61,8 +61,8 @@ GDK_BACKEND=$BACKEND yad \ "CTRL ALT L" "screen lock" "(hyprlock)" \ "CTRL ALT Del" "Hyprland Exit" "(NOTE: Hyprland Will exit immediately)" \ " SHIFT F" "Fullscreen" "Toggles to full screen" \ - " CTL F" "Fake Fullscreen" "Toggles to fake full screen" \ - " ALT L" "Toggle Dwindle|Floating|Monocle|Master layouts" "Hyprland Layouts" \ + " F" "Fake Fullscreen" "Toggles to fake full screen" \ + " ALT L" "Toggle Dwindle|Scrolling|Monocle|Master layouts" "Active workspace layout" \ " SPACEBAR" "Toggle float" "single window" \ " ALT SPACEBAR" "Toggle all windows to float" "all windows" \ " ALT O" "Toggle Blur" "normal or less blur" \ diff --git a/config/hypr/scripts/KeybindsLayoutInit.sh b/config/hypr/scripts/KeybindsLayoutInit.sh index 280e381b..08aff951 100755 --- a/config/hypr/scripts/KeybindsLayoutInit.sh +++ b/config/hypr/scripts/KeybindsLayoutInit.sh @@ -5,14 +5,14 @@ # License: GNU GPLv3 # SPDX-License-Identifier: GPL-3.0-or-later # ================================================== -# Initialize J/K keybinds so they always cycle windows globally (no layout-specific behavior). +# Legacy startup hook for layout keybind initialization. +# Runtime keybind behavior is now resolved per keypress based on active workspace layout. set -euo pipefail -# Always reset and bind SUPER+J/K the same way on startup -hyprctl keyword unbind SUPER,j || true -hyprctl keyword unbind SUPER,k || true +scripts_dir="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts" -# Cycle windows globally -hyprctl keyword bind SUPER,j,cyclenext -hyprctl keyword bind SUPER,k,cyclenext,prev +# Keep compatibility with existing startup entries while avoiding global rebinding. +if [[ -x "${scripts_dir}/ChangeLayout.sh" ]]; then + "${scripts_dir}/ChangeLayout.sh" --quiet init >/dev/null 2>&1 || true +fi diff --git a/config/hypr/scripts/KeyboardLayout.sh b/config/hypr/scripts/KeyboardLayout.sh index fe092e7f..f126b895 100755 --- a/config/hypr/scripts/KeyboardLayout.sh +++ b/config/hypr/scripts/KeyboardLayout.sh @@ -5,10 +5,10 @@ # License: GNU GPLv3 # SPDX-License-Identifier: GPL-3.0-or-later # ================================================== -# This is for changing kb_layouts. Set kb_layouts in "$HOME/.config/hypr/UserConfigs/UserSettings.conf" +# This is for changing kb_layouts. Set kb_layouts in "${XDG_CONFIG_HOME:-$HOME/.config}/hypr/UserConfigs/UserSettings.conf" -notif_icon="$HOME/.config/swaync/images/ja.png" -SCRIPTSDIR="$HOME/.config/hypr/scripts" +notif_icon="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/images/ja.png" +SCRIPTSDIR="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts" # Refined ignore list with patterns or specific device names ignore_patterns=( diff --git a/config/hypr/scripts/KillActiveProcess.sh b/config/hypr/scripts/KillActiveProcess.sh index 66d6b009..9af3f813 100755 --- a/config/hypr/scripts/KillActiveProcess.sh +++ b/config/hypr/scripts/KillActiveProcess.sh @@ -13,7 +13,7 @@ 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." + notify-send -u low -i "${XDG_CONFIG_HOME:-$HOME/.config}/swaync/images/error.png" "Kill Active Window" "No active window PID found." exit 1 fi diff --git a/config/hypr/scripts/Kitty_themes.sh b/config/hypr/scripts/Kitty_themes.sh index 24a4ae11..0de21f8c 100755 --- a/config/hypr/scripts/Kitty_themes.sh +++ b/config/hypr/scripts/Kitty_themes.sh @@ -8,11 +8,11 @@ # Kitty Themes Source https://github.com/dexpota/kitty-themes # # Define directories and variables -kitty_themes_DiR="$HOME/.config/kitty/kitty-themes" # Kitty Themes Directory -kitty_config="$HOME/.config/kitty/kitty.conf" -iDIR="$HOME/.config/swaync/images" # For notifications -rofi_theme_for_this_script="$HOME/.config/rofi/config-kitty-theme.rasi" -wallust_refresh_script="$HOME/.config/hypr/scripts/WallustSwww.sh" +kitty_themes_DiR="${XDG_CONFIG_HOME:-$HOME/.config}/kitty/kitty-themes" # Kitty Themes Directory +kitty_config="${XDG_CONFIG_HOME:-$HOME/.config}/kitty/kitty.conf" +iDIR="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/images" # For notifications +rofi_theme_for_this_script="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/config-kitty-theme.rasi" +wallust_refresh_script="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts/WallustSwww.sh" debug_log="${XDG_CACHE_HOME:-$HOME/.cache}/kooldots-kitty-themes.log" # --- Helper Functions --- diff --git a/config/hypr/scripts/KooLsDotsUpdate.sh b/config/hypr/scripts/KooLsDotsUpdate.sh index 887993a5..0cfb42a4 100755 --- a/config/hypr/scripts/KooLsDotsUpdate.sh +++ b/config/hypr/scripts/KooLsDotsUpdate.sh @@ -8,8 +8,8 @@ # simple bash script to check if update is available by comparing local version and github version # Local Paths -local_dir="$HOME/.config/hypr" -iDIR="$HOME/.config/swaync/images/" +local_dir="${XDG_CONFIG_HOME:-$HOME/.config}/hypr" +iDIR="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/images/" 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" diff --git a/config/hypr/scripts/Kool_Quick_Settings.sh b/config/hypr/scripts/Kool_Quick_Settings.sh index 6ec02bb8..70e98459 100755 --- a/config/hypr/scripts/Kool_Quick_Settings.sh +++ b/config/hypr/scripts/Kool_Quick_Settings.sh @@ -49,11 +49,31 @@ fi # variables configs="$hypr_dir/configs" UserConfigs="$hypr_dir/UserConfigs" -rofi_theme="$HOME/.config/rofi/config-edit.rasi" +rofi_theme="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/config-edit.rasi" msg=' ⁉️ Choose what to do ⁉️' -iDIR="$HOME/.config/swaync/images" +iDIR="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/images" scriptsDir="$hypr_dir/scripts" UserScripts="$hypr_dir/UserScripts" +user_defaults_conf="$UserConfigs/01-UserDefaults.conf" +user_defaults_lua="$UserConfigs/user_defaults.lua" +user_env_conf="$UserConfigs/ENVariables.conf" +user_env_lua="$UserConfigs/user_env.lua" +user_keybinds_conf="$UserConfigs/UserKeybinds.conf" +user_keybinds_lua="$UserConfigs/user_keybinds.lua" +user_startup_conf="$UserConfigs/Startup_Apps.conf" +user_startup_lua="$UserConfigs/user_startup.lua" +user_window_rules_conf="$UserConfigs/WindowRules.conf" +user_window_rules_lua="$UserConfigs/user_window_rules.lua" +user_layer_rules_conf="$UserConfigs/LayerRules.conf" +user_layer_rules_lua="$UserConfigs/user_layer_rules.lua" +user_settings_conf="$UserConfigs/UserSettings.conf" +user_settings_lua="$UserConfigs/user_settings.lua" +user_decorations_conf="$UserConfigs/UserDecorations.conf" +user_decorations_lua="$UserConfigs/user_decorations.lua" +user_animations_conf="$UserConfigs/UserAnimations.conf" +user_animations_lua="$UserConfigs/user_animations.lua" +user_laptops_conf="$UserConfigs/Laptops.conf" +user_laptops_lua="$UserConfigs/user_laptops.lua" # Function to show info notification show_info() { @@ -64,6 +84,22 @@ show_info() { fi } +get_context_monitor_name() { + if ! command -v hyprctl >/dev/null 2>&1; then + return 1 + fi + local monitor="" + if command -v jq >/dev/null 2>&1; then + monitor="$(hyprctl activeworkspace -j 2>/dev/null | jq -r '.monitor // empty' | head -n1)" + if [[ -z "$monitor" ]]; then + monitor="$(hyprctl monitors -j 2>/dev/null | jq -r '.[] | select(.focused) | .name' | head -n1)" + fi + else + monitor="$(hyprctl monitors 2>/dev/null | awk '/^Monitor/{name=$2} /focused: yes/{print name; exit}')" + fi + printf '%s' "$monitor" +} + # Determine whether an editor command is terminal-based (TUI) is_tui_editor() { local -a cmd=("$@") @@ -103,9 +139,24 @@ resolve_system_lua_file() { fi } -resolve_user_defaults_lua_file() { - local preferred="$UserConfigs/user_defaults.lua" - printf '%s' "$preferred" +resolve_mode_file() { + local preferred="$1" + local fallback="$2" + if [[ -f "$preferred" || ! -f "$fallback" ]]; then + printf '%s' "$preferred" + else + printf '%s' "$fallback" + fi +} + +resolve_user_overlay_file() { + local lua_file="$1" + local conf_file="$2" + if [[ "$hypr_config_mode" == "lua" ]]; then + resolve_mode_file "$lua_file" "$conf_file" + else + resolve_mode_file "$conf_file" "$lua_file" + fi } # Function to toggle Rainbow Borders script availability and refresh UI components toggle_rainbow_borders() { @@ -271,6 +322,7 @@ Edit System Default Startup Apps Edit System Default Window Rules Edit System Default Layer Rules Edit System Default Settings +Change Starship Prompt --- UTILITIES --- Set SDDM Wallpaper Choose Kitty Terminal Theme @@ -280,11 +332,13 @@ Configure Workspace Rules (nwg-displays) GTK Settings (nwg-look) QT Apps Settings (qt6ct) QT Apps Settings (qt5ct) +Set Hyprlock Wallpaper Choose Hyprland Animations Choose Monitor Profiles Choose Rofi Themes Search for Keybinds Toggle Waybar Weather units (C/F) +Toggle Waybar Clock (12H/24H) Toggle Game Mode Switch Dark-Light Theme Rainbow Borders Mode @@ -293,36 +347,32 @@ EOF # Main function to handle menu selection main() { + local quick_settings_monitor + quick_settings_monitor="$(get_context_monitor_name)" choice=$(menu | rofi -i -dmenu -config $rofi_theme -mesg "$msg") # Map choices to corresponding files case "$choice" in "Edit User Defaults") - if [[ "$hypr_config_mode" == "lua" ]]; then file="$(resolve_user_defaults_lua_file)"; else file="$UserConfigs/01-UserDefaults.conf"; fi ;; + file="$(resolve_user_overlay_file "$user_defaults_lua" "$user_defaults_conf")" ;; "Edit User ENV variables") - if [[ "$hypr_config_mode" == "lua" ]]; then file="$UserConfigs/user_env.lua"; else file="$UserConfigs/ENVariables.conf"; fi ;; + file="$(resolve_user_overlay_file "$user_env_lua" "$user_env_conf")" ;; "Edit User Keybinds") - if [[ "$hypr_config_mode" == "lua" ]]; then file="$UserConfigs/user_keybinds.lua"; else file="$UserConfigs/UserKeybinds.conf"; fi ;; + file="$(resolve_user_overlay_file "$user_keybinds_lua" "$user_keybinds_conf")" ;; "Edit User Startup Apps (overlay)") - if [[ "$hypr_config_mode" == "lua" ]]; then file="$UserConfigs/user_startup.lua"; else file="$UserConfigs/Startup_Apps.conf"; fi ;; + file="$(resolve_user_overlay_file "$user_startup_lua" "$user_startup_conf")" ;; "Edit User Window Rules (overlay)") - if [[ "$hypr_config_mode" == "lua" ]]; then file="$UserConfigs/user_window_rules.lua"; else file="$UserConfigs/WindowRules.conf"; fi ;; + file="$(resolve_user_overlay_file "$user_window_rules_lua" "$user_window_rules_conf")" ;; "Edit User Layer Rules (overlay)") - if [[ "$hypr_config_mode" == "lua" ]]; then file="$UserConfigs/user_layer_rules.lua"; else file="$UserConfigs/LayerRules.conf"; fi ;; + file="$(resolve_user_overlay_file "$user_layer_rules_lua" "$user_layer_rules_conf")" ;; "Edit User Settings") - if [[ "$hypr_config_mode" == "lua" ]]; then - file="$UserConfigs/user_settings.lua" - show_info "Lua mode detected. Edit UserConfigs/user_settings.lua for user settings." - else - file="$configs/SystemSettings.conf" - show_info "Editing default settings. Copy to UserConfigs/UserSettings.conf to override." - fi ;; + file="$(resolve_user_overlay_file "$user_settings_lua" "$user_settings_conf")" ;; "Edit User Decorations") - if [[ "$hypr_config_mode" == "lua" ]]; then file="$UserConfigs/user_decorations.lua"; else file="$UserConfigs/UserDecorations.conf"; fi ;; + file="$(resolve_user_overlay_file "$user_decorations_lua" "$user_decorations_conf")" ;; "Edit User Animations") - if [[ "$hypr_config_mode" == "lua" ]]; then file="$UserConfigs/user_animations.lua"; else file="$UserConfigs/UserAnimations.conf"; fi ;; + file="$(resolve_user_overlay_file "$user_animations_lua" "$user_animations_conf")" ;; "Edit User Laptop Settings") - if [[ "$hypr_config_mode" == "lua" ]]; then file="$UserConfigs/user_laptops.lua"; else file="$UserConfigs/Laptops.conf"; fi ;; + file="$(resolve_user_overlay_file "$user_laptops_lua" "$user_laptops_conf")" ;; "Edit System Default Keybinds") if [[ "$hypr_config_mode" == "lua" ]]; then file="$(resolve_system_lua_file system_keybinds.lua)"; else file="$configs/Keybinds.conf"; fi ;; "Edit System Default Startup Apps") @@ -333,7 +383,14 @@ main() { if [[ "$hypr_config_mode" == "lua" ]]; then file="$(resolve_system_lua_file system_layer_rules.lua)"; else file="$configs/LayerRules.conf"; fi ;; "Edit System Default Settings") if [[ "$hypr_config_mode" == "lua" ]]; then file="$(resolve_system_lua_file system_settings.lua)"; else file="$configs/SystemSettings.conf"; fi ;; - "Set SDDM Wallpaper") $scriptsDir/sddm_wallpaper.sh --normal ;; + "Change Starship Prompt") "$scriptsDir/ChangeStarshipPrompt.sh" ;; + "Set SDDM Wallpaper") + if [[ -n "$quick_settings_monitor" ]]; then + "$scriptsDir/sddm_wallpaper.sh" --normal "$quick_settings_monitor" + else + "$scriptsDir/sddm_wallpaper.sh" --normal + fi + ;; "Choose Kitty Terminal Theme") $scriptsDir/Kitty_themes.sh ;; "Choose Ghostty Terminal Theme") $scriptsDir/Ghostty_themes.sh ;; "Configure Monitors (nwg-displays)") @@ -366,11 +423,19 @@ main() { exit 1 fi qt5ct ;; + "Set Hyprlock Wallpaper") + if [[ -n "$quick_settings_monitor" ]]; then + "$scriptsDir/HyprlockWallpaperSelect.sh" "$quick_settings_monitor" + else + "$scriptsDir/HyprlockWallpaperSelect.sh" + fi + ;; "Choose Hyprland Animations") $scriptsDir/Animations.sh ;; "Choose Monitor Profiles") $scriptsDir/MonitorProfiles.sh ;; "Choose Rofi Themes") $scriptsDir/RofiThemeSelector.sh ;; "Search for Keybinds") $scriptsDir/KeyBinds.sh ;; "Toggle Waybar Weather units (C/F)") $scriptsDir/Toggle-weather-waybar-units.sh ;; + "Toggle Waybar Clock (12H/24H)") $scriptsDir/ToggleWaybarTime.sh ;; "Toggle Game Mode") $scriptsDir/GameMode.sh ;; "Switch Dark-Light Theme") $scriptsDir/DarkLight.sh ;; "Rainbow Borders Mode") rainbow_borders_menu ;; diff --git a/config/hypr/scripts/LaunchFileManager.sh b/config/hypr/scripts/LaunchFileManager.sh new file mode 100755 index 00000000..8436451b --- /dev/null +++ b/config/hypr/scripts/LaunchFileManager.sh @@ -0,0 +1,122 @@ +#!/usr/bin/env bash +# ================================================== +# KoolDots (2026) +# Project URL: https://github.com/LinuxBeginnings +# License: GNU GPLv3 +# SPDX-License-Identifier: GPL-3.0-or-later +# ================================================== +# Launch preferred file manager with fallback handling. +# Usage: +# LaunchFileManager.sh "<preferred-file-manager-cmd>" "<preferred-terminal-cmd>" +# Examples: +# LaunchFileManager.sh "thunar" "kitty" + +set -u + +notify_msg() { + local urgency="${1:-normal}" + local body="${2:-}" + if command -v notify-send >/dev/null 2>&1; then + notify-send -u "$urgency" "KooL Launchers" "$body" + fi +} + +trim() { + local value="${1:-}" + value="${value#"${value%%[![:space:]]*}"}" + value="${value%"${value##*[![:space:]]}"}" + printf '%s' "$value" +} + +command_bin_from_string() { + local cmd + cmd="$(trim "${1:-}")" + [[ -n "$cmd" ]] || return 1 + ( + eval "set -- $cmd" + printf '%s' "${1:-}" + ) 2>/dev/null +} + +command_exists_from_string() { + local bin + bin="$(command_bin_from_string "${1:-}" 2>/dev/null || true)" + [[ -n "$bin" ]] || return 1 + command -v "$bin" >/dev/null 2>&1 +} + +launch_command_string() { + local cmd + cmd="$(trim "${1:-}")" + [[ -n "$cmd" ]] || return 1 + + if ! command_exists_from_string "$cmd"; then + return 127 + fi + + ( + eval "exec $cmd" + ) >/dev/null 2>&1 & + local pid=$! + + sleep 0.35 + if kill -0 "$pid" >/dev/null 2>&1; then + disown "$pid" >/dev/null 2>&1 || true + return 0 + fi + + wait "$pid" + local rc=$? + [[ $rc -eq 0 ]] +} + +append_unique_candidate() { + local candidate + candidate="$(trim "${1:-}")" + [[ -n "$candidate" ]] || return 0 + local existing + for existing in "${CANDIDATES[@]}"; do + [[ "$existing" == "$candidate" ]] && return 0 + done + CANDIDATES+=("$candidate") +} + +script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +terminal_launcher="$script_dir/LaunchTerminal.sh" + +preferred_files="$(trim "${1:-${FILE_MANAGER:-}}")" +preferred_term="$(trim "${2:-${TERMINAL:-kitty}}")" + +declare -a CANDIDATES=() +append_unique_candidate "$preferred_files" +append_unique_candidate "thunar" +append_unique_candidate "dolphin" +append_unique_candidate "nautilus" + +reported_preferred_issue=0 + +for candidate in "${CANDIDATES[@]}"; do + if launch_command_string "$candidate"; then + exit 0 + fi + + if [[ $reported_preferred_issue -eq 0 && -n "$preferred_files" && "$candidate" == "$preferred_files" ]]; then + if ! command_exists_from_string "$preferred_files"; then + notify_msg normal "Preferred file manager '$preferred_files' is not installed. Falling back." + else + notify_msg normal "Preferred file manager '$preferred_files' failed to launch. Falling back." + fi + reported_preferred_issue=1 + fi +done + +if command -v yazi >/dev/null 2>&1; then + if [[ -x "$terminal_launcher" ]] && "$terminal_launcher" "$preferred_term" "yazi"; then + exit 0 + fi +else + notify_msg normal "No GUI file manager was launched and 'yazi' is not installed." +fi + +notify_msg critical "Unable to launch file manager. Tried preferred app, thunar, dolphin, nautilus, then terminal + yazi." +exit 1 diff --git a/config/hypr/scripts/LaunchTerminal.sh b/config/hypr/scripts/LaunchTerminal.sh new file mode 100755 index 00000000..8992a40d --- /dev/null +++ b/config/hypr/scripts/LaunchTerminal.sh @@ -0,0 +1,160 @@ +#!/usr/bin/env bash +# ================================================== +# KoolDots (2026) +# Project URL: https://github.com/LinuxBeginnings +# License: GNU GPLv3 +# SPDX-License-Identifier: GPL-3.0-or-later +# ================================================== +# Launch preferred terminal with fallback handling. +# Usage: +# LaunchTerminal.sh "<preferred-terminal-cmd>" [payload-command] +# Examples: +# LaunchTerminal.sh "kitty" +# LaunchTerminal.sh "ghostty" "yazi" + +set -u + +notify_msg() { + local urgency="${1:-normal}" + local body="${2:-}" + if command -v notify-send >/dev/null 2>&1; then + notify-send -u "$urgency" "KooL Launchers" "$body" + fi +} + +trim() { + local value="${1:-}" + value="${value#"${value%%[![:space:]]*}"}" + value="${value%"${value##*[![:space:]]}"}" + printf '%s' "$value" +} + +shell_quote() { + local value="${1:-}" + printf "'%s'" "${value//\'/\'\\\'\'}" +} + +command_bin_from_string() { + local cmd + cmd="$(trim "${1:-}")" + [[ -n "$cmd" ]] || return 1 + ( + eval "set -- $cmd" + printf '%s' "${1:-}" + ) 2>/dev/null +} + +command_exists_from_string() { + local bin + bin="$(command_bin_from_string "${1:-}" 2>/dev/null || true)" + [[ -n "$bin" ]] || return 1 + command -v "$bin" >/dev/null 2>&1 +} + +launch_command_string() { + local cmd + cmd="$(trim "${1:-}")" + [[ -n "$cmd" ]] || return 1 + + if ! command_exists_from_string "$cmd"; then + return 127 + fi + + ( + eval "exec $cmd" + ) >/dev/null 2>&1 & + local pid=$! + + sleep 0.35 + if kill -0 "$pid" >/dev/null 2>&1; then + disown "$pid" >/dev/null 2>&1 || true + return 0 + fi + + wait "$pid" + local rc=$? + [[ $rc -eq 0 ]] +} + +build_terminal_command() { + local term_cmd payload bin q_payload + term_cmd="$(trim "${1:-}")" + payload="$(trim "${2:-}")" + + if [[ -z "$payload" ]]; then + printf '%s' "$term_cmd" + return 0 + fi + + bin="$(command_bin_from_string "$term_cmd" 2>/dev/null || true)" + q_payload="$(shell_quote "$payload")" + + case "$bin" in + gnome-terminal) + printf '%s -- %s' "$term_cmd" "$q_payload" + ;; + wezterm) + case "$term_cmd" in + *" start "* | "wezterm start") + printf '%s -- %s' "$term_cmd" "$q_payload" + ;; + *) + printf '%s start -- %s' "$term_cmd" "$q_payload" + ;; + esac + ;; + *) + printf '%s -e %s' "$term_cmd" "$q_payload" + ;; + esac +} + +append_unique_candidate() { + local candidate + candidate="$(trim "${1:-}")" + [[ -n "$candidate" ]] || return 0 + local existing + for existing in "${CANDIDATES[@]}"; do + [[ "$existing" == "$candidate" ]] && return 0 + done + CANDIDATES+=("$candidate") +} + +preferred_term="$(trim "${1:-${TERMINAL:-}}")" +payload_cmd="$(trim "${2:-}")" + +declare -a CANDIDATES=() +append_unique_candidate "$preferred_term" +append_unique_candidate "kitty" +append_unique_candidate "ghostty" +append_unique_candidate "alacritty" +append_unique_candidate "wezterm" +append_unique_candidate "konsole" +append_unique_candidate "gnome-terminal" + +reported_preferred_issue=0 +candidate_cmd="" + +for candidate in "${CANDIDATES[@]}"; do + candidate_cmd="$(build_terminal_command "$candidate" "$payload_cmd")" + if launch_command_string "$candidate_cmd"; then + exit 0 + fi + + if [[ $reported_preferred_issue -eq 0 && -n "$preferred_term" && "$candidate" == "$preferred_term" ]]; then + if ! command_exists_from_string "$preferred_term"; then + notify_msg normal "Preferred terminal '$preferred_term' is not installed. Falling back." + else + notify_msg normal "Preferred terminal '$preferred_term' failed to launch. Falling back." + fi + reported_preferred_issue=1 + fi +done + +if [[ -n "$payload_cmd" ]]; then + notify_msg critical "Unable to launch terminal for command '$payload_cmd'." +else + notify_msg critical "Unable to launch terminal. Install one of: kitty, ghostty, alacritty, wezterm, konsole, gnome-terminal." +fi + +exit 1 diff --git a/config/hypr/scripts/LaunchThunar.sh b/config/hypr/scripts/LaunchThunar.sh new file mode 100755 index 00000000..08ff911e --- /dev/null +++ b/config/hypr/scripts/LaunchThunar.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +# ================================================== +# KoolDots (2026) +# Project URL: https://github.com/LinuxBeginnings +# License: GNU GPLv3 +# SPDX-License-Identifier: GPL-3.0-or-later +# ================================================== +# +# Launch Thunar reliably from Hyprland keybinds. + +runtime="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}" + +if [ -z "${WAYLAND_DISPLAY:-}" ]; then + for sock in "$runtime"/wayland-[0-9]*; do + [ -S "$sock" ] || continue + case "$(basename "$sock")" in + *awww*) continue ;; + esac + export WAYLAND_DISPLAY="$(basename "$sock")" + break + done +fi + +if [ -z "${DISPLAY:-}" ] && [ -n "${WAYLAND_DISPLAY:-}" ]; then + export DISPLAY=:1 +fi + +# If a stale daemon exists with no visible windows, restart it. +if pgrep -x thunar >/dev/null 2>&1; then + if command -v hyprctl >/dev/null 2>&1; then + if ! python3 - <<'PY' +import json +import subprocess +import sys + +try: + clients = json.loads(subprocess.check_output(["hyprctl", "clients", "-j"], text=True)) +except Exception: + sys.exit(0) + +sys.exit(0 if any((c.get("class") or "").lower() == "thunar" for c in clients) else 1) +PY + then + thunar --quit >/dev/null 2>&1 || pkill -x thunar >/dev/null 2>&1 || true + sleep 0.2 + fi + fi +fi + +exec thunar "$HOME" diff --git a/config/hypr/scripts/LayoutKeybindDispatch.sh b/config/hypr/scripts/LayoutKeybindDispatch.sh new file mode 100755 index 00000000..48d3a1c5 --- /dev/null +++ b/config/hypr/scripts/LayoutKeybindDispatch.sh @@ -0,0 +1,219 @@ +#!/usr/bin/env bash +# ================================================== +# KoolDots (2026) +# Project URL: https://github.com/LinuxBeginnings +# License: GNU GPLv3 +# SPDX-License-Identifier: GPL-3.0-or-later +# ================================================== +# Dispatch layout-sensitive navigation actions per active workspace. +# This keeps SUPER+J/K and SUPER+arrow behavior aligned with workspace rules. + +set -u + +if ! command -v hyprctl >/dev/null 2>&1; then + exit 0 +fi + +LUA_CYCLE_SCRIPT="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts/LuaCycleWindow.sh" + +normalize_layout() { + case "$1" in + master | dwindle | scrolling | monocle) + printf '%s\n' "$1" + ;; + *) + printf '\n' + ;; + esac +} + +get_active_layout() { + local layout + + layout="$(hyprctl -j activeworkspace 2>/dev/null | jq -r '.tiledLayout // .tiled_layout // .layout // empty' 2>/dev/null || true)" + layout="$(normalize_layout "$layout")" + + if [[ -z "$layout" ]]; then + layout="$(hyprctl -j getoption general:layout 2>/dev/null | jq -r '.str // empty' 2>/dev/null || true)" + layout="$(normalize_layout "$layout")" + fi + + if [[ -z "$layout" ]]; then + layout="dwindle" + fi + + printf '%s\n' "$layout" +} + +dispatch_quiet() { + local dispatcher="$1" + shift || true + if (($# > 0)); then + hyprctl dispatch "$dispatcher" "$@" >/dev/null 2>&1 || true + else + hyprctl dispatch "$dispatcher" >/dev/null 2>&1 || true + fi +} + +get_active_window_address() { + if ! command -v jq >/dev/null 2>&1; then + printf '\n' + return 0 + fi + hyprctl -j activewindow 2>/dev/null | jq -r '.address // empty' 2>/dev/null || true +} + +dispatch_changed_focus() { + local before after dispatcher="$1" + shift || true + before="$(get_active_window_address)" + dispatch_quiet "$dispatcher" "$@" + after="$(get_active_window_address)" + [[ -n "$before" && -n "$after" && "$before" != "$after" ]] +} + +direction_word() { + case "$1" in + l | left) printf 'left\n' ;; + r | right) printf 'right\n' ;; + u | up) printf 'up\n' ;; + d | down) printf 'down\n' ;; + *) printf 'right\n' ;; + esac +} + +dispatch_lua_focus() { + local dir_word + dir_word="$(direction_word "$1")" + hyprctl dispatch "hl.dsp.focus({ direction = \"$dir_word\" })" >/dev/null 2>&1 || true +} + +cycle_lua() { + local mode="${1:-next}" + if [[ -x "$LUA_CYCLE_SCRIPT" ]]; then + "$LUA_CYCLE_SCRIPT" "$mode" >/dev/null 2>&1 || true + return 0 + fi + case "$mode" in + previous | prev | back) dispatch_lua_focus left ;; + *) dispatch_lua_focus right ;; + esac +} + +cycle_next() { + local layout="$1" + case "$layout" in + scrolling) + if ! dispatch_changed_focus layoutmsg "focus r"; then + dispatch_lua_focus right + fi + ;; + monocle) + if ! dispatch_changed_focus layoutmsg cyclenext; then + cycle_lua next + fi + ;; + *) + if ! dispatch_changed_focus cyclenext; then + cycle_lua next + fi + ;; + esac +} + +cycle_prev() { + local layout="$1" + case "$layout" in + scrolling) + if ! dispatch_changed_focus layoutmsg "focus l"; then + dispatch_lua_focus left + fi + ;; + monocle) + if ! dispatch_changed_focus layoutmsg cycleprev; then + cycle_lua previous + fi + ;; + *) + if ! dispatch_changed_focus cyclenext prev; then + cycle_lua previous + fi + ;; + esac +} + +focus_by_layout() { + local layout="$1" + local direction="$2" + + case "$layout" in + master) + if ! dispatch_changed_focus movefocus "$direction"; then + dispatch_lua_focus "$direction" + fi + ;; + monocle) + case "$direction" in + l | u) cycle_prev "$layout" ;; + *) cycle_next "$layout" ;; + esac + ;; + dwindle | scrolling) + case "$direction" in + l | u) + if [[ "$layout" == "scrolling" ]]; then + if ! dispatch_changed_focus layoutmsg "focus $direction"; then + dispatch_lua_focus "$direction" + fi + else + cycle_prev "$layout" + fi + ;; + *) + if [[ "$layout" == "scrolling" ]]; then + if ! dispatch_changed_focus layoutmsg "focus $direction"; then + dispatch_lua_focus "$direction" + fi + else + cycle_next "$layout" + fi + ;; + esac + ;; + *) + if ! dispatch_changed_focus movefocus "$direction"; then + dispatch_lua_focus "$direction" + fi + ;; + esac +} + +layout="$(get_active_layout)" + +case "${1:-}" in +cycle-next | next) + cycle_next "$layout" + ;; +cycle-prev | prev | previous) + cycle_prev "$layout" + ;; +focus-left | left) + focus_by_layout "$layout" l + ;; +focus-right | right) + focus_by_layout "$layout" r + ;; +focus-up | up) + focus_by_layout "$layout" u + ;; +focus-down | down) + focus_by_layout "$layout" d + ;; +layout | current-layout | status) + printf '%s\n' "$layout" + ;; +*) + echo "Usage: $(basename "$0") [cycle-next|cycle-prev|focus-left|focus-right|focus-up|focus-down|layout]" >&2 + exit 1 + ;; +esac diff --git a/config/hypr/scripts/LockScreen.sh b/config/hypr/scripts/LockScreen.sh index b795a8f7..c63a1e90 100755 --- a/config/hypr/scripts/LockScreen.sh +++ b/config/hypr/scripts/LockScreen.sh @@ -10,7 +10,7 @@ #pidof hyprlock || hyprlock -q # Ensure weather cache is up-to-date before locking (Waybar/lockscreen readers) -bash "$HOME/.config/hypr/UserScripts/WeatherWrap.sh" >/dev/null 2>&1 & +bash "${XDG_CONFIG_HOME:-$HOME/.config}/hypr/UserScripts/WeatherWrap.sh" >/dev/null 2>&1 & loginctl lock-session diff --git a/config/hypr/scripts/LuaAutoReload.sh b/config/hypr/scripts/LuaAutoReload.sh index 4a9d5040..128c1fc9 100755 --- a/config/hypr/scripts/LuaAutoReload.sh +++ b/config/hypr/scripts/LuaAutoReload.sh @@ -9,8 +9,23 @@ set -euo pipefail -watch_root="$HOME/.config/hypr" +watch_root="${XDG_CONFIG_HOME:-$HOME/.config}/hypr" [ -d "$watch_root" ] || exit 0 +session="${HYPRLAND_INSTANCE_SIGNATURE:-default}" +pid_file="/tmp/hypr-lua-autoreload-${session}.pid" + +if [ -f "$pid_file" ]; then + existing_pid="$(cat "$pid_file" 2>/dev/null || true)" + if [ -n "$existing_pid" ] && kill -0 "$existing_pid" 2>/dev/null; then + exit 0 + fi +fi + +echo "$$" >"$pid_file" +cleanup() { + rm -f "$pid_file" +} +trap cleanup EXIT INT TERM reload_hypr() { hyprctl reload >/dev/null 2>&1 || true diff --git a/config/hypr/scripts/MediaCtrl.sh b/config/hypr/scripts/MediaCtrl.sh index aeabcac9..958543dc 100755 --- a/config/hypr/scripts/MediaCtrl.sh +++ b/config/hypr/scripts/MediaCtrl.sh @@ -7,7 +7,7 @@ # ================================================== # Playerctl -music_icon="$HOME/.config/swaync/icons/music.png" +music_icon="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/icons/music.png" # Play the next track play_next() { diff --git a/config/hypr/scripts/MonitorProfiles.sh b/config/hypr/scripts/MonitorProfiles.sh index 6330d45c..09467e76 100755 --- a/config/hypr/scripts/MonitorProfiles.sh +++ b/config/hypr/scripts/MonitorProfiles.sh @@ -13,7 +13,7 @@ if pidof rofi > /dev/null; then fi # Detect active Hyprland config mode (Lua entrypoint vs legacy .conf includes) -config_home="${XDG_CONFIG_HOME:-$HOME/.config}" +config_home="${XDG_CONFIG_HOME:-${XDG_CONFIG_HOME:-$HOME/.config}}" hypr_dir="$config_home/hypr" lua_entry="$hypr_dir/hyprland.lua" legacy_lua_entry="$config_home/hyprland.lua" @@ -35,22 +35,22 @@ if [[ -z "$hypr_config_mode" ]]; then fi # Variables -iDIR="$HOME/.config/swaync/images" -SCRIPTSDIR="$HOME/.config/hypr/scripts" -monitor_dir="$HOME/.config/hypr/Monitor_Profiles" -target_conf="$HOME/.config/hypr/monitors.conf" -target_lua_user="$HOME/.config/hypr/UserConfigs/monitors.lua" -target_lua_legacy="$HOME/.config/hypr/lua/monitors.lua" -rofi_theme="$HOME/.config/rofi/config-Monitors.rasi" +iDIR="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/images" +SCRIPTSDIR="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts" +monitor_dir="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/Monitor_Profiles" +target_conf="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/monitors.conf" +target_lua_user="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/UserConfigs/monitors.lua" +target_lua_legacy="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/lua/monitors.lua" +rofi_theme="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/config-Monitors.rasi" if [[ "$hypr_config_mode" == "lua" ]]; then profile_ext="lua" target="$target_lua_user" - msg="❗NOTE:❗ This will overwrite $HOME/.config/hypr/UserConfigs/monitors.lua" + msg="❗NOTE:❗ This will overwrite ${XDG_CONFIG_HOME:-$HOME/.config}/hypr/UserConfigs/monitors.lua" else profile_ext="conf" target="$target_conf" - msg="❗NOTE:❗ This will overwrite $HOME/.config/hypr/monitors.conf" + msg="❗NOTE:❗ This will overwrite ${XDG_CONFIG_HOME:-$HOME/.config}/hypr/monitors.conf" fi # Define the list of files to ignore diff --git a/config/hypr/scripts/OverviewToggle.sh b/config/hypr/scripts/OverviewToggle.sh index 456ccef1..7c55ae82 100755 --- a/config/hypr/scripts/OverviewToggle.sh +++ b/config/hypr/scripts/OverviewToggle.sh @@ -9,7 +9,7 @@ set -euo pipefail -QS_OVERVIEW_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/quickshell/overview" +QS_OVERVIEW_DIR="${XDG_CONFIG_HOME:-${XDG_CONFIG_HOME:-$HOME/.config}}/quickshell/overview" # 1) Prefer Quickshell when installed and configured if command -v qs >/dev/null 2>&1 && [ -d "$QS_OVERVIEW_DIR" ]; then diff --git a/config/hypr/scripts/PersistWorkspaceLayout.sh b/config/hypr/scripts/PersistWorkspaceLayout.sh new file mode 100755 index 00000000..b5745880 --- /dev/null +++ b/config/hypr/scripts/PersistWorkspaceLayout.sh @@ -0,0 +1,223 @@ +#!/usr/bin/env bash +# ================================================== +# KoolDots (2026) +# Project URL: https://github.com/LinuxBeginnings +# License: GNU GPLv3 +# SPDX-License-Identifier: GPL-3.0-or-later +# ================================================== +# Persist active monitor/workspace layout back into ~/.config/hypr/workspaces.conf. + +set -u + +quiet_mode=0 +layout_override="" +workspace_override="" +monitor_override="" +workspaces_file="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/workspaces.conf" + +usage() { + cat <<'EOF' +Usage: PersistWorkspaceLayout.sh [--quiet] [--layout <layout>] [--workspace <selector>] [--monitor <monitor>] [--file <path>] + --quiet Suppress console notifications. + --layout <layout> Override layout (master|dwindle|scrolling|monocle). + --workspace <sel> Override workspace selector (e.g. 5, name:code, special:scratchpad). + --monitor <name> Override monitor name. + --file <path> Target workspace rules file (default: ~/.config/hypr/workspaces.conf). +EOF +} + +normalize_layout() { + case "$1" in + master | dwindle | scrolling | monocle) + printf '%s\n' "$1" + ;; + *) + printf '\n' + ;; + esac +} + +require_cmd() { + command -v "$1" >/dev/null 2>&1 || { + echo "Missing dependency: $1" >&2 + exit 1 + } +} + +get_active_workspace_json() { + hyprctl -j activeworkspace 2>/dev/null || printf '{}' +} + +get_workspace_selector() { + local ws_json="$1" + local ws_id ws_name + + ws_id="$(jq -r '.id // empty' <<<"$ws_json" 2>/dev/null || true)" + ws_name="$(jq -r '.name // empty' <<<"$ws_json" 2>/dev/null || true)" + + if [[ "$ws_id" =~ ^[0-9]+$ ]] && ((ws_id > 0)); then + printf '%s\n' "$ws_id" + return 0 + fi + + if [[ -n "$ws_name" && "$ws_name" != "null" ]]; then + if [[ "$ws_name" == name:* || "$ws_name" == special:* ]]; then + printf '%s\n' "$ws_name" + else + printf 'name:%s\n' "$ws_name" + fi + return 0 + fi + + return 1 +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --quiet | --no-notify) + quiet_mode=1 + shift + ;; + --layout) + layout_override="${2:-}" + shift 2 + ;; + --workspace) + workspace_override="${2:-}" + shift 2 + ;; + --monitor) + monitor_override="${2:-}" + shift 2 + ;; + --file) + workspaces_file="${2:-}" + shift 2 + ;; + -h | --help) + usage + exit 0 + ;; + *) + echo "Unknown argument: $1" >&2 + usage >&2 + exit 1 + ;; + esac +done + +require_cmd hyprctl +require_cmd jq +require_cmd awk +require_cmd mktemp + +ws_json="$(get_active_workspace_json)" +workspace_selector="${workspace_override:-$(get_workspace_selector "$ws_json" || true)}" +monitor_name="${monitor_override:-$(jq -r '.monitor // empty' <<<"$ws_json" 2>/dev/null || true)}" + +if [[ -n "$layout_override" ]]; then + layout_name="$(normalize_layout "$layout_override")" +else + layout_name="$(jq -r '.tiledLayout // .tiled_layout // empty' <<<"$ws_json" 2>/dev/null || true)" + layout_name="$(normalize_layout "$layout_name")" + if [[ -z "$layout_name" ]]; then + layout_name="$(hyprctl -j getoption general:layout 2>/dev/null | jq -r '.str // empty' 2>/dev/null || true)" + layout_name="$(normalize_layout "$layout_name")" + fi +fi + +if [[ -z "$workspace_selector" || -z "$monitor_name" || -z "$layout_name" ]]; then + echo "Unable to resolve workspace, monitor, or layout for persistence" >&2 + exit 1 +fi + +mkdir -p "$(dirname "$workspaces_file")" +touch "$workspaces_file" + +tmp_file="$(mktemp "${workspaces_file}.XXXXXX")" +cleanup() { + rm -f "$tmp_file" +} +trap cleanup EXIT + +awk \ + -v target_ws="$workspace_selector" \ + -v target_mon="$monitor_name" \ + -v target_layout="$layout_name" ' +function trim(v) { + gsub(/^[[:space:]]+|[[:space:]]+$/, "", v) + return v +} +BEGIN { + updated = 0 +} +{ + line = $0 + content = line + comment = "" + hash_pos = index(line, "#") + if (hash_pos > 0) { + content = substr(line, 1, hash_pos - 1) + comment = substr(line, hash_pos) + } + stripped = trim(content) + indent_len = match(line, /[^[:space:]]/) - 1 + if (indent_len < 0) { + indent_len = length(line) + } + indent = substr(line, 1, indent_len) + + if (stripped ~ /^workspace[[:space:]]*=/) { + sub(/^workspace[[:space:]]*=[[:space:]]*/, "", stripped) + token_count = split(stripped, tokens, /,/) + ws = trim(tokens[1]) + mon = "" + extras_count = 0 + delete extras + + for (i = 2; i <= token_count; i++) { + token = trim(tokens[i]) + if (token == "") { + continue + } + if (token ~ /^monitor:/) { + mon = trim(substr(token, 9)) + continue + } + if (token ~ /^layout:/) { + continue + } + extras[++extras_count] = token + } + + if (ws == target_ws && mon == target_mon) { + if (!updated) { + rebuilt = indent "workspace = " ws ", monitor:" target_mon ", layout:" target_layout + for (i = 1; i <= extras_count; i++) { + rebuilt = rebuilt ", " extras[i] + } + if (comment != "") { + rebuilt = rebuilt " " comment + } + print rebuilt + updated = 1 + } + next + } + } + + print line +} +END { + if (!updated) { + print "workspace = " target_ws ", monitor:" target_mon ", layout:" target_layout + } +} +' "$workspaces_file" >"$tmp_file" + +mv "$tmp_file" "$workspaces_file" +trap - EXIT + +if [[ "$quiet_mode" -eq 0 ]]; then + printf 'Saved workspace layout: %s @ %s -> %s\n' "$workspace_selector" "$monitor_name" "$layout_name" +fi diff --git a/config/hypr/scripts/Polkit-Diag.sh b/config/hypr/scripts/Polkit-Diag.sh index aa4e69a8..8e0e9f23 100755 --- a/config/hypr/scripts/Polkit-Diag.sh +++ b/config/hypr/scripts/Polkit-Diag.sh @@ -15,7 +15,7 @@ INSTALL_OVERRIDE=0 FORCE_OVERRIDE=0 # Systemd override details for hyprpolkitagent -OVERRIDE_DIR="$HOME/.config/systemd/user/hyprpolkitagent.service.d" +OVERRIDE_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user/hyprpolkitagent.service.d" OVERRIDE_FILE="$OVERRIDE_DIR/override.conf" OVERRIDE_CONTENT="[Unit] diff --git a/config/hypr/scripts/PortalHyprland.sh b/config/hypr/scripts/PortalHyprland.sh index 3d3dc410..54ea71bb 100755 --- a/config/hypr/scripts/PortalHyprland.sh +++ b/config/hypr/scripts/PortalHyprland.sh @@ -10,21 +10,73 @@ set -euo pipefail is_ubuntu_family() { if [[ ! -r /etc/os-release ]]; then - return 1 + #return 1 + # It's been reported this also addresses + # The xdg-desktop-portal failure when not using + # UWSM on Arch + exit 0 fi # shellcheck disable=SC1091 . /etc/os-release - [[ "${ID:-}" == "ubuntu" \ - || "${ID:-}" == "linuxmint" \ - || "${ID:-}" == "zorin" \ - || "${ID:-}" == "rhino" \ - || "${ID_LIKE:-}" == *ubuntu* ]] + [[ "${ID:-}" == "ubuntu" || + "${ID:-}" == "linuxmint" || + "${ID:-}" == "zorin" || + "${ID:-}" == "rhino" || + "${ID_LIKE:-}" == *ubuntu* ]] } kill_quietly() { killall -q "$1" 2>/dev/null || true } +wait_for_wayland() { + local runtime_dir="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}" + export XDG_RUNTIME_DIR="$runtime_dir" + + if [[ -n "${WAYLAND_DISPLAY:-}" && -S "$runtime_dir/$WAYLAND_DISPLAY" ]]; then + return 0 + fi + + for _ in $(seq 1 120); do + if [[ -n "${WAYLAND_DISPLAY:-}" && -S "$runtime_dir/$WAYLAND_DISPLAY" ]]; then + return 0 + fi + + for socket in "$runtime_dir"/wayland-[0-9]*; do + [[ -S "$socket" ]] || continue + case "$(basename "$socket")" in + *awww*) continue ;; + esac + export WAYLAND_DISPLAY="$(basename "$socket")" + return 0 + done + sleep 0.1 + done + + return 1 +} + +ensure_portal_env() { + export XDG_CURRENT_DESKTOP="${XDG_CURRENT_DESKTOP:-Hyprland}" + export XDG_SESSION_DESKTOP="${XDG_SESSION_DESKTOP:-Hyprland}" + export XDG_SESSION_TYPE="${XDG_SESSION_TYPE:-wayland}" + if [[ -f "/usr/share/glib-2.0/schemas/gschemas.compiled" ]]; then + export GSETTINGS_SCHEMA_DIR="/usr/share/glib-2.0/schemas" + fi + + local data_dirs="${XDG_DATA_DIRS:-}" + if [[ -z "$data_dirs" ]]; then + data_dirs="/usr/local/share:/usr/share" + else + if [[ ":$data_dirs:" != *":/usr/local/share:"* ]]; then + data_dirs="/usr/local/share:$data_dirs" + fi + if [[ ":$data_dirs:" != *":/usr/share:"* ]]; then + data_dirs="$data_dirs:/usr/share" + fi + fi + export XDG_DATA_DIRS="$data_dirs" +} start_portal_binary() { local description="$1" @@ -38,29 +90,74 @@ start_portal_binary() { echo "Warning: no $description binary found (checked: $*)" >&2 return 1 } -if ! is_ubuntu_family; then - exit 0 -fi +stop_portal_processes() { + kill_quietly xdg-desktop-portal-hyprland + kill_quietly xdg-desktop-portal-wlr + kill_quietly xdg-desktop-portal-gnome + kill_quietly xdg-desktop-portal-gtk + kill_quietly xdg-desktop-portal +} + +restart_portal_via_systemd() { + command -v systemctl >/dev/null 2>&1 || return 1 + ensure_portal_env + if command -v dbus-update-activation-environment >/dev/null 2>&1; then + dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP XDG_SESSION_DESKTOP XDG_SESSION_TYPE XDG_DATA_DIRS GSETTINGS_SCHEMA_DIR >/dev/null 2>&1 || true + fi + + systemctl --user import-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP XDG_SESSION_DESKTOP XDG_SESSION_TYPE XDG_DATA_DIRS GSETTINGS_SCHEMA_DIR >/dev/null 2>&1 || true + systemctl --user stop xdg-desktop-portal.service xdg-desktop-portal-hyprland.service xdg-desktop-portal-gtk.service >/dev/null 2>&1 || true + stop_portal_processes + sleep 0.5 + systemctl --user reset-failed xdg-desktop-portal-hyprland.service xdg-desktop-portal.service xdg-desktop-portal-gtk.service >/dev/null 2>&1 || true + systemctl --user start graphical-session.target >/dev/null 2>&1 || true + + for _ in $(seq 1 30); do + if systemctl --user is-active --quiet graphical-session.target; then + break + fi + sleep 0.1 + done + + systemctl --user start xdg-desktop-portal-hyprland.service >/dev/null 2>&1 || true + if is_ubuntu_family; then + systemctl --user start xdg-desktop-portal-gtk.service >/dev/null 2>&1 || true + fi -sleep 1 -kill_quietly xdg-desktop-portal-hyprland -kill_quietly xdg-desktop-portal-wlr -kill_quietly xdg-desktop-portal-gnome -kill_quietly xdg-desktop-portal-gtk -kill_quietly xdg-desktop-portal -sleep 1 + for _ in $(seq 1 60); do + if systemctl --user is-active --quiet xdg-desktop-portal-hyprland.service; then + return 0 + fi + sleep 0.1 + done + return 1 +} -start_portal_binary "xdg-desktop-portal-hyprland" \ - /usr/lib/xdg-desktop-portal-hyprland \ - /usr/libexec/xdg-desktop-portal-hyprland +restart_portal_manually() { + sleep 1 + stop_portal_processes + sleep 1 -sleep 2 + start_portal_binary "xdg-desktop-portal-hyprland" \ + /usr/lib/xdg-desktop-portal-hyprland \ + /usr/libexec/xdg-desktop-portal-hyprland -start_portal_binary "xdg-desktop-portal-gtk" \ - /usr/lib/xdg-desktop-portal-gtk \ - /usr/libexec/xdg-desktop-portal-gtk + sleep 2 -start_portal_binary "xdg-desktop-portal" \ - /usr/lib/xdg-desktop-portal \ - /usr/libexec/xdg-desktop-portal + if is_ubuntu_family; then + start_portal_binary "xdg-desktop-portal-gtk" \ + /usr/lib/xdg-desktop-portal-gtk \ + /usr/libexec/xdg-desktop-portal-gtk || true + fi + + start_portal_binary "xdg-desktop-portal" \ + /usr/lib/xdg-desktop-portal \ + /usr/libexec/xdg-desktop-portal +} +wait_for_wayland || true +if command -v systemctl >/dev/null 2>&1; then + restart_portal_via_systemd || true +else + restart_portal_manually +fi diff --git a/config/hypr/scripts/PortalHyprlandUbuntu.sh b/config/hypr/scripts/PortalHyprlandUbuntu.sh index 86e1a6d3..79762a84 100755 --- a/config/hypr/scripts/PortalHyprlandUbuntu.sh +++ b/config/hypr/scripts/PortalHyprlandUbuntu.sh @@ -17,8 +17,8 @@ if [[ -r /etc/os-release ]]; then || "${ID:-}" == "zorin" \ || "${ID:-}" == "rhino" \ || "${ID_LIKE:-}" == *ubuntu* ]]; then - if [[ -x "$HOME/.config/hypr/scripts/PortalHyprland.sh" ]]; then - "$HOME/.config/hypr/scripts/PortalHyprland.sh" + if [[ -x "${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts/PortalHyprland.sh" ]]; then + "${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts/PortalHyprland.sh" fi fi fi diff --git a/config/hypr/scripts/Refresh.sh b/config/hypr/scripts/Refresh.sh index 1b043705..ed8c4a0c 100755 --- a/config/hypr/scripts/Refresh.sh +++ b/config/hypr/scripts/Refresh.sh @@ -7,8 +7,8 @@ # ================================================== # Scripts for refreshing ags, waybar, rofi, swaync, wallust -SCRIPTSDIR=$HOME/.config/hypr/scripts -UserScripts=$HOME/.config/hypr/UserScripts +SCRIPTSDIR=${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts +UserScripts=${XDG_CONFIG_HOME:-$HOME/.config}/hypr/UserScripts # Define file_exists function file_exists() { diff --git a/config/hypr/scripts/RefreshNoWaybar.sh b/config/hypr/scripts/RefreshNoWaybar.sh index e92780b1..c9e7464e 100755 --- a/config/hypr/scripts/RefreshNoWaybar.sh +++ b/config/hypr/scripts/RefreshNoWaybar.sh @@ -10,8 +10,8 @@ # Used by automatic wallpaper change # Modified inorder to refresh rofi background, Wallust, SwayNC only -SCRIPTSDIR=$HOME/.config/hypr/scripts -UserScripts=$HOME/.config/hypr/UserScripts +SCRIPTSDIR=${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts +UserScripts=${XDG_CONFIG_HOME:-$HOME/.config}/hypr/UserScripts # Define file_exists function file_exists() { diff --git a/config/hypr/scripts/RofiEmoji.sh b/config/hypr/scripts/RofiEmoji.sh index 539a03b6..65463abc 100755 --- a/config/hypr/scripts/RofiEmoji.sh +++ b/config/hypr/scripts/RofiEmoji.sh @@ -7,7 +7,7 @@ # ================================================== # Variables -rofi_theme="$HOME/.config/rofi/config-emoji.rasi" +rofi_theme="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/config-emoji.rasi" msg='** note ** 👀 Click or Return to choose || Ctrl V to Paste' # Check if rofi is already running diff --git a/config/hypr/scripts/RofiFocusedWallpaperLink.sh b/config/hypr/scripts/RofiFocusedWallpaperLink.sh new file mode 100755 index 00000000..c0f8d64a --- /dev/null +++ b/config/hypr/scripts/RofiFocusedWallpaperLink.sh @@ -0,0 +1,180 @@ +#!/usr/bin/env bash +# ================================================== +# KoolDots (2026) +# Project URL: https://github.com/LinuxBeginnings +# License: GNU GPLv3 +# SPDX-License-Identifier: GPL-3.0-or-later +# ================================================== +# Resolve focused-monitor wallpaper and refresh rofi focused wallpaper link. + +SCRIPTSDIR="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts" +ROFI_FOCUSED_LINK="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/.current_wallpaper_focused" +ROFI_GLOBAL_LINK="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/.current_wallpaper" +WALLPAPER_CURRENT="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/wallpaper_effects/.wallpaper_current" + +# shellcheck source=/dev/null +. "$SCRIPTSDIR/WallpaperCmd.sh" 2>/dev/null || true + +read_cached_wallpaper() { + local cache_file="$1" + [[ -f "$cache_file" ]] || return 1 + awk 'NF && $0 !~ /^filter/ {print; exit}' "$cache_file" +} + +read_wallpaper_from_query() { + local monitor="$1" + [[ -n "$monitor" ]] || return 1 + [[ -n "${WWW_CMD:-}" ]] || return 1 + command -v "$WWW_CMD" >/dev/null 2>&1 || return 1 + "$WWW_CMD" query 2>/dev/null | awk -v mon="$monitor" ' + { + line=$0 + sub(/^Monitor[[:space:]]+/, "", line) + sub(/^:[[:space:]]*/, "", line) + mon_name=line + sub(/:.*/, "", mon_name) + gsub(/^[[:space:]]+|[[:space:]]+$/, "", mon_name) + if (mon_name != mon) next + + path=line + sub(/^.*image:[[:space:]]*/, "", path) + gsub(/^[[:space:]]+|[[:space:]]+$/, "", path) + if (path != line && length(path) > 0) { + print path + exit + } + } + ' +} + +resolve_link_or_file() { + local path="$1" + local resolved="" + if [[ -L "$path" ]]; then + resolved="$(readlink -f "$path" 2>/dev/null || true)" + if [[ -n "$resolved" && -f "$resolved" ]]; then + printf '%s\n' "$resolved" + return 0 + fi + fi + if [[ -f "$path" ]]; then + printf '%s\n' "$path" + return 0 + fi + return 1 +} + +get_active_workspace_monitor() { + command -v hyprctl >/dev/null 2>&1 || return 1 + if command -v jq >/dev/null 2>&1; then + hyprctl activeworkspace -j 2>/dev/null | jq -r '.monitor // empty' | head -n1 + else + hyprctl monitors 2>/dev/null | awk '/^Monitor/{name=$2} /focused: yes/{print name; exit}' + fi +} + +get_focused_monitor() { + command -v hyprctl >/dev/null 2>&1 || return 1 + if command -v jq >/dev/null 2>&1; then + hyprctl monitors -j 2>/dev/null | jq -r '.[] | select(.focused) | .name' | head -n1 + else + hyprctl monitors 2>/dev/null | awk '/^Monitor/{name=$2} /focused: yes/{print name; exit}' + fi +} + +monitor_exists() { + local monitor="$1" + [[ -n "$monitor" ]] || return 1 + command -v hyprctl >/dev/null 2>&1 || return 1 + if command -v jq >/dev/null 2>&1; then + hyprctl monitors -j 2>/dev/null | jq -r --arg mon "$monitor" '.[] | select(.name == $mon) | .name' | grep -qx "$monitor" + else + hyprctl monitors 2>/dev/null | awk '/^Monitor/{print $2}' | grep -qx "$monitor" + fi +} + +resolve_target_monitor() { + local monitor="" + monitor="$(get_active_workspace_monitor 2>/dev/null || true)" + if monitor_exists "$monitor"; then + printf '%s\n' "$monitor" + return 0 + fi + monitor="$(get_focused_monitor 2>/dev/null || true)" + if [[ -n "$monitor" ]]; then + printf '%s\n' "$monitor" + return 0 + fi + return 1 +} + +read_wallpaper_from_cache() { + local monitor="$1" + local cache_root="${WWW_CACHE_DIR:-$HOME/.cache/awww}" + local cache_file="$cache_root/$monitor" + local fallback_cache="" + local path="" + + case "$cache_root" in + "$HOME/.cache/awww") + fallback_cache="$HOME/.cache/swww/$monitor" + ;; + "$HOME/.cache/swww") + fallback_cache="$HOME/.cache/awww/$monitor" + ;; + esac + + path="$(read_cached_wallpaper "$cache_file" 2>/dev/null || true)" + if [[ -z "$path" && -n "$fallback_cache" ]]; then + path="$(read_cached_wallpaper "$fallback_cache" 2>/dev/null || true)" + fi + [[ -n "$path" && -f "$path" ]] || return 1 + printf '%s\n' "$path" +} + +resolve_focused_wallpaper() { + local monitor="$1" + local path="" + local per_monitor_link="" + local per_monitor_current="" + + if [[ -n "$monitor" ]]; then + per_monitor_link="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/.current_wallpaper_${monitor}" + per_monitor_current="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/wallpaper_effects/.wallpaper_current_${monitor}" + + path="$(read_wallpaper_from_query "$monitor" 2>/dev/null || true)" + if [[ -z "$path" ]]; then + path="$(resolve_link_or_file "$per_monitor_link" 2>/dev/null || true)" + fi + if [[ -z "$path" ]]; then + path="$(resolve_link_or_file "$per_monitor_current" 2>/dev/null || true)" + fi + if [[ -z "$path" ]]; then + path="$(read_wallpaper_from_cache "$monitor" 2>/dev/null || true)" + fi + fi + + if [[ -z "$path" ]]; then + path="$(resolve_link_or_file "$ROFI_GLOBAL_LINK" 2>/dev/null || true)" + fi + if [[ -z "$path" ]]; then + path="$(resolve_link_or_file "$WALLPAPER_CURRENT" 2>/dev/null || true)" + fi + + [[ -n "$path" && -f "$path" ]] || return 1 + printf '%s\n' "$path" +} + +main() { + local target_monitor="" + local wallpaper_path="" + + target_monitor="$(resolve_target_monitor 2>/dev/null || true)" + wallpaper_path="$(resolve_focused_wallpaper "$target_monitor" 2>/dev/null || true)" + [[ -n "$wallpaper_path" && -f "$wallpaper_path" ]] || exit 1 + + mkdir -p "$(dirname "$ROFI_FOCUSED_LINK")" + ln -sf "$wallpaper_path" "$ROFI_FOCUSED_LINK" +} + +main "$@" diff --git a/config/hypr/scripts/RofiSearch.sh b/config/hypr/scripts/RofiSearch.sh index 42b54d75..05520ed0 100755 --- a/config/hypr/scripts/RofiSearch.sh +++ b/config/hypr/scripts/RofiSearch.sh @@ -8,7 +8,7 @@ # For Searching via web browsers # Define the path to the config file -config_file=$HOME/.config/hypr/UserConfigs/01-UserDefaults.conf +config_file=${XDG_CONFIG_HOME:-$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 @@ -33,7 +33,7 @@ if [[ -z "$Search_Engine" ]]; then fi # Rofi theme and message -rofi_theme="$HOME/.config/rofi/config-search.rasi" +rofi_theme="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/config-search.rasi" msg='‼️ **note** ‼️ search via default web browser' # Kill Rofi if already running before execution diff --git a/config/hypr/scripts/RofiThemeSelector-modified.sh b/config/hypr/scripts/RofiThemeSelector-modified.sh index 535b7313..9dfafba1 100755 --- a/config/hypr/scripts/RofiThemeSelector-modified.sh +++ b/config/hypr/scripts/RofiThemeSelector-modified.sh @@ -5,12 +5,12 @@ # License: GNU GPLv3 # SPDX-License-Identifier: GPL-3.0-or-later # ================================================== -# A modified version of Rofi-Theme-Selector, concentrating only on ~/.local and also, applying only 10 @themes in ~/.config/rofi/config.rasi +# A modified version of Rofi-Theme-Selector, concentrating only on ~/.local and also, applying only 10 @themes in ${XDG_CONFIG_HOME:-$HOME/.config}/rofi/config.rasi # as opposed to continous adding of //@theme # This code is released in public domain by Dave Davenport <qball@gmpclient.org> -iDIR="$HOME/.config/swaync/images" +iDIR="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/images" OS="linux" @@ -42,7 +42,7 @@ fi TMP_CONFIG_FILE=$(${MKTEMP}).rasi #rofi_theme_dir="${HOME}/.local/share/rofi/themes" -rofi_config_file="${XDG_CONFIG_HOME:-${HOME}/.config}/rofi/config.rasi" +rofi_config_file="${XDG_CONFIG_HOME:-${XDG_CONFIG_HOME:-$HOME/.config}}/rofi/config.rasi" ## # Array with parts to the found themes. @@ -57,7 +57,7 @@ declare -a theme_names ## # Find themes in defined directories find_themes() { - directories=("$HOME/.local/share/rofi/themes" "$HOME/.config/rofi/themes") + directories=("$HOME/.local/share/rofi/themes" "${XDG_CONFIG_HOME:-$HOME/.config}/rofi/themes") for TD in "${directories[@]}"; do if [ -d "$TD" ]; then @@ -86,8 +86,8 @@ add_theme_to_config() { # Determine the correct path for the theme if [[ -f "$HOME/.local/share/rofi/themes/$theme_name.rasi" ]]; then theme_path="$HOME/.local/share/rofi/themes/$theme_name.rasi" - elif [[ -f "$HOME/.config/rofi/themes/$theme_name.rasi" ]]; then - theme_path="$HOME/.config/rofi/themes/$theme_name.rasi" + elif [[ -f "${XDG_CONFIG_HOME:-$HOME/.config}/rofi/themes/$theme_name.rasi" ]]; then + theme_path="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/themes/$theme_name.rasi" else echo "Theme not found: $theme_name" return 1 diff --git a/config/hypr/scripts/RofiThemeSelector.sh b/config/hypr/scripts/RofiThemeSelector.sh index db723b6f..1841b4f5 100755 --- a/config/hypr/scripts/RofiThemeSelector.sh +++ b/config/hypr/scripts/RofiThemeSelector.sh @@ -8,11 +8,11 @@ # Rofi Themes - Script to preview and apply themes by live-reloading the config. # --- Configuration --- -ROFI_THEMES_DIR_CONFIG="$HOME/.config/rofi/themes" +ROFI_THEMES_DIR_CONFIG="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/themes" ROFI_THEMES_DIR_LOCAL="$HOME/.local/share/rofi/themes" -ROFI_CONFIG_FILE="$HOME/.config/rofi/config.rasi" -ROFI_THEME_FOR_THIS_SCRIPT="$HOME/.config/rofi/config-rofi-theme.rasi" # A separate rofi theme for the picker itself -IDIR="$HOME/.config/swaync/images" # For notifications +ROFI_CONFIG_FILE="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/config.rasi" +ROFI_THEME_FOR_THIS_SCRIPT="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/config-rofi-theme.rasi" # A separate rofi theme for the picker itself +IDIR="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/images" # For notifications # --- Helper Functions --- diff --git a/config/hypr/scripts/ScreenShot.sh b/config/hypr/scripts/ScreenShot.sh index baad89a1..ed914552 100755 --- a/config/hypr/scripts/ScreenShot.sh +++ b/config/hypr/scripts/ScreenShot.sh @@ -13,9 +13,9 @@ 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" -iDoR="$HOME/.config/swaync/images" -sDIR="$HOME/.config/hypr/scripts" +iDIR="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/icons" +iDoR="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/images" +sDIR="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts" active_window_class=$(hyprctl -j activewindow | jq -r '(.class)') active_window_file="Screenshot_${time}_${active_window_class}.png" diff --git a/config/hypr/scripts/ScrollCycleColumnWidth.sh b/config/hypr/scripts/ScrollCycleColumnWidth.sh new file mode 100755 index 00000000..c9ab2668 --- /dev/null +++ b/config/hypr/scripts/ScrollCycleColumnWidth.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash +set -euo pipefail + +if ! command -v hyprctl >/dev/null 2>&1; then + exit 0 +fi + +if ! command -v jq >/dev/null 2>&1; then + exit 0 +fi + +workspace_json="$(hyprctl -j activeworkspace 2>/dev/null || true)" +layout_name="$(jq -r '.tiledLayout // .tiled_layout // empty' <<<"$workspace_json")" + +if [[ "$layout_name" != "scrolling" ]]; then + exit 0 +fi + +window_json="$(hyprctl -j activewindow 2>/dev/null || true)" +column_width="$(jq -r '.layout.column.width // .layout.column // empty' <<<"$window_json")" +window_monitor="$(jq -r '.monitor // empty' <<<"$window_json")" +window_width="$(jq -r '.size[0] // empty' <<<"$window_json")" + +if [[ -n "$column_width" && "$column_width" != "null" ]]; then + if ! awk -v v="$column_width" 'BEGIN { exit !(v > 0 && v <= 1.0) }'; then + column_width="" + fi +fi + +if [[ -z "$column_width" || "$column_width" == "null" ]]; then + monitors_json="$(hyprctl -j monitors 2>/dev/null || true)" + monitor_width="$(jq -r --arg id "$window_monitor" '.[] | select((.id | tostring) == $id) | .width' <<<"$monitors_json" 2>/dev/null | head -n1)" + if [[ -n "$window_width" && -n "$monitor_width" && "$window_width" != "null" && "$monitor_width" != "null" ]]; then + column_width="$(awk -v w="$window_width" -v mw="$monitor_width" 'BEGIN { if (w > 0 && mw > 0) printf "%.6f", (w / mw); }')" + fi +fi + +if [[ -z "$column_width" || "$column_width" == "null" ]]; then + exit 0 +fi + +presets=(0.25 0.33 0.5 0.66 0.75 1.0) +closest_idx=0 +best_diff="" + +for idx in "${!presets[@]}"; do + preset="${presets[$idx]}" + diff="$(awk -v a="$preset" -v b="$column_width" 'BEGIN { d = a - b; if (d < 0) d = -d; printf "%.12f", d }')" + if [[ -z "$best_diff" ]] || awk -v d="$diff" -v b="$best_diff" 'BEGIN { exit !(d < b) }'; then + best_diff="$diff" + closest_idx="$idx" + fi +done + +next_idx=$(( (closest_idx + 1) % ${#presets[@]} )) +hyprctl dispatch layoutmsg "colresize ${presets[$next_idx]}" >/dev/null 2>&1 || true diff --git a/config/hypr/scripts/ScrollMaximizeToggle.sh b/config/hypr/scripts/ScrollMaximizeToggle.sh new file mode 100755 index 00000000..29c06eb4 --- /dev/null +++ b/config/hypr/scripts/ScrollMaximizeToggle.sh @@ -0,0 +1,175 @@ +#!/usr/bin/env bash +set -euo pipefail + +if ! command -v hyprctl >/dev/null 2>&1; then + exit 1 +fi +dispatch_ok() { + local dispatcher="$1" + shift + local output="" + case "$dispatcher" in + fullscreen) + if [[ "${1:-}" == "1" ]]; then + output="$(hyprctl dispatch 'hl.dsp.window.fullscreen({ mode = "maximized" })' 2>&1 || true)" + else + output="$(hyprctl dispatch 'hl.dsp.window.fullscreen({ mode = "fullscreen" })' 2>&1 || true)" + fi + ;; + layoutmsg) + local msg="${1:-}" + msg="${msg//\\/\\\\}" + msg="${msg//\"/\\\"}" + output="$(hyprctl dispatch "hl.dsp.layout(\"${msg}\")" 2>&1 || true)" + ;; + *) + output="$(hyprctl dispatch "$dispatcher" "$@" 2>&1 || true)" + ;; + esac + local normalized="" + normalized="$(printf '%s' "$output" | tr -d '\r\n')" + [[ -z "$normalized" || "$normalized" == "ok" ]] +} + +if ! command -v jq >/dev/null 2>&1; then + dispatch_ok fullscreen 1 >/dev/null 2>&1 || true + exit 0 +fi + +run_layoutmsg() { + local msg="$1" + dispatch_ok layoutmsg "$msg" +} +toggle_maximize() { + local active_window_json="$1" + local fullscreen_state="" + fullscreen_state="$(jq -r ' + (.fullscreen // .fullscreenClient // 0) as $value + | if ($value | type) == "boolean" then + (if $value then 1 else 0 end) + elif ($value | type) == "number" then + $value + elif ($value | type) == "string" then + ($value | tonumber? // 0) + else + 0 + end + ' <<<"$active_window_json" 2>/dev/null || true)" + if [[ -n "$fullscreen_state" && "$fullscreen_state" != "null" ]] && awk -v v="$fullscreen_state" 'BEGIN { exit !(v > 0) }'; then + dispatch_ok fullscreen 1 >/dev/null 2>&1 || true + return 0 + fi + return 1 +} + +workspace_json="$(hyprctl -j activeworkspace 2>/dev/null || true)" +layout_name="$(jq -r '.tiledLayout // .tiled_layout // empty' <<<"$workspace_json")" + +if [[ "$layout_name" != "scrolling" ]]; then + dispatch_ok fullscreen 1 >/dev/null 2>&1 || true + exit 0 +fi + +window_json="$(hyprctl -j activewindow 2>/dev/null || true)" +if [[ -z "$window_json" || "$window_json" == "null" ]]; then + exit 0 +fi +if toggle_maximize "$window_json"; then + exit 0 +fi + +window_address="$(jq -r '.address // empty' <<<"$window_json")" +window_width="$(jq -r '.size[0] // empty' <<<"$window_json")" +column_width="$(jq -r ' + .layout.column as $col + | if ($col | type) == "number" then $col + elif ($col | type) == "object" then ($col.width // empty) + elif ($col | type) == "string" then ($col | tonumber? // empty) + else empty + end +' <<<"$window_json")" +if [[ -n "$column_width" && "$column_width" != "null" ]]; then + if ! awk -v v="$column_width" 'BEGIN { exit !(v > 0 && v <= 1.0) }'; then + column_width="" + fi +fi + +if [[ -z "$window_address" || -z "$window_width" || "$window_width" == "null" ]]; then + dispatch_ok fullscreen 1 >/dev/null 2>&1 || true + exit 0 +fi + +runtime_dir="${XDG_RUNTIME_DIR:-/tmp}" +state_dir="${runtime_dir}/hypr" +state_file="${state_dir}/scrolling-maximize-state.json" +mkdir -p "$state_dir" + +if [[ ! -s "$state_file" ]]; then + printf '{}\n' > "$state_file" +elif ! jq -e . "$state_file" >/dev/null 2>&1; then + printf '{}\n' > "$state_file" +fi + +saved_width="$(jq -r --arg key "$window_address" ' + .[$key] as $saved + | if ($saved | type) == "number" then $saved + elif ($saved | type) == "object" then ($saved.width // empty) + elif ($saved | type) == "string" then ($saved | tonumber? // empty) + else empty + end +' "$state_file" 2>/dev/null || true)" +tmp_file="$(mktemp "${state_file}.XXXXXX")" +cleanup() { + rm -f "$tmp_file" +} +trap cleanup EXIT + +if [[ -n "$saved_width" && "$saved_width" != "null" ]]; then + restored=0 + if run_layoutmsg "colresize ${saved_width}"; then + restored=1 + elif run_layoutmsg "colresize exact ${saved_width}"; then + restored=1 + fi + if [[ "$restored" -eq 1 ]]; then + jq --arg key "$window_address" 'del(.[$key])' "$state_file" > "$tmp_file" + mv "$tmp_file" "$state_file" + fi + trap - EXIT + exit 0 +fi +if [[ -z "$column_width" || "$column_width" == "null" ]]; then + if run_layoutmsg "colresize 1.0"; then + max_width="" + for _ in 1 2 3 4 5 6; do + candidate_width="$(hyprctl -j activewindow 2>/dev/null | jq -r '.size[0] // empty')" + if [[ -n "$candidate_width" && "$candidate_width" != "null" ]] && awk -v v="$candidate_width" 'BEGIN { exit !(v > 0) }'; then + if [[ -z "$max_width" ]] || awk -v c="$candidate_width" -v m="$max_width" 'BEGIN { exit !(c > m) }'; then + max_width="$candidate_width" + fi + fi + sleep 0.05 + done + if [[ -n "$max_width" ]]; then + column_width="$(awk -v w="$window_width" -v mw="$max_width" 'BEGIN { if (w > 0 && mw > 0) printf "%.6f", (w / mw); }')" + fi + else + dispatch_ok fullscreen 1 >/dev/null 2>&1 || true + trap - EXIT + exit 0 + fi + if [[ -z "$column_width" || "$column_width" == "null" ]]; then + trap - EXIT + exit 0 + fi + jq --arg key "$window_address" --argjson value "$column_width" '. + {($key): $value}' "$state_file" > "$tmp_file" + mv "$tmp_file" "$state_file" + trap - EXIT + exit 0 +fi + +jq --arg key "$window_address" --argjson value "$column_width" '. + {($key): $value}' "$state_file" > "$tmp_file" +mv "$tmp_file" "$state_file" +trap - EXIT + +run_layoutmsg "colresize 1.0" >/dev/null 2>&1 || dispatch_ok fullscreen 1 >/dev/null 2>&1 || true diff --git a/config/hypr/scripts/Sounds.sh b/config/hypr/scripts/Sounds.sh index 3af4944f..e763475c 100755 --- a/config/hypr/scripts/Sounds.sh +++ b/config/hypr/scripts/Sounds.sh @@ -10,7 +10,7 @@ theme="freedesktop" # Set the theme for the system sounds. mute=false # Set to true to mute the system sounds. -directSoundDir="$HOME/.config/hypr/sounds" +directSoundDir="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/sounds" # Mute individual sounds here. muteScreenshots=false diff --git a/config/hypr/scripts/Tak0-Autodispatch.sh b/config/hypr/scripts/Tak0-Autodispatch.sh index cabe1672..8eea93ad 100755 --- a/config/hypr/scripts/Tak0-Autodispatch.sh +++ b/config/hypr/scripts/Tak0-Autodispatch.sh @@ -72,7 +72,7 @@ fi echo "=== Deploy '$CMD' → WS $TARGET_WS @ $(date) ===" >>"$LOGFILE" # Detect active Hyprland config mode -config_home="${XDG_CONFIG_HOME:-$HOME/.config}" +config_home="${XDG_CONFIG_HOME:-${XDG_CONFIG_HOME:-$HOME/.config}}" hypr_dir="$config_home/hypr" lua_entry="$hypr_dir/hyprland.lua" legacy_lua_entry="$config_home/hyprland.lua" diff --git a/config/hypr/scripts/Tak0-Per-Window-Switch.sh b/config/hypr/scripts/Tak0-Per-Window-Switch.sh index eba3b380..cc878615 100755 --- a/config/hypr/scripts/Tak0-Per-Window-Switch.sh +++ b/config/hypr/scripts/Tak0-Per-Window-Switch.sh @@ -19,12 +19,12 @@ ################################################################## MAP_FILE="$HOME/.cache/kb_layout_per_window" -ICON="$HOME/.config/swaync/images/ja.png" +ICON="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/images/ja.png" SCRIPT_NAME="$(basename "$0")" SCRIPT_PATH="$(readlink -f "$0")" # Detect active Hyprland config mode -config_home="${XDG_CONFIG_HOME:-$HOME/.config}" +config_home="${XDG_CONFIG_HOME:-${XDG_CONFIG_HOME:-$HOME/.config}}" hypr_dir="$config_home/hypr" lua_entry="$hypr_dir/hyprland.lua" legacy_lua_entry="$config_home/hyprland.lua" diff --git a/config/hypr/scripts/ThemeChanger.sh b/config/hypr/scripts/ThemeChanger.sh index c19908e4..f592300c 100755 --- a/config/hypr/scripts/ThemeChanger.sh +++ b/config/hypr/scripts/ThemeChanger.sh @@ -9,8 +9,8 @@ set -euo pipefail # Wallust v3/v4 compatibility wallust_args=() # shellcheck source=/dev/null -if [ -f "$HOME/.config/hypr/scripts/WallustConfig.sh" ]; then - . "$HOME/.config/hypr/scripts/WallustConfig.sh" +if [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts/WallustConfig.sh" ]; then + . "${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts/WallustConfig.sh" fi # SPDX-FileCopyrightText: 2025-present Ahum Maitra theahummaitra@gmail.com @@ -32,8 +32,12 @@ require rofi # notify-send is optional have_notify() { command -v notify-send >/dev/null 2>&1; } capture_current_layout() { + if [ -x "${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts/ChangeLayout.sh" ]; then + "${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts/ChangeLayout.sh" --no-notify current 2>/dev/null | awk 'NF {print; exit}' + return 0 + fi if command -v jq >/dev/null 2>&1; then - hyprctl -j getoption general:layout 2>/dev/null | jq -r '.str // empty' + hyprctl -j activeworkspace 2>/dev/null | jq -r '.tiledLayout // .tiled_layout // empty' else hyprctl getoption general:layout 2>/dev/null | awk 'NR==1 {print $2}' fi @@ -42,13 +46,9 @@ restore_layout_after_reload() { local layout="$1" [ -n "$layout" ] || return 0 - if [ -x "$HOME/.config/hypr/scripts/ChangeLayout.sh" ]; then - if "$HOME/.config/hypr/scripts/ChangeLayout.sh" --no-notify "$layout" >/dev/null 2>&1; then - return 0 - fi + if [ -x "${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts/ChangeLayout.sh" ]; then + "${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts/ChangeLayout.sh" --no-notify "$layout" >/dev/null 2>&1 || true fi - - hyprctl keyword general:layout "$layout" >/dev/null 2>&1 || true } reload_hypr_preserve_layout() { command -v hyprctl >/dev/null 2>&1 || return 0 @@ -91,9 +91,9 @@ if [ ! -s "$theme_cache" ] || [ "$cache_age" -gt "$cache_max_age" ]; then fi ensure_wallust_waybar_style() { - local waybar_style="$HOME/.config/waybar/style.css" - local colors_file="$HOME/.config/waybar/wallust/colors-waybar.css" - local styles_dir="$HOME/.config/waybar/style" + local waybar_style="${XDG_CONFIG_HOME:-$HOME/.config}/waybar/style.css" + local colors_file="${XDG_CONFIG_HOME:-$HOME/.config}/waybar/wallust/colors-waybar.css" + local styles_dir="${XDG_CONFIG_HOME:-$HOME/.config}/waybar/style" [ -f "$colors_file" ] || return 0 if [ -f "$waybar_style" ] && grep -q 'colors-waybar.css' "$waybar_style"; then return 0 @@ -119,7 +119,7 @@ reload_running_cava_colors() { fi } -wallust_hypr_colors="$HOME/.config/hypr/wallust/wallust-hyprland.conf" +wallust_hypr_colors="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/wallust/wallust-hyprland.conf" extract_wallust_hex() { local key="$1" awk -v key="$key" ' @@ -180,16 +180,16 @@ if wallust "${wallust_args[@]}" theme -- "${choice}" >"$wallust_log" 2>&1; then # 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 + mkdir -p "${XDG_CONFIG_HOME:-$HOME/.config}/ghostty" || true targets=( - "$HOME/.config/waybar/wallust/colors-waybar.css" - "$HOME/.config/rofi/wallust/colors-rofi.rasi" - "$HOME/.config/hypr/wallust/wallust-hyprland.conf" + "${XDG_CONFIG_HOME:-$HOME/.config}/waybar/wallust/colors-waybar.css" + "${XDG_CONFIG_HOME:-$HOME/.config}/rofi/wallust/colors-rofi.rasi" + "${XDG_CONFIG_HOME:-$HOME/.config}/hypr/wallust/wallust-hyprland.conf" ) # Normalize Ghostty palette syntax in case upstream templates or older targets used ':' - ghostty_conf="$HOME/.config/ghostty/wallust.conf" + ghostty_conf="${XDG_CONFIG_HOME:-$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 @@ -239,7 +239,7 @@ if wallust "${wallust_args[@]}" theme -- "${choice}" >"$wallust_log" 2>&1; then # 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" + rofi_colors="${XDG_CONFIG_HOME:-$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) @@ -258,8 +258,8 @@ if wallust "${wallust_args[@]}" theme -- "${choice}" >"$wallust_log" 2>&1; then reload_running_cava_colors # 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 + if [ -x "${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts/Refresh.sh" ]; then + "${XDG_CONFIG_HOME:-$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 diff --git a/config/hypr/scripts/Toggle-Active-Window-Audio.sh b/config/hypr/scripts/Toggle-Active-Window-Audio.sh index c954541f..42d63217 100755 --- a/config/hypr/scripts/Toggle-Active-Window-Audio.sh +++ b/config/hypr/scripts/Toggle-Active-Window-Audio.sh @@ -7,7 +7,7 @@ # ================================================== set -euo pipefail -XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" +XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-${XDG_CONFIG_HOME:-$HOME/.config}}" swayIconDir="${XDG_CONFIG_HOME}/swaync/icons" #// Credits to sl1ng for the orginal script. Rewritten by Vyle. diff --git a/config/hypr/scripts/Toggle-weather-waybar-units.sh b/config/hypr/scripts/Toggle-weather-waybar-units.sh index abc089ff..bf0b102e 100755 --- a/config/hypr/scripts/Toggle-weather-waybar-units.sh +++ b/config/hypr/scripts/Toggle-weather-waybar-units.sh @@ -7,7 +7,7 @@ # ================================================== # Toggle waybar-weather units between metric and imperial -CONFIG_FILE="$HOME/.config/waybar-weather/config.toml" +CONFIG_FILE="${XDG_CONFIG_HOME:-$HOME/.config}/waybar-weather/config.toml" if [ ! -f "$CONFIG_FILE" ]; then notify-send "Weather units" "Config not found: $CONFIG_FILE" diff --git a/config/hypr/scripts/ToggleWaybarTime.sh b/config/hypr/scripts/ToggleWaybarTime.sh new file mode 100755 index 00000000..2273c3af --- /dev/null +++ b/config/hypr/scripts/ToggleWaybarTime.sh @@ -0,0 +1,101 @@ +#!/usr/bin/env bash +# ================================================== +# KoolDots (2026) +# Project URL: https://github.com/LinuxBeginnings +# License: GNU GPLv3 +# SPDX-License-Identifier: GPL-3.0-or-later +# ================================================== +# Toggle Waybar clock format between 12H and 24H + +MODULES_FILE="${XDG_CONFIG_HOME:-$HOME/.config}/waybar/Modules" +notify_swaync() { + command -v notify-send >/dev/null 2>&1 || return 0 + export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}" + local icon="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/images/note.png" + if [ -z "${DBUS_SESSION_BUS_ADDRESS:-}" ]; then + local bus_path="${XDG_RUNTIME_DIR}/bus" + if [ -S "$bus_path" ]; then + export DBUS_SESSION_BUS_ADDRESS="unix:path=$bus_path" + fi + fi + DBUS_SESSION_BUS_ADDRESS="$DBUS_SESSION_BUS_ADDRESS" XDG_RUNTIME_DIR="$XDG_RUNTIME_DIR" \ + notify-send -a "Waybar Time" -u low -t 2000 -i "$icon" "$@" >/dev/null 2>&1 || true +} + +if [ ! -f "$MODULES_FILE" ]; then + notify_swaync "Modules file not found: $MODULES_FILE" + exit 1 +fi + +is_12h_active() { + grep -qE '^[[:space:]]*"format":[[:space:]]*" {:%I:%M %p}"' "$MODULES_FILE" +} + +apply_12h() { + sed -i 's#^\([[:space:]]*\)//\("format": " {:%I:%M %p}".*\)#\1\2#' "$MODULES_FILE" + sed -i 's#^\([[:space:]]*\)\("format": " {:%H:%M:%S}".*\)#\1//\2#' "$MODULES_FILE" + sed -i 's#^\([[:space:]]*\)\("format": " {:%H:%M}".*\)#\1//\2#' "$MODULES_FILE" + sed -i 's#^\([[:space:]]*\)//\("format": "{:%I:%M %p - %d/%b}".*\)#\1\2#' "$MODULES_FILE" + sed -i 's#^\([[:space:]]*\)\("format": "{:%H:%M - %d/%b}".*\)#\1//\2#' "$MODULES_FILE" + sed -i 's#^\([[:space:]]*\)//\("format": "{:%B | %a %d, %Y | %I:%M %p}".*\)#\1\2#' "$MODULES_FILE" + sed -i 's#^\([[:space:]]*\)\("format": "{:%B | %a %d, %Y | %H:%M}".*\)#\1//\2#' "$MODULES_FILE" + sed -i 's#^\([[:space:]]*\)//\("format": "{:%A, %I:%M %P}".*\)#\1\2#' "$MODULES_FILE" + sed -i 's#^\([[:space:]]*\)\("format": "{:%a %d | %H:%M}".*\)#\1//\2#' "$MODULES_FILE" +} + +apply_24h() { + sed -i 's#^\([[:space:]]*\)\("format": " {:%I:%M %p}".*\)#\1//\2#' "$MODULES_FILE" + sed -i 's#^\([[:space:]]*\)//\("format": " {:%H:%M:%S}".*\)#\1\2#' "$MODULES_FILE" + sed -i 's#^\([[:space:]]*\)//\("format": " {:%H:%M}".*\)#\1\2#' "$MODULES_FILE" + sed -i 's#^\([[:space:]]*\)\("format": "{:%I:%M %p - %d/%b}".*\)#\1//\2#' "$MODULES_FILE" + sed -i 's#^\([[:space:]]*\)//\("format": "{:%H:%M - %d/%b}".*\)#\1\2#' "$MODULES_FILE" + sed -i 's#^\([[:space:]]*\)\("format": "{:%B | %a %d, %Y | %I:%M %p}".*\)#\1//\2#' "$MODULES_FILE" + sed -i 's#^\([[:space:]]*\)//\("format": "{:%B | %a %d, %Y | %H:%M}".*\)#\1\2#' "$MODULES_FILE" + sed -i 's#^\([[:space:]]*\)\("format": "{:%A, %I:%M %P}".*\)#\1//\2#' "$MODULES_FILE" + sed -i 's#^\([[:space:]]*\)//\("format": "{:%a %d | %H:%M}".*\)#\1\2#' "$MODULES_FILE" +} + +restart_waybar() { + local manage_with_systemd=0 + + if command -v systemctl >/dev/null 2>&1; then + if systemctl --user --quiet is-active waybar.service 2>/dev/null || systemctl --user --quiet is-enabled waybar.service 2>/dev/null; then + manage_with_systemd=1 + fi + fi + + if [ "$manage_with_systemd" -eq 1 ]; then + systemctl --user stop waybar.service >/dev/null 2>&1 || true + fi + + pkill -x waybar >/dev/null 2>&1 || true + pkill -x '.waybar-wrapped' >/dev/null 2>&1 || true + sleep 0.2 + if pgrep -x waybar >/dev/null 2>&1 || pgrep -x '.waybar-wrapped' >/dev/null 2>&1; then + pkill -9 -x waybar >/dev/null 2>&1 || true + pkill -9 -x '.waybar-wrapped' >/dev/null 2>&1 || true + fi + sleep 0.2 + + if [ "$manage_with_systemd" -eq 1 ]; then + if ! systemctl --user start waybar.service >/dev/null 2>&1; then + waybar >/dev/null 2>&1 & + fi + else + waybar >/dev/null 2>&1 & + fi +} + +if is_12h_active; then + apply_24h + mode="24H" +else + apply_12h + mode="12H" +fi + +restart_waybar +sleep 0.3 + +notify_swaync "Switched to ${mode} format" +printf 'Waybar Time: switched to %s format\n' "$mode" diff --git a/config/hypr/scripts/TouchPad.sh b/config/hypr/scripts/TouchPad.sh index 1042a652..73cbfb46 100755 --- a/config/hypr/scripts/TouchPad.sh +++ b/config/hypr/scripts/TouchPad.sh @@ -6,14 +6,14 @@ # SPDX-License-Identifier: GPL-3.0-or-later # ================================================== # For disabling touchpad. -# Edit the Touchpad_Device on ~/.config/hypr/UserConfigs/Laptops.conf according to your system +# Edit the Touchpad_Device on ${XDG_CONFIG_HOME:-$HOME/.config}/hypr/UserConfigs/Laptops.conf according to your system # 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" +notif="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/images/ja.png" +laptops_conf="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/UserConfigs/Laptops.conf" touchpad_device="${TOUCHPAD_DEVICE:-}" if [[ -z "$touchpad_device" && -f "$laptops_conf" ]]; then diff --git a/config/hypr/scripts/UserConfigsSwitcher.sh b/config/hypr/scripts/UserConfigsSwitcher.sh index 7d9968a6..6259f363 100755 --- a/config/hypr/scripts/UserConfigsSwitcher.sh +++ b/config/hypr/scripts/UserConfigsSwitcher.sh @@ -7,7 +7,7 @@ # ================================================== # Script to manage UserConfigs and UserConfigsBak -HYPR_CONFIG_DIR="$HOME/.config/hypr" +HYPR_CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/hypr" USER_CONFIGS="$HYPR_CONFIG_DIR/UserConfigs" USER_CONFIGS_BAK="$HYPR_CONFIG_DIR/UserConfigsBak" diff --git a/config/hypr/scripts/Volume.sh b/config/hypr/scripts/Volume.sh index dec7837c..c6ef8873 100755 --- a/config/hypr/scripts/Volume.sh +++ b/config/hypr/scripts/Volume.sh @@ -7,8 +7,8 @@ # ================================================== # Scripts for volume controls for audio and mic -iDIR="$HOME/.config/swaync/icons" -sDIR="$HOME/.config/hypr/scripts" +iDIR="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/icons" +sDIR="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts" # Get Volume get_volume() { diff --git a/config/hypr/scripts/WallpaperAutoChange.sh b/config/hypr/scripts/WallpaperAutoChange.sh new file mode 100755 index 00000000..a12e90d8 --- /dev/null +++ b/config/hypr/scripts/WallpaperAutoChange.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash +# ================================================== +# KoolDots (2026) +# Project URL: https://github.com/LinuxBeginnings +# License: GNU GPLv3 +# SPDX-License-Identifier: GPL-3.0-or-later +# ================================================== +# source https://wiki.archlinux.org/title/Hyprland#Using_a_script_to_change_wallpaper_every_X_minutes + +# This script will randomly go through the files of a directory, setting it +# up as the wallpaper at regular intervals +# +# NOTE: this script uses bash (not POSIX shell) for the RANDOM variable + +wallust_refresh=${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts/RefreshNoWaybar.sh +SCRIPTSDIR="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts" +# shellcheck source=/dev/null +. "$SCRIPTSDIR/WallpaperCmd.sh" + +focused_monitor=$(hyprctl monitors | awk '/^Monitor/{name=$2} /focused: yes/{print name}') +wallpaper_base="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/wallpaper_effects/.wallpaper_base_${focused_monitor}" + +if [[ $# -lt 1 ]] || [[ ! -d $1 ]]; then + echo "Usage: + $0 <dir containing images>" + exit 1 +fi + +# Edit below to control the images transition (swww/awww) +export SWWW_TRANSITION_FPS=60 +export SWWW_TRANSITION_TYPE=simple + +# This controls (in seconds) when to switch to the next image +INTERVAL=1800 + +while true; do + find "$1" \ + | while read -r img; do + echo "$((RANDOM % 1000)):$img" + done \ + | sort -n | cut -d':' -f2- \ + | while read -r img; do + resize_mode="$(wallpaper_resize_mode "$img" "$focused_monitor")" + "$WWW_CMD" img -o "$focused_monitor" --resize "$resize_mode" "$img" + mkdir -p "$(dirname "$wallpaper_base")" + cp -f "$img" "$wallpaper_base" || true + # Regenerate colors from the exact image path to avoid cache races + ${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts/WallustSwww.sh "$img" + # Refresh UI components that depend on wallust output + $wallust_refresh + sleep $INTERVAL + + done +done diff --git a/config/hypr/scripts/WallpaperDaemon.sh b/config/hypr/scripts/WallpaperDaemon.sh index 60c35a6d..aeb6c397 100755 --- a/config/hypr/scripts/WallpaperDaemon.sh +++ b/config/hypr/scripts/WallpaperDaemon.sh @@ -7,7 +7,7 @@ # ================================================== # Start wallpaper daemon, preferring awww with swww fallback -SCRIPTSDIR="$HOME/.config/hypr/scripts" +SCRIPTSDIR="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts" # shellcheck source=/dev/null . "$SCRIPTSDIR/WallpaperCmd.sh" @@ -21,8 +21,8 @@ for _ in {1..50}; do sleep 0.1 done -wallpaper_link="$HOME/.config/rofi/.current_wallpaper" -wallpaper_current="$HOME/.config/hypr/wallpaper_effects/.wallpaper_current" +wallpaper_link="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/.current_wallpaper" +wallpaper_current="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/wallpaper_effects/.wallpaper_current" read_cached_wallpaper() { local cache_file="$1" @@ -40,8 +40,8 @@ get_monitors() { apply_wallpaper_for_monitor() { local monitor="$1" - local per_monitor_link="$HOME/.config/rofi/.current_wallpaper_${monitor}" - local per_monitor_current="$HOME/.config/hypr/wallpaper_effects/.wallpaper_current_${monitor}" + local per_monitor_link="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/.current_wallpaper_${monitor}" + local per_monitor_current="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/wallpaper_effects/.wallpaper_current_${monitor}" local wallpaper_path="" # Prefer per-monitor symlink target if valid diff --git a/config/hypr/scripts/WallpaperEffects.sh b/config/hypr/scripts/WallpaperEffects.sh new file mode 100755 index 00000000..fc88ba1e --- /dev/null +++ b/config/hypr/scripts/WallpaperEffects.sh @@ -0,0 +1,140 @@ +#!/usr/bin/env bash +# ================================================== +# KoolDots (2026) +# Project URL: https://github.com/LinuxBeginnings +# License: GNU GPLv3 +# SPDX-License-Identifier: GPL-3.0-or-later +# ================================================== +# Wallpaper Effects using ImageMagick (SUPER SHIFT W) + +# Variables +terminal=kitty +wallpaper_current="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/wallpaper_effects/.wallpaper_current" +wallpaper_output="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/wallpaper_effects/.wallpaper_modified" +wallpaper_base="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/wallpaper_effects/.wallpaper_base" +wallpaper_link="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/.current_wallpaper" +SCRIPTSDIR="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts" +# shellcheck source=/dev/null +. "$SCRIPTSDIR/WallpaperCmd.sh" +focused_monitor=$(hyprctl monitors -j | jq -r '.[] | select(.focused) | .name') +per_monitor_wallpaper_base="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/wallpaper_effects/.wallpaper_base_${focused_monitor}" +per_monitor_wallpaper_current="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/wallpaper_effects/.wallpaper_current_${focused_monitor}" +per_monitor_wallpaper_link="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/.current_wallpaper_${focused_monitor}" +rofi_theme="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/config-wallpaper-effect.rasi" + +# Directory for swaync +iDIR="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/images" +iDIRi="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/icons" + +# swww/awww transition config +FPS=60 +TYPE="wipe" +DURATION=2 +BEZIER=".43,1.19,1,.4" +if [[ "$WWW_CMD" == "swww" || "$WWW_CMD" == "awww" ]]; then + SWWW_PARAMS=(--transition-fps "$FPS" --transition-type "$TYPE" --transition-duration "$DURATION" --transition-bezier "$BEZIER") +else + SWWW_PARAMS=() +fi + +# Define ImageMagick effects +declare -A effects=( + ["No Effects"]="no-effects" + ["Black & White"]="magick $wallpaper_base -colorspace gray -sigmoidal-contrast 10,40% $wallpaper_output" + ["Blurred"]="magick $wallpaper_base -blur 0x10 $wallpaper_output" + ["Charcoal"]="magick $wallpaper_base -charcoal 0x5 $wallpaper_output" + ["Edge Detect"]="magick $wallpaper_base -edge 1 $wallpaper_output" + ["Emboss"]="magick $wallpaper_base -emboss 0x5 $wallpaper_output" + ["Frame Raised"]="magick $wallpaper_base +raise 150 $wallpaper_output" + ["Frame Sunk"]="magick $wallpaper_base -raise 150 $wallpaper_output" + ["Negate"]="magick $wallpaper_base -negate $wallpaper_output" + ["Oil Paint"]="magick $wallpaper_base -paint 4 $wallpaper_output" + ["Posterize"]="magick $wallpaper_base -posterize 4 $wallpaper_output" + ["Polaroid"]="magick $wallpaper_base -polaroid 0 $wallpaper_output" + ["Sepia Tone"]="magick $wallpaper_base -sepia-tone 65% $wallpaper_output" + ["Solarize"]="magick $wallpaper_base -solarize 80% $wallpaper_output" + ["Sharpen"]="magick $wallpaper_base -sharpen 0x5 $wallpaper_output" + ["Vignette"]="magick $wallpaper_base -vignette 0x3 $wallpaper_output" + ["Vignette-black"]="magick $wallpaper_base -background black -vignette 0x3 $wallpaper_output" + ["Zoomed"]="magick $wallpaper_base -gravity Center -extent 1:1 $wallpaper_output" +) +persist_wallpaper_state() { + local source_wallpaper="$1" + [ -n "$source_wallpaper" ] && [ -f "$source_wallpaper" ] || return 0 + + mkdir -p "$(dirname "$wallpaper_current")" "$(dirname "$wallpaper_link")" + cp -f "$source_wallpaper" "$wallpaper_current" || true + ln -sf "$source_wallpaper" "$wallpaper_link" || true + + if [[ -n "$focused_monitor" ]]; then + cp -f "$source_wallpaper" "$per_monitor_wallpaper_current" || true + ln -sf "$source_wallpaper" "$per_monitor_wallpaper_link" || true + fi +} + +# Function to apply no effects +no-effects() { + local resize_mode + resize_mode="$(wallpaper_resize_mode "$wallpaper_base" "$focused_monitor")" + "$WWW_CMD" img -o "$focused_monitor" --resize "$resize_mode" "$wallpaper_base" "${SWWW_PARAMS[@]}" || return 1 + persist_wallpaper_state "$wallpaper_base" + + notify-send -u low -i "$iDIR/ja.png" "No wallpaper" "effects applied" + # copying wallpaper for rofi menu + cp "$wallpaper_base" "$wallpaper_output" +} + +# Function to run rofi menu +main() { + # Populate rofi menu options + options=("No Effects") + for effect in "${!effects[@]}"; do + [[ "$effect" != "No Effects" ]] && options+=("$effect") + done + + choice=$(printf "%s\n" "${options[@]}" | LC_COLLATE=C sort | rofi -dmenu -i -config $rofi_theme) + + # Process user choice + if [[ -n "$choice" ]]; then + if [[ -f "$per_monitor_wallpaper_base" ]]; then + wallpaper_base="$per_monitor_wallpaper_base" + fi + if [[ ! -f "$wallpaper_base" ]]; then + mkdir -p "$(dirname "$wallpaper_base")" + cp -f "$wallpaper_current" "$wallpaper_base" || true + fi + if [[ "$choice" == "No Effects" ]]; then + no-effects + elif [[ "${effects[$choice]+exists}" ]]; then + # Apply selected effect + notify-send -u normal -i "$iDIR/ja.png" "Applying:" "$choice effects" + if ! eval "${effects[$choice]}"; then + notify-send -u critical -i "$iDIR/error.png" "Wallpaper effect failed" "$choice could not be applied" + return 1 + fi + + # intial kill process + for pid in swaybg mpvpaper; do + killall -SIGUSR1 "$pid" 2>/dev/null || true + done + + sleep 1 + local resize_mode + resize_mode="$(wallpaper_resize_mode "$wallpaper_output" "$focused_monitor")" + "$WWW_CMD" img -o "$focused_monitor" --resize "$resize_mode" "$wallpaper_output" "${SWWW_PARAMS[@]}" + persist_wallpaper_state "$wallpaper_output" + notify-send -u low -i "$iDIR/ja.png" "$choice" "effects applied" + else + echo "Effect '$choice' not recognized." + fi + fi +} + +# Check if rofi is already running and kill it +if pidof rofi > /dev/null; then + pkill rofi +fi + +main + +sleep 1 diff --git a/config/hypr/scripts/WallpaperRandom.sh b/config/hypr/scripts/WallpaperRandom.sh new file mode 100755 index 00000000..8480295c --- /dev/null +++ b/config/hypr/scripts/WallpaperRandom.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +# ================================================== +# KoolDots (2026) +# Project URL: https://github.com/LinuxBeginnings +# License: GNU GPLv3 +# SPDX-License-Identifier: GPL-3.0-or-later +# ================================================== +# Script for Random Wallpaper ( CTRL ALT W) + +PICTURES_DIR="$(xdg-user-dir PICTURES 2>/dev/null || echo "$HOME/Pictures")" +wallDIR="$PICTURES_DIR/wallpapers" +SCRIPTSDIR="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts" +# shellcheck source=/dev/null +. "$SCRIPTSDIR/WallpaperCmd.sh" + +focused_monitor=$(hyprctl monitors -j | jq -r '.[] | select(.focused) | .name') +wallpaper_base="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/wallpaper_effects/.wallpaper_base_${focused_monitor}" + +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[@]} ]} + + +# Transition config (swww/awww) +FPS=30 +TYPE="random" +DURATION=1 +BEZIER=".43,1.19,1,.4" +if [[ "$WWW_CMD" == "swww" || "$WWW_CMD" == "awww" ]]; then + SWWW_PARAMS=(--transition-fps "$FPS" --transition-type "$TYPE" --transition-duration "$DURATION" --transition-bezier "$BEZIER") +else + SWWW_PARAMS=() +fi +if ! "$WWW_CMD" query >/dev/null 2>&1; then + "$WWW_DAEMON" "${WWW_DAEMON_ARGS[@]}" & +fi +resize_mode="$(wallpaper_resize_mode "$RANDOMPICS" "$focused_monitor")" +"$WWW_CMD" img -o "$focused_monitor" --resize "$resize_mode" "$RANDOMPICS" "${SWWW_PARAMS[@]}" + +wait $! +mkdir -p "$(dirname "$wallpaper_base")" +cp -f "$RANDOMPICS" "$wallpaper_base" || true +if ! "$SCRIPTSDIR/WallustSwww.sh" "$RANDOMPICS"; then + notify-send -u critical "Wallust failed" "Wallpaper theme not refreshed" + exit 1 +fi + +wait $! +sleep 0.5 +"$SCRIPTSDIR/Refresh.sh" + diff --git a/config/hypr/scripts/WallpaperSelect.sh b/config/hypr/scripts/WallpaperSelect.sh new file mode 100755 index 00000000..a1684798 --- /dev/null +++ b/config/hypr/scripts/WallpaperSelect.sh @@ -0,0 +1,267 @@ +#!/usr/bin/env bash +# ================================================== +# KoolDots (2026) +# Project URL: https://github.com/LinuxBeginnings +# License: GNU GPLv3 +# SPDX-License-Identifier: GPL-3.0-or-later +# ================================================== +# This script for selecting wallpapers (SUPER W) + +# WALLPAPERS PATH +terminal=kitty +PICTURES_DIR="$(xdg-user-dir PICTURES 2>/dev/null || echo "$HOME/Pictures")" +wallDIR="$PICTURES_DIR/wallpapers" +SCRIPTSDIR="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts" +# shellcheck source=/dev/null +. "$SCRIPTSDIR/WallpaperCmd.sh" +wallpaper_current="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/wallpaper_effects/.wallpaper_current" +wallpaper_link="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/.current_wallpaper" +wallpaper_base="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/wallpaper_effects/.wallpaper_base" + +# Directory for swaync +iDIR="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/images" +iDIRi="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/icons" + +# swww/awww transition config +FPS=60 +TYPE="any" +DURATION=2 +BEZIER=".43,1.19,1,.4" +if [[ "$WWW_CMD" == "swww" || "$WWW_CMD" == "awww" ]]; then + SWWW_PARAMS=(--transition-fps "$FPS" --transition-type "$TYPE" --transition-duration "$DURATION" --transition-bezier "$BEZIER") +else + SWWW_PARAMS=() +fi + + +# Check if package bc exists +if ! command -v bc &>/dev/null; then + notify-send -i "$iDIR/error.png" "bc missing" "Install package bc first" + exit 1 +fi + +# Variables +rofi_theme="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/config-wallpaper.rasi" +focused_monitor=$(hyprctl monitors -j | jq -r '.[] | select(.focused) | .name') + +per_monitor_wallpaper_current="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/wallpaper_effects/.wallpaper_current_${focused_monitor}" +per_monitor_wallpaper_link="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/.current_wallpaper_${focused_monitor}" +per_monitor_wallpaper_base="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/wallpaper_effects/.wallpaper_base_${focused_monitor}" + +# Ensure focused_monitor is detected +if [[ -z "$focused_monitor" ]]; then + notify-send -i "$iDIR/error.png" "E-R-R-O-R" "Could not detect focused monitor" + exit 1 +fi + +# Monitor details +scale_factor=$(hyprctl monitors -j | jq -r --arg mon "$focused_monitor" '.[] | select(.name == $mon) | .scale') +monitor_height=$(hyprctl monitors -j | jq -r --arg mon "$focused_monitor" '.[] | select(.name == $mon) | .height') + +icon_size=$(echo "scale=1; ($monitor_height * 3) / ($scale_factor * 150)" | bc) +adjusted_icon_size=$(echo "$icon_size" | awk '{if ($1 < 15) $1 = 20; if ($1 > 25) $1 = 25; print $1}') +rofi_override="element-icon{size:${adjusted_icon_size}%;}" + +# Kill existing wallpaper daemons for video on the focused monitor only +kill_wallpaper_for_video() { + pkill -f "mpvpaper.*$focused_monitor" 2>/dev/null +} + +# Kill existing wallpaper daemons for image on the focused monitor only +kill_wallpaper_for_image() { + pkill -f "mpvpaper.*$focused_monitor" 2>/dev/null +} + +# Retrieve wallpapers (both images & videos) +mapfile -d '' PICS < <(find -L "${wallDIR}" -type f \( \ + -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" -o -iname "*.gif" -o \ + -iname "*.bmp" -o -iname "*.tiff" -o -iname "*.webp" -o \ + -iname "*.mp4" -o -iname "*.mkv" -o -iname "*.mov" -o -iname "*.webm" \) -print0) + +RANDOM_PIC="${PICS[$((RANDOM % ${#PICS[@]}))]}" +RANDOM_PIC_NAME="$(basename "$RANDOM_PIC")" + +CURRENT_MON_PIC_PATH=$("$WWW_CMD" query 2>/dev/null | grep "$focused_monitor" | awk '{print $NF}') +if [[ -z "$CURRENT_MON_PIC_PATH" ]]; then + if [[ -L "$wallpaper_link" ]]; then + CURRENT_MON_PIC_PATH="$(readlink -f "$wallpaper_link")" + elif [[ -f "$wallpaper_link" ]]; then + CURRENT_MON_PIC_PATH="$wallpaper_link" + elif [[ -f "$wallpaper_current" ]]; then + CURRENT_MON_PIC_PATH="$wallpaper_current" + fi +fi +CURRENT_MON_PIC_NAME=$(basename "$CURRENT_MON_PIC_PATH") + +# Rofi command +rofi_command="rofi -i -show -dmenu -config $rofi_theme -theme-str $rofi_override" + +# Sorting Wallpapers +menu() { + IFS=$'\n' sorted_options=($(sort <<<"${PICS[*]}")) + + printf "%s\x00icon\x1f%s\n" "Random: $RANDOM_PIC_NAME" "$RANDOM_PIC" + if [[ -n "$CURRENT_MON_PIC_PATH" ]]; then + printf "%s\x00icon\x1f%s\n" "Current: $CURRENT_MON_PIC_NAME" "$CURRENT_MON_PIC_PATH" + fi + + for pic_path in "${sorted_options[@]}"; do + pic_name=$(basename "$pic_path") + if [[ "$pic_name" =~ \.gif$ ]]; then + cache_gif_image="$HOME/.cache/gif_preview/${pic_name}.png" + if [[ ! -f "$cache_gif_image" ]]; then + mkdir -p "$HOME/.cache/gif_preview" + magick "$pic_path[0]" -resize 1920x1080 "$cache_gif_image" + fi + printf "%s\x00icon\x1f%s\n" "$pic_name" "$cache_gif_image" + elif [[ "$pic_name" =~ \.(mp4|mkv|mov|webm|MP4|MKV|MOV|WEBM)$ ]]; then + cache_preview_image="$HOME/.cache/video_preview/${pic_name}.png" + if [[ ! -f "$cache_preview_image" ]]; then + mkdir -p "$HOME/.cache/video_preview" + ffmpeg -v error -y -i "$pic_path" -ss 00:00:01.000 -vframes 1 "$cache_preview_image" + fi + printf "%s\x00icon\x1f%s\n" "$pic_name" "$cache_preview_image" + else + printf "%s\x00icon\x1f%s\n" "$pic_name" "$pic_path" + fi + done +} + + +modify_startup_config() { + local selected_file="$1" + local startup_config="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/UserConfigs/Startup_Apps.conf" + + # Check if it's a live wallpaper (video) + if [[ "$selected_file" =~ \.(mp4|mkv|mov|webm)$ ]]; then + # For video wallpapers: + sed -i '/^\s*exec-once\s*=\s*\$scriptsDir\/WallpaperDaemon\.sh\s*$/s/^/\#/' "$startup_config" + sed -i '/^\s*exec-once\s*=\s*swww-daemon\s*--format\s*xrgb\s*$/s/^/\#/' "$startup_config" + sed -i '/^\s*#\s*exec-once\s*=\s*mpvpaper\s*.*$/s/^#\s*//;' "$startup_config" + + # Update the livewallpaper variable with the selected video path (using $HOME) + selected_file="${selected_file/#$HOME/\$HOME}" # Replace /home/user with $HOME + sed -i "s|^\$livewallpaper=.*|\$livewallpaper=\"$selected_file\"|" "$startup_config" + + echo "Configured for live wallpaper (video)." + else + # For image wallpapers: + sed -i '/^\s*#\s*exec-once\s*=\s*\$scriptsDir\/WallpaperDaemon\.sh\s*$/s/^\s*#\s*//;' "$startup_config" + sed -i '/^\s*#\s*exec-once\s*=\s*swww-daemon\s*--format\s*xrgb\s*$/s/^\s*#\s*//;' "$startup_config" + + sed -i '/^\s*exec-once\s*=\s*mpvpaper\s*.*$/s/^/\#/' "$startup_config" + + echo "Configured for static wallpaper (image)." + fi +} + +# Apply Image Wallpaper +apply_image_wallpaper() { + local image_path="$1" + + kill_wallpaper_for_image + + if ! pgrep -x "$WWW_DAEMON" >/dev/null; then + echo "Starting $WWW_DAEMON..." + "$WWW_DAEMON" "${WWW_DAEMON_ARGS[@]}" & + fi + # Wait for daemon to be ready before applying + for _ in {1..20}; do + "$WWW_CMD" query >/dev/null 2>&1 && break + sleep 0.1 + done + local resize_mode + resize_mode="$(wallpaper_resize_mode "$image_path" "$focused_monitor")" + "$WWW_CMD" img -o "$focused_monitor" --resize "$resize_mode" "$image_path" "${SWWW_PARAMS[@]}" || { + sleep 0.2 + "$WWW_CMD" img -o "$focused_monitor" --resize "$resize_mode" "$image_path" "${SWWW_PARAMS[@]}" + } + "$WWW_CMD" img -o "$focused_monitor" --resize "$resize_mode" "$image_path" "${SWWW_PARAMS[@]}" + + # Persist per-monitor wallpaper selection + mkdir -p "$(dirname "$per_monitor_wallpaper_current")" "$(dirname "$per_monitor_wallpaper_link")" + ln -sf "$image_path" "$per_monitor_wallpaper_link" || true + cp -f "$image_path" "$per_monitor_wallpaper_current" || true + mkdir -p "$(dirname "$per_monitor_wallpaper_base")" + cp -f "$image_path" "$per_monitor_wallpaper_base" || true + cp -f "$image_path" "$wallpaper_base" || true + + # Run additional scripts (pass the image path to avoid cache race conditions) + if ! "$SCRIPTSDIR/WallustSwww.sh" "$image_path"; then + notify-send -i "$iDIR/error.png" "Wallust failed" "Wallpaper theme not refreshed" + return 1 + fi + sleep 0.5 + "$SCRIPTSDIR/Refresh.sh" + sleep 0.3 + +} + +apply_video_wallpaper() { + local video_path="$1" + + # Check if mpvpaper is installed + if ! command -v mpvpaper &>/dev/null; then + notify-send -i "$iDIR/error.png" "E-R-R-O-R" "mpvpaper not found" + return 1 + fi + kill_wallpaper_for_video + + # Apply video wallpaper only to the focused monitor + mpvpaper "$focused_monitor" -o "load-scripts=no no-audio --loop" "$video_path" & +} + +# Main function +main() { + choice=$(menu | $rofi_command) + choice=$(echo "$choice" | xargs) + RANDOM_PIC_NAME=$(echo "$RANDOM_PIC_NAME" | xargs) + raw_choice="$choice" + choice="${choice#Random: }" + choice="${choice#Current: }" + + if [[ -z "$choice" ]]; then + echo "No choice selected. Exiting." + exit 0 + fi + + # Resolve selection directly when using Random/Current entries + if [[ "$raw_choice" == Random:\ * ]]; then + selected_file="$RANDOM_PIC" + elif [[ "$raw_choice" == Current:\ * && -n "$CURRENT_MON_PIC_PATH" ]]; then + selected_file="$CURRENT_MON_PIC_PATH" + elif [[ -f "$choice" ]]; then + selected_file="$choice" + else + # Handle random selection by name when needed + if [[ "$choice" == "$RANDOM_PIC_NAME" ]]; then + choice=$(basename "$RANDOM_PIC") + fi + choice_basename=$(basename "$choice" | sed 's/\(.*\)\.[^.]*$/\1/') + + # Search for the selected file in the wallpapers directory, including subdirectories + selected_file=$(find "$wallDIR" -iname "$choice_basename.*" -print -quit) + fi + + if [[ -z "$selected_file" ]]; then + echo "File not found. Selected choice: $choice" + exit 1 + fi + + # Modify the Startup_Apps.conf file based on wallpaper type + modify_startup_config "$selected_file" + + # **CHECK FIRST** if it's a video or an image **before calling any function** + if [[ "$selected_file" =~ \.(mp4|mkv|mov|webm|MP4|MKV|MOV|WEBM)$ ]]; then + apply_video_wallpaper "$selected_file" + else + apply_image_wallpaper "$selected_file" + fi +} + +# Check if rofi is already running +if pidof rofi >/dev/null; then + pkill rofi +fi + +main
\ No newline at end of file diff --git a/config/hypr/scripts/WallustConfig.sh b/config/hypr/scripts/WallustConfig.sh index 44ddff0b..6605a084 100755 --- a/config/hypr/scripts/WallustConfig.sh +++ b/config/hypr/scripts/WallustConfig.sh @@ -8,7 +8,7 @@ # Wallust version compatibility helpers # # Purpose: -# - Wallust v3 reads ~/.config/wallust/wallust.toml (this repo ships a v3 config) +# - Wallust v3 reads ${XDG_CONFIG_HOME:-$HOME/.config}/wallust/wallust.toml (this repo ships a v3 config) # - Wallust v4 alpha uses a different config schema; users frequently install it # via wallust-git, which will fail to parse the v3 config. # @@ -31,8 +31,8 @@ wallust_prepare_args() { # Wallust v4 supports -C/--config-file. if [ -n "$major" ] && [ "$major" -ge 4 ]; then - local v4_cfg="$HOME/.config/wallust/wallust-v4.toml" - local v4_kitty_cfg="$HOME/.config/wallust/wallust-kitty-v4.toml" + local v4_cfg="${XDG_CONFIG_HOME:-$HOME/.config}/wallust/wallust-v4.toml" + local v4_kitty_cfg="${XDG_CONFIG_HOME:-$HOME/.config}/wallust/wallust-kitty-v4.toml" if [ -f "$v4_cfg" ]; then wallust_args=(-C "$v4_cfg") diff --git a/config/hypr/scripts/WallustSwww.sh b/config/hypr/scripts/WallustSwww.sh index 3472d519..7807cf4c 100755 --- a/config/hypr/scripts/WallustSwww.sh +++ b/config/hypr/scripts/WallustSwww.sh @@ -13,15 +13,19 @@ set -euo pipefail wallust_args=() wallust_kitty_args=() # shellcheck source=/dev/null -if [ -f "$HOME/.config/hypr/scripts/WallustConfig.sh" ]; then - . "$HOME/.config/hypr/scripts/WallustConfig.sh" +if [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts/WallustConfig.sh" ]; then + . "${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts/WallustConfig.sh" fi have_notify() { command -v notify-send >/dev/null 2>&1; } wallust_log="${XDG_CACHE_HOME:-$HOME/.cache}/wallust/wallust-swww.log" mkdir -p "$(dirname "$wallust_log")" capture_current_layout() { + if [ -x "${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts/ChangeLayout.sh" ]; then + "${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts/ChangeLayout.sh" --no-notify current 2>/dev/null | awk 'NF {print; exit}' + return 0 + fi if command -v jq >/dev/null 2>&1; then - hyprctl -j getoption general:layout 2>/dev/null | jq -r '.str // empty' + hyprctl -j activeworkspace 2>/dev/null | jq -r '.tiledLayout // .tiled_layout // empty' else hyprctl getoption general:layout 2>/dev/null | awk 'NR==1 {print $2}' fi @@ -30,13 +34,9 @@ restore_layout_after_reload() { local layout="$1" [ -n "$layout" ] || return 0 - if [ -x "$HOME/.config/hypr/scripts/ChangeLayout.sh" ]; then - if "$HOME/.config/hypr/scripts/ChangeLayout.sh" --no-notify "$layout" >/dev/null 2>&1; then - return 0 - fi + if [ -x "${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts/ChangeLayout.sh" ]; then + "${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts/ChangeLayout.sh" --no-notify "$layout" >/dev/null 2>&1 || true fi - - hyprctl keyword general:layout "$layout" >/dev/null 2>&1 || true } reload_hypr_preserve_layout() { command -v hyprctl >/dev/null 2>&1 || return 0 @@ -49,11 +49,11 @@ reload_hypr_preserve_layout() { restore_layout_after_reload "$active_layout" } ensure_wallust_waybar_style() { - local waybar_style="$HOME/.config/waybar/style.css" - local colors_file="$HOME/.config/waybar/wallust/colors-waybar.css" - local styles_dir="$HOME/.config/waybar/style" + local waybar_style="${XDG_CONFIG_HOME:-$HOME/.config}/waybar/style.css" + local colors_file="${XDG_CONFIG_HOME:-$HOME/.config}/waybar/wallust/colors-waybar.css" + local styles_dir="${XDG_CONFIG_HOME:-$HOME/.config}/waybar/style" [ -f "$colors_file" ] || return 0 - if [ -f "$waybar_style" ] && grep -q 'colors-waybar.css' "$waybar_style"; then + if [ -f "$waybar_style" ]; then return 0 fi local candidates=( @@ -88,8 +88,8 @@ else cache_dir="$HOME/.cache/swww/" cache_dir_fallback="$HOME/.cache/awww/" fi -rofi_link="$HOME/.config/rofi/.current_wallpaper" -wallpaper_current="$HOME/.config/hypr/wallpaper_effects/.wallpaper_current" +rofi_link="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/.current_wallpaper" +wallpaper_current="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/wallpaper_effects/.wallpaper_current" read_cached_wallpaper() { local cache_file="$1" if [[ -f "$cache_file" ]]; then @@ -163,7 +163,7 @@ 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 +mkdir -p "${XDG_CONFIG_HOME:-$HOME/.config}/ghostty" || true wait_for_templates() { local start_ts="$1" shift @@ -188,7 +188,7 @@ wait_for_templates() { return 1 } -# Run wallust (silent) to regenerate templates defined in ~/.config/wallust/wallust.toml +# Run wallust (silent) to regenerate templates defined in ${XDG_CONFIG_HOME:-$HOME/.config}/wallust/wallust.toml # -s is used in this repo to keep things quiet and avoid extra prompts start_ts=$(date +%s) if ! wallust "${wallust_args[@]}" run -s "$wallpaper_path" >"$wallust_log" 2>&1; then @@ -197,9 +197,9 @@ if ! wallust "${wallust_args[@]}" run -s "$wallpaper_path" >"$wallust_log" 2>&1; exit 1 fi wallust_targets=( - "$HOME/.config/waybar/wallust/colors-waybar.css" - "$HOME/.config/rofi/wallust/colors-rofi.rasi" - "$HOME/.config/hypr/wallust/wallust-hyprland.conf" + "${XDG_CONFIG_HOME:-$HOME/.config}/waybar/wallust/colors-waybar.css" + "${XDG_CONFIG_HOME:-$HOME/.config}/rofi/wallust/colors-rofi.rasi" + "${XDG_CONFIG_HOME:-$HOME/.config}/hypr/wallust/wallust-hyprland.conf" ) if ! wait_for_templates "$start_ts" "${wallust_targets[@]}"; then have_notify && notify-send -u critical -a WallustSwww \ @@ -210,7 +210,7 @@ ensure_wallust_waybar_style reload_running_cava_colors # Normalize Rofi selection colors to a brighter accent and readable foreground -rofi_colors="$HOME/.config/rofi/wallust/colors-rofi.rasi" +rofi_colors="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/wallust/colors-rofi.rasi" if [ -f "$rofi_colors" ]; then accent_hex=$(sed -n 's/^\s*color13:\s*\(#[0-9A-Fa-f]\{6\}\).*/\1/p' "$rofi_colors" | head -n1) [ -z "$accent_hex" ] && accent_hex=$(sed -n 's/^\s*color12:\s*\(#[0-9A-Fa-f]\{6\}\).*/\1/p' "$rofi_colors" | head -n1) @@ -244,7 +244,7 @@ run_wallust_with_config() { # Legacy fallback for builds that still honor env-based config override. WALLUST_CONFIG="$cfg" wallust run -s "$wallpaper_path" || true } -wallust_hypr_colors="$HOME/.config/hypr/wallust/wallust-hyprland.conf" +wallust_hypr_colors="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/wallust/wallust-hyprland.conf" extract_wallust_hex() { local key="$1" awk -v key="$key" ' @@ -274,7 +274,7 @@ apply_hypr_border_fallback() { } apply_hypr_gap_fallback() { - local decorations_lua="$HOME/.config/hypr/UserConfigs/user_decorations.lua" + local decorations_lua="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/UserConfigs/user_decorations.lua" [ -s "$decorations_lua" ] || return 0 local gaps_in gaps_out border_size gaps_in="$(sed -n 's/^[[:space:]]*gaps_in[[:space:]]*=[[:space:]]*\([0-9]\+\).*/\1/p' "$decorations_lua" | head -n1)" @@ -289,9 +289,9 @@ apply_hypr_gap_fallback() { # Apply Hyprland updates immediately to avoid delayed border/gap changes. reload_hypr_preserve_layout -kitty_cfg="$HOME/.config/wallust/wallust-kitty.toml" +kitty_cfg="${XDG_CONFIG_HOME:-$HOME/.config}/wallust/wallust-kitty.toml" if [ "${#wallust_kitty_args[@]}" -gt 0 ]; then - kitty_cfg="$HOME/.config/wallust/wallust-kitty-v4.toml" + kitty_cfg="${XDG_CONFIG_HOME:-$HOME/.config}/wallust/wallust-kitty-v4.toml" fi ( if [ -f "$kitty_cfg" ]; then @@ -300,7 +300,7 @@ fi # Reload kitty colors when wallpaper-based theme is active. # Use SIGUSR1 directly to avoid extra latency from kitty remote-control calls. - kitty_wallust_theme="$HOME/.config/kitty/kitty-themes/01-Wallust.conf" + kitty_wallust_theme="${XDG_CONFIG_HOME:-$HOME/.config}/kitty/kitty-themes/01-Wallust.conf" if [ -s "$kitty_wallust_theme" ]; then if pidof kitty >/dev/null 2>&1; then for pid in $(pidof kitty); do @@ -310,13 +310,13 @@ fi fi # 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 + if [ -f "${XDG_CONFIG_HOME:-$HOME/.config}/ghostty/wallust.conf" ]; then + sed -i -E 's/^(\s*palette\s*=\s*)([0-9]{1,2}):/\1\2=/' "${XDG_CONFIG_HOME:-$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 + [ -s "${XDG_CONFIG_HOME:-$HOME/.config}/ghostty/wallust.conf" ] && break sleep 0.1 done if pidof ghostty >/dev/null; then diff --git a/config/hypr/scripts/WaybarLayout.sh b/config/hypr/scripts/WaybarLayout.sh index 66d45a07..51e93bb3 100755 --- a/config/hypr/scripts/WaybarLayout.sh +++ b/config/hypr/scripts/WaybarLayout.sh @@ -10,10 +10,10 @@ IFS=$'\n\t' # Define directories -waybar_layouts="$HOME/.config/waybar/configs" -waybar_config="$HOME/.config/waybar/config" -SCRIPTSDIR="$HOME/.config/hypr/scripts" -rofi_config="$HOME/.config/rofi/config-waybar-layout.rasi" +waybar_layouts="${XDG_CONFIG_HOME:-$HOME/.config}/waybar/configs" +waybar_config="${XDG_CONFIG_HOME:-$HOME/.config}/waybar/config" +SCRIPTSDIR="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts" +rofi_config="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/config-waybar-layout.rasi" msg=' 🎌 NOTE: Some waybar LAYOUT NOT fully compatible with some STYLES' # Apply selected configuration diff --git a/config/hypr/scripts/WaybarScripts.sh b/config/hypr/scripts/WaybarScripts.sh index afb55712..dfd175f1 100755 --- a/config/hypr/scripts/WaybarScripts.sh +++ b/config/hypr/scripts/WaybarScripts.sh @@ -5,10 +5,10 @@ # License: GNU GPLv3 # SPDX-License-Identifier: GPL-3.0-or-later # ================================================== -# This file used on waybar modules sourcing defaults set in $HOME/.config/hypr/UserConfigs/01-UserDefaults.conf +# This file used on waybar modules sourcing defaults set in ${XDG_CONFIG_HOME:-$HOME/.config}/hypr/UserConfigs/01-UserDefaults.conf # Define the path to the config file -config_file=$HOME/.config/hypr/UserConfigs/01-UserDefaults.conf +config_file=${XDG_CONFIG_HOME:-$HOME/.config}/hypr/UserConfigs/01-UserDefaults.conf # Check if the config file exists if [[ ! -f "$config_file" ]]; then @@ -31,7 +31,7 @@ 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." + notify-send -u low -i "${XDG_CONFIG_HOME:-$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 &" diff --git a/config/hypr/scripts/WaybarStyles.sh b/config/hypr/scripts/WaybarStyles.sh index 611e0a12..ab951e22 100755 --- a/config/hypr/scripts/WaybarStyles.sh +++ b/config/hypr/scripts/WaybarStyles.sh @@ -10,10 +10,10 @@ IFS=$'\n\t' # Define directories -waybar_styles="$HOME/.config/waybar/style" -waybar_style="$HOME/.config/waybar/style.css" -SCRIPTSDIR="$HOME/.config/hypr/scripts" -rofi_config="$HOME/.config/rofi/config-waybar-style.rasi" +waybar_styles="${XDG_CONFIG_HOME:-$HOME/.config}/waybar/style" +waybar_style="${XDG_CONFIG_HOME:-$HOME/.config}/waybar/style.css" +SCRIPTSDIR="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts" +rofi_config="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/config-waybar-style.rasi" msg=' 🎌 NOTE: Some waybar STYLES NOT fully compatible with some LAYOUTS' # Apply selected style diff --git a/config/hypr/scripts/ZshChangeTheme.sh b/config/hypr/scripts/ZshChangeTheme.sh new file mode 100755 index 00000000..21049317 --- /dev/null +++ b/config/hypr/scripts/ZshChangeTheme.sh @@ -0,0 +1,74 @@ +#!/usr/bin/env bash +# ================================================== +# KoolDots (2026) +# Project URL: https://github.com/LinuxBeginnings +# License: GNU GPLv3 +# SPDX-License-Identifier: GPL-3.0-or-later +# ================================================== +# Script for Oh my ZSH theme ( CTRL SHIFT O) + +# preview of theme can be view here: https://github.com/ohmyzsh/ohmyzsh/wiki/Themes +# after choosing theme, TTY need to be closed and re-open + +# Variables +iDIR="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/images" +rofi_theme="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/config-zsh-theme.rasi" + +if [ -n "$(grep -i nixos < /etc/os-release)" ]; then + notify-send -i "$iDIR/note.png" "NOT Supported" "Sorry NixOS does not support this KooL feature" + exit 1 +fi + +themes_dir="$HOME/.oh-my-zsh/themes" +file_extension=".zsh-theme" + + +themes_array=($(find -L "$themes_dir" -type f -name "*$file_extension" -exec basename {} \; | sed -e "s/$file_extension//")) + +# Add "Random" option to the beginning of the array +themes_array=("Random" "${themes_array[@]}") + +rofi_command="rofi -i -dmenu -config $rofi_theme" + +menu() { + for theme in "${themes_array[@]}"; do + echo "$theme" + done +} + +main() { + choice=$(menu | ${rofi_command}) + + # if nothing selected, script won't change anything + if [ -z "$choice" ]; then + exit 0 + fi + + zsh_path="$HOME/.zshrc" + var_name="ZSH_THEME" + + if [[ "$choice" == "Random" ]]; then + # Pick a random theme from the original themes_array (excluding "Random") + random_theme=${themes_array[$((RANDOM % (${#themes_array[@]} - 1) + 1))]} + theme_to_set="$random_theme" + notify-send -i "$iDIR/ja.png" "Random theme:" "selected: $random_theme" + else + # Set theme to the selected choice + theme_to_set="$choice" + notify-send -i "$iDIR/ja.png" "Theme selected:" "$choice" + fi + + if [ -f "$zsh_path" ]; then + sed -i "s/^$var_name=.*/$var_name=\"$theme_to_set\"/" "$zsh_path" + notify-send -i "$iDIR/ja.png" "OMZ theme" "applied. restart your terminal" + else + notify-send -i "$iDIR/error.png" "E-R-R-O-R" "~.zshrc file not found!" + fi +} + +# Check if rofi is already running +if pidof rofi > /dev/null; then + pkill rofi +fi + +main diff --git a/config/hypr/scripts/fastfetch-wrapper.sh b/config/hypr/scripts/fastfetch-wrapper.sh index ad5f7873..ea76afff 100755 --- a/config/hypr/scripts/fastfetch-wrapper.sh +++ b/config/hypr/scripts/fastfetch-wrapper.sh @@ -6,7 +6,7 @@ SPECIFIC_ID=$ID FAMILY_ID=$ID_LIKE # 2. Define your asset directory -ASSET_DIR="$HOME/.config/fastfetch/images" +ASSET_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/fastfetch/images" # 3. Selection Logic if [ -f "$ASSET_DIR/$SPECIFIC_ID.png" ]; then diff --git a/config/hypr/scripts/kooldots-add-ssh-agent.sh b/config/hypr/scripts/kooldots-add-ssh-agent.sh new file mode 100755 index 00000000..56a62437 --- /dev/null +++ b/config/hypr/scripts/kooldots-add-ssh-agent.sh @@ -0,0 +1,310 @@ +#!/usr/bin/env bash +# ================================================== +# KoolDots (2026) +# Project URL: https://github.com/LinuxBeginnings +# License: GNU GPLv3 +# SPDX-License-Identifier: GPL-3.0-or-later +# ================================================== +# Adds a user ssh-agent systemd service and wires SSH_AUTH_SOCK into Hyprland. + +set -euo pipefail + +SCRIPT_NAME="$(basename "$0")" +CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" +HYPR_DIR="$CONFIG_HOME/hypr" +USER_CONFIGS_DIR="$HYPR_DIR/UserConfigs" +ENV_CONF="$USER_CONFIGS_DIR/ENVariables.conf" +ENV_LUA="$USER_CONFIGS_DIR/user_env.lua" +SYSTEMD_USER_DIR="$CONFIG_HOME/systemd/user" +SERVICE_NAME="ssh-agent" +SERVICE_FILE="$SYSTEMD_USER_DIR/${SERVICE_NAME}.service" +SSH_CONFIG="$HOME/.ssh/config" + +DRY_RUN=0 +ACTION="status" +SHOW_SYSTEMD_STATUS=0 +SHOW_HELP=0 + +info() { printf '[INFO] %s\n' "$*"; } +warn() { printf '[WARN] %s\n' "$*"; } +step() { printf '[STEP] %s\n' "$*"; } + +usage() { + cat <<USAGE +Usage: $SCRIPT_NAME [options] + +Options: + -h, --help Show help. + -d, --dry-run Show what would change without writing files or running systemctl. + -s, --status Show installed/config status and systemctl status output. + -e, --enable Install/enable the user service. + -D, --disable Stop/disable the user service. + -r, --remove Disable and remove the user service file. + +Notes: + --disable has a short flag -D to avoid clashing with -d (dry-run). + Set HYPR_CONFIG_MODE=lua|conf|hyprlang|auto to override detection. + Keys must be loaded separately (e.g. ssh-add ~/.ssh/id_ed25519). AddKeysToAgent only auto-adds after first use. +USAGE +} + +ORIGINAL_ARGS=$# +if [ "$ORIGINAL_ARGS" -eq 0 ]; then + SHOW_HELP=1 + SHOW_SYSTEMD_STATUS=1 +fi + +while [ "$#" -gt 0 ]; do + case "$1" in + -h|--help) + usage + exit 0 + ;; + -d|--dry-run) + DRY_RUN=1 + ;; + -s|--status) + ACTION="status" + SHOW_SYSTEMD_STATUS=1 + ;; + -e|--enable) + ACTION="enable" + ;; + -D|--disable|--disable-service|--disable) + ACTION="disable" + ;; + -r|--remove) + ACTION="remove" + ;; + *) + warn "Unknown option: $1" + usage + exit 1 + ;; + esac + shift +done + +run_cmd() { + if [ "$DRY_RUN" -eq 1 ]; then + printf '[DRY-RUN] %s\n' "$*" + return 0 + fi + "$@" +} + +detect_hypr_config_mode() { + local lua_entry="$HYPR_DIR/hyprland.lua" + local legacy_lua_entry="$CONFIG_HOME/hyprland.lua" + local mode="${HYPR_CONFIG_MODE:-}" + if [ -n "$mode" ]; then + case "${mode,,}" in + lua) echo "lua"; return ;; + conf|hyprlang) echo "conf"; return ;; + auto) ;; + *) ;; + esac + fi + if [ -f "$lua_entry" ] || [ -f "$legacy_lua_entry" ]; then + echo "lua" + else + echo "conf" + fi +} + +service_exists() { + [ -f "$SERVICE_FILE" ] +} + +systemctl_user() { + if ! command -v systemctl >/dev/null 2>&1; then + warn "systemctl not found; cannot manage the user service." + return 1 + fi + run_cmd systemctl --user "$@" +} + +service_status_summary() { + local enabled="unknown" + local active="unknown" + if command -v systemctl >/dev/null 2>&1; then + enabled="$(systemctl --user is-enabled "$SERVICE_NAME" 2>/dev/null || true)" + active="$(systemctl --user is-active "$SERVICE_NAME" 2>/dev/null || true)" + fi + if service_exists; then + info "Service file exists: $SERVICE_FILE" + else + warn "Service file missing: $SERVICE_FILE" + fi + info "Service enabled: ${enabled:-unknown}" + info "Service active: ${active:-unknown}" +} + +env_present_conf() { + [ -f "$ENV_CONF" ] && grep -Eq '^[[:space:]]*env[[:space:]]*=[[:space:]]*SSH_AUTH_SOCK,' "$ENV_CONF" +} + +env_present_lua() { + [ -f "$ENV_LUA" ] && grep -Eq 'hl\.env\([[:space:]]*["'\'']SSH_AUTH_SOCK["'\'']' "$ENV_LUA" +} + +ensure_env_conf() { + if env_present_conf; then + info "Hyprland ENV already set in $ENV_CONF" + return 0 + fi + step "Adding SSH_AUTH_SOCK to $ENV_CONF" + if [ "$DRY_RUN" -eq 1 ]; then + printf '[DRY-RUN] append SSH_AUTH_SOCK to %s\n' "$ENV_CONF" + return 0 + fi + mkdir -p "$(dirname "$ENV_CONF")" + touch "$ENV_CONF" + printf '\n# SSH agent socket\nenv = SSH_AUTH_SOCK,$XDG_RUNTIME_DIR/ssh-agent.socket\n' >> "$ENV_CONF" +} + +ensure_env_lua() { + if env_present_lua; then + info "Hyprland ENV already set in $ENV_LUA" + return 0 + fi + step "Adding SSH_AUTH_SOCK to $ENV_LUA" + if [ "$DRY_RUN" -eq 1 ]; then + printf '[DRY-RUN] append SSH_AUTH_SOCK to %s\n' "$ENV_LUA" + return 0 + fi + mkdir -p "$(dirname "$ENV_LUA")" + touch "$ENV_LUA" + cat <<'LUA' >> "$ENV_LUA" + +-- SSH agent socket +hl.env("SSH_AUTH_SOCK", (os.getenv("XDG_RUNTIME_DIR") or "") .. "/ssh-agent.socket") +LUA +} + +ensure_ssh_config() { + if [ ! -f "$SSH_CONFIG" ]; then + warn "$SSH_CONFIG not found; skipping AddKeysToAgent check." + return 0 + fi + if grep -Eq '^[[:space:]]*AddKeysToAgent[[:space:]]+yes' "$SSH_CONFIG"; then + info "AddKeysToAgent already set in $SSH_CONFIG" + return 0 + fi + step "Adding AddKeysToAgent to $SSH_CONFIG" + if [ "$DRY_RUN" -eq 1 ]; then + printf '[DRY-RUN] append AddKeysToAgent to %s\n' "$SSH_CONFIG" + return 0 + fi + printf '\n# Automatically add keys to ssh-agent\nAddKeysToAgent yes\n' >> "$SSH_CONFIG" +} + +create_service_file() { + if service_exists; then + info "Service file already exists: $SERVICE_FILE" + return 0 + fi + step "Creating systemd user service file" + if [ "$DRY_RUN" -eq 1 ]; then + printf '[DRY-RUN] create service file %s\n' "$SERVICE_FILE" + return 0 + fi + mkdir -p "$SYSTEMD_USER_DIR" + cat <<'EOF' > "$SERVICE_FILE" +[Unit] +Description=SSH key agent + +[Service] +Type=simple +Environment=SSH_AUTH_SOCK=%t/ssh-agent.socket +ExecStart=/usr/bin/ssh-agent -D -a $SSH_AUTH_SOCK + +[Install] +WantedBy=default.target +EOF +} + +enable_service() { + step "Enabling ssh-agent user service" + systemctl_user daemon-reload + systemctl_user enable --now "$SERVICE_NAME" +} + +disable_service() { + step "Disabling ssh-agent user service" + systemctl_user disable --now "$SERVICE_NAME" +} + +remove_service() { + step "Removing ssh-agent user service" + if service_exists; then + disable_service || true + if [ "$DRY_RUN" -eq 1 ]; then + printf '[DRY-RUN] remove service file %s\n' "$SERVICE_FILE" + else + rm -f "$SERVICE_FILE" + fi + systemctl_user daemon-reload + else + warn "Service file not found; nothing to remove." + fi +} + +show_status() { + info "Detected Hyprland config mode: $(detect_hypr_config_mode)" + service_status_summary + info "SSH_AUTH_SOCK in ENVariables.conf: $(env_present_conf && echo yes || echo no)" + info "SSH_AUTH_SOCK in user_env.lua: $(env_present_lua && echo yes || echo no)" + if [ -f "$SSH_CONFIG" ]; then + info "AddKeysToAgent in ~/.ssh/config: $(grep -Eq '^[[:space:]]*AddKeysToAgent[[:space:]]+yes' "$SSH_CONFIG" && echo yes || echo no)" + else + warn "~/.ssh/config not found." + fi + if [ "$SHOW_SYSTEMD_STATUS" -eq 1 ] && command -v systemctl >/dev/null 2>&1; then + systemctl --user status "$SERVICE_NAME" || true + fi +} + +apply_hypr_env() { + local mode + mode="$(detect_hypr_config_mode)" + if [ "$mode" = "lua" ]; then + ensure_env_lua + else + ensure_env_conf + fi +} + +if [ "$SHOW_HELP" -eq 1 ]; then + usage +fi + +case "$ACTION" in + status) + show_status + ;; + enable) + step "Step 1/4: Ensure service file" + create_service_file + step "Step 2/4: Enable user service" + enable_service + step "Step 3/4: Update Hyprland environment" + apply_hypr_env + step "Step 4/4: Update SSH config" + ensure_ssh_config + show_status + ;; + disable) + disable_service + show_status + ;; + remove) + remove_service + show_status + ;; + *) + warn "Unknown action: $ACTION" + usage + exit 1 + ;; +esac diff --git a/config/hypr/scripts/rofi-emacs-keybinds b/config/hypr/scripts/rofi-emacs-keybinds index bee1a54d..6617d3b0 100755 --- a/config/hypr/scripts/rofi-emacs-keybinds +++ b/config/hypr/scripts/rofi-emacs-keybinds @@ -2,7 +2,7 @@ set -u set -o pipefail -ROFI_CONFIG="${HOME}/.config/rofi/config-emacs-keybinds.rasi" +ROFI_CONFIG="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/config-emacs-keybinds.rasi" CACHE_FILE="${HOME}/.cache/rofi-emacs-keybinds.txt" if [[ ! -s "${CACHE_FILE}" ]]; then diff --git a/config/hypr/scripts/rofi-ssh-menu.sh b/config/hypr/scripts/rofi-ssh-menu.sh index d1640c66..1b058f59 100755 --- a/config/hypr/scripts/rofi-ssh-menu.sh +++ b/config/hypr/scripts/rofi-ssh-menu.sh @@ -10,7 +10,7 @@ set -euo pipefail SSH_CONFIG="${HOME}/.ssh/config" -ROFI_CONFIG="${HOME}/.config/rofi/config.rasi" +ROFI_CONFIG="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/config.rasi" MSG='Select a host to connect via SSH' notify() { diff --git a/config/hypr/scripts/sddm_wallpaper.sh b/config/hypr/scripts/sddm_wallpaper.sh index deee938c..f30bac9b 100755 --- a/config/hypr/scripts/sddm_wallpaper.sh +++ b/config/hypr/scripts/sddm_wallpaper.sh @@ -7,69 +7,409 @@ # ================================================== # SDDM Wallpaper and Wallust Colors Setter -# for the upcoming changes on the simple_sddm_theme - # variables terminal=kitty 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" +SCRIPTSDIR="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/scripts" +wallpaper_link="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/.current_wallpaper" +wallpaper_current="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/wallpaper_effects/.wallpaper_current" +wallpaper_modified="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/wallpaper_effects/.wallpaper_modified" +rofi_theme="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/config-wallpaper.rasi" +# Directory for swaync +iDIR="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/images" +iDIRi="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/icons" +video_preview_cache="$HOME/.cache/video_preview" +sddm_video_cache="$HOME/.cache/sddm_preview" +# shellcheck source=/dev/null +. "$SCRIPTSDIR/WallpaperCmd.sh" 2>/dev/null || true + +find_notify_send() { + local candidate="" + if candidate="$(command -v notify-send 2>/dev/null)"; then + if [[ -n "$candidate" && -x "$candidate" ]]; then + printf '%s\n' "$candidate" + return 0 + fi + fi + for candidate in /usr/bin/notify-send /usr/sbin/notify-send /bin/notify-send /sbin/notify-send; do + if [[ -x "$candidate" ]]; then + printf '%s\n' "$candidate" + return 0 + fi + done + return 1 +} + +NOTIFY_SEND_BIN="$(find_notify_send || true)" + +notify_err() { + if [[ -n "$NOTIFY_SEND_BIN" ]]; then + if [[ -f "$iDIR/error.png" ]]; then + "$NOTIFY_SEND_BIN" -i "$iDIR/error.png" "SDDM" "$1" + else + "$NOTIFY_SEND_BIN" "SDDM" "$1" + fi + fi +} + +notify_ok() { + if [[ -n "$NOTIFY_SEND_BIN" ]]; then + if [[ -f "$iDIR/ja.png" ]]; then + "$NOTIFY_SEND_BIN" -i "$iDIR/ja.png" "SDDM" "$1" + else + "$NOTIFY_SEND_BIN" "SDDM" "$1" + fi + fi +} + +read_cached_wallpaper() { + local cache_file="$1" + [[ -f "$cache_file" ]] || return 1 + awk 'NF && $0 !~ /^filter/ {print; exit}' "$cache_file" +} + +read_wallpaper_from_query() { + local monitor="$1" + [[ -n "$monitor" ]] || return 1 + [[ -n "${WWW_CMD:-}" ]] || return 1 + command -v "$WWW_CMD" >/dev/null 2>&1 || return 1 + "$WWW_CMD" query 2>/dev/null | awk -v mon="$monitor" ' + { + line=$0 + sub(/^Monitor[[:space:]]+/, "", line) + sub(/^:[[:space:]]*/, "", line) + mon_name=line + sub(/:.*/, "", mon_name) + gsub(/^[[:space:]]+|[[:space:]]+$/, "", mon_name) + if (mon_name != mon) next + path=line + sub(/^.*image:[[:space:]]*/, "", path) + gsub(/^[[:space:]]+|[[:space:]]+$/, "", path) + if (path != line && length(path) > 0) { + print path + exit + } + } + ' +} + +read_wallpaper_from_cache() { + local monitor="$1" + local cache_root="${WWW_CACHE_DIR:-$HOME/.cache/awww}" + local cache_file="$cache_root/$monitor" + local fallback_cache="" + local path="" + + case "$cache_root" in + "$HOME/.cache/awww") + fallback_cache="$HOME/.cache/swww/$monitor" + ;; + "$HOME/.cache/swww") + fallback_cache="$HOME/.cache/awww/$monitor" + ;; + esac + + path="$(read_cached_wallpaper "$cache_file" 2>/dev/null || true)" + if [[ -z "$path" && -n "$fallback_cache" ]]; then + path="$(read_cached_wallpaper "$fallback_cache" 2>/dev/null || true)" + fi + + [[ -n "$path" && -f "$path" ]] || return 1 + printf '%s\n' "$path" +} + +calculate_rofi_icon_size() { + local monitor="$1" + local scale_factor="" + local monitor_height="" + local icon_size="" + local adjusted_icon_size="" + + if [[ -z "$monitor" ]]; then + monitor="$(get_focused_monitor 2>/dev/null || true)" + fi + + if [[ -z "$monitor" ]]; then + printf '22\n' + return 0 + fi + + if command -v hyprctl >/dev/null 2>&1 && command -v jq >/dev/null 2>&1 && command -v bc >/dev/null 2>&1; then + scale_factor="$(hyprctl monitors -j 2>/dev/null | jq -r --arg mon "$monitor" '.[] | select(.name == $mon) | .scale' | head -n1)" + monitor_height="$(hyprctl monitors -j 2>/dev/null | jq -r --arg mon "$monitor" '.[] | select(.name == $mon) | .height' | head -n1)" + if [[ -n "$scale_factor" && -n "$monitor_height" && "$scale_factor" != "null" && "$monitor_height" =~ ^[0-9]+$ ]]; then + icon_size="$(echo "scale=1; ($monitor_height * 3) / ($scale_factor * 150)" | bc 2>/dev/null || true)" + adjusted_icon_size="$(echo "$icon_size" | awk '{if ($1 < 15) $1 = 20; if ($1 > 25) $1 = 25; print int($1)}')" + if [[ "$adjusted_icon_size" =~ ^[0-9]+$ ]]; then + printf '%s\n' "$adjusted_icon_size" + return 0 + fi + fi + fi + + printf '22\n' +} + +resolve_link_or_file() { + local path="$1" + local resolved="" + if [[ -L "$path" ]]; then + resolved="$(readlink -f "$path" 2>/dev/null || true)" + if [[ -n "$resolved" && -f "$resolved" ]]; then + printf '%s\n' "$resolved" + return 0 + fi + fi + if [[ -f "$path" ]]; then + printf '%s\n' "$path" + return 0 + fi + return 1 +} + +get_active_workspace_monitor() { + if ! command -v hyprctl >/dev/null 2>&1; then + return 1 + fi + if command -v jq >/dev/null 2>&1; then + hyprctl activeworkspace -j 2>/dev/null | jq -r '.monitor // empty' | head -n1 + else + hyprctl monitors 2>/dev/null | awk '/^Monitor/{name=$2} /focused: yes/{print name; exit}' + fi +} + +get_focused_monitor() { + if ! command -v hyprctl >/dev/null 2>&1; then + return 1 + fi + if command -v jq >/dev/null 2>&1; then + hyprctl monitors -j 2>/dev/null | jq -r '.[] | select(.focused) | .name' | head -n1 + else + hyprctl monitors 2>/dev/null | awk '/^Monitor/{name=$2} /focused: yes/{print name; exit}' + fi +} + +monitor_exists() { + local monitor="$1" + [[ -n "$monitor" ]] || return 1 + command -v hyprctl >/dev/null 2>&1 || return 1 + if command -v jq >/dev/null 2>&1; then + hyprctl monitors -j 2>/dev/null | jq -r --arg mon "$monitor" '.[] | select(.name == $mon) | .name' | grep -qx "$monitor" + else + hyprctl monitors 2>/dev/null | awk '/^Monitor/{print $2}' | grep -qx "$monitor" + fi +} + +resolve_target_monitor() { + local requested="$1" + local monitor="" + if monitor_exists "$requested"; then + printf '%s\n' "$requested" + return 0 + fi + monitor="$(get_active_workspace_monitor 2>/dev/null || true)" + if monitor_exists "$monitor"; then + printf '%s\n' "$monitor" + return 0 + fi + monitor="$(get_focused_monitor 2>/dev/null || true)" + if [[ -n "$monitor" ]]; then + printf '%s\n' "$monitor" + return 0 + fi + return 1 +} + +resolve_normal_wallpaper() { + local monitor="$1" + local path="" + local per_monitor_rofi_link="" + local per_monitor_current="" + + if [[ -n "$monitor" ]]; then + per_monitor_rofi_link="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/.current_wallpaper_${monitor}" + per_monitor_current="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/wallpaper_effects/.wallpaper_current_${monitor}" + + path="$(read_wallpaper_from_query "$monitor" 2>/dev/null || true)" + if [[ -z "$path" ]]; then + path="$(resolve_link_or_file "$per_monitor_rofi_link" 2>/dev/null || true)" + fi + if [[ -z "$path" ]]; then + path="$(resolve_link_or_file "$per_monitor_current" 2>/dev/null || true)" + fi + if [[ -z "$path" ]]; then + path="$(read_wallpaper_from_cache "$monitor" 2>/dev/null || true)" + fi + fi + + if [[ -z "$path" ]]; then + path="$(resolve_link_or_file "$wallpaper_current" 2>/dev/null || true)" + fi + if [[ -z "$path" ]]; then + path="$(resolve_link_or_file "$wallpaper_link" 2>/dev/null || true)" + fi + + [[ -n "$path" && -f "$path" ]] || return 1 + printf '%s\n' "$path" +} + +resolve_effects_wallpaper() { + local monitor="$1" + local path="" + local per_monitor_modified="" + + if [[ -n "$monitor" ]]; then + per_monitor_modified="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/wallpaper_effects/.wallpaper_modified_${monitor}" + path="$(resolve_link_or_file "$per_monitor_modified" 2>/dev/null || true)" + fi + + if [[ -z "$path" ]]; then + path="$(resolve_link_or_file "$wallpaper_modified" 2>/dev/null || true)" + fi + if [[ -z "$path" ]]; then + path="$(resolve_normal_wallpaper "$monitor" 2>/dev/null || true)" + fi + + [[ -n "$path" && -f "$path" ]] || return 1 + printf '%s\n' "$path" +} + +resolve_current_sddm_background() { + local sddm_simple="$1" + local candidate="" + for candidate in "$sddm_simple/Backgrounds/default" "$sddm_simple/Backgrounds/default.jpg" "$sddm_simple/Backgrounds/default.png"; do + if [[ -f "$candidate" ]]; then + printf '%s\n' "$candidate" + return 0 + fi + done + return 1 +} + +extract_color() { + local key="$1" + local value + value="$(grep -oP "$key:\\s*\\K#[A-Fa-f0-9]+" "$rofi_wallust" | head -n1)" + printf '%s\n' "$value" +} + +prepare_sddm_wallpaper() { + local selected_file="$1" + local target_monitor="$2" + local prepared_path="$selected_file" + + if [[ ! -f "$selected_file" ]]; then + notify_err "Selected file not found for ${target_monitor:-current context}." + return 1 + fi + + if [[ "$selected_file" =~ \.(mp4|mkv|mov|webm|MP4|MKV|MOV|WEBM)$ ]]; then + if ! command -v ffmpeg >/dev/null 2>&1; then + notify_err "ffmpeg not found; cannot convert selected video wallpaper." + return 1 + fi + mkdir -p "$sddm_video_cache" + local video_name + video_name="$(basename "$selected_file")" + prepared_path="$sddm_video_cache/${video_name}.png" + if ! ffmpeg -v error -y -i "$selected_file" -ss 00:00:01.000 -vframes 1 "$prepared_path"; then + notify_err "Could not generate preview from selected video wallpaper." + return 1 + fi + fi + + printf '%s\n' "$prepared_path" +} + +# Parse arguments +mode="effects" # default +requested_monitor="${SDDM_TARGET_MONITOR:-${HYPRLOCK_TARGET_MONITOR:-}}" +for arg in "$@"; do + case "$arg" in + --normal) + mode="normal" + ;; + --effects) + mode="effects" + ;; + --monitor=*) + requested_monitor="${arg#--monitor=}" + ;; + --*) + ;; + *) + if [[ -z "$requested_monitor" ]]; then + requested_monitor="$arg" + fi + ;; + esac +done + # Resolve SDDM themes directory (standard paths and NixOS path) sddm_themes_dir="/usr/share/sddm/themes" -if [ ! -d "$sddm_themes_dir" ] && [ -d "/run/current-system/sw/share/sddm/themes" ]; then +if [[ ! -d "$sddm_themes_dir" && -d "/run/current-system/sw/share/sddm/themes" ]]; then sddm_themes_dir="/run/current-system/sw/share/sddm/themes" fi sddm_simple="$sddm_themes_dir/simple_sddm_2" +sddm_theme_conf="$sddm_simple/theme.conf" # rofi-wallust-sddm colors path -rofi_wallust="$HOME/.config/rofi/wallust/colors-rofi.rasi" -sddm_theme_conf="$sddm_simple/theme.conf" +rofi_wallust="${XDG_CONFIG_HOME:-$HOME/.config}/rofi/wallust/colors-rofi.rasi" if [[ ! -f "$rofi_wallust" ]]; then - notify-send -i "$iDIR/error.png" "SDDM" "Wallust colors file not found ($rofi_wallust). Aborting." + notify_err "Wallust colors file not found ($rofi_wallust). Aborting." + exit 1 +fi +if [[ ! -d "$sddm_simple/Backgrounds" ]]; then + notify_err "SDDM theme backgrounds not found ($sddm_simple/Backgrounds)." + exit 1 +fi +if [[ ! -f "$sddm_theme_conf" ]]; then + notify_err "SDDM theme config not found ($sddm_theme_conf)." + exit 1 +fi +if [[ ! -d "$wallDIR" ]]; then + notify_err "Wallpaper directory not found ($wallDIR)." + exit 1 +fi +if ! command -v rofi >/dev/null 2>&1; then + notify_err "rofi not found." + exit 1 +fi +if ! command -v "$terminal" >/dev/null 2>&1; then + notify_err "Terminal '$terminal' not found." + exit 1 +fi +if ! command -v sudo >/dev/null 2>&1; then + notify_err "sudo not found." exit 1 fi -# Directory for swaync -iDIR="$HOME/.config/swaync/images" -iDIRi="$HOME/.config/swaync/icons" - -# Parse arguments -mode="effects" # default -if [[ "$1" == "--normal" ]]; then - mode="normal" -elif [[ "$1" == "--effects" ]]; then - mode="effects" +# Abort on NixOS where this repo doesn't manage SDDM and themes are typically read-only +if hostnamectl 2>/dev/null | grep -q 'Operating System: NixOS'; then + notify_err "NixOS detected: skipping SDDM background change." + exit 0 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." + notify_err "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." + notify_err "SDDM is not running. Skipping SDDM wallpaper update." exit 0 fi # Extract colors from rofi wallust config - -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") +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 @@ -79,57 +419,172 @@ for var in color0 color1 color7 color10 color12 color13 foreground; do done if [[ ${#missing_colors[@]} -gt 0 ]]; then - notify-send -i "$iDIR/error.png" "SDDM" "Missing color(s): ${missing_colors[*]}. Run Wallust first." + notify_err "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 +target_monitor="$(resolve_target_monitor "$requested_monitor" 2>/dev/null || true)" +current_monitor_path="" if [[ "$mode" == "normal" ]]; then - wallpaper_path="$wallpaper_current" + current_monitor_path="$(resolve_normal_wallpaper "$target_monitor" 2>/dev/null || true)" else - wallpaper_path="$wallpaper_modified" + current_monitor_path="$(resolve_effects_wallpaper "$target_monitor" 2>/dev/null || true)" fi +current_sddm_path="$(resolve_current_sddm_background "$sddm_simple" 2>/dev/null || true)" -# Abort on NixOS where this repo doesn't manage SDDM and themes are typically read-only -if hostnamectl 2>/dev/null | grep -q 'Operating System: NixOS'; then - notify-send -i "$iDIR/error.png" "SDDM" "NixOS detected: skipping SDDM background change." +current_monitor_label="" +if [[ -n "$current_monitor_path" && -f "$current_monitor_path" ]]; then + if [[ -n "$target_monitor" ]]; then + current_monitor_label="Current monitor ($target_monitor): $(basename "$current_monitor_path")" + else + current_monitor_label="Current monitor wallpaper: $(basename "$current_monitor_path")" + fi +fi + +current_sddm_label="" +if [[ -n "$current_sddm_path" && -f "$current_sddm_path" ]]; then + current_sddm_label="Current SDDM background: $(basename "$current_sddm_path")" +fi + +mapfile -d '' WALLPAPERS < <(find -L "$wallDIR" -type f \( \ + -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" -o -iname "*.gif" -o \ + -iname "*.bmp" -o -iname "*.tiff" -o -iname "*.webp" -o \ + -iname "*.mp4" -o -iname "*.mkv" -o -iname "*.mov" -o -iname "*.webm" \ +\) -print0) + +if [[ ${#WALLPAPERS[@]} -eq 0 ]]; then + notify_err "No wallpapers found in $wallDIR." + exit 1 +fi + +random_wallpaper="${WALLPAPERS[$((RANDOM % ${#WALLPAPERS[@]}))]}" +random_label="Random: $(basename "$random_wallpaper")" + +has_ffmpeg=0 +if command -v ffmpeg >/dev/null 2>&1; then + has_ffmpeg=1 +fi + +menu_message="Select SDDM wallpaper" +if [[ -n "$target_monitor" ]]; then + menu_message="Select SDDM wallpaper for $target_monitor" +fi +rofi_icon_size="$(calculate_rofi_icon_size "$target_monitor")" +rofi_override="element-icon{size:${rofi_icon_size}%;}" + +menu() { + local -a sorted_options=() + local pic_path pic_name cache_preview_image + + mapfile -t sorted_options < <(printf '%s\n' "${WALLPAPERS[@]}" | sort) + + printf "%s\x00icon\x1f%s\n" "$random_label" "$random_wallpaper" + if [[ -n "$current_monitor_label" && -n "$current_monitor_path" ]]; then + printf "%s\x00icon\x1f%s\n" "$current_monitor_label" "$current_monitor_path" + fi + if [[ -n "$current_sddm_label" && -n "$current_sddm_path" ]]; then + printf "%s\x00icon\x1f%s\n" "$current_sddm_label" "$current_sddm_path" + fi + + for pic_path in "${sorted_options[@]}"; do + pic_name="$(basename "$pic_path")" + if [[ "$pic_name" =~ \.(mp4|mkv|mov|webm|MP4|MKV|MOV|WEBM)$ ]]; then + cache_preview_image="$video_preview_cache/${pic_name}.png" + if [[ ! -f "$cache_preview_image" && "$has_ffmpeg" -eq 1 ]]; then + mkdir -p "$video_preview_cache" + ffmpeg -v error -y -i "$pic_path" -ss 00:00:01.000 -vframes 1 "$cache_preview_image" >/dev/null 2>&1 || true + fi + if [[ -f "$cache_preview_image" ]]; then + printf "%s\x00icon\x1f%s\n" "$pic_name" "$cache_preview_image" + else + printf "%s\n" "$pic_name" + fi + else + printf "%s\x00icon\x1f%s\n" "$pic_name" "$pic_path" + fi + done +} + +rofi_cmd=(rofi -i -show -dmenu -mesg "$menu_message" -theme-str "$rofi_override") +if [[ -f "$rofi_theme" ]]; then + rofi_cmd+=(-config "$rofi_theme") +fi + +choice="$(menu | "${rofi_cmd[@]}")" +choice="${choice#"${choice%%[![:space:]]*}"}" +choice="${choice%"${choice##*[![:space:]]}"}" + +if [[ -z "$choice" ]]; then exit 0 fi -# Launch terminal and apply changes -$terminal -e bash -c " -echo 'Enter your password to update SDDM wallpapers and colors'; +selected_file="" +if [[ "$choice" == "$random_label" ]]; then + selected_file="$random_wallpaper" +elif [[ -n "$current_monitor_label" && "$choice" == "$current_monitor_label" ]]; then + selected_file="$current_monitor_path" +elif [[ -n "$current_sddm_label" && "$choice" == "$current_sddm_label" ]]; then + selected_file="$current_sddm_path" +elif [[ -f "$choice" ]]; then + selected_file="$choice" +else + choice_basename="$(basename "$choice" | sed 's/\(.*\)\.[^.]*$/\1/')" + selected_file="$(find -L "$wallDIR" -type f -iname "$choice_basename.*" -print -quit)" +fi -# Update the colors in the SDDM config -sudo sed -i \"s/HeaderTextColor=\\\"#.*\\\"/HeaderTextColor=\\\"$color13\\\"/\" \"$sddm_theme_conf\" -sudo sed -i \"s/DateTextColor=\\\"#.*\\\"/DateTextColor=\\\"$color13\\\"/\" \"$sddm_theme_conf\" -sudo sed -i \"s/TimeTextColor=\\\"#.*\\\"/TimeTextColor=\\\"$color13\\\"/\" \"$sddm_theme_conf\" -sudo sed -i \"s/DropdownSelectedBackgroundColor=\\\"#.*\\\"/DropdownSelectedBackgroundColor=\\\"$color13\\\"/\" \"$sddm_theme_conf\" -sudo sed -i \"s/SystemButtonsIconsColor=\\\"#.*\\\"/SystemButtonsIconsColor=\\\"$color13\\\"/\" \"$sddm_theme_conf\" -sudo sed -i \"s/SessionButtonTextColor=\\\"#.*\\\"/SessionButtonTextColor=\\\"$color13\\\"/\" \"$sddm_theme_conf\" -sudo sed -i \"s/VirtualKeyboardButtonTextColor=\\\"#.*\\\"/VirtualKeyboardButtonTextColor=\\\"$color13\\\"/\" \"$sddm_theme_conf\" -sudo sed -i \"s/HighlightBackgroundColor=\\\"#.*\\\"/HighlightBackgroundColor=\\\"$color12\\\"/\" \"$sddm_theme_conf\" -sudo sed -i \"s/LoginFieldTextColor=\\\"#.*\\\"/LoginFieldTextColor=\\\"$color12\\\"/\" \"$sddm_theme_conf\" -sudo sed -i \"s/PasswordFieldTextColor=\\\"#.*\\\"/PasswordFieldTextColor=\\\"$color12\\\"/\" \"$sddm_theme_conf\" +if [[ -z "$selected_file" || ! -f "$selected_file" ]]; then + notify_err "Selected wallpaper not found: $choice" + exit 1 +fi -sudo sed -i \"s/DropdownBackgroundColor=\\\"#.*\\\"/DropdownBackgroundColor=\\\"$color1\\\"/\" \"$sddm_theme_conf\" -sudo sed -i \"s/HighlightTextColor=\\\"#.*\\\"/HighlightTextColor=\\\"$color10\\\"/\" \"$sddm_theme_conf\" +wallpaper_path="$(prepare_sddm_wallpaper "$selected_file" "$target_monitor" 2>/dev/null || true)" +if [[ -z "$wallpaper_path" || ! -f "$wallpaper_path" ]]; then + notify_err "Could not prepare selected wallpaper for SDDM." + exit 1 +fi + +# Launch terminal and apply changes +if ! "$terminal" -e bash -c ' +set -e +theme_conf="$1" +wallpaper_path="$2" +sddm_simple="$3" +color13="$4" +color12="$5" +color1="$6" +color10="$7" +color7="$8" -sudo sed -i \"s/PlaceholderTextColor=\\\"#.*\\\"/PlaceholderTextColor=\\\"$color7\\\"/\" \"$sddm_theme_conf\" -sudo sed -i \"s/UserIconColor=\\\"#.*\\\"/UserIconColor=\\\"$color7\\\"/\" \"$sddm_theme_conf\" -sudo sed -i \"s/PasswordIconColor=\\\"#.*\\\"/PasswordIconColor=\\\"$color7\\\"/\" \"$sddm_theme_conf\" +echo "Enter your password to update SDDM wallpapers and colors" + +# Update the colors in the SDDM config +sudo sed -i "s/HeaderTextColor=\"#.*\"/HeaderTextColor=\"$color13\"/" "$theme_conf" +sudo sed -i "s/DateTextColor=\"#.*\"/DateTextColor=\"$color13\"/" "$theme_conf" +sudo sed -i "s/TimeTextColor=\"#.*\"/TimeTextColor=\"$color13\"/" "$theme_conf" +sudo sed -i "s/DropdownSelectedBackgroundColor=\"#.*\"/DropdownSelectedBackgroundColor=\"$color13\"/" "$theme_conf" +sudo sed -i "s/SystemButtonsIconsColor=\"#.*\"/SystemButtonsIconsColor=\"$color13\"/" "$theme_conf" +sudo sed -i "s/SessionButtonTextColor=\"#.*\"/SessionButtonTextColor=\"$color13\"/" "$theme_conf" +sudo sed -i "s/VirtualKeyboardButtonTextColor=\"#.*\"/VirtualKeyboardButtonTextColor=\"$color13\"/" "$theme_conf" +sudo sed -i "s/HighlightBackgroundColor=\"#.*\"/HighlightBackgroundColor=\"$color12\"/" "$theme_conf" +sudo sed -i "s/LoginFieldTextColor=\"#.*\"/LoginFieldTextColor=\"$color12\"/" "$theme_conf" +sudo sed -i "s/PasswordFieldTextColor=\"#.*\"/PasswordFieldTextColor=\"$color12\"/" "$theme_conf" +sudo sed -i "s/DropdownBackgroundColor=\"#.*\"/DropdownBackgroundColor=\"$color1\"/" "$theme_conf" +sudo sed -i "s/HighlightTextColor=\"#.*\"/HighlightTextColor=\"$color10\"/" "$theme_conf" +sudo sed -i "s/PlaceholderTextColor=\"#.*\"/PlaceholderTextColor=\"$color7\"/" "$theme_conf" +sudo sed -i "s/UserIconColor=\"#.*\"/UserIconColor=\"$color7\"/" "$theme_conf" +sudo sed -i "s/PasswordIconColor=\"#.*\"/PasswordIconColor=\"$color7\"/" "$theme_conf" # Copy wallpaper to SDDM theme -# Primary: set Backgrounds/default (no extension) for simple_sddm_2 -sudo cp -f \"$wallpaper_path\" \"$sddm_simple/Backgrounds/default\" || true -# Fallbacks: if theme ships default.jpg or default.png, update those too -if [ -e \"$sddm_simple/Backgrounds/default.jpg\" ]; then - sudo cp -f \"$wallpaper_path\" \"$sddm_simple/Backgrounds/default.jpg\" +sudo cp -f "$wallpaper_path" "$sddm_simple/Backgrounds/default" +if [ -e "$sddm_simple/Backgrounds/default.jpg" ]; then + sudo cp -f "$wallpaper_path" "$sddm_simple/Backgrounds/default.jpg" fi -if [ -e \"$sddm_simple/Backgrounds/default.png\" ]; then - sudo cp -f \"$wallpaper_path\" \"$sddm_simple/Backgrounds/default.png\" +if [ -e "$sddm_simple/Backgrounds/default.png" ]; then + sudo cp -f "$wallpaper_path" "$sddm_simple/Backgrounds/default.png" +fi +' _ "$sddm_theme_conf" "$wallpaper_path" "$sddm_simple" "$color13" "$color12" "$color1" "$color10" "$color7"; then + notify_err "Failed to update SDDM for ${target_monitor:-current context}: $(basename "$wallpaper_path")." + exit 1 fi -notify-send -i \"$iDIR/ja.png\" \"SDDM\" \"Background SET\" -"
\ No newline at end of file +notify_ok "Set for ${target_monitor:-current context}: $(basename "$wallpaper_path")." diff --git a/config/hypr/scripts/set-default-thunar-terminal.sh b/config/hypr/scripts/set-default-thunar-terminal.sh index fd50eb6c..cf5107cf 100755 --- a/config/hypr/scripts/set-default-thunar-terminal.sh +++ b/config/hypr/scripts/set-default-thunar-terminal.sh @@ -11,7 +11,7 @@ setup_default_terminal() { # 1. Configure XFCE/Exo (Thunar's primary helper) # This handles "Open Terminal Here" and "Open with [CLI App]" - HELPER_DIR="$HOME/.config/xfce4" + HELPER_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/xfce4" mkdir -p "$HELPER_DIR" KITTY_PATH="$(command -v kitty 2>/dev/null || true)" if [ -z "$KITTY_PATH" ]; then diff --git a/config/hypr/scripts/update_WindowRules.sh b/config/hypr/scripts/update_WindowRules.sh index 293b14e9..d9cb08e4 100755 --- a/config/hypr/scripts/update_WindowRules.sh +++ b/config/hypr/scripts/update_WindowRules.sh @@ -7,7 +7,7 @@ # ================================================== # Script to update WindowRules config if Hyprland version is >= 0.53 -CONFIGS_DIR="$HOME/.config/hypr/configs" +CONFIGS_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/configs" TARGET_FILE="$CONFIGS_DIR/WindowRules.conf" get_hyprland_version() { |
