Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Conversation

@moffatman
Copy link
Contributor

@moffatman moffatman commented Feb 21, 2022

Start sending PointerPanZoom events from ChromeOS/Android when trackpad is used

Fixes flutter/flutter#23604

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 Hixie said 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.

@flutter-dashboard
Copy link

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.

Copy link

@blasten blasten left a 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.

@chinmaygarde
Copy link
Member

@moffatman Any updates on the tests or are you seeking specific guidance from @blasten ?

@moffatman
Copy link
Contributor Author

@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.

@justinmc
Copy link
Contributor

If the framework PR is merged without this will it just gracefully not receive pan/zoom events?

@moffatman
Copy link
Contributor Author

@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.

@justinmc
Copy link
Contributor

Sounds good, thanks for the clarification.

@moffatman moffatman force-pushed the trackpad_gestures_android branch from f13d0e9 to c17c6b4 Compare March 31, 2022 22:42
@moffatman
Copy link
Contributor Author

@blasten
I want to try making the following change to robolectric to fix the failure, can't seem to get the tests to use a locally-built version though.

diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowMotionEvent.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowMotionEvent.java
index 1ee385479..682938376 100644
--- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowMotionEvent.java
+++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowMotionEvent.java
@@ -52,7 +52,7 @@ import org.robolectric.util.ReflectionHelpers;
  */
 @SuppressWarnings({"UnusedDeclaration"})
 @Implements(MotionEvent.class)
-public class ShadowMotionEvent {
+public class ShadowMotionEvent extends ShadowInputEvent {
 
   private static NativeObjRegistry<NativeInput.MotionEvent> nativeMotionEventRegistry =
       new NativeObjRegistry<>(NativeInput.MotionEvent.class);

@blasten
Copy link

blasten commented Apr 5, 2022

@moffatman that's weird. I think the workaround requires to supply a shadow implementation that extends InputEvent.

For more, see http://robolectric.org/extending/

@moffatman moffatman force-pushed the trackpad_gestures_android branch from 1631a78 to ef8d9db Compare April 6, 2022 00:54
@moffatman
Copy link
Contributor Author

@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.

@moffatman moffatman force-pushed the trackpad_gestures_android branch 2 times, most recently from 35d6f96 to cae15af Compare April 6, 2022 13:05
@moffatman moffatman requested a review from blasten April 6, 2022 14:27
@chinmaygarde
Copy link
Member

chinmaygarde commented Apr 14, 2022

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))) {
Copy link
Contributor

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.

Copy link
Contributor

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.

Copy link
Contributor Author

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 ?

Copy link
Contributor

@dkwingsmt dkwingsmt Apr 20, 2022

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.

@chinmaygarde
Copy link
Member

@dkwingsmt I think this is good for another review. Thanks.

Copy link
Contributor

@dkwingsmt dkwingsmt left a 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

@dkwingsmt
Copy link
Contributor

@blasten Would you like to make a second review?

@moffatman moffatman force-pushed the trackpad_gestures_android branch from e0ee901 to f290c83 Compare May 11, 2022 18:57
Comment on lines +232 to +240
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);
}
Copy link
Contributor

@dkwingsmt dkwingsmt May 12, 2022

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.

Suggested change
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

Copy link
Contributor Author

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.

Copy link
Contributor

@dkwingsmt dkwingsmt May 12, 2022

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?

Copy link
Contributor

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.

Copy link
Contributor

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.

@dkwingsmt
Copy link
Contributor

@blasten Would you like to make a second review of this PR?

@blasten
Copy link

blasten commented May 21, 2022

This change LGTM once the two minor comments are resolved

@zanderso
Copy link
Member

zanderso commented Jun 2, 2022

@moffatman From PR review triage: it looks like the next step for this PR is to respond to the comments from @blasten

@dkwingsmt dkwingsmt requested a review from blasten June 2, 2022 22:32
@moffatman moffatman force-pushed the trackpad_gestures_android branch from d0d72b3 to cc49d6d Compare June 2, 2022 22:33
@moffatman moffatman force-pushed the trackpad_gestures_android branch from cc49d6d to 8df97aa Compare June 2, 2022 23:11
@chinmaygarde
Copy link
Member

@blasten is OOO for the rest of this week.

Copy link

@blasten blasten left a comment

Choose a reason for hiding this comment

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

LGTM

@blasten blasten added the waiting for tree to go green This PR is approved and tested, but waiting for the tree to be green to land. label Jun 13, 2022
@fluttergithubbot fluttergithubbot merged commit 984ef27 into flutter:main Jun 14, 2022
dkwingsmt added a commit that referenced this pull request Jun 14, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Jun 14, 2022
houhuayong pushed a commit to houhuayong/engine that referenced this pull request Jun 21, 2022
houhuayong pushed a commit to houhuayong/engine that referenced this pull request Jun 21, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

needs tests platform-android waiting for tree to go green This PR is approved and tested, but waiting for the tree to be green to land.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Should support trackpad gestures from host

7 participants