@@ -185,19 +185,18 @@ impl<T: WinitApp> WinitAppWrapper<T> {
185185 return true ; // not yet ready
186186 }
187187
188- event_loop. set_control_flow ( ControlFlow :: Poll ) ;
189-
190188 if let Some ( window) = self . winit_app . window ( * window_id) {
191- log:: trace!( "request_redraw for {window_id:?}" ) ;
192- window. request_redraw ( ) ;
193-
194189 // On Windows, invisible windows don't receive RedrawRequested
195190 // events, so pending viewport commands (e.g. Visible(true)) would
196191 // never be processed. We collect these windows to paint them
197192 // directly below.
198193 // See: https://github.com/emilk/egui/issues/5229
199194 if window. is_visible ( ) == Some ( false ) {
200195 invisible_window_ids. push ( * window_id) ;
196+ } else {
197+ log:: trace!( "request_redraw for {window_id:?}" ) ;
198+ event_loop. set_control_flow ( ControlFlow :: Poll ) ;
199+ window. request_redraw ( ) ;
201200 }
202201 } else {
203202 log:: trace!( "No window found for {window_id:?}" ) ;
@@ -208,11 +207,24 @@ impl<T: WinitApp> WinitAppWrapper<T> {
208207 // Paint invisible windows directly, since they won't receive
209208 // RedrawRequested events on Windows. This ensures that viewport
210209 // commands like Visible(true) are still processed.
211- for window_id in invisible_window_ids {
212- let event_result = self . winit_app . run_ui_and_paint ( event_loop, window_id) ;
210+ for window_id in & invisible_window_ids {
211+ let event_result = self . winit_app . run_ui_and_paint ( event_loop, * window_id) ;
213212 self . handle_event_result ( event_loop, event_result) ;
214213 }
215214
215+ // Schedule a throttled repaint for invisible windows so they keep
216+ // processing viewport commands even when egui doesn't request repaints.
217+ // See: https://github.com/emilk/egui/issues/7776
218+ if !invisible_window_ids. is_empty ( ) {
219+ let next_paint = Instant :: now ( ) + std:: time:: Duration :: from_millis ( 100 ) ;
220+ for window_id in & invisible_window_ids {
221+ self . windows_next_repaint_times
222+ . entry ( * window_id)
223+ . and_modify ( |t| * t = ( * t) . min ( next_paint) )
224+ . or_insert ( next_paint) ;
225+ }
226+ }
227+
216228 let next_repaint_time = self . windows_next_repaint_times . values ( ) . min ( ) . copied ( ) ;
217229 if let Some ( next_repaint_time) = next_repaint_time {
218230 event_loop. set_control_flow ( ControlFlow :: WaitUntil ( next_repaint_time) ) ;
@@ -289,6 +301,16 @@ impl<T: WinitApp> ApplicationHandler<UserEvent> for WinitAppWrapper<T> {
289301 if let Some ( window_id) =
290302 self . winit_app . window_id_from_viewport_id ( viewport_id)
291303 {
304+ // Throttle repaints for invisible windows to prevent
305+ // high CPU usage on Windows.
306+ // See: https://github.com/emilk/egui/issues/7776
307+ let when = if let Some ( window) = self . winit_app . window ( window_id)
308+ && window. is_visible ( ) == Some ( false )
309+ {
310+ when. max ( Instant :: now ( ) + std:: time:: Duration :: from_millis ( 100 ) )
311+ } else {
312+ when
313+ } ;
292314 Ok ( EventResult :: RepaintAt ( window_id, when) )
293315 } else {
294316 Ok ( EventResult :: Wait )
0 commit comments