diff --git a/komorebi/src/animation.rs b/komorebi/src/animation.rs index 09c2fc44..61302e5c 100644 --- a/komorebi/src/animation.rs +++ b/komorebi/src/animation.rs @@ -174,7 +174,7 @@ pub struct EaseOutExpo; impl Ease for EaseOutExpo { fn evaluate(t: f64) -> f64 { - if t == 1.0 { + if (t - 1.0).abs() < f64::EPSILON { return t; } @@ -186,7 +186,7 @@ pub struct EaseInOutExpo; impl Ease for EaseInOutExpo { fn evaluate(t: f64) -> f64 { - if t == 0.0 || t == 1.0 { + if t == 0.0 || (t - 1.0).abs() < f64::EPSILON { return t; } @@ -275,7 +275,7 @@ pub struct EaseInElastic; impl Ease for EaseInElastic { fn evaluate(t: f64) -> f64 { - if t == 1.0 || t == 0.0 { + if (t - 1.0).abs() < f64::EPSILON || t == 0.0 { return t; } @@ -289,7 +289,7 @@ pub struct EaseOutElastic; impl Ease for EaseOutElastic { fn evaluate(t: f64) -> f64 { - if t == 1.0 || t == 0.0 { + if (t - 1.0).abs() < f64::EPSILON || t == 0.0 { return t; } @@ -305,7 +305,7 @@ pub struct EaseInOutElastic; impl Ease for EaseInOutElastic { fn evaluate(t: f64) -> f64 { - if t == 1.0 || t == 0.0 { + if (t - 1.0).abs() < f64::EPSILON || t == 0.0 { return t; } @@ -399,7 +399,7 @@ fn apply_ease_func(t: f64) -> f64 { } } -#[derive(Debug, Clone, Copy, JsonSchema)] +#[derive(Debug, Default, Clone, Copy, JsonSchema)] pub struct Animation { // is_cancel: AtomicBool, // pub in_progress: AtomicBool, @@ -407,36 +407,37 @@ pub struct Animation { pub in_progress: bool, } -impl Default for Animation { - fn default() -> Self { - Animation { - // I'm not sure if this is the right way to do it - // I've tried to use Arc> but it dooes not implement Copy trait - // and I dont want to rewrite everything cause I'm not experienced with rust - // Down here you can see the idea I've tried to achive like in any other OOP language - // My thought is that in order to prevent Google Chrome breaking render window - // I need to cancel animation if user starting new window movement. So window stops - // moving at one point and then fires new animation. - // But my approach does not work because of rust borrowing rules and wired pointers - // lifetime annotation that I dont know how to use. - is_cancel: false, - in_progress: false, - // is_cancel: AtomicBool::new(false), - // in_progress: AtomicBool::new(false), - } - } -} +// impl Default for Animation { +// fn default() -> Self { +// Animation { +// // I'm not sure if this is the right way to do it +// // I've tried to use Arc> but it dooes not implement Copy trait +// // and I dont want to rewrite everything cause I'm not experienced with rust +// // Down here you can see the idea I've tried to achive like in any other OOP language +// // My thought is that in order to prevent Google Chrome breaking render window +// // I need to cancel animation if user starting new window movement. So window stops +// // moving at one point and then fires new animation. +// // But my approach does not work because of rust borrowing rules and wired pointers +// // lifetime annotation that I dont know how to use. +// is_cancel: false, +// in_progress: false, +// // is_cancel: AtomicBool::new(false), +// // in_progress: AtomicBool::new(false), +// } +// } +// } impl Animation { - pub fn cancel(&mut self) -> Result<()> { + pub fn cancel(&mut self) { if !self.in_progress { - return Ok(()); + return; } self.is_cancel = true; let max_duration = Duration::from_secs(1); let spent_duration = Instant::now(); + // TODO: Come back to this clippy lint while self.in_progress { if spent_duration.elapsed() >= max_duration { break; @@ -444,10 +445,9 @@ impl Animation { std::thread::sleep(Duration::from_millis(16)); } - - Ok(()) } + #[allow(clippy::cast_possible_truncation)] pub fn lerp(x: i32, new_x: i32, t: f64) -> i32 { let time = apply_ease_func(t); f64::from(new_x - x).mul_add(time, f64::from(x)) as i32 @@ -462,6 +462,7 @@ impl Animation { } } + #[allow(clippy::cast_precision_loss)] pub fn animate( &mut self, duration: Duration, diff --git a/komorebi/src/process_event.rs b/komorebi/src/process_event.rs index f3ac58d7..58a8e4a6 100644 --- a/komorebi/src/process_event.rs +++ b/komorebi/src/process_event.rs @@ -515,7 +515,8 @@ impl WindowManager { WindowManagerEvent::DisplayChange(..) | WindowManagerEvent::MouseCapture(..) | WindowManagerEvent::Cloak(..) - | WindowManagerEvent::Uncloak(..) => {} + | WindowManagerEvent::Uncloak(..) + | WindowManagerEvent::SetFocusedBorderWindow(..) => {} }; if *self.focused_workspace()?.tile() && BORDER_ENABLED.load(Ordering::SeqCst) { @@ -529,7 +530,8 @@ impl WindowManager { | WindowManagerEvent::Show(_, window) | WindowManagerEvent::FocusChange(_, window) | WindowManagerEvent::Hide(_, window) - | WindowManagerEvent::Minimize(_, window) => { + | WindowManagerEvent::Minimize(_, window) + | WindowManagerEvent::SetFocusedBorderWindow(window) => { let border = Border::from(BORDER_HWND.load(Ordering::SeqCst)); let mut target_window = None; let mut target_window_is_monocle = false; diff --git a/komorebi/src/window.rs b/komorebi/src/window.rs index df1a08e2..b64f9f3a 100644 --- a/komorebi/src/window.rs +++ b/komorebi/src/window.rs @@ -1,4 +1,5 @@ use crate::com::SetCloak; +use crate::winevent_listener::WINEVENT_CALLBACK_CHANNEL; use crate::ANIMATE_DURATION; use crate::ANIMATE_ENABLED; use std::collections::HashMap; @@ -110,7 +111,7 @@ impl Serialize for Window { impl Window { // for instantiation of animation struct pub fn new(hwnd: isize) -> Self { - Window { + Self { hwnd, animation: Animation::default(), } @@ -149,19 +150,23 @@ impl Window { let target_rect = *layout; let duration = Duration::from_millis(ANIMATE_DURATION.load(Ordering::SeqCst)); let mut animation = self.animation; + + let self_copied = *self; std::thread::spawn(move || { - animation - .animate(duration, |progress: f64| { - let new_rect = Animation::lerp_rect(&curr_rect, &target_rect, progress); - if progress < 1.0 { - // using MoveWindow because it runs faster than SetWindowPos - // so animation have more fps and feel smoother - WindowsApi::move_window(hwnd, &new_rect, true) - } else { - WindowsApi::position_window(hwnd, &new_rect, top) - } - }) - .unwrap(); + animation.animate(duration, |progress: f64| { + let new_rect = Animation::lerp_rect(&curr_rect, &target_rect, progress); + if progress < 1.0 { + // using MoveWindow because it runs faster than SetWindowPos + // so animation have more fps and feel smoother + WindowsApi::move_window(hwnd, &new_rect, true) + } else { + WindowsApi::position_window(hwnd, &new_rect, top)?; + Ok(WINEVENT_CALLBACK_CHANNEL + .lock() + .0 + .send(WindowManagerEvent::SetFocusedBorderWindow(self_copied))?) + } + }) }); Ok(()) @@ -202,8 +207,8 @@ impl Window { if ANIMATE_ENABLED.load(Ordering::SeqCst) { // check if animation is in progress if self.animation.in_progress { - // wait for cancle animation - self.animation.cancel().unwrap(); + // wait for cancel animation + self.animation.cancel(); } self.animate_position(&rect, top) diff --git a/komorebi/src/window_manager_event.rs b/komorebi/src/window_manager_event.rs index ae6d19bd..fa5af6f5 100644 --- a/komorebi/src/window_manager_event.rs +++ b/komorebi/src/window_manager_event.rs @@ -27,6 +27,7 @@ pub enum WindowManagerEvent { Unmanage(Window), Raise(Window), DisplayChange(Window), + SetFocusedBorderWindow(Window), } impl Display for WindowManagerEvent { @@ -77,6 +78,9 @@ impl Display for WindowManagerEvent { Self::DisplayChange(window) => { write!(f, "DisplayChange (Window: {window})") } + Self::SetFocusedBorderWindow(window) => { + write!(f, "SetFocusedBorderWindow (Window: {window})") + } } } } @@ -97,7 +101,8 @@ impl WindowManagerEvent { | Self::Raise(window) | Self::Manage(window) | Self::DisplayChange(window) - | Self::Unmanage(window) => window, + | Self::Unmanage(window) + | Self::SetFocusedBorderWindow(window) => window, } } diff --git a/komorebi/src/workspace.rs b/komorebi/src/workspace.rs index eddfd5bc..748dfff7 100644 --- a/komorebi/src/workspace.rs +++ b/komorebi/src/workspace.rs @@ -19,11 +19,15 @@ use komorebi_core::Layout; use komorebi_core::OperationDirection; use komorebi_core::Rect; +use crate::border::Border; use crate::container::Container; use crate::ring::Ring; use crate::static_config::WorkspaceConfig; use crate::window::Window; use crate::windows_api::WindowsApi; +use crate::ANIMATE_ENABLED; +use crate::BORDER_HIDDEN; +use crate::BORDER_HWND; use crate::DEFAULT_CONTAINER_PADDING; use crate::DEFAULT_WORKSPACE_PADDING; use crate::INITIAL_CONFIGURATION_LOADED; @@ -276,6 +280,12 @@ impl Workspace { window.add_title_bar()?; } + if ANIMATE_ENABLED.load(Ordering::SeqCst) { + let border = Border::from(BORDER_HWND.load(Ordering::SeqCst)); + border.hide()?; + BORDER_HIDDEN.store(true, Ordering::SeqCst); + } + window.set_position(layout, invisible_borders, false)?; } }