90 Commits

Author SHA1 Message Date
Storm Dragon e2f9a7c2e2 A few touch ups before release tag. 2026-05-14 18:42:06 -04:00
Storm Dragon 922ba60445 Make new cthulhu-git arch package for testing latest code. 2026-05-09 22:08:13 -04:00
Storm Dragon a5f7c9a8f3 Work on sound positioning for objects. Enable in sounds in preferences. 2026-05-08 07:41:44 -04:00
Storm Dragon 6f33caade1 Sound should now stop when speech stops. This means no more interrupting speech just to have the link sounds on a page continue to play. 2026-05-08 01:02:57 -04:00
Storm Dragon e54600ff4d Reworked the xterm hand off so it's faster and more reliable. 2026-05-07 18:05:16 -04:00
Storm Dragon e6b6b1051e A few minor fixes for windows that aren't reported by at-spi. 2026-05-07 12:31:25 -04:00
Storm Dragon e377f39fe3 version update. 2026-05-06 19:27:11 -04:00
Storm Dragon 42006f4725 Merge branch 'testing' 2026-05-06 19:23:44 -04:00
Storm Dragon 3ae49f48ac A bit of pre-release polish. 2026-05-06 19:23:07 -04:00
Storm Dragon 4c0c0013ca Version bump. 2026-05-02 18:53:06 -04:00
Storm Dragon 77b7c81d73 Potential fix for nvda2cthulhu plugin crash bug. 2026-05-02 17:59:39 -04:00
Storm Dragon 265feb8188 Backport Orca's d-bus remote fixes. 2026-04-26 13:18:23 -04:00
Storm Dragon 337b5d4273 Hopefully fixed a weird speech bug where some games could make it suddenly stop speaking. 2026-04-25 19:03:24 -04:00
Storm Dragon 1707dca020 Fixed a regression in table navigation. 2026-04-12 15:19:09 -04:00
Storm Dragon 60d3fc613b docs: clarify Xorg-first platform stance 2026-04-11 21:13:52 -04:00
Storm Dragon 23abeca651 docs: clarify current fork maintenance 2026-04-10 19:03:43 -04:00
Storm Dragon a98aa174f8 docs: add Tolk NVDA presence compatibility design 2026-04-10 14:07:25 -04:00
hjozwiak ec7e073431 Add pywayland to the dependencies array. 2026-04-09 12:19:26 -04:00
hjozwiak 5bb5f3d711 fix: harden Wayland compositor runtime checks 2026-04-09 12:02:26 -04:00
hjozwiak 8fc77c5a2f feat: prioritize script activation using compositor context 2026-04-09 12:02:26 -04:00
hjozwiak 309822a0ca feat: suppress stale AT-SPI churn from compositor state 2026-04-09 12:02:26 -04:00
hjozwiak 80d53ebcc3 fix: dispatch Wayland workspace events at runtime 2026-04-09 12:02:06 -04:00
hjozwiak 3671b0d6b9 fix: normalize workspace state signals 2026-04-09 12:02:06 -04:00
hjozwiak d0aef1331d feat: add shared Wayland workspace backend 2026-04-09 12:02:06 -04:00
hjozwiak f2f1de737d fix: tighten compositor adapter lifecycle 2026-04-09 12:02:06 -04:00
hjozwiak 0f54fad9ba feat: add compositor state adapter scaffold 2026-04-09 12:02:06 -04:00
hjozwiak daf3d46eeb fix: add relevance gate state defaults 2026-04-09 11:42:16 -04:00
hjozwiak 16004af7c1 fix: tighten relevance gate focus handling 2026-04-09 11:38:09 -04:00
hjozwiak 45b57b4d13 feat: wire event relevance gate 2026-04-09 11:38:09 -04:00
hjozwiak 629785d548 refactor: add relevance gate helpers 2026-04-09 11:38:09 -04:00
hjozwiak fb5684f8ef fix: restore speech dispatcher interruption 2026-04-09 11:34:41 -04:00
hjozwiak 56030567ed test: harden relevance gate regressions 2026-04-09 10:41:06 -04:00
hjozwiak 6793522d93 test: add relevance gate regressions 2026-04-09 10:35:15 -04:00
hjozwiak 67abceda9a Add Wayland compositor event interface design spec 2026-04-09 06:14:03 -04:00
hjozwiak cc5adf4cce Merge branch 'atspi-document-selection' into testing 2026-04-09 05:24:07 -04:00
hjozwiak 04c79f2e0f Implement AT-SPI selection bridging groundwork
Add the document selection adapter, integrate it through script utilities and major callers, and package the clipboard fallback work that was needed during manual testing on Wayland.

Also include a handoff note for the still-open browser link-selection issue so other developers can continue from the current branch state without reconstructing the debug trail.
2026-04-09 05:22:00 -04:00
hjozwiak 4a41b51d37 Ignore local worktrees 2026-04-08 18:35:36 -04:00
Storm Dragon 3dc565e8df Actually add the link sound files. :) 2026-04-08 17:29:36 -04:00
Storm Dragon 6e049e35e2 Attempt to speed up Steam even more. Sound for link added. 2026-04-08 06:41:24 -04:00
Storm Dragon ee4292564a More hopeful fixes for wayland. 2026-04-08 04:19:37 -04:00
Storm Dragon eeb7bd046f Hopefully fix some wayland keyboard stuff. 2026-04-08 03:37:50 -04:00
Storm Dragon 2d9790de88 Improvements with Steam. 2026-04-07 19:03:46 -04:00
Storm Dragon 633ff214a4 Install Wnck session support helpers 2026-04-07 17:37:07 -04:00
Storm Dragon ceb03668b9 Add guarded AT-SPI pointer mouse review backend 2026-04-07 17:15:27 -04:00
Storm Dragon d7d26c57f4 Add AT-SPI pointer monitor wrappers 2026-04-07 17:11:13 -04:00
Storm Dragon 8e792dd4e2 Add mouse review Wayland backport design spec 2026-04-07 16:29:42 -04:00
Storm Dragon 9c94191583 Hell of a speed boost for Steam. 2026-04-07 16:07:32 -04:00
Storm Dragon d51ef2ad69 Attempt to prevent key pass through in wayland. Hopefully also improve web browsing speed. 2026-04-07 15:39:49 -04:00
hjozwiak e72cc79c6a When dismissing a message, it should be removed from the list and the tree view. 2026-04-06 23:53:46 -04:00
hjozwiak 667c0babcb Add support for getting at the actions of notifications inline. 2026-04-06 23:08:20 -04:00
hjozwiak a8950c42e2 Initial support for mako notification daemon. 2026-04-06 21:09:41 -04:00
hjozwiak 91edf64a72 Drop claude.md. 2026-04-06 20:27:17 -04:00
Storm Dragon 296c47be36 Sounds split off into own tab in settings. 2026-04-05 21:32:06 -04:00
Storm Dragon 5779444d4b Add persisted progress bar beep interval setting 2026-04-05 21:05:39 -04:00
Storm Dragon c072f903db Add sounds tab design spec 2026-04-05 20:48:41 -04:00
Storm Dragon 64ad1ab3e0 Hopefully fixed weird gstreamer traceback. 2026-04-04 23:04:33 -04:00
Storm Dragon 20e61d6259 Merge branch 'testing' 2026-04-04 21:44:47 -04:00
Storm Dragon a750761f61 Steam UI improvements. 2026-04-04 20:22:54 -04:00
Storm Dragon 03b3880622 Merge branch 'testing' 2026-04-04 19:05:35 -04:00
Storm Dragon f4af54228a Tightened up Steam notifications. Fixed a system notifications regression.? 2026-04-04 19:04:45 -04:00
Storm Dragon 518d2b3bb6 Attempt to make the sound system more robust. Improve some web component detection. Fixed a place where Cthulhu gets stuck on netgear's web interface. 2026-04-04 18:31:11 -04:00
Storm Dragon 7043f08dab Simplify GStreamer sound playback 2026-03-23 13:51:42 -04:00
Storm Dragon d0bc7d8a3a I tested these changes for so long I actually forgot what they were, but they seem to work, so committing. 2026-03-23 12:46:27 -04:00
Storm Dragon 438fae4fef Fix script manager resets and isolate startup sound 2026-03-23 12:44:12 -04:00
Storm Dragon a7cd1d033a Speculative fix on preferences weirdness. 2026-03-09 01:14:01 -04:00
Storm Dragon c4890f31af Fix 2026.03.02 release versioning 2026-03-02 17:56:45 -05:00
Storm Dragon c44245189a Merge branch 'testing' 2026-03-02 15:42:15 -05:00
Storm Dragon c7b8e4a30d Clean stale autostart source references from translations 2026-03-02 15:42:04 -05:00
Storm Dragon 20fe1a7e30 Remove autogenerated autostart desktop template 2026-03-02 15:38:29 -05:00
Storm Dragon 25931758f7 Merge branch 'testing'
# Conflicts:
#	distro-packages/Arch-Linux/PKGBUILD
#	meson.build
#	src/cthulhu/cthulhuVersion.py
2026-03-02 15:37:50 -05:00
Storm Dragon daf57ef22c Removed the autogenerated autostart desktop file. Moved the desktop file to contrib so it's still available if people want it. 2026-02-25 23:20:05 -05:00
Storm Dragon 1d2d727fa2 Requested feature added. It is now possible to customize speech used for echo settings including speech module, voice, rate, volume, pitch. 2026-02-22 01:44:19 -05:00
Storm Dragon 11bd7107d2 Attempt to stop plugins from spontaneously re-enabling themselves. 2026-02-19 02:40:46 -05:00
Storm Dragon 95d33047fa Fix prefs state churn and sound-only role speech
Some settings were being reset when tab changed and a key was pressed, e.g. control.

Radio buttons were still announced even with sound only set.

Controls for AI assistant tab were vanishing after being set.
2026-02-18 07:03:12 -05:00
Storm Dragon 523b896053 Couple minor bug fixes, new speech code added in prefs. 2026-02-18 06:10:57 -05:00
Storm Dragon 9152455227 Speech in settings now uses the voice when switched to it. 2026-02-18 06:07:55 -05:00
Storm Dragon c0fdaca4d0 Merge remote-tracking branch 'origin/web-and-punctuation-fixes' into testing 2026-02-17 14:50:01 -05:00
destructatron 8312a842c1 Fix duplicate role name when aria-roledescription is present
When an element has aria-roledescription (e.g. Discord messages use
'Message'), _generateRoleName was adding both the roledescription AND
the standard localized role name (e.g. 'article'). This resulted in
the role being announced twice.

The aria-roledescription attribute is intended to replace the standard
role name, not supplement it. Return early after adding the
roledescription to match Orca's behavior.
2026-02-17 19:21:36 +00:00
destructatron 07138197cb Fix web content editable label, line boundary, and punctuation bugs
Bug 1: Content editable entry label not announced on caret-nav focus
- When navigating into a content editable via caret navigation (e.g. down
  arrow from message list to message entry in Discord), the label and role
  were suppressed because the code treated entering the field the same as
  navigating within it.
- Fixed locus_of_focus_changed in web/script.py to detect when focus enters
  a content editable from outside and generate full object speech.
- Fixed _generateLabelOrName in web/speech_generator.py to preserve the
  label when the prior object was outside the content editable.

Bug 2: Adjacent button included in line contents on first line
- When reading line contents inside a content editable, the layout-mode
  expansion could walk outside the content editable boundary and include
  adjacent UI elements (e.g. a 'More options' button) that happened to
  share the same visual line.
- Fixed _getLineContentsAtOffset in web/script_utilities.py to stop
  expanding at content editable boundaries in both directions.

Bug 3: Punctuation stripped from live regions and AT-SPI announcements
- presentMessage uses resetStyles=True by default, which sets punctuation
  to NONE for system voice messages. This is correct for generated text
  but wrong for user content in live regions and AT-SPI announcements.
- Fixed liveregions.py pumpMessages and default.py onAnnouncement to pass
  resetStyles=False, preserving the user's punctuation settings.
