Finish threading the accent colour through the whole desktop

The recent accent-colour setting only reached part of the desktop.
looks.lua still hardcoded the focused-window border and glow to blue,
so any hyprctl reload -- or every fresh session, for about a second --
reverted a chosen accent; it now reads accentName the same way it
already read colorScheme. The lock screen and terminal stayed blue
regardless of the chosen accent despite the setting's own description
claiming otherwise; panama-lock and panama-theme-apps now resolve and
apply the real accent.

AccentPicker built its swatch model from Theme.accents directly
instead of the schema's own options list, so the two could drift
silently; switched it to read the schema. Its hit target only covered
the swatch, not the name label added specifically for colour-vision
accessibility -- extended to the whole row. Settings search had no
route for the "appearance" group, so searching for the accent or
colour scheme landed on Home.

ColorScheme's hex-to-Hyprland helper assumed 6-digit colours and would
silently corrupt a future translucent one; fixed it to read from the
end of the string instead of the start. An accent-only change no
longer reruns the full colour-scheme pipeline. The gradient it builds
for the focused border now goes through SystemSettings' existing
serialiser instead of a second, under-escaped copy of the same logic.

The settings-ownership contract test enforced the old rule that
ColorScheme must never touch the focused border; updated it to verify
the real, intended rule instead of contradicting the code.

Claude-Session: https://claude.ai/code/session_01E6TJUAh41HaP25MVHWkhRZ
This commit is contained in:
Gabriel Brown
2026-08-18 21:23:16 -04:00
parent 8b59b78d9f
commit 9ba224d776
9 changed files with 301 additions and 83 deletions
+42 -7
View File
@@ -1,9 +1,10 @@
#!/usr/bin/env bash
# Generates Panama's hyprlock configuration into the state directory. The
# tracked config is never rewritten and remains the fallback if generation
# fails, so a malformed preference can never leave the session without a
# working locker.
# gitignored fallback config (rendered from the tracked .template at link
# time) is never rewritten by this script and remains the fallback if
# generation fails, so a malformed preference can never leave the session
# without a working locker.
set -euo pipefail
@@ -78,6 +79,31 @@ valid_path() {
[[ "$1" == /* && "$1" != *","* && "$1" != *$'\n'* ]]
}
# Same 8 named accents as config/Theme.qml's `accents` map (kept in sync by
# hand -- there is no shared source between QML and a shell script), primary
# hue per scheme only: the lock screen shows a flat focus ring, not the
# two-stop gradient the window border does. Falls back to blue for an unknown
# name, matching Theme.accentPair's own fallback.
accent_hex() {
local name="$1" scheme="$2"
case "$name" in
orchid) [[ "$scheme" == light ]] && printf '7847bd' || printf 'c099ff' ;;
teal) [[ "$scheme" == light ]] && printf '007197' || printf '86e1fc' ;;
green) [[ "$scheme" == light ]] && printf '587539' || printf 'c3e88d' ;;
amber) [[ "$scheme" == light ]] && printf '8c6c3e' || printf 'ffc777' ;;
orange) [[ "$scheme" == light ]] && printf 'b15c00' || printf 'ff966c' ;;
rose) [[ "$scheme" == light ]] && printf 'f52a65' || printf 'ff757f' ;;
slate) [[ "$scheme" == light ]] && printf '6172b0' || printf '828bb8' ;;
*) [[ "$scheme" == light ]] && printf '2e7de9' || printf '82aaff' ;;
esac
}
# hyprlock wants "R, G, B" decimal, not hex.
hex_to_rgb() {
local hex="$1"
printf '%d, %d, %d' "0x${hex:0:2}" "0x${hex:2:2}" "0x${hex:4:2}"
}
load_preferences() {
if [[ -r "$settings" ]] && jq -e 'type == "object"' "$settings" >/dev/null 2>&1; then
settings_valid=true
@@ -99,6 +125,12 @@ load_preferences() {
color_scheme="$(read_string colorScheme dark)"
[[ "$color_scheme" == dark || "$color_scheme" == light ]] || color_scheme=dark
accent_name="$(read_string accentName blue)"
case "$accent_name" in
blue|orchid|teal|green|amber|orange|rose|slate) ;;
*) accent_name=blue ;;
esac
wallpaper_mode="$(read_string wallpaperMode single)"
[[ "$wallpaper_mode" == single || "$wallpaper_mode" == slideshow || "$wallpaper_mode" == per-monitor ]] \
|| wallpaper_mode=single
@@ -121,8 +153,6 @@ load_preferences() {
background_color='rgba(225, 226, 231, 1.0)'
foreground_color='rgba(55, 96, 191, 1.0)'
dim_color='rgba(97, 114, 176, 1.0)'
accent_color='rgba(46, 125, 233, 1.0)'
accent_ring_color='rgba(46, 125, 233, 0.9)'
error_color='rgba(245, 42, 101, 1.0)'
field_color='rgba(208, 213, 227, 0.85)'
dim_hex='6172b0'
@@ -131,13 +161,18 @@ load_preferences() {
background_color='rgba(34, 36, 54, 1.0)'
foreground_color='rgba(200, 211, 245, 1.0)'
dim_color='rgba(130, 139, 184, 1.0)'
accent_color='rgba(130, 170, 255, 1.0)'
accent_ring_color='rgba(130, 170, 255, 0.9)'
error_color='rgba(255, 117, 127, 1.0)'
field_color='rgba(46, 47, 61, 0.85)'
dim_hex='828bb8'
error_hex='ff757f'
fi
# The focus ring is the accent role, not a scheme-relative one: it follows
# accentName the same way ColorScheme.qml's active_border does, and needs
# both the accent and the scheme since each accent carries a separate pair.
accent_rgb="$(hex_to_rgb "$(accent_hex "$accent_name" "$color_scheme")")"
accent_color="rgba($accent_rgb, 1.0)"
accent_ring_color="rgba($accent_rgb, 0.9)"
}
monitor_names() {