On Windows, make AdjustRect calls DPI-aware when possible (#1015)

* Use AdjustWidowRectExForDPI when available

* Prioritize presevering logical size when handling WM_DPICHANGED

* Format

* Add changelog entry
This commit is contained in:
Osspial 2020-01-04 01:29:40 -05:00
parent f379d069b9
commit 6ffd78767f
7 changed files with 143 additions and 107 deletions

View file

@ -36,7 +36,7 @@ use winapi::{
},
um::{
commctrl, libloaderapi, ole2, processthreadsapi, winbase,
winnt::{HANDLE, LPCSTR, SHORT},
winnt::{HANDLE, LPCSTR, SHORT},
winuser,
},
};
@ -48,15 +48,12 @@ use crate::{
event_loop::{ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootELW},
platform_impl::platform::{
dark_mode::try_dark_mode,
dpi::{
become_dpi_aware, dpi_to_scale_factor, enable_non_client_dpi_scaling,
},
dpi::{become_dpi_aware, dpi_to_scale_factor, enable_non_client_dpi_scaling},
drop_handler::FileDropHandler,
event::{
self, handle_extended_keys, process_key_params, vkey_to_winit_vkey, ModifiersStateSide,
},
monitor, raw_input, util,
window::adjust_size,
window_state::{CursorFlags, WindowFlags, WindowState},
wrap_device_id, WindowId, DEVICE_ID,
},
@ -1394,11 +1391,9 @@ unsafe extern "system" fn public_window_callback<T: 'static>(
let window_state = subclass_input.window_state.lock();
if window_state.min_size.is_some() || window_state.max_size.is_some() {
let style = winuser::GetWindowLongA(window, winuser::GWL_STYLE) as DWORD;
let ex_style = winuser::GetWindowLongA(window, winuser::GWL_EXSTYLE) as DWORD;
if let Some(min_size) = window_state.min_size {
let min_size = min_size.to_physical(window_state.dpi_factor);
let (width, height) = adjust_size(min_size, style, ex_style);
let (width, height): (u32, u32) = util::adjust_size(window, min_size).into();
(*mmi).ptMinTrackSize = POINT {
x: width as i32,
y: height as i32,
@ -1406,7 +1401,7 @@ unsafe extern "system" fn public_window_callback<T: 'static>(
}
if let Some(max_size) = window_state.max_size {
let max_size = max_size.to_physical(window_state.dpi_factor);
let (width, height) = adjust_size(max_size, style, ex_style);
let (width, height): (u32, u32) = util::adjust_size(window, max_size).into();
(*mmi).ptMaxTrackSize = POINT {
x: width as i32,
y: height as i32,
@ -1428,10 +1423,11 @@ unsafe extern "system" fn public_window_callback<T: 'static>(
// https://msdn.microsoft.com/en-us/library/windows/desktop/dn312083(v=vs.85).aspx
let new_dpi_x = u32::from(LOWORD(wparam as DWORD));
let new_dpi_factor = dpi_to_scale_factor(new_dpi_x);
let old_dpi_factor: f64;
let allow_resize = {
let mut window_state = subclass_input.window_state.lock();
let old_dpi_factor = window_state.dpi_factor;
old_dpi_factor = window_state.dpi_factor;
window_state.dpi_factor = new_dpi_factor;
new_dpi_factor != old_dpi_factor && window_state.fullscreen.is_none()
@ -1468,10 +1464,26 @@ unsafe extern "system" fn public_window_callback<T: 'static>(
margins_vertical = (margin_bottom + margin_top) as u32;
}
let physical_inner_rect = PhysicalSize::new(
(rect.right - rect.left) as u32 - margins_horizontal,
(rect.bottom - rect.top) as u32 - margins_vertical,
);
// Use the rect suggested by Windows
// let physical_inner_rect = PhysicalSize::new(
// (rect.right - rect.left) as u32 - margins_horizontal,
// (rect.bottom - rect.top) as u32 - margins_vertical,
// );
// We calculate our own rect because the default suggested rect doesn't do a great job
// of preserving the window's logical size.
let physical_inner_rect = {
let mut current_rect = mem::zeroed();
winuser::GetClientRect(window, &mut current_rect);
let client_rect = PhysicalSize::new(
(current_rect.right - current_rect.left) as u32,
(current_rect.bottom - current_rect.top) as u32,
);
client_rect
.to_logical(old_dpi_factor)
.to_physical(new_dpi_factor)
};
// `allow_resize` prevents us from re-applying DPI adjustment to the restored size after
// exiting fullscreen (the restored size is already DPI adjusted).