Extend NativeWindow to track touch-based scroll events on OS X

In N1, we want to implement the famous "swipe to archive" action on threads in the user's inbox. Chrome exposes `scroll` and `wheel` events, but these aren't sufficient to implement the interaction because the element needs to "snap" when the user lifts their fingers from the trackpad, not when they / we stop receiving `wheel` / `scroll` events. These events may stop before the user lifts their fingers, or continue after the user has lifted their fingers if they had enough momentum for the gesture to continue.

This exposes BrowserWindow `scroll-touch-down` and `scroll-touch-up`, which fire immeditaely when the user touches two fingers to the trackpad, and again when the user lifts their fingers. Combined with the existing wheel event should allow for "swipe-to-archive" and other similar interactions.

Note: This is only implemented on Mac OS X and the events don't fire unless you're using a trackpad!

Related: #1486, #2683, https://github.com/nylas/N1/issues/541
This commit is contained in:
Ben Gotow 2016-01-21 09:40:21 -08:00
parent fda480d1aa
commit bd2252ea55
6 changed files with 43 additions and 0 deletions

View file

@ -227,6 +227,14 @@ void Window::OnWindowLeaveFullScreen() {
Emit("leave-full-screen");
}
void Window::OnWindowScrollTouchUp() {
Emit("scroll-touch-up");
}
void Window::OnWindowScrollTouchDown() {
Emit("scroll-touch-down");
}
void Window::OnWindowEnterHtmlFullScreen() {
Emit("enter-html-full-screen");
}

View file

@ -65,6 +65,8 @@ class Window : public mate::TrackableObject<Window>,
void OnWindowResize() override;
void OnWindowMove() override;
void OnWindowMoved() override;
void OnWindowScrollTouchUp() override;
void OnWindowScrollTouchDown() override;
void OnWindowEnterFullScreen() override;
void OnWindowLeaveFullScreen() override;
void OnWindowEnterHtmlFullScreen() override;

View file

@ -442,6 +442,16 @@ void NativeWindow::NotifyWindowEnterFullScreen() {
OnWindowEnterFullScreen());
}
void NativeWindow::NotifyWindowScrollTouchUp() {
FOR_EACH_OBSERVER(NativeWindowObserver, observers_,
OnWindowScrollTouchUp());
}
void NativeWindow::NotifyWindowScrollTouchDown() {
FOR_EACH_OBSERVER(NativeWindowObserver, observers_,
OnWindowScrollTouchDown());
}
void NativeWindow::NotifyWindowLeaveFullScreen() {
FOR_EACH_OBSERVER(NativeWindowObserver, observers_,
OnWindowLeaveFullScreen());

View file

@ -205,6 +205,8 @@ class NativeWindow : public base::SupportsUserData,
void NotifyWindowMove();
void NotifyWindowResize();
void NotifyWindowMoved();
void NotifyWindowScrollTouchUp();
void NotifyWindowScrollTouchDown();
void NotifyWindowEnterFullScreen();
void NotifyWindowLeaveFullScreen();
void NotifyWindowEnterHtmlFullScreen();

View file

@ -490,6 +490,25 @@ NativeWindowMac::NativeWindowMac(
NSView* view = inspectable_web_contents()->GetView()->GetNativeView();
[view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
BOOL __block down = NO;
[NSEvent addLocalMonitorForEventsMatchingMask:NSScrollWheelMask handler:^NSEvent * _Nullable(NSEvent * event) {
if (![window_ isKeyWindow])
return event;
if (!web_contents)
return event;
if (!down && (([event phase] == NSEventPhaseMayBegin) || ([event phase] == NSEventPhaseBegan))) {
this->NotifyWindowScrollTouchDown();
down = YES;
}
if (down && (([event phase] == NSEventPhaseEnded) || ([event phase] == NSEventPhaseCancelled))) {
this->NotifyWindowScrollTouchUp();
down = NO;
}
return event;
}];
InstallView();
}

View file

@ -50,6 +50,8 @@ class NativeWindowObserver {
virtual void OnWindowResize() {}
virtual void OnWindowMove() {}
virtual void OnWindowMoved() {}
virtual void OnWindowScrollTouchUp() {}
virtual void OnWindowScrollTouchDown() {}
virtual void OnWindowEnterFullScreen() {}
virtual void OnWindowLeaveFullScreen() {}
virtual void OnWindowEnterHtmlFullScreen() {}