Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename hidpi_factor to scale_factor #1334

Merged
merged 7 commits into from
Jan 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Unreleased

- On macOS, fix application termination on `ControlFlow::Exit`
- Rename `hidpi_factor` to `scale_factor`
- On X11, deprecate `WINIT_HIDPI_FACTOR` environment variable in favor of `WINIT_X11_SCALE_FACTOR`

# 0.20.0 Alpha 4 (2019-10-18)

Expand Down
78 changes: 39 additions & 39 deletions src/dpi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,62 +19,62 @@
//!
//! That's a description of what happens when the button is 100x100 *physical* pixels. Instead, let's try using 100x100
//! *logical* pixels. To map logical pixels to physical pixels, we simply multiply by the DPI (dots per inch) factor.
//! On a "typical" desktop display, the DPI factor will be 1.0, so 100x100 logical pixels equates to 100x100 physical
//! pixels. However, a 1440p display may have a DPI factor of 1.25, so the button is rendered as 125x125 physical pixels.
//! On a "typical" desktop display, the scale factor will be 1.0, so 100x100 logical pixels equates to 100x100 physical
//! pixels. However, a 1440p display may have a scale factor of 1.25, so the button is rendered as 125x125 physical pixels.
//! Ideally, the button now has approximately the same perceived size across varying displays.
//!
//! Failure to account for the DPI factor can create a badly degraded user experience. Most notably, it can make users
//! Failure to account for the scale factor can create a badly degraded user experience. Most notably, it can make users
//! feel like they have bad eyesight, which will potentially cause them to think about growing elderly, resulting in
//! them entering an existential panic. Once users enter that state, they will no longer be focused on your application.
//!
//! There are two ways to get the DPI factor:
//! - You can track the [`HiDpiFactorChanged`](../enum.WindowEvent.html#variant.HiDpiFactorChanged) event of your
//! windows. This event is sent any time the DPI factor changes, either because the window moved to another monitor,
//! There are two ways to get the scale factor:
//! - You can track the [`DpiChanged`](../enum.WindowEvent.html#variant.DpiChanged) event of your
//! windows. This event is sent any time the scale factor changes, either because the window moved to another monitor,
//! or because the user changed the configuration of their screen.
//! - You can also retrieve the DPI factor of a monitor by calling
//! [`MonitorHandle::hidpi_factor`](../monitor/struct.MonitorHandle.html#method.hidpi_factor), or the
//! current DPI factor applied to a window by calling
//! [`Window::hidpi_factor`](../window/struct.Window.html#method.hidpi_factor), which is roughly equivalent
//! to `window.current_monitor().hidpi_factor()`.
//! - You can also retrieve the scale factor of a monitor by calling
//! [`MonitorHandle::scale_factor`](../monitor/struct.MonitorHandle.html#method.scale_factor), or the
//! current scale factor applied to a window by calling
//! [`Window::scale_factor`](../window/struct.Window.html#method.scale_factor), which is roughly equivalent
//! to `window.current_monitor().scale_factor()`.
//!
//! Depending on the platform, the window's actual DPI factor may only be known after
//! Depending on the platform, the window's actual scale factor may only be known after
//! the event loop has started and your window has been drawn once. To properly handle these cases,
//! the most robust way is to monitor the [`HiDpiFactorChanged`](../enum.WindowEvent.html#variant.HiDpiFactorChanged)
//! event and dynamically adapt your drawing logic to follow the DPI factor.
//! the most robust way is to monitor the [`DpiChanged`](../enum.WindowEvent.html#variant.DpiChanged)
//! event and dynamically adapt your drawing logic to follow the scale factor.
//!
//! Here's an overview of what sort of DPI factors you can expect, and where they come from:
//! Here's an overview of what sort of scale factors you can expect, and where they come from:
//! - **Windows:** On Windows 8 and 10, per-monitor scaling is readily configured by users from the display settings.
//! While users are free to select any option they want, they're only given a selection of "nice" DPI factors, i.e.
//! 1.0, 1.25, 1.5... on Windows 7, the DPI factor is global and changing it requires logging out.
//! - **macOS:** The buzzword is "retina displays", which have a DPI factor of 2.0. Otherwise, the DPI factor is 1.0.
//! Intermediate DPI factors are never used, thus 1440p displays/etc. aren't properly supported. It's possible for any
//! display to use that 2.0 DPI factor, given the use of the command line.
//! - **X11:** On X11, we calcuate the DPI factor based on the millimeter dimensions provided by XRandR. This can
//! While users are free to select any option they want, they're only given a selection of "nice" scale factors, i.e.
//! 1.0, 1.25, 1.5... on Windows 7, the scale factor is global and changing it requires logging out.
//! - **macOS:** The buzzword is "retina displays", which have a scale factor of 2.0. Otherwise, the scale factor is 1.0.
//! Intermediate scale factors are never used, thus 1440p displays/etc. aren't properly supported. It's possible for any
//! display to use that 2.0 scale factor, given the use of the command line.
//! - **X11:** On X11, we calcuate the scale factor based on the millimeter dimensions provided by XRandR. This can
//! result in a wide range of possible values, including some interesting ones like 1.0833333333333333. This can be
//! overridden using the `WINIT_HIDPI_FACTOR` environment variable, though that's not recommended.
//! - **Wayland:** On Wayland, DPI factors are set per-screen by the server, and are always integers (most often 1 or 2).
//! - **iOS:** DPI factors are both constant and device-specific on iOS.
//! - **Android:** This feature isn't yet implemented on Android, so the DPI factor will always be returned as 1.0.
//! - **Web:** DPI factors are handled by the browser and will always be 1.0 for your application.
//! overridden using the `WINIT_X11_SCALE_FACTOR` environment variable, though that's not recommended.
//! - **Wayland:** On Wayland, scale factors are set per-screen by the server, and are always integers (most often 1 or 2).
//! - **iOS:** scale factors are both constant and device-specific on iOS.
//! - **Android:** This feature isn't yet implemented on Android, so the scale factor will always be returned as 1.0.
//! - **Web:** scale factors are handled by the browser and will always be 1.0 for your application.
//!
//! The window's logical size is conserved across DPI changes, resulting in the physical size changing instead. This
//! may be surprising on X11, but is quite standard elsewhere. Physical size changes always produce a
//! [`Resized`](../event/enum.WindowEvent.html#variant.Resized) event, even on platforms where no resize actually occurs,
//! such as macOS and Wayland. As a result, it's not necessary to separately handle
//! [`HiDpiFactorChanged`](../event/enum.WindowEvent.html#variant.HiDpiFactorChanged) if you're only listening for size.
//! [`DpiChanged`](../event/enum.WindowEvent.html#variant.DpiChanged) if you're only listening for size.
//!
//! Your GPU has no awareness of the concept of logical pixels, and unless you like wasting pixel density, your
//! framebuffer's size should be in physical pixels.
//!
//! `winit` will send [`Resized`](../enum.WindowEvent.html#variant.Resized) events whenever a window's logical size
//! changes, and [`HiDpiFactorChanged`](../enum.WindowEvent.html#variant.HiDpiFactorChanged) events
//! whenever the DPI factor changes. Receiving either of these events means that the physical size of your window has
//! changes, and [`DpiChanged`](../enum.WindowEvent.html#variant.DpiChanged) events
//! whenever the scale factor changes. Receiving either of these events means that the physical size of your window has
//! changed, and you should recompute it using the latest values you received for each. If the logical size and the
//! DPI factor change simultaneously, `winit` will send both events together; thus, it's recommended to buffer
//! scale factor change simultaneously, `winit` will send both events together; thus, it's recommended to buffer
//! these events and process them at the end of the queue.
//!
//! If you never received any [`HiDpiFactorChanged`](../enum.WindowEvent.html#variant.HiDpiFactorChanged) events,
//! then your window's DPI factor is 1.
//! If you never received any [`DpiChanged`](../enum.WindowEvent.html#variant.DpiChanged) events,
//! then your window's scale factor is 1.

