Add application-specific sleep mode that disables speech and events while preserving the ability to toggle back to normal operation. Features: - Keybinding: Cthulhu+Ctrl+Alt+Shift+Q (matches Orca) - Per-application scope (only affects focused app) - Suppresses all speech, braille, and event processing - Preserves sleep mode toggle keybinding for exit - Status messages on enter/exit Implementation: - New sleepmode script module in src/cthulhu/scripts/sleepmode/ - Toggle handler in default.py using script manager - Proper autotools integration with correct installation paths - Build system fixes for module discovery Files modified: - src/cthulhu/common_keyboardmap.py: Add sleep mode keybinding - src/cthulhu/scripts/default.py: Add toggleSleepMode handler - src/cthulhu/scripts/sleepmode/: Complete sleep mode implementation - CLAUDE.md: Documentation for build system and sleep mode - Fix sleepmode/Makefile.am installation path 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
420 lines
15 KiB
Markdown
420 lines
15 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Project Overview
|
|
|
|
Cthulhu is a fork of the Orca screen reader, providing access to the graphical desktop via speech and/or braille. It's designed as a supplemental screen reader for advanced users, particularly useful for older Qt applications and specific window managers like i3.
|
|
|
|
## Build System and Commands
|
|
|
|
### Local Development Build (Recommended)
|
|
```bash
|
|
# Build and install locally to ~/.local (no system overwrite)
|
|
./build-local.sh
|
|
|
|
# Test local installation
|
|
./test-local.sh
|
|
|
|
# Run local version
|
|
~/.local/bin/cthulhu
|
|
|
|
# Clean build artifacts and local installation
|
|
./clean-local.sh
|
|
```
|
|
|
|
### System Build (Autotools)
|
|
```bash
|
|
# Configure and build for system installation
|
|
./autogen.sh --prefix=/usr
|
|
make
|
|
make install
|
|
|
|
# Or use CI script
|
|
ci/build_and_install.sh
|
|
```
|
|
|
|
### Alternative Build (Python packaging)
|
|
```bash
|
|
# Using pip/hatchling
|
|
pip install -e .
|
|
```
|
|
|
|
### Testing
|
|
```bash
|
|
# Run all regression tests
|
|
test/harness/runall.sh
|
|
|
|
# Run single test
|
|
test/harness/runone.sh <test.py> <app-name>
|
|
|
|
# Run specific app tests
|
|
test/harness/runall.sh -a /path/to/app/tests
|
|
|
|
# Coverage analysis
|
|
test/harness/runall.sh -c
|
|
|
|
# Profile mode
|
|
test/harness/runall.sh -p
|
|
```
|
|
|
|
## Core Architecture
|
|
|
|
### Main Components
|
|
- **Event System**: `event_manager.py`, `signal_manager.py` - Central event handling
|
|
- **Accessibility Layer**: `ax_object.py`, `ax_utilities.py` - AT-SPI object management
|
|
- **Output Systems**: `speech.py`, `braille.py` - Speech and braille generation
|
|
- **Navigation**: `structural_navigation.py`, `flat_review.py` - Document and screen navigation
|
|
- **Plugin System**: `plugin_system_manager.py` - Extensible plugin architecture using pluggy
|
|
|
|
### Application Scripts
|
|
Scripts in `src/cthulhu/scripts/` provide application-specific behavior:
|
|
- `scripts/apps/` - Specific applications (Firefox, Thunderbird, LibreOffice)
|
|
- `scripts/toolkits/` - Toolkit support (GTK, Qt, Gecko, WebKit)
|
|
- `scripts/web/` - Web browsing enhancements
|
|
|
|
### Plugin Development
|
|
System plugins in `src/cthulhu/plugins/`, user plugins in `~/.local/share/cthulhu/plugins/`:
|
|
|
|
#### Basic Plugin Structure
|
|
```
|
|
src/cthulhu/plugins/MyPlugin/
|
|
├── __init__.py # Package import: from .plugin import MyPlugin
|
|
├── plugin.py # Main implementation
|
|
├── plugin.info # Metadata
|
|
└── Makefile.am # Build system integration
|
|
```
|
|
|
|
#### Minimal Plugin Template
|
|
```python
|
|
from cthulhu.plugin import Plugin, cthulhu_hookimpl
|
|
|
|
class MyPlugin(Plugin):
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self._enabled = True
|
|
|
|
@cthulhu_hookimpl
|
|
def activate(self, plugin=None):
|
|
if plugin is not None and plugin is not self:
|
|
return
|
|
# Plugin activation logic
|
|
return True
|
|
|
|
@cthulhu_hookimpl
|
|
def deactivate(self, plugin=None):
|
|
if plugin is not None and plugin is not self:
|
|
return
|
|
# Cleanup logic
|
|
return True
|
|
```
|
|
|
|
#### Plugin Integration Patterns
|
|
|
|
**1. Keybinding Registration:**
|
|
```python
|
|
def _register_keybinding(self):
|
|
if not self.app:
|
|
return
|
|
api_helper = self.app.getAPIHelper()
|
|
self._kb_binding = api_helper.registerGestureByString(
|
|
"Cthulhu+key", self._handler_method, "Description"
|
|
)
|
|
```
|
|
|
|
**2. Accessing Cthulhu APIs:**
|
|
```python
|
|
# Get current active script
|
|
state = self.app.getDynamicApiManager().getAPI('CthulhuState')
|
|
active_script = state.activeScript
|
|
|
|
# Access speech/messages
|
|
speech = self.app.getDynamicApiManager().getAPI('Speech')
|
|
messages = self.app.getDynamicApiManager().getAPI('Messages')
|
|
```
|
|
|
|
**3. Sound Generation:**
|
|
```python
|
|
from cthulhu import sound
|
|
from cthulhu.sound_generator import Tone
|
|
|
|
# Initialize player
|
|
self._player = sound.getPlayer()
|
|
|
|
# Create and play tone
|
|
tone = Tone(duration=0.15, frequency=400, volumeMultiplier=0.7)
|
|
self._player.play(tone, interrupt=False)
|
|
```
|
|
|
|
**4. Script Method Monkey-Patching:**
|
|
```python
|
|
def _monkey_patch_script_methods(self):
|
|
state = self.app.getDynamicApiManager().getAPI('CthulhuState')
|
|
if state and state.activeScript:
|
|
script = state.activeScript
|
|
self._original_method = script.methodName
|
|
|
|
def wrapped_method(*args, **kwargs):
|
|
result = self._original_method(*args, **kwargs)
|
|
# Add custom logic here
|
|
return result
|
|
|
|
script.methodName = wrapped_method
|
|
```
|
|
|
|
#### Plugin Files
|
|
|
|
**plugin.info format:**
|
|
```ini
|
|
[Core]
|
|
Name = PluginName
|
|
Module = PluginName
|
|
|
|
[Documentation]
|
|
Description = Plugin description
|
|
Author = Author Name
|
|
Version = 1.0.0
|
|
Website = https://example.com
|
|
```
|
|
|
|
**Makefile.am template:**
|
|
```makefile
|
|
pluginname_PYTHON = \
|
|
__init__.py \
|
|
plugin.py
|
|
|
|
pluginnamedir = $(pkgdatadir)/cthulhu/plugins/PluginName
|
|
|
|
pluginname_DATA = \
|
|
plugin.info
|
|
|
|
EXTRA_DIST = $(pluginname_DATA)
|
|
```
|
|
|
|
**Build Integration:**
|
|
Add plugin to `src/cthulhu/plugins/Makefile.am` SUBDIRS line.
|
|
|
|
#### Advanced Plugin Features
|
|
|
|
**Event System Integration:**
|
|
- Register with Dynamic API: `api_manager.registerAPI('MyPlugin', self)`
|
|
- Hook into script changes via monkey-patching
|
|
- Access event manager for custom event handling
|
|
|
|
**Text Analysis:**
|
|
- Use `script.getTextLineAtCaret(obj)` for current line
|
|
- Access text attributes via `script.utilities.getTextAttributes()`
|
|
- Leverage existing utilities like `indentationDescription()`
|
|
|
|
**Settings Integration:**
|
|
- Access settings manager: `settings_manager.getManager()`
|
|
- Create plugin-specific settings with prefixes
|
|
- Integrate with preferences GUI if needed
|
|
|
|
## Development Workflow
|
|
|
|
### Contributing
|
|
- Repository: https://git.stormux.org/storm/cthulhu
|
|
- Create branch for changes, merge to master when ready
|
|
- Email patches to storm_dragon@stormux.org if no direct access
|
|
- Community: IRC #stormux on irc.stormux.org
|
|
|
|
### Key Dependencies
|
|
- Python 3.3+, pygobject-3.0, pluggy, gtk+-3.0
|
|
- AT-SPI2, ATK for accessibility
|
|
- Optional: BrlTTY/BrlAPI (braille), Speech Dispatcher, liblouis, GStreamer
|
|
|
|
### Version Information
|
|
Current version in `src/cthulhu/cthulhuVersion.py`, codename "plugins"
|
|
|
|
### Self-voicing Feature
|
|
Direct speech output via Unix socket:
|
|
```bash
|
|
echo "Hello world." | socat - UNIX-CLIENT:/tmp/cthulhu.sock
|
|
echo "<!#APPEND#!>Hello world." | socat - UNIX-CLIENT:/tmp/cthulhu.sock # No interrupt
|
|
echo "Hello world.<#APPEND#>" | socat - UNIX-CLIENT:/tmp/cthulhu.sock # Persistent braille
|
|
```
|
|
|
|
## Key Directories
|
|
|
|
- `src/cthulhu/` - Core source code
|
|
- `test/` - Regression test framework with keystroke-based testing
|
|
- `po/` - Internationalization files (extensive i18n support)
|
|
- `help/` - Multi-language user documentation
|
|
- `ci/` - Continuous integration scripts
|
|
|
|
## Testing Notes
|
|
|
|
The test system uses keystroke recording/playback with speech and braille output comparison. Tests are organized by application and toolkit. The testing framework automatically handles application launching and result comparison for regression testing.
|
|
|
|
---
|
|
|
|
## ORCA vs CTHULHU COMPARISON & INTEGRATION CONSIDERATIONS
|
|
|
|
### **Fork History & Strategic Decisions**
|
|
- **Cthulhu Origin**: Forked from Orca 45 (GNOME-45 release) - `git log` shows initial commit `a523205`
|
|
- **Strategic Goals**:
|
|
- Supplemental screen reader for advanced users
|
|
- Better support for older Qt applications
|
|
- Enhanced window manager support (i3, etc.)
|
|
- Plugin system with pluggy framework
|
|
- Community-driven development
|
|
|
|
### **Major Architectural Differences**
|
|
|
|
#### **Build Systems**
|
|
- **Cthulhu**: Autotools (102 Makefile.am files) - mature, stable build system
|
|
- **Orca**: Meson/Ninja (33 meson.build files, 84 legacy makefiles) - modern, faster builds
|
|
- **Integration Consideration**: Should Cthulhu migrate to Meson for faster builds and better dependencies?
|
|
|
|
#### **Plugin Architecture**
|
|
- **Cthulhu**: Extensive pluggy-based plugin system with 9 core plugins
|
|
- **Orca**: No comparable plugin system - features are integrated directly into core
|
|
- **Strategic Value**: Plugin system is Cthulhu's key differentiator - maintain this advantage
|
|
|
|
#### **New Orca Features (v49.alpha)**
|
|
1. **D-Bus Remote Controller** (`dbus_service.py`)
|
|
- Service: `org.gnome.Orca.Service`
|
|
- Remote command execution, module access
|
|
- Requires: `dasbus` library
|
|
- **Integration Value**: HIGH - would enable external control of Cthulhu
|
|
|
|
2. **Spiel TTS Support** (`spiel.py`)
|
|
- Alternative to speech-dispatcher
|
|
- Multi-synthesizer support (eSpeak, Piper)
|
|
- Flatpak-based providers
|
|
- **Integration Value**: MEDIUM - broader TTS options
|
|
|
|
3. **Enhanced Module Architecture**
|
|
- `focus_manager.py`, `input_event_manager.py`
|
|
- Better separation of concerns
|
|
- **Integration Value**: LOW - architectural improvement but not user-facing
|
|
|
|
### **Current Bug Investigation: Plugin Keybindings**
|
|
[Previous debugging section remains valid - plugin keybinding integration is working but needs refinement]
|
|
|
|
### **Integration Recommendations**
|
|
|
|
#### **HIGH Priority - D-Bus Remote Controller**
|
|
- **Benefit**: External application control, automation, integration with other tools
|
|
- **Risk**: LOW - self-contained feature, minimal core impact
|
|
- **Files to Port**: `dbus_service.py`, related D-Bus infrastructure
|
|
- **Dependencies**: Add `dasbus` to Cthulhu's requirements
|
|
|
|
#### **MEDIUM Priority - Build System Migration**
|
|
- **Benefit**: Faster builds, better dependency management, alignment with GNOME ecosystem
|
|
- **Risk**: MEDIUM - significant build system changes, potential disruption
|
|
- **Approach**: Gradual migration, maintain autotools compatibility initially
|
|
|
|
#### **LOW Priority - Spiel Integration**
|
|
- **Benefit**: More TTS options, potentially better voice quality
|
|
- **Risk**: MEDIUM - additional complexity, Flatpak dependencies
|
|
- **Approach**: Optional feature, don't replace speech-dispatcher by default
|
|
|
|
### **Files Requiring Attention for Integration**
|
|
|
|
#### **D-Bus Remote Controller Integration**:
|
|
```bash
|
|
# Core files to review and potentially port:
|
|
src/orca/dbus_service.py # Main D-Bus service implementation
|
|
README-REMOTE-CONTROLLER.md # API documentation and examples
|
|
```
|
|
|
|
#### **Build System Files**:
|
|
```bash
|
|
# Modern build configuration to consider:
|
|
meson.build # Root build configuration
|
|
meson_options.txt # Build options
|
|
subprojects/spiel.wrap # Subproject integration
|
|
```
|
|
|
|
### **Strategic Questions for Decision**
|
|
|
|
1. **Build System**: Should Cthulhu migrate to Meson for better GNOME ecosystem alignment?
|
|
2. **D-Bus Interface**: High value feature - should this be priority #1 for integration?
|
|
3. **Plugin System**: How to maintain Cthulhu's plugin advantage while integrating Orca improvements?
|
|
4. **Version Strategy**: Selective feature backporting vs. major version sync?
|
|
|
|
## D-Bus Remote Controller Integration
|
|
|
|
### **NEW FEATURE**: D-Bus Service for Remote Control
|
|
Cthulhu now includes a D-Bus service (ported from Orca v49.alpha) for external control and automation:
|
|
|
|
- **Service Name**: `org.stormux.Cthulhu.Service`
|
|
- **Object Path**: `/org/stormux/Cthulhu/Service`
|
|
- **Dependency**: `dasbus` library (automatically detected)
|
|
|
|
### Testing D-Bus Functionality
|
|
```bash
|
|
# Start Cthulhu with D-Bus service
|
|
~/.local/bin/cthulhu
|
|
|
|
# Test service availability
|
|
busctl --user list | grep Cthulhu
|
|
|
|
# Get Cthulhu version via D-Bus
|
|
busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service org.stormux.Cthulhu.Service GetVersion
|
|
|
|
# Present message to user via D-Bus
|
|
busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service org.stormux.Cthulhu.Service PresentMessage s "Hello from D-Bus"
|
|
|
|
# List available modules and commands
|
|
busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service org.stormux.Cthulhu.Service ListModules
|
|
```
|
|
|
|
### Integration Status
|
|
- ✅ **Core D-Bus service**: Fully ported and integrated
|
|
- ✅ **Service lifecycle**: Automatic start/shutdown with Cthulhu
|
|
- ✅ **Message presentation**: `PresentMessage()` method working - **FULLY FUNCTIONAL**
|
|
- ✅ **Version info**: `GetVersion()` method working - **FULLY FUNCTIONAL**
|
|
- ✅ **Circular import issues**: All resolved - Cthulhu imports work correctly
|
|
- ✅ **GDK version conflicts**: Fixed with proper gi.require_version calls
|
|
- ✅ **Presenter singleton patterns**: Fixed with lazy initialization
|
|
- ✅ **Settings manager backend**: Fixed with proper activation sequence
|
|
- ✅ **ATSPI registry startup**: Fixed with deferred D-Bus service initialization
|
|
- ✅ **API naming conventions**: All Orca→Cthulhu API differences resolved
|
|
- 🔄 **Module registration**: Ready for individual managers to register D-Bus commands
|
|
- 🔄 **Plugin integration**: Plugins can expose D-Bus commands using decorators
|
|
|
|
### **✅ COMPLETED - D-Bus Remote Controller Integration**
|
|
The D-Bus Remote Controller from Orca v49.alpha has been successfully integrated into Cthulhu and is fully functional.
|
|
|
|
**Root Cause of Issues**: D-Bus service startup timing conflicts with ATSPI registry initialization.
|
|
|
|
**Solution Implemented**:
|
|
- Deferred D-Bus service startup using `GObject.idle_add()` after ATSPI event loop is running
|
|
- Fixed all API naming convention differences between Orca and Cthulhu
|
|
|
|
**Files Modified for D-Bus Integration**:
|
|
- `src/cthulhu/dbus_service.py` (NEW FILE) - Complete D-Bus service port with Cthulhu API fixes
|
|
- `src/cthulhu/input_event.py` - Added RemoteControllerEvent + GDK version fix
|
|
- `src/cthulhu/cthulhu.py` - D-Bus integration + lazy BrailleEvent import + settings manager activation + deferred startup
|
|
- `src/cthulhu/Makefile.am` - Added dbus_service.py to build
|
|
- Multiple presenter files - Converted to lazy initialization pattern
|
|
- `src/cthulhu/keybindings.py` - Fixed GDK version requirement
|
|
- `README-REMOTE-CONTROLLER.md` (NEW FILE) - Complete documentation with examples
|
|
|
|
**API Fixes Applied**:
|
|
- `debug.print_message` → `debug.printMessage`
|
|
- `script_manager.get_manager()` → `script_manager.getManager()`
|
|
- `get_active_script()` → `cthulhu_state.activeScript`
|
|
- `get_default_script()` → `getDefaultScript()`
|
|
|
|
### Bug Fixes Applied
|
|
- Fixed circular imports in presenter modules (learn_mode_presenter, notification_presenter, etc.)
|
|
- Added lazy imports for BrailleEvent to break cthulhu.py ↔ input_event.py cycle
|
|
- Fixed GDK version conflicts by adding gi.require_version("Gdk", "3.0") to input_event.py
|
|
- Changed all presenter singleton patterns to lazy initialization to prevent import-time issues
|
|
- Added settings manager activation before loadUserSettings() to fix backend initialization
|
|
|
|
### **Commands for Analysis**
|
|
```bash
|
|
# Compare specific features between projects
|
|
diff -r /home/storm/devel/cthulhu/src/cthulhu /home/storm/devel/orca/src/orca
|
|
|
|
# Test Orca's new features
|
|
cd /home/storm/devel/orca && meson setup _build && meson compile -C _build
|
|
|
|
# Test D-Bus interface
|
|
# (requires running Orca instance with D-Bus support)
|
|
``` |