# Objective - #16883 - Improve the default behaviour of the exclusive fullscreen API. ## Solution This PR changes the exclusive fullscreen window mode to require the type `WindowMode::Fullscreen(MonitorSelection, VideoModeSelection)` and removes `WindowMode::SizedFullscreen`. This API somewhat intentionally more closely resembles Winit 0.31's upcoming fullscreen and video mode API. The new VideoModeSelection enum is specified as follows: ```rust pub enum VideoModeSelection { /// Uses the video mode that the monitor is already in. Current, /// Uses a given [`crate::monitor::VideoMode`]. A list of video modes supported by the monitor /// is supplied by [`crate::monitor::Monitor::video_modes`]. Specific(VideoMode), } ``` ### Changing default behaviour This might be contentious because it removes the previous behaviour of `WindowMode::Fullscreen` which selected the highest resolution possible. While the previous behaviour would be quite easy to re-implement as additional options, or as an impl method on Monitor, I would argue that this isn't an implementation that should be encouraged. From the perspective of a Windows user, I prefer what the majority of modern games do when entering fullscreen which is to preserve the OS's current resolution settings, which allows exclusive fullscreen to be entered faster, and to only have it change if I manually select it in either the options of the game or the OS. The highest resolution available is not necessarily what the user prefers. I am open to changing this if I have just missed a good use case for it. Likewise, the only functionality that `WindowMode::SizedFullscreen` provided was that it selected the resolution closest to the current size of the window so it was removed since this behaviour can be replicated via the new `VideoModeSelection::Specific` if necessary. ## Out of scope WindowResolution and scale factor act strangely in exclusive fullscreen, this PR doesn't address it or regress it. ## Testing - Tested on Windows 11 and macOS 12.7 - Linux untested ## Migration Guide `WindowMode::SizedFullscreen(MonitorSelection)` and `WindowMode::Fullscreen(MonitorSelection)` has become `WindowMode::Fullscreen(MonitorSelection, VideoModeSelection)`. Previously, the VideoMode was selected based on the closest resolution to the current window size for SizedFullscreen and the largest resolution for Fullscreen. It is possible to replicate that behaviour by searching `Monitor::video_modes` and selecting it with `VideoModeSelection::Specific(VideoMode)` but it is recommended to use `VideoModeSelection::Current` as the default video mode when entering fullscreen.
73 lines
2.6 KiB
Rust
73 lines
2.6 KiB
Rust
use alloc::{string::String, vec::Vec};
|
|
use bevy_ecs::component::Component;
|
|
use bevy_math::{IVec2, UVec2};
|
|
|
|
#[cfg(feature = "bevy_reflect")]
|
|
use {bevy_ecs::prelude::ReflectComponent, bevy_reflect::Reflect};
|
|
|
|
#[cfg(all(feature = "serialize", feature = "bevy_reflect"))]
|
|
use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
|
|
|
|
/// Represents an available monitor as reported by the user's operating system, which can be used
|
|
/// to query information about the display, such as its size, position, and video modes.
|
|
///
|
|
/// Each monitor corresponds to an entity and can be used to position a monitor using
|
|
/// [`crate::window::MonitorSelection::Entity`].
|
|
///
|
|
/// # Warning
|
|
///
|
|
/// This component is synchronized with `winit` through `bevy_winit`, but is effectively
|
|
/// read-only as `winit` does not support changing monitor properties.
|
|
#[derive(Component, Debug, Clone)]
|
|
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Component, Debug))]
|
|
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
|
#[cfg_attr(
|
|
all(feature = "serialize", feature = "bevy_reflect"),
|
|
reflect(Serialize, Deserialize)
|
|
)]
|
|
pub struct Monitor {
|
|
/// The name of the monitor
|
|
pub name: Option<String>,
|
|
/// The height of the monitor in physical pixels
|
|
pub physical_height: u32,
|
|
/// The width of the monitor in physical pixels
|
|
pub physical_width: u32,
|
|
/// The position of the monitor in physical pixels
|
|
pub physical_position: IVec2,
|
|
/// The refresh rate of the monitor in millihertz
|
|
pub refresh_rate_millihertz: Option<u32>,
|
|
/// The scale factor of the monitor
|
|
pub scale_factor: f64,
|
|
/// The video modes that the monitor supports
|
|
pub video_modes: Vec<VideoMode>,
|
|
}
|
|
|
|
/// A marker component for the primary monitor
|
|
#[derive(Component, Debug, Clone)]
|
|
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Component, Debug))]
|
|
pub struct PrimaryMonitor;
|
|
|
|
impl Monitor {
|
|
/// Returns the physical size of the monitor in pixels
|
|
pub fn physical_size(&self) -> UVec2 {
|
|
UVec2::new(self.physical_width, self.physical_height)
|
|
}
|
|
}
|
|
|
|
/// Represents a video mode that a monitor supports
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug))]
|
|
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
|
#[cfg_attr(
|
|
all(feature = "serialize", feature = "bevy_reflect"),
|
|
reflect(Serialize, Deserialize)
|
|
)]
|
|
pub struct VideoMode {
|
|
/// The resolution of the video mode
|
|
pub physical_size: UVec2,
|
|
/// The bit depth of the video mode
|
|
pub bit_depth: u16,
|
|
/// The refresh rate in millihertz
|
|
pub refresh_rate_millihertz: u32,
|
|
}
|