Make 'primary_monitor' return 'Option<MonitorHandle>'

Certain platforms like Wayland don't have a concept of
primary Monitor in particular. To indicate that
'primary_monitor' will return 'None' as well as in cases
where the primary monitor can't be detected.

Fixes #1683.
This commit is contained in:
Kirill Chibisov 2020-09-07 20:20:47 +03:00 committed by GitHub
parent cac627ed05
commit d103dc2631
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 86 additions and 56 deletions

View file

@ -29,6 +29,7 @@
- **Breaking:** On X11, `-` key is mapped to the `Minus` virtual key code, instead of `Subtract`. - **Breaking:** On X11, `-` key is mapped to the `Minus` virtual key code, instead of `Subtract`.
- On macOS, fix inverted horizontal scroll. - On macOS, fix inverted horizontal scroll.
- **Breaking:** `current_monitor` now returns `Option<MonitorHandle>`. - **Breaking:** `current_monitor` now returns `Option<MonitorHandle>`.
- **Breaking:** `primary_monitor` now returns `Option<MonitorHandle>`.
# 0.22.2 (2020-05-16) # 0.22.2 (2020-05-16)

View file

@ -3,7 +3,13 @@ use winit::event_loop::EventLoop;
fn main() { fn main() {
simple_logger::init().unwrap(); simple_logger::init().unwrap();
let event_loop = EventLoop::new(); let event_loop = EventLoop::new();
let monitor = event_loop.primary_monitor(); let monitor = match event_loop.primary_monitor() {
Some(monitor) => monitor,
None => {
println!("No primary monitor detected.");
return;
}
};
println!("Listing available video modes:"); println!("Listing available video modes:");

View file

@ -178,11 +178,15 @@ impl<T> EventLoopWindowTarget<T> {
} }
/// Returns the primary monitor of the system. /// Returns the primary monitor of the system.
///
/// Returns `None` if it can't identify any monitor as a primary one.
///
/// ## Platform-specific
///
/// **Wayland:** Always returns `None`.
#[inline] #[inline]
pub fn primary_monitor(&self) -> MonitorHandle { pub fn primary_monitor(&self) -> Option<MonitorHandle> {
MonitorHandle { self.p.primary_monitor()
inner: self.p.primary_monitor(),
}
} }
} }

View file

@ -333,13 +333,15 @@ pub struct EventLoopWindowTarget<T: 'static> {
} }
impl<T: 'static> EventLoopWindowTarget<T> { impl<T: 'static> EventLoopWindowTarget<T> {
pub fn primary_monitor(&self) -> MonitorHandle { pub fn primary_monitor(&self) -> Option<monitor::MonitorHandle> {
MonitorHandle Some(monitor::MonitorHandle {
inner: MonitorHandle,
})
} }
pub fn available_monitors(&self) -> VecDeque<MonitorHandle> { pub fn available_monitors(&self) -> VecDeque<MonitorHandle> {
let mut v = VecDeque::with_capacity(1); let mut v = VecDeque::with_capacity(1);
v.push_back(self.primary_monitor()); v.push_back(MonitorHandle);
v v
} }
} }
@ -381,8 +383,10 @@ impl Window {
WindowId WindowId
} }
pub fn primary_monitor(&self) -> MonitorHandle { pub fn primary_monitor(&self) -> Option<monitor::MonitorHandle> {
MonitorHandle Some(monitor::MonitorHandle {
inner: MonitorHandle,
})
} }
pub fn available_monitors(&self) -> VecDeque<MonitorHandle> { pub fn available_monitors(&self) -> VecDeque<MonitorHandle> {

View file

@ -13,6 +13,7 @@ use crate::{
event_loop::{ event_loop::{
ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootEventLoopWindowTarget, ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootEventLoopWindowTarget,
}, },
monitor::MonitorHandle as RootMonitorHandle,
platform::ios::Idiom, platform::ios::Idiom,
}; };
@ -56,9 +57,11 @@ impl<T: 'static> EventLoopWindowTarget<T> {
unsafe { monitor::uiscreens() } unsafe { monitor::uiscreens() }
} }
pub fn primary_monitor(&self) -> MonitorHandle { pub fn primary_monitor(&self) -> Option<RootMonitorHandle> {
// guaranteed to be on main thread // guaranteed to be on main thread
unsafe { monitor::main_uiscreen() } let monitor = unsafe { monitor::main_uiscreen() };
Some(RootMonitorHandle { inner: monitor })
} }
} }

View file

