diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9d2fb68b1..edb7fcc4d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+# GEF Classic 3.20.0 (Eclipse 2024-06)
+
+## Draw2d
+ - Overlay scrolling is disabled by default for FigureCanvas. Clients can
+ restore the original behavior by calling FigureCanvas.setScrollbarsMode()
+ prior to creating the object.
+
# GEF Classic 3.19.0 (Eclipse 2024-03)
## Draw2d
diff --git a/org.eclipse.draw2d/src/org/eclipse/draw2d/FigureCanvas.java b/org.eclipse.draw2d/src/org/eclipse/draw2d/FigureCanvas.java
index 6d4e51ca8..72ed38f52 100644
--- a/org.eclipse.draw2d/src/org/eclipse/draw2d/FigureCanvas.java
+++ b/org.eclipse.draw2d/src/org/eclipse/draw2d/FigureCanvas.java
@@ -13,6 +13,9 @@
package org.eclipse.draw2d;
import java.beans.PropertyChangeListener;
+import java.lang.reflect.Method;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
@@ -21,6 +24,7 @@
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Scrollable;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
@@ -49,6 +53,7 @@
*/
public class FigureCanvas extends Canvas {
+ private static final Logger LOGGER = Logger.getLogger(FigureCanvas.class.getSimpleName());
private static final int ACCEPTED_STYLES = SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT | SWT.V_SCROLL | SWT.H_SCROLL
| SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE | SWT.DOUBLE_BUFFERED | SWT.BORDER;
@@ -73,6 +78,16 @@ public class FigureCanvas extends Canvas {
/** Always show scrollbar */
public static int ALWAYS = 2;
+ /**
+ * Static property specifying whether new instances of this class should be
+ * created with overlay scrolling enabled. Possible values are {@link SWT#NONE}
+ * or {@link SWT#SCROLLBAR_OVERLAY}. This value is set to {@link SWT#NONE} by
+ * default, due to performance issues on Linux/GTK3.
+ *
+ * @see here
+ */
+ private static int SCROLLBARS_MODE = SWT.NONE;
+
private int vBarVisibility = AUTOMATIC;
private int hBarVisibility = AUTOMATIC;
private Viewport viewport;
@@ -155,6 +170,7 @@ public FigureCanvas(Composite parent, LightweightSystem lws) {
*/
public FigureCanvas(int style, Composite parent, LightweightSystem lws) {
super(parent, checkStyle(style));
+ adjustScrollbarsMode();
getHorizontalBar().setVisible(false);
getVerticalBar().setVisible(false);
this.lws = lws;
@@ -255,6 +271,25 @@ public Viewport getViewport() {
return viewport;
}
+ /**
+ * Calls {@link Scrollable#setScrollbarsMode(int)} if executed with SWT 3.126.
+ *
+ * @since 3.2
+ */
+ private void adjustScrollbarsMode() {
+ // TODO Check version of SWT binary after PR has been merged:
+ // https://github.com/eclipse-platform/eclipse.platform.swt/pull/1188
+ if (SWT.getVersion() >= 4965 && getScrollbarsMode() != SCROLLBARS_MODE) {
+ try {
+ // Invoke method via reflection to remain compatible with older SWT versions
+ Method setScrollbarsMode = Scrollable.class.getMethod("setScrollbarsMode", Integer.class); //$NON-NLS-1$
+ setScrollbarsMode.invoke(this, SCROLLBARS_MODE);
+ } catch (ReflectiveOperationException e) {
+ LOGGER.log(Level.SEVERE, e.getMessage(), e);
+ }
+ }
+ }
+
/**
* Adds listeners for scrolling.
*/
@@ -552,6 +587,29 @@ public void setViewport(Viewport vp) {
hookViewport();
}
+ /**
+ * Global property to enable overlay scrolling for all figure canvas when
+ * {@link SWT#SCROLLBAR_OVERLAY} and to disable overlay scrolling when
+ * {@link SWT#NONE} is given. The default value is {@link SWT#NONE}.
+ * Calling this method has no effect on already created instances of this
+ * class.
+ * Calling this method has no effect if overlay scrolling is not supported by
+ * the operating system.
+ *
+ * @param mode One of {@link SWT#NONE}, {@link SWT#SCROLLBAR_OVERLAY}.
+ * @since 3.16
+ * @throws IllegalArgumentException if the given {@code mode} isn't one of
+ * {@link SWT#NONE}
+ * {@link SWT#SCROLLBAR_OVERLAY}.
+ * @see #SCROLLBARS_MODE
+ */
+ public static void setScrollbarsMode(int mode) throws IllegalArgumentException {
+ if (mode != SWT.NONE && mode != SWT.SCROLLBAR_OVERLAY) {
+ throw new IllegalArgumentException("Scrollbars mode must be either SWT.SCROLLBAR_OVERLAY or SWT.NONE"); //$NON-NLS-1$
+ }
+ SCROLLBARS_MODE = mode;
+ }
+
private static int verifyScrollBarOffset(RangeModel model, int value) {
value = Math.max(model.getMinimum(), value);
return Math.min(model.getMaximum() - model.getExtent(), value);