Skip to content

When executing events other than focus, only take running tree interceptors into account#11653

Closed
LeonarddeR wants to merge 1 commit into
nvaccess:masterfrom
LeonarddeR:ti
Closed

When executing events other than focus, only take running tree interceptors into account#11653
LeonarddeR wants to merge 1 commit into
nvaccess:masterfrom
LeonarddeR:ti

Conversation

@LeonarddeR

Copy link
Copy Markdown
Collaborator

Link to issue number:

Fixes #11533
Closes #11652

Summary of the issue:

When an event is fired, NVDA tries to fetch the tree interceptor for the object on which the event is fired. This includes a check whether the object belongs to every running tree interceptor. If an object in Chromium belongs to the same window but not to the same tree interceptor as another tree interceptor, this check can take some time, therefore causing major performance degradation. This happens in VS Code where the root node of the Electron application has a tree interceptor but most child nodes are part of an application.nodes are part of

Description of how this pull request fixes the issue:

  1. Added a new object property: runningTreeInterceptor. This property only reveals the tree interceptor that is cached on the object, it does not call treeInterceptorHandler.getTreeInterceptor
  2. When executing events, the new property is used. This ensures that we're no longer unnecessarily trying to get a tree interceptor when executing events.

Testing performed:

Tested by several people that performance issues in VS Code are gone, see #11533.

Known issues with pull request:

I think this needs to be tested more broadly. I can think of some possible regressions:

  1. event_caret for objects in the BrowseModeDocumentTreeInterceptor are discarded when pass through is off. With this change, this no longer applies to objects that don't have a cached tree interceptor on them. However, we discard caret events for all but focus objects anyway, so I don't see how this could cause issues.
  2. Something similar applies to event_focusEntered. The event might not come across the tree interceptor this way.

Change log entry:

@LeonarddeR

Copy link
Copy Markdown
Collaborator Author

@michaelDCurran I'm aware of the fact that this solution is probably not ideal, though I'm sure we must somehow fix the way tree interceptors are getting in the way here.

@AppVeyorBot

Copy link
Copy Markdown

See test results for failed build of commit 7a677ca2cb

@michaelDCurran

Copy link
Copy Markdown
Member

event_scrollingStart in the gecko_ia2 virtualBuffer will not be handled anymore, plus event_valueChange in the adobeAcrobat virtualBuffer.
I'm not worried about event_caret.
Event_focusEntered: yes this is a problem. We'd need to change api.setFocusObject and eventHandler.doPreDocumentLoadComplete to ensure the right treeInterceptor was cached on the focus ancestors which are descendants of a newly created treeInterceptor. But even if we did specifically fix this, it does significantly change the concept that treeInterceptors catch all events for all descendants. Note event_scrollingStart and event_valueChange above.
I'd like to better understand why the __contains__ on the TreeInterceptor for Chrome in VSCode is so slow.

@michaelDCurran

Copy link
Copy Markdown
Member

Currently, NVDA is creating a treeInterceptor for the root of the app (The read-only document that contains everything). However, its only child is an application, thus we don't actually ever render anything.
But, Every descendant object NvDA knows about may ask if it is in this treeInterceptor. Chromium says yes (accChild on the root returns a valid object) but then we do some very costly things to check if we are inside an application in the virtualBuffer.
Unless I am really misunderstanding things here, I feel that we should reintroduce a VS Code appModule which disables the treeInterceptor on the root of the application (the top read-only document below the Desktop). As now most if not all VS code subdocuments (Release Notes etc) have correct readonly document objects, virtualBuffers will be created for each of them when needed.
If the user does however for some reason get confused or deliberately presses NVDA+space when focused in the code editor, or something that is within the application objectbut not within a subDocument, they will force a virtualBuffer for the application object, and from then on need to fiddle with NVDA+space, and they will also hit the performance problem again.
Perhaps, we should specifically also disallowing forcing a virtualBuffer on that application object as well, perhaps by making treeInterceptorClass None.

@MarcoZehe

Copy link
Copy Markdown
Contributor

Do all Electron apps have this problem? Or will they get it if an app like Slack or Discord also introduce an application role on their respective body elements, or as in the Slack case already, somewhere further down the tree structure?

@LeonarddeR

Copy link
Copy Markdown
Collaborator Author

But, Every descendant object NvDA knows about may ask if it is in this treeInterceptor. Chromium says yes (accChild on the root returns a valid object) but then we do some very costly things to check if we are inside an application in the virtualBuffer.

I wonder, why don't we ask the vbuf itself whether an object is part of it? Is that less reliable?

Unless I am really misunderstanding things here, I feel that we should reintroduce a VS Code appModule which disables the treeInterceptor on the root of the application (the top read-only document below the Desktop). As now most if not all VS code subdocuments (Release Notes etc) have correct readonly document objects, virtualBuffers will be created for each of them when needed.

While I think this is a sane workaround for now, I'm afraid that we aren't fixing the actual underlying issue in that case. @MarcoZehe raised a valid point here. Though not all electron apps might have this issue, I'm pretty sure there are more apps using an application role like this. We'd have to add an exception for all of these.

If the user does however for some reason get confused or deliberately presses NVDA+space when focused in the code editor, or something that is within the application objectbut not within a subDocument, they will force a virtualBuffer for the application object, and from then on need to fiddle with NVDA+space, and they will also hit the performance problem again.

Interesting enough, the performance hit caused when there is a virtual buffer on the application object is much less prevalent.

Perhaps, we should specifically also disallowing forcing a virtualBuffer on that application object as well, perhaps by making treeInterceptorClass None.

Also feels a bit like a workaround to me, honestly.

@LeonarddeR

Copy link
Copy Markdown
Collaborator Author

This pr has too much regressions. It will have to be another approach. I think I'll start with reintroducing the appModule as @michaelDCurran suggested.

@LeonarddeR

LeonarddeR commented Sep 22, 2020

Copy link
Copy Markdown
Collaborator Author

Filed #11657

@LeonarddeR LeonarddeR closed this Sep 22, 2020
@LeonarddeR LeonarddeR deleted the ti branch August 23, 2025 06:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

4 participants