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

Commit 471a2c8

Browse files
authored
Send scroll events from the macOS shell (#8056)
Adds scroll event handling to the macOS shell, sending them using the new embedding API. Currently, trackpad scrolling is just handled like scrollwheel scrolling, since the trackpad-gesture-based scroll handling in Flutter is still in progress. Adds code to synthesize Add events if mouse tracking isn't enabled, so that it doesn't rely on Flutter being lenient about handling events from pointers that have never been added.
1 parent 2fe9c9b commit 471a2c8

File tree

1 file changed

+53
-1
lines changed

1 file changed

+53
-1
lines changed

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

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,14 @@ @interface FLEViewController ()
3939
*/
4040
@property(nonatomic) NSTrackingArea* trackingArea;
4141

42+
/**
43+
* Whether or not a kAdd event has been sent for the mouse (or sent again since
44+
* the last kRemove was sent if tracking is enabled). Used to determine whether
45+
* to send an Add event before sending an incoming mouse event, since Flutter
46+
* expects a pointers to be added before events are sent for them.
47+
*/
48+
@property(nonatomic) BOOL mouseCurrentlyAdded;
49+
4250
/**
4351
* Updates |trackingArea| for the current tracking settings, creating it with
4452
* the correct mode if tracking is enabled, or removing it if not.
@@ -416,16 +424,54 @@ - (void)handlePlatformMessage:(const FlutterPlatformMessage*)message {
416424
}
417425

418426
- (void)dispatchMouseEvent:(NSEvent*)event phase:(FlutterPointerPhase)phase {
427+
// If a pointer added event hasn't been sent, synthesize one using this event for the basic
428+
// information.
429+
if (!_mouseCurrentlyAdded && phase != kAdd) {
430+
// Only the values extracted for use in flutterEvent below matter, the rest are dummy values.
431+
NSEvent* addEvent = [NSEvent enterExitEventWithType:NSEventTypeMouseEntered
432+
location:event.locationInWindow
433+
modifierFlags:0
434+
timestamp:event.timestamp
435+
windowNumber:event.windowNumber
436+
context:nil
437+
eventNumber:0
438+
trackingNumber:0
439+
userData:NULL];
440+
[self dispatchMouseEvent:addEvent phase:kAdd];
441+
}
442+
419443
NSPoint locationInView = [self.view convertPoint:event.locationInWindow fromView:nil];
420444
NSPoint locationInBackingCoordinates = [self.view convertPointToBacking:locationInView];
421-
const FlutterPointerEvent flutterEvent = {
445+
FlutterPointerEvent flutterEvent = {
422446
.struct_size = sizeof(flutterEvent),
423447
.phase = phase,
424448
.x = locationInBackingCoordinates.x,
425449
.y = -locationInBackingCoordinates.y, // convertPointToBacking makes this negative.
426450
.timestamp = static_cast<size_t>(event.timestamp * NSEC_PER_MSEC),
427451
};
452+
453+
if (event.type == NSEventTypeScrollWheel) {
454+
flutterEvent.signal_kind = kFlutterPointerSignalKindScroll;
455+
456+
double pixelsPerLine = 1.0;
457+
if (!event.hasPreciseScrollingDeltas) {
458+
CGEventSourceRef source = CGEventCreateSourceFromEvent(event.CGEvent);
459+
pixelsPerLine = CGEventSourceGetPixelsPerLine(source);
460+
if (source) {
461+
CFRelease(source);
462+
}
463+
}
464+
double scaleFactor = self.view.layer.contentsScale;
465+
flutterEvent.scroll_delta_x = event.scrollingDeltaX * pixelsPerLine * scaleFactor;
466+
flutterEvent.scroll_delta_y = -event.scrollingDeltaY * pixelsPerLine * scaleFactor;
467+
}
428468
FlutterEngineSendPointerEvent(_engine, &flutterEvent, 1);
469+
470+
if (phase == kAdd) {
471+
_mouseCurrentlyAdded = YES;
472+
} else if (phase == kRemove) {
473+
_mouseCurrentlyAdded = NO;
474+
}
429475
}
430476

431477
- (void)dispatchKeyEvent:(NSEvent*)event ofType:(NSString*)type {
@@ -539,4 +585,10 @@ - (void)mouseMoved:(NSEvent*)event {
539585
[self dispatchMouseEvent:event phase:kHover];
540586
}
541587

588+
- (void)scrollWheel:(NSEvent*)event {
589+
// TODO: Add gesture-based (trackpad) scroll support once it's supported by the engine rather
590+
// than always using kHover.
591+
[self dispatchMouseEvent:event phase:kHover];
592+
}
593+
542594
@end

0 commit comments

Comments
 (0)