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

Fix non-vd android platform view input event offsets #52532

Merged
merged 20 commits into from
May 14, 2024

Conversation

gmackall
Copy link
Member

@gmackall gmackall commented May 2, 2024

Fixes flutter/flutter#146570, which tracks a regression from #49268 regarding platform view inputs in some specific cases.

This PR translates the input event location to be the same as the location we calculated before #49268, returning to the previous behavior, while maintaining the input event's verified status (I checked this manually with the InputManager).

Tested manually with the reproduction in the linked issue.

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.

@gmackall gmackall changed the title Fix platform view input offsets Fix non-vd android platform view input event offsets May 2, 2024
@gmackall
Copy link
Member Author

gmackall commented May 2, 2024

Not sure if I need to consider a different element than pointerCoords[0]?


originalEvent.offsetLocation(xOffset, yOffset);
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Could we add a roboelectric test programmatically invokes translateNonVirtualDisplayMotionEvent and toMotionEvent and checks their return values?

Copy link
Member Author

Choose a reason for hiding this comment

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

I wrote a test that invokes toMotionEvent in both the vd and non-vd case, and expects that they have equivalent x and y coords. This isn't exactly what you asked for, but does it make sense to you?

@gmackall gmackall marked this pull request as ready for review May 7, 2024 16:27
@gmackall
Copy link
Member Author

gmackall commented May 7, 2024

I also deleted a test that had been skipped for 4 years, which seems to have sort of confused the diff (the test was the itUsesActionEventTypeFromMotionEventForHybridPlatformViews). I tried unskipping it and it did not pass.

Copy link
Contributor

@johnmccutchan johnmccutchan left a comment

Choose a reason for hiding this comment

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

Great fix. Just a bunch of nits and some questions.

@VisibleForTesting
public MotionEvent toMotionEvent(
float density, PlatformViewsChannel.PlatformViewTouch touch, boolean usingVirtualDiplay) {
MotionEventTracker.MotionEventId motionEventId =
MotionEventTracker.MotionEventId.from(touch.motionEventId);
MotionEvent trackedEvent = motionEventTracker.pop(motionEventId);

// Pointer coordinates in the tracked events are global to FlutterView
Copy link
Contributor

Choose a reason for hiding this comment

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

I have a deeper question about this change:

If the original MotionEvent had view-local coordinates why can't we just deliver the original MotionEvent here? Let me explain below:

When someone touches a Platform View the following happens:

  1. MotionEvent (O) is delivered directly to the PlatformView. We stash it on the side in our "motionEventTracker".
  2. Transform MotionEvent into a Flutter TouchEvent
  3. TouchEvent is delivered to Flutter Widgets and eventually to the PlatformView widget.
  4. We end up back in this code to (finally) deliver the event to the Android View.

My intuition would be that in step (1) the events in O have the correct coordinates. And then in (4) we deliver O to the view.

In what cases do we see a non-zero offset? Help me understand intuitively what's happening here.

Copy link
Member Author

@gmackall gmackall May 13, 2024

Choose a reason for hiding this comment

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

There is something weird going on here for sure. The reporting issue has a repro, which includes an example of a temporary fix that forces the platform view to refresh. In investigating why this temporarily fixes the issue, I printed out the original motion events and our calculated locations of platform view touches (and some more locations from framework code).

It turns out refreshing the webview changes the location of the original motion event that we store. Still need to investigate further as to why this would be the case, but it wasn't what I was originally expecting at all.

Copy link
Member Author

@gmackall gmackall May 14, 2024

Choose a reason for hiding this comment

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

It looks like probably the reason why we can't deliver the motion events as is in (4) is that the Platform view in question believes it is at (0,0) (thats the output of platformView.getView.getX() and getY()). Still not sure why that is though!

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok, I think I actually know the answer here now. MotionEvents in general are relative to the view they are delivered to. So this particular motion event is global to the FlutterView, but still relative to a view.

When we deliver the motion event in (4), we are then delivering it to an inner view, and as such need to make it relative to the inner view, which is why we need to offset. Does that make sense?

Copy link
Member Author

Choose a reason for hiding this comment

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

(Talked with @johnmccutchan offline and we still aren't sure this reasoning is 100% correct, but landing regardless as the fix works better than what we have)

@reidbaker reidbaker self-requested a review May 8, 2024 17:45
@gmackall gmackall marked this pull request as draft May 9, 2024 21:08
@gmackall gmackall marked this pull request as ready for review May 13, 2024 19:33
@gmackall gmackall added the autosubmit Merge PR when tree becomes green via auto submit App label May 14, 2024
@auto-submit auto-submit bot merged commit 70de32b into flutter:main May 14, 2024
29 checks passed
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request May 15, 2024
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request May 15, 2024
auto-submit bot pushed a commit to flutter/flutter that referenced this pull request May 15, 2024
…148367)

flutter/engine@55c62ff...d35a1a6

2024-05-15 [email protected] Roll FreeType from af4c2d86 to bfc3453f (flutter/engine#52829)
2024-05-14 [email protected] [Impeller] immediately encode blit commands for Vulkan. (flutter/engine#52794)
2024-05-14 [email protected] Fix non-vd android platform view input event offsets (flutter/engine#52532)
2024-05-14 [email protected] Roll Dart SDK from 0380354e2448 to 0b77fbab8cf5 (1 revision) (flutter/engine#52827)

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
@gmackall gmackall added the cp: stable cherry pick to the stable release candidate branch label May 22, 2024
flutteractionsbot pushed a commit to flutteractionsbot/engine that referenced this pull request May 22, 2024
Fixes flutter/flutter#146570, which tracks a regression from flutter#49268 regarding platform view inputs in some specific cases.

This PR translates the input event location to be the same as the location we calculated before flutter#49268, returning to the previous behavior, while maintaining the input event's verified status (I checked this manually with the `InputManager`).

Tested manually with the reproduction in the linked issue.

[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
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 cp: stable cherry pick to the stable release candidate branch platform-android
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Android] PlatformView tap coordinates mapping incorrectly when in a scroll view
3 participants