Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXi Yan2018-11-06 20:49:56 +0000
committerXi Yan2018-11-08 19:41:07 +0000
commitbb73fc03ae98f2ebd7738c9c9a6a892001dfcb5e (patch)
tree6923bae7c2fe9f5e6279b56b1f554e1d87194f63
parent65722792346a14add8d31f7c4fbedf035a34654e (diff)
downloadeclipse.platform.swt-bb73fc03ae98f2ebd7738c9c9a6a892001dfcb5e.tar.gz
eclipse.platform.swt-bb73fc03ae98f2ebd7738c9c9a6a892001dfcb5e.tar.xz
eclipse.platform.swt-bb73fc03ae98f2ebd7738c9c9a6a892001dfcb5e.zip
Bug 533469 - [GTK3] Ghost button since upgrade to GTK 3.22
1) On GTK3.19+, widgets are shown with the default minimum size. As a result, calling gtk_widget_set_visible in Control#setInitialBounds causes 0x0 widgets to be visible but cannot be used. 2) The previous patch that tries to hide all 0x0 widgets in gtk_draw causes NPE with display being disposed (see bug 540298). 3) The right way to go about (1) is to omit showing widgets in setInitialBounds, but this seems to cause the regression that button does not gain focus. (https://git.eclipse.org/r/#/c/131745/ ) This patch attempts to address these issues. It uses (3) for all widgets except Button and Composite, and limits the fix in (2) for Button only. Change-Id: I1283df211395897e582cbc9d4d11255fb363938c Signed-off-by: Xi Yan <xixiyan@redhat.com>
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Button.java22
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java9
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java17
-rw-r--r--tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug533469_GhostButton.java29
4 files changed, 63 insertions, 14 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Button.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Button.java
index fddf28e744..e600273b4e 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Button.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Button.java
@@ -514,6 +514,28 @@ long /*int*/ gtk_clicked (long /*int*/ widget) {
}
@Override
+long /*int*/ gtk_draw (long /*int*/ widget, long /*int*/ cairo) {
+ /*
+ * On GTK3.19+, widget are are shown with the default minimum size regardless of the
+ * size of the fixed container. This causes 0x0 widgets to be visible but cannot be used.
+ * The fix is to make the widget invisible to the user. Resizing widget later on to a larger size
+ * makes the widget visible again in setBounds. See Bug 533469, Bug 531120.
+ */
+ if (GTK.GTK_VERSION >= OS.VERSION (3, 20, 0) && (state & ZERO_WIDTH) != 0 && (state & ZERO_HEIGHT) != 0) {
+ if (GTK.gtk_widget_get_visible(widget)) GTK.gtk_widget_set_visible(widget, false);
+ // Button and display should not be disposed after hiding widget
+ if (isDisposed() || display == null || display.isDisposed()) error (SWT.ERROR_DEVICE_DISPOSED);
+ }
+ return super.gtk_draw(widget, cairo);
+}
+
+@Override
+boolean mustBeVisibleOnInitBounds() {
+ // Bug 540298: Button needs to be visible in order to gain focus.
+ return true;
+}
+
+@Override
long /*int*/ gtk_focus_in_event (long /*int*/ widget, long /*int*/ event) {
long /*int*/ result = super.gtk_focus_in_event (widget, event);
// widget could be disposed at this point
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java
index 77255563f1..685563b7f6 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java
@@ -434,6 +434,15 @@ long /*int*/ gtk_draw (long /*int*/ widget, long /*int*/ cairo) {
return super.gtk_draw(widget, cairo);
}
+
+@Override
+boolean mustBeVisibleOnInitBounds() {
+ // Bug 540298: if we return false, we will be invisible if the size is
+ // not set, but our layout will not properly work, so that not all children
+ // will be shown properly
+ return true;
+}
+
@Override
void deregister () {
super.deregister ();
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java
index 503b1c6595..1b3740d97b 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java
@@ -4965,14 +4965,27 @@ void setInitialBounds () {
allocation.x = 0;
}
allocation.y = 0;
- GTK.gtk_widget_set_visible(topHandle, true);
- GTK.gtk_widget_set_allocation(topHandle, allocation);
+ if (mustBeVisibleOnInitBounds ()) {
+ GTK.gtk_widget_set_visible(topHandle, true);
+ }
+ GTK.gtk_widget_size_allocate(topHandle, allocation);
} else {
resizeHandle (1, 1);
forceResize ();
}
}
+/**
+ * Widgets with unusual bounds calculation behavior can override this method
+ * to return {@code true} if the widget must be visible during call to
+ * {@link #setInitialBounds()}.
+ *
+ * @return {@code false} by default on modern GTK 3 versions (3.20+).
+ */
+boolean mustBeVisibleOnInitBounds() {
+ return GTK.GTK_VERSION < OS.VERSION(3, 20, 0);
+}
+
/*
* Sets the receivers Drag Gestures in order to do drag detection correctly for
* X11/Wayland window managers after GTK3.14.
diff --git a/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug533469_GhostButton.java b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug533469_GhostButton.java
index d6b32410ef..d5879201a6 100644
--- a/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug533469_GhostButton.java
+++ b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug533469_GhostButton.java
@@ -16,32 +16,37 @@ package org.eclipse.swt.tests.gtk.snippets;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
/*
* On GTK3.18: Empty Shell
* On GTK3.20+: Button/Text/etc is visible when size is 0x0
*/
public class Bug533469_GhostButton {
- public static void main (String [] args) {
- Display display = new Display ();
+ public static void main(String[] args) {
+ Display display = new Display();
Shell shell = new Shell(display);
+ Text text = new Text(shell, SWT.None); // text size is not set, it
+ // should be 0x0
+ text.setText("hello");
+ text.setVisible(true);
+
Button button = new Button(shell, SWT.None);
button.setText("Hi"); // size is not set, it should be 0x0
-// button.setSize(100, 100);
-
-// Text text = new Text(shell, SWT.None);
-// text.setText("Hello");
-// text.setSize(100, 100);
-// System.out.println(button.getSize());
+ Group group = new Group(shell, SWT.None);
+ group.setText("Hi Group"); // size is not set, it should be 0x0
+ System.err.println(group.getSize());
shell.setSize(300, 300);
- shell.open ();
- while (!shell.isDisposed ()) {
- if (!display.readAndDispatch ()) display.sleep ();
+ shell.open();
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch())
+ display.sleep();
}
- display.dispose ();
+ display.dispose();
}
}

Back to the top