X11+Windows: Guess initial DPI factor (#583)
* X11: Guess initial DPI factor * Windows: Guess initial DPI factor
This commit is contained in:
parent
85ee422acd
commit
2f7321a076
13 changed files with 183 additions and 82 deletions
|
|
@ -1,5 +1,6 @@
|
|||
use winapi::shared::minwindef::{BOOL, DWORD, LPARAM, TRUE};
|
||||
use winapi::shared::windef::{HDC, HMONITOR, HWND, LPRECT, POINT};
|
||||
use winapi::um::winnt::LONG;
|
||||
use winapi::um::winuser;
|
||||
|
||||
use std::{mem, ptr};
|
||||
|
|
@ -49,7 +50,7 @@ unsafe extern "system" fn monitor_enum_proc(
|
|||
TRUE // continue enumeration
|
||||
}
|
||||
|
||||
fn get_available_monitors() -> VecDeque<MonitorId> {
|
||||
pub fn get_available_monitors() -> VecDeque<MonitorId> {
|
||||
let mut monitors: VecDeque<MonitorId> = VecDeque::new();
|
||||
unsafe {
|
||||
winuser::EnumDisplayMonitors(
|
||||
|
|
@ -62,7 +63,7 @@ fn get_available_monitors() -> VecDeque<MonitorId> {
|
|||
monitors
|
||||
}
|
||||
|
||||
fn get_primary_monitor() -> MonitorId {
|
||||
pub fn get_primary_monitor() -> MonitorId {
|
||||
const ORIGIN: POINT = POINT { x: 0, y: 0 };
|
||||
let hmonitor = unsafe {
|
||||
winuser::MonitorFromPoint(ORIGIN, winuser::MONITOR_DEFAULTTOPRIMARY)
|
||||
|
|
@ -132,6 +133,14 @@ impl MonitorId {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn contains_point(&self, point: &POINT) -> bool {
|
||||
let left = self.position.0 as LONG;
|
||||
let right = left + self.dimensions.0 as LONG;
|
||||
let top = self.position.1 as LONG;
|
||||
let bottom = top + self.dimensions.1 as LONG;
|
||||
point.x >= left && point.x <= right && point.y >= top && point.y <= bottom
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_name(&self) -> Option<String> {
|
||||
Some(self.monitor_name.clone())
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ use std::{self, mem, ptr, slice};
|
|||
use std::ops::BitAnd;
|
||||
|
||||
use winapi::ctypes::wchar_t;
|
||||
use winapi::shared::minwindef::DWORD;
|
||||
use winapi::shared::windef::{HWND, RECT};
|
||||
use winapi::shared::minwindef::{BOOL, DWORD};
|
||||
use winapi::shared::windef::{HWND, POINT, RECT};
|
||||
use winapi::um::errhandlingapi::GetLastError;
|
||||
use winapi::um::winbase::{
|
||||
FormatMessageW,
|
||||
|
|
@ -38,15 +38,23 @@ pub fn wchar_ptr_to_string(wchar: *const wchar_t) -> String {
|
|||
wchar_to_string(wchar_slice)
|
||||
}
|
||||
|
||||
pub fn get_window_rect(hwnd: HWND) -> Option<RECT> {
|
||||
let mut rect: RECT = unsafe { mem::uninitialized() };
|
||||
if unsafe { winuser::GetWindowRect(hwnd, &mut rect) } != 0 {
|
||||
Some(rect)
|
||||
pub unsafe fn status_map<T, F: FnMut(&mut T) -> BOOL>(mut fun: F) -> Option<T> {
|
||||
let mut data: T = mem::uninitialized();
|
||||
if fun(&mut data) != 0 {
|
||||
Some(data)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_cursor_pos() -> Option<POINT> {
|
||||
unsafe { status_map(|cursor_pos| winuser::GetCursorPos(cursor_pos)) }
|
||||
}
|
||||
|
||||
pub fn get_window_rect(hwnd: HWND) -> Option<RECT> {
|
||||
unsafe { status_map(|rect| winuser::GetWindowRect(hwnd, rect)) }
|
||||
}
|
||||
|
||||
// This won't be needed anymore if we just add a derive to winapi.
|
||||
pub fn rect_eq(a: &RECT, b: &RECT) -> bool {
|
||||
let left_eq = a.left == b.left;
|
||||
|
|
|
|||
|
|
@ -26,9 +26,10 @@ use {
|
|||
WindowAttributes,
|
||||
};
|
||||
use platform::platform::{Cursor, PlatformSpecificWindowBuilderAttributes, WindowId};
|
||||
use platform::platform::dpi::{BASE_DPI, dpi_to_scale_factor, get_window_dpi, get_window_scale_factor};
|
||||
use platform::platform::dpi::{dpi_to_scale_factor, get_window_dpi, get_window_scale_factor};
|
||||
use platform::platform::events_loop::{self, DESTROY_MSG_ID, EventsLoop, INITIAL_DPI_MSG_ID};
|
||||
use platform::platform::icon::{self, IconType, WinIcon};
|
||||
use platform::platform::monitor::get_available_monitors;
|
||||
use platform::platform::raw_input::register_all_mice_and_keyboards_for_raw_input;
|
||||
use platform::platform::util;
|
||||
|
||||
|
|
@ -858,9 +859,38 @@ unsafe fn init(
|
|||
// registering the window class
|
||||
let class_name = register_window_class(&window_icon, &taskbar_icon);
|
||||
|
||||
let (width, height) = attributes.dimensions
|
||||
.map(Into::into)
|
||||
.unwrap_or((1024, 768));
|
||||
let guessed_dpi_factor = {
|
||||
let monitors = get_available_monitors();
|
||||
let dpi_factor = if !monitors.is_empty() {
|
||||
let mut dpi_factor = Some(monitors[0].get_hidpi_factor());
|
||||
for monitor in &monitors {
|
||||
if Some(monitor.get_hidpi_factor()) != dpi_factor {
|
||||
dpi_factor = None;
|
||||
}
|
||||
}
|
||||
dpi_factor
|
||||
} else {
|
||||
unreachable!("There are no detected monitors, which should've already caused a panic.");
|
||||
};
|
||||
dpi_factor.unwrap_or_else(|| {
|
||||
util::get_cursor_pos()
|
||||
.and_then(|cursor_pos| {
|
||||
let mut dpi_factor = None;
|
||||
for monitor in &monitors {
|
||||
if monitor.contains_point(&cursor_pos) {
|
||||
dpi_factor = Some(monitor.get_hidpi_factor());
|
||||
break;
|
||||
}
|
||||
}
|
||||
dpi_factor
|
||||
})
|
||||
.unwrap_or(1.0)
|
||||
})
|
||||
};
|
||||
info!("Guessed window DPI factor: {}", guessed_dpi_factor);
|
||||
|
||||
let dimensions = attributes.dimensions.unwrap_or_else(|| (1024, 768).into());
|
||||
let (width, height): (u32, u32) = dimensions.to_physical(guessed_dpi_factor).into();
|
||||
// building a RECT object with coordinates
|
||||
let mut rect = RECT {
|
||||
left: 0,
|
||||
|
|
@ -899,11 +929,11 @@ unsafe fn init(
|
|||
let real_window = {
|
||||
let (adjusted_width, adjusted_height) = if attributes.dimensions.is_some() {
|
||||
let min_dimensions = attributes.min_dimensions
|
||||
.map(|logical_size| PhysicalSize::from_logical(logical_size, 1.0))
|
||||
.map(|logical_size| PhysicalSize::from_logical(logical_size, guessed_dpi_factor))
|
||||
.map(|physical_size| adjust_size(physical_size, style, ex_style))
|
||||
.unwrap_or((0, 0));
|
||||
let max_dimensions = attributes.max_dimensions
|
||||
.map(|logical_size| PhysicalSize::from_logical(logical_size, 1.0))
|
||||
.map(|logical_size| PhysicalSize::from_logical(logical_size, guessed_dpi_factor))
|
||||
.map(|physical_size| adjust_size(physical_size, style, ex_style))
|
||||
.unwrap_or((c_int::max_value(), c_int::max_value()));
|
||||
(
|
||||
|
|
@ -968,7 +998,8 @@ unsafe fn init(
|
|||
|
||||
let dpi = get_window_dpi(real_window.0, real_window.1);
|
||||
let dpi_factor = dpi_to_scale_factor(dpi);
|
||||
if dpi != BASE_DPI {
|
||||
if dpi_factor != guessed_dpi_factor {
|
||||
let (width, height): (u32, u32) = dimensions.into();
|
||||
let mut packed_dimensions = 0;
|
||||
// MAKELPARAM isn't provided by winapi yet.
|
||||
let ptr = &mut packed_dimensions as *mut LPARAM as *mut WORD;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue