Eclipse 3.5 and GTK+ 2.18

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,

Share

One thought on “Eclipse 3.5 and GTK+ 2.18”

  1. Not surprisingly, this bug also broke Java RCP applications developed in Eclipse. Once it is fixed, it looks like RCP apps will need to be recompiled, perhaps in Eclipse 3.5.2 or 3.6.0. Progress can be painful!

Leave a Reply

Your email address will not be published. Required fields are marked *