Commit 393521de authored by Dwayne Slater's avatar Dwayne Slater Committed by Greg Spencer

Allow PointerEnterEvent and PointerExitEvents to be created from any PointerEvent (#28602)

Avoids an implicit downcast + crash in MouseTracker, since the last
pointer event can be a Move or Down event, in addition to Hover.
parent 64a28e36
...@@ -518,30 +518,35 @@ class PointerEnterEvent extends PointerEvent { ...@@ -518,30 +518,35 @@ class PointerEnterEvent extends PointerEvent {
/// Creates an enter event from a [PointerHoverEvent]. /// Creates an enter event from a [PointerHoverEvent].
/// ///
/// This is used by the [MouseTracker] to synthesize enter events, since it /// Deprecated. Please use [PointerEnterEvent.fromMouseEvent] instead.
/// only actually receives hover events. @Deprecated('use PointerEnterEvent.fromMouseEvent instead')
PointerEnterEvent.fromHoverEvent(PointerHoverEvent hover) : super( PointerEnterEvent.fromHoverEvent(PointerHoverEvent event) : this.fromMouseEvent(event);
timeStamp: hover?.timeStamp,
kind: hover?.kind, /// Creates an enter event from a [PointerEvent].
device: hover?.device, ///
position: hover?.position, /// This is used by the [MouseTracker] to synthesize enter events.
delta: hover?.delta, PointerEnterEvent.fromMouseEvent(PointerEvent event) : super(
buttons: hover?.buttons, timeStamp: event?.timeStamp,
down: hover?.down, kind: event?.kind,
obscured: hover?.obscured, device: event?.device,
pressure: hover?.pressure, position: event?.position,
pressureMin: hover?.pressureMin, delta: event?.delta,
pressureMax: hover?.pressureMax, buttons: event?.buttons,
distance: hover?.distance, down: event?.down,
distanceMax: hover?.distanceMax, obscured: event?.obscured,
size: hover?.size, pressure: event?.pressure,
radiusMajor: hover?.radiusMajor, pressureMin: event?.pressureMin,
radiusMinor: hover?.radiusMinor, pressureMax: event?.pressureMax,
radiusMin: hover?.radiusMin, distance: event?.distance,
radiusMax: hover?.radiusMax, distanceMax: event?.distanceMax,
orientation: hover?.orientation, size: event?.size,
tilt: hover?.tilt, radiusMajor: event?.radiusMajor,
synthesized: hover?.synthesized, radiusMinor: event?.radiusMinor,
radiusMin: event?.radiusMin,
radiusMax: event?.radiusMax,
orientation: event?.orientation,
tilt: event?.tilt,
synthesized: event?.synthesized,
); );
} }
...@@ -606,30 +611,35 @@ class PointerExitEvent extends PointerEvent { ...@@ -606,30 +611,35 @@ class PointerExitEvent extends PointerEvent {
/// Creates an exit event from a [PointerHoverEvent]. /// Creates an exit event from a [PointerHoverEvent].
/// ///
/// This is used by the [MouseTracker] to synthesize exit events, since it /// Deprecated. Please use [PointerExitEvent.fromMouseEvent] instead.
/// only actually receives hover events. @Deprecated('use PointerExitEvent.fromMouseEvent instead')
PointerExitEvent.fromHoverEvent(PointerHoverEvent hover) : super( PointerExitEvent.fromHoverEvent(PointerHoverEvent event) : this.fromMouseEvent(event);
timeStamp: hover?.timeStamp,
kind: hover?.kind, /// Creates an exit event from a [PointerEvent].
device: hover?.device, ///
position: hover?.position, /// This is used by the [MouseTracker] to synthesize exit events.
delta: hover?.delta, PointerExitEvent.fromMouseEvent(PointerEvent event) : super(
buttons: hover?.buttons, timeStamp: event?.timeStamp,
down: hover?.down, kind: event?.kind,
obscured: hover?.obscured, device: event?.device,
pressure: hover?.pressure, position: event?.position,
pressureMin: hover?.pressureMin, delta: event?.delta,
pressureMax: hover?.pressureMax, buttons: event?.buttons,
distance: hover?.distance, down: event?.down,
distanceMax: hover?.distanceMax, obscured: event?.obscured,
size: hover?.size, pressure: event?.pressure,
radiusMajor: hover?.radiusMajor, pressureMin: event?.pressureMin,
radiusMinor: hover?.radiusMinor, pressureMax: event?.pressureMax,
radiusMin: hover?.radiusMin, distance: event?.distance,
radiusMax: hover?.radiusMax, distanceMax: event?.distanceMax,
orientation: hover?.orientation, size: event?.size,
tilt: hover?.tilt, radiusMajor: event?.radiusMajor,
synthesized: hover?.synthesized, radiusMinor: event?.radiusMinor,
radiusMin: event?.radiusMin,
radiusMax: event?.radiusMax,
orientation: event?.orientation,
tilt: event?.tilt,
synthesized: event?.synthesized,
); );
} }
......
...@@ -122,7 +122,7 @@ class MouseTracker { ...@@ -122,7 +122,7 @@ class MouseTracker {
final _TrackedAnnotation trackedAnnotation = _findAnnotation(annotation); final _TrackedAnnotation trackedAnnotation = _findAnnotation(annotation);
assert(trackedAnnotation != null, "Tried to detach an annotation that wasn't attached: $annotation"); assert(trackedAnnotation != null, "Tried to detach an annotation that wasn't attached: $annotation");
for (int deviceId in trackedAnnotation.activeDevices) { for (int deviceId in trackedAnnotation.activeDevices) {
annotation.onExit(PointerExitEvent.fromHoverEvent(_lastMouseEvent[deviceId])); annotation.onExit(PointerExitEvent.fromMouseEvent(_lastMouseEvent[deviceId]));
} }
_trackedAnnotations.remove(annotation); _trackedAnnotations.remove(annotation);
} }
...@@ -194,7 +194,7 @@ class MouseTracker { ...@@ -194,7 +194,7 @@ class MouseTracker {
void collectMousePositions() { void collectMousePositions() {
void exitAnnotation(_TrackedAnnotation trackedAnnotation, int deviceId) { void exitAnnotation(_TrackedAnnotation trackedAnnotation, int deviceId) {
if (trackedAnnotation.annotation?.onExit != null && trackedAnnotation.activeDevices.contains(deviceId)) { if (trackedAnnotation.annotation?.onExit != null && trackedAnnotation.activeDevices.contains(deviceId)) {
trackedAnnotation.annotation.onExit(PointerExitEvent.fromHoverEvent(_lastMouseEvent[deviceId])); trackedAnnotation.annotation.onExit(PointerExitEvent.fromMouseEvent(_lastMouseEvent[deviceId]));
trackedAnnotation.activeDevices.remove(deviceId); trackedAnnotation.activeDevices.remove(deviceId);
} }
} }
...@@ -236,10 +236,10 @@ class MouseTracker { ...@@ -236,10 +236,10 @@ class MouseTracker {
// event sent to it. // event sent to it.
hitAnnotation.activeDevices.add(deviceId); hitAnnotation.activeDevices.add(deviceId);
if (hitAnnotation.annotation?.onEnter != null) { if (hitAnnotation.annotation?.onEnter != null) {
hitAnnotation.annotation.onEnter(PointerEnterEvent.fromHoverEvent(lastEvent)); hitAnnotation.annotation.onEnter(PointerEnterEvent.fromMouseEvent(lastEvent));
} }
} }
if (hitAnnotation.annotation?.onHover != null) { if (hitAnnotation.annotation?.onHover != null && lastEvent is PointerHoverEvent) {
hitAnnotation.annotation.onHover(lastEvent); hitAnnotation.annotation.onHover(lastEvent);
} }
...@@ -251,7 +251,7 @@ class MouseTracker { ...@@ -251,7 +251,7 @@ class MouseTracker {
} }
if (trackedAnnotation.activeDevices.contains(deviceId)) { if (trackedAnnotation.activeDevices.contains(deviceId)) {
if (trackedAnnotation.annotation?.onExit != null) { if (trackedAnnotation.annotation?.onExit != null) {
trackedAnnotation.annotation.onExit(PointerExitEvent.fromHoverEvent(lastEvent)); trackedAnnotation.annotation.onExit(PointerExitEvent.fromMouseEvent(lastEvent));
} }
trackedAnnotation.activeDevices.remove(deviceId); trackedAnnotation.activeDevices.remove(deviceId);
} }
......
...@@ -256,5 +256,50 @@ void main() { ...@@ -256,5 +256,50 @@ void main() {
expect(exit.first.device, isNull); expect(exit.first.device, isNull);
expect(exit.first.runtimeType, equals(PointerExitEvent)); expect(exit.first.runtimeType, equals(PointerExitEvent));
}); });
test('handles mouse down and move', () {
final ui.PointerDataPacket packet1 = ui.PointerDataPacket(data: <ui.PointerData>[
ui.PointerData(
change: ui.PointerChange.hover,
physicalX: 0.0 * ui.window.devicePixelRatio,
physicalY: 0.0 * ui.window.devicePixelRatio,
kind: PointerDeviceKind.mouse,
),
ui.PointerData(
change: ui.PointerChange.hover,
physicalX: 1.0 * ui.window.devicePixelRatio,
physicalY: 101.0 * ui.window.devicePixelRatio,
kind: PointerDeviceKind.mouse,
),
]);
final ui.PointerDataPacket packet2 = ui.PointerDataPacket(data: <ui.PointerData>[
ui.PointerData(
change: ui.PointerChange.down,
physicalX: 1.0 * ui.window.devicePixelRatio,
physicalY: 101.0 * ui.window.devicePixelRatio,
kind: PointerDeviceKind.mouse,
),
ui.PointerData(
change: ui.PointerChange.move,
physicalX: 1.0 * ui.window.devicePixelRatio,
physicalY: 201.0 * ui.window.devicePixelRatio,
kind: PointerDeviceKind.mouse,
),
]);
isInHitRegion = true;
tracker.attachAnnotation(annotation);
ui.window.onPointerDataPacket(packet1);
tracker.collectMousePositions();
ui.window.onPointerDataPacket(packet2);
tracker.collectMousePositions();
expect(enter.length, equals(1), reason: 'enter contains $enter');
expect(enter.first.position, equals(const Offset(1.0, 101.0)));
expect(enter.first.device, equals(0));
expect(enter.first.runtimeType, equals(PointerEnterEvent));
expect(move.length, equals(1), reason: 'move contains $move');
expect(move.first.position, equals(const Offset(1.0, 101.0)));
expect(move.first.device, equals(0));
expect(move.first.runtimeType, equals(PointerHoverEvent));
expect(exit.length, equals(0), reason: 'exit contains $exit');
});
}); });
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment