bread-theme: generate Hyprland layer rules from the shell theme (Phase 4a)
Adds `bread-theme layerrules`, which writes the active shell theme's [compositor] table to ~/.config/hypr/layerrules.json (atomic write). This lets ~/.config/hypr/scripts/ui/rules.lua read theme-driven blur/transparency/ animation for the breadbar/breadbox layer-shell namespaces instead of having them hardcoded, following THEME_SYSTEM_PLAN.md §9. rules.lua keeps its previous hardcoded rules as a pcall-guarded fallback for when the JSON is missing or malformed (lives outside this repo, so not part of this commit). Also fixes a pre-existing test race: shell::tests and the new layerrules::tests both mutate XDG_CONFIG_HOME in parallel `cargo test` threads but previously used separate, unrelated locks (or none), so they could observe each other's env var changes mid-test. Both now share bread_theme::test_support::XDG_CONFIG_HOME_LOCK.
This commit is contained in:
parent
92d3362a6b
commit
ea9758a5d5
6 changed files with 241 additions and 14 deletions
|
|
@ -403,13 +403,6 @@ pub fn list() -> Vec<ThemeSummary> {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::sync::Mutex;
|
||||
|
||||
// Guards mutation of XDG_CONFIG_HOME / BREAD_SHELL_THEME, which are
|
||||
// process-global — mirrors bread_theme::output's XDG_ENV_LOCK pattern
|
||||
// (a different env var, same reason: cargo test runs a module's tests
|
||||
// in parallel by default).
|
||||
static ENV_LOCK: Mutex<()> = Mutex::new(());
|
||||
|
||||
struct EnvGuard {
|
||||
_lock: std::sync::MutexGuard<'static, ()>,
|
||||
|
|
@ -437,7 +430,12 @@ mod tests {
|
|||
/// whatever's set in the outer test-runner environment. Held for the
|
||||
/// guard's lifetime.
|
||||
fn isolated_xdg() -> EnvGuard {
|
||||
let lock = ENV_LOCK.lock().unwrap_or_else(|e| e.into_inner());
|
||||
// Shared with `layerrules::tests`, which also isolates
|
||||
// XDG_CONFIG_HOME — see `crate::test_support` for why this must be
|
||||
// the *same* lock rather than a module-private one.
|
||||
let lock = crate::test_support::XDG_CONFIG_HOME_LOCK
|
||||
.lock()
|
||||
.unwrap_or_else(|e| e.into_inner());
|
||||
let dir = std::env::temp_dir().join(format!(
|
||||
"bread-theme-shell-test-{}-{}",
|
||||
std::process::id(),
|
||||
|
|
|
|||
|
|
@ -181,9 +181,18 @@ pub struct Surface {
|
|||
/// ignore_alpha, blur_popups, animation, no_anim) — that Lua API isn't in
|
||||
/// hyprland-api.lua's type annotations, so this field set is evidenced by
|
||||
/// working usage, not documentation (plan §12 risk 3).
|
||||
#[derive(Debug, Clone, PartialEq, Default)]
|
||||
///
|
||||
/// Also `Serialize`: this is the per-namespace shape written to
|
||||
/// `~/.config/hypr/layerrules.json` by `bread_theme::layerrules` (plan §9
|
||||
/// step 3-4), which `scripts/ui/rules.lua` parses back into `hl.layer_rule`
|
||||
/// calls. `Option::None` fields are omitted rather than emitted as `null` —
|
||||
/// the Lua JSON reader treats a missing key and a `null` value identically
|
||||
/// (assigning `nil` into a table key is a no-op), so either encoding is
|
||||
/// correct, but omitting keeps the file legible for hand inspection.
|
||||
#[derive(Debug, Clone, PartialEq, Default, serde::Serialize)]
|
||||
pub struct LayerRule {
|
||||
pub blur: bool,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub ignore_alpha: Option<f64>,
|
||||
pub blur_popups: bool,
|
||||
/// Passed through verbatim to `hl.layer_rule`'s `animation` field
|
||||
|
|
@ -192,6 +201,7 @@ pub struct LayerRule {
|
|||
/// evidenced by working usage in `rules.lua`, not documented (plan §12
|
||||
/// risk 3); a closed Rust enum here would need updating in lockstep
|
||||
/// with Hyprland additions this crate has no way to know about.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub animation: Option<String>,
|
||||
pub no_anim: bool,
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue