@@ -27,7 +27,7 @@ class MockFlutterWindow : public FlutterWindow {
2727 ON_CALL (*this , GetDpiScale ())
2828 .WillByDefault (Return (this ->FlutterWindow ::GetDpiScale ()));
2929 }
30- virtual ~MockFlutterWindow () {}
30+ virtual ~MockFlutterWindow () { SetView ( nullptr ); }
3131
3232 // Wrapper for GetCurrentDPI() which is a protected method.
3333 UINT GetDpi () { return GetCurrentDPI (); }
@@ -229,6 +229,10 @@ TEST(FlutterWindowTest, OnPointerStarSendsDeviceType) {
229229 kDefaultPointerDeviceId , WM_LBUTTONDOWN);
230230 win32window.OnPointerLeave (10.0 , 10.0 , kFlutterPointerDeviceKindStylus ,
231231 kDefaultPointerDeviceId );
232+
233+ // Destruction of win32window sends a HIDE update. In situ, the window is
234+ // owned by the delegate, and so is destructed first. Not so here.
235+ win32window.SetView (nullptr );
232236}
233237
234238// Tests that calls to OnScroll in turn calls GetScrollOffsetMultiplier
@@ -324,5 +328,61 @@ TEST(FlutterWindowTest, AlertNode) {
324328 EXPECT_EQ (role.lVal , ROLE_SYSTEM_ALERT);
325329}
326330
331+ TEST (FlutterWindowTest, LifecycleFocusMessages) {
332+ MockFlutterWindow win32window;
333+ ON_CALL (win32window, GetPlatformWindow).WillByDefault ([]() {
334+ return reinterpret_cast <HWND>(1 );
335+ });
336+ MockWindowBindingHandlerDelegate delegate;
337+ win32window.SetView (&delegate);
338+
339+ WindowStateEvent last_event;
340+ ON_CALL (delegate, OnWindowStateEvent)
341+ .WillByDefault ([&last_event](HWND hwnd, WindowStateEvent event) {
342+ last_event = event;
343+ });
344+
345+ win32window.InjectWindowMessage (WM_SIZE, 0 , 0 );
346+ EXPECT_EQ (last_event, WindowStateEvent::kHide );
347+
348+ win32window.InjectWindowMessage (WM_SIZE, 0 , MAKEWORD (1 , 1 ));
349+ EXPECT_EQ (last_event, WindowStateEvent::kShow );
350+
351+ win32window.InjectWindowMessage (WM_SETFOCUS, 0 , 0 );
352+ EXPECT_EQ (last_event, WindowStateEvent::kFocus );
353+
354+ win32window.InjectWindowMessage (WM_KILLFOCUS, 0 , 0 );
355+ EXPECT_EQ (last_event, WindowStateEvent::kUnfocus );
356+ }
357+
358+ TEST (FlutterWindowTest, CachedLifecycleMessage) {
359+ MockFlutterWindow win32window;
360+ ON_CALL (win32window, GetPlatformWindow).WillByDefault ([]() {
361+ return reinterpret_cast <HWND>(1 );
362+ });
363+
364+ // Restore
365+ win32window.InjectWindowMessage (WM_SIZE, 0 , MAKEWORD (1 , 1 ));
366+
367+ // Focus
368+ win32window.InjectWindowMessage (WM_SETFOCUS, 0 , 0 );
369+
370+ MockWindowBindingHandlerDelegate delegate;
371+ bool focused = false ;
372+ bool restored = false ;
373+ ON_CALL (delegate, OnWindowStateEvent)
374+ .WillByDefault ([&](HWND hwnd, WindowStateEvent event) {
375+ if (event == WindowStateEvent::kFocus ) {
376+ focused = true ;
377+ } else if (event == WindowStateEvent::kShow ) {
378+ restored = true ;
379+ }
380+ });
381+
382+ win32window.SetView (&delegate);
383+ EXPECT_TRUE (focused);
384+ EXPECT_TRUE (restored);
385+ }
386+
327387} // namespace testing
328388} // namespace flutter
0 commit comments