Category Archives: Software

Eclipse crashes with Lucid

Update: it seems like a lot of people find this useful. With the final release of Ubuntu 10.04 Lucid Lynx, xulrunner-1.9.2 is in the main repository. Because of this, just uninstall xulrunner-1.9.1 and you’re done.

I like living on the edge: I use Ubuntu Lucid and Eclipse 3.6M5 on my x86-64 notebook. Since the 25th of February, Eclipse started crashing when closing the content assist popup window. I narrowed it down to the upgrade to libcairo2-1.8.10-2ubuntu1. This causes a RenderBadPicture X Error when the documentation popup that appears on the right of the possible completions is closed. Downgrading to libcairo2-1.8.8 solved the problem, but it seems that the real problem lies within xulrunner 1.9.1 which SWT uses to render the docs. The Mozilla bug is https://bugzilla.mozilla.org/show_bug.cgi?id=522635. A quick workaround is to set the GRE_HOME environment variable to some meaningless path (e.g. /tmp) before launching Eclipse. Another possible solution is to install xulrunner-1.9.2 (only available from the mozilla-daily-ppa). I have filed a bug report un Launchpad asking for an official upgrade to xulrunner 1.9.2.

Share

XBMC+NVIDIA+DynamicTwinView = Wrong refresh rate

I was wondering why I got tearing with XBMC even though I had enabled vsync and why XBMC was reporting a refresh rate of 50Hz for my screen instead of 75Hz as it should have been. It turns out that NVIDIA’s DynamicTwinView feature reports a fake refresh rate (that of the MetaMode which encompasses all of the screens involved in the TwinView) which may not be the one for the physical device. As I am not using TwinView I added the following Option to my xorg.conf Device section:

Option "DynamicTwinView" "False"
Share

Static resources versioning in web applications

I recently had trouble with a Javascript-heavy application which was deployed to the end users quite frequently in its initial stages. The problem was that users were seeing bugs which had been fixed with the latest release and that was because their browsers were caching the static resources of the web application for too long. A forced refresh (Ctrl+F5 or Ctrl+R) solved the problem but I wanted a better, automatic way.

The solution was to add a version to the path of each static resource and then use url rewriting to get the real file. In practice in my HTML I refer to resources like this:


In my case the 1.0.6 is the pom.version which I get using Maven resource filtering. I then use the wonderful URL Rewrite Filter (but I could also have used Apache’s mod_rewrite ) to rewrite URLs matching

^/[0-9]+[a-zA-Z0-9\.\-]+/(js|css|img)/(.*)$

to

/$1/$2

I think I’ll go back and apply this fix to all my apps 🙂

Share

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

Avoid roaming with Network Manager and HSDPA/3G dongles

Today a friend of mine asked if I knew a way to avoid connection via his HSDPA/3G dongle when in roaming: he uses Italy’s Tre network, and sometimes the connection will fall back to TIM or Vodafone, which he wants to avoid because of increased costs.

I’ve discovered that in GNOME’s Network Manager connection editor you can force a network by inserting the MCC/MNC (Mobile Network Codes), a list of which can be found at http://www.flatbatt.co.uk/Unlocking/Network_codes/network_codes.html

Editing a mobile connection to Vodafone Italy
Editing a mobile connection to Vodafone Italy
Share

Canyon: more JSR-223 and the SimpleBindings

In order to make the widgets available as object during script execution, I have extended javax.script.SimpleBindings so that I lookup keys in the widget hierarchy before handing it down to the backing map by overriding the get() method. This was how I did it when using the Groovy implementation directly. I have discovered that javax.script requires that I override containsKey() as well as get(), otherwise it doesn’t even attempt to invoke get(). Now that is fixed in SVN and I am nearing the first public release of Canyon.

Share

Canyon: JSR-223

Canyon is my implementation of the concepts behind various kinds of XML-based application interface tools (XAML, Flash MXML, ZK, etc).
Canyon started off as a way to describe Echo2 (http://echo.nextapp.com) applications using XML bound together with Groovy (http://groovy.codehaus.org) scripts.
Recently I’ve been working on refactoring Canyon to support multiple widget libraries (Echo2, Cooee, Echo3, Swing, SWT, etc) and JSR-223 (aka javax.script) instead of just Groovy. Currently canyon and its bits are available on Sourceforge SVN (http://sourceforge.net/projects/canyon).

I promise I will hopefully get a half-way decent site for all these projects of mine and create some sort of community going.

Share

WARShield: progress

The WARShield stuff progresses nicely: it now implements most of the feature-set I had in mind.

I have also implemented an event/listener method so that other ContextListeners / Servlets /Filters can get notified when the configuration is readily available, changes, etc.

Currently the configuration is stored in a single properties file, but I am adding a “multi-resource” method so that applications supply a set of template files which get populated with the configuration data (similar to the maven resource filtering by using the ${} notation).

I plan on adding hooks for containers such as Spring, so that they look for their data in the appropriate place and wait until the configuration is ready before reading it.

Share