@@ -71,6 +71,7 @@ pub struct SharedState {
7171 painter : egui_wgpu:: winit:: Painter ,
7272 viewport_from_window : HashMap < WindowId , ViewportId > ,
7373 focused_viewport : Option < ViewportId > ,
74+ resized_viewport : Option < ViewportId > ,
7475}
7576
7677pub type Viewports = egui:: OrderedViewportIdMap < Viewport > ;
@@ -302,6 +303,7 @@ impl<'app> WgpuWinitApp<'app> {
302303 viewports,
303304 painter,
304305 focused_viewport : Some ( ViewportId :: ROOT ) ,
306+ resized_viewport : None ,
305307 } ) ) ;
306308
307309 {
@@ -763,20 +765,34 @@ impl WgpuWinitRunning<'_> {
763765 let viewport_id = shared. viewport_from_window . get ( & window_id) . copied ( ) ;
764766
765767 // On Windows, if a window is resized by the user, it should repaint synchronously, inside the
766- // event handler.
767- //
768- // If this is not done, the compositor will assume that the window does not want to redraw,
769- // and continue ahead.
768+ // event handler. If this is not done, the compositor will assume that the window does not want
769+ // to redraw and continue ahead.
770770 //
771771 // In eframe's case, that causes the window to rapidly flicker, as it struggles to deliver
772- // new frames to the compositor in time.
773- //
774- // The flickering is technically glutin or glow's fault, but we should be responding properly
772+ // new frames to the compositor in time. The flickering is technically glutin or glow's fault, but we should be responding properly
775773 // to resizes anyway, as doing so avoids dropping frames.
776774 //
777775 // See: https://github.com/emilk/egui/issues/903
778776 let mut repaint_asap = false ;
779777
778+ // On MacOS the asap repaint is not enough. The drawn frames must be synchronized with
779+ // the CoreAnimation transactions driving the window resize process.
780+ //
781+ // Thus, Painter, responsible for wgpu surfaces and their resize, has to be notified of the
782+ // resize lifecycle, yet winit does not provide any events for that. To work around,
783+ // the last resized viewport is tracked until any next non-resize event is received.
784+ //
785+ // Accidental state change during the resize process due to an unexpected event fire
786+ // is ok, state will switch back upon next resize event.
787+ //
788+ // See: https://github.com/emilk/egui/issues/903
789+ if let Some ( id) = viewport_id
790+ && shared. resized_viewport == viewport_id
791+ {
792+ shared. painter . on_window_resize_state_change ( id, false ) ;
793+ shared. resized_viewport = None ;
794+ }
795+
780796 match event {
781797 winit:: event:: WindowEvent :: Focused ( focused) => {
782798 let focused = if cfg ! ( target_os = "macos" )
@@ -799,14 +815,18 @@ impl WgpuWinitRunning<'_> {
799815 // Resize with 0 width and height is used by winit to signal a minimize event on Windows.
800816 // See: https://github.com/rust-windowing/winit/issues/208
801817 // This solves an issue where the app would panic when minimizing on Windows.
802- if let Some ( viewport_id ) = viewport_id
818+ if let Some ( id ) = viewport_id
803819 && let ( Some ( width) , Some ( height) ) = (
804820 NonZeroU32 :: new ( physical_size. width ) ,
805821 NonZeroU32 :: new ( physical_size. height ) ,
806822 )
807823 {
824+ if shared. resized_viewport != viewport_id {
825+ shared. resized_viewport = viewport_id;
826+ shared. painter . on_window_resize_state_change ( id, true ) ;
827+ }
828+ shared. painter . on_window_resized ( id, width, height) ;
808829 repaint_asap = true ;
809- shared. painter . on_window_resized ( viewport_id, width, height) ;
810830 }
811831 }
812832
0 commit comments