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

i82973 scroll mouse wheel support #44724

Merged
merged 29 commits into from
Aug 22, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
4fc9130
Pair progress
Piinks Aug 9, 2023
17faa0d
Working mouse scroll wheel, note flutter takes longer to "see" a mous…
reidbaker Aug 15, 2023
95f5aa0
refactor packet method to have an override when context is null
reidbaker Aug 15, 2023
2b9686c
Add unit test for scroll wheel
reidbaker Aug 16, 2023
43619cc
Add unit test for scroll wheel
reidbaker Aug 16, 2023
aa01e98
Add unit test for scroll wheel
reidbaker Aug 16, 2023
05420ee
make pointer logic easier to read
reidbaker Aug 16, 2023
e14b961
revert unrelated file
reidbaker Aug 16, 2023
9efded6
Merge branch 'main' into i82973-scroll-mouse-wheel-support
reidbaker Aug 16, 2023
2ea445d
Fix merge, add timestamp test, code does not compile
reidbaker Aug 16, 2023
5140201
Merge branch 'main' into i82973-scroll-mouse-wheel-support
reidbaker Aug 16, 2023
e76fec0
Make tests compile
reidbaker Aug 16, 2023
22e8a77
Make tests pass
reidbaker Aug 17, 2023
e7dfa9d
add device test
reidbaker Aug 17, 2023
53ac277
Add tests for pressure, obscured and synth
reidbaker Aug 17, 2023
02e1176
Add tests for pressure min and max
reidbaker Aug 17, 2023
2c823c7
Add test for stylus distance
reidbaker Aug 17, 2023
c2f3c56
Add test for stylus distance
reidbaker Aug 17, 2023
168164f
Add tests for size and radius
reidbaker Aug 17, 2023
06cda9a
Add tests for pan deltax and rotation and scale
reidbaker Aug 17, 2023
bb157fb
formatting
reidbaker Aug 17, 2023
01e8ebb
Add test for buttons, specifically stylus
reidbaker Aug 18, 2023
8f3aa72
formatting
reidbaker Aug 18, 2023
4df1fee
Merge branch 'main' into i82973-scroll-mouse-wheel-support
reidbaker Aug 18, 2023
eb4dbb0
extract mock event values into function
reidbaker Aug 18, 2023
33be4af
formatting
reidbaker Aug 18, 2023
2cd1f46
Tests for pre 26 scroll behavior
reidbaker Aug 18, 2023
3848a28
Merge branch 'main' into i82973-scroll-mouse-wheel-support
reidbaker Aug 21, 2023
ae7439f
Update shell/platform/android/io/flutter/embedding/android/AndroidTou…
Piinks Aug 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package io.flutter.embedding.android;

import android.content.Context;
import android.graphics.Matrix;
import android.os.Build;
import android.view.InputDevice;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
Expand Down Expand Up @@ -138,7 +140,8 @@ public boolean onTouchEvent(@NonNull MotionEvent event, @NonNull Matrix transfor
|| maskedAction == MotionEvent.ACTION_POINTER_UP);
if (updateForSinglePointer) {
// ACTION_DOWN and ACTION_POINTER_DOWN always apply to a single pointer only.
addPointerForIndex(event, event.getActionIndex(), pointerChange, 0, transformMatrix, packet);
addPointerForIndex(
event, event.getActionIndex(), pointerChange, 0, transformMatrix, packet, null);
} else if (updateForMultiplePointers) {
// ACTION_UP and ACTION_POINTER_UP may contain position updates for other pointers.
// We are converting these updates to move events here in order to preserve this data.
Expand All @@ -147,18 +150,25 @@ public boolean onTouchEvent(@NonNull MotionEvent event, @NonNull Matrix transfor
for (int p = 0; p < pointerCount; p++) {
if (p != event.getActionIndex() && event.getToolType(p) == MotionEvent.TOOL_TYPE_FINGER) {
addPointerForIndex(
event, p, PointerChange.MOVE, POINTER_DATA_FLAG_BATCHED, transformMatrix, packet);
event,
p,
PointerChange.MOVE,
POINTER_DATA_FLAG_BATCHED,
transformMatrix,
packet,
null);
}
}
// It's important that we're sending the UP event last. This allows PlatformView
// to correctly batch everything back into the original Android event if needed.
addPointerForIndex(event, event.getActionIndex(), pointerChange, 0, transformMatrix, packet);
addPointerForIndex(
event, event.getActionIndex(), pointerChange, 0, transformMatrix, packet, null);
} else {
// ACTION_MOVE may not actually mean all pointers have moved
// but it's the responsibility of a later part of the system to
// ignore 0-deltas if desired.
for (int p = 0; p < pointerCount; p++) {
addPointerForIndex(event, p, pointerChange, 0, transformMatrix, packet);
addPointerForIndex(event, p, pointerChange, 0, transformMatrix, packet, null);
}
}

