From 025cb08b3e059ab310658dd149fd928fd22d92bc Mon Sep 17 00:00:00 2001 From: LGUG2Z Date: Sat, 6 Jan 2024 14:30:09 -0800 Subject: [PATCH] fix(wm): identify monitor dpi correctly This commit uses a more reliable Win32 API call to determine the scaling factor / DPI of user monitors, so that the scale of a window can be correctly adjusted when moved between monitors with different DPI settings. fix #622 --- justfile | 2 +- komorebi/src/window_manager.rs | 2 +- komorebi/src/windows_api.rs | 30 ++++++++++++++++++++++-------- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/justfile b/justfile index c9baefe4..30de3cca 100644 --- a/justfile +++ b/justfile @@ -28,7 +28,7 @@ install: just install-target komorebi run: - just install-komorebic + just install-target komorebic cargo +stable run --bin komorebi --locked warn $RUST_LOG="warn": diff --git a/komorebi/src/window_manager.rs b/komorebi/src/window_manager.rs index 59d530cc..6ddebf72 100644 --- a/komorebi/src/window_manager.rs +++ b/komorebi/src/window_manager.rs @@ -1322,7 +1322,7 @@ impl WindowManager { .ok_or_else(|| anyhow!("there is no monitor at this index"))? .id(); - if !WindowsApi::monitors_have_same_scale_factor(a, b)? { + if !WindowsApi::monitors_have_same_dpi(a, b)? { self.update_focused_workspace(self.mouse_follows_focus)?; } } diff --git a/komorebi/src/windows_api.rs b/komorebi/src/windows_api.rs index 103c041c..f1858586 100644 --- a/komorebi/src/windows_api.rs +++ b/komorebi/src/windows_api.rs @@ -52,8 +52,10 @@ use windows::Win32::System::Threading::QueryFullProcessImageNameW; use windows::Win32::System::Threading::PROCESS_ACCESS_RIGHTS; use windows::Win32::System::Threading::PROCESS_NAME_WIN32; use windows::Win32::System::Threading::PROCESS_QUERY_INFORMATION; +use windows::Win32::UI::HiDpi::GetDpiForMonitor; use windows::Win32::UI::HiDpi::SetProcessDpiAwarenessContext; use windows::Win32::UI::HiDpi::DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2; +use windows::Win32::UI::HiDpi::MDT_EFFECTIVE_DPI; use windows::Win32::UI::Input::KeyboardAndMouse::GetKeyState; use windows::Win32::UI::Input::KeyboardAndMouse::SendInput; use windows::Win32::UI::Input::KeyboardAndMouse::SetFocus; @@ -64,8 +66,6 @@ use windows::Win32::UI::Input::KeyboardAndMouse::MOUSEEVENTF_LEFTDOWN; use windows::Win32::UI::Input::KeyboardAndMouse::MOUSEEVENTF_LEFTUP; use windows::Win32::UI::Input::KeyboardAndMouse::MOUSEINPUT; use windows::Win32::UI::Input::KeyboardAndMouse::VK_MENU; -use windows::Win32::UI::Shell::Common::DEVICE_SCALE_FACTOR; -use windows::Win32::UI::Shell::GetScaleFactorForMonitor; use windows::Win32::UI::WindowsAndMessaging::AllowSetForegroundWindow; use windows::Win32::UI::WindowsAndMessaging::BringWindowToTop; use windows::Win32::UI::WindowsAndMessaging::CreateWindowExW; @@ -802,15 +802,29 @@ impl WindowsApi { Result::from(WindowsResult::from(unsafe { RegisterClassW(window_class) })) } - pub fn scale_factor_for_monitor(hmonitor: isize) -> Result { - unsafe { GetScaleFactorForMonitor(HMONITOR(hmonitor)) }.process() + pub fn dpi_for_monitor(hmonitor: isize) -> Result { + let mut dpi_x = u32::default(); + let mut dpi_y = u32::default(); + + unsafe { + GetDpiForMonitor( + HMONITOR(hmonitor), + MDT_EFFECTIVE_DPI, + std::ptr::addr_of_mut!(dpi_x), + std::ptr::addr_of_mut!(dpi_y), + ) + } + .process()?; + + #[allow(clippy::cast_precision_loss)] + Ok(dpi_y as f32 / 96.0) } - pub fn monitors_have_same_scale_factor(a: isize, b: isize) -> Result { - let a = Self::scale_factor_for_monitor(a)?; - let b = Self::scale_factor_for_monitor(b)?; + pub fn monitors_have_same_dpi(hmonitor_a: isize, hmonitor_b: isize) -> Result { + let dpi_a = Self::dpi_for_monitor(hmonitor_a)?; + let dpi_b = Self::dpi_for_monitor(hmonitor_b)?; - Ok(a == b) + Ok((dpi_a - dpi_b).abs() < f32::EPSILON) } pub fn round_corners(hwnd: isize) -> Result<()> {