Skip to content

Commit

Permalink
Correctly synthesise event buttons (flutter#30535)
Browse files Browse the repository at this point in the history
* Correctly synthesise buttons, and add tests
  • Loading branch information
dkwingsmt authored Apr 5, 2019
1 parent 8e3906a commit 1ae32fa
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 18 deletions.
28 changes: 20 additions & 8 deletions packages/flutter/lib/src/gestures/converter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,22 @@ class _PointerState {
}
}

// Add `kPrimaryButton` to [buttons] when a pointer of certain devices is down.
//
// TODO(tongmu): This patch is supposed to be done by embedders. Patching it
// in framework is a workaround before [PointerEventConverter] is moved to embedders.
// https://github.com/flutter/flutter/issues/30454
int _synthesiseDownButtons(int buttons, PointerDeviceKind kind) {
switch (kind) {
case PointerDeviceKind.touch:
case PointerDeviceKind.stylus:
case PointerDeviceKind.invertedStylus:
return buttons | kPrimaryButton;
default:
return buttons;
}
}

/// Converts from engine pointer data to framework pointer events.
///
/// This takes [PointerDataPacket] objects, as received from the engine via
Expand Down Expand Up @@ -207,8 +223,7 @@ class PointerEventConverter {
kind: kind,
device: datum.device,
position: position,
// TODO(tongmu): Move button patching to embedder, https://github.com/flutter/flutter/issues/30454
buttons: datum.buttons | kPrimaryButton,
buttons: _synthesiseDownButtons(datum.buttons, kind),
obscured: datum.obscured,
pressure: datum.pressure,
pressureMin: datum.pressureMin,
Expand Down Expand Up @@ -237,8 +252,7 @@ class PointerEventConverter {
device: datum.device,
position: position,
delta: state.deltaTo(position),
// TODO(tongmu): Move button patching to embedder, https://github.com/flutter/flutter/issues/30454
buttons: datum.buttons | kPrimaryButton,
buttons: _synthesiseDownButtons(datum.buttons, kind),
obscured: datum.obscured,
pressure: datum.pressure,
pressureMin: datum.pressureMin,
Expand Down Expand Up @@ -273,8 +287,7 @@ class PointerEventConverter {
device: datum.device,
position: position,
delta: state.deltaTo(position),
// TODO(tongmu): Move button patching to embedder, https://github.com/flutter/flutter/issues/30454
buttons: datum.buttons | kPrimaryButton,
buttons: _synthesiseDownButtons(datum.buttons, kind),
obscured: datum.obscured,
pressure: datum.pressure,
pressureMin: datum.pressureMin,
Expand Down Expand Up @@ -421,8 +434,7 @@ class PointerEventConverter {
device: datum.device,
position: position,
delta: state.deltaTo(position),
// TODO(tongmu): Move button patching to embedder, https://github.com/flutter/flutter/issues/30454
buttons: datum.buttons | kPrimaryButton,
buttons: _synthesiseDownButtons(datum.buttons, kind),
obscured: datum.obscured,
pressure: datum.pressure,
pressureMin: datum.pressureMin,
Expand Down
111 changes: 101 additions & 10 deletions packages/flutter/test/gestures/gesture_binding_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ void main() {
ui.window.onPointerDataPacket(packet);
expect(events.length, 2);
expect(events[0].runtimeType, equals(PointerDownEvent));
expect(events[0].buttons, equals(1));
expect(events[1].runtimeType, equals(PointerUpEvent));
});

Expand All @@ -66,9 +65,7 @@ void main() {
ui.window.onPointerDataPacket(packet);
expect(events.length, 3);
expect(events[0].runtimeType, equals(PointerDownEvent));
expect(events[0].buttons, equals(1));
expect(events[1].runtimeType, equals(PointerMoveEvent));
expect(events[1].buttons, equals(1));
expect(events[2].runtimeType, equals(PointerUpEvent));
});

Expand Down Expand Up @@ -122,9 +119,7 @@ void main() {
ui.window.onPointerDataPacket(packet);
expect(events.length, 3);
expect(events[0].runtimeType, equals(PointerDownEvent));
expect(events[0].buttons, equals(1));
expect(events[1].runtimeType, equals(PointerMoveEvent));
expect(events[1].buttons, equals(1));
expect(events[1].delta, equals(const Offset(9.0, 12.0)));
expect(events[2].runtimeType, equals(PointerUpEvent));
});
Expand All @@ -143,7 +138,6 @@ void main() {
ui.window.onPointerDataPacket(packet);
expect(events.length, 2);
expect(events[0].runtimeType, equals(PointerDownEvent));
expect(events[0].buttons, equals(1));
expect(events[1].runtimeType, equals(PointerCancelEvent));
});

