Refine shell status controls and glass rendering; defer cursor redraw safely

This commit is contained in:
Samuel Onoja committed 2026-09-26 05:05:50 +01:00
1 parent e85fc1e032
commit b3fa82b53b
53 files changed
+3329 -259

No files matched your search

+111
View File
@@ -25,6 +25,8 @@ pub struct Config {
#[serde(default)]
theme: ThemeConfig,
#[serde(default)]
appearance: AppearanceConfig,
#[serde(default)]
commands: HashMap<String, Vec<String>>,
#[serde(default)]
bindings: Vec<BindingConfig>,
@@ -116,6 +118,9 @@ pub struct ThemeSettings {
pub shadow_blur: f64,
pub shadow_opacity: f64,
pub material_style: MaterialStyle,
pub glass: GlassSettings,
pub material_radius: f64,
pub panel_radius: f64,
}
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq)]
@@ -127,6 +132,56 @@ pub enum MaterialStyle {
Solid,
}
/// Ordered quality tiers; each step retains the preceding reductions.
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Ord, PartialOrd)]
#[serde(rename_all = "snake_case")]
pub enum GlassQuality {
#[default]
Full,
NoGrain,
NoSaturation,
ReducedBlur,
Translucent,
Solid,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct GlassSettings {
pub tint: RgbaColor,
pub blur_scale: f32,
pub grain: bool,
pub quality: GlassQuality,
}
impl Default for GlassSettings {
fn default() -> Self {
Self {
tint: RgbaColor([28.0 / 255.0, 32.0 / 255.0, 46.0 / 255.0, 1.0]),
blur_scale: 1.0,
grain: true,
quality: GlassQuality::Full,
}
}
}
#[derive(Debug, Default, Deserialize)]
struct AppearanceConfig {
corner_radius: Option<f64>,
#[serde(default)]
reduced_effects: bool,
#[serde(default)]
glass: GlassConfig,
}
#[derive(Debug, Default, Deserialize)]
struct GlassConfig {
tint_color: Option<String>,
blur_scale: Option<f64>,
grain: Option<bool>,
#[serde(default)]
quality: GlassQuality,
}
#[derive(Debug, Default, Deserialize)]
struct ThemeConfig {
#[serde(default)]
@@ -202,6 +257,8 @@ struct ThemeGeometryConfig {
focus_ring_width: f64,
#[serde(default = "default_window_radius")]
window_radius: f64,
#[serde(default)]
top_bar_radius: f64,
}
impl Default for ThemeGeometryConfig {
@@ -210,6 +267,7 @@ impl Default for ThemeGeometryConfig {
border_width: default_border_width(),
focus_ring_width: default_focus_ring_width(),
window_radius: default_window_radius(),
top_bar_radius: 0.0,
}
}
}
@@ -803,6 +861,26 @@ impl Config {
let shadow_opacity =
unit_theme_value(self.theme.shadow.soft.opacity, "shadow.soft.opacity")?;
let mut glass = GlassSettings::default();
if let Some(tint) = &self.appearance.glass.tint_color {
glass.tint = parse_color(tint, "appearance.glass.tint_color")?;
// Opacity belongs to the semantic role, never the color token.
glass.tint.0[3] = 1.0;
}
glass.blur_scale = finite_theme_value(
self.appearance.glass.blur_scale.unwrap_or(1.0),
"appearance.glass.blur_scale",
)?
.clamp(0.5, 1.5) as f32;
glass.grain = self.appearance.glass.grain.unwrap_or(true);
glass.quality = self.appearance.glass.quality;
if self.appearance.reduced_effects {
glass.quality = glass.quality.max(GlassQuality::ReducedBlur);
}
let material_radius = nonnegative_theme_value(
self.appearance.corner_radius.unwrap_or(14.0),
"appearance.corner_radius",
)?;
Ok(ThemeSettings {
border_width,
focus_ring_width,
@@ -818,6 +896,12 @@ impl Config {
shadow_blur,
shadow_opacity,
material_style: self.theme.material.style,
glass,
material_radius,
panel_radius: nonnegative_theme_value(
self.theme.geometry.top_bar_radius,
"geometry.top_bar_radius",
)?,
})
}
@@ -1581,6 +1665,30 @@ mod tests {
assert!(invalid.gap_config().is_err());
}
#[test]
fn glass_configuration_clamps_cost_and_rejects_nonfinite_values() {
for (value, expected) in [(0.1, 0.5), (1.2, 1.2), (100.0, 1.5)] {
let config = parse(&format!("[appearance.glass]\nblur_scale = {value}"));
assert_eq!(config.theme_settings().unwrap().glass.blur_scale, expected);
}
for value in ["nan", "inf", "-inf"] {
assert!(
parse(&format!("[appearance.glass]\nblur_scale = {value}"))
.theme_settings()
.is_err()
);
}
let settings = parse("[appearance]\nreduced_effects = true\ncorner_radius = 17.0\n[appearance.glass]\ntint_color = \"#123456\"\ngrain = false")
.theme_settings().unwrap();
assert_eq!(settings.glass.quality, GlassQuality::ReducedBlur);
assert!(!settings.glass.grain);
assert_eq!(settings.material_radius, 17.0);
assert_eq!(
settings.glass.tint,
RgbaColor([18.0 / 255.0, 52.0 / 255.0, 86.0 / 255.0, 1.0])
);
}
#[test]
fn parses_and_validates_theme_window_tokens() {
let configured = parse(
@@ -1604,6 +1712,9 @@ mod tests {
shadow_blur: 24.0,
shadow_opacity: 0.4,
material_style: MaterialStyle::Translucent,
glass: GlassSettings::default(),
material_radius: 14.0,
panel_radius: 0.0,
}
);
assert!(invalid_color.theme_settings().is_err());