-
Notifications
You must be signed in to change notification settings - Fork 0
Input Drivers
Input device drivers with keyboard layouts and mouse protocol handlers.
JNode's Input Drivers subsystem provides the foundation for keyboard and mouse support, enabling user input to flow from hardware devices through the driver framework into the GUI and shell subsystems. The architecture is split into two distinct areas: keyboard input handling via locale-specific KeyboardInterpreter implementations, and pointer input handling via MouseProtocolHandler plugins. The InputPlugin serves as the plugin entry point, registering two extension points (keyboard-layouts and mouse-protocol-handlers) and binding the KeyboardLayoutManager and MouseProtocolHandlerManager into the InitialNaming namespace.
Keyboard input arrives as raw scancodes from the PS/2 keyboard controller (or USB HID reports translated by a USB driver). These scancodes are passed to a KeyboardInterpreter which maintains modifier state (Shift, Ctrl, Alt, AltGr, CapsLock) and translates scancodes into KeyEvent virtual key codes and character values based on the active keyboard layout. Mouse input arrives as raw packet bytes from the PS/2 mouse port (or USB HID boot protocol). These packets are passed to a MouseProtocolHandler which decodes the packet format and produces PointerEvent objects containing button state and X/Y/Z (wheel) values in either absolute or relative coordinates.
| Class / File | Role |
|---|---|
core/src/driver/org/jnode/driver/input/InputPlugin.java |
Plugin entry point; registers extension points and binds managers to InitialNaming |
core/src/driver/org/jnode/driver/input/KeyboardInterpreter.java |
Interface for translating scancodes to KeyboardEvent; defines Factory inner interface |
core/src/driver/org/jnode/driver/input/AbstractKeyboardInterpreter.java |
Base implementation handling modifier state, extended scancodes (0xE0), dead keys, and KeyEvent construction |
core/src/driver/org/jnode/driver/input/KeyboardLayoutManager.java |
Factory manager for keyboard layouts; resolves locale, plugin extensions, and fallback l10n class loading |
core/src/driver/org/jnode/driver/input/KeyboardEvent.java |
Event wrapping KeyEvent.KEY_PRESSED/KEY_RELEASED, modifiers, virtual key code, and character |
core/src/driver/org/jnode/driver/input/Key.java |
Per-scancode key descriptor holding lower/upper/AltGr characters and virtual key codes |
core/src/driver/org/jnode/driver/input/Keys.java |
Array of 128 key descriptors indexed by scancode; provides getScanCode() reverse lookup |
core/src/driver/org/jnode/driver/input/MouseProtocolHandler.java |
Interface for decoding raw mouse packets into PointerEvent; provides getName(), supportsId(), getPacketSize(), buildEvent()
|
core/src/driver/org/jnode/driver/input/MouseProtocolHandlerManager.java |
Manager for mouse protocol handler plugins via the mouse-protocol-handlers extension point |
core/src/driver/org/jnode/driver/input/MouseInterpreter.java |
Driver-side interpreter using MouseProtocolHandlerManager to route packets to the appropriate handler |
core/src/driver/org/jnode/driver/input/LogitechProtocol.java |
MouseProtocolHandler implementation for standard 3-byte Logitech mouse packets |
core/src/driver/org/jnode/driver/input/LogitechWheelMouseProtocol.java |
MouseProtocolHandler for 4-byte Logitech mice with wheel support |
core/src/driver/org/jnode/driver/input/PointerEvent.java |
Event holding button bitmask, X/Y/Z values, and absolute/relative coordinate mode |
core/src/driver/org/jnode/driver/input/l10n/KeyboardInterpreter_*.java |
Locale-specific AbstractKeyboardInterpreter subclasses (US_en, GB_en, DE, FR, IT, ES, HU, RU, etc.) |
PS/2 Keyboard Controller → KeyboardDriver → AbstractKeyboardInterpreter.interpretScancode()
→ KeyboardEvent → KeyboardListener (e.g., AWT KeyboardHandler)
The AbstractKeyboardInterpreter is stateful. It tracks modifier flags (SHIFT_DOWN_MASK, CTRL_DOWN_MASK, ALT_DOWN_MASK, ALT_GRAPH_DOWN_MASK) updated on each keypress, and handles CapsLock with a 4-state cycle. Extended scancodes (prefix 0xE0) set an extendedMode flag; the next scancode is interpreted as an extended key (arrows, Home/End, Insert/Delete, etc.). The interpretExtendedScanCode() method handles dead keys (accent marks like acute, grave, circumflex) by throwing DeadKeyException to buffer the dead key state, then combining it with the next key to produce the accented character.
Layout selection uses the KeyboardLayout resource bundle to resolve the locale (defaultCountry, defaultRegion, defaultVariant). KeyboardLayoutManager.createDefaultKeyboardInterpreter() builds an ID like US_en or HU_hu_101 and looks up the factory from the keyboard-layouts extension point. If no plugin extension is found, it falls back to dynamically loading org.jnode.driver.input.l10n.KeyboardInterpreter_<id> by class name.
PS/2 Mouse Port → MouseDriver → MouseInterpreter → MouseProtocolHandlerManager
→ MouseProtocolHandler.buildEvent() → PointerEvent → PointerListener (e.g., AWT MouseHandler)
MouseProtocolHandlerManager discovers handlers via the mouse-protocol-handlers extension point. Each handler implements supportsId(int id) to match the device's identification byte(s) and getPacketSize() to indicate how many bytes form a complete packet. The buildEvent() method decodes the packet bytes into a PointerEvent with button state (left/middle/right as bitmask) and X/Y/Z values. The LogitechProtocol uses a 3-byte format where bit 0-2 are buttons, bits 4-5 are sign bits for X/Y overflow detection, and bits 6-7 indicate X/Y overflow. LogitechWheelMouseProtocol extends this to 4 bytes with a wheel delta in byte 3.
protected void startPlugin() throws PluginException {
KeyboardLayoutManager klmgr = new KeyboardLayoutManager(
descriptor.getExtensionPoint("keyboard-layouts"));
InitialNaming.bind(KeyboardLayoutManager.NAME, klmgr);
MouseProtocolHandlerManager mphmgr = new MouseProtocolHandlerManager(
descriptor.getExtensionPoint("mouse-protocol-handlers"));
InitialNaming.bind(MouseProtocolHandlerManager.NAME, mphmgr);
}-
Keyboard layouts vary by locale: JNode ships with ~20 locale-specific interpreters (
KeyboardInterpreter_US_en,KeyboardInterpreter_DE, etc.). A missing or misconfiguredKeyboardLayoutresource bundle causes fallback toUS_en. -
Dead key handling via exceptions:
interpretExtendedScanCode()usesUnsupportedKeyExceptionandDeadKeyExceptionfor control flow. The comment inAbstractKeyboardInterpreternotes this is "an evil hack" to mitigate performance issues from exception-heavy paths. -
Mouse protocol detection is ID-based:
MouseProtocolHandler.supportsId()is checked against the device's identification byte. If no handler claims the ID, the mouse will not function. TheLogitechProtocolonly supports ID0, meaning standard Logitech mice will work but extended-mode devices may not. -
Extended scancode prefix: The
0xE0prefix scancode returnsnullfrominterpretScancode()and setsextendedMode = true; the next scancode is processed in extended mode. This means the caller must handle the two-scancode sequence for arrow keys, etc. -
Input events must be synchronized with GUI rendering: Input listeners (AWT peers) receive events on the same thread that the driver calls back on. In JNode's event-driven GUI model, this requires careful synchronization to avoid race conditions between input processing and rendering.
-
CapsLock state machine: CapsLock toggles via a 4-state counter (
capsLockcycles 0→1→2→3→0), where states 0 and 3 applySHIFT_DOWN_MASK, and states 1 and 2 clear it. This unusual design requires two key-down events before the toggle is complete. -
Keyboard interpreter instances are stateful:
KeyboardInterpreterobjects maintain modifier state and dead-key state per keyboard device. Sharing a single interpreter across multiple keyboards causes input cross-talk.
- Driver-Framework — Base driver model that input devices plug into
- GUI-AWT — Where keyboard and mouse events are consumed by the AWT peer system
- Bus-Drivers — USB and PS/2 bus drivers that produce raw input data for these handlers
- Video-Driver-Architecture — Video subsystem that coordinates with input for cursor and focus