8.3 KiB
LibreOffice integration
Current Orca is the primary behavioral reference for LibreOffice. Python
Cthulhu remains available on the legacy branch for historical comparisons:
git show legacy:src/cthulhu/scripts/apps/soffice/script.py.
Do not switch the active Go checkout to inspect that reference.
Architecture
Application handling runs after screen-lock and foreground validation, before
generic focus and text filtering. internal/app/application_behavior.go
routes copied accessibility events by verified provider process identity.
The LibreOffice handler lives in internal/app/libreoffice.go.
It can normalize an event, request focus adoption, or suppress presentation.
The reader retains window ownership, input policy, pending-output cancellation,
review, and speech/Braille delivery. Ordinary applications keep their existing
event path. Steam's existing integration remains in place.
internal/atspi/libreoffice_native.go captures bounded Calc metadata on the
native owner thread. It does not enumerate a sheet. The controller and
presentation code never retain native objects or perform provider queries.
internal/presentation/libreoffice.go owns the corresponding speech
formatting; LibreOffice Braille formatting stays beside its controller.
The first implementation has no independent mutable application state: logical focus belongs to the existing event loop. Future selections and dynamic headers must be keyed by application bus, document, and sheet identity. Retire them on document/sheet destruction or application exit. Focus loss must cancel pending output while preserving document header choices; shutdown and screen lock must retire pending operations. Add command routing when the first real Office command requires it, using the existing input machinery. Application code must not bypass security/foreground gates or manage its own speech connection, key grabs, or background event loop.
Keep generic table operations and genuinely shared fixes in their existing subsystems. Keep verified LibreOffice exceptions in the dedicated files. Adding later Office features should extend these boundaries, without reorganizing unrelated reader code or building a speculative plugin framework.
First slice
- Calc active-cell events establish logical focus, including after editing and when the sheet changes.
- Cell contents and addresses are separate. Normal speech gives the value, then the address; an empty value gives “blank.” Only-displayed-text mode omits the address and the synthetic blank label.
- Recorded Braille preserves value spacing followed by the address. A cell component is not an editable text route.
- F2 resolves a temporary editor's focused paragraph when available. If the paragraph appears later, its first owned text/caret event establishes editor focus before generic filtering.
- Post-editing sheet focus is adopted silently. Spreadsheet capacity and cell/container state chatter are omitted as in Orca.
- Ancestor focus claims are suppressed when captured ancestry identifies the existing focused spreadsheet object.
- Non-editor caret events do not displace a focused cell. Selection events do not promote the first selected cell of a range into logical focus.
References inspected: Orca commit cd58a88ed (2026-10-14),
scripts/apps/soffice/script.py, script_utilities.py,
speech_generator.py, braille_generator.py, and shared
speech_generator.py / ax_utilities_table.py.
Next slices
- Formula presence and an on-demand formula command, using current Orca's
where_am_i_presenter.py:present_cell_formulaand cell attributes. - Selected/unselected ranges, rows, columns, and Select All. Represent ranges compactly; do not expand every selected cell as Orca's current comparison does. Test very large and disjoint selections.
- Dynamic row/column headers, sheet-scoped state, preferences and bindings. Inspect current Orca's shared table navigator rather than copying only the soffice directory. Spreadsheet full-row reading also needs a bounded, explicitly defined extent; the generic setting is not full Calc support.
- Writer paragraph navigation, selection, Say All, spell-check presentation, and Braille panning. Compare each actual workflow with current Orca.
Merged cells, overflow announcements, large-sheet responsiveness, other LibreOffice backends, and independent-workbook acceptance remain separate checks. This first slice does not establish complete Office support.
Verification
GOCACHE=/tmp/cthulhu-go-cache go test -race ./internal/atspi ./internal/app ./internal/presentation -count=1
/usr/bin/python3 tests/native_libreoffice.py
python3 tests/native_atspi.py --table-only
python3 tests/native_x11.py
The Calc harness launches installed LibreOffice with a disposable profile, document, virtual X11 display, and private session/accessibility buses. It exercises the production native adapter and event loop; recorded speech and Braille are asserted for cell movement and blanks, F2 typing, Escape cancellation, Enter commit, caret movement inside an existing numeric cell, and switching between two sheets. No active reader is replaced and no normal Office profile is changed.
These automated checks do not establish audible speech, physical input, or physical Braille. Before submission, review the diff and test a rebuilt binary:
- In a disposable Calc workbook, populate text, numbers, formulas and blanks. Arrow between them and listen for the value followed by its address.
- Press F2, edit, cancel with Escape, then edit and commit with Enter. Check character/word navigation in an existing cell editor and continued arrows.
- Switch sheets and switch between two workbooks. Return from menus, dialogs, the formula bar, and another application; check logical focus recovery.
- Check the cell value/address, spacing, editor cursor and return to cell display on physical Braille. Text routing applies inside the editor.
- Repeat ordinary GTK table movement/multiselection, browser typing and table reading, and Steam navigation. Check lock/unlock and stale/background events.
Human review and testing remain required by CONTRIBUTING.md. Passing this
fixture alone is not sufficient for submission or live accessibility acceptance.
Initial verification against LibreOffice 26.2.6.3 passed the Calc harness,
affected-package race tests, vet/build, GTK table/multiselection checks, and
Xorg input checks. Browser tab and table checks also passed. Browser editing
failed on an extra title announcement both here and on untouched commit
8e76d23. Browser modes initially failed to focus a heading after reload,
then passed on the baseline and on a rerun here; the cause of that first
failure was not established. Physical acceptance remains pending.
Calc startup focus diagnosis
A normal-profile startup under i3 can leave Calc accepting arrow keys while omitting active-cell accessibility events. In the observed case, cell events were followed by focus claims from the floating Form Design and Form Controls toolbars; subsequent arrows produced formula-bar text updates but no new cell events. A separate AT-SPI observer reproduced the missing events without Cthulhu. The affected workbook worked with a fresh profile, and a generic workbook reproduced the failure with a disposable copy of the normal profile. This establishes a profile-dependent LibreOffice focus/event problem; the precise profile setting responsible has not been isolated.
Press Ctrl+F6 to return focus to the document, then retry the arrows. This directly restored active-cell events in the isolated reproduction. LibreOffice documents this shortcut in its Calc accessibility keyboard guide. Automatic focus stealing would interfere with intentional toolbar use and is not part of the reader's handling.
The native Calc test focuses its window once and uses ordinary key sequences afterward. It also checks F6 followed by Ctrl+F6 and resumed cell speech/Braille. Its fresh-profile virtual display does not cover this normal-profile startup failure. The same production test also passed under private i3 with the copied normal profile after Ctrl+F6 recovery, asserting recorded cell speech and Braille along with editing and sheet switching. Verify startup and recovery under the actual window manager, plus audible speech and physical Braille, separately.