From 3c7ce0073713a89efd9321f3be67d421aa005d89 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Tue, 19 Feb 2019 16:11:17 -0800 Subject: [PATCH 1/2] Send scroll events from the macOS shell 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. --- .../framework/Source/FLEViewController.mm | 56 ++++++++++++++++++- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/shell/platform/darwin/macos/framework/Source/FLEViewController.mm b/shell/platform/darwin/macos/framework/Source/FLEViewController.mm index ac901423ee1b6..ae3bc21843169 100644 --- a/shell/platform/darwin/macos/framework/Source/FLEViewController.mm +++ b/shell/platform/darwin/macos/framework/Source/FLEViewController.mm @@ -39,6 +39,14 @@ @interface FLEViewController () */ @property(nonatomic) NSTrackingArea* trackingArea; +/** + * Whether or not a kAdd event has been sent for the mouse (or sent again since + * the last kRemove was sent if tracking is enabled). Used to determine whether + * to send an Add event before sending an incoming mouse event, since Flutter + * expects a pointers to be added before events are sent for them. + */ +@property(nonatomic) BOOL mouseCurrentlyAdded; + /** * Updates |trackingArea| for the current tracking settings, creating it with * the correct mode if tracking is enabled, or removing it if not. @@ -415,17 +423,55 @@ - (void)handlePlatformMessage:(const FlutterPlatformMessage*)message { } } -- (void)dispatchMouseEvent:(NSEvent*)event phase:(FlutterPointerPhase)phase { +- (void)dispatchMouseEvent:(NSEvent *)event phase:(FlutterPointerPhase)phase { + // If a pointer added event hasn't been sent, synthesize one using this event for the basic + // information. + if (!_mouseCurrentlyAdded && phase != kAdd) { + // Only the values extracted for use in flutterEvent below matter, the rest are dummy values. + NSEvent *addEvent = [NSEvent enterExitEventWithType:NSEventTypeMouseEntered + location:event.locationInWindow + modifierFlags:0 + timestamp:event.timestamp + windowNumber:event.windowNumber + context:nil + eventNumber:0 + trackingNumber:0 + userData:NULL]; + [self dispatchMouseEvent:addEvent phase:kAdd]; + } + NSPoint locationInView = [self.view convertPoint:event.locationInWindow fromView:nil]; NSPoint locationInBackingCoordinates = [self.view convertPointToBacking:locationInView]; - const FlutterPointerEvent flutterEvent = { + FlutterPointerEvent flutterEvent = { .struct_size = sizeof(flutterEvent), .phase = phase, .x = locationInBackingCoordinates.x, .y = -locationInBackingCoordinates.y, // convertPointToBacking makes this negative. .timestamp = static_cast(event.timestamp * NSEC_PER_MSEC), }; + + if (event.type == NSEventTypeScrollWheel) { + flutterEvent.signal_kind = kFlutterPointerSignalKindScroll; + + double pixelsPerLine = 1.0; + if (!event.hasPreciseScrollingDeltas) { + CGEventSourceRef source = CGEventCreateSourceFromEvent(event.CGEvent); + pixelsPerLine = CGEventSourceGetPixelsPerLine(source); + if (source) { + CFRelease(source); + } + } + double scaleFactor = self.view.layer.contentsScale; + flutterEvent.scroll_delta_x = event.scrollingDeltaX * pixelsPerLine * scaleFactor; + flutterEvent.scroll_delta_y = -event.scrollingDeltaY * pixelsPerLine * scaleFactor; + } FlutterEngineSendPointerEvent(_engine, &flutterEvent, 1); + + if (phase == kAdd) { + _mouseCurrentlyAdded = YES; + } else if (phase == kRemove) { + _mouseCurrentlyAdded = NO; + } } - (void)dispatchKeyEvent:(NSEvent*)event ofType:(NSString*)type { @@ -539,4 +585,10 @@ - (void)mouseMoved:(NSEvent*)event { [self dispatchMouseEvent:event phase:kHover]; } +- (void)scrollWheel:(NSEvent *)event { + // TODO: Add gesture-based (trackpad) scroll support once it's supported by the engine rather + // than always using kHover. + [self dispatchMouseEvent:event phase:kHover]; +} + @end From 16e86e39c77925750e09ec874af64a1b42797d11 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Tue, 5 Mar 2019 20:41:55 -0800 Subject: [PATCH 2/2] clang-format --- .../darwin/macos/framework/Source/FLEViewController.mm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/shell/platform/darwin/macos/framework/Source/FLEViewController.mm b/shell/platform/darwin/macos/framework/Source/FLEViewController.mm index ae3bc21843169..76a1e08557004 100644 --- a/shell/platform/darwin/macos/framework/Source/FLEViewController.mm +++ b/shell/platform/darwin/macos/framework/Source/FLEViewController.mm @@ -423,12 +423,12 @@ - (void)handlePlatformMessage:(const FlutterPlatformMessage*)message { } } -- (void)dispatchMouseEvent:(NSEvent *)event phase:(FlutterPointerPhase)phase { +- (void)dispatchMouseEvent:(NSEvent*)event phase:(FlutterPointerPhase)phase { // If a pointer added event hasn't been sent, synthesize one using this event for the basic // information. if (!_mouseCurrentlyAdded && phase != kAdd) { // Only the values extracted for use in flutterEvent below matter, the rest are dummy values. - NSEvent *addEvent = [NSEvent enterExitEventWithType:NSEventTypeMouseEntered + NSEvent* addEvent = [NSEvent enterExitEventWithType:NSEventTypeMouseEntered location:event.locationInWindow modifierFlags:0 timestamp:event.timestamp @@ -585,7 +585,7 @@ - (void)mouseMoved:(NSEvent*)event { [self dispatchMouseEvent:event phase:kHover]; } -- (void)scrollWheel:(NSEvent *)event { +- (void)scrollWheel:(NSEvent*)event { // TODO: Add gesture-based (trackpad) scroll support once it's supported by the engine rather // than always using kHover. [self dispatchMouseEvent:event phase:kHover];