13

I want to detect scroll gestures (two fingers on trackpad). How should i do that?

Erik Sapir
  • 23,209
  • 28
  • 81
  • 141
  • 1
    this [documentation](http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/EventOverview/HandlingTouchEvents/HandlingTouchEvents.html#//apple_ref/doc/uid/10000060i-CH13-SW10) should help –  Jul 10 '11 at 15:57
  • 1
    already checked it. Did not help – Erik Sapir Jul 10 '11 at 16:13

3 Answers3

27

Looks like you want to override your view's scrollWheel: method. You can use the NSEvent's deltaX and deltaY methods to get how much the user has scrolled by.

Code:

@implementation MyView

- (void)scrollWheel:(NSEvent *)theEvent {
    NSLog(@"user scrolled %f horizontally and %f vertically", [theEvent deltaX], [theEvent deltaY]);
}

@end

You also may want to take a look at the Handling Trackpad Events Guide. This will show you how to capture custom gestures, in addition to standard ones.

spudwaffle
  • 2,905
  • 1
  • 22
  • 29
  • 3
    Note that Apple’s documentation recommends using `scrollingDeltaX` and `scrollingDeltaY` for accessing NSScrollWheel values (OX 10.7 and later). – Demitri Mar 18 '16 at 16:43
12

You should do that by implementing touch event methods of NSView in your custom subclass. These methods are :

- (void)touchesBeganWithEvent:(NSEvent *)event;
- (void)touchesMovedWithEvent:(NSEvent *)event;
- (void)touchesEndedWithEvent:(NSEvent *)event;
- (void)touchesCancelledWithEvent:(NSEvent *)event;

The NSEvent object coming along as a paramter contains informations about the touches involded. In particular, you may retrieve them using :

-(NSSet *)touchesMatchingPhase:(NSTouchPhase)phase inView:(NSView *)view;

Also, in the custom view subclass, you must first set it like this :

[self setAcceptsTouchEvents:YES]; 

in order to recieve such events.

Ashkan Mobayen Khiabani
  • 33,575
  • 33
  • 102
  • 171
  • 1
    Apple explicitly recommends against this solution. See "Mouse Events and the Trackpad" in https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/EventOverview/HandlingTouchEvents/HandlingTouchEvents.html – Yoav Nov 10 '13 at 10:45
  • These methods are better suited for detecting two finger swipe gestures. Use scrollWheel instead. – Sentry.co Jan 23 '17 at 12:06
  • Although these events can be tracked, converting the event data and keeping track of the number of touches and their positions is tricky. Since Apple provides the scrollWheel event that gives movement information and any glitching, like a touch event ending and another beginning, due to fingers bouncing, is handled, this solution is not very good at all. – David Rector Apr 21 '23 at 22:49
8

To detect the scrollWheel event, use - (void)scrollWheel:(NSEvent *)theEvent method.

    - (void)scrollWheel:(NSEvent *)theEvent
    {
        //implement what you want
    }

The above method will be called when you scroll using the scroll wheel from your mouse or the two finger gesture from the trackpad.

If your question is to determine if the scrollWheel event is generated by mouse or trackpad, then according to Apple's documentation, this is not possible. Although here is a work around,

- (void)scrollWheel:(NSEvent *)theEvent
    {
        if([theEvent phase])
        {
            // theEvent is generated by trackpad
        }
        else
        {
            // theEvent is generated by mouse
        }
    }

You might also use -(void)beginGestureWithEvent:(NSEvent *)event; and -(void)endGestureWithEvent:(NSEvent *)event. These methods are called before and after the -(void)scrollWheel:(NSEvent *)theEvent respectively.

There is a case when this will not work - if you use the two finger gesture faster and take your fingers out of the trackpad pretty fast, then you might have issues here - (Memory is not getting released)

Community
  • 1
  • 1
AProgrammer
  • 389
  • 3
  • 9
  • Refer - [link] (http://stackoverflow.com/questions/13807616/mac-cocoa-how-to-differentiate-if-a-nsscrollwheel-event-is-from-a-mouse-or-trac). Sorry, I gave the wrong link before. – AProgrammer Dec 11 '12 at 18:36
  • 1
    Incorrect. When scrolling with Apple Magic Mouse, the phase may be > 0. – Yoav Nov 09 '13 at 21:26
  • 2
    I tried your answer on OSX 10.10 and beginGestureWithEvent: and endGestureWithEvent: are _not_ called when scrolling. These two methods are, according to the documentation, only activated for touch events and gestures. – HuaTham Apr 01 '15 at 00:40
  • Although the scrollWheel event has no information that tells you if the event comes from the trackpad or from the mouse (at least not for me for my Magic Mouse), you can use the touch events to keep track of touch count (don't use them for movement information) and then if the touch count is 2 at the time is is triggered, you know that the scrollWheel event must be coming from the trackpad. I tested this touch counting and it was the only solution that worked for me at the time I write this. Some code is here: https://blog.rectorsquid.com/detecting-trackpad-scroll-vs-magic-mouse-scroll/ – David Rector Apr 21 '23 at 22:54