This migrates PlatformViewController from C++ to Objective-C. Generally, we try to keep the embedder interfaces and components written in Objective-C except for the few places where C++ interfaces are requried to interface with engine APIs such as Shell and PlatformView (e.g. the PlatformViewIOS subclass). Now that the implementation is Objective-C, the class and file are renamed to match Objective-C naming conventions.
This allows us to take advantage of ARC and weak references, which eliminates the need for std::shared_ptr, fml::WeakPtr etc. Further, this eliminates some particularly unintuitive behaviour wherein this class was owned via a std::shared_ptr held by FlutterEngine, and injected into many other classes (e.g. AccessibilityBridge) via a std::shared_ptr& reference -- such that only one instance of the std::shared_ptr actually ever existed, presumably to avoid std::shared_ptr refcounting overhead. Given that this overhead was only incurred a single time at engine initialisation, this seems like overkill. One might ask why it wasn't therefore held in a `std::unique_ptr` and a `std::unique_ptr&` reference passed around. Likely, this was because we wanted to take a `fml::WeakPtr` reference on it.
Regardless, none of this is necessary any longer now that we can inject `__weak FlutterPlatformViewsController*` instances to classes that use it.
To be clear, this patch makes no attempt whatsoever to simplify or clean up the interface or implementation of this class. This class ties together far too many concepts and is injected into far too many places, and we should break it up and simplify it. However, the goal of this patch was simply to port to an Objective-C interface that plays nicely with the rest of the iOS embedder. This does include a couple minor cleanups in `#include`/`#import` order and usage to match our style guide.
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
Reverts: flutter/engine#56606
Initiated by: LongCatIsLooong
Reason for reverting: https://github.com/flutter/flutter/issues/159456
Original PR Author: LongCatIsLooong
Reviewed By: {chunhtai, cbracken}
This change reverts the following previous change:
This PR adds basic FKA scrolling support: when the iOS focus (the focus state is maintained separately from the framework focus, see the previous PR) switches to an item in a scrollable container that is too close to the edge of the viewport, the container will scroll to make sure the next item is visible.
Previous PR for context: https://github.com/flutter/engine/pull/55964https://github.com/user-attachments/assets/84ae5153-f955-4d23-9901-ce942c0e98ac
### Why the UIScrollView subclass in the focus hierarchy
The iOS focus system does not provide an API that allows apps to notify it of focus highlight changes. So if we were to keep using the transforms sent by the framework as-is and not introducing any UIViews in the focus hierarchy, the focus highlight will be positioned at the wrong location after scrolling (via FKA or via framework). That does not seem to be part of the public API and the focus system seems to only know how to properly highlight focusable UIViews.
### Things that currently may not work
1. Nested scroll views (have not tried to verify)
The `UIScrollView`s are always subviews of the `FlutterView`. If there are nested scrollables the focus system may not be able to properly determine the focus hierarchy (in theory the iOS focus system should never depend on `UIView.parentView` but I haven't tried to verify that).
2. If the next item is too far below the bottom of the screen and there is a tab bar with focusable items, the focus will be transferred to tab bar instead of the next item in the list
Video demo (as you can see the scrolling is really finicky):
https://github.com/user-attachments/assets/51c2bfe4-d7b3-4614-aa49-4256214f8978
I've tried doing the same thing using a `UITableView` with similar configurations but it seems to have the same problem. I'll try to dig a bit deeper into this and see if there's a workaround.
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
For https://github.com/flutter/flutter/pull/158881
The new Android m3 page transition animates a saveLayer w/ opacity + slide in animation. See example video from linked PR:
https://github.com/user-attachments/assets/1382374a-4e0c-4a0e-9d70-948ce12e6298
On each frame, we intersect the coverage rect of this saveLayer contents with the screen rect, and shrink it to a partial rectangle. But this changes each frame, which forces us to re-allocate a large texture each frame, causing performance issues.
Why not ignore the cull rect entirely? We sometimes ignore the cull rect for the image filter layer for similar reasons, but from observation, the sizes of these saveLayer can be slightly larger than the screen for flutter gallery. Instead, I attempted to use the cull rect size to shrink the saveLayer by shifting the origin before intersecting.
I think this should be safe to do, as I believe it could only leave the coverage as larger than it would have been and not smaller.
In flutter/engine#35501, handling was added to log a debug message to the console in the case where a platform view with a non-zero origin was identified.
Unfortunately:
* In unopt builds, the first thing we do in that block is to call FML_DCHECK asserting that the origin is zero, so we never actually emit the log statement.
* In opt builds, FML_DCHECK is a no-op, so users are unlikely to actually ever notice the crash.
The proper fix is to eliminate this restriction, but in the meantime, this eliminates this block entirely and leaves the TODO. We've had only two comments on that bug in the 2.5 years since it was added.
Issue: https://github.com/flutter/flutter/issues/109700
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
This PR adds basic FKA scrolling support: when the iOS focus (the focus state is maintained separately from the framework focus, see the previous PR) switches to an item in a scrollable container that is too close to the edge of the viewport, the container will scroll to make sure the next item is visible.
Previous PR for context: https://github.com/flutter/engine/pull/55964https://github.com/user-attachments/assets/84ae5153-f955-4d23-9901-ce942c0e98ac
### Why the UIScrollView subclass in the focus hierarchy
The iOS focus system does not provide an API that allows apps to notify it of focus highlight changes. So if we were to keep using the transforms sent by the framework as-is and not introducing any UIViews in the focus hierarchy, the focus highlight will be positioned at the wrong location after scrolling (via FKA or via framework). That does not seem to be part of the public API and the focus system seems to only know how to properly highlight focusable UIViews.
### Things that currently may not work
1. Nested scroll views (have not tried to verify)
The `UIScrollView`s are always subviews of the `FlutterView`. If there are nested scrollables the focus system may not be able to properly determine the focus hierarchy (in theory the iOS focus system should never depend on `UIView.parentView` but I haven't tried to verify that).
2. If the next item is too far below the bottom of the screen and there is a tab bar with focusable items, the focus will be transferred to tab bar instead of the next item in the list
Video demo (as you can see the scrolling is really finicky):
https://github.com/user-attachments/assets/51c2bfe4-d7b3-4614-aa49-4256214f8978
I've tried doing the same thing using a `UITableView` with similar configurations but it seems to have the same problem. I'll try to dig a bit deeper into this and see if there's a workaround.
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
Bumps the version of AGP used in the IDE-support `build.gradle`, as well as the robolectric version in both the IDE-support `build.gradle` and test-runner-`build.gradle`.
This is the current latest robolectric: https://github.com/robolectric/robolectric/releases/tag/robolectric-4.14.1.
Also
1. configures robolectric to use API 35, and
2. removes the use of a deprecated class which (from what I could tell) looked like it was just used for setup, and the test still passes without it.
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
Internal bug: b/380745221
The use of `malloc` in L70:
d48ceb1ba2/third_party/tonic/filesystem/filesystem/file.cc (L70)
Results in the following error, after an update to the internal toolchain. For some reason, this error only appears when targeting Linux.
```
tonic/filesystem/filesystem/file.cc:70:28: error: use of undeclared identifier 'malloc'
70 | uint8_t* ptr = (uint8_t*)malloc(file_size);
| ^
1 error generated.
```
This PR fixes it by including the header file.
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
Reverts: flutter/engine#56738
Initiated by: jonahwilliams
Reason for reverting: speculative revert for framework failures.
Original PR Author: jonahwilliams
Reviewed By: {jason-simmons}
This change reverts the following previous change:
Changes the following shell callbacks to flush the dart event loop:
* OnPlatformViewSetViewportMetrics
* OnPlatformViewDispatchPointerDataPacket
* OnPlatformViewDispatchPlatformMessage
* OnPlatformViewSetSemanticsEnabled
* OnPlatformViewSetAccessibilityFeatures
Using a new TaskRunner API RunNowAndFlushMessages. If the task runner can run tasks on the current thread, this will immediately invoke a callback and then post an empty task to the event loop to ensure dart listeners fire.
This also updates the vsync waiter to use RunNowOrPostTask, so that we start vsync events as early as possible.
The Skia snapshot controller will activate the delegate's surface render context on the current thread. If the delegate has no surface, then it will use the snapshot surface producer to create a temporary surface.
The Impeller snapshot controller needs to do the same in order to support OpenGL/GLES scenarios where the thread does not currently have an EGL context.
The DlColorSource code uses Skia geometry classes for its internal computations. This PR switches those implementations to use the Impeller geometry classes for consistency and 3rd party header file independence.
Creating and attaching textures/render buffers to a FBO is an expensive operation. Similar to how we cache vulkan framebuffers/render passes, we can cache the FBO object on the color0 texture to avoid extra state invalidation.
Part of https://github.com/flutter/flutter/issues/159177
Changes the following shell callbacks to flush the dart event loop:
* OnPlatformViewSetViewportMetrics
* OnPlatformViewDispatchPointerDataPacket
* OnPlatformViewDispatchPlatformMessage
* OnPlatformViewSetSemanticsEnabled
* OnPlatformViewSetAccessibilityFeatures
Using a new TaskRunner API RunNowAndFlushMessages. If the task runner can run tasks on the current thread, this will immediately invoke a callback and then post an empty task to the event loop to ensure dart listeners fire.
This also updates the vsync waiter to use RunNowOrPostTask, so that we start vsync events as early as possible.
Moves code specific to each graphics backend into the (existing) translation unit associated with that backend.
Previously, we could not include any Objective-C types in `shell_test_platform_view_metal.h`, since that file was included into `shell_test_platform_view.cc`, which is pure C++. To work around this, we had encapsulated Objective-C Metal types in a `DarwinContextMetal` struct hidden in the implementation file with a pointer to it forward-declared in the header.
We now use Metal types directly in the header, without the workarounds.
Issue: https://github.com/flutter/flutter/issues/158998
Issue: https://github.com/flutter/flutter/issues/137801
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
`kDefaultBackendType` is intended to make life easier for authors of tests, but in any switch statement where it's used (currently just a single location), we rely on ordering it first and `#ifdef`ing out all backends that aren't available.
Instead, we define a static function that returns the default that callers can invoke instead. This avoids relinace on case ordering and fallthrough.
In https://github.com/flutter/engine/pull/56722 we split backends out into separate translation units, and ideally should remove the `#ifdef`s, which means we can't rely on this trick anymore.
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
_`impeller.hpp` is to `impeller.h` what `vulkan.hpp` is to `vulkan.h`_
* A single header C++ 17 library that only depends on impeller.h and standard libc++ utilities.
* The C++ library proc. table is setup at runtime (via dlsym and related methods). Impeller users don't need to link against libimpeller.so as long as they can discover it at runtime.
* RAII wrappers for all opaque objects.
* Namespaces are configurable depending on target.
* Included in the distributed SDK next to impeller.h.
The Info.plist override was missed earlier.
The main changes to the tests are due to the UI thread merge with the platform thread. The amendment to the "spawn" API are due to the fact that the assertions checked for the presence of GrDirectContext which will never exist with Impeller.
Unblocks https://github.com/flutter/engine/pull/56706
Reverts: flutter/engine#56705
Initiated by: jonahwilliams
Reason for reverting: goldens occassionally fail to render anything.
Original PR Author: jonahwilliams
Reviewed By: {gaaclarke}
This change reverts the following previous change:
Adds multisampling support for GLES devices without GL_EXT_multisampled_render_to_texture provided they are at least GLES 3.0 to support mutlisampled render buffers.
Fixes https://github.com/flutter/flutter/issues/158360
Fixes https://github.com/flutter/flutter/issues/157951
TBD: should we prefer renderbuffer 3.0 approach over multisample_render_to_texture?
This PR introduces a `NativeAssetsManifest.json` next to the `AssetManifest.json` and `FontManifest.json`. This removes the need for embedding the native assets mapping inside the kernel file and will enable decoupling native assets building and bundling from the kernel compilation in flutter tools. This will then allow us to remove dry-run from the build hook protocol.
(It also means all isolate groups will have the same native assets. However, since Flutter does not support `Isolate.spawnUri` from kernel files anyways, this is not a regression.)
This manifest is parsed eagerly on startup by the engine in a manner similar to how the font manifest is parsed. The manifest contents need to be available in the callback for resolving assets, which does not have access to the engine. Therefore the parsed manifest is `NativeAssetsManager` stored in the `IsolateGroupData`. The engine passes it in on isolate group creation, and the FFI callbacks access it from the isolate group data.
Issue:
* https://github.com/flutter/flutter/issues/154425
Related PRs:
* https://dart-review.googlesource.com/c/sdk/+/388161
Follow up work:
* This PR does not yet remove the engine callbacks registered via the dart_api that rely on kernel embedding. If we were to do that in this PR, it would require a manual roll of the engine into flutter/flutter with the PR that switches flutter_tools to emit the native assets manifest instead of embedding in kernel, and a manual roll into g3 to switch emitting a manifest instead of embedding in kernel. A TODO is left in the code for those callbacks to be removed.
## Testing
Most of this PR cannot be tested in isolation. The code in this PR is heavily exercised in the follow up flutter_tools PR which creates the `NativeAssetsManifest.json` and removes the embedding of native assets in kernel files.
* This PR adds a unit test for parsing the JSON manifest.
[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style