Cacio Swing AWT peers

The last couple of days, I was shitting out^W^W writing some new interesting stuff for Caciocavallo. Inspired by the old Swing based AWT peers of GNU Classpath, and the X11 peers of OpenJDK, here comes the shiny new Swing based AWT peers of Caciocavallo and OpenJDK.

The idea

.. is this: implement a set of AWT widget peers, which are not backed up by Motif, Win32, GTK or Qt (the traditional implementations of (Open)JDK and GNU Classpath), but, as the names says, by Swing! This probably sounds a little weird. Isn’t Swing built on top of AWT? How can I then build AWT on top of Swing? Yeah, I admit, there’s some magic and wizardry involved here, but the general idea is this: Swing is not really based on AWT (as: AWT, the widget set), Swing basically only uses the Java2D implementation and the toplevel widgets (Window, Frame and Dialog) from AWT. All the widgets (buttons, labels, textareas, etc) are implemented separately (using only a little bit of common infrastructure from Component, Container and for the event handling). So it should be possible to build AWT peers, that use Swing components for drawing and for handling the logic. This is particularily cool for platforms that don’t have any native widget set (that is, most of the platforms I usually work on: they only barely have a screen to draw on, no desktop, no widgets, etc).

For people that followed my blog in the past, this should not be so much news. In GNU Classpath we already had an implementation of this idea for a long time, and it was working quite well – to some degree. At some point, some problems were popping up, which were related to some special behaviour of heavyweight components. Back then, I added some workarounds to ’emulate’ this behavious, but it was becoming worse and worse. Examples of this behaviour are: Making a component invisible must expose the underlying heavyweight. Lightweights are always painted on top of their containing heavyweight (try mixing Swing and AWT widgets in a hierarchy – it’s fun!)

I was ‘enlightened’ when I studied OpenJDK’s X11 peers. The trick was to make all AWT components live in their own (X11) window! This was the missing piece of the puzzle. Unfortunately, the X11 peers were not designed with portability in mind, but instead are designed to be very closely tied to X11. They even use some Swing stuff for text components!

The implementation

So, what were are doing now is pulling together these two ideas: Let all AWT components live in their own native window, and use Swing for drawing and handling the logic. The implementation of this idea looks like this: At the top of the peer hierarchy is the CacioComponentPeer class. This class implements all of the common infrastructure that is shared by all components. And since all components are now real windows, this class also implements the windowing behaviour. The tricky part is, how to make this portable? On different platforms we want to replace how the native windows are implemented. Subclassing is not an option, because we want to subclass the other widget peers from the CacioComponentPeer. A reasonable solution is to not actually implement the windowing behaviour in the CacioComponentPeer, but delegate all this behaviour to a delegate object. I called it ‘PlatformWindow’ and created a nice clean interface for that. This looks very much like the WindowPeer interface, but has some additional stuff in it. In order to port AWT, it would only be necessary to implement this one interface, and get all the AWT widgets for free (because they use this interface only, plus Swing for the rest).

Now the widget peers: they are of course subclasses of CacioComponentPeer. The CacioButtonPeer for example: it subclasses CacioComponentPeer, and thus inherits the fact that it lives in a window. It also has a Swing component ‘inside’, to which the painting and event handling is delegated. I had to do some tricks there: for example, the Swing component must not be connected to the component hierarchy (applications must not see it!), but it must still think it has a parent. So I override getParent() in this Swing component to give it the ‘containing’ AWT component as parent. From the AWT hierarchy POV, there is no Swing component, but from the Swing component POV, there is a valid hierarchy. This is only an example of the tricks that are necessary inside.

So far, I have some working proof-of-concept code in the Caciocavallo-NG repository. It is already possible to open up an AWT frame with an AWT Button, Label and Canvas inside – which look exactly like Swing components:

Caciocavallo Swing peers prototype

Even some event handling already works: I can click on the button and activate it using the space bar.

The best thing from my point of view is the great portability of this solution: in order to port AWT, it’s only necessary to implement a Java2D pipeline (which is not so difficult because it’s possible to reuse a lot of code in OpenJDK) and the PlatformWindow interface for the native windowing support as well as the usual suspects like Toolkit (actually, better to subclass CacioToolkit now) and GraphicsEnvironment. That should make my life (and hopefully the life of other developers who want to port AWT to their favorite platform) much easier. Get the code from from the Cacio-NG repository.


4 Responses to Cacio Swing AWT peers

  1. Try to implement AWT menus and pop up menus first. That way you can support the task bar functionality in some Swing applications.

    Painting is easy. Events are hard.

  2. Hervé says:

    That’s great !! The necessity to redevelop each of AWT widgets as a required part of the JDK has always been one the major difficulty for making Java available on a new given platform. Caciocavallo is really a very interesting project !!!

  3. Pingback: Swing links of the week: September 7 : Pushing Pixels

  4. stolsvik says:

    Enlightening in the way of how Swing *should* be implemented: only use Java2D for drawing, and AWT for the windowing part. I don’t quite see why Swing should not be a completely stand-alone library that could run on any platform that had Java2D and the windowing aspects of AWT implemented.

    Also interesting in a SwingWT and SWTSwing kinda way.

    Too bad that those projects both doesn’t seem to quite get to 100%.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: