Skip to content

Commit dce1fa3

Browse files
authored
Merge pull request #10 from warpdotdev/andy/fix-windows-dpi-changed-4
Use the Tauri implementation of the DPI-change fix
2 parents e1958d8 + fbfa5ed commit dce1fa3

File tree

3 files changed

+107
-37
lines changed

3 files changed

+107
-37
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ features = [
204204

205205
[target.'cfg(target_os = "windows")'.dependencies]
206206
unicode-segmentation = "1.7.1"
207+
windows-version = "0.1.1"
207208

208209
[target.'cfg(target_os = "windows")'.dependencies.windows-sys]
209210
version = "0.52.0"

src/platform_impl/windows/event_loop.rs

Lines changed: 102 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ use crate::utils::Lazy;
1818
use windows_sys::Win32::Devices::HumanInterfaceDevice::MOUSE_MOVE_RELATIVE;
1919
use windows_sys::Win32::Foundation::{HWND, LPARAM, LRESULT, POINT, RECT, WPARAM};
2020
use windows_sys::Win32::Graphics::Gdi::{
21-
MonitorFromRect, RedrawWindow, ScreenToClient, ValidateRect, MONITOR_DEFAULTTONULL,
22-
RDW_INTERNALPAINT, SC_SCREENSAVE,
21+
GetMonitorInfoW, MonitorFromRect, MonitorFromWindow, RedrawWindow, ScreenToClient,
22+
ValidateRect, MONITORINFO, MONITOR_DEFAULTTONULL, RDW_INTERNALPAINT, SC_SCREENSAVE,
2323
};
2424
use windows_sys::Win32::System::Ole::RevokeDragDrop;
2525
use windows_sys::Win32::System::Threading::{GetCurrentThreadId, INFINITE};
@@ -2196,45 +2196,110 @@ unsafe fn public_window_callback_inner(
21962196
}
21972197

21982198
let new_outer_rect: RECT;
2199-
{
2200-
let suggested_ul =
2201-
(suggested_rect.left + margin_left, suggested_rect.top + margin_top);
2202-
2203-
let mut conservative_rect = RECT {
2204-
left: suggested_ul.0,
2205-
top: suggested_ul.1,
2206-
right: suggested_ul.0 + new_physical_inner_size.width as i32,
2207-
bottom: suggested_ul.1 + new_physical_inner_size.height as i32,
2208-
};
2199+
if util::WIN_VERSION.build < 22000 {
2200+
// The window position needs adjustment on Windows 10.
2201+
{
2202+
let suggested_ul =
2203+
(suggested_rect.left + margin_left, suggested_rect.top + margin_top);
2204+
2205+
let mut conservative_rect = RECT {
2206+
left: suggested_ul.0,
2207+
top: suggested_ul.1,
2208+
right: suggested_ul.0 + new_physical_inner_size.width as i32,
2209+
bottom: suggested_ul.1 + new_physical_inner_size.height as i32,
2210+
};
22092211

2210-
conservative_rect = window_flags
2211-
.adjust_rect(window, conservative_rect)
2212-
.unwrap_or(conservative_rect);
2213-
2214-
// If we're dragging the window, offset the window so that the cursor's
2215-
// relative horizontal position in the title bar is preserved.
2216-
if dragging_window {
2217-
let bias = {
2218-
let cursor_pos = {
2219-
let mut pos = unsafe { mem::zeroed() };
2220-
unsafe { GetCursorPos(&mut pos) };
2221-
pos
2212+
conservative_rect = window_flags
2213+
.adjust_rect(window, conservative_rect)
2214+
.unwrap_or(conservative_rect);
2215+
2216+
// If we're dragging the window, offset the window so that the cursor's
2217+
// relative horizontal position in the title bar is preserved.
2218+
if dragging_window {
2219+
let bias = {
2220+
let cursor_pos = {
2221+
let mut pos = unsafe { mem::zeroed() };
2222+
unsafe { GetCursorPos(&mut pos) };
2223+
pos
2224+
};
2225+
let suggested_cursor_horizontal_ratio =
2226+
(cursor_pos.x - suggested_rect.left) as f64
2227+
/ (suggested_rect.right - suggested_rect.left) as f64;
2228+
2229+
(cursor_pos.x
2230+
- (suggested_cursor_horizontal_ratio
2231+
* (conservative_rect.right - conservative_rect.left) as f64)
2232+
as i32)
2233+
- conservative_rect.left
22222234
};
2223-
let suggested_cursor_horizontal_ratio = (cursor_pos.x - suggested_rect.left)
2224-
as f64
2225-
/ (suggested_rect.right - suggested_rect.left) as f64;
2226-
2227-
(cursor_pos.x
2228-
- (suggested_cursor_horizontal_ratio
2229-
* (conservative_rect.right - conservative_rect.left) as f64)
2230-
as i32)
2231-
- conservative_rect.left
2235+
conservative_rect.left += bias;
2236+
conservative_rect.right += bias;
2237+
}
2238+
2239+
// Check to see if the new window rect is on the monitor with the new DPI factor.
2240+
// If it isn't, offset the window so that it is.
2241+
let new_dpi_monitor =
2242+
unsafe { MonitorFromWindow(window, MONITOR_DEFAULTTONULL) };
2243+
let conservative_rect_monitor =
2244+
unsafe { MonitorFromRect(&conservative_rect, MONITOR_DEFAULTTONULL) };
2245+
new_outer_rect = if conservative_rect_monitor == new_dpi_monitor {
2246+
conservative_rect
2247+
} else {
2248+
let get_monitor_rect = |monitor| {
2249+
let mut monitor_info = MONITORINFO {
2250+
cbSize: mem::size_of::<MONITORINFO>() as _,
2251+
..unsafe { mem::zeroed() }
2252+
};
2253+
unsafe { GetMonitorInfoW(monitor, &mut monitor_info) };
2254+
monitor_info.rcMonitor
2255+
};
2256+
let wrong_monitor = conservative_rect_monitor;
2257+
let wrong_monitor_rect = get_monitor_rect(wrong_monitor);
2258+
let new_monitor_rect = get_monitor_rect(new_dpi_monitor);
2259+
2260+
// The direction to nudge the window in to get the window onto the monitor with
2261+
// the new DPI factor. We calculate this by seeing which monitor edges are
2262+
// shared and nudging away from the wrong monitor based on those.
2263+
#[allow(clippy::bool_to_int_with_if)]
2264+
let delta_nudge_to_dpi_monitor = (
2265+
if wrong_monitor_rect.left == new_monitor_rect.right {
2266+
-1
2267+
} else if wrong_monitor_rect.right == new_monitor_rect.left {
2268+
1
2269+
} else {
2270+
0
2271+
},
2272+
if wrong_monitor_rect.bottom == new_monitor_rect.top {
2273+
1
2274+
} else if wrong_monitor_rect.top == new_monitor_rect.bottom {
2275+
-1
2276+
} else {
2277+
0
2278+
},
2279+
);
2280+
2281+
let abort_after_iterations = new_monitor_rect.right - new_monitor_rect.left
2282+
+ new_monitor_rect.bottom
2283+
- new_monitor_rect.top;
2284+
for _ in 0..abort_after_iterations {
2285+
conservative_rect.left += delta_nudge_to_dpi_monitor.0;
2286+
conservative_rect.right += delta_nudge_to_dpi_monitor.0;
2287+
conservative_rect.top += delta_nudge_to_dpi_monitor.1;
2288+
conservative_rect.bottom += delta_nudge_to_dpi_monitor.1;
2289+
2290+
if unsafe { MonitorFromRect(&conservative_rect, MONITOR_DEFAULTTONULL) }
2291+
== new_dpi_monitor
2292+
{
2293+
break;
2294+
}
2295+
}
2296+
2297+
conservative_rect
22322298
};
2233-
conservative_rect.left += bias;
2234-
conservative_rect.right += bias;
22352299
}
2236-
2237-
new_outer_rect = conservative_rect;
2300+
} else {
2301+
// The suggested position is fine w/o adjustment on Windows 11.
2302+
new_outer_rect = suggested_rect
22382303
}
22392304

22402305
unsafe {

src/platform_impl/windows/util.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::iter::once;
33
use std::ops::BitAnd;
44
use std::os::windows::prelude::{OsStrExt, OsStringExt};
55
use std::sync::atomic::{AtomicBool, Ordering};
6+
use std::sync::LazyLock;
67
use std::{io, mem, ptr};
78

89
use crate::utils::Lazy;
@@ -26,6 +27,9 @@ use windows_sys::Win32::UI::WindowsAndMessaging::{
2627

2728
use crate::window::CursorIcon;
2829

30+
pub static WIN_VERSION: LazyLock<windows_version::OsVersion> =
31+
LazyLock::new(windows_version::OsVersion::current);
32+
2933
pub fn encode_wide(string: impl AsRef<OsStr>) -> Vec<u16> {
3034
string.as_ref().encode_wide().chain(once(0)).collect()
3135
}

0 commit comments

Comments
 (0)