eclipse/eclipse-bug-531928-2.patch
2018-04-09 12:52:24 +01:00

254 lines
12 KiB
Diff

From 1a3294ba5966b01cc2953d4ad12ed02eb971b97f Mon Sep 17 00:00:00 2001
From: Leo Ufimtsev
Date: Wed, 14 Feb 2018 10:49:01 -0500
Subject: Bug 510803 [GTK3] Regression in table editing capabilities in
tabfolder.
Breakage occurred because tabItem reparented an item that had a
non-standard gDk parent window.
Solution: fix gdk window parent for such special controls.
(I.e ControlEditors in tables).
Verification:
- Open child eclipse, change method signature.
Now table cells can be edited via click.
- Open attached snippet, with patch cells can be edited properly.
- AllTests Gtk3.22
- X11/Wayland.
Patchset 3:
- Minor rename of methods to clarify that it's a *gdk* window,
Bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=5108033
Change-Id: I8dcaac950eb0847dd97016b2140c607012550d2f
Signed-off-by: Leo Ufimtsev <lufimtse@redhat.com>
---
.../Eclipse SWT PI/gtk/library/os.c | 8 ++
.../gtk/org/eclipse/swt/internal/gtk/OS.java | 4 +
.../gtk/org/eclipse/swt/widgets/Composite.java | 10 ++
.../gtk/org/eclipse/swt/widgets/Control.java | 51 ++++++++-
.../gtk/org/eclipse/swt/widgets/ExpandItem.java | 2 +-
.../gtk/org/eclipse/swt/widgets/TabItem.java | 4 +-
.../gtk/org/eclipse/swt/widgets/Table.java | 6 +-
.../gtk/org/eclipse/swt/widgets/Tree.java | 6 +-
.../gtk/org/eclipse/swt/widgets/Widget.java | 15 ---
.../Bug510803_TabFolder_Table_inPlaceEditing.java | 108 ------------------
.../Bug510803_TabFolder_TreeEditor_Regression.java | 124 +++++++++++++++++++++
11 files changed, 203 insertions(+), 135 deletions(-)
delete mode 100644 tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug510803_TabFolder_Table_inPlaceEditing.java
create mode 100644 tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug510803_TabFolder_TreeEditor_Regression.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 bf5de70..428d448 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
@@ -13853,7 +13853,15 @@ JNIEXPORT void JNICALL OS_NATIVE(_1gtk_1widget_1reparent)
(JNIEnv *env, jclass that, jintLong arg0, jintLong arg1)
{
OS_NATIVE_ENTER(env, that, _1gtk_1widget_1reparent_FUNC);
+/*
gtk_widget_reparent((GtkWidget *)arg0, (GtkWidget *)arg1);
+*/
+ {
+ OS_LOAD_FUNCTION(fp, gtk_widget_reparent)
+ if (fp) {
+ ((void (CALLING_CONVENTION*)(GtkWidget *, GtkWidget *))fp)((GtkWidget *)arg0, (GtkWidget *)arg1);
+ }
+ }
OS_NATIVE_EXIT(env, that, _1gtk_1widget_1reparent_FUNC);
}
#endif
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 2619114..57bbf52 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
@@ -487,6 +487,16 @@ void fixChildren (Shell newShell, Shell oldShell, Decorations newDecorations, De
}
@Override
+void fixParentGdkWindow() {
+ assert OS.GTK3;
+ // Changes to this method should be verified via
+ // org.eclipse.swt.tests.gtk/*/Bug510803_TabFolder_TreeEditor_Regression.java (part two)
+ for (Control child : _getChildren()) {
+ child.fixParentGdkWindow();
+ }
+}
+
+@Override
void fixModal(long /*int*/ group, long /*int*/ modalGroup) {
Control[] controls = _getChildren ();
for (int i = 0; i < controls.length; i++) {
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 e29d144..b0768d5 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
@@ -2655,6 +2655,51 @@ void fixChildren (Shell newShell, Shell oldShell, Decorations newDecorations, De
oldDecorations.fixDecorations (newDecorations, this, menus);
}
+/**
+ * In some situations, a control has a non-standard parent GdkWindow (Note gDk, not gTk).
+ * E.g, an TreeEditor who's parent is a Tree should have the Tree Viewer's inner bin as parent window.
+ *
+ * Note, composites should treat this differently and take child controls into consideration.
+ */
+void fixParentGdkWindow() {
+ assert OS.GTK3;
+ // Changes to this method should be verified via
+ // org.eclipse.swt.tests.gtk/*/Bug510803_TabFolder_TreeEditor_Regression.java (part one)
+ parent.setParentGdkWindow(this);
+}
+
+/**
+ * Native gtkwidget re-parenting in SWT on Gtk3 needs to be handled in a special way because
+ * some controls have non-standard GdkWindow as parents. (E.g ControlEditors), and other controls
+ * like TabItem and ExpandBar use reparenting to preserve proper hierarchy for correct event traversal (like dnd).
+ *
+ * Note, GdkWindows != GtkWindows.
+ *
+ * You should never call gtk_widget_reparent() directly or reparent widgets outside this method,
+ * otherwise you can break TabItem/TreeEditors.
+ *
+ * @param control that should be reparented.
+ * @param newParentHandle pointer/handle to the new GtkWidget parent.
+ */
+static void gtk_widget_reparent (Control control, long /*int*/ newParentHandle) {
+ if (OS.GTK3) {
+ // Changes to this method should be verified via both parts in:
+ // org.eclipse.swt.tests.gtk/*/Bug510803_TabFolder_TreeEditor_Regression.java
+ long /*int*/ widget = control.topHandle();
+ long /*int*/ parentContainer = OS.gtk_widget_get_parent (widget);
+ assert parentContainer != 0 : "Improper use of Control.gtk_widget_reparent. Widget currently has no parent.";
+ if (parentContainer != 0) {
+ OS.g_object_ref (widget); //so that it won't get destroyed due to lack of references.
+ OS.gtk_container_remove (parentContainer, widget);
+ OS.gtk_container_add (newParentHandle, widget);
+ OS.g_object_unref (widget);
+ control.fixParentGdkWindow();
+ }
+ } else { // Gtk2.
+ OS.gtk_widget_reparent(control.topHandle(), newParentHandle);
+ }
+}
+
@Override
long /*int*/ fixedMapProc (long /*int*/ widget) {
OS.gtk_widget_set_mapped (widget, true);
@@ -5323,7 +5368,7 @@ public boolean setParent (Composite parent) {
oldDecorations.fixAccelGroup ();
}
long /*int*/ newParent = parent.parentingHandle();
- OS.gtk_widget_reparent(topHandle, newParent);
+ gtk_widget_reparent(this, newParent);
if (OS.GTK3) {
OS.swt_fixed_move (newParent, topHandle, x, y);
} else {
@@ -5361,7 +5406,7 @@ void setParentBackground () {
if (fixedHandle != 0) setBackgroundColor (fixedHandle, null);
}
-void setParentWindow (Control child) {
+void setParentGdkWindow (Control child) {
}
boolean setRadioSelection (boolean value) {
@@ -5777,7 +5822,7 @@ void showWidget () {
state |= ZERO_WIDTH | ZERO_HEIGHT;
long /*int*/ topHandle = topHandle ();
long /*int*/ parentHandle = parent.parentingHandle ();
- parent.setParentWindow (this);
+ parent.setParentGdkWindow (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/ExpandItem.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ExpandItem.java
index fcfbd33..6e48823 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ExpandItem.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ExpandItem.java
@@ -532,7 +532,7 @@ public void setControl (Control control) {
//As ExpandItem's child can be created before the ExpandItem, our only
//option is to reparent the child upon the setControl(..) call.
//This is simmilar to TabFolder.
- gtk_widget_reparent (control.topHandle (), clientHandle ());
+ Control.gtk_widget_reparent (control, clientHandle ());
}
}
parent.layoutItems (0, true);
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TabItem.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TabItem.java
index 208a373..ce9b4cc 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TabItem.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TabItem.java
@@ -293,8 +293,8 @@ public void setControl (Control control) {
}
if (control != null && OS.GTK3) {
- // See implementation note about bug 454936 at the start of TabFolder.
- OS.gtk_widget_reparent (control.topHandle (), pageHandle);
+ // To understand why we reparent, see implementation note about bug 454936 at the start of TabFolder.
+ Control.gtk_widget_reparent (control, pageHandle);
}
Control oldControl = this.control, newControl = control;
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 ccf01ec..c572e51 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
@@ -3726,9 +3726,9 @@ void setParentBackground () {
}
@Override
-void setParentWindow (Control child) {
- long /*int*/ window = eventWindow ();
- OS.gtk_widget_set_parent_window (child.topHandle(), window);
+void setParentGdkWindow (Control child) {
+ long /*int*/ parentGdkWindow = eventWindow ();
+ OS.gtk_widget_set_parent_window (child.topHandle(), parentGdkWindow);
/*
* Feature in GTK3: all children of Table have their GdkWindows
* re-parented so they are siblings of the parent Table
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 86b72a0..50de17c 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
@@ -3717,9 +3717,9 @@ void setParentBackground () {
}
@Override
-void setParentWindow (Control child) {
- long /*int*/ window = eventWindow ();
- OS.gtk_widget_set_parent_window (child.topHandle(), window);
+void setParentGdkWindow (Control child) {
+ long /*int*/ parentGdkWindow = eventWindow ();
+ OS.gtk_widget_set_parent_window (child.topHandle(), parentGdkWindow);
/*
* Feature in GTK3: all children of Tree have their GdkWindows
* re-parented so they are siblings of the parent Tree
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Widget.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Widget.java
index 40fe88c..2da1da5 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Widget.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Widget.java
@@ -951,21 +951,6 @@ long /*int*/ gtk_value_changed (long /*int*/ adjustment) {
return 0;
}
-/**
- * Reparent on gtk side.
- * Note: Composites with a setControl() function should probably use this function
- * to correct hierarchy on gtk side.
- * @param widget the handle to the widget. (usually topHandle())
- * @param newParent handle to the new widget.
- */
-void gtk_widget_reparent (long /*int*/ widget, long /*int*/ newParent) {
- //Note, we do not actually call * 'gtk_widget_reparent(...) as it's deprecated as of gtk 3.14
- OS.g_object_ref (widget); //so that it won't get destroyed due to lack of references.
- OS.gtk_container_remove (OS.gtk_widget_get_parent (widget), widget);
- OS.gtk_container_add (newParent, widget);
- OS.g_object_unref (widget);
-}
-
long /*int*/ gtk_window_state_event (long /*int*/ widget, long /*int*/ event) {
return 0;
}