Skip to content

Commit e603629

Browse files
authored
Don't unnecessarily repeat row and column headers when navigating ARIA grids in focus mode. (#20091)
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: 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. 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.
1 parent 3de7248 commit e603629

3 files changed

Lines changed: 18 additions & 6 deletions

File tree

source/browseMode.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2225,12 +2225,15 @@ def event_gainFocus(self, obj, nextHandler):
22252225
# we need to call it manually here.
22262226
vision.handler.handleGainFocus(obj)
22272227
else:
2228-
# Although we are going to speak the object rather than textInfo content, we still need to silently speak the textInfo content so that the textInfo speech cache is updated correctly.
2228+
self._replayFocusEnteredEvents()
2229+
nextHandler()
2230+
# Although we spoke the object rather than textInfo content, we still need to silently speak the textInfo content so that the textInfo speech cache is updated correctly.
22292231
# Not doing this would cause later browseMode speaking to either not speak controlFields it had entered, or speak controlField exits after having already exited.
22302232
# See #7435 for a discussion on this.
2233+
# #17750: It's important that we do this *after* speaking the object.
2234+
# Otherwise, the cached info would prevent NVDA from detecting things like
2235+
# row and column changes.
22312236
speech.speakTextInfo(focusInfo, reason=OutputReason.ONLYCACHE)
2232-
self._replayFocusEnteredEvents()
2233-
nextHandler()
22342237
focusInfo.collapse()
22352238
if self._focusEventMustUpdateCaretPosition:
22362239
self._set_selection(focusInfo, reason=OutputReason.FOCUS)

source/virtualBuffers/gecko_ia2.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,15 @@ def _normalizeControlField(self, attrs): # noqa: C901
216216
attrs["detailsRoles"] = set(self._normalizeDetailsRole(detailsRoles))
217217
if config.conf["debugLog"]["annotations"]:
218218
log.debug(f"detailsRoles: {attrs['detailsRoles']}")
219-
return super()._normalizeControlField(attrs)
219+
attrs = super()._normalizeControlField(attrs)
220+
# #17750: The table-id attribute from the buffer is just a unique id.
221+
# However, the IAccessible NVDAObject specifies the tableID as
222+
# (windowHandle, uniqueId). These need to be compatible for speech cache
223+
# comparison lest we break row/column change detection.
224+
tableID = attrs.get("table-id")
225+
if tableID:
226+
attrs["table-id"] = (int(attrs["controlIdentifier_docHandle"]), tableID)
227+
return attrs
220228

221229
def _normalizeDetailsRole(self, detailsRoles: str) -> Iterable[Optional[controlTypes.Role]]:
222230
"""
@@ -579,8 +587,7 @@ def event_scrollingStart(self, obj, nextHandler):
579587
event_scrollingStart.ignoreIsReady = True
580588

581589
def _getTableCellAt(self, tableID, startPos, destRow, destCol):
582-
docHandle = self.rootDocHandle
583-
table = self.getNVDAObjectFromIdentifier(docHandle, tableID)
590+
table = self.getNVDAObjectFromIdentifier(*tableID)
584591
try:
585592
try:
586593
cell = table.IAccessibleTable2Object.cellAt(destRow - 1, destCol - 1).QueryInterface(

user_docs/en/changes.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
### Bug Fixes
1212

13+
* 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. (#17750, @jcsteh)
14+
1315
### Changes for Developers
1416

1517
Please refer to [the developer guide](https://download.nvaccess.org/documentation/developerGuide.html#API) for information on NVDA's API deprecation and removal process.

0 commit comments

Comments
 (0)