Skip to content

Don't unnecessarily repeat row and column headers when navigating ARIA grids in focus mode.#20091

Merged
seanbudd merged 5 commits into
nvaccess:masterfrom
jcsteh:gridCellHeaders
May 15, 2026
Merged

Don't unnecessarily repeat row and column headers when navigating ARIA grids in focus mode.#20091
seanbudd merged 5 commits into
nvaccess:masterfrom
jcsteh:gridCellHeaders

Conversation

@jcsteh
Copy link
Copy Markdown
Contributor

@jcsteh jcsteh commented May 9, 2026

Link to issue number:

Fixes #17750.

Summary of the issue:

When moving to an ARIA grid cell in focus mode in web browsers, NVDA previously reported both the row and column headers even if only the row or only the column changed.

Description of user facing changes:

When moving to an ARIA grid cell in focus mode in web browsers, NVDA no longer reports both the row and column headers even if only the row or only the column changed.

Description of development approach:

Previously, there were two problems:

  1. After c4c3da6 (BrowseModeDocumentTextInfo.getControlFieldSpeech: Report the name of groupings (such as fieldsets) for quicknav and focus jumps, similar to how landmark labels are reported. #7435), Browse mode was updating the speech properties cache before speaking the focused object, even in focus mode. That meant that the row and column coordinates for the newly focused cell were already cached before NVDA spoke it, which made NVDA behave as if the coordinates never changed. The fix is to update the cache from the TextInfo after speaking the focused object.
  2. Virtual buffers just used the IA2 unique id as the table id, but NVDAObjects use both the window handle and id, meaning that these didn't compare correctly in the speech cache. The fix is to make the vbuf normalize table ids to windowHandle and id.

Testing strategy:

In both Firefox and Edge:

Tested as described in #17750 (comment). Confirmed that this works as expected.

With the same test URL, also verified that table navigation (control+alt+arrows) still behaves correctly in browse mode.

To ensure this doesn't regress #7435, tested with the following test case:

data:text/html,
<p>before</p>
<input>
<fieldset>
<legend>fs</legend>
<label>cb <input type="checkbox"></label>
</fieldset>
  1. Press control+home.
  2. Press x.
    • Observe speech: "fs grouping cb check box not checked"
  3. Press control+home.
  4. Press tab.
  5. Press tab again.
    • Observe speech: "fs grouping cb check box not checked"

Known issues with pull request:

None.

Code Review Checklist:

  • Documentation:
    • Change log entry
    • User Documentation
    • Developer / Technical Documentation
    • Context sensitive help for GUI changes
  • Testing:
    • Unit tests
    • System (end to end) tests
    • Manual testing
  • UX of all users considered:
    • Speech
    • Braille
    • Low Vision
    • Different web browsers
    • Localization in other languages / culture than English
  • API is compatible with existing add-ons.
  • Security precautions taken.

@jcsteh jcsteh marked this pull request as ready for review May 9, 2026 05:55
@jcsteh jcsteh requested a review from a team as a code owner May 9, 2026 05:55
@jcsteh jcsteh requested a review from SaschaCowley May 9, 2026 05:55
@seanbudd seanbudd added the merge-early Merge Early in a developer cycle label May 11, 2026
@seanbudd seanbudd added this to the 2026.3 milestone May 11, 2026
@SaschaCowley SaschaCowley added the conceptApproved Similar 'triaged' for issues, PR accepted in theory, implementation needs review. label May 12, 2026
Copy link
Copy Markdown
Member

@seanbudd seanbudd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jcsteh

@seanbudd seanbudd enabled auto-merge (squash) May 15, 2026 02:38
@seanbudd seanbudd requested a review from Copilot May 15, 2026 02:40
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes #17750 by addressing two issues that caused NVDA to repeat row/column headers when navigating ARIA grid cells in focus mode: (1) the speech cache was being updated before speaking the focused object, and (2) virtual buffers used a different table id format than NVDAObjects, preventing cache comparison.

Changes:

  • In browseMode.py, reorder event_gainFocus to speak the object first and update the speech cache via speakTextInfo(..., ONLYCACHE) afterwards, so cached coordinates don't suppress row/column change reports.
  • In gecko_ia2._normalizeControlField, normalize table-id to (windowHandle, uniqueId) so it matches the IAccessible NVDAObject tableID, and update _getTableCellAt to unpack the tuple via getNVDAObjectFromIdentifier(*tableID).
  • Add a user changes entry for the bug fix.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
user_docs/en/changes.md Adds a bug-fix entry describing the corrected ARIA grid header behaviour.
source/virtualBuffers/gecko_ia2.py Normalizes vbuf table-id to a (docHandle, id) tuple and adapts _getTableCellAt to use it.
source/browseMode.py Speaks the focused object before updating the speech cache so row/column changes are detected.

@seanbudd seanbudd merged commit e603629 into nvaccess:master May 15, 2026
69 of 75 checks passed
Boumtchack pushed a commit to France-Travail/nvda that referenced this pull request May 18, 2026
…A grids in focus mode. (nvaccess#20091)

Fixes nvaccess#17750.
Summary of the issue:

When moving to an ARIA grid cell in focus mode in web browsers, NVDA previously reported both the row and column headers even if only the row or only the column changed.
Description of user facing changes:

When moving to an ARIA grid cell in focus mode in web browsers, NVDA no longer reports both the row and column headers even if only the row or only the column changed.
Description of development approach:

Previously, there were two problems:

    After c4c3da6 (BrowseModeDocumentTextInfo.getControlFieldSpeech: Report the name of groupings (such as fieldsets) for quicknav and focus jumps, similar to how landmark labels are reported. nvaccess#7435), Browse mode was updating the speech properties cache before speaking the focused object, even in focus mode. That meant that the row and column coordinates for the newly focused cell were already cached before NVDA spoke it, which made NVDA behave as if the coordinates never changed. The fix is to update the cache from the TextInfo after speaking the focused object.
    Virtual buffers just used the IA2 unique id as the table id, but NVDAObjects use both the window handle and id, meaning that these didn't compare correctly in the speech cache. The fix is to make the vbuf normalize table ids to windowHandle and id.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

conceptApproved Similar 'triaged' for issues, PR accepted in theory, implementation needs review. merge-early Merge Early in a developer cycle

Projects

None yet

Development

Successfully merging this pull request may close these issues.

NVDA unnecessarily repeats row and column header labels

4 participants