diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2022-01-17 07:12:35 +0200 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2022-01-17 07:12:35 +0200 |
commit | fb3889c6021013b6dc028cae0f4392bc0bcf0eae (patch) | |
tree | cb6f6a19a61db26130bab6e39a181e179b4b6b1d /src | |
parent | a777e1a26a9e9ec97bc636e82349144912ce4a6b (diff) |
macOS: Scroll glitch prevention (Monterey 12.1)
Diffstat (limited to 'src')
-rw-r--r-- | src/macos.m | 39 |
1 files changed, 38 insertions, 1 deletions
diff --git a/src/macos.m b/src/macos.m index 911f5e3a..4ad267c1 100644 --- a/src/macos.m +++ b/src/macos.m | |||
@@ -429,12 +429,48 @@ static void trackSwipe_(NSEvent *event) { | |||
429 | #endif | 429 | #endif |
430 | 430 | ||
431 | static int swipeDir_ = 0; | 431 | static int swipeDir_ = 0; |
432 | static int preventTapGlitch_ = 0; | ||
432 | 433 | ||
433 | static iBool processScrollWheelEvent_(NSEvent *event) { | 434 | static iBool processScrollWheelEvent_(NSEvent *event) { |
434 | const iBool isPerPixel = (event.hasPreciseScrollingDeltas != 0); | 435 | const iBool isPerPixel = (event.hasPreciseScrollingDeltas != 0); |
435 | const iBool isInertia = (event.momentumPhase & (NSEventPhaseBegan | NSEventPhaseChanged)) != 0; | 436 | const iBool isInertia = (event.momentumPhase & (NSEventPhaseBegan | NSEventPhaseChanged)) != 0; |
436 | const iBool isEnded = event.scrollingDeltaX == 0.0f && event.scrollingDeltaY == 0.0f && !isInertia; | 437 | const iBool isEnded = event.scrollingDeltaX == 0.0f && event.scrollingDeltaY == 0.0f && !isInertia; |
437 | const iWindow *win = &get_MainWindow()->base; | 438 | const iWindow *win = &get_MainWindow()->base; |
439 | if (isPerPixel) { | ||
440 | /* On macOS 12.1, stopping ongoing inertia scroll with a tap seems to sometimes produce | ||
441 | spurious large scroll events. */ | ||
442 | switch (preventTapGlitch_) { | ||
443 | case 0: | ||
444 | if (isInertia && event.momentumPhase == NSEventPhaseChanged) { | ||
445 | preventTapGlitch_++; | ||
446 | } | ||
447 | else { | ||
448 | preventTapGlitch_ = 0; | ||
449 | } | ||
450 | break; | ||
451 | case 1: | ||
452 | if (event.scrollingDeltaY == 0 && event.momentumPhase == NSEventPhaseEnded) { | ||
453 | preventTapGlitch_++; | ||
454 | } | ||
455 | break; | ||
456 | case 2: | ||
457 | if (event.scrollingDeltaY == 0 && event.momentumPhase == 0 && isEnded) { | ||
458 | preventTapGlitch_++; | ||
459 | } | ||
460 | else { | ||
461 | preventTapGlitch_ = 0; | ||
462 | } | ||
463 | break; | ||
464 | case 3: | ||
465 | if (event.scrollingDeltaY != 0 && event.momentumPhase == 0 && !isInertia) { | ||
466 | preventTapGlitch_ = 0; | ||
467 | // printf("SPURIOUS\n"); fflush(stdout); | ||
468 | return iTrue; | ||
469 | } | ||
470 | preventTapGlitch_ = 0; | ||
471 | break; | ||
472 | } | ||
473 | } | ||
438 | /* Post corresponding MOUSEWHEEL events. */ | 474 | /* Post corresponding MOUSEWHEEL events. */ |
439 | SDL_MouseWheelEvent e = { .type = SDL_MOUSEWHEEL }; | 475 | SDL_MouseWheelEvent e = { .type = SDL_MOUSEWHEEL }; |
440 | e.timestamp = SDL_GetTicks(); | 476 | e.timestamp = SDL_GetTicks(); |
@@ -464,7 +500,8 @@ static iBool processScrollWheelEvent_(NSEvent *event) { | |||
464 | e.x = -event.scrollingDeltaX; | 500 | e.x = -event.scrollingDeltaX; |
465 | e.y = iSign(event.scrollingDeltaY); | 501 | e.y = iSign(event.scrollingDeltaY); |
466 | } | 502 | } |
467 | // printf("#### dx:%d dy:%d phase:%ld end:%d\n", e.x, e.y, (long) event.momentumPhase, isEnded); fflush(stdout); | 503 | // printf("#### [%d] dx:%d dy:%d phase:%ld inertia:%d end:%d\n", preventTapGlitch_, e.x, e.y, (long) event.momentumPhase, |
504 | // isInertia, isEnded); fflush(stdout); | ||
468 | SDL_PushEvent((SDL_Event *) &e); | 505 | SDL_PushEvent((SDL_Event *) &e); |
469 | #if 0 | 506 | #if 0 |
470 | /* On macOS, we handle both trackpad and mouse events. We expect SDL to identify | 507 | /* On macOS, we handle both trackpad and mouse events. We expect SDL to identify |