Skip to content

DesktopFrame

opencode-agent[bot] edited this page May 11, 2026 · 1 revision

DesktopFrame

Desktop window manager providing window decoration, task bar, and application launching capabilities for JNode's GUI system.

Overview

JNode implements a complete desktop environment independent of any host operating system. The DesktopFrame system consists of two interrelated components:

  1. 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
  2. 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.

Key Components

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/Desktop.java Runnable that initializes the control bar and integrates with the AWT context
ControlBar gui/src/desktop/org/jnode/desktop/ControlBar.java Bottom panel containing ApplicationBar and WindowBar
ApplicationBar gui/src/desktop/org/jnode/desktop/ApplicationBar.java Application launcher with plugin extension point
WindowBar gui/src/desktop/org/jnode/desktop/WindowBar.java Window list showing active internal frames
DesktopPlugin gui/src/desktop/org/jnode/desktop/DesktopPlugin.java Plugin descriptor for desktop subsystem

Architecture

Component Hierarchy

DesktopFrame (JFrame)
└── JDesktopPane
    └── JInternalFrame (multiple - one per AWT Window)
         └── SwingBaseWindow (peer)
              └── AWT Window/Component

ControlBar (JPanel, positioned at bottom)
├── ApplicationBar (center)
└── WindowBar (east)

Initialization Flow

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

Desktop Integration

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", ...);
}

Window Management

Internal Frame Handling

All AWT Window and Frame objects are rendered as JInternalFrame instances within the JDesktopPane:

  1. When a new AWT Window is created, SwingToolkit creates a corresponding SwingBaseWindow
  2. SwingBaseWindow wraps a JInternalFrame that handles native-looking decorations
  3. The WindowBar tracks all open internal frames in a JList

WindowBar Functionality

The WindowBar provides window switching:

// From WindowBar.java
public void addFrame(final JInternalFrame frame) {
    final FrameWrapper wrapper = new FrameWrapper(frame);
    model.addElement(wrapper);
}

// Selecting a window activates it
private class SelectionListener implements ListSelectionListener {
    public void valueChanged(ListSelectionEvent e) {
        JInternalFrame frame = wrappers.get(list.getSelectedValue()).getFrame();
        frame.toFront();
        frame.setSelected(true);
    }
}

Application Launching

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>

Gotchas

  • Plugin ClassLoader Requirement: The Desktop class must be loaded via a PluginClassLoader to access the applications extension point. This is enforced at runtime with an AWTError if not.
  • Swing Dependency: The entire desktop system depends on Swing (javax.swing), so the swingpeers plugin must be loaded for GUI operation.
  • Background Image: DesktopFrame supports 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.Preferences and 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.

Related Pages

Clone this wiki locally