mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-23 22:01:31 +11:00
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:
parent
f379d069b9
commit
6ffd78767f
|
@ -144,6 +144,9 @@ and `WindowEvent::HoveredFile`.
|
||||||
- On macOS, change `WindowExtMacOS::request_user_attention()` to take an `enum` instead of a `bool`.
|
- On macOS, change `WindowExtMacOS::request_user_attention()` to take an `enum` instead of a `bool`.
|
||||||
|
|
||||||
# 0.20.0 Alpha 1 (2019-06-21)
|
# 0.20.0 Alpha 1 (2019-06-21)
|
||||||
|
- On Windows, fix window rectangle not getting set correctly on high-DPI systems.
|
||||||
|
|
||||||
|
# 0.20.0 Alpha 1
|
||||||
|
|
||||||
- Changes below are considered **breaking**.
|
- Changes below are considered **breaking**.
|
||||||
- Change all occurrences of `EventsLoop` to `EventLoop`.
|
- Change all occurrences of `EventsLoop` to `EventLoop`.
|
||||||
|
|
|
@ -5,7 +5,7 @@ fn main() {
|
||||||
use std::{collections::HashMap, sync::mpsc, thread, time::Duration};
|
use std::{collections::HashMap, sync::mpsc, thread, time::Duration};
|
||||||
|
|
||||||
use winit::{
|
use winit::{
|
||||||
dpi::{PhysicalPosition, PhysicalSize},
|
dpi::{PhysicalPosition, PhysicalSize},
|
||||||
event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent},
|
event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent},
|
||||||
event_loop::{ControlFlow, EventLoop},
|
event_loop::{ControlFlow, EventLoop},
|
||||||
window::{CursorIcon, Fullscreen, WindowBuilder},
|
window::{CursorIcon, Fullscreen, WindowBuilder},
|
||||||
|
|
10
src/event.rs
10
src/event.rs
|
@ -333,7 +333,15 @@ impl<'a> WindowEvent<'a> {
|
||||||
HoveredFileCancelled => Some(HoveredFileCancelled),
|
HoveredFileCancelled => Some(HoveredFileCancelled),
|
||||||
ReceivedCharacter(c) => Some(ReceivedCharacter(c)),
|
ReceivedCharacter(c) => Some(ReceivedCharacter(c)),
|
||||||
Focused(focused) => Some(Focused(focused)),
|
Focused(focused) => Some(Focused(focused)),
|
||||||
KeyboardInput { device_id, input, is_synthetic } => Some(KeyboardInput { device_id, input, is_synthetic }),
|
KeyboardInput {
|
||||||
|
device_id,
|
||||||
|
input,
|
||||||
|
is_synthetic,
|
||||||
|
} => Some(KeyboardInput {
|
||||||
|
device_id,
|
||||||
|
input,
|
||||||
|
is_synthetic,
|
||||||
|
}),
|
||||||
CursorMoved {
|
CursorMoved {
|
||||||
device_id,
|
device_id,
|
||||||
position,
|
position,
|
||||||
|
|
|
@ -2,54 +2,30 @@
|
||||||
|
|
||||||
use std::sync::Once;
|
use std::sync::Once;
|
||||||
|
|
||||||
|
use crate::platform_impl::platform::util::{
|
||||||
|
ENABLE_NON_CLIENT_DPI_SCALING, GET_DPI_FOR_MONITOR, GET_DPI_FOR_WINDOW, SET_PROCESS_DPI_AWARE,
|
||||||
|
SET_PROCESS_DPI_AWARENESS, SET_PROCESS_DPI_AWARENESS_CONTEXT,
|
||||||
|
};
|
||||||
use winapi::{
|
use winapi::{
|
||||||
shared::{
|
shared::{
|
||||||
minwindef::{BOOL, FALSE, UINT},
|
minwindef::FALSE,
|
||||||
windef::{DPI_AWARENESS_CONTEXT, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE, HMONITOR, HWND},
|
windef::{DPI_AWARENESS_CONTEXT, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE, HMONITOR, HWND},
|
||||||
winerror::S_OK,
|
winerror::S_OK,
|
||||||
},
|
},
|
||||||
um::{
|
um::{
|
||||||
shellscalingapi::{
|
shellscalingapi::{MDT_EFFECTIVE_DPI, PROCESS_PER_MONITOR_DPI_AWARE},
|
||||||
MDT_EFFECTIVE_DPI, MONITOR_DPI_TYPE, PROCESS_DPI_AWARENESS,
|
|
||||||
PROCESS_PER_MONITOR_DPI_AWARE,
|
|
||||||
},
|
|
||||||
wingdi::{GetDeviceCaps, LOGPIXELSX},
|
wingdi::{GetDeviceCaps, LOGPIXELSX},
|
||||||
winnt::HRESULT,
|
|
||||||
winuser::{self, MONITOR_DEFAULTTONEAREST},
|
winuser::{self, MONITOR_DEFAULTTONEAREST},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2: DPI_AWARENESS_CONTEXT = -4isize as _;
|
const DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2: DPI_AWARENESS_CONTEXT = -4isize as _;
|
||||||
|
|
||||||
type SetProcessDPIAware = unsafe extern "system" fn() -> BOOL;
|
|
||||||
type SetProcessDpiAwareness = unsafe extern "system" fn(value: PROCESS_DPI_AWARENESS) -> HRESULT;
|
|
||||||
type SetProcessDpiAwarenessContext =
|
|
||||||
unsafe extern "system" fn(value: DPI_AWARENESS_CONTEXT) -> BOOL;
|
|
||||||
type GetDpiForWindow = unsafe extern "system" fn(hwnd: HWND) -> UINT;
|
|
||||||
type GetDpiForMonitor = unsafe extern "system" fn(
|
|
||||||
hmonitor: HMONITOR,
|
|
||||||
dpi_type: MONITOR_DPI_TYPE,
|
|
||||||
dpi_x: *mut UINT,
|
|
||||||
dpi_y: *mut UINT,
|
|
||||||
) -> HRESULT;
|
|
||||||
type EnableNonClientDpiScaling = unsafe extern "system" fn(hwnd: HWND) -> BOOL;
|
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
static ref GET_DPI_FOR_WINDOW: Option<GetDpiForWindow> =
|
|
||||||
get_function!("user32.dll", GetDpiForWindow);
|
|
||||||
static ref GET_DPI_FOR_MONITOR: Option<GetDpiForMonitor> =
|
|
||||||
get_function!("shcore.dll", GetDpiForMonitor);
|
|
||||||
static ref ENABLE_NON_CLIENT_DPI_SCALING: Option<EnableNonClientDpiScaling> =
|
|
||||||
get_function!("user32.dll", EnableNonClientDpiScaling);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn become_dpi_aware() {
|
pub fn become_dpi_aware() {
|
||||||
static ENABLE_DPI_AWARENESS: Once = Once::new();
|
static ENABLE_DPI_AWARENESS: Once = Once::new();
|
||||||
ENABLE_DPI_AWARENESS.call_once(|| {
|
ENABLE_DPI_AWARENESS.call_once(|| {
|
||||||
unsafe {
|
unsafe {
|
||||||
if let Some(SetProcessDpiAwarenessContext) =
|
if let Some(SetProcessDpiAwarenessContext) = *SET_PROCESS_DPI_AWARENESS_CONTEXT {
|
||||||
get_function!("user32.dll", SetProcessDpiAwarenessContext)
|
|
||||||
{
|
|
||||||
// We are on Windows 10 Anniversary Update (1607) or later.
|
// We are on Windows 10 Anniversary Update (1607) or later.
|
||||||
if SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)
|
if SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)
|
||||||
== FALSE
|
== FALSE
|
||||||
|
@ -58,13 +34,10 @@ pub fn become_dpi_aware() {
|
||||||
// V1 if we can't set V2.
|
// V1 if we can't set V2.
|
||||||
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE);
|
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE);
|
||||||
}
|
}
|
||||||
} else if let Some(SetProcessDpiAwareness) =
|
} else if let Some(SetProcessDpiAwareness) = *SET_PROCESS_DPI_AWARENESS {
|
||||||
get_function!("shcore.dll", SetProcessDpiAwareness)
|
|
||||||
{
|
|
||||||
// We are on Windows 8.1 or later.
|
// We are on Windows 8.1 or later.
|
||||||
SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
|
SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
|
||||||
} else if let Some(SetProcessDPIAware) = get_function!("user32.dll", SetProcessDPIAware)
|
} else if let Some(SetProcessDPIAware) = *SET_PROCESS_DPI_AWARE {
|
||||||
{
|
|
||||||
// We are on Vista or later.
|
// We are on Vista or later.
|
||||||
SetProcessDPIAware();
|
SetProcessDPIAware();
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ use winapi::{
|
||||||
},
|
},
|
||||||
um::{
|
um::{
|
||||||
commctrl, libloaderapi, ole2, processthreadsapi, winbase,
|
commctrl, libloaderapi, ole2, processthreadsapi, winbase,
|
||||||
winnt::{HANDLE, LPCSTR, SHORT},
|
winnt::{HANDLE, LPCSTR, SHORT},
|
||||||
winuser,
|
winuser,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -48,15 +48,12 @@ use crate::{
|
||||||
event_loop::{ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootELW},
|
event_loop::{ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootELW},
|
||||||
platform_impl::platform::{
|
platform_impl::platform::{
|
||||||
dark_mode::try_dark_mode,
|
dark_mode::try_dark_mode,
|
||||||
dpi::{
|
dpi::{become_dpi_aware, dpi_to_scale_factor, enable_non_client_dpi_scaling},
|
||||||
become_dpi_aware, dpi_to_scale_factor, enable_non_client_dpi_scaling,
|
|
||||||
},
|
|
||||||
drop_handler::FileDropHandler,
|
drop_handler::FileDropHandler,
|
||||||
event::{
|
event::{
|
||||||
self, handle_extended_keys, process_key_params, vkey_to_winit_vkey, ModifiersStateSide,
|
self, handle_extended_keys, process_key_params, vkey_to_winit_vkey, ModifiersStateSide,
|
||||||
},
|
},
|
||||||
monitor, raw_input, util,
|
monitor, raw_input, util,
|
||||||
window::adjust_size,
|
|
||||||
window_state::{CursorFlags, WindowFlags, WindowState},
|
window_state::{CursorFlags, WindowFlags, WindowState},
|
||||||
wrap_device_id, WindowId, DEVICE_ID,
|
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();
|
let window_state = subclass_input.window_state.lock();
|
||||||
|
|
||||||
if window_state.min_size.is_some() || window_state.max_size.is_some() {
|
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 {
|
if let Some(min_size) = window_state.min_size {
|
||||||
let min_size = min_size.to_physical(window_state.dpi_factor);
|
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 {
|
(*mmi).ptMinTrackSize = POINT {
|
||||||
x: width as i32,
|
x: width as i32,
|
||||||
y: height 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 {
|
if let Some(max_size) = window_state.max_size {
|
||||||
let max_size = max_size.to_physical(window_state.dpi_factor);
|
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 {
|
(*mmi).ptMaxTrackSize = POINT {
|
||||||
x: width as i32,
|
x: width as i32,
|
||||||
y: height 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
|
// 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_x = u32::from(LOWORD(wparam as DWORD));
|
||||||
let new_dpi_factor = dpi_to_scale_factor(new_dpi_x);
|
let new_dpi_factor = dpi_to_scale_factor(new_dpi_x);
|
||||||
|
let old_dpi_factor: f64;
|
||||||
|
|
||||||
let allow_resize = {
|
let allow_resize = {
|
||||||
let mut window_state = subclass_input.window_state.lock();
|
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;
|
window_state.dpi_factor = new_dpi_factor;
|
||||||
|
|
||||||
new_dpi_factor != old_dpi_factor && window_state.fullscreen.is_none()
|
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;
|
margins_vertical = (margin_bottom + margin_top) as u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
let physical_inner_rect = PhysicalSize::new(
|
// Use the rect suggested by Windows
|
||||||
(rect.right - rect.left) as u32 - margins_horizontal,
|
// let physical_inner_rect = PhysicalSize::new(
|
||||||
(rect.bottom - rect.top) as u32 - margins_vertical,
|
// (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
|
// `allow_resize` prevents us from re-applying DPI adjustment to the restored size after
|
||||||
// exiting fullscreen (the restored size is already DPI adjusted).
|
// exiting fullscreen (the restored size is already DPI adjusted).
|
||||||
|
|
|
@ -6,51 +6,22 @@ use std::{
|
||||||
sync::atomic::{AtomicBool, Ordering},
|
sync::atomic::{AtomicBool, Ordering},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::window::CursorIcon;
|
use crate::{dpi::PhysicalSize, window::CursorIcon};
|
||||||
use winapi::{
|
use winapi::{
|
||||||
ctypes::wchar_t,
|
ctypes::wchar_t,
|
||||||
shared::{
|
shared::{
|
||||||
minwindef::{BOOL, DWORD},
|
minwindef::{BOOL, DWORD, UINT},
|
||||||
windef::{HWND, RECT},
|
windef::{DPI_AWARENESS_CONTEXT, HMONITOR, HWND, LPRECT, RECT},
|
||||||
},
|
},
|
||||||
um::{
|
um::{
|
||||||
libloaderapi::{GetProcAddress, LoadLibraryA},
|
libloaderapi::{GetProcAddress, LoadLibraryA},
|
||||||
|
shellscalingapi::{MONITOR_DPI_TYPE, PROCESS_DPI_AWARENESS},
|
||||||
winbase::lstrlenW,
|
winbase::lstrlenW,
|
||||||
winnt::LPCSTR,
|
winnt::{HRESULT, LONG, LPCSTR},
|
||||||
winuser,
|
winuser,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helper function to dynamically load function pointer.
|
|
||||||
// `library` and `function` must be zero-terminated.
|
|
||||||
pub(super) fn get_function_impl(library: &str, function: &str) -> Option<*const c_void> {
|
|
||||||
assert_eq!(library.chars().last(), Some('\0'));
|
|
||||||
assert_eq!(function.chars().last(), Some('\0'));
|
|
||||||
|
|
||||||
// Library names we will use are ASCII so we can use the A version to avoid string conversion.
|
|
||||||
let module = unsafe { LoadLibraryA(library.as_ptr() as LPCSTR) };
|
|
||||||
if module.is_null() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let function_ptr = unsafe { GetProcAddress(module, function.as_ptr() as LPCSTR) };
|
|
||||||
if function_ptr.is_null() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(function_ptr as _)
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! get_function {
|
|
||||||
($lib:expr, $func:ident) => {
|
|
||||||
crate::platform_impl::platform::util::get_function_impl(
|
|
||||||
concat!($lib, '\0'),
|
|
||||||
concat!(stringify!($func), '\0'),
|
|
||||||
)
|
|
||||||
.map(|f| unsafe { std::mem::transmute::<*const _, $func>(f) })
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn has_flag<T>(bitset: T, flag: T) -> bool
|
pub fn has_flag<T>(bitset: T, flag: T) -> bool
|
||||||
where
|
where
|
||||||
T: Copy + PartialEq + BitAnd<T, Output = T>,
|
T: Copy + PartialEq + BitAnd<T, Output = T>,
|
||||||
|
@ -105,6 +76,18 @@ pub fn get_client_rect(hwnd: HWND) -> Result<RECT, io::Error> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn adjust_size(hwnd: HWND, size: PhysicalSize) -> PhysicalSize {
|
||||||
|
let (width, height): (u32, u32) = size.into();
|
||||||
|
let rect = RECT {
|
||||||
|
left: 0,
|
||||||
|
right: width as LONG,
|
||||||
|
top: 0,
|
||||||
|
bottom: height as LONG,
|
||||||
|
};
|
||||||
|
let rect = adjust_window_rect(hwnd, rect).unwrap_or(rect);
|
||||||
|
PhysicalSize::new((rect.right - rect.left) as _, (rect.bottom - rect.top) as _)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn adjust_window_rect(hwnd: HWND, rect: RECT) -> Option<RECT> {
|
pub fn adjust_window_rect(hwnd: HWND, rect: RECT) -> Option<RECT> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let style = winuser::GetWindowLongW(hwnd, winuser::GWL_STYLE);
|
let style = winuser::GetWindowLongW(hwnd, winuser::GWL_STYLE);
|
||||||
|
@ -124,7 +107,14 @@ pub fn adjust_window_rect_with_styles(
|
||||||
*r = rect;
|
*r = rect;
|
||||||
|
|
||||||
let b_menu = !winuser::GetMenu(hwnd).is_null() as BOOL;
|
let b_menu = !winuser::GetMenu(hwnd).is_null() as BOOL;
|
||||||
winuser::AdjustWindowRectEx(r, style as _, b_menu, style_ex as _)
|
if let (Some(get_dpi_for_window), Some(adjust_window_rect_ex_for_dpi)) =
|
||||||
|
(*GET_DPI_FOR_WINDOW, *ADJUST_WINDOW_RECT_EX_FOR_DPI)
|
||||||
|
{
|
||||||
|
let dpi = get_dpi_for_window(hwnd);
|
||||||
|
adjust_window_rect_ex_for_dpi(r, style as _, b_menu, style_ex as _, dpi)
|
||||||
|
} else {
|
||||||
|
winuser::AdjustWindowRectEx(r, style as _, b_menu, style_ex as _)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -206,3 +196,71 @@ impl CursorIcon {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper function to dynamically load function pointer.
|
||||||
|
// `library` and `function` must be zero-terminated.
|
||||||
|
pub(super) fn get_function_impl(library: &str, function: &str) -> Option<*const c_void> {
|
||||||
|
assert_eq!(library.chars().last(), Some('\0'));
|
||||||
|
assert_eq!(function.chars().last(), Some('\0'));
|
||||||
|
|
||||||
|
// Library names we will use are ASCII so we can use the A version to avoid string conversion.
|
||||||
|
let module = unsafe { LoadLibraryA(library.as_ptr() as LPCSTR) };
|
||||||
|
if module.is_null() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let function_ptr = unsafe { GetProcAddress(module, function.as_ptr() as LPCSTR) };
|
||||||
|
if function_ptr.is_null() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(function_ptr as _)
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! get_function {
|
||||||
|
($lib:expr, $func:ident) => {
|
||||||
|
crate::platform_impl::platform::util::get_function_impl(
|
||||||
|
concat!($lib, '\0'),
|
||||||
|
concat!(stringify!($func), '\0'),
|
||||||
|
)
|
||||||
|
.map(|f| unsafe { std::mem::transmute::<*const _, $func>(f) })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type SetProcessDPIAware = unsafe extern "system" fn() -> BOOL;
|
||||||
|
pub type SetProcessDpiAwareness =
|
||||||
|
unsafe extern "system" fn(value: PROCESS_DPI_AWARENESS) -> HRESULT;
|
||||||
|
pub type SetProcessDpiAwarenessContext =
|
||||||
|
unsafe extern "system" fn(value: DPI_AWARENESS_CONTEXT) -> BOOL;
|
||||||
|
pub type GetDpiForWindow = unsafe extern "system" fn(hwnd: HWND) -> UINT;
|
||||||
|
pub type GetDpiForMonitor = unsafe extern "system" fn(
|
||||||
|
hmonitor: HMONITOR,
|
||||||
|
dpi_type: MONITOR_DPI_TYPE,
|
||||||
|
dpi_x: *mut UINT,
|
||||||
|
dpi_y: *mut UINT,
|
||||||
|
) -> HRESULT;
|
||||||
|
pub type EnableNonClientDpiScaling = unsafe extern "system" fn(hwnd: HWND) -> BOOL;
|
||||||
|
pub type AdjustWindowRectExForDpi = unsafe extern "system" fn(
|
||||||
|
rect: LPRECT,
|
||||||
|
dwStyle: DWORD,
|
||||||
|
bMenu: BOOL,
|
||||||
|
dwExStyle: DWORD,
|
||||||
|
dpi: UINT,
|
||||||
|
) -> BOOL;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
pub static ref GET_DPI_FOR_WINDOW: Option<GetDpiForWindow> =
|
||||||
|
get_function!("user32.dll", GetDpiForWindow);
|
||||||
|
pub static ref ADJUST_WINDOW_RECT_EX_FOR_DPI: Option<AdjustWindowRectExForDpi> =
|
||||||
|
get_function!("user32.dll", AdjustWindowRectExForDpi);
|
||||||
|
pub static ref GET_DPI_FOR_MONITOR: Option<GetDpiForMonitor> =
|
||||||
|
get_function!("shcore.dll", GetDpiForMonitor);
|
||||||
|
pub static ref ENABLE_NON_CLIENT_DPI_SCALING: Option<EnableNonClientDpiScaling> =
|
||||||
|
get_function!("user32.dll", EnableNonClientDpiScaling);
|
||||||
|
pub static ref SET_PROCESS_DPI_AWARENESS_CONTEXT: Option<SetProcessDpiAwarenessContext> =
|
||||||
|
get_function!("user32.dll", SetProcessDpiAwarenessContext);
|
||||||
|
pub static ref SET_PROCESS_DPI_AWARENESS: Option<SetProcessDpiAwareness> =
|
||||||
|
get_function!("shcore.dll", SetProcessDpiAwareness);
|
||||||
|
pub static ref SET_PROCESS_DPI_AWARE: Option<SetProcessDPIAware> =
|
||||||
|
get_function!("user32.dll", SetProcessDPIAware);
|
||||||
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ use std::{
|
||||||
use winapi::{
|
use winapi::{
|
||||||
ctypes::c_int,
|
ctypes::c_int,
|
||||||
shared::{
|
shared::{
|
||||||
minwindef::{DWORD, HINSTANCE, UINT},
|
minwindef::{HINSTANCE, UINT},
|
||||||
windef::{HWND, POINT, RECT},
|
windef::{HWND, POINT, RECT},
|
||||||
},
|
},
|
||||||
um::{
|
um::{
|
||||||
|
@ -37,9 +37,7 @@ use crate::{
|
||||||
dark_mode::try_dark_mode,
|
dark_mode::try_dark_mode,
|
||||||
dpi::{dpi_to_scale_factor, hwnd_dpi},
|
dpi::{dpi_to_scale_factor, hwnd_dpi},
|
||||||
drop_handler::FileDropHandler,
|
drop_handler::FileDropHandler,
|
||||||
event_loop::{
|
event_loop::{self, EventLoopWindowTarget, DESTROY_MSG_ID},
|
||||||
self, EventLoopWindowTarget, DESTROY_MSG_ID,
|
|
||||||
},
|
|
||||||
icon::{self, IconType, WinIcon},
|
icon::{self, IconType, WinIcon},
|
||||||
monitor, util,
|
monitor, util,
|
||||||
window_state::{CursorFlags, SavedWindow, WindowFlags, WindowState},
|
window_state::{CursorFlags, SavedWindow, WindowFlags, WindowState},
|
||||||
|
@ -669,22 +667,6 @@ pub struct WindowWrapper(HWND);
|
||||||
unsafe impl Sync for WindowWrapper {}
|
unsafe impl Sync for WindowWrapper {}
|
||||||
unsafe impl Send for WindowWrapper {}
|
unsafe impl Send for WindowWrapper {}
|
||||||
|
|
||||||
pub unsafe fn adjust_size(
|
|
||||||
physical_size: PhysicalSize,
|
|
||||||
style: DWORD,
|
|
||||||
ex_style: DWORD,
|
|
||||||
) -> (LONG, LONG) {
|
|
||||||
let (width, height): (u32, u32) = physical_size.into();
|
|
||||||
let mut rect = RECT {
|
|
||||||
left: 0,
|
|
||||||
right: width as LONG,
|
|
||||||
top: 0,
|
|
||||||
bottom: height as LONG,
|
|
||||||
};
|
|
||||||
winuser::AdjustWindowRectEx(&mut rect, style, 0, ex_style);
|
|
||||||
(rect.right - rect.left, rect.bottom - rect.top)
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn init<T: 'static>(
|
unsafe fn init<T: 'static>(
|
||||||
mut attributes: WindowAttributes,
|
mut attributes: WindowAttributes,
|
||||||
pl_attribs: PlatformSpecificWindowBuilderAttributes,
|
pl_attribs: PlatformSpecificWindowBuilderAttributes,
|
||||||
|
|
Loading…
Reference in a new issue