Moves application termination handling to FlutterAppDelegate.
Previously, we required macOS applications using Flutter to ensure their
main application class was FlutterApplication. Instead, we now do all
handling in FlutterAppDelegate and FlutterEngine.
There are two termination workflows to consider:
* Termination requested from framework side: In this case, then engine
receives a `System.exitApplication` method call, and starts the app
termination workflow via `[FlutterEngine
requestApplicationTermination:exitType:result]`.
* Termination requested from macOS (e.g. Cmd-Q): In this case,
`FlutterAppDelegate`'s `applicationShouldTerminate:` handler is invoked
by AppKit, and the delegate starts the app termination workflow via
`[FlutterEngine requestApplicationTermination:exitType:result]`.
In either case, at this point, if the request is not cancellable, the
app immediately exits. If it is cancellable, the embedder sends a
`System.requestAppExit` method channel invocation to the framework,
which responds with either `exit` or `cancel`. In the case of `exit` we
immediately exit, otherwise we do nothing and the app continues running.
This is a minor refactoring of the original approach we took in:
https://github.com/flutter/engine/pull/39836
This does not remove the FlutterApplication class, since the framework
migration from NSApplication to FlutterApplication still depends on it.
A followup patch with replace the migration with a reverse migration
will land, then FlutterApplication will be removed.
Issue: https://github.com/flutter/flutter/issues/30735
No new tests since this refactors existing behaviour while retaining the
same app semantics as before.
(this is attempt 3; details below)
Remove obsolete object caches and introduce a simpler way to manage
native objects:
* Remove the unused `SynchronousSkiaObjectCache`.
* Introduce new library `native_memory.dart` that's smaller and simpler
than `skia_object_cache.dart`.
* Introduce two types of native object references:
* `UniqueRef` a reference with a unique Dart object owner.
* `CountedRef` a ref-counted reference with multiple Dart object owners.
* All native references use GC (via `FinalizationRegistry`) as a
back-up.
* The new library removes everything related to object resurrection that
was needed only in browsers that didn't support `FinalizationRegistry`.
All browsers support it now.
* Remove the ad hoc `SkParagraph` cache that predates the introduction
of `Paragraph.dispose`.
* Rewrite `CkParagraph` in terms of `UniqueRef`.
* Rewrite `CkImage` in terms of `CountedRef`; delete `SkiaObjectBox`.
This PR does not migrate all objects from the old
`skia_object_cache.dart` to `native_memory.dart`. That would be too big
of a change. The migration can be done in multiple smaller PRs.
This also removes a few unnecessary relayouts observed in
https://github.com/flutter/flutter/issues/120921, but not all of them
(more details in
https://github.com/flutter/flutter/issues/120921#issuecomment-1481958762)
## About attempt 3
More about [attempt 2
here](https://github.com/flutter/engine/pull/40862).
In this attempt 3 I'm replacing the `factory` with a top-level function.
Reverts flutter/engine#40886
This renders incorrectly when applied directly to contents instead of as
a filter, essentially due to some transform mis handling.
The code only works when the snapshot has an identity transform, which
is only true as a subpass
With this approach, when the last window of an app is closed, the engine
sends a message to the framework to check if it is allowed to exit. If
it may, the windows lifecycle manager synthesizes a second `WM_CLOSE`
message that it will ignore, and so the next registered top level window
proc delegate, if any, will be able to process the message. If none do
so, the message will be handled by the default window proc, so the app
will be able to close.
I was not able to get a full system tray example application running to
test this, but I could get an application that stays open when its
window is closed and can be seen as a system tray icon as long as it is
running, albeit the icon was non-functional. As this repro app still
exhibited this behavior when using this engine build, I am reasonably
confident in concluding that applications that want to be able to run
headless when their windows close will function properly.
Addresses https://github.com/flutter/flutter/issues/123654.
## 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 <737941+loic-sharma@users.noreply.github.com>
Reverts flutter/engine#40862
Google Testing is failing on
```
The compiler crashed: root:🎯_engine::SkObjectFinalizationRegistry::@methods::|staticInteropFactoryStub is already bound to Reference to dart:_engine::SkObjectFinalizationRegistry::@methods::|staticInteropFactoryStub, trying to bind to Reference to SkObjectFinalizationRegistry.|staticInteropFactoryStub with node SkObjectFinalizationRegistry.|staticInteropFactoryStub (Procedure:1207727)
```