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
|
|
@ -21,6 +21,7 @@ use winit::error::RequestError;
|
|||
use winit::event::{DeviceEvent, DeviceId, Ime, MouseButton, MouseScrollDelta, WindowEvent};
|
||||
use winit::event_loop::{ActiveEventLoop, EventLoop};
|
||||
use winit::keyboard::{Key, ModifiersState};
|
||||
use winit::monitor::Fullscreen;
|
||||
#[cfg(macos_platform)]
|
||||
use winit::platform::macos::{
|
||||
ApplicationHandlerExtMacOS, OptionAsAlt, WindowAttributesExtMacOS, WindowExtMacOS,
|
||||
|
|
@ -34,8 +35,8 @@ use winit::platform::web::{ActiveEventLoopExtWeb, CustomCursorExtWeb, WindowAttr
|
|||
#[cfg(x11_platform)]
|
||||
use winit::platform::x11::WindowAttributesExtX11;
|
||||
use winit::window::{
|
||||
Cursor, CursorGrabMode, CustomCursor, CustomCursorSource, Fullscreen, Icon, ResizeDirection,
|
||||
Theme, Window, WindowAttributes, WindowId,
|
||||
Cursor, CursorGrabMode, CustomCursor, CustomCursorSource, Icon, ResizeDirection, Theme, Window,
|
||||
WindowAttributes, WindowId,
|
||||
};
|
||||
|
||||
#[path = "util/tracing.rs"]
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ changelog entry.
|
|||
- On X11, Wayland, Windows and macOS, improved scancode conversions for more obscure key codes.
|
||||
- Add ability to make non-activating window on macOS using `NSPanel` with `NSWindowStyleMask::NonactivatingPanel`.
|
||||
- On Windows, add `IconExtWindows::from_resource_name`.
|
||||
- Implement `MonitorHandleProvider` for `MonitorHandle` to access common monitor API.
|
||||
|
||||
### Changed
|
||||
|
||||
|
|
@ -189,6 +190,7 @@ changelog entry.
|
|||
- On macOS, no longer need control of the main `NSApplication` class (which means you can now override it yourself).
|
||||
- Removed `KeyEventExtModifierSupplement`, and made the fields `text_with_all_modifiers` and
|
||||
`key_without_modifiers` public on `KeyEvent` instead.
|
||||
- Move `window::Fullscreen` to `monitor::Fullscreen`.
|
||||
|
||||
### Removed
|
||||
|
||||
|
|
|
|||
190
src/monitor.rs
190
src/monitor.rs
|
|
@ -1,57 +1,18 @@
|
|||
//! Types useful for interacting with a user's monitors.
|
||||
//!
|
||||
//! If you want to get basic information about a monitor, you can use the
|
||||
//! [`MonitorHandle`] type. This is retrieved from one of the following
|
||||
//! methods, which return an iterator of [`MonitorHandle`]:
|
||||
//! - [`ActiveEventLoop::available_monitors`][crate::event_loop::ActiveEventLoop::available_monitors].
|
||||
//! - [`Window::available_monitors`][crate::window::Window::available_monitors].
|
||||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
use std::num::{NonZeroU16, NonZeroU32};
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::dpi::{PhysicalPosition, PhysicalSize};
|
||||
use crate::platform_impl;
|
||||
|
||||
/// Describes a fullscreen video mode of a monitor.
|
||||
///
|
||||
/// Can be retrieved with [`MonitorHandle::video_modes()`].
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct VideoMode {
|
||||
pub(crate) size: PhysicalSize<u32>,
|
||||
pub(crate) bit_depth: Option<NonZeroU16>,
|
||||
pub(crate) refresh_rate_millihertz: Option<NonZeroU32>,
|
||||
}
|
||||
|
||||
impl VideoMode {
|
||||
/// Returns the resolution of this video mode. This **must not** be used to create your
|
||||
/// rendering surface. Use [`Window::surface_size()`] instead.
|
||||
///
|
||||
/// [`Window::surface_size()`]: crate::window::Window::surface_size
|
||||
pub fn size(&self) -> PhysicalSize<u32> {
|
||||
self.size
|
||||
}
|
||||
|
||||
/// Returns the bit depth of this video mode, as in how many bits you have
|
||||
/// available per color. This is generally 24 bits or 32 bits on modern
|
||||
/// systems, depending on whether the alpha channel is counted or not.
|
||||
pub fn bit_depth(&self) -> Option<NonZeroU16> {
|
||||
self.bit_depth
|
||||
}
|
||||
|
||||
/// Returns the refresh rate of this video mode in mHz.
|
||||
pub fn refresh_rate_millihertz(&self) -> Option<NonZeroU32> {
|
||||
self.refresh_rate_millihertz
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for VideoMode {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}x{}", self.size.width, self.size.height)?;
|
||||
|
||||
if let Some(refresh_rate) = self.refresh_rate_millihertz {
|
||||
write!(f, "@{refresh_rate}mHz")?;
|
||||
}
|
||||
|
||||
if let Some(bit_depth) = self.bit_depth {
|
||||
write!(f, " ({bit_depth} bpp)")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
use crate::utils::AsAny;
|
||||
|
||||
/// Handle to a monitor.
|
||||
///
|
||||
|
|
@ -83,21 +44,48 @@ impl fmt::Display for VideoMode {
|
|||
/// to check.
|
||||
///
|
||||
/// [`Window`]: crate::window::Window
|
||||
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct MonitorHandle {
|
||||
pub(crate) inner: platform_impl::MonitorHandle,
|
||||
}
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MonitorHandle(pub(crate) Arc<dyn MonitorHandleProvider>);
|
||||
|
||||
impl std::fmt::Debug for MonitorHandle {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.inner.fmt(f)
|
||||
impl Deref for MonitorHandle {
|
||||
type Target = dyn MonitorHandleProvider;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.0.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl MonitorHandle {
|
||||
impl PartialEq for MonitorHandle {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.0.as_ref().eq(other.0.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for MonitorHandle {}
|
||||
|
||||
/// Provider of the [`MonitorHandle`].
|
||||
pub trait MonitorHandleProvider: AsAny + fmt::Debug + Send + Sync {
|
||||
/// Identifier for this monitor.
|
||||
///
|
||||
/// The representation of this modifier is not guaranteed and should be used only to compare
|
||||
/// monitors.
|
||||
fn id(&self) -> u128;
|
||||
|
||||
/// Native platform identifier of this monitor.
|
||||
///
|
||||
/// # Platform-specific
|
||||
///
|
||||
/// - **Windows**: This is `HMONITOR`.
|
||||
/// - **macOS**: This is `CGDirectDisplayID`.
|
||||
/// - **iOS**: This is `UIScreen*`.
|
||||
/// - **Wayland**: This is the ID of the `wl_output` device.
|
||||
/// - **X11**: This is the ID of the CRTC.
|
||||
/// - **Web**: This is an internal ID not meant for consumption.
|
||||
fn native_id(&self) -> u64;
|
||||
|
||||
/// Returns a human-readable name of the monitor.
|
||||
///
|
||||
/// Returns `None` if the monitor doesn't exist anymore.
|
||||
/// Returns `None` if the monitor doesn't exist anymore or the name couldn't be obtained.
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
|
|
@ -107,10 +95,7 @@ impl MonitorHandle {
|
|||
doc = "[detailed monitor permissions][crate::platform::web::ActiveEventLoopExtWeb::request_detailed_monitor_permission]."
|
||||
)]
|
||||
#[cfg_attr(not(any(web_platform, docsrs)), doc = "detailed monitor permissions.")]
|
||||
#[inline]
|
||||
pub fn name(&self) -> Option<String> {
|
||||
self.inner.name()
|
||||
}
|
||||
fn name(&self) -> Option<Cow<'_, str>>;
|
||||
|
||||
/// Returns the top-left corner position of the monitor in desktop coordinates.
|
||||
///
|
||||
|
|
@ -126,10 +111,7 @@ impl MonitorHandle {
|
|||
doc = "[detailed monitor permissions][crate::platform::web::ActiveEventLoopExtWeb::request_detailed_monitor_permission]."
|
||||
)]
|
||||
#[cfg_attr(not(any(web_platform, docsrs)), doc = "detailed monitor permissions.")]
|
||||
#[inline]
|
||||
pub fn position(&self) -> Option<PhysicalPosition<i32>> {
|
||||
self.inner.position()
|
||||
}
|
||||
fn position(&self) -> Option<PhysicalPosition<i32>>;
|
||||
|
||||
/// Returns the scale factor of the underlying monitor. To map logical pixels to physical
|
||||
/// pixels and vice versa, use [`Window::scale_factor`].
|
||||
|
|
@ -150,20 +132,72 @@ impl MonitorHandle {
|
|||
///
|
||||
#[rustfmt::skip]
|
||||
/// [`Window::scale_factor`]: crate::window::Window::scale_factor
|
||||
#[inline]
|
||||
pub fn scale_factor(&self) -> f64 {
|
||||
self.inner.scale_factor()
|
||||
}
|
||||
fn scale_factor(&self) -> f64;
|
||||
|
||||
/// Returns the currently active video mode of this monitor.
|
||||
#[inline]
|
||||
pub fn current_video_mode(&self) -> Option<VideoMode> {
|
||||
self.inner.current_video_mode()
|
||||
}
|
||||
fn current_video_mode(&self) -> Option<VideoMode>;
|
||||
|
||||
/// Returns all fullscreen video modes supported by this monitor.
|
||||
#[inline]
|
||||
pub fn video_modes(&self) -> impl Iterator<Item = VideoMode> {
|
||||
self.inner.video_modes()
|
||||
fn video_modes(&self) -> Box<dyn Iterator<Item = VideoMode>>;
|
||||
}
|
||||
|
||||
impl PartialEq for dyn MonitorHandleProvider + '_ {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.id() == other.id()
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for dyn MonitorHandleProvider + '_ {}
|
||||
|
||||
/// Describes a fullscreen video mode of a monitor.
|
||||
///
|
||||
/// Can be acquired with [`MonitorHandleProvider::video_modes`].
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct VideoMode {
|
||||
pub(crate) size: PhysicalSize<u32>,
|
||||
pub(crate) bit_depth: Option<NonZeroU16>,
|
||||
pub(crate) refresh_rate_millihertz: Option<NonZeroU32>,
|
||||
}
|
||||
|
||||
impl VideoMode {
|
||||
/// Returns the resolution of this video mode. This **must not** be used to create your
|
||||
/// rendering surface. Use [`Window::surface_size()`] instead.
|
||||
///
|
||||
/// [`Window::surface_size()`]: crate::window::Window::surface_size
|
||||
pub fn size(&self) -> PhysicalSize<u32> {
|
||||
self.size
|
||||
}
|
||||
|
||||
/// Returns the bit depth of this video mode, as in how many bits you have
|
||||
/// available per color. This is generally 24 bits or 32 bits on modern
|
||||
/// systems, depending on whether the alpha channel is counted or not.
|
||||
pub fn bit_depth(&self) -> Option<NonZeroU16> {
|
||||
self.bit_depth
|
||||
}
|
||||
|
||||
/// Returns the refresh rate of this video mode in mHz.
|
||||
pub fn refresh_rate_millihertz(&self) -> Option<NonZeroU32> {
|
||||
self.refresh_rate_millihertz
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for VideoMode {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}x{} {}{}",
|
||||
self.size.width,
|
||||
self.size.height,
|
||||
self.refresh_rate_millihertz.map(|rate| format!("@ {rate} mHz ")).unwrap_or_default(),
|
||||
self.bit_depth.map(|bit_depth| format!("({bit_depth} bpp)")).unwrap_or_default(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Fullscreen modes.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum Fullscreen {
|
||||
Exclusive(MonitorHandle, VideoMode),
|
||||
|
||||
/// Providing `None` to `Borderless` will fullscreen on the current monitor.
|
||||
Borderless(Option<MonitorHandle>),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ use std::os::raw::c_void;
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::monitor::{MonitorHandle, VideoMode};
|
||||
use crate::platform_impl::MonitorHandle as IosMonitorHandle;
|
||||
use crate::window::{Window, WindowAttributes};
|
||||
|
||||
/// Additional methods on [`Window`] that are specific to iOS.
|
||||
|
|
@ -115,10 +116,11 @@ pub trait WindowExtIOS {
|
|||
/// 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::scale_factor()`].
|
||||
/// this to [`MonitorHandleProvider::scale_factor()`].
|
||||
///
|
||||
/// [`UIWindow`]: https://developer.apple.com/documentation/uikit/uiwindow?language=objc
|
||||
/// [`contentScaleFactor`]: https://developer.apple.com/documentation/uikit/uiview/1622657-contentscalefactor?language=objc
|
||||
/// [`MonitorHandleProvider::scale_factor()`]: crate::monitor::MonitorHandleProvider::scale_factor()
|
||||
fn set_scale_factor(&self, scale_factor: f64);
|
||||
|
||||
/// Sets the valid orientations for the [`Window`].
|
||||
|
|
@ -289,10 +291,11 @@ pub trait WindowAttributesExtIOS {
|
|||
/// 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::scale_factor()`].
|
||||
/// this to [`MonitorHandleProvider::scale_factor()`].
|
||||
///
|
||||
/// [`UIWindow`]: https://developer.apple.com/documentation/uikit/uiwindow?language=objc
|
||||
/// [`contentScaleFactor`]: https://developer.apple.com/documentation/uikit/uiview/1622657-contentscalefactor?language=objc
|
||||
/// [`MonitorHandleProvider::scale_factor()`]: crate::monitor::MonitorHandleProvider::scale_factor()
|
||||
fn with_scale_factor(self, scale_factor: f64) -> Self;
|
||||
|
||||
/// Sets the valid orientations for the [`Window`].
|
||||
|
|
@ -395,12 +398,14 @@ impl MonitorHandleExtIOS for MonitorHandle {
|
|||
fn ui_screen(&self) -> *mut c_void {
|
||||
// SAFETY: The marker is only used to get the pointer of the screen
|
||||
let mtm = unsafe { objc2::MainThreadMarker::new_unchecked() };
|
||||
objc2::rc::Retained::as_ptr(self.inner.ui_screen(mtm)) as *mut c_void
|
||||
let monitor = self.as_any().downcast_ref::<IosMonitorHandle>().unwrap();
|
||||
objc2::rc::Retained::as_ptr(monitor.ui_screen(mtm)) as *mut c_void
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn preferred_video_mode(&self) -> VideoMode {
|
||||
self.inner.preferred_video_mode()
|
||||
let monitor = self.as_any().downcast_ref::<IosMonitorHandle>().unwrap();
|
||||
monitor.preferred_video_mode()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ use serde::{Deserialize, Serialize};
|
|||
use crate::application::ApplicationHandler;
|
||||
use crate::event_loop::{ActiveEventLoop, EventLoopBuilder};
|
||||
use crate::monitor::MonitorHandle;
|
||||
use crate::platform_impl::MonitorHandle as MacOsMonitorHandle;
|
||||
use crate::window::{Window, WindowAttributes, WindowId};
|
||||
|
||||
/// Additional methods on [`Window`] that are specific to MacOS.
|
||||
|
|
@ -499,22 +500,16 @@ impl EventLoopBuilderExtMacOS for EventLoopBuilder {
|
|||
|
||||
/// Additional methods on [`MonitorHandle`] that are specific to MacOS.
|
||||
pub trait MonitorHandleExtMacOS {
|
||||
/// Returns the identifier of the monitor for Cocoa.
|
||||
fn native_id(&self) -> u32;
|
||||
/// Returns a pointer to the NSScreen representing this monitor.
|
||||
fn ns_screen(&self) -> Option<*mut c_void>;
|
||||
}
|
||||
|
||||
impl MonitorHandleExtMacOS for MonitorHandle {
|
||||
#[inline]
|
||||
fn native_id(&self) -> u32 {
|
||||
self.inner.native_identifier()
|
||||
}
|
||||
|
||||
fn ns_screen(&self) -> Option<*mut c_void> {
|
||||
let monitor = self.as_any().downcast_ref::<MacOsMonitorHandle>().unwrap();
|
||||
// SAFETY: We only use the marker to get a pointer
|
||||
let mtm = unsafe { objc2::MainThreadMarker::new_unchecked() };
|
||||
self.inner.ns_screen(mtm).map(|s| objc2::rc::Retained::as_ptr(&s) as _)
|
||||
monitor.ns_screen(mtm).map(|s| objc2::rc::Retained::as_ptr(&s) as _)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
//! * `wayland-csd-adwaita-crossfont`.
|
||||
//! * `wayland-csd-adwaita-notitle`.
|
||||
use crate::event_loop::{ActiveEventLoop, EventLoop, EventLoopBuilder};
|
||||
use crate::monitor::MonitorHandle;
|
||||
pub use crate::window::Theme;
|
||||
use crate::window::{Window as CoreWindow, WindowAttributes};
|
||||
|
||||
|
|
@ -97,16 +96,3 @@ impl WindowAttributesExtWayland for WindowAttributes {
|
|||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Additional methods on `MonitorHandle` that are specific to Wayland.
|
||||
pub trait MonitorHandleExtWayland {
|
||||
/// Returns the inner identifier of the monitor.
|
||||
fn native_id(&self) -> u32;
|
||||
}
|
||||
|
||||
impl MonitorHandleExtWayland for MonitorHandle {
|
||||
#[inline]
|
||||
fn native_id(&self) -> u32 {
|
||||
self.inner.native_identifier()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,8 +58,7 @@ use crate::application::ApplicationHandler;
|
|||
use crate::cursor::CustomCursorSource;
|
||||
use crate::error::NotSupportedError;
|
||||
use crate::event_loop::{ActiveEventLoop, EventLoop};
|
||||
use crate::monitor::MonitorHandle;
|
||||
use crate::platform_impl::PlatformCustomCursorSource;
|
||||
use crate::monitor::MonitorHandleProvider;
|
||||
#[cfg(web_platform)]
|
||||
use crate::platform_impl::{
|
||||
CustomCursorFuture as PlatformCustomCursorFuture,
|
||||
|
|
@ -67,6 +66,7 @@ use crate::platform_impl::{
|
|||
MonitorPermissionFuture as PlatformMonitorPermissionFuture,
|
||||
OrientationLockFuture as PlatformOrientationLockFuture,
|
||||
};
|
||||
use crate::platform_impl::{MonitorHandle as WebMonitorHandle, PlatformCustomCursorSource};
|
||||
use crate::window::{CustomCursor, Window, WindowAttributes};
|
||||
|
||||
#[cfg(not(web_platform))]
|
||||
|
|
@ -253,12 +253,18 @@ pub trait EventLoopExtWeb {
|
|||
///
|
||||
/// [`MonitorHandle`]s don't automatically make use of this after permission is granted. New
|
||||
/// [`MonitorHandle`]s have to be created instead.
|
||||
///
|
||||
/// [`MonitorHandle`]: crate::monitor::MonitorHandle
|
||||
fn request_detailed_monitor_permission(&self) -> MonitorPermissionFuture;
|
||||
|
||||
/// Returns whether the user has given permission to access detailed monitor information.
|
||||
///
|
||||
/// [`MonitorHandle`]s don't automatically make use of detailed monitor information after
|
||||
/// permission is granted. New [`MonitorHandle`]s have to be created instead.
|
||||
///
|
||||
/// [`MonitorHandle`]: crate::monitor::MonitorHandle
|
||||
///
|
||||
/// [`MonitorHandle`]: crate::monitor::MonitorHandle
|
||||
fn has_detailed_monitor_permission(&self) -> HasMonitorPermissionFuture;
|
||||
}
|
||||
|
||||
|
|
@ -348,12 +354,16 @@ pub trait ActiveEventLoopExtWeb {
|
|||
///
|
||||
/// [`MonitorHandle`]s don't automatically make use of this after permission is granted. New
|
||||
/// [`MonitorHandle`]s have to be created instead.
|
||||
///
|
||||
/// [`MonitorHandle`]: crate::monitor::MonitorHandle
|
||||
fn request_detailed_monitor_permission(&self) -> MonitorPermissionFuture;
|
||||
|
||||
/// Returns whether the user has given permission to access detailed monitor information.
|
||||
///
|
||||
/// [`MonitorHandle`]s don't automatically make use of detailed monitor information after
|
||||
/// permission is granted. New [`MonitorHandle`]s have to be created instead.
|
||||
///
|
||||
/// [`MonitorHandle`]: crate::monitor::MonitorHandle
|
||||
fn has_detailed_monitor_permission(&self) -> bool;
|
||||
}
|
||||
|
||||
|
|
@ -650,6 +660,8 @@ impl Future for HasMonitorPermissionFuture {
|
|||
}
|
||||
|
||||
/// Additional methods on [`MonitorHandle`] that are specific to the Web.
|
||||
///
|
||||
/// [`MonitorHandle`]: crate::monitor::MonitorHandle
|
||||
pub trait MonitorHandleExtWeb {
|
||||
/// Returns whether the screen is internal to the device or external.
|
||||
///
|
||||
|
|
@ -677,28 +689,35 @@ pub trait MonitorHandleExtWeb {
|
|||
/// specific monitor.
|
||||
///
|
||||
/// See [`ActiveEventLoopExtWeb::request_detailed_monitor_permission()`].
|
||||
///
|
||||
/// [`MonitorHandle`]: crate::monitor::MonitorHandle
|
||||
fn is_detailed(&self) -> bool;
|
||||
}
|
||||
|
||||
impl MonitorHandleExtWeb for MonitorHandle {
|
||||
impl MonitorHandleExtWeb for dyn MonitorHandleProvider + '_ {
|
||||
fn is_internal(&self) -> Option<bool> {
|
||||
self.inner.is_internal()
|
||||
self.as_any().downcast_ref::<WebMonitorHandle>().unwrap().is_internal()
|
||||
}
|
||||
|
||||
fn orientation(&self) -> OrientationData {
|
||||
self.inner.orientation()
|
||||
self.as_any().downcast_ref::<WebMonitorHandle>().unwrap().orientation()
|
||||
}
|
||||
|
||||
fn request_lock(&self, orientation_lock: OrientationLock) -> OrientationLockFuture {
|
||||
OrientationLockFuture(self.inner.request_lock(orientation_lock))
|
||||
let future = self
|
||||
.as_any()
|
||||
.downcast_ref::<WebMonitorHandle>()
|
||||
.unwrap()
|
||||
.request_lock(orientation_lock);
|
||||
OrientationLockFuture(future)
|
||||
}
|
||||
|
||||
fn unlock(&self) -> Result<(), OrientationLockError> {
|
||||
self.inner.unlock()
|
||||
self.as_any().downcast_ref::<WebMonitorHandle>().unwrap().unlock()
|
||||
}
|
||||
|
||||
fn is_detailed(&self) -> bool {
|
||||
self.inner.is_detailed()
|
||||
self.as_any().downcast_ref::<WebMonitorHandle>().unwrap().is_detailed()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ use windows_sys::Win32::Foundation::HANDLE;
|
|||
use crate::dpi::PhysicalSize;
|
||||
use crate::event::DeviceId;
|
||||
use crate::event_loop::EventLoopBuilder;
|
||||
use crate::monitor::MonitorHandle;
|
||||
use crate::window::{BadIcon, Icon, Window, WindowAttributes};
|
||||
|
||||
/// Window Handle type used by Win32 API
|
||||
|
|
@ -618,27 +617,6 @@ impl WindowAttributesExtWindows for WindowAttributes {
|
|||
}
|
||||
}
|
||||
|
||||
/// Additional methods on `MonitorHandle` that are specific to Windows.
|
||||
pub trait MonitorHandleExtWindows {
|
||||
/// Returns the name of the monitor adapter specific to the Win32 API.
|
||||
fn native_id(&self) -> String;
|
||||
|
||||
/// Returns the handle of the monitor - `HMONITOR`.
|
||||
fn hmonitor(&self) -> HMONITOR;
|
||||
}
|
||||
|
||||
impl MonitorHandleExtWindows for MonitorHandle {
|
||||
#[inline]
|
||||
fn native_id(&self) -> String {
|
||||
self.inner.native_identifier()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn hmonitor(&self) -> HMONITOR {
|
||||
self.inner.hmonitor()
|
||||
}
|
||||
}
|
||||
|
||||
/// Additional methods on `DeviceId` that are specific to Windows.
|
||||
pub trait DeviceIdExtWindows {
|
||||
/// Returns an identifier that persistently refers to this specific device.
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ use serde::{Deserialize, Serialize};
|
|||
|
||||
use crate::dpi::Size;
|
||||
use crate::event_loop::{ActiveEventLoop, EventLoop, EventLoopBuilder};
|
||||
use crate::monitor::MonitorHandle;
|
||||
use crate::window::{Window as CoreWindow, WindowAttributes};
|
||||
|
||||
/// X window type. Maps directly to
|
||||
|
|
@ -240,16 +239,3 @@ impl WindowAttributesExtX11 for WindowAttributes {
|
|||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Additional methods on `MonitorHandle` that are specific to X11.
|
||||
pub trait MonitorHandleExtX11 {
|
||||
/// Returns the inner identifier of the monitor.
|
||||
fn native_id(&self) -> u32;
|
||||
}
|
||||
|
||||
impl MonitorHandleExtX11 for MonitorHandle {
|
||||
#[inline]
|
||||
fn native_id(&self) -> u32 {
|
||||
self.inner.native_identifier()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,12 +20,11 @@ use crate::event_loop::{
|
|||
EventLoopProxy as CoreEventLoopProxy, EventLoopProxyProvider,
|
||||
OwnedDisplayHandle as CoreOwnedDisplayHandle,
|
||||
};
|
||||
use crate::monitor::{MonitorHandle as RootMonitorHandle, VideoMode};
|
||||
use crate::monitor::{Fullscreen, MonitorHandle as CoreMonitorHandle};
|
||||
use crate::platform::pump_events::PumpStatus;
|
||||
use crate::window::{
|
||||
self, CursorGrabMode, CustomCursor, CustomCursorSource, Fullscreen, ImePurpose,
|
||||
ResizeDirection, Theme, Window as CoreWindow, WindowAttributes, WindowButtons, WindowId,
|
||||
WindowLevel,
|
||||
self, CursorGrabMode, CustomCursor, CustomCursorSource, ImePurpose, ResizeDirection, Theme,
|
||||
Window as CoreWindow, WindowAttributes, WindowButtons, WindowId, WindowLevel,
|
||||
};
|
||||
|
||||
mod keycodes;
|
||||
|
|
@ -700,11 +699,11 @@ impl RootActiveEventLoop for ActiveEventLoop {
|
|||
Err(NotSupportedError::new("create_custom_cursor is not supported").into())
|
||||
}
|
||||
|
||||
fn available_monitors(&self) -> Box<dyn Iterator<Item = RootMonitorHandle>> {
|
||||
fn available_monitors(&self) -> Box<dyn Iterator<Item = CoreMonitorHandle>> {
|
||||
Box::new(std::iter::empty())
|
||||
}
|
||||
|
||||
fn primary_monitor(&self) -> Option<RootMonitorHandle> {
|
||||
fn primary_monitor(&self) -> Option<CoreMonitorHandle> {
|
||||
None
|
||||
}
|
||||
|
||||
|
|
@ -824,15 +823,15 @@ impl CoreWindow for Window {
|
|||
GLOBAL_WINDOW
|
||||
}
|
||||
|
||||
fn primary_monitor(&self) -> Option<RootMonitorHandle> {
|
||||
fn primary_monitor(&self) -> Option<CoreMonitorHandle> {
|
||||
None
|
||||
}
|
||||
|
||||
fn available_monitors(&self) -> Box<dyn Iterator<Item = RootMonitorHandle>> {
|
||||
fn available_monitors(&self) -> Box<dyn Iterator<Item = CoreMonitorHandle>> {
|
||||
Box::new(std::iter::empty())
|
||||
}
|
||||
|
||||
fn current_monitor(&self) -> Option<RootMonitorHandle> {
|
||||
fn current_monitor(&self) -> Option<CoreMonitorHandle> {
|
||||
None
|
||||
}
|
||||
|
||||
|
|
@ -1018,31 +1017,6 @@ impl Display for OsError {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct MonitorHandle;
|
||||
|
||||
impl MonitorHandle {
|
||||
pub fn name(&self) -> Option<String> {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
pub fn position(&self) -> Option<PhysicalPosition<i32>> {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
pub fn scale_factor(&self) -> f64 {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
pub fn current_video_mode(&self) -> Option<VideoMode> {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
pub fn video_modes(&self) -> std::iter::Empty<VideoMode> {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
fn screen_size(app: &AndroidApp) -> PhysicalSize<u32> {
|
||||
if let Some(native_window) = app.native_window() {
|
||||
PhysicalSize::new(native_window.width() as _, native_window.height() as _)
|
||||
|
|
|
|||
|
|
@ -29,7 +29,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::macos::ActivationPolicy;
|
||||
use crate::platform::pump_events::PumpStatus;
|
||||
use crate::platform_impl::Window;
|
||||
|
|
@ -114,13 +114,17 @@ impl RootActiveEventLoop for ActiveEventLoop {
|
|||
Ok(RootCustomCursor { inner: CustomCursor::new(source.inner)? })
|
||||
}
|
||||
|
||||
fn available_monitors(&self) -> Box<dyn Iterator<Item = RootMonitorHandle>> {
|
||||
Box::new(monitor::available_monitors().into_iter().map(|inner| RootMonitorHandle { inner }))
|
||||
fn available_monitors(&self) -> Box<dyn Iterator<Item = CoreMonitorHandle>> {
|
||||
Box::new(
|
||||
monitor::available_monitors()
|
||||
.into_iter()
|
||||
.map(|monitor| CoreMonitorHandle(Arc::new(monitor))),
|
||||
)
|
||||
}
|
||||
|
||||
fn primary_monitor(&self) -> Option<crate::monitor::MonitorHandle> {
|
||||
let monitor = monitor::primary_monitor();
|
||||
Some(RootMonitorHandle { inner: monitor })
|
||||
Some(CoreMonitorHandle(Arc::new(monitor)))
|
||||
}
|
||||
|
||||
fn listen_device_events(&self, _allowed: DeviceEvents) {}
|
||||
|
|
|
|||
|
|
@ -24,4 +24,3 @@ pub(crate) use self::window::Window;
|
|||
pub(crate) use self::window_delegate::PlatformSpecificWindowAttributes;
|
||||
pub(crate) use crate::cursor::OnlyCursorImageSource as PlatformCustomCursorSource;
|
||||
pub(crate) use crate::icon::NoIcon as PlatformIcon;
|
||||
pub(crate) use crate::platform_impl::Fullscreen;
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ use objc2_foundation::{ns_string, NSNumber, NSPoint, NSRect};
|
|||
use super::ffi;
|
||||
use super::util::cgerr;
|
||||
use crate::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize};
|
||||
use crate::monitor::VideoMode;
|
||||
use crate::monitor::{MonitorHandleProvider, VideoMode};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct VideoModeHandle {
|
||||
|
|
@ -54,7 +54,7 @@ impl std::hash::Hash for VideoModeHandle {
|
|||
|
||||
impl std::fmt::Debug for VideoModeHandle {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("VideoMode")
|
||||
f.debug_struct("VideoModeHandle")
|
||||
.field("mode", &self.mode)
|
||||
.field("monitor", &self.monitor)
|
||||
.finish()
|
||||
|
|
@ -106,10 +106,113 @@ pub struct MonitorHandle(CGDirectDisplayID);
|
|||
|
||||
impl MonitorHandle {
|
||||
/// Internal comparisons of [`MonitorHandle`]s are done first requesting a UUID for the handle.
|
||||
fn uuid(&self) -> [u8; 16] {
|
||||
fn uuid(&self) -> u128 {
|
||||
let ptr = unsafe { ffi::CGDisplayCreateUUIDFromDisplayID(self.0) };
|
||||
let cf_uuid = unsafe { CFRetained::from_raw(NonNull::new(ptr).unwrap()) };
|
||||
unsafe { CFUUIDGetUUIDBytes(&cf_uuid) }.into()
|
||||
u128::from_ne_bytes(unsafe { CFUUIDGetUUIDBytes(&cf_uuid) }.into())
|
||||
}
|
||||
|
||||
pub fn new(id: CGDirectDisplayID) -> Self {
|
||||
MonitorHandle(id)
|
||||
}
|
||||
|
||||
fn refresh_rate_millihertz(&self) -> Option<NonZeroU32> {
|
||||
let current_display_mode =
|
||||
NativeDisplayMode(unsafe { CGDisplayCopyDisplayMode(self.0) }.unwrap());
|
||||
refresh_rate_millihertz(self.0, ¤t_display_mode)
|
||||
}
|
||||
|
||||
pub fn video_mode_handles(&self) -> impl Iterator<Item = VideoModeHandle> {
|
||||
let refresh_rate_millihertz = self.refresh_rate_millihertz();
|
||||
let monitor = self.clone();
|
||||
|
||||
unsafe {
|
||||
let modes = {
|
||||
let array = CGDisplayCopyAllDisplayModes(self.0, None)
|
||||
.expect("failed to get list of display modes");
|
||||
let array_count = CFArrayGetCount(&array);
|
||||
let modes: Vec<_> = (0..array_count)
|
||||
.map(move |i| {
|
||||
let mode = CFArrayGetValueAtIndex(&array, i) as *mut CGDisplayMode;
|
||||
CFRetained::retain(NonNull::new(mode).unwrap())
|
||||
})
|
||||
.collect();
|
||||
modes
|
||||
};
|
||||
|
||||
modes.into_iter().map(move |mode| {
|
||||
let cg_refresh_rate_hertz = CGDisplayModeGetRefreshRate(Some(&mode)).round() as i64;
|
||||
|
||||
// CGDisplayModeGetRefreshRate returns 0.0 for any display that
|
||||
// isn't a CRT
|
||||
let refresh_rate_millihertz = if cg_refresh_rate_hertz > 0 {
|
||||
NonZeroU32::new((cg_refresh_rate_hertz * 1000) as u32)
|
||||
} else {
|
||||
refresh_rate_millihertz
|
||||
};
|
||||
|
||||
VideoModeHandle::new(
|
||||
monitor.clone(),
|
||||
NativeDisplayMode(mode),
|
||||
refresh_rate_millihertz,
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn ns_screen(&self, mtm: MainThreadMarker) -> Option<Retained<NSScreen>> {
|
||||
let uuid = self.uuid();
|
||||
NSScreen::screens(mtm).into_iter().find(|screen| {
|
||||
let other_native_id = get_display_id(screen);
|
||||
let other = MonitorHandle::new(other_native_id);
|
||||
uuid == other.uuid()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl MonitorHandleProvider for MonitorHandle {
|
||||
fn id(&self) -> u128 {
|
||||
self.uuid()
|
||||
}
|
||||
|
||||
fn native_id(&self) -> u64 {
|
||||
self.0 as _
|
||||
}
|
||||
|
||||
// TODO: Be smarter about this:
|
||||
//
|
||||
// <https://github.com/glfw/glfw/blob/57cbded0760a50b9039ee0cb3f3c14f60145567c/src/cocoa_monitor.m#L44-L126>
|
||||
fn name(&self) -> Option<std::borrow::Cow<'_, str>> {
|
||||
let screen_num = unsafe { CGDisplayModelNumber(self.0) };
|
||||
Some(format!("Monitor #{screen_num}").into())
|
||||
}
|
||||
|
||||
fn position(&self) -> Option<PhysicalPosition<i32>> {
|
||||
// This is already in screen coordinates. If we were using `NSScreen`,
|
||||
// then a conversion would've been needed:
|
||||
// flip_window_screen_coordinates(self.ns_screen(mtm)?.frame())
|
||||
let bounds = unsafe { CGDisplayBounds(self.0) };
|
||||
let position = LogicalPosition::new(bounds.origin.x, bounds.origin.y);
|
||||
Some(position.to_physical(self.scale_factor()))
|
||||
}
|
||||
|
||||
fn scale_factor(&self) -> f64 {
|
||||
run_on_main(|mtm| {
|
||||
match self.ns_screen(mtm) {
|
||||
Some(screen) => screen.backingScaleFactor() as f64,
|
||||
None => 1.0, // default to 1.0 when we can't find the screen
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn current_video_mode(&self) -> Option<VideoMode> {
|
||||
let mode = NativeDisplayMode(unsafe { CGDisplayCopyDisplayMode(self.0) }.unwrap());
|
||||
let refresh_rate_millihertz = refresh_rate_millihertz(self.0, &mode);
|
||||
Some(VideoModeHandle::new(self.clone(), mode, refresh_rate_millihertz).mode)
|
||||
}
|
||||
|
||||
fn video_modes(&self) -> Box<dyn Iterator<Item = VideoMode>> {
|
||||
Box::new(self.video_mode_handles().map(|mode| mode.mode))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -175,113 +278,13 @@ impl fmt::Debug for MonitorHandle {
|
|||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("MonitorHandle")
|
||||
.field("name", &self.name())
|
||||
.field("native_identifier", &self.native_identifier())
|
||||
.field("native_id", &self.native_id())
|
||||
.field("position", &self.position())
|
||||
.field("scale_factor", &self.scale_factor())
|
||||
.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
impl MonitorHandle {
|
||||
pub fn new(id: CGDirectDisplayID) -> Self {
|
||||
MonitorHandle(id)
|
||||
}
|
||||
|
||||
// TODO: Be smarter about this:
|
||||
// <https://github.com/glfw/glfw/blob/57cbded0760a50b9039ee0cb3f3c14f60145567c/src/cocoa_monitor.m#L44-L126>
|
||||
pub fn name(&self) -> Option<String> {
|
||||
let screen_num = unsafe { CGDisplayModelNumber(self.0) };
|
||||
Some(format!("Monitor #{screen_num}"))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn native_identifier(&self) -> u32 {
|
||||
self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn position(&self) -> Option<PhysicalPosition<i32>> {
|
||||
// This is already in screen coordinates. If we were using `NSScreen`,
|
||||
// then a conversion would've been needed:
|
||||
// flip_window_screen_coordinates(self.ns_screen(mtm)?.frame())
|
||||
let bounds = unsafe { CGDisplayBounds(self.0) };
|
||||
let position = LogicalPosition::new(bounds.origin.x, bounds.origin.y);
|
||||
Some(position.to_physical(self.scale_factor()))
|
||||
}
|
||||
|
||||
pub fn scale_factor(&self) -> f64 {
|
||||
run_on_main(|mtm| {
|
||||
match self.ns_screen(mtm) {
|
||||
Some(screen) => screen.backingScaleFactor() as f64,
|
||||
None => 1.0, // default to 1.0 when we can't find the screen
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn refresh_rate_millihertz(&self) -> Option<NonZeroU32> {
|
||||
let current_display_mode =
|
||||
NativeDisplayMode(unsafe { CGDisplayCopyDisplayMode(self.0) }.unwrap());
|
||||
refresh_rate_millihertz(self.0, ¤t_display_mode)
|
||||
}
|
||||
|
||||
pub fn current_video_mode(&self) -> Option<VideoMode> {
|
||||
let mode = NativeDisplayMode(unsafe { CGDisplayCopyDisplayMode(self.0) }.unwrap());
|
||||
let refresh_rate_millihertz = refresh_rate_millihertz(self.0, &mode);
|
||||
Some(VideoModeHandle::new(self.clone(), mode, refresh_rate_millihertz).mode)
|
||||
}
|
||||
|
||||
pub fn video_modes(&self) -> impl Iterator<Item = VideoMode> {
|
||||
self.video_modes_handles().map(|handle| handle.mode)
|
||||
}
|
||||
|
||||
pub(crate) fn video_modes_handles(&self) -> impl Iterator<Item = VideoModeHandle> {
|
||||
let refresh_rate_millihertz = self.refresh_rate_millihertz();
|
||||
let monitor = self.clone();
|
||||
|
||||
unsafe {
|
||||
let modes = {
|
||||
let array = CGDisplayCopyAllDisplayModes(self.0, None)
|
||||
.expect("failed to get list of display modes");
|
||||
let array_count = CFArrayGetCount(&array);
|
||||
let modes: Vec<_> = (0..array_count)
|
||||
.map(move |i| {
|
||||
let mode = CFArrayGetValueAtIndex(&array, i) as *mut CGDisplayMode;
|
||||
CFRetained::retain(NonNull::new(mode).unwrap())
|
||||
})
|
||||
.collect();
|
||||
modes
|
||||
};
|
||||
|
||||
modes.into_iter().map(move |mode| {
|
||||
let cg_refresh_rate_hertz = CGDisplayModeGetRefreshRate(Some(&mode)).round() as i64;
|
||||
|
||||
// CGDisplayModeGetRefreshRate returns 0.0 for any display that
|
||||
// isn't a CRT
|
||||
let refresh_rate_millihertz = if cg_refresh_rate_hertz > 0 {
|
||||
NonZeroU32::new((cg_refresh_rate_hertz * 1000) as u32)
|
||||
} else {
|
||||
refresh_rate_millihertz
|
||||
};
|
||||
|
||||
VideoModeHandle::new(
|
||||
monitor.clone(),
|
||||
NativeDisplayMode(mode),
|
||||
refresh_rate_millihertz,
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn ns_screen(&self, mtm: MainThreadMarker) -> Option<Retained<NSScreen>> {
|
||||
let uuid = self.uuid();
|
||||
NSScreen::screens(mtm).into_iter().find(|screen| {
|
||||
let other_native_id = get_display_id(screen);
|
||||
let other = MonitorHandle::new(other_native_id);
|
||||
uuid == other.uuid()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_display_id(screen: &NSScreen) -> u32 {
|
||||
let key = ns_string!("NSScreenNumber");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#![allow(clippy::unnecessary_cast)]
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use dispatch2::MainThreadBound;
|
||||
use dpi::{Position, Size};
|
||||
use objc2::rc::{autoreleasepool, Retained};
|
||||
|
|
@ -10,10 +12,10 @@ use objc2_foundation::NSObject;
|
|||
use super::event_loop::ActiveEventLoop;
|
||||
use super::window_delegate::WindowDelegate;
|
||||
use crate::error::RequestError;
|
||||
use crate::monitor::MonitorHandle as CoreMonitorHandle;
|
||||
use crate::monitor::{Fullscreen, MonitorHandle as CoreMonitorHandle};
|
||||
use crate::window::{
|
||||
Cursor, Fullscreen, Icon, ImePurpose, Theme, UserAttentionType, Window as CoreWindow,
|
||||
WindowAttributes, WindowButtons, WindowId, WindowLevel,
|
||||
Cursor, Icon, ImePurpose, Theme, UserAttentionType, Window as CoreWindow, WindowAttributes,
|
||||
WindowButtons, WindowId, WindowLevel,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
@ -206,11 +208,11 @@ impl CoreWindow for Window {
|
|||
}
|
||||
|
||||
fn set_fullscreen(&self, fullscreen: Option<Fullscreen>) {
|
||||
self.maybe_wait_on_main(|delegate| delegate.set_fullscreen(fullscreen.map(Into::into)))
|
||||
self.maybe_wait_on_main(|delegate| delegate.set_fullscreen(fullscreen))
|
||||
}
|
||||
|
||||
fn fullscreen(&self) -> Option<Fullscreen> {
|
||||
self.maybe_wait_on_main(|delegate| delegate.fullscreen().map(Into::into))
|
||||
self.maybe_wait_on_main(|delegate| delegate.fullscreen())
|
||||
}
|
||||
|
||||
fn set_decorations(&self, decorations: bool) {
|
||||
|
|
@ -307,21 +309,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)))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,13 +42,14 @@ use super::observer::RunLoop;
|
|||
use super::util::cgerr;
|
||||
use super::view::WinitView;
|
||||
use super::window::{window_id, WinitPanel, WinitWindow};
|
||||
use super::{ffi, Fullscreen, MonitorHandle};
|
||||
use super::{ffi, MonitorHandle};
|
||||
use crate::dpi::{
|
||||
LogicalInsets, LogicalPosition, LogicalSize, PhysicalInsets, PhysicalPosition, PhysicalSize,
|
||||
Position, Size,
|
||||
};
|
||||
use crate::error::{NotSupportedError, RequestError};
|
||||
use crate::event::{SurfaceSizeWriter, WindowEvent};
|
||||
use crate::monitor::{Fullscreen, MonitorHandle as CoreMonitorHandle, MonitorHandleProvider};
|
||||
use crate::platform::macos::{OptionAsAlt, WindowExtMacOS};
|
||||
use crate::window::{
|
||||
Cursor, CursorGrabMode, Icon, ImePurpose, ResizeDirection, Theme, UserAttentionType,
|
||||
|
|
@ -257,7 +258,9 @@ define_class!(
|
|||
// Otherwise, we must've reached fullscreen by the user clicking
|
||||
// on the green fullscreen button. Update state!
|
||||
None => {
|
||||
let current_monitor = self.current_monitor_inner();
|
||||
let current_monitor = self
|
||||
.current_monitor_inner()
|
||||
.map(|monitor| CoreMonitorHandle(Arc::new(monitor)));
|
||||
*fullscreen = Some(Fullscreen::Borderless(current_monitor));
|
||||
},
|
||||
}
|
||||
|
|
@ -550,9 +553,10 @@ fn new_window(
|
|||
mtm: MainThreadMarker,
|
||||
) -> Option<Retained<NSWindow>> {
|
||||
autoreleasepool(|_| {
|
||||
let screen = match attrs.fullscreen.clone().map(Into::into) {
|
||||
let screen = match attrs.fullscreen.clone() {
|
||||
Some(Fullscreen::Borderless(Some(monitor)))
|
||||
| Some(Fullscreen::Exclusive(monitor, _)) => {
|
||||
let monitor = monitor.as_any().downcast_ref::<MonitorHandle>().unwrap();
|
||||
monitor.ns_screen(mtm).or_else(|| NSScreen::mainScreen(mtm))
|
||||
},
|
||||
Some(Fullscreen::Borderless(None)) => NSScreen::mainScreen(mtm),
|
||||
|
|
@ -871,7 +875,7 @@ impl WindowDelegate {
|
|||
delegate.set_cursor(attrs.cursor);
|
||||
|
||||
// Set fullscreen mode after we setup everything
|
||||
delegate.set_fullscreen(attrs.fullscreen.map(Into::into));
|
||||
delegate.set_fullscreen(attrs.fullscreen);
|
||||
|
||||
// Setting the window as key has to happen *after* we set the fullscreen
|
||||
// state, since otherwise we'll briefly see the window at normal size
|
||||
|
|
@ -1455,17 +1459,18 @@ impl WindowDelegate {
|
|||
// does not take a screen parameter, but uses the current screen)
|
||||
if let Some(ref fullscreen) = fullscreen {
|
||||
let new_screen = match fullscreen {
|
||||
Fullscreen::Borderless(Some(monitor)) => monitor.clone(),
|
||||
Fullscreen::Borderless(Some(monitor)) | Fullscreen::Exclusive(monitor, _) => {
|
||||
let monitor = monitor.as_any().downcast_ref::<MonitorHandle>().unwrap();
|
||||
monitor.ns_screen(mtm)
|
||||
},
|
||||
Fullscreen::Borderless(None) => {
|
||||
if let Some(monitor) = self.current_monitor_inner() {
|
||||
monitor
|
||||
monitor.ns_screen(mtm)
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
},
|
||||
Fullscreen::Exclusive(monitor, _) => monitor.clone(),
|
||||
}
|
||||
.ns_screen(mtm)
|
||||
.unwrap();
|
||||
|
||||
let old_screen = self.window().screen().unwrap();
|
||||
|
|
@ -1487,7 +1492,7 @@ impl WindowDelegate {
|
|||
// parameter, which is not consistent with the docs saying that it
|
||||
// takes a `NSDictionary`..
|
||||
|
||||
let display_id = monitor.native_identifier();
|
||||
let display_id = monitor.native_id() as _;
|
||||
|
||||
let mut fade_token = ffi::kCGDisplayFadeReservationInvalidToken;
|
||||
|
||||
|
|
@ -1514,8 +1519,9 @@ impl WindowDelegate {
|
|||
cgerr(CGDisplayCapture(display_id)).unwrap();
|
||||
}
|
||||
|
||||
let monitor = monitor.as_any().downcast_ref::<MonitorHandle>().unwrap();
|
||||
let video_mode =
|
||||
match monitor.video_modes_handles().find(|mode| &mode.mode == video_mode) {
|
||||
match monitor.video_mode_handles().find(|mode| &mode.mode == video_mode) {
|
||||
Some(video_mode) => video_mode,
|
||||
None => return,
|
||||
};
|
||||
|
|
@ -1580,7 +1586,8 @@ impl WindowDelegate {
|
|||
// State is restored by `window_did_exit_fullscreen`
|
||||
toggle_fullscreen(self.window());
|
||||
},
|
||||
(Some(Fullscreen::Exclusive(ref monitor, _)), None) => {
|
||||
(Some(Fullscreen::Exclusive(monitor, _)), None) => {
|
||||
let monitor = monitor.as_any().downcast_ref::<MonitorHandle>().unwrap();
|
||||
restore_and_release_display(monitor);
|
||||
toggle_fullscreen(self.window());
|
||||
},
|
||||
|
|
@ -1603,7 +1610,7 @@ impl WindowDelegate {
|
|||
let window_level = unsafe { CGShieldingWindowLevel() } as NSWindowLevel + 1;
|
||||
self.window().setLevel(window_level);
|
||||
},
|
||||
(Some(Fullscreen::Exclusive(ref monitor, _)), Some(Fullscreen::Borderless(_))) => {
|
||||
(Some(Fullscreen::Exclusive(monitor, _)), Some(Fullscreen::Borderless(_))) => {
|
||||
let presentation_options = self.ivars().save_presentation_opts.get().unwrap_or(
|
||||
NSApplicationPresentationOptions::FullScreen
|
||||
| NSApplicationPresentationOptions::AutoHideDock
|
||||
|
|
@ -1611,6 +1618,7 @@ impl WindowDelegate {
|
|||
);
|
||||
app.setPresentationOptions(presentation_options);
|
||||
|
||||
let monitor = monitor.as_any().downcast_ref::<MonitorHandle>().unwrap();
|
||||
restore_and_release_display(monitor);
|
||||
|
||||
// Restore the normal window level following the Borderless fullscreen
|
||||
|
|
@ -1815,11 +1823,11 @@ fn restore_and_release_display(monitor: &MonitorHandle) {
|
|||
if available_monitors.contains(monitor) {
|
||||
unsafe {
|
||||
CGRestorePermanentDisplayConfiguration();
|
||||
cgerr(CGDisplayRelease(monitor.native_identifier())).unwrap();
|
||||
cgerr(CGDisplayRelease(monitor.native_id() as _)).unwrap();
|
||||
};
|
||||
} else {
|
||||
warn!(
|
||||
monitor = monitor.name(),
|
||||
monitor = monitor.name().map(|name| name.to_string()),
|
||||
"Tried to restore exclusive fullscreen on a monitor that is no longer available"
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,13 +14,11 @@ pub(crate) use self::common::xkb::{physicalkey_to_scancode, scancode_to_physical
|
|||
use self::x11::{XConnection, XError, XNotSupported};
|
||||
use crate::application::ApplicationHandler;
|
||||
pub(crate) use crate::cursor::OnlyCursorImageSource as PlatformCustomCursorSource;
|
||||
use crate::dpi::PhysicalPosition;
|
||||
#[cfg(x11_platform)]
|
||||
use crate::dpi::Size;
|
||||
use crate::error::{EventLoopError, NotSupportedError};
|
||||
use crate::event_loop::ActiveEventLoop;
|
||||
pub(crate) use crate::icon::RgbaIcon as PlatformIcon;
|
||||
use crate::monitor::VideoMode;
|
||||
use crate::platform::pump_events::PumpStatus;
|
||||
#[cfg(x11_platform)]
|
||||
use crate::platform::x11::{WindowType as XWindowType, XlibErrorHook};
|
||||
|
|
@ -104,14 +102,6 @@ impl Default for PlatformSpecificWindowAttributes {
|
|||
pub(crate) static X11_BACKEND: Lazy<Mutex<Result<Arc<XConnection>, XNotSupported>>> =
|
||||
Lazy::new(|| Mutex::new(XConnection::new(Some(x_error_callback)).map(Arc::new)));
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub enum MonitorHandle {
|
||||
#[cfg(x11_platform)]
|
||||
X(x11::MonitorHandle),
|
||||
#[cfg(wayland_platform)]
|
||||
Wayland(wayland::MonitorHandle),
|
||||
}
|
||||
|
||||
/// `x11_or_wayland!(match expr; Enum(foo) => foo.something())`
|
||||
/// expands to the equivalent of
|
||||
/// ```ignore
|
||||
|
|
@ -140,38 +130,6 @@ macro_rules! x11_or_wayland {
|
|||
};
|
||||
}
|
||||
|
||||
impl MonitorHandle {
|
||||
#[inline]
|
||||
pub fn name(&self) -> Option<String> {
|
||||
x11_or_wayland!(match self; MonitorHandle(m) => m.name())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn native_identifier(&self) -> u32 {
|
||||
x11_or_wayland!(match self; MonitorHandle(m) => m.native_identifier())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn position(&self) -> Option<PhysicalPosition<i32>> {
|
||||
x11_or_wayland!(match self; MonitorHandle(m) => m.position())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn scale_factor(&self) -> f64 {
|
||||
x11_or_wayland!(match self; MonitorHandle(m) => m.scale_factor() as _)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn current_video_mode(&self) -> Option<VideoMode> {
|
||||
x11_or_wayland!(match self; MonitorHandle(m) => m.current_video_mode())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn video_modes(&self) -> Box<dyn Iterator<Item = VideoMode>> {
|
||||
x11_or_wayland!(match self; MonitorHandle(m) => Box::new(m.video_modes()))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||
pub(crate) enum PlatformCustomCursor {
|
||||
#[cfg(wayland_platform)]
|
||||
|
|
|
|||
|
|
@ -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))),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ use crate::event_loop::{
|
|||
EventLoopProxy as CoreEventLoopProxy, EventLoopProxyProvider,
|
||||
OwnedDisplayHandle as CoreOwnedDisplayHandle,
|
||||
};
|
||||
use crate::monitor::MonitorHandle as CoreMonitorHandle;
|
||||
use crate::platform::pump_events::PumpStatus;
|
||||
use crate::platform_impl::common::xkb::Context;
|
||||
use crate::platform_impl::platform::min_timeout;
|
||||
|
|
@ -672,23 +673,18 @@ impl RootActiveEventLoop for ActiveEventLoop {
|
|||
})
|
||||
}
|
||||
|
||||
fn available_monitors(&self) -> Box<dyn Iterator<Item = crate::monitor::MonitorHandle>> {
|
||||
fn available_monitors(&self) -> Box<dyn Iterator<Item = CoreMonitorHandle>> {
|
||||
Box::new(
|
||||
self.xconn
|
||||
.available_monitors()
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.map(crate::platform_impl::MonitorHandle::X)
|
||||
.map(|inner| crate::monitor::MonitorHandle { inner }),
|
||||
.map(|monitor| CoreMonitorHandle(Arc::new(monitor))),
|
||||
)
|
||||
}
|
||||
|
||||
fn primary_monitor(&self) -> Option<crate::monitor::MonitorHandle> {
|
||||
self.xconn
|
||||
.primary_monitor()
|
||||
.ok()
|
||||
.map(crate::platform_impl::MonitorHandle::X)
|
||||
.map(|inner| crate::monitor::MonitorHandle { inner })
|
||||
fn primary_monitor(&self) -> Option<CoreMonitorHandle> {
|
||||
self.xconn.primary_monitor().ok().map(|monitor| CoreMonitorHandle(Arc::new(monitor)))
|
||||
}
|
||||
|
||||
fn system_theme(&self) -> Option<Theme> {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use x11rb::protocol::xproto;
|
|||
|
||||
use super::{util, X11Error, XConnection};
|
||||
use crate::dpi::PhysicalPosition;
|
||||
use crate::monitor::VideoMode;
|
||||
use crate::monitor::{MonitorHandleProvider, VideoMode};
|
||||
|
||||
// Used for testing. This should always be committed as false.
|
||||
const DISABLE_MONITOR_LIST_CACHING: bool = false;
|
||||
|
|
@ -23,7 +23,6 @@ pub struct VideoModeHandle {
|
|||
pub(crate) current: bool,
|
||||
pub(crate) mode: VideoMode,
|
||||
pub(crate) native_mode: randr::Mode,
|
||||
pub(crate) monitor: Option<MonitorHandle>,
|
||||
}
|
||||
|
||||
impl From<VideoModeHandle> for VideoMode {
|
||||
|
|
@ -50,6 +49,36 @@ pub struct MonitorHandle {
|
|||
pub(crate) video_modes: Vec<VideoModeHandle>,
|
||||
}
|
||||
|
||||
impl MonitorHandleProvider for MonitorHandle {
|
||||
fn id(&self) -> u128 {
|
||||
self.native_id() as _
|
||||
}
|
||||
|
||||
fn native_id(&self) -> u64 {
|
||||
self.id as _
|
||||
}
|
||||
|
||||
fn name(&self) -> Option<std::borrow::Cow<'_, str>> {
|
||||
Some(self.name.as_str().into())
|
||||
}
|
||||
|
||||
fn position(&self) -> Option<PhysicalPosition<i32>> {
|
||||
Some(self.position.into())
|
||||
}
|
||||
|
||||
fn scale_factor(&self) -> f64 {
|
||||
self.scale_factor
|
||||
}
|
||||
|
||||
fn current_video_mode(&self) -> Option<VideoMode> {
|
||||
self.video_modes.iter().find_map(|mode| mode.current.then(|| mode.clone().into()))
|
||||
}
|
||||
|
||||
fn video_modes(&self) -> Box<dyn Iterator<Item = VideoMode>> {
|
||||
Box::new(self.video_modes.clone().into_iter().map(|mode| mode.into()))
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for MonitorHandle {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.id == other.id
|
||||
|
|
@ -121,34 +150,6 @@ impl MonitorHandle {
|
|||
// Zero is an invalid XID value; no real monitor will have it
|
||||
self.id == 0
|
||||
}
|
||||
|
||||
pub fn name(&self) -> Option<String> {
|
||||
Some(self.name.clone())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn native_identifier(&self) -> u32 {
|
||||
self.id as _
|
||||
}
|
||||
|
||||
pub fn position(&self) -> Option<PhysicalPosition<i32>> {
|
||||
Some(self.position.into())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn scale_factor(&self) -> f64 {
|
||||
self.scale_factor
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn current_video_mode(&self) -> Option<VideoMode> {
|
||||
self.video_modes.iter().find(|mode| mode.current).cloned().map(Into::into)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn video_modes(&self) -> impl Iterator<Item = VideoMode> {
|
||||
self.video_modes.clone().into_iter().map(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
impl XConnection {
|
||||
|
|
|
|||
|
|
@ -83,19 +83,14 @@ impl XConnection {
|
|||
// XRROutputInfo contains an array of mode ids that correspond to
|
||||
// modes in the array in XRRScreenResources
|
||||
.filter(|x| output_modes.iter().any(|id| x.id == *id))
|
||||
.map(|mode| {
|
||||
VideoModeHandle {
|
||||
current: mode.id == current_mode,
|
||||
mode: VideoMode {
|
||||
size: (mode.width as u32, mode.height as u32).into(),
|
||||
refresh_rate_millihertz: monitor::mode_refresh_rate_millihertz(mode),
|
||||
bit_depth: NonZeroU16::new(bit_depth as u16),
|
||||
},
|
||||
native_mode: mode.id,
|
||||
// This is populated in `MonitorHandle::video_modes` as the
|
||||
// video mode is returned to the user
|
||||
monitor: None,
|
||||
}
|
||||
.map(|mode| VideoModeHandle {
|
||||
current: mode.id == current_mode,
|
||||
mode: VideoMode {
|
||||
size: (mode.width as u32, mode.height as u32).into(),
|
||||
refresh_rate_millihertz: monitor::mode_refresh_rate_millihertz(mode),
|
||||
bit_depth: NonZeroU16::new(bit_depth as u16),
|
||||
},
|
||||
native_mode: mode.id,
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use std::borrow::Cow;
|
||||
use std::ffi::CString;
|
||||
use std::mem::replace;
|
||||
use std::num::NonZeroU32;
|
||||
|
|
@ -26,14 +27,15 @@ use crate::dpi::{PhysicalInsets, PhysicalPosition, PhysicalSize, Position, Size}
|
|||
use crate::error::{NotSupportedError, RequestError};
|
||||
use crate::event::{SurfaceSizeWriter, WindowEvent};
|
||||
use crate::event_loop::AsyncRequestSerial;
|
||||
use crate::monitor::{
|
||||
Fullscreen, MonitorHandle as CoreMonitorHandle, MonitorHandleProvider, VideoMode,
|
||||
};
|
||||
use crate::platform::x11::WindowType;
|
||||
use crate::platform_impl::x11::atoms::*;
|
||||
use crate::platform_impl::x11::{
|
||||
xinput_fp1616_to_float, MonitorHandle as X11MonitorHandle, WakeSender, X11Error,
|
||||
};
|
||||
use crate::platform_impl::{
|
||||
common, Fullscreen, MonitorHandle as PlatformMonitorHandle, PlatformCustomCursor, PlatformIcon,
|
||||
};
|
||||
use crate::platform_impl::{common, PlatformCustomCursor, PlatformIcon};
|
||||
use crate::window::{
|
||||
CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, Window as CoreWindow,
|
||||
WindowAttributes, WindowButtons, WindowId, WindowLevel,
|
||||
|
|
@ -179,12 +181,12 @@ impl CoreWindow for Window {
|
|||
self.0.is_maximized()
|
||||
}
|
||||
|
||||
fn set_fullscreen(&self, fullscreen: Option<crate::window::Fullscreen>) {
|
||||
self.0.set_fullscreen(fullscreen.map(Into::into))
|
||||
fn set_fullscreen(&self, fullscreen: Option<Fullscreen>) {
|
||||
self.0.set_fullscreen(fullscreen)
|
||||
}
|
||||
|
||||
fn fullscreen(&self) -> Option<crate::window::Fullscreen> {
|
||||
self.0.fullscreen().map(Into::into)
|
||||
fn fullscreen(&self) -> Option<Fullscreen> {
|
||||
self.0.fullscreen()
|
||||
}
|
||||
|
||||
fn set_decorations(&self, decorations: bool) {
|
||||
|
|
@ -275,28 +277,21 @@ impl CoreWindow for Window {
|
|||
self.0.set_cursor_hittest(hittest)
|
||||
}
|
||||
|
||||
fn current_monitor(&self) -> Option<crate::monitor::MonitorHandle> {
|
||||
self.0
|
||||
.current_monitor()
|
||||
.map(crate::platform_impl::MonitorHandle::X)
|
||||
.map(|inner| crate::monitor::MonitorHandle { inner })
|
||||
fn current_monitor(&self) -> Option<CoreMonitorHandle> {
|
||||
self.0.current_monitor().map(|monitor| CoreMonitorHandle(Arc::new(monitor)))
|
||||
}
|
||||
|
||||
fn available_monitors(&self) -> Box<dyn Iterator<Item = crate::monitor::MonitorHandle>> {
|
||||
fn available_monitors(&self) -> Box<dyn Iterator<Item = CoreMonitorHandle>> {
|
||||
Box::new(
|
||||
self.0
|
||||
.available_monitors()
|
||||
.into_iter()
|
||||
.map(crate::platform_impl::MonitorHandle::X)
|
||||
.map(|inner| crate::monitor::MonitorHandle { inner }),
|
||||
.map(|monitor| CoreMonitorHandle(Arc::new(monitor))),
|
||||
)
|
||||
}
|
||||
|
||||
fn primary_monitor(&self) -> Option<crate::monitor::MonitorHandle> {
|
||||
self.0
|
||||
.primary_monitor()
|
||||
.map(crate::platform_impl::MonitorHandle::X)
|
||||
.map(|inner| crate::monitor::MonitorHandle { inner })
|
||||
fn primary_monitor(&self) -> Option<CoreMonitorHandle> {
|
||||
self.0.primary_monitor().map(|monitor| CoreMonitorHandle(Arc::new(monitor)))
|
||||
}
|
||||
|
||||
fn rwh_06_display_handle(&self) -> &dyn rwh_06::HasDisplayHandle {
|
||||
|
|
@ -862,8 +857,7 @@ impl UnownedWindow {
|
|||
|
||||
if window_attrs.fullscreen.is_some() {
|
||||
if let Some(flusher) =
|
||||
leap!(window
|
||||
.set_fullscreen_inner(window_attrs.fullscreen.clone().map(Into::into)))
|
||||
leap!(window.set_fullscreen_inner(window_attrs.fullscreen.clone()))
|
||||
{
|
||||
flusher.ignore_error()
|
||||
}
|
||||
|
|
@ -1039,7 +1033,7 @@ impl UnownedWindow {
|
|||
// to the desktop video mode as macOS and Windows do
|
||||
(&None, &Some(Fullscreen::Exclusive(ref monitor, _)))
|
||||
| (&Some(Fullscreen::Borderless(_)), &Some(Fullscreen::Exclusive(ref monitor, _))) => {
|
||||
let id = monitor.native_identifier();
|
||||
let id = monitor.native_id() as _;
|
||||
shared_state_lock.desktop_video_mode = Some((
|
||||
id,
|
||||
self.xconn.get_crtc_mode(id).expect("Failed to get desktop video mode"),
|
||||
|
|
@ -1070,19 +1064,22 @@ impl UnownedWindow {
|
|||
flusher.map(Some)
|
||||
},
|
||||
Some(fullscreen) => {
|
||||
let (video_mode, monitor) = match fullscreen {
|
||||
Fullscreen::Exclusive(PlatformMonitorHandle::X(monitor), video_mode) => {
|
||||
(Some(video_mode), monitor.clone())
|
||||
},
|
||||
Fullscreen::Borderless(Some(PlatformMonitorHandle::X(monitor))) => {
|
||||
(None, monitor)
|
||||
},
|
||||
Fullscreen::Borderless(None) => {
|
||||
(None, self.shared_state_lock().last_monitor.clone())
|
||||
},
|
||||
#[cfg(wayland_platform)]
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let (monitor, video_mode): (Cow<'_, X11MonitorHandle>, Option<&VideoMode>) =
|
||||
match &fullscreen {
|
||||
Fullscreen::Exclusive(monitor, video_mode) => {
|
||||
let monitor =
|
||||
monitor.as_any().downcast_ref::<X11MonitorHandle>().unwrap();
|
||||
(Cow::Borrowed(monitor), Some(video_mode))
|
||||
},
|
||||
Fullscreen::Borderless(Some(monitor)) => {
|
||||
let monitor =
|
||||
monitor.as_any().downcast_ref::<X11MonitorHandle>().unwrap();
|
||||
(Cow::Borrowed(monitor), None)
|
||||
},
|
||||
Fullscreen::Borderless(None) => {
|
||||
(Cow::Owned(self.shared_state_lock().last_monitor.clone()), None)
|
||||
},
|
||||
};
|
||||
|
||||
// Don't set fullscreen on an invalid dummy monitor handle
|
||||
if monitor.is_dummy() {
|
||||
|
|
@ -1091,7 +1088,7 @@ impl UnownedWindow {
|
|||
|
||||
if let Some(native_mode) = video_mode.and_then(|requested| {
|
||||
monitor.video_modes.iter().find_map(|mode| {
|
||||
if mode.mode == requested {
|
||||
if &mode.mode == requested {
|
||||
Some(mode.native_mode)
|
||||
} else {
|
||||
None
|
||||
|
|
@ -1124,7 +1121,7 @@ impl UnownedWindow {
|
|||
// this will make someone unhappy, but it's very unusual for
|
||||
// games to want to do this anyway).
|
||||
self.xconn
|
||||
.set_crtc_config(monitor.id, native_mode)
|
||||
.set_crtc_config(monitor.native_id() as _, native_mode)
|
||||
.expect("failed to set video mode");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
use crate::monitor::{MonitorHandle as RootMonitorHandle, VideoMode};
|
||||
use crate::window::Fullscreen as RootFullscreen;
|
||||
|
||||
#[cfg(android_platform)]
|
||||
mod android;
|
||||
#[cfg(target_vendor = "apple")]
|
||||
|
|
@ -29,40 +26,6 @@ use self::web as platform;
|
|||
#[cfg(windows_platform)]
|
||||
use self::windows as platform;
|
||||
|
||||
/// Helper for converting between platform-specific and generic
|
||||
/// [`VideoMode`]/[`MonitorHandle`]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub(crate) enum Fullscreen {
|
||||
Exclusive(MonitorHandle, VideoMode),
|
||||
Borderless(Option<MonitorHandle>),
|
||||
}
|
||||
|
||||
impl From<RootFullscreen> for Fullscreen {
|
||||
fn from(f: RootFullscreen) -> Self {
|
||||
match f {
|
||||
RootFullscreen::Exclusive(handle, video_mode) => {
|
||||
Self::Exclusive(handle.inner, video_mode)
|
||||
},
|
||||
RootFullscreen::Borderless(Some(handle)) => Self::Borderless(Some(handle.inner)),
|
||||
RootFullscreen::Borderless(None) => Self::Borderless(None),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Fullscreen> for RootFullscreen {
|
||||
fn from(f: Fullscreen) -> Self {
|
||||
match f {
|
||||
Fullscreen::Exclusive(inner, video_mode) => {
|
||||
Self::Exclusive(RootMonitorHandle { inner }, video_mode)
|
||||
},
|
||||
Fullscreen::Borderless(Some(inner)) => {
|
||||
Self::Borderless(Some(RootMonitorHandle { inner }))
|
||||
},
|
||||
Fullscreen::Borderless(None) => Self::Borderless(None),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(ios_platform),
|
||||
not(windows_platform),
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::cell::Cell;
|
|||
use std::collections::VecDeque;
|
||||
use std::sync::{mpsc, Arc, Mutex};
|
||||
use std::time::Instant;
|
||||
use std::{mem, slice};
|
||||
use std::{iter, mem, slice};
|
||||
|
||||
use bitflags::bitflags;
|
||||
use orbclient::{
|
||||
|
|
@ -11,9 +11,7 @@ use orbclient::{
|
|||
};
|
||||
use smol_str::SmolStr;
|
||||
|
||||
use super::{
|
||||
MonitorHandle, PlatformSpecificEventLoopAttributes, RedoxSocket, TimeSocket, WindowProperties,
|
||||
};
|
||||
use super::{PlatformSpecificEventLoopAttributes, RedoxSocket, TimeSocket, WindowProperties};
|
||||
use crate::application::ApplicationHandler;
|
||||
use crate::error::{EventLoopError, NotSupportedError, RequestError};
|
||||
use crate::event::{self, Ime, Modifiers, StartCause};
|
||||
|
|
@ -711,9 +709,7 @@ impl RootActiveEventLoop for ActiveEventLoop {
|
|||
}
|
||||
|
||||
fn available_monitors(&self) -> Box<dyn Iterator<Item = crate::monitor::MonitorHandle>> {
|
||||
let mut v = VecDeque::with_capacity(1);
|
||||
v.push_back(crate::monitor::MonitorHandle { inner: MonitorHandle });
|
||||
Box::new(v.into_iter())
|
||||
Box::new(iter::empty())
|
||||
}
|
||||
|
||||
fn system_theme(&self) -> Option<Theme> {
|
||||
|
|
@ -721,7 +717,7 @@ impl RootActiveEventLoop for ActiveEventLoop {
|
|||
}
|
||||
|
||||
fn primary_monitor(&self) -> Option<crate::monitor::MonitorHandle> {
|
||||
Some(crate::monitor::MonitorHandle { inner: MonitorHandle })
|
||||
None
|
||||
}
|
||||
|
||||
fn listen_device_events(&self, _allowed: DeviceEvents) {}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,6 @@ use std::{fmt, str};
|
|||
|
||||
pub(crate) use self::event_loop::{ActiveEventLoop, EventLoop};
|
||||
pub use self::window::Window;
|
||||
use crate::dpi::PhysicalPosition;
|
||||
use crate::monitor::VideoMode;
|
||||
|
||||
mod event_loop;
|
||||
mod window;
|
||||
|
|
@ -133,29 +131,3 @@ impl fmt::Display for WindowProperties<'_> {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
pub struct MonitorHandle;
|
||||
|
||||
impl MonitorHandle {
|
||||
pub fn name(&self) -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn position(&self) -> Option<PhysicalPosition<i32>> {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn scale_factor(&self) -> f64 {
|
||||
1.0 // TODO
|
||||
}
|
||||
|
||||
pub fn current_video_mode(&self) -> Option<VideoMode> {
|
||||
// (it is guaranteed to support 32 bit color though)
|
||||
None
|
||||
}
|
||||
|
||||
pub fn video_modes(&self) -> impl Iterator<Item = VideoMode> {
|
||||
std::iter::empty()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
use std::collections::VecDeque;
|
||||
use std::iter;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use super::event_loop::EventLoopProxy;
|
||||
use super::{ActiveEventLoop, MonitorHandle, RedoxSocket, WindowProperties};
|
||||
use super::{ActiveEventLoop, RedoxSocket, WindowProperties};
|
||||
use crate::cursor::Cursor;
|
||||
use crate::dpi::{PhysicalInsets, PhysicalPosition, PhysicalSize, Position, Size};
|
||||
use crate::error::{NotSupportedError, RequestError};
|
||||
use crate::monitor::MonitorHandle as CoreMonitorHandle;
|
||||
use crate::window::{self, Fullscreen, ImePurpose, Window as CoreWindow, WindowId};
|
||||
use crate::monitor::{Fullscreen, MonitorHandle as CoreMonitorHandle};
|
||||
use crate::window::{self, ImePurpose, Window as CoreWindow, WindowId};
|
||||
|
||||
// These values match the values uses in the `window_new` function in orbital:
|
||||
// https://gitlab.redox-os.org/redox-os/orbital/-/blob/master/src/scheme.rs
|
||||
|
|
@ -33,7 +34,7 @@ impl Window {
|
|||
el: &ActiveEventLoop,
|
||||
attrs: window::WindowAttributes,
|
||||
) -> Result<Self, RequestError> {
|
||||
let scale = MonitorHandle.scale_factor();
|
||||
let scale = 1.;
|
||||
|
||||
let (x, y) = if let Some(pos) = attrs.position {
|
||||
pos.to_physical::<i32>(scale).into()
|
||||
|
|
@ -161,22 +162,22 @@ impl CoreWindow for Window {
|
|||
|
||||
#[inline]
|
||||
fn primary_monitor(&self) -> Option<CoreMonitorHandle> {
|
||||
Some(CoreMonitorHandle { inner: MonitorHandle })
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn available_monitors(&self) -> Box<dyn Iterator<Item = CoreMonitorHandle>> {
|
||||
Box::new(vec![CoreMonitorHandle { inner: MonitorHandle }].into_iter())
|
||||
Box::new(iter::empty())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn current_monitor(&self) -> Option<CoreMonitorHandle> {
|
||||
Some(CoreMonitorHandle { inner: MonitorHandle })
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn scale_factor(&self) -> f64 {
|
||||
MonitorHandle.scale_factor()
|
||||
1.
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ use crate::event_loop::{
|
|||
EventLoopProxy as RootEventLoopProxy, OwnedDisplayHandle as CoreOwnedDisplayHandle,
|
||||
};
|
||||
use crate::keyboard::ModifiersState;
|
||||
use crate::monitor::MonitorHandle as RootMonitorHandle;
|
||||
use crate::monitor::MonitorHandle as CoremMonitorHandle;
|
||||
use crate::platform::web::{CustomCursorFuture, PollStrategy, WaitUntilStrategy};
|
||||
use crate::platform_impl::platform::cursor::CustomCursor;
|
||||
use crate::platform_impl::web::event_loop::proxy::EventLoopProxy;
|
||||
|
|
@ -502,18 +502,18 @@ impl RootActiveEventLoop for ActiveEventLoop {
|
|||
Ok(RootCustomCursor { inner: CustomCursor::new(self, source.inner) })
|
||||
}
|
||||
|
||||
fn available_monitors(&self) -> Box<dyn Iterator<Item = RootMonitorHandle>> {
|
||||
fn available_monitors(&self) -> Box<dyn Iterator<Item = CoremMonitorHandle>> {
|
||||
Box::new(
|
||||
self.runner
|
||||
.monitor()
|
||||
.available_monitors()
|
||||
.into_iter()
|
||||
.map(|inner| RootMonitorHandle { inner }),
|
||||
.map(|monitor| CoremMonitorHandle(Arc::new(monitor))),
|
||||
)
|
||||
}
|
||||
|
||||
fn primary_monitor(&self) -> Option<RootMonitorHandle> {
|
||||
self.runner.monitor().primary_monitor().map(|inner| RootMonitorHandle { inner })
|
||||
fn primary_monitor(&self) -> Option<CoremMonitorHandle> {
|
||||
self.runner.monitor().primary_monitor().map(|monitor| CoremMonitorHandle(Arc::new(monitor)))
|
||||
}
|
||||
|
||||
fn listen_device_events(&self, allowed: DeviceEvents) {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use std::num::NonZeroU16;
|
|||
use std::ops::{Deref, DerefMut};
|
||||
use std::pin::Pin;
|
||||
use std::rc::{Rc, Weak};
|
||||
use std::sync::OnceLock;
|
||||
use std::sync::{Arc, OnceLock};
|
||||
use std::task::{ready, Context, Poll};
|
||||
|
||||
use dpi::LogicalSize;
|
||||
|
|
@ -28,7 +28,7 @@ use super::main_thread::MainThreadMarker;
|
|||
use super::r#async::{Dispatcher, Notified, Notifier};
|
||||
use super::web_sys::{Engine, EventListenerHandle};
|
||||
use crate::dpi::{PhysicalPosition, PhysicalSize};
|
||||
use crate::monitor::{MonitorHandle as RootMonitorHandle, VideoMode};
|
||||
use crate::monitor::{MonitorHandle as CoreMonitorHandle, MonitorHandleProvider, VideoMode};
|
||||
use crate::platform::web::{
|
||||
MonitorPermissionError, Orientation, OrientationData, OrientationLock, OrientationLockError,
|
||||
};
|
||||
|
|
@ -46,30 +46,6 @@ impl MonitorHandle {
|
|||
Self { id, inner: Dispatcher::new(main_thread, inner).0 }
|
||||
}
|
||||
|
||||
pub fn scale_factor(&self) -> f64 {
|
||||
self.inner.queue(|inner| inner.scale_factor())
|
||||
}
|
||||
|
||||
pub fn position(&self) -> Option<PhysicalPosition<i32>> {
|
||||
self.inner.queue(|inner| inner.position())
|
||||
}
|
||||
|
||||
pub fn name(&self) -> Option<String> {
|
||||
self.inner.queue(|inner| inner.name())
|
||||
}
|
||||
|
||||
pub fn current_video_mode(&self) -> Option<VideoMode> {
|
||||
Some(VideoMode {
|
||||
size: self.inner.queue(|inner| inner.size()),
|
||||
bit_depth: self.inner.queue(|inner| inner.bit_depth()),
|
||||
refresh_rate_millihertz: None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn video_modes(&self) -> impl Iterator<Item = VideoMode> {
|
||||
self.current_video_mode().into_iter()
|
||||
}
|
||||
|
||||
pub fn orientation(&self) -> OrientationData {
|
||||
self.inner.queue(|inner| inner.orientation())
|
||||
}
|
||||
|
|
@ -143,6 +119,40 @@ impl MonitorHandle {
|
|||
}
|
||||
}
|
||||
|
||||
impl MonitorHandleProvider for MonitorHandle {
|
||||
fn id(&self) -> u128 {
|
||||
self.native_id() as _
|
||||
}
|
||||
|
||||
fn native_id(&self) -> u64 {
|
||||
self.id.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn scale_factor(&self) -> f64 {
|
||||
self.inner.queue(|inner| inner.scale_factor())
|
||||
}
|
||||
|
||||
fn position(&self) -> Option<PhysicalPosition<i32>> {
|
||||
self.inner.queue(|inner| inner.position())
|
||||
}
|
||||
|
||||
fn name(&self) -> Option<std::borrow::Cow<'_, str>> {
|
||||
self.inner.queue(|inner| inner.name().map(Into::into))
|
||||
}
|
||||
|
||||
fn current_video_mode(&self) -> Option<VideoMode> {
|
||||
Some(VideoMode {
|
||||
size: self.inner.queue(|inner| inner.size()),
|
||||
bit_depth: self.inner.queue(|inner| inner.bit_depth()),
|
||||
refresh_rate_millihertz: None,
|
||||
})
|
||||
}
|
||||
|
||||
fn video_modes(&self) -> Box<dyn Iterator<Item = VideoMode>> {
|
||||
Box::new(self.current_video_mode().into_iter())
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for MonitorHandle {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
let (name, position, scale_factor, orientation, is_internal, is_detailed) =
|
||||
|
|
@ -192,9 +202,9 @@ impl PartialOrd for MonitorHandle {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<MonitorHandle> for RootMonitorHandle {
|
||||
fn from(inner: MonitorHandle) -> Self {
|
||||
RootMonitorHandle { inner }
|
||||
impl From<MonitorHandle> for CoreMonitorHandle {
|
||||
fn from(monitor: MonitorHandle) -> Self {
|
||||
CoreMonitorHandle(Arc::new(monitor))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ use crate::event::{
|
|||
SurfaceSizeWriter, WindowEvent,
|
||||
};
|
||||
use crate::keyboard::{Key, KeyLocation, ModifiersState, PhysicalKey};
|
||||
use crate::platform_impl::Fullscreen;
|
||||
use crate::monitor::Fullscreen;
|
||||
use crate::window::{WindowAttributes, WindowId};
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
|
@ -149,13 +149,7 @@ impl Canvas {
|
|||
}
|
||||
|
||||
if let Some(fullscreen) = attr.fullscreen {
|
||||
fullscreen::request_fullscreen(
|
||||
main_thread,
|
||||
&window,
|
||||
&document,
|
||||
&canvas,
|
||||
fullscreen.into(),
|
||||
);
|
||||
fullscreen::request_fullscreen(main_thread, &window, &document, &canvas, fullscreen);
|
||||
}
|
||||
|
||||
if attr.active {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ use web_sys::{console, Document, Element, HtmlCanvasElement, Window};
|
|||
|
||||
use super::super::main_thread::MainThreadMarker;
|
||||
use super::super::monitor::{self, ScreenDetailed};
|
||||
use crate::platform_impl::Fullscreen;
|
||||
use crate::monitor::Fullscreen;
|
||||
use crate::platform_impl::MonitorHandle;
|
||||
|
||||
pub(crate) fn request_fullscreen(
|
||||
main_thread: MainThreadMarker,
|
||||
|
|
@ -64,6 +65,8 @@ pub(crate) fn request_fullscreen(
|
|||
return;
|
||||
}
|
||||
|
||||
let monitor = monitor.as_any().downcast_ref::<MonitorHandle>().unwrap();
|
||||
|
||||
if let Some(monitor) = monitor.detailed(main_thread) {
|
||||
let options: FullscreenOptions = Object::new().unchecked_into();
|
||||
options.set_screen(&monitor);
|
||||
|
|
|
|||
|
|
@ -13,11 +13,10 @@ use super::{backend, lock, ActiveEventLoop};
|
|||
use crate::dpi::{LogicalInsets, PhysicalInsets, PhysicalPosition, PhysicalSize, Position, Size};
|
||||
use crate::error::{NotSupportedError, RequestError};
|
||||
use crate::icon::Icon;
|
||||
use crate::monitor::MonitorHandle as RootMonitorHandle;
|
||||
use crate::monitor::{Fullscreen, MonitorHandle as CoremMonitorHandle};
|
||||
use crate::window::{
|
||||
Cursor, CursorGrabMode, Fullscreen as RootFullscreen, ImePurpose, ResizeDirection, Theme,
|
||||
UserAttentionType, Window as RootWindow, WindowAttributes, WindowButtons, WindowId,
|
||||
WindowLevel,
|
||||
Cursor, CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType,
|
||||
Window as RootWindow, WindowAttributes, WindowButtons, WindowId, WindowLevel,
|
||||
};
|
||||
|
||||
pub struct Window {
|
||||
|
|
@ -270,20 +269,20 @@ impl RootWindow for Window {
|
|||
false
|
||||
}
|
||||
|
||||
fn set_fullscreen(&self, fullscreen: Option<RootFullscreen>) {
|
||||
fn set_fullscreen(&self, fullscreen: Option<Fullscreen>) {
|
||||
self.inner.dispatch(move |inner| {
|
||||
if let Some(fullscreen) = fullscreen {
|
||||
inner.canvas.request_fullscreen(fullscreen.into());
|
||||
inner.canvas.request_fullscreen(fullscreen);
|
||||
} else {
|
||||
inner.canvas.exit_fullscreen()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn fullscreen(&self) -> Option<RootFullscreen> {
|
||||
fn fullscreen(&self) -> Option<Fullscreen> {
|
||||
self.inner.queue(|inner| {
|
||||
if inner.canvas.is_fullscreen() {
|
||||
Some(RootFullscreen::Borderless(None))
|
||||
Some(Fullscreen::Borderless(None))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
@ -396,21 +395,21 @@ impl RootWindow for Window {
|
|||
Err(NotSupportedError::new("set_cursor_hittest is not supported").into())
|
||||
}
|
||||
|
||||
fn current_monitor(&self) -> Option<RootMonitorHandle> {
|
||||
fn current_monitor(&self) -> Option<CoremMonitorHandle> {
|
||||
Some(self.inner.queue(|inner| inner.monitor.current_monitor()).into())
|
||||
}
|
||||
|
||||
fn available_monitors(&self) -> Box<dyn Iterator<Item = RootMonitorHandle>> {
|
||||
fn available_monitors(&self) -> Box<dyn Iterator<Item = CoremMonitorHandle>> {
|
||||
Box::new(
|
||||
self.inner
|
||||
.queue(|inner| inner.monitor.available_monitors())
|
||||
.into_iter()
|
||||
.map(RootMonitorHandle::from),
|
||||
.map(CoremMonitorHandle::from),
|
||||
)
|
||||
}
|
||||
|
||||
fn primary_monitor(&self) -> Option<RootMonitorHandle> {
|
||||
self.inner.queue(|inner| inner.monitor.primary_monitor()).map(RootMonitorHandle::from)
|
||||
fn primary_monitor(&self) -> Option<CoremMonitorHandle> {
|
||||
self.inner.queue(|inner| inner.monitor.primary_monitor()).map(CoremMonitorHandle::from)
|
||||
}
|
||||
|
||||
fn rwh_06_display_handle(&self) -> &dyn rwh_06::HasDisplayHandle {
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ use crate::event_loop::{
|
|||
OwnedDisplayHandle as CoreOwnedDisplayHandle,
|
||||
};
|
||||
use crate::keyboard::ModifiersState;
|
||||
use crate::monitor::MonitorHandle as RootMonitorHandle;
|
||||
use crate::monitor::{Fullscreen, MonitorHandle as CoreMonitorHandle};
|
||||
use crate::platform::pump_events::PumpStatus;
|
||||
use crate::platform_impl::platform::dark_mode::try_theme;
|
||||
use crate::platform_impl::platform::dpi::{become_dpi_aware, dpi_to_scale_factor};
|
||||
|
|
@ -89,7 +89,7 @@ use crate::platform_impl::platform::window::InitData;
|
|||
use crate::platform_impl::platform::window_state::{
|
||||
CursorFlags, ImeState, WindowFlags, WindowState,
|
||||
};
|
||||
use crate::platform_impl::platform::{raw_input, util, wrap_device_id, Fullscreen};
|
||||
use crate::platform_impl::platform::{raw_input, util, wrap_device_id};
|
||||
use crate::platform_impl::Window;
|
||||
use crate::utils::Lazy;
|
||||
use crate::window::{
|
||||
|
|
@ -425,16 +425,16 @@ impl RootActiveEventLoop for ActiveEventLoop {
|
|||
Ok(RootCustomCursor { inner: WinCursor::new(&source.inner.0)? })
|
||||
}
|
||||
|
||||
fn available_monitors(&self) -> Box<dyn Iterator<Item = crate::monitor::MonitorHandle>> {
|
||||
fn available_monitors(&self) -> Box<dyn Iterator<Item = CoreMonitorHandle>> {
|
||||
Box::new(
|
||||
monitor::available_monitors()
|
||||
.into_iter()
|
||||
.map(|inner| crate::monitor::MonitorHandle { inner }),
|
||||
.map(|monitor| CoreMonitorHandle(Arc::new(monitor))),
|
||||
)
|
||||
}
|
||||
|
||||
fn primary_monitor(&self) -> Option<crate::monitor::MonitorHandle> {
|
||||
Some(RootMonitorHandle { inner: monitor::primary_monitor() })
|
||||
fn primary_monitor(&self) -> Option<CoreMonitorHandle> {
|
||||
Some(CoreMonitorHandle(Arc::new(monitor::primary_monitor())))
|
||||
}
|
||||
|
||||
fn exiting(&self) -> bool {
|
||||
|
|
@ -1221,7 +1221,7 @@ unsafe fn public_window_callback_inner(
|
|||
if !new_monitor.is_null()
|
||||
&& fullscreen_monitor
|
||||
.as_ref()
|
||||
.map(|monitor| new_monitor != monitor.hmonitor())
|
||||
.map(|monitor| new_monitor != monitor.native_id() as _)
|
||||
.unwrap_or(true)
|
||||
{
|
||||
if let Ok(new_monitor_info) = monitor::get_monitor_info(new_monitor)
|
||||
|
|
@ -1232,12 +1232,15 @@ unsafe fn public_window_callback_inner(
|
|||
window_pos.cx = new_monitor_rect.right - new_monitor_rect.left;
|
||||
window_pos.cy = new_monitor_rect.bottom - new_monitor_rect.top;
|
||||
}
|
||||
*fullscreen_monitor = Some(MonitorHandle::new(new_monitor));
|
||||
*fullscreen_monitor = Some(CoreMonitorHandle(Arc::new(
|
||||
MonitorHandle::new(new_monitor),
|
||||
)));
|
||||
}
|
||||
},
|
||||
Fullscreen::Exclusive(ref monitor, _) => {
|
||||
let old_monitor = monitor.hmonitor();
|
||||
if let Ok(old_monitor_info) = monitor::get_monitor_info(old_monitor) {
|
||||
Fullscreen::Exclusive(monitor, _) => {
|
||||
if let Ok(old_monitor_info) =
|
||||
monitor::get_monitor_info(monitor.native_id() as _)
|
||||
{
|
||||
let old_monitor_rect = old_monitor_info.monitorInfo.rcMonitor;
|
||||
window_pos.x = old_monitor_rect.left;
|
||||
window_pos.y = old_monitor_rect.top;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ pub(crate) use crate::cursor::OnlyCursorImageSource as PlatformCustomCursorSourc
|
|||
use crate::event::DeviceId;
|
||||
use crate::icon::Icon;
|
||||
use crate::platform::windows::{BackdropType, Color, CornerPreference};
|
||||
use crate::platform_impl::Fullscreen;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct PlatformSpecificWindowAttributes {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::collections::{HashSet, VecDeque};
|
||||
use std::hash::Hash;
|
||||
use std::num::{NonZeroU16, NonZeroU32};
|
||||
use std::{io, mem, ptr};
|
||||
use std::{io, iter, mem, ptr};
|
||||
|
||||
use windows_sys::Win32::Foundation::{BOOL, HWND, LPARAM, POINT, RECT};
|
||||
use windows_sys::Win32::Graphics::Gdi::{
|
||||
|
|
@ -13,7 +13,7 @@ use windows_sys::Win32::Graphics::Gdi::{
|
|||
|
||||
use super::util::decode_wide;
|
||||
use crate::dpi::{PhysicalPosition, PhysicalSize};
|
||||
use crate::monitor::VideoMode;
|
||||
use crate::monitor::{MonitorHandleProvider, VideoMode};
|
||||
use crate::platform_impl::platform::dpi::{dpi_to_scale_factor, get_monitor_dpi};
|
||||
use crate::platform_impl::platform::util::has_flag;
|
||||
|
||||
|
|
@ -60,14 +60,6 @@ impl VideoModeHandle {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
|
||||
pub struct MonitorHandle(HMONITOR);
|
||||
|
||||
// Send and Sync are not implemented for HMONITOR, we have to wrap it and implement them manually.
|
||||
|
||||
unsafe impl Send for MonitorHandle {}
|
||||
unsafe impl Sync for MonitorHandle {}
|
||||
|
||||
unsafe extern "system" fn monitor_enum_proc(
|
||||
hmonitor: HMONITOR,
|
||||
_hdc: HDC,
|
||||
|
|
@ -116,27 +108,19 @@ pub(crate) fn get_monitor_info(hmonitor: HMONITOR) -> Result<MONITORINFOEXW, io:
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
|
||||
pub struct MonitorHandle(HMONITOR);
|
||||
|
||||
// Send and Sync are not implemented for HMONITOR, we have to wrap it and implement them manually.
|
||||
|
||||
unsafe impl Send for MonitorHandle {}
|
||||
unsafe impl Sync for MonitorHandle {}
|
||||
|
||||
impl MonitorHandle {
|
||||
pub(crate) fn new(hmonitor: HMONITOR) -> Self {
|
||||
MonitorHandle(hmonitor)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn name(&self) -> Option<String> {
|
||||
let monitor_info = get_monitor_info(self.0).unwrap();
|
||||
Some(decode_wide(&monitor_info.szDevice).to_string_lossy().to_string())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn native_identifier(&self) -> String {
|
||||
self.name().unwrap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn hmonitor(&self) -> HMONITOR {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub(crate) fn size(&self) -> PhysicalSize<u32> {
|
||||
let rc_monitor = get_monitor_info(self.0).unwrap().monitorInfo.rcMonitor;
|
||||
PhysicalSize {
|
||||
|
|
@ -145,39 +129,7 @@ impl MonitorHandle {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn position(&self) -> Option<PhysicalPosition<i32>> {
|
||||
get_monitor_info(self.0)
|
||||
.map(|info| {
|
||||
let rc_monitor = info.monitorInfo.rcMonitor;
|
||||
PhysicalPosition { x: rc_monitor.left, y: rc_monitor.top }
|
||||
})
|
||||
.ok()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn scale_factor(&self) -> f64 {
|
||||
dpi_to_scale_factor(get_monitor_dpi(self.0).unwrap_or(96))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn current_video_mode(&self) -> Option<VideoMode> {
|
||||
let monitor_info = get_monitor_info(self.0).ok()?;
|
||||
let device_name = monitor_info.szDevice.as_ptr();
|
||||
unsafe {
|
||||
let mut mode: DEVMODEW = mem::zeroed();
|
||||
mode.dmSize = mem::size_of_val(&mode) as u16;
|
||||
if EnumDisplaySettingsExW(device_name, ENUM_CURRENT_SETTINGS, &mut mode, 0)
|
||||
== false.into()
|
||||
{
|
||||
None
|
||||
} else {
|
||||
Some(VideoModeHandle::new(mode).mode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn video_mode_handles(&self) -> impl Iterator<Item = VideoModeHandle> {
|
||||
pub(crate) fn video_mode_handles(&self) -> Box<dyn Iterator<Item = VideoModeHandle>> {
|
||||
// EnumDisplaySettingsExW can return duplicate values (or some of the
|
||||
// fields are probably changing, but we aren't looking at those fields
|
||||
// anyway), so we're using a BTreeSet deduplicate
|
||||
|
|
@ -187,7 +139,7 @@ impl MonitorHandle {
|
|||
Ok(monitor_info) => monitor_info,
|
||||
Err(error) => {
|
||||
tracing::warn!("Error from get_monitor_info: {error}");
|
||||
return modes.into_iter();
|
||||
return Box::new(iter::empty());
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -206,10 +158,54 @@ impl MonitorHandle {
|
|||
i += 1;
|
||||
}
|
||||
|
||||
modes.into_iter()
|
||||
}
|
||||
|
||||
pub fn video_modes(&self) -> impl Iterator<Item = VideoMode> {
|
||||
self.video_mode_handles().map(|mode| mode.mode)
|
||||
Box::new(modes.into_iter())
|
||||
}
|
||||
}
|
||||
|
||||
impl MonitorHandleProvider for MonitorHandle {
|
||||
fn id(&self) -> u128 {
|
||||
self.native_id() as _
|
||||
}
|
||||
|
||||
fn native_id(&self) -> u64 {
|
||||
self.0 as _
|
||||
}
|
||||
|
||||
fn name(&self) -> Option<std::borrow::Cow<'_, str>> {
|
||||
let monitor_info = get_monitor_info(self.0).unwrap();
|
||||
Some(decode_wide(&monitor_info.szDevice).to_string_lossy().to_string().into())
|
||||
}
|
||||
|
||||
fn position(&self) -> Option<PhysicalPosition<i32>> {
|
||||
get_monitor_info(self.0)
|
||||
.map(|info| {
|
||||
let rc_monitor = info.monitorInfo.rcMonitor;
|
||||
PhysicalPosition { x: rc_monitor.left, y: rc_monitor.top }
|
||||
})
|
||||
.ok()
|
||||
}
|
||||
|
||||
fn scale_factor(&self) -> f64 {
|
||||
dpi_to_scale_factor(get_monitor_dpi(self.0).unwrap_or(96))
|
||||
}
|
||||
|
||||
fn current_video_mode(&self) -> Option<crate::monitor::VideoMode> {
|
||||
let monitor_info = get_monitor_info(self.0).ok()?;
|
||||
let device_name = monitor_info.szDevice.as_ptr();
|
||||
unsafe {
|
||||
let mut mode: DEVMODEW = mem::zeroed();
|
||||
mode.dmSize = mem::size_of_val(&mode) as u16;
|
||||
if EnumDisplaySettingsExW(device_name, ENUM_CURRENT_SETTINGS, &mut mode, 0)
|
||||
== false.into()
|
||||
{
|
||||
None
|
||||
} else {
|
||||
Some(VideoModeHandle::new(mode).mode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn video_modes(&self) -> Box<dyn Iterator<Item = VideoMode>> {
|
||||
Box::new(self.video_mode_handles().map(|mode| mode.mode))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#![cfg(windows_platform)]
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::cell::Cell;
|
||||
use std::ffi::c_void;
|
||||
use std::mem::{self, MaybeUninit};
|
||||
|
|
@ -46,11 +47,12 @@ use windows_sys::Win32::UI::WindowsAndMessaging::{
|
|||
WDA_EXCLUDEFROMCAPTURE, WDA_NONE, WM_NCLBUTTONDOWN, WM_SYSCOMMAND, WNDCLASSEXW,
|
||||
};
|
||||
|
||||
use super::MonitorHandle;
|
||||
use crate::cursor::Cursor;
|
||||
use crate::dpi::{PhysicalInsets, PhysicalPosition, PhysicalSize, Position, Size};
|
||||
use crate::error::{NotSupportedError, RequestError};
|
||||
use crate::icon::Icon;
|
||||
use crate::monitor::MonitorHandle as CoreMonitorHandle;
|
||||
use crate::monitor::{Fullscreen, MonitorHandle as CoreMonitorHandle, MonitorHandleProvider};
|
||||
use crate::platform::windows::{BackdropType, Color, CornerPreference};
|
||||
use crate::platform_impl::platform::dark_mode::try_theme;
|
||||
use crate::platform_impl::platform::definitions::{
|
||||
|
|
@ -69,11 +71,10 @@ use crate::platform_impl::platform::keyboard::KeyEventBuilder;
|
|||
use crate::platform_impl::platform::window_state::{
|
||||
CursorFlags, SavedWindow, WindowFlags, WindowState,
|
||||
};
|
||||
use crate::platform_impl::platform::{monitor, util, Fullscreen, SelectedCursor};
|
||||
use crate::platform_impl::platform::{monitor, util, SelectedCursor};
|
||||
use crate::window::{
|
||||
CursorGrabMode, Fullscreen as CoreFullscreen, ImePurpose, ResizeDirection, Theme,
|
||||
UserAttentionType, Window as CoreWindow, WindowAttributes, WindowButtons, WindowId,
|
||||
WindowLevel,
|
||||
CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, Window as CoreWindow,
|
||||
WindowAttributes, WindowButtons, WindowId, WindowLevel,
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
|
@ -352,7 +353,7 @@ impl Window {
|
|||
impl Drop for Window {
|
||||
fn drop(&mut self) {
|
||||
// Restore fullscreen video mode on exit.
|
||||
if matches!(self.fullscreen(), Some(CoreFullscreen::Exclusive(_, _))) {
|
||||
if matches!(self.fullscreen(), Some(Fullscreen::Exclusive(_, _))) {
|
||||
self.set_fullscreen(None);
|
||||
}
|
||||
|
||||
|
|
@ -755,13 +756,12 @@ impl CoreWindow for Window {
|
|||
window_state.window_flags.contains(WindowFlags::MAXIMIZED)
|
||||
}
|
||||
|
||||
fn fullscreen(&self) -> Option<CoreFullscreen> {
|
||||
fn fullscreen(&self) -> Option<Fullscreen> {
|
||||
let window_state = self.window_state_lock();
|
||||
window_state.fullscreen.clone().map(Into::into)
|
||||
window_state.fullscreen.clone()
|
||||
}
|
||||
|
||||
fn set_fullscreen(&self, fullscreen: Option<CoreFullscreen>) {
|
||||
let fullscreen = fullscreen.map(Into::into);
|
||||
fn set_fullscreen(&self, fullscreen: Option<Fullscreen>) {
|
||||
let window = self.window;
|
||||
let window_state = Arc::clone(&self.window_state);
|
||||
|
||||
|
|
@ -774,7 +774,7 @@ impl CoreWindow for Window {
|
|||
// Return if saved Borderless(monitor) is the same as current monitor when requested
|
||||
// fullscreen is Borderless(None)
|
||||
(Some(Fullscreen::Borderless(Some(monitor))), Some(Fullscreen::Borderless(None)))
|
||||
if *monitor == monitor::current_monitor(window.hwnd()) =>
|
||||
if monitor.native_id() == monitor::current_monitor(window.hwnd()).native_id() =>
|
||||
{
|
||||
return
|
||||
},
|
||||
|
|
@ -790,12 +790,13 @@ impl CoreWindow for Window {
|
|||
// fullscreen
|
||||
match (&old_fullscreen, &fullscreen) {
|
||||
(_, Some(Fullscreen::Exclusive(monitor, video_mode))) => {
|
||||
let monitor_info = monitor::get_monitor_info(monitor.hmonitor()).unwrap();
|
||||
let monitor = monitor.as_any().downcast_ref::<MonitorHandle>().unwrap();
|
||||
let video_mode =
|
||||
match monitor.video_mode_handles().find(|mode| &mode.mode == video_mode) {
|
||||
Some(monitor) => monitor,
|
||||
None => return,
|
||||
};
|
||||
let monitor_info = monitor::get_monitor_info(monitor.native_id() as _).unwrap();
|
||||
|
||||
let res = unsafe {
|
||||
ChangeDisplaySettingsExW(
|
||||
|
|
@ -880,11 +881,16 @@ impl CoreWindow for Window {
|
|||
window_state.lock().unwrap().saved_window = Some(SavedWindow { placement });
|
||||
|
||||
let monitor = match &fullscreen {
|
||||
Fullscreen::Exclusive(monitor, _) => monitor.clone(),
|
||||
Fullscreen::Borderless(Some(monitor)) => monitor.clone(),
|
||||
Fullscreen::Borderless(None) => monitor::current_monitor(window.hwnd()),
|
||||
Fullscreen::Exclusive(monitor, _)
|
||||
| Fullscreen::Borderless(Some(monitor)) => Some(Cow::Borrowed(
|
||||
monitor.as_any().downcast_ref::<MonitorHandle>().unwrap(),
|
||||
)),
|
||||
Fullscreen::Borderless(None) => None,
|
||||
};
|
||||
|
||||
let monitor = monitor
|
||||
.unwrap_or_else(|| Cow::Owned(monitor::current_monitor(window.hwnd())));
|
||||
|
||||
let position: (i32, i32) = monitor.position().unwrap_or_default().into();
|
||||
let size: (u32, u32) = monitor.size().into();
|
||||
|
||||
|
|
@ -946,15 +952,19 @@ impl CoreWindow for Window {
|
|||
}
|
||||
|
||||
fn current_monitor(&self) -> Option<CoreMonitorHandle> {
|
||||
Some(CoreMonitorHandle { inner: monitor::current_monitor(self.hwnd()) })
|
||||
Some(CoreMonitorHandle(Arc::new(monitor::current_monitor(self.hwnd()))))
|
||||
}
|
||||
|
||||
fn available_monitors(&self) -> Box<dyn Iterator<Item = CoreMonitorHandle>> {
|
||||
Box::new(monitor::available_monitors().into_iter().map(|inner| CoreMonitorHandle { inner }))
|
||||
Box::new(
|
||||
monitor::available_monitors()
|
||||
.into_iter()
|
||||
.map(|monitor| CoreMonitorHandle(Arc::new(monitor))),
|
||||
)
|
||||
}
|
||||
|
||||
fn primary_monitor(&self) -> Option<CoreMonitorHandle> {
|
||||
Some(CoreMonitorHandle { inner: monitor::primary_monitor() })
|
||||
Some(CoreMonitorHandle(Arc::new(monitor::primary_monitor())))
|
||||
}
|
||||
|
||||
fn set_window_icon(&self, window_icon: Option<Icon>) {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@ use windows_sys::Win32::UI::WindowsAndMessaging::{
|
|||
use crate::dpi::{PhysicalPosition, PhysicalSize, Size};
|
||||
use crate::icon::Icon;
|
||||
use crate::keyboard::ModifiersState;
|
||||
use crate::platform_impl::platform::{event_loop, util, Fullscreen, SelectedCursor};
|
||||
use crate::monitor::Fullscreen;
|
||||
use crate::platform_impl::platform::{event_loop, util, SelectedCursor};
|
||||
use crate::window::{Theme, WindowAttributes};
|
||||
|
||||
/// Contains information about states and the window that the callback is going to use.
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ pub use crate::cursor::{BadImage, Cursor, CustomCursor, CustomCursorSource, MAX_
|
|||
use crate::dpi::{PhysicalInsets, PhysicalPosition, PhysicalSize, Position, Size};
|
||||
use crate::error::RequestError;
|
||||
pub use crate::icon::{BadIcon, Icon};
|
||||
use crate::monitor::{MonitorHandle, VideoMode};
|
||||
use crate::monitor::{Fullscreen, MonitorHandle};
|
||||
use crate::platform_impl::PlatformSpecificWindowAttributes;
|
||||
use crate::utils::AsAny;
|
||||
|
||||
|
|
@ -442,7 +442,7 @@ pub trait Window: AsAny + Send + Sync + fmt::Debug {
|
|||
/// moved to another screen); as such, tracking [`WindowEvent::ScaleFactorChanged`] events is
|
||||
/// the most robust way to track the DPI you need to use to draw.
|
||||
///
|
||||
/// This value may differ from [`MonitorHandle::scale_factor`].
|
||||
/// This value may differ from [`MonitorHandleProvider::scale_factor`].
|
||||
///
|
||||
/// See the [`dpi`] crate for more information.
|
||||
///
|
||||
|
|
@ -496,6 +496,7 @@ pub trait Window: AsAny + Send + Sync + fmt::Debug {
|
|||
/// [android_1]: https://developer.android.com/training/multiscreen/screendensities
|
||||
/// [web_1]: https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio
|
||||
/// [`contentScaleFactor`]: https://developer.apple.com/documentation/uikit/uiview/1622657-contentscalefactor?language=objc
|
||||
/// [`MonitorHandleProvider::scale_factor`]: crate::monitor::MonitorHandleProvider::scale_factor.
|
||||
fn scale_factor(&self) -> f64;
|
||||
|
||||
/// Queues a [`WindowEvent::RedrawRequested`] event to be emitted that aligns with the windowing
|
||||
|
|
@ -972,6 +973,7 @@ pub trait Window: AsAny + Send + Sync + fmt::Debug {
|
|||
/// or calling without a [transient activation] does nothing.
|
||||
///
|
||||
/// [transient activation]: https://developer.mozilla.org/en-US/docs/Glossary/Transient_activation
|
||||
/// [`VideoMode`]: crate::monitor::VideoMode
|
||||
fn set_fullscreen(&self, fullscreen: Option<Fullscreen>);
|
||||
|
||||
/// Gets the window's current fullscreen state.
|
||||
|
|
@ -1430,18 +1432,6 @@ impl From<ResizeDirection> for CursorIcon {
|
|||
}
|
||||
}
|
||||
|
||||
/// Fullscreen modes.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum Fullscreen {
|
||||
/// This changes the video mode of the monitor for fullscreen windows and,
|
||||
/// if applicable, captures the monitor for exclusive use by this
|
||||
/// application.
|
||||
Exclusive(MonitorHandle, VideoMode),
|
||||
|
||||
/// Providing `None` to `Borderless` will fullscreen on the current monitor.
|
||||
Borderless(Option<MonitorHandle>),
|
||||
}
|
||||
|
||||
/// The theme variant to use.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue