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>
15 KiB
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)
# 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)
# 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)
# Using pip/hatchling
pip install -e .
Testing
# 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
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:
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:
# 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:
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:
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:
[Core]
Name = PluginName
Module = PluginName
[Documentation]
Description = Plugin description
Author = Author Name
Version = 1.0.0
Website = https://example.com
Makefile.am template:
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:
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 codetest/
- Regression test framework with keystroke-based testingpo/
- Internationalization files (extensive i18n support)help/
- Multi-language user documentationci/
- 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 commita523205
- 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)
-
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
- Service:
-
Spiel TTS Support (
spiel.py
)- Alternative to speech-dispatcher
- Multi-synthesizer support (eSpeak, Piper)
- Flatpak-based providers
- Integration Value: MEDIUM - broader TTS options
-
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:
# 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:
# Modern build configuration to consider:
meson.build # Root build configuration
meson_options.txt # Build options
subprojects/spiel.wrap # Subproject integration
Strategic Questions for Decision
- Build System: Should Cthulhu migrate to Meson for better GNOME ecosystem alignment?
- D-Bus Interface: High value feature - should this be priority #1 for integration?
- Plugin System: How to maintain Cthulhu's plugin advantage while integrating Orca improvements?
- 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
# 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 fixessrc/cthulhu/input_event.py
- Added RemoteControllerEvent + GDK version fixsrc/cthulhu/cthulhu.py
- D-Bus integration + lazy BrailleEvent import + settings manager activation + deferred startupsrc/cthulhu/Makefile.am
- Added dbus_service.py to build- Multiple presenter files - Converted to lazy initialization pattern
src/cthulhu/keybindings.py
- Fixed GDK version requirementREADME-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
# 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)