Fix COMError crashes and performance in Thunderbird#19
Open
serrebi wants to merge 2 commits intojavidominguez:masterfrom
Open
Fix COMError crashes and performance in Thunderbird#19serrebi wants to merge 2 commits intojavidominguez:masterfrom
serrebi wants to merge 2 commits intojavidominguez:masterfrom
Conversation
Thunderbird works much better now.
- COMError from stale Mozilla COM objects was not caught anywhere.
Every property access (.role, .firstChild, .parent, .IA2Attributes,
.states, .name) can throw _ctypes.COMError when Thunderbird's UI
updates. Only AttributeError/KeyError were caught, so COMErrors
hit NVDA's error handler 11+ times per focus change, causing
freezes (watchdog recovery of 0.5-0.9s per event).
- event_focusEntered ran expensive _IA2Relations COM call on every
ancestor object in the focus chain. Now restricted to INTERNALFRAME
role only. Also changed if/if/if chain to if/elif so only the
matching branch runs.
- event_documentLoadComplete called api.setFocusObject() twice just
to get a tree interceptor, firing the entire focus event chain
twice. Removed. Also capped text to 4000 chars so large HTML
emails don't block the main thread.
- initOverlayClass crashed with KeyError on IA2Attributes["id"]
when "id" key was missing. Changed to .get("id", "").
- chooseNVDAObjectOverlayClasses used dict["key"] instead of
.get("key") causing unnecessary KeyError exceptions.
- Added auto-focus to message list on Thunderbird startup instead
of landing on the preview pane.
Tested with Thunderbird Daily 150.0a1 (2026-03-15) (64-bit).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace unreliable shift+tab startup focus with F6 pane cycling that retries until focus lands on the actual message list (identified by threadTree-row ID prefix) - Schedule startup focus 4s after init to handle Thunderbird's Home tab loading before the Inbox tab - Optimize event_documentLoadComplete to limit text extraction range before accessing .text (avoids processing entire large messages) - Optimize readPreviewPane to avoid unnecessary double focus swap when tree interceptor is already available - Reduce COM calls in chooseNVDAObjectOverlayClasses by short-circuiting parent attribute checks - Add safety checks in event_focusEntered INTERNALFRAME case Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Thunderbird works much better
I vibe coded this. I just wanted this addon to help make Thunderbird very user friendly for blind users.
What was broken
.role,.firstChild,.parent,.IA2Attributes,.states,.name) throws_ctypes.COMErrorwhen objects go stale during UI updates. OnlyAttributeError/KeyErrorwere caught. COMErrors hit NVDA's error handler 11+ times per focus change, triggering watchdog freeze recovery (0.5–0.9s freezes).event_focusEnteredran expensive_IA2RelationsCOM call on every ancestor object in the focus chain. Also used a chain ofif/if/ifinstead ofif/elif, so every branch ran on every event.event_documentLoadCompleteread entire message body withmakeTextInfo("all").text, blocking the main thread on large HTML emails before truncating to 4000 chars.readPreviewPaneswapped focus twice unnecessarily — calledapi.setFocusObject()twice just to get a tree interceptor reference, firing the entire focus event chain for no reason.chooseNVDAObjectOverlayClassesmade redundant COM calls — accessed parent IA2Attributes even when the object's own attributes already matched.What this PR does
COMErrorand catch it in all event handlers, overlay class methods, and property accessors_IA2Relationslookup toINTERNALFRAMErole only, with its own try/except and null check onobjectWithFocus()event_documentLoadComplete: limit the text range to 4000 chars before extracting.text(collapse + move end point), avoiding full virtual buffer processingreadPreviewPane: tryobj.treeInterceptorandgetTreeInterceptor()first, only fall back to the double focus swap if neither returns a tree interceptorchooseNVDAObjectOverlayClasses: checkobj.IA2Attributesfirst and short-circuit — only query parent attributes if the object's ownxml-rolesdoesn't matchthreadTree-row*IA2 ID prefix (distinguishes message list from folder tree). Falls back gracefully if inbox hasn't loaded.Testing
Manually tested with Thunderbird Daily 150.0a1 (2026-03-15) (64-bit) and NVDA 2026.1beta6.
🤖 Generated with Claude Code