diff --git a/sample files/pandora.kdl b/sample files/pandora.kdl index 0398884..6b8eba3 100644 --- a/sample files/pandora.kdl +++ b/sample files/pandora.kdl @@ -21,4 +21,10 @@ output "DP-2" { mode "static" } +animation { + + // Slow down animation by this factor. Values below 1 speeds up instead. + // slowdown 0.5 +} + // logging "default" diff --git a/src/pithos/config.rs b/src/pithos/config.rs index 04ad3a8..efd14cb 100644 --- a/src/pithos/config.rs +++ b/src/pithos/config.rs @@ -44,6 +44,7 @@ impl LogLevel { pub enum ConfigNode { Output(OutputConfig), Logging(#[knuffel(argument)] LogLevel), + Animation(AnimationConfig), } #[derive(Clone, Debug, knuffel::DecodeScalar, serde::Serialize, serde::Deserialize)] @@ -97,11 +98,18 @@ pub struct WorkspaceConfig { pub trigger: Vec, } +#[derive(Clone, Debug, Default, knuffel::Decode, serde::Serialize, serde::Deserialize)] +pub struct AnimationConfig { + #[knuffel(child, unwrap(argument), default=1.0)] + pub slowdown: f64, +} + #[derive(Clone, Default, Debug, serde::Serialize, serde::Deserialize)] pub struct DaemonConfig { pub outputs: Vec, // lockscreen: LockscreenConfig, pub log_level: LogLevel, + pub animation: AnimationConfig, } pub fn get_config_dir() -> PathBuf { @@ -149,6 +157,7 @@ pub fn load_config() -> miette::Result { } } + let config_nodes = knuffel::parse::>( config_path.to_str().unwrap(), config_file_contents.clone().unwrap().as_str(), @@ -157,6 +166,7 @@ pub fn load_config() -> miette::Result { let mut config = DaemonConfig { outputs: Vec::new(), log_level: LogLevel::DEFAULT, + animation: AnimationConfig::default(), }; for node in config_nodes { match node { @@ -176,6 +186,7 @@ pub fn load_config() -> miette::Result { config.outputs.push(n) } ConfigNode::Logging(level) => config.log_level = level, + ConfigNode::Animation(animation) => config.animation = animation, } } diff --git a/src/wayland/render_base.rs b/src/wayland/render_base.rs index 2f68398..c6451c2 100644 --- a/src/wayland/render_base.rs +++ b/src/wayland/render_base.rs @@ -172,6 +172,7 @@ pub struct WallpaperRenderState { pub position_x: i32, pub position_y: i32, pub scroll_state: Option, // should be None'd once scroll is finished + pub slowdown: f64, } impl WallpaperRenderState { @@ -184,6 +185,7 @@ impl WallpaperRenderState { wl_output: WlOutput, output_state: &OutputState, initial_pos: Option<(i32, i32)>, + slowdown: f64, ) -> Self { // create new buffer, load image into it, attach it to surface, apply role through daemon let pandora = weak.upgrade().unwrap(); @@ -271,6 +273,7 @@ impl WallpaperRenderState { position_y, scroll_state: None, mode: mode, + slowdown, }; } @@ -344,6 +347,7 @@ impl WallpaperRenderState { anim_start: Instant::now(), anim_duration: spring.duration(), anim: spring, + slowdown: self.slowdown, }); if !is_already_scrolling { @@ -359,7 +363,9 @@ impl WallpaperRenderState { fn calc_next_pos(&self) -> i32 { let scroll_state = self.scroll_state.as_ref().unwrap(); let eclipsed_duration = Instant::now() - scroll_state.anim_start; - return scroll_state.anim.value_at(eclipsed_duration).round() as i32; + let seconds = eclipsed_duration.as_secs_f64() / scroll_state.slowdown; + let scaled_duration = Duration::from_secs_f64(seconds); + return scroll_state.anim.value_at(scaled_duration).round() as i32; } fn do_scroll_tick(&mut self, conn: &mut Connection) { @@ -429,6 +435,7 @@ pub struct ScrollState { pub anim_start: Instant, pub anim_duration: Duration, // only needed for LERP'd animations with fixed durations pub anim: Spring, + pub slowdown: f64, } impl ScrollState { @@ -497,6 +504,7 @@ pub fn initialize_wallpaper_outputs( output.wl_output, output_state, None, + config.animation.slowdown.max(0.001), ); output_state.render_state = Some(crate::wayland::render_base::OutputRenderStateVariety::Wallpaper(wallpaper_state));