From 46145bdcbfb2ed40848dada4d738047b56ec674c Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Wed, 8 Feb 2017 19:22:20 +0400 Subject: [PATCH] 8173876: Fast precise scrolling and DeltaAccumulator fix for macOS Sierra 10.12.2 Reviewed-by: serb, alexsch --- .../sun/lwawt/macosx/CPlatformResponder.java | 27 ++++++-------- .../classes/sun/lwawt/macosx/NSEvent.java | 4 +- .../macosx/native/libawt_lwawt/awt/AWTView.m | 11 +++++- .../native/libawt_lwawt/awt/CTrayIcon.m | 13 +++++-- .../native/libawt_lwawt/awt/LWCToolkit.h | 1 + .../native/libawt_lwawt/awt/LWCToolkit.m | 37 ++++++++++++++----- .../TooMuchWheelRotationEventsTest.java | 2 +- 7 files changed, 62 insertions(+), 33 deletions(-) diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java index de99473a176..c0172f60ff0 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java @@ -265,9 +265,8 @@ final class CPlatformResponder { static class DeltaAccumulator { - static final double MIN_THRESHOLD = 0.1; - static final double MAX_THRESHOLD = 0.5; double accumulatedDelta; + boolean accumulate; int getRoundedDelta(double delta, int scrollPhase) { @@ -278,25 +277,23 @@ final class CPlatformResponder { roundDelta = delta > 0 ? 1 : -1; } } else { // trackpad - boolean begin = scrollPhase == NSEvent.SCROLL_PHASE_BEGAN; - boolean end = scrollPhase == NSEvent.SCROLL_MASK_PHASE_ENDED - || scrollPhase == NSEvent.SCROLL_MASK_PHASE_CANCELLED; - - if (begin) { + if (scrollPhase == NSEvent.SCROLL_PHASE_BEGAN) { accumulatedDelta = 0; + accumulate = true; } + else if (scrollPhase == NSEvent.SCROLL_PHASE_MOMENTUM_BEGAN) { + accumulate = true; + } + if (accumulate) { - accumulatedDelta += delta; + accumulatedDelta += delta; - double absAccumulatedDelta = Math.abs(accumulatedDelta); - if (absAccumulatedDelta > MAX_THRESHOLD) { roundDelta = (int) Math.round(accumulatedDelta); - accumulatedDelta -= roundDelta; - } - if (end) { - if (roundDelta == 0 && absAccumulatedDelta > MIN_THRESHOLD) { - roundDelta = accumulatedDelta > 0 ? 1 : -1; + accumulatedDelta -= roundDelta; + + if (scrollPhase == NSEvent.SCROLL_PHASE_ENDED) { + accumulate = false; } } } diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/NSEvent.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/NSEvent.java index 5710988643d..252ce1122c9 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/NSEvent.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/NSEvent.java @@ -36,8 +36,8 @@ final class NSEvent { static final int SCROLL_PHASE_UNSUPPORTED = 1; static final int SCROLL_PHASE_BEGAN = 2; static final int SCROLL_PHASE_CONTINUED = 3; - static final int SCROLL_MASK_PHASE_CANCELLED = 4; - static final int SCROLL_MASK_PHASE_ENDED = 5; + static final int SCROLL_PHASE_MOMENTUM_BEGAN = 4; + static final int SCROLL_PHASE_ENDED = 5; private int type; private int modifierFlags; diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m index 208d22d69ff..186a002dd5f 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m @@ -381,6 +381,13 @@ static BOOL shouldUsePressAndHold() { } else { clickCount = [event clickCount]; } + + jdouble deltaX = [event deltaX]; + jdouble deltaY = [event deltaY]; + if ([AWTToolkit hasPreciseScrollingDeltas: event]) { + deltaX = [event scrollingDeltaX] * 0.1; + deltaY = [event scrollingDeltaY] * 0.1; + } static JNF_CLASS_CACHE(jc_NSEvent, "sun/lwawt/macosx/NSEvent"); static JNF_CTOR_CACHE(jctor_NSEvent, jc_NSEvent, "(IIIIIIIIDDI)V"); @@ -391,8 +398,8 @@ static BOOL shouldUsePressAndHold() { [event buttonNumber], (jint)localPoint.x, (jint)localPoint.y, (jint)absP.x, (jint)absP.y, - [event deltaY], - [event deltaX], + deltaY, + deltaX, [AWTToolkit scrollStateWithEvent: event]); CHECK_NULL(jEvent); diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CTrayIcon.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CTrayIcon.m index 8057972d301..bfce2fde5c7 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CTrayIcon.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CTrayIcon.m @@ -139,7 +139,14 @@ static NSSize ScaledImageSizeForStatusBar(NSSize imageSize, BOOL autosize) { jint clickCount; clickCount = [event clickCount]; - + + jdouble deltaX = [event deltaX]; + jdouble deltaY = [event deltaY]; + if ([AWTToolkit hasPreciseScrollingDeltas: event]) { + deltaX = [event scrollingDeltaX] * 0.1; + deltaY = [event scrollingDeltaY] * 0.1; + } + static JNF_CLASS_CACHE(jc_NSEvent, "sun/lwawt/macosx/NSEvent"); static JNF_CTOR_CACHE(jctor_NSEvent, jc_NSEvent, "(IIIIIIIIDDI)V"); jobject jEvent = JNFNewObject(env, jctor_NSEvent, @@ -149,8 +156,8 @@ static NSSize ScaledImageSizeForStatusBar(NSSize imageSize, BOOL autosize) { [event buttonNumber], (jint)localPoint.x, (jint)localPoint.y, (jint)absP.x, (jint)absP.y, - [event deltaY], - [event deltaX], + deltaY, + deltaX, [AWTToolkit scrollStateWithEvent: event]); CHECK_NULL(jEvent); diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.h b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.h index c581cb45be1..34532ecb05f 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.h +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.h @@ -42,6 +42,7 @@ extern jint* gButtonDownMasks; + (long) getEventCount; + (void) eventCountPlusPlus; + (jint) scrollStateWithEvent: (NSEvent*) event; ++ (BOOL) hasPreciseScrollingDeltas: (NSEvent*) event; @end /* diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m index 41e966894ce..8cba8ccb8a9 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m @@ -47,7 +47,7 @@ #define SCROLL_PHASE_UNSUPPORTED 1 #define SCROLL_PHASE_BEGAN 2 #define SCROLL_PHASE_CONTINUED 3 -#define SCROLL_PHASE_CANCELLED 4 +#define SCROLL_PHASE_MOMENTUM_BEGAN 4 #define SCROLL_PHASE_ENDED 5 int gNumberOfButtons; @@ -85,16 +85,33 @@ static long eventCount; return 0; } - NSEventPhase phase = [event phase]; - NSEventPhase momentumPhase = [event momentumPhase]; - - if (!phase && !momentumPhase) return SCROLL_PHASE_UNSUPPORTED; - switch (phase) { - case NSEventPhaseBegan: return SCROLL_PHASE_BEGAN; - case NSEventPhaseCancelled: return SCROLL_PHASE_CANCELLED; - case NSEventPhaseEnded: return SCROLL_PHASE_ENDED; - default: return SCROLL_PHASE_CONTINUED; + if ([event phase]) { + // process a phase of manual scrolling + switch ([event phase]) { + case NSEventPhaseBegan: return SCROLL_PHASE_BEGAN; + case NSEventPhaseCancelled: return SCROLL_PHASE_ENDED; + case NSEventPhaseEnded: return SCROLL_PHASE_ENDED; + default: return SCROLL_PHASE_CONTINUED; + } } + + if ([event momentumPhase]) { + // process a phase of automatic scrolling + switch ([event momentumPhase]) { + case NSEventPhaseBegan: return SCROLL_PHASE_MOMENTUM_BEGAN; + case NSEventPhaseCancelled: return SCROLL_PHASE_ENDED; + case NSEventPhaseEnded: return SCROLL_PHASE_ENDED; + default: return SCROLL_PHASE_CONTINUED; + } + } + // phase and momentum phase both are not set + return SCROLL_PHASE_UNSUPPORTED; +} + ++ (BOOL) hasPreciseScrollingDeltas: (NSEvent*) event { + return [event type] == NSScrollWheel + && [event respondsToSelector:@selector(hasPreciseScrollingDeltas)] + && [event hasPreciseScrollingDeltas]; } @end diff --git a/jdk/test/javax/swing/plaf/basic/BasicScrollPaneUI/8166591/TooMuchWheelRotationEventsTest.java b/jdk/test/javax/swing/plaf/basic/BasicScrollPaneUI/8166591/TooMuchWheelRotationEventsTest.java index 4504475d554..640cc055dff 100644 --- a/jdk/test/javax/swing/plaf/basic/BasicScrollPaneUI/8166591/TooMuchWheelRotationEventsTest.java +++ b/jdk/test/javax/swing/plaf/basic/BasicScrollPaneUI/8166591/TooMuchWheelRotationEventsTest.java @@ -40,7 +40,7 @@ import javax.swing.SwingUtilities; /* * @test - * @bug 8166591 + * @bug 8166591 8173876 * @key headful * @summary [macos 10.12] Trackpad scrolling of text on OS X 10.12 Sierra * is very fast (Trackpad, Retina only)