diff --git a/packages/flutter/lib/src/gestures/events.dart b/packages/flutter/lib/src/gestures/events.dart index e75608e838..6f68aec528 100644 --- a/packages/flutter/lib/src/gestures/events.dart +++ b/packages/flutter/lib/src/gestures/events.dart @@ -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, ); } diff --git a/packages/flutter/lib/src/gestures/mouse_tracking.dart b/packages/flutter/lib/src/gestures/mouse_tracking.dart index 90a28b5b4d..b4701467d9 100644 --- a/packages/flutter/lib/src/gestures/mouse_tracking.dart +++ b/packages/flutter/lib/src/gestures/mouse_tracking.dart @@ -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); } diff --git a/packages/flutter/test/gestures/mouse_tracking_test.dart b/packages/flutter/test/gestures/mouse_tracking_test.dart index 3afe3355a9..294065283f 100644 --- a/packages/flutter/test/gestures/mouse_tracking_test.dart +++ b/packages/flutter/test/gestures/mouse_tracking_test.dart @@ -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( + 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( + 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'); + }); }); }