Saturday, May 12, 2007

Easier Alpha Masks

The per-pixel alpha masking in this post has been codified into a simple API.

WindowUtils.setWindowTransparent(Window w, boolean transparent);

This effectively gives the window a transparent background. The alpha levels of the window's contents are preserved.

The demo is similar to the previous one but adds a few standard components to the mix.



UPDATE If you have a linux system and this for some reason doesn't work, please post a comment to that effect, or post a message to users@jna.dev.java.net so we can ensure this works reliably across all linux systems (64-bit is in the works).

26 comments:

Francis Perreault said...

Cool! Can't wait to try this. I've noticed that if you hover your mouse on the button, the transparency jumps back to 100% (i.e. no transparency). I'm running JRE 1.6.0_01 on XP. Could be triggered by the repainting of the button (it gets a yellowish border when mouse is over it), because I doubt this is as per design... Also, do you know if this will work with desklets from Josh M.'s Glossitope project ?

redsolo said...

Java source link is not working:

Authorization Required

This server could not verify that you are authorized to access the document requested. Either you supplied the wrong credentials (e.g., bad password), or your browser doesn't understand how to supply the credentials required.

Anonymous said...

Great stuff!

One small problem though:
When you start dragging the image, the transparency is set back to opaque.

technomage said...

Francis,
The alpha mask code is probably working at cross-purposes to the constant-alpha code, since on w32 they are two entirely different mechanisms. Shouldn't be that hard to fix.

Josh said he was going to put shaped/mask support into Glossitope for JavaOne, but I don't know if he got it done in time. Romain Guy did include it in his Rich Clients presentation.

redsolo,
You may need a dev.java.net account to see the source; you can also try navigating directly to http://jna.dev.java.net and follow the SCM/Subversion browsing links.

Anonymous said...

Can you post your code to glossitope.org? They urgently need it :-)

Francis Perreault said...

Looks like Josh started integrating some of your new stuff into its Glossitope project. Getting better and better!

Augusto said...

I use this in a JFX app I have, and get a weird stack trace. Any ideas, what's going on?

http://sellmic.com/lab/dev/jfx/clock/webstart/jna_stack_trace.txt

Here's the app ...
http://sellmic.com/blog/2007/05/22/javafx-clock-update-now-with-transparency/

technomage said...

You might try rebuilding the JNA example library from source. There have been significant changes to WindowUtils since the last library snapshot.

Seems odd that it's a generic "Exception" that's thrown...

Augusto said...

Thanks, downloaded the latest sources and recompiled (plus removed a lot of unused stuff in examples.jar) and it works great now.

Somebody posted on my blog they were having problems in Ubuntu, wish I had an install to try it out.

Thanks!!!

technomage said...

