IDEA-158500 new fix based on the fix for JDK 9
http://cr.openjdk.java.net/~alexsch/8166591/webrev.09/
diff --git a/src/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java b/src/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java
index 859909e..99a7ea9 100644
--- a/src/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java
+++ b/src/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java
@@ -91,7 +91,7 @@
int x = (int)pluginX;
int y = (int)pluginY;
- responder.handleScrollEvent(x, y, modifierFlags, deltaX, deltaY);
+ responder.handleScrollEvent(x, y, modifierFlags, deltaX, deltaY, NSEvent.SCROLL_PHASE_UNSUPPORTED);
}
public void handleKeyEvent(int eventType, int modifierFlags, String characters,
diff --git a/src/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java b/src/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java
index 114fbbe..a9e27a7 100644
--- a/src/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java
+++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java
@@ -47,6 +47,8 @@
private final PlatformEventNotifier eventNotifier;
private final boolean isNpapiCallback;
private int lastKeyPressCode = KeyEvent.VK_UNDEFINED;
+ private final DeltaAccumulator deltaAccumulatorX = new DeltaAccumulator();
+ private final DeltaAccumulator deltaAccumulatorY = new DeltaAccumulator();
CPlatformResponder(final PlatformEventNotifier eventNotifier,
final boolean isNpapiCallback) {
@@ -93,37 +95,38 @@
* Handles scroll events.
*/
void handleScrollEvent(final int x, final int y, final int modifierFlags,
- final double deltaX, final double deltaY) {
+ final double deltaX, final double deltaY,
+ final int scrollPhase) {
final int buttonNumber = CocoaConstants.kCGMouseButtonCenter;
int jmodifiers = NSEvent.nsToJavaMouseModifiers(buttonNumber,
modifierFlags);
final boolean isShift = (jmodifiers & InputEvent.SHIFT_DOWN_MASK) != 0;
+ int roundDeltaX = deltaAccumulatorX.getRoundedDelta(deltaX, scrollPhase);
+ int roundDeltaY = deltaAccumulatorY.getRoundedDelta(deltaY, scrollPhase);
+
// Vertical scroll.
- if (!isShift && deltaY != 0.0) {
- dispatchScrollEvent(x, y, jmodifiers, deltaY);
+ if (!isShift && (deltaY != 0.0 || roundDeltaY != 0)) {
+ dispatchScrollEvent(x, y, jmodifiers, roundDeltaY, deltaY);
}
// Horizontal scroll or shirt+vertical scroll.
final double delta = isShift && deltaY != 0.0 ? deltaY : deltaX;
- if (delta != 0.0) {
+ final int roundDelta = isShift && roundDeltaY != 0 ? roundDeltaY : roundDeltaX;
+ if (delta != 0.0 || roundDelta != 0) {
jmodifiers |= InputEvent.SHIFT_DOWN_MASK;
- dispatchScrollEvent(x, y, jmodifiers, delta);
+ dispatchScrollEvent(x, y, jmodifiers, roundDelta, delta);
}
}
private void dispatchScrollEvent(final int x, final int y,
- final int modifiers, final double delta) {
+ final int modifiers,
+ final int roundDelta, final double delta) {
final long when = System.currentTimeMillis();
final int scrollType = MouseWheelEvent.WHEEL_UNIT_SCROLL;
final int scrollAmount = 1;
- int wheelRotation = (int) delta;
- int signum = (int) Math.signum(delta);
- if (signum * delta < 1) {
- wheelRotation = signum;
- }
// invert the wheelRotation for the peer
eventNotifier.notifyMouseWheelEvent(when, x, y, modifiers, scrollType,
- scrollAmount, -wheelRotation, -delta, null);
+ scrollAmount, -roundDelta, -delta, null);
}
/**
@@ -259,4 +262,46 @@
void handleWindowFocusEvent(boolean gained, LWWindowPeer opposite) {
eventNotifier.notifyActivation(gained, opposite);
}
+
+ static class DeltaAccumulator {
+
+ static final double MIN_THRESHOLD = 0.1;
+ static final double MAX_THRESHOLD = 0.5;
+ double accumulatedDelta;
+
+ int getRoundedDelta(double delta, int scrollPhase) {
+
+ int roundDelta = (int) Math.round(delta);
+
+ if (scrollPhase == NSEvent.SCROLL_PHASE_UNSUPPORTED) { // mouse wheel
+ if (roundDelta == 0 && delta != 0) {
+ 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) {
+ accumulatedDelta = 0;
+ }
+
+ 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;
+ }
+ }
+ }
+
+ return roundDelta;
+ }
+ }
}
diff --git a/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java b/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java
index 3c2cd23..9d1acaf 100644
--- a/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java
+++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java
@@ -192,7 +192,8 @@
if (event.getType() == CocoaConstants.NSScrollWheel) {
responder.handleScrollEvent(x, y, event.getModifierFlags(),
- event.getScrollDeltaX(), event.getScrollDeltaY());
+ event.getScrollDeltaX(), event.getScrollDeltaY(),
+ event.getScrollPhase());
} else {
responder.handleMouseEvent(event.getType(), event.getModifierFlags(), event.getButtonNumber(),
event.getClickCount(), x, y, event.getAbsX(), event.getAbsY());
diff --git a/src/macosx/classes/sun/lwawt/macosx/NSEvent.java b/src/macosx/classes/sun/lwawt/macosx/NSEvent.java
index d30a39c..eccc257 100644
--- a/src/macosx/classes/sun/lwawt/macosx/NSEvent.java
+++ b/src/macosx/classes/sun/lwawt/macosx/NSEvent.java
@@ -32,6 +32,13 @@
* JDK functionality.
*/
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;
+
private int type;
private int modifierFlags;
@@ -42,6 +49,7 @@
private int y;
private double scrollDeltaY;
private double scrollDeltaX;
+ private int scrollPhase;
private int absX;
private int absY;
@@ -62,7 +70,7 @@
// Called from native
NSEvent(int type, int modifierFlags, int clickCount, int buttonNumber,
int x, int y, int absX, int absY,
- double scrollDeltaY, double scrollDeltaX) {
+ double scrollDeltaY, double scrollDeltaX, int scrollPhase) {
this.type = type;
this.modifierFlags = modifierFlags;
this.clickCount = clickCount;
@@ -73,6 +81,7 @@
this.absY = absY;
this.scrollDeltaY = scrollDeltaY;
this.scrollDeltaX = scrollDeltaX;
+ this.scrollPhase = scrollPhase;
}
int getType() {
@@ -107,6 +116,10 @@
return scrollDeltaX;
}
+ int getScrollPhase() {
+ return scrollPhase;
+ }
+
int getAbsX() {
return absX;
}
diff --git a/src/macosx/native/sun/awt/AWTView.m b/src/macosx/native/sun/awt/AWTView.m
index 3c38cee..584aefd 100644
--- a/src/macosx/native/sun/awt/AWTView.m
+++ b/src/macosx/native/sun/awt/AWTView.m
@@ -431,7 +431,7 @@
}
static JNF_CLASS_CACHE(jc_NSEvent, "sun/lwawt/macosx/NSEvent");
- static JNF_CTOR_CACHE(jctor_NSEvent, jc_NSEvent, "(IIIIIIIIDD)V");
+ static JNF_CTOR_CACHE(jctor_NSEvent, jc_NSEvent, "(IIIIIIIIDDI)V");
jobject jEvent = JNFNewObject(env, jctor_NSEvent,
[event type],
[event modifierFlags],
@@ -440,7 +440,8 @@
(jint)localPoint.x, (jint)localPoint.y,
(jint)absP.x, (jint)absP.y,
[event deltaY],
- [event deltaX]);
+ [event deltaX],
+ [AWTToolkit scrollStateWithEvent: event]);
if (jEvent == nil) {
// Unable to create event by some reason.
return;
diff --git a/src/macosx/native/sun/awt/CTrayIcon.m b/src/macosx/native/sun/awt/CTrayIcon.m
index 79ae024..b3967df 100644
--- a/src/macosx/native/sun/awt/CTrayIcon.m
+++ b/src/macosx/native/sun/awt/CTrayIcon.m
@@ -136,7 +136,7 @@
clickCount = [event clickCount];
static JNF_CLASS_CACHE(jc_NSEvent, "sun/lwawt/macosx/NSEvent");
- static JNF_CTOR_CACHE(jctor_NSEvent, jc_NSEvent, "(IIIIIIIIDD)V");
+ static JNF_CTOR_CACHE(jctor_NSEvent, jc_NSEvent, "(IIIIIIIIDDI)V");
jobject jEvent = JNFNewObject(env, jctor_NSEvent,
[event type],
[event modifierFlags],
@@ -145,7 +145,8 @@
(jint)localPoint.x, (jint)localPoint.y,
(jint)absP.x, (jint)absP.y,
[event deltaY],
- [event deltaX]);
+ [event deltaX],
+ [AWTToolkit scrollStateWithEvent: event]);
if (jEvent == nil) {
// Unable to create event by some reason.
return;
diff --git a/src/macosx/native/sun/awt/LWCToolkit.h b/src/macosx/native/sun/awt/LWCToolkit.h
index c3e1b53..0a57501 100644
--- a/src/macosx/native/sun/awt/LWCToolkit.h
+++ b/src/macosx/native/sun/awt/LWCToolkit.h
@@ -40,6 +40,7 @@
@interface AWTToolkit : NSObject { }
+ (long) getEventCount;
+ (void) eventCountPlusPlus;
++ (jint) scrollStateWithEvent: (NSEvent*) event;
@end
/*
diff --git a/src/macosx/native/sun/awt/LWCToolkit.m b/src/macosx/native/sun/awt/LWCToolkit.m
index 8b34eba..8f0a290 100644
--- a/src/macosx/native/sun/awt/LWCToolkit.m
+++ b/src/macosx/native/sun/awt/LWCToolkit.m
@@ -39,6 +39,13 @@
#import "sizecalc.h"
+// SCROLL PHASE STATE
+#define SCROLL_PHASE_UNSUPPORTED 1
+#define SCROLL_PHASE_BEGAN 2
+#define SCROLL_PHASE_CONTINUED 3
+#define SCROLL_PHASE_CANCELLED 4
+#define SCROLL_PHASE_ENDED 5
+
int gNumberOfButtons;
jint* gButtonDownMasks;
@@ -54,6 +61,23 @@
eventCount++;
}
++ (jint) scrollStateWithEvent: (NSEvent*) event {
+
+ if ([event type] != NSScrollWheel) {
+ 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;
+ }
+ return SCROLL_PHASE_CONTINUED;
+}
@end