Files
omarchy/bin/omarchy-theme-switcher
T
David Heinemeier HanssonandClaude Opus 5.5 24f1243120 Make the theme picker open instantly (#13403)
* Run menu summon actions in-process

A menu action that only summons another shell plugin spawned bash and a
qs ipc client to ask this same shell to do it, about 60ms of the path.
Call shell.summon directly instead, and fall back to bash when the call
is refused or the action is anything more than a bare summon.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Open the theme picker from rows held in the shell

Opening the theme picker ran omarchy-theme-switcher to rebuild its index
and then made a second IPC call, about 170ms before the picker mapped.
The picker now holds the theme rows itself, opens from them at once, and
refreshes them behind the open via omarchy-theme-switcher --print-rows.
It applies the chosen theme with omarchy-theme-set directly, so
omarchy-theme-set no longer preloads the picker.

From the keybinding to the overlay mapped drops from ~245ms to ~83ms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Keep the image picker surface mapped between opens

Each open mapped a fresh surface, which rendered its first frames before
Hyprland sent its fractional scale: the pixel ratio stepped 2, 1, then
1.6, so the picker flashed blurry for ~130ms and re-uploaded every
thumbnail texture. Keep the surface and park it transparent and
input-less on the bottom layer while closed, since anything on the
overlay layer blocks direct scanout for fullscreen apps. It follows the
focused monitor on each open.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 15:10:49 +02:00

131 lines
4.2 KiB
Bash
Executable File

#!/bin/bash
# omarchy:summary=Open the Omarchy theme switcher
print_rows=false
# The shell's picker opens from rows it already holds and runs this to refresh
# them, so the theme list never waits on the index below.
if [[ $1 == "--print-rows" ]]; then
print_rows=true
shift
fi
USER_THEMES_PATH="$HOME/.config/omarchy/themes"
OMARCHY_THEMES_PATH="$OMARCHY_PATH/themes"
CACHE_PATH="${XDG_CACHE_HOME:-$HOME/.cache}/omarchy/theme-selector"
preview_dir="$CACHE_PATH/previews"
signature_file="$CACHE_PATH/signature"
fast_signature_file="$CACHE_PATH/fast-signature"
mkdir -p "$preview_dir"
find_preview() {
local theme_path="$1"
local preview preview_name
for preview_name in preview.png preview.jpg preview.jpeg preview.webp preview.gif preview.bmp preview.mp4 preview.m4v preview.mov preview.webm preview.mkv preview.avi; do
preview=$(find -L "$theme_path" -maxdepth 1 -type f -iname "$preview_name" -print -quit 2>/dev/null)
if [[ -n $preview ]]; then
printf '%s\n' "$preview"
return
fi
done
if [[ -d $theme_path/backgrounds ]]; then
find -L "$theme_path/backgrounds" -maxdepth 1 -type f \
\( -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.png' -o -iname '*.gif' -o -iname '*.bmp' -o -iname '*.webp' \
-o -iname '*.mp4' -o -iname '*.m4v' -o -iname '*.mov' -o -iname '*.webm' -o -iname '*.mkv' -o -iname '*.avi' \) \
-print 2>/dev/null | sort | head -n 1
fi
}
add_theme_preview() {
local theme_name="$1"
local preview="$2"
local extension="${preview##*.}"
extension="${extension,,}"
[[ -n $preview ]] || return
[[ -e $preview_dir/$theme_name.$extension ]] && return
ln -s "$preview" "$preview_dir/$theme_name.$extension"
}
fast_signature="v2"$'\n'
for theme_dir in "$USER_THEMES_PATH" "$OMARCHY_THEMES_PATH"; do
if [[ -d $theme_dir ]]; then
fast_signature+="$theme_dir:$(stat -Lc '%Y' "$theme_dir")"$'\n'
while IFS= read -r -d '' theme_path; do
fast_signature+="$theme_path:$(stat -Lc '%Y' "$theme_path")"$'\n'
done < <(find -L "$theme_dir" -mindepth 1 -maxdepth 1 \( -type d -o -type l \) -print0 2>/dev/null | sort -z)
fi
done
if [[ ! -f $fast_signature_file ]] || ! cmp -s "$fast_signature_file" <(printf '%s' "$fast_signature"); then
theme_signature=""
for theme_dir in "$USER_THEMES_PATH" "$OMARCHY_THEMES_PATH"; do
if [[ -d $theme_dir ]]; then
theme_signature+="$theme_dir:$(stat -Lc '%Y' "$theme_dir")"$'\n'
while IFS= read -r -d '' theme_path; do
preview=$(find_preview "$theme_path")
theme_signature+="$theme_path:$(stat -Lc '%Y' "$theme_path")"$'\n'
if [[ -n $preview ]]; then
theme_signature+="$preview:$(stat -Lc '%s:%Y' "$preview")"$'\n'
fi
done < <(find -L "$theme_dir" -mindepth 1 -maxdepth 1 \( -type d -o -type l \) -print0 2>/dev/null | sort -z)
fi
done
fi
if [[ ! -f $fast_signature_file ]] || ! cmp -s "$fast_signature_file" <(printf '%s' "$fast_signature"); then
rm -rf "$preview_dir"
mkdir -p "$preview_dir"
while IFS= read -r theme_path; do
theme_name=${theme_path##*/}
preview=$(find_preview "$theme_path")
if [[ -z $preview ]]; then
preview=$(find_preview "$OMARCHY_THEMES_PATH/$theme_name")
fi
add_theme_preview "$theme_name" "$preview"
done < <(find -L "$USER_THEMES_PATH" -mindepth 1 -maxdepth 1 \( -type d -o -type l \) -print 2>/dev/null | sort)
while IFS= read -r theme_path; do
theme_name=${theme_path##*/}
preview=$(find_preview "$theme_path")
add_theme_preview "$theme_name" "$preview"
done < <(find -L "$OMARCHY_THEMES_PATH" -mindepth 1 -maxdepth 1 -type d -print 2>/dev/null | sort)
printf '%s' "$theme_signature" >"$signature_file"
printf '%s' "$fast_signature" >"$fast_signature_file"
fi
current_theme=$(cat "$HOME/.local/state/omarchy/current/theme.name" 2>/dev/null)
selected_preview=""
for extension in png jpg jpeg webp gif bmp mp4 m4v mov webm mkv avi; do
if [[ -e $preview_dir/$current_theme.$extension ]]; then
selected_preview="$preview_dir/$current_theme.$extension"
break
fi
done
menu_args=(
--print-name
--show-labels
--filterable
--lazy-thumbnails
--selected "$selected_preview"
)
if [[ $print_rows == true ]]; then
menu_args+=(--print-rows)
fi
exec omarchy-menu-images "${menu_args[@]}" "$preview_dir"