Blob Blame History Raw
From 8a745bffa40230e73fb229950d6d0520b474c8f3 Mon Sep 17 00:00:00 2001
From: Eric Williams
Date: Tue, 13 Feb 2018 14:25:46 -0500
Subject: Bug 511133: [GTK3.10+] Some critical icons missing on Ubuntu 16.04

This patch fixes Table/Tree drawing in EGit. It patch reverts the
changes introduced for bug 438505, which causes this regression. This
patch also contains fixes to prevent bug 438505 from being
re-introduced.

EGit drawing was broken because TableItem.getBounds() was taking the
position of the header into account. This is because we were drawing on
the fixedHandle instead of the GtkTreeView. The positioning of the Table
header broke simple drawing cases like Snippet051TableCenteredImage
(JFace snippet). Reverting the fix back to drawing on the handle has
fixed that issue.

Unfortunately this means bug 438505 is re-introduced. To fix that issue
I have tweaked the re-parenting logic found in
Table/Tree.setParentWindow(). GTK3.10+ onward only draws on toplevel or
native GdkWindows. This means the Text widgets used for Table/Tree
editing continue to get events, but they are not drawn. The solution to
this problem is call gdk_window_raise/lower on these Text widgets when
setVisible() is called. This raises and lowers the Text's GdkWindow when
the widget's visibility is changed, ensuring that it actually is drawn
when visible, and not when hidden. This isn't a huge change as the
GdkWindow re-parenting already existed in Table/Tree.setParentWindow(),
this patch just builds on that.

I have tested against the following cases/snippets:
Snippet88
Snippet019 (JFace snippets)
Snippet025 (JFace snippets)
Snippet026 (JFace snippets)
Snippet051 (JFace snippets)
use case from bug 438505
use case from bug 436324
use case from bug 460581
use case from bug 458630

Additionally, using a child Eclipse I have verified that the missing
EGit icons have returned. No AllNonBrowser JUnit tests fail.

