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

Commit b7d5129

Browse files
authored
[macos] Add hover support to FLEViewController (#7975)
Adds an option to enable mouse tracking, which will send add/hover/remove events to the Flutter engine.
1 parent a82c7ee commit b7d5129

File tree

2 files changed

+86
-1
lines changed

2 files changed

+86
-1
lines changed

shell/platform/darwin/macos/framework/Headers/FLEViewController.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,17 @@
1616
#import "FlutterMacros.h"
1717
#endif
1818

19+
typedef NS_ENUM(NSInteger, FlutterMouseTrackingMode) {
20+
// Hover events will never be sent to Flutter.
21+
FlutterMouseTrackingModeNone = 0,
22+
// Hover events will be sent to Flutter when the view is in the key window.
23+
FlutterMouseTrackingModeInKeyWindow,
24+
// Hover events will be sent to Flutter when the view is in the active app.
25+
FlutterMouseTrackingModeInActiveApp,
26+
// Hover events will be sent to Flutter regardless of window and app focus.
27+
FlutterMouseTrackingModeAlways,
28+
};
29+
1930
/**
2031
* Controls embedder plugins and communication with the underlying Flutter engine, managing a view
2132
* intended to handle key inputs and drawing protocols (see |view|).
@@ -33,6 +44,12 @@ FLUTTER_EXPORT
3344
*/
3445
@property(nullable) NSView<FLEOpenGLContextHandling>* view;
3546

47+
/**
48+
* The style of mouse tracking to use for the view. Defaults to
49+
* FlutterMouseTrackingModeNone.
50+
*/
51+
@property(nonatomic) FlutterMouseTrackingMode mouseTrackingMode;
52+
3653
/**
3754
* Launches the Flutter engine with the provided configuration.
3855
*

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

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,18 @@ @interface FLEViewController ()
3232
/**
3333
* A list of additional responders to keyboard events. Keybord events are forwarded to all of them.
3434
*/
35-
@property NSMutableOrderedSet<NSResponder*>* additionalKeyResponders;
35+
@property(nonatomic) NSMutableOrderedSet<NSResponder*>* additionalKeyResponders;
36+
37+
/**
38+
* The tracking area used to generate hover events, if enabled.
39+
*/
40+
@property(nonatomic) NSTrackingArea* trackingArea;
41+
42+
/**
43+
* Updates |trackingArea| for the current tracking settings, creating it with
44+
* the correct mode if tracking is enabled, or removing it if not.
45+
*/
46+
- (void)configureTrackingArea;
3647

3748
/**
3849
* Creates and registers plugins used by this view controller.
@@ -202,12 +213,28 @@ - (void)dealloc {
202213
}
203214
}
204215

216+
- (void)setView:(NSView*)view {
217+
if (_trackingArea) {
218+
[self.view removeTrackingArea:_trackingArea];
219+
}
220+
[super setView:view];
221+
[self configureTrackingArea];
222+
}
223+
205224
- (void)loadView {
206225
self.view = [[FLEView alloc] init];
207226
}
208227

209228
#pragma mark - Public methods
210229

230+
- (void)setMouseTrackingMode:(FlutterMouseTrackingMode)mode {
231+
if (_mouseTrackingMode == mode) {
232+
return;
233+
}
234+
_mouseTrackingMode = mode;
235+
[self configureTrackingArea];
236+
}
237+
211238
- (BOOL)launchEngineWithAssetsPath:(NSURL*)assets
212239
commandLineArguments:(NSArray<NSString*>*)arguments {
213240
return [self launchEngineInternalWithAssetsPath:assets
@@ -241,6 +268,35 @@ - (void)removeKeyResponder:(NSResponder*)responder {
241268

242269
#pragma mark - Private methods
243270

271+
- (void)configureTrackingArea {
272+
if (_mouseTrackingMode != FlutterMouseTrackingModeNone && self.view) {
273+
NSTrackingAreaOptions options =
274+
NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingInVisibleRect;
275+
switch (_mouseTrackingMode) {
276+
case FlutterMouseTrackingModeInKeyWindow:
277+
options |= NSTrackingActiveInKeyWindow;
278+
break;
279+
case FlutterMouseTrackingModeInActiveApp:
280+
options |= NSTrackingActiveInActiveApp;
281+
break;
282+
case FlutterMouseTrackingModeAlways:
283+
options |= NSTrackingActiveAlways;
284+
break;
285+
default:
286+
NSLog(@"Error: Unrecognized mouse tracking mode: %ld", _mouseTrackingMode);
287+
return;
288+
}
289+
_trackingArea = [[NSTrackingArea alloc] initWithRect:NSZeroRect
290+
options:options
291+
owner:self
292+
userInfo:nil];
293+
[self.view addTrackingArea:_trackingArea];
294+
} else if (_trackingArea) {
295+
[self.view removeTrackingArea:_trackingArea];
296+
_trackingArea = nil;
297+
}
298+
}
299+
244300
- (void)addInternalPlugins {
245301
_textInputPlugin = [[FLETextInputPlugin alloc] initWithViewController:self];
246302
_keyEventChannel =
@@ -471,4 +527,16 @@ - (void)mouseDragged:(NSEvent*)event {
471527
[self dispatchMouseEvent:event phase:kMove];
472528
}
473529

530+
- (void)mouseEntered:(NSEvent*)event {
531+
[self dispatchMouseEvent:event phase:kAdd];
532+
}
533+
534+
- (void)mouseExited:(NSEvent*)event {
535+
[self dispatchMouseEvent:event phase:kRemove];
536+
}
537+
538+
- (void)mouseMoved:(NSEvent*)event {
539+
[self dispatchMouseEvent:event phase:kHover];
540+
}
541+
474542
@end

0 commit comments

Comments
 (0)