Files

9.8 KiB
Raw Permalink Blame History

Messaging support

Pidgin now uses the shared Go messaging history. This first port follows the legacy defaults: announce inserted messages from all conversations, keep one combined history for each running Pidgin accessibility provider, omit room-name prefixes, and suppress typing-status announcements. History contains messages received while this reader is running; it does not import an existing transcript.

The legacy controls for separate conversation histories, room-name prefixes, typing announcements, and message verbosity are not yet ported.

When plain Enter clears the focused message entry, the deleted draft is no longer spoken before the transcript announces the sent message. This shared presentation rule requires a freshly observed plain Enter and a known empty native text line at offset zero. It keeps deletion feedback when text was selected, including when selection removal arrives before the deletion. Backspace/Delete, cut/paste, undo/redo, modified Enter, unknown input/caret data, autocomplete, terminals and document editors retain their existing behavior. Caret and Braille updates still run before speech is suppressed. This does not change word echo or Thunderbird foreground handling.

Shortcuts

Both desktop and laptop layouts use:

  • Cthulhu+F1–F9: review the newest through ninth-newest message.
  • Cthulhu+Shift+F1–F9: copy that message and confirm after the write succeeds.
  • Cthulhu+H: enter or exit learn mode. Cthulhu+F1 no longer opens it.

Empty history slots are silent. Chat commands act only when Pidgin owns the reader's current focus. They are configurable in the existing key-binding page. An explicit shortcut assignment takes precedence over an uncustomized chat default, preserving existing configurations; the shortcut list reflects this. Within temporary OCR review, Cthulhu+F5 retains its refresh behavior. In learn mode, plain F1 still opens documentation, and F2/F3 retain their existing functions.

Steam retains its existing notification support: Cthulhu+N for the latest notification and Cthulhu+Ctrl+N for the notification list. Neither the legacy Steam script nor this port provides F-key conversation review for Steam.

Implementation boundary

  • internal/atspi/pidgin_native.go recognizes the legacy transcript shape: a noneditable, multiline text object directly inside a scroll pane, belonging to a provider whose process name is pidgin. Its bounded ancestor scan copies conversation/window identities and the room name. Typing status is identified from the inserted range's smaller/lighter text attributes.
  • internal/messaging stores copied messages without native handles or output dependencies. It bounds each provider's history to nine messages and the number of retained providers to 32. Provider identities prevent cross-instance replay.
  • internal/app/messaging.go coordinates passive speech, one Braille flash, review, and asynchronous clipboard copying on the reader event loop. A bounded worker uses the shared clipboard writer; writes have a three-second deadline. The event loop cancels pending copies when foreground ownership is cleared, when another copy replaces them, on screen lock, and during shutdown.
  • internal/input/messaging.go defines numbered semantic commands independently of their physical shortcuts. Existing binding configuration and learn mode describe the same commands.

Background chat never becomes focus or review ownership. Lock gates reject messages; lock transitions clear history. Destruction of a known transcript or window retires its messages. Ordinary edits, buddy-list activity, and unrelated providers keep their existing event-filtering behavior. History is never saved.

Future application support should add its own verified native detector and explicit dispatch to this shared message contract. Keep transcript identification out of generic focus, speech, and history code. Steam conversation support needs inspection of an actual chat accessibility tree before choosing its detector; notification text alone does not establish conversation identity.

Automated checks

From the repository root:

GOCACHE=/tmp/cthulhu-cache go test ./...
GOCACHE=/tmp/cthulhu-cache go test -race ./internal/messaging ./internal/input ./internal/atspi ./internal/app
python3 tests/native_test_session.py env GOCACHE=/tmp/cthulhu-cache CTHULHU_NATIVE_MESSAGING=1 go test ./internal/atspi -run '^TestNativePidginTranscriptCapture$' -count=1 -v
python3 tests/native_test_session.py env GOCACHE=/tmp/cthulhu-cache CTHULHU_NATIVE_MESSAGING=1 go test ./internal/app -run '^TestNativeMessagingCopyPreservesClipboardText$' -count=1 -v
python3 tests/native_test_session.py env GOCACHE=/tmp/cthulhu-cache CTHULHU_NATIVE_X11=1 go test ./internal/platform/xorg -run '^TestNativeLearnModeCapturesKeysAndRestoresCommands$' -count=1 -v
go test ./internal/input ./internal/app -run '^(TestPlainEnterActivityLifetime|TestSubmittedMessageIsAnnouncedOnce|TestSubmissionClearPreservesEditingFeedback)$' -count=1
python3 tests/native_test_session.py env CTHULHU_NATIVE_SUBMISSION_ECHO=1 go test ./internal/app -run '^TestNativeSubmissionClearAndSelectedReplacement$' -count=1 -v

