Drive bar/window geometry and CSS tokens from the shell theme manifest
breadbar no longer hardcodes BAR_HEIGHT/BAR_MARGIN_TOP/BAR_MARGIN_SIDES/ CHIP_HEIGHT/ICON_PX or the root window's layer-shell setup: it loads bread_theme:🐚:ShellTheme once (theme::shell_theme(), cached in a thread-local) and reads bar.window (anchors, margin, exclusive zone, keyboard mode - now set explicitly instead of relying on the library default) plus tokens.{icon_px,chip_height} from it everywhere those used to be literals. The four satellite surfaces (breadbar-osd, breadbar-notif, breadbar-panel, breadbar-dismiss) now get their anchor/margin/width/layer from the manifest's [surfaces.*] table via a small new surface::apply() helper, narrowly scoped to the three anchor shapes those surfaces actually use. The pre-existing 8px gap between the panel's top margin and the dismiss scrim's is preserved exactly (and now commented) rather than "fixed". theme.rs's load_css() keeps its ~250 lines of hand-written breadbar CSS (notifications, wifi popover, control panel, media widget) but now reads its five radius/pad locals and the two easing curves (spring vs spring_settle - hover/settle transitions were previously miscategorized as the overshoot curve in the constant audit; the actual code already used the settle curve there, confirmed against src) from theme tokens instead of hardcoding them. Also wires bread_theme:🐚:watch() so editing the active theme's theme.toml/extra.css hot-reloads CSS tokens without a restart, same as a pywal palette change already does. Window-spec values still need a restart per the plan (read once at window-construction time). Verified pixel-identical: captured all 10 breadbar --screenshot views (bar, control-panel, connectivity-wifi/bluetooth, media-popover, notification/-critical, osd-volume/-brightness, wifi-add-dialog) via bread-capture's isolated headless-Sway harness against both the pre-change and post-change binaries; every view diffs byte-identical at the decoded-pixel level.
This commit is contained in:
parent
297207a7aa
commit
bbb1a6c8d2
11 changed files with 278 additions and 99 deletions
78
src/surface.rs
Normal file
78
src/surface.rs
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
//! Applies a `[surfaces.<namespace>]` entry (plan §4/§6, Phase 2) to a
|
||||
//! satellite layer-shell window: anchor, margin (from `offset`), width and
|
||||
//! layer. Deliberately narrow — it only understands the three anchor shapes
|
||||
//! breadbar's four built-in surfaces actually use today ("breadbar-notif",
|
||||
//! "breadbar-osd", "breadbar-panel", "breadbar-dismiss": `top_right`,
|
||||
//! `bottom_centre`, `fill`), not a general anchor DSL (the plan's own
|
||||
//! anti-goal, §2). `exclusive` zone and `keyboard` mode aren't part of the
|
||||
//! `[surfaces.*]` schema (`bread_theme::shell::Surface` has no such fields)
|
||||
//! and stay hardcoded at each call site, same as before this refactor.
|
||||
|
||||
use bread_theme::shell::SurfaceWidth;
|
||||
use gtk4::prelude::*;
|
||||
use gtk4_layer_shell::{Edge, Layer, LayerShell};
|
||||
|
||||
/// `namespace` should be a key in the active theme's `[surfaces.*]` table —
|
||||
/// every call site in this crate passes one of breadbar's own namespace
|
||||
/// literals, so a miss here means the active theme fell out of sync with
|
||||
/// the Rust source, not a bad runtime value. Logs and leaves the window at
|
||||
/// gtk4-layer-shell's own defaults rather than panicking, matching every
|
||||
/// other "malformed/incomplete theme" fallback in this system.
|
||||
///
|
||||
/// Does not set `set_default_width` for a namespace shared by more than one
|
||||
/// window with genuinely different widths (`breadbar-notif`'s live toast is
|
||||
/// 320px, its history sibling is 360px, and only the toast's width is
|
||||
/// modeled in `[surfaces.*]` — see the Phase 0 constant inventory); callers
|
||||
/// that need a different width than the theme's own set it explicitly
|
||||
/// afterward.
|
||||
pub fn apply(window: >k4::Window, namespace: &str) {
|
||||
let theme = crate::theme::shell_theme();
|
||||
let Some(surf) = theme.surfaces().get(namespace) else {
|
||||
eprintln!(
|
||||
"breadbar: no [surfaces.{namespace}] entry in the active theme; \
|
||||
window left at layer-shell defaults"
|
||||
);
|
||||
return;
|
||||
};
|
||||
|
||||
window.set_layer(if surf.layer == "top" {
|
||||
Layer::Top
|
||||
} else {
|
||||
Layer::Overlay
|
||||
});
|
||||
|
||||
match surf.anchor.as_str() {
|
||||
"top_right" => {
|
||||
window.set_anchor(Edge::Top, true);
|
||||
window.set_anchor(Edge::Right, true);
|
||||
// offset = [right, top] for this anchor shape.
|
||||
let right = surf.offset.first().copied().unwrap_or(0.0) as i32;
|
||||
let top = surf.offset.get(1).copied().unwrap_or(0.0) as i32;
|
||||
window.set_margin(Edge::Right, right);
|
||||
window.set_margin(Edge::Top, top);
|
||||
}
|
||||
"bottom_centre" => {
|
||||
window.set_anchor(Edge::Bottom, true);
|
||||
let bottom = surf.offset.first().copied().unwrap_or(0.0) as i32;
|
||||
window.set_margin(Edge::Bottom, bottom);
|
||||
}
|
||||
"fill" => {
|
||||
for edge in [Edge::Top, Edge::Bottom, Edge::Left, Edge::Right] {
|
||||
window.set_anchor(edge, true);
|
||||
}
|
||||
// Only a top margin is meaningful here — a fullscreen click-away
|
||||
// scrim that starts below the bar rather than covering it.
|
||||
let top = surf.offset.first().copied().unwrap_or(0.0) as i32;
|
||||
window.set_margin(Edge::Top, top);
|
||||
}
|
||||
other => eprintln!(
|
||||
"breadbar: surfaces.{namespace}.anchor = \"{other}\" is not one of \
|
||||
top_right|bottom_centre|fill — breadbar's satellite windows don't \
|
||||
understand any other shape yet, leaving this window unanchored"
|
||||
),
|
||||
}
|
||||
|
||||
if let SurfaceWidth::Px(px) = surf.width {
|
||||
window.set_default_width(px);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue