Skip to content

Commit b1f57bb

Browse files
committed
Split change_window system into multiple system that handle WindowCommands
1 parent 9325098 commit b1f57bb

File tree

2 files changed

+558
-143
lines changed

2 files changed

+558
-143
lines changed

crates/bevy_winit/src/lib.rs

Lines changed: 38 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
11
mod converters;
2+
mod system;
23
#[cfg(target_arch = "wasm32")]
34
mod web_resize;
45
mod winit_config;
56
mod winit_windows;
67

8+
use core::panic;
9+
10+
use bevy_ecs::system::Command;
11+
use system::{
12+
destroy_windows, update_cursor_icon, update_cursor_lock_mode, update_cursor_position,
13+
update_cursor_visibility, update_decorations, update_maximized, update_minimized,
14+
update_position, update_present_mode, update_resizable, update_resize_contraints,
15+
update_resolution, update_scale_factor, update_title, update_window_mode, window_destroyed,
16+
};
17+
use winit::window;
718
pub use winit_config::*;
819
pub use winit_windows::*;
920

@@ -25,9 +36,9 @@ use bevy_utils::{
2536
};
2637
use bevy_window::{
2738
CreateWindow, CursorEntered, CursorLeft, CursorMoved, FileDragAndDrop, ModifiesWindows,
28-
ReceivedCharacter, RequestRedraw, WindowBackendScaleFactorChanged, WindowCloseRequested,
29-
WindowClosed, WindowCreated, WindowFocused, WindowMoved, WindowResized,
30-
WindowScaleFactorChanged, Windows,
39+
ReceivedCharacter, RequestRedraw, Window, WindowBackendScaleFactorChanged,
40+
WindowCloseRequested, WindowCreated, WindowCurrentlyFocused, WindowCursorPosition,
41+
WindowFocused, WindowMoved, WindowResized, WindowResolution, WindowScaleFactorChanged, PrimaryWindow, WindowPosition,
3142
};
3243

