#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", html_favicon_url = "https://bevyengine.org/assets/icon.png" )] #![no_std] //! `bevy_window` provides a platform-agnostic interface for windowing in Bevy. //! //! This crate contains types for window management and events, //! used by windowing implementors such as `bevy_winit`. //! The [`WindowPlugin`] sets up some global window-related parameters and //! is part of the [`DefaultPlugins`](https://docs.rs/bevy/latest/bevy/struct.DefaultPlugins.html). #[cfg(feature = "std")] extern crate std; extern crate alloc; use alloc::sync::Arc; use bevy_platform_support::sync::Mutex; mod event; mod monitor; mod raw_handle; mod system; mod system_cursor; mod window; pub use crate::raw_handle::*; #[cfg(target_os = "android")] pub use android_activity; pub use event::*; pub use monitor::*; pub use system::*; pub use system_cursor::*; pub use window::*; /// The windowing prelude. /// /// This includes the most common types in this crate, re-exported for your convenience. pub mod prelude { #[doc(hidden)] pub use crate::{ CursorEntered, CursorLeft, CursorMoved, FileDragAndDrop, Ime, MonitorSelection, Window, WindowMoved, WindowPlugin, WindowPosition, WindowResizeConstraints, }; } use bevy_app::prelude::*; impl Default for WindowPlugin { fn default() -> Self { WindowPlugin { primary_window: Some(Window::default()), exit_condition: ExitCondition::OnAllClosed, close_when_requested: true, } } } /// A [`Plugin`] that defines an interface for windowing support in Bevy. pub struct WindowPlugin { /// Settings for the primary window. /// /// `Some(custom_window)` will spawn an entity with `custom_window` and [`PrimaryWindow`] as components. /// `None` will not spawn a primary window. /// /// Defaults to `Some(Window::default())`. /// /// Note that if there are no windows the App will exit (by default) due to /// [`exit_on_all_closed`]. pub primary_window: Option, /// Whether to exit the app when there are no open windows. /// /// If disabling this, ensure that you send the [`bevy_app::AppExit`] /// event when the app should exit. If this does not occur, you will /// create 'headless' processes (processes without windows), which may /// surprise your users. It is recommended to leave this setting to /// either [`ExitCondition::OnAllClosed`] or [`ExitCondition::OnPrimaryClosed`]. /// /// [`ExitCondition::OnAllClosed`] will add [`exit_on_all_closed`] to [`Update`]. /// [`ExitCondition::OnPrimaryClosed`] will add [`exit_on_primary_closed`] to [`Update`]. pub exit_condition: ExitCondition, /// Whether to close windows when they are requested to be closed (i.e. /// when the close button is pressed). /// /// If true, this plugin will add [`close_when_requested`] to [`Update`]. /// If this system (or a replacement) is not running, the close button will have no effect. /// This may surprise your users. It is recommended to leave this setting as `true`. pub close_when_requested: bool, } impl Plugin for WindowPlugin { fn build(&self, app: &mut App) { // User convenience events app.add_event::() .add_event::() .add_event::() .add_event::() .add_event::() .add_event::() .add_event::() .add_event::() .add_event::() .add_event::() .add_event::() .add_event::() .add_event::() .add_event::() .add_event::() .add_event::() .add_event::() .add_event::() .add_event::() .add_event::(); if let Some(primary_window) = &self.primary_window { app.world_mut().spawn(primary_window.clone()).insert(( PrimaryWindow, RawHandleWrapperHolder(Arc::new(Mutex::new(None))), )); } match self.exit_condition { ExitCondition::OnPrimaryClosed => { app.add_systems(PostUpdate, exit_on_primary_closed); } ExitCondition::OnAllClosed => { app.add_systems(PostUpdate, exit_on_all_closed); } ExitCondition::DontExit => {} } if self.close_when_requested { // Need to run before `exit_on_*` systems app.add_systems(Update, close_when_requested); } // Register event types #[cfg(feature = "bevy_reflect")] app.register_type::() .register_type::() .register_type::() .register_type::() .register_type::() .register_type::() .register_type::() .register_type::() .register_type::() .register_type::() .register_type::() .register_type::() .register_type::() .register_type::() .register_type::() .register_type::() .register_type::() .register_type::() .register_type::(); // Register window descriptor and related types #[cfg(feature = "bevy_reflect")] app.register_type::() .register_type::(); } } /// Defines the specific conditions the application should exit on #[derive(Clone)] pub enum ExitCondition { /// Close application when the primary window is closed /// /// The plugin will add [`exit_on_primary_closed`] to [`Update`]. OnPrimaryClosed, /// Close application when all windows are closed /// /// The plugin will add [`exit_on_all_closed`] to [`Update`]. OnAllClosed, /// Keep application running headless even after closing all windows /// /// If selecting this, ensure that you send the [`bevy_app::AppExit`] /// event when the app should exit. If this does not occur, you will /// create 'headless' processes (processes without windows), which may /// surprise your users. DontExit, } /// [`AndroidApp`] provides an interface to query the application state as well as monitor events /// (for example lifecycle and input events). #[cfg(target_os = "android")] pub static ANDROID_APP: std::sync::OnceLock = std::sync::OnceLock::new();