mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
Allow closing windows at runtime (#3575)
# Objective Fixes #3180, builds from https://github.com/bevyengine/bevy/pull/2898 ## Solution Support requesting a window to be closed and closing a window in `bevy_window`, and handle this in `bevy_winit`. This is a stopgap until we move to windows as entites, which I'm sure I'll get around to eventually. ## Changelog ### Added - `Window::close` to allow closing windows. - `WindowClosed` to allow reacting to windows being closed. ### Changed Replaced `bevy::system::exit_on_esc_system` with `bevy:🪟:close_on_esc`. ## Fixed The app no longer exits when any window is closed. This difference is only observable when there are multiple windows. ## Migration Guide `bevy::input::system::exit_on_esc_system` has been removed. Use `bevy:🪟:close_on_esc` instead. `CloseWindow` has been removed. Use `Window::close` instead. The `Close` variant has been added to `WindowCommand`. Handle this by closing the relevant window.
This commit is contained in:
parent
558530871d
commit
b731ebad1b
16 changed files with 182 additions and 69 deletions
|
@ -3,7 +3,6 @@ pub mod gamepad;
|
||||||
mod input;
|
mod input;
|
||||||
pub mod keyboard;
|
pub mod keyboard;
|
||||||
pub mod mouse;
|
pub mod mouse;
|
||||||
pub mod system;
|
|
||||||
pub mod touch;
|
pub mod touch;
|
||||||
|
|
||||||
pub use axis::*;
|
pub use axis::*;
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
use crate::{ButtonState, KeyCode, KeyboardInput};
|
|
||||||
use bevy_app::AppExit;
|
|
||||||
use bevy_ecs::prelude::{EventReader, EventWriter};
|
|
||||||
|
|
||||||
/// Sends an [`AppExit`] event whenever the `ESC` key is pressed.
|
|
||||||
///
|
|
||||||
/// ## Note
|
|
||||||
///
|
|
||||||
/// This system is not added as part of the `DefaultPlugins`. You can add the [`exit_on_esc_system`]
|
|
||||||
/// yourself if desired.
|
|
||||||
pub fn exit_on_esc_system(
|
|
||||||
mut keyboard_input_events: EventReader<KeyboardInput>,
|
|
||||||
mut app_exit_events: EventWriter<AppExit>,
|
|
||||||
) {
|
|
||||||
for event in keyboard_input_events.iter() {
|
|
||||||
if let Some(key_code) = event.key_code {
|
|
||||||
if event.state == ButtonState::Pressed && key_code == KeyCode::Escape {
|
|
||||||
app_exit_events.send_default();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -7,7 +7,7 @@ use crate::{
|
||||||
use bevy_app::{App, Plugin};
|
use bevy_app::{App, Plugin};
|
||||||
use bevy_ecs::prelude::*;
|
use bevy_ecs::prelude::*;
|
||||||
use bevy_utils::{tracing::debug, HashMap, HashSet};
|
use bevy_utils::{tracing::debug, HashMap, HashSet};
|
||||||
use bevy_window::{PresentMode, RawWindowHandleWrapper, WindowId, Windows};
|
use bevy_window::{PresentMode, RawWindowHandleWrapper, WindowClosed, WindowId, Windows};
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use wgpu::TextureFormat;
|
use wgpu::TextureFormat;
|
||||||
|
|
||||||
|
@ -67,8 +67,12 @@ impl DerefMut for ExtractedWindows {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_windows(mut render_world: ResMut<RenderWorld>, windows: Res<Windows>) {
|
fn extract_windows(
|
||||||
let mut extracted_windows = render_world.resource_mut::<ExtractedWindows>();
|
mut render_world: ResMut<RenderWorld>,
|
||||||
|
mut closed: EventReader<WindowClosed>,
|
||||||
|
windows: Res<Windows>,
|
||||||
|
) {
|
||||||
|
let mut extracted_windows = render_world.get_resource_mut::<ExtractedWindows>().unwrap();
|
||||||
for window in windows.iter() {
|
for window in windows.iter() {
|
||||||
let (new_width, new_height) = (
|
let (new_width, new_height) = (
|
||||||
window.physical_width().max(1),
|
window.physical_width().max(1),
|
||||||
|
@ -105,6 +109,9 @@ fn extract_windows(mut render_world: ResMut<RenderWorld>, windows: Res<Windows>)
|
||||||
extracted_window.physical_height = new_height;
|
extracted_window.physical_height = new_height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for closed_window in closed.iter() {
|
||||||
|
extracted_windows.remove(&closed_window.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
|
@ -14,6 +14,8 @@ bevy_app = { path = "../bevy_app", version = "0.8.0-dev" }
|
||||||
bevy_ecs = { path = "../bevy_ecs", version = "0.8.0-dev" }
|
bevy_ecs = { path = "../bevy_ecs", version = "0.8.0-dev" }
|
||||||
bevy_math = { path = "../bevy_math", version = "0.8.0-dev" }
|
bevy_math = { path = "../bevy_math", version = "0.8.0-dev" }
|
||||||
bevy_utils = { path = "../bevy_utils", version = "0.8.0-dev" }
|
bevy_utils = { path = "../bevy_utils", version = "0.8.0-dev" }
|
||||||
|
# Used for close_on_esc
|
||||||
|
bevy_input = { path = "../bevy_input", version = "0.8.0-dev" }
|
||||||
raw-window-handle = "0.4.2"
|
raw-window-handle = "0.4.2"
|
||||||
|
|
||||||
# other
|
# other
|
||||||
|
|
|
@ -25,25 +25,40 @@ pub struct CreateWindow {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct RequestRedraw;
|
pub struct RequestRedraw;
|
||||||
|
|
||||||
/// An event that indicates a window should be closed.
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct CloseWindow {
|
|
||||||
pub id: WindowId,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An event that is sent whenever a new window is created.
|
/// An event that is sent whenever a new window is created.
|
||||||
|
///
|
||||||
|
/// To create a new window, send a [`CreateWindow`] event - this
|
||||||
|
/// event will be sent in the handler for that event.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct WindowCreated {
|
pub struct WindowCreated {
|
||||||
pub id: WindowId,
|
pub id: WindowId,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An event that is sent whenever a close was requested for a window. For example: when the "close"
|
/// An event that is sent whenever the operating systems requests that a window
|
||||||
/// button is pressed on a window.
|
/// be closed. This will be sent when the close button of the window is pressed.
|
||||||
|
///
|
||||||
|
/// If the default [`WindowPlugin`] is used, these events are handled
|
||||||
|
/// by [closing] the corresponding [`Window`].
|
||||||
|
/// To disable this behaviour, set `close_when_requested` on the [`WindowPlugin`]
|
||||||
|
/// to `false`.
|
||||||
|
///
|
||||||
|
/// [`WindowPlugin`]: crate::WindowPlugin
|
||||||
|
/// [`Window`]: crate::Window
|
||||||
|
/// [closing]: crate::Window::close
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct WindowCloseRequested {
|
pub struct WindowCloseRequested {
|
||||||
pub id: WindowId,
|
pub id: WindowId,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An event that is sent whenever a window is closed. This will be sent by the
|
||||||
|
/// handler for [`Window::close`].
|
||||||
|
///
|
||||||
|
/// [`Window::close`]: crate::Window::close
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct WindowClosed {
|
||||||
|
pub id: WindowId,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct CursorMoved {
|
pub struct CursorMoved {
|
||||||
pub id: WindowId,
|
pub id: WindowId,
|
||||||
|
|
|
@ -24,15 +24,34 @@ use bevy_app::prelude::*;
|
||||||
use bevy_ecs::{event::Events, schedule::SystemLabel};
|
use bevy_ecs::{event::Events, schedule::SystemLabel};
|
||||||
|
|
||||||
pub struct WindowPlugin {
|
pub struct WindowPlugin {
|
||||||
|
/// Whether to create a window when added.
|
||||||
|
///
|
||||||
|
/// Note that if there are no windows, by default the App will exit,
|
||||||
|
/// due to [`exit_on_all_closed`].
|
||||||
pub add_primary_window: bool,
|
pub add_primary_window: bool,
|
||||||
pub exit_on_close: bool,
|
/// 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 as `true`.
|
||||||
|
///
|
||||||
|
/// If true, this plugin will add [`exit_on_all_closed`] to [`CoreStage::Update`].
|
||||||
|
pub exit_on_all_closed: bool,
|
||||||
|
/// 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 [`CoreStage::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 Default for WindowPlugin {
|
impl Default for WindowPlugin {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
WindowPlugin {
|
WindowPlugin {
|
||||||
add_primary_window: true,
|
add_primary_window: true,
|
||||||
exit_on_close: true,
|
exit_on_all_closed: true,
|
||||||
|
close_when_requested: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,9 +61,9 @@ impl Plugin for WindowPlugin {
|
||||||
app.add_event::<WindowResized>()
|
app.add_event::<WindowResized>()
|
||||||
.add_event::<CreateWindow>()
|
.add_event::<CreateWindow>()
|
||||||
.add_event::<WindowCreated>()
|
.add_event::<WindowCreated>()
|
||||||
|
.add_event::<WindowClosed>()
|
||||||
.add_event::<WindowCloseRequested>()
|
.add_event::<WindowCloseRequested>()
|
||||||
.add_event::<RequestRedraw>()
|
.add_event::<RequestRedraw>()
|
||||||
.add_event::<CloseWindow>()
|
|
||||||
.add_event::<CursorMoved>()
|
.add_event::<CursorMoved>()
|
||||||
.add_event::<CursorEntered>()
|
.add_event::<CursorEntered>()
|
||||||
.add_event::<CursorLeft>()
|
.add_event::<CursorLeft>()
|
||||||
|
@ -69,8 +88,11 @@ impl Plugin for WindowPlugin {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.exit_on_close {
|
if self.exit_on_all_closed {
|
||||||
app.add_system(exit_on_window_close_system);
|
app.add_system(exit_on_all_closed);
|
||||||
|
}
|
||||||
|
if self.close_when_requested {
|
||||||
|
app.add_system(close_when_requested);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,57 @@
|
||||||
use crate::WindowCloseRequested;
|
use crate::{Window, WindowCloseRequested, WindowFocused, WindowId, Windows};
|
||||||
use bevy_app::AppExit;
|
|
||||||
use bevy_ecs::event::{EventReader, EventWriter};
|
|
||||||
|
|
||||||
pub fn exit_on_window_close_system(
|
use bevy_app::AppExit;
|
||||||
mut app_exit_events: EventWriter<AppExit>,
|
use bevy_ecs::prelude::*;
|
||||||
mut window_close_requested_events: EventReader<WindowCloseRequested>,
|
use bevy_input::{keyboard::KeyCode, Input};
|
||||||
) {
|
|
||||||
if window_close_requested_events.iter().next().is_some() {
|
/// Exit the application when there are no open windows.
|
||||||
|
///
|
||||||
|
/// This system is added by the [`WindowPlugin`] in the default configuration.
|
||||||
|
/// To disable this behaviour, set `close_when_requested` (on the [`WindowPlugin`]) to `false`.
|
||||||
|
/// Ensure that you read the caveats documented on that field if doing so.
|
||||||
|
///
|
||||||
|
/// [`WindowPlugin`]: crate::WindowPlugin
|
||||||
|
pub fn exit_on_all_closed(mut app_exit_events: EventWriter<AppExit>, windows: Res<Windows>) {
|
||||||
|
if windows.iter().count() == 0 {
|
||||||
app_exit_events.send(AppExit);
|
app_exit_events.send(AppExit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Close windows in response to [`WindowCloseRequested`] (e.g. when the close button is pressed).
|
||||||
|
///
|
||||||
|
/// This system is added by the [`WindowPlugin`] in the default configuration.
|
||||||
|
/// To disable this behaviour, set `close_when_requested` (on the [`WindowPlugin`]) to `false`.
|
||||||
|
/// Ensure that you read the caveats documented on that field if doing so.
|
||||||
|
///
|
||||||
|
/// [`WindowPlugin`]: crate::WindowPlugin
|
||||||
|
pub fn close_when_requested(
|
||||||
|
mut windows: ResMut<Windows>,
|
||||||
|
mut closed: EventReader<WindowCloseRequested>,
|
||||||
|
) {
|
||||||
|
for event in closed.iter() {
|
||||||
|
windows.get_mut(event.id).map(Window::close);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Close the focused window whenever the escape key (<kbd>Esc</kbd>) is pressed
|
||||||
|
///
|
||||||
|
/// This is useful for examples or prototyping.
|
||||||
|
pub fn close_on_esc(
|
||||||
|
mut focused: Local<Option<WindowId>>,
|
||||||
|
mut focused_events: EventReader<WindowFocused>,
|
||||||
|
mut windows: ResMut<Windows>,
|
||||||
|
input: Res<Input<KeyCode>>,
|
||||||
|
) {
|
||||||
|
// TODO: Track this in e.g. a resource to ensure consistent behaviour across similar systems
|
||||||
|
for event in focused_events.iter() {
|
||||||
|
*focused = event.focused.then(|| event.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(focused) = &*focused {
|
||||||
|
if input.just_pressed(KeyCode::Escape) {
|
||||||
|
if let Some(window) = windows.get_mut(*focused) {
|
||||||
|
window.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -219,6 +219,7 @@ pub enum WindowCommand {
|
||||||
SetResizeConstraints {
|
SetResizeConstraints {
|
||||||
resize_constraints: WindowResizeConstraints,
|
resize_constraints: WindowResizeConstraints,
|
||||||
},
|
},
|
||||||
|
Close,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Defines the way a window is displayed
|
/// Defines the way a window is displayed
|
||||||
|
@ -571,6 +572,21 @@ impl Window {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Close the operating system window corresponding to this [`Window`].
|
||||||
|
/// This will also lead to this [`Window`] being removed from the
|
||||||
|
/// [`Windows`] resource.
|
||||||
|
///
|
||||||
|
/// If the default [`WindowPlugin`] is used, when no windows are
|
||||||
|
/// open, the [app will exit](bevy_app::AppExit).
|
||||||
|
/// To disable this behaviour, set `exit_on_all_closed` on the [`WindowPlugin`]
|
||||||
|
/// to `false`
|
||||||
|
///
|
||||||
|
/// [`Windows`]: crate::Windows
|
||||||
|
/// [`WindowPlugin`]: crate::WindowPlugin
|
||||||
|
pub fn close(&mut self) {
|
||||||
|
self.command_queue.push(WindowCommand::Close);
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn drain_commands(&mut self) -> impl Iterator<Item = WindowCommand> + '_ {
|
pub fn drain_commands(&mut self) -> impl Iterator<Item = WindowCommand> + '_ {
|
||||||
self.command_queue.drain(..)
|
self.command_queue.drain(..)
|
||||||
|
|
|
@ -70,4 +70,8 @@ impl Windows {
|
||||||
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Window> {
|
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Window> {
|
||||||
self.windows.values_mut()
|
self.windows.values_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn remove(&mut self, id: WindowId) -> Option<Window> {
|
||||||
|
self.windows.remove(&id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,39 +2,38 @@ mod converters;
|
||||||
mod winit_config;
|
mod winit_config;
|
||||||
mod winit_windows;
|
mod winit_windows;
|
||||||
|
|
||||||
|
pub use winit_config::*;
|
||||||
|
pub use winit_windows::*;
|
||||||
|
|
||||||
|
use bevy_app::{App, AppExit, CoreStage, Plugin};
|
||||||
|
use bevy_ecs::prelude::*;
|
||||||
|
use bevy_ecs::{
|
||||||
|
event::{Events, ManualEventReader},
|
||||||
|
world::World,
|
||||||
|
};
|
||||||
use bevy_input::{
|
use bevy_input::{
|
||||||
keyboard::KeyboardInput,
|
keyboard::KeyboardInput,
|
||||||
mouse::{MouseButtonInput, MouseMotion, MouseScrollUnit, MouseWheel},
|
mouse::{MouseButtonInput, MouseMotion, MouseScrollUnit, MouseWheel},
|
||||||
touch::TouchInput,
|
touch::TouchInput,
|
||||||
};
|
};
|
||||||
pub use winit_config::*;
|
|
||||||
pub use winit_windows::*;
|
|
||||||
|
|
||||||
use bevy_app::{App, AppExit, CoreStage, Plugin};
|
|
||||||
use bevy_ecs::{
|
|
||||||
event::{EventWriter, Events, ManualEventReader},
|
|
||||||
schedule::ParallelSystemDescriptorCoercion,
|
|
||||||
system::{NonSend, ResMut},
|
|
||||||
world::World,
|
|
||||||
};
|
|
||||||
use bevy_math::{ivec2, DVec2, Vec2};
|
use bevy_math::{ivec2, DVec2, Vec2};
|
||||||
use bevy_utils::{
|
use bevy_utils::{
|
||||||
tracing::{error, trace, warn},
|
tracing::{error, info, trace, warn},
|
||||||
Instant,
|
Instant,
|
||||||
};
|
};
|
||||||
use bevy_window::{
|
use bevy_window::{
|
||||||
CreateWindow, CursorEntered, CursorLeft, CursorMoved, FileDragAndDrop, ModifiesWindows,
|
CreateWindow, CursorEntered, CursorLeft, CursorMoved, FileDragAndDrop, ModifiesWindows,
|
||||||
ReceivedCharacter, RequestRedraw, WindowBackendScaleFactorChanged, WindowCloseRequested,
|
ReceivedCharacter, RequestRedraw, WindowBackendScaleFactorChanged, WindowCloseRequested,
|
||||||
WindowCreated, WindowFocused, WindowMoved, WindowResized, WindowScaleFactorChanged, Windows,
|
WindowClosed, WindowCreated, WindowFocused, WindowMoved, WindowResized,
|
||||||
|
WindowScaleFactorChanged, Windows,
|
||||||
};
|
};
|
||||||
|
|
||||||
use winit::{
|
use winit::{
|
||||||
dpi::PhysicalPosition,
|
dpi::{LogicalSize, PhysicalPosition},
|
||||||
event::{self, DeviceEvent, Event, StartCause, WindowEvent},
|
event::{self, DeviceEvent, Event, StartCause, WindowEvent},
|
||||||
event_loop::{ControlFlow, EventLoop, EventLoopWindowTarget},
|
event_loop::{ControlFlow, EventLoop, EventLoopWindowTarget},
|
||||||
};
|
};
|
||||||
|
|
||||||
use winit::dpi::LogicalSize;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct WinitPlugin;
|
pub struct WinitPlugin;
|
||||||
|
|
||||||
|
@ -51,10 +50,12 @@ impl Plugin for WinitPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn change_window(
|
fn change_window(
|
||||||
winit_windows: NonSend<WinitWindows>,
|
mut winit_windows: NonSendMut<WinitWindows>,
|
||||||
mut windows: ResMut<Windows>,
|
mut windows: ResMut<Windows>,
|
||||||
mut window_dpi_changed_events: EventWriter<WindowScaleFactorChanged>,
|
mut window_dpi_changed_events: EventWriter<WindowScaleFactorChanged>,
|
||||||
|
mut window_close_events: EventWriter<WindowClosed>,
|
||||||
) {
|
) {
|
||||||
|
let mut removed_windows = vec![];
|
||||||
for bevy_window in windows.iter_mut() {
|
for bevy_window in windows.iter_mut() {
|
||||||
let id = bevy_window.id();
|
let id = bevy_window.id();
|
||||||
for command in bevy_window.drain_commands() {
|
for command in bevy_window.drain_commands() {
|
||||||
|
@ -166,9 +167,25 @@ fn change_window(
|
||||||
window.set_max_inner_size(Some(max_inner_size));
|
window.set_max_inner_size(Some(max_inner_size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bevy_window::WindowCommand::Close => {
|
||||||
|
// Since we have borrowed `windows` to iterate through them, we can't remove the window from it.
|
||||||
|
// Add the removal requests to a queue to solve this
|
||||||
|
removed_windows.push(id);
|
||||||
|
// No need to run any further commands - this drops the rest of the commands, although the `bevy_window::Window` will be dropped later anyway
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if !removed_windows.is_empty() {
|
||||||
|
for id in removed_windows {
|
||||||
|
// Close the OS window. (The `Drop` impl actually closes the window)
|
||||||
|
let _ = winit_windows.remove_window(id);
|
||||||
|
// Clean up our own data structures
|
||||||
|
windows.remove(id);
|
||||||
|
window_close_events.send(WindowClosed { id });
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run<F>(event_loop: EventLoop<()>, event_handler: F) -> !
|
fn run<F>(event_loop: EventLoop<()>, event_handler: F) -> !
|
||||||
|
@ -316,7 +333,8 @@ pub fn winit_runner_with(mut app: App) {
|
||||||
let window = if let Some(window) = windows.get_mut(window_id) {
|
let window = if let Some(window) = windows.get_mut(window_id) {
|
||||||
window
|
window
|
||||||
} else {
|
} else {
|
||||||
warn!("Skipped event for unknown Window Id {:?}", winit_window_id);
|
// If we're here, this window was previously opened
|
||||||
|
info!("Skipped event for closed window: {:?}", window_id);
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
winit_state.low_power_event = true;
|
winit_state.low_power_event = true;
|
||||||
|
|
|
@ -181,6 +181,12 @@ impl WinitWindows {
|
||||||
pub fn get_window_id(&self, id: winit::window::WindowId) -> Option<WindowId> {
|
pub fn get_window_id(&self, id: winit::window::WindowId) -> Option<WindowId> {
|
||||||
self.winit_to_window_id.get(&id).cloned()
|
self.winit_to_window_id.get(&id).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn remove_window(&mut self, id: WindowId) -> Option<winit::window::Window> {
|
||||||
|
let winit_id = self.window_id_to_winit.remove(&id)?;
|
||||||
|
// Don't remove from winit_to_window_id, to track that we used to know about this winit window
|
||||||
|
self.windows.remove(&winit_id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_fitting_videomode(
|
pub fn get_fitting_videomode(
|
||||||
|
|
|
@ -18,7 +18,7 @@ fn main() {
|
||||||
.with_system(snap_to_player_system)
|
.with_system(snap_to_player_system)
|
||||||
.with_system(rotate_to_player_system),
|
.with_system(rotate_to_player_system),
|
||||||
)
|
)
|
||||||
.add_system(bevy::input::system::exit_on_esc_system)
|
.add_system(bevy::window::close_on_esc)
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ fn main() {
|
||||||
.with_run_criteria(FixedTimestep::step(5.0))
|
.with_run_criteria(FixedTimestep::step(5.0))
|
||||||
.with_system(spawn_bonus),
|
.with_system(spawn_bonus),
|
||||||
)
|
)
|
||||||
.add_system(bevy::input::system::exit_on_esc_system)
|
.add_system(bevy::window::close_on_esc)
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ fn main() {
|
||||||
.with_system(play_collision_sound.after(check_for_collisions)),
|
.with_system(play_collision_sound.after(check_for_collisions)),
|
||||||
)
|
)
|
||||||
.add_system(update_scoreboard)
|
.add_system(update_scoreboard)
|
||||||
.add_system(bevy::input::system::exit_on_esc_system)
|
.add_system(bevy::window::close_on_esc)
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ fn main() {
|
||||||
.add_plugin(SecondWindowCameraPlugin)
|
.add_plugin(SecondWindowCameraPlugin)
|
||||||
.add_startup_system(setup)
|
.add_startup_system(setup)
|
||||||
.add_startup_system(create_new_window)
|
.add_startup_system(create_new_window)
|
||||||
|
.add_system(bevy::window::close_on_esc)
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! A test to confirm that `bevy` allows setting the window to arbitrary small sizes
|
//! A test to confirm that `bevy` allows setting the window to arbitrary small sizes
|
||||||
//! This is run in CI to ensure that this doesn't regress again.
|
//! This is run in CI to ensure that this doesn't regress again.
|
||||||
|
|
||||||
use bevy::{input::system::exit_on_esc_system, prelude::*};
|
use bevy::prelude::*;
|
||||||
|
|
||||||
// The smallest size reached is 1x1, as X11 doesn't support windows with a 0 dimension
|
// The smallest size reached is 1x1, as X11 doesn't support windows with a 0 dimension
|
||||||
// TODO: Add a check for platforms other than X11 for 0xk and kx0, despite those currently unsupported on CI.
|
// TODO: Add a check for platforms other than X11 for 0xk and kx0, despite those currently unsupported on CI.
|
||||||
|
@ -33,7 +33,7 @@ fn main() {
|
||||||
.insert_resource(Phase::ContractingY)
|
.insert_resource(Phase::ContractingY)
|
||||||
.add_system(change_window_size)
|
.add_system(change_window_size)
|
||||||
.add_system(sync_dimensions)
|
.add_system(sync_dimensions)
|
||||||
.add_system(exit_on_esc_system)
|
.add_system(bevy::window::close_on_esc)
|
||||||
.add_startup_system(setup_3d)
|
.add_startup_system(setup_3d)
|
||||||
.add_startup_system(setup_2d)
|
.add_startup_system(setup_2d)
|
||||||
.run();
|
.run();
|
||||||
|
|
Loading…
Reference in a new issue