mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Updates documentation and non-public API to use American spellings for consistency with the rest of the codebase. No changes to behaviour... other than how it's spelt.
386 lines
17 KiB
Dart
386 lines
17 KiB
Dart
// Copyright 2016 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import 'dart:ui' as ui;
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/gestures.dart';
|
|
|
|
import '../flutter_test_alternative.dart';
|
|
|
|
typedef HandleEventCallback = void Function(PointerEvent event);
|
|
|
|
class TestGestureFlutterBinding extends BindingBase with GestureBinding {
|
|
HandleEventCallback callback;
|
|
|
|
@override
|
|
void handleEvent(PointerEvent event, HitTestEntry entry) {
|
|
super.handleEvent(event, entry);
|
|
if (callback != null)
|
|
callback(event);
|
|
}
|
|
}
|
|
|
|
TestGestureFlutterBinding _binding = TestGestureFlutterBinding();
|
|
|
|
void ensureTestGestureBinding() {
|
|
_binding ??= TestGestureFlutterBinding();
|
|
PointerEventConverter.clearPointers();
|
|
assert(GestureBinding.instance != null);
|
|
}
|
|
|
|
void main() {
|
|
setUp(ensureTestGestureBinding);
|
|
|
|
test('Pointer tap events', () {
|
|
const ui.PointerDataPacket packet = ui.PointerDataPacket(
|
|
data: <ui.PointerData>[
|
|
ui.PointerData(change: ui.PointerChange.down),
|
|
ui.PointerData(change: ui.PointerChange.up),
|
|
]
|
|
);
|
|
|
|
final List<PointerEvent> events = <PointerEvent>[];
|
|
_binding.callback = events.add;
|
|
|
|
ui.window.onPointerDataPacket(packet);
|
|
expect(events.length, 2);
|
|
expect(events[0].runtimeType, equals(PointerDownEvent));
|
|
expect(events[1].runtimeType, equals(PointerUpEvent));
|
|
});
|
|
|
|
test('Pointer move events', () {
|
|
const ui.PointerDataPacket packet = ui.PointerDataPacket(
|
|
data: <ui.PointerData>[
|
|
ui.PointerData(change: ui.PointerChange.down),
|
|
ui.PointerData(change: ui.PointerChange.move),
|
|
ui.PointerData(change: ui.PointerChange.up),
|
|
]
|
|
);
|
|
|
|
final List<PointerEvent> events = <PointerEvent>[];
|
|
_binding.callback = events.add;
|
|
|
|
ui.window.onPointerDataPacket(packet);
|
|
expect(events.length, 3);
|
|
expect(events[0].runtimeType, equals(PointerDownEvent));
|
|
expect(events[1].runtimeType, equals(PointerMoveEvent));
|
|
expect(events[2].runtimeType, equals(PointerUpEvent));
|
|
});
|
|
|
|
test('Pointer hover events', () {
|
|
const ui.PointerDataPacket packet = ui.PointerDataPacket(
|
|
data: <ui.PointerData>[
|
|
ui.PointerData(change: ui.PointerChange.hover),
|
|
ui.PointerData(change: ui.PointerChange.hover),
|
|
ui.PointerData(change: ui.PointerChange.remove),
|
|
ui.PointerData(change: ui.PointerChange.hover),
|
|
]
|
|
);
|
|
|
|
final List<PointerEvent> pointerRouterEvents = <PointerEvent>[];
|
|
GestureBinding.instance.pointerRouter.addGlobalRoute(pointerRouterEvents.add);
|
|
|
|
final List<PointerEvent> events = <PointerEvent>[];
|
|
_binding.callback = events.add;
|
|
|
|
ui.window.onPointerDataPacket(packet);
|
|
expect(events.length, 0);
|
|
expect(pointerRouterEvents.length, 6,
|
|
reason: 'pointerRouterEvents contains: $pointerRouterEvents');
|
|
expect(pointerRouterEvents[0].runtimeType, equals(PointerAddedEvent));
|
|
expect(pointerRouterEvents[1].runtimeType, equals(PointerHoverEvent));
|
|
expect(pointerRouterEvents[2].runtimeType, equals(PointerHoverEvent));
|
|
expect(pointerRouterEvents[3].runtimeType, equals(PointerRemovedEvent));
|
|
expect(pointerRouterEvents[4].runtimeType, equals(PointerAddedEvent));
|
|
expect(pointerRouterEvents[5].runtimeType, equals(PointerHoverEvent));
|
|
});
|
|
|
|
test('Synthetic move events', () {
|
|
final ui.PointerDataPacket packet = ui.PointerDataPacket(
|
|
data: <ui.PointerData>[
|
|
ui.PointerData(
|
|
change: ui.PointerChange.down,
|
|
physicalX: 1.0 * ui.window.devicePixelRatio,
|
|
physicalY: 3.0 * ui.window.devicePixelRatio,
|
|
),
|
|
ui.PointerData(
|
|
change: ui.PointerChange.up,
|
|
physicalX: 10.0 * ui.window.devicePixelRatio,
|
|
physicalY: 15.0 * ui.window.devicePixelRatio,
|
|
),
|
|
]
|
|
);
|
|
|
|
final List<PointerEvent> events = <PointerEvent>[];
|
|
_binding.callback = events.add;
|
|
|
|
ui.window.onPointerDataPacket(packet);
|
|
expect(events.length, 3);
|
|
expect(events[0].runtimeType, equals(PointerDownEvent));
|
|
expect(events[1].runtimeType, equals(PointerMoveEvent));
|
|
expect(events[1].delta, equals(const Offset(9.0, 12.0)));
|
|
expect(events[2].runtimeType, equals(PointerUpEvent));
|
|
});
|
|
|
|
test('Pointer cancel events', () {
|
|
const ui.PointerDataPacket packet = ui.PointerDataPacket(
|
|
data: <ui.PointerData>[
|
|
ui.PointerData(change: ui.PointerChange.down),
|
|
ui.PointerData(change: ui.PointerChange.cancel),
|
|
]
|
|
);
|
|
|
|
final List<PointerEvent> events = <PointerEvent>[];
|
|
_binding.callback = events.add;
|
|
|
|
ui.window.onPointerDataPacket(packet);
|
|
expect(events.length, 2);
|
|
expect(events[0].runtimeType, equals(PointerDownEvent));
|
|
expect(events[1].runtimeType, equals(PointerCancelEvent));
|
|
});
|
|
|
|
test('Can cancel pointers', () {
|
|
const ui.PointerDataPacket packet = ui.PointerDataPacket(
|
|
data: <ui.PointerData>[
|
|
ui.PointerData(change: ui.PointerChange.down),
|
|
ui.PointerData(change: ui.PointerChange.up),
|
|
]
|
|
);
|
|
|
|
final List<PointerEvent> events = <PointerEvent>[];
|
|
_binding.callback = (PointerEvent event) {
|
|
events.add(event);
|
|
if (event is PointerDownEvent)
|
|
_binding.cancelPointer(event.pointer);
|
|
};
|
|
|
|
ui.window.onPointerDataPacket(packet);
|
|
expect(events.length, 2);
|
|
expect(events[0].runtimeType, equals(PointerDownEvent));
|
|
expect(events[1].runtimeType, equals(PointerCancelEvent));
|
|
});
|
|
|
|
test('Can expand add and hover pointers', () {
|
|
const ui.PointerDataPacket packet = ui.PointerDataPacket(
|
|
data: <ui.PointerData>[
|
|
ui.PointerData(change: ui.PointerChange.add, device: 24),
|
|
ui.PointerData(change: ui.PointerChange.hover, device: 24),
|
|
ui.PointerData(change: ui.PointerChange.remove, device: 24),
|
|
ui.PointerData(change: ui.PointerChange.hover, device: 24),
|
|
]
|
|
);
|
|
|
|
final List<PointerEvent> events = PointerEventConverter.expand(
|
|
packet.data, ui.window.devicePixelRatio).toList();
|
|
|
|
expect(events.length, 5);
|
|
expect(events[0].runtimeType, equals(PointerAddedEvent));
|
|
expect(events[1].runtimeType, equals(PointerHoverEvent));
|
|
expect(events[2].runtimeType, equals(PointerRemovedEvent));
|
|
expect(events[3].runtimeType, equals(PointerAddedEvent));
|
|
expect(events[4].runtimeType, equals(PointerHoverEvent));
|
|
});
|
|
|
|
test('Synthetic hover and cancel for misplaced down and remove', () {
|
|
final ui.PointerDataPacket packet = ui.PointerDataPacket(
|
|
data: <ui.PointerData>[
|
|
ui.PointerData(change: ui.PointerChange.add, device: 25, physicalX: 10.0 * ui.window.devicePixelRatio, physicalY: 10.0 * ui.window.devicePixelRatio),
|
|
ui.PointerData(change: ui.PointerChange.down, device: 25, physicalX: 15.0 * ui.window.devicePixelRatio, physicalY: 17.0 * ui.window.devicePixelRatio),
|
|
const ui.PointerData(change: ui.PointerChange.remove, device: 25),
|
|
]
|
|
);
|
|
|
|
final List<PointerEvent> events = PointerEventConverter.expand(
|
|
packet.data, ui.window.devicePixelRatio).toList();
|
|
|
|
expect(events.length, 6);
|
|
expect(events[0].runtimeType, equals(PointerAddedEvent));
|
|
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[3].runtimeType, equals(PointerCancelEvent));
|
|
expect(events[4].runtimeType, equals(PointerHoverEvent));
|
|
expect(events[5].runtimeType, equals(PointerRemovedEvent));
|
|
});
|
|
|
|
test('Can expand pointer scroll events', () {
|
|
const ui.PointerDataPacket packet = ui.PointerDataPacket(
|
|
data: <ui.PointerData>[
|
|
ui.PointerData(change: ui.PointerChange.add),
|
|
ui.PointerData(change: ui.PointerChange.hover, signalKind: ui.PointerSignalKind.scroll),
|
|
]
|
|
);
|
|
|
|
final List<PointerEvent> events = PointerEventConverter.expand(
|
|
packet.data, ui.window.devicePixelRatio).toList();
|
|
|
|
expect(events.length, 2);
|
|
expect(events[0].runtimeType, equals(PointerAddedEvent));
|
|
expect(events[1].runtimeType, equals(PointerScrollEvent));
|
|
});
|
|
|
|
test('Synthetic hover/move for misplaced scrolls', () {
|
|
final Offset lastLocation = const Offset(10.0, 10.0) * ui.window.devicePixelRatio;
|
|
const Offset unexpectedOffset = Offset(5.0, 7.0);
|
|
final Offset scrollLocation = lastLocation + unexpectedOffset * ui.window.devicePixelRatio;
|
|
final ui.PointerDataPacket packet = ui.PointerDataPacket(
|
|
data: <ui.PointerData>[
|
|
ui.PointerData(change: ui.PointerChange.add, physicalX: lastLocation.dx, physicalY: lastLocation.dy),
|
|
ui.PointerData(change: ui.PointerChange.hover, physicalX: scrollLocation.dx, physicalY: scrollLocation.dy, signalKind: ui.PointerSignalKind.scroll),
|
|
// Move back to starting location, click, and repeat to test mouse-down version.
|
|
ui.PointerData(change: ui.PointerChange.hover, physicalX: lastLocation.dx, physicalY: lastLocation.dy),
|
|
ui.PointerData(change: ui.PointerChange.down, physicalX: lastLocation.dx, physicalY: lastLocation.dy),
|
|
ui.PointerData(change: ui.PointerChange.hover, physicalX: scrollLocation.dx, physicalY: scrollLocation.dy, signalKind: ui.PointerSignalKind.scroll),
|
|
]
|
|
);
|
|
|
|
final List<PointerEvent> events = PointerEventConverter.expand(
|
|
packet.data, ui.window.devicePixelRatio).toList();
|
|
|
|
expect(events.length, 7);
|
|
expect(events[0].runtimeType, equals(PointerAddedEvent));
|
|
expect(events[1].runtimeType, equals(PointerHoverEvent));
|
|
expect(events[1].delta, equals(unexpectedOffset));
|
|
expect(events[2].runtimeType, equals(PointerScrollEvent));
|
|
expect(events[3].runtimeType, equals(PointerHoverEvent));
|
|
expect(events[4].runtimeType, equals(PointerDownEvent));
|
|
expect(events[5].runtimeType, equals(PointerMoveEvent));
|
|
expect(events[5].delta, equals(unexpectedOffset));
|
|
expect(events[6].runtimeType, equals(PointerScrollEvent));
|
|
});
|
|
|
|
test('Should synthesize 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 synthesize 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 synthesize kPrimaryButton for unknown devices', () {
|
|
final Offset location = const Offset(10.0, 10.0) * ui.window.devicePixelRatio;
|
|
const PointerDeviceKind kind = PointerDeviceKind.unknown;
|
|
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 not synthesize kPrimaryButton for mouse', () {
|
|
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();
|
|
}
|
|
});
|
|
}
|