SWT, Browsers and Swing, Oh my …
By meverett | November 30, 2007
There has been talk, at least according to the LimeWire JIRA reports, about adding a browser to the LimeWire client for sometime. The first attempt came when the SwingLabs introduced the Java Desktop Integration Component (JDIC). The idea behind JDIC was to make it easier for Java applications to integrate with native components. The reason being is that in many cases it’s easier to borrow the functionality of already built software such as a web browser or a video player than to rewrite it in Java.
So a JDIC browser would use a native browser on each OS and simply paint it on a heavy weight AWT component. The only problem was Sun dropped the ball. Like much of the SwingLabs projects, JDIC seems to have died a quiet death. The last official announcement on the JDIC website was posted Nov. 10, 2006. The JDIC web browser integration seemed like a good idea except it was only stable (if it worked at all) on Windows XP and only with IE and FireFox. So the browser project was put back into the LimeWire TODO list.
With the launch of the LimeWire Store, we wanted to be able to search the Store through the LimeWire client and the easiest way to achieve this was to integrate a web browser into the client. During my search for browsers, I was surprised to learn that Eclipse has a fully integrated web browser. IBM apparently succeeded where the JDIC failed. Using essentially the same approach as Sun, they have been able to successfully deploy a native browser within a SWT component and they got it to work on every operating system we have tested it with (various Windows, OS X and Linux flavors). To top it off, it’s rather simple to create a native browser in SWT. This is all it takes to create a bare bones browser: (To actually run these examples you will first need to download the appropriate SWT.jar from here: http://www.eclipse.org/swt/)
public static void main(String args[]) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setSize(800,600);
Browser browser = new Browser(shell, SWT.NONE);
browser.setLayoutData( new GridData(GridData.FILL_BOTH));
browser.setSize(800,600);
browser.setUrl("http://www.limewire.com");
shell.open();
while(!shell.isDisposed()) {
if(!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
So we could create a browser in SWT, but the LimeWire client is in Swing. Luckily, IBM has also been working on a SWT-AWT bridge. The purpose of the bridge is to allow SWT to embed Swing components and Swing to embed SWT components. How can this be possible?
If you think about it, it’s not really all that surprising. Both AWT and SWT use native widgets to perform their painting on. Swing is really just a bunch of paint operations on top of an AWT component. So when you embed a SWT component in Swing, you’re really embedding a native component on top of another native component. So it’s no surprise that the bridge requires the use of an AWT Canvas, a heavy-weight container. So what would the code look like for an SWT browser in Swing? Surprisingly not all that different:
public static void main(String args[]) {
JFrame f = new JFrame();
Canvas canvas = new Canvas();
f.setSize(800,500);
f.add(canvas);
f.setVisible(true);
Display display = new Display();
Shell shell = SWT_AWT.new_Shell(display, canvas);
shell.setSize(800,600);
Browser browser = new Browser(shell, SWT.NONE);
browser.setLayoutData( new GridData(GridData.FILL_BOTH));
browser.setSize(800,600);
browser.setUrl("http://www.limewire.com");
shell.open();
while(!shell.isDisposed()) {
if(!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
If you compare to two sets of code, the only thing that has really changed is the way the SWT Shell component is created. Instead of creating a Shell directly, it uses the SWT_AWT bridge to create a Shell with its container being a Swing Canvas object. Since both Canvas and Shell are actually native widgets, the bridge lets us take the widget from Swing instead of SWT. In reality, it’s actually the same object, a native Container. One caveat here is the Swing container must be visible prior to creating the bridge which is why we display the JFrame prior to creating the SWT component.
Does this solve the web browser problem? Well, almost. There are a few gotcha’s involved in this.
First, we are painting a heavy weight object on top of Swing. This means that things like JMenus will be hidden by the browser since we have a heavy weight component on top of a lightweight one. As a result, all menus must be converted to heavy weight objects, not a huge problem but something to be aware of. Another problem is we are now introducing a new paint manager into the application. Just like Swing has the Swing Event Dispatch Thread, SWT has its own separate Event Queue which should always be wrapped in its own thread. So we are now introducing the problem of concurrency issues anytime we wish to interact between Swing components and the browser. This immediately adds a new level of complexity to the application. The biggest problem, however, is the SWT-AWT bridge hasn’t been completed. With the release of Eclipse 3.3 most of the mapping has been finished but things such as keyboard inputs on Linux machines are lacking. So for the time being we’re releasing our browser on Windows. Until IBM finishes the SWT-AWT bridge or we have enough time to hack it ourselves Linux and OS X user’s will just have to wait =)

Comments and Trackbacks
Zootella Says:
December 12th, 2007 at 3:30 pm |
Permalink
Great article, Mike. I look forward to working through it.
Limewire is getting a web browser | Fresh Web 2.0 News Says:
January 5th, 2008 at 10:59 am |
Permalink
[…] Many newborn media players aforementioned Miro or Songbird are supported on Mozilla’s XUL framework, which is the aforementioned cipher that Firefox is based, so they essentially hit scheme feeding capabilities shapely in from the start. Limewire still is Java-based, and that seems to be a completely assorted story. The authorised Limewire journal has every the details for expressed Java fans: […]
anon Says:
April 1st, 2008 at 3:39 pm |
Permalink
IntelliJ IDEA 6+ can install a “netscape” (not sure what it means by that) HTML/CSS renderer and display it in a panel. IDEA uses Swing. It may be worth checking out.
Zotella Says:
May 16th, 2008 at 7:58 am |
Permalink
Anyone has idea if the SWT_AWT bridge for linux is available now or not?
Warren Anderson Says:
May 6th, 2009 at 4:07 pm |
Permalink
Great examples. One issue with the SWT browser embedded in Swing JFrame example you give. The JVM never exists when the application is closed. Check your TASK manager for the hung JVMs. One for each execution. Do you know fix?
Scorpion Black Says:
May 26th, 2009 at 2:28 pm |
Permalink
Hi! I’m living in mexico, but my english is not perfect. I am making an application that used just the browser of SWT for see a radio from internet. My question is… How i can do to set the browser in a JPanel, without buttons and nothing anymore. I think embed the JPanel in a JFrame, but i cannot embed the swtbrowser in a JPanel.
Thanks!
meverett Says:
June 25th, 2009 at 11:30 am |
Permalink
Warren,
SWT, unlike Swing, uses native components so you need to explicitely dispose of them when you are finished. When exiting you need to call shell.dispose() and browser.dispose() to properlly release resources.
Scorpion,
The browser is a heavy weight component so you need to embed it in an AWT component, not a swing one. Try adding the browser to Canvas and embed the Canvas into the JFrame.
To see how we used it, you can checkout from our cvs and go to an old 4.18 Production tag.