pub trait Pixel: Copy + Into<f64> {
fn from_f64(f: f64) -> Self;
Expand Down Expand Up @@ -124,13 +124,13 @@ impl Pixel for f64 {
}
}

/// Checks that the DPI factor is a normal positive `f64`.
/// Checks that the scale factor is a normal positive `f64`.
///
/// All functions that take a DPI factor assert that this will return `true`. If you're sourcing DPI factors from
/// All functions that take a scale factor assert that this will return `true`. If you're sourcing scale factors from
/// anywhere other than winit, it's recommended to validate them using this function before passing them to winit;
/// otherwise, you risk panics.
#[inline]
pub fn validate_hidpi_factor(dpi_factor: f64) -> bool {
pub fn validate_scale_factor(dpi_factor: f64) -> bool {
dpi_factor.is_sign_positive() && dpi_factor.is_normal()
}

Expand Down Expand Up @@ -164,7 +164,7 @@ impl<P: Pixel> LogicalPosition<P> {

#[inline]
pub fn to_physical<X: Pixel>(&self, dpi_factor: f64) -> PhysicalPosition<X> {
assert!(validate_hidpi_factor(dpi_factor));
assert!(validate_scale_factor(dpi_factor));
let x = self.x.into() * dpi_factor;
let y = self.y.into() * dpi_factor;
PhysicalPosition::new(x, y).cast()
Expand Down Expand Up @@ -233,7 +233,7 @@ impl<P: Pixel> PhysicalPosition<P> {

#[inline]
pub fn to_logical<X: Pixel>(&self, dpi_factor: f64) -> LogicalPosition<X> {
assert!(validate_hidpi_factor(dpi_factor));
assert!(validate_scale_factor(dpi_factor));
let x = self.x.into() / dpi_factor;
let y = self.y.into() / dpi_factor;
LogicalPosition::new(x, y).cast()
Expand Down Expand Up @@ -299,7 +299,7 @@ impl<P: Pixel> LogicalSize<P> {

#[inline]
pub fn to_physical<X: Pixel>(&self, dpi_factor: f64) -> PhysicalSize<X> {
assert!(validate_hidpi_factor(dpi_factor));
assert!(validate_scale_factor(dpi_factor));
let width = self.width.into() * dpi_factor;
let height = self.height.into() * dpi_factor;
PhysicalSize::new(width, height).cast()
Expand Down Expand Up @@ -361,7 +361,7 @@ impl<P: Pixel> PhysicalSize<P> {

#[inline]
pub fn to_logical<X: Pixel>(&self, dpi_factor: f64) -> LogicalSize<X> {
assert!(validate_hidpi_factor(dpi_factor));
assert!(validate_scale_factor(dpi_factor));
let width = self.width.into() / dpi_factor;
let height = self.height.into() / dpi_factor;
LogicalSize::new(width, height).cast()
Expand Down
12 changes: 6 additions & 6 deletions src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,21 +213,21 @@ pub enum WindowEvent<'a> {
/// Touch event has been received
Touch(Touch),

/// The DPI factor of the window has changed.
/// The window's scale factor has changed.
///
/// The following user actions can cause DPI changes:
///
/// * Changing the display's resolution.
/// * Changing the display's DPI factor (e.g. in Control Panel on Windows).
/// * Moving the window to a display with a different DPI factor.
/// * Changing the display's scale factor (e.g. in Control Panel on Windows).
/// * Moving the window to a display with a different scale factor.
///
/// After this event callback has been processed, the window will be resized to whatever value
/// 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.
///
/// For more information about DPI in general, see the [`dpi`](dpi/index.html) module.
HiDpiFactorChanged {
hidpi_factor: f64,
DpiChanged {
scale_factor: f64,
new_inner_size: &'a mut PhysicalSize<u32>,
},
}
Expand Down Expand Up @@ -300,7 +300,7 @@ impl<'a> WindowEvent<'a> {
}),
RedrawRequested => Some(RedrawRequested),
Touch(touch) => Some(Touch(touch)),
HiDpiFactorChanged { .. } => None,
DpiChanged { .. } => None,
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/monitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,18 +148,18 @@ impl MonitorHandle {
self.inner.position()
}

/// Returns the DPI factor that can be used to map logical pixels to physical pixels, and vice versa.
/// Returns the scale factor that can be used to map logical pixels to physical pixels, and vice versa.
///
/// See the [`dpi`](../dpi/index.html) module for more information.
///
/// ## Platform-specific
///
/// - **X11:** Can be overridden using the `WINIT_HIDPI_FACTOR` environment variable.
/// - **X11:** Can be overridden using the `WINIT_X11_SCALE_FACTOR` environment variable.
/// - **Android:** Always returns 1.0.
/// - **Web:** Always returns 1.0
#[inline]
pub fn hidpi_factor(&self) -> f64 {
self.inner.hidpi_factor()
pub fn scale_factor(&self) -> f64 {
self.inner.scale_factor()
}

/// Returns all fullscreen video modes supported by this monitor.
Expand Down
20 changes: 10 additions & 10 deletions src/platform/ios.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ pub trait WindowExtIOS {
/// [`UIView`]: https://developer.apple.com/documentation/uikit/uiview?language=objc
fn ui_view(&self) -> *mut c_void;

/// Sets the [`contentScaleFactor`] of the underlying [`UIWindow`] to `hidpi_factor`.
/// Sets the [`contentScaleFactor`] of the underlying [`UIWindow`] to `scale_factor`.
///
/// The default value is device dependent, and it's recommended GLES or Metal applications set
/// this to [`MonitorHandle::hidpi_factor()`].
/// this to [`MonitorHandle::scale_factor()`].
///
/// [`UIWindow`]: https://developer.apple.com/documentation/uikit/uiwindow?language=objc
/// [`contentScaleFactor`]: https://developer.apple.com/documentation/uikit/uiview/1622657-contentscalefactor?language=objc
fn set_hidpi_factor(&self, hidpi_factor: f64);
fn set_scale_factor(&self, scale_factor: f64);

/// Sets the valid orientations for the [`Window`].
///
Expand Down Expand Up @@ -113,8 +113,8 @@ impl WindowExtIOS for Window {
}

#[inline]
fn set_hidpi_factor(&self, hidpi_factor: f64) {
self.window.set_hidpi_factor(hidpi_factor)
fn set_scale_factor(&self, scale_factor: f64) {
self.window.set_scale_factor(scale_factor)
}

#[inline]
Expand Down Expand Up @@ -148,14 +148,14 @@ pub trait WindowBuilderExtIOS {
/// [`UIView`]: https://developer.apple.com/documentation/uikit/uiview?language=objc
fn with_root_view_class(self, root_view_class: *const c_void) -> WindowBuilder;

/// Sets the [`contentScaleFactor`] of the underlying [`UIWindow`] to `hidpi_factor`.
/// Sets the [`contentScaleFactor`] of the underlying [`UIWindow`] to `scale_factor`.
///
/// The default value is device dependent, and it's recommended GLES or Metal applications set
/// this to [`MonitorHandle::hidpi_factor()`].
/// this to [`MonitorHandle::scale_factor()`].
///
/// [`UIWindow`]: https://developer.apple.com/documentation/uikit/uiwindow?language=objc
/// [`contentScaleFactor`]: https://developer.apple.com/documentation/uikit/uiview/1622657-contentscalefactor?language=objc
fn with_hidpi_factor(self, hidpi_factor: f64) -> WindowBuilder;
fn with_scale_factor(self, scale_factor: f64) -> WindowBuilder;

/// Sets the valid orientations for the [`Window`].
///
Expand Down Expand Up @@ -204,8 +204,8 @@ impl WindowBuilderExtIOS for WindowBuilder {
}

#[inline]
fn with_hidpi_factor(mut self, hidpi_factor: f64) -> WindowBuilder {
self.platform_specific.hidpi_factor = Some(hidpi_factor);
fn with_scale_factor(mut self, scale_factor: f64) -> WindowBuilder {
self.platform_specific.scale_factor = Some(scale_factor);
self
}

Expand Down
16 changes: 8 additions & 8 deletions src/platform_impl/android/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl EventLoop {
while let Ok(event) = self.event_rx.try_recv() {
let e = match event {
android_glue::Event::EventMotion(motion) => {
let dpi_factor = MonitorHandle.hidpi_factor();
let dpi_factor = MonitorHandle.scale_factor();
let location = LogicalPosition::from_physical(
(motion.x as f64, motion.y as f64),
dpi_factor,
Expand Down Expand Up @@ -102,7 +102,7 @@ impl EventLoop {
if native_window.is_null() {
None
} else {
let dpi_factor = MonitorHandle.hidpi_factor();
let dpi_factor = MonitorHandle.scale_factor();
let physical_size = MonitorHandle.size();
let size = LogicalSize::from_physical(physical_size, dpi_factor);
Some(Event::WindowEvent {
Expand Down Expand Up @@ -195,14 +195,14 @@ impl fmt::Debug for MonitorHandle {
name: Option<String>,
dimensions: PhysicalSize<u32>,
position: PhysicalPosition<i32>,
hidpi_factor: f64,
scale_factor: f64,
}

let monitor_id_proxy = MonitorHandle {
name: self.name(),
dimensions: self.size(),
position: self.outer_position(),
hidpi_factor: self.hidpi_factor(),
scale_factor: self.scale_factor(),
};

monitor_id_proxy.fmt(f)
Expand Down Expand Up @@ -234,7 +234,7 @@ impl MonitorHandle {
}

#[inline]
pub fn hidpi_factor(&self) -> f64 {
pub fn scale_factor(&self) -> f64 {
1.0
}
}
Expand Down Expand Up @@ -319,7 +319,7 @@ impl Window {
if self.native_window.is_null() {
None
} else {
let dpi_factor = self.hidpi_factor();
let dpi_factor = self.scale_factor();
let physical_size = self.current_monitor().size();
Some(LogicalSize::from_physical(physical_size, dpi_factor))
}
Expand All @@ -336,8 +336,8 @@ impl Window {
}

#[inline]
pub fn hidpi_factor(&self) -> f64 {
self.current_monitor().hidpi_factor()
pub fn scale_factor(&self) -> f64 {
self.current_monitor().scale_factor()
}

#[inline]
Expand Down
16 changes: 8 additions & 8 deletions src/platform_impl/ios/app_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -842,15 +842,15 @@ fn handle_event_proxy(
proxy: EventProxy,
) {
match proxy {
EventProxy::HiDpiFactorChangedProxy {
EventProxy::DpiChangedProxy {
suggested_size,
hidpi_factor,
scale_factor,
window_id,
} => handle_hidpi_proxy(
event_handler,
control_flow,
suggested_size,
hidpi_factor,
scale_factor,
window_id,
),
}
Expand All @@ -860,22 +860,22 @@ fn handle_hidpi_proxy(
event_handler: &mut Box<dyn EventHandler>,
mut control_flow: ControlFlow,
suggested_size: LogicalSize<f64>,
hidpi_factor: f64,
scale_factor: f64,
window_id: id,
) {
let mut size = suggested_size.to_physical(hidpi_factor);
let mut size = suggested_size.to_physical(scale_factor);
let new_inner_size = &mut size;
let event = Event::WindowEvent {
window_id: RootWindowId(window_id.into()),
event: WindowEvent::HiDpiFactorChanged {
hidpi_factor,
event: WindowEvent::DpiChanged {
scale_factor,
new_inner_size,
},
};
event_handler.handle_nonuser_event(event, &mut control_flow);
let (view, screen_frame) = get_view_and_screen_frame(window_id);
let physical_size = *new_inner_size;
let logical_size = physical_size.to_logical(hidpi_factor);
let logical_size = physical_size.to_logical(scale_factor);
let size = CGSize::new(logical_size);
let new_frame: CGRect = CGRect::new(screen_frame.origin, size);
unsafe {
Expand Down
4 changes: 2 additions & 2 deletions src/platform_impl/ios/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ pub enum EventWrapper {

#[derive(Debug, PartialEq)]
pub enum EventProxy {
HiDpiFactorChangedProxy {
DpiChangedProxy {
window_id: id,
suggested_size: LogicalSize<f64>,
hidpi_factor: f64,
scale_factor: f64,
},
}

Expand Down
Loading