From 6f00c527a43a0ab5a7a51be70a104bb9b7db7cbb Mon Sep 17 00:00:00 2001 From: alex-ds13 <145657253+alex-ds13@users.noreply.github.com> Date: Sun, 24 Nov 2024 03:40:13 +0000 Subject: [PATCH] fix(wm): cross-monitor max floating window moves When moving maximized floating windows across monitors they were magically disappearing! The window would be on the correct place, with the correct coordinates and size, its styles wouldn't change it would still have the `VISIBLE` style, however the window was invisible. If we used the system move to try to move it sometimes we would be able to see a bar on the top of the monitor and if we moved the window with the keyboard on the direction of another monitor then the window would start showing up on that monitor... So it was visible on that monitor but not on the one we just moved it into. After some investigation I decided to atribute that behavior to magic, since I couldn't find any other plausible explanation, if someone knows about this please tell me, I too would like to learn the ways of this dark mysteries from the deep of the Windows OS. On a serious note, this commit creates a workaround for this by simply unmaximazing the window first (it's not restore, it doesn't change the size) then it moves the window (if animations are enabled it proceeds to wait for the animation to finish...), then it maximizes the window again. --- komorebi/src/window.rs | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/komorebi/src/window.rs b/komorebi/src/window.rs index c6b5437b..9740b560 100644 --- a/komorebi/src/window.rs +++ b/komorebi/src/window.rs @@ -25,6 +25,7 @@ use std::fmt::Formatter; use std::fmt::Write as _; use std::sync::atomic::AtomicI32; use std::sync::atomic::Ordering; +use std::thread; use std::time::Duration; use crate::core::config_generation::IdWithIdentifier; @@ -331,7 +332,46 @@ impl Window { bottom: corrected_height, }; - self.set_position(&new_rect, true) + let is_maximized = &new_rect == target_area; + if is_maximized { + windows_api::WindowsApi::unmaximize_window(self.hwnd); + let animation_enabled = ANIMATION_ENABLED_PER_ANIMATION.lock(); + let move_enabled = animation_enabled + .get(&MovementRenderDispatcher::PREFIX) + .is_some_and(|v| *v); + drop(animation_enabled); + + if move_enabled || ANIMATION_ENABLED_GLOBAL.load(Ordering::SeqCst) { + let anim_count = ANIMATION_MANAGER + .lock() + .count_in_progress(MovementRenderDispatcher::PREFIX); + self.set_position(&new_rect, true)?; + let hwnd = self.hwnd; + // Wait for the animation to finish before maximizing the window again, otherwise + // we would be maximizing the window on the current monitor anyway + thread::spawn(move || { + let mut new_anim_count = ANIMATION_MANAGER + .lock() + .count_in_progress(MovementRenderDispatcher::PREFIX); + let mut max_wait = 2000; // Max waiting time. No one will be using an animation longer than 2s, right? RIGHT??? WHY? + while new_anim_count > anim_count && max_wait > 0 { + thread::sleep(Duration::from_millis(10)); + new_anim_count = ANIMATION_MANAGER + .lock() + .count_in_progress(MovementRenderDispatcher::PREFIX); + max_wait -= 1; + } + windows_api::WindowsApi::maximize_window(hwnd); + }); + } else { + self.set_position(&new_rect, true)?; + windows_api::WindowsApi::maximize_window(self.hwnd); + } + } else { + self.set_position(&new_rect, true)?; + } + + Ok(()) } pub fn center(&mut self, work_area: &Rect) -> Result<()> {