Expand All @@ -165,7 +159,6 @@ void main() {
ui.window.onPointerDataPacket(packet);
expect(events.length, 2);
expect(events[0].runtimeType, equals(PointerDownEvent));
expect(events[0].buttons, equals(1));
expect(events[1].runtimeType, equals(PointerCancelEvent));
});

Expand Down Expand Up @@ -207,7 +200,6 @@ void main() {
expect(events[1].runtimeType, equals(PointerHoverEvent));
expect(events[1].delta, equals(const Offset(5.0, 7.0)));
expect(events[2].runtimeType, equals(PointerDownEvent));
expect(events[2].buttons, equals(1));
expect(events[3].runtimeType, equals(PointerCancelEvent));
expect(events[4].runtimeType, equals(PointerHoverEvent));
expect(events[5].runtimeType, equals(PointerRemovedEvent));
Expand Down Expand Up @@ -254,10 +246,109 @@ void main() {
expect(events[2].runtimeType, equals(PointerScrollEvent));
expect(events[3].runtimeType, equals(PointerHoverEvent));
expect(events[4].runtimeType, equals(PointerDownEvent));
expect(events[4].buttons, equals(1));
expect(events[5].runtimeType, equals(PointerMoveEvent));
expect(events[5].buttons, equals(1));
expect(events[5].delta, equals(unexpectedOffset));
expect(events[6].runtimeType, equals(PointerScrollEvent));
});

test('Should synthesise kPrimaryButton for touch', () {
final Offset location = const Offset(10.0, 10.0) * ui.window.devicePixelRatio;
const PointerDeviceKind kind = PointerDeviceKind.touch;
final ui.PointerDataPacket packet = ui.PointerDataPacket(
data: <ui.PointerData>[
ui.PointerData(change: ui.PointerChange.add, kind: kind, physicalX: location.dx, physicalY: location.dy),
ui.PointerData(change: ui.PointerChange.hover, kind: kind, physicalX: location.dx, physicalY: location.dy),
ui.PointerData(change: ui.PointerChange.down, kind: kind, physicalX: location.dx, physicalY: location.dy),
ui.PointerData(change: ui.PointerChange.move, kind: kind, physicalX: location.dx, physicalY: location.dy),
ui.PointerData(change: ui.PointerChange.up, kind: kind, physicalX: location.dx, physicalY: location.dy),
]
);

final List<PointerEvent> events = PointerEventConverter.expand(
packet.data, ui.window.devicePixelRatio).toList();

expect(events.length, 5);
expect(events[0].runtimeType, equals(PointerAddedEvent));
expect(events[0].buttons, equals(0));
expect(events[1].runtimeType, equals(PointerHoverEvent));
expect(events[1].buttons, equals(0));
expect(events[2].runtimeType, equals(PointerDownEvent));
expect(events[2].buttons, equals(kPrimaryButton));
expect(events[3].runtimeType, equals(PointerMoveEvent));
expect(events[3].buttons, equals(kPrimaryButton));
expect(events[4].runtimeType, equals(PointerUpEvent));
expect(events[4].buttons, equals(0));

PointerEventConverter.clearPointers();
});

