From 0e614355216f2def2cada31ff53c6a6804bf8c36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Tue, 9 Jan 2024 16:41:46 +0100 Subject: [PATCH] mobile and webgpu: trigger redraw request when needed and improve window creation (#11245) # Objective - Since #11227, Bevy doesn't work on mobile anymore. Windows are not created. ## Solution - Create initial window on mobile after the initial `Resume` event. macOS is included because it's excluded from the other initial window creation and I didn't want it to feel alone. Also, it makes sense. this is needed for Android https://github.com/bevyengine/bevy/blob/cfcb6885e3b475a93ec0fe7e88023ac0f354bbbf/crates/bevy_winit/src/lib.rs#L152 - request redraw during plugin initialisation (needed for WebGPU) - request redraw when receiving `AboutToWait` instead of at the end of the event handler. request to redraw during a `RedrawRequested` event are ignored on iOS --- crates/bevy_winit/src/lib.rs | 100 ++++++++++++++++++++--------------- 1 file changed, 56 insertions(+), 44 deletions(-) diff --git a/crates/bevy_winit/src/lib.rs b/crates/bevy_winit/src/lib.rs index 4f3a34ab71841..920f0103a2835 100644 --- a/crates/bevy_winit/src/lib.rs +++ b/crates/bevy_winit/src/lib.rs @@ -46,7 +46,7 @@ use bevy_window::{PrimaryWindow, RawHandleWrapper}; pub use winit::platform::android::activity as android_activity; use winit::{ - event::{self, DeviceEvent, Event, StartCause, WindowEvent}, + event::{self, DeviceEvent, Event, WindowEvent}, event_loop::{ControlFlow, EventLoop, EventLoopBuilder, EventLoopWindowTarget}, }; @@ -352,6 +352,7 @@ pub fn winit_runner(mut app: App) { app.finish(); app.cleanup(); } + runner_state.redraw_requested = true; if let Some(app_exit_events) = app.world.get_resource::>() { if app_exit_event_reader.read(app_exit_events).last().is_some() { @@ -360,45 +361,25 @@ pub fn winit_runner(mut app: App) { } } } - runner_state.redraw_requested = false; match event { - Event::NewEvents(start_cause) => match start_cause { - StartCause::Init => { - #[cfg(any(target_os = "ios", target_os = "macos"))] - { - let ( - commands, - mut windows, - event_writer, - winit_windows, - adapters, - handlers, - accessibility_requested, - ) = create_window_system_state.get_mut(&mut app.world); - - create_windows( - event_loop, - commands, - windows.iter_mut(), - event_writer, - winit_windows, - adapters, - handlers, - accessibility_requested, - ); - - create_window_system_state.apply(&mut app.world); + Event::AboutToWait => { + if runner_state.redraw_requested { + let (_, winit_windows, _, _) = + event_writer_system_state.get_mut(&mut app.world); + for window in winit_windows.windows.values() { + window.request_redraw(); } } - _ => { - if let Some(t) = runner_state.scheduled_update { - let now = Instant::now(); - let remaining = t.checked_duration_since(now).unwrap_or(Duration::ZERO); - runner_state.wait_elapsed = remaining.is_zero(); - } + runner_state.redraw_requested = false; + } + Event::NewEvents(_) => { + if let Some(t) = runner_state.scheduled_update { + let now = Instant::now(); + let remaining = t.checked_duration_since(now).unwrap_or(Duration::ZERO); + runner_state.wait_elapsed = remaining.is_zero(); } - }, + } Event::WindowEvent { event, window_id, .. } => { @@ -682,7 +663,6 @@ pub fn winit_runner(mut app: App) { event: DeviceEvent::MouseMotion { delta: (x, y) }, .. } => { - runner_state.redraw_requested = true; let (mut event_writers, ..) = event_writer_system_state.get_mut(&mut app.world); event_writers.mouse_motion.send(MouseMotion { delta: Vec2::new(x as f32, y as f32), @@ -696,6 +676,44 @@ pub fn winit_runner(mut app: App) { runner_state.active = ActiveState::WillSuspend; } Event::Resumed => { + #[cfg(any(target_os = "android", target_os = "ios", target_os = "macos"))] + { + if runner_state.active == ActiveState::NotYetStarted { + let mut create_window_system_state: SystemState<( + Commands, + Query<(Entity, &mut Window)>, + EventWriter, + NonSendMut, + NonSendMut, + ResMut, + ResMut, + )> = SystemState::from_world(&mut app.world); + + let ( + commands, + mut windows, + event_writer, + winit_windows, + adapters, + handlers, + accessibility_requested, + ) = create_window_system_state.get_mut(&mut app.world); + + create_windows( + &event_loop, + commands, + windows.iter_mut(), + event_writer, + winit_windows, + adapters, + handlers, + accessibility_requested, + ); + + create_window_system_state.apply(&mut app.world); + } + } + let (mut event_writers, ..) = event_writer_system_state.get_mut(&mut app.world); match runner_state.active { ActiveState::NotYetStarted => { @@ -706,6 +724,7 @@ pub fn winit_runner(mut app: App) { } } runner_state.active = ActiveState::Active; + runner_state.redraw_requested = true; #[cfg(target_os = "android")] { // Get windows that are cached but without raw handles. Those window were already created, but got their @@ -748,12 +767,6 @@ pub fn winit_runner(mut app: App) { } _ => (), } - if runner_state.redraw_requested { - let (_, winit_windows, _, _) = event_writer_system_state.get_mut(&mut app.world); - for window in winit_windows.windows.values() { - window.request_redraw(); - } - } }; trace!("starting winit event loop"); @@ -820,8 +833,7 @@ fn run_app_update_if_should( app.update(); // decide when to run the next update - let (config, windows) = focused_windows_state.get(&app.world); - let focused = windows.iter().any(|window| window.focused); + let (config, _) = focused_windows_state.get(&app.world); match config.update_mode(focused) { UpdateMode::Continuous => { runner_state.redraw_requested = true;