Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move PointerDataPacketConverter from PlatformView to RuntimeController #51952

Merged
merged 10 commits into from
Apr 26, 2024

Conversation

dkwingsmt
Copy link
Contributor

@dkwingsmt dkwingsmt commented Apr 5, 2024

This is a refactor that moves the PointerDataPacketConverter from PlatformView to RuntimeController.

This change is made for the following reasons:

  • Currently, the pointer data conversion contains no platform specific logic (because the current converter's only responsibility is to make the event sequence conform Flutter's protocol). Therefore these logics should reside in a platform-independent place.
  • The converter typically converts one event to many. It's better to have this conversion later than earlier.
  • It removes a member from PlatformView, making it closer to a pure virtual class.

The reason to choose RuntimeController as the destination is because RuntimeController manages a map for views, which is required for the converter to implement a later patch #51925.

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 and the C , Objective-C, Java style guides.
  • I listed at least one issue that this PR fixes in the description above.
  • I added new tests to check the change I am making or feature I am adding, or the PR is test-exempt. See testing the engine for instructions on writing and running engine tests.
  • I updated/added relevant documentation (doc comments with ///).
  • I signed the CLA.
  • All existing and new tests are passing.

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

@dkwingsmt dkwingsmt marked this pull request as draft April 6, 2024 00:02
@dkwingsmt
Copy link
Contributor Author

Update: There are some unexpected unit test failures and I'm resolving.

@flutter-dashboard
Copy link

This pull request has been changed to a draft. The currently pending flutter-gold status will not be able to resolve until a new commit is pushed or the change is marked ready for review again.

@dkwingsmt dkwingsmt marked this pull request as ready for review April 8, 2024 18:38
Copy link
Contributor

@chunhtai chunhtai left a comment

Choose a reason for hiding this comment

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

is the RuntimeController to be per view? or is it going to be shared by multipleview?

@loic-sharma
Copy link
Member

is the RuntimeController to be per view? or is it going to be shared by multipleview?

The runtime controller is 1 per Dart VM, so it is shared by all views within a single engine instance.

@@ -124,7 124,9 @@ static void TestSimulatedInputEvents(
for (int i = 0, j = 0; i < num_events; j = 1) {
double t = j * frame_time;
while (i < num_events && delivery_time(i) <= t) {
ShellTest::DispatchFakePointerData(shell.get());
// Use a different x every time for the pointer data converter to
// generate non-empty events.
Copy link
Member

Choose a reason for hiding this comment

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

Should we move the "use a different x" trick to DispatchFakePointerData's implementation? I don't feel strongly about this, feel free to keep as is.

platform_configuration->DispatchPointerDataPacket(packet);
std::unique_ptr<PointerDataPacket> converted_packet =
pointer_data_packet_converter_.Convert(packet);
if (converted_packet->GetLength() != 0) {
Copy link
Member

Choose a reason for hiding this comment

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

I see PlatformView::DispatchPointerDataPacket didn't have this length check before. Could you explain why it was added?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're right. It was a legacy design that proves to be no longer necessary. I've removed the length check and all code that was created for it.

@chunhtai
Copy link
Contributor

chunhtai commented Apr 8, 2024

The runtime controller is 1 per Dart VM, so it is shared by all views within a single engine instance.

If that is the case, should we still to put it below this level? The converter has state to keep track of pointer down or up, and each converter state should not be mixed between different view. If we put in runtime controller, we would have to maintain one converter per view.

@dkwingsmt
Copy link
Contributor Author

dkwingsmt commented Apr 8, 2024

The runtime controller is 1 per engine, and putting the converter under RuntimeController means that there's one converter per engine. The converter currently doesn't distinguish states between views. It keeps states by pointers, and this scheme works for multiple views (IIRC add/remove pointer events are dispatched when a pointer moves in/out of a view).

I don't think it needs to keep states by views, but even if we need to, we can add a private class under it. And even in that case, the converter needs to be aware of views, which PlatformView doesn't provide.

@chunhtai
Copy link
Contributor

chunhtai commented Apr 8, 2024

I don't think it needs to keep states by views

If you have a gesture across multiple view, like a drag and drop, should they be treated as one gesture, or 2 gesture one for each view? sharing the same state or not will change how pointer event is synthesized

the converter needs to be aware of views, which PlatformView doesn't provide.

Can you explain a bit more? what information from the view does converter need?

@dkwingsmt
Copy link
Contributor Author

dkwingsmt commented Apr 8, 2024

Can you explain a bit more? what information from the view does converter need?

The converter simply needs to know when a view is added or removed. However, currently we managed to implement the entire multi-view rendering without adding such API to PlatformView.

Well, now that I think about it, it might have been a better idea to add Add/RemoveView to PlatformView instead of to Shell. It feels like Shell is just a glue between the engine's components, not something to operate on. And in that case, PlatformView will have view information and this change is not needed.

This goes with the current convention on how a message is dispatched to the shell by platforms that do not use the embedder API. For example, iOS dispatches a system pointer event to the shell by:

- (void)dispatchPointerDataPacket:(std::unique_ptr<flutter::PointerDataPacket>)packet {
if (!self.platformView) {
return;
}
self.platformView->DispatchPointerDataPacket(std::move(packet));
}

The iOS platform does not operate the shell, but operate the platform view.

@loic-sharma What do you think?

@dkwingsmt
Copy link
Contributor Author

If you have a gesture across multiple view, like a drag and drop, should they be treated as one gesture, or 2 gesture one for each view? sharing the same state or not will change how pointer event is synthesized

The idea is that, a pointer's state is indexed by its pointer ID. The converter tracks whether this pointer travels across the view boundary and synthesize add/remove events accordingly.

An easier way to think about it is what Flutter "remembers" about pointers of an app.

  • Flutter should think, "I have 2 pointers, pointer 1 is currently on view 10, pointer 2 is currently not on any views."
  • Flutter should not think, "I have 3 views, view 10 currently has 1 pointer on it, view 11 and view 12 don't have any pointers on it".

@loic-sharma
Copy link
Member

Well, now that I think about it, it might have been a better idea to add Add/RemoveView to PlatformView instead of to Shell. It feels like Shell is just a glue between the engine's components, not something to operate on. And in that case, PlatformView will have view information and this change is not needed.

I think the Shell setup we have today fits this paradigm: Shell::AddView just switches to the UI thread and then calls Engine::AddView. It's still just glue :)

Also, the PlatformView is operated on the platform thread, right? Would the approach you suggested require us to track views' states in the engine on the platform thread as well? Personally I'd rather have as much pointer logic on the UI thread as possible.

@chunhtai
Copy link
Contributor

chunhtai commented Apr 9, 2024

The idea is that, a pointer's state is indexed by its pointer ID. The converter tracks whether this pointer travels across the view boundary and synthesize add/remove events accordingly.

yes that can work, but then the converter will be more complex to not only memorize the pointer is down/up, it also need to know which view the pointer has been downed on.

I am not too familiar with the shell/platformview/view relationship, if it makes more sense to handle it in the shell level, then I think this is fine.

@dkwingsmt
Copy link
Contributor Author

dkwingsmt commented Apr 9, 2024

then the converter will be more complex to not only memorize the pointer is down/up, it also need to know which view the pointer has been downed on.

But this is unavoidable. The native platforms typically dispatch pointer-add/remove-events when a pointer enters/leaves a view. The app would like to know it as well. So this behavior is intended. The only problem is how to organize our data to compute the logic conveniently.

If we don't dispatch pointer-add/remove-events when a pointer enters/leaves a view, what's the behavior then? When the pointer hovers out of the Flutter window, Flutter probably won't receive any pointer events, and therefore the app will stop seeing pointer events for a long time before it sees another pointer event faraway when the pointer enters a Flutter view again.

@chinmaygarde
Copy link
Member

Are we making progress on this?

@chunhtai
Copy link
Contributor

If we don't dispatch pointer-add/remove-events when a pointer enters/leaves a view, what's the behavior then? When the pointer hovers out of the Flutter window, Flutter probably won't receive any pointer events, and therefore the app will stop seeing pointer events for a long time before it sees another pointer event faraway when the pointer enters a Flutter view again.

We definitely need a pointer add when pointer enters, not sure about leaves. I think most native app don't send pointer up when pointer leaves a window.

If you want to mimic the behavior with a single pointerpacketconverter, it need to constantly checking whether a move/hover has entered/leaves a new view. If we keep separate converter for each view, it should mostly work out of the box.

However, as I state before, if this is the place that makes most sense for pointerpacketconverter, then i guess we have no choice.

Copy link
Contributor

@chunhtai chunhtai left a comment

Choose a reason for hiding this comment

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

Talked with @dkwingsmt offline. It makes sense to pull these kind of logic out of platform view. LGTM

@dkwingsmt dkwingsmt added the autosubmit Merge PR when tree becomes green via auto submit App label Apr 26, 2024
@auto-submit auto-submit bot merged commit cecf5aa into flutter:main Apr 26, 2024
31 checks passed
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Apr 27, 2024
auto-submit bot pushed a commit to flutter/flutter that referenced this pull request Apr 27, 2024
…147444)

flutter/engine@8af10eb...cecf5aa

2024-04-26 [email protected] Move `PointerDataPacketConverter` from `PlatformView` to `RuntimeController` (flutter/engine#51952)

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://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/ doc/main/autoroll/README.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
autosubmit Merge PR when tree becomes green via auto submit App
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants