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

Close window (pipelined-rendering) #2898

Closed
wants to merge 10 commits into from
Closed
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
6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ ron = "0.6.2"
serde = { version = "1", features = ["derive"] }
# Needed to poll Task examples
futures-lite = "1.11.3"
crevice = {path = "crates/crevice"}
crevice = { path = "crates/crevice" }

[[example]]
name = "hello_world"
Expand Down Expand Up @@ -514,6 +514,10 @@ path = "examples/window/clear_color_pipelined.rs"
name = "multiple_windows"
path = "examples/window/multiple_windows.rs"

[[example]]
name = "multiple_windows_pipelined"
path = "examples/window/multiple_windows_pipelined.rs"

[[example]]
name = "scale_factor_override"
path = "examples/window/scale_factor_override.rs"
Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_window/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ keywords = ["bevy"]

[dependencies]
# bevy
bevy_app = { path = "../bevy_app", version = "0.5.0" }
bevy_ecs = { path = "../bevy_ecs", version = "0.5.0" }
bevy_app = { path = "../bevy_app", version = "0.5.0" }
bevy_math = { path = "../bevy_math", version = "0.5.0" }
bevy_utils = { path = "../bevy_utils", version = "0.5.0" }
bevy_input = { path = "../bevy_input", version = "0.5.0" }
raw-window-handle = "0.3.0"

# other
Expand Down
21 changes: 15 additions & 6 deletions crates/bevy_window/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,6 @@ pub struct CreateWindow {
pub descriptor: WindowDescriptor,
}

/// 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.
#[derive(Debug, Clone)]
pub struct WindowCreated {
Expand All @@ -32,11 +26,26 @@ pub struct WindowCreated {

/// An event that is sent whenever a close was requested for a window. For example: when the "close"
/// button is pressed on a window.
///
/// By default, these events are handled by closing the corresponding [`crate::Window`].
/// To disable this behaviour, set `close_when_requested` on the [`crate::WindowPlugin`] to `false`
#[derive(Debug, Clone)]
pub struct WindowCloseRequested {
pub id: WindowId,
}

/// An event that is sent whenever a window is closed.
/// This will only be sent in response to the [`Window::close`] method.
///
/// By default, when no windows are open, the app will close.
/// To disable this behaviour, set `exit_on_all_closed` on the [`crate::WindowPlugin`] to `false`
///
/// [`Window::close`]: `crate::Window::close`
#[derive(Debug, Clone)]
pub struct WindowClosed {
pub id: WindowId,
}

#[derive(Debug, Clone)]
pub struct CursorMoved {
pub id: WindowId,
Expand Down
18 changes: 13 additions & 5 deletions crates/bevy_window/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,20 @@ use bevy_app::{prelude::*, Events};
use bevy_ecs::system::IntoSystem;

pub struct WindowPlugin {
/// Whether to add a default window based on the [`WindowDescriptor`] resource
pub add_primary_window: bool,
pub exit_on_close: bool,
/// Whether to close the app when there are no open windows
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)
pub close_when_requested: bool,
}

impl Default for WindowPlugin {
fn default() -> Self {
WindowPlugin {
add_primary_window: true,
exit_on_close: true,
close_when_requested: true,
exit_on_all_closed: true,
}
}
}
Expand All @@ -40,8 +45,8 @@ impl Plugin for WindowPlugin {
app.add_event::<WindowResized>()
.add_event::<CreateWindow>()
.add_event::<WindowCreated>()
.add_event::<WindowClosed>()
.add_event::<WindowCloseRequested>()
.add_event::<CloseWindow>()
.add_event::<CursorMoved>()
.add_event::<CursorEntered>()
.add_event::<CursorLeft>()
Expand Down Expand Up @@ -69,8 +74,11 @@ impl Plugin for WindowPlugin {
});
}

if self.exit_on_close {
app.add_system(exit_on_window_close_system.system());
if self.exit_on_all_closed {
app.add_system(exit_on_all_closed.system());
}
if self.close_when_requested {
app.add_system(close_when_requested.system());
}
}
}
41 changes: 35 additions & 6 deletions crates/bevy_window/src/system.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,40 @@
use crate::WindowCloseRequested;
use crate::{Window, WindowCloseRequested, WindowFocused, WindowId, Windows};
use bevy_app::{AppExit, EventReader, EventWriter};
use bevy_ecs::prelude::*;
use bevy_input::{keyboard::KeyCode, Input};

pub fn exit_on_window_close_system(
mut app_exit_events: EventWriter<AppExit>,
mut window_close_requested_events: EventReader<WindowCloseRequested>,
) {
if window_close_requested_events.iter().next().is_some() {
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);
}
}

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);
}
}

