diff options
| -rw-r--r-- | niri-config/src/animations.rs | 667 | ||||
| -rw-r--r-- | niri-config/src/lib.rs | 668 |
2 files changed, 671 insertions, 664 deletions
diff --git a/niri-config/src/animations.rs b/niri-config/src/animations.rs new file mode 100644 index 00000000..a119ba19 --- /dev/null +++ b/niri-config/src/animations.rs @@ -0,0 +1,667 @@ +use knuffel::errors::DecodeError; +use knuffel::Decode as _; + +use crate::{expect_only_children, parse_arg_node, FloatOrInt}; + +#[derive(knuffel::Decode, Debug, Clone, PartialEq)] +pub struct Animations { + #[knuffel(child)] + pub off: bool, + #[knuffel(child, unwrap(argument), default = FloatOrInt(1.))] + pub slowdown: FloatOrInt<0, { i32::MAX }>, + #[knuffel(child, default)] + pub workspace_switch: WorkspaceSwitchAnim, + #[knuffel(child, default)] + pub window_open: WindowOpenAnim, + #[knuffel(child, default)] + pub window_close: WindowCloseAnim, + #[knuffel(child, default)] + pub horizontal_view_movement: HorizontalViewMovementAnim, + #[knuffel(child, default)] + pub window_movement: WindowMovementAnim, + #[knuffel(child, default)] + pub window_resize: WindowResizeAnim, + #[knuffel(child, default)] + pub config_notification_open_close: ConfigNotificationOpenCloseAnim, + #[knuffel(child, default)] + pub exit_confirmation_open_close: ExitConfirmationOpenCloseAnim, + #[knuffel(child, default)] + pub screenshot_ui_open: ScreenshotUiOpenAnim, + #[knuffel(child, default)] + pub overview_open_close: OverviewOpenCloseAnim, +} + +impl Default for Animations { + fn default() -> Self { + Self { + off: false, + slowdown: FloatOrInt(1.), + workspace_switch: Default::default(), + horizontal_view_movement: Default::default(), + window_movement: Default::default(), + window_open: Default::default(), + window_close: Default::default(), + window_resize: Default::default(), + config_notification_open_close: Default::default(), + exit_confirmation_open_close: Default::default(), + screenshot_ui_open: Default::default(), + overview_open_close: Default::default(), + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct Animation { + pub off: bool, + pub kind: AnimationKind, +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum AnimationKind { + Easing(EasingParams), + Spring(SpringParams), +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct EasingParams { + pub duration_ms: u32, + pub curve: AnimationCurve, +} + +#[derive(knuffel::DecodeScalar, Debug, Clone, Copy, PartialEq)] +pub enum AnimationCurve { + Linear, + EaseOutQuad, + EaseOutCubic, + EaseOutExpo, +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct SpringParams { + pub damping_ratio: f64, + pub stiffness: u32, + pub epsilon: f64, +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct WorkspaceSwitchAnim(pub Animation); + +impl Default for WorkspaceSwitchAnim { + fn default() -> Self { + Self(Animation { + off: false, + kind: AnimationKind::Spring(SpringParams { + damping_ratio: 1., + stiffness: 1000, + epsilon: 0.0001, + }), + }) + } +} + +#[derive(Debug, Clone, PartialEq)] +pub struct WindowOpenAnim { + pub anim: Animation, + pub custom_shader: Option<String>, +} + +impl Default for WindowOpenAnim { + fn default() -> Self { + Self { + anim: Animation { + off: false, + kind: AnimationKind::Easing(EasingParams { + duration_ms: 150, + curve: AnimationCurve::EaseOutExpo, + }), + }, + custom_shader: None, + } + } +} + +#[derive(Debug, Clone, PartialEq)] +pub struct WindowCloseAnim { + pub anim: Animation, + pub custom_shader: Option<String>, +} + +impl Default for WindowCloseAnim { + fn default() -> Self { + Self { + anim: Animation { + off: false, + kind: AnimationKind::Easing(EasingParams { + duration_ms: 150, + curve: AnimationCurve::EaseOutQuad, + }), + }, + custom_shader: None, + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct HorizontalViewMovementAnim(pub Animation); + +impl Default for HorizontalViewMovementAnim { + fn default() -> Self { + Self(Animation { + off: false, + kind: AnimationKind::Spring(SpringParams { + damping_ratio: 1., + stiffness: 800, + epsilon: 0.0001, + }), + }) + } +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct WindowMovementAnim(pub Animation); + +impl Default for WindowMovementAnim { + fn default() -> Self { + Self(Animation { + off: false, + kind: AnimationKind::Spring(SpringParams { + damping_ratio: 1., + stiffness: 800, + epsilon: 0.0001, + }), + }) + } +} + +#[derive(Debug, Clone, PartialEq)] +pub struct WindowResizeAnim { + pub anim: Animation, + pub custom_shader: Option<String>, +} + +impl Default for WindowResizeAnim { + fn default() -> Self { + Self { + anim: Animation { + off: false, + kind: AnimationKind::Spring(SpringParams { + damping_ratio: 1., + stiffness: 800, + epsilon: 0.0001, + }), + }, + custom_shader: None, + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct ConfigNotificationOpenCloseAnim(pub Animation); + +impl Default for ConfigNotificationOpenCloseAnim { + fn default() -> Self { + Self(Animation { + off: false, + kind: AnimationKind::Spring(SpringParams { + damping_ratio: 0.6, + stiffness: 1000, + epsilon: 0.001, + }), + }) + } +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct ExitConfirmationOpenCloseAnim(pub Animation); + +impl Default for ExitConfirmationOpenCloseAnim { + fn default() -> Self { + Self(Animation { + off: false, + kind: AnimationKind::Spring(SpringParams { + damping_ratio: 0.6, + stiffness: 500, + epsilon: 0.01, + }), + }) + } +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct ScreenshotUiOpenAnim(pub Animation); + +impl Default for ScreenshotUiOpenAnim { + fn default() -> Self { + Self(Animation { + off: false, + kind: AnimationKind::Easing(EasingParams { + duration_ms: 200, + curve: AnimationCurve::EaseOutQuad, + }), + }) + } +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct OverviewOpenCloseAnim(pub Animation); + +impl Default for OverviewOpenCloseAnim { + fn default() -> Self { + Self(Animation { + off: false, + kind: AnimationKind::Spring(SpringParams { + damping_ratio: 1., + stiffness: 800, + epsilon: 0.0001, + }), + }) + } +} + +impl<S> knuffel::Decode<S> for WorkspaceSwitchAnim +where + S: knuffel::traits::ErrorSpan, +{ + fn decode_node( + node: &knuffel::ast::SpannedNode<S>, + ctx: &mut knuffel::decode::Context<S>, + ) -> Result<Self, DecodeError<S>> { + let default = Self::default().0; + Ok(Self(Animation::decode_node(node, ctx, default, |_, _| { + Ok(false) + })?)) + } +} + +impl<S> knuffel::Decode<S> for HorizontalViewMovementAnim +where + S: knuffel::traits::ErrorSpan, +{ + fn decode_node( + node: &knuffel::ast::SpannedNode<S>, + ctx: &mut knuffel::decode::Context<S>, + ) -> Result<Self, DecodeError<S>> { + let default = Self::default().0; + Ok(Self(Animation::decode_node(node, ctx, default, |_, _| { + Ok(false) + })?)) + } +} + +impl<S> knuffel::Decode<S> for WindowMovementAnim +where + S: knuffel::traits::ErrorSpan, +{ + fn decode_node( + node: &knuffel::ast::SpannedNode<S>, + ctx: &mut knuffel::decode::Context<S>, + ) -> Result<Self, DecodeError<S>> { + let default = Self::default().0; + Ok(Self(Animation::decode_node(node, ctx, default, |_, _| { + Ok(false) + })?)) + } +} + +impl<S> knuffel::Decode<S> for WindowOpenAnim +where + S: knuffel::traits::ErrorSpan, +{ + fn decode_node( + node: &knuffel::ast::SpannedNode<S>, + ctx: &mut knuffel::decode::Context<S>, + ) -> Result<Self, DecodeError<S>> { + let default = Self::default().anim; + let mut custom_shader = None; + let anim = Animation::decode_node(node, ctx, default, |child, ctx| { + if &**child.node_name == "custom-shader" { + custom_shader = parse_arg_node("custom-shader", child, ctx)?; + Ok(true) + } else { + Ok(false) + } + })?; + + Ok(Self { + anim, + custom_shader, + }) + } +} + +impl<S> knuffel::Decode<S> for WindowCloseAnim +where + S: knuffel::traits::ErrorSpan, +{ + fn decode_node( + node: &knuffel::ast::SpannedNode<S>, + ctx: &mut knuffel::decode::Context<S>, + ) -> Result<Self, DecodeError<S>> { + let default = Self::default().anim; + let mut custom_shader = None; + let anim = Animation::decode_node(node, ctx, default, |child, ctx| { + if &**child.node_name == "custom-shader" { + custom_shader = parse_arg_node("custom-shader", child, ctx)?; + Ok(true) + } else { + Ok(false) + } + })?; + + Ok(Self { + anim, + custom_shader, + }) + } +} + +impl<S> knuffel::Decode<S> for WindowResizeAnim +where + S: knuffel::traits::ErrorSpan, +{ + fn decode_node( + node: &knuffel::ast::SpannedNode<S>, + ctx: &mut knuffel::decode::Context<S>, + ) -> Result<Self, DecodeError<S>> { + let default = Self::default().anim; + let mut custom_shader = None; + let anim = Animation::decode_node(node, ctx, default, |child, ctx| { + if &**child.node_name == "custom-shader" { + custom_shader = parse_arg_node("custom-shader", child, ctx)?; + Ok(true) + } else { + Ok(false) + } + })?; + + Ok(Self { + anim, + custom_shader, + }) + } +} + +impl<S> knuffel::Decode<S> for ConfigNotificationOpenCloseAnim +where + S: knuffel::traits::ErrorSpan, +{ + fn decode_node( + node: &knuffel::ast::SpannedNode<S>, + ctx: &mut knuffel::decode::Context<S>, + ) -> Result<Self, DecodeError<S>> { + let default = Self::default().0; + Ok(Self(Animation::decode_node(node, ctx, default, |_, _| { + Ok(false) + })?)) + } +} + +impl<S> knuffel::Decode<S> for ExitConfirmationOpenCloseAnim +where + S: knuffel::traits::ErrorSpan, +{ + fn decode_node( + node: &knuffel::ast::SpannedNode<S>, + ctx: &mut knuffel::decode::Context<S>, + ) -> Result<Self, DecodeError<S>> { + let default = Self::default().0; + Ok(Self(Animation::decode_node(node, ctx, default, |_, _| { + Ok(false) + })?)) + } +} + +impl<S> knuffel::Decode<S> for ScreenshotUiOpenAnim +where + S: knuffel::traits::ErrorSpan, +{ + fn decode_node( + node: &knuffel::ast::SpannedNode<S>, + ctx: &mut knuffel::decode::Context<S>, + ) -> Result<Self, DecodeError<S>> { + let default = Self::default().0; + Ok(Self(Animation::decode_node(node, ctx, default, |_, _| { + Ok(false) + })?)) + } +} + +impl<S> knuffel::Decode<S> for OverviewOpenCloseAnim +where + S: knuffel::traits::ErrorSpan, +{ + fn decode_node( + node: &knuffel::ast::SpannedNode<S>, + ctx: &mut knuffel::decode::Context<S>, + ) -> Result<Self, DecodeError<S>> { + let default = Self::default().0; + Ok(Self(Animation::decode_node(node, ctx, default, |_, _| { + Ok(false) + })?)) + } +} + +impl Animation { + pub fn new_off() -> Self { + Self { + off: true, + kind: AnimationKind::Easing(EasingParams { + duration_ms: 0, + curve: AnimationCurve::Linear, + }), + } + } + + fn decode_node<S: knuffel::traits::ErrorSpan>( + node: &knuffel::ast::SpannedNode<S>, + ctx: &mut knuffel::decode::Context<S>, + default: Self, + mut process_children: impl FnMut( + &knuffel::ast::SpannedNode<S>, + &mut knuffel::decode::Context<S>, + ) -> Result<bool, DecodeError<S>>, + ) -> Result<Self, DecodeError<S>> { + #[derive(Default, PartialEq)] + struct OptionalEasingParams { + duration_ms: Option<u32>, + curve: Option<AnimationCurve>, + } + + expect_only_children(node, ctx); + + let mut off = false; + let mut easing_params = OptionalEasingParams::default(); + let mut spring_params = None; + + for child in node.children() { + match &**child.node_name { + "off" => { + knuffel::decode::check_flag_node(child, ctx); + if off { + ctx.emit_error(DecodeError::unexpected( + &child.node_name, + "node", + "duplicate node `off`, single node expected", + )); + } else { + off = true; + } + } + "spring" => { + if easing_params != OptionalEasingParams::default() { + ctx.emit_error(DecodeError::unexpected( + child, + "node", + "cannot set both spring and easing parameters at once", + )); + } + if spring_params.is_some() { + ctx.emit_error(DecodeError::unexpected( + &child.node_name, + "node", + "duplicate node `spring`, single node expected", + )); + } + + spring_params = Some(SpringParams::decode_node(child, ctx)?); + } + "duration-ms" => { + if spring_params.is_some() { + ctx.emit_error(DecodeError::unexpected( + child, + "node", + "cannot set both spring and easing parameters at once", + )); + } + if easing_params.duration_ms.is_some() { + ctx.emit_error(DecodeError::unexpected( + &child.node_name, + "node", + "duplicate node `duration-ms`, single node expected", + )); + } + + easing_params.duration_ms = Some(parse_arg_node("duration-ms", child, ctx)?); + } + "curve" => { + if spring_params.is_some() { + ctx.emit_error(DecodeError::unexpected( + child, + "node", + "cannot set both spring and easing parameters at once", + )); + } + if easing_params.curve.is_some() { + ctx.emit_error(DecodeError::unexpected( + &child.node_name, + "node", + "duplicate node `curve`, single node expected", + )); + } + + easing_params.curve = Some(parse_arg_node("curve", child, ctx)?); + } + name_str => { + if !process_children(child, ctx)? { + ctx.emit_error(DecodeError::unexpected( + child, + "node", + format!("unexpected node `{}`", name_str.escape_default()), + )); + } + } + } + } + + let kind = if let Some(spring_params) = spring_params { + // Configured spring. + AnimationKind::Spring(spring_params) + } else if easing_params == OptionalEasingParams::default() { + // Did not configure anything. + default.kind + } else { + // Configured easing. + let default = if let AnimationKind::Easing(easing) = default.kind { + easing + } else { + // Generic fallback values for when the default animation is spring, but the user + // configured an easing animation. + EasingParams { + duration_ms: 250, + curve: AnimationCurve::EaseOutCubic, + } + }; + + AnimationKind::Easing(EasingParams { + duration_ms: easing_params.duration_ms.unwrap_or(default.duration_ms), + curve: easing_params.curve.unwrap_or(default.curve), + }) + }; + + Ok(Self { off, kind }) + } +} + +impl<S> knuffel::Decode<S> for SpringParams +where + S: knuffel::traits::ErrorSpan, +{ + fn decode_node( + node: &knuffel::ast::SpannedNode<S>, + ctx: &mut knuffel::decode::Context<S>, + ) -> Result<Self, DecodeError<S>> { + if let Some(type_name) = &node.type_name { + ctx.emit_error(DecodeError::unexpected( + type_name, + "type name", + "no type name expected for this node", + )); + } + if let Some(val) = node.arguments.first() { + ctx.emit_error(DecodeError::unexpected( + &val.literal, + "argument", + "unexpected argument", + )); + } + for child in node.children() { + ctx.emit_error(DecodeError::unexpected( + child, + "node", + format!("unexpected node `{}`", child.node_name.escape_default()), + )); + } + + let mut damping_ratio = None; + let mut stiffness = None; + let mut epsilon = None; + for (name, val) in &node.properties { + match &***name { + "damping-ratio" => { + damping_ratio = Some(knuffel::traits::DecodeScalar::decode(val, ctx)?); + } + "stiffness" => { + stiffness = Some(knuffel::traits::DecodeScalar::decode(val, ctx)?); + } + "epsilon" => { + epsilon = Some(knuffel::traits::DecodeScalar::decode(val, ctx)?); + } + name_str => { + ctx.emit_error(DecodeError::unexpected( + name, + "property", + format!("unexpected property `{}`", name_str.escape_default()), + )); + } + } + } + let damping_ratio = damping_ratio + .ok_or_else(|| DecodeError::missing(node, "property `damping-ratio` is required"))?; + let stiffness = stiffness + .ok_or_else(|| DecodeError::missing(node, "property `stiffness` is required"))?; + let epsilon = + epsilon.ok_or_else(|| DecodeError::missing(node, "property `epsilon` is required"))?; + + if !(0.1..=10.).contains(&damping_ratio) { + ctx.emit_error(DecodeError::conversion( + node, + "damping-ratio must be between 0.1 and 10.0", + )); + } + if stiffness < 1 { + ctx.emit_error(DecodeError::conversion(node, "stiffness must be >= 1")); + } + if !(0.00001..=0.1).contains(&epsilon) { + ctx.emit_error(DecodeError::conversion( + node, + "epsilon must be between 0.00001 and 0.1", + )); + } + + Ok(SpringParams { + damping_ratio, + stiffness, + epsilon, + }) + } +} diff --git a/niri-config/src/lib.rs b/niri-config/src/lib.rs index f0b89a4a..f5aa3e1a 100644 --- a/niri-config/src/lib.rs +++ b/niri-config/src/lib.rs @@ -12,7 +12,6 @@ use std::time::Duration; use bitflags::bitflags; use knuffel::errors::DecodeError; -use knuffel::Decode as _; use miette::{miette, Context, IntoDiagnostic}; use niri_ipc::{ ColumnDisplay, ConfiguredMode, LayoutSwitchTarget, PositionChange, SizeChange, Transform, @@ -27,10 +26,14 @@ use smithay::reexports::input; pub const DEFAULT_BACKGROUND_COLOR: Color = Color::from_array_unpremul([0.25, 0.25, 0.25, 1.]); pub const DEFAULT_BACKDROP_COLOR: Color = Color::from_array_unpremul([0.15, 0.15, 0.15, 1.]); +pub mod animations; pub mod layer_rule; pub mod utils; pub mod window_rule; +pub use crate::animations::{ + Animation, AnimationCurve, AnimationKind, Animations, EasingParams, SpringParams, +}; pub use crate::layer_rule::LayerRule; pub use crate::window_rule::{FloatingPosition, RelativeTo, WindowRule}; @@ -1089,261 +1092,6 @@ pub struct Clipboard { pub disable_primary: bool, } -#[derive(knuffel::Decode, Debug, Clone, PartialEq)] -pub struct Animations { - #[knuffel(child)] - pub off: bool, - #[knuffel(child, unwrap(argument), default = FloatOrInt(1.))] - pub slowdown: FloatOrInt<0, { i32::MAX }>, - #[knuffel(child, default)] - pub workspace_switch: WorkspaceSwitchAnim, - #[knuffel(child, default)] - pub window_open: WindowOpenAnim, - #[knuffel(child, default)] - pub window_close: WindowCloseAnim, - #[knuffel(child, default)] - pub horizontal_view_movement: HorizontalViewMovementAnim, - #[knuffel(child, default)] - pub window_movement: WindowMovementAnim, - #[knuffel(child, default)] - pub window_resize: WindowResizeAnim, - #[knuffel(child, default)] - pub config_notification_open_close: ConfigNotificationOpenCloseAnim, - #[knuffel(child, default)] - pub exit_confirmation_open_close: ExitConfirmationOpenCloseAnim, - #[knuffel(child, default)] - pub screenshot_ui_open: ScreenshotUiOpenAnim, - #[knuffel(child, default)] - pub overview_open_close: OverviewOpenCloseAnim, -} - -impl Default for Animations { - fn default() -> Self { - Self { - off: false, - slowdown: FloatOrInt(1.), - workspace_switch: Default::default(), - horizontal_view_movement: Default::default(), - window_movement: Default::default(), - window_open: Default::default(), - window_close: Default::default(), - window_resize: Default::default(), - config_notification_open_close: Default::default(), - exit_confirmation_open_close: Default::default(), - screenshot_ui_open: Default::default(), - overview_open_close: Default::default(), - } - } -} - -#[derive(Debug, Clone, Copy, PartialEq)] -pub struct WorkspaceSwitchAnim(pub Animation); - -impl Default for WorkspaceSwitchAnim { - fn default() -> Self { - Self(Animation { - off: false, - kind: AnimationKind::Spring(SpringParams { - damping_ratio: 1., - stiffness: 1000, - epsilon: 0.0001, - }), - }) - } -} - -#[derive(Debug, Clone, PartialEq)] -pub struct WindowOpenAnim { - pub anim: Animation, - pub custom_shader: Option<String>, -} - -impl Default for WindowOpenAnim { - fn default() -> Self { - Self { - anim: Animation { - off: false, - kind: AnimationKind::Easing(EasingParams { - duration_ms: 150, - curve: AnimationCurve::EaseOutExpo, - }), - }, - custom_shader: None, - } - } -} - -#[derive(Debug, Clone, PartialEq)] -pub struct WindowCloseAnim { - pub anim: Animation, - pub custom_shader: Option<String>, -} - -impl Default for WindowCloseAnim { - fn default() -> Self { - Self { - anim: Animation { - off: false, - kind: AnimationKind::Easing(EasingParams { - duration_ms: 150, - curve: AnimationCurve::EaseOutQuad, - }), - }, - custom_shader: None, - } - } -} - -#[derive(Debug, Clone, Copy, PartialEq)] -pub struct HorizontalViewMovementAnim(pub Animation); - -impl Default for HorizontalViewMovementAnim { - fn default() -> Self { - Self(Animation { - off: false, - kind: AnimationKind::Spring(SpringParams { - damping_ratio: 1., - stiffness: 800, - epsilon: 0.0001, - }), - }) - } -} - -#[derive(Debug, Clone, Copy, PartialEq)] -pub struct WindowMovementAnim(pub Animation); - -impl Default for WindowMovementAnim { - fn default() -> Self { - Self(Animation { - off: false, - kind: AnimationKind::Spring(SpringParams { - damping_ratio: 1., - stiffness: 800, - epsilon: 0.0001, - }), - }) - } -} - -#[derive(Debug, Clone, PartialEq)] -pub struct WindowResizeAnim { - pub anim: Animation, - pub custom_shader: Option<String>, -} - -impl Default for WindowResizeAnim { - fn default() -> Self { - Self { - anim: Animation { - off: false, - kind: AnimationKind::Spring(SpringParams { - damping_ratio: 1., - stiffness: 800, - epsilon: 0.0001, - }), - }, - custom_shader: None, - } - } -} - -#[derive(Debug, Clone, Copy, PartialEq)] -pub struct ConfigNotificationOpenCloseAnim(pub Animation); - -impl Default for ConfigNotificationOpenCloseAnim { - fn default() -> Self { - Self(Animation { - off: false, - kind: AnimationKind::Spring(SpringParams { - damping_ratio: 0.6, - stiffness: 1000, - epsilon: 0.001, - }), - }) - } -} - -#[derive(Debug, Clone, Copy, PartialEq)] -pub struct ExitConfirmationOpenCloseAnim(pub Animation); - -impl Default for ExitConfirmationOpenCloseAnim { - fn default() -> Self { - Self(Animation { - off: false, - kind: AnimationKind::Spring(SpringParams { - damping_ratio: 0.6, - stiffness: 500, - epsilon: 0.01, - }), - }) - } -} - -#[derive(Debug, Clone, Copy, PartialEq)] -pub struct ScreenshotUiOpenAnim(pub Animation); - -impl Default for ScreenshotUiOpenAnim { - fn default() -> Self { - Self(Animation { - off: false, - kind: AnimationKind::Easing(EasingParams { - duration_ms: 200, - curve: AnimationCurve::EaseOutQuad, - }), - }) - } -} - -#[derive(Debug, Clone, Copy, PartialEq)] -pub struct OverviewOpenCloseAnim(pub Animation); - -impl Default for OverviewOpenCloseAnim { - fn default() -> Self { - Self(Animation { - off: false, - kind: AnimationKind::Spring(SpringParams { - damping_ratio: 1., - stiffness: 800, - epsilon: 0.0001, - }), - }) - } -} - -#[derive(Debug, Clone, Copy, PartialEq)] -pub struct Animation { - pub off: bool, - pub kind: AnimationKind, -} - -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum AnimationKind { - Easing(EasingParams), - Spring(SpringParams), -} - -#[derive(Debug, Clone, Copy, PartialEq)] -pub struct EasingParams { - pub duration_ms: u32, - pub curve: AnimationCurve, -} - -#[derive(knuffel::DecodeScalar, Debug, Clone, Copy, PartialEq)] -pub enum AnimationCurve { - Linear, - EaseOutQuad, - EaseOutCubic, - EaseOutExpo, -} - -#[derive(Debug, Clone, Copy, PartialEq)] -pub struct SpringParams { - pub damping_ratio: f64, - pub stiffness: u32, - pub epsilon: f64, -} - #[derive(knuffel::Decode, Debug, Default, Clone, Copy, PartialEq)] pub struct Gestures { #[knuffel(child, default)] @@ -3061,51 +2809,6 @@ fn parse_arg_node<S: knuffel::traits::ErrorSpan, T: knuffel::traits::DecodeScala Ok(value) } -impl<S> knuffel::Decode<S> for WorkspaceSwitchAnim -where - S: knuffel::traits::ErrorSpan, -{ - fn decode_node( - node: &knuffel::ast::SpannedNode<S>, - ctx: &mut knuffel::decode::Context<S>, - ) -> Result<Self, DecodeError<S>> { - let default = Self::default().0; - Ok(Self(Animation::decode_node(node, ctx, default, |_, _| { - Ok(false) - })?)) - } -} - -impl<S> knuffel::Decode<S> for HorizontalViewMovementAnim -where - S: knuffel::traits::ErrorSpan, -{ - fn decode_node( - node: &knuffel::ast::SpannedNode<S>, - ctx: &mut knuffel::decode::Context<S>, - ) -> Result<Self, DecodeError<S>> { - let default = Self::default().0; - Ok(Self(Animation::decode_node(node, ctx, default, |_, _| { - Ok(false) - })?)) - } -} - -impl<S> knuffel::Decode<S> for WindowMovementAnim -where - S: knuffel::traits::ErrorSpan, -{ - fn decode_node( - node: &knuffel::ast::SpannedNode<S>, - ctx: &mut knuffel::decode::Context<S>, - ) -> Result<Self, DecodeError<S>> { - let default = Self::default().0; - Ok(Self(Animation::decode_node(node, ctx, default, |_, _| { - Ok(false) - })?)) - } -} - impl<S: knuffel::traits::ErrorSpan> knuffel::DecodeScalar<S> for WorkspaceName { fn type_check( type_name: &Option<knuffel::span::Spanned<knuffel::ast::TypeName, S>>, @@ -3157,369 +2860,6 @@ impl<S: knuffel::traits::ErrorSpan> knuffel::DecodeScalar<S> for WorkspaceName { } } -impl<S> knuffel::Decode<S> for WindowOpenAnim -where - S: knuffel::traits::ErrorSpan, -{ - fn decode_node( - node: &knuffel::ast::SpannedNode<S>, - ctx: &mut knuffel::decode::Context<S>, - ) -> Result<Self, DecodeError<S>> { - let default = Self::default().anim; - let mut custom_shader = None; - let anim = Animation::decode_node(node, ctx, default, |child, ctx| { - if &**child.node_name == "custom-shader" { - custom_shader = parse_arg_node("custom-shader", child, ctx)?; - Ok(true) - } else { - Ok(false) - } - })?; - - Ok(Self { - anim, - custom_shader, - }) - } -} - -impl<S> knuffel::Decode<S> for WindowCloseAnim -where - S: knuffel::traits::ErrorSpan, -{ - fn decode_node( - node: &knuffel::ast::SpannedNode<S>, - ctx: &mut knuffel::decode::Context<S>, - ) -> Result<Self, DecodeError<S>> { - let default = Self::default().anim; - let mut custom_shader = None; - let anim = Animation::decode_node(node, ctx, default, |child, ctx| { - if &**child.node_name == "custom-shader" { - custom_shader = parse_arg_node("custom-shader", child, ctx)?; - Ok(true) - } else { - Ok(false) - } - })?; - - Ok(Self { - anim, - custom_shader, - }) - } -} - -impl<S> knuffel::Decode<S> for WindowResizeAnim -where - S: knuffel::traits::ErrorSpan, -{ - fn decode_node( - node: &knuffel::ast::SpannedNode<S>, - ctx: &mut knuffel::decode::Context<S>, - ) -> Result<Self, DecodeError<S>> { - let default = Self::default().anim; - let mut custom_shader = None; - let anim = Animation::decode_node(node, ctx, default, |child, ctx| { - if &**child.node_name == "custom-shader" { - custom_shader = parse_arg_node("custom-shader", child, ctx)?; - Ok(true) - } else { - Ok(false) - } - })?; - - Ok(Self { - anim, - custom_shader, - }) - } -} - -impl<S> knuffel::Decode<S> for ConfigNotificationOpenCloseAnim -where - S: knuffel::traits::ErrorSpan, -{ - fn decode_node( - node: &knuffel::ast::SpannedNode<S>, - ctx: &mut knuffel::decode::Context<S>, - ) -> Result<Self, DecodeError<S>> { - let default = Self::default().0; - Ok(Self(Animation::decode_node(node, ctx, default, |_, _| { - Ok(false) - })?)) - } -} - -impl<S> knuffel::Decode<S> for ExitConfirmationOpenCloseAnim -where - S: knuffel::traits::ErrorSpan, -{ - fn decode_node( - node: &knuffel::ast::SpannedNode<S>, - ctx: &mut knuffel::decode::Context<S>, - ) -> Result<Self, DecodeError<S>> { - let default = Self::default().0; - Ok(Self(Animation::decode_node(node, ctx, default, |_, _| { - Ok(false) - })?)) - } -} - -impl<S> knuffel::Decode<S> for ScreenshotUiOpenAnim -where - S: knuffel::traits::ErrorSpan, -{ - fn decode_node( - node: &knuffel::ast::SpannedNode<S>, - ctx: &mut knuffel::decode::Context<S>, - ) -&g |
