557 lines
32 KiB
Markdown
557 lines
32 KiB
Markdown
# Cthulhu
|
||
|
||
Cthulhu is a Linux screen reader written in Go.
|
||
|
||
- [Repository Guidelines](AGENTS.md): layout, commands, and working safeguards.
|
||
- [Contributing](CONTRIBUTING.md): development, accessibility verification, licensing, and the AI-assisted contribution policy.
|
||
- [LibreOffice support](LIBREOFFICE_SUPPORT.md): integration boundaries, initial Calc behavior, remaining work, and verification.
|
||
- [Progress reporting](PROGRESS_BARS.md): web progress bars, Steam shader processing, and verification.
|
||
- [Steam keyboard focus](STEAM_FOCUS.md): Xorg workspace focus recovery and verification.
|
||
- [XTerm handoff](docs/testing/xterm-handoff.md): terminal reader keys, lock state, speech interruption, and verification.
|
||
- [Graphical terminals](docs/testing/graphical-terminals.md): repaint coalescing, editing feedback, title animation, and verification.
|
||
- [Messaging support](docs/testing/messaging.md): Pidgin message review/copy shortcuts, application boundaries, and verification.
|
||
- [Flatpak foreground accessibility](docs/testing/flatpak-foreground.md): process identity and proxy matching, tests, and live acceptance.
|
||
- [Background event filtering](docs/testing/background-events.md): early foreground checks, notification exceptions, and performance verification.
|
||
- [Browser Find](docs/testing/browser-find.md): native Ctrl+F focus, typing, window ownership and verification.
|
||
- [MATE window switcher](docs/testing/window-switcher.md): Marco selection announcements, isolated checks, and live verification.
|
||
- [MATE desktop](docs/testing/mate-desktop.md): Orca comparison, panel menus and icon labels, regression checks, and live verification.
|
||
- [Qt control states](docs/testing/qt-control-states.md): menu checkability, native regressions, and the Qt 5 provider limitation.
|
||
- [Audacious GUI](docs/testing/audacious.md): isolated Qt/GTK menu and playlist checks, row-focus fixes, and live verification.
|
||
- [Tentacle updates](docs/testing/tentacle-updates.md): package recovery, version comparison, and update verification.
|
||
|
||
AI-assisted contributions are welcome. Contributors remain responsible for human review and testing before submission; see the [full policy](CONTRIBUTING.md#ai-assisted-contributions).
|
||
|
||
## Building
|
||
|
||
Run `./build-cthulhu.sh` to build `cthulhu` and `cthulhu-braille` in the
|
||
checkout root. The script works from any directory. It uses Go's automatic
|
||
toolchain selection with Go 1.21 or newer. If Go is missing or older, it
|
||
downloads the version required by `go.mod`, verifies the archive's SHA-256,
|
||
and caches it under `${XDG_CACHE_HOME:-$HOME/.cache}/cthulhu/toolchains`.
|
||
It does not replace system Go or require root.
|
||
|
||
Install a C compiler, `pkg-config`, and the development libraries for GTK3,
|
||
AT-SPI, GLib/GIO, GStreamer, X11, XTest, libXi, XFixes, XRes, xkbcommon,
|
||
liblouis, and BRLTTY/BrlAPI first. The script checks the pkg-config dependencies;
|
||
BrlAPI headers and its library are checked by the compiler during the build.
|
||
Bootstrapping Go additionally needs `curl`, `tar`, and `sha256sum`.
|
||
See [Contributing](CONTRIBUTING.md#development-and-architecture) and the
|
||
Arch package recipes under `distro-packages/Arch-Linux/` for dependencies.
|
||
|
||
For packaging, put both binaries in a separate directory and pass build flags
|
||
after `--`:
|
||
|
||
```sh
|
||
./build-cthulhu.sh --output-dir build -- -trimpath -mod=readonly
|
||
```
|
||
|
||
Relative output paths start at the caller's directory. `GOFLAGS`, `GOCACHE`,
|
||
`GOMODCACHE`, `GOTMPDIR`, and CGO compiler/linker settings are inherited.
|
||
CGO defaults to enabled and cannot be disabled. The Braille helper always
|
||
uses the `brlapi` build tag. Package recipes install both binaries beside
|
||
one another and stage documentation and other resources separately.
|
||
|
||
`GOTOOLCHAIN` defaults to `auto`; set it explicitly to `local` for builds
|
||
that must use an installed toolchain:
|
||
|
||
```sh
|
||
GOTOOLCHAIN=local GOPROXY=off ./build-cthulhu.sh --output-dir build -- -mod=readonly
|
||
install -Dm755 build/cthulhu "$pkgdir/usr/bin/cthulhu"
|
||
install -Dm755 build/cthulhu-braille "$pkgdir/usr/bin/cthulhu-braille"
|
||
```
|
||
|
||
For offline builds, provision a suitable Go version and module cache in
|
||
advance. Build inside the target distribution to link against its native
|
||
libraries; downloading Go does not supply those libraries. `--help` lists
|
||
the script's options without checking dependencies or accessing the network.
|
||
|
||
## Start with the laptop keyboard layout
|
||
|
||
Run `cthulhu -l` to use the laptop layout with Caps Lock as the Cthulhu
|
||
modifier for this session. No number pad is needed. The selection stays
|
||
active when switching applications and does not change the saved profile.
|
||
Starting without `-l` uses the saved keyboard settings again.
|
||
|
||
Press Caps Lock+Space to open Preferences. Applying preferences replaces the
|
||
temporary selection; save the laptop layout there to make it permanent.
|
||
Use `cthulhu -l -s` to open Preferences at startup.
|
||
|
||
## Login greeter settings
|
||
|
||
Copy your saved active profile into the LightDM account's default Cthulhu
|
||
settings location, without starting or replacing a reader:
|
||
|
||
```sh
|
||
cthulhu --greeter lightdm
|
||
```
|
||
|
||
Run this as your normal user. Cthulhu requests sudo authentication to run the
|
||
copy as the `lightdm` account. It discovers that account's home directory and
|
||
writes `.local/share/cthulhu/user-settings-go.toml` there, creating directories
|
||
as needed. The destination belongs to that account and has mode `0600`.
|
||
Cthulhu must be installed where the greeter account can execute it.
|
||
LightDM's default greeter account is `lightdm`; custom greeter accounts are
|
||
not currently supported.
|
||
|
||
Use `cthulhu --greeter lightdm --config FILE` to copy from an alternative
|
||
configuration. Your normal configuration remains unchanged. The copy contains
|
||
one complete active profile, including speech, Braille and keyboard preferences;
|
||
application profiles and Tentacles are not copied. Save preferences first:
|
||
unsaved changes are not included. Repeating the command updates the installed
|
||
settings. A missing source file selects built-in defaults, as at normal startup.
|
||
|
||
Configure the LightDM GTK greeter's reader command as
|
||
`cthulhu --no-tentacles` so it uses that account's default settings. Remove any
|
||
explicit `--config` path from an existing reader command to use the new location.
|
||
Changes take effect when the greeter reader next starts.
|
||
|
||
The greeter account needs its own accessibility bus and working audio setup.
|
||
Selected voices, Braille tables and custom sound assets must also be installed
|
||
and readable by that account. The command copies settings; it does not configure
|
||
LightDM or audio, restart a reader, or create a restricted login mode.
|
||
|
||
Native X11 grab-window regression:
|
||
`python3 tests/native_test_session.py env CTHULHU_NATIVE_GRAB_FOREGROUND=1 go test ./internal/platform/xorg -run '^TestNativeInputOnlyGrabForeground$' -count=1`.
|
||
|
||
## Speech preferences
|
||
|
||
Use Cthulhu+Left/Right to select a quick speech setting and Cthulhu+Up/Down
|
||
to adjust it. These changes follow you across windows, including application
|
||
profiles, for the current session. Cthulhu+Control+Shift+S saves the choices to
|
||
the global profile. Switching windows does not save or discard them. Applying
|
||
preferences replaces the temporary quick speech choices; restarting discards
|
||
unsaved changes. Saved application overrides still apply on the next startup.
|
||
|
||
Speech preferences let you adjust rate, pitch and volume directly, without
|
||
first disabling a default checkbox. Unconfigured values display Speech
|
||
Dispatcher's defaults when available, or rate 50, pitch 5 and volume 5.
|
||
Adjusting a slider creates an explicit setting; untouched values retain their
|
||
inheritance, including automatic Uppercase pitch. Apply saves the changes;
|
||
Cancel restores the last applied voice. See
|
||
[speech preferences verification](docs/testing/speech-preferences.md).
|
||
|
||
## Speech interruption
|
||
|
||
Incoming announcements queue in order. Focus, selection, state changes,
|
||
notifications, tooltips and terminal output let earlier speech finish.
|
||
Passive announcements also queue behind Say All. By default, a new key press
|
||
or reader command stops earlier speech and clears its pending announcements.
|
||
Delayed copies of the key that started a command preserve that command's response.
|
||
|
||
The Speech tab in Preferences offers **All keys interrupt**, **Control, Enter,
|
||
Space, and Escape**, and **Define interruption keys**. The second choice includes
|
||
both Control keys and the keypad Enter key. These choices apply immediately
|
||
after Apply and are saved with the profile. Key echo remains independent;
|
||
reader commands and explicit stop requests still interrupt speech in every mode.
|
||
|
||
For custom keys, select **Define interruption keys**, then activate **Record
|
||
interruption keys**. Press the individual keys to record, including Tab, Enter,
|
||
Space or Escape. Press and release a modifier separately to record it; left and
|
||
right modifiers can be selected independently. **Control+Enter** finishes and
|
||
**Control+Escape** cancels. Neither finishing nor cancelling adds its Control
|
||
key to the list. There is no timer. Recording replaces the previous list when
|
||
finished and requires at least one key. Duplicate keys are ignored. Focus
|
||
returns to the recording button, and the read-only **Defined interruption keys**
|
||
field displays the result. Tab and Shift+Tab work normally outside recording.
|
||
|
||
Screen lock, shutdown, speech configuration changes and explicit stop requests
|
||
retain their lifecycle behavior. Existing Tentacle requests marked
|
||
uninterruptible retain their bounded protection. The speech queue remains
|
||
bounded against excessive output.
|
||
See [speech queue verification](docs/testing/speech-queue.md) for automated
|
||
checks and the listening procedure.
|
||
|
||
## Automatic focus mode during structural navigation
|
||
|
||
In Preferences → General, enable **Automatic focus mode during structural
|
||
navigation** to enter focus mode when a structural command reaches a form
|
||
field or another widget that needs keyboard interaction. For example, press
|
||
E to move to a text entry, then type directly. Ordinary headings and links
|
||
keep browse mode. Like Orca, this option is off by default.
|
||
|
||
The option is available in global and application preferences. Apply saves it;
|
||
application choices override the global value. Sticky browse mode still keeps
|
||
browse mode, and sticky focus mode still keeps focus mode. Use Cthulhu+A to
|
||
switch back to browse mode when finished interacting.
|
||
|
||
## Emoji menu
|
||
|
||
On Xorg, press **Cthulhu+Control+E** in either keyboard layout to open the
|
||
Emoji Menu. Choose a category with arrows, then Tab to the searchable grid.
|
||
Type a name prefix, navigate with arrows, and press Enter to select.
|
||
|
||
**Copy selected emoji to clipboard** is unchecked by default. Unchecked types
|
||
the emoji at the current input focus, including terminals and browser fields,
|
||
without using the clipboard. Browse mode blocks typing. Checked copies the
|
||
emoji without typing it. The choice is remembered for the current reader
|
||
session. Escape cancels.
|
||
|
||
## Key echo
|
||
|
||
The Key Echo preferences page offers three radio choices: Disable key echo,
|
||
Enable key echo, and Key echo in edit fields. The last choice limits typing
|
||
and key-name echo to writable edit controls. It uses the existing key categories
|
||
and custom echo voice settings, and Apply takes effect immediately. Existing
|
||
configurations keep their previous enabled or disabled behavior. The new setting
|
||
is `edit-fields-only` in the profile's `key-echo` table.
|
||
|
||
Enable **Use custom echo voice** to choose the echo synthesizer, voice, rate,
|
||
pitch and volume. The synthesizer starts with the main speech synthesizer unless
|
||
a separate echo synthesizer was previously configured. No additional synthesizer
|
||
checkbox is needed. Under **Use the custom voice for:**, choose **Key names**
|
||
(such as Enter, Shift and arrows), **Typed characters**, **Words** or **Sentences**.
|
||
These choices select the voice; the corresponding echo settings still control
|
||
what is spoken. Turn off custom echo voice to use the main speech settings.
|
||
|
||
Debug speech delivery records include `custom_echo: true` for the custom echo
|
||
path and `false` for ordinary speech. See [key echo verification](docs/testing/key-echo.md)
|
||
for automated mode/voice tests, the native Enter regression and listening steps.
|
||
|
||
Key names finish before the resulting navigation or focus announcement starts.
|
||
For example, Right speaks "right" in the selected key echo voice, followed by
|
||
the character at the caret in the normal reading voice. A configured interruption
|
||
key still interrupts the previous key's speech and discards its pending feedback.
|
||
|
||
Changing the custom echo synthesizer, person, rate, pitch or volume speaks the
|
||
selected value using the echo voice and its draft settings, before Apply.
|
||
Tab and Shift+Tab announce the field label in the main voice, followed by its
|
||
current value in the echo voice. Other controls use the main voice.
|
||
Apply saves the changes; Cancel restores the previous settings.
|
||
|
||
For the combined reader, GTK and recorded-speech regression check, build a test
|
||
binary and run `CTHULHU_BINARY=/path/to/test-binary CTHULHU_PREFS_ECHO_RUNTIME_ONLY=1 /usr/bin/python3 tests/native_preferences.py`.
|
||
This uses private Xvfb, D-Bus and SSIP services. Live listening still needs a
|
||
separate check: Tab and Shift+Tab across all five fields, change synthesizer
|
||
and person with arrows and their popups, and confirm labels use the main voice
|
||
while values finish in the selected echo voice.
|
||
|
||
Native controls must expose editable accessibility metadata. This includes
|
||
standard entries, text editors and editable browser controls. Read-only fields,
|
||
password contents, buttons, menus and terminals do not enable this mode. Controls
|
||
that omit editable metadata stay quiet. Pasted text, terminal output containing
|
||
multiple characters, live regions, navigation and deletion feedback retain their
|
||
existing presentation rules; those announcements are distinct from key echo.
|
||
|
||
Wine Access supplies edit-control focus and typing feedback, including standard
|
||
Edit controls and its supported Scintilla editors. Key-name echo also requires
|
||
matching current X11 foreground metadata; without that evidence it stays quiet.
|
||
Wine insertion feedback uses the custom key voice when character echo is off,
|
||
and the custom character voice when character echo is on.
|
||
|
||
## Capital letters
|
||
|
||
Speech preferences group three independent checkboxes under Capital letters:
|
||
Raise pitch for capital letters (on by default), Beep for capital letters,
|
||
and Say “cap” before capital letters (both off by default). Any combination,
|
||
including all off, is supported. These settings apply to character navigation,
|
||
spelling, and typing feedback, including a custom key echo voice. Word and line
|
||
reading keep their normal presentation.
|
||
|
||
The beep matches NVDA's generated 2000 Hz, 50 ms capital-letter tone. It uses
|
||
the Sounds volume and audio backend, independently of role sounds and themes.
|
||
The pitch checkbox enables the existing Uppercase voice pitch. That voice
|
||
uses automatic adjustment until an explicit pitch is set with its slider. Apply
|
||
changes the running reader, and saved choices survive restart and can be set
|
||
per application. Older capitalization styles are imported into the corresponding
|
||
beep or “cap” checkbox.
|
||
|
||
## Reading settings descriptions
|
||
|
||
Under Speech, the Reading settings table has three columns: Enabled, Setting
|
||
and Description. Each description explains what the checkbox changes, with
|
||
examples where useful. Use Left and Right to read individual cells and Space
|
||
to toggle the selected setting from any column. With full-row reading enabled,
|
||
moving between rows reads the state, title and description together. Further
|
||
input interrupts speech as usual.
|
||
|
||
See [reading settings verification](docs/testing/reading-settings.md) for
|
||
automated checks and live listening steps.
|
||
|
||
## Flat review spelling and phonetic hints
|
||
|
||
Press Numpad 2 twice to hear the current character phonetically. Press Numpad 5
|
||
once to read the current word, twice to spell it, or three times to spell it
|
||
phonetically. Numpad 8 provides the same three choices for the current line.
|
||
Successive presses must be within 500 milliseconds. Single presses speak
|
||
immediately. Laptop equivalents are Cthulhu+Comma, Cthulhu+K and Cthulhu+I.
|
||
|
||
Under Speech → Reading settings, **Phonetic character hints** is off by default.
|
||
Enable it to hear a phonetic letter about 300 milliseconds after a character
|
||
spoken by plain Left or Right, for example “a … alpha”. Further input cancels
|
||
the pending hint. Selection, word navigation, Home/End and typing echo do not
|
||
add hints. Spaces, punctuation and letters without a phonetic name keep their
|
||
normal announcements. This applies to native text controls, browser character
|
||
navigation and supported Wine editor character navigation.
|
||
The delayed hint uses the normal voice without repeating capital beeps, pitch
|
||
changes or “cap”. Explicit phonetic review commands retain capital indicators.
|
||
|
||
See [phonetic review verification](docs/testing/phonetic-review.md) for checks
|
||
and live listening steps.
|
||
|
||
## Read the current line
|
||
|
||
Press **Cthulhu+Shift+Up** in either keyboard layout to read the line at the
|
||
application caret in native AT-SPI controls, or at the browse cursor on a webpage
|
||
in browse mode.
|
||
Press twice within 500 milliseconds to spell the line, or three times for
|
||
phonetics. The command leaves the caret and flat-review position in place.
|
||
Empty lines say “blank”; password contents are never read. Controls without
|
||
a text interface read their accessible name. Cthulhu+Up still increases the
|
||
selected speech setting.
|
||
|
||
This follows NVDA's desktop NVDA+Up current-line command, rather than replaying
|
||
the last spoken message. Numpad 8 (laptop: Cthulhu+I) continues to read the
|
||
independent flat-review line.
|
||
See [current-line verification](docs/testing/current-line.md) for checks.
|
||
|
||
## Read the current window title
|
||
|
||
Press **Cthulhu+Numpad Enter** in the desktop keyboard layout, or
|
||
**Cthulhu+Slash** in the laptop layout, to read the current window title.
|
||
In a browser this normally includes the active page title. The command also
|
||
flashes the title on Braille when flash messages are enabled. It works with
|
||
automatic title announcements disabled and can repeat the same title without
|
||
moving focus or the browser reading position.
|
||
|
||
These bindings match Orca's title command. Plain **Numpad Enter** on desktop
|
||
and **Cthulhu+Enter** on laptop retain their Where Am I behavior. Repeated title
|
||
commands read the title again; a double press does not read the status bar.
|
||
See [window title checks](tests/window_titles.md) for verification.
|
||
|
||
## Browser button updates
|
||
|
||
Web buttons announce their current label when focused. Automatic label changes
|
||
wait for 350 milliseconds without another change before speaking, so a rapidly
|
||
updating counter does not continually interrupt reading. Braille receives each
|
||
update immediately. Moving focus, navigating, changing tabs or windows, and
|
||
locking the session discard pending announcements. Live regions retain their
|
||
existing announcement behavior.
|
||
|
||
Debug logging with `--debug-file PATH` replaces any existing log at that path.
|
||
Add `--append` to preserve earlier sessions, for example
|
||
`cthulhu --debug-file /tmp/cthulhu.log --append`.
|
||
`--append` requires `--debug-file`. A log can still grow during a long session.
|
||
|
||
For browser bug reports, start Cthulhu with `--debug-file /tmp/cthulhu-browser.log`
|
||
and reproduce the affected navigation. The startup record includes the release
|
||
version, embedded Git revision and modified-build status, Go and AT-SPI versions,
|
||
and session information. Builds without Go VCS stamps report `unknown`; a
|
||
modified build identifies its base commit, not the exact uncommitted changes.
|
||
Display availability does not establish whether the browser uses native Wayland
|
||
or XWayland. Include the browser version and its actual display backend separately.
|
||
|
||
Navigation records include focus and document identities, the cursor before and
|
||
after focus synchronization and movement, recovery decisions, capture attempts,
|
||
errors and structural-navigation wrapping. For example, `preserved` retains the
|
||
saved position, `replaced-text-child` recovers a replacement under its surviving
|
||
parent, and `saved-object-missing` falls back to native focus. These records help
|
||
distinguish a cursor reset from an intentional wrap without extra native queries.
|
||
Review debug logs before sharing: they also contain spoken page text.
|
||
|
||
When the browser confirms that a navigation target no longer exists, Cthulhu
|
||
retires the cached object and refreshes its parent's child list. It retries
|
||
caret placement only if the same target survives the refresh. Otherwise the
|
||
move reports a location failure; repeat the navigation command to find a live
|
||
target from the retained browser focus. An ordinary native caret refusal still
|
||
allows a successful virtual reading move.
|
||
|
||
## Wine Access
|
||
|
||
Install the separate `wine-access` helper for Wine application accessibility.
|
||
See [Steam/Proton and controller-only verification](docs/testing/wine-proton.md)
|
||
for loader support, container staging, hook exclusions, and live regression checks.
|
||
Cthulhu checks `CTHULHU_WINE_ACCESS_HELPER`, then
|
||
`~/.local/libexec/wine-access/wine-access.exe`,
|
||
`/usr/local/libexec/wine-access/wine-access.exe`,
|
||
`/usr/libexec/wine-access/wine-access.exe`, and `wine-access.exe` on `PATH`.
|
||
The existing `cthulhu-wine-access.exe` lookup remains supported: the old user
|
||
location follows the new user location, the old `/usr` location follows the new
|
||
system locations, and the old name on `PATH` follows the new name.
|
||
Restart Cthulhu after changing the selected helper. Keep the launcher, its
|
||
`.exe.so` sidecar, and the native hooks together in the installed directory.
|
||
|
||
With an updated Wine Access helper, the log records the running helper's
|
||
embedded release version, Git revision and modified-build flag, followed by
|
||
initialization status for its workers, hooks, controller and control poll.
|
||
The process-start message alone does not establish successful initialization.
|
||
Debug logs also identify the selected executable, Wine loader and prefix;
|
||
check those paths for an older local copy when machines behave differently.
|
||
Helpers built before identity reporting do not provide these identity/status
|
||
records. The installed helper's `--version` option can be used for a manual
|
||
check; it does not require a running reader.
|
||
|
||
`cthulhu -v`, `cthulhu --version`, and **Cthulhu+Shift+V** append
|
||
`wine-access YYYY.MM.DD` when the selected installed helper contains release
|
||
metadata. This reads its `.exe.so` sidecar directly without starting Wine.
|
||
Rebuild Wine Access to supply the metadata; older helpers are omitted.
|
||
The reported release describes the installed files, which can differ from a
|
||
helper still running after an upgrade.
|
||
|
||
Helper-prefixed stderr diagnostics are captured with a 4096-byte line limit,
|
||
a 64-record queue and up to 32 distinct records per ten-second window. Repeated,
|
||
oversized and excess records are counted in a suppression notice. Unrelated
|
||
Wine/application stderr is ignored. Capture does not log accessible control
|
||
contents or change speech delivery; output already present in debug speech
|
||
logs can still contain private text. Review debug logs before sharing them.
|
||
|
||
The standalone helper currently installs under the compatible name
|
||
`~/.local/libexec/cthulhu/wine/cthulhu-wine-access.exe`. Its complete installation
|
||
contains the launcher, `cthulhu-wine-access.exe.so`, `wine-access-menu.dll`,
|
||
`wine-access-menu32.dll`, and `wine-access-menu-host32.exe`. The 32-bit host
|
||
supplies native menu and editor feedback for applications such as MUSHclient.
|
||
|
||
Older Python Cthulhu builds can overwrite the helper launcher and sidecar in
|
||
that same directory while leaving the standalone hook files behind. The old
|
||
helper can still run and connect to Cthulhu without providing the standalone
|
||
menu and editor hooks. If Wine reading disappears after installing an older
|
||
Cthulhu build, rebuild and reinstall the separate `wine-access` project, then
|
||
reload Cthulhu from the same desktop session. If a Wine application already
|
||
loaded a previous hook DLL, save its work and restart it to load the replacement.
|
||
See [local installation and reload](CONTRIBUTING.md#local-installation-and-reload)
|
||
for the Go reader commands.
|
||
|
||
Wine typing feedback in standard Edit controls follows the current key echo
|
||
settings, including the master switch, character echo, and alphabetic, numeric,
|
||
punctuation, space and diacritical categories. Tabs and line breaks follow
|
||
key echo's action-key setting. Applying preferences takes effect without
|
||
restarting the helper. Navigation, selection and deletion feedback remain
|
||
available when typing echo is disabled. Word and sentence typing echo are not
|
||
currently supplied by the Wine helper.
|
||
|
||
For a live check, type repeated letters, numbers, punctuation and spaces in
|
||
Wine Notepad, change the corresponding echo settings and apply them, then
|
||
continue typing. Disable key echo and verify that typing stays quiet while
|
||
arrows, selection and Backspace still report editing feedback. Re-enable it
|
||
and check capital/lowercase voices and password exclusion. Automated tests
|
||
cover queued speech and Braille; audible speech and a physical Braille display
|
||
still require live verification.
|
||
|
||
## Tentacle process supervision
|
||
|
||
Installed Tentacles run as the current user and require no administrator setup or
|
||
particular init system. Each session has a private Linux subreaper helper. The
|
||
helper watches a reader-owned lifetime pipe and terminates and reaps its child
|
||
and detached descendants when the session ends, including abrupt reader exit.
|
||
Exited orphaned descendants are also reaped while the Tentacle remains active.
|
||
Installation and enabling report success only after registration, keyboard
|
||
shortcut setup and activation succeed. A failed start leaves the installed
|
||
package disabled, with an error in Preferences; enabling it again retries.
|
||
Enabling an already enabled Tentacle restarts it if its session has failed.
|
||
Cancelling startup during shortcut setup restores the other Tentacles' shortcuts.
|
||
|
||
Only install Tentacles from publishers you trust. They inherit your account's
|
||
file and network access. Protocol sizes, request deadlines and host admission
|
||
limits always apply. CPU, memory and task limits require an explicitly configured,
|
||
writable cgroup v2 parent with the `cpu`, `memory` and `pids` controllers enabled.
|
||
Set `CTHULHU_TENTACLE_CGROUP_PARENT` or pass
|
||
`--tentacle-cgroup-parent /absolute/delegated/parent` to opt in. Provisioning that
|
||
parent is an administrator or session-launcher responsibility, independent of
|
||
any init system. An invalid explicit parent fails startup rather than silently
|
||
ignoring the requested limits. Without that configuration, supervision works
|
||
without kernel resource quotas; it does not provide a security sandbox.
|
||
|
||
## Browser navigation
|
||
|
||
Browser element lists use **Alt+Shift** plus the structural navigation
|
||
key: **K** for links, **A** for clickables, **H** for headings, and **1–6** for
|
||
headings at a specific level. Use arrows or type a name to select an item,
|
||
Enter to move to it, and Escape to cancel. See [browser element lists](docs/testing/browser-lists.md)
|
||
for every list shortcut and verification steps.
|
||
|
||
Heading and browse-caret commands retain the virtual reading position while
|
||
the browser reports delayed native caret events. Each reader command takes
|
||
ownership before its result arrives. Native keyboard input, text selection,
|
||
pointer presses, document loads and leaving the document release that ownership.
|
||
An unsuccessful native caret placement does not undo a successful virtual move.
|
||
|
||
When a page replaces a plain text child in a paragraph, heading, section or
|
||
ordinary link, navigation can retain its offset through the same surviving
|
||
parent and document generation. With multiple children, the replacement must
|
||
remain between the same generation-checked adjacent siblings (or the same
|
||
start/end boundary).
|
||
This prevents repeatedly restarting a paragraph when an inline text object is
|
||
recreated. No text-label matching is used to guess a replacement.
|
||
This includes CSS-generated link prefixes such as `::before`, which browsers
|
||
can recreate when placing the native caret. Explicitly named links retain their
|
||
separate label-navigation behavior. Recovery never transfers an activation to
|
||
a replacement link.
|
||
Read All uses navigation recovery too, and stops if the document generation
|
||
changes. Text that disappears during a native read requires a refresh rather
|
||
than silently losing that part of the line.
|
||
When a larger subtree disappears, navigation can restart within its nearest
|
||
surviving noninteractive container. Ambiguous children, editable controls and
|
||
replaced parents do not inherit the old offset. Removing a native focus anchor
|
||
does not reset a still-valid virtual reading position elsewhere in that document.
|
||
Verify repeated native replacements, forward/reverse lines and subsequent
|
||
Read All with
|
||
`CTHULHU_NATIVE_BROWSER_TESTS=replacement,generatedlinks python3 tests/native_browser.py`.
|
||
|
||
Explicitly named links retain their complete accessible label when reading by
|
||
line. Left/Right, Ctrl+Left/Right, and Home/End review that label by character,
|
||
word, or boundary, including links with no native text or only a numeric badge.
|
||
The label's review position remains separate from the browser's text caret.
|
||
|
||
Browse arrows, word navigation and Read All skip non-focusable, non-editable
|
||
tooltips and their contents. This avoids repeatedly entering a tooltip that
|
||
disappears when native caret placement moves focus away from its owner.
|
||
Focusable or editable tooltip contents remain navigable. Verify the native
|
||
focus-triggered case with
|
||
`CTHULHU_NATIVE_BROWSER_TESTS=tooltips python3 tests/native_browser.py`.
|
||
|
||
Enter activates the current link or clickable, including explicitly named custom
|
||
controls and clickable ancestors of ordinary text. Activation itself is silent
|
||
whether it succeeds or fails; the page's own focus changes and live regions still
|
||
speak. Ordinary text does not cause an unnecessary document recapture. A removed
|
||
target or replaced document cannot silently substitute a different action.
|
||
|
||
Successful virtual navigation presents the requested content even if the browser
|
||
refuses native caret placement; synchronization failures remain in diagnostic logs.
|
||
Stale native placement gets one refresh and retry at the same target and offset.
|
||
Braille routing also recognizes the temporary caret produced by clearing a
|
||
selection, so it cannot reset the routed reading position.
|
||
|
||
Browser Braille expands embedded links and preserves that text when native
|
||
caret events repair line offsets. If a descendant read fails or reaches its
|
||
expansion limit, a clean accessible name can recover a range covering the whole
|
||
object. Wrapped line fragments retain their own content. Names are also stripped
|
||
of embedded-object placeholders before calculating Braille label offsets.
|
||
After rebuilding, check H/Shift+H in Firefox and Chromium on linked headings,
|
||
headings containing linked images, and wrapped headings. Compare speech with
|
||
Braille, then check arrow reading, selection, panning and ordinary text routing.
|
||
Expanded text has no native cell routes because its offsets differ from the
|
||
browser's raw text.
|
||
|
||
Reading a final ellipsis avoids the provider's native line-boundary request:
|
||
Chromium can calculate a boundary past truncated text and abort the browser.
|
||
At that character, Cthulhu reads a bounded logical line using explicit line
|
||
breaks; visual wrapping may be combined. Ordinary line, character and word
|
||
navigation retain their existing boundaries. The regression checks are
|
||
`go test ./internal/atspi -run TestTextBoundaryAvoidsProviderEllipsisAbort`
|
||
and `CTHULHU_NATIVE_BROWSER_TESTS=lines python3 tests/native_browser.py`.
|
||
|
||
Browse-mode arrows and Read All include text inside embedded editors. Reading
|
||
continues through the editor's paragraphs before reaching the following page
|
||
content.
|
||
|
||
Native menu rows can contain several controls. Up and Down announce those
|
||
controls individually, including Brave's Sidebar choices and Zoom controls.
|
||
Check this workflow with `CTHULHU_NATIVE_BROWSER_TESTS=menu python3 tests/native_browser.py`.
|
||
|
||
See [browser release review](docs/testing/browser-release-review.md) for findings,
|
||
automated checks and remaining live acceptance.
|
||
|
||
The generic changing-document regression starts a private reader, browser
|
||
profile, X display, accessibility bus and speech protocol recorder:
|
||
|
||
```sh
|
||
go build -o /tmp/cthulhu-browser-review ./cmd/cthulhu
|
||
CTHULHU_BINARY=/tmp/cthulhu-browser-review python3 tests/native_browser_navigation.py
|
||
CTHULHU_NATIVE_BROWSER_TESTS=pointer,positions,dynamic,linkedheadings,document,editing,selection,tabs,modes python3 tests/native_browser.py
|
||
```
|
||
|
||
These checks leave the desktop reader unchanged. They verify synthetic X11
|
||
input and recorded speech requests; real-page listening, physical keyboard
|
||
and Braille checks remain necessary. On an updating page, traverse headings in
|
||
both directions, pause and continue, read changing lines with arrows and word
|
||
commands, then verify Tab, selection, editable fields and browser chrome.
|