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
|
|
@ -20,6 +20,7 @@ use crate::event_loop::{
|
|||
ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents,
|
||||
OwnedDisplayHandle as CoreOwnedDisplayHandle,
|
||||
};
|
||||
use crate::monitor::MonitorHandle as CoreMonitorHandle;
|
||||
use crate::platform::pump_events::PumpStatus;
|
||||
use crate::platform_impl::platform::min_timeout;
|
||||
use crate::platform_impl::PlatformCustomCursor;
|
||||
|
|
@ -31,6 +32,7 @@ pub mod sink;
|
|||
use proxy::EventLoopProxy;
|
||||
use sink::EventSink;
|
||||
|
||||
use super::output::MonitorHandle;
|
||||
use super::state::{WindowCompositorUpdate, WinitState};
|
||||
use super::window::state::FrameCallbackState;
|
||||
use super::{logical_to_physical_rounded, WindowId};
|
||||
|
|
@ -621,19 +623,18 @@ impl RootActiveEventLoop for ActiveEventLoop {
|
|||
Ok(Box::new(window))
|
||||
}
|
||||
|
||||
fn available_monitors(&self) -> Box<dyn Iterator<Item = crate::monitor::MonitorHandle>> {
|
||||
fn available_monitors(&self) -> Box<dyn Iterator<Item = CoreMonitorHandle>> {
|
||||
Box::new(
|
||||
self.state
|
||||
.borrow()
|
||||
.output_state
|
||||
.outputs()
|
||||
.map(crate::platform_impl::wayland::output::MonitorHandle::new)
|
||||
.map(crate::platform_impl::MonitorHandle::Wayland)
|
||||
.map(|inner| crate::monitor::MonitorHandle { inner }),
|
||||
.map(MonitorHandle::new)
|
||||
.map(|inner| CoreMonitorHandle(Arc::new(inner))),
|
||||
)
|
||||
}
|
||||
|
||||
fn primary_monitor(&self) -> Option<crate::monitor::MonitorHandle> {
|
||||
fn primary_monitor(&self) -> Option<CoreMonitorHandle> {
|
||||
// There's no primary monitor on Wayland.
|
||||
None
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
//! Winit's Wayland backend.
|
||||
|
||||
pub use event_loop::{ActiveEventLoop, EventLoop};
|
||||
pub use output::MonitorHandle;
|
||||
use sctk::reexports::client::protocol::wl_surface::WlSurface;
|
||||
use sctk::reexports::client::Proxy;
|
||||
pub use window::Window;
|
||||
|
||||
pub(super) use crate::cursor::OnlyCursorImage as CustomCursor;
|
||||
use crate::dpi::{LogicalSize, PhysicalSize};
|
||||
|
|
@ -17,6 +14,9 @@ mod state;
|
|||
mod types;
|
||||
mod window;
|
||||
|
||||
pub use event_loop::{ActiveEventLoop, EventLoop};
|
||||
pub use window::Window;
|
||||
|
||||
/// Get the WindowId out of the surface.
|
||||
#[inline]
|
||||
fn make_wid(surface: &WlSurface) -> WindowId {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use std::borrow::Cow;
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use sctk::output::{Mode, OutputData};
|
||||
|
|
@ -5,7 +6,7 @@ use sctk::reexports::client::protocol::wl_output::WlOutput;
|
|||
use sctk::reexports::client::Proxy;
|
||||
|
||||
use crate::dpi::{LogicalPosition, PhysicalPosition};
|
||||
use crate::monitor::VideoMode;
|
||||
use crate::monitor::{MonitorHandleProvider as CoreMonitorHandle, VideoMode};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MonitorHandle {
|
||||
|
|
@ -17,21 +18,24 @@ impl MonitorHandle {
|
|||
pub(crate) fn new(proxy: WlOutput) -> Self {
|
||||
Self { proxy }
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn name(&self) -> Option<String> {
|
||||
let output_data = self.proxy.data::<OutputData>().unwrap();
|
||||
output_data.with_output_info(|info| info.name.clone())
|
||||
impl CoreMonitorHandle for MonitorHandle {
|
||||
fn id(&self) -> u128 {
|
||||
self.native_id() as _
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn native_identifier(&self) -> u32 {
|
||||
fn native_id(&self) -> u64 {
|
||||
let output_data = self.proxy.data::<OutputData>().unwrap();
|
||||
output_data.with_output_info(|info| info.id)
|
||||
output_data.with_output_info(|info| info.id as u64)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn position(&self) -> Option<PhysicalPosition<i32>> {
|
||||
fn name(&self) -> Option<Cow<'_, str>> {
|
||||
let output_data = self.proxy.data::<OutputData>().unwrap();
|
||||
output_data.with_output_info(|info| info.name.clone().map(Cow::Owned))
|
||||
}
|
||||
|
||||
fn position(&self) -> Option<PhysicalPosition<i32>> {
|
||||
let output_data = self.proxy.data::<OutputData>().unwrap();
|
||||
Some(output_data.with_output_info(|info| {
|
||||
info.logical_position.map_or_else(
|
||||
|
|
@ -47,56 +51,37 @@ impl MonitorHandle {
|
|||
}))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn scale_factor(&self) -> i32 {
|
||||
fn scale_factor(&self) -> f64 {
|
||||
let output_data = self.proxy.data::<OutputData>().unwrap();
|
||||
output_data.scale_factor()
|
||||
output_data.scale_factor() as f64
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn current_video_mode(&self) -> Option<VideoMode> {
|
||||
fn current_video_mode(&self) -> Option<crate::monitor::VideoMode> {
|
||||
let output_data = self.proxy.data::<OutputData>().unwrap();
|
||||
output_data.with_output_info(|info| {
|
||||
let mode = info.modes.iter().find(|mode| mode.current).cloned();
|
||||
|
||||
mode.map(wayland_mode_to_core_mode)
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn video_modes(&self) -> impl Iterator<Item = VideoMode> {
|
||||
fn video_modes(&self) -> Box<dyn Iterator<Item = VideoMode>> {
|
||||
let output_data = self.proxy.data::<OutputData>().unwrap();
|
||||
let modes = output_data.with_output_info(|info| info.modes.clone());
|
||||
modes.into_iter().map(wayland_mode_to_core_mode)
|
||||
|
||||
Box::new(modes.into_iter().map(wayland_mode_to_core_mode))
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for MonitorHandle {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.native_identifier() == other.native_identifier()
|
||||
self.native_id() == other.native_id()
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for MonitorHandle {}
|
||||
|
||||
impl PartialOrd for MonitorHandle {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for MonitorHandle {
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
self.native_identifier().cmp(&other.native_identifier())
|
||||
}
|
||||
}
|
||||
|
||||
impl std::hash::Hash for MonitorHandle {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.native_identifier().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert Wayland's [`Mode`] to winit's [`VideoMode`].
|
||||
/// Convert the wayland's [`Mode`] to winit's [`VideoMode`].
|
||||
fn wayland_mode_to_core_mode(mode: Mode) -> VideoMode {
|
||||
VideoMode {
|
||||
size: (mode.dimensions.0, mode.dimensions.1).into(),
|
||||
|
|
|
|||
|
|
@ -21,12 +21,12 @@ use crate::dpi::{LogicalSize, PhysicalInsets, PhysicalPosition, PhysicalSize, Po
|
|||
use crate::error::{NotSupportedError, RequestError};
|
||||
use crate::event::{Ime, WindowEvent};
|
||||
use crate::event_loop::AsyncRequestSerial;
|
||||
use crate::monitor::MonitorHandle as CoreMonitorHandle;
|
||||
use crate::platform_impl::{Fullscreen, MonitorHandle as PlatformMonitorHandle};
|
||||
use crate::monitor::{Fullscreen, MonitorHandle as CoreMonitorHandle};
|
||||
use crate::platform_impl::wayland::output;
|
||||
use crate::utils::AsAny;
|
||||
use crate::window::{
|
||||
Cursor, CursorGrabMode, Fullscreen as CoreFullscreen, ImePurpose, ResizeDirection, Theme,
|
||||
UserAttentionType, Window as CoreWindow, WindowAttributes, WindowButtons, WindowId,
|
||||
WindowLevel,
|
||||
Cursor, CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType,
|
||||
Window as CoreWindow, WindowAttributes, WindowButtons, WindowId, WindowLevel,
|
||||
};
|
||||
|
||||
pub(crate) mod state;
|
||||
|
|
@ -139,19 +139,20 @@ impl Window {
|
|||
window_state.set_resizable(attributes.resizable);
|
||||
|
||||
// Set startup mode.
|
||||
match attributes.fullscreen.map(Into::into) {
|
||||
match attributes.fullscreen {
|
||||
Some(Fullscreen::Exclusive(..)) => {
|
||||
warn!("`Fullscreen::Exclusive` is ignored on Wayland");
|
||||
},
|
||||
#[cfg_attr(not(x11_platform), allow(clippy::bind_instead_of_map))]
|
||||
Some(Fullscreen::Borderless(monitor)) => {
|
||||
let output = monitor.and_then(|monitor| match monitor {
|
||||
PlatformMonitorHandle::Wayland(monitor) => Some(monitor.proxy),
|
||||
#[cfg(x11_platform)]
|
||||
PlatformMonitorHandle::X(_) => None,
|
||||
let output = monitor.as_ref().and_then(|monitor| {
|
||||
monitor
|
||||
.as_any()
|
||||
.downcast_ref::<output::MonitorHandle>()
|
||||
.map(|handle| &handle.proxy)
|
||||
});
|
||||
|
||||
window.set_fullscreen(output.as_ref())
|
||||
window.set_fullscreen(output)
|
||||
},
|
||||
_ if attributes.maximized => window.set_maximized(),
|
||||
_ => (),
|
||||
|
|
@ -437,26 +438,27 @@ impl CoreWindow for Window {
|
|||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn set_fullscreen(&self, fullscreen: Option<CoreFullscreen>) {
|
||||
fn set_fullscreen(&self, fullscreen: Option<Fullscreen>) {
|
||||
match fullscreen {
|
||||
Some(CoreFullscreen::Exclusive(..)) => {
|
||||
Some(Fullscreen::Exclusive(..)) => {
|
||||
warn!("`Fullscreen::Exclusive` is ignored on Wayland");
|
||||
},
|
||||
#[cfg_attr(not(x11_platform), allow(clippy::bind_instead_of_map))]
|
||||
Some(CoreFullscreen::Borderless(monitor)) => {
|
||||
let output = monitor.and_then(|monitor| match monitor.inner {
|
||||
PlatformMonitorHandle::Wayland(monitor) => Some(monitor.proxy),
|
||||
#[cfg(x11_platform)]
|
||||
PlatformMonitorHandle::X(_) => None,
|
||||
Some(Fullscreen::Borderless(monitor)) => {
|
||||
let output = monitor.as_ref().and_then(|monitor| {
|
||||
monitor
|
||||
.as_any()
|
||||
.downcast_ref::<output::MonitorHandle>()
|
||||
.map(|handle| &handle.proxy)
|
||||
});
|
||||
|
||||
self.window.set_fullscreen(output.as_ref())
|
||||
self.window.set_fullscreen(output)
|
||||
},
|
||||
None => self.window.unset_fullscreen(),
|
||||
}
|
||||
}
|
||||
|
||||
fn fullscreen(&self) -> Option<CoreFullscreen> {
|
||||
fn fullscreen(&self) -> Option<Fullscreen> {
|
||||
let is_fullscreen = self
|
||||
.window_state
|
||||
.lock()
|
||||
|
|
@ -468,7 +470,7 @@ impl CoreWindow for Window {
|
|||
|
||||
if is_fullscreen {
|
||||
let current_monitor = self.current_monitor();
|
||||
Some(CoreFullscreen::Borderless(current_monitor))
|
||||
Some(Fullscreen::Borderless(current_monitor))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
@ -628,8 +630,7 @@ impl CoreWindow for Window {
|
|||
data.outputs()
|
||||
.next()
|
||||
.map(MonitorHandle::new)
|
||||
.map(crate::platform_impl::MonitorHandle::Wayland)
|
||||
.map(|inner| CoreMonitorHandle { inner })
|
||||
.map(|monitor| CoreMonitorHandle(Arc::new(monitor)))
|
||||
}
|
||||
|
||||
fn available_monitors(&self) -> Box<dyn Iterator<Item = CoreMonitorHandle>> {
|
||||
|
|
@ -639,8 +640,7 @@ impl CoreWindow for Window {
|
|||
.unwrap()
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(crate::platform_impl::MonitorHandle::Wayland)
|
||||
.map(|inner| CoreMonitorHandle { inner }),
|
||||
.map(|inner| CoreMonitorHandle(Arc::new(inner))),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue