Skip to content

Commit

Permalink
Send scroll events from the macOS shell (#8056)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
stuartmorgan authored Mar 6, 2019
1 parent 2fe9c9b commit 471a2c8
Showing 1 changed file with 53 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -416,16 +424,54 @@ - (void)handlePlatformMessage:(const FlutterPlatformMessage*)message {
}

- (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<size_t>(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 {
Expand Down Expand Up @@ -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

0 comments on commit 471a2c8

Please sign in to comment.