mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-23 22:01:31 +11:00
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
|
@ -5,20 +5,21 @@ 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},
|
||||||
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},
|
||||||
};
|
};
|
||||||
|
|
||||||
const WINDOW_COUNT: usize = 3;
|
const WINDOW_COUNT: usize = 3;
|
||||||
const WINDOW_SIZE: (u32, u32) = (600, 400);
|
const WINDOW_SIZE: PhysicalSize = PhysicalSize::new(600, 400);
|
||||||
|
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
let event_loop = EventLoop::new();
|
let event_loop = EventLoop::new();
|
||||||
let mut window_senders = HashMap::with_capacity(WINDOW_COUNT);
|
let mut window_senders = HashMap::with_capacity(WINDOW_COUNT);
|
||||||
for _ in 0..WINDOW_COUNT {
|
for _ in 0..WINDOW_COUNT {
|
||||||
let window = WindowBuilder::new()
|
let window = WindowBuilder::new()
|
||||||
.with_inner_size(WINDOW_SIZE.into())
|
.with_inner_size(WINDOW_SIZE)
|
||||||
.build(&event_loop)
|
.build(&event_loop)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -101,7 +102,7 @@ fn main() {
|
||||||
println!("-> fullscreen : {:?}", window.fullscreen());
|
println!("-> fullscreen : {:?}", window.fullscreen());
|
||||||
}
|
}
|
||||||
L => window.set_min_inner_size(match state {
|
L => window.set_min_inner_size(match state {
|
||||||
true => Some(WINDOW_SIZE.into()),
|
true => Some(WINDOW_SIZE),
|
||||||
false => None,
|
false => None,
|
||||||
}),
|
}),
|
||||||
M => window.set_maximized(state),
|
M => window.set_maximized(state),
|
||||||
|
@ -114,17 +115,18 @@ fn main() {
|
||||||
}),
|
}),
|
||||||
Q => window.request_redraw(),
|
Q => window.request_redraw(),
|
||||||
R => window.set_resizable(state),
|
R => window.set_resizable(state),
|
||||||
S => window.set_inner_size(
|
S => window.set_inner_size(match state {
|
||||||
match state {
|
true => PhysicalSize::new(
|
||||||
true => (WINDOW_SIZE.0 + 100, WINDOW_SIZE.1 + 100),
|
WINDOW_SIZE.width + 100,
|
||||||
false => WINDOW_SIZE,
|
WINDOW_SIZE.height + 100,
|
||||||
}
|
|
||||||
.into(),
|
|
||||||
),
|
),
|
||||||
|
false => WINDOW_SIZE,
|
||||||
|
}),
|
||||||
W => window
|
W => window
|
||||||
.set_cursor_position(
|
.set_cursor_position(PhysicalPosition::new(
|
||||||
(WINDOW_SIZE.0 as i32 / 2, WINDOW_SIZE.1 as i32 / 2).into(),
|
WINDOW_SIZE.width as f64 / 2.0,
|
||||||
)
|
WINDOW_SIZE.height as f64 / 2.0,
|
||||||
|
))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
Z => {
|
Z => {
|
||||||
window.set_visible(false);
|
window.set_visible(false);
|
||||||
|
@ -161,9 +163,11 @@ fn main() {
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if let Some(tx) = window_senders.get(&window_id) {
|
if let Some(tx) = window_senders.get(&window_id) {
|
||||||
|
if let Some(event) = event.to_static() {
|
||||||
tx.send(event).unwrap();
|
tx.send(event).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use winit::{
|
use winit::{
|
||||||
|
dpi::LogicalSize,
|
||||||
event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent},
|
event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent},
|
||||||
event_loop::{ControlFlow, EventLoop},
|
event_loop::{ControlFlow, EventLoop},
|
||||||
window::WindowBuilder,
|
window::WindowBuilder,
|
||||||
|
@ -11,7 +12,7 @@ fn main() {
|
||||||
|
|
||||||
let window = WindowBuilder::new()
|
let window = WindowBuilder::new()
|
||||||
.with_title("Hit space to toggle resizability.")
|
.with_title("Hit space to toggle resizability.")
|
||||||
.with_inner_size((400, 200).into())
|
.with_inner_size(LogicalSize::new(400.0, 200.0))
|
||||||
.with_resizable(resizable)
|
.with_resizable(resizable)
|
||||||
.build(&event_loop)
|
.build(&event_loop)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
@ -9,6 +9,7 @@ fn main() {
|
||||||
|
|
||||||
let window = WindowBuilder::new()
|
let window = WindowBuilder::new()
|
||||||
.with_title("A fantastic window!")
|
.with_title("A fantastic window!")
|
||||||
|
.with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0))
|
||||||
.build(&event_loop)
|
.build(&event_loop)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
124
src/dpi.rs
124
src/dpi.rs
|
@ -100,7 +100,7 @@ pub struct LogicalPosition {
|
||||||
|
|
||||||
impl LogicalPosition {
|
impl LogicalPosition {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(x: f64, y: f64) -> Self {
|
pub const fn new(x: f64, y: f64) -> Self {
|
||||||
LogicalPosition { x, y }
|
LogicalPosition { x, y }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +161,7 @@ pub struct PhysicalPosition {
|
||||||
|
|
||||||
impl PhysicalPosition {
|
impl PhysicalPosition {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(x: f64, y: f64) -> Self {
|
pub const fn new(x: f64, y: f64) -> Self {
|
||||||
PhysicalPosition { x, y }
|
PhysicalPosition { x, y }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,7 +222,7 @@ pub struct LogicalSize {
|
||||||
|
|
||||||
impl LogicalSize {
|
impl LogicalSize {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(width: f64, height: f64) -> Self {
|
pub const fn new(width: f64, height: f64) -> Self {
|
||||||
LogicalSize { width, height }
|
LogicalSize { width, height }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,7 +236,7 @@ impl LogicalSize {
|
||||||
assert!(validate_hidpi_factor(dpi_factor));
|
assert!(validate_hidpi_factor(dpi_factor));
|
||||||
let width = self.width * dpi_factor;
|
let width = self.width * dpi_factor;
|
||||||
let height = self.height * dpi_factor;
|
let height = self.height * dpi_factor;
|
||||||
PhysicalSize::new(width, height)
|
PhysicalSize::new(width.round() as _, height.round() as _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,20 +270,16 @@ impl Into<(u32, u32)> for LogicalSize {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A size represented in physical pixels.
|
/// A size represented in physical pixels.
|
||||||
///
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
/// The size is stored as floats, so please be careful. Casting floats to integers truncates the fractional part,
|
|
||||||
/// which can cause noticable issues. To help with that, an `Into<(u32, u32)>` implementation is provided which
|
|
||||||
/// does the rounding for you.
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub struct PhysicalSize {
|
pub struct PhysicalSize {
|
||||||
pub width: f64,
|
pub width: u32,
|
||||||
pub height: f64,
|
pub height: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PhysicalSize {
|
impl PhysicalSize {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(width: f64, height: f64) -> Self {
|
pub const fn new(width: u32, height: u32) -> Self {
|
||||||
PhysicalSize { width, height }
|
PhysicalSize { width, height }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,30 +291,16 @@ impl PhysicalSize {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_logical(&self, dpi_factor: f64) -> LogicalSize {
|
pub fn to_logical(&self, dpi_factor: f64) -> LogicalSize {
|
||||||
assert!(validate_hidpi_factor(dpi_factor));
|
assert!(validate_hidpi_factor(dpi_factor));
|
||||||
let width = self.width / dpi_factor;
|
let width = self.width as f64 / dpi_factor;
|
||||||
let height = self.height / dpi_factor;
|
let height = self.height as f64 / dpi_factor;
|
||||||
LogicalSize::new(width, height)
|
LogicalSize::new(width, height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<(f64, f64)> for PhysicalSize {
|
|
||||||
#[inline]
|
|
||||||
fn from((width, height): (f64, f64)) -> Self {
|
|
||||||
Self::new(width, height)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<(u32, u32)> for PhysicalSize {
|
impl From<(u32, u32)> for PhysicalSize {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from((width, height): (u32, u32)) -> Self {
|
fn from((width, height): (u32, u32)) -> Self {
|
||||||
Self::new(width as f64, height as f64)
|
Self::new(width, height)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Into<(f64, f64)> for PhysicalSize {
|
|
||||||
#[inline]
|
|
||||||
fn into(self) -> (f64, f64) {
|
|
||||||
(self.width, self.height)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,6 +308,88 @@ impl Into<(u32, u32)> for PhysicalSize {
|
||||||
/// Note that this rounds instead of truncating.
|
/// Note that this rounds instead of truncating.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into(self) -> (u32, u32) {
|
fn into(self) -> (u32, u32) {
|
||||||
(self.width.round() as _, self.height.round() as _)
|
(self.width, self.height)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
pub enum Size {
|
||||||
|
Physical(PhysicalSize),
|
||||||
|
Logical(LogicalSize),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Size {
|
||||||
|
pub fn new<S: Into<Size>>(size: S) -> Size {
|
||||||
|
size.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_logical(&self, dpi_factor: f64) -> LogicalSize {
|
||||||
|
match *self {
|
||||||
|
Size::Physical(size) => size.to_logical(dpi_factor),
|
||||||
|
Size::Logical(size) => size,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_physical(&self, dpi_factor: f64) -> PhysicalSize {
|
||||||
|
match *self {
|
||||||
|
Size::Physical(size) => size,
|
||||||
|
Size::Logical(size) => size.to_physical(dpi_factor),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<PhysicalSize> for Size {
|
||||||
|
#[inline]
|
||||||
|
fn from(size: PhysicalSize) -> Size {
|
||||||
|
Size::Physical(size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<LogicalSize> for Size {
|
||||||
|
#[inline]
|
||||||
|
fn from(size: LogicalSize) -> Size {
|
||||||
|
Size::Logical(size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
pub enum Position {
|
||||||
|
Physical(PhysicalPosition),
|
||||||
|
Logical(LogicalPosition),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Position {
|
||||||
|
pub fn new<S: Into<Position>>(position: S) -> Position {
|
||||||
|
position.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_logical(&self, dpi_factor: f64) -> LogicalPosition {
|
||||||
|
match *self {
|
||||||
|
Position::Physical(position) => position.to_logical(dpi_factor),
|
||||||
|
Position::Logical(position) => position,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_physical(&self, dpi_factor: f64) -> PhysicalPosition {
|
||||||
|
match *self {
|
||||||
|
Position::Physical(position) => position,
|
||||||
|
Position::Logical(position) => position.to_physical(dpi_factor),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<PhysicalPosition> for Position {
|
||||||
|
#[inline]
|
||||||
|
fn from(position: PhysicalPosition) -> Position {
|
||||||
|
Position::Physical(position)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<LogicalPosition> for Position {
|
||||||
|
#[inline]
|
||||||
|
fn from(position: LogicalPosition) -> Position {
|
||||||
|
Position::Logical(position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
128
src/event.rs
128
src/event.rs
|
@ -37,7 +37,7 @@ use instant::Instant;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
dpi::{LogicalPosition, LogicalSize},
|
dpi::{LogicalPosition, PhysicalPosition, PhysicalSize},
|
||||||
platform_impl,
|
platform_impl,
|
||||||
window::{Theme, WindowId},
|
window::{Theme, WindowId},
|
||||||
};
|
};
|
||||||
|
@ -45,8 +45,8 @@ use crate::{
|
||||||
/// Describes a generic event.
|
/// Describes a generic event.
|
||||||
///
|
///
|
||||||
/// See the module-level docs for more information on the event loop manages each event.
|
/// See the module-level docs for more information on the event loop manages each event.
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum Event<T> {
|
pub enum Event<'a, T: 'static> {
|
||||||
/// Emitted when new events arrive from the OS to be processed.
|
/// Emitted when new events arrive from the OS to be processed.
|
||||||
///
|
///
|
||||||
/// This event type is useful as a place to put code that should be done before you start
|
/// This event type is useful as a place to put code that should be done before you start
|
||||||
|
@ -58,7 +58,7 @@ pub enum Event<T> {
|
||||||
/// Emitted when the OS sends an event to a winit window.
|
/// Emitted when the OS sends an event to a winit window.
|
||||||
WindowEvent {
|
WindowEvent {
|
||||||
window_id: WindowId,
|
window_id: WindowId,
|
||||||
event: WindowEvent,
|
event: WindowEvent<'a>,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Emitted when the OS sends an event to a device.
|
/// Emitted when the OS sends an event to a device.
|
||||||
|
@ -114,8 +114,8 @@ pub enum Event<T> {
|
||||||
LoopDestroyed,
|
LoopDestroyed,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Event<T> {
|
impl<'a, T> Event<'a, T> {
|
||||||
pub fn map_nonuser_event<U>(self) -> Result<Event<U>, Event<T>> {
|
pub fn map_nonuser_event<U>(self) -> Result<Event<'a, U>, Event<'a, T>> {
|
||||||
use self::Event::*;
|
use self::Event::*;
|
||||||
match self {
|
match self {
|
||||||
UserEvent(_) => Err(self),
|
UserEvent(_) => Err(self),
|
||||||
|
@ -130,6 +130,26 @@ impl<T> Event<T> {
|
||||||
Resumed => Ok(Resumed),
|
Resumed => Ok(Resumed),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If the event doesn't contain a reference, turn it into an event with a `'static` lifetime.
|
||||||
|
/// Otherwise, return `None`.
|
||||||
|
pub fn to_static(self) -> Option<Event<'static, T>> {
|
||||||
|
use self::Event::*;
|
||||||
|
match self {
|
||||||
|
WindowEvent { window_id, event } => event
|
||||||
|
.to_static()
|
||||||
|
.map(|event| WindowEvent { window_id, event }),
|
||||||
|
UserEvent(_) => None,
|
||||||
|
DeviceEvent { device_id, event } => Some(DeviceEvent { device_id, event }),
|
||||||
|
NewEvents(cause) => Some(NewEvents(cause)),
|
||||||
|
MainEventsCleared => Some(MainEventsCleared),
|
||||||
|
RedrawRequested(wid) => Some(RedrawRequested(wid)),
|
||||||
|
RedrawEventsCleared => Some(RedrawEventsCleared),
|
||||||
|
LoopDestroyed => Some(LoopDestroyed),
|
||||||
|
Suspended => Some(Suspended),
|
||||||
|
Resumed => Some(Resumed),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Describes the reason the event loop is resuming.
|
/// Describes the reason the event loop is resuming.
|
||||||
|
@ -159,13 +179,13 @@ pub enum StartCause {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Describes an event from a `Window`.
|
/// Describes an event from a `Window`.
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum WindowEvent {
|
pub enum WindowEvent<'a> {
|
||||||
/// The size of the window has changed. Contains the client area's new dimensions.
|
/// The size of the window has changed. Contains the client area's new dimensions.
|
||||||
Resized(LogicalSize),
|
Resized(PhysicalSize),
|
||||||
|
|
||||||
/// The position of the window has changed. Contains the window's new position.
|
/// The position of the window has changed. Contains the window's new position.
|
||||||
Moved(LogicalPosition),
|
Moved(PhysicalPosition),
|
||||||
|
|
||||||
/// The window has been requested to close.
|
/// The window has been requested to close.
|
||||||
CloseRequested,
|
CloseRequested,
|
||||||
|
@ -222,7 +242,7 @@ pub enum WindowEvent {
|
||||||
/// (x,y) coords in pixels relative to the top-left corner of the window. Because the range of this data is
|
/// (x,y) coords in pixels relative to the top-left corner of the window. Because the range of this data is
|
||||||
/// limited by the display area and it may have been transformed by the OS to implement effects such as cursor
|
/// limited by the display area and it may have been transformed by the OS to implement effects such as cursor
|
||||||
/// acceleration, it should not be used to implement non-cursor-like interactions such as 3D camera control.
|
/// acceleration, it should not be used to implement non-cursor-like interactions such as 3D camera control.
|
||||||
position: LogicalPosition,
|
position: PhysicalPosition,
|
||||||
#[deprecated = "Deprecated in favor of DeviceEvent::ModifiersChanged"]
|
#[deprecated = "Deprecated in favor of DeviceEvent::ModifiersChanged"]
|
||||||
modifiers: ModifiersState,
|
modifiers: ModifiersState,
|
||||||
},
|
},
|
||||||
|
@ -280,8 +300,16 @@ pub enum WindowEvent {
|
||||||
/// * Changing the display's DPI factor (e.g. in Control Panel on Windows).
|
/// * Changing the display's DPI factor (e.g. in Control Panel on Windows).
|
||||||
/// * Moving the window to a display with a different DPI factor.
|
/// * Moving the window to a display with a different DPI factor.
|
||||||
///
|
///
|
||||||
/// For more information about DPI in general, see the [`dpi`](crate::dpi) module.
|
/// After this event callback has been processed, the window will be resized to whatever value
|
||||||
HiDpiFactorChanged(f64),
|
/// is pointed to by the `new_inner_size` reference. By default, this will contain the size suggested
|
||||||
|
/// by the OS, but it can be changed to any value. If `new_inner_size` is set to `None`, no resizing
|
||||||
|
/// will occur.
|
||||||
|
///
|
||||||
|
/// For more information about DPI in general, see the [`dpi`](dpi/index.html) module.
|
||||||
|
HiDpiFactorChanged {
|
||||||
|
hidpi_factor: f64,
|
||||||
|
new_inner_size: &'a mut Option<PhysicalSize>,
|
||||||
|
},
|
||||||
|
|
||||||
/// The system window theme has changed.
|
/// The system window theme has changed.
|
||||||
///
|
///
|
||||||
|
@ -292,6 +320,78 @@ pub enum WindowEvent {
|
||||||
ThemeChanged(Theme),
|
ThemeChanged(Theme),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> WindowEvent<'a> {
|
||||||
|
pub fn to_static(self) -> Option<WindowEvent<'static>> {
|
||||||
|
use self::WindowEvent::*;
|
||||||
|
match self {
|
||||||
|
Resized(size) => Some(Resized(size)),
|
||||||
|
Moved(position) => Some(Moved(position)),
|
||||||
|
CloseRequested => Some(CloseRequested),
|
||||||
|
Destroyed => Some(Destroyed),
|
||||||
|
DroppedFile(file) => Some(DroppedFile(file)),
|
||||||
|
HoveredFile(file) => Some(HoveredFile(file)),
|
||||||
|
HoveredFileCancelled => Some(HoveredFileCancelled),
|
||||||
|
ReceivedCharacter(c) => Some(ReceivedCharacter(c)),
|
||||||
|
Focused(focused) => Some(Focused(focused)),
|
||||||
|
KeyboardInput { device_id, input, is_synthetic } => Some(KeyboardInput { device_id, input, is_synthetic }),
|
||||||
|
CursorMoved {
|
||||||
|
device_id,
|
||||||
|
position,
|
||||||
|
modifiers,
|
||||||
|
} => Some(CursorMoved {
|
||||||
|
device_id,
|
||||||
|
position,
|
||||||
|
modifiers,
|
||||||
|
}),
|
||||||
|
CursorEntered { device_id } => Some(CursorEntered { device_id }),
|
||||||
|
CursorLeft { device_id } => Some(CursorLeft { device_id }),
|
||||||
|
MouseWheel {
|
||||||
|
device_id,
|
||||||
|
delta,
|
||||||
|
phase,
|
||||||
|
modifiers,
|
||||||
|
} => Some(MouseWheel {
|
||||||
|
device_id,
|
||||||
|
delta,
|
||||||
|
phase,
|
||||||
|
modifiers,
|
||||||
|
}),
|
||||||
|
MouseInput {
|
||||||
|
device_id,
|
||||||
|
state,
|
||||||
|
button,
|
||||||
|
modifiers,
|
||||||
|
} => Some(MouseInput {
|
||||||
|
device_id,
|
||||||
|
state,
|
||||||
|
button,
|
||||||
|
modifiers,
|
||||||
|
}),
|
||||||
|
TouchpadPressure {
|
||||||
|
device_id,
|
||||||
|
pressure,
|
||||||
|
stage,
|
||||||
|
} => Some(TouchpadPressure {
|
||||||
|
device_id,
|
||||||
|
pressure,
|
||||||
|
stage,
|
||||||
|
}),
|
||||||
|
AxisMotion {
|
||||||
|
device_id,
|
||||||
|
axis,
|
||||||
|
value,
|
||||||
|
} => Some(AxisMotion {
|
||||||
|
device_id,
|
||||||
|
axis,
|
||||||
|
value,
|
||||||
|
}),
|
||||||
|
Touch(touch) => Some(Touch(touch)),
|
||||||
|
ThemeChanged(theme) => Some(ThemeChanged(theme)),
|
||||||
|
HiDpiFactorChanged { .. } => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Identifier of an input device.
|
/// Identifier of an input device.
|
||||||
///
|
///
|
||||||
/// Whenever you receive an event arising from a particular input device, this event contains a `DeviceId` which
|
/// Whenever you receive an event arising from a particular input device, this event contains a `DeviceId` which
|
||||||
|
@ -426,7 +526,7 @@ pub enum TouchPhase {
|
||||||
pub struct Touch {
|
pub struct Touch {
|
||||||
pub device_id: DeviceId,
|
pub device_id: DeviceId,
|
||||||
pub phase: TouchPhase,
|
pub phase: TouchPhase,
|
||||||
pub location: LogicalPosition,
|
pub location: PhysicalPosition,
|
||||||
/// Describes how hard the screen was pressed. May be `None` if the platform
|
/// Describes how hard the screen was pressed. May be `None` if the platform
|
||||||
/// does not support pressure sensitivity.
|
/// does not support pressure sensitivity.
|
||||||
///
|
///
|
||||||
|
|
|
@ -143,7 +143,7 @@ impl<T> EventLoop<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn run<F>(self, event_handler: F) -> !
|
pub fn run<F>(self, event_handler: F) -> !
|
||||||
where
|
where
|
||||||
F: 'static + FnMut(Event<T>, &EventLoopWindowTarget<T>, &mut ControlFlow),
|
F: 'static + FnMut(Event<'_, T>, &EventLoopWindowTarget<T>, &mut ControlFlow),
|
||||||
{
|
{
|
||||||
self.event_loop.run(event_handler)
|
self.event_loop.run(event_handler)
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,11 @@ pub trait EventLoopExtDesktop {
|
||||||
/// You are strongly encouraged to use `run`, unless the use of this is absolutely necessary.
|
/// You are strongly encouraged to use `run`, unless the use of this is absolutely necessary.
|
||||||
fn run_return<F>(&mut self, event_handler: F)
|
fn run_return<F>(&mut self, event_handler: F)
|
||||||
where
|
where
|
||||||
F: FnMut(Event<Self::UserEvent>, &EventLoopWindowTarget<Self::UserEvent>, &mut ControlFlow);
|
F: FnMut(
|
||||||
|
Event<'_, Self::UserEvent>,
|
||||||
|
&EventLoopWindowTarget<Self::UserEvent>,
|
||||||
|
&mut ControlFlow,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> EventLoopExtDesktop for EventLoop<T> {
|
impl<T> EventLoopExtDesktop for EventLoop<T> {
|
||||||
|
@ -38,7 +42,11 @@ impl<T> EventLoopExtDesktop for EventLoop<T> {
|
||||||
|
|
||||||
fn run_return<F>(&mut self, event_handler: F)
|
fn run_return<F>(&mut self, event_handler: F)
|
||||||
where
|
where
|
||||||
F: FnMut(Event<T>, &EventLoopWindowTarget<T>, &mut ControlFlow),
|
F: FnMut(
|
||||||
|
Event<'_, Self::UserEvent>,
|
||||||
|
&EventLoopWindowTarget<Self::UserEvent>,
|
||||||
|
&mut ControlFlow,
|
||||||
|
),
|
||||||
{
|
{
|
||||||
self.event_loop.run_return(event_handler)
|
self.event_loop.run_return(event_handler)
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,7 +141,3 @@ pub unsafe fn hwnd_dpi(hwnd: HWND) -> u32 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hwnd_scale_factor(hwnd: HWND) -> f64 {
|
|
||||||
dpi_to_scale_factor(unsafe { hwnd_dpi(hwnd) })
|
|
||||||
}
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ pub struct FileDropHandlerData {
|
||||||
pub interface: IDropTarget,
|
pub interface: IDropTarget,
|
||||||
refcount: AtomicUsize,
|
refcount: AtomicUsize,
|
||||||
window: HWND,
|
window: HWND,
|
||||||
send_event: Box<dyn Fn(Event<()>)>,
|
send_event: Box<dyn Fn(Event<'static, ()>)>,
|
||||||
cursor_effect: DWORD,
|
cursor_effect: DWORD,
|
||||||
hovered_is_valid: bool, /* If the currently hovered item is not valid there must not be any `HoveredFileCancelled` emitted */
|
hovered_is_valid: bool, /* If the currently hovered item is not valid there must not be any `HoveredFileCancelled` emitted */
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ pub struct FileDropHandler {
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
impl FileDropHandler {
|
impl FileDropHandler {
|
||||||
pub fn new(window: HWND, send_event: Box<dyn Fn(Event<()>)>) -> FileDropHandler {
|
pub fn new(window: HWND, send_event: Box<dyn Fn(Event<'static, ()>)>) -> FileDropHandler {
|
||||||
let data = Box::new(FileDropHandlerData {
|
let data = Box::new(FileDropHandlerData {
|
||||||
interface: IDropTarget {
|
interface: IDropTarget {
|
||||||
lpVtbl: &DROP_TARGET_VTBL as *const IDropTargetVtbl,
|
lpVtbl: &DROP_TARGET_VTBL as *const IDropTargetVtbl,
|
||||||
|
@ -227,7 +227,7 @@ impl FileDropHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FileDropHandlerData {
|
impl FileDropHandlerData {
|
||||||
fn send_event(&self, event: Event<()>) {
|
fn send_event(&self, event: Event<'static, ()>) {
|
||||||
(self.send_event)(event);
|
(self.send_event)(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@ use std::{
|
||||||
use winapi::shared::basetsd::{DWORD_PTR, UINT_PTR};
|
use winapi::shared::basetsd::{DWORD_PTR, UINT_PTR};
|
||||||
|
|
||||||
use winapi::{
|
use winapi::{
|
||||||
ctypes::c_int,
|
|
||||||
shared::{
|
shared::{
|
||||||
minwindef::{BOOL, DWORD, HIWORD, INT, LOWORD, LPARAM, LRESULT, UINT, WPARAM},
|
minwindef::{BOOL, DWORD, HIWORD, INT, LOWORD, LPARAM, LRESULT, UINT, WPARAM},
|
||||||
windef::{HWND, POINT, RECT},
|
windef::{HWND, POINT, RECT},
|
||||||
|
@ -37,20 +36,20 @@ use winapi::{
|
||||||
},
|
},
|
||||||
um::{
|
um::{
|
||||||
commctrl, libloaderapi, ole2, processthreadsapi, winbase,
|
commctrl, libloaderapi, ole2, processthreadsapi, winbase,
|
||||||
winnt::{HANDLE, LONG, LPCSTR, SHORT},
|
winnt::{HANDLE, LPCSTR, SHORT},
|
||||||
winuser,
|
winuser,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use self::runner::{ELRShared, EventLoopRunnerShared};
|
use self::runner::{ELRShared, EventLoopRunnerShared};
|
||||||
use crate::{
|
use crate::{
|
||||||
dpi::{LogicalPosition, LogicalSize, PhysicalSize},
|
dpi::{PhysicalPosition, PhysicalSize},
|
||||||
event::{DeviceEvent, Event, Force, KeyboardInput, Touch, TouchPhase, WindowEvent},
|
event::{DeviceEvent, Event, Force, KeyboardInput, Touch, TouchPhase, WindowEvent},
|
||||||
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, hwnd_scale_factor,
|
become_dpi_aware, dpi_to_scale_factor, enable_non_client_dpi_scaling,
|
||||||
},
|
},
|
||||||
drop_handler::FileDropHandler,
|
drop_handler::FileDropHandler,
|
||||||
event::{
|
event::{
|
||||||
|
@ -97,26 +96,30 @@ lazy_static! {
|
||||||
get_function!("user32.dll", GetPointerPenInfo);
|
get_function!("user32.dll", GetPointerPenInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct SubclassInput<T> {
|
pub(crate) struct SubclassInput<T: 'static> {
|
||||||
pub window_state: Arc<Mutex<WindowState>>,
|
pub window_state: Arc<Mutex<WindowState>>,
|
||||||
pub event_loop_runner: EventLoopRunnerShared<T>,
|
pub event_loop_runner: EventLoopRunnerShared<T>,
|
||||||
pub file_drop_handler: FileDropHandler,
|
pub file_drop_handler: FileDropHandler,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> SubclassInput<T> {
|
impl<T> SubclassInput<T> {
|
||||||
unsafe fn send_event(&self, event: Event<T>) {
|
unsafe fn send_event(&self, event: Event<'static, T>) {
|
||||||
self.event_loop_runner.send_event(event);
|
self.event_loop_runner.send_event(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe fn send_event_unbuffered<'e>(&self, event: Event<'e, T>) -> Result<(), Event<'e, T>> {
|
||||||
|
self.event_loop_runner.send_event_unbuffered(event)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ThreadMsgTargetSubclassInput<T> {
|
struct ThreadMsgTargetSubclassInput<T: 'static> {
|
||||||
event_loop_runner: EventLoopRunnerShared<T>,
|
event_loop_runner: EventLoopRunnerShared<T>,
|
||||||
user_event_receiver: Receiver<T>,
|
user_event_receiver: Receiver<T>,
|
||||||
modifiers_state: ModifiersStateSide,
|
modifiers_state: ModifiersStateSide,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> ThreadMsgTargetSubclassInput<T> {
|
impl<T> ThreadMsgTargetSubclassInput<T> {
|
||||||
unsafe fn send_event(&self, event: Event<T>) {
|
unsafe fn send_event(&self, event: Event<'static, T>) {
|
||||||
self.event_loop_runner.send_event(event);
|
self.event_loop_runner.send_event(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,7 +129,7 @@ pub struct EventLoop<T: 'static> {
|
||||||
window_target: RootELW<T>,
|
window_target: RootELW<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EventLoopWindowTarget<T> {
|
pub struct EventLoopWindowTarget<T: 'static> {
|
||||||
thread_id: DWORD,
|
thread_id: DWORD,
|
||||||
thread_msg_target: HWND,
|
thread_msg_target: HWND,
|
||||||
pub(crate) runner_shared: EventLoopRunnerShared<T>,
|
pub(crate) runner_shared: EventLoopRunnerShared<T>,
|
||||||
|
@ -191,7 +194,7 @@ impl<T: 'static> EventLoop<T> {
|
||||||
|
|
||||||
pub fn run<F>(mut self, event_handler: F) -> !
|
pub fn run<F>(mut self, event_handler: F) -> !
|
||||||
where
|
where
|
||||||
F: 'static + FnMut(Event<T>, &RootELW<T>, &mut ControlFlow),
|
F: 'static + FnMut(Event<'_, T>, &RootELW<T>, &mut ControlFlow),
|
||||||
{
|
{
|
||||||
self.run_return(event_handler);
|
self.run_return(event_handler);
|
||||||
::std::process::exit(0);
|
::std::process::exit(0);
|
||||||
|
@ -199,7 +202,7 @@ impl<T: 'static> EventLoop<T> {
|
||||||
|
|
||||||
pub fn run_return<F>(&mut self, mut event_handler: F)
|
pub fn run_return<F>(&mut self, mut event_handler: F)
|
||||||
where
|
where
|
||||||
F: FnMut(Event<T>, &RootELW<T>, &mut ControlFlow),
|
F: FnMut(Event<'_, T>, &RootELW<T>, &mut ControlFlow),
|
||||||
{
|
{
|
||||||
let event_loop_windows_ref = &self.window_target;
|
let event_loop_windows_ref = &self.window_target;
|
||||||
|
|
||||||
|
@ -465,13 +468,6 @@ lazy_static! {
|
||||||
winuser::RegisterWindowMessageA("Winit::DestroyMsg\0".as_ptr() as LPCSTR)
|
winuser::RegisterWindowMessageA("Winit::DestroyMsg\0".as_ptr() as LPCSTR)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// Message sent by a `Window` after creation if it has a DPI != 96.
|
|
||||||
// WPARAM is the the DPI (u32). LOWORD of LPARAM is width, and HIWORD is height.
|
|
||||||
pub static ref INITIAL_DPI_MSG_ID: u32 = {
|
|
||||||
unsafe {
|
|
||||||
winuser::RegisterWindowMessageA("Winit::InitialDpiMsg\0".as_ptr() as LPCSTR)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// WPARAM is a bool specifying the `WindowFlags::MARKER_RETAIN_STATE_ON_SIZE` flag. See the
|
// WPARAM is a bool specifying the `WindowFlags::MARKER_RETAIN_STATE_ON_SIZE` flag. See the
|
||||||
// documentation in the `window_state` module for more information.
|
// documentation in the `window_state` module for more information.
|
||||||
pub static ref SET_RETAIN_STATE_ON_SIZE_MSG_ID: u32 = unsafe {
|
pub static ref SET_RETAIN_STATE_ON_SIZE_MSG_ID: u32 = unsafe {
|
||||||
|
@ -597,7 +593,7 @@ fn normalize_pointer_pressure(pressure: u32) -> Option<Force> {
|
||||||
//
|
//
|
||||||
// Returning 0 tells the Win32 API that the message has been processed.
|
// Returning 0 tells the Win32 API that the message has been processed.
|
||||||
// FIXME: detect WM_DWMCOMPOSITIONCHANGED and call DwmEnableBlurBehindWindow if necessary
|
// FIXME: detect WM_DWMCOMPOSITIONCHANGED and call DwmEnableBlurBehindWindow if necessary
|
||||||
unsafe extern "system" fn public_window_callback<T>(
|
unsafe extern "system" fn public_window_callback<T: 'static>(
|
||||||
window: HWND,
|
window: HWND,
|
||||||
msg: UINT,
|
msg: UINT,
|
||||||
wparam: WPARAM,
|
wparam: WPARAM,
|
||||||
|
@ -713,12 +709,11 @@ unsafe extern "system" fn public_window_callback<T>(
|
||||||
|
|
||||||
let windowpos = lparam as *const winuser::WINDOWPOS;
|
let windowpos = lparam as *const winuser::WINDOWPOS;
|
||||||
if (*windowpos).flags & winuser::SWP_NOMOVE != winuser::SWP_NOMOVE {
|
if (*windowpos).flags & winuser::SWP_NOMOVE != winuser::SWP_NOMOVE {
|
||||||
let dpi_factor = hwnd_scale_factor(window);
|
let physical_position =
|
||||||
let logical_position =
|
PhysicalPosition::new((*windowpos).x as f64, (*windowpos).y as f64);
|
||||||
LogicalPosition::from_physical(((*windowpos).x, (*windowpos).y), dpi_factor);
|
|
||||||
subclass_input.send_event(Event::WindowEvent {
|
subclass_input.send_event(Event::WindowEvent {
|
||||||
window_id: RootWindowId(WindowId(window)),
|
window_id: RootWindowId(WindowId(window)),
|
||||||
event: Moved(logical_position),
|
event: Moved(physical_position),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -731,11 +726,10 @@ unsafe extern "system" fn public_window_callback<T>(
|
||||||
let w = LOWORD(lparam as DWORD) as u32;
|
let w = LOWORD(lparam as DWORD) as u32;
|
||||||
let h = HIWORD(lparam as DWORD) as u32;
|
let h = HIWORD(lparam as DWORD) as u32;
|
||||||
|
|
||||||
let dpi_factor = hwnd_scale_factor(window);
|
let physical_size = PhysicalSize::new(w, h);
|
||||||
let logical_size = LogicalSize::from_physical((w, h), dpi_factor);
|
|
||||||
let event = Event::WindowEvent {
|
let event = Event::WindowEvent {
|
||||||
window_id: RootWindowId(WindowId(window)),
|
window_id: RootWindowId(WindowId(window)),
|
||||||
event: Resized(logical_size),
|
event: Resized(physical_size),
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -840,8 +834,7 @@ unsafe extern "system" fn public_window_callback<T>(
|
||||||
|
|
||||||
let x = windowsx::GET_X_LPARAM(lparam) as f64;
|
let x = windowsx::GET_X_LPARAM(lparam) as f64;
|
||||||
let y = windowsx::GET_Y_LPARAM(lparam) as f64;
|
let y = windowsx::GET_Y_LPARAM(lparam) as f64;
|
||||||
let dpi_factor = hwnd_scale_factor(window);
|
let position = PhysicalPosition::new(x, y);
|
||||||
let position = LogicalPosition::from_physical((x, y), dpi_factor);
|
|
||||||
|
|
||||||
subclass_input.send_event(Event::WindowEvent {
|
subclass_input.send_event(Event::WindowEvent {
|
||||||
window_id: RootWindowId(WindowId(window)),
|
window_id: RootWindowId(WindowId(window)),
|
||||||
|
@ -1130,7 +1123,6 @@ unsafe extern "system" fn public_window_callback<T>(
|
||||||
mem::size_of::<winuser::TOUCHINPUT>() as INT,
|
mem::size_of::<winuser::TOUCHINPUT>() as INT,
|
||||||
) > 0
|
) > 0
|
||||||
{
|
{
|
||||||
let dpi_factor = hwnd_scale_factor(window);
|
|
||||||
for input in &inputs {
|
for input in &inputs {
|
||||||
let mut location = POINT {
|
let mut location = POINT {
|
||||||
x: input.x / 100,
|
x: input.x / 100,
|
||||||
|
@ -1143,7 +1135,7 @@ unsafe extern "system" fn public_window_callback<T>(
|
||||||
|
|
||||||
let x = location.x as f64 + (input.x % 100) as f64 / 100f64;
|
let x = location.x as f64 + (input.x % 100) as f64 / 100f64;
|
||||||
let y = location.y as f64 + (input.y % 100) as f64 / 100f64;
|
let y = location.y as f64 + (input.y % 100) as f64 / 100f64;
|
||||||
let location = LogicalPosition::from_physical((x, y), dpi_factor);
|
let location = PhysicalPosition::new(x, y);
|
||||||
subclass_input.send_event(Event::WindowEvent {
|
subclass_input.send_event(Event::WindowEvent {
|
||||||
window_id: RootWindowId(WindowId(window)),
|
window_id: RootWindowId(WindowId(window)),
|
||||||
event: WindowEvent::Touch(Touch {
|
event: WindowEvent::Touch(Touch {
|
||||||
|
@ -1204,7 +1196,6 @@ unsafe extern "system" fn public_window_callback<T>(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
let dpi_factor = hwnd_scale_factor(window);
|
|
||||||
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getpointerframeinfohistory
|
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getpointerframeinfohistory
|
||||||
// The information retrieved appears in reverse chronological order, with the most recent entry in the first
|
// The information retrieved appears in reverse chronological order, with the most recent entry in the first
|
||||||
// row of the returned array
|
// row of the returned array
|
||||||
|
@ -1282,7 +1273,7 @@ unsafe extern "system" fn public_window_callback<T>(
|
||||||
|
|
||||||
let x = location.x as f64 + x.fract();
|
let x = location.x as f64 + x.fract();
|
||||||
let y = location.y as f64 + y.fract();
|
let y = location.y as f64 + y.fract();
|
||||||
let location = LogicalPosition::from_physical((x, y), dpi_factor);
|
let location = PhysicalPosition::new(x, y);
|
||||||
subclass_input.send_event(Event::WindowEvent {
|
subclass_input.send_event(Event::WindowEvent {
|
||||||
window_id: RootWindowId(WindowId(window)),
|
window_id: RootWindowId(WindowId(window)),
|
||||||
event: WindowEvent::Touch(Touch {
|
event: WindowEvent::Touch(Touch {
|
||||||
|
@ -1446,27 +1437,66 @@ unsafe extern "system" fn public_window_callback<T>(
|
||||||
new_dpi_factor != old_dpi_factor && window_state.fullscreen.is_none()
|
new_dpi_factor != old_dpi_factor && window_state.fullscreen.is_none()
|
||||||
};
|
};
|
||||||
|
|
||||||
// This prevents us from re-applying DPI adjustment to the restored size after exiting
|
let style = winuser::GetWindowLongW(window, winuser::GWL_STYLE) as _;
|
||||||
// fullscreen (the restored size is already DPI adjusted).
|
let style_ex = winuser::GetWindowLongW(window, winuser::GWL_EXSTYLE) as _;
|
||||||
if allow_resize {
|
let b_menu = !winuser::GetMenu(window).is_null() as BOOL;
|
||||||
// Resize window to the size suggested by Windows.
|
|
||||||
let rect = &*(lparam as *const RECT);
|
// New size as suggested by Windows.
|
||||||
|
let rect = *(lparam as *const RECT);
|
||||||
|
|
||||||
|
// The window rect provided is the window's outer size, not it's inner size. However,
|
||||||
|
// win32 doesn't provide an `UnadjustWindowRectEx` function to get the client rect from
|
||||||
|
// the outer rect, so we instead adjust the window rect to get the decoration margins
|
||||||
|
// and remove them from the outer size.
|
||||||
|
let margins_horizontal: u32;
|
||||||
|
let margins_vertical: u32;
|
||||||
|
{
|
||||||
|
let mut adjusted_rect = rect;
|
||||||
|
winuser::AdjustWindowRectExForDpi(
|
||||||
|
&mut adjusted_rect,
|
||||||
|
style,
|
||||||
|
b_menu,
|
||||||
|
style_ex,
|
||||||
|
new_dpi_x,
|
||||||
|
);
|
||||||
|
let margin_left = rect.left - adjusted_rect.left;
|
||||||
|
let margin_right = adjusted_rect.right - rect.right;
|
||||||
|
let margin_top = rect.top - adjusted_rect.top;
|
||||||
|
let margin_bottom = adjusted_rect.bottom - rect.bottom;
|
||||||
|
|
||||||
|
margins_horizontal = (margin_left + margin_right) as u32;
|
||||||
|
margins_vertical = (margin_bottom + margin_top) as u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
let physical_inner_rect = PhysicalSize::new(
|
||||||
|
(rect.right - rect.left) as u32 - margins_horizontal,
|
||||||
|
(rect.bottom - rect.top) as u32 - margins_vertical,
|
||||||
|
);
|
||||||
|
|
||||||
|
// `allow_resize` prevents us from re-applying DPI adjustment to the restored size after
|
||||||
|
// exiting fullscreen (the restored size is already DPI adjusted).
|
||||||
|
let mut new_inner_rect_opt = Some(physical_inner_rect).filter(|_| allow_resize);
|
||||||
|
|
||||||
|
let _ = subclass_input.send_event_unbuffered(Event::WindowEvent {
|
||||||
|
window_id: RootWindowId(WindowId(window)),
|
||||||
|
event: HiDpiFactorChanged {
|
||||||
|
hidpi_factor: new_dpi_factor,
|
||||||
|
new_inner_size: &mut new_inner_rect_opt,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Some(new_inner_rect) = new_inner_rect_opt {
|
||||||
winuser::SetWindowPos(
|
winuser::SetWindowPos(
|
||||||
window,
|
window,
|
||||||
ptr::null_mut(),
|
ptr::null_mut(),
|
||||||
rect.left,
|
rect.left,
|
||||||
rect.top,
|
rect.top,
|
||||||
rect.right - rect.left,
|
(new_inner_rect.width + margins_horizontal) as _,
|
||||||
rect.bottom - rect.top,
|
(new_inner_rect.height + margins_vertical) as _,
|
||||||
winuser::SWP_NOZORDER | winuser::SWP_NOACTIVATE,
|
winuser::SWP_NOZORDER | winuser::SWP_NOACTIVATE,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
subclass_input.send_event(Event::WindowEvent {
|
|
||||||
window_id: RootWindowId(WindowId(window)),
|
|
||||||
event: HiDpiFactorChanged(new_dpi_factor),
|
|
||||||
});
|
|
||||||
|
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1502,44 +1532,6 @@ unsafe extern "system" fn public_window_callback<T>(
|
||||||
f.set(WindowFlags::MARKER_RETAIN_STATE_ON_SIZE, wparam != 0)
|
f.set(WindowFlags::MARKER_RETAIN_STATE_ON_SIZE, wparam != 0)
|
||||||
});
|
});
|
||||||
0
|
0
|
||||||
} else if msg == *INITIAL_DPI_MSG_ID {
|
|
||||||
use crate::event::WindowEvent::HiDpiFactorChanged;
|
|
||||||
let scale_factor = dpi_to_scale_factor(wparam as u32);
|
|
||||||
subclass_input.send_event(Event::WindowEvent {
|
|
||||||
window_id: RootWindowId(WindowId(window)),
|
|
||||||
event: HiDpiFactorChanged(scale_factor),
|
|
||||||
});
|
|
||||||
// Automatically resize for actual DPI
|
|
||||||
let width = LOWORD(lparam as DWORD) as u32;
|
|
||||||
let height = HIWORD(lparam as DWORD) as u32;
|
|
||||||
let (adjusted_width, adjusted_height): (u32, u32) =
|
|
||||||
PhysicalSize::from_logical((width, height), scale_factor).into();
|
|
||||||
// We're not done yet! `SetWindowPos` needs the window size, not the client area size.
|
|
||||||
let mut rect = RECT {
|
|
||||||
top: 0,
|
|
||||||
left: 0,
|
|
||||||
bottom: adjusted_height as LONG,
|
|
||||||
right: adjusted_width as LONG,
|
|
||||||
};
|
|
||||||
let dw_style = winuser::GetWindowLongA(window, winuser::GWL_STYLE) as DWORD;
|
|
||||||
let b_menu = !winuser::GetMenu(window).is_null() as BOOL;
|
|
||||||
let dw_style_ex = winuser::GetWindowLongA(window, winuser::GWL_EXSTYLE) as DWORD;
|
|
||||||
winuser::AdjustWindowRectEx(&mut rect, dw_style, b_menu, dw_style_ex);
|
|
||||||
let outer_x = (rect.right - rect.left).abs() as c_int;
|
|
||||||
let outer_y = (rect.top - rect.bottom).abs() as c_int;
|
|
||||||
winuser::SetWindowPos(
|
|
||||||
window,
|
|
||||||
ptr::null_mut(),
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
outer_x,
|
|
||||||
outer_y,
|
|
||||||
winuser::SWP_NOMOVE
|
|
||||||
| winuser::SWP_NOREPOSITION
|
|
||||||
| winuser::SWP_NOZORDER
|
|
||||||
| winuser::SWP_NOACTIVATE,
|
|
||||||
);
|
|
||||||
0
|
|
||||||
} else {
|
} else {
|
||||||
commctrl::DefSubclassProc(window, msg, wparam, lparam)
|
commctrl::DefSubclassProc(window, msg, wparam, lparam)
|
||||||
}
|
}
|
||||||
|
@ -1547,7 +1539,7 @@ unsafe extern "system" fn public_window_callback<T>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "system" fn thread_event_target_callback<T>(
|
unsafe extern "system" fn thread_event_target_callback<T: 'static>(
|
||||||
window: HWND,
|
window: HWND,
|
||||||
msg: UINT,
|
msg: UINT,
|
||||||
wparam: WPARAM,
|
wparam: WPARAM,
|
||||||
|
|
|
@ -10,17 +10,17 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) type EventLoopRunnerShared<T> = Rc<ELRShared<T>>;
|
pub(crate) type EventLoopRunnerShared<T> = Rc<ELRShared<T>>;
|
||||||
pub(crate) struct ELRShared<T> {
|
pub(crate) struct ELRShared<T: 'static> {
|
||||||
runner: RefCell<Option<EventLoopRunner<T>>>,
|
runner: RefCell<Option<EventLoopRunner<T>>>,
|
||||||
buffer: RefCell<VecDeque<Event<T>>>,
|
buffer: RefCell<VecDeque<Event<'static, T>>>,
|
||||||
redraw_buffer: Rc<RefCell<VecDeque<WindowId>>>,
|
redraw_buffer: Rc<RefCell<VecDeque<WindowId>>>,
|
||||||
}
|
}
|
||||||
struct EventLoopRunner<T> {
|
struct EventLoopRunner<T: 'static> {
|
||||||
control_flow: ControlFlow,
|
control_flow: ControlFlow,
|
||||||
runner_state: RunnerState,
|
runner_state: RunnerState,
|
||||||
modal_redraw_window: HWND,
|
modal_redraw_window: HWND,
|
||||||
in_modal_loop: bool,
|
in_modal_loop: bool,
|
||||||
event_handler: Box<dyn FnMut(Event<T>, &mut ControlFlow)>,
|
event_handler: Box<dyn FnMut(Event<'_, T>, &mut ControlFlow)>,
|
||||||
panic_error: Option<PanicError>,
|
panic_error: Option<PanicError>,
|
||||||
redraw_buffer: Rc<RefCell<VecDeque<WindowId>>>,
|
redraw_buffer: Rc<RefCell<VecDeque<WindowId>>>,
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ impl<T> ELRShared<T> {
|
||||||
|
|
||||||
pub(crate) unsafe fn set_runner<F>(&self, event_loop: &EventLoop<T>, f: F)
|
pub(crate) unsafe fn set_runner<F>(&self, event_loop: &EventLoop<T>, f: F)
|
||||||
where
|
where
|
||||||
F: FnMut(Event<T>, &mut ControlFlow),
|
F: FnMut(Event<'_, T>, &mut ControlFlow),
|
||||||
{
|
{
|
||||||
let mut runner = EventLoopRunner::new(event_loop, self.redraw_buffer.clone(), f);
|
let mut runner = EventLoopRunner::new(event_loop, self.redraw_buffer.clone(), f);
|
||||||
{
|
{
|
||||||
|
@ -66,7 +66,18 @@ impl<T> ELRShared<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) unsafe fn send_event(&self, event: Event<T>) {
|
pub(crate) unsafe fn send_event(&self, event: Event<'static, T>) {
|
||||||
|
if let Err(event) = self.send_event_unbuffered(event) {
|
||||||
|
// If the runner is already borrowed, we're in the middle of an event loop invocation. Add
|
||||||
|
// the event to a buffer to be processed later.
|
||||||
|
self.buffer_event(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) unsafe fn send_event_unbuffered<'e>(
|
||||||
|
&self,
|
||||||
|
event: Event<'e, T>,
|
||||||
|
) -> Result<(), Event<'e, T>> {
|
||||||
if let Ok(mut runner_ref) = self.runner.try_borrow_mut() {
|
if let Ok(mut runner_ref) = self.runner.try_borrow_mut() {
|
||||||
if let Some(ref mut runner) = *runner_ref {
|
if let Some(ref mut runner) = *runner_ref {
|
||||||
runner.process_event(event);
|
runner.process_event(event);
|
||||||
|
@ -84,16 +95,14 @@ impl<T> ELRShared<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the runner is already borrowed, we're in the middle of an event loop invocation. Add
|
Err(event)
|
||||||
// the event to a buffer to be processed later.
|
|
||||||
self.buffer_event(event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) unsafe fn call_event_handler(&self, event: Event<T>) {
|
pub(crate) unsafe fn call_event_handler(&self, event: Event<'static, T>) {
|
||||||
if let Ok(mut runner_ref) = self.runner.try_borrow_mut() {
|
if let Ok(mut runner_ref) = self.runner.try_borrow_mut() {
|
||||||
if let Some(ref mut runner) = *runner_ref {
|
if let Some(ref mut runner) = *runner_ref {
|
||||||
runner.call_event_handler(event);
|
runner.call_event_handler(event);
|
||||||
|
@ -143,7 +152,7 @@ impl<T> ELRShared<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn buffer_event(&self, event: Event<T>) {
|
fn buffer_event(&self, event: Event<'static, T>) {
|
||||||
match event {
|
match event {
|
||||||
Event::RedrawRequested(window_id) => {
|
Event::RedrawRequested(window_id) => {
|
||||||
self.redraw_buffer.borrow_mut().push_back(window_id)
|
self.redraw_buffer.borrow_mut().push_back(window_id)
|
||||||
|
@ -176,7 +185,7 @@ impl<T> EventLoopRunner<T> {
|
||||||
f: F,
|
f: F,
|
||||||
) -> EventLoopRunner<T>
|
) -> EventLoopRunner<T>
|
||||||
where
|
where
|
||||||
F: FnMut(Event<T>, &mut ControlFlow),
|
F: FnMut(Event<'_, T>, &mut ControlFlow),
|
||||||
{
|
{
|
||||||
EventLoopRunner {
|
EventLoopRunner {
|
||||||
control_flow: ControlFlow::default(),
|
control_flow: ControlFlow::default(),
|
||||||
|
@ -184,8 +193,8 @@ impl<T> EventLoopRunner<T> {
|
||||||
in_modal_loop: false,
|
in_modal_loop: false,
|
||||||
modal_redraw_window: event_loop.window_target.p.thread_msg_target,
|
modal_redraw_window: event_loop.window_target.p.thread_msg_target,
|
||||||
event_handler: mem::transmute::<
|
event_handler: mem::transmute::<
|
||||||
Box<dyn FnMut(Event<T>, &mut ControlFlow)>,
|
Box<dyn FnMut(Event<'_, T>, &mut ControlFlow)>,
|
||||||
Box<dyn FnMut(Event<T>, &mut ControlFlow)>,
|
Box<dyn FnMut(Event<'_, T>, &mut ControlFlow)>,
|
||||||
>(Box::new(f)),
|
>(Box::new(f)),
|
||||||
panic_error: None,
|
panic_error: None,
|
||||||
redraw_buffer,
|
redraw_buffer,
|
||||||
|
@ -251,7 +260,7 @@ impl<T> EventLoopRunner<T> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_event(&mut self, event: Event<T>) {
|
fn process_event(&mut self, event: Event<'_, T>) {
|
||||||
// If we're in the modal loop, we need to have some mechanism for finding when the event
|
// If we're in the modal loop, we need to have some mechanism for finding when the event
|
||||||
// queue has been cleared so we can call `events_cleared`. Windows doesn't give any utilities
|
// queue has been cleared so we can call `events_cleared`. Windows doesn't give any utilities
|
||||||
// for doing this, but it DOES guarantee that WM_PAINT will only occur after input events have
|
// for doing this, but it DOES guarantee that WM_PAINT will only occur after input events have
|
||||||
|
@ -390,7 +399,7 @@ impl<T> EventLoopRunner<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_event_handler(&mut self, event: Event<T>) {
|
fn call_event_handler(&mut self, event: Event<'_, T>) {
|
||||||
if self.panic_error.is_none() {
|
if self.panic_error.is_none() {
|
||||||
let EventLoopRunner {
|
let EventLoopRunner {
|
||||||
ref mut panic_error,
|
ref mut panic_error,
|
||||||
|
|
|
@ -168,14 +168,6 @@ impl MonitorHandle {
|
||||||
MonitorHandle(hmonitor)
|
MonitorHandle(hmonitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn contains_point(&self, point: &POINT) -> bool {
|
|
||||||
let monitor_info = get_monitor_info(self.0).unwrap();
|
|
||||||
point.x >= monitor_info.rcMonitor.left
|
|
||||||
&& point.x <= monitor_info.rcMonitor.right
|
|
||||||
&& point.y >= monitor_info.rcMonitor.top
|
|
||||||
&& point.y <= monitor_info.rcMonitor.bottom
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn name(&self) -> Option<String> {
|
pub fn name(&self) -> Option<String> {
|
||||||
let monitor_info = get_monitor_info(self.0).unwrap();
|
let monitor_info = get_monitor_info(self.0).unwrap();
|
||||||
|
@ -196,8 +188,8 @@ impl MonitorHandle {
|
||||||
pub fn size(&self) -> PhysicalSize {
|
pub fn size(&self) -> PhysicalSize {
|
||||||
let monitor_info = get_monitor_info(self.0).unwrap();
|
let monitor_info = get_monitor_info(self.0).unwrap();
|
||||||
PhysicalSize {
|
PhysicalSize {
|
||||||
width: (monitor_info.rcMonitor.right - monitor_info.rcMonitor.left) as f64,
|
width: (monitor_info.rcMonitor.right - monitor_info.rcMonitor.left) as u32,
|
||||||
height: (monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top) as f64,
|
height: (monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top) as u32,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ use winapi::{
|
||||||
ctypes::wchar_t,
|
ctypes::wchar_t,
|
||||||
shared::{
|
shared::{
|
||||||
minwindef::{BOOL, DWORD},
|
minwindef::{BOOL, DWORD},
|
||||||
windef::{HWND, POINT, RECT},
|
windef::{HWND, RECT},
|
||||||
},
|
},
|
||||||
um::{
|
um::{
|
||||||
libloaderapi::{GetProcAddress, LoadLibraryA},
|
libloaderapi::{GetProcAddress, LoadLibraryA},
|
||||||
|
@ -85,10 +85,6 @@ fn win_to_err<F: FnOnce() -> BOOL>(f: F) -> Result<(), io::Error> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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> {
|
pub fn get_window_rect(hwnd: HWND) -> Option<RECT> {
|
||||||
unsafe { status_map(|rect| winuser::GetWindowRect(hwnd, rect)) }
|
unsafe { status_map(|rect| winuser::GetWindowRect(hwnd, rect)) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ use std::{
|
||||||
use winapi::{
|
use winapi::{
|
||||||
ctypes::c_int,
|
ctypes::c_int,
|
||||||
shared::{
|
shared::{
|
||||||
minwindef::{DWORD, HINSTANCE, LPARAM, UINT, WORD, WPARAM},
|
minwindef::{DWORD, HINSTANCE, UINT},
|
||||||
windef::{HWND, POINT, RECT},
|
windef::{HWND, POINT, RECT},
|
||||||
},
|
},
|
||||||
um::{
|
um::{
|
||||||
|
@ -30,14 +30,16 @@ use winapi::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
dpi::{LogicalPosition, LogicalSize, PhysicalSize},
|
dpi::{PhysicalPosition, PhysicalSize, Position, Size},
|
||||||
error::{ExternalError, NotSupportedError, OsError as RootOsError},
|
error::{ExternalError, NotSupportedError, OsError as RootOsError},
|
||||||
monitor::MonitorHandle as RootMonitorHandle,
|
monitor::MonitorHandle as RootMonitorHandle,
|
||||||
platform_impl::platform::{
|
platform_impl::platform::{
|
||||||
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::{self, EventLoopWindowTarget, DESTROY_MSG_ID, INITIAL_DPI_MSG_ID},
|
event_loop::{
|
||||||
|
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},
|
||||||
|
@ -125,8 +127,8 @@ impl Window {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_visible(&self, visible: bool) {
|
pub fn set_visible(&self, visible: bool) {
|
||||||
let window_state = Arc::clone(&self.window_state);
|
|
||||||
let window = self.window.clone();
|
let window = self.window.clone();
|
||||||
|
let window_state = Arc::clone(&self.window_state);
|
||||||
self.thread_executor.execute_in_thread(move || {
|
self.thread_executor.execute_in_thread(move || {
|
||||||
WindowState::set_window_flags(window_state.lock(), window.0, |f| {
|
WindowState::set_window_flags(window_state.lock(), window.0, |f| {
|
||||||
f.set(WindowFlags::VISIBLE, visible)
|
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)
|
util::get_window_rect(self.window.0)
|
||||||
.map(|rect| (rect.left as i32, rect.top as i32))
|
.map(|rect| Ok(PhysicalPosition::new(rect.left as f64, rect.top as f64)))
|
||||||
.unwrap()
|
.expect("Unexpected GetWindowRect failure; please report this error to https://github.com/rust-windowing/winit")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn outer_position(&self) -> Result<LogicalPosition, NotSupportedError> {
|
pub fn inner_position(&self) -> Result<PhysicalPosition, 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) {
|
|
||||||
let mut position: POINT = unsafe { mem::zeroed() };
|
let mut position: POINT = unsafe { mem::zeroed() };
|
||||||
if unsafe { winuser::ClientToScreen(self.window.0, &mut position) } == 0 {
|
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")
|
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]
|
#[inline]
|
||||||
pub fn inner_position(&self) -> Result<LogicalPosition, NotSupportedError> {
|
pub fn set_outer_position(&self, position: Position) {
|
||||||
let physical_position = self.inner_position_physical();
|
let (x, y): (i32, i32) = position.to_physical(self.hidpi_factor()).into();
|
||||||
let dpi_factor = self.hidpi_factor();
|
|
||||||
Ok(LogicalPosition::from_physical(
|
let window_state = Arc::clone(&self.window_state);
|
||||||
physical_position,
|
let window = self.window.clone();
|
||||||
dpi_factor,
|
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 {
|
unsafe {
|
||||||
winuser::SetWindowPos(
|
winuser::SetWindowPos(
|
||||||
self.window.0,
|
self.window.0,
|
||||||
|
@ -199,43 +194,22 @@ impl Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_outer_position(&self, logical_position: LogicalPosition) {
|
pub fn inner_size(&self) -> PhysicalSize {
|
||||||
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) {
|
|
||||||
let mut rect: RECT = unsafe { mem::zeroed() };
|
let mut rect: RECT = unsafe { mem::zeroed() };
|
||||||
if unsafe { winuser::GetClientRect(self.window.0, &mut rect) } == 0 {
|
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")
|
panic!("Unexpected GetClientRect failure: please report this error to https://github.com/rust-windowing/winit")
|
||||||
}
|
}
|
||||||
(
|
PhysicalSize::new(
|
||||||
(rect.right - rect.left) as u32,
|
(rect.right - rect.left) as u32,
|
||||||
(rect.bottom - rect.top) as u32,
|
(rect.bottom - rect.top) as u32,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn inner_size(&self) -> LogicalSize {
|
pub fn outer_size(&self) -> PhysicalSize {
|
||||||
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) {
|
|
||||||
util::get_window_rect(self.window.0)
|
util::get_window_rect(self.window.0)
|
||||||
.map(|rect| {
|
.map(|rect| {
|
||||||
(
|
PhysicalSize::new(
|
||||||
(rect.right - rect.left) as u32,
|
(rect.right - rect.left) as u32,
|
||||||
(rect.bottom - rect.top) as u32,
|
(rect.bottom - rect.top) as u32,
|
||||||
)
|
)
|
||||||
|
@ -243,13 +217,6 @@ impl Window {
|
||||||
.unwrap()
|
.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) {
|
pub(crate) fn set_inner_size_physical(&self, x: u32, y: u32) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let rect = util::adjust_window_rect(
|
let rect = util::adjust_window_rect(
|
||||||
|
@ -283,9 +250,9 @@ impl Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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 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_state = Arc::clone(&self.window_state);
|
||||||
let window = self.window.clone();
|
let window = self.window.clone();
|
||||||
|
@ -298,36 +265,20 @@ impl Window {
|
||||||
self.set_inner_size_physical(width, height);
|
self.set_inner_size_physical(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn set_min_inner_size_physical(&self, dimensions: Option<(u32, u32)>) {
|
#[inline]
|
||||||
self.window_state.lock().min_size = dimensions.map(Into::into);
|
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.
|
// Make windows re-check the window size bounds.
|
||||||
let (width, height) = self.inner_size_physical();
|
let size = self.inner_size();
|
||||||
self.set_inner_size_physical(width, height);
|
self.set_inner_size(size.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_min_inner_size(&self, logical_size: Option<LogicalSize>) {
|
pub fn set_max_inner_size(&self, size: Option<Size>) {
|
||||||
let physical_size = logical_size.map(|logical_size| {
|
self.window_state.lock().max_size = 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);
|
|
||||||
// Make windows re-check the window size bounds.
|
// Make windows re-check the window size bounds.
|
||||||
let (width, height) = self.inner_size_physical();
|
let size = self.inner_size();
|
||||||
self.set_inner_size_physical(width, height);
|
self.set_inner_size(size.into());
|
||||||
}
|
|
||||||
|
|
||||||
#[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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -411,7 +362,11 @@ impl Window {
|
||||||
self.window_state.lock().dpi_factor
|
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 };
|
let mut point = POINT { x, y };
|
||||||
unsafe {
|
unsafe {
|
||||||
if winuser::ClientToScreen(self.window.0, &mut point) == 0 {
|
if winuser::ClientToScreen(self.window.0, &mut point) == 0 {
|
||||||
|
@ -424,16 +379,6 @@ impl Window {
|
||||||
Ok(())
|
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]
|
#[inline]
|
||||||
pub fn id(&self) -> WindowId {
|
pub fn id(&self) -> WindowId {
|
||||||
WindowId(self.window.0)
|
WindowId(self.window.0)
|
||||||
|
@ -691,7 +636,7 @@ impl Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_ime_position(&self, _logical_spot: LogicalPosition) {
|
pub fn set_ime_position(&self, _position: Position) {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -770,41 +715,6 @@ unsafe fn init<T: 'static>(
|
||||||
// registering the window class
|
// registering the window class
|
||||||
let class_name = register_window_class(&window_icon, &taskbar_icon);
|
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();
|
let mut window_flags = WindowFlags::empty();
|
||||||
window_flags.set(WindowFlags::DECORATIONS, attributes.decorations);
|
window_flags.set(WindowFlags::DECORATIONS, attributes.decorations);
|
||||||
window_flags.set(WindowFlags::ALWAYS_ON_TOP, attributes.always_on_top);
|
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 = hwnd_dpi(real_window.0);
|
||||||
let dpi_factor = dpi_to_scale_factor(dpi);
|
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
|
// making the window transparent
|
||||||
if attributes.transparent && !pl_attribs.no_redirection_bitmap {
|
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);
|
window_flags.set(WindowFlags::MAXIMIZED, attributes.maximized);
|
||||||
|
|
||||||
// If the system theme is dark, we need to set the window theme now
|
// 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(),
|
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 {
|
if let Some(_) = attributes.fullscreen {
|
||||||
win.set_fullscreen(attributes.fullscreen);
|
win.set_fullscreen(attributes.fullscreen);
|
||||||
force_window_active(win.window.0);
|
force_window_active(win.window.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(dimensions) = attributes.inner_size {
|
|
||||||
win.set_inner_size(dimensions);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(win)
|
Ok(win)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
dpi::LogicalSize,
|
dpi::Size,
|
||||||
platform_impl::platform::{event_loop, icon::WinIcon, util},
|
platform_impl::platform::{event_loop, icon::WinIcon, util},
|
||||||
window::{CursorIcon, Fullscreen, WindowAttributes},
|
window::{CursorIcon, Fullscreen, WindowAttributes},
|
||||||
};
|
};
|
||||||
|
@ -19,8 +19,8 @@ pub struct WindowState {
|
||||||
pub mouse: MouseProperties,
|
pub mouse: MouseProperties,
|
||||||
|
|
||||||
/// Used by `WM_GETMINMAXINFO`.
|
/// Used by `WM_GETMINMAXINFO`.
|
||||||
pub min_size: Option<LogicalSize>,
|
pub min_size: Option<Size>,
|
||||||
pub max_size: Option<LogicalSize>,
|
pub max_size: Option<Size>,
|
||||||
|
|
||||||
pub window_icon: Option<WinIcon>,
|
pub window_icon: Option<WinIcon>,
|
||||||
pub taskbar_icon: Option<WinIcon>,
|
pub taskbar_icon: Option<WinIcon>,
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
dpi::{LogicalPosition, LogicalSize},
|
dpi::{PhysicalPosition, PhysicalSize, Position, Size},
|
||||||
error::{ExternalError, NotSupportedError, OsError},
|
error::{ExternalError, NotSupportedError, OsError},
|
||||||
event_loop::EventLoopWindowTarget,
|
event_loop::EventLoopWindowTarget,
|
||||||
monitor::{MonitorHandle, VideoMode},
|
monitor::{MonitorHandle, VideoMode},
|
||||||
|
@ -102,17 +102,17 @@ pub struct WindowAttributes {
|
||||||
/// used.
|
/// used.
|
||||||
///
|
///
|
||||||
/// The default is `None`.
|
/// The default is `None`.
|
||||||
pub inner_size: Option<LogicalSize>,
|
pub inner_size: Option<Size>,
|
||||||
|
|
||||||
/// The minimum dimensions a window can be, If this is `None`, the window will have no minimum dimensions (aside from reserved).
|
/// The minimum dimensions a window can be, If this is `None`, the window will have no minimum dimensions (aside from reserved).
|
||||||
///
|
///
|
||||||
/// The default is `None`.
|
/// The default is `None`.
|
||||||
pub min_inner_size: Option<LogicalSize>,
|
pub min_inner_size: Option<Size>,
|
||||||
|
|
||||||
/// The maximum dimensions a window can be, If this is `None`, the maximum will have no maximum or will be set to the primary monitor's dimensions by the platform.
|
/// The maximum dimensions a window can be, If this is `None`, the maximum will have no maximum or will be set to the primary monitor's dimensions by the platform.
|
||||||
///
|
///
|
||||||
/// The default is `None`.
|
/// The default is `None`.
|
||||||
pub max_inner_size: Option<LogicalSize>,
|
pub max_inner_size: Option<Size>,
|
||||||
|
|
||||||
/// Whether the window is resizable or not.
|
/// Whether the window is resizable or not.
|
||||||
///
|
///
|
||||||
|
@ -197,8 +197,8 @@ impl WindowBuilder {
|
||||||
///
|
///
|
||||||
/// [`Window::set_inner_size`]: crate::window::Window::set_inner_size
|
/// [`Window::set_inner_size`]: crate::window::Window::set_inner_size
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn with_inner_size(mut self, size: LogicalSize) -> Self {
|
pub fn with_inner_size<S: Into<Size>>(mut self, size: S) -> Self {
|
||||||
self.window.inner_size = Some(size);
|
self.window.inner_size = Some(size.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,8 +208,8 @@ impl WindowBuilder {
|
||||||
///
|
///
|
||||||
/// [`Window::set_min_inner_size`]: crate::window::Window::set_min_inner_size
|
/// [`Window::set_min_inner_size`]: crate::window::Window::set_min_inner_size
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn with_min_inner_size(mut self, min_size: LogicalSize) -> Self {
|
pub fn with_min_inner_size<S: Into<Size>>(mut self, min_size: S) -> Self {
|
||||||
self.window.min_inner_size = Some(min_size);
|
self.window.min_inner_size = Some(min_size.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,8 +219,8 @@ impl WindowBuilder {
|
||||||
///
|
///
|
||||||
/// [`Window::set_max_inner_size`]: crate::window::Window::set_max_inner_size
|
/// [`Window::set_max_inner_size`]: crate::window::Window::set_max_inner_size
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn with_max_inner_size(mut self, max_size: LogicalSize) -> Self {
|
pub fn with_max_inner_size<S: Into<Size>>(mut self, max_size: S) -> Self {
|
||||||
self.window.max_inner_size = Some(max_size);
|
self.window.max_inner_size = Some(max_size.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -422,7 +422,7 @@ impl Window {
|
||||||
///
|
///
|
||||||
/// [safe area]: https://developer.apple.com/documentation/uikit/uiview/2891103-safeareainsets?language=objc
|
/// [safe area]: https://developer.apple.com/documentation/uikit/uiview/2891103-safeareainsets?language=objc
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn inner_position(&self) -> Result<LogicalPosition, NotSupportedError> {
|
pub fn inner_position(&self) -> Result<PhysicalPosition, NotSupportedError> {
|
||||||
self.window.inner_position()
|
self.window.inner_position()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,7 +441,7 @@ impl Window {
|
||||||
/// - **iOS:** Can only be called on the main thread. Returns the top left coordinates of the
|
/// - **iOS:** Can only be called on the main thread. Returns the top left coordinates of the
|
||||||
/// window in the screen space coordinate system.
|
/// window in the screen space coordinate system.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn outer_position(&self) -> Result<LogicalPosition, NotSupportedError> {
|
pub fn outer_position(&self) -> Result<PhysicalPosition, NotSupportedError> {
|
||||||
self.window.outer_position()
|
self.window.outer_position()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -455,24 +455,22 @@ impl Window {
|
||||||
/// - **iOS:** Can only be called on the main thread. Sets the top left coordinates of the
|
/// - **iOS:** Can only be called on the main thread. Sets the top left coordinates of the
|
||||||
/// window in the screen space coordinate system.
|
/// window in the screen space coordinate system.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_outer_position(&self, position: LogicalPosition) {
|
pub fn set_outer_position<P: Into<Position>>(&self, position: P) {
|
||||||
self.window.set_outer_position(position)
|
self.window.set_outer_position(position.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the logical size of the window's client area.
|
/// Returns the logical size of the window's client area.
|
||||||
///
|
///
|
||||||
/// The client area is the content of the window, excluding the title bar and borders.
|
/// The client area is the content of the window, excluding the title bar and borders.
|
||||||
///
|
///
|
||||||
/// Converting the returned `LogicalSize` to `PhysicalSize` produces the size your framebuffer should be.
|
|
||||||
///
|
|
||||||
/// ## Platform-specific
|
/// ## Platform-specific
|
||||||
///
|
///
|
||||||
/// - **iOS:** Can only be called on the main thread. Returns the `LogicalSize` of the window's
|
/// - **iOS:** Can only be called on the main thread. Returns the `PhysicalSize` of the window's
|
||||||
/// [safe area] in screen space coordinates.
|
/// [safe area] in screen space coordinates.
|
||||||
///
|
///
|
||||||
/// [safe area]: https://developer.apple.com/documentation/uikit/uiview/2891103-safeareainsets?language=objc
|
/// [safe area]: https://developer.apple.com/documentation/uikit/uiview/2891103-safeareainsets?language=objc
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn inner_size(&self) -> LogicalSize {
|
pub fn inner_size(&self) -> PhysicalSize {
|
||||||
self.window.inner_size()
|
self.window.inner_size()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -486,8 +484,8 @@ impl Window {
|
||||||
/// - **iOS:** Unimplemented. Currently this panics, as it's not clear what `set_inner_size`
|
/// - **iOS:** Unimplemented. Currently this panics, as it's not clear what `set_inner_size`
|
||||||
/// would mean for iOS.
|
/// would mean for iOS.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_inner_size(&self, size: LogicalSize) {
|
pub fn set_inner_size<S: Into<Size>>(&self, size: S) {
|
||||||
self.window.set_inner_size(size)
|
self.window.set_inner_size(size.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the logical size of the entire window.
|
/// Returns the logical size of the entire window.
|
||||||
|
@ -497,10 +495,10 @@ impl Window {
|
||||||
///
|
///
|
||||||
/// ## Platform-specific
|
/// ## Platform-specific
|
||||||
///
|
///
|
||||||
/// - **iOS:** Can only be called on the main thread. Returns the `LogicalSize` of the window in
|
/// - **iOS:** Can only be called on the main thread. Returns the `PhysicalSize` of the window in
|
||||||
/// screen space coordinates.
|
/// screen space coordinates.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn outer_size(&self) -> LogicalSize {
|
pub fn outer_size(&self) -> PhysicalSize {
|
||||||
self.window.outer_size()
|
self.window.outer_size()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -511,8 +509,8 @@ impl Window {
|
||||||
/// - **iOS:** Has no effect.
|
/// - **iOS:** Has no effect.
|
||||||
/// - **Web:** Has no effect.
|
/// - **Web:** Has no effect.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_min_inner_size(&self, dimensions: Option<LogicalSize>) {
|
pub fn set_min_inner_size<S: Into<Size>>(&self, min_size: Option<S>) {
|
||||||
self.window.set_min_inner_size(dimensions)
|
self.window.set_min_inner_size(min_size.map(|s| s.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets a maximum dimension size for the window.
|
/// Sets a maximum dimension size for the window.
|
||||||
|
@ -522,8 +520,8 @@ impl Window {
|
||||||
/// - **iOS:** Has no effect.
|
/// - **iOS:** Has no effect.
|
||||||
/// - **Web:** Has no effect.
|
/// - **Web:** Has no effect.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_max_inner_size(&self, dimensions: Option<LogicalSize>) {
|
pub fn set_max_inner_size<S: Into<Size>>(&self, max_size: Option<S>) {
|
||||||
self.window.set_max_inner_size(dimensions)
|
self.window.set_max_inner_size(max_size.map(|s| s.into()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -675,8 +673,8 @@ impl Window {
|
||||||
/// **iOS:** Has no effect.
|
/// **iOS:** Has no effect.
|
||||||
/// - **Web:** Has no effect.
|
/// - **Web:** Has no effect.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_ime_position(&self, position: LogicalPosition) {
|
pub fn set_ime_position<P: Into<Position>>(&self, position: P) {
|
||||||
self.window.set_ime_position(position)
|
self.window.set_ime_position(position.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -700,8 +698,8 @@ impl Window {
|
||||||
/// - **iOS:** Always returns an `Err`.
|
/// - **iOS:** Always returns an `Err`.
|
||||||
/// - **Web:** Has no effect.
|
/// - **Web:** Has no effect.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_cursor_position(&self, position: LogicalPosition) -> Result<(), ExternalError> {
|
pub fn set_cursor_position<P: Into<Position>>(&self, position: P) -> Result<(), ExternalError> {
|
||||||
self.window.set_cursor_position(position)
|
self.window.set_cursor_position(position.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Grabs the cursor, preventing it from leaving the window.
|
/// Grabs the cursor, preventing it from leaving the window.
|
||||||
|
|
Loading…
Reference in a new issue