| /* |
| * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package sun.lwawt.macosx; |
| |
| import sun.awt.SunToolkit; |
| import sun.lwawt.LWWindowPeer; |
| import sun.lwawt.PlatformEventNotifier; |
| import sun.lwawt.PlatformWindow; |
| import sun.util.logging.PlatformLogger; |
| |
| import java.awt.Toolkit; |
| import java.awt.event.MouseEvent; |
| import java.awt.event.InputEvent; |
| import java.awt.event.MouseWheelEvent; |
| import java.awt.event.KeyEvent; |
| import java.security.PrivilegedAction; |
| import java.util.Locale; |
| |
| /** |
| * Translates NSEvents/NPCocoaEvents into AWT events. |
| */ |
| final class CPlatformResponder { |
| |
| private static final PlatformLogger keyboardLog = PlatformLogger.getLogger("sun.lwawt.macosx.CPlatformResponder"); |
| |
| 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(); |
| private boolean momentumStarted; |
| private int momentumX; |
| private int momentumY; |
| private int momentumModifiers; |
| private int lastDraggedAbsoluteX; |
| private int lastDraggedAbsoluteY; |
| private int lastDraggedRelativeX; |
| private int lastDraggedRelativeY; |
| private final static boolean useOldKeyEventProcessing = java.security.AccessController.doPrivileged((PrivilegedAction<Boolean>)()-> "true".equals(System.getProperty("com.jetbrains.use.old.keyevent.processing"))); |
| |
| |
| CPlatformResponder(final PlatformEventNotifier eventNotifier, |
| final boolean isNpapiCallback) { |
| this.eventNotifier = eventNotifier; |
| this.isNpapiCallback = isNpapiCallback; |
| } |
| |
| /** |
| * Handles mouse events. |
| */ |
| void handleMouseEvent(PlatformWindow platformWindow, int eventType, int modifierFlags, int buttonNumber, |
| int clickCount, int x, int y, int absoluteX, |
| int absoluteY) { |
| final SunToolkit tk = (SunToolkit)Toolkit.getDefaultToolkit(); |
| if ((buttonNumber > 2 && !tk.areExtraMouseButtonsEnabled()) |
| || buttonNumber > tk.getNumberOfButtons() - 1) { |
| return; |
| } |
| |
| int jeventType = isNpapiCallback ? NSEvent.npToJavaEventType(eventType) : |
| NSEvent.nsToJavaEventType(eventType); |
| |
| boolean dragged = jeventType == MouseEvent.MOUSE_DRAGGED; |
| if (dragged // ignore dragged event that does not change any location |
| && lastDraggedAbsoluteX == absoluteX && lastDraggedRelativeX == x |
| && lastDraggedAbsoluteY == absoluteY && lastDraggedRelativeY == y) return; |
| |
| if (dragged || jeventType == MouseEvent.MOUSE_PRESSED) { |
| lastDraggedAbsoluteX = absoluteX; |
| lastDraggedAbsoluteY = absoluteY; |
| lastDraggedRelativeX = x; |
| lastDraggedRelativeY = y; |
| } |
| |
| int jbuttonNumber = MouseEvent.NOBUTTON; |
| int jclickCount = 0; |
| |
| if (jeventType != MouseEvent.MOUSE_MOVED && |
| jeventType != MouseEvent.MOUSE_ENTERED && |
| jeventType != MouseEvent.MOUSE_EXITED) |
| { |
| jbuttonNumber = NSEvent.nsToJavaButton(buttonNumber); |
| jclickCount = clickCount; |
| } |
| |
| int jmodifiers = NSEvent.nsToJavaMouseModifiers(buttonNumber, |
| modifierFlags); |
| boolean jpopupTrigger = NSEvent.isPopupTrigger(jmodifiers); |
| |
| eventNotifier.notifyMouseEvent(platformWindow, jeventType, System.currentTimeMillis(), jbuttonNumber, |
| x, y, absoluteX, absoluteY, jmodifiers, jclickCount, |
| jpopupTrigger, null); |
| } |
| |
| /** |
| * Handles scroll events. |
| */ |
| void handleScrollEvent(int x, int y, final int modifierFlags, |
| final double deltaX, final double deltaY, |
| final int scrollPhase) { |
| final int buttonNumber = CocoaConstants.kCGMouseButtonCenter; |
| int jmodifiers = NSEvent.nsToJavaMouseModifiers(buttonNumber, |
| modifierFlags); |
| if (scrollPhase > NSEvent.SCROLL_PHASE_UNSUPPORTED) { |
| if (scrollPhase == NSEvent.SCROLL_PHASE_BEGAN) { |
| momentumStarted = false; |
| } else if (scrollPhase == NSEvent.SCROLL_PHASE_MOMENTUM_BEGAN) { |
| momentumStarted = true; |
| momentumX = x; |
| momentumY = y; |
| momentumModifiers = jmodifiers; |
| } else if (momentumStarted) { |
| x = momentumX; |
| y = momentumY; |
| jmodifiers = momentumModifiers; |
| } |
| } |
| 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 || roundDeltaY != 0)) { |
| dispatchScrollEvent(x, y, jmodifiers, roundDeltaY, deltaY); |
| } |
| // Horizontal scroll or shirt+vertical scroll. |
| final double delta = isShift && deltaY != 0.0 ? deltaY : deltaX; |
| final int roundDelta = isShift && roundDeltaY != 0 ? roundDeltaY : roundDeltaX; |
| if (delta != 0.0 || roundDelta != 0) { |
| jmodifiers |= InputEvent.SHIFT_DOWN_MASK; |
| dispatchScrollEvent(x, y, jmodifiers, roundDelta, delta); |
| } |
| } |
| |
| private void dispatchScrollEvent(final int x, final int y, |
| 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; |
| // invert the wheelRotation for the peer |
| eventNotifier.notifyMouseWheelEvent(when, x, y, modifiers, scrollType, |
| scrollAmount, -roundDelta, -delta, null); |
| } |
| |
| private void handleFlagChangedEvent(int modifierFlags, short keyCode) { |
| int[] in = new int[] {modifierFlags, keyCode}; |
| int[] out = new int[3]; // [jkeyCode, jkeyLocation, jkeyType] |
| |
| NSEvent.nsKeyModifiersToJavaKeyInfo(in, out); |
| |
| int jkeyCode = out[0]; |
| int jkeyLocation = out[1]; |
| int jeventType = out[2]; |
| |
| int jmodifiers = NSEvent.nsToJavaKeyModifiers(modifierFlags); |
| long when = System.currentTimeMillis(); |
| |
| if (jeventType == KeyEvent.KEY_PRESSED) { |
| lastKeyPressCode = jkeyCode; |
| } |
| eventNotifier.notifyKeyEvent(jeventType, when, jmodifiers, |
| jkeyCode, KeyEvent.CHAR_UNDEFINED, jkeyLocation); |
| } |
| |
| private static char mapNsCharsToCompatibleWithJava (char ch) { |
| switch (ch) { |
| case 0x0003: // NSEnterCharacter |
| case 0x000d: // NSCarriageReturnCharacter |
| return 0x000a; // NSNewlineCharacter |
| // case 0x007f: // NSDeleteCharacter |
| // return 0x0008; // NSBackspaceCharacter |
| case 0xF728: // NSDeleteFunctionKey |
| return 0x0008; // NSDeleteCharacter |
| case 0x0019: // NSBackTabCharacter |
| return 0x0009; // NSTabCharacter |
| } |
| return ch; |
| } |
| |
| /** |
| * Handles key events. |
| */ |
| void handleKeyEvent(NSEvent nsEvent) |
| { |
| |
| if (useOldKeyEventProcessing) { |
| handleKeyEvent( |
| nsEvent.getType(), |
| nsEvent.getModifierFlags(), |
| nsEvent.getOldCharacters(), |
| nsEvent.getOldCharactersIgnoringModifiers(), |
| nsEvent.getKeyCode(), |
| true, |
| false |
| ); |
| return; |
| } |
| |
| boolean isFlagsChangedEvent = |
| isNpapiCallback ? (nsEvent.getType() == CocoaConstants.NPCocoaEventFlagsChanged) : |
| (nsEvent.getType() == CocoaConstants.NSFlagsChanged); |
| |
| int jeventType = KeyEvent.KEY_PRESSED; |
| int jkeyCode = KeyEvent.VK_UNDEFINED; |
| int jkeyLocation = KeyEvent.KEY_LOCATION_UNKNOWN; |
| boolean postsTyped = false; |
| |
| |
| if (isFlagsChangedEvent) { |
| handleFlagChangedEvent(nsEvent.getModifierFlags(), nsEvent.getKeyCode()); |
| return; |
| } |
| |
| int jmodifiers = NSEvent.nsToJavaKeyModifiers(nsEvent.getModifierFlags()); |
| |
| boolean metaAltCtrlAreNotPressed = (jmodifiers & |
| (InputEvent.META_DOWN_MASK |
| | InputEvent.ALT_DOWN_MASK |
| | InputEvent.CTRL_DOWN_MASK) |
| ) == 0; |
| |
| boolean shiftIsPressed = (jmodifiers & InputEvent.SHIFT_DOWN_MASK) != 0; |
| |
| boolean useShiftedCharacters = metaAltCtrlAreNotPressed && shiftIsPressed; |
| |
| boolean shiftAltDownAreNotPressed = (jmodifiers & |
| (InputEvent.META_DOWN_MASK |
| | InputEvent.ALT_DOWN_MASK |
| | InputEvent.SHIFT_DOWN_MASK) |
| ) == 0; |
| |
| boolean ctrlIsPressed = (jmodifiers & InputEvent.CTRL_DOWN_MASK) != 0; |
| |
| boolean isISOControl = false; |
| |
| char checkedChar = (nsEvent.getCharacters() == null |
| || nsEvent.getCharacters().isEmpty()) ? KeyEvent.CHAR_UNDEFINED : nsEvent.getCharacters().charAt(0); |
| |
| if (shiftAltDownAreNotPressed && ctrlIsPressed) { |
| if (Character.isISOControl(checkedChar)) { |
| isISOControl = true; |
| } |
| } |
| |
| char characterToGetKeyCode = KeyEvent.CHAR_UNDEFINED; |
| |
| boolean charactersIgnoringModifiersIsValid = (nsEvent.getCharactersIgnoringModifiers() != null && nsEvent.getCharactersIgnoringModifiers().length() > 0); |
| boolean charactersIsValid = (nsEvent.getCharacters() != null && nsEvent.getCharacters().length() > 0); |
| |
| // We use this char to find a character that is printed depending on pressing modifiers |
| characterToGetKeyCode = charactersIgnoringModifiersIsValid |
| ? nsEvent.getCharactersIgnoringModifiers().charAt(0) |
| : charactersIsValid ? nsEvent.getCharacters().charAt(0) : KeyEvent.CHAR_UNDEFINED; |
| |
| if (useShiftedCharacters && nsEvent.getCharactersIgnoringModifiers() != null && !nsEvent.getCharactersIgnoringModifiers().isEmpty()) { |
| characterToGetKeyCode = nsEvent.getCharactersIgnoringModifiers().charAt(0); |
| } else if (nsEvent.getCharactersIgnoringModifiersAndShift() != null && !nsEvent.getCharactersIgnoringModifiersAndShift().isEmpty()) { |
| characterToGetKeyCode = nsEvent.getCharactersIgnoringModifiersAndShift().charAt(0); |
| } else if (nsEvent.getCharacters() != null && !nsEvent.getCharacters().isEmpty() && metaAltCtrlAreNotPressed && shiftIsPressed) { |
| characterToGetKeyCode = checkedChar; |
| } |
| |
| // We use char candidate if modifiers are not used |
| // otherwise, we use char ignoring modifiers |
| int[] in = new int[] { |
| characterToGetKeyCode, |
| nsEvent.getModifierFlags(), |
| nsEvent.isHasDeadKey() ? 1 : 0, |
| nsEvent.getKeyCode() |
| }; |
| |
| int[] out = new int[3]; // [jkeyCode, jkeyLocation, deadChar] |
| |
| postsTyped = NSEvent.nsToJavaKeyInfo(in, out); |
| |
| char characterToSendWithTheEvent = characterToGetKeyCode; |
| |
| if(nsEvent.isHasDeadKey()){ |
| characterToSendWithTheEvent = (char) out[2]; |
| jkeyCode = nsEvent.getDeadKeyCode(); |
| if(characterToSendWithTheEvent == 0){ |
| return; |
| } |
| } |
| |
| // If Pinyin Simplified input method is selected, CAPS_LOCK key is supposed to switch |
| // input to la tin letters. |
| // It is necessary to use charIgnoringModifiers instead of charCandidate for event |
| // generation in such case to avoid uppercase letters in text components. |
| LWCToolkit lwcToolkit = (LWCToolkit)Toolkit.getDefaultToolkit(); |
| if (lwcToolkit.getLockingKeyState(KeyEvent.VK_CAPS_LOCK) && |
| Locale.SIMPLIFIED_CHINESE.equals(lwcToolkit.getDefaultKeyboardLocale())) { |
| characterToSendWithTheEvent = characterToGetKeyCode; |
| } |
| |
| jkeyCode = out[0]; |
| |
| jkeyLocation = out[1]; |
| jeventType = isNpapiCallback ? NSEvent.npToJavaEventType(nsEvent.getType()) : |
| NSEvent.nsToJavaEventType(nsEvent.getType()); |
| |
| |
| if (isISOControl) { |
| characterToSendWithTheEvent = checkedChar; |
| } else { |
| characterToSendWithTheEvent = mapNsCharsToCompatibleWithJava(characterToSendWithTheEvent); |
| } |
| |
| String stringWithChar = NSEvent.nsToJavaChar(characterToSendWithTheEvent, nsEvent.getModifierFlags()); |
| characterToSendWithTheEvent = stringWithChar == null ? KeyEvent.CHAR_UNDEFINED : stringWithChar.charAt(0); |
| |
| long when = System.currentTimeMillis(); |
| |
| if (jeventType == KeyEvent.KEY_PRESSED) { |
| lastKeyPressCode = jkeyCode; |
| } |
| |
| if (0xF700 <= characterToSendWithTheEvent && characterToSendWithTheEvent <= 0xF8FF ) { |
| characterToSendWithTheEvent = KeyEvent.CHAR_UNDEFINED; |
| } |
| eventNotifier.notifyKeyEvent(jeventType, when, jmodifiers, |
| jkeyCode, characterToSendWithTheEvent, jkeyLocation); |
| |
| // Current browser may be sending input events, so don't |
| // post the KEY_TYPED here. |
| postsTyped &= true; |
| |
| // That's the reaction on the PRESSED (not RELEASED) event as it comes to |
| // appear in MacOSX. |
| // Modifier keys (shift, etc) don't want to send TYPED events. |
| // On the other hand we don't want to generate keyTyped events |
| // for clipboard related shortcuts like Meta + [CVX] |
| if (jeventType == KeyEvent.KEY_PRESSED && postsTyped && |
| (jmodifiers & KeyEvent.META_DOWN_MASK) == 0) { |
| |
| char characterToSendWithTypedEvent = KeyEvent.CHAR_UNDEFINED; |
| |
| if (nsEvent.getCharacters()!= null ) { |
| characterToSendWithTypedEvent = mapNsCharsToCompatibleWithJava(checkedChar); |
| stringWithChar = NSEvent.nsToJavaChar(characterToSendWithTypedEvent, nsEvent.getModifierFlags()); |
| characterToSendWithTypedEvent = stringWithChar == null ? KeyEvent.CHAR_UNDEFINED : stringWithChar.charAt(0); |
| } |
| |
| boolean nonInputMethodsModifiersAreNotPressed = (jmodifiers & |
| (InputEvent.META_DOWN_MASK | InputEvent.CTRL_DOWN_MASK) |
| ) == 0; |
| |
| if (nonInputMethodsModifiersAreNotPressed) { |
| eventNotifier.notifyKeyEvent(KeyEvent.KEY_TYPED, when, jmodifiers, |
| jkeyCode, characterToSendWithTypedEvent, |
| KeyEvent.KEY_LOCATION_UNKNOWN); |
| } |
| } |
| } |
| |
| void handleInputEvent(String text) { |
| if (text != null) { |
| int index = 0, length = text.length(); |
| char c = 0; |
| while (index < length) { |
| c = text.charAt(index); |
| eventNotifier.notifyKeyEvent(KeyEvent.KEY_TYPED, |
| System.currentTimeMillis(), |
| 0, KeyEvent.VK_UNDEFINED, c, |
| KeyEvent.KEY_LOCATION_UNKNOWN); |
| index++; |
| } |
| eventNotifier.notifyKeyEvent(KeyEvent.KEY_RELEASED, |
| System.currentTimeMillis(), |
| 0, lastKeyPressCode, c, |
| KeyEvent.KEY_LOCATION_UNKNOWN); |
| } |
| } |
| |
| /** |
| * Handles key events. |
| * @deprecated |
| */ |
| @Deprecated |
| void handleKeyEvent(int eventType, int modifierFlags, String chars, String charsIgnoringModifiers, |
| short keyCode, boolean needsKeyTyped, boolean needsKeyReleased) { |
| boolean isFlagsChangedEvent = |
| isNpapiCallback ? (eventType == CocoaConstants.NPCocoaEventFlagsChanged) : |
| (eventType == CocoaConstants.NSFlagsChanged); |
| |
| int jeventType = KeyEvent.KEY_PRESSED; |
| int jkeyCode = KeyEvent.VK_UNDEFINED; |
| int jkeyLocation = KeyEvent.KEY_LOCATION_UNKNOWN; |
| boolean postsTyped = false; |
| |
| char testChar = KeyEvent.CHAR_UNDEFINED; |
| boolean isDeadChar = (chars!= null && chars.length() == 0); |
| |
| if (isFlagsChangedEvent) { |
| int[] in = new int[] {modifierFlags, keyCode}; |
| int[] out = new int[3]; // [jkeyCode, jkeyLocation, jkeyType] |
| |
| NSEvent.nsKeyModifiersToJavaKeyInfo(in, out); |
| |
| jkeyCode = out[0]; |
| jkeyLocation = out[1]; |
| jeventType = out[2]; |
| } else { |
| if (chars != null && chars.length() > 0) { |
| testChar = chars.charAt(0); |
| } |
| |
| char testCharIgnoringModifiers = charsIgnoringModifiers != null && charsIgnoringModifiers.length() > 0 ? |
| charsIgnoringModifiers.charAt(0) : KeyEvent.CHAR_UNDEFINED; |
| |
| int[] in = new int[] {testCharIgnoringModifiers, isDeadChar ? 1 : 0, modifierFlags, keyCode}; |
| int[] out = new int[3]; // [jkeyCode, jkeyLocation, deadChar] |
| |
| postsTyped = NSEvent.nsToJavaKeyInfoOld(in, out); |
| if (!postsTyped) { |
| testChar = KeyEvent.CHAR_UNDEFINED; |
| } |
| |
| if(isDeadChar){ |
| testChar = (char) out[2]; |
| if(testChar == 0){ |
| return; |
| } |
| } |
| |
| // If Pinyin Simplified input method is selected, CAPS_LOCK key is supposed to switch |
| // input to latin letters. |
| // It is necessary to use testCharIgnoringModifiers instead of testChar for event |
| // generation in such case to avoid uppercase letters in text components. |
| LWCToolkit lwcToolkit = (LWCToolkit)Toolkit.getDefaultToolkit(); |
| if (lwcToolkit.getLockingKeyState(KeyEvent.VK_CAPS_LOCK) && |
| Locale.SIMPLIFIED_CHINESE.equals(lwcToolkit.getDefaultKeyboardLocale())) { |
| testChar = testCharIgnoringModifiers; |
| } |
| |
| jkeyCode = out[0]; |
| jkeyLocation = out[1]; |
| jeventType = isNpapiCallback ? NSEvent.npToJavaEventType(eventType) : |
| NSEvent.nsToJavaEventType(eventType); |
| } |
| |
| char javaChar = NSEvent.nsToJavaCharOld(testChar, modifierFlags); |
| // Some keys may generate a KEY_TYPED, but we can't determine |
| // what that character is. That's likely a bug, but for now we |
| // just check for CHAR_UNDEFINED. |
| if (javaChar == KeyEvent.CHAR_UNDEFINED) { |
| postsTyped = false; |
| } |
| |
| |
| int jmodifiers = NSEvent.nsToJavaKeyModifiers(modifierFlags); |
| long when = System.currentTimeMillis(); |
| |
| if (jeventType == KeyEvent.KEY_PRESSED) { |
| lastKeyPressCode = jkeyCode; |
| } |
| eventNotifier.notifyKeyEvent(jeventType, when, jmodifiers, |
| jkeyCode, javaChar, jkeyLocation); |
| |
| // Current browser may be sending input events, so don't |
| // post the KEY_TYPED here. |
| postsTyped &= needsKeyTyped; |
| |
| // That's the reaction on the PRESSED (not RELEASED) event as it comes to |
| // appear in MacOSX. |
| // Modifier keys (shift, etc) don't want to send TYPED events. |
| // On the other hand we don't want to generate keyTyped events |
| // for clipboard related shortcuts like Meta + [CVX] |
| if (jeventType == KeyEvent.KEY_PRESSED && postsTyped && |
| (jmodifiers & KeyEvent.META_DOWN_MASK) == 0) { |
| // Enter and Space keys finish the input method processing, |
| // KEY_TYPED and KEY_RELEASED events for them are synthesized in handleInputEvent. |
| if (needsKeyReleased && (jkeyCode == KeyEvent.VK_ENTER || jkeyCode == KeyEvent.VK_SPACE)) { |
| return; |
| } |
| eventNotifier.notifyKeyEvent(KeyEvent.KEY_TYPED, when, jmodifiers, |
| KeyEvent.VK_UNDEFINED, javaChar, |
| KeyEvent.KEY_LOCATION_UNKNOWN); |
| //If events come from Firefox, released events should also be generated. |
| if (needsKeyReleased) { |
| eventNotifier.notifyKeyEvent(KeyEvent.KEY_RELEASED, when, jmodifiers, |
| jkeyCode, javaChar, |
| KeyEvent.KEY_LOCATION_UNKNOWN); |
| } |
| } |
| } |
| |
| void handleWindowFocusEvent(boolean gained, LWWindowPeer opposite) { |
| eventNotifier.notifyActivation(gained, opposite); |
| } |
| |
| static class DeltaAccumulator { |
| |
| double accumulatedDelta; |
| boolean accumulate; |
| |
| 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 |
| if (scrollPhase == NSEvent.SCROLL_PHASE_BEGAN) { |
| accumulatedDelta = 0; |
| accumulate = true; |
| } |
| else if (scrollPhase == NSEvent.SCROLL_PHASE_MOMENTUM_BEGAN) { |
| accumulate = true; |
| } |
| if (accumulate) { |
| |
| accumulatedDelta += delta; |
| |
| roundDelta = (int) Math.round(accumulatedDelta); |
| |
| accumulatedDelta -= roundDelta; |
| |
| if (scrollPhase == NSEvent.SCROLL_PHASE_ENDED) { |
| accumulate = false; |
| } |
| } |
| } |
| |
| return roundDelta; |
| } |
| } |
| } |