summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2022-01-17 07:12:35 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2022-01-17 07:12:35 +0200
commitfb3889c6021013b6dc028cae0f4392bc0bcf0eae (patch)
treecb6f6a19a61db26130bab6e39a181e179b4b6b1d
parenta777e1a26a9e9ec97bc636e82349144912ce4a6b (diff)
macOS: Scroll glitch prevention (Monterey 12.1)
-rw-r--r--src/macos.m39
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
431static int swipeDir_ = 0; 431static int swipeDir_ = 0;
432static int preventTapGlitch_ = 0;
432 433
433static iBool processScrollWheelEvent_(NSEvent *event) { 434static 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