monitor: refactor MonitorHandle to store dyn object
This also alters `VideoMode` to be a regular object and not reference the `MonitorHandle`, since it's a static data. Given that `VideoMode` set may change during runtime keeping the reference as a some sort of validity may not be idea and propagating errors when changing video mode could be more reliable.
This commit is contained in:
parent
be1baf164c
commit
f1c5afd84e
43 changed files with 726 additions and 826 deletions
|
|
@ -28,7 +28,7 @@ use crate::event_loop::{
|
|||
ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents,
|
||||
EventLoopProxy as CoreEventLoopProxy, OwnedDisplayHandle as CoreOwnedDisplayHandle,
|
||||
};
|
||||
use crate::monitor::MonitorHandle as RootMonitorHandle;
|
||||
use crate::monitor::MonitorHandle as CoreMonitorHandle;
|
||||
use crate::platform_impl::Window;
|
||||
use crate::window::{CustomCursor, CustomCursorSource, Theme, Window as CoreWindow};
|
||||
|
||||
|
|
@ -56,14 +56,18 @@ impl RootActiveEventLoop for ActiveEventLoop {
|
|||
Err(NotSupportedError::new("create_custom_cursor is not supported").into())
|
||||
}
|
||||
|
||||
fn available_monitors(&self) -> Box<dyn Iterator<Item = RootMonitorHandle>> {
|
||||
Box::new(monitor::uiscreens(self.mtm).into_iter().map(|inner| RootMonitorHandle { inner }))
|
||||
fn available_monitors(&self) -> Box<dyn Iterator<Item = CoreMonitorHandle>> {
|
||||
Box::new(
|
||||
monitor::uiscreens(self.mtm)
|
||||
.into_iter()
|
||||
.map(|monitor| CoreMonitorHandle(Arc::new(monitor))),
|
||||
)
|
||||
}
|
||||
|
||||
fn primary_monitor(&self) -> Option<crate::monitor::MonitorHandle> {
|
||||
#[allow(deprecated)]
|
||||
let monitor = MonitorHandle::new(UIScreen::mainScreen(self.mtm));
|
||||
Some(RootMonitorHandle { inner: monitor })
|
||||
Some(CoreMonitorHandle(Arc::new(monitor)))
|
||||
}
|
||||
|
||||
fn listen_device_events(&self, _allowed: DeviceEvents) {}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ pub(crate) use crate::cursor::{
|
|||
NoCustomCursor as PlatformCustomCursor, NoCustomCursor as PlatformCustomCursorSource,
|
||||
};
|
||||
pub(crate) use crate::icon::NoIcon as PlatformIcon;
|
||||
pub(crate) use crate::platform_impl::Fullscreen;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum OsError {}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use objc2_foundation::NSInteger;
|
|||
use objc2_ui_kit::{UIScreen, UIScreenMode};
|
||||
|
||||
use crate::dpi::PhysicalPosition;
|
||||
use crate::monitor::VideoMode;
|
||||
use crate::monitor::{MonitorHandleProvider, VideoMode};
|
||||
|
||||
// Workaround for `MainThreadBound` implementing almost no traits
|
||||
#[derive(Debug)]
|
||||
|
|
@ -76,6 +76,60 @@ pub struct MonitorHandle {
|
|||
ui_screen: MainThreadBound<Retained<UIScreen>>,
|
||||
}
|
||||
|
||||
impl MonitorHandleProvider for MonitorHandle {
|
||||
fn id(&self) -> u128 {
|
||||
self.native_id() as _
|
||||
}
|
||||
|
||||
fn native_id(&self) -> u64 {
|
||||
// SAFETY: Only getting the pointer.
|
||||
let mtm = unsafe { MainThreadMarker::new_unchecked() };
|
||||
Retained::as_ptr(self.ui_screen.get(mtm)) as u64
|
||||
}
|
||||
|
||||
fn name(&self) -> Option<std::borrow::Cow<'_, str>> {
|
||||
run_on_main(|mtm| {
|
||||
#[allow(deprecated)]
|
||||
let main = UIScreen::mainScreen(mtm);
|
||||
if *self.ui_screen(mtm) == main {
|
||||
Some("Primary".into())
|
||||
} else if Some(self.ui_screen(mtm)) == main.mirroredScreen().as_ref() {
|
||||
Some("Mirrored".into())
|
||||
} else {
|
||||
#[allow(deprecated)]
|
||||
UIScreen::screens(mtm)
|
||||
.iter()
|
||||
.position(|rhs| rhs == *self.ui_screen(mtm))
|
||||
.map(|idx| idx.to_string().into())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn position(&self) -> Option<PhysicalPosition<i32>> {
|
||||
let bounds = self.ui_screen.get_on_main(|ui_screen| ui_screen.nativeBounds());
|
||||
Some((bounds.origin.x as f64, bounds.origin.y as f64).into())
|
||||
}
|
||||
|
||||
fn scale_factor(&self) -> f64 {
|
||||
self.ui_screen.get_on_main(|ui_screen| ui_screen.nativeScale()) as f64
|
||||
}
|
||||
|
||||
fn current_video_mode(&self) -> Option<VideoMode> {
|
||||
Some(run_on_main(|mtm| {
|
||||
VideoModeHandle::new(
|
||||
self.ui_screen(mtm).clone(),
|
||||
self.ui_screen(mtm).currentMode().unwrap(),
|
||||
mtm,
|
||||
)
|
||||
.mode
|
||||
}))
|
||||
}
|
||||
|
||||
fn video_modes(&self) -> Box<dyn Iterator<Item = VideoMode>> {
|
||||
Box::new(self.video_modes())
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for MonitorHandle {
|
||||
fn clone(&self) -> Self {
|
||||
run_on_main(|mtm| Self {
|
||||
|
|
@ -137,44 +191,6 @@ impl MonitorHandle {
|
|||
Self { ui_screen: MainThreadBound::new(ui_screen, mtm) }
|
||||
}
|
||||
|
||||
pub fn name(&self) -> Option<String> {
|
||||
run_on_main(|mtm| {
|
||||
#[allow(deprecated)]
|
||||
let main = UIScreen::mainScreen(mtm);
|
||||
if *self.ui_screen(mtm) == main {
|
||||
Some("Primary".to_string())
|
||||
} else if Some(self.ui_screen(mtm)) == main.mirroredScreen().as_ref() {
|
||||
Some("Mirrored".to_string())
|
||||
} else {
|
||||
#[allow(deprecated)]
|
||||
UIScreen::screens(mtm)
|
||||
.iter()
|
||||
.position(|rhs| rhs == *self.ui_screen(mtm))
|
||||
.map(|idx| idx.to_string())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn position(&self) -> Option<PhysicalPosition<i32>> {
|
||||
let bounds = self.ui_screen.get_on_main(|ui_screen| ui_screen.nativeBounds());
|
||||
Some((bounds.origin.x as f64, bounds.origin.y as f64).into())
|
||||
}
|
||||
|
||||
pub fn scale_factor(&self) -> f64 {
|
||||
self.ui_screen.get_on_main(|ui_screen| ui_screen.nativeScale()) as f64
|
||||
}
|
||||
|
||||
pub fn current_video_mode(&self) -> Option<VideoMode> {
|
||||
Some(run_on_main(|mtm| {
|
||||
VideoModeHandle::new(
|
||||
self.ui_screen(mtm).clone(),
|
||||
self.ui_screen(mtm).currentMode().unwrap(),
|
||||
mtm,
|
||||
)
|
||||
.mode
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn video_modes_handles(&self) -> impl Iterator<Item = VideoModeHandle> {
|
||||
run_on_main(|mtm| {
|
||||
let ui_screen = self.ui_screen(mtm);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#![allow(clippy::unnecessary_cast)]
|
||||
|
||||
use std::collections::VecDeque;
|
||||
use std::sync::Arc;
|
||||
|
||||
use dispatch2::MainThreadBound;
|
||||
use objc2::rc::Retained;
|
||||
|
|
@ -16,7 +17,7 @@ use tracing::{debug, warn};
|
|||
use super::app_state::EventWrapper;
|
||||
use super::view::WinitView;
|
||||
use super::view_controller::WinitViewController;
|
||||
use super::{app_state, monitor, ActiveEventLoop, Fullscreen, MonitorHandle};
|
||||
use super::{app_state, monitor, ActiveEventLoop, MonitorHandle};
|
||||
use crate::cursor::Cursor;
|
||||
use crate::dpi::{
|
||||
LogicalInsets, LogicalPosition, LogicalSize, PhysicalInsets, PhysicalPosition, PhysicalSize,
|
||||
|
|
@ -25,7 +26,7 @@ use crate::dpi::{
|
|||
use crate::error::{NotSupportedError, RequestError};
|
||||
use crate::event::WindowEvent;
|
||||
use crate::icon::Icon;
|
||||
use crate::monitor::MonitorHandle as CoreMonitorHandle;
|
||||
use crate::monitor::{Fullscreen, MonitorHandle as CoreMonitorHandle};
|
||||
use crate::platform::ios::{ScreenEdge, StatusBarStyle, ValidOrientations};
|
||||
use crate::window::{
|
||||
CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, Window as CoreWindow,
|
||||
|
|
@ -78,8 +79,9 @@ impl WinitUIWindow {
|
|||
|
||||
this.setRootViewController(Some(view_controller));
|
||||
|
||||
match window_attributes.fullscreen.clone().map(Into::into) {
|
||||
Some(Fullscreen::Exclusive(ref monitor, ref video_mode)) => {
|
||||
match window_attributes.fullscreen.clone() {
|
||||
Some(Fullscreen::Exclusive(monitor, ref video_mode)) => {
|
||||
let monitor = monitor.as_any().downcast_ref::<MonitorHandle>().unwrap();
|
||||
let screen = monitor.ui_screen(mtm);
|
||||
if let Some(video_mode) =
|
||||
monitor.video_modes_handles().find(|mode| &mode.mode == video_mode)
|
||||
|
|
@ -89,6 +91,7 @@ impl WinitUIWindow {
|
|||
this.setScreen(screen);
|
||||
},
|
||||
Some(Fullscreen::Borderless(Some(ref monitor))) => {
|
||||
let monitor = monitor.as_any().downcast_ref::<MonitorHandle>().unwrap();
|
||||
let screen = monitor.ui_screen(mtm);
|
||||
this.setScreen(screen);
|
||||
},
|
||||
|
|
@ -303,6 +306,7 @@ impl Inner {
|
|||
let mtm = MainThreadMarker::new().unwrap();
|
||||
let uiscreen = match &monitor {
|
||||
Some(Fullscreen::Exclusive(monitor, video_mode)) => {
|
||||
let monitor = monitor.as_any().downcast_ref::<MonitorHandle>().unwrap();
|
||||
let uiscreen = monitor.ui_screen(mtm);
|
||||
if let Some(video_mode) =
|
||||
monitor.video_modes_handles().find(|mode| &mode.mode == video_mode)
|
||||
|
|
@ -311,7 +315,9 @@ impl Inner {
|
|||
}
|
||||
uiscreen.clone()
|
||||
},
|
||||
Some(Fullscreen::Borderless(Some(monitor))) => monitor.ui_screen(mtm).clone(),
|
||||
Some(Fullscreen::Borderless(Some(monitor))) => {
|
||||
monitor.as_any().downcast_ref::<MonitorHandle>().unwrap().ui_screen(mtm).clone()
|
||||
},
|
||||
Some(Fullscreen::Borderless(None)) => {
|
||||
self.current_monitor_inner().ui_screen(mtm).clone()
|
||||
},
|
||||
|
|
@ -349,7 +355,7 @@ impl Inner {
|
|||
&& screen_space_bounds.size.width == screen_bounds.size.width
|
||||
&& screen_space_bounds.size.height == screen_bounds.size.height
|
||||
{
|
||||
Some(Fullscreen::Borderless(Some(monitor)))
|
||||
Some(Fullscreen::Borderless(Some(CoreMonitorHandle(Arc::new(monitor)))))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
@ -482,10 +488,13 @@ impl Window {
|
|||
|
||||
#[allow(deprecated)]
|
||||
let main_screen = UIScreen::mainScreen(mtm);
|
||||
let fullscreen = window_attributes.fullscreen.clone().map(Into::into);
|
||||
let fullscreen = window_attributes.fullscreen.clone();
|
||||
let screen = match fullscreen {
|
||||
Some(Fullscreen::Exclusive(ref monitor, _)) => monitor.ui_screen(mtm),
|
||||
Some(Fullscreen::Borderless(Some(ref monitor))) => monitor.ui_screen(mtm),
|
||||
Some(Fullscreen::Exclusive(ref monitor, _))
|
||||
| Some(Fullscreen::Borderless(Some(ref monitor))) => {
|
||||
let monitor = monitor.as_any().downcast_ref::<MonitorHandle>().unwrap();
|
||||
monitor.ui_screen(mtm)
|
||||
},
|
||||
Some(Fullscreen::Borderless(None)) | None => &main_screen,
|
||||
};
|
||||
|
||||
|
|
@ -670,12 +679,12 @@ impl CoreWindow for Window {
|
|||
self.maybe_wait_on_main(|delegate| delegate.is_maximized())
|
||||
}
|
||||
|
||||
fn set_fullscreen(&self, fullscreen: Option<crate::window::Fullscreen>) {
|
||||
self.maybe_wait_on_main(|delegate| delegate.set_fullscreen(fullscreen.map(Into::into)))
|
||||
fn set_fullscreen(&self, fullscreen: Option<Fullscreen>) {
|
||||
self.maybe_wait_on_main(|delegate| delegate.set_fullscreen(fullscreen))
|
||||
}
|
||||
|
||||
fn fullscreen(&self) -> Option<crate::window::Fullscreen> {
|
||||
self.maybe_wait_on_main(|delegate| delegate.fullscreen().map(Into::into))
|
||||
fn fullscreen(&self) -> Option<Fullscreen> {
|
||||
self.maybe_wait_on_main(|delegate| delegate.fullscreen())
|
||||
}
|
||||
|
||||
fn set_decorations(&self, decorations: bool) {
|
||||
|
|
@ -771,21 +780,24 @@ impl CoreWindow for Window {
|
|||
|
||||
fn current_monitor(&self) -> Option<CoreMonitorHandle> {
|
||||
self.maybe_wait_on_main(|delegate| {
|
||||
delegate.current_monitor().map(|inner| CoreMonitorHandle { inner })
|
||||
delegate.current_monitor().map(|monitor| CoreMonitorHandle(Arc::new(monitor)))
|
||||
})
|
||||
}
|
||||
|
||||
fn available_monitors(&self) -> Box<dyn Iterator<Item = CoreMonitorHandle>> {
|
||||
self.maybe_wait_on_main(|delegate| {
|
||||
Box::new(
|
||||
delegate.available_monitors().into_iter().map(|inner| CoreMonitorHandle { inner }),
|
||||
delegate
|
||||
.available_monitors()
|
||||
.into_iter()
|
||||
.map(|monitor| CoreMonitorHandle(Arc::new(monitor))),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
fn primary_monitor(&self) -> Option<CoreMonitorHandle> {
|
||||
self.maybe_wait_on_main(|delegate| {
|
||||
delegate.primary_monitor().map(|inner| CoreMonitorHandle { inner })
|
||||
delegate.primary_monitor().map(|monitor| CoreMonitorHandle(Arc::new(monitor)))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue