-
Notifications
You must be signed in to change notification settings - Fork 6k
Reintroduce Windows lifecycle with guard for posthumous OnWindowStateEvent
#44344
Conversation
|
Should I incorporate the changes in #44238 into this PR? Doing so will resolve the startup warnings issue at the same time, but will make this a rather broad request. |
shell/platform/windows/window.h
Outdated
| std::unique_ptr<ui::AXPlatformNodeWin> alert_node_; | ||
|
|
||
| // Guard against posthumous vtable access; | ||
| bool vtable_is_alive = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is spooky. Some potential alternative options:
- Merge
FlutterWindowandWindowto make destruction simpler - Expose a
Destroymethod to destroy the window manually. This would need to be called before theWindowis destructed to ensure no messages are receive post destruction. - Switch from an inheritance pattern to a delegate pattern so that the
Windowis destructed before theFlutterWindow
What are your thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- I do not see any reason why they need to be separate classes, though I am a little nervous about trying it. As long as it's safe, and no one will complain about needing both classes for some 3rd party or future change, this seems like a valid option.
- We could also try this, though do we know from where we could call it, or also importantly, if we have any way to ensure it's called before destruction?
- If
FlutterWindowis our only use case forWindow, merging the classes seems like a better idea.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- I do not see any reason why they need to be separate classes, though I am a little nervous about trying it. As long as it's safe, and no one will complain about needing both classes for some 3rd party or future change, this seems like a valid option.
This type hierarchy is a common win32 C++ pattern: https://learn.microsoft.com/windows/win32/learnwin32/managing-application-state-#an-object-oriented-approach
I'm not in love with this pattern though 😅
- ... though do we know from where we could call it, or also importantly, if we have any way to ensure it's called before destruction?
One potential place might FlutterDesktopViewControllerDestroy. We could manually close the window before destroying our objects:
engine/shell/platform/windows/flutter_windows.cc
Lines 90 to 93 in 138a1ea
| void FlutterDesktopViewControllerDestroy( | |
| FlutterDesktopViewControllerRef controller) { | |
| delete controller; | |
| } |
- ... merging the classes seems like a better idea.
Agreed. Right now I'm leaning towards option 2, it seems like the least intrusive option.
/cc @cbracken For thoughts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think about moving the call to Window::Destroy() from ~Window to ~FlutterWindow? I just do not know how we can enforce within a test that window messages are received between the two destructors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the interest of getting this landed, agreed that option 2 (make Destroy() protected, then move the destroy call down to the subclass) is probably the quickest fix. Once that's landed, let's follow up with a patch that implements option 1 (merge Window and FlutterWindow).
I don't think there's a strong case for keeping them separate. Now that the UWP embedder is gone let's use the YAGNI rule here and merge the two. If we ever find a good reason for a separation, we can look at that in the future.
shell/platform/windows/window.h
Outdated
| std::unique_ptr<ui::AXPlatformNodeWin> alert_node_; | ||
|
|
||
| // Guard against posthumous vtable access; | ||
| bool vtable_is_alive = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On a separate note, I'm surprised the linter didn't catch the missing underscore suffix on this field. Probably irrelevant given the change in approach proposed for this patch, but I'll file a bug to see why the linters aren't running on windows.
| void SetNextFrameCallback(std::function<void()> callback); | ||
|
|
||
| // Called to pass an external window message to the engine for lifecycle | ||
| // state updates. This does not consume the window message. Non-Flutter |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| // state updates. This does not consume the window message. Non-Flutter | |
| // state updates. Non-Flutter |
| virtual void PluginRegistrarUnregisterTopLevelWindowProcDelegate( | ||
| FlutterDesktopWindowProcCallback delegate) {} | ||
|
|
||
| // Claled for FlutterDesktopEngineProcessExternalWindowMessage. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| // Claled for FlutterDesktopEngineProcessExternalWindowMessage. | |
| // Called for FlutterDesktopEngineProcessExternalWindowMessage. |
| FlutterDesktopViewRef view); | ||
|
|
||
| // Called to pass an external window message to the engine for lifecycle | ||
| // state updates. This does not consume the window message. Non-Flutter windows |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| // state updates. This does not consume the window message. Non-Flutter windows | |
| // state updates. Non-Flutter windows |
| // Called to pass an external window message to the engine for lifecycle | ||
| // state updates. This does not consume the window message. Non-Flutter windows | ||
| // must call this method in their WndProc in order to be included in the logic | ||
| // for application lifecycle state updates. Returns true when the message is |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| // for application lifecycle state updates. Returns true when the message is | |
| // for application lifecycle state updates. Returns true if the message should be |
| // the logic for application lifecycle state updates. Returns a result when | ||
| // the message has been consumed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| // the logic for application lifecycle state updates. Returns a result when | |
| // the message has been consumed. | |
| // the logic for application lifecycle state updates. Returns a result if | |
| // the message should be consumed. |
| // state updates. Non-Flutter | ||
| // windows must call this method in their WndProc in order to be included in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please reformat this to fill the line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment for FlutterDesktopEngineProcessExternalWindowMessage
shell/platform/windows/window.h
Outdated
| // Returns the root view accessibility node, or nullptr if none. | ||
| virtual gfx::NativeViewAccessible GetNativeViewAccessible() = 0; | ||
|
|
||
| // Release OS resources associated with window. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| // Release OS resources associated with window. | |
| // Release OS resources associated with the window. |
|
@yaakovschectman Before merging this, please verify that this latest approach also works as expected with the internal app team. |
|
@loic-sharma Someone from said team confirmed they experience no crash when testing with this build. |
loic-sharma
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, nice work! 🎉
Co-authored-by: Loïc Sharma <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
…132332) flutter/engine@a9be77e...16b01b9 2023-08-10 [email protected] Roll Dart SDK from 46da53e7abe2 to a2eac00da6b8 (1 revision) (flutter/engine#44601) 2023-08-10 [email protected] Fix unexpected pointer change issue and Add test case (flutter/engine#43949) 2023-08-10 [email protected] Reland "Android a11y bridge sets importantness" (flutter/engine#44589) 2023-08-10 [email protected] Support for Android Platform Views under Impeller/Vulkan (flutter/engine#44571) 2023-08-10 [email protected] Reintroduce Windows lifecycle with guard for posthumous `OnWindowStateEvent` (flutter/engine#44344) 2023-08-10 [email protected] Roll Skia from 92e6f52b0fa8 to b6492f5ce8c3 (1 revision) (flutter/engine#44597) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll Please CC [email protected],[email protected],[email protected] on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
…eEvent` (flutter#44344) Previously, destruction of `Window` called `DestroyWindow`, which may send `WM_KILLFOCUS` to the to-be-destroyed window. Because `Window`'s destructor is called after `FlutterWindow`'s, the `FlutterWindow` vtable was already destroyed at this point, and the subsequent call to the virtual method `OnWindowStateEvent` would cause a crash. This PR reintroduces the reverted changes for Windows lifecycle with a check before calling the virtual method that the `FlutterWindow` object has not yet been destructed. flutter/flutter#131872 *If you had to change anything in the [flutter/tests] repo, include a link to the migration guide as per the [breaking change policy].* ## 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] and the [C++, Objective-C, Java style guides]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I added new tests to check the change I am making or feature I am adding, or Hixie said the PR is test-exempt. See [testing the engine] for instructions on writing and running engine tests. - [x] I updated/added relevant documentation (doc comments with `///`). - [ ] I signed the [CLA]. - [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/wiki/Tree-hygiene#overview [Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene [Flutter Style Guide]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style [testing the engine]: https://github.com/flutter/flutter/wiki/Testing-the-engine [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/wiki/Chat --------- Co-authored-by: Loïc Sharma <[email protected]>

Previously, destruction of
WindowcalledDestroyWindow, which may sendWM_KILLFOCUSto the to-be-destroyed window. BecauseWindow's destructor is called afterFlutterWindow's, theFlutterWindowvtable was already destroyed at this point, and the subsequent call to the virtual methodOnWindowStateEventwould cause a crash. This PR reintroduces the reverted changes for Windows lifecycle with a check before calling the virtual method that theFlutterWindowobject has not yet been destructed.flutter/flutter#131872
If you had to change anything in the flutter/tests repo, include a link to the migration guide as per the breaking change policy.
Pre-launch Checklist
///).If you need help, consider asking for advice on the #hackers-new channel on Discord.