diff options
Diffstat (limited to 'config/hypr/scripts')
| -rwxr-xr-x | config/hypr/scripts/Kitty_themes.sh | 61 | ||||
| -rwxr-xr-x | config/hypr/scripts/Kool_Quick_Settings.sh | 2 | ||||
| -rwxr-xr-x | config/hypr/scripts/PortalHyprlandUbuntu2604.sh | 15 | ||||
| -rwxr-xr-x | config/hypr/scripts/Refresh.sh | 3 | ||||
| -rwxr-xr-x | config/hypr/scripts/Tak0-Per-Window-Switch.sh | 21 | ||||
| -rwxr-xr-x | config/hypr/scripts/Toggle-Active-Window-Audio.sh | 147 | ||||
| -rwxr-xr-x | config/hypr/scripts/Toggle-weather-waybar-units.sh | 33 | ||||
| -rwxr-xr-x | config/hypr/scripts/WallustSwww.sh | 31 | ||||
| -rwxr-xr-x | config/hypr/scripts/WaybarCava.sh | 12 | ||||
| l--------- | config/hypr/scripts/dots-tui | 1 | ||||
| -rwxr-xr-x | config/hypr/scripts/dots-tui-ubuntu-2404 | bin | 0 -> 17736736 bytes | |||
| -rwxr-xr-x | config/hypr/scripts/hyprshot.sh | 317 | ||||
| -rwxr-xr-x | config/hypr/scripts/install-uv.sh | 2 |
13 files changed, 615 insertions, 30 deletions
diff --git a/config/hypr/scripts/Kitty_themes.sh b/config/hypr/scripts/Kitty_themes.sh index 585bc7fc..8bc6e0f0 100755 --- a/config/hypr/scripts/Kitty_themes.sh +++ b/config/hypr/scripts/Kitty_themes.sh @@ -16,14 +16,20 @@ notify_user() { # Function to apply the selected kitty theme apply_kitty_theme_to_config() { local theme_name_to_apply="$1" + local apply_mode="${2:-preview}" if [ -z "$theme_name_to_apply" ]; then echo "Error: No theme name provided to apply_kitty_theme_to_config." >&2 return 1 fi + local theme_file_path_to_apply + if [ "$theme_name_to_apply" = "Set by wallpaper" ]; then + theme_file_path_to_apply="$kitty_themes_DiR/00-Default.conf" + else + theme_file_path_to_apply="$kitty_themes_DiR/$theme_name_to_apply.conf" + fi - local theme_file_path_to_apply="$kitty_themes_DiR/$theme_name_to_apply.conf" if [ ! -f "$theme_file_path_to_apply" ]; then - notify_user "$iDIR/error.png" "Error" "Theme file not found: $theme_name_to_apply.conf" + notify_user "$iDIR/error.png" "Error" "Theme file not found: $(basename "$theme_file_path_to_apply")" return 1 fi @@ -31,23 +37,31 @@ apply_kitty_theme_to_config() { temp_kitty_config_file=$(mktemp) cp "$kitty_config" "$temp_kitty_config_file" + local include_target + include_target="include ./kitty-themes/$(basename "$theme_file_path_to_apply")" + if grep -q -E '^[#[:space:]]*include\s+\./kitty-themes/.*\.conf' "$temp_kitty_config_file"; then - sed -i -E "s|^([#[:space:]]*include\s+\./kitty-themes/).*\.conf|include ./kitty-themes/$theme_name_to_apply.conf|g" "$temp_kitty_config_file" + sed -i -E "s|^([#[:space:]]*include\s+\./kitty-themes/).*\.conf|$include_target|g" "$temp_kitty_config_file" else if [ -s "$temp_kitty_config_file" ] && [ "$(tail -c1 "$temp_kitty_config_file")" != "" ]; then echo >>"$temp_kitty_config_file" fi - echo "include ./kitty-themes/$theme_name_to_apply.conf" >>"$temp_kitty_config_file" + echo "$include_target" >>"$temp_kitty_config_file" fi cp "$temp_kitty_config_file" "$kitty_config" rm "$temp_kitty_config_file" - - for pid_kitty in $(pidof kitty); do - if [ -n "$pid_kitty" ]; then - kill -SIGUSR1 "$pid_kitty" + if pidof kitty >/dev/null 2>&1; then + if [ "$apply_mode" = "apply" ] && command -v kitty >/dev/null 2>&1; then + kitty @ load-config >/dev/null 2>&1 + kitty @ set-colors --all --configured "$theme_file_path_to_apply" >/dev/null 2>&1 fi - done + for pid_kitty in $(pidof kitty); do + if [ -n "$pid_kitty" ]; then + kill -SIGUSR1 "$pid_kitty" + fi + done + fi return 0 } @@ -65,7 +79,8 @@ fi original_kitty_config_content_backup=$(cat "$kitty_config") -mapfile -t available_theme_names < <(find "$kitty_themes_DiR" -maxdepth 1 -name "*.conf" -type f -printf "%f\n" | sed 's/\.conf$//' | sort) +mapfile -t available_theme_names < <(find "$kitty_themes_DiR" -maxdepth 1 -name "*.conf" -type f -printf "%f\n" | sed 's/\.conf$//' | grep -v -E '^(00-Default|01-Wallust)$' | sort) +available_theme_names=("Set by wallpaper" "${available_theme_names[@]}") if [ ${#available_theme_names[@]} -eq 0 ]; then notify_user "$iDIR/error.png" "No Kitty Themes" "No .conf files found in $kitty_themes_DiR." @@ -73,7 +88,10 @@ if [ ${#available_theme_names[@]} -eq 0 ]; then fi current_selection_index=0 -current_active_theme_name=$(awk -F'include ./kitty-themes/|\\.conf' '/^[[:space:]]*include \.\/kitty-themes\/.*\.conf/{print $2; exit}' "$kitty_config") +current_active_theme_name=$(awk -F'include ./kitty-themes/|\\.conf' '/^[[:space:]]*include \\.\/kitty-themes\/.*\\.conf/{print $2; exit}' "$kitty_config") +if [ "$current_active_theme_name" = "00-Default" ]; then + current_active_theme_name="Set by wallpaper" +fi if [ -n "$current_active_theme_name" ]; then for i in "${!available_theme_names[@]}"; do @@ -85,14 +103,6 @@ if [ -n "$current_active_theme_name" ]; then fi while true; do - theme_to_preview_now="${available_theme_names[$current_selection_index]}" - - if ! apply_kitty_theme_to_config "$theme_to_preview_now"; then - echo "$original_kitty_config_content_backup" >"$kitty_config" - for pid_kitty in $(pidof kitty); do if [ -n "$pid_kitty" ]; then kill -SIGUSR1 "$pid_kitty"; fi; done - notify_user "$iDIR/error.png" "Preview Error" "Failed to apply $theme_to_preview_now. Reverted." - exit 1 - fi rofi_input_list="" for theme_name_in_list in "${available_theme_names[@]}"; do @@ -104,16 +114,24 @@ while true; do rofi -dmenu -i \ -format 'i' \ -p "Kitty Theme" \ - -mesg "Preview: ${theme_to_preview_now} | Enter: Preview | Ctrl+S: Apply & Exit | Esc: Cancel" \ + -mesg "Enter: Preview | Ctrl+S: Apply & Exit | Esc: Cancel" \ -config "$rofi_theme_for_this_script" \ -selected-row "$current_selection_index" \ - -kb-custom-1 "Control+s") # MODIFIED HERE: Changed to Control+s for custom action 1 + -kb-custom-1 "Control+s") rofi_exit_code=$? if [ $rofi_exit_code -eq 0 ]; then if [[ "$chosen_index_from_rofi" =~ ^[0-9]+$ ]] && [ "$chosen_index_from_rofi" -lt "${#available_theme_names[@]}" ]; then current_selection_index="$chosen_index_from_rofi" + theme_to_preview_now="${available_theme_names[$current_selection_index]}" + if ! apply_kitty_theme_to_config "$theme_to_preview_now" "preview"; then + echo "$original_kitty_config_content_backup" >"$kitty_config" + for pid_kitty in $(pidof kitty); do if [ -n "$pid_kitty" ]; then kill -SIGUSR1 "$pid_kitty"; fi; done + notify_user "$iDIR/error.png" "Preview Error" "Failed to apply $theme_to_preview_now. Reverted." + exit 1 + fi + continue else : fi @@ -123,6 +141,7 @@ while true; do for pid_kitty in $(pidof kitty); do if [ -n "$pid_kitty" ]; then kill -SIGUSR1 "$pid_kitty"; fi; done break elif [ $rofi_exit_code -eq 10 ]; then # This is the exit code for -kb-custom-1 + apply_kitty_theme_to_config "$theme_to_preview_now" "apply" notify_user "$iDIR/ja.png" "Kitty Theme Applied" "$theme_to_preview_now" break else diff --git a/config/hypr/scripts/Kool_Quick_Settings.sh b/config/hypr/scripts/Kool_Quick_Settings.sh index 2e4004c5..5081fe72 100755 --- a/config/hypr/scripts/Kool_Quick_Settings.sh +++ b/config/hypr/scripts/Kool_Quick_Settings.sh @@ -202,6 +202,7 @@ Choose Hyprland Animations Choose Monitor Profiles Choose Rofi Themes Search for Keybinds +Toggle Waybar Weather units (C/F) Toggle Game Mode Switch Dark-Light Theme Rainbow Borders Mode @@ -263,6 +264,7 @@ main() { "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 Game Mode") $scriptsDir/GameMode.sh ;; "Switch Dark-Light Theme") $scriptsDir/DarkLight.sh ;; "Rainbow Borders Mode") rainbow_borders_menu ;; diff --git a/config/hypr/scripts/PortalHyprlandUbuntu2604.sh b/config/hypr/scripts/PortalHyprlandUbuntu2604.sh new file mode 100755 index 00000000..5cb3c01b --- /dev/null +++ b/config/hypr/scripts/PortalHyprlandUbuntu2604.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +# /* ---- 💫 https://github.com/LinuxBeginnings 💫 ---- */ ## +# Ubuntu 26.04 workaround: start portals manually before waybar. + +set -euo pipefail + +if [[ -r /etc/os-release ]]; then + # shellcheck disable=SC1091 + . /etc/os-release + if [[ "${ID:-}" == "ubuntu" && "${VERSION_ID:-}" == "26.04" ]]; then + if [[ -x "$HOME/.config/hypr/scripts/PortalHyprland.sh" ]]; then + "$HOME/.config/hypr/scripts/PortalHyprland.sh" + fi + fi +fi diff --git a/config/hypr/scripts/Refresh.sh b/config/hypr/scripts/Refresh.sh index 10901dbb..95248b35 100755 --- a/config/hypr/scripts/Refresh.sh +++ b/config/hypr/scripts/Refresh.sh @@ -22,6 +22,9 @@ for _prs in "${_ps[@]}"; do fi done +# Clean up any Waybar-spawned cava instances (unique temp conf names) +pkill -f 'waybar-cava\..*\.conf' 2>/dev/null || true + # added since wallust sometimes not applying killall -SIGUSR2 waybar # Added sleep for GameMode causing multiple waybar diff --git a/config/hypr/scripts/Tak0-Per-Window-Switch.sh b/config/hypr/scripts/Tak0-Per-Window-Switch.sh index 6cd0c564..3ba2c7af 100755 --- a/config/hypr/scripts/Tak0-Per-Window-Switch.sh +++ b/config/hypr/scripts/Tak0-Per-Window-Switch.sh @@ -1,5 +1,5 @@ ################################################################## -# # +# # # # # TAK_0'S Per-Window-Switch # # # @@ -7,13 +7,14 @@ # # # Just a little script that I made to switch keyboard layouts # # per-window instead of global switching for the more # -# smooth and comfortable workflow. # +# smooth and comfortable workflow. # # # ################################################################## # This is for changing kb_layouts. Set kb_layouts in MAP_FILE="$HOME/.cache/kb_layout_per_window" -CFG_FILE="$HOME/.config/hypr/configs/SystemSettings.conf" +USER_CFG="$HOME/.config/hypr/UserConfigs/UserSettings.conf" +SYS_CFG="$HOME/.config/hypr/configs/SystemSettings.conf" ICON="$HOME/.config/swaync/images/ja.png" SCRIPT_NAME="$(basename "$0")" @@ -21,13 +22,16 @@ SCRIPT_NAME="$(basename "$0")" touch "$MAP_FILE" # Read layouts from config -if ! grep -q 'kb_layout' "$CFG_FILE"; then - echo "Error: cannot find kb_layout in $CFG_FILE" >&2 +if grep -q 'kb_layout' "$USER_CFG" 2>/dev/null; then + CFG_FILE="$USER_CFG" +elif grep -q 'kb_layout' "$SYS_CFG" 2>/dev/null; then + CFG_FILE="$SYS_CFG" +else + echo "Error: cannot find kb_layout in UserSettings.conf nor SystemSettings.conf" >&2 exit 1 fi kb_layouts=($(grep 'kb_layout' "$CFG_FILE" | cut -d '=' -f2 | tr -d '[:space:]' | tr ',' ' ')) count=${#kb_layouts[@]} - # Get current active window ID get_win() { hyprctl activewindow -j | jq -r '.address // .id' @@ -96,7 +100,10 @@ cmd_restore() { # Listen to focus events and restore window-specific layouts subscribe() { local SOCKET2="$XDG_RUNTIME_DIR/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock" - [[ -S "$SOCKET2" ]] || { echo "Error: Hyprland socket not found." >&2; exit 1; } + [[ -S "$SOCKET2" ]] || { + echo "Error: Hyprland socket not found." >&2 + exit 1 + } socat -u UNIX-CONNECT:"$SOCKET2" - | while read -r line; do [[ "$line" =~ ^activewindow ]] && cmd_restore diff --git a/config/hypr/scripts/Toggle-Active-Window-Audio.sh b/config/hypr/scripts/Toggle-Active-Window-Audio.sh new file mode 100755 index 00000000..4d9bcd33 --- /dev/null +++ b/config/hypr/scripts/Toggle-Active-Window-Audio.sh @@ -0,0 +1,147 @@ +#!/usr/bin/env bash +set -euo pipefail + +XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" +swayIconDir="${XDG_CONFIG_HOME}/swaync/icons" + +#// Credits to sl1ng for the orginal script. Rewritten by Vyle. +ctlcheck=("pactl" "jq" "notify-send" "awk" "pgrep" "hyprctl" "iconv") +missing=() + +for ctl in "${ctlcheck[@]}"; do + command -v "${ctl}" >/dev/null || missing+=("${ctl}") +done + +if (( ${#missing[@]} )) 2>/dev/null; then + if printf '%s\n' "${missing[@]}" | grep -qx "pactl"; then + notify-send -a "t1" -r 91190 -t 2000 -i "${swayIconDir}/volume-low.png" "ERROR: pactl not installed" "Install 'pactl' (pulseaudio-utils or pipewire-pulse)." + fi + echo "Missing required dependencies: \"${missing[*]}\"" + exit 1 +fi + +#// Parse .pid, .class, .title to __pid, __class, __title. +active_json="$(hyprctl -j activewindow 2>/dev/null || { echo -e "Did hyprctl fail to run? [EXIT-CODE:-1]"; exit 1; } )" +PID="$(jq -r '"\(.pid)\t\(.class)\t\(.title)"' <<< "${active_json}" || { echo -e "Did jq fail to run? [EXIT-CODE:-1]"; exit 1; } )" + +IFS=$'\t' read -r __pid __class __title <<< "${PID}" + +[[ -z "${__pid}" ]] && { echo -e "Could not resolve PID for focused window."; exit 1; } +sink_json="$(pactl -f json list sink-inputs 2>/dev/null | iconv -f utf-8 -t utf-8 -c || { echo -e "Did pactl or iconv fail to run? Required manual intervention."; exit 1; } )" +#// Collect all descendant PIDs for the active window (Chrome/Wayland audio often runs in child processes). +declare -A seen_pids=() +queue=("${__pid}") +all_pids=() +while ((${#queue[@]})); do + pid="${queue[0]}" + queue=("${queue[@]:1}") + [[ -n "${seen_pids[$pid]:-}" ]] && continue + seen_pids["$pid"]=1 + all_pids+=("$pid") + mapfile -t children < <(pgrep -P "$pid" || true) + for child in "${children[@]}"; do + [[ -n "${seen_pids[$child]:-}" ]] || queue+=("$child") + done +done +pidsJson="$(printf '%s\n' "${all_pids[@]}" | jq -s 'map(tonumber)')" + +#// Check if any descendant PID matches application.process.id or else verify other statements. +mapfile -t sink_ids < <(jq -r --argjson pids "${pidsJson}" --arg class "${__class}" --arg title "${__title}" ' +.[] | + def lc(x): (x // "" | ascii_downcase); + def normalize(x): x | gsub("[-_~.]+";" ") ; + select( + (.properties["application.process.id"] | tostring | tonumber? as $p | $p != null and ($pids | index($p))) + or + (lc(.properties["application.name"]) | contains(lc($class))) + or + (lc(.properties["application.id"]) | contains(lc($class))) + or + (lc(.properties["application.process.binary"]) | contains(lc($class))) + or + (normalize(lc(.properties["media.name"])) | contains(normalize(lc($title)))) + ) | .index' <<< "${sink_json}" +) + +if [[ "${#sink_ids[@]}" -eq 0 ]]; then + mapfile -t fallback_pids < <(pgrep -x "${__class}" || true) + if [[ "${#fallback_pids[@]}" -gt 0 ]]; then + declare -A seen_fallback=() + queue=("${fallback_pids[@]}") + all_fallback=() + while ((${#queue[@]})); do + pid="${queue[0]}" + queue=("${queue[@]:1}") + [[ -n "${seen_fallback[$pid]:-}" ]] && continue + seen_fallback["$pid"]=1 + all_fallback+=("$pid") + mapfile -t children < <(pgrep -P "$pid" || true) + for child in "${children[@]}"; do + [[ -n "${seen_fallback[$child]:-}" ]] || queue+=("$child") + done + done + fallbackJson="$(printf '%s\n' "${all_fallback[@]}" | jq -s 'map(tonumber)')" + mapfile -t sink_ids < <( jq -r --argjson pids "${fallbackJson}" '.[] | + select((.properties["application.process.id"] | tostring | tonumber? as $p | $p != null and ($pids | index($p)))) | .index' <<< "${sink_json}" ) + fi +fi + +#// Auto-Detect if the environment is on Hyprland or $HYPRLAND_INSTANCE_SIGNATURE. +if [[ ${#sink_ids[@]} -eq 0 ]]; then + if [[ -n "${HYPRLAND_INSTANCE_SIGNATURE}" ]]; then + # Even if the fallback_pid remains empty, we will dispatch exit code based on $HYPRLAND_INSTANCE_SIGNATURE. + notify-send -a "t1" -r 91190 -t 1200 -i "${swayIconDir}/volume-low.png" "No sink input for the active_window: ${__class}" + echo "No sink input for focused window: ${__class}" + exit 1 + else + echo "No sink input for focused active_window ${__class}" + exit 1 + fi +fi + +idsJson=$(printf '%s\n' "${sink_ids[@]}" | jq -s 'map(tonumber)') + +#// Get the available option from pactl. +want_mute=$(jq -r --argjson ids "$idsJson" ' + [ .[] | select(.index as $i | $ids | index($i)) | .mute ] as $m | + if all($m[]; . == true) then "no" + else "yes" + end' <<< "${sink_json}" +) + +if [[ "${want_mute}" == "no" ]]; then + state_msg="Unmuted" + swayIcon="${swayIconDir}/volume-high.png" +else + state_msg="Muted" + swayIcon="${swayIconDir}/volume-mute.png" +fi + +[[ -f "${swayIcon}" ]] || echo -e "Missing swaync icons." + +changed=0 +failed_ids=() +for id in "${sink_ids[@]}"; do + if pactl set-sink-input-mute "$id" "$want_mute"; then + changed=1 + else + failed_ids+=("$id") + fi +done + +if [[ "$changed" -eq 0 ]]; then + notify-send -a "t2" -r 91190 -t 1200 -i "${swayIconDir}/volume-low.png" "Failed to change sink input(s)" "${failed_ids[*]:-unknown}" + exit 1 +fi + +#// Append pamixer to get a nice result. Pamixer is complete optional here. +if command -v pamixer >/dev/null; then + sink_name="$(pamixer --get-default-sink 2>/dev/null | awk -F '"' 'END{print $(NF - 1)}' 2>/dev/null || true)" + if [[ -n "${sink_name}" ]]; then + notify-send -a "t2" -r 91190 -t 800 -i "${swayIcon}" "${state_msg} ${__class}" "${sink_name}" + else + notify-send -a "t2" -r 91190 -t 800 -i "${swayIcon}" "${state_msg} ${__class}" + fi +else + notify-send -a "t2" -r 91190 -t 800 -i "${swayIcon}" "${state_msg} ${__class}" +fi diff --git a/config/hypr/scripts/Toggle-weather-waybar-units.sh b/config/hypr/scripts/Toggle-weather-waybar-units.sh new file mode 100755 index 00000000..4007536c --- /dev/null +++ b/config/hypr/scripts/Toggle-weather-waybar-units.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +# Toggle waybar-weather units between metric and imperial + +CONFIG_FILE="$HOME/.config/waybar-weather/config.toml" + +if [ ! -f "$CONFIG_FILE" ]; then + notify-send "Weather units" "Config not found: $CONFIG_FILE" + exit 1 +fi + +# Determine current units (default to metric when unset/commented) +current_units="metric" +if grep -qE '^[[:space:]]*units[[:space:]]*=' "$CONFIG_FILE"; then + current_units=$(sed -nE 's/^[[:space:]]*units[[:space:]]*=[[:space:]]*"([^"]+)".*/\1/p' "$CONFIG_FILE" | head -n1) +fi + +if [ "$current_units" = "imperial" ]; then + new_units="metric" +else + new_units="imperial" +fi + +# Update config: prefer replacing existing units line, otherwise uncomment default, else append +if grep -qE '^[[:space:]]*units[[:space:]]*=' "$CONFIG_FILE"; then + sed -i 's/^[[:space:]]*units[[:space:]]*=.*/units = "'"$new_units"'"/' "$CONFIG_FILE" +elif grep -qE '^[[:space:]]*#\s*units[[:space:]]*=' "$CONFIG_FILE"; then + sed -i 's/^[[:space:]]*#\s*units[[:space:]]*=.*/units = "'"$new_units"'"/' "$CONFIG_FILE" +else + printf '\nunits = "%s"\n' "$new_units" >> "$CONFIG_FILE" +fi + +pkill waybar-weather 2>/dev/null || true +notify-send "Weather units now ${new_units}" "Click on waybar-weather to update units" diff --git a/config/hypr/scripts/WallustSwww.sh b/config/hypr/scripts/WallustSwww.sh index 4d1fdd25..1f0f50c7 100755 --- a/config/hypr/scripts/WallustSwww.sh +++ b/config/hypr/scripts/WallustSwww.sh @@ -114,6 +114,37 @@ wallust_targets=( ) wait_for_templates "$start_ts" "${wallust_targets[@]}" || true +# Run kitty-only wallust config to keep terminal palette separate +run_wallust_with_config() { + local cfg="$1" + if wallust run --help 2>&1 | grep -q -E '(^|[[:space:]])-c([,[:space:]]|$)|--config'; then + wallust run -s -c "$cfg" "$wallpaper_path" || true + else + WALLUST_CONFIG="$cfg" wallust run -s "$wallpaper_path" || true + fi +} + +kitty_cfg="$HOME/.config/wallust/wallust-kitty.toml" +if [ -f "$kitty_cfg" ]; then + kitty_ts=$(date +%s) + run_wallust_with_config "$kitty_cfg" + wait_for_templates "$kitty_ts" "$HOME/.config/kitty/kitty-themes/01-Wallust.conf" || true +fi + +# Reload kitty colors when wallpaper-based theme is active +kitty_wallust_theme="$HOME/.config/kitty/kitty-themes/01-Wallust.conf" +if [ -s "$kitty_wallust_theme" ]; then + if command -v kitty >/dev/null 2>&1; then + kitty @ load-config >/dev/null 2>&1 || true + kitty @ set-colors --all --configured "$kitty_wallust_theme" >/dev/null 2>&1 || true + fi + if pidof kitty >/dev/null 2>&1; then + for pid in $(pidof kitty); do + kill -SIGUSR1 "$pid" 2>/dev/null || true + done + 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 diff --git a/config/hypr/scripts/WaybarCava.sh b/config/hypr/scripts/WaybarCava.sh index 3305bb67..98db60dd 100755 --- a/config/hypr/scripts/WaybarCava.sh +++ b/config/hypr/scripts/WaybarCava.sh @@ -10,6 +10,9 @@ if ! command -v cava >/dev/null 2>&1; then exit 1 fi +# Proactively reap any stale Waybar-spawned cava (unique temp conf names) +pkill -f 'waybar-cava\..*\.conf' 2>/dev/null || true + # 0..7 → ▁▂▃▄▅▆▇█ bar="▁▂▃▄▅▆▇█" dict="s/;//g" @@ -32,7 +35,11 @@ printf '%d' $$ >"$pidfile" # Unique temp config + cleanup on exit config_file="$(mktemp "$RUNTIME_DIR/waybar-cava.XXXXXX.conf")" -cleanup() { rm -f "$config_file" "$pidfile"; } +cleanup() { + # Kill children (cava, sed) of this script, then remove files + pkill -P "$$" 2>/dev/null || true + rm -f "$config_file" "$pidfile" +} trap cleanup EXIT INT TERM cat >"$config_file" <<EOF @@ -52,4 +59,5 @@ ascii_max_range = 7 EOF # Stream cava output and translate digits 0..7 to bar glyphs -exec cava -p "$config_file" | sed -u "$dict" +# (no exec: keep this shell as the parent so the trap can reap children) +cava -p "$config_file" | sed -u "$dict" diff --git a/config/hypr/scripts/dots-tui b/config/hypr/scripts/dots-tui new file mode 120000 index 00000000..007282b4 --- /dev/null +++ b/config/hypr/scripts/dots-tui @@ -0,0 +1 @@ +dots-tui-ubuntu-2404
\ No newline at end of file diff --git a/config/hypr/scripts/dots-tui-ubuntu-2404 b/config/hypr/scripts/dots-tui-ubuntu-2404 Binary files differnew file mode 100755 index 00000000..9aad6ecf --- /dev/null +++ b/config/hypr/scripts/dots-tui-ubuntu-2404 diff --git a/config/hypr/scripts/hyprshot.sh b/config/hypr/scripts/hyprshot.sh new file mode 100755 index 00000000..0fb976fa --- /dev/null +++ b/config/hypr/scripts/hyprshot.sh @@ -0,0 +1,317 @@ +#!/usr/bin/env bash + +set -e + +function Help() { + cat <<EOF +Usage: hyprshot [options ..] [-m [mode] ..] -- [command] + +Hyprshot is an utility to easily take screenshot in Hyprland using your mouse. + +It allows taking screenshots of windows, regions and monitors which are saved to a folder of your choosing and copied to your clipboard. + +Examples: + capture a window \`hyprshot -m window\` + capture active window to clipboard \`hyprshot -m window -m active --clipboard-only\` + capture selected monitor \`hyprshot -m output -m DP-1\` + +Options: + -h, --help show help message + -m, --mode one of: output, window, region, active, OUTPUT_NAME + -o, --output-folder directory in which to save screenshot + -f, --filename the file name of the resulting screenshot + -D, --delay how long to delay taking the screenshot after selection (seconds) + -z, --freeze freeze the screen on initialization + -d, --debug print debug information + -s, --silent don't send notification when screenshot is saved + -r, --raw output raw image data to stdout + -t, --notif-timeout notification timeout in milliseconds (default 5000) + --clipboard-only copy screenshot to clipboard and don't save image in disk + -- [command] open screenshot with a command of your choosing. e.g. hyprshot -m window -- mirage + +Modes: + output take screenshot of an entire monitor + window take screenshot of an open window + region take screenshot of selected region + active take screenshot of active window|output + (you must use --mode again with the intended selection) + OUTPUT_NAME take screenshot of output with OUTPUT_NAME + (you must use --mode again with the intended selection) + (you can get this from \`hyprctl monitors\`) +EOF +} + +function Print() { + if [ $DEBUG -eq 0 ]; then + return 0 + fi + + 1>&2 printf "$@" +} + +function send_notification() { + if [ $SILENT -eq 1 ]; then + return 0 + fi + + local message=$([ $CLIPBOARD -eq 1 ] && \ + echo "Image copied to the clipboard" || \ + echo "Image saved in <i>${1}</i> and copied to the clipboard.") + notify-send "Screenshot saved" \ + "${message}" \ + -t "$NOTIF_TIMEOUT" -i "${1}" -a Hyprshot +} + +function trim() { + Print "Geometry: %s\n" "${1}" + local geometry="${1}" + local xy_str=$(echo "${geometry}" | cut -d' ' -f1) + local wh_str=$(echo "${geometry}" | cut -d' ' -f2) + local x=`echo "${xy_str}" | cut -d',' -f1` + local y=`echo "${xy_str}" | cut -d',' -f2` + local width=`echo "${wh_str}" | cut -dx -f1` + local height=`echo "${wh_str}" | cut -dx -f2` + + local max_width=`hyprctl monitors -j | jq -r '[.[] | if (.transform % 2 == 0) then (.x + .width) else (.x + .height) end] | max'` + local max_height=`hyprctl monitors -j | jq -r '[.[] | if (.transform % 2 == 0) then (.y + .height) else (.y + .width) end] | max'` + + local min_x=`hyprctl monitors -j | jq -r '[.[] | (.x)] | min'` + local min_y=`hyprctl monitors -j | jq -r '[.[] | (.y)] | min'` + + local cropped_x=$x + local cropped_y=$y + local cropped_width=$width + local cropped_height=$height + + if ((x + width > max_width)); then + cropped_width=$((max_width - x)) + fi + if ((y + height > max_height)); then + cropped_height=$((max_height - y)) + fi + + if ((x < min_x)); then + cropped_x="$min_x" + cropped_width=$((cropped_width + x - min_x)) + fi + if ((y < min_y)); then + cropped_y="$min_y" + cropped_height=$((cropped_height + y - min_y)) + fi + + local cropped=`printf "%s,%s %sx%s\n" \ + "${cropped_x}" "${cropped_y}" \ + "${cropped_width}" "${cropped_height}"` + Print "Crop: %s\n" "${cropped}" + echo ${cropped} +} + +function save_geometry() { + local geometry="${1}" + local output="" + + if [ $RAW -eq 1 ]; then + grim -g "${geometry}" - + return 0 + fi + + if [ $CLIPBOARD -eq 0 ]; then + mkdir -p "$SAVEDIR" + grim -g "${geometry}" "$SAVE_FULLPATH" + output="$SAVE_FULLPATH" + wl-copy --type image/png < "$output" + [ -z "$COMMAND" ] || { + "$COMMAND" "$output" + } + else + wl-copy --type image/png < <(grim -g "${geometry}" -) + fi + + send_notification $output +} + +function checkRunning() { + sleep 1 + while [[ 1 == 1 ]]; do + if [[ $(pgrep slurp | wc -m) == 0 ]]; then + pkill hyprpicker + exit + fi + done +} + +function begin_grab() { + if [ $FREEZE -eq 1 ] && [ "$(command -v "hyprpicker")" ] >/dev/null 2>&1; then + hyprpicker -r -z & + sleep 0.2 + HYPRPICKER_PID=$! + fi + local option=$1 + case $option in + output) + if [ $CURRENT -eq 1 ]; then + local geometry=`grab_active_output` + elif [ -z $SELECTED_MONITOR ]; then + local geometry=`grab_output` + else + local geometry=`grab_selected_output $SELECTED_MONITOR` + fi + ;; + region) + local geometry=`grab_region` + ;; + window) + if [ $CURRENT -eq 1 ]; then + local geometry=`grab_active_window` + else + local geometry=`grab_window` + fi + geometry=`trim "${geometry}"` + ;; + esac + if [ ${DELAY} -gt 0 ] 2>/dev/null; then + sleep ${DELAY} + fi + save_geometry "${geometry}" +} + +function grab_output() { + slurp -or +} + +function grab_active_output() { + local active_workspace=`hyprctl -j activeworkspace` + local monitors=`hyprctl -j monitors` + Print "Monitors: %s\n" "$monitors" + Print "Active workspace: %s\n" "$active_workspace" + local current_monitor="$(echo $monitors | jq -r 'first(.[] | select(.activeWorkspace.id == '$(echo $active_workspace | jq -r '.id')'))')" + Print "Current output: %s\n" "$current_monitor" + echo $current_monitor | jq -r '"\(.x),\(.y) \(.width/.scale|round)x\(.height/.scale|round)"' +} + +function grab_selected_output() { + local monitor=`hyprctl -j monitors | jq -r '.[] | select(.name == "'$(echo $1)'")'` + Print "Capturing: %s\n" "${1}" + echo $monitor | jq -r '"\(.x),\(.y) \(.width/.scale|round)x\(.height/.scale|round)"' +} + +function grab_region() { + slurp -d +} + +function grab_window() { + local monitors=`hyprctl -j monitors` + local clients=`hyprctl -j clients | jq -r '[.[] | select(.workspace.id | contains('$(echo $monitors | jq -r 'map(.activeWorkspace.id) | join(",")')'))]'` + Print "Monitors: %s\n" "$monitors" + Print "Clients: %s\n" "$clients" + # Generate boxes for each visible window and send that to slurp + # through stdin + local boxes="$(echo $clients | jq -r '.[] | "\(.at[0]),\(.at[1]) \(.size[0])x\(.size[1]) \(.title)"' | cut -f1,2 -d' ')" + Print "Boxes:\n%s\n" "$boxes" + slurp -r <<< "$boxes" +} + +function grab_active_window() { + local active_window=`hyprctl -j activewindow` + local box=$(echo $active_window | jq -r '"\(.at[0]),\(.at[1]) \(.size[0])x\(.size[1])"' | cut -f1,2 -d' ') + Print "Box:\n%s\n" "$box" + echo "$box" +} + +function parse_mode() { + local mode="${1}" + + case $mode in + window | region | output) + OPTION=$mode + ;; + active) + CURRENT=1 + ;; + *) + hyprctl monitors -j | jq -re '.[] | select(.name == "'$(echo $mode)'")' &>/dev/null + SELECTED_MONITOR=$mode + ;; + esac +} + +function args() { + local options=$(getopt -o hf:o:m:D:dszr:t: --long help,filename:,output-folder:,mode:,delay:,clipboard-only,debug,silent,freeze,raw,notif-timeout: -- "$@") + eval set -- "$options" + + while true; do + case "$1" in + -h | --help) + Help + exit + ;; + -o | --output-folder) + shift; + SAVEDIR=$1 + ;; + -f | --filename) + shift; + FILENAME=$1 + ;; + -D | --delay) + shift; + DELAY=$1 + ;; + -m | --mode) + shift; + parse_mode $1 + ;; + --clipboard-only) + CLIPBOARD=1 + ;; + -d | --debug) + DEBUG=1 + ;; + -z | --freeze) + FREEZE=1 + ;; + -s | --silent) + SILENT=1 + ;; + -r | --raw) + RAW=1 + ;; + -t | --notif-timeout) + shift; + NOTIF_TIMEOUT=$1 + ;; + --) + shift # Skip -- argument + COMMAND=${@:2} + break;; + esac + shift + done + + if [ -z $OPTION ]; then + Print "A mode is required\n\nAvailable modes are:\n\toutput\n\tregion\n\twindow\n" + exit 2 + fi +} + +if [ -z $1 ]; then + Help + exit +fi + +CLIPBOARD=0 +DEBUG=0 +SILENT=0 +RAW=0 +NOTIF_TIMEOUT=5000 +CURRENT=0 +FREEZE=0 +[ -z "$XDG_PICTURES_DIR" ] && type xdg-user-dir &> /dev/null && XDG_PICTURES_DIR=$(xdg-user-dir PICTURES) +FILENAME="$(date +'%Y-%m-%d-%H%M%S_hyprshot.png')" +[ -z "$HYPRSHOT_DIR" ] && SAVEDIR=${XDG_PICTURES_DIR:=~} || SAVEDIR=${HYPRSHOT_DIR} + +args $0 "$@" + +SAVE_FULLPATH="$SAVEDIR/$FILENAME" +[ $CLIPBOARD -eq 0 ] && Print "Saving in: %s\n" "$SAVE_FULLPATH" +begin_grab $OPTION & checkRunning diff --git a/config/hypr/scripts/install-uv.sh b/config/hypr/scripts/install-uv.sh new file mode 100755 index 00000000..3582a78e --- /dev/null +++ b/config/hypr/scripts/install-uv.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +curl -LsSf https://astral.sh/uv/install.sh | sh |
