From 7e9a78c8209d86b26e264434063f6d7eea6713e0 Mon Sep 17 00:00:00 2001 From: Matej Knopp Date: Wed, 17 Apr 2024 19:42:17 +0200 Subject: [PATCH 1/3] [macOS] Handle inteleaved movement and scroll events --- .../framework/Source/FlutterViewController.mm | 1 - .../Source/FlutterViewControllerTest.mm | 40 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) 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..550ab2bf69636 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,39 @@ - (bool)testTrackpadGesturesAreSentToFramework:(id)engineMock { return true; } +- (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]]; + + 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]]; + + // Magic mouse can interleave mouse events with scroll events. + 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]]; + + return true; +} + - (bool)testViewWillAppearCalledMultipleTimes:(id)engineMock { FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock nibName:@"" From 37a8ca9aa0c74633d0eb7964f70ebcd56af064c8 Mon Sep 17 00:00:00 2001 From: Matej Knopp Date: Wed, 17 Apr 2024 20:27:38 +0200 Subject: [PATCH 2/3] Missing CFRelease --- .../darwin/macos/framework/Source/FlutterViewControllerTest.mm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm b/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm index 550ab2bf69636..b605a011dc6d6 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm @@ -1024,12 +1024,14 @@ - (bool)mouseAndGestureEventsAreHandledSeparately:(id)engineMock { 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); // Magic mouse can interleave mouse events with scroll events. NSEvent* mouseEvent = flutter::testing::CreateMouseEvent(0x00); @@ -1040,6 +1042,7 @@ - (bool)mouseAndGestureEventsAreHandledSeparately:(id)engineMock { CGEventRef cgEventEnd = CGEventCreateCopy(cgEventStart); CGEventSetIntegerValueField(cgEventEnd, kCGScrollWheelEventScrollPhase, kCGScrollPhaseEnded); [viewController scrollWheel:[NSEvent eventWithCGEvent:cgEventEnd]]; + CFRelease(cgEventEnd); return true; } From 3d10a418e8bb58aad83e2413ced58721c4f26b6f Mon Sep 17 00:00:00 2001 From: Matej Knopp Date: Wed, 17 Apr 2024 20:30:06 +0200 Subject: [PATCH 3/3] Move comment --- .../darwin/macos/framework/Source/FlutterViewControllerTest.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm b/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm index b605a011dc6d6..1d630e03001ac 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm @@ -1011,6 +1011,7 @@ - (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:@"" @@ -1033,7 +1034,6 @@ - (bool)mouseAndGestureEventsAreHandledSeparately:(id)engineMock { [viewController scrollWheel:[NSEvent eventWithCGEvent:cgEventUpdate]]; CFRelease(cgEventUpdate); - // Magic mouse can interleave mouse events with scroll events. NSEvent* mouseEvent = flutter::testing::CreateMouseEvent(0x00); [viewController mouseEntered:mouseEvent]; [viewController mouseExited:mouseEvent];