Files
omarchy/test/shell.d/hyprland-window-transparency-test.sh
T
David Heinemeier HanssonandClaude Opus 5.5 a98e55eb91 Pick window transparency from Appearance > Window Transparency, and a Glassy bar background (#14991)
* Pick window transparency from Appearance > Window Transparency

Transparent, the default, keeps today's windows. Opaque turns the windows
Omarchy makes transparent solid. Glassy is the frosted glass Starship
(#14726): its blur behind every see-through window and shell surface, and a
see-through, blurred background in the theme's terminal files, since foot
turns compositor blur down and a Hyprland opacity rule fades text.

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

* Leave window transparency to Appearance when animations are off

Turning animations off no longer makes windows opaque. VM installs start
with opaque windows instead, and a migration keeps them opaque for anyone
who already has animations off.

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

* Add a Glassy bar background, under Menu Bar > Bar Background

Menu Bar > Bar Background picks Opaque Bar, Glassy Bar or Clear Bar, and
Indicators becomes Bar Indicators to match. Glassy keeps the theme
background faintly and Hyprland blurs what is behind it, with the same blur
as Glassy windows.

omarchy bar background opaque|glassy|none|cycle sets it and prints it when
given nothing. omarchy bar transparent true|false|toggle stays for
compatibility, as none and opaque. Double-clicking the bar cycles through
the three backgrounds the same way, from clear to glassy to opaque.

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

* Stop when a saved corner choice can't be removed

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

* Make btop follow glassy windows

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:21:00 +09:00

231 lines
13 KiB
Bash
Executable File

#!/bin/bash
set -euo pipefail
source "$(dirname "${BASH_SOURCE[0]}")/base-test.sh"
tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT
stub_dir="$tmpdir/bin"
home_dir="$tmpdir/home"
state_home="$tmpdir/state"
toggles_dir="$state_home/omarchy/toggles/hypr"
mkdir -p "$stub_dir" "$home_dir"
for command in hyprctl omarchy-notification-send omarchy-restart-terminal omarchy-theme-set-foot omarchy-restart-btop; do
printf '#!/bin/bash\nprintf "%%s\\n" "%s $*" >>"%s/commands.log"\n' "$command" "$tmpdir" >"$stub_dir/$command"
done
chmod +x "$stub_dir"/*
run() {
HOME="$home_dir" XDG_RUNTIME_DIR="$tmpdir" XDG_STATE_HOME="$state_home" XDG_CONFIG_HOME="$home_dir/.config" OMARCHY_PATH="$ROOT" PATH="$stub_dir:$ROOT/bin:$PATH" "$@"
}
[[ $(run omarchy-hyprland-window-transparency) == "transparent" ]] || fail "windows start out transparent"
pass "windows start out transparent"
run omarchy-hyprland-window-transparency glassy
[[ $(run omarchy-hyprland-window-transparency) == "glassy" ]] || fail "glassy windows are reported"
cmp -s "$ROOT/default/hypr/toggles/window-glassy.lua" "$toggles_dir/window-glassy.lua" || fail "glassy windows are loaded after the theme"
grep -qx 'hyprctl reload' "$tmpdir/commands.log" || fail "new transparency reloads Hyprland"
grep -q '^omarchy-restart-btop ' "$tmpdir/commands.log" || fail "new transparency reloads running btop windows"
pass "glassy windows override the theme"
run omarchy-hyprland-window-transparency opaque
[[ $(run omarchy-hyprland-window-transparency) == "opaque" ]] || fail "opaque windows are reported"
[[ ! -e $toggles_dir/window-glassy.lua ]] || fail "opaque windows replace glassy ones"
pass "opaque windows replace glassy ones"
run omarchy-hyprland-window-transparency transparent
[[ $(run omarchy-hyprland-window-transparency) == "transparent" ]] || fail "transparent windows are reported"
[[ ! -e $toggles_dir/window-opaque.lua ]] || fail "transparent windows drop the override"
pass "transparent windows drop the override"
if run omarchy-hyprland-window-transparency frosted 2>/dev/null; then
fail "unknown transparency is refused"
fi
pass "unknown transparency is refused"
# A failed save keeps the transparency already chosen.
run omarchy-hyprland-window-transparency glassy
chmod a-w "$toggles_dir"
if run omarchy-hyprland-window-transparency opaque 2>/dev/null; then
chmod u+w "$toggles_dir"
fail "a failed save is reported"
fi
chmod u+w "$toggles_dir"
[[ $(run omarchy-hyprland-window-transparency) == "glassy" ]] || fail "a failed save keeps the transparency already chosen"
run omarchy-hyprland-window-transparency transparent
pass "a failed save keeps the transparency already chosen"
# GTK apps only ask Hyprland for blur under a CSS backdrop-filter, so glassy
# imports one into the user's gtk.css, leaving the rest of it alone.
gtk_css="$home_dir/.config/gtk-4.0/gtk.css"
mkdir -p "${gtk_css%/*}"
printf 'label { color: red; }\n' >"$gtk_css"
run omarchy-hyprland-window-transparency glassy
grep -qxF "@import url(\"file://$ROOT/default/gtk/glass.css\");" "$gtk_css" || fail "glassy GTK apps import the backdrop blur"
grep -qx 'label { color: red; }' "$gtk_css" || fail "glassy keeps the user's own GTK CSS"
run omarchy-hyprland-window-transparency glassy
(( $(grep -c 'omarchy-glass begin' "$gtk_css") == 1 )) || fail "glassy GTK apps import the backdrop blur once"
run omarchy-hyprland-window-transparency transparent
[[ $(<"$gtk_css") == 'label { color: red; }' ]] || fail "leaving glassy restores the user's GTK CSS"
grep -qF 'backdrop-filter: blur(' "$ROOT/default/gtk/glass.css" || fail "the GTK glass is a backdrop blur"
printf 'label { color: red; }' >"$gtk_css"
run omarchy-hyprland-window-transparency glassy
run omarchy-hyprland-window-transparency transparent
[[ $(od -An -c "$gtk_css" | tr -d ' \n') == 'label{color:red;}' ]] || fail "leaving glassy restores GTK CSS without a final newline"
# A GTK config that cannot be written fails the change rather than announcing it.
printf 'label { color: red; }\n' >"$gtk_css"
chmod a-w "$gtk_css"
: >"$tmpdir/commands.log"
if run omarchy-hyprland-window-transparency glassy 2>/dev/null; then
chmod u+w "$gtk_css"
fail "a GTK config that cannot be written fails the change"
fi
chmod u+w "$gtk_css"
! grep -q '^omarchy-notification-send' "$tmpdir/commands.log" || fail "a failed change is not announced"
[[ $(run omarchy-hyprland-window-transparency) == "transparent" ]] || fail "a failed change keeps the previous choice"
run omarchy-hyprland-window-transparency transparent
pass "glassy GTK apps get a backdrop blur, and leaving glassy takes it out"
# Opaque reaches the windows Omarchy makes transparent through their tag.
grep -qF 'tag = "+transparent-window"' "$ROOT/default/hypr/helpers.lua" || fail "transparent windows carry a tag"
grep -qF 'o.window({ tag = "transparent-window" }, { opacity = "1 1" })' "$ROOT/default/hypr/toggles/window-opaque.lua" ||
fail "opaque windows apply to the tagged windows"
pass "opaque windows apply to the windows Omarchy makes transparent"
# Terminals turn compositor blur down and fade their text with the window, so
# glassy gives each theme terminal file a see-through, blurred background.
theme_dir="$tmpdir/theme"
mkdir -p "$theme_dir"
printf '[colors.primary]\nbackground = "#000000"\n' >"$theme_dir/alacritty.toml"
printf '[colors-dark]\nbackground=000000\n' >"$theme_dir/foot.ini"
printf 'background #000000\n' >"$theme_dir/kitty.conf"
printf 'background = #000000\nbackground-opacity = 0.9\n' >"$theme_dir/ghostty.conf"
printf 'theme[main_bg]="#102030"\ntheme[main_fg]="#ffffff"\n' >"$theme_dir/btop.theme"
cp -r "$theme_dir" "$tmpdir/theme-before"
run omarchy-hyprland-window-transparency glassy
run omarchy-theme-set-glass "$theme_dir"
run omarchy-theme-set-glass "$theme_dir"
grep -qx 'opacity = 0.65' "$theme_dir/alacritty.toml" || fail "glassy alacritty is see-through"
grep -qx 'alpha=0.65' "$theme_dir/foot.ini" && grep -qx 'blur=yes' "$theme_dir/foot.ini" || fail "glassy foot is see-through and asks for blur"
grep -qx 'background_opacity 0.65' "$theme_dir/kitty.conf" || fail "glassy kitty is see-through"
(( $(grep -c 'omarchy-glass begin' "$theme_dir/foot.ini") == 1 )) || fail "glassy terminals get the glass once"
[[ $(grep '^theme\[main_bg\]=' "$theme_dir/btop.theme" | tail -1) == 'theme[main_bg]=""' ]] || fail "glassy btop uses the terminal background"
(( $(grep -c 'omarchy-glass begin' "$theme_dir/btop.theme") == 1 )) || fail "glassy btop gets the glass once"
pass "btop follows the glassy terminal background"
(( $(grep -c 'background-opacity' "$theme_dir/ghostty.conf") == 1 )) &&
grep -qx 'background-opacity = 0.9' "$theme_dir/ghostty.conf" || fail "a theme's own terminal opacity is kept"
grep -qx "gtk-custom-css = $ROOT/default/gtk/glass.css" "$theme_dir/ghostty.conf" ||
fail "a ghostty theme with its own opacity still gets the backdrop blur"
# A foot theme with its own alpha keeps it but still asks for blur, as
# Hyprland skips blur for foot unless it does.
own_alpha_dir="$tmpdir/own-alpha-theme"
mkdir -p "$own_alpha_dir"
printf '[colors-dark]\nbackground=000000\nalpha=0.8\n' >"$own_alpha_dir/foot.ini"
run omarchy-theme-set-glass "$own_alpha_dir"
(( $(grep -c '^alpha=' "$own_alpha_dir/foot.ini") == 1 )) && grep -qx 'alpha=0.8' "$own_alpha_dir/foot.ini" &&
grep -qx 'blur=yes' "$own_alpha_dir/foot.ini" || fail "a foot theme with its own alpha still asks for blur"
if command -v foot >/dev/null; then
foot --check-config -c "$own_alpha_dir/foot.ini" || fail "a foot theme with its own alpha stays valid"
fi
pass "a theme's own terminal opacity is kept, and its blur is still added"
if command -v foot >/dev/null; then
foot --check-config -c "$theme_dir/foot.ini" || fail "glassy foot config is valid"
fi
# A window table of the theme's own takes the glass in, as TOML refuses a
# table declared twice.
window_dir="$tmpdir/window-theme"
mkdir -p "$window_dir"
printf '[window] # mine\npadding = { x = 4, y = 4 }\nblur = false\n\n[colors.primary]\nbackground = "#000000"\n' >"$window_dir/alacritty.toml"
cp "$window_dir/alacritty.toml" "$tmpdir/window-before.toml"
run omarchy-theme-set-glass "$window_dir"
run omarchy-theme-set-glass "$window_dir"
(( $(grep -c '^\[window\]' "$window_dir/alacritty.toml") == 1 )) || fail "glassy alacritty keeps a single window table"
if command -v python3 >/dev/null; then
python3 -c 'import sys, tomllib; c = tomllib.load(open(sys.argv[1], "rb")); assert c["window"]["opacity"] == 0.65 and c["window"]["padding"]["x"] == 4' "$window_dir/alacritty.toml" ||
fail "glassy alacritty with a window table of its own stays valid TOML"
fi
HOME="$home_dir" XDG_STATE_HOME="$tmpdir/no-glass" OMARCHY_PATH="$ROOT" PATH="$stub_dir:$ROOT/bin:$PATH" omarchy-theme-set-glass "$window_dir"
cmp -s "$tmpdir/window-before.toml" "$window_dir/alacritty.toml" || fail "leaving glassy restores an alacritty window table"
pass "glassy alacritty joins a window table the theme already has"
# A file without a final newline gets one with the glass, and loses it again
# when the glass comes out, so leaving glassy restores it byte for byte.
bare_dir="$tmpdir/bare-theme"
mkdir -p "$bare_dir"
printf 'background #000000' >"$bare_dir/kitty.conf"
cp "$bare_dir/kitty.conf" "$tmpdir/bare-before.conf"
run omarchy-theme-set-glass "$bare_dir"
grep -qx 'background_opacity 0.65' "$bare_dir/kitty.conf" || fail "glassy reaches a file without a final newline"
grep -qx 'background #000000' "$bare_dir/kitty.conf" || fail "glassy ends the line before its block"
HOME="$home_dir" XDG_STATE_HOME="$tmpdir/no-glass" OMARCHY_PATH="$ROOT" PATH="$stub_dir:$ROOT/bin:$PATH" omarchy-theme-set-glass "$bare_dir"
cmp -s "$tmpdir/bare-before.conf" "$bare_dir/kitty.conf" || fail "leaving glassy restores a file without a final newline"
pass "leaving glassy restores a file without a final newline byte for byte"
btop_dir="$tmpdir/transparent-btop-theme"
mkdir -p "$btop_dir"
printf 'theme[main_bg]=""\n' >"$btop_dir/btop.theme"
cp "$btop_dir/btop.theme" "$tmpdir/btop-before.theme"
run omarchy-theme-set-glass "$btop_dir"
cmp -s "$tmpdir/btop-before.theme" "$btop_dir/btop.theme" || fail "btop themes already using the terminal background are kept"
pass "btop themes already using the terminal background are kept"
ghostty_dir="$tmpdir/ghostty-theme"
mkdir -p "$ghostty_dir"
printf 'background = #000000\n' >"$ghostty_dir/ghostty.conf"
run omarchy-theme-set-glass "$ghostty_dir"
grep -qx 'background-opacity = 0.65' "$ghostty_dir/ghostty.conf" &&
grep -qx "gtk-custom-css = $ROOT/default/gtk/glass.css" "$ghostty_dir/ghostty.conf" ||
fail "glassy ghostty is see-through and loads the GTK backdrop blur"
pass "glassy terminals get a see-through, blurred background"
run omarchy-hyprland-window-transparency transparent
run omarchy-theme-set-glass "$theme_dir"
diff -r "$tmpdir/theme-before" "$theme_dir" || fail "leaving glassy restores the terminal files"
pass "leaving glassy restores the terminal files"
# Running foot terminals take the theme's background alpha over OSC, so a
# change of transparency reaches them without a restart. script stands in for
# foot: its child sits on a real pty, and whatever reaches the pty lands in the
# typescript.
if command -v script >/dev/null; then
foot_home="$tmpdir/foot-home"
foot_theme="$foot_home/.local/state/omarchy/current/theme"
mkdir -p "$foot_theme" "$tmpdir/foot-bin"
printf 'background = "#102030"\nforeground = "#ffffff"\n' >"$foot_theme/colors.toml"
printf '[colors-dark]\nbackground=102030\n' >"$foot_theme/foot.ini"
script -qfc "sleep 30" "$tmpdir/typescript" >/dev/null 2>&1 &
script_pid=$!
for _ in {1..50}; do pgrep -P "$script_pid" >/dev/null && break; sleep 0.1; done
# Only the foot lookup is faked; finding its shell goes to the real pgrep.
real_pgrep=$(command -v pgrep)
printf '#!/bin/bash\nif [[ $1 == "-x" && $2 == "foot" ]]; then echo %s; else exec %s "$@"; fi\n' "$script_pid" "$real_pgrep" >"$tmpdir/foot-bin/pgrep"
chmod +x "$tmpdir/foot-bin/pgrep"
set_foot() {
HOME="$foot_home" PATH="$tmpdir/foot-bin:$ROOT/bin:$PATH" omarchy-theme-set-foot
sleep 0.3
}
set_foot
grep -qF $'\e]11;[100]#102030' "$tmpdir/typescript" || fail "running foot terminals stay opaque without glass"
printf '# omarchy-glass begin\n[colors-dark]\nalpha=0.65\nblur=yes\n# omarchy-glass end\n' >>"$foot_theme/foot.ini"
set_foot
grep -qF $'\e]11;[65]#102030' "$tmpdir/typescript" || fail "running foot terminals turn glassy"
kill "$script_pid" 2>/dev/null || true
pass "running foot terminals take the theme's background alpha"
else
skip "script is not installed"
fi
grep -qx 'blur=yes' "$ROOT/default/themed/foot.ini.tpl" || fail "foot starts ready to blur"
grep -qx 'dynamic_background_opacity yes' "$ROOT/default/themed/kitty.conf.tpl" || fail "kitty starts ready to change opacity"
pass "foot and kitty start ready for glass, since they read that only at launch"