Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose winit's MonitorHandle #13669

Merged
merged 26 commits into from
Aug 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3344,3 +3344,14 @@ panic = "abort"
rustdoc-args = ["-Zunstable-options", "--generate-link-to-definition"]
all-features = true
cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"]

[[example]]
name = "monitor_info"
path = "examples/window/monitor_info.rs"
doc-scrape-examples = true

[package.metadata.example.monitor_info]
name = "Monitor info"
description = "Displays information about available monitors (displays)."
category = "Window"
wasm = false
2 changes: 2 additions & 0 deletions crates/bevy_window/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use bevy_a11y::Focus;

mod cursor;
mod event;
mod monitor;
mod raw_handle;
mod system;
mod window;
Expand All @@ -25,6 +26,7 @@ pub use crate::raw_handle::*;

pub use cursor::*;
pub use event::*;
pub use monitor::*;
pub use system::*;
pub use window::*;

Expand Down
69 changes: 69 additions & 0 deletions crates/bevy_window/src/monitor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use bevy_ecs::component::Component;
use bevy_ecs::prelude::ReflectComponent;
use bevy_math::{IVec2, UVec2};
use bevy_reflect::Reflect;

#[cfg(feature = "serialize")]
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
tychedelia marked this conversation as resolved.
Show resolved Hide resolved
/// read-only as `winit` does not support changing monitor properties.
#[derive(Component, Debug, Clone, Reflect)]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
reflect(Serialize, Deserialize)
)]
#[reflect(Component)]
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, Reflect)]
#[reflect(Component)]
pub struct PrimaryMonitor;
tychedelia marked this conversation as resolved.
Show resolved Hide resolved

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, Reflect)]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
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,
}
14 changes: 8 additions & 6 deletions crates/bevy_window/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,8 @@ pub enum MonitorSelection {
Primary,
/// Uses the monitor with the specified index.
Index(usize),
/// Uses a given [`crate::monitor::Monitor`] entity.
Entity(Entity),
}

/// Presentation mode for a [`Window`].
Expand Down Expand Up @@ -1092,7 +1094,7 @@ pub enum WindowMode {
#[default]
Windowed,
/// The window should appear fullscreen by being borderless and using the full
/// size of the screen.
/// size of the screen on the given [`MonitorSelection`].
///
/// 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
Expand All @@ -1102,17 +1104,17 @@ pub enum WindowMode {
/// the window's logical size may be different from its physical size.
/// If you want to avoid that behavior, you can use the [`WindowResolution::set_scale_factor_override`] function
/// or the [`WindowResolution::with_scale_factor_override`] builder method to set the scale factor to 1.0.
BorderlessFullscreen,
/// The window should be in "true"/"legacy" Fullscreen mode.
BorderlessFullscreen(MonitorSelection),
/// The window should be in "true"/"legacy" Fullscreen mode on the given [`MonitorSelection`].
///
/// 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,
/// The window should be in "true"/"legacy" Fullscreen mode.
SizedFullscreen(MonitorSelection),
/// The window should be in "true"/"legacy" Fullscreen mode on the given [`MonitorSelection`].
///
/// When setting this, the operating system will be requested to use the
/// **biggest** resolution available for the current monitor.
Expand All @@ -1124,7 +1126,7 @@ pub enum WindowMode {
/// the window's logical size may be different from its physical size.
/// If you want to avoid that behavior, you can use the [`WindowResolution::set_scale_factor_override`] function
/// or the [`WindowResolution::with_scale_factor_override`] builder method to set the scale factor to 1.0.
Fullscreen,
Fullscreen(MonitorSelection),
}

/// Specifies where a [`Window`] should appear relative to other overlapping windows (on top or under) .
Expand Down
9 changes: 8 additions & 1 deletion crates/bevy_winit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,24 @@ use bevy_app::{App, Last, Plugin};
use bevy_ecs::prelude::*;
#[allow(deprecated)]
use bevy_window::{exit_on_all_closed, Window, WindowCreated};
pub use system::create_windows;
use system::{changed_windows, despawn_windows};
pub use system::{create_monitors, create_windows};
pub use winit::event_loop::EventLoopProxy;
pub use winit_config::*;
pub use winit_event::*;
pub use winit_windows::*;

use crate::accessibility::{AccessKitAdapters, AccessKitPlugin, WinitActionRequestHandlers};
use crate::state::winit_runner;
use crate::winit_monitors::WinitMonitors;

pub mod accessibility;
mod converters;
mod state;
mod system;
mod winit_config;
pub mod winit_event;
mod winit_monitors;
mod winit_windows;

/// [`AndroidApp`] provides an interface to query the application state as well as monitor events
Expand Down Expand Up @@ -113,6 +115,7 @@ impl<T: Event> Plugin for WinitPlugin<T> {
}

app.init_non_send_resource::<WinitWindows>()
.init_resource::<WinitMonitors>()
.init_resource::<WinitSettings>()
.add_event::<WinitEvent>()
.set_runner(winit_runner::<T>)
Expand Down Expand Up @@ -181,4 +184,8 @@ pub type CreateWindowParams<'w, 's, F = ()> = (
NonSendMut<'w, AccessKitAdapters>,
ResMut<'w, WinitActionRequestHandlers>,
Res<'w, AccessibilityRequested>,
Res<'w, WinitMonitors>,
);

/// The parameters of the [`create_monitors`] system.
pub type CreateMonitorParams<'w, 's> = (Commands<'w, 's>, ResMut<'w, WinitMonitors>);
11 changes: 8 additions & 3 deletions crates/bevy_winit/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ use bevy_window::{
use bevy_window::{PrimaryWindow, RawHandleWrapper};

use crate::accessibility::AccessKitAdapters;
use crate::system::CachedWindow;
use crate::system::{create_monitors, CachedWindow};
use crate::{
converters, create_windows, AppSendEvent, CreateWindowParams, EventLoopProxyWrapper,
UpdateMode, WinitEvent, WinitSettings, WinitWindows,
converters, create_windows, AppSendEvent, CreateMonitorParams, CreateWindowParams,
EventLoopProxyWrapper, UpdateMode, WinitEvent, WinitSettings, WinitWindows,
};

/// Persistent state that is used to run the [`App`] according to the current
Expand Down Expand Up @@ -401,10 +401,13 @@ impl<T: Event> ApplicationHandler<T> for WinitAppRunnerState<T> {
}

fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) {
let mut create_monitor = SystemState::<CreateMonitorParams>::from_world(self.world_mut());
// create any new windows
// (even if app did not update, some may have been created by plugin setup)
let mut create_window =
SystemState::<CreateWindowParams<Added<Window>>>::from_world(self.world_mut());
create_monitors(event_loop, create_monitor.get_mut(self.world_mut()));
create_monitor.apply(self.world_mut());
create_windows(event_loop, create_window.get_mut(self.world_mut()));
create_window.apply(self.world_mut());

Expand Down Expand Up @@ -475,6 +478,7 @@ impl<T: Event> ApplicationHandler<T> for WinitAppRunnerState<T> {
mut adapters,
mut handlers,
accessibility_requested,
monitors,
) = create_window.get_mut(self.world_mut());

let winit_window = winit_windows.create_window(
Expand All @@ -484,6 +488,7 @@ impl<T: Event> ApplicationHandler<T> for WinitAppRunnerState<T> {
&mut adapters,
&mut handlers,
&accessibility_requested,
&monitors,
);

let wrapper = RawHandleWrapper::new(winit_window).unwrap();
Expand Down
Loading
Loading