From 7dc791f4d411fd32b28324f1ba3fac448dff59ca Mon Sep 17 00:00:00 2001 From: Martin Askestad Date: Thu, 9 May 2024 12:25:57 +0200 Subject: [PATCH] Use async windows pos functions --- src/win32/mod.rs | 58 +++++++++++++++++++++++++------------------- src/windowmanager.rs | 9 +++++-- 2 files changed, 40 insertions(+), 27 deletions(-) diff --git a/src/win32/mod.rs b/src/win32/mod.rs index 5e376f7..99476ea 100644 --- a/src/win32/mod.rs +++ b/src/win32/mod.rs @@ -4,7 +4,6 @@ use std::{ path::PathBuf, }; -use log::debug; use windows::{ core::PCWSTR, w, @@ -27,14 +26,14 @@ use windows::{ Accessibility::{SetWinEventHook, HWINEVENTHOOK, WINEVENTPROC}, Shell::{FOLDERID_LocalAppData, SHGetKnownFolderPath, KF_FLAG_DEFAULT}, WindowsAndMessaging::{ - DefWindowProcW, EnumWindows, FindWindowW, GetClassNameW, GetCursorPos, - GetSystemMetrics, GetWindow, GetWindowLongPtrW, GetWindowTextLengthW, - GetWindowTextW, GetWindowThreadProcessId, IsIconic, IsWindowVisible, LoadIconW, - PostMessageW, PostQuitMessage, RegisterClassW, RegisterShellHookWindow, - RegisterWindowMessageW, SetWindowLongPtrW, SetWindowPos, ShowWindow, - SystemParametersInfoW, GET_WINDOW_CMD, GWL_EXSTYLE, GWL_STYLE, HICON, HWND_TOP, - SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN, SM_XVIRTUALSCREEN, SM_YVIRTUALSCREEN, - SPI_GETWORKAREA, SWP_NOACTIVATE, SW_SHOWMINNOACTIVE, + BeginDeferWindowPos, DefWindowProcW, DeferWindowPos, EndDeferWindowPos, + EnumWindows, FindWindowW, GetClassNameW, GetCursorPos, GetSystemMetrics, GetWindow, + GetWindowLongPtrW, GetWindowTextLengthW, GetWindowTextW, GetWindowThreadProcessId, + IsIconic, IsWindowVisible, LoadIconW, PostMessageW, PostQuitMessage, + RegisterClassW, RegisterShellHookWindow, RegisterWindowMessageW, SetWindowLongPtrW, + ShowWindow, SystemParametersInfoW, GET_WINDOW_CMD, GWL_EXSTYLE, GWL_STYLE, HDWP, + HICON, HWND_TOP, SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN, SM_XVIRTUALSCREEN, + SM_YVIRTUALSCREEN, SPI_GETWORKAREA, SWP_NOACTIVATE, SW_SHOWMINNOACTIVE, SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS, WINDOW_LONG_PTR_INDEX, WINEVENT_OUTOFCONTEXT, WNDCLASSW, WNDENUMPROC, }, @@ -50,6 +49,31 @@ pub(crate) mod taskbar; pub(crate) mod theme; pub(crate) mod virtualdesktop; +pub fn begin_defer_window_pos(num_windows: usize) -> Result { + Ok(unsafe { BeginDeferWindowPos(num_windows as i32)? }) +} + +pub fn defer_window_pos(hdwp: HDWP, hwnd: HWND, rect: RECT) -> Result { + let margin = dwm::get_window_extended_frame_bounds(hwnd); // Should be: (left: 7, top: 0, right: -7, bottom: -7) + let res = unsafe { + DeferWindowPos( + hdwp, + hwnd, + HWND_TOP, + rect.left - margin.left, + rect.top - margin.top, + (rect.right - rect.left) + margin.left * 2, + (rect.bottom - rect.top) - margin.bottom, + SWP_NOACTIVATE, + )? + }; + Ok(res) +} + +pub fn end_defer_window_pos(hdwp: HDWP) { + unsafe { EndDeferWindowPos(hdwp) }; +} + pub fn is_iconic(hwnd: HWND) -> bool { unsafe { IsIconic(hwnd).into() } } @@ -101,22 +125,6 @@ pub fn get_working_area() -> Result { } } -pub fn set_window_pos(hwnd: HWND, r: RECT) { - let margin = dwm::get_window_extended_frame_bounds(hwnd); // should be: { left: 7, top: 0, right:-7, bottom -7 } - debug!("{margin:?}"); - unsafe { - SetWindowPos( - hwnd, - HWND_TOP, - r.left - margin.left, - r.top - margin.top, - (r.right - r.left) - margin.right * 2, - (r.bottom - r.top) - margin.bottom, - SWP_NOACTIVATE, - ); - } -} - pub fn get_module_handle() -> windows::core::Result { unsafe { GetModuleHandleA(None) } } diff --git a/src/windowmanager.rs b/src/windowmanager.rs index 5931172..f7f3bb8 100644 --- a/src/windowmanager.rs +++ b/src/windowmanager.rs @@ -142,8 +142,13 @@ impl WindowManager { .collect(); let number_of_windows = windows_on_screen.len(); let ds = self.layout.arrange(self.working_area, number_of_windows); - for (w, d) in windows_on_screen.iter().zip(ds.iter()) { - win32::set_window_pos(w.0, *d); + if let Ok(mut hdwp) = win32::begin_defer_window_pos(number_of_windows) { + for (w, d) in windows_on_screen.iter().zip(ds.iter()) { + if let Ok(res) = win32::defer_window_pos(hdwp, w.0, *d) { + hdwp = res; + } + } + win32::end_defer_window_pos(hdwp); } let _ = win32::dwm::invalidate_iconic_bitmaps(self.hwnd); }