Wayne Meissner added some path searching code that should improve things for ubuntu users. A workaround for the old version is to set -Djna.library.path=/usr/lib and ensure that libX11.so is properly symlinked to libX11.so.6 (for some reason ubuntu doesn't do this while other distros do).

Augusto said...

Added that path, but yes seem Ubuntu doesn't do that symlink.

The new path searching code, is it in subversion?

I also installed Ubuntu on a virtual machine under XP, but after doing the symlink I got another exception asking about a render library. Symlinked that too, and got another error saying shaped/transparent windows are not supported.

technomage said...

The improved JNA path searching is in SVN. If you're using that and it doesn't work, please post to users@jna.dev.java.net.

Make sure you have xfce, beryl, compiz, or any other window manager installed which supports compositing.

I found xfce the easiest; it is the default with X-Ubuntu. The KDE wm should work as well.

JNA looks for a 32-bit X visual, if none is found you get the "not supported" error. Do "xdpyinfo" in a terminal and see if you get any 32-bit entries in the output.

Chavdar said...

I am using WindowUtils.setWindowTransparent(Window w, boolean transparent) in Macintosh.

I have a JFRame with JTextPane with JSCrollPane.

The vertical scrollbar doesn't work well.When i drag the thumb all the frame is moved.
Can you tell me what is the reason?

In windows i don't have such problem.

technomage said...

do Component.setBackground(new Color(0,0,0,0)) on the problematic frame, instead of WindowUtils.setTransparent(). Does the problem still occur? If so, report a bug to Apple at bugreporter.apple.com.

Thi said...

Problem :(
I got the AlphaMaskDemo2 and only replaced the image.
Everytime I use the WindowUtils.setWindowTransparent I get this error on console:

java.lang.Exception
at com.sun.jna.examples.WindowUtils$W32WindowUtils$W32RepaintTrigger.update(WindowUtils.java:510) at com.sun.jna.examples.WindowUtils$RepaintTrigger.paintComponent(WindowUtils.java:181)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JLayeredPane.paint(Unknown Source)

technomage said...

Pick up the most recent code from http://jna.dev.java.net and build from source. The issue you're seeing has been fixed there.

Thi said...

Thanks technomage, I got the WindowUtils source and it worked. But it still seems slow, when I click on a button it takes 1 second to execute it. This only happens when Im using the setWindowTransparent() method. Any idea?

technomage said...

Post you question with relevant details to the JNA user's list (users at jna.dev.java.net).

You may also find some useful info in the list archives; there have been some optimizations posted there.

Netbeans' profiler is very easy to use if you want to take a look at the performance yourself.

technomage said...

BTW, the exception posted to the console is only a debug stack trace that was inadvertently left in the code.

ZEN said...

Hi,

Ive built the latest source and when I use it in my app the widgets get painted only when you hover over them

I am using the WindowUtils.setWindowTransparent()on windows xp


Thanks,
Donny.

Anonymous said...

i'm running ubuntu6.10 .. i hope this is useful

Java Web Start 1.5.0_08
Using JRE version 1.6.0 Java HotSpot(TM) Client VM
User home directory = /home/something
----------------------------------------------------
c: clear console window
f: finalize objects on finalization queue
g: garbage collect
h: display this help message
m: print memory usage
o: trigger logging
p: reload proxy configuration
q: hide console
r: reload policy configuration
s: dump system and deployment properties
t: dump thread list
0-5: set trace level to
----------------------------------------------------
Exception in thread "AWT-EventQueue-0" java.lang.UnsatisfiedLinkError: X11
at com.sun.jna.Function.find(Native Method)
at com.sun.jna.Function.[init](Function.java:85)
at com.sun.jna.Function.[init](Function.java:59)
at com.sun.jna.Library$Handler.invoke(Library.java:192)
at $Proxy0.XOpenDisplay(Unknown Source)
at com.sun.jna.examples.WindowUtils$X11WindowUtils.getAlphaVisuals(WindowUtils.java:863)
at com.sun.jna.examples.WindowUtils$X11WindowUtils.isWindowAlphaSupported(WindowUtils.java:821)
at com.sun.jna.examples.WindowUtils$X11WindowUtils.getAlphaCompatibleGraphicsConfiguration(WindowUtils.java:828)
at com.sun.jna.examples.WindowUtils.getAlphaCompatibleGraphicsConfiguration(WindowUtils.java:1097)
at com.sun.jna.examples.AlphaMaskDemo2.run(AlphaMaskDemo2.java:107)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

technomage said...

More recent builds of JNA address this automatically, but what you are missing on your ubuntu system is symlinks like this:

libX11.so -> libX11.so.6.0.1
libXext.so -> libXext.so.6.0.1

These are usually included in the developer X11 packages, but not in a vanilla install.

The lack of symlinks is handled automagically in later JNA builds, so the demo will just work whether or not you have the symlinks.

led said...

i got the same problem that zen

Ive built the latest source and when i use a jButton its not rendering very well. just some times when i roll over or when i click. a very strange behavior...

I am using the WindowUtils.setWindowTransparent()on windows xp

Adnan said...

i get the following error when i use this function

Exception in thread "main" java.lang.IllegalArgumentException: Window GraphicsConfiguration 'X11GraphicsConfig[dev=X11GraphicsDevice[screen=0],vis=0x23]' does not support transparency
at com.sun.jna.examples.WindowUtils$X11WindowUtils.setWindowTransparent(WindowUtils.java:1369)
at com.sun.jna.examples.WindowUtils.setWindowTransparent(WindowUtils.java:1510)
at MainClass$TransparentScreen.<init>(MainClass.java:123)
at MainClass.main(MainClass.java:55)

but i can make any window transparent by clicking alt and mouse scroll down which means transparency is supported on my system.

I am using Ubuntu 8.04

technomage said...

You need to create your window or frame with a proper GraphicsConfiguration argument obtained via WindowUtils.getAlphaCompatibleGraphicsConfiguration(). Otherwise the GC you obtain will likely lack an alpha channel.

bdk said...

Finally Sun officially implemented transparent/shaped window support in JDK 7
(was also already present in JDK 6_10)

(see here)