Repository: nvaccess/nvda

Issue:
NVDA very sluggish when navigating 1password for windows desktop
<!--
Please thoroughly read NVDA's wiki article on how to fill in this template, including how to provide the required files.
Issues may be closed if the required information is not present.
https://github.com/nvaccess/nvda/wiki/Github-issue-template-explanation-and-examples
-->

### Steps to reproduce:
1. Download the latest windows desktop version of 1password from http://www.1password.com
2. If you don't have a 1password account, sign up for a free trial.
3. Add a few passwords to your vault.
4. Tab to the list of passwords and use the arrow keys to navigate. NVDA will pause for around 1.5-2 seconds as you press the arrow keys to navigate.
JAWS and Narrator don't present this issue.

### Actual behavior:
NVDA very sluggish when navigating between items in password list. No errors show up in the log.


### Expected behavior:
NVDA should be as responsive as in other list views.

### System configuration
#### NVDA installed/portable/running from source:
NVDA installed 


#### NVDA version:
. 2019.2.1.
#### Windows version:
insider build 19023.1
#### Name and version of other software in use when reproducing the issue:
1password desktop version 7.3.712
#### Other information about your system:

### 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.
same behavior on alpha-19195,8306ec15
[nvda.log](https://github.com/nvaccess/nvda/files/3863695/nvda.log)



Discussion:
Just wanted to add a clarification. The sluggishness happens in the main 1password desktop app, not 1password Mini, which is the interface used to fill in passwords on websites, etc.
This looks like something specific to 1password, as running 7.2.576 on both machines here, doesn't present this issue with latest stable NVDA.
I've been offered the upgrade multiple times, but now I'm glad I didn't upgrade.
@jfayre contact me privately, I still have the older installer.

I am also seeing this. Not always, but often. It also happens that sometimes, NVDA takes about 10 to 20 seconds after entering the master password to speak the search field. Searching then also reacts very slowly.
Can confirm. Using latest 1Password desktop 7.4.759 and Alpha 19834, this issue still occurs. Using narrator, there is no major lag between each list item. It does not occur for every press of down or up arrow, but it is quite frequent.
I've just started using 1Password and this is really, really horrible. I regularly see lag of more than a second when moving between items in the list.

I debugged this a bit. 1Password fires 50+ UIA property change (name and item status) events every time you move between items in the list. These all seem to be on the fields for viewing/editing the item. This is very poor behaviour on their part and they should really fix it. If I make NVDA stop listening to property change events, it's as responsive as Narrator.

Interestingly, with the property change events enabled, the focus event callback happens after the lag. So, this isn't due to stuff we're doing when we handle the event in the main thread. This is all happening in the MTA (where UIA events get handled), before the event is queued to NVDA's core.

Obviously, not listening to property change events altogether isn't an option. However, Narrator and JAWS don't seem to be impacted like NVDA is. Some thoughts on that:

1. This is another reason to again consider selectively registering for property change events (e.g. on focus + ancestors and progress bar value changes), rather than unconditionally listening to all of them.
2. If I Register for property change events but return at the top of IUIAutomationPropertyChangedEventHandler_HandlePropertyChangedEvent (so we receive the event but discard it), it's pretty responsive. That suggests we might be able to optimise some of the stuff we do in the event handler; e.g. constructing the object, choosing overlay classes, etc.
I have a really hacky patch which works around this, but there's no way to do this in an app module, which means we end up with 1Password specific code in UIAHandler. :(

Resolving patch:
diff --git a/source/_UIAHandler.py b/source/_UIAHandler.py
--- a/source/_UIAHandler.py
+++ b/source/_UIAHandler.py
@@ -417,6 +417,14 @@ def IUIAutomationPropertyChangedEventHandler_HandlePropertyChangedEvent(self,sen
 			if _isDebug():
 				log.debug("HandlePropertyChangedEvent: event received while not fully initialized")
 			return
+		try:
+			processId = sender.CachedProcessID
+		except COMError:
+			pass
+		else:
+			appMod = appModuleHandler.getAppModuleFromProcessID(processId)
+			if not appMod.shouldProcessUIAPropertyChangedEvent(sender, propertyId):
+				return
 		NVDAEventName=UIAPropertyIdsToNVDAEventNames.get(propertyId,None)
 		if not NVDAEventName:
 			if _isDebug():
diff --git a/source/appModuleHandler.py b/source/appModuleHandler.py
--- a/source/appModuleHandler.py
+++ b/source/appModuleHandler.py
@@ -487,6 +487,18 @@ def isBadUIAWindow(self,hwnd):
 		"""
 		return False
 
+	def shouldProcessUIAPropertyChangedEvent(self, sender, propertyId):
+		"""
+		Determines whether NVDA should process a UIA property changed event.
+		Returning False will cause the event to be dropped completely. This can be
+		used to work around UIA implementations which flood events and cause poor
+		performance.
+		Returning True means that the event will be processed, but it might still
+		be rejected later; e.g. because it isn't native UIA, because
+		shouldAcceptEvent returns False, etc.
+		"""
+		return True
+
 	def dumpOnCrash(self):
 		"""Request that this process writes a minidump when it crashes for debugging.
 		This should only be called if instructed by a developer.
diff --git a/source/appModules/1password.py b/source/appModules/1password.py
new file mode 100644
--- /dev/null
+++ b/source/appModules/1password.py
@@ -0,0 +1,22 @@
+# appModules/1password.py
+# A part of NonVisual Desktop Access (NVDA)
+# Copyright (C) 2020 James Teh
+# This file is covered by the GNU General Public License.
+# See the file COPYING for more details.
+
+import appModuleHandler
+import UIAHandler
+
+
+class AppModule(appModuleHandler.AppModule):
+
+	def shouldProcessUIAPropertyChangedEvent(self, sender, propertyId):
+		if propertyId in (
+			UIAHandler.UIA_NamePropertyId,
+			UIAHandler.UIA_ItemStatusPropertyId,
+			UIAHandler.UIA_IsEnabledPropertyId
+		):
+			# #10508: 1Password floods property change events, resulting in very poor
+			# performance. Just drop them.
+			return False
+		return True


Test patch: