nvda
f7dc081e - Fix JAB freeze when navigating in JetBrains IDEs (#19934)

Commit
98 days ago
Fix JAB freeze when navigating in JetBrains IDEs (#19934) Closes #16741 Summary of the issue: NVDA freezes for 10-15 seconds when navigating in JetBrains IDEs. Holding arrow keys in the editor causes the watchdog to trigger and eventually force recovery. Description of user facing changes: Navigation in JetBrains IDEs no longer causes NVDA to freeze. This may also help with other rapid interaction patterns like scrolling with the mouse and clicking on code repeatedly. Description of developer facing changes: None. Description of development approach: Two compounding issues in JABHandler caused the freeze: Synchronous property change callbacks: event_nameChange, event_descriptionChange, and event_valueChange were registered directly as JAB callbacks, doing heavy work (NVDAObject creation, bridge queries, event queuing) on the callback thread. This blocked the main thread during wx.Yield(). The fix wraps them in internalQueueFunction, matching the pattern already used by event_focusGained, event_stateChange, and event_caretChange. Recursive parent traversal in findOverlayClasses: The table-cell check self.parent and isinstance(self.parent, Table) called _get_parent(), which created a full NVDAObject for the parent, recursively triggering findOverlayClasses up the entire component tree. Each level makes at least 2 cross-process bridge calls (getAccessibleParentFromContext + getAccessibleContextInfo). In JetBrains Rider, the editor text field sits 19 levels deep in the Java component hierarchy, so a single findOverlayClasses call caused 19 recursive NVDAObject instantiations with ~38 bridge calls. The fix introduces _hasTableParent() which checks the immediate parent's role via a lightweight bridge call and only creates a full NVDAObject when the role is "table" (which involves additional bridge calls). Incomplete callback cleanup: 4 of 7 registered JAB callbacks were deregistered in terminate(), the 3 property change callbacks (name, description, value) were missing. All 7 are now symmetrically deregistered. Evict-oldest queue overflow strategy: When the internal event queue (1000 items) is full, the oldest event is evicted to make room for the newest. JOBJECT64 handles owned by evicted events are released to prevent JNI reference leaks. This also fixes a pre-existing leak in internal_event_activeDescendantChange where newDescendant was never released when the source object did not have focus.
Parents
Loading