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:
Osspial 2019-06-19 16:49:43 -04:00
parent 2da24089de
commit f379d069b9
16 changed files with 427 additions and 369 deletions

View file

@ -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)
}