From 5cdef5409b29810e63d2ea36b897e0b267977cf6 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Fri, 25 Aug 2023 15:24:28 +0200 Subject: [PATCH] Smooth Scrolling: fixed jittery scrolling with trackpad or Magic Mouse (if smooth scrolling is enabled) --- .../formdev/flatlaf/ui/FlatScrollPaneUI.java | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatScrollPaneUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatScrollPaneUI.java index d4b67c9b..3e42cece 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatScrollPaneUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatScrollPaneUI.java @@ -144,8 +144,7 @@ public class FlatScrollPaneUI scrollpane.isWheelScrollingEnabled() ) { if( e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL && - e.getPreciseWheelRotation() != 0 && - e.getPreciseWheelRotation() != e.getWheelRotation() ) + isPreciseWheelEvent( e ) ) { // precise scrolling mouseWheelMovedPrecise( e ); @@ -179,6 +178,30 @@ public class FlatScrollPaneUI return UIManager.getBoolean( "ScrollPane.smoothScrolling" ); } + private long lastPreciseWheelWhen; + + private boolean isPreciseWheelEvent( MouseWheelEvent e ) { + double preciseWheelRotation = e.getPreciseWheelRotation(); + if( preciseWheelRotation != 0 && preciseWheelRotation != e.getWheelRotation() ) { + // precise wheel event + lastPreciseWheelWhen = e.getWhen(); + return true; + } + + // If a non-precise wheel event occurs shortly after a precise wheel event, + // then it is probably still a precise wheel but the precise value + // is by chance an integer value (e.g. 1.0 or 2.0). + // Not handling this special case, would start an animation for smooth scrolling, + // which would be interrupted soon when the next precise wheel event occurs. + // This would result in jittery scrolling. E.g. on a MacBook using Trackpad or Magic Mouse. + if( e.getWhen() - lastPreciseWheelWhen < 1000 ) + return true; + + // non-precise wheel event + lastPreciseWheelWhen = 0; + return false; + } + private void mouseWheelMovedPrecise( MouseWheelEvent e ) { // return if there is no viewport JViewport viewport = scrollpane.getViewport();