Add exclusive fullscreen mode (#925)
* Add exclusive fullscreen mode * Add `WindowExtMacOS::set_fullscreen_presentation_options` * Capture display for exclusive fullscreen on macOS * Fix applying video mode on macOS after a fullscreen cycle * Fix compilation on iOS * Set monitor appropriately for fullscreen on macOS * Fix exclusive to borderless fullscreen transitions on macOS * Fix borderless to exclusive fullscreen transition on macOS * Sort video modes on Windows * Fix fullscreen issues on Windows * Fix video mode changes during exclusive fullscreen on Windows * Add video mode sorting for macOS and iOS * Fix monitor `ns_screen` returning `None` after video mode change * Fix "multithreaded" example on macOS * Restore video mode upon closing an exclusive fullscreen window * Fix "multithreaded" example closing multiple windows at once * Fix compilation on Linux * Update FEATURES.md * Don't care about logical monitor groups on X11 * Add exclusive fullscreen for X11 * Update FEATURES.md * Fix transitions between exclusive and borderless fullscreen on X11 * Update CHANGELOG.md * Document that Wayland doesn't support exclusive fullscreen * Replace core-graphics display mode bindings on macOS * Use `panic!()` instead of `unreachable!()` in "fullscreen" example * Fix fullscreen "always on top" flag on Windows * Track current monitor for fullscreen in "multithreaded" example * Fix exclusive fullscreen sometimes not positioning window properly * Format * More formatting and fix CI issues * Fix formatting * Fix changelog formatting
This commit is contained in:
parent
131e67ddc1
commit
5bc3cf18d9
31 changed files with 1452 additions and 605 deletions
|
|
@ -16,8 +16,11 @@ use crate::{
|
|||
dpi::{PhysicalPosition, PhysicalSize},
|
||||
event::ModifiersState,
|
||||
event_loop::{ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootELW},
|
||||
monitor::VideoMode,
|
||||
platform_impl::platform::sticky_exit_callback,
|
||||
monitor::{MonitorHandle as RootMonitorHandle, VideoMode as RootVideoMode},
|
||||
platform_impl::platform::{
|
||||
sticky_exit_callback, MonitorHandle as PlatformMonitorHandle,
|
||||
VideoMode as PlatformVideoMode,
|
||||
},
|
||||
};
|
||||
|
||||
use super::{window::WindowStore, DeviceId, WindowId};
|
||||
|
|
@ -603,17 +606,67 @@ impl<T> Drop for SeatData<T> {
|
|||
* Monitor stuff
|
||||
*/
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct VideoMode {
|
||||
pub(crate) size: (u32, u32),
|
||||
pub(crate) bit_depth: u16,
|
||||
pub(crate) refresh_rate: u16,
|
||||
pub(crate) monitor: MonitorHandle,
|
||||
}
|
||||
|
||||
impl VideoMode {
|
||||
#[inline]
|
||||
pub fn size(&self) -> PhysicalSize {
|
||||
self.size.into()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn bit_depth(&self) -> u16 {
|
||||
self.bit_depth
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn refresh_rate(&self) -> u16 {
|
||||
self.refresh_rate
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn monitor(&self) -> RootMonitorHandle {
|
||||
RootMonitorHandle {
|
||||
inner: PlatformMonitorHandle::Wayland(self.monitor.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MonitorHandle {
|
||||
pub(crate) proxy: wl_output::WlOutput,
|
||||
pub(crate) mgr: OutputMgr,
|
||||
}
|
||||
|
||||
impl Clone for MonitorHandle {
|
||||
fn clone(&self) -> MonitorHandle {
|
||||
MonitorHandle {
|
||||
proxy: self.proxy.clone(),
|
||||
mgr: self.mgr.clone(),
|
||||
}
|
||||
impl PartialEq for MonitorHandle {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.native_identifier() == other.native_identifier()
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -680,15 +733,20 @@ impl MonitorHandle {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn video_modes(&self) -> impl Iterator<Item = VideoMode> {
|
||||
pub fn video_modes(&self) -> impl Iterator<Item = RootVideoMode> {
|
||||
let monitor = self.clone();
|
||||
|
||||
self.mgr
|
||||
.with_info(&self.proxy, |_, info| info.modes.clone())
|
||||
.unwrap_or(vec![])
|
||||
.into_iter()
|
||||
.map(|x| VideoMode {
|
||||
size: (x.dimensions.0 as u32, x.dimensions.1 as u32),
|
||||
refresh_rate: (x.refresh_rate as f32 / 1000.0).round() as u16,
|
||||
bit_depth: 32,
|
||||
.map(move |x| RootVideoMode {
|
||||
video_mode: PlatformVideoMode::Wayland(VideoMode {
|
||||
size: (x.dimensions.0 as u32, x.dimensions.1 as u32),
|
||||
refresh_rate: (x.refresh_rate as f32 / 1000.0).round() as u16,
|
||||
bit_depth: 32,
|
||||
monitor: monitor.clone(),
|
||||
}),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@
|
|||
|
||||
pub use self::{
|
||||
event_loop::{
|
||||
EventLoop, EventLoopProxy, EventLoopWindowTarget, MonitorHandle, WindowEventsSink,
|
||||
EventLoop, EventLoopProxy, EventLoopWindowTarget, MonitorHandle, VideoMode,
|
||||
WindowEventsSink,
|
||||
},
|
||||
window::Window,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,10 +8,11 @@ use crate::{
|
|||
error::{ExternalError, NotSupportedError, OsError as RootOsError},
|
||||
monitor::MonitorHandle as RootMonitorHandle,
|
||||
platform_impl::{
|
||||
platform::wayland::event_loop::{available_monitors, primary_monitor},
|
||||
MonitorHandle as PlatformMonitorHandle,
|
||||
PlatformSpecificWindowBuilderAttributes as PlAttributes,
|
||||
},
|
||||
window::{CursorIcon, WindowAttributes},
|
||||
window::{CursorIcon, Fullscreen, WindowAttributes},
|
||||
};
|
||||
|
||||
use smithay_client_toolkit::{
|
||||
|
|
@ -25,7 +26,6 @@ use smithay_client_toolkit::{
|
|||
};
|
||||
|
||||
use super::{make_wid, EventLoopWindowTarget, MonitorHandle, WindowId};
|
||||
use crate::platform_impl::platform::wayland::event_loop::{available_monitors, primary_monitor};
|
||||
|
||||
pub struct Window {
|
||||
surface: wl_surface::WlSurface,
|
||||
|
|
@ -108,13 +108,19 @@ impl Window {
|
|||
}
|
||||
|
||||
// Check for fullscreen requirements
|
||||
if let Some(RootMonitorHandle {
|
||||
inner: PlatformMonitorHandle::Wayland(ref monitor_id),
|
||||
}) = attributes.fullscreen
|
||||
{
|
||||
frame.set_fullscreen(Some(&monitor_id.proxy));
|
||||
} else if attributes.maximized {
|
||||
frame.set_maximized();
|
||||
match attributes.fullscreen {
|
||||
Some(Fullscreen::Exclusive(_)) => {
|
||||
panic!("Wayland doesn't support exclusive fullscreen")
|
||||
}
|
||||
Some(Fullscreen::Borderless(RootMonitorHandle {
|
||||
inner: PlatformMonitorHandle::Wayland(ref monitor_id),
|
||||
})) => frame.set_fullscreen(Some(&monitor_id.proxy)),
|
||||
Some(Fullscreen::Borderless(_)) => unreachable!(),
|
||||
None => {
|
||||
if attributes.maximized {
|
||||
frame.set_maximized();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
frame.set_resizable(attributes.resizable);
|
||||
|
|
@ -252,25 +258,31 @@ impl Window {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn fullscreen(&self) -> Option<MonitorHandle> {
|
||||
pub fn fullscreen(&self) -> Option<Fullscreen> {
|
||||
if *(self.fullscreen.lock().unwrap()) {
|
||||
Some(self.current_monitor())
|
||||
Some(Fullscreen::Borderless(RootMonitorHandle {
|
||||
inner: PlatformMonitorHandle::Wayland(self.current_monitor()),
|
||||
}))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_fullscreen(&self, monitor: Option<RootMonitorHandle>) {
|
||||
if let Some(RootMonitorHandle {
|
||||
inner: PlatformMonitorHandle::Wayland(ref monitor_id),
|
||||
}) = monitor
|
||||
{
|
||||
self.frame
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_fullscreen(Some(&monitor_id.proxy));
|
||||
} else {
|
||||
self.frame.lock().unwrap().unset_fullscreen();
|
||||
pub fn set_fullscreen(&self, fullscreen: Option<Fullscreen>) {
|
||||
match fullscreen {
|
||||
Some(Fullscreen::Exclusive(_)) => {
|
||||
panic!("Wayland doesn't support exclusive fullscreen")
|
||||
}
|
||||
Some(Fullscreen::Borderless(RootMonitorHandle {
|
||||
inner: PlatformMonitorHandle::Wayland(ref monitor_id),
|
||||
})) => {
|
||||
self.frame
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_fullscreen(Some(&monitor_id.proxy));
|
||||
}
|
||||
Some(Fullscreen::Borderless(_)) => unreachable!(),
|
||||
None => self.frame.lock().unwrap().unset_fullscreen(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue