365 lines
16 KiB
Diff
365 lines
16 KiB
Diff
From 4b0412b94e47be8f2c5480568a36ec71809a148f Mon Sep 17 00:00:00 2001
|
|
From: Eric Williams
|
|
Date: Fri, 23 Mar 2018 16:12:53 -0400
|
|
Subject: Bug 531928: [GTK3] Table editing is broken
|
|
|
|
The fix for bug 511133 introduced some logic which raises/lowers the
|
|
GdkWindows of widgets who are children of Table or Tree. Unforunately,
|
|
this breaks certain cases such as Tables/Trees that have more than one
|
|
child widget.
|
|
|
|
Additionally, changing the drawing handle from fixedHandle to handle
|
|
meant that some child widgets were not getting their draw events
|
|
properly. According to GTK, child widgets with non-native windows should
|
|
receive draw events from their parent containers using
|
|
gtk_container_propagate_draw(). This patch follows this advice and
|
|
connects a Table/Tree's fixedHandle to the draw signal. The incoming
|
|
draw events to that fixedHandle are then propagated to the respective
|
|
child widgets using gtk_container_propagate_draw().
|
|
|
|
A reproducer snippet is attached. This patch also fixes a regression
|
|
from bug 511133 which caused the file permissions table (right click
|
|
file -> properties -> resources) to be empty/contain only one checkbox.
|
|
|
|
Change-Id: I645a04df6773372aa27a360d3df9a3521437828f
|
|
Signed-off-by: Eric Williams <ericwill@redhat.com>---
|
|
.../Eclipse SWT PI/gtk/library/os.c | 18 ++++
|
|
.../Eclipse SWT PI/gtk/library/os_stats.c | 1 +
|
|
.../Eclipse SWT PI/gtk/library/os_stats.h | 1 +
|
|
.../gtk/org/eclipse/swt/internal/gtk/OS.java | 15 ++++
|
|
.../gtk/org/eclipse/swt/widgets/Composite.java | 44 ++++++++++
|
|
.../gtk/org/eclipse/swt/widgets/Control.java | 14 ----
|
|
.../gtk/org/eclipse/swt/widgets/Table.java | 32 ++++---
|
|
.../gtk/org/eclipse/swt/widgets/TableItem.java | 3 -
|
|
.../gtk/org/eclipse/swt/widgets/Tree.java | 32 ++++---
|
|
.../gtk/org/eclipse/swt/widgets/TreeItem.java | 3 -
|
|
.../Bug531928_TableTreeEditorVisibility.java | 98 ++++++++++++++++++++++
|
|
11 files changed, 219 insertions(+), 42 deletions(-)
|
|
create mode 100644 tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug531928_TableTreeEditorVisibility.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 cb6b841..5fc92d0 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
|
|
@@ -8497,6 +8497,24 @@ JNIEXPORT jintLong JNICALL OS_NATIVE(_1gtk_1container_1get_1children)
|
|
}
|
|
#endif
|
|
|
|
+#ifndef NO__1gtk_1container_1propagate_1draw
|
|
+JNIEXPORT void JNICALL OS_NATIVE(_1gtk_1container_1propagate_1draw)
|
|
+ (JNIEnv *env, jclass that, jintLong arg0, jintLong arg1, jintLong arg2)
|
|
+{
|
|
+ OS_NATIVE_ENTER(env, that, _1gtk_1container_1propagate_1draw_FUNC);
|
|
+/*
|
|
+ gtk_container_propagate_draw((GtkContainer *)arg0, (GtkWidget *)arg1, (cairo_t *)arg2);
|
|
+*/
|
|
+ {
|
|
+ OS_LOAD_FUNCTION(fp, gtk_container_propagate_draw)
|
|
+ if (fp) {
|
|
+ ((void (CALLING_CONVENTION*)(GtkContainer *, GtkWidget *, cairo_t *))fp)((GtkContainer *)arg0, (GtkWidget *)arg1, (cairo_t *)arg2);
|
|
+ }
|
|
+ }
|
|
+ OS_NATIVE_EXIT(env, that, _1gtk_1container_1propagate_1draw_FUNC);
|
|
+}
|
|
+#endif
|
|
+
|
|
#ifndef NO__1gtk_1container_1remove
|
|
JNIEXPORT void JNICALL OS_NATIVE(_1gtk_1container_1remove)
|
|
(JNIEnv *env, jclass that, jintLong arg0, jintLong arg1)
|
|
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 ebfe993..98f36e6 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
|
|
@@ -680,6 +680,7 @@ char * GTK_nativeFunctionNames[] = {
|
|
"_1gtk_1container_1forall",
|
|
"_1gtk_1container_1get_1border_1width",
|
|
"_1gtk_1container_1get_1children",
|
|
+ "_1gtk_1container_1propagate_1draw",
|
|
"_1gtk_1container_1remove",
|
|
"_1gtk_1container_1set_1border_1width",
|
|
"_1gtk_1css_1provider_1get_1named",
|
|
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 f707a39..97f4d14 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
|
|
@@ -690,6 +690,7 @@ typedef enum {
|
|
_1gtk_1container_1forall_FUNC,
|
|
_1gtk_1container_1get_1border_1width_FUNC,
|
|
_1gtk_1container_1get_1children_FUNC,
|
|
+ _1gtk_1container_1propagate_1draw_FUNC,
|
|
_1gtk_1container_1remove_FUNC,
|
|
_1gtk_1container_1set_1border_1width_FUNC,
|
|
_1gtk_1css_1provider_1get_1named_FUNC,
|
|
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java
|
|
index cc80140..78ba8d3 100644
|
|
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java
|
|
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java
|
|
@@ -6915,6 +6915,21 @@ public class GTK extends OS {
|
|
lock.unlock();
|
|
}
|
|
}
|
|
+ /**
|
|
+ * @method flags=dynamic
|
|
+ * @param container cast=(GtkContainer *)
|
|
+ * @param child cast=(GtkWidget *)
|
|
+ * @param cairo cast=(cairo_t *)
|
|
+ */
|
|
+ public static final native void _gtk_container_propagate_draw(long /*int*/ container, long /*int*/ child, long /*int*/ cairo);
|
|
+ public static final void gtk_container_propagate_draw(long /*int*/ container, long /*int*/ child, long /*int*/ cairo) {
|
|
+ lock.lock();
|
|
+ try {
|
|
+ _gtk_container_propagate_draw(container, child, cairo);
|
|
+ } finally {
|
|
+ lock.unlock();
|
|
+ }
|
|
+ }
|
|
/** @param container cast=(GtkContainer *) */
|
|
public static final native int _gtk_container_get_border_width(long /*int*/ container);
|
|
public static final int gtk_container_get_border_width(long /*int*/ container) {
|
|
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 57bbf52..bd253c4 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
|
|
@@ -1393,6 +1393,50 @@ void printWidget (GC gc, long /*int*/ drawable, int depth, int x, int y) {
|
|
newClip.dispose ();
|
|
}
|
|
|
|
+/**
|
|
+ * Connects this widget's fixedHandle to the "draw" signal.<br>
|
|
+ * NOTE: only the "draw" (EXPOSE) signal is connected, not EXPOSE_EVENT_INVERSE.
|
|
+ */
|
|
+void connectFixedHandleDraw () {
|
|
+ long /*int*/ paintHandle = fixedHandle;
|
|
+ int paintMask = OS.GDK_EXPOSURE_MASK;
|
|
+ OS.gtk_widget_add_events (paintHandle, paintMask);
|
|
+
|
|
+ OS.g_signal_connect_closure_by_id (paintHandle, display.signalIds [DRAW], 0, display.getClosure (DRAW), true);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * <p>Propagates draw events from a parent container to its children using
|
|
+ * gtk_container_propagate_draw(). This method only works if the fixedHandle
|
|
+ * has been connected to the "draw" signal, and only propagates draw events
|
|
+ * to other siblings of handle (i.e. other children of fixedHandle, but not
|
|
+ * handle itself).</p>
|
|
+ *
|
|
+ * <p>It's useful to propagate draw events to other child widgets for things
|
|
+ * like Table/Tree editors, or other scenarios where a widget is a child of
|
|
+ * a non-standard container widget (i.e., not a direct child of a Composite).</p>
|
|
+ *
|
|
+ * @param container the parent container, i.e. fixedHandle
|
|
+ * @param cairo the cairo context provided by GTK
|
|
+ */
|
|
+void propagateDraw (long /*int*/ container, long /*int*/ cairo) {
|
|
+ if (container == fixedHandle && OS.GTK3) {
|
|
+ long /*int*/ list = OS.gtk_container_get_children (container);
|
|
+ long /*int*/ temp = list;
|
|
+ while (temp != 0) {
|
|
+ long /*int*/ child = OS.g_list_data (temp);
|
|
+ if (child != 0) {
|
|
+ Widget widget = display.getWidget (child);
|
|
+ if (widget != this) {
|
|
+ OS.gtk_container_propagate_draw(container, child, cairo);
|
|
+ }
|
|
+ }
|
|
+ temp = OS.g_list_next (temp);
|
|
+ }
|
|
+ OS.g_list_free (list);
|
|
+ }
|
|
+}
|
|
+
|
|
@Override
|
|
void redrawChildren () {
|
|
super.redrawChildren ();
|
|
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 7971ff6..f075de8 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
|
|
@@ -5537,13 +5537,6 @@ 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 {
|
|
@@ -5580,13 +5573,6 @@ 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);
|
|
}
|
|
}
|
|
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 a64bdfc..dff41bd 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
|
|
@@ -85,7 +85,7 @@ public class Table extends Composite {
|
|
GdkRGBA background, foreground;
|
|
Color headerBackground, headerForeground;
|
|
String headerCSSBackground, headerCSSForeground;
|
|
- boolean ownerDraw, ignoreSize, ignoreAccessibility, pixbufSizeSet;
|
|
+ boolean ownerDraw, ignoreSize, ignoreAccessibility, pixbufSizeSet, hasChildren;
|
|
int maxWidth = 0;
|
|
int topIndex;
|
|
double cachedAdjustment, currentAdjustment;
|
|
@@ -3653,18 +3653,18 @@ 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
|
|
- * (i.e. on the same level in the z-order).
|
|
+ * Feature in GTK3: non-native GdkWindows are not drawn implicitly
|
|
+ * as of GTK3.10+. It is the client's responsibility to propagate draw
|
|
+ * events to these windows in the "draw" signal handler.
|
|
*
|
|
- * 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.
|
|
+ * This change breaks table editing on GTK3.10+, as the table editor
|
|
+ * widgets no longer receive draw signals. The fix is to connect the
|
|
+ * Table's fixedHandle to the draw signal, and propagate the draw
|
|
+ * signal using gtk_container_propagate_draw(). See bug 531928.
|
|
*/
|
|
- if (child != null && OS.GTK3) {
|
|
- child.reparentOnVisibility = true;
|
|
+ if (OS.GTK_VERSION >= OS.VERSION(3, 10, 0)) {
|
|
+ hasChildren = true;
|
|
+ connectFixedHandleDraw();
|
|
}
|
|
}
|
|
|
|
@@ -4080,6 +4080,16 @@ void updateScrollBarValue (ScrollBar bar) {
|
|
@Override
|
|
long /*int*/ windowProc (long /*int*/ handle, long /*int*/ arg0, long /*int*/ user_data) {
|
|
switch ((int)/*64*/user_data) {
|
|
+ case EXPOSE_EVENT: {
|
|
+ /*
|
|
+ * If this Table has any child widgets, propagate the draw signal
|
|
+ * to them using gtk_container_propagate_draw(). See bug 531928.
|
|
+ */
|
|
+ if (OS.GTK_VERSION >= OS.VERSION(3, 10, 0) && hasChildren) {
|
|
+ propagateDraw(handle, arg0);
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
case EXPOSE_EVENT_INVERSE: {
|
|
/*
|
|
* Feature in GTK. When the GtkTreeView has no items it does not propagate
|
|
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 a1d3b89..c6031d2 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
|
|
@@ -331,9 +331,6 @@ Rectangle getBoundsinPixels () {
|
|
}
|
|
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 6644346..1842b84 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
|
|
@@ -91,7 +91,7 @@ public class Tree extends Composite {
|
|
int drawState, drawFlags;
|
|
GdkColor drawForeground;
|
|
GdkRGBA background, foreground;
|
|
- boolean ownerDraw, ignoreSize, ignoreAccessibility, pixbufSizeSet;
|
|
+ boolean ownerDraw, ignoreSize, ignoreAccessibility, pixbufSizeSet, hasChildren;
|
|
int pixbufHeight, pixbufWidth;
|
|
TreeItem topItem;
|
|
double cachedAdjustment, currentAdjustment;
|
|
@@ -3658,18 +3658,18 @@ 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
|
|
- * (i.e. on the same level in the z-order).
|
|
+ * Feature in GTK3: non-native GdkWindows are not drawn implicitly
|
|
+ * as of GTK3.10+. It is the client's responsibility to propagate draw
|
|
+ * events to these windows in the "draw" signal handler.
|
|
*
|
|
- * 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.
|
|
+ * This change breaks tree editing on GTK3.10+, as the tree editor
|
|
+ * widgets no longer receive draw signals. The fix is to connect the
|
|
+ * Tree's fixedHandle to the draw signal, and propagate the draw
|
|
+ * signal using gtk_container_propagate_draw(). See bug 531928.
|
|
*/
|
|
- if (child != null && OS.GTK3) {
|
|
- child.reparentOnVisibility = true;
|
|
+ if (OS.GTK_VERSION >= OS.VERSION(3, 10, 0)) {
|
|
+ hasChildren = true;
|
|
+ connectFixedHandleDraw();
|
|
}
|
|
}
|
|
|
|
@@ -4010,6 +4010,16 @@ void updateScrollBarValue (ScrollBar bar) {
|
|
@Override
|
|
long /*int*/ windowProc (long /*int*/ handle, long /*int*/ arg0, long /*int*/ user_data) {
|
|
switch ((int)/*64*/user_data) {
|
|
+ case EXPOSE_EVENT: {
|
|
+ /*
|
|
+ * If this Tree has any child widgets, propagate the draw signal
|
|
+ * to them using gtk_container_propagate_draw(). See bug 531928.
|
|
+ */
|
|
+ if (OS.GTK_VERSION >= OS.VERSION(3, 10, 0) && hasChildren) {
|
|
+ propagateDraw(handle, arg0);
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
case EXPOSE_EVENT_INVERSE: {
|
|
/*
|
|
* Feature in GTK. When the GtkTreeView has no items it does not propagate
|
|
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 03b847c..66307f8 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
|
|
@@ -517,9 +517,6 @@ Rectangle getBoundsInPixels () {
|
|
}
|
|
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 PI/gtk/library/os_custom.h b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.h
|
|
index ddb326e..43acdb3 100644
|
|
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.h
|
|
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.h
|
|
@@ -255,6 +255,8 @@
|
|
#define gdk_cairo_create_LIB LIB_GDK
|
|
#define gdk_colormap_alloc_color_LIB LIB_GDK
|
|
#define gdk_colormap_free_colors_LIB LIB_GDK
|
|
+#define gtk_container_propagate_draw_LIB LIB_GTK
|
|
+#define gtk_widget_reparent_LIB LIB_GTK
|
|
#define gtk_paint_box_LIB LIB_GTK
|
|
#define gtk_paint_handle_LIB LIB_GTK
|
|
#define gtk_paint_focus_LIB LIB_GTK
|