#!/usr/bin/env bash # ================================================== # KoolDots (2026) # Project URL: https://github.com/LinuxBeginnings # License: GNU GPLv3 # SPDX-License-Identifier: GPL-3.0-or-later # ================================================== # Wallust: derive colors from the current wallpaper and update templates # Usage: WallustSwww.sh [absolute_path_to_wallpaper] set -euo pipefail # Inputs and paths passed_path="${1:-}" if command -v awww >/dev/null 2>&1; then WWW="awww" cache_dir="$HOME/.cache/awww/" cache_dir_fallback="$HOME/.cache/swww/" else WWW="swww" 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" read_cached_wallpaper() { local cache_file="$1" if [[ -f "$cache_file" ]]; then awk 'NF && $0 !~ /^filter/ {print; exit}' "$cache_file" fi } read_wallpaper_from_query() { local monitor="$1" $WWW query | awk -v mon="$monitor" ' /^Monitor/ { cur=$2 gsub(":", "", cur) } /image:/ && cur==mon { sub(/^.*image: /,"") print exit } ' } # Helper: get focused monitor name (prefer JSON) get_focused_monitor() { if command -v jq >/dev/null 2>&1; then hyprctl monitors -j | jq -r '.[] | select(.focused) | .name' else hyprctl monitors | awk '/^Monitor/{name=$2} /focused: yes/{print name}' fi } # Determine wallpaper_path wallpaper_path="" if [[ -n "$passed_path" && -f "$passed_path" ]]; then wallpaper_path="$passed_path" else # Try to read from awww/swww cache for the focused monitor, with a short retry loop current_monitor="$(get_focused_monitor)" cache_file="$cache_dir$current_monitor" alt_cache_file="${cache_dir_fallback}${current_monitor}" # Wait briefly for awww/swww to write its cache after an image change for i in {1..10}; do if [[ -f "$cache_file" || -f "$alt_cache_file" ]]; then break fi sleep 0.1 done if [[ ! -f "$cache_file" && -f "$alt_cache_file" ]]; then cache_file="$alt_cache_file" fi if [[ -f "$cache_file" ]]; then # The first non-filter line is the original wallpaper path wallpaper_path="$(read_cached_wallpaper "$cache_file")" fi if [[ -z "$wallpaper_path" ]]; then wallpaper_path="$(read_wallpaper_from_query "$current_monitor")" fi fi if [[ -z "${wallpaper_path:-}" || ! -f "$wallpaper_path" ]]; then # Nothing to do; avoid failing loudly so callers can continue exit 0 fi # Update helpers that depend on the path ln -sf "$wallpaper_path" "$rofi_link" || true mkdir -p "$(dirname "$wallpaper_current")" cp -f "$wallpaper_path" "$wallpaper_current" || true # Ensure Ghostty directory exists so Wallust can write target even if Ghostty isn't installed mkdir -p "$HOME/.config/ghostty" || true wait_for_templates() { local start_ts="$1" shift local files=("$@") for _ in {1..50}; do local ready=true for file in "${files[@]}"; do if [[ ! -s "$file" ]]; then ready=false break fi local mtime mtime=$(stat -c %Y "$file" 2>/dev/null || echo 0) if (( mtime < start_ts )); then ready=false break fi done $ready && return 0 sleep 0.1 done return 1 } # Run wallust (silent) to regenerate templates defined in ~/.config/wallust/wallust.toml # -s is used in this repo to keep things quiet and avoid extra prompts start_ts=$(date +%s) wallust run -s "$wallpaper_path" || true wallust_targets=( "$HOME/.config/waybar/wallust/colors-waybar.css" "$HOME/.config/rofi/wallust/colors-rofi.rasi" "$HOME/.config/hypr/wallust/wallust-hyprland.conf" ) wait_for_templates "$start_ts" "${wallust_targets[@]}" || true # Normalize Rofi selection colors to a brighter accent and readable foreground rofi_colors="$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) fg_hex=$(sed -n 's/^\s*foreground:\s*\(#[0-9A-Fa-f]\{6\}\).*/\1/p' "$rofi_colors" | head -n1) if [ -n "$accent_hex" ]; then sed -i -E "s|^(\s*selected-normal-background:\s*).*$|\1$accent_hex;|" "$rofi_colors" sed -i -E "s|^(\s*selected-active-background:\s*).*$|\1$accent_hex;|" "$rofi_colors" sed -i -E "s|^(\s*selected-urgent-background:\s*).*$|\1$accent_hex;|" "$rofi_colors" fi if [ -n "$fg_hex" ]; then sed -i -E "s|^(\s*selected-normal-foreground:\s*).*$|\1$fg_hex;|" "$rofi_colors" sed -i -E "s|^(\s*selected-active-foreground:\s*).*$|\1$fg_hex;|" "$rofi_colors" sed -i -E "s|^(\s*selected-urgent-foreground:\s*).*$|\1$fg_hex;|" "$rofi_colors" fi fi # 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 fi # Light wait for Ghostty colors file to be present then signal Ghostty to reload (SIGUSR2) for _ in 1 2 3; do [ -s "$HOME/.config/ghostty/wallust.conf" ] && break sleep 0.1 done if pidof ghostty >/dev/null; then for pid in $(pidof ghostty); do kill -SIGUSR2 "$pid" 2>/dev/null || true; done fi # Reload Hyprland so new border colors from wallust-hyprland.conf take effect if command -v hyprctl >/dev/null 2>&1; then hyprctl reload >/dev/null 2>&1 || true fi ) >/dev/null 2>&1 &