Skip to content

Conversation

LongCatIsLooong
Copy link
Contributor

@LongCatIsLooong LongCatIsLooong commented Aug 20, 2025

#104117

Adds a viewController (per #104117 (comment), presumably because iOS plugins want to presenting new view controllers) getter that makes the single-view assumption. This is a method instead of a weak + readonly property like the macOS registrar protocol because existing getters are also methods, e.g.,

- (NSObject<FlutterBinaryMessenger>*)messenger;
- (NSObject<FlutterTextureRegistry>*)textures;

Unfortunately swift callers will have to use a preprocess macro and add different code paths for macOS and iOS.

Single view assumption

I've considered adding a - (nullable UIViewController*)viewControllerForViewID: ViewIDType; method but that will force plugins to make breaking changes in order to migrate off of the deprecated keyWindow property. Take the text input plugin as an example, it has to add a viewID argument to the setTextInputClient call when establishing a new text input connection, so the text input plugin knows which view hierarchy to add the text input view to. It is unclear to me whether more FlutterPluginRegistrar changes are needed to completely get rid of the single-view assumption in the protocol (the views FlutterPlatformViewFactory creates are always added as subviews to flutterView so I guess that interface may have to change in the future? According to according to Flutter’s multi-window status, only a viewForIdentifier method will be added to registrar), so IMO it would be a better experience to not introduce the viewID concept right now and force plugins to make break changes, since they may have to make more breaking changes in the future.

Alternatively, we could also ignore the viewID args for now and always return the view controller of the implicit view in the implementation, so that plugin authors can use made-up view IDs to get the implicit view controller. But that's going to make future multiview migrations difficult since the compiler won't be able to catch unmigrated code if the plugin is using a bogus view ID.

Pre-launch Checklist

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

Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the gemini-code-assist bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

@github-actions github-actions bot added platform-ios iOS applications specifically engine flutter/engine related. See also e: labels. team-ios Owned by iOS platform team labels Aug 20, 2025
@LongCatIsLooong
Copy link
Contributor Author

LongCatIsLooong commented Aug 21, 2025

Hi @loic-sharma according to Multi-view runner APIs the only plugin registrar change required to add multiview support to the macOS plugin registrar is to add a get view by id method (which is pretty similar to what this PR does but for macOS). But adding that method now will require some plugins to add a viewID parameter to their API (in order to remove the deprecated keyWindow usages from their codebase), are you OK with adding the single view version first and deprecate this in favor of the multi view version in the future?

@@ -34,7 +34,7 @@ FLUTTER_DARWIN_EXPORT
* @param frame The rectangle for the newly created `UIView` measured in points.
* @param viewId A unique identifier for this `UIView`.
* @param args Parameters for creating the `UIView` sent from the Dart side of the Flutter app.
* If `createArgsCodec` is not implemented, or if no creation arguments were sent from the Dart
* If `createArgsCodec` is not implemented, or if no creation arguments were sent from the Dart
Copy link
Contributor Author

Choose a reason for hiding this comment

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

(unrelated change, removed an invisible character)

@loic-sharma
Copy link
Member

... are you OK with adding the single view version first and deprecate this in favor of the multi view version in the future?

For iOS that seems reasonable, yes. Plumbing view IDs around is a significant/painful migration, so it seems reasonable to do separate migrations for keyWindow and single view assumptions.

@LongCatIsLooong
Copy link
Contributor Author

To answer my own question regarding whether the platform view factory registration methods on the registrar interface would need a view ID parameter: looks like each layer (including those representing platform views) knows which view it is supposed to render on, so it probably doesn't need a view ID.

bool FlutterCompositor::Present(FlutterViewIdentifier view_id,
const FlutterLayer** layers,
size_t layers_count) {
FlutterView* view = [view_provider_ viewForIdentifier:view_id];
if (!view) {
return false;
}
NSMutableArray* surfaces = [NSMutableArray array];
for (size_t i = 0; i < layers_count; i++) {
const FlutterLayer* layer = layers[i];
if (layer->type == kFlutterLayerContentTypeBackingStore) {
FlutterSurface* surface =
[FlutterSurface fromFlutterMetalTexture:&layer->backing_store->metal.texture];
if (surface) {
FlutterSurfacePresentInfo* info = [[FlutterSurfacePresentInfo alloc] init];
info.surface = surface;
info.offset = CGPointMake(layer->offset.x, layer->offset.y);
info.zIndex = i;
FlutterBackingStorePresentInfo* present_info = layer->backing_store_present_info;
if (present_info != nullptr && present_info->paint_region != nullptr) {
auto paint_region = present_info->paint_region;
// Safe because the size of FlutterRect is not expected to change.
info.paintRegion = std::vector<FlutterRect>(
paint_region->rects, paint_region->rects + paint_region->rects_count);
}
[surfaces addObject:info];
}
}
}
CFTimeInterval presentation_time = 0;
if (layers_count > 0 && layers[0]->presentation_time != 0) {
presentation_time = [time_converter_ engineTimeToCAMediaTime:layers[0]->presentation_time];
}
// Notify block below may be called asynchronously, hence the need to copy
// the layer information instead of passing the original pointers from embedder.
auto layers_copy = std::make_shared<std::vector<LayerVariant>>(CopyLayers(layers, layers_count));
[view.surfaceManager presentSurfaces:surfaces
atTime:presentation_time
notify:^{
// Accessing presenters_ here does not need a
// lock to avoid race condition against
// AddView and RemoveView, since all three
// take place on the platform thread. (The
// macOS API requires platform view presenting
// to take place on the platform thread,
// enforced by `FlutterThreadSynchronizer`.)
dispatch_assert_queue(dispatch_get_main_queue());
auto found_presenter = presenters_.find(view_id);
if (found_presenter != presenters_.end()) {
found_presenter->second.PresentPlatformViews(
view, *layers_copy, platform_view_controller_);
}
}];
return true;
}

@LongCatIsLooong LongCatIsLooong marked this pull request as ready for review August 22, 2025 21:14
@LongCatIsLooong LongCatIsLooong requested a review from a team as a code owner August 22, 2025 21:14
@vashworth
Copy link
Contributor

Unfortunately swift callers will have to use a preprocess macro and add different code paths for macOS and iOS.

@stuartmorgan-g @LongCatIsLooong What do you think of adding a viewController property to the macOS version as well to keep them uniform?

@stuartmorgan-g
Copy link
Contributor

This is a method instead of a weak + readonly property like the macOS registrar protocol because existing getters are also methods

AFAIK that's only because the API predates properties, and nobody thought to change it before the introduction of Swift made it a breaking change to do so. I would recommend making it a property; IMO new code should follow current best practices even when older code doesn't. We already have an open issue for trying to migrate the old methods to properties in a non-breaking way.

@stuartmorgan-g
Copy link
Contributor

What do you think of adding a viewController property to the macOS version as well to keep them uniform?

The obvious argument against is that it adds a new API surface that will be quasi-deprecated from the start. That said, it doesn't add anything conceptually new over view, so as long as we also add viewControllerForViewIdentifier: on macOS at the same time as viewController, I think the consistency argument is stronger than the deprecation counter-argument.

@LongCatIsLooong
Copy link
Contributor Author

What do you think of adding a viewController property to the macOS version as well to keep them uniform?

The obvious argument against is that it adds a new API surface that will be quasi-deprecated from the start. That said, it doesn't add anything conceptually new over view, so as long as we also add viewControllerForViewIdentifier: on macOS at the same time as viewController, I think the consistency argument is stronger than the deprecation counter-argument.

Ah adding viewController and viewControllerForViewID: together to both platforms so people can decide which one to use / when to migrate? Sounds good.

@github-actions github-actions bot added a: desktop Running on desktop platform-macos labels Aug 25, 2025
@stuartmorgan-g
Copy link
Contributor

stuartmorgan-g commented Aug 26, 2025

Ah adding viewController and viewControllerForViewID: together to both platforms so people can decide which one to use / when to migrate? Sounds good.

I thought the plumbing didn't exist on the iOS side to properly implement the ID-based version, in which case we shouldn't add it there yet.

Actually, looking at macOS headers, do we not have the view-by-identifier method yet? I thought it had been added, but if not, then we don't need to add it here. I just didn't want to get into a situation where the view controller version was less capable than the existing API.

@LongCatIsLooong
Copy link
Contributor Author

Ah adding viewController and viewControllerForViewID: together to both platforms so people can decide which one to use / when to migrate? Sounds good.

I thought the plumbing didn't exist on the iOS side to properly implement the ID-based version, in which case we shouldn't add it there yet.

Actually, looking at macOS headers, do we not have the view-by-identifier method yet? I thought it had been added, but if not, then we don't need to add it here. I just didn't want to get into a situation where the view controller version was less capable than the existing API.

IIRC the macos multi view change was reverted. I'll remove the multi view stuff then.

OCMVerify(times(1), [mockEngine viewController]);
}

