8173876: Fast precise scrolling and DeltaAccumulator fix for macOS Sierra 10.12.2
authormalenkov
Wed, 08 Feb 2017 19:22:20 +0400
changeset 43823 bf04b9310757
parent 43822 d8b083d63bbd
child 43824 a77cc25713e9
8173876: Fast precise scrolling and DeltaAccumulator fix for macOS Sierra 10.12.2 Reviewed-by: serb, alexsch
jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java
jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/NSEvent.java
jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m
jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CTrayIcon.m
jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.h
jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m
jdk/test/javax/swing/plaf/basic/BasicScrollPaneUI/8166591/TooMuchWheelRotationEventsTest.java
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java	Wed Feb 08 18:10:13 2017 +0300
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java	Wed Feb 08 19:22:20 2017 +0400
@@ -265,9 +265,8 @@
 
     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 @@
                     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;
                 }
-
-                accumulatedDelta += delta;
+                else if (scrollPhase == NSEvent.SCROLL_PHASE_MOMENTUM_BEGAN) {
+                    accumulate = true;
+                }
+                if (accumulate) {
 
-                double absAccumulatedDelta = Math.abs(accumulatedDelta);
-                if (absAccumulatedDelta > MAX_THRESHOLD) {
+                    accumulatedDelta += delta;
+
                     roundDelta = (int) Math.round(accumulatedDelta);
+
                     accumulatedDelta -= roundDelta;
-                }
 
-                if (end) {
-                    if (roundDelta == 0 && absAccumulatedDelta > MIN_THRESHOLD) {
-                        roundDelta = accumulatedDelta > 0 ? 1 : -1;
+                    if (scrollPhase == NSEvent.SCROLL_PHASE_ENDED) {
+                        accumulate = false;
                     }
                 }
             }
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/NSEvent.java	Wed Feb 08 18:10:13 2017 +0300
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/NSEvent.java	Wed Feb 08 19:22:20 2017 +0400
@@ -36,8 +36,8 @@
     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;
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m	Wed Feb 08 18:10:13 2017 +0300
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m	Wed Feb 08 19:22:20 2017 +0400
@@ -381,6 +381,13 @@
     } 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 @@
                                   [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);
     
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CTrayIcon.m	Wed Feb 08 18:10:13 2017 +0300
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CTrayIcon.m	Wed Feb 08 19:22:20 2017 +0400
@@ -139,7 +139,14 @@
     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 @@
                                   [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);
 
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.h	Wed Feb 08 18:10:13 2017 +0300
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.h	Wed Feb 08 19:22:20 2017 +0400
@@ -42,6 +42,7 @@
 + (long) getEventCount;
 + (void) eventCountPlusPlus;
 + (jint) scrollStateWithEvent: (NSEvent*) event;
++ (BOOL) hasPreciseScrollingDeltas: (NSEvent*) event;
 @end
 
 /*
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m	Wed Feb 08 18:10:13 2017 +0300
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m	Wed Feb 08 19:22:20 2017 +0400
@@ -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 @@
         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
 
--- a/jdk/test/javax/swing/plaf/basic/BasicScrollPaneUI/8166591/TooMuchWheelRotationEventsTest.java	Wed Feb 08 18:10:13 2017 +0300
+++ b/jdk/test/javax/swing/plaf/basic/BasicScrollPaneUI/8166591/TooMuchWheelRotationEventsTest.java	Wed Feb 08 19:22:20 2017 +0400
@@ -40,7 +40,7 @@
 
 /*
  * @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)