mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-03-24 02:11:14 +01:00
refactor(animation): generalized ANIMATION_MANAGER
instead of isize key for ANIMATION_MANAGER hashmap, now we use string
key. For window move animation key wouldbe `window_move:{hwnd}`.
That allows to use single manager for more types of animations.
This commit is contained in:
@@ -13,29 +13,23 @@ use super::ANIMATION_FPS;
|
||||
use super::ANIMATION_MANAGER;
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq)]
|
||||
pub struct Animation {
|
||||
pub hwnd: isize,
|
||||
}
|
||||
pub struct Animation {}
|
||||
|
||||
impl Animation {
|
||||
pub fn new(hwnd: isize) -> Self {
|
||||
Self { hwnd }
|
||||
}
|
||||
|
||||
/// Returns true if the animation needs to continue
|
||||
pub fn cancel(&mut self) -> bool {
|
||||
if !ANIMATION_MANAGER.lock().in_progress(self.hwnd) {
|
||||
pub fn cancel(animation_key: &str) -> bool {
|
||||
if !ANIMATION_MANAGER.lock().in_progress(animation_key) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// should be more than 0
|
||||
let cancel_idx = ANIMATION_MANAGER.lock().init_cancel(self.hwnd);
|
||||
let cancel_idx = ANIMATION_MANAGER.lock().init_cancel(animation_key);
|
||||
let max_duration = Duration::from_secs(1);
|
||||
let spent_duration = Instant::now();
|
||||
|
||||
while ANIMATION_MANAGER.lock().in_progress(self.hwnd) {
|
||||
while ANIMATION_MANAGER.lock().in_progress(animation_key) {
|
||||
if spent_duration.elapsed() >= max_duration {
|
||||
ANIMATION_MANAGER.lock().end(self.hwnd);
|
||||
ANIMATION_MANAGER.lock().end(animation_key);
|
||||
}
|
||||
|
||||
std::thread::sleep(Duration::from_millis(
|
||||
@@ -43,28 +37,28 @@ impl Animation {
|
||||
));
|
||||
}
|
||||
|
||||
let latest_cancel_idx = ANIMATION_MANAGER.lock().latest_cancel_idx(self.hwnd);
|
||||
let latest_cancel_idx = ANIMATION_MANAGER.lock().latest_cancel_idx(animation_key);
|
||||
|
||||
ANIMATION_MANAGER.lock().end_cancel(self.hwnd);
|
||||
ANIMATION_MANAGER.lock().end_cancel(animation_key);
|
||||
|
||||
latest_cancel_idx == cancel_idx
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_precision_loss)]
|
||||
pub fn animate(
|
||||
&mut self,
|
||||
animation_key: &str,
|
||||
duration: Duration,
|
||||
mut render_callback: impl FnMut(f64) -> Result<()>,
|
||||
) -> Result<()> {
|
||||
if ANIMATION_MANAGER.lock().in_progress(self.hwnd) {
|
||||
let should_animate = self.cancel();
|
||||
if ANIMATION_MANAGER.lock().in_progress(animation_key) {
|
||||
let should_animate = Self::cancel(animation_key);
|
||||
|
||||
if !should_animate {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
ANIMATION_MANAGER.lock().start(self.hwnd);
|
||||
ANIMATION_MANAGER.lock().start(animation_key);
|
||||
|
||||
let target_frame_time = Duration::from_millis(1000 / ANIMATION_FPS.load(Ordering::Relaxed));
|
||||
let mut progress = 0.0;
|
||||
@@ -73,9 +67,9 @@ impl Animation {
|
||||
// start animation
|
||||
while progress < 1.0 {
|
||||
// check if animation is cancelled
|
||||
if ANIMATION_MANAGER.lock().is_cancelled(self.hwnd) {
|
||||
if ANIMATION_MANAGER.lock().is_cancelled(animation_key) {
|
||||
// cancel animation
|
||||
ANIMATION_MANAGER.lock().cancel(self.hwnd);
|
||||
ANIMATION_MANAGER.lock().cancel(animation_key);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -92,7 +86,7 @@ impl Animation {
|
||||
}
|
||||
}
|
||||
|
||||
ANIMATION_MANAGER.lock().end(self.hwnd);
|
||||
ANIMATION_MANAGER.lock().end(animation_key);
|
||||
|
||||
// limit progress to 1.0 if animation took longer
|
||||
if progress > 1.0 {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
use super::ANIMATIONS_IN_PROGRESS;
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct AnimationState {
|
||||
@@ -12,7 +10,7 @@ struct AnimationState {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AnimationManager {
|
||||
animations: HashMap<isize, AnimationState>,
|
||||
animations: HashMap<String, AnimationState>,
|
||||
}
|
||||
|
||||
impl Default for AnimationManager {
|
||||
@@ -28,24 +26,24 @@ impl AnimationManager {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_cancelled(&self, hwnd: isize) -> bool {
|
||||
if let Some(animation_state) = self.animations.get(&hwnd) {
|
||||
pub fn is_cancelled(&self, animation_key: &str) -> bool {
|
||||
if let Some(animation_state) = self.animations.get(animation_key) {
|
||||
animation_state.pending_cancel_count > 0
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn in_progress(&self, hwnd: isize) -> bool {
|
||||
if let Some(animation_state) = self.animations.get(&hwnd) {
|
||||
pub fn in_progress(&self, animation_key: &str) -> bool {
|
||||
if let Some(animation_state) = self.animations.get(animation_key) {
|
||||
animation_state.in_progress
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_cancel(&mut self, hwnd: isize) -> usize {
|
||||
if let Some(animation_state) = self.animations.get_mut(&hwnd) {
|
||||
pub fn init_cancel(&mut self, animation_key: &str) -> usize {
|
||||
if let Some(animation_state) = self.animations.get_mut(animation_key) {
|
||||
animation_state.pending_cancel_count += 1;
|
||||
animation_state.cancel_idx_counter += 1;
|
||||
|
||||
@@ -56,51 +54,56 @@ impl AnimationManager {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn latest_cancel_idx(&mut self, hwnd: isize) -> usize {
|
||||
if let Some(animation_state) = self.animations.get_mut(&hwnd) {
|
||||
pub fn latest_cancel_idx(&mut self, animation_key: &str) -> usize {
|
||||
if let Some(animation_state) = self.animations.get_mut(animation_key) {
|
||||
animation_state.cancel_idx_counter
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn end_cancel(&mut self, hwnd: isize) {
|
||||
if let Some(animation_state) = self.animations.get_mut(&hwnd) {
|
||||
pub fn end_cancel(&mut self, animation_key: &str) {
|
||||
if let Some(animation_state) = self.animations.get_mut(animation_key) {
|
||||
animation_state.pending_cancel_count -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cancel(&mut self, hwnd: isize) {
|
||||
if let Some(animation_state) = self.animations.get_mut(&hwnd) {
|
||||
pub fn cancel(&mut self, animation_key: &str) {
|
||||
if let Some(animation_state) = self.animations.get_mut(animation_key) {
|
||||
animation_state.in_progress = false;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start(&mut self, hwnd: isize) {
|
||||
if let Entry::Vacant(e) = self.animations.entry(hwnd) {
|
||||
pub fn start(&mut self, animation_key: &str) {
|
||||
if let Entry::Vacant(e) = self.animations.entry(animation_key.to_string()) {
|
||||
e.insert(AnimationState {
|
||||
in_progress: true,
|
||||
cancel_idx_counter: 0,
|
||||
pending_cancel_count: 0,
|
||||
});
|
||||
|
||||
ANIMATIONS_IN_PROGRESS.store(self.animations.len(), Ordering::Release);
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(animation_state) = self.animations.get_mut(&hwnd) {
|
||||
if let Some(animation_state) = self.animations.get_mut(animation_key) {
|
||||
animation_state.in_progress = true;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn end(&mut self, hwnd: isize) {
|
||||
if let Some(animation_state) = self.animations.get_mut(&hwnd) {
|
||||
pub fn end(&mut self, animation_key: &str) {
|
||||
if let Some(animation_state) = self.animations.get_mut(animation_key) {
|
||||
animation_state.in_progress = false;
|
||||
|
||||
if animation_state.pending_cancel_count == 0 {
|
||||
self.animations.remove(&hwnd);
|
||||
ANIMATIONS_IN_PROGRESS.store(self.animations.len(), Ordering::Release);
|
||||
self.animations.remove(animation_key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn animations_in_progress(&self, animation_key_prefix: &str) -> usize {
|
||||
self.animations
|
||||
.keys()
|
||||
.filter(|key| key.starts_with(animation_key_prefix))
|
||||
.count()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ use crate::core::animation::AnimationStyle;
|
||||
use lazy_static::lazy_static;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::atomic::AtomicU64;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::Arc;
|
||||
|
||||
use parking_lot::Mutex;
|
||||
@@ -25,4 +24,3 @@ lazy_static! {
|
||||
pub static ANIMATION_ENABLED: AtomicBool = AtomicBool::new(false);
|
||||
pub static ANIMATION_DURATION: AtomicU64 = AtomicU64::new(250);
|
||||
pub static ANIMATION_FPS: AtomicU64 = AtomicU64::new(60);
|
||||
pub static ANIMATIONS_IN_PROGRESS: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::animation::lerp::Lerp;
|
||||
use crate::animation::ANIMATIONS_IN_PROGRESS;
|
||||
use crate::animation::ANIMATION_DURATION;
|
||||
use crate::animation::ANIMATION_ENABLED;
|
||||
use crate::animation::ANIMATION_MANAGER;
|
||||
use crate::animation::ANIMATION_STYLE;
|
||||
use crate::border_manager;
|
||||
use crate::com::SetCloak;
|
||||
@@ -60,16 +60,11 @@ pub static MINIMUM_HEIGHT: AtomicI32 = AtomicI32::new(0);
|
||||
#[derive(Debug, Default, Clone, Copy, Deserialize, JsonSchema, PartialEq)]
|
||||
pub struct Window {
|
||||
pub hwnd: isize,
|
||||
#[serde(skip)]
|
||||
animation: Animation,
|
||||
}
|
||||
|
||||
impl From<isize> for Window {
|
||||
fn from(value: isize) -> Self {
|
||||
Self {
|
||||
hwnd: value,
|
||||
animation: Animation::new(value),
|
||||
}
|
||||
Self { hwnd: value }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +72,6 @@ impl From<HWND> for Window {
|
||||
fn from(value: HWND) -> Self {
|
||||
Self {
|
||||
hwnd: value.0 as isize,
|
||||
animation: Animation::new(value.0 as isize),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -205,7 +199,6 @@ impl Window {
|
||||
pub fn animate_position(&self, start_rect: &Rect, target_rect: &Rect, top: bool) -> Result<()> {
|
||||
let start_rect = *start_rect;
|
||||
let target_rect = *target_rect;
|
||||
let mut animation = self.animation;
|
||||
let duration = Duration::from_millis(ANIMATION_DURATION.load(Ordering::SeqCst));
|
||||
let style = *ANIMATION_STYLE.lock();
|
||||
|
||||
@@ -218,33 +211,42 @@ impl Window {
|
||||
let hwnd = self.hwnd;
|
||||
|
||||
std::thread::spawn(move || {
|
||||
animation.animate(duration, |progress: f64| {
|
||||
let new_rect = start_rect.lerp(target_rect, progress, style);
|
||||
Animation::animate(
|
||||
format!("window_move:{}", hwnd).as_str(),
|
||||
duration,
|
||||
|progress: f64| {
|
||||
let new_rect = start_rect.lerp(target_rect, progress, style);
|
||||
|
||||
if progress == 1.0 {
|
||||
WindowsApi::position_window(hwnd, &new_rect, top)?;
|
||||
if WindowsApi::foreground_window().unwrap_or_default() == hwnd {
|
||||
focus_manager::send_notification(hwnd)
|
||||
if progress == 1.0 {
|
||||
WindowsApi::position_window(hwnd, &new_rect, top)?;
|
||||
if WindowsApi::foreground_window().unwrap_or_default() == hwnd {
|
||||
focus_manager::send_notification(hwnd)
|
||||
}
|
||||
|
||||
if ANIMATION_MANAGER
|
||||
.lock()
|
||||
.animations_in_progress("window_move")
|
||||
== 0
|
||||
{
|
||||
border_manager::BORDER_TEMPORARILY_DISABLED
|
||||
.store(false, Ordering::SeqCst);
|
||||
stackbar_manager::STACKBAR_TEMPORARILY_DISABLED
|
||||
.store(false, Ordering::SeqCst);
|
||||
|
||||
border_manager::send_notification(Some(hwnd));
|
||||
stackbar_manager::send_notification();
|
||||
transparency_manager::send_notification();
|
||||
}
|
||||
} else {
|
||||
// using MoveWindow because it runs faster than SetWindowPos
|
||||
// so animation have more fps and feel smoother
|
||||
WindowsApi::move_window(hwnd, &new_rect, false)?;
|
||||
WindowsApi::invalidate_rect(hwnd, None, false);
|
||||
}
|
||||
|
||||
if ANIMATIONS_IN_PROGRESS.load(Ordering::Acquire) == 0 {
|
||||
border_manager::BORDER_TEMPORARILY_DISABLED.store(false, Ordering::SeqCst);
|
||||
stackbar_manager::STACKBAR_TEMPORARILY_DISABLED
|
||||
.store(false, Ordering::SeqCst);
|
||||
|
||||
border_manager::send_notification(Some(hwnd));
|
||||
stackbar_manager::send_notification();
|
||||
transparency_manager::send_notification();
|
||||
}
|
||||
} else {
|
||||
// using MoveWindow because it runs faster than SetWindowPos
|
||||
// so animation have more fps and feel smoother
|
||||
WindowsApi::move_window(hwnd, &new_rect, false)?;
|
||||
WindowsApi::invalidate_rect(hwnd, None, false);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
Ok(())
|
||||
},
|
||||
)
|
||||
});
|
||||
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user