-
Notifications
You must be signed in to change notification settings - Fork 1
DesktopFrame
Desktop window manager providing window decoration, task bar, and application launching capabilities for JNode's GUI system.
JNode implements a complete desktop environment independent of any host operating system. The DesktopFrame system consists of two interrelated components:
-
Swing DesktopFrame (
gui/src/awt/org/jnode/awt/swingpeers/DesktopFrame.java) - The root AWT Frame that serves as the desktop canvas, hosting all other windows as internal frames -
Desktop Manager (
gui/src/desktop/org/jnode/desktop/) - The task bar and application launcher that provides window management and application access
This dual-layer approach allows JNode to simulate a complete windowing system using Swing's JDesktopPane and JInternalFrame components, while providing a custom control bar for application management.
| Class | Location | Purpose |
|---|---|---|
DesktopFrame |
gui/src/awt/org/jnode/awt/swingpeers/DesktopFrame.java |
Root JFrame containing the JDesktopPane; implements JNodeAwtContext |
DesktopFramePeer |
gui/src/awt/org/jnode/awt/swingpeers/DesktopFramePeer.java |
AWT peer for DesktopFrame |
Desktop |
gui/src/desktop/org/jnode/desktop/classic/Desktop.java |
Runnable that initializes the control bar and integrates with the AWT context |
ControlBar |
gui/src/desktop/org/jnode/desktop/classic/ControlBar.java |
Bottom panel containing ApplicationBar and WindowBar |
ApplicationBar |
gui/src/desktop/org/jnode/desktop/classic/ApplicationBar.java |
Application launcher with plugin extension point |
WindowBar |
gui/src/desktop/org/jnode/desktop/classic/WindowBar.java |
Button bar showing open internal frames; also owns selectNextFrame
|
TaskBar |
gui/src/desktop/org/jnode/desktop/classic/TaskBar.java |
Container holding the WindowBar (and the clock) |
DesktopPlugin |
gui/src/desktop/org/jnode/desktop/DesktopPlugin.java |
Plugin descriptor for desktop subsystem |
There are two generations of these classes: the older org.jnode.desktop.* (Desktop.java, WindowBar.java, ControlBar.java, ApplicationBar.java) and the live org.jnode.desktop.classic.* (Desktop.java, WindowBar.java, TaskBar.java). The descriptor gui/descriptors/org.jnode.desktop.xml exports both (:38-39) but only instantiates org.jnode.desktop.DesktopPlugin, and every recent change lands in the classic package. Always check the classic/ path.
DesktopFrame (JFrame)
└── JDesktopPane
└── JInternalFrame (multiple - one per AWT Window)
└── SwingBaseWindow (peer)
└── AWT Window/Component
ControlBar (JPanel, positioned at bottom)
├── ApplicationBar (center)
└── WindowBar (east)
1. Boot → AWTPlugin.startPlugin()
2. Application calls Toolkit.getDefaultToolkit()
3. JNodeToolkit creates SwingToolkit
4. SwingToolkit.onInitialize() creates DesktopFrame
5. Desktop.run() creates ControlBar
6. ControlBar integrates with DesktopFrame's JDesktopPane
The Desktop class (in gui/src/desktop/) bridges the control bar to the AWT context:
// From Desktop.java
public void run() {
// Get the AWT context from JNodeToolkit
final JNodeToolkit tk = JNodeToolkit.getJNodeToolkit();
final JNodeAwtContext ctx = tk.getAwtContext();
final JDesktopPane desktop = ctx.getDesktop();
// Add control bar at bottom
awtRoot.add(controlBar);
controlBar.setBounds(0, h - controlBarHeight, w, controlBarHeight);
// Add Halt and Reboot buttons
controlBar.getApplicationBar().addApp("Halt", ...);
controlBar.getApplicationBar().addApp("Reboot", ...);
}All AWT Window and Frame objects are rendered as JInternalFrame instances within the JDesktopPane:
- When a new AWT
Windowis created,SwingToolkitcreates a correspondingSwingBaseWindow -
SwingBaseWindowwraps aJInternalFramethat handles native-looking decorations - The
WindowBartracks all open internal frames asFrameWrapperbuttons in aHashMap
The WindowBar provides window switching. It is a JPanel with a FlowLayout(LEFT, 1, 1) and a lowered BevelBorder, holding one FrameWrapper (JButton) per tracked frame in a HashMap<JInternalFrame, FrameWrapper> — not a JList with a selection listener:
// From WindowBar.java
public void addFrame(final JInternalFrame frame) {
...
final FrameWrapper wrapper = new FrameWrapper(frame);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
wrappers.put(frame, wrapper);
add(wrapper);
revalidate();
repaint();
}
});
}
// FrameWrapper's toggle: raise, or iconify if it is already "selected"
public void actionPerformed(ActionEvent event) {
if (frame.isIcon()) {
frame.setIcon(false);
frame.setSelected(true);
} else if (frame.isSelected()) { // was: ... && isTopFrame(frame), reverted 2026-10-01
frame.setSelected(false);
frame.setIcon(true);
selectNextFrame(frame.getDesktopPane());
} else {
frame.setSelected(true);
}
}addFrame skips frames whose ISwingPeer AWT component is a Frame that is not undecorated, and for undecorated/other components installs a componentHidden listener that calls selectNextFrame instead of adding a button. selectNextFrame picks the visible, non-iconified frame with the lowest non-negative getComponentZOrder — Swing's inverted z-order means lowest index is on top.
FrameWrapper also registers an InternalFrameListener that paints the button white on internalFrameActivated, light gray on internalFrameDeactivated, and removes the wrapper on internalFrameClosing.
Since isSelected() can be true for several windows at once and there is no z-order gate (see AWT-Peer-Implementation for the reverted isTopFrame), clicking the button of a background-but-selected window iconifies it rather than raising it.
The ApplicationBar uses JNode's plugin extension system to discover and launch applications:
// From ApplicationBar.java
private void reloadApps() {
final Extension[] exts = ep.getExtensions();
for (int i = 0; i < exts.length; i++) {
final ConfigurationElement[] elems = ext[i].getConfigurationElements();
for (ConfigurationElement ce : elems) {
final String name = ce.getAttribute("name");
final String className = ce.getAttribute("class");
addApp(name, new LaunchListener(className));
}
}
}
final void startApp(final String name, final String className) {
// Reflection to invoke main(String[]) method
final Class<?> cls = cl.loadClass(className);
final Method main = cls.getMethod("main", mainTypes);
main.invoke(null, new Object[]{new String[0]});
}Applications are declared in plugin descriptors:
<extension point="org.jnode.desktop.apps">
<app name="FileManager" class="org.jnode.shell.file.FileManager"/>
</extension>-
Plugin ClassLoader Requirement: The
Desktopclass must be loaded via aPluginClassLoaderto access the applications extension point. This is enforced at runtime with anAWTErrorif not. - Swing Dependency: The entire desktop system depends on Swing (javax.swing), so the swingpeers plugin must be loaded for GUI operation.
-
Background Image:
DesktopFramesupports a background image that is painted in the bottom-right corner with a 30x20 pixel offset. -
Color Preferences: Desktop background color is persisted via
java.util.prefs.Preferencesand restored on each launch. -
DesktopPane Size Management: When screen resolution changes,
DesktopFrame.adjustDesktopSize()must be called to resize the desktop and invalidate the component tree.
- AWT-Peer-Implementation - Contains the peer implementation details for DesktopFrame
- GUI-AWT - Parent GUI documentation
- Video-Driver-Architecture - Framebuffer integration
- Thinlet - Alternative lightweight GUI toolkit
- Plugin-System - Extension point mechanism for application discovery