Skip to content

Conversation

@knopp
Copy link
Member

@knopp knopp commented Mar 9, 2025

Required for multi-window.

On windows the LifecycleManager currently sends the lifecycle event as soon as windows message is processed. This however causes problems when changing focus between application windows.

When switching focus from HWND1 to HWND2, HWND1 first gets unfocused, followed by HWND2 getting focused. After HWND1 gets unfocused, LifecycleManager immediately notifies the framework that the application is inactive, which is wrong as the application never went into inactive state, followed by subsequent call to put the application in resumed state when HWND2 is focused. Because this happens very quickly, sometimes focus manager gets into inconsistent state.

To resolve this LifecycleManager should gather the all the changes while window sends the messages and then notify the framework atomically in next run loop turn.

This PR also simplifies the logic in LifecycleManager through which the application state is derived from window states.

This PR removes engine forcing resumed lifecycle state at startup. I'm not entirely sure what the point of this was - the state can and should be determined solely from window states, this just seems to muddy the state logic. Also it happens before the framework is even listening to state changes.

The mutex in WindowsLifecycleManager is removed. Not sure why it was there.

Pre-launch Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

@knopp knopp requested a review from loic-sharma March 9, 2025 17:02
@github-actions github-actions bot added engine flutter/engine related. See also e: labels. platform-windows Building on or for Windows specifically a: desktop Running on desktop labels Mar 9, 2025
@knopp knopp requested review from hbatagelo and mattkae March 9, 2025 17:02
Copy link
Contributor

@mattkae mattkae left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks reasonable to me! If someone else who has more opinions about the system wants to comment, please be my guest :)

@knopp
Copy link
Member Author

knopp commented Mar 10, 2025

Note that this fixes the window being stuck in focus/unfocus loop in the multi-window branch when switching between windows.

Copy link
Contributor

@hbatagelo hbatagelo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! In the reference app, I got the focus switch loop fixed by parenting the FocusTraversalGroup of each root view to the root focus scope, but I wasn't aware that the actual cause could be in the lifecycle manager!

@knopp
Copy link
Member Author

knopp commented Mar 10, 2025

but I wasn't aware that the actual cause could be in the lifecycle manager!

@hbatagelo, those are actually two different loops. The one here causes the following issue:

focus.mov

It is due to application temporarily entering inactive state while switching between two windows.

It is unrelated to focus traversal loop, which is caused by nested scopes.

Copy link
Member

@loic-sharma loic-sharma left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice fix and cleanup, thanks!

@knopp knopp force-pushed the win_multiwindow_lifecycle branch from c03f6f0 to afb71ef Compare March 11, 2025 10:14
@knopp knopp enabled auto-merge March 11, 2025 10:33
@knopp knopp added this pull request to the merge queue Mar 11, 2025
Merged via the queue into flutter:master with commit b1d0ffb Mar 11, 2025
170 checks passed
@knopp knopp deleted the win_multiwindow_lifecycle branch March 11, 2025 11:53
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 11, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 11, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 11, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 15, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 15, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 16, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 16, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 16, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 17, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 20, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 25, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 25, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 26, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 26, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 26, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 26, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 26, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 26, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 26, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 26, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 27, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 27, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 27, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 27, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 27, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 27, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 27, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 27, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 28, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request May 20, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request May 20, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request May 21, 2025
romanejaquez pushed a commit to romanejaquez/flutter that referenced this pull request Aug 14, 2025
Required for multi-window.

On windows the `LifecycleManager` currently sends the lifecycle event as
soon as windows message is processed. This however causes problems when
changing focus between application windows.

When switching focus from HWND1 to HWND2, HWND1 first gets unfocused,
followed by HWND2 getting focused. After HWND1 gets unfocused,
`LifecycleManager` immediately notifies the framework that the
application is inactive, which is wrong as the application never went
into inactive state, followed by subsequent call to put the application
in resumed state when HWND2 is focused. Because this happens very
quickly, sometimes focus manager gets into inconsistent state.

To resolve this `LifecycleManager` should gather the all the changes
while window sends the messages and then notify the framework atomically
in next run loop turn.

This PR also simplifies the logic in `LifecycleManager` through which
the application state is derived from window states.

This PR removes engine forcing `resumed` lifecycle state at startup. I'm
not entirely sure what the point of this was - the state can and should
be determined solely from window states, this just seems to muddy the
state logic. Also it happens before the framework is even listening to
state changes.

The mutex in `WindowsLifecycleManager` is removed. Not sure why it was
there.

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x ] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md

---------

Co-authored-by: Matthew Kosarek <[email protected]>
Co-authored-by: Harlen Batagelo <[email protected]>
Co-authored-by: Loïc Sharma <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a: desktop Running on desktop engine flutter/engine related. See also e: labels. platform-windows Building on or for Windows specifically

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants