* Give scratchpad a Quake-style presentation
* Keep the Quake scratchpad from restyling every window
The presentation was bought with global decoration defaults: rounding went
0 -> 5 and both shadow and blur were switched back on for every window on
the system, undoing 935283c8. Blur in particular is close to invisible
here, since every window is already tagged 0.985/0.96 opacity and no layer
rule asks for it, so it was GPU load on every frame for almost nothing.
Put the globals back and scope the rounding to the scratchpad with a window
rule, the same way popped windows already get theirs. The inset, dim_special
and the slide carry the effect on their own. dim_special only applies while
a special workspace is open, so it stays.
Also drop the four workspace-rule booleans that only restated Hyprland's
defaults, fold the stale scratchpad rows in the hotkey table into the new
ones, and give the binding assertions their own fixture instead of borrowing
the bar-panel one.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Omabot <david@hey.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
244 lines
10 KiB
Bash
244 lines
10 KiB
Bash
#!/bin/bash
|
|
|
|
source "$(dirname "${BASH_SOURCE[0]}")/base-test.sh"
|
|
|
|
require_command lua
|
|
|
|
run_application_bindings() {
|
|
local home="$1"
|
|
local prelude="${2:-}"
|
|
|
|
HOME="$home" XDG_CONFIG_HOME="$home/.config" XDG_STATE_HOME="$home/.local/state" OMARCHY_PATH="$ROOT" OMARCHY_BINDING_PRELUDE="$prelude" lua <<'LUA'
|
|
package.path = os.getenv("HOME") .. "/.config/?.lua;" .. os.getenv("OMARCHY_PATH") .. "/?.lua;" .. package.path
|
|
|
|
local prelude = os.getenv("OMARCHY_BINDING_PRELUDE") or ""
|
|
if prelude ~= "" then
|
|
assert(load(prelude))()
|
|
end
|
|
|
|
hl = {
|
|
dsp = {
|
|
exec_cmd = function(command)
|
|
return { kind = "exec", arg = command }
|
|
end,
|
|
},
|
|
bind = function(keys, dispatcher, opts)
|
|
opts = opts or {}
|
|
if opts.description then
|
|
print(keys .. "\t" .. opts.description)
|
|
end
|
|
end,
|
|
}
|
|
|
|
require("default.hypr.helpers")
|
|
require("default.hypr.bindings.applications")
|
|
LUA
|
|
}
|
|
|
|
run_omarchy_bindings() {
|
|
local home="$1"
|
|
local prelude="${2:-}"
|
|
|
|
HOME="$home" XDG_CONFIG_HOME="$home/.config" XDG_STATE_HOME="$home/.local/state" OMARCHY_PATH="$ROOT" OMARCHY_BINDING_PRELUDE="$prelude" lua <<'LUA'
|
|
package.path = os.getenv("HOME") .. "/.config/?.lua;" .. os.getenv("OMARCHY_PATH") .. "/?.lua;" .. package.path
|
|
|
|
local function proxy()
|
|
return setmetatable({}, {
|
|
__index = function(self, key)
|
|
local value = proxy()
|
|
rawset(self, key, value)
|
|
return value
|
|
end,
|
|
__call = function()
|
|
return {}
|
|
end,
|
|
})
|
|
end
|
|
|
|
local prelude = os.getenv("OMARCHY_BINDING_PRELUDE") or ""
|
|
if prelude ~= "" then
|
|
assert(load(prelude))()
|
|
end
|
|
|
|
hl = setmetatable({
|
|
dsp = proxy(),
|
|
bind = function(keys, dispatcher, opts)
|
|
opts = opts or {}
|
|
if opts.description then
|
|
print(keys .. "\t" .. opts.description)
|
|
end
|
|
end,
|
|
config = function() end,
|
|
env = function() end,
|
|
monitor = function() end,
|
|
window_rule = function() end,
|
|
workspace_rule = function() end,
|
|
layer_rule = function() end,
|
|
gesture = function() end,
|
|
animation = function() end,
|
|
curve = function() end,
|
|
exec_cmd = function() end,
|
|
dispatch = function() end,
|
|
on = function() end,
|
|
timer = function() end,
|
|
get_config = function() return nil end,
|
|
get_active_window = function() return nil end,
|
|
}, {
|
|
__index = function()
|
|
return function()
|
|
return {}
|
|
end
|
|
end,
|
|
})
|
|
|
|
require("default.hypr.omarchy")
|
|
LUA
|
|
}
|
|
|
|
tmpdir=$(mktemp -d)
|
|
trap 'rm -rf "$tmpdir"' EXIT
|
|
|
|
fresh_home="$tmpdir/fresh-home"
|
|
mkdir -p "$fresh_home"
|
|
fresh_output=$(run_application_bindings "$fresh_home")
|
|
grep -Fq $'SUPER + RETURN Terminal' <<<"$fresh_output" || fail "default application bindings include essentials"
|
|
grep -Fq $'SUPER + SHIFT + A ChatGPT' <<<"$fresh_output" || fail "default application bindings include preinstalled web apps"
|
|
pass "default application bindings load from package defaults"
|
|
|
|
grep -F 'hl.dsp.send_key_state({ mods = mods, key = key, state = "down" })' "$ROOT/default/hypr/bindings/clipboard.lua" >/dev/null ||
|
|
fail "universal clipboard shortcuts send explicit mods to the focused surface"
|
|
pass "universal clipboard shortcuts send explicit mods to the focused surface"
|
|
|
|
if grep -E 'send_key_state\(\{[^}]*window' "$ROOT/default/hypr/bindings/clipboard.lua" >/dev/null; then
|
|
fail "universal clipboard shortcuts do not target only normal windows"
|
|
fi
|
|
pass "universal clipboard shortcuts do not exclude layer-shell fields"
|
|
|
|
if grep -F 'wtype -M' "$ROOT/default/hypr/bindings/clipboard.lua" >/dev/null; then
|
|
fail "universal clipboard shortcuts avoid the virtual keyboard so held SUPER cannot merge in"
|
|
fi
|
|
pass "universal clipboard shortcuts avoid virtual keyboard modifier merging"
|
|
|
|
removed_home="$tmpdir/removed-home"
|
|
mkdir -p "$removed_home/.local/state/omarchy"
|
|
touch "$removed_home/.local/state/omarchy/preinstalls-removed"
|
|
removed_output=$(run_application_bindings "$removed_home")
|
|
grep -Fq $'SUPER + RETURN Terminal' <<<"$removed_output" || fail "preinstall removal keeps essential bindings"
|
|
if grep -Fq $'SUPER + SHIFT + A ChatGPT' <<<"$removed_output"; then
|
|
fail "preinstall removal skips preinstalled web app bindings"
|
|
fi
|
|
pass "preinstall removal flag skips optional application bindings"
|
|
|
|
variable_home="$tmpdir/variable-home"
|
|
mkdir -p "$variable_home"
|
|
variable_output=$(run_application_bindings "$variable_home" 'omarchy_preinstalled_bindings = false')
|
|
grep -Fq $'SUPER + RETURN Terminal' <<<"$variable_output" || fail "preinstalled binding variable keeps essential bindings"
|
|
if grep -Fq $'SUPER + SHIFT + A ChatGPT' <<<"$variable_output"; then
|
|
fail "preinstalled binding variable skips optional application bindings"
|
|
fi
|
|
pass "preinstalled binding variable skips optional application bindings"
|
|
|
|
no_bindings_home="$tmpdir/no-bindings-home"
|
|
mkdir -p "$no_bindings_home"
|
|
no_bindings_output=$(run_omarchy_bindings "$no_bindings_home" 'omarchy_default_bindings = false')
|
|
[[ -z $no_bindings_output ]] || fail "default binding variable disables all Omarchy bindings" "$no_bindings_output"
|
|
pass "default binding variable disables all Omarchy bindings"
|
|
|
|
voxtype_home="$tmpdir/voxtype-home"
|
|
voxtype_bin="$tmpdir/voxtype-bin"
|
|
mkdir -p "$voxtype_home" "$voxtype_bin"
|
|
touch "$voxtype_bin/voxtype"
|
|
chmod +x "$voxtype_bin/voxtype"
|
|
voxtype_output=$(PATH="$voxtype_bin:$PATH" run_omarchy_bindings "$voxtype_home")
|
|
grep -Fq $'SUPER + CTRL + X Toggle dictation' <<<"$voxtype_output" ||
|
|
fail "installed Voxtype enables its toggle binding"
|
|
grep -Fq $'F9 Start dictation (push-to-talk)' <<<"$voxtype_output" ||
|
|
fail "installed Voxtype enables its push-to-talk binding"
|
|
grep -Fq $'F9 Stop dictation (push-to-talk)' <<<"$voxtype_output" ||
|
|
fail "installed Voxtype enables its release binding"
|
|
pass "installed Voxtype conditionally enables dictation bindings"
|
|
|
|
voxtype_without_execute_output=$(PATH="$voxtype_bin:$PATH" run_omarchy_bindings \
|
|
"$voxtype_home" 'os.execute = function() return nil, "No child processes", 10 end')
|
|
grep -Fq $'SUPER + CTRL + X Toggle dictation' <<<"$voxtype_without_execute_output" ||
|
|
fail "Voxtype detection does not require spawning a subprocess"
|
|
pass "installed Voxtype detection works without os.execute"
|
|
|
|
missing_bin="$tmpdir/missing-bin"
|
|
mkdir -p "$missing_bin"
|
|
ln -s "$(command -v lua)" "$missing_bin/lua"
|
|
ln -s "$(command -v lspci)" "$missing_bin/lspci"
|
|
ln -s "$(command -v sort)" "$missing_bin/sort"
|
|
missing_voxtype_output=$(PATH="$missing_bin" run_omarchy_bindings "$voxtype_home")
|
|
if grep -Fq $'SUPER + CTRL + X Toggle dictation' <<<"$missing_voxtype_output"; then
|
|
fail "missing Voxtype skips its bindings"
|
|
fi
|
|
pass "missing Voxtype skips dictation bindings"
|
|
|
|
# The Grave shortcuts are aliases, so the original SUPER + S pair has to keep
|
|
# working alongside them.
|
|
scratchpad_home="$tmpdir/scratchpad-home"
|
|
mkdir -p "$scratchpad_home"
|
|
scratchpad_output=$(run_omarchy_bindings "$scratchpad_home")
|
|
grep -Fqx $'SUPER + S Toggle scratchpad' <<<"$scratchpad_output" ||
|
|
fail "scratchpad keeps its existing toggle binding"
|
|
grep -Fqx $'SUPER + grave Toggle scratchpad' <<<"$scratchpad_output" ||
|
|
fail "scratchpad supports a Quake-style toggle binding"
|
|
grep -Fqx $'SUPER + ALT + S Move window to scratchpad' <<<"$scratchpad_output" ||
|
|
fail "scratchpad keeps its existing move binding"
|
|
grep -Fqx $'SUPER + SHIFT + grave Move window to scratchpad' <<<"$scratchpad_output" ||
|
|
fail "scratchpad supports a Quake-style move binding"
|
|
pass "scratchpad retains existing bindings and adds Grave shortcuts"
|
|
|
|
# The panel hotkeys claim a row of keys that workspace switching already uses
|
|
# under other modifiers, so the count matters as much as the bindings: a tenth
|
|
# claim on SUPER + CTRL + a number is a collision with one of these.
|
|
panels_home="$tmpdir/panels-home"
|
|
mkdir -p "$panels_home"
|
|
panels_output=$(run_omarchy_bindings "$panels_home")
|
|
for panel in 1 2 3 4 5 6 7 8 9; do
|
|
grep -Fqx "SUPER + CTRL + code:$((panel + 9))"$'\t'"Bar panel $panel" <<<"$panels_output" ||
|
|
fail "bar panel hotkeys count the right section" "$panel"
|
|
done
|
|
number_claims=$(cut -f1 <<<"$panels_output" | grep -cE '^SUPER \+ CTRL \+ code:1[0-9]$' || true)
|
|
(( number_claims == 9 )) ||
|
|
fail "only the bar panel hotkeys bind SUPER + CTRL + a number" "$number_claims"
|
|
pass "bar panel hotkeys bind SUPER + CTRL + a number without a collision"
|
|
|
|
migration=$(grep -rl 'Move stock Hyprland user overrides into package defaults' "$ROOT/migrations" | head -n 1 || true)
|
|
[[ -n $migration ]] || fail "Hyprland default config migration exists"
|
|
|
|
migration_home="$tmpdir/migration-home"
|
|
mkdir -p "$migration_home/.config/hypr"
|
|
cat >"$migration_home/.config/hypr/bindings.lua" <<'LUA'
|
|
require("default.hypr.bindings.media")
|
|
require("default.hypr.bindings.clipboard")
|
|
require("default.hypr.bindings.tiling")
|
|
require("default.hypr.bindings.utilities")
|
|
|
|
-- Application bindings without Omarchy's preinstalled web apps, TUIs, or desktop apps.
|
|
o.bind("SUPER + RETURN", "Terminal", { omarchy = "terminal" })
|
|
o.bind("SUPER + SHIFT + RETURN", "Browser", { omarchy = "browser" })
|
|
o.bind("SUPER + SHIFT + F", "File manager", { omarchy = "nautilus" })
|
|
o.bind("SUPER + ALT + SHIFT + F", "File manager (cwd)", { omarchy = "nautilus-cwd" })
|
|
o.bind("SUPER + SHIFT + B", "Browser", { omarchy = "browser" })
|
|
o.bind("SUPER + SHIFT + ALT + B", "Browser (private)", { omarchy = "browser --private" })
|
|
o.bind("SUPER + SHIFT + N", "Editor", { omarchy = "editor" })
|
|
LUA
|
|
HOME="$migration_home" OMARCHY_PATH="$ROOT" bash -euo pipefail "$migration" >/dev/null
|
|
cmp -s "$ROOT/config/hypr/bindings.lua" "$migration_home/.config/hypr/bindings.lua" ||
|
|
fail "plain legacy bindings migrate to the user override stub"
|
|
[[ -f $migration_home/.local/state/omarchy/preinstalls-removed ]] ||
|
|
fail "plain legacy bindings preserve preinstall removal state"
|
|
pass "migration converts plain legacy bindings to package-owned defaults"
|
|
|
|
upgrade_script="$ROOT/bin/omarchy-upgrade-to-quattro"
|
|
grep -Fq 'touch "$state_dir/preinstalls-removed"' "$upgrade_script" ||
|
|
fail "upgrade-to-quattro preserves preinstall removal state"
|
|
|
|
mark_line=$(awk '/^mark_removed_preinstalls_from_legacy_bindings$/ { print NR; exit }' "$upgrade_script")
|
|
copy_line=$(awk '/^copy_always_config_defaults$/ { print NR; exit }' "$upgrade_script")
|
|
[[ -n $mark_line && -n $copy_line ]] || fail "upgrade-to-quattro preinstall marker and config refresh calls exist"
|
|
(( mark_line < copy_line )) || fail "upgrade-to-quattro detects plain legacy bindings before overwriting Hyprland bindings"
|
|
pass "upgrade-to-quattro preserves preinstall removal before refreshing Hyprland bindings"
|