@ -276,8 +276,9 @@ impl Inner {
unsafe { monitor::uiscreens() } unsafe { monitor::uiscreens() }
} }
pub fn primary_monitor(&self) -> MonitorHandle { pub fn primary_monitor(&self) -> Option<RootMonitorHandle> {
unsafe { monitor::main_uiscreen() } let monitor = unsafe { monitor::main_uiscreen() };
Some(RootMonitorHandle { inner: monitor })
} }
pub fn id(&self) -> WindowId { pub fn id(&self) -> WindowId {

View file

@ -463,8 +463,18 @@ impl Window {
} }
#[inline] #[inline]
pub fn primary_monitor(&self) -> MonitorHandle { pub fn primary_monitor(&self) -> Option<RootMonitorHandle> {
x11_or_wayland!(match self; Window(window) => window.primary_monitor(); as MonitorHandle) match self {
#[cfg(feature = "x11")]
&Window::X(ref window) => {
let primary_monitor = MonitorHandle::X(window.primary_monitor());
Some(RootMonitorHandle {
inner: primary_monitor,
})
}
#[cfg(feature = "wayland")]
&Window::Wayland(ref window) => window.primary_monitor(),
}
} }
pub fn raw_window_handle(&self) -> RawWindowHandle { pub fn raw_window_handle(&self) -> RawWindowHandle {
@ -682,15 +692,16 @@ impl<T> EventLoopWindowTarget<T> {
} }
#[inline] #[inline]
pub fn primary_monitor(&self) -> MonitorHandle { pub fn primary_monitor(&self) -> Option<RootMonitorHandle> {
match *self { match *self {
#[cfg(feature = "wayland")] #[cfg(feature = "wayland")]
EventLoopWindowTarget::Wayland(ref evlp) => { EventLoopWindowTarget::Wayland(ref evlp) => evlp.primary_monitor(),
MonitorHandle::Wayland(evlp.primary_monitor())
}
#[cfg(feature = "x11")] #[cfg(feature = "x11")]
EventLoopWindowTarget::X(ref evlp) => { EventLoopWindowTarget::X(ref evlp) => {
MonitorHandle::X(evlp.x_connection().primary_monitor()) let primary_monitor = MonitorHandle::X(evlp.x_connection().primary_monitor());
Some(RootMonitorHandle {
inner: primary_monitor,
})
} }
} }
} }

View file

@ -648,8 +648,9 @@ impl<T> EventLoopWindowTarget<T> {
available_monitors(&self.outputs) available_monitors(&self.outputs)
} }
pub fn primary_monitor(&self) -> MonitorHandle { pub fn primary_monitor(&self) -> Option<RootMonitorHandle> {
primary_monitor(&self.outputs) // Wayland doesn't have a notion of primary monitor.
None
} }
} }
@ -1121,19 +1122,6 @@ impl MonitorHandle {
} }
} }
pub fn primary_monitor(outputs: &OutputMgr) -> MonitorHandle {
outputs.with_all(|list| {
if let Some(&(_, ref proxy, _)) = list.first() {
MonitorHandle {
proxy: proxy.clone(),
mgr: outputs.clone(),
}
} else {
panic!("No monitor is available.")
}
})
}
pub fn available_monitors(outputs: &OutputMgr) -> VecDeque<MonitorHandle> { pub fn available_monitors(outputs: &OutputMgr) -> VecDeque<MonitorHandle> {
outputs.with_all(|list| { outputs.with_all(|list| {
list.iter() list.iter()

View file

@ -10,8 +10,7 @@ use crate::{
error::{ExternalError, NotSupportedError, OsError as RootOsError}, error::{ExternalError, NotSupportedError, OsError as RootOsError},
monitor::MonitorHandle as RootMonitorHandle, monitor::MonitorHandle as RootMonitorHandle,
platform_impl::{ platform_impl::{
platform::wayland::event_loop::{available_monitors, primary_monitor}, platform::wayland::event_loop::available_monitors, MonitorHandle as PlatformMonitorHandle,
MonitorHandle as PlatformMonitorHandle,
PlatformSpecificWindowBuilderAttributes as PlAttributes, PlatformSpecificWindowBuilderAttributes as PlAttributes,
}, },
window::{CursorIcon, Fullscreen, WindowAttributes}, window::{CursorIcon, Fullscreen, WindowAttributes},
@ -410,8 +409,9 @@ impl Window {
available_monitors(&self.outputs) available_monitors(&self.outputs)
} }
pub fn primary_monitor(&self) -> MonitorHandle { pub fn primary_monitor(&self) -> Option<RootMonitorHandle> {
primary_monitor(&self.outputs) // Wayland doesn't have a notion of primary monitor.
None
} }
pub fn raw_window_handle(&self) -> WaylandHandle { pub fn raw_window_handle(&self) -> WaylandHandle {

View file

@ -12,6 +12,7 @@ use cocoa::{
use crate::{ use crate::{
event::Event, event::Event,
event_loop::{ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootWindowTarget}, event_loop::{ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootWindowTarget},
monitor::MonitorHandle as RootMonitorHandle,
platform_impl::platform::{ platform_impl::platform::{
app::APP_CLASS, app::APP_CLASS,
app_delegate::APP_DELEGATE_CLASS, app_delegate::APP_DELEGATE_CLASS,
@ -41,8 +42,9 @@ impl<T: 'static> EventLoopWindowTarget<T> {
} }
#[inline] #[inline]
pub fn primary_monitor(&self) -> MonitorHandle { pub fn primary_monitor(&self) -> Option<RootMonitorHandle> {
monitor::primary_monitor() let monitor = monitor::primary_monitor();
Some(RootMonitorHandle { inner: monitor })
} }
} }

View file

@ -997,8 +997,9 @@ impl UnownedWindow {
} }
#[inline] #[inline]
pub fn primary_monitor(&self) -> MonitorHandle { pub fn primary_monitor(&self) -> Option<RootMonitorHandle> {
monitor::primary_monitor() let monitor = monitor::primary_monitor();
Some(RootMonitorHandle { inner: monitor })
} }
#[inline] #[inline]

View file

@ -2,6 +2,7 @@ use super::{super::monitor, backend, device, proxy::Proxy, runner, window};
use crate::dpi::{PhysicalSize, Size}; use crate::dpi::{PhysicalSize, Size};
use crate::event::{DeviceId, ElementState, Event, KeyboardInput, TouchPhase, WindowEvent}; use crate::event::{DeviceId, ElementState, Event, KeyboardInput, TouchPhase, WindowEvent};
use crate::event_loop::ControlFlow; use crate::event_loop::ControlFlow;
use crate::monitor::MonitorHandle as RootMH;
use crate::window::{Theme, WindowId}; use crate::window::{Theme, WindowId};
use std::clone::Clone; use std::clone::Clone;
use std::collections::{vec_deque::IntoIter as VecDequeIter, VecDeque}; use std::collections::{vec_deque::IntoIter as VecDequeIter, VecDeque};
@ -237,7 +238,9 @@ impl<T> WindowTarget<T> {
VecDeque::new().into_iter() VecDeque::new().into_iter()
} }
pub fn primary_monitor(&self) -> monitor::Handle { pub fn primary_monitor(&self) -> Option<RootMH> {
monitor::Handle Some(RootMH {
inner: monitor::Handle,
})
} }
} }

View file

@ -255,8 +255,10 @@ impl Window {
} }
#[inline] #[inline]
pub fn primary_monitor(&self) -> monitor::Handle { pub fn primary_monitor(&self) -> Option<RootMH> {
monitor::Handle Some(RootMH {
inner: monitor::Handle,
})
} }
#[inline] #[inline]

View file

@ -34,6 +34,7 @@ use crate::{
dpi::{PhysicalPosition, PhysicalSize}, dpi::{PhysicalPosition, PhysicalSize},
event::{DeviceEvent, Event, Force, KeyboardInput, Touch, TouchPhase, WindowEvent}, event::{DeviceEvent, Event, Force, KeyboardInput, Touch, TouchPhase, WindowEvent},
event_loop::{ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootELW}, event_loop::{ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootELW},
monitor::MonitorHandle as RootMonitorHandle,
platform_impl::platform::{ platform_impl::platform::{
dark_mode::try_dark_mode, dark_mode::try_dark_mode,
dpi::{become_dpi_aware, dpi_to_scale_factor, enable_non_client_dpi_scaling}, dpi::{become_dpi_aware, dpi_to_scale_factor, enable_non_client_dpi_scaling},
@ -255,8 +256,9 @@ impl<T> EventLoopWindowTarget<T> {
monitor::available_monitors() monitor::available_monitors()
} }
pub fn primary_monitor(&self) -> MonitorHandle { pub fn primary_monitor(&self) -> Option<RootMonitorHandle> {
monitor::primary_monitor() let monitor = monitor::primary_monitor();
Some(RootMonitorHandle { inner: monitor })
} }
} }

View file

@ -131,8 +131,9 @@ impl Window {
available_monitors() available_monitors()
} }
pub fn primary_monitor(&self) -> MonitorHandle { pub fn primary_monitor(&self) -> Option<RootMonitorHandle> {
primary_monitor() let monitor = primary_monitor();
Some(RootMonitorHandle { inner: monitor })
} }
} }

View file

@ -765,16 +765,17 @@ impl Window {
/// Returns the primary monitor of the system. /// Returns the primary monitor of the system.
/// ///
/// Returns `None` if it can't identify any monitor as a primary one.
///
/// This is the same as `EventLoopWindowTarget::primary_monitor`, and is provided for convenience. /// This is the same as `EventLoopWindowTarget::primary_monitor`, and is provided for convenience.
/// ///
/// ## Platform-specific /// ## Platform-specific
/// ///
/// **iOS:** Can only be called on the main thread. /// **iOS:** Can only be called on the main thread.
/// **Wayland:** Always returns `None`.
#[inline] #[inline]
pub fn primary_monitor(&self) -> MonitorHandle { pub fn primary_monitor(&self) -> Option<MonitorHandle> {
MonitorHandle { self.window.primary_monitor()
inner: self.window.primary_monitor(),
}
} }
} }