Repository: nvaccess/nvda

Issue:
Major performance regression in Firefox edit fields on Windows 10 1903
Cc @jcsteh @michaeldcurran @codeofdusk 

### Steps to reproduce:
Try to edit and select text in firefox edit controls, particularly multi line controls.

### Actual behavior:
Typing, movement and selection are all pretty slow compared to older NVDA releases.

### Expected behavior:
No performance regressions.

### Testing performed
It occurred to me that I only experienced these performance regressions on installed copies of latest Alpha versions, not when running from source. Testing revealed that as soon as I forcefully enabled support for UIA  Text TextChanged events, the regression occurred also in source copies.

On windows 1903, UIA has bridging support for IAccessible2 built-in. It looks like IA2 events are translated to UIA events, and we really should try to avoid that.

### System configuration
#### NVDA installed/portable/running from source:
installed

#### NVDA version:
alpha-17384

#### Windows version:
Windows 10 1903 build 18362.145

#### Name and version of other software in use when reproducing the issue:
Firefox 67.0 X64

#### Other information about your system:
I haven't tested with Chrome yet

### Other questions
#### Does the issue still occur after restarting your PC?
Yes

#### Have you tried any other versions of NVDA? If so, please report their behaviors.
Yes, NVDA from source doesn't suffer from this as it does not register for these UIA events.


Discussion:

Resolving patch:
diff --git a/source/_UIAHandler.py b/source/_UIAHandler.py
--- a/source/_UIAHandler.py
+++ b/source/_UIAHandler.py
@@ -25,7 +25,6 @@
 import eventHandler
 from logHandler import log
 import UIAUtils
-
 from comtypes.gen.UIAutomationClient import *
 
 #Some newer UIA constants that could be missing
@@ -154,6 +153,12 @@
 if winVersion.isAtLeastWin10():
 	UIAEventIdsToNVDAEventNames[UIA_Text_TextChangedEventId] = "textChange"
 
+ignoreWinEventsMap = {
+	UIA_AutomationPropertyChangedEventId: list(UIAPropertyIdsToNVDAEventNames.keys()),
+}
+for id in UIAEventIdsToNVDAEventNames.iterkeys():
+	ignoreWinEventsMap[id] = [0]
+
 class UIAHandler(COMObject):
 	_com_interfaces_=[IUIAutomationEventHandler,IUIAutomationFocusChangedEventHandler,IUIAutomationPropertyChangedEventHandler,IUIAutomationNotificationEventHandler]
 
@@ -192,20 +197,24 @@ def MTAThreadFunc(self):
 			pfm=self.clientObject.proxyFactoryMapping
 			for index in xrange(pfm.count):
 				e=pfm.getEntry(index)
-				for propertyID in UIAPropertyIdsToNVDAEventNames.keys():
-					# Check if this proxy has mapped any winEvents to the UIA propertyChange event for this property ID 
-					try:
-						oldWinEvents=e.getWinEventsForAutomationEvent(UIA_AutomationPropertyChangedEventId,propertyID)
-					except IndexError:
-						# comtypes does not seem to correctly handle a returned empty SAFEARRAY, raising IndexError
-						oldWinEvents=None
-					if oldWinEvents:
-						# As winEvents were mapped, replace them with an empty list
-						e.setWinEventsForAutomationEvent(UIA_AutomationPropertyChangedEventId,propertyID,[])
-						# Changes to an enty are not automatically picked up.
-						# Therefore remove the entry and re-insert it.
-						pfm.removeEntry(index)
-						pfm.insertEntry(index,e)
+				entryChanged = False
+				for eventId, propertyIds in ignoreWinEventsMap.iteritems():
+					for propertyId in propertyIds:
+						# Check if this proxy has mapped any winEvents to the UIA propertyChange event for this property ID 
+						try:
+							oldWinEvents=e.getWinEventsForAutomationEvent(eventId,propertyId)
+						except IndexError:
+							# comtypes does not seem to correctly handle a returned empty SAFEARRAY, raising IndexError
+							oldWinEvents=None
+						if oldWinEvents:
+							# As winEvents were mapped, replace them with an empty list
+							e.setWinEventsForAutomationEvent(eventId,propertyId,[])
+							entryChanged = True
+				if entryChanged:
+					# Changes to an entry are not automatically picked up.
+					# Therefore remove the entry and re-insert it.
+					pfm.removeEntry(index)
+					pfm.insertEntry(index,e)
 			if isUIA8:
 				# #8009: use appropriate interface based on highest supported interface.
 				# #8338: made easier by traversing interfaces supported on Windows 8 and later in reverse.


Test patch: