#!/usr/bin/env bash set -euo pipefail SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" HYPR_DIR="$(cd -- "$SCRIPT_DIR/.." && pwd)" THEME_DIR="$HYPR_DIR/Themes" CURRENT_THEME="$HYPR_DIR/current-theme.conf" HYPRLOCK_CONF="$HYPR_DIR/hyprlock.conf" HYPRPAPER_CONF="$HYPR_DIR/hyprpaper.conf" CURRENT_WALLPAPER="$HYPR_DIR/current-wallpaper" WOFI_STYLE="${XDG_CONFIG_HOME:-$HOME/.config}/wofi/style.css" SWAYNC_STYLE="${XDG_CONFIG_HOME:-$HOME/.config}/swaync/style.css" WAYBAR_STYLE="${XDG_CONFIG_HOME:-$HOME/.config}/waybar/style.css" GTK3_SETTINGS="${XDG_CONFIG_HOME:-$HOME/.config}/gtk-3.0/settings.ini" GTK4_SETTINGS="${XDG_CONFIG_HOME:-$HOME/.config}/gtk-4.0/settings.ini" GTK3_CSS="${XDG_CONFIG_HOME:-$HOME/.config}/gtk-3.0/gtk.css" GTK4_CSS="${XDG_CONFIG_HOME:-$HOME/.config}/gtk-4.0/gtk.css" KDEGLOBALS="${XDG_CONFIG_HOME:-$HOME/.config}/kdeglobals" KDE_COLOR_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/color-schemes" LOCAL_ICON_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/icons" QT6CT_CONF="${XDG_CONFIG_HOME:-$HOME/.config}/qt6ct/qt6ct.conf" QT5CT_CONF="${XDG_CONFIG_HOME:-$HOME/.config}/qt5ct/qt5ct.conf" STARSHIP_CONF="${XDG_CONFIG_HOME:-$HOME/.config}/starship.toml" SDDM_STATE_DIR="/var/lib/pascal-sddm-theme" notify() { notify-send "󰌪 Theme" "$1" >/dev/null 2>&1 || true } load_theme() { local theme_file="$1" NAME="" ICON="󰌪" WALLPAPER="" TRANSITION_TYPE="grow" TRANSITION_DURATION="1.0" TRANSITION_FPS="60" TRANSITION_POS="center" ACTIVE_BORDER="" INACTIVE_BORDER="" ACCENT="" ACCENT_2="" BACKGROUND="" BACKGROUND_SOFT="" BACKGROUND_HEX="" PANEL_HEX="" FOREGROUND="" MUTED="" SELECTED_TEXT="" WAYBAR_PANEL="" WAYBAR_ISLAND="" WAYBAR_MUTED="" WAYBAR_SUCCESS="" WAYBAR_WARNING="" WAYBAR_DANGER="" WAYBAR_BLUE="" WAYBAR_CYAN="" WAYBAR_ORANGE="" WAYBAR_PURPLE="" APP_THEME_MODE="prefer-dark" GNOME_ACCENT_COLOR="blue" GTK_THEME_NAME="Adwaita" ICON_THEME_NAME="Adwaita" PAPIRUS_FOLDER_COLOR="" KDE_COLOR_SCHEME="" # shellcheck source=/dev/null source "$theme_file" if [[ -z "$NAME" || -z "$WALLPAPER" || -z "$ACTIVE_BORDER" || -z "$INACTIVE_BORDER" || -z "$ACCENT" || -z "$ACCENT_2" || -z "$BACKGROUND" || -z "$BACKGROUND_SOFT" || -z "$FOREGROUND" || -z "$MUTED" || -z "$SELECTED_TEXT" ]]; then notify "Theme ist unvollstaendig: $(basename "$theme_file")" exit 1 fi if [[ ! -f "$WALLPAPER" ]]; then notify "Wallpaper nicht gefunden: $WALLPAPER" exit 1 fi WAYBAR_PANEL="${WAYBAR_PANEL:-$BACKGROUND_SOFT}" WAYBAR_ISLAND="${WAYBAR_ISLAND:-$BACKGROUND}" WAYBAR_MUTED="${WAYBAR_MUTED:-$MUTED}" WAYBAR_SUCCESS="${WAYBAR_SUCCESS:-$ACCENT_2}" WAYBAR_WARNING="${WAYBAR_WARNING:-#f9e2af}" WAYBAR_DANGER="${WAYBAR_DANGER:-#f38ba8}" WAYBAR_BLUE="${WAYBAR_BLUE:-$ACCENT}" WAYBAR_CYAN="${WAYBAR_CYAN:-$ACCENT_2}" WAYBAR_ORANGE="${WAYBAR_ORANGE:-#fab387}" WAYBAR_PURPLE="${WAYBAR_PURPLE:-$ACCENT_2}" BACKGROUND_HEX="${BACKGROUND_HEX:-#18141f}" PANEL_HEX="${PANEL_HEX:-#313244}" KDE_COLOR_SCHEME="${KDE_COLOR_SCHEME:-${NAME//[^[:alnum:]]/}}" } backup_once() { local file="$1" local backup="$file.before-theme-switcher" if [[ -f "$file" && ! -f "$backup" ]]; then cp "$file" "$backup" fi } start_detached() { local command_name="$1" local unit_name="${command_name//[^[:alnum:]_.-]/-}" if command -v systemd-run >/dev/null 2>&1; then systemd-run --user --unit="$unit_name" --collect "$@" >/dev/null 2>&1 && return fi if command -v setsid >/dev/null 2>&1; then setsid -f "$@" >/dev/null 2>&1 else "$@" >/dev/null 2>&1 & fi } restart_waybar() { local i pkill -x waybar >/dev/null 2>&1 || true for i in {1..20}; do pgrep -x waybar >/dev/null 2>&1 || break sleep 0.05 done pgrep -x waybar >/dev/null 2>&1 && pkill -9 -x waybar >/dev/null 2>&1 || true start_detached waybar } hex_to_rgb() { local hex="${1#'#'}" if [[ ! "$hex" =~ ^[0-9a-fA-F]{6}$ ]]; then printf '0,0,0\n' return fi printf '%d,%d,%d\n' "0x${hex:0:2}" "0x${hex:2:2}" "0x${hex:4:2}" } hex_to_argb() { local hex="${1#'#'}" if [[ ! "$hex" =~ ^[0-9a-fA-F]{6}$ ]]; then printf '#ff000000\n' return fi printf '#ff%s\n' "${hex,,}" } write_gtk_settings() { mkdir -p "$(dirname "$GTK3_SETTINGS")" "$(dirname "$GTK4_SETTINGS")" backup_once "$GTK3_SETTINGS" backup_once "$GTK4_SETTINGS" backup_once "$GTK3_CSS" backup_once "$GTK4_CSS" cat >"$GTK3_SETTINGS" <"$GTK4_SETTINGS" <"$gtk_css" </dev/null 2>&1; then gsettings set org.gnome.desktop.interface color-scheme "$APP_THEME_MODE" >/dev/null 2>&1 || true gsettings set org.gnome.desktop.interface accent-color "$GNOME_ACCENT_COLOR" >/dev/null 2>&1 || true gsettings set org.gnome.desktop.interface gtk-theme "$GTK_THEME_NAME" >/dev/null 2>&1 || true gsettings set org.gnome.desktop.interface icon-theme "$ICON_THEME_NAME" >/dev/null 2>&1 || true fi } link_icon_if_present() { local source="$1" local target="$2" if [[ -e "$source" ]]; then ln -sfn "$source" "$target" fi } write_papirus_icon_theme() { local source_theme="/usr/share/icons/Papirus-Dark" local target_theme="$LOCAL_ICON_DIR/$ICON_THEME_NAME" local source_places relative_dir target_places source_size size scale suffix local folder_color="${PAPIRUS_FOLDER_COLOR:-}" local stamp_file="$target_theme/.theme-switcher-stamp" local stamp_value="$NAME|$ICON_THEME_NAME|$folder_color" local place_dirs=() local directories [[ -d "$source_theme" && -n "$folder_color" && "$ICON_THEME_NAME" == Papirus-* ]] || return 0 if [[ -f "$target_theme/index.theme" && -f "$stamp_file" && "$(cat "$stamp_file")" == "$stamp_value" ]]; then return 0 fi mkdir -p "$target_theme" mapfile -t place_dirs < <(find -L "$source_theme" -path '*/places' -type d | sort) directories="$( for source_places in "${place_dirs[@]}"; do printf '%s,' "${source_places#"$source_theme"/}" done )" directories="${directories%,}" cat >"$target_theme/index.theme" <>"$target_theme/index.theme" </dev/null 2>&1; then gtk-update-icon-cache -q "$target_theme" >/dev/null 2>&1 || true fi printf '%s\n' "$stamp_value" >"$stamp_file" } write_qtct_theme() { local qt_dir conf_file color_file local foreground_argb muted_argb background_argb panel_argb accent_argb accent_2_argb selected_argb danger_argb placeholder_argb local active_colors disabled_colors inactive_colors foreground_argb="$(hex_to_argb "$FOREGROUND")" muted_argb="$(hex_to_argb "$MUTED")" background_argb="$(hex_to_argb "${BACKGROUND_HEX:-#18141f}")" panel_argb="$(hex_to_argb "${PANEL_HEX:-#313244}")" accent_argb="$(hex_to_argb "$ACCENT")" accent_2_argb="$(hex_to_argb "$ACCENT_2")" selected_argb="$(hex_to_argb "$SELECTED_TEXT")" danger_argb="$(hex_to_argb "$WAYBAR_DANGER")" placeholder_argb="#80${MUTED#'#'}" active_colors="$foreground_argb, $panel_argb, #ffffffff, $muted_argb, $background_argb, $panel_argb, $foreground_argb, #ffffffff, $foreground_argb, $background_argb, $background_argb, #ff000000, $accent_argb, $selected_argb, $accent_2_argb, $danger_argb, $panel_argb, $foreground_argb, $panel_argb, $foreground_argb, $placeholder_argb" disabled_colors="$muted_argb, $panel_argb, #ffffffff, $muted_argb, $background_argb, $panel_argb, $muted_argb, #ffffffff, $muted_argb, $background_argb, $background_argb, #ff000000, $panel_argb, $muted_argb, $accent_2_argb, $danger_argb, $panel_argb, $muted_argb, $panel_argb, $muted_argb, $placeholder_argb" inactive_colors="$foreground_argb, $panel_argb, #ffffffff, $muted_argb, $background_argb, $panel_argb, $foreground_argb, #ffffffff, $foreground_argb, $background_argb, $background_argb, #ff000000, $accent_argb, $selected_argb, $accent_2_argb, $danger_argb, $panel_argb, $foreground_argb, $panel_argb, $foreground_argb, $placeholder_argb" for qt_dir in "${XDG_CONFIG_HOME:-$HOME/.config}/qt6ct" "${XDG_CONFIG_HOME:-$HOME/.config}/qt5ct"; do mkdir -p "$qt_dir/colors" color_file="$qt_dir/colors/$KDE_COLOR_SCHEME.conf" cat >"$color_file" <"$conf_file" <"$scheme_file" </dev/null 2>&1; then kwriteconfig6 --file kdeglobals --group General --key ColorScheme "$KDE_COLOR_SCHEME" >/dev/null 2>&1 || true kwriteconfig6 --file kdeglobals --group General --key Name "$NAME" >/dev/null 2>&1 || true kwriteconfig6 --file kdeglobals --group Icons --key Theme "$ICON_THEME_NAME" >/dev/null 2>&1 || true kwriteconfig6 --file kdeglobals --group KDE --key widgetStyle Fusion >/dev/null 2>&1 || true else mkdir -p "$(dirname "$KDEGLOBALS")" cat >"$KDEGLOBALS" <"$WOFI_STYLE" <"$SWAYNC_STYLE" <"$WAYBAR_STYLE" <"$HYPRLOCK_CONF" <Passwort oder Fingerprint check_color = rgba($accent_2_rgb, 0.88) fail_color = rgba($danger_rgb, 0.95) capslock_color = rgba($warning_rgb, 0.95) position = 0, -20 halign = center valign = center } label { monitor = text = cmd[update:1000] echo " $(whoami)@$(hostname)" color = rgba($muted_rgb, 0.70) font_size = 16 font_family = JetBrainsMono Nerd Font position = 0, -92 halign = center valign = center } EOF } write_starship_theme() { mkdir -p "$(dirname "$STARSHIP_CONF")" backup_once "$STARSHIP_CONF" cat >"$STARSHIP_CONF" <"$SDDM_STATE_DIR/theme.conf" <"$HYPRPAPER_CONF" <"$CURRENT_WALLPAPER" if command -v awww >/dev/null 2>&1; then if ! pgrep -x awww-daemon >/dev/null 2>&1; then start_detached awww-daemon sleep 0.2 fi awww img "$WALLPAPER" \ --transition-type "$TRANSITION_TYPE" \ --transition-duration "$TRANSITION_DURATION" \ --transition-fps "$TRANSITION_FPS" \ --transition-pos "$TRANSITION_POS" >/dev/null 2>&1 || true return fi if command -v swww >/dev/null 2>&1; then if ! pgrep -x swww-daemon >/dev/null 2>&1; then start_detached swww-daemon sleep 0.2 fi swww img "$WALLPAPER" \ --transition-type "$TRANSITION_TYPE" \ --transition-duration "$TRANSITION_DURATION" \ --transition-fps "$TRANSITION_FPS" \ --transition-pos "$TRANSITION_POS" >/dev/null 2>&1 || true return fi if command -v hyprctl >/dev/null 2>&1; then if ! pgrep -x hyprpaper >/dev/null 2>&1; then start_detached hyprpaper sleep 0.2 fi hyprctl hyprpaper preload "$WALLPAPER" >/dev/null || true hyprctl hyprpaper wallpaper ",$WALLPAPER" >/dev/null || true fi } apply_theme() { local theme_file="$1" load_theme "$theme_file" cat >"$CURRENT_THEME" </dev/null 2>&1; then hyprctl keyword general:col.active_border "$ACTIVE_BORDER" >/dev/null || true hyprctl keyword general:col.inactive_border "$INACTIVE_BORDER" >/dev/null || true fi if command -v swaync-client >/dev/null 2>&1; then swaync-client -rs >/dev/null 2>&1 || true fi if command -v waybar >/dev/null 2>&1; then restart_waybar fi if pgrep -x nautilus >/dev/null 2>&1; then nautilus -q >/dev/null 2>&1 || pkill -x nautilus >/dev/null 2>&1 || true fi notify "$NAME aktiviert." } if [[ "${1:-}" == "--apply" ]]; then theme_arg="${2:-}" if [[ -z "$theme_arg" ]]; then notify "Kein Theme angegeben." exit 1 fi if [[ -f "$theme_arg" ]]; then apply_theme "$theme_arg" elif [[ -f "$THEME_DIR/$theme_arg.theme" ]]; then apply_theme "$THEME_DIR/$theme_arg.theme" else notify "Theme nicht gefunden: $theme_arg" exit 1 fi exit 0 fi mkdir -p "$THEME_DIR" mapfile -t theme_files < <(find "$THEME_DIR" -maxdepth 1 -type f -name '*.theme' | sort) if ((${#theme_files[@]} == 0)); then notify "Keine Themes in $THEME_DIR gefunden." exit 1 fi menu_entries=() for theme_file in "${theme_files[@]}"; do load_theme "$theme_file" menu_entries+=("$ICON $NAME") done choice="$( printf '%s\n' "${menu_entries[@]}" | wofi --dmenu --prompt "󰌪 Theme wechseln" --insensitive )" [[ -z "${choice:-}" ]] && exit 0 for i in "${!menu_entries[@]}"; do if [[ "$choice" == "${menu_entries[$i]}" ]]; then apply_theme "${theme_files[$i]}" exit 0 fi done