Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java13
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Scrollable.java39
-rw-r--r--tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug546248_CompositeTooManyPaintEvents.java78
3 files changed, 130 insertions, 0 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java
index 813c4b0e64..8715917033 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java
@@ -717,6 +717,11 @@ public class OS extends C {
*/
public static final String GTK_THEME_SET_NAME;
/**
+ * True iff overlay scrolling has been disabled via GTK_OVERLAY_SCROLLING=0.
+ * See bug 546248.
+ */
+ public static final boolean GTK_OVERLAY_SCROLLING_DISABLED;
+ /**
* True if SWT is running on the GNOME desktop environment.
*/
public static final boolean isGNOME;
@@ -769,6 +774,14 @@ public class OS extends C {
GTK_THEME_SET = gtkThemeSet;
GTK_THEME_SET_NAME = gtkThemeName;
+ String scrollingProperty = "GTK_OVERLAY_SCROLLING";
+ String scrollingCheck = getEnvironmentalVariable(scrollingProperty);
+ boolean scrollingDisabled = false;
+ if (scrollingCheck != null && scrollingCheck.equals("0")) {
+ scrollingDisabled = true;
+ }
+ GTK_OVERLAY_SCROLLING_DISABLED = scrollingDisabled;
+
Map<String, String> env = System.getenv();
String desktopEnvironment = env.get("XDG_CURRENT_DESKTOP");
boolean gnomeDetected = false;
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Scrollable.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Scrollable.java
index d4a8252ace..2344fbe300 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Scrollable.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Scrollable.java
@@ -304,6 +304,45 @@ public ScrollBar getVerticalBar () {
}
@Override
+long gtk_draw (long widget, long cairo) {
+ /*
+ * Draw events destined for an SwtFixed instance will sometimes
+ * only be redrawing the scrollbars attached to it. GTK will send many
+ * draw events to an SwtFixed instance if:
+ * 1) that instance has overlay scrollbars attached to it, and
+ * 2) the mouse has just left (leave-notify) that SwtFixed widget.
+ *
+ * Such extra draw events cause extra SWT.Paint events to be sent and
+ * reduce performance. The fix is to check if the dirty region in need
+ * of a redraw is the same region that the scroll bars occupy, and ignore
+ * draw events that target such cases. See bug 546248.
+ */
+ boolean overlayScrolling = !OS.GTK_OVERLAY_SCROLLING_DISABLED &&
+ GTK.GTK_VERSION >= OS.VERSION(3, 16, 0);
+ if (overlayScrolling && OS.G_OBJECT_TYPE(widget) == OS.swt_fixed_get_type()) {
+ if ((style & SWT.V_SCROLL) != 0 && verticalBar != null) {
+ GtkAllocation verticalBarAlloc = new GtkAllocation();
+ GTK.gtk_widget_get_allocation(verticalBar.handle, verticalBarAlloc);
+ GdkRectangle rect = new GdkRectangle();
+ GDK.gdk_cairo_get_clip_rectangle(cairo, rect);
+ if (rect.width == verticalBarAlloc.width && rect.height == verticalBarAlloc.height) {
+ return 0;
+ }
+ }
+ if ((style & SWT.H_SCROLL) != 0 && horizontalBar != null) {
+ GtkAllocation horizontalBarAlloc = new GtkAllocation();
+ GTK.gtk_widget_get_allocation(horizontalBar.handle, horizontalBarAlloc);
+ GdkRectangle rect = new GdkRectangle();
+ GDK.gdk_cairo_get_clip_rectangle(cairo, rect);
+ if (rect.width == horizontalBarAlloc.width && rect.height == horizontalBarAlloc.height) {
+ return 0;
+ }
+ }
+ }
+ return super.gtk_draw(widget, cairo);
+}
+
+@Override
long gtk_scroll_event (long widget, long eventPtr) {
long result = super.gtk_scroll_event (widget, eventPtr);
diff --git a/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug546248_CompositeTooManyPaintEvents.java b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug546248_CompositeTooManyPaintEvents.java
new file mode 100644
index 0000000000..c4c7f23190
--- /dev/null
+++ b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug546248_CompositeTooManyPaintEvents.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2019 Thomas Singer and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Thomas Singer - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.tests.gtk.snippets;
+
+import java.text.DateFormat;
+import java.util.Date;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+
+public class Bug546248_CompositeTooManyPaintEvents {
+
+ public static void main(String[] args) {
+ final Display display = new Display();
+
+ final StringBuilder buffer = new StringBuilder();
+
+ final int period = 250;
+ display.timerExec(period, new Runnable() {
+ @Override
+ public void run() {
+ if (buffer.length() > 0) {
+ System.out.println(DateFormat.getTimeInstance().format(new Date()) + ": " + buffer);
+ buffer.setLength(0);
+ }
+ if (!display.isDisposed()) {
+ display.timerExec(period, this);
+ }
+ }
+ });
+
+ final Shell shell = new Shell(display);
+ shell.setLayout(new FillLayout());
+
+ final Composite composite = new Composite(shell, SWT.DOUBLE_BUFFERED | SWT.V_SCROLL);
+ final Listener listener = event -> {
+ if (event.type == SWT.Paint) {
+ buffer.append('p');
+ event.gc.drawText("Hello world", 0, 0);
+ }
+ else if (event.type == SWT.MouseMove) {
+ buffer.append('m');
+ }
+ else if (event.type == SWT.MouseHover) {
+ buffer.append('h');
+ }
+ };
+ composite.addListener(SWT.Paint, listener);
+ composite.addListener(SWT.MouseMove, listener);
+ composite.addListener(SWT.MouseHover, listener);
+
+ shell.setSize(400, 300);
+ shell.open();
+
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch()) {
+ display.sleep();
+ }
+ }
+
+ display.dispose();
+ }
+}

Back to the top