WIP - Make EL2 DPI changes and implement on Windows (#895)
* Modify DPI API publicly and on Windows * Add generic Position and make dpi creation functions const * Make examples work * Fix fullscreen windows not appearing * Replace Logical coordinates in window events with Physical coordinates * Update HiDpiFactorChanged * Document to_static
This commit is contained in:
parent
2da24089de
commit
f379d069b9
16 changed files with 427 additions and 369 deletions
|
|
@ -14,7 +14,7 @@ use std::{
|
|||
use winapi::{
|
||||
ctypes::c_int,
|
||||
shared::{
|
||||
minwindef::{DWORD, HINSTANCE, LPARAM, UINT, WORD, WPARAM},
|
||||
minwindef::{DWORD, HINSTANCE, UINT},
|
||||
windef::{HWND, POINT, RECT},
|
||||
},
|
||||
um::{
|
||||
|
|
@ -30,14 +30,16 @@ use winapi::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
dpi::{LogicalPosition, LogicalSize, PhysicalSize},
|
||||
dpi::{PhysicalPosition, PhysicalSize, Position, Size},
|
||||
error::{ExternalError, NotSupportedError, OsError as RootOsError},
|
||||
monitor::MonitorHandle as RootMonitorHandle,
|
||||
platform_impl::platform::{
|
||||
dark_mode::try_dark_mode,
|
||||
dpi::{dpi_to_scale_factor, hwnd_dpi},
|
||||
drop_handler::FileDropHandler,
|
||||
event_loop::{self, EventLoopWindowTarget, DESTROY_MSG_ID, INITIAL_DPI_MSG_ID},
|
||||
event_loop::{
|
||||
self, EventLoopWindowTarget, DESTROY_MSG_ID,
|
||||
},
|
||||
icon::{self, IconType, WinIcon},
|
||||
monitor, util,
|
||||
window_state::{CursorFlags, SavedWindow, WindowFlags, WindowState},
|
||||
|
|
@ -125,8 +127,8 @@ impl Window {
|
|||
|
||||
#[inline]
|
||||
pub fn set_visible(&self, visible: bool) {
|
||||
let window_state = Arc::clone(&self.window_state);
|
||||
let window = self.window.clone();
|
||||
let window_state = Arc::clone(&self.window_state);
|
||||
self.thread_executor.execute_in_thread(move || {
|
||||
WindowState::set_window_flags(window_state.lock(), window.0, |f| {
|
||||
f.set(WindowFlags::VISIBLE, visible)
|
||||
|
|
@ -146,41 +148,34 @@ impl Window {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn outer_position_physical(&self) -> (i32, i32) {
|
||||
#[inline]
|
||||
pub fn outer_position(&self) -> Result<PhysicalPosition, NotSupportedError> {
|
||||
util::get_window_rect(self.window.0)
|
||||
.map(|rect| (rect.left as i32, rect.top as i32))
|
||||
.unwrap()
|
||||
.map(|rect| Ok(PhysicalPosition::new(rect.left as f64, rect.top as f64)))
|
||||
.expect("Unexpected GetWindowRect failure; please report this error to https://github.com/rust-windowing/winit")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn outer_position(&self) -> Result<LogicalPosition, NotSupportedError> {
|
||||
let physical_position = self.outer_position_physical();
|
||||
let dpi_factor = self.hidpi_factor();
|
||||
Ok(LogicalPosition::from_physical(
|
||||
physical_position,
|
||||
dpi_factor,
|
||||
))
|
||||
}
|
||||
|
||||
pub(crate) fn inner_position_physical(&self) -> (i32, i32) {
|
||||
pub fn inner_position(&self) -> Result<PhysicalPosition, NotSupportedError> {
|
||||
let mut position: POINT = unsafe { mem::zeroed() };
|
||||
if unsafe { winuser::ClientToScreen(self.window.0, &mut position) } == 0 {
|
||||
panic!("Unexpected ClientToScreen failure: please report this error to https://github.com/rust-windowing/winit")
|
||||
}
|
||||
(position.x, position.y)
|
||||
Ok(PhysicalPosition::new(position.x as f64, position.y as f64))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn inner_position(&self) -> Result<LogicalPosition, NotSupportedError> {
|
||||
let physical_position = self.inner_position_physical();
|
||||
let dpi_factor = self.hidpi_factor();
|
||||
Ok(LogicalPosition::from_physical(
|
||||
physical_position,
|
||||
dpi_factor,
|
||||
))
|
||||
}
|
||||
pub fn set_outer_position(&self, position: Position) {
|
||||
let (x, y): (i32, i32) = position.to_physical(self.hidpi_factor()).into();
|
||||
|
||||
let window_state = Arc::clone(&self.window_state);
|
||||
let window = self.window.clone();
|
||||
self.thread_executor.execute_in_thread(move || {
|
||||
WindowState::set_window_flags(window_state.lock(), window.0, |f| {
|
||||
f.set(WindowFlags::MAXIMIZED, false)
|
||||
});
|
||||
});
|
||||
|
||||
pub(crate) fn set_position_physical(&self, x: i32, y: i32) {
|
||||
unsafe {
|
||||
winuser::SetWindowPos(
|
||||
self.window.0,
|
||||
|
|
@ -199,43 +194,22 @@ impl Window {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_outer_position(&self, logical_position: LogicalPosition) {
|
||||
let dpi_factor = self.hidpi_factor();
|
||||
let (x, y) = logical_position.to_physical(dpi_factor).into();
|
||||
|
||||
let window_state = Arc::clone(&self.window_state);
|
||||
let window = self.window.clone();
|
||||
self.thread_executor.execute_in_thread(move || {
|
||||
WindowState::set_window_flags(window_state.lock(), window.0, |f| {
|
||||
f.set(WindowFlags::MAXIMIZED, false)
|
||||
});
|
||||
});
|
||||
|
||||
self.set_position_physical(x, y);
|
||||
}
|
||||
|
||||
pub(crate) fn inner_size_physical(&self) -> (u32, u32) {
|
||||
pub fn inner_size(&self) -> PhysicalSize {
|
||||
let mut rect: RECT = unsafe { mem::zeroed() };
|
||||
if unsafe { winuser::GetClientRect(self.window.0, &mut rect) } == 0 {
|
||||
panic!("Unexpected GetClientRect failure: please report this error to https://github.com/rust-windowing/winit")
|
||||
}
|
||||
(
|
||||
PhysicalSize::new(
|
||||
(rect.right - rect.left) as u32,
|
||||
(rect.bottom - rect.top) as u32,
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn inner_size(&self) -> LogicalSize {
|
||||
let physical_size = self.inner_size_physical();
|
||||
let dpi_factor = self.hidpi_factor();
|
||||
LogicalSize::from_physical(physical_size, dpi_factor)
|
||||
}
|
||||
|
||||
pub(crate) fn outer_size_physical(&self) -> (u32, u32) {
|
||||
pub fn outer_size(&self) -> PhysicalSize {
|
||||
util::get_window_rect(self.window.0)
|
||||
.map(|rect| {
|
||||
(
|
||||
PhysicalSize::new(
|
||||
(rect.right - rect.left) as u32,
|
||||
(rect.bottom - rect.top) as u32,
|
||||
)
|
||||
|
|
@ -243,13 +217,6 @@ impl Window {
|
|||
.unwrap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn outer_size(&self) -> LogicalSize {
|
||||
let physical_size = self.outer_size_physical();
|
||||
let dpi_factor = self.hidpi_factor();
|
||||
LogicalSize::from_physical(physical_size, dpi_factor)
|
||||
}
|
||||
|
||||
pub(crate) fn set_inner_size_physical(&self, x: u32, y: u32) {
|
||||
unsafe {
|
||||
let rect = util::adjust_window_rect(
|
||||
|
|
@ -283,9 +250,9 @@ impl Window {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_inner_size(&self, logical_size: LogicalSize) {
|
||||
pub fn set_inner_size(&self, size: Size) {
|
||||
let dpi_factor = self.hidpi_factor();
|
||||
let (width, height) = logical_size.to_physical(dpi_factor).into();
|
||||
let (width, height) = size.to_physical(dpi_factor).into();
|
||||
|
||||
let window_state = Arc::clone(&self.window_state);
|
||||
let window = self.window.clone();
|
||||
|
|
@ -298,36 +265,20 @@ impl Window {
|
|||
self.set_inner_size_physical(width, height);
|
||||
}
|
||||
|
||||
pub(crate) fn set_min_inner_size_physical(&self, dimensions: Option<(u32, u32)>) {
|
||||
self.window_state.lock().min_size = dimensions.map(Into::into);
|
||||
#[inline]
|
||||
pub fn set_min_inner_size(&self, size: Option<Size>) {
|
||||
self.window_state.lock().min_size = size;
|
||||
// Make windows re-check the window size bounds.
|
||||
let (width, height) = self.inner_size_physical();
|
||||
self.set_inner_size_physical(width, height);
|
||||
let size = self.inner_size();
|
||||
self.set_inner_size(size.into());
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_min_inner_size(&self, logical_size: Option<LogicalSize>) {
|
||||
let physical_size = logical_size.map(|logical_size| {
|
||||
let dpi_factor = self.hidpi_factor();
|
||||
logical_size.to_physical(dpi_factor).into()
|
||||
});
|
||||
self.set_min_inner_size_physical(physical_size);
|
||||
}
|
||||
|
||||
pub fn set_max_inner_size_physical(&self, dimensions: Option<(u32, u32)>) {
|
||||
self.window_state.lock().max_size = dimensions.map(Into::into);
|
||||
pub fn set_max_inner_size(&self, size: Option<Size>) {
|
||||
self.window_state.lock().max_size = size;
|
||||
// Make windows re-check the window size bounds.
|
||||
let (width, height) = self.inner_size_physical();
|
||||
self.set_inner_size_physical(width, height);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_max_inner_size(&self, logical_size: Option<LogicalSize>) {
|
||||
let physical_size = logical_size.map(|logical_size| {
|
||||
let dpi_factor = self.hidpi_factor();
|
||||
logical_size.to_physical(dpi_factor).into()
|
||||
});
|
||||
self.set_max_inner_size_physical(physical_size);
|
||||
let size = self.inner_size();
|
||||
self.set_inner_size(size.into());
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -411,7 +362,11 @@ impl Window {
|
|||
self.window_state.lock().dpi_factor
|
||||
}
|
||||
|
||||
fn set_cursor_position_physical(&self, x: i32, y: i32) -> Result<(), ExternalError> {
|
||||
#[inline]
|
||||
pub fn set_cursor_position(&self, position: Position) -> Result<(), ExternalError> {
|
||||
let dpi_factor = self.hidpi_factor();
|
||||
let (x, y) = position.to_physical(dpi_factor).into();
|
||||
|
||||
let mut point = POINT { x, y };
|
||||
unsafe {
|
||||
if winuser::ClientToScreen(self.window.0, &mut point) == 0 {
|
||||
|
|
@ -424,16 +379,6 @@ impl Window {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_cursor_position(
|
||||
&self,
|
||||
logical_position: LogicalPosition,
|
||||
) -> Result<(), ExternalError> {
|
||||
let dpi_factor = self.hidpi_factor();
|
||||
let (x, y) = logical_position.to_physical(dpi_factor).into();
|
||||
self.set_cursor_position_physical(x, y)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn id(&self) -> WindowId {
|
||||
WindowId(self.window.0)
|
||||
|
|
@ -691,7 +636,7 @@ impl Window {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_ime_position(&self, _logical_spot: LogicalPosition) {
|
||||
pub fn set_ime_position(&self, _position: Position) {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
|
|
@ -770,41 +715,6 @@ unsafe fn init<T: 'static>(
|
|||
// registering the window class
|
||||
let class_name = register_window_class(&window_icon, &taskbar_icon);
|
||||
|
||||
let guessed_dpi_factor = {
|
||||
let monitors = monitor::available_monitors();
|
||||
let dpi_factor = if !monitors.is_empty() {
|
||||
let mut dpi_factor = Some(monitors[0].hidpi_factor());
|
||||
for monitor in &monitors {
|
||||
if Some(monitor.hidpi_factor()) != dpi_factor {
|
||||
dpi_factor = None;
|
||||
}
|
||||
}
|
||||
dpi_factor
|
||||
} else {
|
||||
return Err(os_error!(io::Error::new(
|
||||
io::ErrorKind::NotFound,
|
||||
"No monitors were detected."
|
||||
)));
|
||||
};
|
||||
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.hidpi_factor());
|
||||
break;
|
||||
}
|
||||
}
|
||||
dpi_factor
|
||||
})
|
||||
.unwrap_or(1.0)
|
||||
})
|
||||
};
|
||||
info!("Guessed window DPI factor: {}", guessed_dpi_factor);
|
||||
|
||||
let dimensions = attributes.inner_size.unwrap_or_else(|| (1024, 768).into());
|
||||
|
||||
let mut window_flags = WindowFlags::empty();
|
||||
window_flags.set(WindowFlags::DECORATIONS, attributes.decorations);
|
||||
window_flags.set(WindowFlags::ALWAYS_ON_TOP, attributes.always_on_top);
|
||||
|
|
@ -853,20 +763,6 @@ unsafe fn init<T: 'static>(
|
|||
|
||||
let dpi = hwnd_dpi(real_window.0);
|
||||
let dpi_factor = dpi_to_scale_factor(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;
|
||||
*ptr.offset(0) = width as WORD;
|
||||
*ptr.offset(1) = height as WORD;
|
||||
winuser::PostMessageW(
|
||||
real_window.0,
|
||||
*INITIAL_DPI_MSG_ID,
|
||||
dpi as WPARAM,
|
||||
packed_dimensions,
|
||||
);
|
||||
}
|
||||
|
||||
// making the window transparent
|
||||
if attributes.transparent && !pl_attribs.no_redirection_bitmap {
|
||||
|
|
@ -900,7 +796,6 @@ unsafe fn init<T: 'static>(
|
|||
}
|
||||
}
|
||||
|
||||
window_flags.set(WindowFlags::VISIBLE, attributes.visible);
|
||||
window_flags.set(WindowFlags::MAXIMIZED, attributes.maximized);
|
||||
|
||||
// If the system theme is dark, we need to set the window theme now
|
||||
|
|
@ -927,15 +822,17 @@ unsafe fn init<T: 'static>(
|
|||
thread_executor: event_loop.create_thread_executor(),
|
||||
};
|
||||
|
||||
let dimensions = attributes
|
||||
.inner_size
|
||||
.unwrap_or_else(|| PhysicalSize::new(1024, 768).into());
|
||||
win.set_inner_size(dimensions);
|
||||
win.set_visible(attributes.visible);
|
||||
|
||||
if let Some(_) = attributes.fullscreen {
|
||||
win.set_fullscreen(attributes.fullscreen);
|
||||
force_window_active(win.window.0);
|
||||
}
|
||||
|
||||
if let Some(dimensions) = attributes.inner_size {
|
||||
win.set_inner_size(dimensions);
|
||||
}
|
||||
|
||||
Ok(win)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue