Skip to content

Commit ee245c5

Browse files
authored
api: make VideoModeHandle into VideoMode
The video mode is generally a static data and not a reference to some video mode. This changes the exclusive fullscreen API to match that an accept a monitor now.
1 parent 5462f27 commit ee245c5

28 files changed

Lines changed: 246 additions & 474 deletions

File tree

src/changelog/unreleased.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ changelog entry.
162162
- On macOS, no longer emit `Focused` upon window creation.
163163
- On iOS, emit more events immediately, instead of queuing them.
164164
- Update `smol_str` to version `0.3`
165+
- Rename `VideoModeHandle` to `VideoMode`, now it only stores plain data.
166+
- Make `Fullscreen::Exclusive` contain `(MonitorHandle, VideoMode)`.
165167

166168
### Removed
167169

src/monitor.rs

Lines changed: 29 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,55 @@
11
//! Types useful for interacting with a user's monitors.
2+
use std::fmt;
23
use std::num::{NonZeroU16, NonZeroU32};
34

45
use crate::dpi::{PhysicalPosition, PhysicalSize};
56
use crate::platform_impl;
67

7-
/// A handle to a fullscreen video mode of a specific monitor.
8+
/// Describes a fullscreen video mode of a monitor.
89
///
9-
/// This can be acquired with [`MonitorHandle::video_modes`].
10-
#[derive(Clone, PartialEq, Eq, Hash)]
11-
pub struct VideoModeHandle {
12-
pub(crate) video_mode: platform_impl::VideoModeHandle,
10+
/// Can be retrieved with [`MonitorHandle::video_modes()`].
11+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
12+
pub struct VideoMode {
13+
pub(crate) size: PhysicalSize<u32>,
14+
pub(crate) bit_depth: Option<NonZeroU16>,
15+
pub(crate) refresh_rate_millihertz: Option<NonZeroU32>,
1316
}
1417

15-
impl std::fmt::Debug for VideoModeHandle {
16-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17-
self.video_mode.fmt(f)
18-
}
19-
}
20-
21-
impl PartialOrd for VideoModeHandle {
22-
fn partial_cmp(&self, other: &VideoModeHandle) -> Option<std::cmp::Ordering> {
23-
Some(self.cmp(other))
24-
}
25-
}
26-
27-
impl Ord for VideoModeHandle {
28-
fn cmp(&self, other: &VideoModeHandle) -> std::cmp::Ordering {
29-
self.monitor().cmp(&other.monitor()).then(
30-
self.size()
31-
.cmp(&other.size())
32-
.then(
33-
self.refresh_rate_millihertz()
34-
.cmp(&other.refresh_rate_millihertz())
35-
.then(self.bit_depth().cmp(&other.bit_depth())),
36-
)
37-
.reverse(),
38-
)
39-
}
40-
}
41-
42-
impl VideoModeHandle {
18+
impl VideoMode {
4319
/// Returns the resolution of this video mode. This **must not** be used to create your
4420
/// rendering surface. Use [`Window::surface_size()`] instead.
4521
///
4622
/// [`Window::surface_size()`]: crate::window::Window::surface_size
47-
#[inline]
4823
pub fn size(&self) -> PhysicalSize<u32> {
49-
self.video_mode.size()
24+
self.size
5025
}
5126

5227
/// Returns the bit depth of this video mode, as in how many bits you have
5328
/// available per color. This is generally 24 bits or 32 bits on modern
5429
/// systems, depending on whether the alpha channel is counted or not.
55-
#[inline]
5630
pub fn bit_depth(&self) -> Option<NonZeroU16> {
57-
self.video_mode.bit_depth()
31+
self.bit_depth
5832
}
5933

6034
/// Returns the refresh rate of this video mode in mHz.
61-
#[inline]
6235
pub fn refresh_rate_millihertz(&self) -> Option<NonZeroU32> {
63-
self.video_mode.refresh_rate_millihertz()
64-
}
65-
66-
/// Returns the monitor that this video mode is valid for. Each monitor has
67-
/// a separate set of valid video modes.
68-
#[inline]
69-
pub fn monitor(&self) -> MonitorHandle {
70-
MonitorHandle { inner: self.video_mode.monitor() }
36+
self.refresh_rate_millihertz
7137
}
7238
}
7339

74-
impl std::fmt::Display for VideoModeHandle {
75-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76-
write!(
77-
f,
78-
"{}x{} {}{}",
79-
self.size().width,
80-
self.size().height,
81-
self.refresh_rate_millihertz().map(|rate| format!("@ {rate} mHz ")).unwrap_or_default(),
82-
self.bit_depth().map(|bit_depth| format!("({bit_depth} bpp)")).unwrap_or_default(),
83-
)
40+
impl fmt::Display for VideoMode {
41+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42+
write!(f, "{}x{}", self.size.width, self.size.height)?;
43+
44+
if let Some(refresh_rate) = self.refresh_rate_millihertz {
45+
write!(f, "@{refresh_rate}mHz")?;
46+
}
47+
48+
if let Some(bit_depth) = self.bit_depth {
49+
write!(f, " ({bit_depth} bpp)")?;
50+
}
51+
52+
Ok(())
8453
}
8554
}
8655

@@ -188,13 +157,13 @@ impl MonitorHandle {
188157

189158
/// Returns the currently active video mode of this monitor.
190159
#[inline]
191-
pub fn current_video_mode(&self) -> Option<VideoModeHandle> {
192-
self.inner.current_video_mode().map(|video_mode| VideoModeHandle { video_mode })
160+
pub fn current_video_mode(&self) -> Option<VideoMode> {
161+
self.inner.current_video_mode()
193162
}
194163

195164
/// Returns all fullscreen video modes supported by this monitor.
196165
#[inline]
197-
pub fn video_modes(&self) -> impl Iterator<Item = VideoModeHandle> {
198-
self.inner.video_modes().map(|video_mode| VideoModeHandle { video_mode })
166+
pub fn video_modes(&self) -> impl Iterator<Item = VideoMode> {
167+
self.inner.video_modes()
199168
}
200169
}

src/platform/ios.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ use std::os::raw::c_void;
107107
#[cfg(feature = "serde")]
108108
use serde::{Deserialize, Serialize};
109109

110-
use crate::monitor::{MonitorHandle, VideoModeHandle};
110+
use crate::monitor::{MonitorHandle, VideoMode};
111111
use crate::window::{Window, WindowAttributes};
112112

113113
/// Additional methods on [`Window`] that are specific to iOS.
@@ -384,10 +384,10 @@ pub trait MonitorHandleExtIOS {
384384
/// [`UIScreen`]: https://developer.apple.com/documentation/uikit/uiscreen?language=objc
385385
fn ui_screen(&self) -> *mut c_void;
386386

387-
/// Returns the preferred [`VideoModeHandle`] for this monitor.
387+
/// Returns the preferred [`VideoMode`] for this monitor.
388388
///
389389
/// This translates to a call to [`-[UIScreen preferredMode]`](https://developer.apple.com/documentation/uikit/uiscreen/1617823-preferredmode?language=objc).
390-
fn preferred_video_mode(&self) -> VideoModeHandle;
390+
fn preferred_video_mode(&self) -> VideoMode;
391391
}
392392

393393
impl MonitorHandleExtIOS for MonitorHandle {
@@ -399,8 +399,8 @@ impl MonitorHandleExtIOS for MonitorHandle {
399399
}
400400

401401
#[inline]
402-
fn preferred_video_mode(&self) -> VideoModeHandle {
403-
VideoModeHandle { video_mode: self.inner.preferred_video_mode() }
402+
fn preferred_video_mode(&self) -> VideoMode {
403+
self.inner.preferred_video_mode()
404404
}
405405
}
406406

src/platform_impl/android/mod.rs

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use std::cell::Cell;
22
use std::hash::Hash;
3-
use std::num::{NonZeroU16, NonZeroU32};
43
use std::sync::atomic::{AtomicBool, Ordering};
54
use std::sync::{Arc, Mutex};
65
use std::time::{Duration, Instant};
@@ -21,7 +20,7 @@ use crate::event_loop::{
2120
EventLoopProxy as CoreEventLoopProxy, EventLoopProxyProvider,
2221
OwnedDisplayHandle as CoreOwnedDisplayHandle,
2322
};
24-
use crate::monitor::MonitorHandle as RootMonitorHandle;
23+
use crate::monitor::{MonitorHandle as RootMonitorHandle, VideoMode};
2524
use crate::platform::pump_events::PumpStatus;
2625
use crate::window::{
2726
self, CursorGrabMode, CustomCursor, CustomCursorSource, Fullscreen, ImePurpose,
@@ -1021,32 +1020,11 @@ impl MonitorHandle {
10211020
unreachable!()
10221021
}
10231022

1024-
pub fn current_video_mode(&self) -> Option<VideoModeHandle> {
1023+
pub fn current_video_mode(&self) -> Option<VideoMode> {
10251024
unreachable!()
10261025
}
10271026

1028-
pub fn video_modes(&self) -> std::iter::Empty<VideoModeHandle> {
1029-
unreachable!()
1030-
}
1031-
}
1032-
1033-
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
1034-
pub struct VideoModeHandle;
1035-
1036-
impl VideoModeHandle {
1037-
pub fn size(&self) -> PhysicalSize<u32> {
1038-
unreachable!()
1039-
}
1040-
1041-
pub fn bit_depth(&self) -> Option<NonZeroU16> {
1042-
unreachable!()
1043-
}
1044-
1045-
pub fn refresh_rate_millihertz(&self) -> Option<NonZeroU32> {
1046-
unreachable!()
1047-
}
1048-
1049-
pub fn monitor(&self) -> MonitorHandle {
1027+
pub fn video_modes(&self) -> std::iter::Empty<VideoMode> {
10501028
unreachable!()
10511029
}
10521030
}

src/platform_impl/apple/appkit/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub(crate) use self::event::{physicalkey_to_scancode, scancode_to_physicalkey, K
1919
pub(crate) use self::event_loop::{
2020
ActiveEventLoop, EventLoop, PlatformSpecificEventLoopAttributes,
2121
};
22-
pub(crate) use self::monitor::{MonitorHandle, VideoModeHandle};
22+
pub(crate) use self::monitor::MonitorHandle;
2323
pub(crate) use self::window::Window;
2424
pub(crate) use self::window_delegate::PlatformSpecificWindowAttributes;
2525
pub(crate) use crate::cursor::OnlyCursorImageSource as PlatformCustomCursorSource;

src/platform_impl/apple/appkit/monitor.rs

Lines changed: 23 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -17,42 +17,33 @@ use objc2_foundation::{ns_string, run_on_main, MainThreadMarker, NSNumber, NSPoi
1717

1818
use super::ffi;
1919
use crate::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize};
20+
use crate::monitor::VideoMode;
2021

2122
#[derive(Clone)]
2223
pub struct VideoModeHandle {
23-
size: PhysicalSize<u32>,
24-
bit_depth: Option<NonZeroU16>,
25-
refresh_rate_millihertz: Option<NonZeroU32>,
24+
pub(crate) mode: VideoMode,
2625
pub(crate) monitor: MonitorHandle,
2726
pub(crate) native_mode: NativeDisplayMode,
2827
}
2928

3029
impl PartialEq for VideoModeHandle {
3130
fn eq(&self, other: &Self) -> bool {
32-
self.size == other.size
33-
&& self.bit_depth == other.bit_depth
34-
&& self.refresh_rate_millihertz == other.refresh_rate_millihertz
35-
&& self.monitor == other.monitor
31+
self.monitor == other.monitor && self.mode == other.mode
3632
}
3733
}
3834

3935
impl Eq for VideoModeHandle {}
4036

4137
impl std::hash::Hash for VideoModeHandle {
4238
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
43-
self.size.hash(state);
44-
self.bit_depth.hash(state);
45-
self.refresh_rate_millihertz.hash(state);
4639
self.monitor.hash(state);
4740
}
4841
}
4942

5043
impl std::fmt::Debug for VideoModeHandle {
5144
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52-
f.debug_struct("VideoModeHandle")
53-
.field("size", &self.size)
54-
.field("bit_depth", &self.bit_depth)
55-
.field("refresh_rate_millihertz", &self.refresh_rate_millihertz)
45+
f.debug_struct("VideoMode")
46+
.field("mode", &self.mode)
5647
.field("monitor", &self.monitor)
5748
.finish()
5849
}
@@ -83,13 +74,14 @@ impl Clone for NativeDisplayMode {
8374
impl VideoModeHandle {
8475
fn new(
8576
monitor: MonitorHandle,
86-
mode: NativeDisplayMode,
77+
native_mode: NativeDisplayMode,
8778
refresh_rate_millihertz: Option<NonZeroU32>,
8879
) -> Self {
8980
unsafe {
90-
let pixel_encoding =
91-
CFString::wrap_under_create_rule(ffi::CGDisplayModeCopyPixelEncoding(mode.0))
92-
.to_string();
81+
let pixel_encoding = CFString::wrap_under_create_rule(
82+
ffi::CGDisplayModeCopyPixelEncoding(native_mode.0),
83+
)
84+
.to_string();
9385
let bit_depth = if pixel_encoding.eq_ignore_ascii_case(ffi::IO32BitDirectPixels) {
9486
32
9587
} else if pixel_encoding.eq_ignore_ascii_case(ffi::IO16BitDirectPixels) {
@@ -100,33 +92,17 @@ impl VideoModeHandle {
10092
unimplemented!()
10193
};
10294

103-
VideoModeHandle {
95+
let mode = VideoMode {
10496
size: PhysicalSize::new(
105-
ffi::CGDisplayModeGetPixelWidth(mode.0) as u32,
106-
ffi::CGDisplayModeGetPixelHeight(mode.0) as u32,
97+
ffi::CGDisplayModeGetPixelWidth(native_mode.0) as u32,
98+
ffi::CGDisplayModeGetPixelHeight(native_mode.0) as u32,
10799
),
108100
refresh_rate_millihertz,
109101
bit_depth: NonZeroU16::new(bit_depth),
110-
monitor: monitor.clone(),
111-
native_mode: mode,
112-
}
113-
}
114-
}
115-
116-
pub fn size(&self) -> PhysicalSize<u32> {
117-
self.size
118-
}
119-
120-
pub fn bit_depth(&self) -> Option<NonZeroU16> {
121-
self.bit_depth
122-
}
123-
124-
pub fn refresh_rate_millihertz(&self) -> Option<NonZeroU32> {
125-
self.refresh_rate_millihertz
126-
}
102+
};
127103

128-
pub fn monitor(&self) -> MonitorHandle {
129-
self.monitor.clone()
104+
VideoModeHandle { mode, monitor: monitor.clone(), native_mode }
105+
}
130106
}
131107
}
132108

@@ -240,13 +216,17 @@ impl MonitorHandle {
240216
refresh_rate_millihertz(self.0, &current_display_mode)
241217
}
242218

243-
pub fn current_video_mode(&self) -> Option<VideoModeHandle> {
219+
pub fn current_video_mode(&self) -> Option<VideoMode> {
244220
let mode = NativeDisplayMode(unsafe { CGDisplayCopyDisplayMode(self.0) } as _);
245221
let refresh_rate_millihertz = refresh_rate_millihertz(self.0, &mode);
246-
Some(VideoModeHandle::new(self.clone(), mode, refresh_rate_millihertz))
222+
Some(VideoModeHandle::new(self.clone(), mode, refresh_rate_millihertz).mode)
223+
}
224+
225+
pub fn video_modes(&self) -> impl Iterator<Item = VideoMode> {
226+
self.video_modes_handles().map(|handle| handle.mode)
247227
}
248228

249-
pub fn video_modes(&self) -> impl Iterator<Item = VideoModeHandle> {
229+
pub(crate) fn video_modes_handles(&self) -> impl Iterator<Item = VideoModeHandle> {
250230
let refresh_rate_millihertz = self.refresh_rate_millihertz();
251231
let monitor = self.clone();
252232

src/platform_impl/apple/appkit/window.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ impl Window {
6464
impl Drop for Window {
6565
fn drop(&mut self) {
6666
// Restore the video mode.
67-
if matches!(self.fullscreen(), Some(Fullscreen::Exclusive(_))) {
67+
if matches!(self.fullscreen(), Some(Fullscreen::Exclusive(_, _))) {
6868
self.set_fullscreen(None);
6969
}
7070

0 commit comments

Comments
 (0)