From be9f3ff707e25f4aa304df53c2b712b9678a7772 Mon Sep 17 00:00:00 2001 From: Eric Williams Date: Wed, 7 Aug 2019 17:04:52 -0400 Subject: Bug 541427: [GTK3][X11] Tree with no items and the size of the header is blank A change in the GTK3.20 drawing model means that Trees without any items will have blank headers (not drawn). The fix is to ensure that a window-system native window is created for the Tree. Only X11 is affected by this bug, Trees on Wayland behave normally. Tested on GTK3.24 on X11 and Wayland, using the snippet attached and a child Eclipse. No AllNonBrowser JUnit tests fail. Change-Id: I5f8528b43a5ed41d652c663637673385d5eed945 Signed-off-by: Eric Williams --- .../Eclipse SWT PI/gtk/library/os.c | 12 ++++++ .../Eclipse SWT PI/gtk/library/os.h | 1 + .../Eclipse SWT PI/gtk/library/os_stats.c | 1 + .../Eclipse SWT PI/gtk/library/os_stats.h | 1 + .../gtk/org/eclipse/swt/internal/gtk/GDK.java | 12 ++++++ .../gtk/org/eclipse/swt/widgets/Tree.java | 12 ++++++ .../tests/gtk/snippets/Bug541427_TreeNoHeader.java | 47 ++++++++++++++++++++++ 7 files changed, 86 insertions(+) create mode 100644 tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug541427_TreeNoHeader.java diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c index 81feb4b3ab..000161b36f 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c @@ -2821,6 +2821,18 @@ JNIEXPORT jlong JNICALL GDK_NATIVE(_1gdk_1window_1end_1draw_1frame) } #endif +#ifndef NO__1gdk_1window_1ensure_1native +JNIEXPORT jboolean JNICALL GDK_NATIVE(_1gdk_1window_1ensure_1native) + (JNIEnv *env, jclass that, jlong arg0) +{ + jboolean rc = 0; + GDK_NATIVE_ENTER(env, that, _1gdk_1window_1ensure_1native_FUNC); + rc = (jboolean)gdk_window_ensure_native((GdkWindow *)arg0); + GDK_NATIVE_EXIT(env, that, _1gdk_1window_1ensure_1native_FUNC); + return rc; +} +#endif + #ifndef NO__1gdk_1window_1focus JNIEXPORT void JNICALL GDK_NATIVE(_1gdk_1window_1focus) (JNIEnv *env, jclass that, jlong arg0, jint arg1) diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.h b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.h index 11abf15d99..4518ddba0d 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.h +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.h @@ -314,6 +314,7 @@ #define NO__1gdk_1window_1begin_1draw_1frame #define NO__1gdk_1window_1create_1similar_1surface #define NO__1gdk_1window_1destroy +#define NO__1gdk_1window_1ensure_1native #define NO__1gdk_1window_1end_1draw_1frame #define NO__1gdk_1window_1focus #define NO__1gdk_1window_1get_1children diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c index c99927c3f5..4828ccc0e9 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c @@ -217,6 +217,7 @@ char * GDK_nativeFunctionNames[] = { "_1gdk_1window_1create_1similar_1surface", "_1gdk_1window_1destroy", "_1gdk_1window_1end_1draw_1frame", + "_1gdk_1window_1ensure_1native", "_1gdk_1window_1focus", "_1gdk_1window_1get_1children", "_1gdk_1window_1get_1device_1position", diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h index b368da0b32..71bbc4ecac 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h @@ -227,6 +227,7 @@ typedef enum { _1gdk_1window_1create_1similar_1surface_FUNC, _1gdk_1window_1destroy_FUNC, _1gdk_1window_1end_1draw_1frame_FUNC, + _1gdk_1window_1ensure_1native_FUNC, _1gdk_1window_1focus_FUNC, _1gdk_1window_1get_1children_FUNC, _1gdk_1window_1get_1device_1position_FUNC, diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GDK.java b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GDK.java index 16e7f629f0..6f82cb4632 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GDK.java +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GDK.java @@ -550,6 +550,18 @@ public class GDK extends OS { lock.unlock(); } } + /** + * @param window cast=(GdkWindow *) + */ + public static final native boolean _gdk_window_ensure_native(long window); + public static final boolean gdk_window_ensure_native(long window) { + lock.lock(); + try { + return _gdk_window_ensure_native(window); + } finally { + lock.unlock(); + } + } /** * @param window cast=(GdkWindow *) */ diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Tree.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Tree.java index 29c3cb6d88..95776fc898 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Tree.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Tree.java @@ -89,6 +89,8 @@ public class Tree extends Composite { TreeItem currentItem; ImageList imageList, headerImageList; boolean firstCustomDraw; + /** True iff a draw event has never been processed by this Tree */ + boolean firstDraw = true; /** True iff computeSize has never been called on this Tree */ boolean firstCompute = true; boolean modelChanged; @@ -2412,6 +2414,16 @@ void drawInheritedBackground (long cairo) { long gtk_draw (long widget, long cairo) { boolean haveBoundsChanged = boundsChangedSinceLastDraw; boundsChangedSinceLastDraw = false; + /* + * Feature in GTK: a drawing model change in GTK3.20 means that headers are not drawn + * if the Tree has no items. In such cases, the fix is to ensure that the Tree's GdkWindow + * is a native one. Only X11 is affected by this issue, see bug 541427 for more info. + */ + if (firstDraw && OS.isX11() && getItemCount() == 0 && GTK.GTK_VERSION >= OS.VERSION(3, 20, 0)) { + long binWindow = GTK.gtk_tree_view_get_bin_window(handle); + GDK.gdk_window_ensure_native(binWindow); + } + firstDraw = false; if ((state & OBSCURED) != 0) return 0; /* * Bug 537960: JFace tree viewers miss a repaint when resized by a SashForm diff --git a/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug541427_TreeNoHeader.java b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug541427_TreeNoHeader.java new file mode 100644 index 0000000000..b5da42f115 --- /dev/null +++ b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug541427_TreeNoHeader.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2018 Matthew Khouzam and others. All rights reserved. + * The contents of this file are made available under the terms + * of the GNU Lesser General Public License (LGPL) Version 2.1 that + * accompanies this distribution (lgpl-v21.txt). The LGPL is also + * available at http://www.gnu.org/licenses/lgpl.html. If the version + * of the LGPL at http://www.gnu.org is different to the version of + * the LGPL accompanying this distribution and there is any conflict + * between the two license versions, the terms of the LGPL accompanying + * this distribution shall govern. + * + * Contributors: + * Matthew Khouzam - 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.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeColumn; + +public class Bug541427_TreeNoHeader { + public static void main(String[] args) { + // useless setup + Display display = new Display(); + Shell shell = new Shell(display); + shell.setSize(new Point(300, 200)); + + final Tree tree = new Tree(shell, SWT.NO_SCROLL); + tree.setHeaderVisible(true); + tree.setBounds(0, 0, 300, tree.getHeaderHeight()); + TreeColumn col1 = new TreeColumn(tree, SWT.NONE); + col1.setText("Hi Mom!"); + col1.setWidth(200); + TreeColumn col2 = new TreeColumn(tree, SWT.NONE); + col2.setText("Hi Dad!"); + col2.setWidth(200); + shell.open(); + while (!shell.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + display.dispose(); + } +} -- cgit v1.2.3