Expand All @@ -183,7 +193,7 @@ public boolean onTouchEvent(@NonNull MotionEvent event, @NonNull Matrix transfor
* @param event The generic motion event being processed.
* @return True if the event was handled.
*/
public boolean onGenericMotionEvent(@NonNull MotionEvent event) {
public boolean onGenericMotionEvent(@NonNull MotionEvent event, Context context) {
// Method isFromSource is only available in API 18+ (Jelly Bean MR2)
// Mouse hover support is not implemented for API < 18.
boolean isPointerEvent =
Expand All @@ -203,7 +213,8 @@ public boolean onGenericMotionEvent(@NonNull MotionEvent event) {
packet.order(ByteOrder.LITTLE_ENDIAN);

// ACTION_HOVER_MOVE always applies to a single pointer only.
addPointerForIndex(event, event.getActionIndex(), pointerChange, 0, IDENTITY_TRANSFORM, packet);
addPointerForIndex(
event, event.getActionIndex(), pointerChange, 0, IDENTITY_TRANSFORM, packet, context);
if (packet.position() % (POINTER_DATA_FIELD_COUNT * BYTES_PER_FIELD) != 0) {
throw new AssertionError("Packet position is not on field boundary.");
}
Expand All @@ -219,7 +230,8 @@ private void addPointerForIndex(
int pointerChange,
int pointerData,
Matrix transformMatrix,
ByteBuffer packet) {
ByteBuffer packet,
Context context) {
if (pointerChange == -1) {
return;
}
Expand Down Expand Up @@ -334,12 +346,26 @@ private void addPointerForIndex(

packet.putLong(pointerData); // platformData

// See android scrollview for insperation.
Piinks marked this conversation as resolved.
Show resolved Hide resolved
// https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/core/java/android/widget/ScrollView.java;l=930?q=ScrollView&ss=android%2Fplatform%2Fsuperproject%2Fmain
reidbaker marked this conversation as resolved.
Show resolved Hide resolved
if (signalKind == PointerSignalKind.SCROLL) {
packet.putDouble(-event.getAxisValue(MotionEvent.AXIS_HSCROLL)); // scroll_delta_x
packet.putDouble(-event.getAxisValue(MotionEvent.AXIS_VSCROLL)); // scroll_delta_y
double verticalScaleFactor = 1.0;
double horizontalScaleFactor = 1.0;
if (context != null) {
horizontalScaleFactor = ViewConfiguration.get(context).getScaledHorizontalScrollFactor();
verticalScaleFactor = ViewConfiguration.get(context).getScaledVerticalScrollFactor();
}
// Without flipping the sign of the value scroll moves the opposite direction of android
reidbaker marked this conversation as resolved.
Show resolved Hide resolved
final double horizontalScrollDistance =
reidbaker marked this conversation as resolved.
Show resolved Hide resolved
horizontalScaleFactor * -event.getAxisValue(MotionEvent.AXIS_HSCROLL, pointerIndex);
final double verticalScrollDistance =
verticalScaleFactor * -event.getAxisValue(MotionEvent.AXIS_VSCROLL, pointerIndex);

packet.putDouble(horizontalScrollDistance); // scroll_delta_x
packet.putDouble(verticalScrollDistance); // scroll_delta_y
} else {
packet.putDouble(0.0); // scroll_delta_x
packet.putDouble(0.0); // scroll_delta_x
packet.putDouble(0.0); // scroll_delta_y
}

if (isTrackpadPan) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -952,7 +952,8 @@ public boolean onTouchEvent(@NonNull MotionEvent event) {
@Override
public boolean onGenericMotionEvent(@NonNull MotionEvent event) {
boolean handled =
isAttachedToFlutterEngine() && androidTouchProcessor.onGenericMotionEvent(event);
isAttachedToFlutterEngine()
&& androidTouchProcessor.onGenericMotionEvent(event, getContext());
return handled ? true : super.onGenericMotionEvent(event);
}

Expand Down
3 changes: 2 additions & 1 deletion shell/platform/android/io/flutter/view/FlutterView.java
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,8 @@ public boolean onHoverEvent(MotionEvent event) {
*/
@Override
public boolean onGenericMotionEvent(MotionEvent event) {
boolean handled = isAttached() && androidTouchProcessor.onGenericMotionEvent(event);
boolean handled =
isAttached() && androidTouchProcessor.onGenericMotionEvent(event, getContext());
return handled ? true : super.onGenericMotionEvent(event);
}

Expand Down
50 changes: 25 additions & 25 deletions sky/packages/sky_engine/lib/_embedder.yaml
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
# This file is suitable for use within the tree. A different _embedder.yaml
# is generated by the BUILD.gn in this directory. Changes here must be
# mirrored there.
# This file is generated by //flutter/sky/packages/sky_engine:_embedder_yaml
# Do not modify this file directly. Instead, update the build file.

embedded_libs:
"dart:async": "../../../../../third_party/dart/sdk/lib/async/async.dart"
"dart:collection": "../../../../../third_party/dart/sdk/lib/collection/collection.dart"
"dart:convert": "../../../../../third_party/dart/sdk/lib/convert/convert.dart"
"dart:core": "../../../../../third_party/dart/sdk/lib/core/core.dart"
"dart:developer": "../../../../../third_party/dart/sdk/lib/developer/developer.dart"
"dart:ffi": "../../../../../third_party/dart/sdk/lib/ffi/ffi.dart"
"dart:html": "../../../../../third_party/dart/sdk/lib/html/html_dart2js.dart"
"dart:io": "../../../../../third_party/dart/sdk/lib/io/io.dart"
"dart:isolate": "../../../../../third_party/dart/sdk/lib/isolate/isolate.dart"
"dart:js": "../../../../../third_party/dart/sdk/lib/js/js.dart"
"dart:js_interop": "../../../../../third_party/dart/sdk/lib/js_interop/js_interop.dart"
"dart:js_interop_unsafe": "../../../../../third_party/dart/sdk/lib/js_interop_unsafe/js_interop_unsafe.dart"
"dart:js_util": "../../../../../third_party/dart/sdk/lib/js_util/js_util.dart"
"dart:math": "../../../../../third_party/dart/sdk/lib/math/math.dart"
"dart:typed_data": "../../../../../third_party/dart/sdk/lib/typed_data/typed_data.dart"
"dart:ui": "../../../../lib/ui/ui.dart"
"dart:ui_web": "../../../../lib/web_ui/lib/ui_web/src/ui_web.dart"
"dart:async": "async/async.dart"
"dart:collection": "collection/collection.dart"
"dart:convert": "convert/convert.dart"
"dart:core": "core/core.dart"
"dart:developer": "developer/developer.dart"
"dart:ffi": "ffi/ffi.dart"
"dart:html": "html/html_dart2js.dart"
"dart:io": "io/io.dart"
"dart:isolate": "isolate/isolate.dart"
"dart:js": "js/js.dart"
"dart:js_interop": "js_interop/js_interop.dart"
"dart:js_interop_unsafe": "js_interop_unsafe/js_interop_unsafe.dart"
"dart:js_util": "js_util/js_util.dart"
"dart:math": "math/math.dart"
"dart:typed_data": "typed_data/typed_data.dart"
"dart:ui": "ui/ui.dart"
"dart:ui_web": "ui_web/ui_web.dart"

"dart:_http": "../../../../../third_party/dart/sdk/lib/_http/http.dart"
"dart:_interceptors": "../../../../../third_party/dart/sdk/lib/_interceptors/interceptors.dart"
"dart:_http": "_http/http.dart"
"dart:_interceptors": "_interceptors/interceptors.dart"
# The _internal library is needed as some implementations bleed into the
# public API, e.g. List being Iterable by virtue of implementing
# EfficientLengthIterable. Not including this library yields analysis errors.
"dart:_internal": "../../../../../third_party/dart/sdk/lib/internal/internal.dart"
"dart:_internal": "internal/internal.dart"
# The _js_annotations library is also needed for the same reasons as _internal.
"dart:_js_annotations": "../../../../../third_party/dart/sdk/lib/js/_js_annotations.dart"
"dart:_js_annotations": "_js_annotations/_js_annotations.dart"
# The _js_types library is also needed for the same reasons as _internal.
"dart:_js_types": "../../../../../third_party/dart/sdk/lib/_internal/js_shared/lib/js_types.dart"
"dart:_js_types": "_js_types/js_types.dart"
"dart:nativewrappers": "_empty.dart"