Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions .config/matugen/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ output_path = '~/.config/matugen/generated/hyprlock-colors.conf'
input_path = '~/.config/matugen/templates/colors.css'
output_path = '~/.config/matugen/generated/waybar-colors.css'
post_hook = '''
~/user_scripts/waybar/waybar_autostart.sh || true;
~/user_scripts/waybar/waybar_autostart.sh theme-change || true;
'''

[templates.swaync]
Expand Down Expand Up @@ -122,7 +122,6 @@ input_path = '~/.config/matugen/templates/zathura-colors'
output_path = '~/.config/matugen/generated/zathura-colors'
post_hook = 'ln -nfs $HOME/.config/matugen/generated/zathura-colors $HOME/.config/zathura/zathurarc'


# [templates.starship]
# input_path = '~/.config/matugen/templates/starship-colors.toml'
# output_path = '~/.config/matugen/generated/starship-colors.toml'
Expand Down Expand Up @@ -156,7 +155,7 @@ ln -nfs $HOME/.config/matugen/generated/obsidian-theme.css $HOME/Documents/pensi
input_path = '~/.config/matugen/templates/midnight-discord.css'
output_path = '~/.config/matugen/generated/midnight-discord.css'
post_hook = '''
mkdir -p $HOME/~/.config/vesktop/themes/;
mkdir -p $HOME/.config/vesktop/themes/;
ln -nfs $HOME/.config/matugen/generated/midnight-discord.css $HOME/.config/vesktop/themes/midnight-discord.css
'''

Expand Down
22 changes: 22 additions & 0 deletions user_scripts/theme_matugen/theme_ctl.sh
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ readonly DEFAULT_CONTRAST="0"
readonly FLOCK_TIMEOUT_SEC=30
readonly DAEMON_POLL_INTERVAL=0.1
readonly DAEMON_POLL_LIMIT=50
readonly WAYBAR_STATE_FILE="${XDG_RUNTIME_DIR:-/tmp}/waybar_was_running"

