Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get NSScrollView to scroll horizontally with the scroll wheel without the Shift key?

I'm using an NSScrollView to implement a tab bar which scrolls horizontally when there are too many tabs to fit in the window. I can move the scrollview left and right using the trackpad just fine. I'd like to enable mouse users to scroll left and right using the scroll wheel. Right now, this already works if the user holds the Shift key while turning the scroll wheel - the tabs will scroll horizontally. However, I'd like for it to work without the Shift key. This is how Safari's tabs work, for example.

How do I implement horizontal scrolling using the scroll wheel without the Shift key?

Please note that my tab bar does not display a horizontal scroller. Since macOS 10.9's introduction of responsive scrolling, I don't believe we can override -scrollWheel: anymore (see the Update at the bottom of this post: https://stackoverflow.com/a/31201614/111418)

like image 971
sam Avatar asked Oct 15 '25 01:10

sam


1 Answers

I used an NSEvent monitor to accomplish this.

_scrollWheelEventMonitor = [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskScrollWheel handler:^NSEvent * _Nullable(NSEvent * _Nonnull event) {
    NSPoint location = [_scrollView convertPoint:event.locationInWindow fromView:nil];
    // We want events:
    //   where the mouse is over the _scrollView
    //   and where the user is not modifying it with the SHIFT key
    //   and initiated by the scroll wheel and not the trackpad
    if ([_scrollView mouse:location inRect:_scrollView.bounds]
        && !event.modifierFlags
        && !event.hasPreciseScrollingDeltas)
    {
        // Create a new scroll wheel event based on the original,
        // but set the new deltaX to the original's deltaY.
        // stackoverflow.com/a/38991946/111418
        CGEventRef cgEvent = CGEventCreateCopy(event.CGEvent);
        CGEventSetIntegerValueField(cgEvent, kCGScrollWheelEventDeltaAxis2, event.scrollingDeltaY);
        NSEvent *newEvent = [NSEvent eventWithCGEvent:cgEvent];
        CFRelease(cgEvent);
        return newEvent;
    }
    return event;
}];
like image 112
sam Avatar answered Oct 18 '25 03:10

sam



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!