support precise wheel rotation to scroll a viewport

This commit is contained in:
Sergey Malenkov
2017-01-24 22:32:56 +03:00
parent a44f03fbef
commit 75798c013f
5 changed files with 65 additions and 6 deletions
@@ -182,7 +182,16 @@ public class JBScrollPane extends SmoothScrollPane {
JScrollPane pane = (JScrollPane)source;
if (pane.isWheelScrollingEnabled()) {
JScrollBar bar = event.isShiftDown() ? pane.getHorizontalScrollBar() : pane.getVerticalScrollBar();
if (bar != null && bar.isVisible()) oldListener.mouseWheelMoved(event);
if (bar != null && bar.isVisible()) {
boolean isUnitScroll = MouseWheelEvent.WHEEL_UNIT_SCROLL == event.getScrollType();
JViewport viewport = pane.getViewport();
if (isUnitScroll && viewport instanceof JBViewport && isPreciseRotationSupported()) {
((JBViewport)viewport).updateViewPosition(event.isShiftDown(), 10 * event.getPreciseWheelRotation());
}
else {
oldListener.mouseWheelMoved(event);
}
}
}
}
}
@@ -735,7 +744,7 @@ public class JBScrollPane extends SmoothScrollPane {
if (event.isConsumed()) return false;
// any rotation expected (forward or backward)
boolean ignore = event.getWheelRotation() == 0;
if (ignore && isPreciseRotationSupported()) {
if (ignore && (isPreciseRotationSupported() || isTrueSmoothScrollingEnabled())) {
double rotation = event.getPreciseWheelRotation();
double delta = MouseWheelEventEx.getScrollingDelta(event);
ignore = (rotation == 0.0D || !Double.isFinite(rotation)) && (delta == 0.0D || !Double.isFinite(delta));
@@ -743,8 +752,15 @@ public class JBScrollPane extends SmoothScrollPane {
return !ignore && 0 == (SCROLL_MODIFIERS & event.getModifiers());
}
private static boolean isPreciseRotationSupported() {
return isTrueSmoothScrollingEnabled();
/**
* Indicates whether the smooth scrolling is supported by any means.
*
* @deprecated will be removed after fixing a blit-scrolling
*/
@Deprecated
@SuppressWarnings("DeprecatedIsStillUsed")
public static boolean isPreciseRotationSupported() {
return Registry.is("ide.scroll.precise");
}
private static final int SCROLL_MODIFIERS = // event modifiers allowed during scrolling
@@ -79,6 +79,10 @@ public class JBViewport extends JViewport implements ZoomableViewport {
private volatile boolean myBackgroundRequested; // avoid cyclic references
private boolean myUpdateViewPosition; // avoid cyclic references
private double myViewX;
private double myViewY;
public JBViewport() {
addContainerListener(new ContainerListener() {
@Override
@@ -107,9 +111,42 @@ public class JBViewport extends JViewport implements ZoomableViewport {
checkScrollingCapabilities();
}
if (myUpdateViewPosition) return;
myViewX = p.x;
myViewY = p.y;
super.setViewPosition(p);
}
/**
* Updates a view position directly without using a corresponding scroll bar.
*
* @param horizontal {@code true} for horizontal scrolling, {@code false} for vertical scrolling
* @param preciseValue precise wheel rotation in pixels for the specified direction
*/
void updateViewPosition(boolean horizontal, double preciseValue) {
int x = (int)myViewX;
int y = (int)myViewY;
if (horizontal) {
int old = x;
myViewX = Math.max(0, myViewX + preciseValue);
x = (int)myViewX;
if (x == old) return; // nothing changed
}
else {
int old = y;
myViewY = Math.max(0, myViewY + preciseValue);
y = (int)myViewY;
if (y == old) return; // nothing changed
}
try {
myUpdateViewPosition = true;
super.setViewPosition(new Point(x, y));
}
finally {
myUpdateViewPosition = false;
}
}
// A heuristic to detect whether this viewport belongs to the "Event Log" tool window (which we use for output)
private boolean isInsideLogToolWindow() {
Container parent1 = getParent();
@@ -507,7 +507,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
myPanel = new JPanel();
// JBScrollPane.Layout relies on "opaque" property directly (instead of "editor.transparent.scrollbar")
if (SystemProperties.isTrueSmoothScrollingEnabled() && !IdeBackgroundUtil.isBackgroundImageSet(project)) {
boolean opaque = JBScrollPane.isPreciseRotationSupported() || SystemProperties.isTrueSmoothScrollingEnabled();
if (opaque && !IdeBackgroundUtil.isBackgroundImageSet(project)) {
//Do not set opaque to false if a scroll bar is opaque (System Preferences / Show scroll bars / Always)
myVerticalScrollBar.setOpaque(true);
myScrollPane.getHorizontalScrollBar().setOpaque(true);
@@ -54,6 +54,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.impl.IdeBackgroundUtil;
import com.intellij.ui.*;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.util.Alarm;
import com.intellij.util.SystemProperties;
import com.intellij.util.containers.ContainerUtil;
@@ -487,7 +488,8 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
This helps to improve scrolling performance and to reduce CPU usage (especially if drawing is compute-intensive).
When there's a background image, blit-acceleration cannot be used (because of the static overlay). */
return !(SystemProperties.isTrueSmoothScrollingEnabled() && !IdeBackgroundUtil.isBackgroundImageSet(myEditor.getProject())) &&
boolean opaque = JBScrollPane.isPreciseRotationSupported() || SystemProperties.isTrueSmoothScrollingEnabled();
return !(opaque && !IdeBackgroundUtil.isBackgroundImageSet(myEditor.getProject())) &&
Registry.is("editor.transparent.scrollbar", false) &&
EditorUtil.isRealFileEditor(myEditor);
}
@@ -118,6 +118,9 @@ ide.splitter.mouseZone=6
ide.autoscroll.from.source.delay=100
ide.autoscroll.from.source.delay.description=Delay before performing the AutoscrollFromSource action
ide.scroll.precise=false
ide.scroll.precise.description=Use precise wheel rotation (may decrease scrolling performance).
ide.scroll.default.unit.increment=false
ide.scroll.default.unit.increment.description=Use default unit increment from Java (may decrease scrolling performance).