- (void)testGetViewControllerByViewIDFromRegistrar {
Copy link
Contributor

Choose a reason for hiding this comment

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

This test should be removed since viewControllerForViewIdentifier was removed

auto-submit bot pushed a commit to flutter/packages that referenced this pull request Sep 2, 2025
Interface change PR: flutter/flutter#174168

## Pre-Review Checklist

**Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

[^1]: Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling.
auto-submit bot pushed a commit to flutter/packages that referenced this pull request Sep 2, 2025
This is for flutter/flutter#174168

Adds the new methods to the registrar interface.

## Pre-Review Checklist

**Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

[^1]: Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling.
@LongCatIsLooong LongCatIsLooong added the autosubmit Merge PR when tree becomes green via auto submit App label Sep 3, 2025
@auto-submit auto-submit bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Sep 3, 2025
Copy link
Contributor

auto-submit bot commented Sep 3, 2025

autosubmit label was removed for flutter/flutter/174168, because - The status or check suite Mac tool_integration_tests_5_5 has failed. Please fix the issues identified (or deflake) before re-applying this label.

@LongCatIsLooong LongCatIsLooong added the autosubmit Merge PR when tree becomes green via auto submit App label Sep 3, 2025
@auto-submit auto-submit bot added this pull request to the merge queue Sep 4, 2025
Merged via the queue into flutter:master with commit 251f4a8 Sep 4, 2025
183 checks passed
@flutter-dashboard flutter-dashboard bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Sep 4, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Sep 4, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Sep 4, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Sep 4, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Sep 4, 2025
@LongCatIsLooong LongCatIsLooong deleted the ios-plugin-registrar-vc branch September 4, 2025 23:18
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Sep 5, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Sep 5, 2025
auto-submit bot pushed a commit to flutter/packages that referenced this pull request Sep 5, 2025
Roll Flutter from 6b18740d5a23 to 87d5b753196c (88 revisions)

flutter/flutter@6b18740...87d5b75

2025-09-05 [email protected] [ Device Lab ] Add regression testing for flutter/flutter#174952 (flutter/flutter#174956)
2025-09-05 [email protected] Roll Skia from 0ca53adfc6cc to 845ec125e94c (2 revisions) (flutter/flutter#174978)
2025-09-05 [email protected] [a11y-app] Fix NavigationRail leading and trailing labels (flutter/flutter#174861)
2025-09-05 [email protected] Roll Skia from d7e99be07d5d to 0ca53adfc6cc (5 revisions) (flutter/flutter#174972)
2025-09-05 [email protected] Roll Fuchsia Linux SDK from izfNA3o_2zL4Cjqmy... to xG_uERsxHvUwFHpF2... (flutter/flutter#174970)
2025-09-04 [email protected] Fix IconButton.color overrided by IconButtomTheme (flutter/flutter#174515)
2025-09-04 [email protected] [web] Reuse chrome instance to run all flutter tests (flutter/flutter#174957)
2025-09-04 [email protected] fix(Semantics): Ensure semantics properties take priority over button's (flutter/flutter#174473)
2025-09-04 [email protected] Make every LLDB Init error message actionable (flutter/flutter#174726)
2025-09-04 [email protected] Fix table cell semantics rect alignment issues.  (flutter/flutter#174914)
2025-09-04 [email protected] Fix: Use route navigator for CupertinoSheetRoute pop (flutter/flutter#173103)
2025-09-04 [email protected] [ Widget Preview] Add `group` property to `Preview` (flutter/flutter#174849)
2025-09-04 [email protected] Allow OverlayPortal.overlayChildLayoutBuilder to choose root Overlay (flutter/flutter#174239)
2025-09-04 [email protected] Roll Skia from 7c2f502e3304 to d7e99be07d5d (18 revisions) (flutter/flutter#174936)
2025-09-04 [email protected] Remove 'terms of use' wording from web_unicode (flutter/flutter#174939)
2025-09-04 [email protected] [ Tool ] Remove leftover Android x86 deprecation warning constant (flutter/flutter#174941)
2025-09-04 [email protected] Prevent potential crash when accessing window in FlutterSceneDelegate (flutter/flutter#174873)
2025-09-04 [email protected] Roll Packages from 42bb347 to 98580c6 (5 revisions) (flutter/flutter#174943)
2025-09-04 [email protected] [ Device Lab ] Fix wakefulness check to only match log entries with string values (flutter/flutter#174953)
2025-09-04 [email protected] Fix expanded DropdownMenu panel is shorter than text field (flutter/flutter#174443)
2025-09-04 [email protected] Add a `viewController` property to the ios/macOS `FlutterPluginRegistrar` protocol  (flutter/flutter#174168)
2025-09-03 [email protected] Roll Fuchsia Linux SDK from J3T_wZqL_57mRfWky... to izfNA3o_2zL4Cjqmy... (flutter/flutter#174908)
2025-09-03 [email protected] Wires up Android API to set section locale (flutter/flutter#173364)
2025-09-03 [email protected] Delete impeller::SPrintF. (flutter/flutter#174900)
2025-09-03 [email protected] Make sure that a DropdownMenuFormField doesn't crash in 0x0 environment (flutter/flutter#174777)
2025-09-03 [email protected] Remove unnecessary `presubmit_max_attempts` from .ci.yaml (flutter/flutter#174885)
2025-09-03 [email protected] Use local canvaskit in `dart_data_asset_test.dart` (flutter/flutter#174891)
2025-09-03 98614782+auto-submit[bot]@users.noreply.github.com Reverts "Mark Linux web_canvaskit_tests_7_last as bringup (#174878)" (flutter/flutter#174897)
2025-09-03 [email protected] Correct intrinsics calculation for CupertinoTextField with placeholder (flutter/flutter#174889)
2025-09-03 [email protected] Considers large title height in CupertinoNavigationBar's preferred size (flutter/flutter#173722)
2025-09-03 [email protected] [A11y] Add semantics for CupertinoExpansionTile (flutter/flutter#174480)
2025-09-03 [email protected] Fix LinearProgressIndicator track painting. (flutter/flutter#173108)
2025-09-03 [email protected] update triage documentation to include team-android (flutter/flutter#174850)
2025-09-03 [email protected] Update `test_timeout_secs` to match `timeout` for `Linux web_skwasm_tests_*` and `Linux web_canvaskit_tests_*` (flutter/flutter#174881)
2025-09-03 [email protected] Roll Packages from 5d785a0 to 42bb347 (10 revisions) (flutter/flutter#174876)
2025-09-03 [email protected] Fixup formatting of gn files in the old buildroot. (flutter/flutter#174852)
2025-09-03 [email protected] Roll Dart SDK to 3.10.0-162.1.beta (flutter/flutter#174834)
2025-09-03 [email protected] Mark Linux web_canvaskit_tests_7_last as bringup (flutter/flutter#174878)
2025-09-02 [email protected] [Impeller] Fix overdraw in DrawRect geometry (flutter/flutter#174735)
2025-09-02 [email protected] Patch .clang-format files to specify C++20. (flutter/flutter#174848)
2025-09-02 [email protected] Add data assets (flutter/flutter#174685)
2025-09-02 [email protected] refactors `FlutterPlugin.kt` to use one line statement in the `into` bloc (flutter/flutter#174759)
2025-09-02 [email protected] Ensures initial semantics state is sent to engine (flutter/flutter#174845)
2025-09-02 [email protected] [Android] Break up plugin_test integration tests (flutter/flutter#174728)
2025-09-02 [email protected] Fix: Assertion failure in RawScrollbarState with dynamic controller assignment (flutter/flutter#173156)
2025-09-02 [email protected] Roll Skia from 359f3d7cc7ed to 7c2f502e3304 (1 revision) (flutter/flutter#174844)
...
mboetger pushed a commit to mboetger/flutter that referenced this pull request Sep 18, 2025
…rar` protocol (flutter#174168)

flutter#104117

Adds a `viewController` (per
flutter#104117 (comment),
presumably because iOS plugins want to presenting new view controllers)
getter that makes the single-view assumption. ~This is a method instead
of a weak + readonly property like the macOS registrar protocol because
existing getters are also methods, e.g.,~
```objc
- (NSObject<FlutterBinaryMessenger>*)messenger;
- (NSObject<FlutterTextureRegistry>*)textures;
```

~Unfortunately swift callers will have to use a preprocess macro and add
different code paths for macOS and iOS.~

#### Single view assumption

I've considered adding a `- (nullable
UIViewController*)viewControllerForViewID: ViewIDType;` method but that
will force plugins to make breaking changes in order to migrate off of
the deprecated `keyWindow` property. Take the text input plugin as an
example, it has to add a `viewID` argument to the `setTextInputClient`
call when establishing a new text input connection, so the text input
plugin knows which view hierarchy to add the text input view to. It is
unclear to me whether more `FlutterPluginRegistrar` changes are needed
to completely get rid of the single-view assumption in the protocol (the
views `FlutterPlatformViewFactory` creates are always added as subviews
to `flutterView` so I guess that interface may have to change in the
future? According to according to [Flutter’s multi-window
status](https://docs.google.com/document/d/13E27tD8_9f6lDgwg3MpGNTV8XIRCZH3ByI-t9kI9IUM/edit?tab=t.0#heading=h.8lxwn1tiky70),
only a `viewForIdentifier` method will be added to registrar), so IMO it
would be a better experience to not introduce the `viewID` concept right
now and force plugins to make break changes, since they may have to make
more breaking changes in the future.

Alternatively, we could also ignore the `viewID` args for now and always
return the view controller of the implicit view in the implementation,
so that plugin authors can use made-up view IDs to get the implicit view
controller. But that's going to make future multiview migrations
difficult since the compiler won't be able to catch unmigrated code if
the plugin is using a bogus view ID.

##  Pre-launch Checklist

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

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

**Note**: The Flutter team is currently trialing the use of [Gemini Code
Assist for
GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code).
Comments from the `gemini-code-assist` bot should not be taken as
authoritative feedback from the Flutter team. If you find its comments
useful you can update your code accordingly, but if you are unsure or
disagree with the feedback, please feel free to wait for a Flutter team
member's review for guidance on which automated comments should be
addressed.

<!-- 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
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-ios iOS applications specifically platform-macos team-ios Owned by iOS platform team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants