diff --git a/lib/stub_ui/hooks.dart b/lib/stub_ui/hooks.dart index 8fd0c2a338a01..6e0820832939b 100644 --- a/lib/stub_ui/hooks.dart +++ b/lib/stub_ui/hooks.dart @@ -213,7 +213,7 @@ void _invoke3(void callback(A1 a1, A2 a2, A3 a3), Zone zone, A1 arg1 // // * pointer_data.cc // * FlutterView.java -const int _kPointerDataFieldCount = 21; +const int _kPointerDataFieldCount = 24; PointerDataPacket _unpackPointerDataPacket(ByteData packet) { const int kStride = Int64List.bytesPerElement; @@ -227,6 +227,7 @@ PointerDataPacket _unpackPointerDataPacket(ByteData packet) { timeStamp: new Duration(microseconds: packet.getInt64(kStride * offset++, _kFakeHostEndian)), change: PointerChange.values[packet.getInt64(kStride * offset++, _kFakeHostEndian)], kind: PointerDeviceKind.values[packet.getInt64(kStride * offset++, _kFakeHostEndian)], + signalKind: PointerSignalKind.values[packet.getInt64(kStride * offset++, _kFakeHostEndian)], device: packet.getInt64(kStride * offset++, _kFakeHostEndian), physicalX: packet.getFloat64(kStride * offset++, _kFakeHostEndian), physicalY: packet.getFloat64(kStride * offset++, _kFakeHostEndian), @@ -245,6 +246,8 @@ PointerDataPacket _unpackPointerDataPacket(ByteData packet) { orientation: packet.getFloat64(kStride * offset++, _kFakeHostEndian), tilt: packet.getFloat64(kStride * offset++, _kFakeHostEndian), platformData: packet.getInt64(kStride * offset++, _kFakeHostEndian), + scrollDeltaX: packet.getFloat64(kStride * offset++, _kFakeHostEndian), + scrollDeltaY: packet.getFloat64(kStride * offset++, _kFakeHostEndian) ); assert(offset == (i + 1) * _kPointerDataFieldCount); } diff --git a/lib/stub_ui/pointer.dart b/lib/stub_ui/pointer.dart index c0d3757d84bd5..fd5f3a13e25aa 100644 --- a/lib/stub_ui/pointer.dart +++ b/lib/stub_ui/pointer.dart @@ -54,6 +54,18 @@ enum PointerDeviceKind { unknown } +/// The kind of [PointerDeviceKind.signal]. +enum PointerSignalKind { + /// The event is not associated with a pointer signal. + none, + + /// A pointer-generated scroll (e.g., mouse wheel or trackpad scroll). + scroll, + + /// An unknown pointer signal kind. + unknown +} + /// Information about the state of a pointer. class PointerData { /// Creates an object that represents the state of a pointer. @@ -61,6 +73,7 @@ class PointerData { this.timeStamp: Duration.zero, this.change: PointerChange.cancel, this.kind: PointerDeviceKind.touch, + this.signalKind, this.device: 0, this.physicalX: 0.0, this.physicalY: 0.0, @@ -79,6 +92,8 @@ class PointerData { this.orientation: 0.0, this.tilt: 0.0, this.platformData: 0, + this.scrollDeltaX: 0.0, + this.scrollDeltaY: 0.0, }); /// Time of event dispatch, relative to an arbitrary timeline. @@ -90,6 +105,9 @@ class PointerData { /// The kind of input device for which the event was generated. final PointerDeviceKind kind; + /// The kind of signal for a pointer signal event. + final PointerSignalKind signalKind; + /// Unique identifier for the pointing device, reused across interactions. final int device; @@ -203,6 +221,16 @@ class PointerData { /// Opaque platform-specific data associated with the event. final int platformData; + /// For events with signalKind of PointerSignalKind.scroll: + /// + /// The amount to scroll in the x direction, in physical pixels. + final double scrollDeltaX; + + /// For events with signalKind of PointerSignalKind.scroll: + /// + /// The amount to scroll in the y direction, in physical pixels. + final double scrollDeltaY; + @override String toString() => '$runtimeType(x: $physicalX, y: $physicalY)'; @@ -212,6 +240,7 @@ class PointerData { 'timeStamp: $timeStamp, ' 'change: $change, ' 'kind: $kind, ' + 'signalKind: $signalKind, ' 'device: $device, ' 'physicalX: $physicalX, ' 'physicalY: $physicalY, ' @@ -228,7 +257,9 @@ class PointerData { 'radiusMax: $radiusMax, ' 'orientation: $orientation, ' 'tilt: $tilt, ' - 'platformData: $platformData' + 'platformData: $platformData, ' + 'scrollDeltaX: $scrollDeltaX, ' + 'scrollDeltaY: $scrollDeltaY' ')'; } } diff --git a/lib/ui/hooks.dart b/lib/ui/hooks.dart index b1550bf90b1ee..e88580a95ce06 100644 --- a/lib/ui/hooks.dart +++ b/lib/ui/hooks.dart @@ -259,7 +259,7 @@ void _invoke3(void callback(A1 a1, A2 a2, A3 a3), Zone zone, A1 arg1 // // * pointer_data.cc // * FlutterView.java -const int _kPointerDataFieldCount = 21; +const int _kPointerDataFieldCount = 24; PointerDataPacket _unpackPointerDataPacket(ByteData packet) { const int kStride = Int64List.bytesPerElement; @@ -273,6 +273,7 @@ PointerDataPacket _unpackPointerDataPacket(ByteData packet) { timeStamp: new Duration(microseconds: packet.getInt64(kStride * offset++, _kFakeHostEndian)), change: PointerChange.values[packet.getInt64(kStride * offset++, _kFakeHostEndian)], kind: PointerDeviceKind.values[packet.getInt64(kStride * offset++, _kFakeHostEndian)], + signalKind: PointerSignalKind.values[packet.getInt64(kStride * offset++, _kFakeHostEndian)], device: packet.getInt64(kStride * offset++, _kFakeHostEndian), physicalX: packet.getFloat64(kStride * offset++, _kFakeHostEndian), physicalY: packet.getFloat64(kStride * offset++, _kFakeHostEndian), @@ -291,6 +292,8 @@ PointerDataPacket _unpackPointerDataPacket(ByteData packet) { orientation: packet.getFloat64(kStride * offset++, _kFakeHostEndian), tilt: packet.getFloat64(kStride * offset++, _kFakeHostEndian), platformData: packet.getInt64(kStride * offset++, _kFakeHostEndian), + scrollDeltaX: packet.getFloat64(kStride * offset++, _kFakeHostEndian), + scrollDeltaY: packet.getFloat64(kStride * offset++, _kFakeHostEndian) ); assert(offset == (i + 1) * _kPointerDataFieldCount); } diff --git a/lib/ui/pointer.dart b/lib/ui/pointer.dart index c0d3757d84bd5..fd5f3a13e25aa 100644 --- a/lib/ui/pointer.dart +++ b/lib/ui/pointer.dart @@ -54,6 +54,18 @@ enum PointerDeviceKind { unknown } +/// The kind of [PointerDeviceKind.signal]. +enum PointerSignalKind { + /// The event is not associated with a pointer signal. + none, + + /// A pointer-generated scroll (e.g., mouse wheel or trackpad scroll). + scroll, + + /// An unknown pointer signal kind. + unknown +} + /// Information about the state of a pointer. class PointerData { /// Creates an object that represents the state of a pointer. @@ -61,6 +73,7 @@ class PointerData { this.timeStamp: Duration.zero, this.change: PointerChange.cancel, this.kind: PointerDeviceKind.touch, + this.signalKind, this.device: 0, this.physicalX: 0.0, this.physicalY: 0.0, @@ -79,6 +92,8 @@ class PointerData { this.orientation: 0.0, this.tilt: 0.0, this.platformData: 0, + this.scrollDeltaX: 0.0, + this.scrollDeltaY: 0.0, }); /// Time of event dispatch, relative to an arbitrary timeline. @@ -90,6 +105,9 @@ class PointerData { /// The kind of input device for which the event was generated. final PointerDeviceKind kind; + /// The kind of signal for a pointer signal event. + final PointerSignalKind signalKind; + /// Unique identifier for the pointing device, reused across interactions. final int device; @@ -203,6 +221,16 @@ class PointerData { /// Opaque platform-specific data associated with the event. final int platformData; + /// For events with signalKind of PointerSignalKind.scroll: + /// + /// The amount to scroll in the x direction, in physical pixels. + final double scrollDeltaX; + + /// For events with signalKind of PointerSignalKind.scroll: + /// + /// The amount to scroll in the y direction, in physical pixels. + final double scrollDeltaY; + @override String toString() => '$runtimeType(x: $physicalX, y: $physicalY)'; @@ -212,6 +240,7 @@ class PointerData { 'timeStamp: $timeStamp, ' 'change: $change, ' 'kind: $kind, ' + 'signalKind: $signalKind, ' 'device: $device, ' 'physicalX: $physicalX, ' 'physicalY: $physicalY, ' @@ -228,7 +257,9 @@ class PointerData { 'radiusMax: $radiusMax, ' 'orientation: $orientation, ' 'tilt: $tilt, ' - 'platformData: $platformData' + 'platformData: $platformData, ' + 'scrollDeltaX: $scrollDeltaX, ' + 'scrollDeltaY: $scrollDeltaY' ')'; } } diff --git a/lib/ui/window/pointer_data.cc b/lib/ui/window/pointer_data.cc index e74e0b5ce94f0..d52bda18c3f58 100644 --- a/lib/ui/window/pointer_data.cc +++ b/lib/ui/window/pointer_data.cc @@ -9,7 +9,7 @@ namespace blink { // If this value changes, update the pointer data unpacking code in hooks.dart. -static constexpr int kPointerDataFieldCount = 21; +static constexpr int kPointerDataFieldCount = 24; static_assert(sizeof(PointerData) == sizeof(int64_t) * kPointerDataFieldCount, "PointerData has the wrong size"); diff --git a/lib/ui/window/pointer_data.h b/lib/ui/window/pointer_data.h index d9d01b560a1d2..56fd6067a1b35 100644 --- a/lib/ui/window/pointer_data.h +++ b/lib/ui/window/pointer_data.h @@ -28,11 +28,19 @@ struct alignas(8) PointerData { kMouse, kStylus, kInvertedStylus, + kSignal, + }; + + // Must match the PointerSignalKind enum in pointer.dart. + enum class SignalKind : int64_t { + kNone, + kScroll, }; int64_t time_stamp; Change change; DeviceKind kind; + SignalKind signal_kind; int64_t device; double physical_x; double physical_y; @@ -51,6 +59,8 @@ struct alignas(8) PointerData { double orientation; double tilt; int64_t platformData; + double scroll_delta_x; + double scroll_delta_y; void Clear(); }; diff --git a/shell/platform/android/io/flutter/view/FlutterView.java b/shell/platform/android/io/flutter/view/FlutterView.java index c766305fd7dcc..6c42dc152d739 100644 --- a/shell/platform/android/io/flutter/view/FlutterView.java +++ b/shell/platform/android/io/flutter/view/FlutterView.java @@ -378,10 +378,16 @@ public InputConnection onCreateInputConnection(EditorInfo outAttrs) { private static final int kPointerDeviceKindMouse = 1; private static final int kPointerDeviceKindStylus = 2; private static final int kPointerDeviceKindInvertedStylus = 3; - private static final int kPointerDeviceKindUnknown = 4; + private static final int kPointerDeviceKindSignal = 4; + private static final int kPointerDeviceKindUnknown = 5; + + // Must match the PointerSignalKind enum in pointer.dart. + private static final int kPointerSignalKindNone = 0; + private static final int kPointerSignalKindScroll = 1; + private static final int kPointerSignalKindUnknown = 2; // These values must match the unpacking code in hooks.dart. - private static final int kPointerDataFieldCount = 21; + private static final int kPointerDataFieldCount = 24; private static final int kPointerBytesPerField = 8; private int getPointerChangeForAction(int maskedAction) { @@ -436,11 +442,14 @@ private void addPointerForIndex(MotionEvent event, int pointerIndex, int pointer int pointerKind = getPointerDeviceTypeForToolType(event.getToolType(pointerIndex)); + int signalKind = kPointerSignalKindNone; + long timeStamp = event.getEventTime() * 1000; // Convert from milliseconds to microseconds. packet.putLong(timeStamp); // time_stamp packet.putLong(pointerChange); // change packet.putLong(pointerKind); // kind + packet.putLong(signalKind); // signal_kind packet.putLong(event.getPointerId(pointerIndex)); // device packet.putDouble(event.getX(pointerIndex)); // physical_x packet.putDouble(event.getY(pointerIndex)); // physical_y @@ -492,6 +501,9 @@ private void addPointerForIndex(MotionEvent event, int pointerIndex, int pointer } packet.putLong(pointerData); // platformData + + packet.putDouble(0.0); // scroll_delta_x + packet.putDouble(0.0); // scroll_delta_y } @Override diff --git a/shell/platform/embedder/embedder.cc b/shell/platform/embedder/embedder.cc index 7dffc91718e77..c4d0546474411 100644 --- a/shell/platform/embedder/embedder.cc +++ b/shell/platform/embedder/embedder.cc @@ -677,6 +677,19 @@ inline blink::PointerData::Change ToPointerDataChange( return blink::PointerData::Change::kCancel; } +// Returns the blink::PointerData::SignalKind for the given +// FlutterPointerSignaKind. +inline blink::PointerData::SignalKind ToPointerDataSignalKind( + FlutterPointerSignalKind kind) { + switch (kind) { + case kFlutterPointerSignalKindNone: + return blink::PointerData::SignalKind::kNone; + case kFlutterPointerSignalKindScroll: + return blink::PointerData::SignalKind::kScroll; + } + return blink::PointerData::SignalKind::kNone; +} + FlutterEngineResult FlutterEngineSendPointerEvent( FlutterEngine engine, const FlutterPointerEvent* pointers, @@ -699,6 +712,10 @@ FlutterEngineResult FlutterEngineSendPointerEvent( pointer_data.physical_x = SAFE_ACCESS(current, x, 0.0); pointer_data.physical_y = SAFE_ACCESS(current, y, 0.0); pointer_data.device = SAFE_ACCESS(current, device, 0); + pointer_data.signal_kind = ToPointerDataSignalKind( + SAFE_ACCESS(current, signal_kind, kFlutterPointerSignalKindNone)); + pointer_data.scroll_delta_x = SAFE_ACCESS(current, scroll_delta_x, 0.0); + pointer_data.scroll_delta_y = SAFE_ACCESS(current, scroll_delta_y, 0.0); packet->SetPointerData(i, pointer_data); current = reinterpret_cast( reinterpret_cast(current) + current->struct_size); diff --git a/shell/platform/embedder/embedder.h b/shell/platform/embedder/embedder.h index 402f58ebcd3ef..103da739a2147 100644 --- a/shell/platform/embedder/embedder.h +++ b/shell/platform/embedder/embedder.h @@ -277,6 +277,7 @@ typedef struct { double pixel_ratio; } FlutterWindowMetricsEvent; +// The phase of the pointer event. typedef enum { kCancel, kUp, @@ -287,6 +288,12 @@ typedef enum { kHover, } FlutterPointerPhase; +// The type of a pointer signal. +typedef enum { + kFlutterPointerSignalKindNone, + kFlutterPointerSignalKindScroll, +} FlutterPointerSignalKind; + typedef struct { // The size of this struct. Must be sizeof(FlutterPointerEvent). size_t struct_size; @@ -297,6 +304,9 @@ typedef struct { // An optional device identifier. If this is not specified, it is assumed that // the embedder has no multitouch capability. int32_t device; + FlutterPointerSignalKind signal_kind; + double scroll_delta_x; + double scroll_delta_y; } FlutterPointerEvent; struct _FlutterPlatformMessageResponseHandle;