diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2025-09-20 12:57:41 +0300 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2025-10-02 09:33:08 +0300 |
| commit | 1fa9dd32ed028c88248644a13421c098fef72894 (patch) | |
| tree | e6ea60b5b0b7ebc390ecc623b091bbe3dc40fdf0 | |
| parent | 2781d3a74338806f631acda99e9f702b1b59a3e6 (diff) | |
| download | niri-1fa9dd32ed028c88248644a13421c098fef72894.tar.gz niri-1fa9dd32ed028c88248644a13421c098fef72894.tar.bz2 niri-1fa9dd32ed028c88248644a13421c098fef72894.zip | |
config: Split Layout from LayoutPart
| -rw-r--r-- | niri-config/src/appearance.rs | 214 | ||||
| -rw-r--r-- | niri-config/src/layout.rs | 127 | ||||
| -rw-r--r-- | niri-config/src/lib.rs | 480 | ||||
| -rw-r--r-- | niri-config/src/macros.rs | 10 | ||||
| -rw-r--r-- | niri-config/src/utils.rs | 15 | ||||
| -rw-r--r-- | niri-visual-tests/src/cases/gradient_area.rs | 4 | ||||
| -rw-r--r-- | niri-visual-tests/src/cases/layout.rs | 4 | ||||
| -rw-r--r-- | niri-visual-tests/src/cases/tile.rs | 4 | ||||
| -rw-r--r-- | src/layer/mapped.rs | 4 | ||||
| -rw-r--r-- | src/layout/floating.rs | 4 | ||||
| -rw-r--r-- | src/layout/focus_ring.rs | 4 | ||||
| -rw-r--r-- | src/layout/insert_hint_element.rs | 6 | ||||
| -rw-r--r-- | src/layout/mod.rs | 24 | ||||
| -rw-r--r-- | src/layout/scrolling.rs | 8 | ||||
| -rw-r--r-- | src/layout/shadow.rs | 4 | ||||
| -rw-r--r-- | src/layout/tab_indicator.rs | 16 | ||||
| -rw-r--r-- | src/layout/tests.rs | 33 | ||||
| -rw-r--r-- | src/layout/tests/fullscreen.rs | 2 | ||||
| -rw-r--r-- | src/layout/workspace.rs | 4 | ||||
| -rw-r--r-- | src/niri.rs | 4 | ||||
| -rw-r--r-- | src/tests/animations.rs | 2 |
21 files changed, 559 insertions, 414 deletions
diff --git a/niri-config/src/appearance.rs b/niri-config/src/appearance.rs index dfe4ebbb..bdcbb318 100644 --- a/niri-config/src/appearance.rs +++ b/niri-config/src/appearance.rs @@ -5,7 +5,7 @@ use knuffel::errors::DecodeError; use miette::{miette, IntoDiagnostic as _}; use smithay::backend::renderer::Color32F; -use crate::utils::MergeWith; +use crate::utils::{Flag, MergeWith}; use crate::FloatOrInt; pub const DEFAULT_BACKGROUND_COLOR: Color = Color::from_array_unpremul([0.25, 0.25, 0.25, 1.]); @@ -222,23 +222,15 @@ impl CornerRadius { } } -#[derive(knuffel::Decode, Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq)] pub struct FocusRing { - #[knuffel(child)] pub off: bool, - #[knuffel(child, unwrap(argument), default = Self::default().width)] - pub width: FloatOrInt<0, 65535>, - #[knuffel(child, default = Self::default().active_color)] + pub width: f64, pub active_color: Color, - #[knuffel(child, default = Self::default().inactive_color)] pub inactive_color: Color, - #[knuffel(child, default = Self::default().urgent_color)] pub urgent_color: Color, - #[knuffel(child)] pub active_gradient: Option<Gradient>, - #[knuffel(child)] pub inactive_gradient: Option<Gradient>, - #[knuffel(child)] pub urgent_gradient: Option<Gradient>, } @@ -246,7 +238,7 @@ impl Default for FocusRing { fn default() -> Self { Self { off: false, - width: FloatOrInt(4.), + width: 4., active_color: Color::from_rgba8_unpremul(127, 200, 255, 255), inactive_color: Color::from_rgba8_unpremul(80, 80, 80, 255), urgent_color: Color::from_rgba8_unpremul(155, 0, 0, 255), @@ -257,23 +249,15 @@ impl Default for FocusRing { } } -#[derive(knuffel::Decode, Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq)] pub struct Border { - #[knuffel(child)] pub off: bool, - #[knuffel(child, unwrap(argument), default = Self::default().width)] - pub width: FloatOrInt<0, 65535>, - #[knuffel(child, default = Self::default().active_color)] + pub width: f64, pub active_color: Color, - #[knuffel(child, default = Self::default().inactive_color)] pub inactive_color: Color, - #[knuffel(child, default = Self::default().urgent_color)] pub urgent_color: Color, - #[knuffel(child)] pub active_gradient: Option<Gradient>, - #[knuffel(child)] pub inactive_gradient: Option<Gradient>, - #[knuffel(child)] pub urgent_gradient: Option<Gradient>, } @@ -281,7 +265,7 @@ impl Default for Border { fn default() -> Self { Self { off: true, - width: FloatOrInt(4.), + width: 4., active_color: Color::from_rgba8_unpremul(255, 200, 127, 255), inactive_color: Color::from_rgba8_unpremul(80, 80, 80, 255), urgent_color: Color::from_rgba8_unpremul(155, 0, 0, 255), @@ -329,7 +313,7 @@ impl MergeWith<BorderRule> for Border { self.off = false; } - merge_clone!((self, part), width); + merge!((self, part), width); merge_color_gradient!( (self, part), @@ -348,21 +332,14 @@ impl MergeWith<BorderRule> for FocusRing { } } -#[derive(knuffel::Decode, Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq)] pub struct Shadow { - #[knuffel(child)] pub on: bool, - #[knuffel(child, default = Self::default().offset)] pub offset: ShadowOffset, - #[knuffel(child, unwrap(argument), default = Self::default().softness)] - pub softness: FloatOrInt<0, 1024>, - #[knuffel(child, unwrap(argument), default = Self::default().spread)] - pub spread: FloatOrInt<-1024, 1024>, - #[knuffel(child, unwrap(argument), default = Self::default().draw_behind_window)] + pub softness: f64, + pub spread: f64, pub draw_behind_window: bool, - #[knuffel(child, default = Self::default().color)] pub color: Color, - #[knuffel(child)] pub inactive_color: Option<Color>, } @@ -374,8 +351,8 @@ impl Default for Shadow { x: FloatOrInt(0.), y: FloatOrInt(5.), }, - softness: FloatOrInt(30.), - spread: FloatOrInt(5.), + softness: 30., + spread: 5., draw_behind_window: false, color: Color::from_rgba8_unpremul(0, 0, 0, 0x77), inactive_color: None, @@ -390,7 +367,7 @@ impl MergeWith<ShadowRule> for Shadow { self.on = false; } - merge_clone!((self, part), softness, spread); + merge!((self, part), softness, spread); merge_clone!((self, part), offset, draw_behind_window, color); @@ -440,8 +417,8 @@ impl From<WorkspaceShadow> for Shadow { Self { on: !value.off, offset: value.offset, - softness: value.softness, - spread: value.spread, + softness: value.softness.0, + spread: value.spread.0, draw_behind_window: false, color: value.color, inactive_color: None, @@ -449,37 +426,22 @@ impl From<WorkspaceShadow> for Shadow { } } -#[derive(knuffel::Decode, Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq)] pub struct TabIndicator { - #[knuffel(child)] pub off: bool, - #[knuffel(child)] pub hide_when_single_tab: bool, - #[knuffel(child)] pub place_within_column: bool, - #[knuffel(child, unwrap(argument), default = Self::default().gap)] - pub gap: FloatOrInt<-65535, 65535>, - #[knuffel(child, unwrap(argument), default = Self::default().width)] - pub width: FloatOrInt<0, 65535>, - #[knuffel(child, default = Self::default().length)] + pub gap: f64, + pub width: f64, pub length: TabIndicatorLength, - #[knuffel(child, unwrap(argument), default = Self::default().position)] pub position: TabIndicatorPosition, - #[knuffel(child, unwrap(argument), default = Self::default().gaps_between_tabs)] - pub gaps_between_tabs: FloatOrInt<0, 65535>, - #[knuffel(child, unwrap(argument), default = Self::default().corner_radius)] - pub corner_radius: FloatOrInt<0, 65535>, - #[knuffel(child)] + pub gaps_between_tabs: f64, + pub corner_radius: f64, pub active_color: Option<Color>, - #[knuffel(child)] pub inactive_color: Option<Color>, - #[knuffel(child)] pub urgent_color: Option<Color>, - #[knuffel(child)] pub active_gradient: Option<Gradient>, - #[knuffel(child)] pub inactive_gradient: Option<Gradient>, - #[knuffel(child)] pub urgent_gradient: Option<Gradient>, } @@ -489,14 +451,14 @@ impl Default for TabIndicator { off: false, hide_when_single_tab: false, place_within_column: false, - gap: FloatOrInt(5.), - width: FloatOrInt(4.), + gap: 5., + width: 4., length: TabIndicatorLength { total_proportion: Some(0.5), }, position: TabIndicatorPosition::Left, - gaps_between_tabs: FloatOrInt(0.), - corner_radius: FloatOrInt(0.), + gaps_between_tabs: 0., + corner_radius: 0., active_color: None, inactive_color: None, urgent_color: None, @@ -507,6 +469,70 @@ impl Default for TabIndicator { } } +impl MergeWith<TabIndicatorPart> for TabIndicator { + fn merge_with(&mut self, part: &TabIndicatorPart) { + self.off |= part.off; + if part.on { + self.off = false; + } + + merge!( + (self, part), + hide_when_single_tab, + place_within_column, + gap, + width, + gaps_between_tabs, + corner_radius, + ); + + merge_clone!((self, part), length, position); + + merge_color_gradient_opt!( + (self, part), + (active_color, active_gradient), + (inactive_color, inactive_gradient), + (urgent_color, urgent_gradient), + ); + } +} + +#[derive(knuffel::Decode, Debug, Default, Clone, Copy, PartialEq)] +pub struct TabIndicatorPart { + #[knuffel(child)] + pub off: bool, + #[knuffel(child)] + pub on: bool, + #[knuffel(child)] + pub hide_when_single_tab: Option<Flag>, + #[knuffel(child)] + pub place_within_column: Option<Flag>, + #[knuffel(child, unwrap(argument))] + pub gap: Option<FloatOrInt<-65535, 65535>>, + #[knuffel(child, unwrap(argument))] + pub width: Option<FloatOrInt<0, 65535>>, + #[knuffel(child)] + pub length: Option<TabIndicatorLength>, + #[knuffel(child, unwrap(argument))] + pub position: Option<TabIndicatorPosition>, + #[knuffel(child, unwrap(argument))] + pub gaps_between_tabs: Option<FloatOrInt<0, 65535>>, + #[knuffel(child, unwrap(argument))] + pub corner_radius: Option<FloatOrInt<0, 65535>>, + #[knuffel(child)] + pub active_color: Option<Color>, + #[knuffel(child)] + pub inactive_color: Option<Color>, + #[knuffel(child)] + pub urgent_color: Option<Color>, + #[knuffel(child)] + pub active_gradient: Option<Gradient>, + #[knuffel(child)] + pub inactive_gradient: Option<Gradient>, + #[knuffel(child)] + pub urgent_gradient: Option<Gradient>, +} + #[derive(knuffel::Decode, Debug, Clone, Copy, PartialEq)] pub struct TabIndicatorLength { #[knuffel(property)] @@ -521,13 +547,10 @@ pub enum TabIndicatorPosition { Bottom, } -#[derive(knuffel::Decode, Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq)] pub struct InsertHint { - #[knuffel(child)] pub off: bool, - #[knuffel(child, default = Self::default().color)] pub color: Color, - #[knuffel(child)] pub gradient: Option<Gradient>, } @@ -541,6 +564,29 @@ impl Default for InsertHint { } } +impl MergeWith<InsertHintPart> for InsertHint { + fn merge_with(&mut self, part: &InsertHintPart) { + self.off |= part.off; + if part.on { + self.off = false; + } + + merge_color_gradient!((self, part), (color, gradient)); + } +} + +#[derive(knuffel::Decode, Debug, Default, Clone, Copy, PartialEq)] +pub struct InsertHintPart { + #[knuffel(child)] + pub off: bool, + #[knuffel(child)] + pub on: bool, + #[knuffel(child)] + pub color: Option<Color>, + #[knuffel(child)] + pub gradient: Option<Gradient>, +} + #[derive(knuffel::DecodeScalar, Debug, Clone, Copy, PartialEq, Eq)] pub enum BlockOutFrom { Screencast, @@ -1016,16 +1062,9 @@ mod tests { #[test] fn test_border_rule_on_off_merging() { fn is_on(config: &str, rules: &[&str]) -> String { - let mut resolved = BorderRule { - off: false, - on: false, - width: None, - active_color: None, - inactive_color: None, - urgent_color: None, - active_gradient: None, - inactive_gradient: None, - urgent_gradient: None, + let mut resolved = Border { + off: config == "off", + ..Default::default() }; for rule in rules.iter().copied() { @@ -1038,14 +1077,7 @@ mod tests { resolved.merge_with(&rule); } - let mut border = Border { - off: config == "off", - ..Default::default() - }; - - border.merge_with(&resolved); - - if border.off { "off" } else { "on" }.to_owned() + if resolved.off { "off" } else { "on" }.to_owned() } assert_snapshot!(is_on("off", &[]), @"off"); @@ -1095,13 +1127,11 @@ mod tests { ) .unwrap(); - let mut border_rule = BorderRule::default(); + let mut border = config.resolve_layout().border; for rule in &config.window_rules { - border_rule.merge_with(&rule.border); + border.merge_with(&rule.border); } - let border = config.layout.border.merged_with(&border_rule); - // Gradient should be None because it's overwritten. assert_debug_snapshot!( ( @@ -1166,15 +1196,13 @@ mod tests { ) .unwrap(); - let mut border_rule = BorderRule::default(); + let mut border = config.resolve_layout().border; let mut tab_indicator_rule = TabIndicatorRule::default(); for rule in &config.window_rules { - border_rule.merge_with(&rule.border); + border.merge_with(&rule.border); tab_indicator_rule.merge_with(&rule.tab_indicator); } - let border = config.layout.border.merged_with(&border_rule); - // Gradient should be None because it's overwritten. assert_debug_snapshot!( ( diff --git a/niri-config/src/layout.rs b/niri-config/src/layout.rs index 768199d5..f84528bd 100644 --- a/niri-config/src/layout.rs +++ b/niri-config/src/layout.rs @@ -4,65 +4,130 @@ use niri_ipc::{ColumnDisplay, SizeChange}; use crate::appearance::{ Border, FocusRing, InsertHint, Shadow, TabIndicator, DEFAULT_BACKGROUND_COLOR, }; -use crate::utils::expect_only_children; -use crate::{Color, FloatOrInt}; +use crate::utils::{expect_only_children, Flag, MergeWith}; +use crate::{BorderRule, Color, FloatOrInt, InsertHintPart, ShadowRule, TabIndicatorPart}; -#[derive(knuffel::Decode, Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq)] pub struct Layout { - #[knuffel(child, default)] pub focus_ring: FocusRing, - #[knuffel(child, default)] pub border: Border, - #[knuffel(child, default)] pub shadow: Shadow, - #[knuffel(child, default)] pub tab_indicator: TabIndicator, - #[knuffel(child, default)] pub insert_hint: InsertHint, - #[knuffel(child, unwrap(children), default)] pub preset_column_widths: Vec<PresetSize>, - #[knuffel(child)] - pub default_column_width: Option<DefaultPresetSize>, - #[knuffel(child, unwrap(children), default)] + pub default_column_width: Option<PresetSize>, pub preset_window_heights: Vec<PresetSize>, - #[knuffel(child, unwrap(argument), default)] pub center_focused_column: CenterFocusedColumn, - #[knuffel(child)] pub always_center_single_column: bool, - #[knuffel(child)] pub empty_workspace_above_first: bool, - #[knuffel(child, unwrap(argument, str), default = Self::default().default_column_display)] pub default_column_display: ColumnDisplay, - #[knuffel(child, unwrap(argument), default = Self::default().gaps)] - pub gaps: FloatOrInt<0, 65535>, - #[knuffel(child, default)] + pub gaps: f64, pub struts: Struts, - #[knuffel(child, default = DEFAULT_BACKGROUND_COLOR)] pub background_color: Color, } impl Default for Layout { fn default() -> Self { Self { - focus_ring: Default::default(), - border: Default::default(), - shadow: Default::default(), - tab_indicator: Default::default(), - insert_hint: Default::default(), - preset_column_widths: Default::default(), - default_column_width: Default::default(), - center_focused_column: Default::default(), + focus_ring: FocusRing::default(), + border: Border::default(), + shadow: Shadow::default(), + tab_indicator: TabIndicator::default(), + insert_hint: InsertHint::default(), + preset_column_widths: vec![ + PresetSize::Proportion(1. / 3.), + PresetSize::Proportion(0.5), + PresetSize::Proportion(2. / 3.), + ], + default_column_width: Some(PresetSize::Proportion(0.5)), + center_focused_column: CenterFocusedColumn::Never, always_center_single_column: false, empty_workspace_above_first: false, default_column_display: ColumnDisplay::Normal, - gaps: FloatOrInt(16.), - struts: Default::default(), - preset_window_heights: Default::default(), + gaps: 16., + struts: Struts::default(), + preset_window_heights: vec![ + PresetSize::Proportion(1. / 3.), + PresetSize::Proportion(0.5), + PresetSize::Proportion(2. / 3.), + ], background_color: DEFAULT_BACKGROUND_COLOR, } } } +impl MergeWith<LayoutPart> for Layout { + fn merge_with(&mut self, part: &LayoutPart) { + merge!( + (self, part), + focus_ring, + border, + shadow, + tab_indicator, + insert_hint, + always_center_single_column, + empty_workspace_above_first, + gaps, + ); + + merge_clone!( + (self, part), + preset_column_widths, + preset_window_heights, + center_focused_column, + default_column_display, + struts, + background_color, + ); + + if let Some(x) = part.default_column_width { + self.default_column_width = x.0; + } + + if self.preset_column_widths.is_empty() { + self.preset_column_widths = Layout::default().preset_column_widths; + } + + if self.preset_window_heights.is_empty() { + self.preset_window_heights = Layout::default().preset_window_heights; + } + } +} + +#[derive(knuffel::Decode, Debug, Default, Clone, PartialEq)] +pub struct LayoutPart { + #[knuffel(child)] + pub focus_ring: Option<BorderRule>, + #[knuffel(child)] + pub border: Option<BorderRule>, + #[knuffel(child)] + pub shadow: Option<ShadowRule>, + #[knuffel(child)] + pub tab_indicator: Option<TabIndicatorPart>, + #[knuffel(child)] + pub insert_hint: Option<InsertHintPart>, + #[knuffel(child, unwrap(children))] + pub preset_column_widths: Option<Vec<PresetSize>>, + #[knuffel(child)] + pub default_column_width: Option<DefaultPresetSize>, + #[knuffel(child, unwrap(children))] + pub preset_window_heights: Option<Vec<PresetSize>>, + #[knuffel(child, unwrap(argument))] + pub center_focused_column: Option<CenterFocusedColumn>, + #[knuffel(child)] + pub always_center_single_column: Option<Flag>, + #[knuffel(child)] + pub empty_workspace_above_first: Option<Flag>, + #[knuffel(child, unwrap(argument, str))] + pub default_column_display: Option<ColumnDisplay>, + #[knuffel(child, unwrap(argument))] + pub gaps: Option<FloatOrInt<0, 65535>>, + #[knuffel(child)] + pub struts: Option<Struts>, + #[knuffel(child)] + pub background_color: Option<Color>, +} + #[derive(knuffel::Decode, Debug, Clone, Copy, PartialEq)] pub enum PresetSize { Proportion(#[knuffel(argument)] f64), diff --git a/niri-config/src/lib.rs b/niri-config/src/lib.rs index 575be90b..6dd32620 100644 --- a/niri-config/src/lib.rs +++ b/niri-config/src/lib.rs @@ -36,6 +36,7 @@ pub use crate::layout::*; pub use crate::misc::*; pub use crate::output::{Output, OutputName, Outputs, Position, Vrr}; pub use crate::utils::FloatOrInt; +use crate::utils::MergeWith as _; pub use crate::window_rule::{FloatingPosition, RelativeTo, WindowRule}; pub use crate::workspace::Workspace; @@ -50,7 +51,7 @@ pub struct Config { #[knuffel(children(name = "spawn-sh-at-startup"))] pub spawn_sh_at_startup: Vec<SpawnShAtStartup>, #[knuffel(child, default)] - pub layout: Layout, + pub layout: LayoutPart, #[knuffel(child, default)] pub prefer_no_csd: bool, #[knuffel(child, default)] @@ -133,6 +134,35 @@ impl Config { let _span = tracy_client::span!("Config::parse"); knuffel::parse(filename, text) } + + pub fn resolve_layout(&self) -> Layout { + let mut rv = Layout::from_part(&self.layout); + + // Preserve the behavior we'd always had for the border section: + // - `layout {}` gives border = off + // - `layout { border {} }` gives border = on + // - `layout { border { off } }` gives border = off + // + // This behavior is inconsistent with the rest of the config where adding an empty section + // generally doesn't change the outcome. Particularly, shadows are also disabled by default + // (like borders), and they always had an `on` instead of an `off` for this reason, so that + // writing `layout { shadow {} }` still results in shadow = off, as it should. + // + // Unfortunately, the default config has always had wording that heavily implies that + // `layout { border {} }` enables the borders. This wording is sure to be present in a lot + // of users' configs by now, which we can't change. + // + // Another way to make things consistent would be to default borders to on. However, that + // is annoying because it would mean changing many tests that rely on borders being off by + // default. This would also contradict the intended default borders value (off). + // + // So, let's just work around the problem here, preserving the original behavior. + if self.layout.border.is_some_and(|x| !x.on && !x.off) { + rv.border.off = false; + } + + rv + } } impl Default for Config { @@ -778,181 +808,182 @@ mod tests { command: "qs -c ~/source/qs/MyAwesomeShell", }, ], - layout: Layout { - focus_ring: FocusRing { - off: false, - width: FloatOrInt( - 5.0, - ), - active_color: Color { - r: 0.0, - g: 0.39215687, - b: 0.78431374, - a: 1.0, - }, - inactive_color: Color { - r: 1.0, - g: 0.78431374, - b: 0.39215687, - a: 0.0, - }, - urgent_color: Color { - r: 0.60784316, - g: 0.0, - b: 0.0, - a: 1.0, - }, - active_gradient: Some( - Gradient { - from: Color { - r: 0.039215688, - g: 0.078431375, - b: 0.11764706, - a: 1.0, - }, - to: Color { + layout: LayoutPart { + focus_ring: Some( + BorderRule { + off: false, + on: false, + width: Some( + FloatOrInt( + 5.0, + ), + ), + active_color: Some( + Color { r: 0.0, - g: 0.5019608, - b: 1.0, + g: 0.39215687, + b: 0.78431374, a: 1.0, }, - angle: 180, - relative_to: WorkspaceView, - in_: GradientInterpolation { - color_space: Srgb, - hue_interpolation: Shorter, + ), + inactive_color: Some( + Color { + r: 1.0, + g: 0.78431374, + b: 0.39215687, + a: 0.0, }, - }, - ), - inactive_gradient: None, - urgent_gradient: None, - }, - border: Border { - off: false, - width: FloatOrInt( - 3.0, - ), - active_color: Color { - r: 1.0, - g: 0.78431374, - b: 0.49803922, - a: 1.0, - }, - inactive_color: Color { - r: 1.0, - g: 0.78431374, - b: 0.39215687, - a: 0.0, - }, - urgent_color: Color { - r: 0.60784316, - g: 0.0, - b: 0.0, - a: 1.0, - }, - active_gradient: None, - inactive_gradient: None, - urgent_gradient: None, - }, - shadow: Shadow { - on: false, - offset: ShadowOffset { - x: FloatOrInt( - 10.0, ), - y: FloatOrInt( - -20.0, + urgent_color: None, + active_gradient: Some( + Gradient { + from: Color { + r: 0.039215688, + g: 0.078431375, + b: 0.11764706, + a: 1.0, + }, + to: Color { + r: 0.0, + g: 0.5019608, + b: 1.0, + a: 1.0, + }, + angle: 180, + relative_to: WorkspaceView, + in_: GradientInterpolation { + color_space: Srgb, + hue_interpolation: Shorter, + }, + }, ), + inactive_gradient: None, + urgent_gradient: None, }, - softness: FloatOrInt( - 30.0, - ), - spread: FloatOrInt( - 5.0, - ), - draw_behind_window: false, - color: Color { - r: 0.0, - g: 0.0, - b: 0.0, - a: 0.46666667, + ), + border: Some( + BorderRule { + off: false, + on: false, + width: Some( + FloatOrInt( + 3.0, + ), + ), + active_color: None, + inactive_color: Some( + Color { + r: 1.0, + g: 0.78431374, + b: 0.39215687, + a: 0.0, + }, + ), + urgent_color: None, + active_gradient: None, + inactive_gradient: None, + urgent_gradient: None, }, - inactive_color: None, - }, - tab_indicator: TabIndicator { - off: false, - hide_when_single_tab: false, - place_within_column: false, - gap: FloatOrInt( - 5.0, - ), - width: FloatOrInt( - 10.0, - ), - length: TabIndicatorLength { - total_proportion: Some( - 0.5, + ), + shadow: Some( + ShadowRule { + off: false, + on: false, + offset: Some( + ShadowOffset { + x: FloatOrInt( + 10.0, + ), + y: FloatOrInt( + -20.0, + ), + }, ), + softness: None, + spread: None, + draw_behind_window: None, + color: None, + inactive_color: None, }, - position: Top, - gaps_between_tabs: FloatOrInt( - 0.0, - ), - corner_radius: FloatOrInt( - 0.0, - ), - active_color: None, - inactive_color: None, - urgent_color: None, - active_gradient: None, - inactive_gradient: None, - urgent_gradient: None, - }, - insert_hint: InsertHint { - off: false, - color: Color { - r: 1.0, - g: 0.78431374, - b: 0.49803922, - a: 1.0, + ), + tab_indicator: Some( + TabIndicatorPart { + off: false, + on: false, + hide_when_single_tab: None, + place_within_column: None, + gap: None, + width: Some( + FloatOrInt( + 10.0, + ), + ), + l |
