-
Notifications
You must be signed in to change notification settings - Fork 6k
ChromeOS/Android trackpad gestures #31595
ChromeOS/Android trackpad gestures #31595
Conversation
|
It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption to this rule, contact Hixie on the #hackers channel in Chat (don't just cc him here, he won't see it! He's on Discord!). If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix? Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. |
blasten
left a comment
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.
Thanks for the contribution! It will really help to get some unit tests and comments for each case that this PR is handling.
|
@moffatman Any updates on the tests or are you seeking specific guidance from @blasten ? |
|
@chinmaygarde Framework side needs to be merged first so I haven't spent any time on adding tests here yet (also this platform is the least priority, trackpad gestures already functionally work). Should get around to it within the next week. |
|
If the framework PR is merged without this will it just gracefully not receive pan/zoom events? |
|
@justinmc Framework PR needs to be merged first as merging only engine changes will break scrolling. If only the framework PR is merged there should be no changes to existing behaviour. In fact the Web engine will never get a PR, as it's not possible to get trackpad gestures to work there. So there is no rush or synchronization needed in merging the engine PRs after the framework lands. This specific one I have been slow on amending since I can't build for android on my ARM mac. |
|
Sounds good, thanks for the clarification. |
f13d0e9 to
c17c6b4
Compare
|
@blasten |
|
@moffatman that's weird. I think the workaround requires to supply a shadow implementation that extends InputEvent. |
1631a78 to
ef8d9db
Compare
|
@blasten Making a new shadow implementation will be a lot of code since we cannot extend the existing one as we wish to change its parent class. I updated the test to just use Mockito mock instead of shadowed object, and it's running fine now. |
35d6f96 to
cae15af
Compare
|
Ping @blasten. He may be busy with some firefighting ATM though. |
| packet.putLong(timeStamp); // time_stamp | ||
| packet.putLong(pointerChange); // change | ||
| packet.putLong(pointerKind); // kind | ||
| if (ongoingPans.containsKey(event.getPointerId(pointerIndex))) { |
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.
Extract this recurring condition as a boolean.
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.
Or do you think it makes sense to extract the trackpad related data to another function? Because it seems that there are contains exclusive logic on both side, such as adding to and removing from ongoingPans, and many if clauses.
If we define a "data packet" class (as commented by a TODO on L207 of this file), then we don't have to worry about assignment order or packet structure. We can assign the common fields first, then split exclusive parts into two functions.
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.
Just extracted the condition for now. It would be nice to use a data packet if it could be used in the test class as well. I don't know that much about how the java code interoperates with the rest of the engine, but I assume we can't change the signature on FlutterRenderer::dispatchPointerDataPacket ?
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.
Nope, but the "data packet" class is actually just a builder. Check out https://github.com/flutter/engine/blob/main/lib/ui/window/pointer_data_packet.h . Although I don't really think the one I linked helps much in this scenario... What might really makes it prettier is something like a struct where you assign each field and then get data() out of it. In this way we can ensure that the data packet structure is correct no matter how you assign the properties. But just my two cents. See if you like the idea.
|
@dkwingsmt I think this is good for another review. Thanks. |
shell/platform/android/io/flutter/embedding/android/AndroidTouchProcessor.java
Show resolved
Hide resolved
dkwingsmt
left a comment
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.
LGTM except for a comment
|
@blasten Would you like to make a second review? |
e0ee901 to
f290c83
Compare
| if (pointerKind == PointerDeviceKind.MOUSE) { | ||
| buttons = event.getButtonState() & 0x1F; | ||
| if (buttons == 0 | ||
| && event.getSource() == InputDevice.SOURCE_MOUSE | ||
| && pointerChange == PointerChange.DOWN) { | ||
| // Some implementations translate trackpad scrolling into a mouse down-move-up event | ||
| // sequence with buttons: 0, such as ARC on a Chromebook. See #11420, a legacy | ||
| // implementation that uses the same condition but converts differently. | ||
| ongoingPans.put(event.getPointerId(pointerIndex), viewToScreenCoords); | ||
| } |
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 just tested on a real device and found out that ChromeOS now converts trackpad scrolling into events with tool type "finger" instead of "mouse". I've therefore fixed the logic as below. This also makes these events especially distinctive.
| if (pointerKind == PointerDeviceKind.MOUSE) { | |
| buttons = event.getButtonState() & 0x1F; | |
| if (buttons == 0 | |
| && event.getSource() == InputDevice.SOURCE_MOUSE | |
| && pointerChange == PointerChange.DOWN) { | |
| // Some implementations translate trackpad scrolling into a mouse down-move-up event | |
| // sequence with buttons: 0, such as ARC on a Chromebook. See #11420, a legacy | |
| // implementation that uses the same condition but converts differently. | |
| ongoingPans.put(event.getPointerId(pointerIndex), viewToScreenCoords); | |
| } | |
| if (pointerKind == PointerDeviceKind.MOUSE) { | |
| buttons = event.getButtonState() & 0x1F; | |
| } else if (pointerKind == PointerDeviceKind.TOUCH) { | |
| buttons = 0; | |
| // Chromebook with ARC translates trackpad scrolling into a touch down-move-up event | |
| // sequence, which can be identified by a distinctive combination of input device "mouse", | |
| // tool type "finger", and buttons 0. | |
| if (event.getButtonState() == 0 | |
| && event.getSource() == InputDevice.SOURCE_MOUSE | |
| && pointerChange == PointerChange.DOWN) { | |
| ongoingPans.put(event.getPointerId(pointerIndex), viewToScreenCoords); | |
| } |
As a result, running the demo at https://docs.flutter.dev/cookbook/effects/drag-a-widget#interactive-example, moving the cursor onto the menu and scrolling the trackpad now correctly scrolls the list instead of dragging the items. :D
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.
Any concern that we have no idea which proportion of devices this will work on? I guess it's based on undocumented behaviour anyway, and Chrome OS is always up to date.
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.
We're required to make Flutter work on ChromeOS, so the portion of device shouldn't matter. Sure the behavior might change, and it's best we run an integration test, but I don't think we can achieve this in a short while. Maybe leave a TODO?
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.
Also maybe it's better to use switch instead.
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.
Never mind, I'll handle this change in another PR. The current code passes all tests anyway.
|
@blasten Would you like to make a second review of this PR? |
shell/platform/android/io/flutter/embedding/android/AndroidTouchProcessor.java
Show resolved
Hide resolved
shell/platform/android/io/flutter/embedding/android/AndroidTouchProcessor.java
Outdated
Show resolved
Hide resolved
|
This change LGTM once the two minor comments are resolved |
|
@moffatman From PR review triage: it looks like the next step for this PR is to respond to the comments from @blasten |
d0d72b3 to
cc49d6d
Compare
cc49d6d to
8df97aa
Compare
|
@blasten is OOO for the rest of this week. |
blasten
left a comment
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.
LGTM
This reverts commit 984ef27.
Start sending PointerPanZoom events from ChromeOS/Android when trackpad is used
Fixes flutter/flutter#23604
Pre-launch Checklist
writing and running engine tests.
///).