2026-02-17 19:07:41 +00:00
Storm Dragon ed78ffc248 Visual speech monitor added to speech history plugin. Toggle with cthulhu+shift+D 2026-02-17 08:40:51 -05:00
Storm Dragon 4add36f5ca latest changed merged, seems to be reasonably stable. 2026-02-17 08:01:47 -05:00
Storm Dragon 40e63150a6 Read a list of applications that should always be started in sleep mode from sleep.toml. 2026-02-17 07:57:14 -05:00
Storm Dragon 4dba0ec0cd Fixed a bug with sleep mode, was not suspending review keys for sleeping applications. 2026-02-16 14:55:56 -05:00
Storm Dragon e6f780c38b New code tested and seems pretty stable so merged and bumped version. 2026-02-15 12:10:36 -05:00
Storm Dragon 0f7f73a6a0 Fixed flat review bug affecting some sites in chrome. 2026-02-13 13:23:14 -05:00
Storm Dragon aa71d02036 Merge remote-tracking branch 'origin/keyboard-monitoring-api' into testing 2026-02-13 11:19:40 -05:00
destructatron 51ef3de672 Port keyboard monitoring API from Orca, and fix flat review bug in GTK apps 2026-02-13 10:14:04 +00:00
Storm Dragon c6049ef5f3 Preparing for release. 2026-01-26 13:07:33 -05:00
Storm Dragon 78ef51d01f Latest code, hopefully stable. 2026-01-19 05:24:48 -05:00
Storm Dragon 30a40f6974 Merged dbus implementation for plugins. 2026-01-12 11:54:42 -05:00
216 changed files with 16402 additions and 15988 deletions
+2
View File
@@ -75,6 +75,7 @@ debug.log
# Package artifacts
*.pkg.tar.zst
distro-packages/*/cthulhu/
distro-packages/*/cthulhu-git/
distro-packages/*/pkg/
# Generated makefiles (should not be committed)
@@ -103,3 +104,4 @@ po/insert-header.sed
/help/*/*.mo
/help/*/*.stamp
.aider*
.worktrees/
+22
View File
@@ -14,6 +14,23 @@ This repository is a screen reader. Prioritize accessibility, correctness, and s
- `meson compile -C _build`
- `meson install -C _build`
## Runtime target and testing rules
- Make source changes in this repo, not in `~/.local/lib/python*/site-packages/cthulhu/`, unless the user explicitly asks for an installed-package hotfix.
- If you confirm the active import comes from `~/.local/...`, that does **not** mean you should edit there. It means you should update the repo and then run `./build-local.sh` to replace the installed copy for testing.
- Default test/apply workflow for local Cthulhu fixes:
- edit repo files
- run `./build-local.sh`
- reproduce/test against the refreshed `~/.local` install
- If repo and installed behavior differ, prefer rebuilding with `./build-local.sh` over patching the installed package directly.
- Treat direct edits under `~/.local/.../cthulhu/` as an exception path that requires explicit user approval.
## Platform support stance
- **critical** Robust Xorg support is required and is a merge gate for Cthulhu.
- Wayland support is desirable, but it is secondary to keeping Xorg stable and usable.
- If a change that improves Wayland would break, weaken, or regress Xorg support, the answer is a hard no by default.
- If the user explicitly insists on such a change anyway, warn them plainly that the change is expected to be rejected without further consideration as long as Xorg is adversely affected.
- Prefer desktop-agnostic fixes first. If a tradeoff is unavoidable, choose the path that preserves Xorg correctness and defer the Wayland-specific improvement.
## Coding guidelines
- **When modifying existing code:** follow the surrounding codes conventions.
- **When writing new code from scratch:** prefer
@@ -55,3 +72,8 @@ This repository is a screen reader. Prioritize accessibility, correctness, and s
## Meson install reminder (important)
- If you add new Python modules under `src/cthulhu/`, update `src/cthulhu/meson.build` so they get installed (otherwise imports can fail after install).
- If you add a new plugin directory, update `src/cthulhu/plugins/meson.build` and add a `meson.build` in the plugin directory.
## Common Cthulhu agent mistakes
- Checking the import origin, seeing `~/.local/...`, and then editing the installed package instead of the repo.
- Forgetting that `./build-local.sh` is the normal way to apply repo changes into the installed copy for testing.
- Making repo fixes and then diagnosing the old installed copy without rebuilding.
-182
View File
@@ -1,182 +0,0 @@
# 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, designed as a desktop-agnostic screen reader for Linux. It works with applications supporting AT-SPI (Assistive Technology Service Provider Interface) including GTK+, Qt, Java Swing, LibreOffice, Gecko, and WebKitGtk.
**Key differentiators from Orca:**
- Desktop-agnostic: Works on KDE, XFCE, i3, Sway, and other environments (not just GNOME)
- Extensible plugin architecture using pluggy framework
- D-Bus remote control interface for external automation
- Enhanced support for tiling window managers
## Build Commands
```bash
# Local development build (installs to ~/.local)
./build-local.sh
# Test local installation
./test-local.sh
# Run local version
~/.local/bin/cthulhu
# Clean build artifacts and local installation
./clean-local.sh
./clean-local.sh --build-only # Clean only build artifacts
./clean-local.sh --install-only # Remove only local installation
# Manual Meson build
meson setup _build --prefix=$HOME/.local
meson compile -C _build
meson install -C _build
```
## Testing
Manual testing is recommended. The legacy keystroke-driven test harness has been removed.
## Architecture Overview
### Core Components (`src/cthulhu/`)
**Event & Input Processing:**
- `event_manager.py` - Central AT-SPI event handling and routing
- `input_event_manager.py` - Keyboard/mouse input processing
- `input_event.py` - Input event data structures
- `focus_manager.py` - Focus tracking across applications
**Accessibility Layer (ax_* files):**
- `ax_object.py` - Core accessible object abstraction
- `ax_utilities.py` - Common accessibility utilities
- `ax_utilities_role.py` - Role-based accessibility helpers
- `ax_utilities_collection.py` - Collection traversal utilities
- `ax_text.py`, `ax_table.py`, `ax_component.py` - Specialized interfaces
**Output Systems:**
- `speech.py`, `speechdispatcherfactory.py` - Speech synthesis
- `braille.py`, `braille_generator.py` - Braille display support
- `speech_generator.py` - Generate speech from accessible objects
- `sound.py`, `sound_generator.py` - Audio cue generation
**Script System:**
- `script_manager.py` - Loads/manages application-specific scripts
- `script.py` - Base script class
- `scripts/default.py` - Default behavior for all applications
- `scripts/apps/` - Application-specific customizations (Firefox, LibreOffice, etc.)
- `scripts/toolkits/` - Toolkit-specific scripts (GTK, Qt, WebKitGtk)
- `scripts/web/` - Web content handling
**Plugin System:**
- `plugin.py` - Base plugin class with `cthulhu_hookimpl` decorator
- `plugin_system_manager.py` - Plugin discovery and lifecycle
- `plugins/` - Built-in plugins (OCR, Clipboard, SpeechHistory, etc.)
**D-Bus Remote Control:**
- `dbus_service.py` - D-Bus service implementation
- Service: `org.stormux.Cthulhu.Service`
- Path: `/org/stormux/Cthulhu/Service`
**Settings & State:**
- `settings_manager.py` - User preferences persistence
- `settings.py` - Default settings values
- `cthulhu_state.py` - Runtime state (active script, focus, etc.)
### Key Design Patterns
**Script Inheritance:** Application scripts extend `default.Script`, overriding methods for custom behavior. The script manager selects scripts based on the focused application.
**Event Flow:** AT-SPI events → `event_manager` → active script's event handler → generators → output systems (speech/braille)
**Plugin Hooks:** Plugins implement hooks via `@cthulhu_hookimpl` decorator. Use `registerGestureByString()` for keybindings.
## Adding New Modules
When adding new Python modules under `src/cthulhu/`:
1. **Update `src/cthulhu/meson.build`** - Add the `.py` file to `cthulhu_python_sources`
2. **For new script modules** (e.g., `scripts/newmodule/`):
- Create the directory with `__init__.py` and `script.py`
- Add `meson.build` in the new directory
- Add subdirectory to `src/cthulhu/scripts/meson.build`
3. **For new plugins**:
- Create directory under `src/cthulhu/plugins/` with:
- `__init__.py`, `plugin.py`, `plugin.info`, `meson.build`
- Add subdirectory to `src/cthulhu/plugins/meson.build`
## Plugin Structure
```
src/cthulhu/plugins/MyPlugin/
├── __init__.py # from .plugin import *
├── plugin.py # Main implementation extending Plugin
├── plugin.info # Metadata (name, version, description, etc.)
└── meson.build # install_data for .py and .info files
```
Example plugin.py:
```python
from cthulhu.plugin import Plugin, cthulhu_hookimpl
class MyPlugin(Plugin):
@cthulhu_hookimpl
def activate(self, plugin=None):
if plugin is not None and plugin is not self:
return
self.registerGestureByString(self.myHandler, "description", "kb:cthulhu+key")
def myHandler(self, script=None, inputEvent=None):
self.app.getDynamicApiManager().getAPI('CthulhuState').activeScript.presentMessage('Message')
return True
```
## D-Bus Testing
```bash
# Check service availability
busctl --user list | grep Cthulhu
# Get version
busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service \
org.stormux.Cthulhu.Service GetVersion
# Present message
busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service \
org.stormux.Cthulhu.Service PresentMessage s "Hello"
# Introspect available methods
busctl --user introspect org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service
```
## Key Keybindings
- `Cthulhu+Space` - Open preferences
- `Cthulhu+H` - Enter learn mode
- `Cthulhu+Ctrl+Alt+Shift+Q` - Toggle sleep mode for current application
- `Cthulhu+Q` - Quit Cthulhu
## Self-Voicing Interface
External applications can speak through Cthulhu via Unix socket:
```bash
echo "Hello world" | socat - UNIX-CLIENT:/tmp/cthulhu.sock
echo "<!#APPEND#!>Without interrupt" | socat - UNIX-CLIENT:/tmp/cthulhu.sock
```
## Dependencies
**Core:** Python 3.9+, pygobject-3.0, gtk+-3.0, AT-SPI2, ATK
**Speech:** python-speechd, gstreamer-1.0
**Plugins:** pluggy, python-dasbus (optional, for D-Bus)
**Braille:** BrlTTY, BrlAPI, liblouis (optional)
## Repository
- **Main repo:** https://git.stormux.org/storm/cthulhu
- **Community:** IRC #stormux on irc.stormux.org
- **Email patches:** storm_dragon@stormux.org
-13049
View File
File diff suppressed because it is too large Load Diff
+10 -6
View File
@@ -1,5 +1,9 @@
# Cthulhu Development Guide
This document applies to the Cthulhu fork maintained by Storm Dragon.
Cthulhu is forked from Orca; prior Orca maintainers and contributors are part
of the upstream history, but they are not current maintainers of this fork.
## Local Development Build
To develop Cthulhu without overwriting your system installation, use the provided build scripts:
@@ -55,8 +59,8 @@ cthulhu
Cthulhu now includes a D-Bus service for remote control:
- **Service**: `org.stormux.Cthulhu.Service`
- **Path**: `/org/stormux/Cthulhu/Service`
- **Service**: `org.stormux.Cthulhu1.Service`
- **Path**: `/org/stormux/Cthulhu1/Service`
- **Requires**: `dasbus` library (should be installed)
### Testing D-Bus Service
@@ -66,10 +70,10 @@ Cthulhu now includes a D-Bus service for remote control:
~/.local/bin/cthulhu
# In another terminal, test the service
busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service org.stormux.Cthulhu.Service GetVersion
busctl --user call org.stormux.Cthulhu1.Service /org/stormux/Cthulhu1/Service org.stormux.Cthulhu1.Service GetVersion
# Present a message via D-Bus
busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service org.stormux.Cthulhu.Service PresentMessage s "Hello from D-Bus"
busctl --user call org.stormux.Cthulhu1.Service /org/stormux/Cthulhu1/Service org.stormux.Cthulhu1.Service PresentMessage s "Hello from D-Bus"
```
## Development Workflow
@@ -98,11 +102,11 @@ git status
## Dependencies
- **Runtime**: python3, pygobject-3.0, pluggy, AT-SPI2
- **Runtime**: python3, pygobject-3.0, pluggy, tomlkit, AT-SPI2
- **Build**: meson, ninja, gettext
- **Optional**: dasbus (for D-Bus service), BrlTTY, speech-dispatcher, piper-tts
Install build dependencies on Arch Linux:
```bash
sudo pacman -S meson ninja gettext python-dasbus
sudo pacman -S meson ninja gettext python-dasbus python-tomlkit
```
+94 -174
View File
@@ -1,5 +1,10 @@
# Cthulhu Remote Controller (D-Bus Interface)
This documentation covers the Cthulhu fork maintained by Storm Dragon.
Cthulhu is forked from Orca; former Orca maintainers and contributors are part
of the project's upstream history, but they are not current maintainers of
this fork.
> **⚠️⚠️ WORK IN PROGRESS**: This D-Bus interface is brand new and not yet feature complete.
Low-risk feature additions will continue to be made. The API may be
modified beyond bug fixes in future versions based on feedback from consumers of this support.
@@ -17,10 +22,11 @@ on any Linux desktop environment or window manager.
Cthulhu exposes a D-Bus service at:
- **Service Name**: `org.stormux.Cthulhu.Service`
- **Main Object Path**: `/org/stormux/Cthulhu/Service`
- **Module Object Paths**: `/org/stormux.Cthulhu/Service/ModuleName`
(e.g., `/org/stormux/Cthulhu/Service/SpeechAndVerbosityManager`)
- **Service Name**: `org.stormux.Cthulhu1.Service`
- **Main Object Path**: `/org/stormux/Cthulhu1/Service`
- **Module Object Paths**: `/org/stormux/Cthulhu1/Service/ModuleName`
(e.g., `/org/stormux/Cthulhu1/Service/SpeechManager`)
- **Module Interfaces**: `org.stormux.Cthulhu1.ModuleName`
See [REMOTE-CONTROLLER-COMMANDS.md](REMOTE-CONTROLLER-COMMANDS.md) for a complete
list of available commands.
@@ -38,34 +44,34 @@ While this documentation primarily uses `gdbus` for examples, you can use any D-
### Using `busctl` (systemd D-Bus tool)
```bash
busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service \
org.stormux.Cthulhu.Service GetVersion
busctl --user call org.stormux.Cthulhu1.Service /org/stormux/Cthulhu1/Service \
org.stormux.Cthulhu1.Service GetVersion
```
### Using Python with `dasbus`
```python
from dasbus.connection import SessionMessageBus
bus = SessionMessageBus()
proxy = bus.get_proxy("org.stormux.Cthulhu.Service", "/org/stormux/Cthulhu/Service")
proxy = bus.get_proxy("org.stormux.Cthulhu1.Service", "/org/stormux/Cthulhu1/Service")
version = proxy.GetVersion()
```
### Using `qdbus` (Qt D-Bus tool - available on KDE)
```bash
qdbus org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service \
org.stormux.Cthulhu.Service.GetVersion
qdbus org.stormux.Cthulhu1.Service /org/stormux/Cthulhu1/Service \
org.stormux.Cthulhu1.Service.GetVersion
```
## Service-Level Commands
Commands available directly on the main service (`/org/stormux/Cthulhu/Service`):
Commands available directly on the main service (`/org/stormux/Cthulhu1/Service`):
### Get Cthulhu's Version
```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service \
--method org.stormux.Cthulhu.Service.GetVersion
gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu1/Service \
--method org.stormux.Cthulhu1.Service.GetVersion
```
**Returns:** String containing the version (and revision if available)
@@ -73,9 +79,9 @@ gdbus call --session --dest org.stormux.Cthulhu.Service \
### Present a Custom Message in Speech and/or Braille
```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service \
--method org.stormux.Cthulhu.Service.PresentMessage "Your message here"
gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu1/Service \
--method org.stormux.Cthulhu1.Service.PresentMessage "Your message here"
```
**Parameters:**
@@ -87,9 +93,9 @@ gdbus call --session --dest org.stormux.Cthulhu.Service \
### Show Cthulhu's Preferences GUI
```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service \
--method org.stormux.Cthulhu.Service.ShowPreferences
gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu1/Service \
--method org.stormux.Cthulhu1.Service.ShowPreferences
```
**Returns:** Boolean indicating success
@@ -97,44 +103,39 @@ gdbus call --session --dest org.stormux.Cthulhu.Service \
### Quit Cthulhu
```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service \
--method org.stormux.Cthulhu.Service.Quit
gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu1/Service \
--method org.stormux.Cthulhu1.Service.Quit
```
**Returns:** Boolean indicating if the quit request was accepted
### List Available Service Commands
## Discovering Modules and Their Capabilities
Use the standard DBus introspection interface to discover registered modules:
```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service \
--method org.stormux.Cthulhu.Service.ListCommands
gdbus introspect --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu1/Service --recurse
```
**Returns:** List of (command_name, description) tuples
### List Registered Modules
The child `<node>` entries beneath `/org/stormux/Cthulhu1/Service` are the
registered modules. To inspect the methods and properties for one module:
```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service \
--method org.stormux.Cthulhu.Service.ListModules
gdbus introspect --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu1/Service/SpeechManager
```
**Returns:** List of module names
## Interacting with Modules
Each registered module exposes its own set of operations. Based on the underlying Cthulhu code, these
are categorized as **Commands**, **Runtime Getters**, and **Runtime Setters**:
Each registered module exposes its own native DBus interface. Based on the underlying Cthulhu code,
these are categorized as **Commands** and **Properties**:
- **Commands**: Actions that perform a task. These typically correspond to Cthulhu commands bound
to a keystroke (e.g., `IncreaseRate`).
- **Runtime Getters**: Operations that retrieve the current value of an item, often a setting
(e.g., `GetRate`).
- **Runtime Setters**: Operations that set the current value of an item, often a setting
(e.g., `SetRate`). Note that setting a value does NOT cause it to become permanently saved.
- **Properties**: Runtime values, often settings (e.g., `Rate`). Setting a property does not cause
it to become permanently saved.
You can discover and execute these for each module.
@@ -142,41 +143,41 @@ You can discover and execute these for each module.
Plugins that expose D-Bus decorators are automatically registered as modules using the naming
convention `Plugin_<ModuleName>` (e.g., `Plugin_GameMode`, `Plugin_WindowTitleReader`). Use
`ListModules` to discover available plugin modules at runtime.
standard DBus introspection to discover available plugin modules at runtime.
#### Plugin_WindowTitleReader
Controls for the Window Title Reader plugin:
- Parameterized command: `SetEnabled` (`enabled`: bool)
- Runtime getter: `Enabled`
- Method: `SetEnabled` (`enabled`: bool, `notify_user`: bool)
- Property: `Enabled`
Example:
```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/Plugin_WindowTitleReader \
--method org.stormux.Cthulhu.Module.ExecuteParameterizedCommand \
'SetEnabled' '{"enabled": <true>}' false
gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu1/Service/Plugin_WindowTitleReader \
--method org.stormux.Cthulhu1.Plugin_WindowTitleReader.SetEnabled true false
# Check current state
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/Plugin_WindowTitleReader \
--method org.stormux.Cthulhu.Module.ExecuteRuntimeGetter 'Enabled'
gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu1/Service/Plugin_WindowTitleReader \
--method org.freedesktop.DBus.Properties.Get \
org.stormux.Cthulhu1.Plugin_WindowTitleReader Enabled
```
Busctl example:
```bash
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/Plugin_WindowTitleReader \
org.stormux.Cthulhu.Module ExecuteParameterizedCommand \
s a{sv} b 'SetEnabled' 1 enabled b true false
busctl --user call org.stormux.Cthulhu1.Service \
/org/stormux/Cthulhu1/Service/Plugin_WindowTitleReader \
org.stormux.Cthulhu1.Plugin_WindowTitleReader SetEnabled bb true false
# Check current state
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/Plugin_WindowTitleReader \
org.stormux.Cthulhu.Module ExecuteRuntimeGetter s 'Enabled'
busctl --user call org.stormux.Cthulhu1.Service \
/org/stormux/Cthulhu1/Service/Plugin_WindowTitleReader \
org.freedesktop.DBus.Properties Get ss \
org.stormux.Cthulhu1.Plugin_WindowTitleReader Enabled
```
### PluginSystemManager Module
@@ -185,166 +186,85 @@ The `PluginSystemManager` module provides session-only plugin control:
- `ListPlugins`
- `ListActivePlugins`
- `IsPluginActive` (parameterized)
- `SetPluginActive` (parameterized)
- `IsPluginActive`
- `SetPluginActive`
- `RescanPlugins`
These calls do **not** persist changes to user preferences.
### Discovering Module Capabilities
#### List Commands for a Module
```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/ModuleName \
--method org.stormux.Cthulhu.Module.ListCommands
```
Replace `ModuleName` with an actual module name from `ListModules`.
**Returns:** List of (command_name, description) tuples.
#### List Parameterized Commands for a Module
```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/ModuleName \
--method org.stormux.Cthulhu.Module.ListParameterizedCommands
```
Replace `ModuleName` with an actual module name from `ListModules`.
**Returns:** List of (command_name, description, parameters) tuples, where `parameters` is a
list of (parameter_name, parameter_type) tuples.
**Example output:**
```bash
([('GetVoicesForLanguage',
'Returns a list of available voices for the specified language.',
[('language', 'str'), ('variant', 'str'), ('notify_user', 'bool')])],)
```
#### List Runtime Getters for a Module
```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/ModuleName \
--method org.stormux.Cthulhu.Module.ListRuntimeGetters
```
Replace `ModuleName` with an actual module name from `ListModules`.
**Returns:** List of (getter_name, description) tuples.
#### List Runtime Setters for a Module
```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/ModuleName \
--method org.stormux.Cthulhu.Module.ListRuntimeSetters
```
Replace `ModuleName` with an actual module name from `ListModules`.
**Returns:** List of (setter_name, description) tuples.
### Executing Module Operations
#### Execute a Runtime Getter
#### Get a Property
```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/ModuleName \
--method org.stormux.Cthulhu.Module.ExecuteRuntimeGetter 'PropertyName'
gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu1/Service/ModuleName \
--method org.freedesktop.DBus.Properties.Get \
org.stormux.Cthulhu1.ModuleName PropertyName
```
**Parameters:**
- `PropertyName` (string): The name of the runtime getter to execute.
**Returns:** The value returned by the getter as a GLib variant (type depends on the getter).
##### Example: Get the current speech rate
```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/SpeechAndVerbosityManager \
--method org.stormux.Cthulhu.Module.ExecuteRuntimeGetter 'Rate'
gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu1/Service/SpeechManager \
--method org.freedesktop.DBus.Properties.Get \
org.stormux.Cthulhu1.SpeechManager Rate
```
This will return the rate as a GLib Variant.
#### Execute a Runtime Setter
#### Set a Property
```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/ModuleName \
--method org.stormux.Cthulhu.Module.ExecuteRuntimeSetter 'PropertyName' <value>
gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu1/Service/ModuleName \
--method org.freedesktop.DBus.Properties.Set \
org.stormux.Cthulhu1.ModuleName PropertyName '<value>'
```
**Parameters:**
- `PropertyName` (string): The name of the runtime setter to execute.
- `<value>`: The value to set, as a GLib variant (type depends on the setter).
**Returns:** Boolean indicating success.
##### Example: Set the current speech rate
```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/SpeechAndVerbosityManager \
--method org.stormux.Cthulhu.Module.ExecuteRuntimeSetter 'Rate' '<90>'
gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu1/Service/SpeechManager \
--method org.freedesktop.DBus.Properties.Set \
org.stormux.Cthulhu1.SpeechManager Rate '<90>'
```
#### Execute a Module Command
```bash
# With user notification
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/ModuleName \
--method org.stormux.Cthulhu.Module.ExecuteCommand 'CommandName' true
gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu1/Service/ModuleName \
--method org.stormux.Cthulhu1.ModuleName.CommandName true
# Without user notification (silent)
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/ModuleName \
--method org.stormux.Cthulhu.Module.ExecuteCommand 'CommandName' false
gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu1/Service/ModuleName \
--method org.stormux.Cthulhu1.ModuleName.CommandName false
```
**Parameters (both required):**
- `CommandName` (string): The name of the command to execute
- `notify_user` (boolean): Whether to notify the user of the action (see section below)
**Returns:** Boolean indicating success
#### Execute a Parameterized Command
```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/ModuleName \
--method org.stormux.Cthulhu.Module.ExecuteParameterizedCommand 'CommandName' \
'{"param1": <"value1">, "param2": <"value2">}' false
gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu1/Service/ModuleName \
--method org.stormux.Cthulhu1.ModuleName.CommandName \
"value1" "value2" false
```
**Parameters:**
- `CommandName` (string): The name of the parameterized command to execute
- `parameters` (dict): Dictionary of parameter names and values as GLib variants
- `notify_user` (boolean): Whether to notify the user of the action
**Returns:** The result returned by the command as a GLib variant (type depends on the command)
##### Example: Get voices for a specific language
```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/SpeechAndVerbosityManager \
--method org.stormux.Cthulhu.Module.ExecuteParameterizedCommand 'GetVoicesForLanguage' \
'{"language": <"en-us">, "variant": <"">}' false
gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu1/Service/SpeechManager \
--method org.stormux.Cthulhu1.SpeechManager.GetVoicesForLanguage "en-us" "" false
```
This will return a list of available voices for US English.
@@ -357,9 +277,9 @@ Some commands inherently don't make sense to announce. For example:
```bash
# This command should simply stop speech, not announce that it is stopping speech.
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/SpeechAndVerbosityManager \
--method org.stormux.Cthulhu.Module.ExecuteCommand 'InterruptSpeech' true
gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu1/Service/SpeechManager \
--method org.stormux.Cthulhu1.SpeechManager.InterruptSpeech true
```
In those cases Cthulhu will ignore the value of `notify_user`.
+30 -14
View File
@@ -2,7 +2,22 @@
## Note
Cthulhu is a fork of the Orca screen reader. Project home: https://git.stormux.org/storm/cthulhu. Cthulhu is currently a supplemental screen reader that fills a nitch for some advanced users. E.g. some older QT based programs may work with Cthulhu, and if you use certain window managers like i3, Mozilla applications like Firefox and Thunderbird may work better.
Cthulhu is a fork of the Orca screen reader. Project home: https://git.stormux.org/storm/cthulhu. Cthulhu is currently a supplemental screen reader that fills a niche for some advanced users. For example, some older Qt-based programs may work with Cthulhu, and if you use certain window managers like i3, Mozilla applications like Firefox and Thunderbird may work better.
## Current Maintenance
Cthulhu is currently maintained by Storm Dragon.
Current contributors called out in this fork's documentation:
- Hunter Joziak
- Harley Richardson (`destructatron`)
## Project History
Cthulhu is forked from Orca and builds on many years of upstream work by the Orca community, including former maintainers and contributors such as Joanmarie Diggs and others.
Those upstream maintainers and contributors are part of the project's history, but they are not current maintainers of this fork unless explicitly noted elsewhere.
## Introduction
@@ -51,22 +66,21 @@ toolkit, OpenOffice/LibreOffice, Gecko, WebKitGtk, and KDE Qt toolkit.
Cthulhu exposes a D-Bus service for external automation and integrations.
### Service Details
- **Service Name**: `org.stormux.Cthulhu.Service`
- **Main Object Path**: `/org/stormux/Cthulhu/Service`
- **Module Object Paths**: `/org/stormux/Cthulhu/Service/<ModuleName>`
- **Service Name**: `org.stormux.Cthulhu1.Service`
- **Main Object Path**: `/org/stormux/Cthulhu1/Service`
- **Module Object Paths**: `/org/stormux/Cthulhu1/Service/<ModuleName>`
- **Module Interfaces**: `org.stormux.Cthulhu1.<ModuleName>`
### Discovering Capabilities
```bash
# List registered modules
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service \
--method org.stormux.Cthulhu.Service.ListModules
# List registered module object paths and introspect their methods/properties
gdbus introspect --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu1/Service --recurse
# List commands on a module
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/ModuleName \
--method org.stormux.Cthulhu.Module.ListCommands
# Inspect one module
gdbus introspect --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu1/Service/ModuleName
```
### Plugin Modules
@@ -80,8 +94,8 @@ The `PluginSystemManager` module provides **session-only** plugin control (no pr
- `ListPlugins`
- `ListActivePlugins`
- `IsPluginActive` (parameterized)
- `SetPluginActive` (parameterized)
- `IsPluginActive`
- `SetPluginActive`
- `RescanPlugins`
### Plugin Preferences Pages
@@ -179,6 +193,7 @@ Ensure you have the development dependencies installed:
```bash
sudo pacman -S python python-gobject gtk3 at-spi2-core at-spi2-atk \
python-speechd gstreamer python-pluggy python-dasbus \
python-tomlkit \
meson ninja pkgconf intltool gettext
```
@@ -187,6 +202,7 @@ sudo pacman -S python python-gobject gtk3 at-spi2-core at-spi2-atk \
sudo apt install python3 python3-gi python3-gi-cairo gir1.2-gtk-3.0 \
at-spi2-core libatk-adaptor python3-speechd \
gstreamer1.0-plugins-base python3-pluggy python3-dasbus \
python3-tomlkit \
meson ninja-build pkg-config intltool gettext
```
+43 -38
View File
@@ -1,12 +1,17 @@
# Cthulhu Remote Controller - Available Commands
This documentation covers the Cthulhu fork maintained by Storm Dragon.
Cthulhu is forked from Orca; former Orca maintainers and contributors are part
of the project's upstream history, but they are not current maintainers of
this fork.
This document lists the currently available D-Bus commands in Cthulhu's Remote Controller interface.
> **Note**: This is a work-in-progress. As more modules are exposed via D-Bus, this document will be expanded. Eventually this will be auto-generated using `tools/generate_dbus_documentation.py`.
## Service-Level Commands
Available on the main service object `/org/stormux/Cthulhu/Service`:
Available on the main service object `/org/stormux/Cthulhu1/Service`:
### Service Commands
@@ -16,40 +21,37 @@ Available on the main service object `/org/stormux/Cthulhu/Service`:
| `PresentMessage` | Present a message via speech/braille | `message` (string) | Boolean (success) |
| `ShowPreferences` | Opens Cthulhu's preferences GUI | None | Boolean (success) |
| `Quit` | Exits Cthulhu | None | Boolean (accepted) |
| `ListCommands` | Lists available service commands | None | List of (name, description) tuples |
| `ListModules` | Lists registered D-Bus modules | None | List of module names |
### Example Usage
```bash
# Get Cthulhu version
busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service \
org.stormux.Cthulhu.Service GetVersion
busctl --user call org.stormux.Cthulhu1.Service /org/stormux/Cthulhu1/Service \
org.stormux.Cthulhu1.Service GetVersion
# Present a custom message
busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service \
org.stormux.Cthulhu.Service PresentMessage s "Hello from D-Bus"
# List available commands
busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service \
org.stormux.Cthulhu.Service ListCommands
# List registered modules
busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service \
org.stormux.Cthulhu.Service ListModules
busctl --user call org.stormux.Cthulhu1.Service /org/stormux/Cthulhu1/Service \
org.stormux.Cthulhu1.Service PresentMessage s "Hello from D-Bus"
# Open preferences
busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service \
org.stormux.Cthulhu.Service ShowPreferences
busctl --user call org.stormux.Cthulhu1.Service /org/stormux/Cthulhu1/Service \
org.stormux.Cthulhu1.Service ShowPreferences
# Quit Cthulhu
busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service \
org.stormux.Cthulhu.Service Quit
busctl --user call org.stormux.Cthulhu1.Service /org/stormux/Cthulhu1/Service \
org.stormux.Cthulhu1.Service Quit
```
## Module-Level Commands
Module-level commands are available and can be discovered via `ListModules`. Two key additions are:
Module-level commands and properties are discovered with standard DBus introspection:
```bash
gdbus introspect --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu1/Service --recurse
```
Two key additions are:
### PluginSystemManager
@@ -57,8 +59,8 @@ Session-only plugin control (does not persist preferences):
- `ListPlugins`
- `ListActivePlugins`
- `IsPluginActive` (parameterized)
- `SetPluginActive` (parameterized)
- `IsPluginActive`
- `SetPluginActive`
- `RescanPlugins`
### Plugin Modules
@@ -68,31 +70,30 @@ convention `Plugin_<ModuleName>` (e.g., `Plugin_GameMode`, `Plugin_WindowTitleRe
#### WindowTitleReader (Plugin_WindowTitleReader)
- `SetEnabled` (parameterized) -> enabled (bool)
- `Enabled` (runtime getter)
- `SetEnabled` -> enabled (bool), notify_user (bool)
- `Enabled` (property)
Example:
```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/Plugin_WindowTitleReader \
--method org.stormux.Cthulhu.Module.ExecuteParameterizedCommand \
'SetEnabled' '{"enabled": <true>}' false
gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu1/Service/Plugin_WindowTitleReader \
--method org.stormux.Cthulhu1.Plugin_WindowTitleReader.SetEnabled true false
```
Busctl example:
```bash
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/Plugin_WindowTitleReader \
org.stormux.Cthulhu.Module ExecuteParameterizedCommand \
s a{sv} b 'SetEnabled' 1 enabled b true false
busctl --user call org.stormux.Cthulhu1.Service \
/org/stormux/Cthulhu1/Service/Plugin_WindowTitleReader \
org.stormux.Cthulhu1.Plugin_WindowTitleReader SetEnabled bb true false
```
# Check current state
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/Plugin_WindowTitleReader \
org.stormux.Cthulhu.Module ExecuteRuntimeGetter s 'Enabled'
busctl --user call org.stormux.Cthulhu1.Service \
/org/stormux/Cthulhu1/Service/Plugin_WindowTitleReader \
org.freedesktop.DBus.Properties Get ss \
org.stormux.Cthulhu1.Plugin_WindowTitleReader Enabled
See [README-REMOTE-CONTROLLER.md](README-REMOTE-CONTROLLER.md) for comprehensive D-Bus API documentation and usage examples.
@@ -102,11 +103,15 @@ See [README-REMOTE-CONTROLLER.md](README-REMOTE-CONTROLLER.md) for comprehensive
# Check if Cthulhu's D-Bus service is running
busctl --user list | grep Cthulhu
# Introspect the service to see all available methods
busctl --user introspect org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service
# Introspect the service to see available module nodes
busctl --user introspect org.stormux.Cthulhu1.Service /org/stormux/Cthulhu1/Service
# Introspect a module to see its methods and properties
busctl --user introspect org.stormux.Cthulhu1.Service \
/org/stormux/Cthulhu1/Service/Plugin_WindowTitleReader
# Get detailed service information
busctl --user status org.stormux.Cthulhu.Service
busctl --user status org.stormux.Cthulhu1.Service
```
## Contributing
+26
View File
@@ -26,6 +26,31 @@ for cmd in meson ninja python3; do
fi
done
if ! python3 -c "import tomlkit" 2>/dev/null; then
echo "Error: Python module tomlkit is not installed"
echo "Please install: python-tomlkit"
exit 1
fi
getPythonSiteDir() {
python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")'
}
removeExistingLocalInstall() {
local pythonSite packageDir binPath desktopFile manPage
pythonSite="$HOME/.local/lib/python$(getPythonSiteDir)/site-packages"
packageDir="$pythonSite/cthulhu"
binPath="$HOME/.local/bin/cthulhu"
desktopFile="$HOME/.local/share/applications/cthulhu.desktop"
manPage="$HOME/.local/share/man/man1/cthulhu.1"
echo "Removing existing local installation targets..."
rm -f "$binPath"
rm -rf "$packageDir"
rm -f "$desktopFile"
rm -f "$manPage"
}
# Check for optional dependencies
missingOptional=()
if ! python3 -c "import gi" 2>/dev/null; then
@@ -57,6 +82,7 @@ meson compile -C _build
# Install
echo "Installing Cthulhu to ~/.local..."
removeExistingLocalInstall
meson install -C _build
# Update desktop database and icon cache
-8
View File
@@ -8,13 +8,11 @@ set -e # Exit on error
# Colors for output (only if stdout is a terminal)
if [[ -t 1 ]]; then
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
else
RED=''
GREEN=''
YELLOW=''
BLUE=''
@@ -56,12 +54,6 @@ if [[ $REPLY =~ ^[Yy]$ ]]; then
# Remove data files
# Remove desktop files
if [[ -f "$HOME/.local/share/applications/cthulhu-autostart.desktop" ]]; then
rm -f "$HOME/.local/share/applications/cthulhu-autostart.desktop"
echo " Removed: ~/.local/share/applications/cthulhu-autostart.desktop"
fi
# Remove icons
for size in 16x16 22x22 24x24 32x32 48x48 256x256 scalable symbolic; do
icon_path="$HOME/.local/share/icons/hicolor/$size/apps"
-11
View File
@@ -1,11 +0,0 @@
[Desktop Entry]
Type=Application
Name=Cthulhu Screen Reader
Exec=cthulhu
NoDisplay=true
# Desktop-neutral autostart - no GNOME-specific conditions
# Users can enable/disable via their desktop environment's accessibility settings
# or by adding/removing this file from ~/.config/autostart/
X-GNOME-AutoRestart=true
Categories=Accessibility;
Keywords=screen;reader;accessibility;speech;braille;
+2 -10
View File
@@ -15,16 +15,8 @@
<programming-language>Python</programming-language>
<maintainer>
<foaf:Person>
<foaf:name>Joanmarie Diggs</foaf:name>
<foaf:mbox rdf:resource="mailto:jdiggs@igalia.com" />
<gnome:userid>joanied</gnome:userid>
</foaf:Person>
</maintainer>
<maintainer>
<foaf:Person>
<foaf:name>Federico Mena Quintero</foaf:name>
<foaf:mbox rdf:resource="mailto:federico@gnome.org" />
<gnome:userid>federico</gnome:userid>
<foaf:name>Storm Dragon</foaf:name>
<foaf:mbox rdf:resource="mailto:storm_dragon@stormux.org" />
</foaf:Person>
</maintainer>
</Project>
@@ -0,0 +1,126 @@
# Maintainer: Storm Dragon <storm_dragon@stormux.org>
pkgname=cthulhu-git
_pkgname=cthulhu
pkgver=2026.05.06.r394.ga5f7c9a
pkgrel=1
pkgdesc="Desktop-agnostic screen reader with plugin system, forked from Orca"
url="https://git.stormux.org/storm/cthulhu"
arch=(any)
license=(LGPL)
provides=("${_pkgname}")
conflicts=("${_pkgname}")
depends=(
# Core AT-SPI accessibility
at-spi2-core
gobject-introspection-runtime
python-gobject
python-cairo
gtk3
python-pywayland
# Audio and speech
speech-dispatcher
gstreamer
gst-plugins-base # playbin, audiotestsrc, basic decoders
gst-plugins-good # pulsesink, more decoders
# Braille support
brltty
liblouis
# Plugin system and D-Bus remote control
python-pluggy
python-tomlkit
python-dasbus
# AI Assistant dependencies (for screenshots, HTTP requests, and actions)
python-requests
python-pyautogui
# Desktop integration
hicolor-icon-theme
libwnck3
pango
# System utilities
python
python-setproctitle
socat # for self-voicing feature
xorg-xkbcomp
xorg-xmodmap
)
optdepends=(
'espeak-ng: Alternative TTS engine'
'festival: Alternative TTS engine'
'flite: Lightweight TTS engine'
'espeak: Legacy TTS engine'
# AI Assistant providers (optional)
'claude-code: Claude AI provider support'
'openai-codex: ChatGPT AI provider support'
'gemini-cli: Gemini AI provider support'
'ollama: Local AI model support'
# OCR plugin dependencies (optional)
'python-pillow: Image processing for OCR and AI Assistant'
'python-pytesseract: Python wrapper for Tesseract OCR engine'
'python-pdf2image: PDF to image conversion for OCR'
'python-scipy: Scientific computing for OCR color analysis'
'python-webcolors: Color name lookup for OCR text decoration'
'tesseract: OCR engine for text recognition'
'tesseract-data-eng: English language data for Tesseract'
# nvda2cthulhu plugin (optional)
'python-msgpack: Msgpack decoding for nvda2cthulhu'
'python-tornado: WebSocket server for nvda2cthulhu'
# Window Title Reader plugin (optional)
'python-xlib: X11 access for Wine window title plugin'
)
makedepends=(
git
meson
ninja
python-build
python-installer
python-wheel
)
install=cthulhu.install
source=(
"${_pkgname}::git+https://git.stormux.org/storm/${_pkgname}.git#branch=master"
"cthulhu.install"
)
b2sums=(
'SKIP'
'SKIP'
)
pkgver() {
cd "${_pkgname}"
local projectVersion revisionCount commitHash
projectVersion=$(sed -n "s/^[[:space:]]*version: '\([^']*\)'.*/\1/p" meson.build)
projectVersion=${projectVersion%-master}
projectVersion=${projectVersion//-/.}
[[ -n "${projectVersion}" ]] || return 1
revisionCount=$(git rev-list --count HEAD)
commitHash=$(git rev-parse --short=7 HEAD)
printf "%s.r%s.g%s\n" "${projectVersion}" "${revisionCount}" "${commitHash}"
}
build() {
cd "${_pkgname}"
arch-meson _build
meson compile -C _build
}
package() {
cd "${_pkgname}"
meson install -C _build --destdir "$pkgdir"
# Remove icon cache - it will be generated by post-install hooks
rm -f "$pkgdir/usr/share/icons/hicolor/icon-theme.cache"
}
# vim:set sw=2 sts=-1 et:
@@ -1,7 +1,7 @@
# Maintainer: Storm Dragon <storm_dragon@stormux.org>
pkgname=cthulhu
pkgver=2026.01.19
pkgver=2026.05.14
pkgrel=1
pkgdesc="Desktop-agnostic screen reader with plugin system, forked from Orca"
url="https://git.stormux.org/storm/cthulhu"
@@ -14,7 +14,7 @@ depends=(
python-gobject
python-cairo
gtk3
python-pywayland
# Audio and speech
speech-dispatcher
gstreamer
@@ -84,7 +84,7 @@ makedepends=(
)
install=cthulhu.install
source=(
"git+https://git.stormux.org/storm/cthulhu.git"
"git+https://git.stormux.org/storm/cthulhu.git#tag=${pkgver}"
"cthulhu.install"
)
b2sums=(
@@ -92,11 +92,6 @@ b2sums=(
'SKIP'
)
pkgver() {
cd cthulhu
grep "^version = " src/cthulhu/cthulhuVersion.py | sed 's/version = "\(.*\)"/\1/'
}
build() {
cd cthulhu
arch-meson _build
@@ -0,0 +1,11 @@
post_install() {
gtk-update-icon-cache -q -t -f usr/share/icons/hicolor
}
post_upgrade() {
post_install
}
post_remove() {
gtk-update-icon-cache -q -t -f usr/share/icons/hicolor
}
+1 -1
View File
@@ -82,7 +82,7 @@ find $PKG -print0 | xargs -0 file | grep -e "executable" -e "shared object" | gr
| cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null || true
mkdir -p $PKG/usr/doc/$PRGNAM-$VERSION
cp -a AUTHORS COPYING ChangeLog NEWS README.md \
cp -a AUTHORS COPYING ChangeLog README.md \
$PKG/usr/doc/$PRGNAM-$VERSION
cat $CWD/$PRGNAM.SlackBuild > $PKG/usr/doc/$PRGNAM-$VERSION/$PRGNAM.SlackBuild
+6 -3
View File
@@ -1,11 +1,15 @@
Cthulhu is a screen reader for individuals who are blind or visually impaired,
forked from Orca. It provides access to applications and toolkits that support
the AT-SPI (e.g., the GNOME desktop).
the AT-SPI (e.g., GNOME and other Linux desktop environments).
This fork is currently maintained by Storm Dragon. It builds on upstream Orca
work, but former Orca maintainers and contributors are not current maintainers
of this fork.
This screen reader helps users navigate their desktop environment and applications
through speech synthesis and braille output.
After installation, you can start Cthulhu through the GNOME desktop environment
After installation, you can start Cthulhu through your desktop environment
or by running 'cthulhu' from the command line.
DEPENDENCIES:
@@ -13,7 +17,6 @@ This package requires the following packages, all available from SlackBuilds.org
- at-spi2-core
- brltty
- gobject-introspection
- gsettings-desktop-schemas
- gstreamer
- gst-plugins-base
- gst-plugins-good
+1 -1
View File
@@ -5,6 +5,6 @@ DOWNLOAD="https://git.stormux.org/storm/cthulhu.git"
MD5SUM="SKIP"
DOWNLOAD_x86_64=""
MD5SUM_x86_64=""
REQUIRES="at-spi2-core brltty gobject-introspection gsettings-desktop-schemas gstreamer gst-plugins-base gst-plugins-good gtk3 liblouis libwnck3 python3-atspi python3-cairo python3-gobject python3-setproctitle speech-dispatcher"
REQUIRES="at-spi2-core brltty gobject-introspection gstreamer gst-plugins-base gst-plugins-good gtk3 liblouis libwnck3 python3-atspi python3-cairo python3-gobject python3-setproctitle speech-dispatcher"
MAINTAINER="Storm Dragon"
EMAIL="storm_dragon@stormux.org"
+1 -1
View File
@@ -82,7 +82,7 @@ find $PKG -print0 | xargs -0 file | grep -e "executable" -e "shared object" | gr
| cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null || true
mkdir -p $PKG/usr/doc/$PRGNAM-$VERSION
cp -a AUTHORS COPYING ChangeLog NEWS README.md \
cp -a AUTHORS COPYING ChangeLog README.md \
$PKG/usr/doc/$PRGNAM-$VERSION
cat $CWD/$PRGNAM.SlackBuild > $PKG/usr/doc/$PRGNAM-$VERSION/$PRGNAM.SlackBuild
+51
View File
@@ -0,0 +1,51 @@
# AT-SPI Document Selection Branch Handoff
Branch: `atspi-document-selection`
## Implemented
- Added document-wide AT-SPI selection normalization in
`src/cthulhu/ax_document_selection.py`.
- Reworked text-selection handling in `src/cthulhu/script_utilities.py` to use
the shared adapter where possible and fall back cleanly where not.
- Updated primary callers in the default and web scripts so copy/cut,
selection announcements, and selected-text queries use the shared selection
path.
- Added keyboard-driven clipboard announcement fallback in
`src/cthulhu/scripts/default.py`, including Wayland-specific policy changes.
- Fixed `build-local.sh` so rebuilding refreshes modified installed modules
under `~/.local`.
## Verified
- `python3 -m pytest -q tests/test_document_selection_regressions.py`
- `python3 -m pytest -q tests/test_default_script_clipboard_regressions.py`
- `python3 -m pytest -q tests/test_web_input_regressions.py`
- `HOME=/tmp/cthulhu-test-home python3 -m pytest -q tests`
- `./build-local.sh`
Latest full-suite result before handoff: `95 passed, 1 warning`.
## Still Open
- Browser link-text selection is still not reliable in Chromium/Edge and in
web-backed content like Steam.
- The current branch includes extra diagnostics around clipboard and selection
paths because they were useful during manual debugging.
- The newest attempted web fix is in `src/cthulhu/scripts/web/script.py`, but
the manual repro still fails:
- selecting link text with `Shift+Left` / `Shift+Right`
- hearing no selection announcement
- then having copy behavior depend on fallback logic instead of real
selection state
## Useful Files For Follow-Up
- `src/cthulhu/ax_document_selection.py`
- `src/cthulhu/script_utilities.py`
- `src/cthulhu/scripts/default.py`
- `src/cthulhu/scripts/web/script.py`
- `src/cthulhu/scripts/web/script_utilities.py`
- `tests/test_document_selection_regressions.py`
- `tests/test_default_script_clipboard_regressions.py`
- `tests/test_web_input_regressions.py`
+17 -15
View File
@@ -14,7 +14,7 @@
.\" along with this; if not write to the Free Software Foundation, Inc.
.\" 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
'\"
.TH cthulhu 1 "20 September 2013" "GNOME"
.TH cthulhu 1 "10 April 2026" "Stormux"
.SH NAME
cthulhu \- a scriptable screen reader
.SH SYNOPSIS
@@ -26,13 +26,17 @@ is a screen reader for people with visual impairments,
it provides alternative access to the desktop by using speech synthesis and braille.
.P
.B cthulhu
is maintained in this fork by Storm Dragon. It is forked from Orca and builds
on upstream work by former Orca maintainers and contributors, who are part of
the project's history but are not current maintainers of this fork.
.P
.B cthulhu
works with applications and toolkits that support
the Assistive Technology Service Provider Interface (AT-SPI), which
is the primary assistive technology infrastructure for Linux and
Solaris. Applications and toolkits supporting the AT-SPI include the
GNOME Gtk+ toolkit, the Java platform's Swing toolkit, LibreOffice,
Gecko, and WebKitGtk. AT-SPI support for the KDE Qt toolkit is being
pursued.
Gecko, WebKitGtk, and the KDE Qt toolkit.
.SH OPTIONS
.TP
.B \-s, --setup
@@ -121,7 +125,7 @@ in desktop keyboard layout and
in laptop keyboard layout.
.B Cthulhu
uses default GNOME keyboard shortcuts to navigate the desktop and interact with various applications. The flat review commands provide an alternative method of interaction in certain inaccessible applications. It should not be confused with flat review functionality provided by other screen readers.
uses its configured keyboard shortcuts to navigate the desktop and interact with various applications. The flat review commands provide an alternative method of interaction in certain inaccessible applications. It should not be confused with flat review functionality provided by other screen readers.
.SH Desktop Mode
@@ -318,17 +322,15 @@ originated as a community effort led by the Sun Microsystems Inc.
Accessibility Program Office and with contributions from many community members.
.SH SEE ALSO
For more information please visit
.B cthulhu
wiki at
.UR http://live.gnome.org/Cthulhu
<http://live.gnome.org/Cthulhu>
.B Cthulhu
at
.UR https://git.stormux.org/storm/cthulhu
<https://git.stormux.org/storm/cthulhu>
.UE
.P
The
.B cthulhu
mailing list
.UR http://mail.gnome.org/mailman/listinfo/cthulhu-list
<http://mail.gnome.org/mailman/listinfo/cthulhu-list>
To post a message to all
.B cthulhu
list, send a email to https://groups.io/g/stormux
.B Stormux
community list is available at
.UR https://groups.io/g/stormux
<https://groups.io/g/stormux>
.UE
@@ -0,0 +1,171 @@
# Sounds Tab Design
Date: 2026-04-05
## Context
Cthulhu currently stores several non-speech sound settings in the general settings file, but the preferences dialog does not present them coherently:
- The General tab contains an inline Sound section for backend, theme, and role-sound presentation.
- The progress-bar beep checkbox lives in the General tab's progress-bar section.
- `soundVolume` exists in settings and the user's active profile, but there is no UI control for it.
- `enableSound`, `playSoundForRole`, `playSoundForState`, `playSoundForPositionInSet`, and `playSoundForValue` exist as persisted settings but are not currently exposed in the dialog.
- `progressBarBeepInterval` exists in runtime defaults but is not part of the normal persisted general-settings key list.
The result is that sound-related behavior is split across the dialog and some active settings cannot be inspected or changed from the UI.
## Goals
- Add a dedicated `Sounds` preferences tab.
- Move currently exposed sound-related controls out of `General` and into `Sounds`.
- Move the progress-bar beep option into `Sounds` while leaving the rest of the progress-bar section in `General`.
- Expose currently hidden sound-related settings in the UI.
- Add a UI control for `soundVolume`.
- Expose and persist `progressBarBeepInterval`.
- Preserve the existing settings model and save format.
- Avoid clobbering unrelated settings when saving preferences.
## Non-Goals
- No refactor of the broader preferences architecture.
- No changes to sound playback implementation outside what is needed to load and save settings correctly.
- No new settings schema beyond persisting the existing hidden `progressBarBeepInterval`.
- No dynamic enable/disable logic for sound controls in this pass.
## Design Summary
Add a new notebook page labeled `Sounds` and make it the single home for non-speech sound configuration. Remove the inline Sound frame from `General`. Keep the existing progress-bar speech/braille controls and shared progress-bar behavior controls in `General`, but move beep-specific controls into `Sounds`.
The new tab will use existing settings keys wherever possible and will save through the existing `prefsDict` and settings-manager flow.
## Sounds Tab Layout
The `Sounds` tab will contain three sections.
### Output
- `enableSound` checkbox
- `soundVolume` slider
- `soundSink` combo box
`soundVolume` should be represented by a native `GtkScale` and persisted back to the existing floating-point `soundVolume` setting. The control should initialize from `prefsDict.get("soundVolume", settings.soundVolume)`.
For this implementation, the slider should match the stored setting directly rather than introducing a new percentage representation. That keeps the implementation small and avoids conversion-only complexity in a settings path that already exists.
### Presentation
- `soundTheme` combo box
- `roleSoundPresentation` combo box
- `playSoundForRole` checkbox
- `playSoundForState` checkbox
- `playSoundForPositionInSet` checkbox
- `playSoundForValue` checkbox
These controls will expose already-existing settings and use the same `prefsDict` update pattern already used by the current dialog.
### Alerts
- `beepProgressBarUpdates` checkbox
- `progressBarBeepInterval` spin button
This section controls only beep-based progress-bar alerts. The label should make it clear that the interval is beep-specific, not the general progress-bar announcement interval.
## General Tab Changes
Keep these controls in `General`:
- `speakProgressBarUpdates`
- `brailleProgressBarUpdates`
- `progressBarUpdateInterval`
- `progressBarVerbosity`
- `ignoreStatusBarProgressBars`
Remove these from `General`:
- the inline Sound frame
- `beepProgressBarUpdates`
This preserves the current organization for general progress-bar announcement behavior while moving sound-only concerns into the new tab.
## Settings and Persistence
### Existing Keys Reused
The new UI will continue to use the existing settings keys:
- `enableSound`
- `soundVolume`
- `soundSink`
- `soundTheme`
- `roleSoundPresentation`
- `playSoundForRole`
- `playSoundForState`
- `playSoundForPositionInSet`
- `playSoundForValue`
- `beepProgressBarUpdates`
### Persisted Hidden Key
Add `progressBarBeepInterval` to the persisted general-settings key list so it round-trips through:
- defaults in `settings.py`
- settings-manager general settings
- TOML backend save/load
- `prefsDict` in the preferences dialog
This avoids the current mismatch where beep interval exists as a runtime default but is not part of the normal persisted general-settings path.
### Save Behavior
The implementation should continue to update individual keys in `prefsDict` and then rely on the existing general-settings save flow. No bulk replacement of the whole settings structure should be introduced.
This is specifically intended to avoid accidental overwrites of unrelated settings already present in `user-settings.toml`.
## Default Values
- Keep `progressBarUpdateInterval = 10` as the default for speech and braille progress-bar updates.
- Keep `progressBarBeepInterval = 0` as the default for beep-based progress-bar updates.
- Keep `soundVolume = 0.5` as the existing default unless the user explicitly changes it.
The new UI should reflect these values accurately on load.
## Accessibility
Use native GTK controls and follow the existing preferences-dialog patterns:
- every label must be associated with its control via `mnemonic_widget`
- checkboxes should use the existing `checkButtonToggled` convention when possible
- combo boxes should keep proper `label-for` / `labelled-by` relationships
- no custom-drawn controls
- no keyboard traps
The new tab should be fully reachable with standard tab navigation.
## Implementation Notes
Expected files to change:
- `src/cthulhu/cthulhu-setup.ui`
- `src/cthulhu/cthulhu_gui_prefs.py`
- `src/cthulhu/settings.py`
Implementation should:
- add the new notebook page and move or recreate the relevant widgets there
- initialize and save the new sound controls using existing dialog patterns
- add explicit handling for `soundVolume`
- add explicit handling for `progressBarBeepInterval`
- keep all unrelated preference behavior unchanged
## Verification
The implementation should be considered complete only after all of the following are checked:
1. The preferences dialog opens and the new `Sounds` tab is present.
2. Existing sound settings load into the correct controls.
3. Changing sound settings updates `prefsDict` without breaking unrelated settings.
4. Saving preferences preserves unrelated keys in `user-settings.toml`.
5. `progressBarBeepInterval` is written and reloaded correctly.
6. The General tab still handles speech/braille progress-bar settings correctly.
7. Touched Python files pass compile checks.
8. Manual verification confirms keyboard navigation and label association remain intact.
@@ -0,0 +1,117 @@
# Guarded Mouse Review Wayland Backport
## Summary
Backport Orca's modern mouse review split into Cthulhu in a conservative way. Keep the current X11 `Wnck` plus `mouse:abs` implementation as the existing path. Add a second path that uses `Atspi.Device` pointer monitoring only when the local AT-SPI version is new enough and the compositor/device actually grants `POINTER_MONITOR`. If either condition fails, Cthulhu stays on the current behavior.
This is explicitly an X-safe design. The X11 path remains first-class and unchanged in behavior. Wayland support is opportunistic and must fail closed.
## Current State
- Cthulhu mouse review currently depends on `Wnck` window lookup and `mouse:abs` events in [mouse_review.py](/home/storm/devel/cthulhu/src/cthulhu/mouse_review.py).
- Recent local changes already avoid importing `Wnck` on Wayland to suppress the terminal warning, but they do not add functional Wayland mouse review.
- Cthulhu already has an `Atspi.Device` for keyboard handling in [input_event_manager.py](/home/storm/devel/cthulhu/src/cthulhu/input_event_manager.py), which is the required foundation for an Orca-style pointer-monitor path.
## Goals
- Preserve existing X11 mouse review behavior.
- Add a guarded Wayland-capable path modeled on Orca's `Atspi.Device` pointer monitoring.
- Avoid startup warnings from `Wnck` on Wayland.
- Avoid enabling any new path unless support is positively confirmed at runtime.
## Non-Goals
- No full Orca mouse review rewrite beyond the pointer-monitor split.
- No removal or semantic change of the current X11 `Wnck` path.
- No OCR refactor beyond existing `Wnck` gating already added.
- No assumption that Wayland mouse review will work everywhere; unsupported compositors must remain a no-op.
## Design
### Capability Detection
Mouse review will select its backend at runtime:
1. If AT-SPI version is at least `2.60`, or the pre-release threshold Orca used (`2.59.90`), Cthulhu may try the new backend.
2. The new backend must call `set_capabilities(... | POINTER_MONITOR)` on the existing `Atspi.Device`.
3. The new backend is considered available only if `POINTER_MONITOR` is present in the returned capability set.
4. If any of those checks fail, Cthulhu uses the existing X11 path.
This means X11 systems on older stacks continue to use the current implementation. Wayland systems with insufficient AT-SPI support do not partially enable mouse review.
### InputEventManager Extension
Extend [input_event_manager.py](/home/storm/devel/cthulhu/src/cthulhu/input_event_manager.py) with narrow pointer-monitor wrappers:
- `enable_pointer_monitoring() -> bool`
- `start_pointer_watcher(callback) -> None`
- `stop_pointer_watcher() -> None`
These wrappers should mirror Orca's error handling:
- return `False` on missing device or `GLib.GError`
- never raise into callers
- leave existing keyboard handling unchanged
No unrelated device-manager refactor is included in this pass.
### Mouse Review Backend Split
Update [mouse_review.py](/home/storm/devel/cthulhu/src/cthulhu/mouse_review.py) to maintain two internal paths:
- Legacy path:
- existing `Wnck` window tracking
- existing `mouse:abs` listener
- existing absolute-coordinate flow
- New path:
- register a `pointer-moved` watcher on the `Atspi.Device`
- use the accessible object and local coordinates delivered by AT-SPI
- if the event source is an application, resolve the containing window from the app's accessible children
- otherwise use the event object directly
The common object-presentation logic should stay shared as much as possible. Only the event source and coordinate acquisition differ.
### Safety Rules
- Do not change the old X11 path except for harmless factoring needed to share code.
- Do not force the new path on X11 systems that are currently using the legacy path successfully.
- If pointer monitoring disconnects, errors, or cannot be enabled, mouse review must behave as unavailable rather than falling into a broken mixed state.
- Existing `Wnck` suppression on Wayland remains in place.
## Testing
### Automated
Add focused regressions for:
- version/capability gating chooses the new backend only when allowed
- `enable_pointer_monitoring()` returns `False` on capability failure
- pointer watcher start/stop are no-ops when there is no device
- mouse review activation chooses the legacy backend when AT-SPI support is not available
- mouse review activation chooses the pointer-monitor backend when support is available
Tests should mock AT-SPI rather than requiring a compositor.
### Manual
X11:
- mouse review still enables and behaves as before
- no regressions in pointer routing or reviewed object presentation
Wayland:
- no `Wnck` warning on startup
- mouse review only enables when AT-SPI pointer monitoring is actually available
- if supported, pointer hover review works without breaking keyboard handling
- if unsupported, failure is clean and explicit rather than noisy or partially broken
## Risks
- The local environment here is still on AT-SPI `2.58.4`, so the new backend cannot be exercised live in this workspace.
- The guarded design limits that risk by preserving the existing path and enabling the new path only under the same runtime conditions Orca used.
- The main regression risk is accidental interaction with Cthulhu's existing keyboard `Atspi.Device`; that is why the change is limited to small wrappers plus mouse-review-specific watcher usage.
## Recommendation
Implement the guarded dual-path backport and stop there. Do not port broader Orca mouse review refactors in the same pass.
@@ -0,0 +1,355 @@
# Wayland Compositor Event Interface For Churn Reduction
## Summary
Revise Cthulhu's event interface so Wayland session state can reduce AT-SPI churn before it reaches the current object-event pipeline. Keep `AT-SPI` authoritative for object semantics, text, selection, and actions. Add a small compositor-state normalization layer that is authoritative for desktop context such as active workspace, active top-level window, and focus routing during transitions.
This is not a Newton-style redesign. It is a conservative performance-oriented split intended to reduce queue growth, redundant script activation, and processing of stale events on Wayland systems while preserving existing accessibility semantics.
## Current State
- Cthulhu's main event flow is still centered on `Atspi.EventListener` and a single `event_manager` queue in `src/cthulhu/event_manager.py`.
- The current design already spends significant effort filtering spam, handling floods and deluges, recovering focus context, and pruning duplicate events.
- `src/cthulhu/input_event_manager.py` already uses `Atspi.Device` for keyboard handling and pointer monitoring wrappers, so Cthulhu already has one narrow example of a side-channel interface on Wayland.
- `src/cthulhu/focus_manager.py` and `src/cthulhu/cthulhu_state.py` still derive active-window and focus truth primarily from AT-SPI objects and events.
- `src/cthulhu/wnck_support.py` correctly gates `Wnck` to X11-only use, which is a useful precedent for runtime capability-based backend selection.
- Recent work in this repository has improved individual Wayland features, but there is not yet a compositor-agnostic interface for desktop state that can suppress irrelevant object churn before it enters the hot path.
## Goals
- Reduce AT-SPI event churn on Wayland systems before it reaches the main queue.
- Keep the design generic and compositor-agnostic at the Cthulhu interface level.
- Preserve current `AT-SPI` object semantics and script behavior as much as possible.
- Improve prioritization of focus and active-window related work during workspace and window transitions.
- Provide a single internal contract that can support Mutter, KWin, and wlroots-based compositors without teaching the rest of Cthulhu about compositor brands.
- Fail safe to current behavior when compositor state is missing, incomplete, or inconsistent.
## Non-Goals
- No Newton-style compositor-authoritative accessibility tree transport.
- No replacement of AT-SPI for object semantics, text, selection, caret movement, or actions.
- No dependency on `niri` IPC, GNOME Shell extensions, or KWin scripts in the core architecture for phase one.
- No requirement that every supported compositor expose the same amount of state.
- No broad rewrite of script listeners or script modules in this pass.
## Approaches Considered
### 1. Direct Wayland Integration Inside `event_manager`
Teach `event_manager` to consume shared Wayland state directly and add compositor-specific checks inside its current logic.
Pros:
- smallest code footprint up front
- no new internal abstraction layer
Cons:
- quickly leaks compositor-specific capability checks into the hottest code path
- makes Mutter, KWin, and wlroots differences part of `event_manager` logic
- harder to test in isolation
### 2. Thin Compositor-State Adapter Layer
Introduce a small internal normalization layer that consumes shared compositor-facing signals and emits a compact generic event vocabulary to `event_manager`.
Pros:
- keeps compositor-specific capability detection out of the hot path
- gives `event_manager` one stable interface to consume
- matches the long-term direction of consuming normalized state below the main screen reader logic
- easy to test with mocked backends
Cons:
- adds one more internal subsystem
- requires careful definition of authority boundaries to avoid duplication with AT-SPI
### 3. Full Compositor-Authoritative Routing
Make compositor state the primary truth for most event routing and use AT-SPI only for fine-grained object semantics.
Pros:
- highest potential performance ceiling
- most direct path toward a future compositor-led architecture
Cons:
- much higher correctness risk
- too large a shift for a churn-focused first pass
- would require significantly more backend-specific coverage and recovery logic
## Recommendation
Implement approach 2.
For phase one, Cthulhu should add a thin compositor-state adapter layer. It should be authoritative for desktop context and transition hints, but not for accessible object semantics. This gives Cthulhu a generic way to suppress or reprioritize AT-SPI noise without requiring a full architecture rewrite.
## Design
### Authority Split
The revised interface should split responsibility cleanly:
- compositor-state adapter is authoritative for:
- active desktop context
- active workspace set
- active top-level window identity when available
- desktop transition start and end
- focus-routing hints during compositor-driven changes
- AT-SPI remains authoritative for:
- focused accessible object
- accessible roles, names, and states
- text, caret, and selection semantics
- actionable objects and accessibility events consumed by scripts
Inference from upstream: current Orca remains AT-SPI-authoritative in its main pipeline, while newer GNOME accessibility work moves normalization below Orca rather than throughout it. This design follows that same direction without depending on Newton itself.
### New Internal Boundary
Add a new internal interface named `CompositorStateAdapter`.
Responsibilities:
- detect and activate the best available compositor-state backend at runtime
- normalize raw backend signals into a small generic event vocabulary
- maintain a current desktop-context snapshot
- emit state deltas and control hints to `event_manager`
- degrade to no-op behavior when capabilities are absent or unclear
This adapter should not expose compositor-specific event names or objects outside its own implementation.
### Normalized Event Vocabulary
The adapter should emit two families of signals.
State deltas:
- `workspace_state_changed`
- `desktop_focus_context_changed`
- `desktop_transition_started`
- `desktop_transition_finished`
Control hints:
- `pause_atspi_churn`
- `resume_atspi_churn`
- `prioritize_focus`
- `deprioritize_context`
- `flush_stale_atspi_events`
This vocabulary is intentionally small. It exists to shape queueing and prioritization, not to mirror every compositor event.
### Desktop Context Snapshot
The adapter should maintain a compact snapshot object with fields along these lines:
- `session_type`
- `backend_name`
- `active_workspace_ids`
- `active_window_token`
- `focus_route_token`
- `transition_active`
- `timestamp`
`active_window_token` and `focus_route_token` are intentionally generic. They should be comparable identifiers, not compositor-native objects leaking into the rest of Cthulhu.
### Backend Selection
Phase one should use capability-driven backend selection with generic shared interfaces first.
Preferred order:
1. `WaylandSharedProtocolsBackend`
2. `AtspiContextBackend`
3. `NullBackend`
#### `WaylandSharedProtocolsBackend`
This backend should consume shared Wayland-facing protocols where available and normalize them for Cthulhu. The first protocol target should be `ext_workspace_v1`.
Reasoning:
- `ext_workspace_v1` provides workspace groups, workspaces, active state, and atomic `done` notifications, which is exactly the sort of low-volume desktop-state signal Cthulhu needs to reason about transitions.
- As of April 9, 2026, Wayland Explorer lists `ext_workspace_v1` support for Mutter `49.2`, KWin `6.6`, and niri `25.11`, making it a good cross-family starting point.
This backend should only expose normalized state to the rest of Cthulhu. It should not expose protocol objects or protocol-specific state transitions outside the backend.
#### `AtspiContextBackend`
This backend should use current AT-SPI-based context recovery when shared Wayland state is missing or insufficient. It does not improve churn by itself, but it preserves current behavior and keeps the adapter contract usable everywhere.
#### `NullBackend`
This backend should emit no compositor hints and leave the rest of Cthulhu in its current behavior. It is the fail-safe path.
### Explicit Exclusions For Phase One
The following are not part of the core architecture in phase one:
- `niri` IPC as a first-class public interface
- compositor-specific `D-Bus` integrations
- GNOME Shell extension event streams
- KWin scripting APIs
These may become optional backend implementations in the future if a shared protocol proves insufficient, but they must remain behind the same generic adapter contract.
### Event Flow
The adapter should sit ahead of the current `event_manager`, not replace it.
Proposed flow:
1. backend receives shared compositor-facing state changes
2. adapter updates its desktop-context snapshot
3. adapter emits normalized state deltas and control hints
4. `event_manager` updates queueing, prioritization, and obsolescence decisions
5. AT-SPI object events continue to provide object-level truth within the selected desktop context
This allows Cthulhu to reduce irrelevant work before scripts interpret it, while keeping existing AT-SPI semantics intact.
### `event_manager` Integration
`event_manager` should gain a separate notion of desktop-context state in addition to its existing AT-SPI queue.
New responsibilities:
- track whether churn suppression is active
- track the currently prioritized desktop context
- reject queued AT-SPI work that became stale because the compositor already moved to a new context
- prefer script activation and focus recovery work that matches the current desktop context
The existing queue does not need to be replaced, but it does need one new concept: context obsolescence.
### Context Obsolescence
Add a new pruning rule: an event can be obsolete not only because a newer event of the same type exists, but because the desktop context that made the event relevant no longer exists.
Examples:
- a large `children-changed` burst from a window on a workspace that is no longer active
- queued `showing` or `name-change` events from a window that just lost compositor priority
- stale background application updates that were queued before a workspace switch finished
This is the primary performance win of the new interface. It lets Cthulhu discard irrelevant work based on context freshness, not only on event-type heuristics.
### Churn Suppression Mode
When the adapter emits `pause_atspi_churn`, `event_manager` should enter a guarded suppression mode.
This is not a full stop. It is a mode where:
- high-value focus and activation events are always preserved
- low-value background churn is collapsed, deprioritized, or dropped
- stale work from the prior desktop context is pruned aggressively
Events that should still be preserved during suppression:
- `window:*`
- `object:state-changed:focused` with `detail1=true`
- `object:state-changed:active` on frames and windows
- `object:text-selection-changed`
- `object:selection-changed` for the prioritized context
- user-trigger-correlated events associated with the last input event
Events that should usually be suppressed, collapsed, or deprioritized:
- `object:children-changed:*`
- `object:state-changed:showing`
- `object:state-changed:sensitive`
- background `object:property-change:accessible-name`
- bulk `object:text-changed:*`
- repeated `object:text-caret-moved` from non-priority contexts
### Transition Handling
When the adapter indicates a desktop transition:
- `desktop_transition_started`
- adapter marks `transition_active=True`
- adapter emits `pause_atspi_churn`
- `desktop_focus_context_changed`
- `event_manager` updates the preferred app/window context before AT-SPI focus settles
- focus-related events for the new context get priority
- `desktop_transition_finished`
- adapter emits `resume_atspi_churn`
- adapter emits `flush_stale_atspi_events`
- `event_manager` drops queued events that belong to the old context and resumes normal flow
This allows Cthulhu to be more decisive during workspace switches, app switches, and transient window transitions without needing compositor-authoritative object trees.
### Script Activation
`event_manager` should use the adapter's prioritized desktop context as an additional input when deciding whether to activate a script.
It should not activate a script purely because the compositor hinted at it, but it should:
- prioritize AT-SPI events from the compositor-indicated context
- deprioritize or skip activation from obviously stale background contexts
- improve focus recovery when AT-SPI active-window truth is noisy or delayed
This should reduce cases where script activation thrashes between background and foreground apps during Wayland transitions.
### Debugging And Observability
Add explicit logs around the new boundary:
- backend chosen and why
- normalized adapter signal emitted
- transition suppression entered and left
- events dropped due to context obsolescence
- events preserved during suppression and why
These logs should make it possible to explain every major pruning decision in the same way current flood and ignore logic can be debugged.
## Testing
### Automated
Add targeted tests for:
- backend capability detection and fallback order
- normalization of backend signals into adapter events
- transition start and finish behavior
- churn suppression activation and release
- context-obsolescence pruning of queued AT-SPI events
- preservation of focus and selection events during suppression
- script activation preferring compositor-indicated context when AT-SPI is noisy
- fail-safe fallback to current behavior when the adapter is uncertain
These tests should be written with mocks and fake backend signals. No real compositor should be required for unit coverage.
### Manual
Manual validation should focus on:
- workspace switches on Mutter, KWin, and niri
- fast application switching
- opening and dismissing transient dialogs and menus
- noisy web or Steam-like scenarios where background AT-SPI churn is high
- confirmation that speech follows real focused objects once AT-SPI settles
- confirmation that no important notifications or menu interactions are lost during suppression
## Risks
- Shared Wayland protocols may provide enough workspace truth but not enough top-level detail on every compositor.
- Compositor state may lead AT-SPI focus briefly, which could cause over-eager prioritization if the suppression policy is too aggressive.
- Some legitimate background AT-SPI events may look like churn if the rules are too broad.
- Adding a new boundary introduces state-synchronization bugs if adapter and event queue state diverge.
## Risk Management
- keep suppression guarded rather than absolute
- keep AT-SPI authoritative for object semantics
- make context obsolescence explicit and debuggable
- fail back to current behavior whenever backend certainty is too low
- avoid compositor-specific backends in phase one unless a shared protocol is clearly insufficient
## Recommendation
Implement a small generic `CompositorStateAdapter` and teach `event_manager` to consume its normalized desktop-state signals and churn-control hints.
Do not make `niri` IPC part of the core contract.
Do not attempt a compositor-authoritative accessibility architecture in this pass.
Do not broaden the first implementation beyond shared protocol detection, AT-SPI fallback, context-based pruning, and guarded churn suppression.
@@ -0,0 +1,195 @@
# Tolk NVDA Presence Compatibility Design
## Goal
Allow applications running under Wine or Proton to use the official upstream `Tolk.dll` unchanged while routing Tolk speech through the existing Linux NVDA-to-Cthulhu path.
The compatibility layer must satisfy only the checks that Tolk performs when selecting its NVDA driver. It must not require replacing `Tolk.dll`, patching Tolk, or using a Tolk-specific DLL override.
## Confirmed Constraints
- The shipped `Tolk.dll` must remain the official upstream binary.
- The existing `wine2speechd` package already provides replacement `nvdaControllerClient32.dll` and `nvdaControllerClient64.dll` implementations for Linux.
- The current blocker is Tolk detection, not the downstream speech transport.
- Scope is limited to making Tolk believe NVDA is present; broader NVDA emulation is out of scope.
## Current Tolk Behavior
From `tolk/src/ScreenReaderDriverNVDA.cpp`, Tolk considers NVDA active only when both of the following succeed:
1. `nvdaController_testIfRunning() == 0`
2. `FindWindow(L"wxWindowClassNR", L"NVDA")` returns a window handle
If either check fails, Tolk will not select the NVDA driver and speech output through Tolk will fail.
## Recommended Approach
Extend the existing Wine NVDA compatibility stack with a minimal NVDA presence helper. The solution has two parts:
1. The existing custom NVDA controller DLLs continue handling `nvdaController_*` API calls and forwarding them into the Linux bridge.
2. A lightweight Windows helper process running inside Wine creates the exact window Tolk expects for NVDA detection.
This keeps the official `Tolk.dll` untouched and confines the compatibility contract to Tolk's actual checks.
## Architecture
### 1. NVDA controller DLLs
The custom `nvdaControllerClient32.dll` and `nvdaControllerClient64.dll` remain the Wine-visible implementation that applications and Tolk load.
Required behavior:
- `nvdaController_speakText` forwards speech to the existing Linux bridge.
- `nvdaController_brailleMessage` continues current behavior.
- `nvdaController_cancelSpeech` continues current behavior.
- `nvdaController_testIfRunning` returns success only when the Linux bridge is reachable and the compatibility environment is operational.
`nvdaController_testIfRunning` must not return success solely because the DLL loaded. It is the main guard against false positive Tolk detection.
### 2. NVDA presence helper
A small Windows executable is added to the Wine-side compatibility package. Its only job is to create and maintain a top-level window with:
- class name: `wxWindowClassNR`
- window title: `NVDA`
Required behavior:
- starts quickly and remains idle
- single-instance per Wine prefix or session
- exits cleanly without user interaction
- does not present visible UI unless Wine forces a window surface
- can be launched independently or on demand by the controller DLL
### 3. Startup coordination
The presence helper must be running before Tolk calls `FindWindow`, or Tolk detection will fail.
Acceptable coordination strategies:
- preferred: launch the helper as part of the existing Wine accessibility startup path
- acceptable: lazily launch the helper the first time the custom NVDA DLL is loaded, then wait briefly for the window to appear
The preferred strategy is external startup rather than in-DLL process creation because it separates concerns and avoids loader-time side effects.
## Detection Contract
Tolk compatibility is considered successful only when all of the following are true:
- official `Tolk.dll` loads normally
- Tolk loads the custom NVDA controller DLL
- `nvdaController_testIfRunning()` returns `0`
- `FindWindow(L"wxWindowClassNR", L"NVDA")` succeeds
- `Tolk_DetectScreenReader()` returns `NVDA`
- `Tolk_Output()` delivers speech through the existing Linux bridge
If the Linux bridge is unavailable, the compatibility layer must fail closed:
- `nvdaController_testIfRunning()` returns failure
- Tolk does not report NVDA as active
The dummy NVDA window alone must never make Tolk think speech is available.
## Packaging
The compatibility feature belongs with the Wine NVDA compatibility stack, not in Tolk itself.
Expected package contents:
- `nvdaControllerClient32.dll`
- `nvdaControllerClient64.dll`
- `nvda-presence-helper.exe` or similarly named helper
- startup integration so the helper is available in Wine and Proton environments where Tolk-based games run
No `Tolk.dll` replacement or override is added.
## Error Handling
### Bridge unavailable
- `nvdaController_testIfRunning` returns failure
- speech-related entry points return the existing failure behavior
- Tolk should not detect NVDA
### Helper missing or failed to start
- `FindWindow` fails
- Tolk should not detect NVDA
- logging should identify missing helper startup distinctly from bridge connectivity failures
### Duplicate helper instances
- duplicates must resolve harmlessly, preferably by allowing one owner and exiting the rest
## Logging
Add targeted logging in the compatibility layer only. Logging should make these states distinguishable:
- controller DLL loaded
- bridge connectivity check succeeded or failed
- presence helper started
- presence window created
- Tolk compatibility ready
No Tolk-side logging changes are needed because Tolk is not being modified.
## Testing
### Functional test
Create or reuse a small Wine test application that:
1. calls `Tolk_Load()`
2. calls `Tolk_DetectScreenReader()`
3. calls `Tolk_Output(L\"test\", false)`
Expected result with bridge and helper active:
- `Tolk_DetectScreenReader()` returns `NVDA`
- speech reaches Cthulhu through the existing NVDA path
### Negative tests
1. Bridge down, helper up:
`Tolk_DetectScreenReader()` must not return `NVDA`
2. Bridge up, helper down:
`Tolk_DetectScreenReader()` must not return `NVDA`
3. Both down:
`Tolk_DetectScreenReader()` must not return `NVDA`
### Regression check
Verify that existing non-Tolk NVDA speech consumers continue using the current `wine2speechd` path without requiring Tolk-specific configuration.
## Out of Scope
- adding a plugin mechanism to Tolk
- maintaining a Tolk fork
- broader NVDA desktop emulation beyond what Tolk checks
- compatibility with applications that perform additional NVDA-specific probing outside the current `wine2speechd` contract
- anti-cheat or anti-tamper guarantees beyond avoiding Tolk replacement
## Risks
### Wine window behavior
The helper must create a window that `FindWindow` can discover reliably under Wine and Proton. If Wine normalizes or alters class registration behavior, the helper may need adjustment.
### Timing
If a game calls Tolk very early, helper startup races could cause intermittent detection failure. This is why pre-starting the helper is preferred.
### Split responsibility
The controller DLL and helper must agree on readiness. If they drift apart, Tolk may see the window but still fail to speak. The fail-closed `testIfRunning` check is the protection against this.
## Recommendation
Implement the feature in the existing Wine NVDA compatibility stack, not in Tolk and not in Cthulhu core.
The smallest correct implementation is:
1. fix or confirm `nvdaController_testIfRunning()` behavior in the custom DLL
2. add a minimal Wine helper that exposes the NVDA window Tolk checks for
3. wire startup so the helper is available before Tolk detection occurs
4. verify with a small Tolk test program under Wine
+2 -11
View File
@@ -1,5 +1,5 @@
project('cthulhu',
version: '2026.01.19-testing',
version: '2026.05.14-master',
meson_version: '>= 1.0.0',
)
@@ -57,6 +57,7 @@ optional_modules = {
'speechd': 'speech output',
'dasbus': 'D-Bus remote controller',
'psutil': 'system information commands',
'pywayland': 'Wayland shared workspace backend',
'gi.repository.Wnck': 'mouse review',
'pdf2image': 'PDF processing for OCR',
'scipy': 'Scientific computing for OCR analysis',
@@ -93,16 +94,6 @@ else
summary += {'sound support': 'no (missing gstreamer)'}
endif
# Integration with session startup
i18n.merge_file(
input: 'cthulhu-autostart.desktop.in',
output: '@BASENAME@',
type: 'desktop',
po_dir: meson.project_source_root() / 'po',
install: true,
install_dir: get_option('sysconfdir') / 'xdg' / 'autostart',
)
# Update icon cache manually (desktop-neutral) - optional, ignore failures
gtk_update_icon_cache = find_program('gtk4-update-icon-cache', required: false)
if gtk_update_icon_cache.found()
-1
View File
@@ -1,6 +1,5 @@
# List of source files containing translatable strings.
# Please keep this file sorted alphabetically.
cthulhu-autostart.desktop.in
src/cthulhu/braille_rolenames.py
src/cthulhu/brltablenames.py
src/cthulhu/chnames.py
-2
View File
@@ -13,11 +13,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-DamnedLies-Scope: partial\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr ""
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -18,11 +18,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 1.6.10\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Lector de pantalla Cthulhu"
#: cthulhu-autostart.desktop.in:11
#, fuzzy
msgid "screen;reader;accessibility;speech;braille;"
msgstr "lector de pantalla; fabla; braille;"
-2
View File
@@ -24,11 +24,9 @@ msgstr ""
"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
"X-Poedit-Language: Arabic\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "قارئ الشاشة Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "شاشة;قارئ;إمكانية الوصول;كلام;برايل;"
-2
View File
@@ -19,11 +19,9 @@ msgstr ""
"X-Poedit-Language: Asturian\n"
"X-Poedit-SourceCharset: utf-8\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Llector de pantalla d'Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -17,11 +17,9 @@ msgstr ""
"X-Generator: Poedit 3.3.2\n"
"X-Project-Style: gnome\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Чытач з экрана Cthulhu"
#: cthulhu-autostart.desktop.in:11
#, fuzzy
msgid "screen;reader;accessibility;speech;braille;"
msgstr "чытач з экрана;экран;голас;маўленне;Брайль;"
-2
View File
@@ -23,11 +23,9 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu — екранен четец"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "екран;четец;достъпност;говор;брайл;"
-2
View File
@@ -21,12 +21,10 @@ msgstr ""
"X-Generator: KBabel 1.9.1\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: cthulhu-autostart.desktop.in:3
#, fuzzy
msgid "Cthulhu Screen Reader"
msgstr "অর্কা স্ক্রীন রিডার / বিবর্ধন"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -18,12 +18,10 @@ msgstr ""
"X-Generator: KBabel 1.9.1\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: cthulhu-autostart.desktop.in:3
#, fuzzy
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu'র বৈশিষ্ট্য"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -15,11 +15,9 @@ msgstr ""
"X-Launchpad-Export-Date: 2015-02-05 06:46+0000\n"
"X-Generator: Poedit 1.7.4\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu čitač ekrana"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "čitač ekrana;govor;brailleovo pismo;"
-2
View File
@@ -27,11 +27,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 3.3.2\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Lector de pantalla Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "pantalla;lector;accessibilitat;veu;braille;"
-2
View File
@@ -27,11 +27,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Poedit 1.8.11\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Lector de pantalla Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "lector de pantalla;pronunciació;braille;"
-2
View File
@@ -19,12 +19,10 @@ msgstr ""
"X-Launchpad-Export-Date: 2020-05-04 21:32+0000\n"
"X-Generator: Poedit 2.3\n"
#: cthulhu-autostart.desktop.in:3
#, fuzzy
msgid "Cthulhu Screen Reader"
msgstr "خوێنەری پەردەی ئۆرکا"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -24,11 +24,9 @@ msgstr ""
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
"X-Generator: Poedit 3.3.2\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Čtečka obrazovky Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "obrazovka;čtečka;přístupnost;řeč;braille;"
-2
View File
@@ -17,12 +17,10 @@ msgstr ""
"Plural-Forms: nplurals=4; plural= (n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != "
"11) ? 2 : 3;\n"
#: cthulhu-autostart.desktop.in:3
#, fuzzy
msgid "Cthulhu Screen Reader"
msgstr "Hoffterau Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -32,11 +32,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 3.0.1\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Skærmlæseren Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "skærm;læser;tilgængelighed;tale;braille;"
-2
View File
@@ -37,11 +37,9 @@ msgstr ""
"X-Generator: Poedit 3.3.2\n"
"X-Project-Style: gnome\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu-Bildschirmleser"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "bildschirm;leser;barrierefreiheit;sprache;braille;"
-2
View File
@@ -20,12 +20,10 @@ msgstr ""
"X-Poedit-SourceCharset: utf-8\n"
"Plural-Forms: nplurals=2; plural=(n!=1)\n"
#: cthulhu-autostart.desktop.in:3
#, fuzzy
msgid "Cthulhu Screen Reader"
msgstr "ཨོར་ཀ་གསལ་གཞི་ལྷག་བྱེད་/ཆེ་ཤེལ་"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -28,11 +28,9 @@ msgstr ""
"X-Generator: Poedit 2.3\n"
"X-Project-Style: gnome\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Αναγνώστης οθόνης Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "οθόνη;αναγνώστης;προσβασιμότητα;ομιλία;μπράιγ;"
-2
View File
@@ -17,11 +17,9 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr ""
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -21,11 +21,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Gtranslator 45.3\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu Screen Reader"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "screen reader;speech;braille;"
-2
View File
@@ -21,11 +21,9 @@ msgstr ""
"X-Generator: Poedit 3.2.2\n"
"X-Project-Style: gnome\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Ekranlegilo Orko"
#: cthulhu-autostart.desktop.in:11
#, fuzzy
msgid "screen;reader;accessibility;speech;braille;"
msgstr "ekranlegilo;parolo;brajlo;"
-2
View File
@@ -28,11 +28,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"X-Generator: Gtranslator 45.alpha0\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Lector de pantalla Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "lector;pantalla;accesibilidad;voz;braille;"
-2
View File
@@ -20,12 +20,10 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: cthulhu-autostart.desktop.in:3
#, fuzzy
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu ekraanilugeja ja luup"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -20,11 +20,9 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu pantaila-irakurlea"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "pantaila;irakurlea;irisgarritasuna;mintzamena;braillea;"
-2
View File
@@ -18,11 +18,9 @@ msgstr ""
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 3.4\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "صفحه‌خوان اورکا"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -27,11 +27,9 @@ msgstr ""
"X-Generator: Poedit 3.3.2\n"
"X-Poedit-Bookmarks: 814,-1,-1,-1,-1,-1,-1,-1,-1,-1\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu-näytönlukija"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "näyttö;lukija;saavutettavuus;puhe;pistekirjoitus;"
-2
View File
@@ -31,11 +31,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"X-Generator: Poedit 3.3.2\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Lecteur d’écran Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "lecteur;écran;accessibilité;parole;braille;"
-2
View File
@@ -18,11 +18,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.0.3\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr ""
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -18,12 +18,10 @@ msgstr ""
"Plural-Forms: nplurals=5; plural=n==1 ? 0 : (n%10==1 || n%10==2) ? 1 : "
"(n%10>=3 && n%10<= 6) ? 2 : ((n%10>=7 && n%10<=9) || n==10) ? 3 : 4;\n"
#: cthulhu-autostart.desktop.in:3
#, fuzzy
msgid "Cthulhu Screen Reader"
msgstr "Léitheoir Scáileáin agus Formhéadaitheoir Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -34,11 +34,9 @@ msgstr ""
"X-DL-Domain: po\n"
"X-DL-State: Translating\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Lector da pantalla Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "pantalla;lector;accesibilidade;fala;braille;"
-2
View File
@@ -33,12 +33,10 @@ msgstr ""
"\n"
"\n"
#: cthulhu-autostart.desktop.in:3
#, fuzzy
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu સ્ક્રીન વાંચક અને વિસ્તૃતકારક"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -14,11 +14,9 @@ msgstr ""
"2 : 3);\n"
"X-Generator: Poedit 3.4.1\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "מקריא המסך Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "מסך;קורא;נגישות;דיבור;ברייל;"
-2
View File
@@ -22,11 +22,9 @@ msgstr ""
"\n"
"X-Generator: Lokalize 1.5\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu स्क्रीन वाचक"
#: cthulhu-autostart.desktop.in:11
#, fuzzy
msgid "screen;reader;accessibility;speech;braille;"
msgstr "स्क्रीन रीडर;भाषण;ब्रेल;"
-2
View File
@@ -20,11 +20,9 @@ msgstr ""
"X-Launchpad-Export-Date: 2016-09-15 12:40+0000\n"
"X-Generator: Poedit 1.6.10\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu čitač zaslona"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "čitač zaslona;govor;brajica;"
-2
View File
@@ -22,11 +22,9 @@ msgstr ""
"X-Generator: Poedit 2.3\n"
# Megjegyzés: Mivel mindenhol régóta Gáborral egyeztetve az Cthulhu nevet magyarosan Orkaként írjuk a fordításban, így a fordítást megváltoztattam Orka képernyőolvasóra az Cthulhu képernyőolvasó helyett.
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Orka képernyőolvasó"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "képernyő;olvasó;akadálymentesítés;beszéd;braille;"
-2
View File
@@ -20,11 +20,9 @@ msgstr ""
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 3.3.2\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Pembaca Layar Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "layar;pembaca;aksesibilitas;ucapan;braille;"
-2
View File
@@ -17,11 +17,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Lokalize 1.5\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu skjálestur"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -39,11 +39,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"X-Generator: Gtranslator 42.0\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Lettore schermo Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "lettore;schermo;accessibilità;voce;braille;"
-2
View File
@@ -25,11 +25,9 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu スクリーンリーダー"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "スクリーン;リーダー;アクセシビリティ;音声;点字;"
-2
View File
@@ -18,11 +18,9 @@ msgstr ""
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 3.3.2\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu - ეკრანის მკითხველი"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "ეკრანი;მკითხველი;ხელმისაწვდომობა;მეტყველება;ბრაილი;"
-2
View File
@@ -18,11 +18,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"X-Generator: Poedit 3.0\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr ""
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -18,11 +18,9 @@ msgstr ""
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 3.3.2\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu экраннан оқитын қолданбасы"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -18,12 +18,10 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: KBabel 1.11.4\n"
#: cthulhu-autostart.desktop.in:3
#, fuzzy
msgid "Cthulhu Screen Reader"
msgstr "ಆದ್ಯತೆಗಳು"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -15,11 +15,9 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu 화면 낭독기"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "화면;리더;접근성;음성;점자;"
-2
View File
@@ -25,11 +25,9 @@ msgstr ""
"(n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Poedit 3.3.2\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu ekrano skaityklė"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "ekrano skaityklė;kalba;brailio raštas;"
-2
View File
@@ -23,11 +23,9 @@ msgstr ""
"2);\n"
"X-Generator: Lokalize 21.12.3\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu ekrāna lasītājs"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "ekrāna lasītājs;runa;Brails;"
-2
View File
@@ -19,12 +19,10 @@ msgstr ""
"\n"
"\n"
#: cthulhu-autostart.desktop.in:3
#, fuzzy
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu स्क्रीन पाठक / आवर्द्धक"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -18,11 +18,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural= n==1 || n%10==1 ? 0 : 1\n"
"X-Generator: KBabel 1.11.4\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu читач на екранот"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -22,12 +22,10 @@ msgstr ""
"X-Generator: Poedit 2.0.1\n"
"X-Project-Style: gnome\n"
#: cthulhu-autostart.desktop.in:3
#, fuzzy
msgid "Cthulhu Screen Reader"
msgstr "സ്ക്രീന്‍ വായന അവസാനിപ്പിക്കാം."
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -18,12 +18,10 @@ msgstr ""
"X-Generator: KBabel 1.9.1\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: cthulhu-autostart.desktop.in:3
#, fuzzy
msgid "Cthulhu Screen Reader"
msgstr "वर्धक भिंग"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -18,11 +18,9 @@ msgstr ""
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 2.0.6\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Pembaca skrin Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "skrin;pembaca;kebolehcapaian;pertuturan;braille;"
-2
View File
@@ -19,11 +19,9 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu skjermleser"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "skjerm;leser;tilgjengelighet;tale;blindeskrift;"
-2
View File
@@ -13,11 +13,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 3.0.1\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "ओर्का दृष्टि वाचक"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "दृष्टि वाचक; वाचन;ब्रेल;"
-2
View File
@@ -31,11 +31,9 @@ msgstr ""
"X-Generator: Poedit 3.2.2\n"
# vergrootglas/loep
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu schermlezer"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "scherm;lezer;toegankelijkheid;spraak;braille;"
-2
View File
@@ -18,12 +18,10 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: cthulhu-autostart.desktop.in:3
#, fuzzy
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu skjermlesar og forstørringsglas"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -23,11 +23,9 @@ msgstr ""
"X-Launchpad-Export-Date: 2015-05-21 18:05+0000\n"
"X-Project-Style: gnome\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Lector d'ecran Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
"lector d'ecran;oral;braille;votz;sintèsi vocala;sintesi vocala;lector "
-2
View File
@@ -22,12 +22,10 @@ msgstr ""
"\n"
"\n"
#: cthulhu-autostart.desktop.in:3
#, fuzzy
msgid "Cthulhu Screen Reader"
msgstr "ଓର୍କା ସ୍କ୍ରିନ ପାଠକ /ଛୋଟକୁ ବଡ ଦେଖଉଥିବା ଉପକରଣ "
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -24,11 +24,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Poedit-Bookmarks: 589,-1,-1,-1,-1,-1,-1,-1,-1,-1\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "ਓਰਕਾ ਸਕਰੀਨ ਰੀਡਰ"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -24,11 +24,9 @@ msgstr ""
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
"|| n%100>=20) ? 1 : 2);\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Czytnik ekranowy Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "czytnik;ekran;dostępność;mowa;braille;"
-2
View File
@@ -28,11 +28,9 @@ msgstr ""
"X-Source-Language: C\n"
"X-Project-Style: gnome\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Leitor de ecrã Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "leitor;ecrã;acessibilidade;voz;braille;"
-2
View File
@@ -49,11 +49,9 @@ msgstr ""
"X-DL-Domain: po\n"
"X-DL-State: Translating\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Leitor de tela Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "leitor;tela;acessibilidade;voz;braille;"
-2
View File
@@ -24,11 +24,9 @@ msgstr ""
"X-Project-Style: gnome\n"
"X-Poedit-SourceCharset: UTF-8\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cititorul de ecran Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "ecran;cititor;accesibilitate;vorbire;braille;"
-2
View File
@@ -22,11 +22,9 @@ msgstr ""
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Poedit 3.3.2\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Экранный диктор Cthulhu"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "экран;чтец;доступность;речь;брайль;"
-2
View File
@@ -24,11 +24,9 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr ""
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -18,11 +18,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: KBabel 1.11.4\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr ""
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -19,11 +19,9 @@ msgstr ""
"Plural-Forms: nplurals=3; plural=(n==1) ? 1 : (n>=2 && n<=4) ? 2 : 0;\n"
"X-Generator: Gtranslator 2.91.7\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Ukončí čítačku obrazovky"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -22,11 +22,9 @@ msgstr ""
"X-Poedit-SourceCharset: utf-8\n"
"X-Generator: Poedit 3.0.1\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Zaslonski bralnik Orka"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "govor;zaslonski bralnik;Braillova pisava;brajica;povečevalnik"
-2
View File
@@ -17,12 +17,10 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: cthulhu-autostart.desktop.in:3
#, fuzzy
msgid "Cthulhu Screen Reader"
msgstr "Ekrani Zmadhues (Lupë)"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr ""
-2
View File
@@ -21,11 +21,9 @@ msgstr ""
"X-Project-Style: gnome\n"
"X-Generator: Poedit 3.1.1\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Читач екрана Орка"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "читач екрана;говор;брајева азбука;"
-2
View File
@@ -20,11 +20,9 @@ msgstr ""
"X-Project-Style: gnome\n"
"X-Generator: Poedit 2.0.3\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Čitač ekrana Orka"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "čitač ekrana;govor;brajeva azbuka;"
-2
View File
@@ -20,11 +20,9 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 3.3.2\n"
#: cthulhu-autostart.desktop.in:3
msgid "Cthulhu Screen Reader"
msgstr "Cthulhu skärmläsare"
#: cthulhu-autostart.desktop.in:11
msgid "screen;reader;accessibility;speech;braille;"
msgstr "skärm;läsare;tillgänglighet;tal;punktskrift;"

Some files were not shown because too many files have changed in this diff Show More