Native checks use private X11 and D-Bus sessions. The transcript fixture sets its own process name to exercise the Pidgin detector; it is not the actual Pidgin client. These checks verify copied metadata, recorded presentation, synthetic keys, and clipboard contents. They do not establish audible speech, physical keyboard behavior, or a connected Braille display.

The submission replay test reproduces both announcements with the original presenter and only the chat announcement with the fix. The GTK submission fixture uses the real X11 input listener and native deletion snapshots, and checks Enter replacing a selection separately. It does not send real messages.

Human review and live acceptance

Review the diff before submission under the contribution policy. Build a reader for testing, then load it using the normal authorized reader-replacement procedure. The implementation work does not replace the running reader.

  1. Open two Pidgin conversations. Receive distinct messages in each and verify they speak once, including when a different application has focus. Confirm keyboard focus remains in that other application.
  2. Return to Pidgin. Check F1/F2 review the most recent messages across both conversations. Receive more than nine messages and check the F9 boundary. Send two identical messages and verify both occupy separate history slots.
  3. Use Shift+F1/F2 to copy, then paste into a native editor. Check Unicode and multiline content. Confirm the copy response follows a successful write.
  4. Type in Pidgin's message entry and account/preferences fields. Check normal echo and editing feedback. Buddy-list updates and remote typing status must not enter chat history. Send an unselected draft with plain Enter and confirm it is spoken once through the transcript. In a native text editor, check Backspace/Delete, Ctrl+Backspace, cut/paste, undo/redo, typing over a selection, and Enter replacing a selection. Verify the empty input is reflected on Braille after sending. Modified Enter and sending selected drafts retain their earlier behavior and need separate evidence before changing them.
  5. Switch to another application and check chat commands do not replay Pidgin history. Close a conversation window and check its messages are retired. Lock/unlock and verify prior history is cleared and messages received while locked are not replayed.
  6. Check Cthulhu+H enters/exits learn mode, F1/F2 work inside it, and the shortcut list identifies the chat commands. Check a saved custom F-key assignment still works and the displaced default is not listed as active.
  7. Check OCR F5 refresh, normal browser navigation, and Steam notifications with their existing review/list commands. On Braille, check each message flashes once and the normal focus display returns afterward.

Actual Pidgin listening, physical shortcuts, and Braille acceptance remain pending.

Discord message focus

Named article ancestors are announced when focus enters their controls, matching Python's article ancestor presentation. Discord supplies the message author, contents, and timestamp in the article's accessible name. The message is spoken once on entry, followed by the focused button. Moving between controls within the same article does not repeat it. Leaving does not repeat the old message. This also works in focus mode and while browser context discovery is pending. Unnamed articles do not add announcements; other container preferences retain their existing browse-mode policy. Native traversal retains its depth and time limits and does not scan message descendants.

Automated checks:

go test ./internal/app -run '^TestMessageArticleAnnouncedOnceWhenTabbingIntoControls$' -count=1
CTHULHU_NATIVE_BROWSER_TESTS=article python3 tests/native_browser.py

Both tests fail without the corresponding fix. The private Chromium fixture checks native capture of a message article labelled by author, body, and time. The speech replay checks entry, movement within a message, movement to another message, exit, and re-entry. Neither establishes audible Discord acceptance.

Before submission, review the diff and test a rebuilt reader in Discord with Tab and Shift+Tab: enter a message's controls, move through Reply/Forward and reactions, then enter another message. Confirm each message is read on entry, control labels remain correct, and message contents do not repeat at each Tab stop. Repeat in browse and focus modes; check the message composer, ordinary browser buttons, and list/panel context announcements for regressions. Verify physical Braille focus and routing separately. Installed-binary, physical-input, audible-speech, and Braille-display acceptance remain pending.