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:
Aleksi Juvani 2019-07-29 21:16:14 +03:00 committed by Osspial
parent 131e67ddc1
commit 5bc3cf18d9
31 changed files with 1452 additions and 605 deletions

View file

@ -5,7 +5,7 @@ use crate::{
dpi::{LogicalPosition, LogicalSize},
error::{ExternalError, NotSupportedError, OsError},
event_loop::EventLoopWindowTarget,
monitor::{AvailableMonitorsIter, MonitorHandle},
monitor::{AvailableMonitorsIter, MonitorHandle, VideoMode},
platform_impl,
};
@ -45,6 +45,18 @@ impl fmt::Debug for Window {
}
}
impl Drop for Window {
fn drop(&mut self) {
// If the window is in exclusive fullscreen, we must restore the desktop
// video mode (generally this would be done on application exit, but
// closing the window doesn't necessarily always mean application exit,
// such as when there are multiple windows)
if let Some(Fullscreen::Exclusive(_)) = self.fullscreen() {
self.set_fullscreen(None);
}
}
}
/// Identifier of a window. Unique for each window.
///
/// Can be obtained with `window.id()`.
@ -110,7 +122,7 @@ pub struct WindowAttributes {
/// Whether the window should be set as fullscreen upon creation.
///
/// The default is `None`.
pub fullscreen: Option<MonitorHandle>,
pub fullscreen: Option<Fullscreen>,
/// The title of the window in the title bar.
///
@ -222,14 +234,14 @@ impl WindowBuilder {
self
}
/// Sets the window fullscreen state. None means a normal window, Some(MonitorHandle)
/// Sets the window fullscreen state. None means a normal window, Some(Fullscreen)
/// means a fullscreen window on that specific monitor
///
/// ## Platform-specific
///
/// - **Windows:** Screen saver is disabled in fullscreen mode.
#[inline]
pub fn with_fullscreen(mut self, monitor: Option<MonitorHandle>) -> WindowBuilder {
pub fn with_fullscreen(mut self, monitor: Option<Fullscreen>) -> WindowBuilder {
self.window.fullscreen = monitor;
self
}
@ -295,7 +307,6 @@ impl WindowBuilder {
self,
window_target: &EventLoopWindowTarget<T>,
) -> Result<Window, OsError> {
// building
platform_impl::Window::new(&window_target.p, self.window, self.platform_specific)
.map(|window| Window { window })
}
@ -537,11 +548,27 @@ impl Window {
///
/// ## Platform-specific
///
/// - **macOS:** `Fullscreen::Exclusive` provides true exclusive mode with a
/// video mode change. *Caveat!* macOS doesn't provide task switching (or
/// spaces!) while in exclusive fullscreen mode. This mode should be used
/// when a video mode change is desired, but for a better user experience,
/// borderless fullscreen might be preferred.
///
/// `Fullscreen::Borderless` provides a borderless fullscreen window on a
/// separate space. This is the idiomatic way for fullscreen games to work
/// on macOS. See [`WindowExtMacOs::set_simple_fullscreen`][simple] if
/// separate spaces are not preferred.
///
/// The dock and the menu bar are always disabled in fullscreen mode.
/// - **iOS:** Can only be called on the main thread.
/// - **Wayland:** Does not support exclusive fullscreen mode.
/// - **Windows:** Screen saver is disabled in fullscreen mode.
///
/// [simple]:
/// ../platform/macos/trait.WindowExtMacOS.html#tymethod.set_simple_fullscreen
#[inline]
pub fn set_fullscreen(&self, monitor: Option<MonitorHandle>) {
self.window.set_fullscreen(monitor)
pub fn set_fullscreen(&self, fullscreen: Option<Fullscreen>) {
self.window.set_fullscreen(fullscreen)
}
/// Gets the window's current fullscreen state.
@ -550,7 +577,7 @@ impl Window {
///
/// - **iOS:** Can only be called on the main thread.
#[inline]
pub fn fullscreen(&self) -> Option<MonitorHandle> {
pub fn fullscreen(&self) -> Option<Fullscreen> {
self.window.fullscreen()
}
@ -759,3 +786,9 @@ impl Default for CursorIcon {
CursorIcon::Default
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Fullscreen {
Exclusive(VideoMode),
Borderless(MonitorHandle),
}