@@ -31,6 +31,25 @@ void drawHelloWorld(ui.FlutterView view) {
3131  view.render (sceneBuilder.build ());
3232}
3333
34+ Future <void > _waitUntilWindowVisible () async  {
35+   while  (! await  isWindowVisible ()) {
36+     await  Future <void >.delayed (const  Duration (milliseconds:  100 ));
37+   }
38+ }
39+ 
40+ void  _expectVisible (bool  current, bool  expect, Completer <String > completer, int  frameCount) {
41+   if  (current !=  expect) {
42+     try  {
43+       throw  'Window should be ${expect  ? 'visible'  : 'hidden' } on frame $frameCount ' ;
44+     } catch  (e) {
45+       if  (! completer.isCompleted) {
46+         completer.completeError (e);
47+       }
48+       rethrow ;
49+     }
50+   }
51+ }
52+ 
3453void  main () async  {
3554  // TODO(goderbauer): Create a window if embedder doesn't provide an implicit view to draw into. 
3655  assert (ui.PlatformDispatcher .instance.implicitView !=  null );
@@ -70,27 +89,39 @@ void main() async {
7089      throw  'Window should be hidden at startup' ;
7190    }
7291
73-     bool  firstFrame =  true ;
74-     ui.PlatformDispatcher .instance.onBeginFrame =  (Duration  duration) async  {
75-       if  (await  isWindowVisible ()) {
76-         if  (firstFrame) {
77-           throw  'Window should be hidden on first frame' ;
78-         }
79- 
80-         if  (! visibilityCompleter.isCompleted) {
81-           visibilityCompleter.complete ('success' );
82-         }
92+     int  frameCount =  0 ;
93+     ui.PlatformDispatcher .instance.onBeginFrame =  (Duration  duration) {
94+       // Our goal is to verify that it's `drawHelloWorld` that makes the window 
95+       // appear, not anything else. This requires checking the visibility right 
96+       // before drawing, but since `isWindowVisible` has to be async, and 
97+       // `FlutterView.render` (in `drawHelloWorld`) forbids async before it, 
98+       // this can not be done during a single onBeginFrame. However, we can 
99+       // verify in separate frames to indirectly prove it, by ensuring that 
100+       // no other mechanism can affect isWindowVisible in the first frame at all. 
101+       frameCount +=  1 ;
102+       switch  (frameCount) {
103+         // The 1st frame: render nothing, just verify that the window is hidden. 
104+         case  1 : 
105+           isWindowVisible ().then ((bool  visible) {
106+             _expectVisible (visible, false , visibilityCompleter, frameCount);
107+             ui.PlatformDispatcher .instance.scheduleFrame ();
108+           });
109+         // The 2nd frame: render, which makes the window appear. 
110+         case  2 : 
111+           drawHelloWorld (view);
112+           _waitUntilWindowVisible ().then ((_) {
113+             if  (! visibilityCompleter.isCompleted) {
114+               visibilityCompleter.complete ('success' );
115+             }
116+           });
117+         // Others, in case requested to render. 
118+         default : 
119+           drawHelloWorld (view);
83120      }
84- 
85-       // Draw something to trigger the first frame callback that displays the 
86-       // window. 
87-       drawHelloWorld (view);
88-       firstFrame =  false ;
89121    };
90- 
91-     ui.PlatformDispatcher .instance.scheduleFrame ();
92122  } catch  (e) {
93123    visibilityCompleter.completeError (e);
94124    rethrow ;
95125  }
126+   ui.PlatformDispatcher .instance.scheduleFrame ();
96127}
0 commit comments