Skip to content

Commit 0433716

Browse files
authored
Merge c12770c into 8c982cd
2 parents 8c982cd + c12770c commit 0433716

2 files changed

Lines changed: 77 additions & 5 deletions

File tree

source/UIAHandler/__init__.py

Lines changed: 76 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# A part of NonVisual Desktop Access (NVDA)
2-
# Copyright (C) 2008-2021 NV Access Limited, Joseph Lee, Babbage B.V., Leonard de Ruijter, Bill Dengler
2+
# Copyright (C) 2008-2022 NV Access Limited, Joseph Lee, Babbage B.V., Leonard de Ruijter, Bill Dengler
33
# This file is covered by the GNU General Public License.
44
# See the file COPYING for more details.
55

@@ -99,6 +99,16 @@
9999
"Shell_SystemDialog", # Various dialogs in Windows 10 Settings app
100100
]
101101

102+
textChangeUIAAutomationIDs = (
103+
"Text Area", # Windows Console Host
104+
)
105+
106+
textChangeUIAClassNames = (
107+
"_WwG", # Microsoft Word
108+
"TermControl",
109+
"TermControl2"
110+
)
111+
102112
NVDAUnitsToUIAUnits: Dict[str, int] = {
103113
textInfos.UNIT_CHARACTER: UIA.TextUnit_Character,
104114
textInfos.UNIT_WORD: UIA.TextUnit_Word,
@@ -206,11 +216,9 @@
206216
autoSelectDetectionAvailable = False
207217
if winVersion.getWinVer() >= winVersion.WIN10:
208218
UIAEventIdsToNVDAEventNames.update({
209-
UIA.UIA_Text_TextChangedEventId: "textChange",
210219
UIA.UIA_Text_TextSelectionChangedEventId: "caret",
211220
})
212221
localEventHandlerGroupUIAEventIds.update({
213-
UIA.UIA_Text_TextChangedEventId,
214222
UIA.UIA_Text_TextSelectionChangedEventId,
215223
})
216224
autoSelectDetectionAvailable = True
@@ -268,6 +276,7 @@ def __init__(self):
268276
super(UIAHandler,self).__init__()
269277
self.globalEventHandlerGroup = None
270278
self.localEventHandlerGroup = None
279+
self.localEventHandlerGroupWithTextChanges = None
271280
self._localEventHandlerGroupElements = set()
272281
self.MTAThreadInitEvent=threading.Event()
273282
self.MTAThreadQueue = Queue()
@@ -403,6 +412,17 @@ def _registerGlobalEventHandlers(self):
403412
self.baseCacheRequest,
404413
self
405414
)
415+
if (
416+
not utils._shouldSelectivelyRegister()
417+
and winVersion.getWinVer() >= winVersion.WIN10
418+
):
419+
# #14067: Due to poor performance, textChange requires special handling
420+
self.globalEventHandlerGroup.AddAutomationEventHandler(
421+
UIA.UIA_Text_TextChangedEventId,
422+
UIA.TreeScope_Subtree,
423+
self.baseCacheRequest,
424+
self
425+
)
406426
# #7984: add support for notification event (IUIAutomation5, part of Windows 10 build 16299 and later).
407427
if isinstance(self.clientObject, UIA.IUIAutomation5):
408428
self.globalEventHandlerGroup.AddNotificationEventHandler(
@@ -421,21 +441,41 @@ def _registerGlobalEventHandlers(self):
421441
def _createLocalEventHandlerGroup(self):
422442
if isinstance(self.clientObject, UIA.IUIAutomation6):
423443
self.localEventHandlerGroup = self.clientObject.CreateEventHandlerGroup()
444+
self.localEventHandlerGroupWithTextChanges = self.clientObject.CreateEventHandlerGroup()
424445
else:
425446
self.localEventHandlerGroup = utils.FakeEventHandlerGroup(self.clientObject)
447+
self.localEventHandlerGroupWithTextChanges = utils.FakeEventHandlerGroup(self.clientObject)
426448
self.localEventHandlerGroup.AddPropertyChangedEventHandler(
427449
UIA.TreeScope_Ancestors | UIA.TreeScope_Element,
428450
self.baseCacheRequest,
429451
self,
430452
*self.clientObject.IntSafeArrayToNativeArray(localEventHandlerGroupUIAPropertyIds)
431453
)
454+
self.localEventHandlerGroupWithTextChanges.AddPropertyChangedEventHandler(
455+
UIA.TreeScope_Ancestors | UIA.TreeScope_Element,
456+
self.baseCacheRequest,
457+
self,
458+
*self.clientObject.IntSafeArrayToNativeArray(localEventHandlerGroupUIAPropertyIds)
459+
)
432460
for eventId in localEventHandlerGroupUIAEventIds:
433461
self.localEventHandlerGroup.AddAutomationEventHandler(
434462
eventId,
435463
UIA.TreeScope_Ancestors | UIA.TreeScope_Element,
436464
self.baseCacheRequest,
437465
self
438466
)
467+
self.localEventHandlerGroupWithTextChanges.AddAutomationEventHandler(
468+
eventId,
469+
UIA.TreeScope_Ancestors | UIA.TreeScope_Element,
470+
self.baseCacheRequest,
471+
self
472+
)
473+
self.localEventHandlerGroupWithTextChanges.AddAutomationEventHandler(
474+
UIA.UIA_Text_TextChangedEventId,
475+
UIA.TreeScope_Ancestors | UIA.TreeScope_Element,
476+
self.baseCacheRequest,
477+
self
478+
)
439479

440480
def addEventHandlerGroup(self, element, eventHandlerGroup):
441481
if isinstance(eventHandlerGroup, UIA.IUIAutomationEventHandlerGroup):
@@ -466,7 +506,23 @@ def func():
466506
if not isStillFocus:
467507
return
468508
try:
469-
self.addEventHandlerGroup(element, self.localEventHandlerGroup)
509+
if (
510+
element.currentClassName in textChangeUIAClassNames
511+
or element.CachedAutomationID in textChangeUIAAutomationIDs
512+
):
513+
group = self.localEventHandlerGroupWithTextChanges
514+
logPrefix = "Explicitly"
515+
else :
516+
group = self.localEventHandlerGroup
517+
logPrefix = "Not"
518+
519+
if _isDebug():
520+
log.debugWarning(
521+
f"{logPrefix} registering for textChange events from UIA element "
522+
f"with class name {repr(element.currentClassName)} "
523+
f"and automation ID {repr(element.CachedAutomationID)}"
524+
)
525+
self.addEventHandlerGroup(element, group)
470526
except COMError:
471527
log.error("Could not register for UIA events for element", exc_info=True)
472528
else:
@@ -500,7 +556,22 @@ def IUIAutomationEventHandler_HandleAutomationEvent(self,sender,eventID):
500556
if _isDebug():
501557
log.debug("HandleAutomationEvent: Ignored MenuOpenedEvent while focus event pending")
502558
return
503-
NVDAEventName=UIAEventIdsToNVDAEventNames.get(eventID,None)
559+
if eventID == UIA.UIA_Text_TextChangedEventId:
560+
if (
561+
sender.currentClassName in textChangeUIAClassNames
562+
or sender.CachedAutomationID in textChangeUIAAutomationIDs
563+
):
564+
NVDAEventName = "textChange"
565+
else:
566+
if _isDebug():
567+
log.debugWarning(
568+
"HandleAutomationEvent: Dropping textChange event from element "
569+
f"with class name {repr(sender.currentClassName)} "
570+
f"and automation ID {repr(sender.CachedAutomationID)}"
571+
)
572+
return
573+
else:
574+
NVDAEventName = UIAEventIdsToNVDAEventNames.get(eventID, None)
504575
if not NVDAEventName:
505576
if _isDebug():
506577
log.debugWarning(f"HandleAutomationEvent: Don't know how to handle event {eventID}")

user_docs/en/changes.t2t

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ What's New in NVDA
4646
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.
4747

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

5152

0 commit comments

Comments
 (0)