Monday, April 02, 2007

Speech Bubble Update (with Drop Shadow)

I added a drop shadow to the speech bubble. You don't need it on OSX (OSX provides one automatically), and I don't have compiz or similar compositing window manager installed on linux at the moment (although if anyone is willing to submit/test the corresponding code, I'm happy to include it).

Nothing fancy, just black with 50% alpha. The shadow mask is just the original mask, sheared, scaled, and offset. The drop shadow would probably look nicer with a blurred edge, but that likely requires a variable alpha setting for the window (although you might be able to fake it by varying the edge color). Applying per-pixel alpha masks prior to Windows Vista seems to be non-trivial (this example uses a single alpha value for the entire window).

The JNA function definitions are trivial:

int GetWindowLongA(Pointer hWnd, int nIndex);
int SetWindowLongA(Pointer hWnd, int nIndex, int dwNewLong);
boolean SetLayeredWindowAttributes(Pointer hwnd, int crKey,
byte bAlpha, int dwFlags);

As is the actual usage:

Pointer hWnd = getHWnd(w);
User32 user = User32.INSTANCE;
int flags = user.GetWindowLongA(hWnd, User32.GWL_EXSTYLE) | User32.WS_EX_LAYERED;
user.SetWindowLongA(hWnd, User32.GWL_EXSTYLE, flags);
user.SetLayeredWindowAttributes(hWnd, 0, (byte)(255*alpha), User32.LWA_ALPHA);

The only real trick is that DirectDraw must be disabled in order to get the transparency effect and avoid leaving behind painting artifacts.

java -Dsun.java2d.noddraw=true ...

NOTE: thanks to l2fprod for the hint and the original round, transparent clock!

Update: Demo is now available from the JNA homepage.


Anonymous said...

Can you clear something for me. TO get this to work, I need to link to native libraries ? I think you have a slotuion for win, mac you said provides this by default, what about linux ? Will thi work on Linux or it needs to be linked against specific library ?

technomage said...

Yes, it will work with linux/x86. The point of this is to use a very small native stub to leverage any amount of native library access. Write the stub once, access native code anywhere without any additional JNI.

If you tried the link on the previous speech bubble post, you would SEE that it works with linux.

The only "linkage" required would be indicating where a particular native library is installed (in this case,, which is in different places on different linux installations) if it's not already in the system's library loading path.

Augusto Sellhorn said...

I believe Win2K and XP support per pixel alpha blending, via the UpdateLayeredWindow function.

Example here:

Google Desktop sidebar uses this feature, my best guess is they use UpdateLayeredWindow.

technomage said...

Thanks Augusto, I was looking for a working example of UpdateLayeredWindow, and this looks like it should work.

Augusto Sellhorn said...

I hope you post any progress you have with this function, I was looking for a while at how people implemented this, and the C# (and there's a C++ version of that same code) that I linked to is the best example I could find.

I'm not an expert at JNA so was trying to figure out how to map all params in Java.

technomage said...

The biggest problem I had was figuring out how to stuff a java.awt.Image into an HBITMAP. Anyhow, check out the latest post on this to see a working demo.