Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 0c31b8e

Browse files
committed
[macOS] FlutterView should not override platform view cursor
1 parent 76a270f commit 0c31b8e

4 files changed

Lines changed: 23 additions & 0 deletions

File tree

shell/platform/darwin/macos/framework/Source/FlutterMutatorView.mm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ - (FlutterCursorCoordinator*)initWithFlutterView:(FlutterView*)flutterView {
4646
- (void)frameCleanup {
4747
_cleanupScheduled = NO;
4848
_mouseMoveHandled = NO;
49+
_flutterView.disableCursorUpdate = NO;
4950
}
5051

5152
- (BOOL)cleanupScheduled {
@@ -85,6 +86,9 @@ - (void)processMouseMoveEvent:(NSEvent*)event
8586
// cursor rect. Unfocused NSTextField uses legacy cursor rects for changing
8687
// its cursor.
8788
[platformView.window invalidateCursorRectsForView:platformView];
89+
// Prevent tracking area in FlutterViewController from updating the cursor.
90+
// This will be reset in [self frameCleanup].
91+
_flutterView.disableCursorUpdate = YES;
8892
_mouseMoveHandled = YES;
8993
}
9094
@end

shell/platform/darwin/macos/framework/Source/FlutterMutatorViewTest.mm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,7 @@ - (void)testCoordinatorEventOutsideFlutterContent {
655655
OCMStub([platformViewWindow invalidateCursorRectsForView:platformView]);
656656
OCMStub([platformView window]).andReturn(platformViewWindow);
657657
OCMStub([flutterView cursorUpdate:[OCMArg any]]);
658+
OCMStub([flutterView setDisableCursorUpdate:YES]);
658659
id mutatorView = OCMStrictClassMock([FlutterMutatorView class]);
659660
OCMStub([mutatorView platformView]).andReturn(platformView);
660661
CGPoint location = NSMakePoint(150, 150);
@@ -671,10 +672,13 @@ - (void)testCoordinatorEventOutsideFlutterContent {
671672
[coordinator processMouseMoveEvent:event
672673
forMutatorView:mutatorView
673674
overlayRegion:{CGRectMake(0, 0, 100, 100)}];
675+
// Prevent trackign area from FlutterView controller from updating the cursor.
676+
OCMVerify([flutterView setDisableCursorUpdate:YES]);
674677
}
675678
EXPECT_TRUE(coordinator.cleanupScheduled);
676679
[[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
677680
EXPECT_FALSE(coordinator.cleanupScheduled);
681+
OCMVerify([flutterView setDisableCursorUpdate:NO]);
678682

679683
// Check that invalidateCursorRectsForView is called again
680684
platformViewWindow = OCMClassMock([NSWindow class]);

shell/platform/darwin/macos/framework/Source/FlutterView.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,15 @@ constexpr FlutterViewId kFlutterImplicitViewId = 0ll;
6868
*/
6969
@property(readonly, nonatomic, nonnull) FlutterSurfaceManager* surfaceManager;
7070

71+
/**
72+
* Prevent FlutterView from updating the cursor inside [cursorUpdate:].
73+
* It is necessary to disable cursor update when cursor is over platform view
74+
* and the tracking area in FlutterViewController is created with
75+
* NSTrackingActiveAlways option. Otherwise the tracking area forces the cursor
76+
* update *after* the platform view has already updated the cursor.
77+
*/
78+
@property(readwrite, nonatomic) BOOL disableCursorUpdate;
79+
7180
/**
7281
* By default, the `FlutterSurfaceManager` creates two layers to manage Flutter
7382
* content, the content layer and containing layer. To set the native background

shell/platform/darwin/macos/framework/Source/FlutterView.mm

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ @interface FlutterView () <FlutterSurfaceManagerDelegate> {
2121

2222
@implementation FlutterView
2323

24+
@synthesize disableCursorUpdate;
25+
2426
- (instancetype)initWithMTLDevice:(id<MTLDevice>)device
2527
commandQueue:(id<MTLCommandQueue>)commandQueue
2628
delegate:(id<FlutterViewDelegate>)delegate
@@ -106,6 +108,10 @@ - (void)didUpdateMouseCursor:(NSCursor*)cursor {
106108
// - When context menu above FlutterView is closed. Context menu will change current cursor to arrow
107109
// and will not restore it back.
108110
- (void)cursorUpdate:(NSEvent*)event {
111+
if (disableCursorUpdate) {
112+
// Cursor is over a platform view, do not update cursor.
113+
return;
114+
}
109115
[_lastCursor set];
110116
// It is possible that there is a platform view with NSTrackingArea below flutter content.
111117
// This could override the mouse cursor as a result of mouse move event. There is no good way

0 commit comments

Comments
 (0)