Change-Id: I02b3fb30037a8f0f74de79144f8e563f5284d571
Signed-off-by: Eric Williams <ericwill@redhat.com>---
 .../gtk/org/eclipse/swt/widgets/Control.java       | 19 +++++++++++++--
 .../gtk/org/eclipse/swt/widgets/Table.java         | 28 ++++++++++++----------
 .../gtk/org/eclipse/swt/widgets/TableItem.java     |  3 ---
 .../gtk/org/eclipse/swt/widgets/Tree.java          | 28 ++++++++++++----------
 .../gtk/org/eclipse/swt/widgets/TreeItem.java      |  3 ---
 5 files changed, 49 insertions(+), 32 deletions(-)

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 5bb916a..e29d144 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	
@@ -64,6 +64,7 @@ public abstract class Control extends Widget implements Drawable {
 	Accessible accessible;
 	Control labelRelation;
 	String cssBackground, cssForeground = " ";
+	boolean reparentOnVisibility;
 
 	LinkedList <Event> dragDetectionQueue;
 
@@ -5286,7 +5287,7 @@ void setParentBackground () {
 	if (fixedHandle != 0) setBackgroundColor (fixedHandle, null);
 }
 
-void setParentWindow (long /*int*/ widget) {
+void setParentWindow (Control child) {
 }
 
 boolean setRadioSelection (boolean value) {
@@ -5491,6 +5492,13 @@ public void setVisible (boolean visible) {
 		state &= ~HIDDEN;
 		if ((state & (ZERO_WIDTH | ZERO_HEIGHT)) == 0) {
 			if (enableWindow != 0) OS.gdk_window_show_unraised (enableWindow);
+			/*
+			 * Raise this widget's GdkWindow if the reparentOnVisibility
+			 * flag has been set and visible is true. See bug 511133.
+			 */
+			if (reparentOnVisibility && OS.GTK3) {
+				OS.gdk_window_raise(gtk_widget_get_window(topHandle));
+			}
 			OS.gtk_widget_show (topHandle);
 		}
 	} else {
@@ -5527,6 +5535,13 @@ public void setVisible (boolean visible) {
 		OS.gtk_widget_hide (topHandle);
 		if (isDisposed ()) return;
 		if (enableWindow != 0) OS.gdk_window_hide (enableWindow);
+		/*
+		 * Lower this widget's GdkWindow if the reparentOnVisibility
+		 * flag has been set and visible is false. See bug 511133.
+		 */
+		if (reparentOnVisibility && OS.GTK3) {
+			OS.gdk_window_lower(gtk_widget_get_window(topHandle));
+		}
 		sendEvent (SWT.Hide);
 	}
 }
@@ -5682,7 +5697,7 @@ void showWidget () {
 	state |= ZERO_WIDTH | ZERO_HEIGHT;
 	long /*int*/ topHandle = topHandle ();
 	long /*int*/ parentHandle = parent.parentingHandle ();
-	parent.setParentWindow (topHandle);
+	parent.setParentWindow (this);
 	OS.gtk_container_add (parentHandle, topHandle);
 	if (handle != 0 && handle != topHandle) OS.gtk_widget_show (handle);
 	if ((state & (ZERO_WIDTH | ZERO_HEIGHT)) == 0) {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Table.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Table.java
index e3d1441..b664f29 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Table.java	
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Table.java	
@@ -1205,9 +1205,6 @@ Rectangle getClientAreaInPixels () {
 	int width = (state & ZERO_WIDTH) != 0 ? 0 : allocation.width;
 	int height = (state & ZERO_HEIGHT) != 0 ? 0 : allocation.height;
 	Rectangle rect = new Rectangle (fixedX [0] - binX [0], fixedY [0] - binY [0], width, height);
-	if (getHeaderVisible() && OS.GTK_VERSION > OS.VERSION(3, 9, 0)) {
-		rect.y += getHeaderHeightInPixels();
-	}
 	return rect;
 }
 
@@ -1601,9 +1598,6 @@ TableItem getItemInPixels (Point point) {
 	long /*int*/ [] path = new long /*int*/ [1];
 	OS.gtk_widget_realize (handle);
 	int y = point.y;
-	if (getHeaderVisible() && OS.GTK_VERSION > OS.VERSION(3, 9, 0)) {
-		y -= getHeaderHeightInPixels();
-	}
 	if (!OS.gtk_tree_view_get_path_at_pos (handle, point.x, y, path, null, null, null)) return null;
 	if (path [0] == 0) return null;
 	long /*int*/ indices = OS.gtk_tree_path_get_indices (path [0]);
@@ -2453,10 +2447,6 @@ boolean mnemonicMatch (char key) {
 @Override
 long /*int*/ paintWindow () {
 	OS.gtk_widget_realize (handle);
-	if (fixedHandle != 0 && OS.GTK_VERSION > OS.VERSION(3, 9, 0)) {
-		OS.gtk_widget_realize (fixedHandle);
-		return OS.gtk_widget_get_window(fixedHandle);
-	}
 	return OS.gtk_tree_view_get_bin_window (handle);
 }
 
@@ -3659,9 +3649,23 @@ void setParentBackground () {
 }
 
 @Override
-void setParentWindow (long /*int*/ widget) {
+void setParentWindow (Control child) {
 	long /*int*/ window = eventWindow ();
-	OS.gtk_widget_set_parent_window (widget, window);
+	OS.gtk_widget_set_parent_window (child.topHandle(), window);
+	/*
+	 * Feature in GTK3: all children of Table have their GdkWindows
+	 * re-parented so they are siblings of the parent Table
+	 * (i.e. on the same level in the z-order).
+	 *
+	 * To fix table editing in GTK3: raise/lower the
+	 * GdkWindow of these child widgets to make them visible when
+	 * setVisible() is called on them. This ensures they are properly
+	 * drawn when setVisible(true) is called, and properly hidden
+	 * when setVisible(false) is called. See bug 511133.
+	 */
+	if (child != null && OS.GTK3) {
+		child.reparentOnVisibility = true;
+	}
 }
 
 @Override
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TableItem.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TableItem.java
index 6efb227..f904159 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TableItem.java	
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TableItem.java	
@@ -403,9 +403,6 @@ Rectangle getBoundsInPixels (int index) {
 	}
 	int width = OS.gtk_tree_view_column_get_visible (column) ? rect.width + 1 : 0;
 	Rectangle r = new Rectangle (rect.x, rect.y, width, rect.height + 1);
-	if (parent.getHeaderVisible() && OS.GTK_VERSION > OS.VERSION(3, 9, 0)) {
-		r.y += parent.getHeaderHeightInPixels();
-	}
 	return r;
 }
 
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 58e0382..2428361 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	
@@ -1203,9 +1203,6 @@ Rectangle getClientAreaInPixels () {
 	int width = (state & ZERO_WIDTH) != 0 ? 0 : allocation.width;
 	int height = (state & ZERO_HEIGHT) != 0 ? 0 : allocation.height;
 	Rectangle rect = new Rectangle (fixedX [0] - binX [0], fixedY [0] - binY [0], width, height);
-	if (getHeaderVisible() && OS.GTK_VERSION > OS.VERSION(3, 9, 0)) {
-		rect.y += getHeaderHeightInPixels();
-	}
 	return rect;
 }
 
@@ -1610,9 +1607,6 @@ TreeItem getItemInPixels (Point point) {
 	OS.gtk_widget_realize (handle);
 	int x = point.x;
 	int y = point.y;
-	if (getHeaderVisible() && OS.GTK_VERSION > OS.VERSION(3, 9, 0)) {
-		y -= getHeaderHeightInPixels();
-	}
 	if ((style & SWT.MIRRORED) != 0) x = getClientWidth () - x;
 	long /*int*/ [] columnHandle = new long /*int*/ [1];
 	if (!OS.gtk_tree_view_get_path_at_pos (handle, x, y, path, columnHandle, null, null)) return null;
@@ -2596,10 +2590,6 @@ boolean mnemonicMatch (char key) {
 @Override
 long /*int*/ paintWindow () {
 	OS.gtk_widget_realize (handle);
-	if (fixedHandle != 0 && OS.GTK_VERSION > OS.VERSION(3, 9, 0)) {
-		OS.gtk_widget_realize (fixedHandle);
-		return OS.gtk_widget_get_window(fixedHandle);
-	}
 	return OS.gtk_tree_view_get_bin_window (handle);
 }
 
@@ -3664,9 +3654,23 @@ void setParentBackground () {
 }
 
 @Override
-void setParentWindow (long /*int*/ widget) {
+void setParentWindow (Control child) {
 	long /*int*/ window = eventWindow ();
-	OS.gtk_widget_set_parent_window (widget, window);
+	OS.gtk_widget_set_parent_window (child.topHandle(), window);
+	/*
+	 * Feature in GTK3: all children of Tree have their GdkWindows
+	 * re-parented so they are siblings of the parent Tree
+	 * (i.e. on the same level in the z-order).
+	 *
+	 * To fix table editing in GTK3: raise/lower the
+	 * GdkWindow of these child widgets to make them visible when
+	 * setVisible() is called on them. This ensures they are properly
+	 * drawn when setVisible(true) is called, and properly hidden
+	 * when setVisible(false) is called. See bug 511133.
+	 */
+	if (child != null && OS.GTK3) {
+		child.reparentOnVisibility = true;
+	}
 }
 
 void setScrollWidth (long /*int*/ column, TreeItem item) {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TreeItem.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TreeItem.java
index 25bb96b..802a1f9 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TreeItem.java	
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TreeItem.java	
@@ -453,9 +453,6 @@ Rectangle getBoundsInPixels (int index) {
 	}
 	int width = OS.gtk_tree_view_column_get_visible (column) ? rect.width + 1 : 0;
 	Rectangle r = new Rectangle (rect.x, rect.y, width, rect.height + 1);
-	if (parent.getHeaderVisible() && OS.GTK_VERSION > OS.VERSION(3, 9, 0)) {
-		r.y += parent.getHeaderHeightInPixels();
-	}
 	return r;
 }
 
-- 
cgit v1.1