Update and improve Window Documentation (#8858)

# Objective

Improve the documentation relating to windows, and update the parts that
have not been updated since version 0.8.

Version 0.9 introduced `Window` as a component, before that
`WindowDescriptor` (which would become `Window` later) was used to store
information about how a window will be created. Since version 0.9, from
my understanding, this information will also be synchronised with the
current state of the window, and can be used to modify this state.

However, some of the documentation has not been updated to reflect that,
here is an example:
https://docs.rs/bevy/0.8.0/bevy/window/enum.WindowMode.html /
https://docs.rs/bevy/latest/bevy/window/enum.WindowMode.html (notice
that the verb "Creates" is still there).

This PR aims at improving the documentation relating to windows.

## Solution

- Change "will" for "should" when relevant, "should" implies that the
information should in both direction (from the window state to the
`Window` component and vice-versa) and can be used to get and set, will
implies it is only used to set a state.
- Remove references to "creation" or be more clear about it.
- Reference back the `Window` component for most of its sub-structs.
- Clarify what needs to be clarified
- A lot of other minor changes, including fixing the link to W3schools
in `bevy_winit`

## Warning

Please note that my knowledge about how winit and bevy_winit work is
limited and some of the informations I added in the doc may be
inaccurate. A person who knows better how it works should review some of
my claims, in particular:
- How fullscreen works:
https://github.com/bevyengine/bevy/pull/8858#discussion_r1232413155
- How WindowResolution / sizes work:
https://github.com/bevyengine/bevy/pull/8858#discussion_r1233010719
- What happens when `WindowPosition` is set to `Centered` or
`Automatic`. From my understanding of the code, it should always be set
back to `At`, but is it really the case? For example [when creating the
window](https://github.com/bevyengine/bevy/blob/main/crates/bevy_winit/src/winit_windows.rs#L74),
or when [a `WindowEvent::Moved` is
triggered](https://github.com/bevyengine/bevy/blob/main/crates/bevy_winit/src/lib.rs#L602)
or when [Centered/Automatic by the code after the window is
created](https://github.com/bevyengine/bevy/blob/main/crates/bevy_winit/src/system.rs#L243),
am I missing some cases and do the codes I linked do that in all of
them?
- Are there any field in the `Window` component that can't be used to
modify the state of the window, only at creation?

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Jerome Humbert <djeedai@gmail.com>
This commit is contained in:
Sélène Amanita 2023-06-22 04:00:40 +01:00 committed by GitHub
parent 0f242eae5d
commit f7ea93a7cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 163 additions and 57 deletions

View File

@ -76,8 +76,8 @@ pub struct ComputedCameraValues {
old_viewport_size: Option<UVec2>,
}
/// The defining component for camera entities, storing information about how and what to render
/// through this camera.
/// The defining [`Component`] for camera entities,
/// storing information about how and what to render through this camera.
///
/// The [`Camera`] component is added to an entity to define the properties of the viewpoint from
/// which rendering occurs. It defines the position of the view to render, the projection method

View File

@ -3,9 +3,9 @@ use bevy_reflect::{prelude::ReflectDefault, FromReflect, Reflect, ReflectFromRef
#[cfg(feature = "serialize")]
use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
/// The icon to display for a window's cursor.
/// The icon to display for a [`Window`](crate::window::Window)'s [`Cursor`](crate::window::Cursor).
///
/// Examples of all of these cursors can be found [here](https://www.w3schools.com/cssref/playit.asp?filename=playcss_cursor).
/// Examples of all of these cursors can be found [here](https://www.w3schools.com/cssref/playit.php?filename=playcss_cursor&preval=crosshair).
/// This `enum` is simply a copy of a similar `enum` found in [`winit`](https://docs.rs/winit/latest/winit/window/enum.CursorIcon.html).
/// `winit`, in turn, mostly copied cursor types available in the browser.
#[derive(Default, Debug, Hash, PartialEq, Eq, Clone, Copy, Reflect, FromReflect)]

View File

@ -12,16 +12,19 @@ use bevy_utils::tracing::warn;
use crate::CursorIcon;
/// Marker component for the window considered the primary window.
/// Marker [`Component`] for the window considered the primary window.
///
/// Currently this is assumed to only exist on 1 entity at a time.
///
/// [`WindowPlugin`](crate::WindowPlugin) will spawn a window entity
/// with this component if `primary_window` is `Some`.
#[derive(
Default, Debug, Component, PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Reflect, FromReflect,
)]
#[reflect(Component, FromReflect)]
pub struct PrimaryWindow;
/// Reference to a window, whether it be a direct link to a specific entity or
/// Reference to a [`Window`], whether it be a direct link to a specific entity or
/// a more vague defaulting choice.
#[repr(C)]
#[derive(Default, Copy, Clone, Debug, Reflect, FromReflect)]
@ -86,7 +89,15 @@ impl NormalizedWindowRef {
}
}
/// Define how a window will be created and how it will behave.
/// The defining [`Component`] for window entities,
/// storing information about how it should appear and behave.
///
/// Each window corresponds to an entity, and is uniquely identified by the value of their [`Entity`].
/// When the [`Window`] component is added to an entity, a new window will be opened.
/// When it is removed or the entity is despawned, the window will close.
///
/// This component is synchronized with `winit` through `bevy_winit`:
/// it will reflect the current state of the window and can be modified to change this state.
#[derive(Component, Debug, Clone, Reflect, FromReflect)]
#[cfg_attr(
feature = "serialize",
@ -99,7 +110,7 @@ pub struct Window {
pub cursor: Cursor,
/// What presentation mode to give the window.
pub present_mode: PresentMode,
/// Which fullscreen or windowing mode should be used?
/// Which fullscreen or windowing mode should be used.
pub mode: WindowMode,
/// Where the window should be placed.
pub position: WindowPosition,
@ -109,7 +120,8 @@ pub struct Window {
pub title: String,
/// How the alpha channel of textures should be handled while compositing.
pub composite_alpha_mode: CompositeAlphaMode,
/// Which size limits to give the window.
/// The limits of the window's logical size
/// (found in its [`resolution`](WindowResolution)) when resizing.
pub resize_constraints: WindowResizeConstraints,
/// Should the window be resizable?
///
@ -135,9 +147,9 @@ pub struct Window {
/// macOS X transparent works with winit out of the box, so this issue might be related to: <https://github.com/gfx-rs/wgpu/issues/687>.
/// You should also set the window `composite_alpha_mode` to `CompositeAlphaMode::PostMultiplied`.
pub transparent: bool,
/// Should the window start focused?
/// Get/set whether the window is focused.
pub focused: bool,
/// Should the window always be on top of other windows?
/// Where should the window appear relative to other overlapping window.
///
/// ## Platform-specific
///
@ -239,36 +251,50 @@ impl Window {
}
/// The window's client area width in logical pixels.
///
/// See [`WindowResolution`] for an explanation about logical/physical sizes.
#[inline]
pub fn width(&self) -> f32 {
self.resolution.width()
}
/// The window's client area height in logical pixels.
///
/// See [`WindowResolution`] for an explanation about logical/physical sizes.
#[inline]
pub fn height(&self) -> f32 {
self.resolution.height()
}
/// The window's client area width in physical pixels.
///
/// See [`WindowResolution`] for an explanation about logical/physical sizes.
#[inline]
pub fn physical_width(&self) -> u32 {
self.resolution.physical_width()
}
/// The window's client area height in physical pixels.
///
/// See [`WindowResolution`] for an explanation about logical/physical sizes.
#[inline]
pub fn physical_height(&self) -> u32 {
self.resolution.physical_height()
}
/// The window's scale factor.
///
/// Ratio of physical size to logical size, see [`WindowResolution`].
#[inline]
pub fn scale_factor(&self) -> f64 {
self.resolution.scale_factor()
}
/// The cursor position in this window
/// The cursor position in this window in logical pixels.
///
/// Returns `None` if the cursor is outside the window area.
///
/// See [`WindowResolution`] for an explanation about logical/physical sizes.
#[inline]
pub fn cursor_position(&self) -> Option<Vec2> {
self.internal
@ -276,7 +302,11 @@ impl Window {
.map(|position| (position / self.scale_factor()).as_vec2())
}
/// The physical cursor position in this window
/// The cursor position in this window in physical pixels.
///
/// Returns `None` if the cursor is outside the window area.
///
/// See [`WindowResolution`] for an explanation about logical/physical sizes.
#[inline]
pub fn physical_cursor_position(&self) -> Option<Vec2> {
self.internal
@ -284,22 +314,27 @@ impl Window {
.map(|position| position.as_vec2())
}
/// Set the cursor position in this window
/// Set the cursor position in this window in logical pixels.
///
/// See [`WindowResolution`] for an explanation about logical/physical sizes.
pub fn set_cursor_position(&mut self, position: Option<Vec2>) {
self.internal.physical_cursor_position =
position.map(|p| p.as_dvec2() * self.scale_factor());
}
/// Set the physical cursor position in this window
/// Set the cursor position in this window in physical pixels.
///
/// See [`WindowResolution`] for an explanation about logical/physical sizes.
pub fn set_physical_cursor_position(&mut self, position: Option<DVec2>) {
self.internal.physical_cursor_position = position;
}
}
/// The size limits on a window.
/// The size limits on a [`Window`].
///
/// These values are measured in logical pixels, so the user's
/// These values are measured in logical pixels (see [`WindowResolution`]), so the user's
/// scale factor does affect the size limits on the window.
///
/// Please note that if the window is resizable, then when the window is
/// maximized it may have a size outside of these limits. The functionality
/// required to disable maximizing is not yet exposed by winit.
@ -369,7 +404,7 @@ impl WindowResizeConstraints {
}
}
/// Stores data about the window's cursor.
/// Cursor data for a [`Window`].
#[derive(Debug, Copy, Clone, Reflect, FromReflect)]
#[cfg_attr(
feature = "serialize",
@ -378,7 +413,7 @@ impl WindowResizeConstraints {
)]
#[reflect(Debug, Default, FromReflect)]
pub struct Cursor {
/// Get the current [`CursorIcon`] while inside the window.
/// What the cursor should look like while inside the window.
pub icon: CursorIcon,
/// Whether the cursor is visible or not.
@ -391,7 +426,7 @@ pub struct Cursor {
/// - **`iOS`** and **`Android`** do not have cursors
pub visible: bool,
/// Whether or not the cursor is locked.
/// Whether or not the cursor is locked by or confined within the window.
///
/// ## Platform-specific
///
@ -421,7 +456,7 @@ impl Default for Cursor {
}
}
/// Defines where window should be placed at on creation.
/// Defines where a [`Window`] should be placed on the screen.
#[derive(Default, Debug, Clone, Copy, PartialEq, Reflect, FromReflect)]
#[cfg_attr(
feature = "serialize",
@ -430,14 +465,19 @@ impl Default for Cursor {
)]
#[reflect(Debug, PartialEq, FromReflect)]
pub enum WindowPosition {
/// Position will be set by the window manager
/// Position will be set by the window manager.
/// Bevy will delegate this decision to the window manager and no guarantees can be made about where the window will be placed.
///
/// Used at creation but will be changed to [`At`](WindowPosition::At).
#[default]
Automatic,
/// Window will be centered on the selected monitor
/// Window will be centered on the selected monitor.
///
/// Note that this does not account for window decorations.
///
/// Used at creation or for update but will be changed to [`At`](WindowPosition::At)
Centered(MonitorSelection),
/// The window's top-left corner will be placed at the specified position (in physical pixels)
/// The window's top-left corner should be placed at the specified position (in physical pixels).
///
/// (0,0) represents top-left corner of screen space.
At(IVec2),
@ -460,19 +500,52 @@ impl WindowPosition {
}
}
/// ## Window Sizes
/// Controls the size of a [`Window`]
///
/// There are three sizes associated with a window. The physical size which is
/// the height and width in physical pixels on the monitor. The logical size
/// which is the physical size scaled by an operating system provided factor to
/// account for monitors with differing pixel densities or user preference. And
/// the requested size, measured in logical pixels, which is the value submitted
/// ## Physical, logical and requested sizes
///
/// There are three sizes associated with a window:
/// - the physical size,
/// which represents the actual height and width in physical pixels
/// the window occupies on the monitor,
/// - the logical size,
/// which represents the size that should be used to scale elements
/// inside the window, measured in logical pixels,
/// - the requested size,
/// measured in logical pixels, which is the value submitted
/// to the API when creating the window, or requesting that it be resized.
///
/// The actual size, in logical pixels, of the window may not match the
/// requested size due to operating system limits on the window size, or the
/// quantization of the logical size when converting the physical size to the
/// logical size through the scaling factor.
/// ## Scale factor
///
/// The reason logical size and physical size are separated and can be different
/// is to account for the cases where:
/// - several monitors have different pixel densities,
/// - the user has set up a pixel density preference in its operating system,
/// - the Bevy `App` has specified a specific scale factor between both.
///
/// The factor between physical size and logical size can be retrieved with
/// [`WindowResolution::scale_factor`].
///
/// For the first two cases, a scale factor is set automatically by the operating
/// system through the window backend. You can get it with
/// [`WindowResolution::base_scale_factor`].
///
/// For the third case, you can override this automatic scale factor with
/// [`WindowResolution::set_scale_factor_override`].
///
/// ## Requested and obtained sizes
///
/// The logical size should be equal to the requested size after creating/resizing,
/// when possible.
/// The reason the requested size and logical size might be different
/// is because the corresponding physical size might exceed limits (either the
/// size limits of the monitor, or limits defined in [`WindowResizeConstraints`]).
///
/// Note: The requested size is not kept in memory, for example requesting a size
/// too big for the screen, making the logical size different from the requested size,
/// and then setting a scale factor that makes the previous requested size within
/// the limits of the screen will not get back that previous requested size.
#[derive(Debug, Clone, PartialEq, Reflect, FromReflect)]
#[cfg_attr(
feature = "serialize",
@ -481,9 +554,17 @@ impl WindowPosition {
)]
#[reflect(Debug, PartialEq, Default, FromReflect)]
pub struct WindowResolution {
/// Width of the window in physical pixels.
physical_width: u32,
/// Height of the window in physical pixels.
physical_height: u32,
/// Code-provided ratio of physical size to logical size.
///
/// Should be used instead `scale_factor` when set.
scale_factor_override: Option<f64>,
/// OS-provided ratio of physical size to logical size.
///
/// Set automatically depending on the pixel density of the screen.
scale_factor: f64,
}
@ -520,7 +601,7 @@ impl WindowResolution {
(self.physical_width() as f64 / self.scale_factor()) as f32
}
/// The window's client area width in logical pixels.
/// The window's client area height in logical pixels.
#[inline]
pub fn height(&self) -> f32 {
(self.physical_height() as f64 / self.scale_factor()) as f32
@ -538,7 +619,7 @@ impl WindowResolution {
self.physical_height
}
/// The ratio of physical pixels to logical pixels
/// The ratio of physical pixels to logical pixels.
///
/// `physical_pixels = logical_pixels * scale_factor`
pub fn scale_factor(&self) -> f64 {
@ -590,6 +671,9 @@ impl WindowResolution {
}
/// Set the window's scale factor, this will be used over what the backend decides.
///
/// This can change the logical and physical sizes if the resulting physical
/// size is not within the limits.
#[inline]
pub fn set_scale_factor_override(&mut self, scale_factor_override: Option<f64>) {
let (width, height) = (self.width(), self.height());
@ -628,7 +712,7 @@ impl From<bevy_math::DVec2> for WindowResolution {
}
}
/// Defines if and how the cursor is grabbed.
/// Defines if and how the [`Cursor`] is grabbed by a [`Window`].
///
/// ## Platform-specific
///
@ -654,7 +738,7 @@ pub enum CursorGrabMode {
Locked,
}
/// Stores internal state that isn't directly accessible.
/// Stores internal [`Window`] state that isn't directly accessible.
#[derive(Default, Debug, Copy, Clone, PartialEq, Reflect, FromReflect)]
#[cfg_attr(
feature = "serialize",
@ -683,7 +767,9 @@ impl InternalWindowState {
}
}
/// Defines which monitor to use.
/// References a screen monitor.
///
/// Used when centering a [`Window`] on a monitor.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Reflect, FromReflect)]
#[cfg_attr(
feature = "serialize",
@ -692,17 +778,18 @@ impl InternalWindowState {
)]
#[reflect(Debug, PartialEq, FromReflect)]
pub enum MonitorSelection {
/// Uses current monitor of the window.
/// Uses the current monitor of the window.
///
/// Will fall back to the system default if the window has not yet been created.
/// If [`WindowPosition::Centered(MonitorSelection::Current)`](WindowPosition::Centered) is used when creating a window,
/// the window doesn't have a monitor yet, this will fall back to [`WindowPosition::Automatic`].
Current,
/// Uses primary monitor of the system.
/// Uses the primary monitor of the system.
Primary,
/// Uses monitor with the specified index.
/// Uses the monitor with the specified index.
Index(usize),
}
/// Presentation mode for a window.
/// Presentation mode for a [`Window`].
///
/// The presentation mode specifies when a frame is presented to the window. The [`Fifo`]
/// option corresponds to a traditional `VSync`, where the framerate is capped by the
@ -760,7 +847,7 @@ pub enum PresentMode {
Fifo = 4, // NOTE: The explicit ordinal values mirror wgpu.
}
/// Specifies how the alpha channel of the textures should be handled during compositing.
/// Specifies how the alpha channel of the textures should be handled during compositing, for a [`Window`].
#[repr(C)]
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash, Reflect, FromReflect)]
#[cfg_attr(
@ -796,7 +883,7 @@ pub enum CompositeAlphaMode {
Inherit = 4,
}
/// Defines the way a window is displayed
/// Defines the way a [`Window`] is displayed.
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Reflect, FromReflect)]
#[cfg_attr(
feature = "serialize",
@ -805,22 +892,41 @@ pub enum CompositeAlphaMode {
)]
#[reflect(Debug, PartialEq, FromReflect)]
pub enum WindowMode {
/// Creates a window that uses the given size.
/// The window should take a portion of the screen, using the window resolution size.
#[default]
Windowed,
/// Creates a borderless window that uses the full size of the screen.
/// The window should appear fullscreen by being borderless and using the full
/// size of the screen.
///
/// When setting this, the window's physical size will be modified to match the size
/// of the current monitor resolution, and the logical size will follow based
/// on the scale factor, see [`WindowResolution`].
BorderlessFullscreen,
/// Creates a fullscreen window that will render at desktop resolution. The app will use the closest supported size
/// from the given size and scale it to fit the screen.
/// The window should be in "true"/"legacy" Fullscreen mode.
///
/// When setting this, the operating system will be requested to use the
/// **closest** resolution available for the current monitor to match as
/// closely as possible the window's physical size.
/// After that, the window's physical size will be modified to match
/// that monitor resolution, and the logical size will follow based on the
/// scale factor, see [`WindowResolution`].
SizedFullscreen,
/// Creates a fullscreen window that uses the maximum supported size.
/// The window should be in "true"/"legacy" Fullscreen mode.
///
/// When setting this, the operating system will be requested to use the
/// **biggest** resolution available for the current monitor.
/// After that, the window's physical size will be modified to match
/// that monitor resolution, and the logical size will follow based on the
/// scale factor, see [`WindowResolution`].
Fullscreen,
}
/// A window level groups windows with respect to their z-position.
/// Specifies where a [`Window`] should appear relative to other overlapping windows (on top or under) .
///
/// Levels are groups of windows with respect to their z-position.
///
/// The relative ordering between windows in different window levels is fixed.
/// The z-order of a window within the same window level may change dynamically on user interaction.
/// The z-order of windows within the same window level may change dynamically on user interaction.
///
/// ## Platform-specific
///
@ -833,18 +939,18 @@ pub enum WindowMode {
)]
#[reflect(Debug, PartialEq, FromReflect)]
pub enum WindowLevel {
/// The window will always be below normal windows.
/// The window will always be below [`WindowLevel::Normal`] and [`WindowLevel::AlwaysOnTop`] windows.
///
/// This is useful for a widget-based app.
AlwaysOnBottom,
/// The default.
/// The default group.
#[default]
Normal,
/// The window will always be on top of normal windows.
/// The window will always be on top of [`WindowLevel::Normal`] and [`WindowLevel::AlwaysOnBottom`] windows.
AlwaysOnTop,
}
/// The window theme variant to use.
/// The [`Window`] theme variant to use.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Reflect, FromReflect)]
#[cfg_attr(
feature = "serialize",