test('Should synthesise kPrimaryButton for stylus', () {
final Offset location = const Offset(10.0, 10.0) * ui.window.devicePixelRatio;
for (PointerDeviceKind kind in <PointerDeviceKind>[
PointerDeviceKind.stylus,
PointerDeviceKind.invertedStylus,
]) {

final ui.PointerDataPacket packet = ui.PointerDataPacket(
data: <ui.PointerData>[
ui.PointerData(change: ui.PointerChange.add, kind: kind, physicalX: location.dx, physicalY: location.dy),
ui.PointerData(change: ui.PointerChange.hover, kind: kind, physicalX: location.dx, physicalY: location.dy),
ui.PointerData(change: ui.PointerChange.down, kind: kind, physicalX: location.dx, physicalY: location.dy),
ui.PointerData(change: ui.PointerChange.move, buttons: kSecondaryStylusButton, kind: kind, physicalX: location.dx, physicalY: location.dy),
ui.PointerData(change: ui.PointerChange.up, kind: kind, physicalX: location.dx, physicalY: location.dy),
]
);

final List<PointerEvent> events = PointerEventConverter.expand(
packet.data, ui.window.devicePixelRatio).toList();

expect(events.length, 5);
expect(events[0].runtimeType, equals(PointerAddedEvent));
expect(events[0].buttons, equals(0));
expect(events[1].runtimeType, equals(PointerHoverEvent));
expect(events[1].buttons, equals(0));
expect(events[2].runtimeType, equals(PointerDownEvent));
expect(events[2].buttons, equals(kPrimaryButton));
expect(events[3].runtimeType, equals(PointerMoveEvent));
expect(events[3].buttons, equals(kPrimaryButton | kSecondaryStylusButton));
expect(events[4].runtimeType, equals(PointerUpEvent));
expect(events[4].buttons, equals(0));

PointerEventConverter.clearPointers();
}
});

test('Should not synthesise kPrimaryButton for certain devices', () {
final Offset location = const Offset(10.0, 10.0) * ui.window.devicePixelRatio;
for (PointerDeviceKind kind in <PointerDeviceKind>[
PointerDeviceKind.mouse,
]) {
final ui.PointerDataPacket packet = ui.PointerDataPacket(
data: <ui.PointerData>[
ui.PointerData(change: ui.PointerChange.add, kind: kind, physicalX: location.dx, physicalY: location.dy),
ui.PointerData(change: ui.PointerChange.hover, kind: kind, physicalX: location.dx, physicalY: location.dy),
ui.PointerData(change: ui.PointerChange.down, kind: kind, buttons: kMiddleMouseButton, physicalX: location.dx, physicalY: location.dy),
ui.PointerData(change: ui.PointerChange.move, kind: kind, buttons: kMiddleMouseButton | kSecondaryMouseButton, physicalX: location.dx, physicalY: location.dy),
ui.PointerData(change: ui.PointerChange.up, kind: kind, physicalX: location.dx, physicalY: location.dy),
]
);

final List<PointerEvent> events = PointerEventConverter.expand(
packet.data, ui.window.devicePixelRatio).toList();

expect(events.length, 5);
expect(events[0].runtimeType, equals(PointerAddedEvent));
expect(events[0].buttons, equals(0));
expect(events[1].runtimeType, equals(PointerHoverEvent));
expect(events[1].buttons, equals(0));
expect(events[2].runtimeType, equals(PointerDownEvent));
expect(events[2].buttons, equals(kMiddleMouseButton));
expect(events[3].runtimeType, equals(PointerMoveEvent));
expect(events[3].buttons, equals(kMiddleMouseButton | kSecondaryMouseButton));
expect(events[4].runtimeType, equals(PointerUpEvent));
expect(events[4].buttons, equals(0));

PointerEventConverter.clearPointers();
}
});
}

0 comments on commit 1ae32fa

Please sign in to comment.