Since GTK+ 2.18 has introduced Client Side Windows, a couple of problems have appeared in Eclipse 3.5. One of them was resolved in GTK+ 2.18.0 (https://bugzilla.gnome.org/show_bug.cgi?id=589963), the other one needs fixing at the SWT-level (https://bugs.eclipse.org/bugs/show_bug.cgi?id=287307)
Since I don’t want to run Eclipse 3.6 milestones yet, I created a small diff between the two SWT versions (3.5.1 and 3.6) and isolated the necessary changes. I am currently running Eclipse 3.5.1 with this patch on my Ubuntu Karmic installation, and it fixes the problem.
Here is the diff:
diff -urN swt-3.5/org/eclipse/swt/internal/gtk/OS.java swt-3.6/org/eclipse/swt/internal/gtk/OS.java
— swt-3.5/org/eclipse/swt/internal/gtk/OS.java 2009-08-20 15:16:38.000000000 +0200
+++ swt-3.6/org/eclipse/swt/internal/gtk/OS.java 2009-09-17 05:24:42.000000000 +0200
@@ -4887,6 +4885,21 @@
lock.unlock();
}
}
+/**
+ * @method flags=dynamic
+ * @param window cast=(GdkWindow *)
+ * @param sibling cast=(GdkWindow *)
+ * @param above cast=(gboolean)
+ */
+public static final native void _gdk_window_restack(int /*long*/ window, int /*long*/ sibling, boolean above);
+public static final void gdk_window_restack(int /*long*/ window, int /*long*/ sibling, boolean above) {
+ lock.lock();
+ try {
+ _gdk_window_restack(window, sibling, above);
+ } finally {
+ lock.unlock();
+ }
+}
/** @param window cast=(GdkWindow *) */
public static final native void _gdk_window_scroll(int /*long*/ window, int dx, int dy);
public static final void gdk_window_scroll(int /*long*/ window, int dx, int dy) {
diff -urN swt-3.5/org/eclipse/swt/widgets/Control.java swt-3.6/org/eclipse/swt/widgets/Control.java
— swt-3.5/org/eclipse/swt/widgets/Control.java 2009-08-07 14:50:38.000000000 +0200
+++ swt-3.6/org/eclipse/swt/widgets/Control.java 2009-09-17 05:24:42.000000000 +0200
@@ -3332,6 +3319,30 @@
region = null;
}
+void restackWindow (int /*long*/ window, int /*long*/ sibling, boolean above) {
+ if (OS.GTK_VERSION >= OS.VERSION (2, 17, 11)) {
+ OS.gdk_window_restack (window, sibling, above);
+ } else {
+ /*
+ * Feature in X. If the receiver is a top level, XConfigureWindow ()
+ * will fail (with a BadMatch error) for top level shells because top
+ * level shells are reparented by the window manager and do not share
+ * the same X window parent. This is the correct behavior but it is
+ * unexpected. The fix is to use XReconfigureWMWindow () instead.
+ * When the receiver is not a top level shell, XReconfigureWMWindow ()
+ * behaves the same as XConfigureWindow ().
+ */
+ int /*long*/ xDisplay = OS.gdk_x11_drawable_get_xdisplay (window);
+ int /*long*/ xWindow = OS.gdk_x11_drawable_get_xid (window);
+ int xScreen = OS.XDefaultScreen (xDisplay);
+ int flags = OS.CWStackMode | OS.CWSibling;
+ XWindowChanges changes = new XWindowChanges ();
+ changes.sibling = OS.gdk_x11_drawable_get_xid (sibling);
+ changes.stack_mode = above ? OS.Above : OS.Below;
+ OS.XReconfigureWMWindow (xDisplay, xWindow, xScreen, flags, changes);
+ }
+ }
+
boolean sendDragEvent (int button, int stateMask, int x, int y, boolean isStateMask) {
Event event = new Event ();
event.button = button;
@@ -3682,15 +3693,7 @@
if (!OS.GDK_WINDOWING_X11 ()) {
OS.gdk_window_raise (enableWindow);
} else {
– int /*long*/ topWindow = OS.GTK_WIDGET_WINDOW (topHandle);
– int /*long*/ xDisplay = OS.gdk_x11_drawable_get_xdisplay (topWindow);
– int /*long*/ xWindow = OS.gdk_x11_drawable_get_xid (enableWindow);
– int xScreen = OS.XDefaultScreen (xDisplay);
– int flags = OS.CWStackMode | OS.CWSibling;
– XWindowChanges changes = new XWindowChanges ();
– changes.sibling = OS.gdk_x11_drawable_get_xid (topWindow);
– changes.stack_mode = OS.Above;
– OS.XReconfigureWMWindow (xDisplay, xWindow, xScreen, flags, changes);
+ restackWindow (enableWindow, OS.GTK_WIDGET_WINDOW (topHandle), true);
}
if (OS.GTK_WIDGET_VISIBLE (topHandle)) OS.gdk_window_show_unraised (enableWindow);
}
@@ -4170,29 +4173,12 @@
OS.gdk_window_lower (window);
}
} else {
– XWindowChanges changes = new XWindowChanges ();
– changes.sibling = OS.gdk_x11_drawable_get_xid (siblingWindow != 0 ? siblingWindow : redrawWindow);
– changes.stack_mode = above ? OS.Above : OS.Below;
– if (redrawWindow != 0 && siblingWindow == 0) changes.stack_mode = OS.Below;
– int /*long*/ xDisplay = OS.gdk_x11_drawable_get_xdisplay (window);
– int /*long*/ xWindow = OS.gdk_x11_drawable_get_xid (window);
– int xScreen = OS.XDefaultScreen (xDisplay);
– int flags = OS.CWStackMode | OS.CWSibling;
– /*
– * Feature in X. If the receiver is a top level, XConfigureWindow ()
– * will fail (with a BadMatch error) for top level shells because top
– * level shells are reparented by the window manager and do not share
– * the same X window parent. This is the correct behavior but it is
– * unexpected. The fix is to use XReconfigureWMWindow () instead.
– * When the receiver is not a top level shell, XReconfigureWMWindow ()
– * behaves the same as XConfigureWindow ().
– */
– OS.XReconfigureWMWindow (xDisplay, xWindow, xScreen, flags, changes);
+ int /*long*/ siblingW = siblingWindow != 0 ? siblingWindow : redrawWindow;
+ boolean stack_mode = above;
+ if (redrawWindow != 0 && siblingWindow == 0) stack_mode = false;
+ restackWindow (window, siblingW, stack_mode);
if (enableWindow != 0) {
– changes.sibling = OS.gdk_x11_drawable_get_xid (window);
– changes.stack_mode = OS.Above;
– xWindow = OS.gdk_x11_drawable_get_xid (enableWindow);
– OS.XReconfigureWMWindow (xDisplay, xWindow, xScreen, flags, changes);
+ restackWindow (enableWindow, window, true);
}
}
}
diff -urN swt-3.5/os.c swt-3.6/os.c
— swt-3.5/os.c 2009-05-29 17:30:14.000000000 +0200
+++ swt-3.6/os.c 2009-09-17 05:24:42.000000000 +0200
@@ -5944,6 +5932,24 @@
}
#endif
+#ifndef NO__1gdk_1window_1restack
+JNIEXPORT void JNICALL OS_NATIVE(_1gdk_1window_1restack)
+ (JNIEnv *env, jclass that, jintLong arg0, jintLong arg1, jboolean arg2)
+{
+ OS_NATIVE_ENTER(env, that, _1gdk_1window_1restack_FUNC);
+/*
+ gdk_window_restack((GdkWindow *)arg0, (GdkWindow *)arg1, (gboolean)arg2);
+*/
+ {
+ LOAD_FUNCTION(fp, gdk_window_restack)
+ if (fp) {
+ ((void (CALLING_CONVENTION*)(GdkWindow *, GdkWindow *, gboolean))fp)((GdkWindow *)arg0, (GdkWindow *)arg1, (gboolean)arg2);
+ }
+ }
+ OS_NATIVE_EXIT(env, that, _1gdk_1window_1restack_FUNC);
+}
+#endif
+
#ifndef NO__1gdk_1window_1scroll
JNIEXPORT void JNICALL OS_NATIVE(_1gdk_1window_1scroll)
(JNIEnv *env, jclass that, jintLong arg0, jint arg1, jint arg2)
diff -urN swt-3.5/os_custom.h swt-3.6/os_custom.h
— swt-3.5/os_custom.h 2009-05-29 17:30:14.000000000 +0200
+++ swt-3.6/os_custom.h 2009-09-17 05:24:42.000000000 +0200
@@ -112,6 +113,7 @@
#define gtk_status_icon_set_tooltip_LIB “libgtk-x11-2.0.so.0”
#define gtk_window_get_group_LIB “libgtk-x11-2.0.so.0”
#define gtk_window_get_opacity_LIB “libgtk-x11-2.0.so.0”
+#define gdk_window_restack_LIB “libgdk-x11-2.0.so.0”
#define gdk_window_set_keep_above_LIB “libgdk-x11-2.0.so.0”
#define gdk_window_set_accept_focus_LIB “libgdk-x11-2.0.so.0”
#define gtk_window_set_opacity_LIB “libgtk-x11-2.0.so.0”
diff -urN swt-3.5/os_stats.c swt-3.6/os_stats.c
— swt-3.5/os_stats.c 2009-05-29 17:30:14.000000000 +0200
+++ swt-3.6/os_stats.c 2009-09-17 05:24:42.000000000 +0200
@@ -18,8 +18,8 @@
#ifdef NATIVE_STATS
-int OS_nativeFunctionCount = 1291;
-int OS_nativeFunctionCallCount[1291];
+int OS_nativeFunctionCount = 1292;
+int OS_nativeFunctionCallCount[1292];
char * OS_nativeFunctionNames[] = {
#ifndef JNI64
“Call__IIII”,
@@ -503,6 +502,7 @@
“_1gdk_1window_1raise”,
“_1gdk_1window_1remove_1filter”,
“_1gdk_1window_1resize”,
+ “_1gdk_1window_1restack”,
“_1gdk_1window_1scroll”,
“_1gdk_1window_1set_1accept_1focus”,
“_1gdk_1window_1set_1back_1pixmap”,
diff -urN swt-3.5/os_stats.h swt-3.6/os_stats.h
— swt-3.5/os_stats.h 2009-05-29 17:30:14.000000000 +0200
+++ swt-3.6/os_stats.h 2009-09-17 05:24:42.000000000 +0200
@@ -511,6 +510,7 @@
_1gdk_1window_1raise_FUNC,
_1gdk_1window_1remove_1filter_FUNC,
_1gdk_1window_1resize_FUNC,
+ _1gdk_1window_1restack_FUNC,
_1gdk_1window_1scroll_FUNC,
_1gdk_1window_1set_1accept_1focus_FUNC,
_1gdk_1window_1set_1back_1pixmap_FUNC,