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.
This commit is contained in:
committed by
Greg Spencer
parent
64a28e3685
commit
393521defe
@@ -518,30 +518,35 @@ class PointerEnterEvent extends PointerEvent {
|
||||
|
||||
/// Creates an enter event from a [PointerHoverEvent].
|
||||
///
|
||||
/// This is used by the [MouseTracker] to synthesize enter events, since it
|
||||
/// only actually receives hover events.
|
||||
PointerEnterEvent.fromHoverEvent(PointerHoverEvent hover) : super(
|
||||
timeStamp: hover?.timeStamp,
|
||||
kind: hover?.kind,
|
||||
device: hover?.device,
|
||||
position: hover?.position,
|
||||
delta: hover?.delta,
|
||||
buttons: hover?.buttons,
|
||||
down: hover?.down,
|
||||
obscured: hover?.obscured,
|
||||
pressure: hover?.pressure,
|
||||
pressureMin: hover?.pressureMin,
|
||||
pressureMax: hover?.pressureMax,
|
||||
distance: hover?.distance,
|
||||
distanceMax: hover?.distanceMax,
|
||||
size: hover?.size,
|
||||
radiusMajor: hover?.radiusMajor,
|
||||
radiusMinor: hover?.radiusMinor,
|
||||
radiusMin: hover?.radiusMin,
|
||||
radiusMax: hover?.radiusMax,
|
||||
orientation: hover?.orientation,
|
||||
tilt: hover?.tilt,
|
||||
synthesized: hover?.synthesized,
|
||||
/// Deprecated. Please use [PointerEnterEvent.fromMouseEvent] instead.
|
||||
@Deprecated('use PointerEnterEvent.fromMouseEvent instead')
|
||||
PointerEnterEvent.fromHoverEvent(PointerHoverEvent event) : this.fromMouseEvent(event);
|
||||
|
||||
/// Creates an enter event from a [PointerEvent].
|
||||
///
|
||||
/// This is used by the [MouseTracker] to synthesize enter events.
|
||||
PointerEnterEvent.fromMouseEvent(PointerEvent event) : super(
|
||||
timeStamp: event?.timeStamp,
|
||||
kind: event?.kind,
|
||||
device: event?.device,
|
||||
position: event?.position,
|
||||
delta: event?.delta,
|
||||
buttons: event?.buttons,
|
||||
down: event?.down,
|
||||
obscured: event?.obscured,
|
||||
pressure: event?.pressure,
|
||||
pressureMin: event?.pressureMin,
|
||||
pressureMax: event?.pressureMax,
|
||||
distance: event?.distance,
|
||||
distanceMax: event?.distanceMax,
|
||||
size: event?.size,
|
||||
radiusMajor: event?.radiusMajor,
|
||||
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 {
|
||||
|
||||
/// Creates an exit event from a [PointerHoverEvent].
|
||||
///
|
||||
/// This is used by the [MouseTracker] to synthesize exit events, since it
|
||||
/// only actually receives hover events.
|
||||
PointerExitEvent.fromHoverEvent(PointerHoverEvent hover) : super(
|
||||
timeStamp: hover?.timeStamp,
|
||||
kind: hover?.kind,
|
||||
device: hover?.device,
|
||||
position: hover?.position,
|
||||
delta: hover?.delta,
|
||||
buttons: hover?.buttons,
|
||||
down: hover?.down,
|
||||
obscured: hover?.obscured,
|
||||
pressure: hover?.pressure,
|
||||
pressureMin: hover?.pressureMin,
|
||||
pressureMax: hover?.pressureMax,
|
||||
distance: hover?.distance,
|
||||
distanceMax: hover?.distanceMax,
|
||||
size: hover?.size,
|
||||
radiusMajor: hover?.radiusMajor,
|
||||
radiusMinor: hover?.radiusMinor,
|
||||
radiusMin: hover?.radiusMin,
|
||||
radiusMax: hover?.radiusMax,
|
||||
orientation: hover?.orientation,
|
||||
tilt: hover?.tilt,
|
||||
synthesized: hover?.synthesized,
|
||||
/// Deprecated. Please use [PointerExitEvent.fromMouseEvent] instead.
|
||||
@Deprecated('use PointerExitEvent.fromMouseEvent instead')
|
||||
PointerExitEvent.fromHoverEvent(PointerHoverEvent event) : this.fromMouseEvent(event);
|
||||
|
||||
/// Creates an exit event from a [PointerEvent].
|
||||
///
|
||||
/// This is used by the [MouseTracker] to synthesize exit events.
|
||||
PointerExitEvent.fromMouseEvent(PointerEvent event) : super(
|
||||
timeStamp: event?.timeStamp,
|
||||
kind: event?.kind,
|
||||
device: event?.device,
|
||||
position: event?.position,
|
||||
delta: event?.delta,
|
||||
buttons: event?.buttons,
|
||||
down: event?.down,
|
||||
obscured: event?.obscured,
|
||||
pressure: event?.pressure,
|
||||
pressureMin: event?.pressureMin,
|
||||
pressureMax: event?.pressureMax,
|
||||
distance: event?.distance,
|
||||
distanceMax: event?.distanceMax,
|
||||
size: event?.size,
|
||||
radiusMajor: event?.radiusMajor,
|
||||
radiusMinor: event?.radiusMinor,
|
||||
radiusMin: event?.radiusMin,
|
||||
radiusMax: event?.radiusMax,
|
||||
orientation: event?.orientation,
|
||||
tilt: event?.tilt,
|
||||
synthesized: event?.synthesized,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ class MouseTracker {
|
||||
final _TrackedAnnotation trackedAnnotation = _findAnnotation(annotation);
|
||||
assert(trackedAnnotation != null, "Tried to detach an annotation that wasn't attached: $annotation");
|
||||
for (int deviceId in trackedAnnotation.activeDevices) {
|
||||
annotation.onExit(PointerExitEvent.fromHoverEvent(_lastMouseEvent[deviceId]));
|
||||
annotation.onExit(PointerExitEvent.fromMouseEvent(_lastMouseEvent[deviceId]));
|
||||
}
|
||||
_trackedAnnotations.remove(annotation);
|
||||
}
|
||||
@@ -194,7 +194,7 @@ class MouseTracker {
|
||||
void collectMousePositions() {
|
||||
void exitAnnotation(_TrackedAnnotation trackedAnnotation, int 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);
|
||||
}
|
||||
}
|
||||
@@ -236,10 +236,10 @@ class MouseTracker {
|
||||
// event sent to it.
|
||||
hitAnnotation.activeDevices.add(deviceId);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -251,7 +251,7 @@ class MouseTracker {
|
||||
}
|
||||
if (trackedAnnotation.activeDevices.contains(deviceId)) {
|
||||
if (trackedAnnotation.annotation?.onExit != null) {
|
||||
trackedAnnotation.annotation.onExit(PointerExitEvent.fromHoverEvent(lastEvent));
|
||||
trackedAnnotation.annotation.onExit(PointerExitEvent.fromMouseEvent(lastEvent));
|
||||
}
|
||||
trackedAnnotation.activeDevices.remove(deviceId);
|
||||
}
|
||||
|
||||
@@ -256,5 +256,50 @@ void main() {
|
||||
expect(exit.first.device, isNull);
|
||||
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');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user