diff --git a/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm b/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm index 291340b3764ac..9928fb03c4070 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm @@ -129,7 +129,6 @@ void Reset() { flutter_state_is_down = false; has_pending_exit = false; buttons = 0; - GestureReset(); } }; diff --git a/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm b/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm index aa0a729b8983c..1d630e03001ac 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm @@ -101,6 +101,7 @@ - (bool)testKeyEquivalentIsPassedToTextInputPlugin:(id)mockEngine; - (bool)testFlagsChangedEventsArePropagatedIfNotHandled:(id)mockEngine; - (bool)testKeyboardIsRestartedOnEngineRestart:(id)mockEngine; - (bool)testTrackpadGesturesAreSentToFramework:(id)mockEngine; +- (bool)mouseAndGestureEventsAreHandledSeparately:(id)engineMock; - (bool)testMouseDownUpEventsSentToNextResponder:(id)mockEngine; - (bool)testModifierKeysAreSynthesizedOnMouseMove:(id)mockEngine; - (bool)testViewWillAppearCalledMultipleTimes:(id)mockEngine; @@ -287,6 +288,12 @@ id MockGestureEvent(NSEventType type, NSEventPhase phase, double magnification, [[FlutterViewControllerTestObjC alloc] testTrackpadGesturesAreSentToFramework:mockEngine]); } +TEST_F(FlutterViewControllerMockEngineTest, TestmouseAndGestureEventsAreHandledSeparately) { + id mockEngine = GetMockEngine(); + ASSERT_TRUE( + [[FlutterViewControllerTestObjC alloc] mouseAndGestureEventsAreHandledSeparately:mockEngine]); +} + TEST_F(FlutterViewControllerMockEngineTest, TestMouseDownUpEventsSentToNextResponder) { id mockEngine = GetMockEngine(); ASSERT_TRUE( @@ -1004,6 +1011,42 @@ - (bool)testTrackpadGesturesAreSentToFramework:(id)engineMock { return true; } +// Magic mouse can interleave mouse events with scroll events. This must not crash. +- (bool)mouseAndGestureEventsAreHandledSeparately:(id)engineMock { + FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock + nibName:@"" + bundle:nil]; + [viewController loadView]; + + // Test for pan events. + // Start gesture. + CGEventRef cgEventStart = CGEventCreateScrollWheelEvent(NULL, kCGScrollEventUnitPixel, 1, 0); + CGEventSetType(cgEventStart, kCGEventScrollWheel); + CGEventSetIntegerValueField(cgEventStart, kCGScrollWheelEventScrollPhase, kCGScrollPhaseBegan); + CGEventSetIntegerValueField(cgEventStart, kCGScrollWheelEventIsContinuous, 1); + [viewController scrollWheel:[NSEvent eventWithCGEvent:cgEventStart]]; + CFRelease(cgEventStart); + + CGEventRef cgEventUpdate = CGEventCreateCopy(cgEventStart); + CGEventSetIntegerValueField(cgEventUpdate, kCGScrollWheelEventScrollPhase, kCGScrollPhaseChanged); + CGEventSetIntegerValueField(cgEventUpdate, kCGScrollWheelEventDeltaAxis2, 1); // pan_x + CGEventSetIntegerValueField(cgEventUpdate, kCGScrollWheelEventDeltaAxis1, 2); // pan_y + [viewController scrollWheel:[NSEvent eventWithCGEvent:cgEventUpdate]]; + CFRelease(cgEventUpdate); + + NSEvent* mouseEvent = flutter::testing::CreateMouseEvent(0x00); + [viewController mouseEntered:mouseEvent]; + [viewController mouseExited:mouseEvent]; + + // End gesture. + CGEventRef cgEventEnd = CGEventCreateCopy(cgEventStart); + CGEventSetIntegerValueField(cgEventEnd, kCGScrollWheelEventScrollPhase, kCGScrollPhaseEnded); + [viewController scrollWheel:[NSEvent eventWithCGEvent:cgEventEnd]]; + CFRelease(cgEventEnd); + + return true; +} + - (bool)testViewWillAppearCalledMultipleTimes:(id)engineMock { FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock nibName:@""