Skip to content

Commit

Permalink
Use removal of window component to signal closing window, some clean …
Browse files Browse the repository at this point in the history
…up/renaming
  • Loading branch information
Aceeri committed Aug 11, 2022
1 parent ba8e19a commit 08daf4b
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 42 deletions.
2 changes: 1 addition & 1 deletion crates/bevy_render/src/view/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ fn extract_windows(
}

for closed_window in closed.iter() {
extracted_windows.remove(&closed_window.entity);
extracted_windows.remove(&closed_window.window);
}
}

Expand Down
10 changes: 6 additions & 4 deletions crates/bevy_window/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,14 @@ pub struct WindowCloseRequested {
pub window: Entity,
}

/// An event that is sent whenever a window is closed. This will be sent by the
/// handler for [`WindowCloseRequested`] or similar.
/// An event that is sent whenever a window is closed. This will be sent by the window
/// backend
#[derive(Debug, Clone)]
pub struct WindowClosed {
/// Window that has been closed.
/// TODO: Does this entity actually exist anymore?
///
/// Note that this entity probably no longer exists
/// by the time this event is received.
pub window: Entity,
}
/// An event reporting that the mouse cursor has moved inside a window.
Expand Down Expand Up @@ -124,7 +126,7 @@ pub struct WindowBackendScaleFactorChanged {
/// Events related to files being dragged and dropped on a window.
#[derive(Debug, Clone)]
pub enum FileDragAndDrop {
/// File is being dropped into a window.
/// File is being dropped into a window.
DroppedFile {
/// Window the file was dropped into.
window: Entity,
Expand Down
17 changes: 6 additions & 11 deletions crates/bevy_window/src/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub fn exit_on_all_closed(mut app_exit_events: EventWriter<AppExit>, windows: Qu
/// Exit the application when the primary window has been closed
///
/// This system is added by the [`WindowPlugin`]
///
///
/// [`WindowPlugin`]: crate::WindowPlugin
pub fn exit_on_primary_closed(
mut app_exit_events: EventWriter<AppExit>,
Expand Down Expand Up @@ -55,32 +55,27 @@ pub fn exit_on_primary_closed(
/// Ensure that you read the caveats documented on that field if doing so.
///
/// [`WindowPlugin`]: crate::WindowPlugin
pub fn close_when_requested(
mut closed: EventReader<WindowCloseRequested>,
mut window_closed: EventWriter<WindowClosed>,
) {
pub fn close_when_requested(mut commands: Commands, mut closed: EventReader<WindowCloseRequested>) {
for event in closed.iter() {
window_closed.send(WindowClosed {
window: event.window,
});
commands.entity(event.window).remove::<Window>();
}
}

/// 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 commands: Commands,
focused_windows: Query<(Entity, &WindowFocus)>,
mut window_closed: EventWriter<WindowClosed>,
input: Res<Input<KeyCode>>,
) {
for (entity, focus) in focused_windows.iter() {
for (window, focus) in focused_windows.iter() {
if !focus.focused() {
continue;
}

if input.just_pressed(KeyCode::Escape) {
window_closed.send(WindowClosed { window: entity });
commands.entity(window).remove::<Window>();
}
}
}
21 changes: 8 additions & 13 deletions crates/bevy_winit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ use core::panic;

use bevy_ecs::system::{SystemParam, SystemState};
use system::{
create_window_system, update_cursor, update_cursor_position, update_resize_constraints,
update_resolution, update_title, update_window_mode, update_window_position,
update_window_state, window_destroyed,
create_window, despawn_window, update_cursor, update_cursor_position,
update_resize_constraints, update_resolution, update_title, update_window_mode,
update_window_position, update_window_state,
};

pub use winit_config::*;
Expand Down Expand Up @@ -67,7 +67,7 @@ impl Plugin for WinitPlugin {
.with_system(update_cursor_position)
.with_system(update_resize_constraints),
)
.add_system_to_stage(CoreStage::Last, window_destroyed);
.add_system_to_stage(CoreStage::PostUpdate, despawn_window.after(ModifiesWindows));

#[cfg(target_arch = "wasm32")]
app.add_plugin(web_resize::CanvasParentResizePlugin);
Expand All @@ -86,7 +86,7 @@ impl Plugin for WinitPlugin {
// Here we need to create a winit-window and give it a WindowHandle which the renderer can use.
// It needs to be spawned before the start of the startup-stage, so we cannot use a regular system.
// Instead we need to create the window and spawn it using direct world access
create_window_system(commands, &**event_loop, new_windows, winit_windows);
create_window(commands, &**event_loop, new_windows, winit_windows);
}

system_state.apply(&mut app.world);
Expand Down Expand Up @@ -199,18 +199,13 @@ impl Default for WinitPersistentState {
}
}

// TODO: Refactor this to work with new pattern
pub fn winit_runner(mut app: App) {
// TODO: Understand what removing and adding this does
// We remove this so that we have ownership over it.
let mut event_loop = app
.world
.remove_non_send_resource::<EventLoop<()>>()
.unwrap();
// let mut create_window_event_reader = app
// .world
// .remove_resource::<WinitCreateWindowReader>()
// .unwrap()
// .0;

let mut app_exit_event_reader = ManualEventReader::<AppExit>::default();
let mut redraw_event_reader = ManualEventReader::<RequestRedraw>::default();
let mut winit_state = WinitPersistentState::default();
Expand Down Expand Up @@ -600,7 +595,7 @@ pub fn winit_runner(mut app: App) {
create_window_system_state.get_mut(&mut app.world);

// Responsible for creating new windows
create_window_system(commands, event_loop, new_windows, winit_windows);
create_window(commands, event_loop, new_windows, winit_windows);

let update = if winit_state.active {
// True if _any_ windows are currently being focused
Expand Down
27 changes: 17 additions & 10 deletions crates/bevy_winit/src/system.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use bevy_ecs::{
entity::Entity,
event::EventReader,
entity::{Entities, Entity},
event::EventWriter,
prelude::{Added, Changed, With},
system::{Commands, NonSendMut, Query, Res},
system::{Commands, NonSendMut, Query, RemovedComponents, Res},
};
use bevy_utils::tracing::{error, info};
use bevy_window::{
Expand All @@ -22,7 +22,7 @@ use crate::{converters, get_best_videomode, get_fitting_videomode, WinitWindows}
/// to an entity.
///
/// This will default any necessary components if they are not already added.
pub fn create_window_system(
pub fn create_window(
mut commands: Commands,
event_loop: &EventLoopWindowTarget<()>,
created_windows: Query<(Entity, WindowComponents), Added<Window>>,
Expand Down Expand Up @@ -58,21 +58,28 @@ pub fn create_window_system(
}
}

pub fn window_destroyed(
pub fn despawn_window(
mut commands: Commands,
entities: &Entities,
primary: Option<Res<PrimaryWindow>>,
mut closed: EventReader<WindowClosed>,
closed: RemovedComponents<Window>,
mut close_events: EventWriter<WindowClosed>,
mut winit_windows: NonSendMut<WinitWindows>,
) {
for event in closed.iter() {
winit_windows.remove_window(event.window);
for window in closed.iter() {
winit_windows.remove_window(window);

if entities.contains(window) {
commands.entity(window).despawn();
}

commands.entity(event.window).despawn();
if let Some(ref primary) = primary {
if primary.window == event.window {
if primary.window == window {
commands.remove_resource::<PrimaryWindow>();
}
}

close_events.send(WindowClosed { window });
}
}

Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_winit/src/winit_windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,9 @@ impl WinitWindows {

winit_window.set_cursor_visible(components.cursor.visible());

// I don't think we can do this immediately with some platforms.
if components.state.minimized() {
winit_window.set_minimized(true);
//winit_window.set_minimized(true);
}

self.window_id_to_winit.insert(entity, winit_window.id());
Expand Down
4 changes: 3 additions & 1 deletion examples/window/multiple_windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use bevy::{

fn main() {
App::new()
// Primary window gets spawned as a result of `DefaultPlugins`
// Primary window gets spawned by `DefaultPlugins`
.add_plugins(DefaultPlugins)
// A window bundle inserted as a resource acts as the descriptor
// for a primary window.
Expand Down Expand Up @@ -50,6 +50,7 @@ fn setup_extra_windows(mut commands: Commands) {
let second_window_id = commands
.spawn_bundle(WindowBundle {
title: WindowTitle::new("Second window"),
// A window can start minimized.
state: WindowState::Minimized,
..Default::default()
})
Expand All @@ -68,6 +69,7 @@ fn setup_extra_windows(mut commands: Commands) {
let third_window_id = commands
.spawn_bundle(WindowBundle {
title: WindowTitle::new("Third window"),
// ... or start maximized.
state: WindowState::Maximized,
..Default::default()
})
Expand Down
2 changes: 1 addition & 1 deletion examples/window/transparent_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ fn main() {
.insert_resource(ClearColor(Color::NONE))
.insert_resource(WindowBundle {
// Setting `transparent` allows the `ClearColor`'s alpha value to take effect
transparency: WindowTransaprency::Transparent,
transparency: WindowTransparency::Transparent,
// Disabling window decorations to make it feel more like a widget than a window
decorations: WindowDecorations::Undecorated,
..default()
Expand Down

0 comments on commit 08daf4b

Please sign in to comment.