3344
use winit::{
@@ -44,11 +55,34 @@ impl Plugin for WinitPlugin {
4455
app.init_non_send_resource::<WinitWindows>()
4556
.init_resource::<WinitSettings>()
4657
.set_runner(winit_runner)
47-
.add_system_to_stage(CoreStage::PostUpdate, change_window.label(ModifiesWindows));
58+
// TODO: Verify that this actually works and does not cause any race-conditions or strange ordering issues
59+
.add_system_set_to_stage(
60+
CoreStage::PostUpdate,
61+
SystemSet::new()
62+
.label(ModifiesWindows)
63+
.with_system(update_title)
64+
.with_system(update_window_mode)
65+
.with_system(update_decorations)
66+
.with_system(update_scale_factor)
67+
.with_system(update_resizable)
68+
.with_system(update_position)
69+
.with_system(update_minimized)
70+
.with_system(update_maximized)
71+
.with_system(update_resolution)
72+
.with_system(update_cursor_icon)
73+
.with_system(update_cursor_lock_mode)
74+
.with_system(update_cursor_visibility)
75+
.with_system(update_cursor_position)
76+
.with_system(update_resize_contraints)
77+
.with_system(update_present_mode)
78+
.with_system(destroy_windows), // TODO: This should probably go last?
79+
// .with_system(window_destroyed) // TODO: Unsure if this is the correct approach
80+
);
4881
#[cfg(target_arch = "wasm32")]
4982
app.add_plugin(web_resize::CanvasParentResizePlugin);
5083
let event_loop = EventLoop::new();
5184
let mut create_window_reader = WinitCreateWindowReader::default();
85+
// TODO: Test if any issues has been caused here
5286
// Note that we create a window here "early" because WASM/WebGL requires the window to exist prior to initializing
5387
// the renderer.
5488
handle_create_window_events(&mut app.world, &event_loop, &mut create_window_reader.0);
@@ -57,145 +91,6 @@ impl Plugin for WinitPlugin {
5791
}
5892
}
5993

60-
fn change_window(
61-
mut winit_windows: NonSendMut<WinitWindows>,
62-
mut windows: ResMut<Windows>,
63-
mut window_dpi_changed_events: EventWriter<WindowScaleFactorChanged>,
64-
mut window_close_events: EventWriter<WindowClosed>,
65-
) {
66-
let mut removed_windows = vec![];
67-
for bevy_window in windows.iter_mut() {
68-
let id = bevy_window.id();
69-
for command in bevy_window.drain_commands() {
70-
match command {
71-
bevy_window::WindowCommand::SetWindowMode {
72-
mode,
73-
resolution: (width, height),
74-
} => {
75-
let window = winit_windows.get_window(id).unwrap();
76-
match mode {
77-
bevy_window::WindowMode::BorderlessFullscreen => {
78-
window
79-
.set_fullscreen(Some(winit::window::Fullscreen::Borderless(None)));
80-
}
81-
bevy_window::WindowMode::Fullscreen => {
82-
window.set_fullscreen(Some(winit::window::Fullscreen::Exclusive(
83-
get_best_videomode(&window.current_monitor().unwrap()),
84-
)));
85-
}
86-
bevy_window::WindowMode::SizedFullscreen => window.set_fullscreen(Some(
87-
winit::window::Fullscreen::Exclusive(get_fitting_videomode(
88-
&window.current_monitor().unwrap(),
89-
width,
90-
height,
91-
)),
92-
)),
93-
bevy_window::WindowMode::Windowed => window.set_fullscreen(None),
94-
}
95-
}
96-
bevy_window::WindowCommand::SetTitle { title } => {
97-
let window = winit_windows.get_window(id).unwrap();
98-
window.set_title(&title);
99-
}
100-
bevy_window::WindowCommand::SetScaleFactor { scale_factor } => {
101-
window_dpi_changed_events.send(WindowScaleFactorChanged { id, scale_factor });
102-
}
103-
bevy_window::WindowCommand::SetResolution {
104-
logical_resolution: (width, height),
105-
scale_factor,
106-
} => {
107-
let window = winit_windows.get_window(id).unwrap();
108-
window.set_inner_size(
109-
winit::dpi::LogicalSize::new(width, height)
110-
.to_physical::<f64>(scale_factor),
111-
);
112-
}
113-
bevy_window::WindowCommand::SetPresentMode { .. } => (),
114-
bevy_window::WindowCommand::SetResizable { resizable } => {
115-
let window = winit_windows.get_window(id).unwrap();
116-
window.set_resizable(resizable);
117-
}
118-
bevy_window::WindowCommand::SetDecorations { decorations } => {
119-
let window = winit_windows.get_window(id).unwrap();
120-
window.set_decorations(decorations);
121-
}
122-
bevy_window::WindowCommand::SetCursorIcon { icon } => {
123-
let window = winit_windows.get_window(id).unwrap();
124-
window.set_cursor_icon(converters::convert_cursor_icon(icon));
125-
}
126-
bevy_window::WindowCommand::SetCursorLockMode { locked } => {
127-
let window = winit_windows.get_window(id).unwrap();
128-
window
129-
.set_cursor_grab(locked)
130-
.unwrap_or_else(|e| error!("Unable to un/grab cursor: {}", e));
131-
}
132-
bevy_window::WindowCommand::SetCursorVisibility { visible } => {
133-
let window = winit_windows.get_window(id).unwrap();
134-
window.set_cursor_visible(visible);
135-
}
136-
bevy_window::WindowCommand::SetCursorPosition { position } => {
137-
let window = winit_windows.get_window(id).unwrap();
138-
let inner_size = window.inner_size().to_logical::<f32>(window.scale_factor());
139-
window
140-
.set_cursor_position(winit::dpi::LogicalPosition::new(
141-
position.x,
142-
inner_size.height - position.y,
143-
))
144-
.unwrap_or_else(|e| error!("Unable to set cursor position: {}", e));
145-
}
146-
bevy_window::WindowCommand::SetMaximized { maximized } => {
147-
let window = winit_windows.get_window(id).unwrap();
148-
window.set_maximized(maximized);
149-
}
150-
bevy_window::WindowCommand::SetMinimized { minimized } => {
151-
let window = winit_windows.get_window(id).unwrap();
152-
window.set_minimized(minimized);
153-
}
154-
bevy_window::WindowCommand::SetPosition { position } => {
155-
let window = winit_windows.get_window(id).unwrap();
156-
window.set_outer_position(PhysicalPosition {
157-
x: position[0],
158-
y: position[1],
159-
});
160-
}
161-
bevy_window::WindowCommand::SetResizeConstraints { resize_constraints } => {
162-
let window = winit_windows.get_window(id).unwrap();
163-
let constraints = resize_constraints.check_constraints();
164-
let min_inner_size = LogicalSize {
165-
width: constraints.min_width,
166-
height: constraints.min_height,
167-
};
168-
let max_inner_size = LogicalSize {
169-
width: constraints.max_width,
170-
height: constraints.max_height,
171-
};
172-
173-
window.set_min_inner_size(Some(min_inner_size));
174-
if constraints.max_width.is_finite() && constraints.max_height.is_finite() {
175-
window.set_max_inner_size(Some(max_inner_size));
176-
}
177-
}
178-
bevy_window::WindowCommand::Close => {
179-
// Since we have borrowed `windows` to iterate through them, we can't remove the window from it.
180-
// Add the removal requests to a queue to solve this
181-
removed_windows.push(id);
182-
// No need to run any further commands - this drops the rest of the commands, although the `bevy_window::Window` will be dropped later anyway
183-
break;
184-
}
185-
}
186-
}
187-
}
188-
if !removed_windows.is_empty() {
189-
for id in removed_windows {
190-
// Close the OS window. (The `Drop` impl actually closes the window)
191-
let _ = winit_windows.remove_window(id);
192-
// Clean up our own data structures
193-
windows.remove(id);
194-
window_close_events.send(WindowClosed { id });
195-
}
196-
}
197-
}
198-
19994
fn run<F>(event_loop: EventLoop<()>, event_handler: F) -> !
20095
where
20196
F: 'static + FnMut(Event<'_, ()>, &EventLoopWindowTarget<()>, &mut ControlFlow),

0 commit comments

Comments
 (0)