Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Williams2018-05-30 14:43:19 +0000
committerEric Williams2018-06-12 19:50:06 +0000
commit9c3a2221fbf96861a67b63fdd282a92f830c49e3 (patch)
tree9d5bacb3028527260538d7b43a1c57507f4b9731
parent394f4e7e26c263b24531e4e9007b110e0f35929d (diff)
downloadeclipse.platform.swt-9c3a2221fbf96861a67b63fdd282a92f830c49e3.tar.gz
eclipse.platform.swt-9c3a2221fbf96861a67b63fdd282a92f830c49e3.tar.xz
eclipse.platform.swt-9c3a2221fbf96861a67b63fdd282a92f830c49e3.zip
Bug 535323: [GTK3] Combo sizing problems
This is a two part fix: 1) Override resizeCalculationsGTK3 in Combo to use the GtkEntry for non-READ_ONLY Combos. This prevents us from using the GtkComboBoxText's preferred size which is usually way too large on GTK3.20+. 2) Update the patch from bug 500703 to support the case where one Composite has multiple Combo widgets inside of it. We support this case by setting fixClipHandle in the parent Composite, and then using a HashMap to keep track of the individual Controls, and their respective children who need to have their clips adjusted. Tested on GTK3.22 on X11 and Wayland -- no ill effects. No AllNonBrowser JUnit tests fail. Change-Id: I1d262c9d321dc314c7f66966bd58fbd8e25ba77e Signed-off-by: Eric Williams <ericwill@redhat.com>
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Combo.java55
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java75
-rw-r--r--tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug535323_ComboSizing.java46
-rw-r--r--tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug535657_MultipleComboOverlap.java79
4 files changed, 212 insertions, 43 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Combo.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Combo.java
index 4718fa2440..ff043982c2 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Combo.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Combo.java
@@ -662,6 +662,34 @@ long /*int*/ findPopupHandle (long /*int*/ oldList) {
return result;
}
+@Override
+Point resizeCalculationsGTK3 (long /*int*/ widget, int width, int height) {
+ Point sizes = new Point (width, height);
+ /*
+ * Feature in GTK3.20+: size calculations take into account GtkCSSNode
+ * elements which we cannot access. If the to-be-allocated size minus
+ * these elements is < 0, allocate the preferred size instead. See bug 486068.
+ */
+ if (GTK.GTK_VERSION >= OS.VERSION(3, 20, 0) && widget == handle) {
+ GtkRequisition minimumSize = new GtkRequisition();
+ GtkRequisition naturalSize = new GtkRequisition();
+ // Use the handle only for READ_ONLY Combos, otherwise use the GtkEntry
+ long /*int*/ preferredSizeHandle = ((style & SWT.READ_ONLY) == 0 && entryHandle != 0) ? entryHandle : handle;
+ GTK.gtk_widget_get_preferred_size(preferredSizeHandle, minimumSize, naturalSize);
+ /*
+ * Use the smallest of the minimum/natural sizes to prevent oversized
+ * widgets.
+ */
+ int smallestWidth = Math.min(minimumSize.width, naturalSize.width);
+ int smallestHeight = Math.min(minimumSize.height, naturalSize.height);
+ sizes.x = (width - (smallestWidth - width)) < 0 ? smallestWidth : width;
+ sizes.y = (height - (smallestHeight - height)) < 0 ? smallestHeight : height;
+ return sizes;
+ } else {
+ return super.resizeCalculationsGTK3(widget, width, height);
+ }
+}
+
long /*int*/ findButtonHandle() {
/*
* Feature in GTK. There is no API to query the button
@@ -1423,25 +1451,30 @@ long /*int*/ gtk_delete_text (long /*int*/ widget, long /*int*/ start_pos, long
@Override
long /*int*/ gtk_draw (long /*int*/ widget, long /*int*/ cairo) {
/*
- * Feature in GTK3.20+: READ_ONLY Combos have their clip unioned
+ * Feature in GTK3.20+: Combos have their clip unioned
* with the parent container (Composite in this case). This causes
* overdrawing into neighbouring widgets and breaks resizing.
*
- * The fix is to adjust the clip and allocation of the Combo and its children
+ * The fix is to adjust the clip and allocation of the Combo (and its children)
* in the parent Composite's draw handler, as it ensures that the draw events
* going to the Combo have the correct geometry specifications. This has to
* happen in the parent Composite since neighouring widgets that share the
* same parent are affected. See bug 500703.
+ *
+ * An additional fix was implemented to support non-READ_ONLY Combos, as well
+ * as the case when one Composite has multiple Combos within it -- see bug 535323.
*/
- if (GTK.GTK_VERSION >= OS.VERSION(3, 20, 0) && (style & SWT.READ_ONLY) != 0) {
- if (parent != null && parent.fixClipHandle == 0) {
- long /*int*/ parentHandle = GTK.gtk_widget_get_parent(fixedHandle);
- if (parentHandle != 0) {
- parent.fixClipHandle = parentHandle;
- GTK.gtk_widget_queue_draw(parentHandle);
- long [] /*int*/ array = {fixedHandle, handle, buttonBoxHandle, buttonHandle, cellBoxHandle, cellHandle};
- parent.fixClipHandleChildren = new long /*int*/ [array.length];
- System.arraycopy (array, 0, parent.fixClipHandleChildren, 0, array.length);
+ if (GTK.GTK_VERSION >= OS.VERSION(3, 20, 0)) {
+ long /*int*/ parentHandle = GTK.gtk_widget_get_parent(fixedHandle);
+ if (parentHandle != 0) {
+ if (parent.fixClipHandle == 0) parent.fixClipHandle = parentHandle;
+ GTK.gtk_widget_queue_draw(parentHandle);
+ if ((style & SWT.READ_ONLY) != 0) {
+ long /*int*/ [] array = {fixedHandle, handle, buttonBoxHandle, buttonHandle, cellBoxHandle, cellHandle};
+ parent.fixClipMap.put(this, array);
+ } else {
+ long /*int*/ [] array = {fixedHandle, handle, entryHandle, buttonBoxHandle, buttonHandle};
+ parent.fixClipMap.put(this, array);
}
}
}
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 ed35e96db8..cf786af88b 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
@@ -11,6 +11,8 @@
package org.eclipse.swt.widgets;
+import java.util.*;
+
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.internal.*;
@@ -72,13 +74,15 @@ public class Composite extends Scrollable {
*/
long /*int*/ fixClipHandle;
/**
- * If fixClipHandle is set, fixClipArray can contain additional child widgets
- * that also need to have their clips adjusted.
+ * If fixClipHandle is set, then the fixClipMap HashMap contains children
+ * of fixClipHandle that also need to have their clips adjusted.
*
- * <p>The array <b>must</b> be ordered by widget hierarchy, as this array will be
- * traversed in-order to adjust the clipping of each element. See bug 500703.</p>
+ * <p>Each key is a Control which needs to have its clip adjusted, and each value
+ * is an array of handles (descendants of the Control) ordered by widget hierarchy.
+ * This array will be traversed in-order to adjust the clipping of each element.
+ * See bug 500703 and 535323.</p>
*/
- long /*int*/ [] fixClipHandleChildren = {};
+ Map<Control, long /*int*/ []> fixClipMap = new HashMap<> ();
static final String NO_INPUT_METHOD = "org.eclipse.swt.internal.gtk.noInputMethod"; //$NON-NLS-1$
@@ -356,41 +360,48 @@ void createHandle (int index, boolean fixed, boolean scrolled) {
* <p>If the array is empty this method just returns. See bug 500703.</p>
*/
void fixChildClippings () {
- if (fixClipHandleChildren == null) {
+ if (fixClipHandle == 0 || fixClipMap.isEmpty()) {
return;
} else {
GtkRequisition minimumSize = new GtkRequisition ();
GtkRequisition naturalSize = new GtkRequisition ();
GtkAllocation clip = new GtkAllocation ();
GtkAllocation allocation = new GtkAllocation ();
- for (long /*int*/ widget : fixClipHandleChildren) {
- GTK.gtk_widget_get_allocation(widget, allocation);
- GTK.gtk_widget_get_clip(widget, clip);
- /*
- * If the clip is negative, add the x coordinate to the width
- * and set the x coordinate to 0.
- */
- if (clip.x < 0) {
- clip.width = clip.width + clip.x;
- clip.x = 0;
- /*
- * Some "transient" widgets like menus get allocations of
- * {-1, -1, 1, 1}. Check to make sure this isn't the case
- * before proceeding.
- */
- if (allocation.x < -1 && (allocation.width > 1 || allocation.height > 1)) {
- // Adjust the allocation just like the clip, if it's negative
- allocation.width = allocation.width + allocation.x;
- allocation.x = 0;
- // Call gtk_widget_get_preferred_size() to prevent warnings
- GTK.gtk_widget_get_preferred_size(widget, minimumSize, naturalSize);
- // Allocate and queue a resize event
- GTK.gtk_widget_size_allocate(widget, allocation);
- GTK.gtk_widget_queue_resize(widget);
+ Control [] children = _getChildren();
+ for (Control child : children) {
+ if (fixClipMap.containsKey(child)) {
+ long /*int*/ [] childHandles = fixClipMap.get(child);
+ for (long /*int*/ widget : childHandles) {
+ GTK.gtk_widget_get_allocation(widget, allocation);
+ GTK.gtk_widget_get_clip(widget, clip);
+ /*
+ * If the clip is negative, add the x coordinate to the width
+ * and set the x coordinate to 0.
+ */
+ if (clip.x < 0) {
+ clip.width = clip.width + clip.x;
+ clip.x = 0;
+ /*
+ * Some "transient" widgets like menus get allocations of
+ * {-1, -1, 1, 1}. Check to make sure this isn't the case
+ * before proceeding.
+ */
+ if (allocation.x < -1 && (allocation.width > 1 || allocation.height > 1)) {
+ // Adjust the allocation just like the clip, if it's negative
+ allocation.width = allocation.width + allocation.x;
+ allocation.x = 0;
+ // Call gtk_widget_get_preferred_size() to prevent warnings
+ GTK.gtk_widget_get_preferred_size(widget, minimumSize, naturalSize);
+ // Allocate and queue a resize event
+ GTK.gtk_widget_size_allocate(widget, allocation);
+ GTK.gtk_widget_queue_resize(widget);
+ }
+ }
+ // Adjust the clip
+ GTK.gtk_widget_set_clip(widget, allocation);
+
}
}
- // Adjust the clip
- GTK.gtk_widget_set_clip(widget, allocation);
}
}
}
diff --git a/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug535323_ComboSizing.java b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug535323_ComboSizing.java
new file mode 100644
index 0000000000..374ebecc51
--- /dev/null
+++ b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug535323_ComboSizing.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Red Hat and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Red Hat - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.tests.gtk.snippets;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+public class Bug535323_ComboSizing {
+
+ public static void main(String[] args) {
+ Display display = new Display();
+ Shell shell = new Shell(display);
+ Rectangle clientArea = shell.getClientArea();
+ Combo combo1 = new Combo(shell, SWT.BORDER);
+ combo1.setItems("Alpha", "Bravo", "Charlie");
+ Point prefSize = combo1.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+ combo1.setBounds(clientArea.x, clientArea.y, prefSize.x, prefSize.y);
+ Combo combo2 = new Combo(shell, SWT.BORDER);
+ combo2.setItems("Alpha", "Bravo", "Charlie");
+ combo2.setBounds(clientArea.x, clientArea.y, prefSize.x, prefSize.y);
+ combo2.setBounds(clientArea.x, clientArea.y + prefSize.y, (prefSize.x / 2) - 1, prefSize.y);
+ Combo combo3 = new Combo(shell, SWT.BORDER);
+ combo3.setItems("Alpha", "Bravo", "Charlie");
+ combo3.setBounds(clientArea.x, clientArea.y + prefSize.y * 2, (prefSize.x / 2) + 1, prefSize.y);
+ shell.pack();
+ shell.open();
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch())
+ display.sleep();
+ }
+ display.dispose();
+ }
+
+} \ No newline at end of file
diff --git a/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug535657_MultipleComboOverlap.java b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug535657_MultipleComboOverlap.java
new file mode 100644
index 0000000000..de17159453
--- /dev/null
+++ b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug535657_MultipleComboOverlap.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Red Hat and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Red Hat - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.tests.gtk.snippets;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+
+public class Bug535657_MultipleComboOverlap {
+
+ public static void main(String[] args) {
+ Display display = new Display();
+ Shell shell = new Shell(display);
+ shell.setSize(400, 200);
+ shell.setText("Bug_odd_combos_on_resize");
+ shell.setLayout(new GridLayout());
+
+ createGroup(shell);
+
+ shell.open();
+
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch())
+ display.sleep();
+ }
+ display.dispose();
+ }
+
+ private static void createGroup(Composite parent) {
+ Group group = new Group(parent, SWT.SHADOW_IN);
+
+ group.setText("some group");
+ GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
+ gridData.horizontalSpan = 2;
+ group.setLayoutData(gridData);
+
+ GridLayout gridLayout = new GridLayout(2, false);
+ group.setLayout(gridLayout);
+
+ class LabelAndText {
+ String labelText;
+ String comboItem;
+
+ LabelAndText(String labelText, String comboItem) {
+ this.labelText = labelText;
+ this.comboItem = comboItem;
+ }
+ }
+
+ LabelAndText[] texts = {
+ new LabelAndText("Some label text: ", "some text"),
+ new LabelAndText("Some label text: ", "some long combo text"),
+ new LabelAndText("Some label text: ", "some text"),
+ };
+
+ for (LabelAndText text : texts) {
+ Label label = new Label(group, SWT.NONE);
+ label.setText(text.labelText);
+ Combo combo = new Combo(group, SWT.READ_ONLY | SWT.DROP_DOWN);
+ GridData comboGridData = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1);
+ combo.setLayoutData(comboGridData);
+ combo.add(text.comboItem);
+ }
+ }
+} \ No newline at end of file

Back to the top