12 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
ThunderPad is an accessibility-focused fork of QJoyPad - a Qt-based Linux application that maps joystick/gamepad inputs to keyboard keys and mouse actions. ThunderPad was completely redesigned for full screen reader compatibility and keyboard navigation support. It's developed for the Stormux project with accessibility as the top priority.
Key Differentiators from QJoyPad
- Full keyboard navigation - No mouse required for any configuration task
- Screen reader compatible - Works seamlessly with Orca and other assistive technologies
- Window mode by default - Opens configuration window directly (use
--tray
for system tray) - English-only interface - Translation system removed for simplicity
- Separate config directory - Uses
~/.config/thunderpad/
to coexist with QJoyPad
Critical Development Principle
🔴 ACCESSIBILITY FIRST: Screen reader accessibility is the top priority for ANY code changes.
All modifications must maintain or improve:
- Complete keyboard navigation (Tab/Shift+Tab/Arrow keys)
- Screen reader compatibility (proper labels, focus management)
- Logical tab order and focus flow
- Accessible widget choices (lists vs. clickable grids)
Build System
This project uses CMake with Qt5 dependencies:
Build Commands
# Standard build process
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)
# For installation
make install
# For development with debug symbols
cmake .. -DCMAKE_BUILD_TYPE=Debug
CMake Configuration Options
-DDEVICE_DIR=/dev/input
- Set joystick device directory (default: /dev/input)-DWITH_LIBUDEV=OFF
- Disable libudev support for automatic device detection-DPLAIN_KEYS=ON
- Use standard X11 key names instead of readable names-DCMAKE_INSTALL_PREFIX=/usr
- Set installation prefix
Dependencies
- Qt5Widgets, Qt5X11Extras
- libudev (optional, for automatic device detection)
- Linux joystick driver support
- For accessibility testing: Orca screen reader or Cthulhu screen reader
Code Architecture
Project Rebranding (QJoyPad → ThunderPad)
Version: 2025.06.30
Executable: thunderpad
Config Directory: ~/.config/thunderpad/
PID File: /tmp/thunderpad.pid
Desktop Entry: thunderpad.desktop
All source code has been systematically updated:
- Header guards:
QJOYPAD_*
→THUNDERPAD_*
- Macro definitions:
QJOYPAD_NAME
→THUNDERPAD_NAME
- Icon paths:
QJOYPAD_ICON24/64
→THUNDERPAD_ICON24/64
- Comments and references updated throughout
Core Components
-
LayoutManager (
layout.h/cpp
) - Central coordinator that manages:- Layout loading/saving to
~/.config/thunderpad/
- Optional system tray icon and menu (when
--tray
used) - Configuration window display (default behavior)
- Joystick device detection and management
- Inter-process communication via signals (SIGUSR1/SIGUSR2)
- Layout loading/saving to
-
JoyPad (
joypad.h/cpp
) - Represents individual joystick devices:- File descriptor management for
/dev/input/jsX
devices - Contains collections of Button and Axis objects
- Handles joystick events via QSocketNotifier
- File descriptor management for
-
Button (
button.h/cpp
) - Individual button configuration:- Key/mouse button mapping
- Sticky mode (toggle on/off)
- Rapid fire functionality
- Layout switching capability
-
Axis (
axis.h/cpp
) - Joystick axis configuration:- Keyboard key mapping for positive/negative directions
- Mouse movement control (relative/absolute)
- Sensitivity and dead zone settings
- Gradient mode for variable input strength
-
Event System (
event.h/cpp
) - X11 integration for:- Key press/release simulation
- Mouse button clicks
- Mouse movement
Accessibility-Focused UI Components
CRITICAL: All UI components prioritize keyboard navigation and screen reader compatibility.
-
LayoutEdit (
layout_edit.h/cpp
) - Main accessible configuration dialog:- QTabWidget for joystick navigation (replaces clickable FlashRadioArray)
- Layout management controls at top (dropdown, add/remove/rename buttons)
- Import/export functionality
- Save/revert controls
-
JoyPadWidget (
joypadw.h/cpp
) - Accessible per-device configuration:- Axes list - QListWidget showing all axes with current assignments
- Configure Axis button - Opens configuration for selected axis
- Buttons list - QListWidget showing all buttons with current assignments
- Configure Button button - Opens configuration for selected button
- Clear/Quick Set buttons - Bulk operations
- Explicit tab order with
setTabOrder()
calls
-
ButtonEdit/AxisEdit - Component-specific configuration dialogs
-
Icon - Floating icon alternative (rarely used in accessibility mode)
Accessibility Design Patterns
- QListWidget over clickable grids - Screen reader navigable
- Dedicated configure buttons - Instead of click-to-configure interfaces
- QTabWidget for device switching - Keyboard accessible tabs
- Explicit tab order -
setTabOrder()
calls ensure logical navigation - Descriptive widget names - Proper accessibility labels
- Qt::StrongFocus policy - Ensures all interactive elements are keyboard reachable
Development Workflows
Testing Changes
# Build and run locally (default: window mode)
make
DISPLAY=:0 ./thunderpad
# Test with system tray mode
DISPLAY=:0 ./thunderpad --tray
# Test with specific layout
DISPLAY=:0 ./thunderpad "layout-name"
# Update device list in running instance
DISPLAY=:0 ./thunderpad --update
# Test accessibility with screen reader
# Start Orca or Cthulhu first, then launch thunderpad
Accessibility Testing Requirements
Before any code changes are considered complete:
-
Keyboard Navigation Test:
- Tab through entire interface without mouse
- Verify all controls are reachable via keyboard
- Test arrow key navigation within lists and tabs
- Ensure Escape key behavior is consistent
-
Screen Reader Test:
- Launch with Orca or Cthulhu running
- Verify all interface elements are announced properly
- Check that focus changes are announced
- Ensure list items have descriptive labels
-
Focus Management Test:
- Verify logical tab order (top to bottom, left to right)
- Check that focus is visible (highlight indicators)
- Test that dialogs return focus appropriately when closed
Configuration Files and Compatibility
- ThunderPad layouts:
~/.config/thunderpad/*.lyt
- Last used layout:
~/.config/thunderpad/layout
- Layout compatibility: Same
.lyt
format as QJoyPad - files can be manually copied between directories - Coexistence: ThunderPad and QJoyPad can run simultaneously (different config dirs, different PID files)
Device Detection
- Scans
/dev/input/js*
by default - Uses libudev for automatic device hotplug detection when available
- Supports manual device directory specification via
--device
flag
Interface Changes from QJoyPad
Major Accessibility Improvements
- Tab-based interface: Replaced
FlashRadioArray
withQTabWidget
- List-based controls: Axes and buttons shown in
QListWidget
instead of clickable grid - Configure buttons: Dedicated buttons for each control type instead of click-only interfaces
- Window mode default: No system tray dependency for basic operation
- Keyboard-only operation: Every function accessible via keyboard
Removed Features (For Accessibility)
- FlashRadioArray widgets: Replaced with standard Qt accessible widgets
- Click-to-configure interfaces: Replaced with explicit configure buttons
- System tray requirement: Optional with
--tray
flag
Command Line Interface
thunderpad [OPTIONS] [LAYOUT_NAME]
Options:
-h, --help Show help message
-d, --device=PATH Specify joystick device directory
-t, --tray Use system tray icon (accessibility: not recommended)
-T, --notray Use window mode (default, accessibility: recommended)
-u, --update Update device list in running instance
Code Quality Standards
Accessibility Requirements
- All interactive elements must be keyboard accessible
- Proper widget labeling for screen readers
- Logical tab order with explicit
setTabOrder()
when needed - Focus indicators must be visible and announced
- No mouse-only functionality - everything must work with keyboard alone
Code Style
- No comments unless necessary - Keep code self-documenting
- Follow existing Qt patterns - Use existing signal/slot architecture
- Maintain security - Never log or expose secrets/keys
- Consistent naming - Use THUNDERPAD_ prefix for all new macros
File Organization
src/
├── config.h.in # Build-time configuration (THUNDERPAD_* macros)
├── main.cpp # Application entry point
├── layout.h/cpp # Central layout management
├── layout_edit.h/cpp # Main configuration dialog
├── joypad.h/cpp # Individual joystick representation
├── joypadw.h/cpp # Accessible joystick widget
├── button.h/cpp # Button configuration
├── buttonw.h/cpp # Accessible button widget
├── axis.h/cpp # Axis configuration
├── axisw.h/cpp # Accessible axis widget
├── event.h/cpp # X11 event generation
├── error.h # Error handling utilities
└── ...
Recent Major Changes
Complete Rebranding (QJoyPad → ThunderPad)
- Project name: qjoypad → thunderpad
- Version: Updated to 2025.06.30
- All source files: Updated header guards, macros, comments
- Configuration: New directory
~/.config/thunderpad/
- Desktop entry: New
thunderpad.desktop
file - Build system: CMakeLists.txt updated for new project name
Accessibility Transformation
- Interface redesign: Complete overhaul for keyboard navigation
- Widget replacement: Accessible alternatives to custom widgets
- Default behavior: Window mode instead of system tray
- Focus management: Explicit tab order and focus policies
Development Impact
- Building: Same CMake process, now produces
thunderpad
executable - Testing: Must include accessibility testing with screen reader
- Configuration: New config directory allows coexistence with QJoyPad
- Installation: Desktop entry and icons updated for ThunderPad branding
Future Development Guidelines
Accessibility-First Development
-
Before implementing any UI change:
- Consider keyboard navigation impact
- Test with screen reader if possible
- Prefer standard Qt widgets over custom implementations
- Ensure all functionality works without mouse
-
Widget selection priority:
- QListWidget > clickable grids
- QPushButton > mouse-only interactions
- QTabWidget > custom tab implementations
- Standard Qt dialogs > custom dialogs
-
Testing requirements:
- Manual keyboard navigation test
- Screen reader compatibility verification
- Focus flow validation
- No mouse required for any operation
Compatibility Considerations
- Maintain
.lyt
file format compatibility with QJoyPad - Keep command-line interface consistent where possible
- Preserve core joystick mapping functionality
- Ensure coexistence capability with QJoyPad installations
Remember: Accessibility is not optional - it's the core mission of ThunderPad.