# --- STATE VARIABLES (populated by read_state) ---
THEME_MODE=""
Expand Down Expand Up @@ -79,6 +80,21 @@ check_deps() {
(( ${#missing[@]} == 0 )) || die "Missing required commands: ${missing[*]}"
}

# --- WAYBAR STATE ---

detect_waybar_state() {
rm -f "$WAYBAR_STATE_FILE"
pgrep -x waybar >/dev/null 2>&1 && touch "$WAYBAR_STATE_FILE" || true
}

restore_waybar_state() {
local autostart="${HOME}/user_scripts/waybar/waybar_autostart.sh"
if [[ -f "$WAYBAR_STATE_FILE" ]]; then
rm -f "$WAYBAR_STATE_FILE"
[[ -x "$autostart" ]] && { "$autostart" & } || true
fi
}

# --- STATE MANAGEMENT ---

update_public_state() {
Expand Down Expand Up @@ -318,13 +334,17 @@ apply_random_wallpaper() {

log "Selected: ${wallpaper##*/}"

detect_waybar_state

ensure_swww_running
swww img "$wallpaper" \
--transition-type grow \
--transition-duration 2 \
--transition-fps 60

generate_colors "$wallpaper"

restore_waybar_state
}

regenerate_current() {
Expand Down Expand Up @@ -358,7 +378,9 @@ regenerate_current() {
log "Current wallpaper: ${resolved_wallpaper##*/}"
fi

detect_waybar_state
generate_colors "$resolved_wallpaper"
restore_waybar_state
}

generate_colors() {
Expand Down
103 changes: 55 additions & 48 deletions user_scripts/waybar/waybar_autostart.sh
Original file line number Diff line number Diff line change
@@ -1,97 +1,104 @@
#!/usr/bin/env bash
# -----------------------------------------------------------------------------
# Description: Robustly restarts Waybar for Hyprland/UWSM sessions.
# Uses systemd-run to spawn from a clean user environment,
# avoiding XDG_ACTIVATION_TOKEN inheritance issues.
# Author: dusk
# -----------------------------------------------------------------------------

set -euo pipefail

# --- Constants ---
# ------------------------------------------------------
# Robust Waybar launcher for Hyprland / systemd
# ------------------------------------------------------
readonly APP_NAME="waybar"
readonly TIMEOUT_SEC=5

# --- Terminal-Aware Colors (stderr detection) ---
# State file written by theme_ctl.sh before Matugen runs.
# Presence means Waybar was running before the theme change.
readonly WAYBAR_STATE_FILE="${XDG_RUNTIME_DIR:-/tmp}/waybar_was_running"

# Terminal-aware colors
if [[ -t 2 ]]; then
readonly C_RED=$'\033[0;31m'
readonly C_GREEN=$'\033[0;32m'
readonly C_BLUE=$'\033[0;34m'
readonly C_RESET=$'\033[0m'
else
readonly C_RED=''
readonly C_GREEN=''
readonly C_BLUE=''
readonly C_RESET=''
readonly C_RED='' C_GREEN='' C_BLUE='' C_RESET=''
fi

# --- Logging Functions (Strictly to stderr) ---
# Redirecting logs to stderr keeps stdout clean for piping if needed.
log_info() { printf '%s[INFO]%s %s\n' "${C_BLUE}" "${C_RESET}" "$*" >&2; }
log_success() { printf '%s[OK]%s %s\n' "${C_GREEN}" "${C_RESET}" "$*" >&2; }
log_err() { printf '%s[ERROR]%s %s\n' "${C_RED}" "${C_RESET}" "$*" >&2; }
log_info() { printf '%s[INFO]%s %s\n' "${C_BLUE}" "${C_RESET}" "$*" >&2; }
log_success() { printf '%s[OK]%s %s\n' "${C_GREEN}" "${C_RESET}" "$*" >&2; }
log_err() { printf '%s[ERROR]%s %s\n' "${C_RED}" "${C_RESET}" "$*" >&2; }

# --- Fallback Strategy ---
# Note: As discovered, this method may not cure the "workspace inheritance"
# bug, but it ensures Waybar launches if systemd is broken.
launch_fallback() {
log_info "Attempting fallback launch (setsid)..."
(
unset XDG_ACTIVATION_TOKEN DESKTOP_STARTUP_ID
setsid "${APP_NAME}" "$@" </dev/null >/dev/null 2>&1 &
)
log_success "${APP_NAME} launched (fallback mode)."
}
# ============================================================
# STATE FILE GUARD
# When called with "theme-change", respect the state file:
# - State file present → Waybar was running → proceed to launch
# - State file absent → Waybar was hidden → exit cleanly
# When called without "theme-change" (e.g. from a keybind or
# session startup), always proceed regardless.
# ============================================================
if [[ "${1:-}" == "theme-change" ]]; then
if [[ ! -f "$WAYBAR_STATE_FILE" ]]; then
log_info "theme-change mode: Waybar was hidden before theme change, skipping launch."
exit 0
fi
log_info "theme-change mode: Waybar was running before theme change, proceeding."
rm -f "$WAYBAR_STATE_FILE"
shift
fi

# --- Preflight Checks ---
(( EUID != 0 )) || { log_err "This script must NOT be run as root."; exit 1; }
command -v "${APP_NAME}" >/dev/null 2>&1 || { log_err "${APP_NAME} binary not found."; exit 1; }
[[ -d ${XDG_RUNTIME_DIR:-} ]] || { log_err "XDG_RUNTIME_DIR is not set or invalid."; exit 1; }
# ============================================================
# PREFLIGHT
# ============================================================
(( EUID != 0 )) || { log_err "Do NOT run as root"; exit 1; }
command -v "${APP_NAME}" >/dev/null 2>&1 || { log_err "${APP_NAME} not found"; exit 1; }
[[ -d ${XDG_RUNTIME_DIR:-} ]] || { log_err "XDG_RUNTIME_DIR invalid"; exit 1; }

readonly LOCK_FILE="${XDG_RUNTIME_DIR}/${APP_NAME}_manager.lock"

# --- Concurrency Lock ---
# FD 9 is used to hold the lock until the script exits.
exec 9>"${LOCK_FILE}"
flock -n 9 || { log_err "Another instance is running. Exiting."; exit 1; }
flock -n 9 || { log_err "Another instance running"; exit 1; }

# --- Process Management ---
# ============================================================
# MANAGE EXISTING INSTANCES
# ============================================================
log_info "Managing ${APP_NAME} instances..."

if pgrep -x "${APP_NAME}" >/dev/null 2>&1; then
log_info "Stopping existing instances..."
pkill -x "${APP_NAME}" >/dev/null 2>&1 || true

# Poll for termination (Bash C-style loop)
for (( i = 0; i < TIMEOUT_SEC * 10; i++ )); do
for (( i=0; i < TIMEOUT_SEC*10; i++ )); do
pgrep -x "${APP_NAME}" >/dev/null 2>&1 || break
sleep 0.1
done

# Force kill if still resistant
if pgrep -x "${APP_NAME}" >/dev/null 2>&1; then
log_err "Process hung. Sending SIGKILL..."
log_err "Hung process, sending SIGKILL..."
pkill -9 -x "${APP_NAME}" >/dev/null 2>&1 || true
sleep 0.2
fi

log_success "Cleanup complete."
else
log_info "No running instance found."
fi

# --- Launch Sequence ---
# ============================================================
# LAUNCH
# ============================================================
launch_fallback() {
log_info "Attempting fallback launch (setsid)..."
(
unset XDG_ACTIVATION_TOKEN DESKTOP_STARTUP_ID
setsid "${APP_NAME}" "$@" </dev/null >/dev/null 2>&1 &
)
log_success "${APP_NAME} launched (fallback mode)."
}

log_info "Starting ${APP_NAME}..."

if command -v systemd-run >/dev/null 2>&1; then
# Optimization: Use Bash 5.0+ $EPOCHSECONDS instead of forking $(date)
# Security: Add $$ (PID) to unit name to prevent collision on rapid re-runs
unit_name="${APP_NAME}-mgr-${EPOCHSECONDS}-$$"

# '--' separates options from the command to prevent flag injection
if systemd-run --user --quiet --unit="${unit_name}" -- "${APP_NAME}" "$@" >/dev/null 2>&1; then
log_success "${APP_NAME} launched via systemd unit: ${unit_name}"
else
log_err "systemd-run failed; attempting fallback."
log_err "systemd-run failed; trying fallback..."
launch_fallback "$@"
fi
else
Expand Down