changeset 12384:2494b1f76644

8173876: Fast precise scrolling and DeltaAccumulator fix for macOS Sierra 10.12.2 Reviewed-by: serb, alexsch
author malenkov
date Fri, 24 Feb 2017 12:04:59 +0400
parents 2ba0ceeb3b10
children 9bc2f86c5e88
files src/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java src/macosx/classes/sun/lwawt/macosx/NSEvent.java src/macosx/native/sun/awt/AWTView.m src/macosx/native/sun/awt/CTrayIcon.m src/macosx/native/sun/awt/LWCToolkit.h src/macosx/native/sun/awt/LWCToolkit.m test/javax/swing/plaf/basic/BasicScrollPaneUI/8166591/TooMuchWheelRotationEventsTest.java
diffstat 7 files changed, 64 insertions(+), 35 deletions(-) [+]
line wrap: on
line diff
--- a/src/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java	Mon Feb 20 21:25:54 2017 +0300
+++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java	Fri Feb 24 12:04:59 2017 +0400
@@ -262,9 +262,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) {
 
@@ -275,25 +274,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 (scrollPhase == NSEvent.SCROLL_PHASE_BEGAN) {
+                    accumulatedDelta = 0;
+                    accumulate = true;
+                }
+                else if (scrollPhase == NSEvent.SCROLL_PHASE_MOMENTUM_BEGAN) {
+                    accumulate = true;
+                }
+                if (accumulate) {
 
-                if (begin) {
-                    accumulatedDelta = 0;
-                }
+                    accumulatedDelta += delta;
 
-                accumulatedDelta += delta;
+                    roundDelta = (int) Math.round(accumulatedDelta);
 
-                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;
+                    if (scrollPhase == NSEvent.SCROLL_PHASE_ENDED) {
+                        accumulate = false;
                     }
                 }
             }
--- a/src/macosx/classes/sun/lwawt/macosx/NSEvent.java	Mon Feb 20 21:25:54 2017 +0300
+++ b/src/macosx/classes/sun/lwawt/macosx/NSEvent.java	Fri Feb 24 12:04:59 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/src/macosx/native/sun/awt/AWTView.m	Mon Feb 20 21:25:54 2017 +0300
+++ b/src/macosx/native/sun/awt/AWTView.m	Fri Feb 24 12:04:59 2017 +0400
@@ -385,6 +385,13 @@
         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,
@@ -394,8 +401,8 @@
                                   [event buttonNumber],
                                   (jint)localPoint.x, (jint)localPoint.y,
                                   (jint)absP.x, (jint)absP.y,
-                                  [event deltaY],
-                                  [event deltaX],
+                                  deltaY,
+                                  deltaX,
                                   [AWTToolkit scrollStateWithEvent: event]);
     if (jEvent == nil) {
         // Unable to create event by some reason.
--- a/src/macosx/native/sun/awt/CTrayIcon.m	Mon Feb 20 21:25:54 2017 +0300
+++ b/src/macosx/native/sun/awt/CTrayIcon.m	Fri Feb 24 12:04:59 2017 +0400
@@ -135,6 +135,13 @@
 
     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,
@@ -144,8 +151,8 @@
                                   [event buttonNumber],
                                   (jint)localPoint.x, (jint)localPoint.y,
                                   (jint)absP.x, (jint)absP.y,
-                                  [event deltaY],
-                                  [event deltaX],
+                                  deltaY,
+                                  deltaX,
                                   [AWTToolkit scrollStateWithEvent: event]);
     if (jEvent == nil) {
         // Unable to create event by some reason.
--- a/src/macosx/native/sun/awt/LWCToolkit.h	Mon Feb 20 21:25:54 2017 +0300
+++ b/src/macosx/native/sun/awt/LWCToolkit.h	Fri Feb 24 12:04:59 2017 +0400
@@ -41,6 +41,7 @@
 + (long) getEventCount;
 + (void) eventCountPlusPlus;
 + (jint) scrollStateWithEvent: (NSEvent*) event;
++ (BOOL) hasPreciseScrollingDeltas: (NSEvent*) event;
 @end
 
 /*
--- a/src/macosx/native/sun/awt/LWCToolkit.m	Mon Feb 20 21:25:54 2017 +0300
+++ b/src/macosx/native/sun/awt/LWCToolkit.m	Fri Feb 24 12:04:59 2017 +0400
@@ -43,7 +43,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;
@@ -62,21 +62,38 @@
 }
 
 + (jint) scrollStateWithEvent: (NSEvent*) event {
-
+    
     if ([event type] != NSScrollWheel) {
         return 0;
     }
+    
+    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;
+}
 
-    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;
-    }
-    return SCROLL_PHASE_CONTINUED;
++ (BOOL) hasPreciseScrollingDeltas: (NSEvent*) event {
+    return [event type] == NSScrollWheel
+    && [event respondsToSelector:@selector(hasPreciseScrollingDeltas)]
+    && [event hasPreciseScrollingDeltas];
 }
 @end
 
--- a/test/javax/swing/plaf/basic/BasicScrollPaneUI/8166591/TooMuchWheelRotationEventsTest.java	Mon Feb 20 21:25:54 2017 +0300
+++ b/test/javax/swing/plaf/basic/BasicScrollPaneUI/8166591/TooMuchWheelRotationEventsTest.java	Fri Feb 24 12:04:59 2017 +0400
@@ -40,7 +40,7 @@
 
 /*
  * @test
- * @bug 8166591
+ * @bug 8166591 8173876
  * @summary [macos 10.12] Trackpad scrolling of text on OS X 10.12 Sierra
  *    is very fast (Trackpad, Retina only)
  * @run main/manual/othervm TooMuchWheelRotationEventsTest