Skip to content

Commit 1abd727

Browse files
Merge a682141 into 2de9755
2 parents 2de9755 + a682141 commit 1abd727

4 files changed

Lines changed: 25 additions & 0 deletions

File tree

source/NVDAObjects/UIA/excel.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
from UIAHandler.constants import (
1212
UIAutomationType,
1313
)
14+
import speech
15+
import api
1416
import colors
1517
import locationHelper
1618
import controlTypes
@@ -592,3 +594,18 @@ class BadExcelFormulaEdit(ExcelObject):
592594
"""
593595

594596
shouldAllowUIAFocusEvent = False
597+
598+
599+
class ExcelTable(UIA):
600+
""" Represents a table within an Excel spreadsheet."""
601+
602+
def event_focusExited(self):
603+
# Generally, NVDA would not announce when focus exits an ancestor control.
604+
# However, it is very common for focus to enter and exit tables within a spreadsheet,
605+
# Thus we specifically announce exiting tables here,
606+
# But only when focus is on an Excel cell,
607+
# As we don't want to announce exiting the table when focus moves out of the spreadsheet entirely.
608+
newFocus = api.getFocusObject()
609+
if isinstance(newFocus, ExcelCell):
610+
# Translators: announced when moving outside of a table in an Excel spreadsheet.
611+
speech.speakMessage(_("Out of table"))

source/NVDAObjects/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,6 +1203,10 @@ def event_loseFocus(self):
12031203
# Forget the word currently being typed as focus is moving to a new control.
12041204
speech.clearTypedWordBuffer()
12051205

1206+
def event_focusExited(self):
1207+
# In the general case, NVDA should not announce anything when focus exits an ancestor control.
1208+
pass
1209+
12061210
def event_foreground(self):
12071211
"""Called when the foreground window changes.
12081212
This method should only perform tasks specific to the foreground window changing.

source/api.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,9 @@ def setFocusObject(obj: NVDAObjects.NVDAObject) -> bool: # noqa: C901
175175
braille.invalidateCachedFocusAncestors(focusDifferenceLevel)
176176
if config.conf["reviewCursor"]["followFocus"]:
177177
setNavigatorObject(obj,isFocus=True)
178+
# Fire focusExited event for all old focus ancestors not common with the new focus
179+
for oldFocusAncestor in reversed(oldFocusLine[focusDifferenceLevel:-1]):
180+
eventHandler.executeEvent("focusExited", oldFocusAncestor)
178181
return True
179182

180183
def getFocusDifferenceLevel():

user_docs/en/changes.t2t

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ What's New in NVDA
2727
- Read entire column: ``NVDA+control+alt+upArrow``
2828
- Read entire row: ``NVDA+control+alt+leftArrow``
2929
-
30+
- Microsoft Excel via UI Automation: NVDA now announces when moving out of a table within a spreadsheet. (#14165)
3031
-
3132

3233

0 commit comments

Comments
 (0)