From cf4defcd474e0a55cfb5970265b3d1f0e99d16b0 Mon Sep 17 00:00:00 2001 From: Adam Strzelecki Date: Thu, 18 Aug 2022 00:15:14 +0200 Subject: [PATCH] mac: Distinguish trackpad from Magic Mouse scroll (#1274) This is the second attempt to distinguish trackpad scrolling that when used should yield panning from Magic Mouse scrolling that should control zoom. Since trackpad will begin with a touch prior to the scroll event, but Magic Mouse not, we can use it to make sure we trigger panning only on a trackpad. Previous "mac: Don't interpret single-touch scroll events as pan gestures" that was flawed was reverted which ultimately lead to being unable to zoom using Magic Mouse. --- src/platform/guimac.mm | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/platform/guimac.mm b/src/platform/guimac.mm index 67d1eb97..83c4bd8a 100644 --- a/src/platform/guimac.mm +++ b/src/platform/guimac.mm @@ -372,6 +372,8 @@ MenuBarRef GetOrCreateMainMenu(bool *unique) { double rotationGestureCurrent; Point2d trackpadPositionShift; bool inTrackpadScrollGesture; + int activeTrackpadTouches; + bool scrollFromTrackpadTouch; Platform::Window::Kind kind; } @@ -397,6 +399,9 @@ MenuBarRef GetOrCreateMainMenu(bool *unique) { editor.action = @selector(didEdit:); inTrackpadScrollGesture = false; + activeTrackpadTouches = 0; + scrollFromTrackpadTouch = false; + self.acceptsTouchEvents = YES; kind = aKind; if(kind == Platform::Window::Kind::TOPLEVEL) { NSGestureRecognizer *mag = [[NSMagnificationGestureRecognizer alloc] initWithTarget:self @@ -573,7 +578,16 @@ MenuBarRef GetOrCreateMainMenu(bool *unique) { using Platform::MouseEvent; MouseEvent event = [self convertMouseEvent:nsEvent]; - if(nsEvent.subtype == NSEventSubtypeTabletPoint && kind == Platform::Window::Kind::TOPLEVEL) { + if(nsEvent.phase == NSEventPhaseBegan) { + // If this scroll began on trackpad then touchesBeganWithEvent was called prior to this + // event and we have at least one active trackpad touch. We store this information so we + // can handle scroll originating from trackpad differently below. + scrollFromTrackpadTouch = activeTrackpadTouches > 0 && + nsEvent.subtype == NSEventSubtypeTabletPoint && + kind == Platform::Window::Kind::TOPLEVEL; + } + // Check if we are scrolling on trackpad and handle things differently. + if(scrollFromTrackpadTouch) { // This is how Cocoa represents 2 finger trackpad drag gestures, rather than going via // NSPanGestureRecognizer which is how you might expect this to work... We complicate this // further by also handling shift-two-finger-drag to mean rotate. Fortunately we're using @@ -626,6 +640,18 @@ MenuBarRef GetOrCreateMainMenu(bool *unique) { receiver->onMouseEvent(event); } +- (void)touchesBeganWithEvent:(NSEvent *)event { + activeTrackpadTouches++; +} + +- (void)touchesEndedWithEvent:(NSEvent *)event { + activeTrackpadTouches--; +} + +- (void)touchesCancelledWithEvent:(NSEvent *)event { + activeTrackpadTouches--; +} + - (void)mouseExited:(NSEvent *)nsEvent { using Platform::MouseEvent;