Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 76 additions & 5 deletions source/UIAHandler/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# A part of NonVisual Desktop Access (NVDA)
# Copyright (C) 2008-2021 NV Access Limited, Joseph Lee, Babbage B.V., Leonard de Ruijter, Bill Dengler
# Copyright (C) 2008-2022 NV Access Limited, Joseph Lee, Babbage B.V., Leonard de Ruijter, Bill Dengler
# This file is covered by the GNU General Public License.
# See the file COPYING for more details.

Expand Down Expand Up @@ -99,6 +99,16 @@
"Shell_SystemDialog", # Various dialogs in Windows 10 Settings app
]

textChangeUIAAutomationIDs = (
"Text Area", # Windows Console Host
)

textChangeUIAClassNames = (
"_WwG", # Microsoft Word
"TermControl",
"TermControl2"
)

NVDAUnitsToUIAUnits: Dict[str, int] = {
textInfos.UNIT_CHARACTER: UIA.TextUnit_Character,
textInfos.UNIT_WORD: UIA.TextUnit_Word,
Expand Down Expand Up @@ -206,11 +216,9 @@
autoSelectDetectionAvailable = False
if winVersion.getWinVer() >= winVersion.WIN10:
UIAEventIdsToNVDAEventNames.update({
UIA.UIA_Text_TextChangedEventId: "textChange",
UIA.UIA_Text_TextSelectionChangedEventId: "caret",
})
localEventHandlerGroupUIAEventIds.update({
UIA.UIA_Text_TextChangedEventId,
UIA.UIA_Text_TextSelectionChangedEventId,
})
autoSelectDetectionAvailable = True
Expand Down Expand Up @@ -268,6 +276,7 @@ def __init__(self):
super(UIAHandler,self).__init__()
self.globalEventHandlerGroup = None
self.localEventHandlerGroup = None
self.localEventHandlerGroupWithTextChanges = None
self._localEventHandlerGroupElements = set()
self.MTAThreadInitEvent=threading.Event()
self.MTAThreadQueue = Queue()
Expand Down Expand Up @@ -403,6 +412,17 @@ def _registerGlobalEventHandlers(self):
self.baseCacheRequest,
self
)
if (
not utils._shouldSelectivelyRegister()
and winVersion.getWinVer() >= winVersion.WIN10
):
# #14067: Due to poor performance, textChange requires special handling
self.globalEventHandlerGroup.AddAutomationEventHandler(
UIA.UIA_Text_TextChangedEventId,
UIA.TreeScope_Subtree,
self.baseCacheRequest,
self
)
# #7984: add support for notification event (IUIAutomation5, part of Windows 10 build 16299 and later).
if isinstance(self.clientObject, UIA.IUIAutomation5):
self.globalEventHandlerGroup.AddNotificationEventHandler(
Expand All @@ -421,21 +441,41 @@ def _registerGlobalEventHandlers(self):
def _createLocalEventHandlerGroup(self):
if isinstance(self.clientObject, UIA.IUIAutomation6):
self.localEventHandlerGroup = self.clientObject.CreateEventHandlerGroup()
self.localEventHandlerGroupWithTextChanges = self.clientObject.CreateEventHandlerGroup()
else:
self.localEventHandlerGroup = utils.FakeEventHandlerGroup(self.clientObject)
self.localEventHandlerGroupWithTextChanges = utils.FakeEventHandlerGroup(self.clientObject)
self.localEventHandlerGroup.AddPropertyChangedEventHandler(
UIA.TreeScope_Ancestors | UIA.TreeScope_Element,
self.baseCacheRequest,
self,
*self.clientObject.IntSafeArrayToNativeArray(localEventHandlerGroupUIAPropertyIds)
)
self.localEventHandlerGroupWithTextChanges.AddPropertyChangedEventHandler(
UIA.TreeScope_Ancestors | UIA.TreeScope_Element,
self.baseCacheRequest,
self,
*self.clientObject.IntSafeArrayToNativeArray(localEventHandlerGroupUIAPropertyIds)
)
for eventId in localEventHandlerGroupUIAEventIds:
self.localEventHandlerGroup.AddAutomationEventHandler(
eventId,
UIA.TreeScope_Ancestors | UIA.TreeScope_Element,
self.baseCacheRequest,
self
)
self.localEventHandlerGroupWithTextChanges.AddAutomationEventHandler(
eventId,
UIA.TreeScope_Ancestors | UIA.TreeScope_Element,
self.baseCacheRequest,
self
)
self.localEventHandlerGroupWithTextChanges.AddAutomationEventHandler(
UIA.UIA_Text_TextChangedEventId,
UIA.TreeScope_Ancestors | UIA.TreeScope_Element,
self.baseCacheRequest,
self
)

def addEventHandlerGroup(self, element, eventHandlerGroup):
if isinstance(eventHandlerGroup, UIA.IUIAutomationEventHandlerGroup):
Expand Down Expand Up @@ -466,7 +506,23 @@ def func():
if not isStillFocus:
return
try:
self.addEventHandlerGroup(element, self.localEventHandlerGroup)
if (
element.currentClassName in textChangeUIAClassNames
or element.CachedAutomationID in textChangeUIAAutomationIDs
):
group = self.localEventHandlerGroupWithTextChanges
logPrefix = "Explicitly"
else :
group = self.localEventHandlerGroup
logPrefix = "Not"

if _isDebug():
log.debugWarning(
f"{logPrefix} registering for textChange events from UIA element "
f"with class name {repr(element.currentClassName)} "
f"and automation ID {repr(element.CachedAutomationID)}"
)
self.addEventHandlerGroup(element, group)
except COMError:
log.error("Could not register for UIA events for element", exc_info=True)
else:
Expand Down Expand Up @@ -500,7 +556,22 @@ def IUIAutomationEventHandler_HandleAutomationEvent(self,sender,eventID):
if _isDebug():
log.debug("HandleAutomationEvent: Ignored MenuOpenedEvent while focus event pending")
return
NVDAEventName=UIAEventIdsToNVDAEventNames.get(eventID,None)
if eventID == UIA.UIA_Text_TextChangedEventId:
if (
sender.currentClassName in textChangeUIAClassNames
or sender.CachedAutomationID in textChangeUIAAutomationIDs
):
NVDAEventName = "textChange"
else:
if _isDebug():
log.debugWarning(
"HandleAutomationEvent: Dropping textChange event from element "
f"with class name {repr(sender.currentClassName)} "
f"and automation ID {repr(sender.CachedAutomationID)}"
)
return
else:
NVDAEventName = UIAEventIdsToNVDAEventNames.get(eventID, None)
if not NVDAEventName:
if _isDebug():
log.debugWarning(f"HandleAutomationEvent: Don't know how to handle event {eventID}")
Expand Down
1 change: 1 addition & 0 deletions user_docs/en/changes.t2t
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ What's New in NVDA
Please refer to [the developer guide https://www.nvaccess.org/files/nvda/documentation/developerGuide.html#API] for information on NVDA's API deprecation and removal process.

- The [NVDA API Announcement mailing list https://groups.google.com/a/nvaccess.org/g/nvda-api/about] was created. (#13999)
- NVDA no longer processes ``textChange`` events for most UI Automation applications due to their extreme negative performance impact. (#11002, #14067)
-


Expand Down