@@ -360,6 +360,7 @@ pub fn winit_runner(mut app: App) {
360360 }
361361 }
362362 }
363+ runner_state. redraw_requested = false ;
363364
364365 match event {
365366 Event :: NewEvents ( start_cause) => match start_cause {
@@ -412,7 +413,7 @@ pub fn winit_runner(mut app: App) {
412413 return ;
413414 } ;
414415
415- let Ok ( ( mut window, mut cache ) ) = windows. get_mut ( window_entity) else {
416+ let Ok ( ( mut window, _ ) ) = windows. get_mut ( window_entity) else {
416417 warn ! (
417418 "Window {:?} is missing `Window` component, skipping event {:?}" ,
418419 window_entity, event
@@ -655,17 +656,33 @@ pub fn winit_runner(mut app: App) {
655656 window : window_entity,
656657 } ) ;
657658 }
659+ WindowEvent :: RedrawRequested => {
660+ runner_state. redraw_requested = false ;
661+ run_app_update_if_should (
662+ & mut runner_state,
663+ & mut app,
664+ & mut focused_windows_state,
665+ event_loop,
666+ & mut create_window_system_state,
667+ & mut app_exit_event_reader,
668+ & mut redraw_event_reader,
669+ ) ;
670+ }
658671 _ => { }
659672 }
660673
661- if window. is_changed ( ) {
662- cache. window = window. clone ( ) ;
674+ let mut windows = app. world . query :: < ( & mut Window , & mut CachedWindow ) > ( ) ;
675+ if let Ok ( ( window, mut cache) ) = windows. get_mut ( & mut app. world , window_entity) {
676+ if window. is_changed ( ) {
677+ cache. window = window. clone ( ) ;
678+ }
663679 }
664680 }
665681 Event :: DeviceEvent {
666682 event : DeviceEvent :: MouseMotion { delta : ( x, y) } ,
667683 ..
668684 } => {
685+ runner_state. redraw_requested = true ;
669686 let ( mut event_writers, ..) = event_writer_system_state. get_mut ( & mut app. world ) ;
670687 event_writers. mouse_motion . send ( MouseMotion {
671688 delta : Vec2 :: new ( x as f32 , y as f32 ) ,
@@ -726,119 +743,142 @@ pub fn winit_runner(mut app: App) {
726743
727744 app. world . entity_mut ( entity) . insert ( wrapper) ;
728745 }
729- event_loop. set_control_flow ( ControlFlow :: Poll ) ;
746+ event_loop. set_control_flow ( ControlFlow :: Wait ) ;
730747 }
731748 }
732- Event :: AboutToWait => {
733- if runner_state. active . should_run ( ) {
734- if runner_state. active == ActiveState :: WillSuspend {
735- runner_state. active = ActiveState :: Suspended ;
736- #[ cfg( target_os = "android" ) ]
737- {
738- // Remove the `RawHandleWrapper` from the primary window.
739- // This will trigger the surface destruction.
740- let mut query =
741- app. world . query_filtered :: < Entity , With < PrimaryWindow > > ( ) ;
742- let entity = query. single ( & app. world ) ;
743- app. world . entity_mut ( entity) . remove :: < RawHandleWrapper > ( ) ;
744- event_loop. set_control_flow ( ControlFlow :: Wait ) ;
745- }
746- }
747- let ( config, windows) = focused_windows_state. get ( & app. world ) ;
748- let focused = windows. iter ( ) . any ( |window| window. focused ) ;
749- let should_update = match config. update_mode ( focused) {
750- UpdateMode :: Continuous | UpdateMode :: Reactive { .. } => {
751- // `Reactive`: In order for `event_handler` to have been called, either
752- // we received a window or raw input event, the `wait` elapsed, or a
753- // redraw was requested (by the app or the OS). There are no other
754- // conditions, so we can just return `true` here.
755- true
756- }
757- UpdateMode :: ReactiveLowPower { .. } => {
758- runner_state. wait_elapsed
759- || runner_state. redraw_requested
760- || runner_state. window_event_received
761- }
762- } ;
763-
764- if app. plugins_state ( ) == PluginsState :: Cleaned && should_update {
765- // reset these on each update
766- runner_state. wait_elapsed = false ;
767- runner_state. window_event_received = false ;
768- runner_state. redraw_requested = false ;
769- runner_state. last_update = Instant :: now ( ) ;
770-
771- app. update ( ) ;
749+ _ => ( ) ,
750+ }
751+ if runner_state. redraw_requested {
752+ let ( _, winit_windows, _, _) = event_writer_system_state. get_mut ( & mut app. world ) ;
753+ for window in winit_windows. windows . values ( ) {
754+ window. request_redraw ( ) ;
755+ }
756+ }
757+ } ;
772758
773- // decide when to run the next update
774- let ( config, windows) = focused_windows_state. get ( & app. world ) ;
775- let focused = windows. iter ( ) . any ( |window| window. focused ) ;
776- match config. update_mode ( focused) {
777- UpdateMode :: Continuous => {
778- event_loop. set_control_flow ( ControlFlow :: Poll ) ;
779- }
780- UpdateMode :: Reactive { wait }
781- | UpdateMode :: ReactiveLowPower { wait } => {
782- if let Some ( next) = runner_state. last_update . checked_add ( * wait) {
783- runner_state. scheduled_update = Some ( next) ;
784- event_loop. set_control_flow ( ControlFlow :: WaitUntil ( next) ) ;
785- } else {
786- runner_state. scheduled_update = None ;
787- event_loop. set_control_flow ( ControlFlow :: Wait ) ;
788- }
789- }
790- }
759+ trace ! ( "starting winit event loop" ) ;
760+ // TODO(clean): the winit docs mention using `spawn` instead of `run` on WASM.
761+ if let Err ( err) = event_loop. run ( event_handler) {
762+ error ! ( "winit event loop returned an error: {err}" ) ;
763+ }
764+ }
791765
792- if let Some ( app_redraw_events) =
793- app. world . get_resource :: < Events < RequestRedraw > > ( )
794- {
795- if redraw_event_reader. read ( app_redraw_events) . last ( ) . is_some ( ) {
796- runner_state. redraw_requested = true ;
797- event_loop. set_control_flow ( ControlFlow :: Poll ) ;
798- }
799- }
766+ fn run_app_update_if_should (
767+ runner_state : & mut WinitAppRunnerState ,
768+ app : & mut App ,
769+ focused_windows_state : & mut SystemState < ( Res < WinitSettings > , Query < & Window > ) > ,
770+ event_loop : & EventLoopWindowTarget < ( ) > ,
771+ create_window_system_state : & mut SystemState < (
772+ Commands ,
773+ Query < ( Entity , & mut Window ) , Added < Window > > ,
774+ EventWriter < WindowCreated > ,
775+ NonSendMut < WinitWindows > ,
776+ NonSendMut < AccessKitAdapters > ,
777+ ResMut < WinitActionHandlers > ,
778+ ResMut < AccessibilityRequested > ,
779+ ) > ,
780+ app_exit_event_reader : & mut ManualEventReader < AppExit > ,
781+ redraw_event_reader : & mut ManualEventReader < RequestRedraw > ,
782+ ) {
783+ if !runner_state. active . should_run ( ) {
784+ return ;
785+ }
786+ if runner_state. active == ActiveState :: WillSuspend {
787+ runner_state. active = ActiveState :: Suspended ;
788+ #[ cfg( target_os = "android" ) ]
789+ {
790+ // Remove the `RawHandleWrapper` from the primary window.
791+ // This will trigger the surface destruction.
792+ let mut query = app. world . query_filtered :: < Entity , With < PrimaryWindow > > ( ) ;
793+ let entity = query. single ( & app. world ) ;
794+ app. world . entity_mut ( entity) . remove :: < RawHandleWrapper > ( ) ;
795+ event_loop. set_control_flow ( ControlFlow :: Wait ) ;
796+ }
797+ }
798+ let ( config, windows) = focused_windows_state. get ( & app. world ) ;
799+ let focused = windows. iter ( ) . any ( |window| window. focused ) ;
800+ let should_update = match config. update_mode ( focused) {
801+ // `Reactive`: In order for `event_handler` to have been called, either
802+ // we received a window or raw input event, the `wait` elapsed, or a
803+ // redraw was requested (by the app or the OS). There are no other
804+ // conditions, so we can just return `true` here.
805+ UpdateMode :: Continuous | UpdateMode :: Reactive { .. } => true ,
806+ // TODO(bug): This is currently always true since we only run this function
807+ // if we received a `RequestRedraw` event.
808+ UpdateMode :: ReactiveLowPower { .. } => {
809+ runner_state. wait_elapsed
810+ || runner_state. redraw_requested
811+ || runner_state. window_event_received
812+ }
813+ } ;
800814
801- if let Some ( app_exit_events) = app. world . get_resource :: < Events < AppExit > > ( ) {
802- if app_exit_event_reader. read ( app_exit_events) . last ( ) . is_some ( ) {
803- event_loop. exit ( ) ;
804- }
805- }
806- }
815+ if app. plugins_state ( ) == PluginsState :: Cleaned && should_update {
816+ // reset these on each update
817+ runner_state. wait_elapsed = false ;
818+ runner_state. last_update = Instant :: now ( ) ;
807819
808- // create any new windows
809- // (even if app did not update, some may have been created by plugin setup)
810- let (
811- commands,
812- mut windows,
813- event_writer,
814- winit_windows,
815- adapters,
816- handlers,
817- accessibility_requested,
818- ) = create_window_system_state. get_mut ( & mut app. world ) ;
819-
820- create_windows (
821- event_loop,
822- commands,
823- windows. iter_mut ( ) ,
824- event_writer,
825- winit_windows,
826- adapters,
827- handlers,
828- accessibility_requested,
829- ) ;
820+ app. update ( ) ;
830821
831- create_window_system_state. apply ( & mut app. world ) ;
822+ // decide when to run the next update
823+ let ( config, windows) = focused_windows_state. get ( & app. world ) ;
824+ let focused = windows. iter ( ) . any ( |window| window. focused ) ;
825+ match config. update_mode ( focused) {
826+ UpdateMode :: Continuous => {
827+ runner_state. redraw_requested = true ;
828+ }
829+ UpdateMode :: Reactive { wait } | UpdateMode :: ReactiveLowPower { wait } => {
830+ // TODO(bug): this is unexpected behavior.
831+ // When Reactive, user expects bevy to actually wait that amount of time,
832+ // and not potentially infinitely depending on plateform specifics (which this does)
833+ // Need to verify the plateform specifics (whether this can occur in
834+ // rare-but-possible cases) and replace this with a panic or a log warn!
835+ if let Some ( next) = runner_state. last_update . checked_add ( * wait) {
836+ runner_state. scheduled_update = Some ( next) ;
837+ event_loop. set_control_flow ( ControlFlow :: WaitUntil ( next) ) ;
838+ } else {
839+ runner_state. scheduled_update = None ;
840+ event_loop. set_control_flow ( ControlFlow :: Wait ) ;
832841 }
833842 }
834- _ => ( ) ,
835843 }
836- } ;
837844
838- trace ! ( "starting winit event loop" ) ;
839- if let Err ( err) = event_loop. run ( event_handler) {
840- error ! ( "winit event loop returned an error: {err}" ) ;
845+ if let Some ( app_redraw_events) = app. world . get_resource :: < Events < RequestRedraw > > ( ) {
846+ if redraw_event_reader. read ( app_redraw_events) . last ( ) . is_some ( ) {
847+ runner_state. redraw_requested = true ;
848+ }
849+ }
850+
851+ if let Some ( app_exit_events) = app. world . get_resource :: < Events < AppExit > > ( ) {
852+ if app_exit_event_reader. read ( app_exit_events) . last ( ) . is_some ( ) {
853+ event_loop. exit ( ) ;
854+ }
855+ }
841856 }
857+
858+ // create any new windows
859+ // (even if app did not update, some may have been created by plugin setup)
860+ let (
861+ commands,
862+ mut windows,
863+ event_writer,
864+ winit_windows,
865+ adapters,
866+ handlers,
867+ accessibility_requested,
868+ ) = create_window_system_state. get_mut ( & mut app. world ) ;
869+
870+ create_windows (
871+ event_loop,
872+ commands,
873+ windows. iter_mut ( ) ,
874+ event_writer,
875+ winit_windows,
876+ adapters,
877+ handlers,
878+ accessibility_requested,
879+ ) ;
880+
881+ create_window_system_state. apply ( & mut app. world ) ;
842882}
843883
844884fn react_to_resize (
0 commit comments