Repository navigation
JAWS no longer repeats a closed dialog's text - #250
Merged
Merged
Conversation
As a dialog opens, JAWS reads its static text (what comes before the first control that takes focus) and keeps it with the window that owns the dialog. After the dialog closed, it said that text again after the main window's title on Alt+Tab back, Escape to home and every view change: "Press Enter or double-click a headline to open in your browser:" from a league's News, the game News label from Live Scores. 1.1.1 did the same. NVDA keeps nothing. dialog_text.DialogTextOrder, installed app-wide, puts each part of a dialog that holds nothing focusable after the parts that do, in Qt's accessibility order (raise_ moves a widget to the end of its parent's children), as the dialog shows and when it's activated again. Nothing moves on screen or in the tab order. Measured with JAWS 2027 speech history in the VM. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Count only what Tab reaches as a control (click focus alone is static text to a screen reader), so a message box's message follows its buttons in every style, not only Fusion. - Look inside a tab widget's pages and a scroll area's contents, which are focusable containers. - Walk children ourselves and stop at child windows. - An exception in the filter is logged, not allowed to end the app. - Tests for tab pages, scroll areas, button boxes, stacked widgets, a dialog with nothing focusable, the whole focus chain, and the error path. - CHANGELOG and CLAUDE.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kellylford
added a commit
that referenced
this pull request
Nov 8, 2026
The first JAWS run of the app: exact JAWS speech from its speech history through its COM API, the before and after for #250, the PyQt harness of the variants tried, and how to run it again. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What Kelly heard
With JAWS, after any dialog closed, its first line of text came back after the main window's title every time he returned to Scores or the screen changed: Alt+Tab back, Escape to Live Scores, Escape to home. From a game's News: "Live Scores - Sports Scores", then "News Headlines (🎯 = Game-specific, Enter or double-click to open in browser):". From a league's News: "Press Enter or double-click a headline to open in your browser:", heard on screens with no news at all. 1.1.1 does the same (Kelly confirmed it, and a 1.1.1 take is in the report), so it isn't a regression. NVDA never says it, which is why the NVDA runs missed it.
Why
Measured with JAWS 2027.2610.428 in the test VM, using JAWS's exact speech, read from its own speech history through its COM API (
FreedomSci.JawsApi:ClearSpeechHistorybefore each key,CopySpeechHistoryToClipboardafter it).As a dialog opens, JAWS reads the static text that comes before its first focusable control and keeps it with the window that owns the dialog, which here is the main window. After the dialog closes, JAWS says that text after the owner's title whenever it announces the owner, until another dialog replaces it. The dialog and its view are long gone by then (it's still said on the home screen), and nothing in the UIA or MSAA trees holds the text any more.
A minimal PyQt6 app (one main window, one
QDialog(self)with a label above a list) reproduces it. Its variants pin down the cause:WA_DeleteOnCloseNotifyWinEvent(EVENT_OBJECT_REORDER)on the main windowraise_(), nothing moves on screen)The fix
dialog_text.DialogTextOrder, installed app-wide next toButtonKeys, puts every part of a dialog that holds nothing Tab can reach after the parts that do, in Qt's accessibility order (raise_()), as each dialog shows and when it's activated again. It also looks inside tab pages and scroll areas. Nothing moves on screen or in the tab order. An exception in it is logged, not allowed to end the app.Trade-off: as a dialog opens, JAWS says its title and the control you're on, but no longer reads the heading or instruction above the first control by itself. A message box's message is still read on open (JAWS reads it as an alert; checked in the harness).
JAWS before and after (exact speech)
Before is the 1.2.0 candidate. After is this branch.
1.1.1 (JAWS, same Statistics path): "NBA Statistics Selection" after the title on Alt+Tab back and on Escape to home, as in the candidate.
NVDA 2026.2 (its own log) on this branch: as each dialog opens, NVDA still reads the dialog's text ("News Headlines - NBA, dialog, Press Enter or double-click a headline to open in your browser:"), since it doesn't go by order. After the dialog closes, it says only the title and the list, as before.
Code review (
code-reviewer): fixed what it found. Only Tab-reachable widgets count as controls, so the result doesn't depend on the style; tab pages and scroll-area contents are reordered too; the walk stops at child windows; errors are logged; more tests. The JAWS takes above were rerun on the reviewed build.Logs, steps and the harness are in Kelly's testing folder (
jaws-stray-dialog-text-2026-11-08).Tests
tests/unit/test_dialog_text.py(offscreen): order after show and after re-activation, nested containers, tab pages and scroll areas, hidden controls, click focus alone, child dialogs, button boxes, stacked widgets, a dialog with nothing focusable, message boxes, an unchanged focus chain and geometry, errors logged, main-window views untouched. Full suite: 5103 passed, 4 xfailed.🤖 Generated with Claude Code