-
Notifications
You must be signed in to change notification settings - Fork 30.7k
[Android] Encode the original pointer count in messages that represent Android touch events #178015
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -619,19 +619,32 @@ class _AndroidMotionEventConverter { | |
| final int pointerIdx = pointers.indexOf(event.pointer); | ||
| final int numPointers = pointers.length; | ||
|
|
||
| // This value must match the value in engine's FlutterView.java. | ||
| // These values must match the values in the engine's AndroidTouchProcessor.java. | ||
| // This flag indicates whether the original Android pointer events were batched together. | ||
| const int kPointerDataFlagBatched = 1; | ||
| // This flag indicates that this event is part of a group of events representing a change | ||
| // that affects multiple pointers. | ||
| const int kPointerDataFlagMultiple = 2; | ||
|
|
||
| // Mask for extracting the flag value from the event's platformData | ||
| const int kPointerDataFlagMask = 0xff; | ||
| const int kPointerDataMultiplePointerCountShift = 8; | ||
|
|
||
| // Android MotionEvent objects can batch information on multiple pointers. | ||
| // Flutter breaks these such batched events into multiple PointerEvent objects. | ||
| // When there are multiple active pointers we accumulate the information for all pointers | ||
| // as we get PointerEvents, and only send it to the embedded Android view when | ||
| // we see the last pointer. This way we achieve the same batching as Android. | ||
| if (event.platformData == kPointerDataFlagBatched || | ||
| (isSinglePointerAction(event) && pointerIdx < numPointers - 1)) { | ||
| final int platformDataFlag = event.platformData & kPointerDataFlagMask; | ||
| if (platformDataFlag == kPointerDataFlagBatched) { | ||
| return null; | ||
| } | ||
| if (platformDataFlag == kPointerDataFlagMultiple) { | ||
| final int originalPointerCount = event.platformData >> kPointerDataMultiplePointerCountShift; | ||
| if (pointerIdx != originalPointerCount - 1) { | ||
| return null; | ||
| } | ||
| } | ||
|
|
||
| final int? action = switch (event) { | ||
| PointerDownEvent() when numPointers == 1 => AndroidViewController.kActionDown, | ||
|
|
@@ -697,9 +710,6 @@ class _AndroidMotionEventConverter { | |
| }, | ||
| ); | ||
| } | ||
|
|
||
| bool isSinglePointerAction(PointerEvent event) => | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this removed because it was a heuristic for determining if the change affected multiple pointers, and we no longer need a heuristic as we explicitly encode that info?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes - with this change the Messages from multiple-pointer events will be marked with the |
||
| event is! PointerDownEvent && event is! PointerUpEvent; | ||
| } | ||
|
|
||
| class _CreationParams { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we also update the logic below this to remove the use of
numPointers, and then remove that value? I would think we would also want to encode the Android action we send based off the true pointer count of the original touch event, is that not right?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
numPointersis still being used by another code path that converts pointer data messages into Android pointer up and down events. Specifically, Android'sMotionEventhas separateACTION_DOWN/ACTION_UPandACTION_POINTER_DOWN/ACTION_POINTER_UPcodes for primary versus non-primary pointers. The framework side decides whether to map a message toACTION_DOWNorACTION_POINTER_DOWNbased on its local state indicating whether this is the first pointer down (and likewise for the last pointer up).AFAICT there is no race or potential for duplicate messages there. Each pointer up/down message will result in exactly one Android pointer up/down event. The logic will ensure that an
ACTION_DOWNis sent before anyACTION_POINTER_DOWNevents (and the reverse for pointer up).The process of trying to recover the original Android events from Flutter's internal event representation does have complexity and potential for errors.
I suspect that there are more cases where the recovered events do not accurately reflect the original events (for example, it looks like the code in
toAndroidMotionEventthat calculatespointerIdxmay not consistently map Flutter's pointer IDs to Android pointer IDs). But I wanted to keep this PR focused on solving only one specific known issue.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good, if this would mean changing additional paths then makes sense to not include it
Yeah, I've personally seen mismatches specifically for this case where the reconstructed event is
ACTION_POINTER_DOWNwhile the saved (true original) event isACTION_DOWN, when testing #177572 and printing them both outThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gmackall is this an area where we should do a deep technical dive to try to reproduce the types of input you are seeing fail to be reproduced correctly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I looked into some issues affecting Android platform view pointer up/down events and wrote it up at #178189