From ace61f01efe3d4e53db1845627028d901e7af3e9 Mon Sep 17 00:00:00 2001 From: xubaolin Date: Fri, 30 Apr 2021 13:44:03 +0800 Subject: [PATCH] MouseRegion enter/exit event can be triggered with button pressed (#81148) --- .../flutter/lib/src/rendering/binding.dart | 8 ++++- .../test/widgets/mouse_region_test.dart | 36 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/packages/flutter/lib/src/rendering/binding.dart b/packages/flutter/lib/src/rendering/binding.dart index 690ca66948..03a9217110 100644 --- a/packages/flutter/lib/src/rendering/binding.dart +++ b/packages/flutter/lib/src/rendering/binding.dart @@ -282,7 +282,13 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture event is PointerAddedEvent || event is PointerRemovedEvent) { assert(event.position != null); - _mouseTracker!.updateWithEvent(event, () => hitTestResult ?? renderView.hitTestMouseTrackers(event.position)); + _mouseTracker!.updateWithEvent( + event, + // Mouse events(enter and exit) can be triggered with or without buttons pressed. + // If the button is pressed, we need to re-execute the hit test instead of + // reusing the cached results to trigger possible events. + () => (hitTestResult == null || event.down) ? renderView.hitTestMouseTrackers(event.position) : hitTestResult, + ); } super.dispatchEvent(event, hitTestResult); } diff --git a/packages/flutter/test/widgets/mouse_region_test.dart b/packages/flutter/test/widgets/mouse_region_test.dart index 71773d3449..af0fcf0db9 100644 --- a/packages/flutter/test/widgets/mouse_region_test.dart +++ b/packages/flutter/test/widgets/mouse_region_test.dart @@ -76,6 +76,42 @@ class _HoverFeedbackState extends State { } void main() { + testWidgets('onEnter and onExit can be triggered with mouse buttons pressed', (WidgetTester tester) async { + PointerEnterEvent? enter; + PointerExitEvent? exit; + await tester.pumpWidget(Center( + child: MouseRegion( + child: Container( + color: const Color.fromARGB(0xff, 0xff, 0x00, 0x00), + width: 100.0, + height: 100.0, + ), + onEnter: (PointerEnterEvent details) => enter = details, + onExit: (PointerExitEvent details) => exit = details, + ), + )); + + final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse, buttons: kPrimaryMouseButton); + await gesture.addPointer(location: Offset.zero); + await gesture.down(Offset.zero); // Press the mouse button. + addTearDown(gesture.removePointer); + await tester.pump(); + enter = null; + exit = null; + // Trigger the enter event. + await gesture.moveTo(const Offset(400.0, 300.0)); + expect(enter, isNotNull); + expect(enter!.position, equals(const Offset(400.0, 300.0))); + expect(enter!.localPosition, equals(const Offset(50.0, 50.0))); + expect(exit, isNull); + + // Trigger the exit event. + await gesture.moveTo(const Offset(1.0, 1.0)); + expect(exit, isNotNull); + expect(exit!.position, equals(const Offset(1.0, 1.0))); + expect(exit!.localPosition, equals(const Offset(-349.0, -249.0))); + }); + testWidgets('detects pointer enter', (WidgetTester tester) async { PointerEnterEvent? enter; PointerHoverEvent? move;