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

Commit dd80fc9

Browse files
authored
Add engine support for scrollwheel events (#7494)
Adds support for pointer signals, in a way that will support both discrete events (e.g., scroll wheels, flutter/flutter#22762) and continuous gestures (e.g., trackpad scroll, flutter/flutter#21953). Also exposes these new event options to the embedder. Does not include code to send the new events from the platform shells.
1 parent f4951df commit dd80fc9

File tree

9 files changed

+124
-7
lines changed

9 files changed

+124
-7
lines changed

lib/stub_ui/hooks.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ void _invoke3<A1, A2, A3>(void callback(A1 a1, A2 a2, A3 a3), Zone zone, A1 arg1
213213
//
214214
// * pointer_data.cc
215215
// * FlutterView.java
216-
const int _kPointerDataFieldCount = 21;
216+
const int _kPointerDataFieldCount = 24;
217217

218218
PointerDataPacket _unpackPointerDataPacket(ByteData packet) {
219219
const int kStride = Int64List.bytesPerElement;
@@ -227,6 +227,7 @@ PointerDataPacket _unpackPointerDataPacket(ByteData packet) {
227227
timeStamp: new Duration(microseconds: packet.getInt64(kStride * offset++, _kFakeHostEndian)),
228228
change: PointerChange.values[packet.getInt64(kStride * offset++, _kFakeHostEndian)],
229229
kind: PointerDeviceKind.values[packet.getInt64(kStride * offset++, _kFakeHostEndian)],
230+
signalKind: PointerSignalKind.values[packet.getInt64(kStride * offset++, _kFakeHostEndian)],
230231
device: packet.getInt64(kStride * offset++, _kFakeHostEndian),
231232
physicalX: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
232233
physicalY: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
@@ -245,6 +246,8 @@ PointerDataPacket _unpackPointerDataPacket(ByteData packet) {
245246
orientation: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
246247
tilt: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
247248
platformData: packet.getInt64(kStride * offset++, _kFakeHostEndian),
249+
scrollDeltaX: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
250+
scrollDeltaY: packet.getFloat64(kStride * offset++, _kFakeHostEndian)
248251
);
249252
assert(offset == (i + 1) * _kPointerDataFieldCount);
250253
}

lib/stub_ui/pointer.dart

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,26 @@ enum PointerDeviceKind {
5454
unknown
5555
}
5656

57+
/// The kind of [PointerDeviceKind.signal].
58+
enum PointerSignalKind {
59+
/// The event is not associated with a pointer signal.
60+
none,
61+
62+
/// A pointer-generated scroll (e.g., mouse wheel or trackpad scroll).
63+
scroll,
64+
65+
/// An unknown pointer signal kind.
66+
unknown
67+
}
68+
5769
/// Information about the state of a pointer.
5870
class PointerData {
5971
/// Creates an object that represents the state of a pointer.
6072
const PointerData({
6173
this.timeStamp: Duration.zero,
6274
this.change: PointerChange.cancel,
6375
this.kind: PointerDeviceKind.touch,
76+
this.signalKind,
6477
this.device: 0,
6578
this.physicalX: 0.0,
6679
this.physicalY: 0.0,
@@ -79,6 +92,8 @@ class PointerData {
7992
this.orientation: 0.0,
8093
this.tilt: 0.0,
8194
this.platformData: 0,
95+
this.scrollDeltaX: 0.0,
96+
this.scrollDeltaY: 0.0,
8297
});
8398

8499
/// Time of event dispatch, relative to an arbitrary timeline.
@@ -90,6 +105,9 @@ class PointerData {
90105
/// The kind of input device for which the event was generated.
91106
final PointerDeviceKind kind;
92107

108+
/// The kind of signal for a pointer signal event.
109+
final PointerSignalKind signalKind;
110+
93111
/// Unique identifier for the pointing device, reused across interactions.
94112
final int device;
95113

@@ -203,6 +221,16 @@ class PointerData {
203221
/// Opaque platform-specific data associated with the event.
204222
final int platformData;
205223

224+
/// For events with signalKind of PointerSignalKind.scroll:
225+
///
226+
/// The amount to scroll in the x direction, in physical pixels.
227+
final double scrollDeltaX;
228+
229+
/// For events with signalKind of PointerSignalKind.scroll:
230+
///
231+
/// The amount to scroll in the y direction, in physical pixels.
232+
final double scrollDeltaY;
233+
206234
@override
207235
String toString() => '$runtimeType(x: $physicalX, y: $physicalY)';
208236

@@ -212,6 +240,7 @@ class PointerData {
212240
'timeStamp: $timeStamp, '
213241
'change: $change, '
214242
'kind: $kind, '
243+
'signalKind: $signalKind, '
215244
'device: $device, '
216245
'physicalX: $physicalX, '
217246
'physicalY: $physicalY, '
@@ -228,7 +257,9 @@ class PointerData {
228257
'radiusMax: $radiusMax, '
229258
'orientation: $orientation, '
230259
'tilt: $tilt, '
231-
'platformData: $platformData'
260+
'platformData: $platformData, '
261+
'scrollDeltaX: $scrollDeltaX, '
262+
'scrollDeltaY: $scrollDeltaY'
232263
')';
233264
}
234265
}

lib/ui/hooks.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ void _invoke3<A1, A2, A3>(void callback(A1 a1, A2 a2, A3 a3), Zone zone, A1 arg1
259259
//
260260
// * pointer_data.cc
261261
// * FlutterView.java
262-
const int _kPointerDataFieldCount = 21;
262+
const int _kPointerDataFieldCount = 24;
263263

264264
PointerDataPacket _unpackPointerDataPacket(ByteData packet) {
265265
const int kStride = Int64List.bytesPerElement;
@@ -273,6 +273,7 @@ PointerDataPacket _unpackPointerDataPacket(ByteData packet) {
273273
timeStamp: new Duration(microseconds: packet.getInt64(kStride * offset++, _kFakeHostEndian)),
274274
change: PointerChange.values[packet.getInt64(kStride * offset++, _kFakeHostEndian)],
275275
kind: PointerDeviceKind.values[packet.getInt64(kStride * offset++, _kFakeHostEndian)],
276+
signalKind: PointerSignalKind.values[packet.getInt64(kStride * offset++, _kFakeHostEndian)],
276277
device: packet.getInt64(kStride * offset++, _kFakeHostEndian),
277278
physicalX: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
278279
physicalY: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
@@ -291,6 +292,8 @@ PointerDataPacket _unpackPointerDataPacket(ByteData packet) {
291292
orientation: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
292293
tilt: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
293294
platformData: packet.getInt64(kStride * offset++, _kFakeHostEndian),
295+
scrollDeltaX: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
296+
scrollDeltaY: packet.getFloat64(kStride * offset++, _kFakeHostEndian)
294297
);
295298
assert(offset == (i + 1) * _kPointerDataFieldCount);
296299
}

lib/ui/pointer.dart

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,26 @@ enum PointerDeviceKind {
5454
unknown
5555
}
5656

57+
/// The kind of [PointerDeviceKind.signal].
58+
enum PointerSignalKind {
59+
/// The event is not associated with a pointer signal.
60+
none,
61+
62+
/// A pointer-generated scroll (e.g., mouse wheel or trackpad scroll).
63+
scroll,
64+
65+
/// An unknown pointer signal kind.
66+
unknown
67+
}
68+
5769
/// Information about the state of a pointer.
5870
class PointerData {
5971
/// Creates an object that represents the state of a pointer.
6072
const PointerData({
6173
this.timeStamp: Duration.zero,
6274
this.change: PointerChange.cancel,
6375
this.kind: PointerDeviceKind.touch,
76+
this.signalKind,
6477
this.device: 0,
6578
this.physicalX: 0.0,
6679
this.physicalY: 0.0,
@@ -79,6 +92,8 @@ class PointerData {
7992
this.orientation: 0.0,
8093
this.tilt: 0.0,
8194
this.platformData: 0,
95+
this.scrollDeltaX: 0.0,
96+
this.scrollDeltaY: 0.0,
8297
});
8398

8499
/// Time of event dispatch, relative to an arbitrary timeline.
@@ -90,6 +105,9 @@ class PointerData {
90105
/// The kind of input device for which the event was generated.
91106
final PointerDeviceKind kind;
92107

108+
/// The kind of signal for a pointer signal event.
109+
final PointerSignalKind signalKind;
110+
93111
/// Unique identifier for the pointing device, reused across interactions.
94112
final int device;
95113

@@ -203,6 +221,16 @@ class PointerData {
203221
/// Opaque platform-specific data associated with the event.
204222
final int platformData;
205223

224+
/// For events with signalKind of PointerSignalKind.scroll:
225+
///
226+
/// The amount to scroll in the x direction, in physical pixels.
227+
final double scrollDeltaX;
228+
229+
/// For events with signalKind of PointerSignalKind.scroll:
230+
///
231+
/// The amount to scroll in the y direction, in physical pixels.
232+
final double scrollDeltaY;
233+
206234
@override
207235
String toString() => '$runtimeType(x: $physicalX, y: $physicalY)';
208236

@@ -212,6 +240,7 @@ class PointerData {
212240
'timeStamp: $timeStamp, '
213241
'change: $change, '
214242
'kind: $kind, '
243+
'signalKind: $signalKind, '
215244
'device: $device, '
216245
'physicalX: $physicalX, '
217246
'physicalY: $physicalY, '
@@ -228,7 +257,9 @@ class PointerData {
228257
'radiusMax: $radiusMax, '
229258
'orientation: $orientation, '
230259
'tilt: $tilt, '
231-
'platformData: $platformData'
260+
'platformData: $platformData, '
261+
'scrollDeltaX: $scrollDeltaX, '
262+
'scrollDeltaY: $scrollDeltaY'
232263
')';
233264
}
234265
}

lib/ui/window/pointer_data.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
namespace blink {
1010

1111
// If this value changes, update the pointer data unpacking code in hooks.dart.
12-
static constexpr int kPointerDataFieldCount = 21;
12+
static constexpr int kPointerDataFieldCount = 24;
1313

1414
static_assert(sizeof(PointerData) == sizeof(int64_t) * kPointerDataFieldCount,
1515
"PointerData has the wrong size");

lib/ui/window/pointer_data.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,19 @@ struct alignas(8) PointerData {
2828
kMouse,
2929
kStylus,
3030
kInvertedStylus,
31+
kSignal,
32+
};
33+
34+
// Must match the PointerSignalKind enum in pointer.dart.
35+
enum class SignalKind : int64_t {
36+
kNone,
37+
kScroll,
3138
};
3239

3340
int64_t time_stamp;
3441
Change change;
3542
DeviceKind kind;
43+
SignalKind signal_kind;
3644
int64_t device;
3745
double physical_x;
3846
double physical_y;
@@ -51,6 +59,8 @@ struct alignas(8) PointerData {
5159
double orientation;
5260
double tilt;
5361
int64_t platformData;
62+
double scroll_delta_x;
63+
double scroll_delta_y;
5464

5565
void Clear();
5666
};

shell/platform/android/io/flutter/view/FlutterView.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -378,10 +378,16 @@ public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
378378
private static final int kPointerDeviceKindMouse = 1;
379379
private static final int kPointerDeviceKindStylus = 2;
380380
private static final int kPointerDeviceKindInvertedStylus = 3;
381-
private static final int kPointerDeviceKindUnknown = 4;
381+
private static final int kPointerDeviceKindSignal = 4;
382+
private static final int kPointerDeviceKindUnknown = 5;
383+
384+
// Must match the PointerSignalKind enum in pointer.dart.
385+
private static final int kPointerSignalKindNone = 0;
386+
private static final int kPointerSignalKindScroll = 1;
387+
private static final int kPointerSignalKindUnknown = 2;
382388

383389
// These values must match the unpacking code in hooks.dart.
384-
private static final int kPointerDataFieldCount = 21;
390+
private static final int kPointerDataFieldCount = 24;
385391
private static final int kPointerBytesPerField = 8;
386392

387393
private int getPointerChangeForAction(int maskedAction) {
@@ -436,11 +442,14 @@ private void addPointerForIndex(MotionEvent event, int pointerIndex, int pointer
436442

437443
int pointerKind = getPointerDeviceTypeForToolType(event.getToolType(pointerIndex));
438444

445+
int signalKind = kPointerSignalKindNone;
446+
439447
long timeStamp = event.getEventTime() * 1000; // Convert from milliseconds to microseconds.
440448

441449
packet.putLong(timeStamp); // time_stamp
442450
packet.putLong(pointerChange); // change
443451
packet.putLong(pointerKind); // kind
452+
packet.putLong(signalKind); // signal_kind
444453
packet.putLong(event.getPointerId(pointerIndex)); // device
445454
packet.putDouble(event.getX(pointerIndex)); // physical_x
446455
packet.putDouble(event.getY(pointerIndex)); // physical_y
@@ -492,6 +501,9 @@ private void addPointerForIndex(MotionEvent event, int pointerIndex, int pointer
492501
}
493502

494503
packet.putLong(pointerData); // platformData
504+
505+
packet.putDouble(0.0); // scroll_delta_x
506+
packet.putDouble(0.0); // scroll_delta_y
495507
}
496508

497509
@Override

shell/platform/embedder/embedder.cc

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,19 @@ inline blink::PointerData::Change ToPointerDataChange(
677677
return blink::PointerData::Change::kCancel;
678678
}
679679

680+
// Returns the blink::PointerData::SignalKind for the given
681+
// FlutterPointerSignaKind.
682+
inline blink::PointerData::SignalKind ToPointerDataSignalKind(
683+
FlutterPointerSignalKind kind) {
684+
switch (kind) {
685+
case kFlutterPointerSignalKindNone:
686+
return blink::PointerData::SignalKind::kNone;
687+
case kFlutterPointerSignalKindScroll:
688+
return blink::PointerData::SignalKind::kScroll;
689+
}
690+
return blink::PointerData::SignalKind::kNone;
691+
}
692+
680693
FlutterEngineResult FlutterEngineSendPointerEvent(
681694
FlutterEngine engine,
682695
const FlutterPointerEvent* pointers,
@@ -699,6 +712,10 @@ FlutterEngineResult FlutterEngineSendPointerEvent(
699712
pointer_data.physical_x = SAFE_ACCESS(current, x, 0.0);
700713
pointer_data.physical_y = SAFE_ACCESS(current, y, 0.0);
701714
pointer_data.device = SAFE_ACCESS(current, device, 0);
715+
pointer_data.signal_kind = ToPointerDataSignalKind(
716+
SAFE_ACCESS(current, signal_kind, kFlutterPointerSignalKindNone));
717+
pointer_data.scroll_delta_x = SAFE_ACCESS(current, scroll_delta_x, 0.0);
718+
pointer_data.scroll_delta_y = SAFE_ACCESS(current, scroll_delta_y, 0.0);
702719
packet->SetPointerData(i, pointer_data);
703720
current = reinterpret_cast<const FlutterPointerEvent*>(
704721
reinterpret_cast<const uint8_t*>(current) + current->struct_size);

shell/platform/embedder/embedder.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ typedef struct {
277277
double pixel_ratio;
278278
} FlutterWindowMetricsEvent;
279279

280+
// The phase of the pointer event.
280281
typedef enum {
281282
kCancel,
282283
kUp,
@@ -287,6 +288,12 @@ typedef enum {
287288
kHover,
288289
} FlutterPointerPhase;
289290

291+
// The type of a pointer signal.
292+
typedef enum {
293+
kFlutterPointerSignalKindNone,
294+
kFlutterPointerSignalKindScroll,
295+
} FlutterPointerSignalKind;
296+
290297
typedef struct {
291298
// The size of this struct. Must be sizeof(FlutterPointerEvent).
292299
size_t struct_size;
@@ -297,6 +304,9 @@ typedef struct {
297304
// An optional device identifier. If this is not specified, it is assumed that
298305
// the embedder has no multitouch capability.
299306
int32_t device;
307+
FlutterPointerSignalKind signal_kind;
308+
double scroll_delta_x;
309+
double scroll_delta_y;
300310
} FlutterPointerEvent;
301311

302312
struct _FlutterPlatformMessageResponseHandle;

0 commit comments

Comments
 (0)