objective-cmacosscrollmacos-sierracgeventtap

How to create a scroll wheel event that scrolls diagonally?


The docs are really stingy regarding this but from the info I gathered online, the wheelCount should be 1 for Y-only, 2 for Y-X, 3 for Y-X-Z.

To my understanding setting wheelCount = 2 inside CGEventCreateScrollWheelEvent should scroll both x and y by 10 pixels but the next chunk of code scrolls, in some apps (Chrome, Safari) only 10 pixels up while in other apps (Preview, Firefox) scrolls both axis:

    CGEventRef scroll = CGEventCreateScrollWheelEvent(NULL,
                                                  kCGScrollEventUnitPixel,
                                                  (uint32_t)2,(int32_t)10,
                                                  (int32_t)10);
    CGEventPost(kCGHIDEventTap, scroll);

    // Verify deltas

    int64_t deltaAxis1 = CGEventGetIntegerValueField(scroll, kCGScrollWheelEventPointDeltaAxis1);
    int64_t deltaAxis2 = CGEventGetIntegerValueField(scroll, kCGScrollWheelEventPointDeltaAxis2);

    NSLog(@"kCGScrollWheelEventPointDeltaAxis1: %lld",deltaAxis1); //kCGScrollWheelEventPointDeltaAxis1: 10
    NSLog(@"kCGScrollWheelEventPointDeltaAxis2: %lld",deltaAxis2); //kCGScrollWheelEventPointDeltaAxis2: 10

    CFRelease(scroll);

Link to docs

Update: After some digging, it seems that some apps don't know how to interpret multi wheel scrolling and scrolls only x or y.

This can be easily reproduced using the above code or a Macbook trackpad:

Open a zoomed in picture in Preview and in Safari. Swiping 2 fingers on a trackpad diagonally while in Preview will create a nice smooth x&y scroll. Doing the same inside Safari or Chrome will result only X or Y being scrolled and will feel broken in general.

I've found a Chrome bug related to this that was closed with "Won't fix". Can't understand why.

Any better explanation on why this is happening would be great.

Thanks


Solution

  • usesPredominantAxisScrolling describes the phenomenon:

    Some content is scrollable in both the horizontal and vertical axes, but is predominantly scrolled one axis at a time. Other content (such as a drawing canvas) should scroll freely in both axes.

    Traditionally this is not an issue with scroll wheels since they can only scroll in one direction at a time. With scroll balls and touch surfaces, it becomes more difficult to determine the user's intention.

    This property helps a scroll view determine the user's intention by specifying if there is a predominant scrolling axis for content.

    In a test app with a WebView, usesPredominantAxisScrolling of the scroll view is YES. Setting it to NO fixes the problem.