pub fn close_on_esc(
mut focused: Local<Option<WindowId>>,
mut focused_events: EventReader<WindowFocused>,
mut windows: ResMut<Windows>,
input: Res<Input<KeyCode>>,
) {
for event in focused_events.iter() {
if event.focused {
*focused = Some(event.id);
}
}

if let Some(focused) = &*focused {
if input.just_pressed(KeyCode::Escape) {
if let Some(window) = windows.get_mut(*focused) {
window.close();
}
}
}
}
5 changes: 5 additions & 0 deletions crates/bevy_window/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ pub enum WindowCommand {
SetResizeConstraints {
resize_constraints: WindowResizeConstraints,
},
Close,
}

/// Defines the way a window is displayed
Expand Down Expand Up @@ -508,6 +509,10 @@ impl Window {
});
}

pub fn close(&mut self) {
self.command_queue.push(WindowCommand::Close);
}

#[inline]
pub fn drain_commands(&mut self) -> impl Iterator<Item = WindowCommand> + '_ {
self.command_queue.drain(..)
Expand Down
4 changes: 4 additions & 0 deletions crates/bevy_window/src/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,8 @@ impl Windows {
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Window> {
self.windows.values_mut()
}

pub fn remove(&mut self, id: WindowId) -> Option<Window> {
self.windows.remove(&id)
}
}
31 changes: 25 additions & 6 deletions crates/bevy_winit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ use bevy_math::{ivec2, Vec2};
use bevy_utils::tracing::{error, trace, warn};
use bevy_window::{
CreateWindow, CursorEntered, CursorLeft, CursorMoved, FileDragAndDrop, ReceivedCharacter,
WindowBackendScaleFactorChanged, WindowCloseRequested, WindowCreated, WindowFocused,
WindowMoved, WindowResized, WindowScaleFactorChanged, Windows,
WindowBackendScaleFactorChanged, WindowCloseRequested, WindowClosed, WindowCreated,
WindowFocused, WindowMoved, WindowResized, WindowScaleFactorChanged, Windows,
};
use winit::{
dpi::PhysicalPosition,
Expand Down Expand Up @@ -48,8 +48,9 @@ impl Plugin for WinitPlugin {

fn change_window(world: &mut World) {
let world = world.cell();
let winit_windows = world.get_resource::<WinitWindows>().unwrap();
let mut winit_windows = world.get_resource_mut::<WinitWindows>().unwrap();
let mut windows = world.get_resource_mut::<Windows>().unwrap();
let mut removed_windows = Vec::new();

for bevy_window in windows.iter_mut() {
let id = bevy_window.id();
Expand Down Expand Up @@ -158,9 +159,24 @@ fn change_window(world: &mut World) {
window.set_max_inner_size(Some(max_inner_size));
}
}
bevy_window::WindowCommand::Close => {
let window = winit_windows.remove_window(id);
// Close the window
drop(window);
removed_windows.push(id);
// Don't run any further commands - this drops the rest of the commands, although the `Window` will be dropped later anyway
break;
}
}
}
}
if !removed_windows.is_empty() {
let mut events = world.get_resource_mut::<Events<WindowClosed>>().unwrap();
for id in removed_windows {
windows.remove(id);
events.send(WindowClosed { id });
}
}
}

fn run<F>(event_loop: EventLoop<()>, event_handler: F) -> !
Expand Down Expand Up @@ -264,16 +280,19 @@ pub fn winit_runner_with(mut app: App, mut event_loop: EventLoop<()>) {
window_id
} else {
warn!(
"Skipped event for unknown winit Window Id {:?}",
winit_window_id
"Skipped event for unknown winit Window Id {:?}: {:?}",
winit_window_id, event
);
return;
};

let window = if let Some(window) = windows.get_mut(window_id) {
window
} else {
warn!("Skipped event for unknown Window Id {:?}", winit_window_id);
warn!(
"Skipped event for unknown Window Id {:?}: {:?}",
winit_window_id, event
);
return;
};

Expand Down
7 changes: 7 additions & 0 deletions crates/bevy_winit/src/winit_windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,14 @@ impl WinitWindows {
pub fn get_window_id(&self, id: winit::window::WindowId) -> Option<WindowId> {
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)?;
self.winit_to_window_id.remove(&winit_id);
self.windows.remove(&winit_id)
}
}

pub fn get_fitting_videomode(
monitor: &winit::monitor::MonitorHandle,
width: u32,
Expand Down
1 change: 1 addition & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ Example | File | Description
`clear_color` | [`window/clear_color.rs`](./window/clear_color.rs) | Creates a solid color window
`clear_color_pipelined` | [`window/clear_color_pipelined.rs`](./window/clear_color_pipelined.rs) | Creates a solid color window with the pipelined renderer
`multiple_windows` | [`window/multiple_windows.rs`](./window/multiple_windows.rs) | Creates two windows and cameras viewing the same mesh
`multiple_windows_pipelined` | [`window/multiple_windows_pipelined.rs`](./window/multiple_windows_pipelined.rs) | Creates two windows and cameras viewing the same mesh
`scale_factor_override` | [`window/scale_factor_override.rs`](./window/scale_factor_override.rs) | Illustrates how to customize the default window settings
`window_settings` | [`window/window_settings.rs`](./window/window_settings.rs) | Demonstrates customizing default window settings

Expand Down
Loading