From 22f43e526b4c7120937e285471b5a4f92ceb55fb Mon Sep 17 00:00:00 2001 From: thearturca Date: Sat, 10 May 2025 16:33:26 +0300 Subject: [PATCH] refactor(animations): adds windows-api calls to improve resize behaviour of apps --- komorebi/src/window.rs | 13 +++++++++++-- komorebi/src/windows_api.rs | 22 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/komorebi/src/window.rs b/komorebi/src/window.rs index 3434203f..dc99aabc 100644 --- a/komorebi/src/window.rs +++ b/komorebi/src/window.rs @@ -59,6 +59,7 @@ use std::time::Duration; use strum::Display; use strum::EnumString; use windows::Win32::Foundation::HWND; +use windows::Win32::Graphics::Dwm::DwmFlush; pub static MINIMUM_WIDTH: AtomicI32 = AtomicI32::new(0); pub static MINIMUM_HEIGHT: AtomicI32 = AtomicI32::new(0); @@ -196,6 +197,8 @@ impl RenderDispatcher for MovementRenderDispatcher { stackbar_manager::STACKBAR_TEMPORARILY_DISABLED.store(true, Ordering::SeqCst); stackbar_manager::send_notification(); + WindowsApi::send_enter_size_move(self.hwnd)?; + Ok(()) } @@ -204,9 +207,14 @@ impl RenderDispatcher for MovementRenderDispatcher { // we don't check WINDOW_HANDLING_BEHAVIOUR here because animations // are always run on a separate thread - WindowsApi::move_window(self.hwnd, &new_rect, false)?; - WindowsApi::invalidate_rect(self.hwnd, None, false); + WindowsApi::move_window(self.hwnd, &new_rect, true)?; + // force window redraw + WindowsApi::invalidate_rect(self.hwnd, None, true); + WindowsApi::update_window(self.hwnd); + + // wait for dwm to flush render queue + unsafe { DwmFlush() }?; Ok(()) } @@ -214,6 +222,7 @@ impl RenderDispatcher for MovementRenderDispatcher { // we don't add the async_window_pos flag here because animations // are always run on a separate thread WindowsApi::position_window(self.hwnd, &self.target_rect, self.top, false)?; + WindowsApi::send_exit_size_move(self.hwnd)?; if ANIMATION_MANAGER .lock() .count_in_progress(MovementRenderDispatcher::PREFIX) diff --git a/komorebi/src/windows_api.rs b/komorebi/src/windows_api.rs index 326c4d5b..74c7a246 100644 --- a/komorebi/src/windows_api.rs +++ b/komorebi/src/windows_api.rs @@ -47,6 +47,7 @@ use windows::Win32::Graphics::Gdi::MonitorFromPoint; use windows::Win32::Graphics::Gdi::MonitorFromWindow; use windows::Win32::Graphics::Gdi::Rectangle; use windows::Win32::Graphics::Gdi::RoundRect; +use windows::Win32::Graphics::Gdi::UpdateWindow; use windows::Win32::System::Com::CLSCTX_ALL; use windows::Win32::System::Com::CoCreateInstance; use windows::Win32::System::LibraryLoader::GetModuleHandleW; @@ -128,6 +129,7 @@ use windows::Win32::UI::WindowsAndMessaging::SWP_NOSIZE; use windows::Win32::UI::WindowsAndMessaging::SWP_SHOWWINDOW; use windows::Win32::UI::WindowsAndMessaging::SYSTEM_PARAMETERS_INFO_ACTION; use windows::Win32::UI::WindowsAndMessaging::SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS; +use windows::Win32::UI::WindowsAndMessaging::SendMessageW; use windows::Win32::UI::WindowsAndMessaging::SetCursorPos; use windows::Win32::UI::WindowsAndMessaging::SetForegroundWindow; use windows::Win32::UI::WindowsAndMessaging::SetLayeredWindowAttributes; @@ -138,6 +140,8 @@ use windows::Win32::UI::WindowsAndMessaging::ShowWindowAsync; use windows::Win32::UI::WindowsAndMessaging::SystemParametersInfoW; use windows::Win32::UI::WindowsAndMessaging::WINDOW_LONG_PTR_INDEX; use windows::Win32::UI::WindowsAndMessaging::WM_CLOSE; +use windows::Win32::UI::WindowsAndMessaging::WM_ENTERSIZEMOVE; +use windows::Win32::UI::WindowsAndMessaging::WM_EXITSIZEMOVE; use windows::Win32::UI::WindowsAndMessaging::WNDCLASSW; use windows::Win32::UI::WindowsAndMessaging::WNDENUMPROC; use windows::Win32::UI::WindowsAndMessaging::WS_DISABLED; @@ -1387,6 +1391,24 @@ impl WindowsApi { unsafe { InvalidateRect(Option::from(HWND(as_ptr!(hwnd))), rect, erase) }.as_bool() } + pub fn send_enter_size_move(hwnd: isize) -> eyre::Result<()> { + unsafe { + SendMessageW(HWND(as_ptr!(hwnd)), WM_ENTERSIZEMOVE, None, None); + Ok(()) + } + } + + pub fn send_exit_size_move(hwnd: isize) -> eyre::Result<()> { + unsafe { + SendMessageW(HWND(as_ptr!(hwnd)), WM_EXITSIZEMOVE, None, None); + Ok(()) + } + } + + pub fn update_window(hwnd: isize) -> bool { + unsafe { UpdateWindow(HWND(as_ptr!(hwnd))) }.as_bool() + } + pub fn alt_is_pressed() -> bool { let state = unsafe { GetKeyState(i32::from(VK_MENU.0)) }; #[allow(clippy::cast_sign_loss)]