mirror of
https://github.com/encounter/engine.git
synced 2026-07-10 03:18:43 -07:00
Cherry-picks for 1.12.13 (#14100)
* 3e6d6bc add pointer data santizing in flutter web engine
This commit is contained in:
@@ -399,6 +399,7 @@ FILE: ../../../flutter/lib/web_ui/lib/src/engine/path_to_svg.dart
|
||||
FILE: ../../../flutter/lib/web_ui/lib/src/engine/platform_views.dart
|
||||
FILE: ../../../flutter/lib/web_ui/lib/src/engine/plugins.dart
|
||||
FILE: ../../../flutter/lib/web_ui/lib/src/engine/pointer_binding.dart
|
||||
FILE: ../../../flutter/lib/web_ui/lib/src/engine/pointer_converter.dart
|
||||
FILE: ../../../flutter/lib/web_ui/lib/src/engine/recording_canvas.dart
|
||||
FILE: ../../../flutter/lib/web_ui/lib/src/engine/render_vertices.dart
|
||||
FILE: ../../../flutter/lib/web_ui/lib/src/engine/rrect_renderer.dart
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Signature: 13a82078efea46e09944716f9ea1949f
|
||||
Signature: 4e55b5baef1fa7d7d9610d567650b3b6
|
||||
|
||||
UNUSED LICENSES:
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ part 'engine/path_to_svg.dart';
|
||||
part 'engine/platform_views.dart';
|
||||
part 'engine/plugins.dart';
|
||||
part 'engine/pointer_binding.dart';
|
||||
part 'engine/pointer_converter.dart';
|
||||
part 'engine/recording_canvas.dart';
|
||||
part 'engine/render_vertices.dart';
|
||||
part 'engine/rrect_renderer.dart';
|
||||
|
||||
@@ -15,23 +15,17 @@ class PointerBinding {
|
||||
static PointerBinding get instance => _instance;
|
||||
static PointerBinding _instance;
|
||||
|
||||
// Set of pointerIds that are added before routing hover and mouse wheel
|
||||
// events.
|
||||
//
|
||||
// The device needs to send a one time PointerChange.add before hover and
|
||||
// wheel events.
|
||||
Set<int> _activePointerIds = <int>{};
|
||||
|
||||
PointerBinding(this.domRenderer) {
|
||||
if (_instance == null) {
|
||||
_instance = this;
|
||||
_pointerDataConverter = PointerDataConverter();
|
||||
_detector = const PointerSupportDetector();
|
||||
_adapter = _createAdapter();
|
||||
}
|
||||
assert(() {
|
||||
registerHotRestartListener(() {
|
||||
_adapter?.clearListeners();
|
||||
_activePointerIds.clear();
|
||||
_pointerDataConverter?.clearPointerState();
|
||||
});
|
||||
return true;
|
||||
}());
|
||||
@@ -40,7 +34,7 @@ class PointerBinding {
|
||||
final DomRenderer domRenderer;
|
||||
PointerSupportDetector _detector;
|
||||
BaseAdapter _adapter;
|
||||
|
||||
PointerDataConverter _pointerDataConverter;
|
||||
/// Should be used in tests to define custom detection of pointer support.
|
||||
///
|
||||
/// ```dart
|
||||
@@ -62,22 +56,22 @@ class PointerBinding {
|
||||
newDetector ??= const PointerSupportDetector();
|
||||
// When changing the detector, we need to swap the adapter.
|
||||
if (newDetector != _detector) {
|
||||
_activePointerIds.clear();
|
||||
_detector = newDetector;
|
||||
_adapter?.clearListeners();
|
||||
_adapter = _createAdapter();
|
||||
_pointerDataConverter?.clearPointerState();
|
||||
}
|
||||
}
|
||||
|
||||
BaseAdapter _createAdapter() {
|
||||
if (_detector.hasPointerEvents) {
|
||||
return PointerAdapter(_onPointerData, domRenderer);
|
||||
return PointerAdapter(_onPointerData, domRenderer, _pointerDataConverter);
|
||||
}
|
||||
if (_detector.hasTouchEvents) {
|
||||
return TouchAdapter(_onPointerData, domRenderer);
|
||||
return TouchAdapter(_onPointerData, domRenderer, _pointerDataConverter);
|
||||
}
|
||||
if (_detector.hasMouseEvents) {
|
||||
return MouseAdapter(_onPointerData, domRenderer);
|
||||
return MouseAdapter(_onPointerData, domRenderer, _pointerDataConverter);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -123,11 +117,19 @@ class _PressedButton {
|
||||
|
||||
/// Common functionality that's shared among adapters.
|
||||
abstract class BaseAdapter {
|
||||
static final Map<String, html.EventListener> _listeners =
|
||||
<String, html.EventListener>{};
|
||||
BaseAdapter(this._callback, this.domRenderer, this._pointerDataConverter) {
|
||||
_setup();
|
||||
}
|
||||
|
||||
/// Listeners that are registered through dart to js api.
|
||||
static final Map<String, html.EventListener> _listeners =
|
||||
<String, html.EventListener>{};
|
||||
/// Listeners that are registered through native javascript api.
|
||||
static final Map<String, html.EventListener> _nativeListeners =
|
||||
<String, html.EventListener>{};
|
||||
final DomRenderer domRenderer;
|
||||
PointerDataCallback _callback;
|
||||
PointerDataConverter _pointerDataConverter;
|
||||
|
||||
// A set of the buttons that are currently being pressed.
|
||||
Set<_PressedButton> _pressedButtons = Set<_PressedButton>();
|
||||
@@ -144,10 +146,6 @@ abstract class BaseAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
BaseAdapter(this._callback, this.domRenderer) {
|
||||
_setup();
|
||||
}
|
||||
|
||||
/// Each subclass is expected to override this method to attach its own event
|
||||
/// listeners and convert events into pointer events.
|
||||
void _setup();
|
||||
@@ -156,9 +154,21 @@ abstract class BaseAdapter {
|
||||
void clearListeners() {
|
||||
final html.Element glassPane = domRenderer.glassPaneElement;
|
||||
_listeners.forEach((String eventName, html.EventListener listener) {
|
||||
glassPane.removeEventListener(eventName, listener, true);
|
||||
glassPane.removeEventListener(eventName, listener, true);
|
||||
});
|
||||
// For native listener, we will need to remove it through native javascript
|
||||
// api.
|
||||
_nativeListeners.forEach((String eventName, html.EventListener listener) {
|
||||
js_util.callMethod(
|
||||
domRenderer.glassPaneElement,
|
||||
'removeEventListener', <dynamic>[
|
||||
'wheel',
|
||||
listener,
|
||||
]
|
||||
);
|
||||
});
|
||||
_listeners.clear();
|
||||
_nativeListeners.clear();
|
||||
}
|
||||
|
||||
void _addEventListener(String eventName, html.EventListener handler) {
|
||||
@@ -177,6 +187,75 @@ abstract class BaseAdapter {
|
||||
domRenderer.glassPaneElement
|
||||
.addEventListener(eventName, loggedHandler, true);
|
||||
}
|
||||
|
||||
/// Converts a floating number timestamp (in milliseconds) to a [Duration] by
|
||||
/// splitting it into two integer components: milliseconds + microseconds.
|
||||
Duration _eventTimeStampToDuration(num milliseconds) {
|
||||
final int ms = milliseconds.toInt();
|
||||
final int micro =
|
||||
((milliseconds - ms) * Duration.microsecondsPerMillisecond).toInt();
|
||||
return Duration(milliseconds: ms, microseconds: micro);
|
||||
}
|
||||
|
||||
List<ui.PointerData> _convertWheelEventToPointerData(
|
||||
html.WheelEvent event,
|
||||
) {
|
||||
const int domDeltaPixel = 0x00;
|
||||
const int domDeltaLine = 0x01;
|
||||
const int domDeltaPage = 0x02;
|
||||
|
||||
// Flutter only supports pixel scroll delta. Convert deltaMode values
|
||||
// to pixels.
|
||||
double deltaX = event.deltaX;
|
||||
double deltaY = event.deltaY;
|
||||
switch (event.deltaMode) {
|
||||
case domDeltaLine:
|
||||
deltaX *= 32.0;
|
||||
deltaY *= 32.0;
|
||||
break;
|
||||
case domDeltaPage:
|
||||
deltaX *= ui.window.physicalSize.width;
|
||||
deltaY *= ui.window.physicalSize.height;
|
||||
break;
|
||||
case domDeltaPixel:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
final List<ui.PointerData> data = <ui.PointerData>[];
|
||||
_pointerDataConverter.convert(
|
||||
data,
|
||||
change: ui.PointerChange.hover,
|
||||
timeStamp: _eventTimeStampToDuration(event.timeStamp),
|
||||
kind: ui.PointerDeviceKind.mouse,
|
||||
signalKind: ui.PointerSignalKind.scroll,
|
||||
device: _mouseDeviceId,
|
||||
physicalX: event.client.x * ui.window.devicePixelRatio,
|
||||
physicalY: event.client.y * ui.window.devicePixelRatio,
|
||||
buttons: event.buttons,
|
||||
pressure: 1.0,
|
||||
pressureMin: 0.0,
|
||||
pressureMax: 1.0,
|
||||
scrollDeltaX: deltaX,
|
||||
scrollDeltaY: deltaY,
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
void _addWheelEventListener(html.EventListener handler) {
|
||||
final dynamic eventOptions = js_util.newObject();
|
||||
final html.EventListener jsHandler = js.allowInterop((html.Event event) => handler(event));
|
||||
_nativeListeners['wheel'] = jsHandler;
|
||||
js_util.setProperty(eventOptions, 'passive', false);
|
||||
js_util.callMethod(
|
||||
domRenderer.glassPaneElement,
|
||||
'addEventListener', <dynamic>[
|
||||
'wheel',
|
||||
jsHandler,
|
||||
eventOptions
|
||||
]
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const int _kPrimaryMouseButton = 0x1;
|
||||
@@ -207,16 +286,17 @@ int _deviceFromHtmlEvent(event) {
|
||||
|
||||
/// Adapter class to be used with browsers that support native pointer events.
|
||||
class PointerAdapter extends BaseAdapter {
|
||||
PointerAdapter(PointerDataCallback callback, DomRenderer domRenderer)
|
||||
: super(callback, domRenderer);
|
||||
PointerAdapter(
|
||||
PointerDataCallback callback,
|
||||
DomRenderer domRenderer,
|
||||
PointerDataConverter _pointerDataConverter
|
||||
) : super(callback, domRenderer, _pointerDataConverter);
|
||||
|
||||
@override
|
||||
void _setup() {
|
||||
_addEventListener('pointerdown', (html.Event event) {
|
||||
final int pointerButton = _pointerButtonFromHtmlEvent(event);
|
||||
final int device = _deviceFromHtmlEvent(event);
|
||||
// The pointerdown event will cause an 'add' event on the framework side.
|
||||
PointerBinding._instance._activePointerIds.add(device);
|
||||
if (_isButtonDown(device, pointerButton)) {
|
||||
// TODO(flutter_web): Remove this temporary fix for right click
|
||||
// on web platform once context guesture is implemented.
|
||||
@@ -239,13 +319,6 @@ class PointerAdapter extends BaseAdapter {
|
||||
? ui.PointerChange.move
|
||||
: ui.PointerChange.hover,
|
||||
pointerEvent);
|
||||
_ensureMouseDeviceAdded(
|
||||
data,
|
||||
pointerEvent.client.x,
|
||||
pointerEvent.client.y,
|
||||
pointerEvent.buttons,
|
||||
pointerEvent.timeStamp,
|
||||
pointerEvent.pointerId);
|
||||
_callback(data);
|
||||
});
|
||||
|
||||
@@ -270,7 +343,8 @@ class PointerAdapter extends BaseAdapter {
|
||||
_callback(_convertEventToPointerData(ui.PointerChange.cancel, event));
|
||||
});
|
||||
|
||||
_addWheelEventListener((html.WheelEvent event) {
|
||||
_addWheelEventListener((html.Event event) {
|
||||
assert(event is html.WheelEvent);
|
||||
if (_debugLogPointerEvents) {
|
||||
print(event.type);
|
||||
}
|
||||
@@ -289,7 +363,8 @@ class PointerAdapter extends BaseAdapter {
|
||||
final List<ui.PointerData> data = <ui.PointerData>[];
|
||||
for (int i = 0; i < allEvents.length; i++) {
|
||||
final html.PointerEvent event = allEvents[i];
|
||||
data.add(ui.PointerData(
|
||||
_pointerDataConverter.convert(
|
||||
data,
|
||||
change: change,
|
||||
timeStamp: _eventTimeStampToDuration(event.timeStamp),
|
||||
kind: _pointerTypeToDeviceKind(event.pointerType),
|
||||
@@ -301,7 +376,7 @@ class PointerAdapter extends BaseAdapter {
|
||||
pressureMin: 0.0,
|
||||
pressureMax: 1.0,
|
||||
tilt: _computeHighestTilt(event),
|
||||
));
|
||||
);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
@@ -343,8 +418,11 @@ class PointerAdapter extends BaseAdapter {
|
||||
|
||||
/// Adapter to be used with browsers that support touch events.
|
||||
class TouchAdapter extends BaseAdapter {
|
||||
TouchAdapter(PointerDataCallback callback, DomRenderer domRenderer)
|
||||
: super(callback, domRenderer);
|
||||
TouchAdapter(
|
||||
PointerDataCallback callback,
|
||||
DomRenderer domRenderer,
|
||||
PointerDataConverter _pointerDataConverter
|
||||
) : super(callback, domRenderer, _pointerDataConverter);
|
||||
|
||||
@override
|
||||
void _setup() {
|
||||
@@ -381,11 +459,12 @@ class TouchAdapter extends BaseAdapter {
|
||||
html.TouchEvent event,
|
||||
) {
|
||||
final html.TouchList touches = event.changedTouches;
|
||||
final List<ui.PointerData> data = List<ui.PointerData>(touches.length);
|
||||
final List<ui.PointerData> data = List<ui.PointerData>();
|
||||
final int len = touches.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
final html.Touch touch = touches[i];
|
||||
data[i] = ui.PointerData(
|
||||
_pointerDataConverter.convert(
|
||||
data,
|
||||
change: change,
|
||||
timeStamp: _eventTimeStampToDuration(event.timeStamp),
|
||||
kind: ui.PointerDeviceKind.touch,
|
||||
@@ -408,8 +487,11 @@ const int _mouseDeviceId = -1;
|
||||
|
||||
/// Adapter to be used with browsers that support mouse events.
|
||||
class MouseAdapter extends BaseAdapter {
|
||||
MouseAdapter(PointerDataCallback callback, DomRenderer domRenderer)
|
||||
: super(callback, domRenderer);
|
||||
MouseAdapter(
|
||||
PointerDataCallback callback,
|
||||
DomRenderer domRenderer,
|
||||
PointerDataConverter _pointerDataConverter
|
||||
) : super(callback, domRenderer, _pointerDataConverter);
|
||||
|
||||
@override
|
||||
void _setup() {
|
||||
@@ -442,7 +524,8 @@ class MouseAdapter extends BaseAdapter {
|
||||
_callback(_convertEventToPointerData(ui.PointerChange.up, event));
|
||||
});
|
||||
|
||||
_addWheelEventListener((html.WheelEvent event) {
|
||||
_addWheelEventListener((html.Event event) {
|
||||
assert(event is html.WheelEvent);
|
||||
if (_debugLogPointerEvents) {
|
||||
print(event.type);
|
||||
}
|
||||
@@ -455,16 +538,9 @@ class MouseAdapter extends BaseAdapter {
|
||||
ui.PointerChange change,
|
||||
html.MouseEvent event,
|
||||
) {
|
||||
final List<ui.PointerData> data = <ui.PointerData>[];
|
||||
// The mousedown event will cause an 'add' event on the framework side.
|
||||
if (event.type == 'mousedown') {
|
||||
PointerBinding._instance._activePointerIds.add(_mouseDeviceId);
|
||||
}
|
||||
if (event.type == 'mousemove') {
|
||||
_ensureMouseDeviceAdded(data, event.client.x, event.client.y,
|
||||
event.buttons, event.timeStamp, _mouseDeviceId);
|
||||
}
|
||||
data.add(ui.PointerData(
|
||||
List<ui.PointerData> data = <ui.PointerData>[];
|
||||
_pointerDataConverter.convert(
|
||||
data,
|
||||
change: change,
|
||||
timeStamp: _eventTimeStampToDuration(event.timeStamp),
|
||||
kind: ui.PointerDeviceKind.mouse,
|
||||
@@ -476,101 +552,7 @@ class MouseAdapter extends BaseAdapter {
|
||||
pressure: 1.0,
|
||||
pressureMin: 0.0,
|
||||
pressureMax: 1.0,
|
||||
));
|
||||
);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a floating number timestamp (in milliseconds) to a [Duration] by
|
||||
/// splitting it into two integer components: milliseconds + microseconds.
|
||||
Duration _eventTimeStampToDuration(num milliseconds) {
|
||||
final int ms = milliseconds.toInt();
|
||||
final int micro =
|
||||
((milliseconds - ms) * Duration.microsecondsPerMillisecond).toInt();
|
||||
return Duration(milliseconds: ms, microseconds: micro);
|
||||
}
|
||||
|
||||
void _ensureMouseDeviceAdded(List<ui.PointerData> data, double clientX,
|
||||
double clientY, int buttons, double timeStamp, int deviceId) {
|
||||
if (PointerBinding.instance._activePointerIds.contains(deviceId)) {
|
||||
return;
|
||||
}
|
||||
PointerBinding.instance._activePointerIds.add(deviceId);
|
||||
// Only send [PointerChange.add] the first time.
|
||||
data.insert(
|
||||
0,
|
||||
ui.PointerData(
|
||||
change: ui.PointerChange.add,
|
||||
timeStamp: _eventTimeStampToDuration(timeStamp),
|
||||
kind: ui.PointerDeviceKind.mouse,
|
||||
// In order for Flutter to actually add this pointer, we need to set the
|
||||
// signal to none.
|
||||
signalKind: ui.PointerSignalKind.none,
|
||||
device: deviceId,
|
||||
physicalX: clientX * ui.window.devicePixelRatio,
|
||||
physicalY: clientY * ui.window.devicePixelRatio,
|
||||
buttons: buttons,
|
||||
pressure: 1.0,
|
||||
pressureMin: 0.0,
|
||||
pressureMax: 1.0,
|
||||
scrollDeltaX: 0,
|
||||
scrollDeltaY: 0,
|
||||
));
|
||||
}
|
||||
|
||||
List<ui.PointerData> _convertWheelEventToPointerData(
|
||||
html.WheelEvent event,
|
||||
) {
|
||||
const int domDeltaPixel = 0x00;
|
||||
const int domDeltaLine = 0x01;
|
||||
const int domDeltaPage = 0x02;
|
||||
|
||||
// Flutter only supports pixel scroll delta. Convert deltaMode values
|
||||
// to pixels.
|
||||
double deltaX = event.deltaX;
|
||||
double deltaY = event.deltaY;
|
||||
switch (event.deltaMode) {
|
||||
case domDeltaLine:
|
||||
deltaX *= 32.0;
|
||||
deltaY *= 32.0;
|
||||
break;
|
||||
case domDeltaPage:
|
||||
deltaX *= ui.window.physicalSize.width;
|
||||
deltaY *= ui.window.physicalSize.height;
|
||||
break;
|
||||
case domDeltaPixel:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
final List<ui.PointerData> data = <ui.PointerData>[];
|
||||
_ensureMouseDeviceAdded(data, event.client.x, event.client.y, event.buttons,
|
||||
event.timeStamp, _mouseDeviceId);
|
||||
data.add(ui.PointerData(
|
||||
change: ui.PointerChange.hover,
|
||||
timeStamp: _eventTimeStampToDuration(event.timeStamp),
|
||||
kind: ui.PointerDeviceKind.mouse,
|
||||
signalKind: ui.PointerSignalKind.scroll,
|
||||
device: _mouseDeviceId,
|
||||
physicalX: event.client.x * ui.window.devicePixelRatio,
|
||||
physicalY: event.client.y * ui.window.devicePixelRatio,
|
||||
buttons: event.buttons,
|
||||
pressure: 1.0,
|
||||
pressureMin: 0.0,
|
||||
pressureMax: 1.0,
|
||||
scrollDeltaX: deltaX,
|
||||
scrollDeltaY: deltaY,
|
||||
));
|
||||
return data;
|
||||
}
|
||||
|
||||
void _addWheelEventListener(void listener(html.WheelEvent e)) {
|
||||
final dynamic eventOptions = js_util.newObject();
|
||||
js_util.setProperty(eventOptions, 'passive', false);
|
||||
js_util.callMethod(PointerBinding.instance.domRenderer.glassPaneElement,
|
||||
'addEventListener', <dynamic>[
|
||||
'wheel',
|
||||
js.allowInterop((html.WheelEvent event) => listener(event)),
|
||||
eventOptions
|
||||
]);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -56,7 +56,11 @@ void main() {
|
||||
}));
|
||||
|
||||
expect(packets, hasLength(3));
|
||||
expect(packets[0].data[0].change, equals(ui.PointerChange.down));
|
||||
// An add will be synthesized.
|
||||
expect(packets[0].data, hasLength(2));
|
||||
expect(packets[0].data[0].change, equals(ui.PointerChange.add));
|
||||
expect(packets[0].data[0].synthesized, equals(true));
|
||||
expect(packets[0].data[1].change, equals(ui.PointerChange.down));
|
||||
expect(packets[1].data[0].change, equals(ui.PointerChange.up));
|
||||
expect(packets[2].data[0].change, equals(ui.PointerChange.down));
|
||||
});
|
||||
@@ -78,10 +82,20 @@ void main() {
|
||||
}));
|
||||
|
||||
expect(packets, hasLength(2));
|
||||
expect(packets[0].data[0].change, equals(ui.PointerChange.down));
|
||||
// An add will be synthesized.
|
||||
expect(packets[0].data, hasLength(2));
|
||||
expect(packets[0].data[0].change, equals(ui.PointerChange.add));
|
||||
expect(packets[0].data[0].synthesized, equals(true));
|
||||
expect(packets[0].data[0].device, equals(1));
|
||||
expect(packets[1].data[0].change, equals(ui.PointerChange.down));
|
||||
expect(packets[0].data[1].change, equals(ui.PointerChange.down));
|
||||
expect(packets[0].data[1].device, equals(1));
|
||||
// An add will be synthesized.
|
||||
expect(packets[1].data, hasLength(2));
|
||||
expect(packets[1].data[0].change, equals(ui.PointerChange.add));
|
||||
expect(packets[1].data[0].synthesized, equals(true));
|
||||
expect(packets[1].data[0].device, equals(2));
|
||||
expect(packets[1].data[1].change, equals(ui.PointerChange.down));
|
||||
expect(packets[1].data[1].device, equals(2));
|
||||
});
|
||||
|
||||
test('creates an add event if the first pointer activity is a hover', () {
|
||||
@@ -99,10 +113,11 @@ void main() {
|
||||
expect(packets.single.data, hasLength(2));
|
||||
|
||||
expect(packets.single.data[0].change, equals(ui.PointerChange.add));
|
||||
expect(packets.single.data[0].synthesized, equals(true));
|
||||
expect(packets.single.data[1].change, equals(ui.PointerChange.hover));
|
||||
});
|
||||
|
||||
test('does not create an add event if got a pointerdown', () {
|
||||
test('does create an add event if got a pointerdown', () {
|
||||
List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
@@ -114,9 +129,247 @@ void main() {
|
||||
}));
|
||||
|
||||
expect(packets, hasLength(1));
|
||||
expect(packets.single.data, hasLength(1));
|
||||
expect(packets.single.data, hasLength(2));
|
||||
|
||||
expect(packets.single.data[0].change, equals(ui.PointerChange.down));
|
||||
expect(packets.single.data[0].change, equals(ui.PointerChange.add));
|
||||
expect(packets.single.data[1].change, equals(ui.PointerChange.down));
|
||||
});
|
||||
|
||||
test('does calculate delta and pointer identifier correctly', () {
|
||||
List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
glassPane.dispatchEvent(html.PointerEvent('pointermove', {
|
||||
'pointerId': 1,
|
||||
'button': 1,
|
||||
'clientX': 10.0,
|
||||
'clientY': 10.0,
|
||||
}));
|
||||
|
||||
glassPane.dispatchEvent(html.PointerEvent('pointermove', {
|
||||
'pointerId': 1,
|
||||
'button': 1,
|
||||
'clientX': 20.0,
|
||||
'clientY': 20.0,
|
||||
}));
|
||||
|
||||
glassPane.dispatchEvent(html.PointerEvent('pointerdown', {
|
||||
'pointerId': 1,
|
||||
'button': 1,
|
||||
'clientX': 20.0,
|
||||
'clientY': 20.0,
|
||||
}));
|
||||
|
||||
glassPane.dispatchEvent(html.PointerEvent('pointermove', {
|
||||
'pointerId': 1,
|
||||
'button': 1,
|
||||
'clientX': 40.0,
|
||||
'clientY': 30.0,
|
||||
}));
|
||||
|
||||
glassPane.dispatchEvent(html.PointerEvent('pointerup', {
|
||||
'pointerId': 1,
|
||||
'button': 1,
|
||||
'clientX': 40.0,
|
||||
'clientY': 30.0,
|
||||
}));
|
||||
|
||||
glassPane.dispatchEvent(html.PointerEvent('pointermove', {
|
||||
'pointerId': 1,
|
||||
'button': 1,
|
||||
'clientX': 20.0,
|
||||
'clientY': 10.0,
|
||||
}));
|
||||
|
||||
glassPane.dispatchEvent(html.PointerEvent('pointerdown', {
|
||||
'pointerId': 1,
|
||||
'button': 1,
|
||||
'clientX': 20.0,
|
||||
'clientY': 10.0,
|
||||
}));
|
||||
|
||||
expect(packets, hasLength(7));
|
||||
|
||||
expect(packets[0].data, hasLength(2));
|
||||
expect(packets[0].data[0].change, equals(ui.PointerChange.add));
|
||||
expect(packets[0].data[0].pointerIdentifier, equals(0));
|
||||
expect(packets[0].data[0].synthesized, equals(true));
|
||||
expect(packets[0].data[0].physicalX, equals(10.0));
|
||||
expect(packets[0].data[0].physicalY, equals(10.0));
|
||||
expect(packets[0].data[0].physicalDeltaX, equals(0.0));
|
||||
expect(packets[0].data[0].physicalDeltaY, equals(0.0));
|
||||
|
||||
expect(packets[0].data[1].change, equals(ui.PointerChange.hover));
|
||||
expect(packets[0].data[1].pointerIdentifier, equals(0));
|
||||
expect(packets[0].data[1].synthesized, equals(false));
|
||||
expect(packets[0].data[1].physicalX, equals(10.0));
|
||||
expect(packets[0].data[1].physicalY, equals(10.0));
|
||||
expect(packets[0].data[1].physicalDeltaX, equals(0.0));
|
||||
expect(packets[0].data[1].physicalDeltaY, equals(0.0));
|
||||
|
||||
expect(packets[1].data, hasLength(1));
|
||||
expect(packets[1].data[0].change, equals(ui.PointerChange.hover));
|
||||
expect(packets[1].data[0].pointerIdentifier, equals(0));
|
||||
expect(packets[1].data[0].synthesized, equals(false));
|
||||
expect(packets[1].data[0].physicalX, equals(20.0));
|
||||
expect(packets[1].data[0].physicalY, equals(20.0));
|
||||
expect(packets[1].data[0].physicalDeltaX, equals(10.0));
|
||||
expect(packets[1].data[0].physicalDeltaY, equals(10.0));
|
||||
|
||||
expect(packets[2].data, hasLength(1));
|
||||
expect(packets[2].data[0].change, equals(ui.PointerChange.down));
|
||||
expect(packets[2].data[0].pointerIdentifier, equals(1));
|
||||
expect(packets[2].data[0].synthesized, equals(false));
|
||||
expect(packets[2].data[0].physicalX, equals(20.0));
|
||||
expect(packets[2].data[0].physicalY, equals(20.0));
|
||||
expect(packets[2].data[0].physicalDeltaX, equals(0.0));
|
||||
expect(packets[2].data[0].physicalDeltaY, equals(0.0));
|
||||
|
||||
expect(packets[3].data, hasLength(1));
|
||||
expect(packets[3].data[0].change, equals(ui.PointerChange.move));
|
||||
expect(packets[3].data[0].pointerIdentifier, equals(1));
|
||||
expect(packets[3].data[0].synthesized, equals(false));
|
||||
expect(packets[3].data[0].physicalX, equals(40.0));
|
||||
expect(packets[3].data[0].physicalY, equals(30.0));
|
||||
expect(packets[3].data[0].physicalDeltaX, equals(20.0));
|
||||
expect(packets[3].data[0].physicalDeltaY, equals(10.0));
|
||||
|
||||
expect(packets[4].data, hasLength(1));
|
||||
expect(packets[4].data[0].change, equals(ui.PointerChange.up));
|
||||
expect(packets[4].data[0].pointerIdentifier, equals(1));
|
||||
expect(packets[4].data[0].synthesized, equals(false));
|
||||
expect(packets[4].data[0].physicalX, equals(40.0));
|
||||
expect(packets[4].data[0].physicalY, equals(30.0));
|
||||
expect(packets[4].data[0].physicalDeltaX, equals(0.0));
|
||||
expect(packets[4].data[0].physicalDeltaY, equals(0.0));
|
||||
|
||||
expect(packets[5].data, hasLength(1));
|
||||
expect(packets[5].data[0].change, equals(ui.PointerChange.hover));
|
||||
expect(packets[5].data[0].pointerIdentifier, equals(1));
|
||||
expect(packets[5].data[0].synthesized, equals(false));
|
||||
expect(packets[5].data[0].physicalX, equals(20.0));
|
||||
expect(packets[5].data[0].physicalY, equals(10.0));
|
||||
expect(packets[5].data[0].physicalDeltaX, equals(-20.0));
|
||||
expect(packets[5].data[0].physicalDeltaY, equals(-20.0));
|
||||
|
||||
expect(packets[6].data, hasLength(1));
|
||||
expect(packets[6].data[0].change, equals(ui.PointerChange.down));
|
||||
expect(packets[6].data[0].pointerIdentifier, equals(2));
|
||||
expect(packets[6].data[0].synthesized, equals(false));
|
||||
expect(packets[6].data[0].physicalX, equals(20.0));
|
||||
expect(packets[6].data[0].physicalY, equals(10.0));
|
||||
expect(packets[6].data[0].physicalDeltaX, equals(0.0));
|
||||
expect(packets[6].data[0].physicalDeltaY, equals(0.0));
|
||||
});
|
||||
|
||||
test('does synthesize add or hover or more for scroll', () {
|
||||
List<ui.PointerDataPacket> packets = <ui.PointerDataPacket>[];
|
||||
ui.window.onPointerDataPacket = (ui.PointerDataPacket packet) {
|
||||
packets.add(packet);
|
||||
};
|
||||
|
||||
glassPane.dispatchEvent(html.WheelEvent('wheel',
|
||||
button: 1,
|
||||
clientX: 10,
|
||||
clientY: 10,
|
||||
deltaX: 10,
|
||||
deltaY: 10,
|
||||
));
|
||||
|
||||
glassPane.dispatchEvent(html.WheelEvent('wheel',
|
||||
button: 1,
|
||||
clientX: 20,
|
||||
clientY: 50,
|
||||
deltaX: 10,
|
||||
deltaY: 10,
|
||||
));
|
||||
|
||||
glassPane.dispatchEvent(html.PointerEvent('pointerdown', {
|
||||
'pointerId': -1,
|
||||
'button': 1,
|
||||
'clientX': 20.0,
|
||||
'clientY': 50.0,
|
||||
}));
|
||||
|
||||
glassPane.dispatchEvent(html.WheelEvent('wheel',
|
||||
button: 1,
|
||||
clientX: 30,
|
||||
clientY: 60,
|
||||
deltaX: 10,
|
||||
deltaY: 10,
|
||||
));
|
||||
|
||||
expect(packets, hasLength(4));
|
||||
|
||||
// An add will be synthesized.
|
||||
expect(packets[0].data, hasLength(2));
|
||||
expect(packets[0].data[0].change, equals(ui.PointerChange.add));
|
||||
expect(packets[0].data[0].pointerIdentifier, equals(0));
|
||||
expect(packets[0].data[0].synthesized, equals(true));
|
||||
expect(packets[0].data[0].physicalX, equals(10.0));
|
||||
expect(packets[0].data[0].physicalY, equals(10.0));
|
||||
expect(packets[0].data[0].physicalDeltaX, equals(0.0));
|
||||
expect(packets[0].data[0].physicalDeltaY, equals(0.0));
|
||||
|
||||
expect(packets[0].data[1].change, equals(ui.PointerChange.hover));
|
||||
expect(packets[0].data[1].signalKind, equals(ui.PointerSignalKind.scroll));
|
||||
expect(packets[0].data[1].pointerIdentifier, equals(0));
|
||||
expect(packets[0].data[1].synthesized, equals(false));
|
||||
expect(packets[0].data[1].physicalX, equals(10.0));
|
||||
expect(packets[0].data[1].physicalY, equals(10.0));
|
||||
expect(packets[0].data[1].physicalDeltaX, equals(0.0));
|
||||
expect(packets[0].data[1].physicalDeltaY, equals(0.0));
|
||||
|
||||
// A hover will be synthesized.
|
||||
expect(packets[1].data, hasLength(2));
|
||||
expect(packets[1].data[0].change, equals(ui.PointerChange.hover));
|
||||
expect(packets[1].data[0].pointerIdentifier, equals(0));
|
||||
expect(packets[1].data[0].synthesized, equals(true));
|
||||
expect(packets[1].data[0].physicalX, equals(20.0));
|
||||
expect(packets[1].data[0].physicalY, equals(50.0));
|
||||
expect(packets[1].data[0].physicalDeltaX, equals(10.0));
|
||||
expect(packets[1].data[0].physicalDeltaY, equals(40.0));
|
||||
|
||||
expect(packets[1].data[1].change, equals(ui.PointerChange.hover));
|
||||
expect(packets[1].data[1].signalKind, equals(ui.PointerSignalKind.scroll));
|
||||
expect(packets[1].data[1].pointerIdentifier, equals(0));
|
||||
expect(packets[1].data[1].synthesized, equals(false));
|
||||
expect(packets[1].data[1].physicalX, equals(20.0));
|
||||
expect(packets[1].data[1].physicalY, equals(50.0));
|
||||
expect(packets[1].data[1].physicalDeltaX, equals(0.0));
|
||||
expect(packets[1].data[1].physicalDeltaY, equals(0.0));
|
||||
|
||||
// No synthetic pointer data for down event.
|
||||
expect(packets[2].data, hasLength(1));
|
||||
expect(packets[2].data[0].change, equals(ui.PointerChange.down));
|
||||
expect(packets[2].data[0].signalKind, equals(null));
|
||||
expect(packets[2].data[0].pointerIdentifier, equals(1));
|
||||
expect(packets[2].data[0].synthesized, equals(false));
|
||||
expect(packets[2].data[0].physicalX, equals(20.0));
|
||||
expect(packets[2].data[0].physicalY, equals(50.0));
|
||||
expect(packets[2].data[0].physicalDeltaX, equals(0.0));
|
||||
expect(packets[2].data[0].physicalDeltaY, equals(0.0));
|
||||
|
||||
// A move will be synthesized instead of hover because the button is currently down.
|
||||
expect(packets[3].data, hasLength(2));
|
||||
expect(packets[3].data[0].change, equals(ui.PointerChange.move));
|
||||
expect(packets[3].data[0].pointerIdentifier, equals(1));
|
||||
expect(packets[3].data[0].synthesized, equals(true));
|
||||
expect(packets[3].data[0].physicalX, equals(30.0));
|
||||
expect(packets[3].data[0].physicalY, equals(60.0));
|
||||
expect(packets[3].data[0].physicalDeltaX, equals(10.0));
|
||||
expect(packets[3].data[0].physicalDeltaY, equals(10.0));
|
||||
|
||||
expect(packets[3].data[1].change, equals(ui.PointerChange.hover));
|
||||
expect(packets[3].data[1].signalKind, equals(ui.PointerSignalKind.scroll));
|
||||
expect(packets[3].data[1].pointerIdentifier, equals(1));
|
||||
expect(packets[3].data[1].synthesized, equals(false));
|
||||
expect(packets[3].data[1].physicalX, equals(30.0));
|
||||
expect(packets[3].data[1].physicalY, equals(60.0));
|
||||
expect(packets[3].data[1].physicalDeltaX, equals(0.0));
|
||||
expect(packets[3].data[1].physicalDeltaY, equals(0.0));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user