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

Commit 30a5018

Browse files
authored
Support trackpad gestures in framework (#89944)
* Implement trackpad gestures in framework * Touch and Pan/Zoom pointers have separate IDs now * Handle trackpad pointer device type * Respect supportedDevices for pan/zoom events * Update after rebase * Fix check failures * Avoid error with very short drags * Address feedback * Refactor drag event handler * Address more feedback * Add some missing punctuation
1 parent 38f360f commit 30a5018

File tree

24 files changed

+1548
-92
lines changed

24 files changed

+1548
-92
lines changed

packages/flutter/lib/src/gestures/binding.dart

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -346,21 +346,21 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H
346346

347347
void _handlePointerEventImmediately(PointerEvent event) {
348348
HitTestResult? hitTestResult;
349-
if (event is PointerDownEvent || event is PointerSignalEvent || event is PointerHoverEvent) {
349+
if (event is PointerDownEvent || event is PointerSignalEvent || event is PointerHoverEvent || event is PointerPanZoomStartEvent) {
350350
assert(!_hitTests.containsKey(event.pointer));
351351
hitTestResult = HitTestResult();
352352
hitTest(hitTestResult, event.position);
353-
if (event is PointerDownEvent) {
353+
if (event is PointerDownEvent || event is PointerPanZoomStartEvent) {
354354
_hitTests[event.pointer] = hitTestResult;
355355
}
356356
assert(() {
357357
if (debugPrintHitTestResults)
358358
debugPrint('$event: $hitTestResult');
359359
return true;
360360
}());
361-
} else if (event is PointerUpEvent || event is PointerCancelEvent) {
361+
} else if (event is PointerUpEvent || event is PointerCancelEvent || event is PointerPanZoomEndEvent) {
362362
hitTestResult = _hitTests.remove(event.pointer);
363-
} else if (event.down) {
363+
} else if (event.down || event is PointerPanZoomUpdateEvent) {
364364
// Because events that occur with the pointer down (like
365365
// [PointerMoveEvent]s) should be dispatched to the same place that their
366366
// initial PointerDownEvent was, we want to re-use the path we found when
@@ -443,9 +443,9 @@ mixin GestureBinding on BindingBase implements HitTestable, HitTestDispatcher, H
443443
@override // from HitTestTarget
444444
void handleEvent(PointerEvent event, HitTestEntry entry) {
445445
pointerRouter.route(event);
446-
if (event is PointerDownEvent) {
446+
if (event is PointerDownEvent || event is PointerPanZoomStartEvent) {
447447
gestureArena.close(event.pointer);
448-
} else if (event is PointerUpEvent) {
448+
} else if (event is PointerUpEvent || event is PointerPanZoomEndEvent) {
449449
gestureArena.sweep(event.pointer);
450450
} else if (event is PointerSignalEvent) {
451451
pointerSignalResolver.resolve(event);

packages/flutter/lib/src/gestures/converter.dart

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,13 @@ import 'events.dart';
1515
int _synthesiseDownButtons(int buttons, PointerDeviceKind kind) {
1616
switch (kind) {
1717
case PointerDeviceKind.mouse:
18+
case PointerDeviceKind.trackpad:
1819
return buttons;
1920
case PointerDeviceKind.touch:
2021
case PointerDeviceKind.stylus:
2122
case PointerDeviceKind.invertedStylus:
2223
return buttons == 0 ? kPrimaryButton : buttons;
2324
case PointerDeviceKind.unknown:
24-
default: // ignore: no_default_cases, to allow adding new device types to [PointerDeviceKind]
25-
// TODO(moffatman): Remove after landing https://github.com/flutter/flutter/issues/23604
2625
// We have no information about the device but we know we never want
2726
// buttons to be 0 when the pointer is down.
2827
return buttons == 0 ? kPrimaryButton : buttons;
@@ -209,9 +208,44 @@ class PointerEventConverter {
209208
radiusMax: radiusMax,
210209
embedderId: datum.embedderId,
211210
);
212-
default: // ignore: no_default_cases, to allow adding new pointer events to [ui.PointerChange]
213-
// TODO(moffatman): Remove after landing https://github.com/flutter/flutter/issues/23604
214-
throw StateError('Unreachable');
211+
case ui.PointerChange.panZoomStart:
212+
return PointerPanZoomStartEvent(
213+
timeStamp: timeStamp,
214+
pointer: datum.pointerIdentifier,
215+
kind: kind,
216+
device: datum.device,
217+
position: position,
218+
embedderId: datum.embedderId,
219+
synthesized: datum.synthesized,
220+
);
221+
case ui.PointerChange.panZoomUpdate:
222+
final Offset pan =
223+
Offset(datum.panX, datum.panY) / devicePixelRatio;
224+
final Offset panDelta =
225+
Offset(datum.panDeltaX, datum.panDeltaY) / devicePixelRatio;
226+
return PointerPanZoomUpdateEvent(
227+
timeStamp: timeStamp,
228+
pointer: datum.pointerIdentifier,
229+
kind: kind,
230+
device: datum.device,
231+
position: position,
232+
pan: pan,
233+
panDelta: panDelta,
234+
scale: datum.scale,
235+
rotation: datum.rotation,
236+
embedderId: datum.embedderId,
237+
synthesized: datum.synthesized,
238+
);
239+
case ui.PointerChange.panZoomEnd:
240+
return PointerPanZoomEndEvent(
241+
timeStamp: timeStamp,
242+
pointer: datum.pointerIdentifier,
243+
kind: kind,
244+
device: datum.device,
245+
position: position,
246+
embedderId: datum.embedderId,
247+
synthesized: datum.synthesized,
248+
);
215249
}
216250
case ui.PointerSignalKind.scroll:
217251
final Offset scrollDelta =

0 commit comments

Comments
 (0)