winit/platform_impl/windows/
dpi.rs1#![allow(non_snake_case, unused_unsafe)]
2
3use std::sync::Once;
4
5use windows_sys::Win32::Foundation::{HWND, S_OK};
6use windows_sys::Win32::Graphics::Gdi::{
7 GetDC, GetDeviceCaps, MonitorFromWindow, HMONITOR, LOGPIXELSX, MONITOR_DEFAULTTONEAREST,
8};
9use windows_sys::Win32::UI::HiDpi::{
10 DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2,
11 MDT_EFFECTIVE_DPI, PROCESS_PER_MONITOR_DPI_AWARE,
12};
13use windows_sys::Win32::UI::WindowsAndMessaging::IsProcessDPIAware;
14
15use crate::platform_impl::platform::util::{
16 ENABLE_NON_CLIENT_DPI_SCALING, GET_DPI_FOR_MONITOR, GET_DPI_FOR_WINDOW, SET_PROCESS_DPI_AWARE,
17 SET_PROCESS_DPI_AWARENESS, SET_PROCESS_DPI_AWARENESS_CONTEXT,
18};
19
20pub fn become_dpi_aware() {
21 static ENABLE_DPI_AWARENESS: Once = Once::new();
22 ENABLE_DPI_AWARENESS.call_once(|| {
23 unsafe {
24 if let Some(SetProcessDpiAwarenessContext) = *SET_PROCESS_DPI_AWARENESS_CONTEXT {
25 if SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)
27 == false.into()
28 {
29 SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE);
32 }
33 } else if let Some(SetProcessDpiAwareness) = *SET_PROCESS_DPI_AWARENESS {
34 SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
36 } else if let Some(SetProcessDPIAware) = *SET_PROCESS_DPI_AWARE {
37 SetProcessDPIAware();
39 }
40 }
41 });
42}
43
44pub fn enable_non_client_dpi_scaling(hwnd: HWND) {
45 unsafe {
46 if let Some(EnableNonClientDpiScaling) = *ENABLE_NON_CLIENT_DPI_SCALING {
47 EnableNonClientDpiScaling(hwnd);
48 }
49 }
50}
51
52pub fn get_monitor_dpi(hmonitor: HMONITOR) -> Option<u32> {
53 unsafe {
54 if let Some(GetDpiForMonitor) = *GET_DPI_FOR_MONITOR {
55 let mut dpi_x = 0;
57 let mut dpi_y = 0;
58 if GetDpiForMonitor(hmonitor, MDT_EFFECTIVE_DPI, &mut dpi_x, &mut dpi_y) == S_OK {
59 return Some(dpi_x);
63 }
64 }
65 }
66 None
67}
68
69pub const BASE_DPI: u32 = 96;
70pub fn dpi_to_scale_factor(dpi: u32) -> f64 {
71 dpi as f64 / BASE_DPI as f64
72}
73
74pub unsafe fn hwnd_dpi(hwnd: HWND) -> u32 {
75 let hdc = unsafe { GetDC(hwnd) };
76 if hdc == 0 {
77 panic!("[winit] `GetDC` returned null!");
78 }
79 if let Some(GetDpiForWindow) = *GET_DPI_FOR_WINDOW {
80 match unsafe { GetDpiForWindow(hwnd) } {
82 0 => BASE_DPI, dpi => dpi,
84 }
85 } else if let Some(GetDpiForMonitor) = *GET_DPI_FOR_MONITOR {
86 let monitor = unsafe { MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST) };
88 if monitor == 0 {
89 return BASE_DPI;
90 }
91
92 let mut dpi_x = 0;
93 let mut dpi_y = 0;
94 if unsafe { GetDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, &mut dpi_x, &mut dpi_y) } == S_OK {
95 dpi_x
96 } else {
97 BASE_DPI
98 }
99 } else {
100 if unsafe { IsProcessDPIAware() } != false.into() {
102 unsafe { GetDeviceCaps(hdc, LOGPIXELSX as i32) as u32 }
105 } else {
106 BASE_DPI
110 }
111 }
112}