Skip to content

feat: prevent UIA COM freezes and suppress braille events for stability#7

Merged
VIPPotato merged 1 commit intoVIPPotato:masterfrom
khsbory:feat/braille-freeze-prevention
Feb 14, 2026
Merged

feat: prevent UIA COM freezes and suppress braille events for stability#7
VIPPotato merged 1 commit intoVIPPotato:masterfrom
khsbory:feat/braille-freeze-prevention

Conversation

@khsbory
Copy link
Copy Markdown
Contributor

@khsbory khsbory commented Feb 13, 2026

Summary

This PR addresses two critical issues that occur when a braille display is connected to NVDA while using KakaoTalk:

Issue 1: NVDA freezes (Watchdog triggered) when opening context menus

When a braille display is connected, pressing the popup key (Shift+F10 or Applications key) on a message in the chat room list or in the message list within a conversation causes NVDA to freeze for 8-22 seconds, triggering the Watchdog recovery mechanism.

Root cause: NVDA's _prefetchUIACacheForPropertyIDs calls UIAElement.buildUpdatedCache(), a synchronous cross-process COM call. When KakaoTalk's UI thread is busy handling the context menu modal loop, this call blocks the NVDA main thread until the COM timeout expires. Additionally, braille.handler.handleGainFocus() queries 15+ UIA properties via COM for the braille display, compounding the blocking.

Fix:

  • KakaoUIABase: Overrides _prefetchUIACacheForPropertyIDs as a no-op for all KakaoTalk UIA objects. Individual property accesses fall back to getCurrentPropertyValueEx(), which uses per-property timeouts and is far less likely to cause a total freeze.
  • KakaoBrailleSuppressed: Skips braille.handler.handleGainFocus() and returns empty getBrailleRegions() for all EVA_Menu objects, preventing braille handler from triggering additional UIA COM queries.
  • isGoodUIAWindow: Changed from unconditional return True to a whitelist approach. Only EVA_VH_ListControl_Dblclk (the main list control) is forced to use UIA. Other windows (including EVA_Menu) fall back to NVDA's core decision logic, which typically selects IAccessible for standard Win32 menus.
  • COMError try-except guards added to event_UIA_elementSelected, _get_states, and _get_name to prevent cascading COM failures.

Trade-off: Context menu items will not be displayed on the braille display. Speech output for menu items is fully preserved. This is a necessary compromise to prevent the severe freezing issue.

Issue 2: Character composition breakage during message input

When a braille display is connected and the user types in the KakaoTalk message input field, Korean IME character composition breaks — characters appear in wrong positions or certain characters fail to input entirely.

Root cause: Korean IME's compositionUpdate() queues valueChange and caret events on every keystroke. The default NVDA handlers for these events call braille.handler.handleUpdate() and braille.handler.handleCaretMove(), which query object properties and disrupt the IAccessible text state, causing focus to jump and character composition to break.

Fix:

  • KakaoTalkMessageEdit: An aggressive overlay for the message input field (RICHEDIT50W, controlID 1006) that:
    • Suppresses all braille-related events and properties (getBrailleRegions, event_braille*, shouldAcceptEvent)
    • Overrides event_valueChange and event_caret to skip braille handler calls while preserving speech output
    • Sets role-related properties to neutral values to minimize NVDA's interference with the edit control
  • event_inputComposition: Suppresses IME composition events for Korean locale in the message input field to prevent additional focus instability.

Class hierarchy

NVDAObjects.UIA.UIA
  └─ KakaoUIABase (prefetch disabled)
       ├─ KakaoListItem (chat/message list items)
       └─ KakaoBrailleSuppressed (braille suppressed)
            └─ KakaoMenuItem (menu items + shouldAllowUIAFocusEvent)

NVDAObjects.IAccessible.IAccessible
  └─ KakaoTalkMessageEdit (message input + braille/event suppression)

Test plan

  • Open KakaoTalk with a braille display connected
  • Navigate the chat room list with arrow keys — items should be announced via speech
  • Press Shift+F10 or Applications key on a chat room — context menu should open without freezing
  • Navigate menu items with arrow keys — items should be announced via speech
  • Enter a chat conversation and navigate messages
  • Press Shift+F10 on a message — context menu should open without freezing
  • Move focus to the message input field and type Korean text — characters should compose correctly without jumping or missing
  • Verify that chat list navigation still works correctly after the changes
  • Test without a braille display to ensure no regressions

🤖 Generated with Claude Code

- Add KakaoUIABase overlay that disables _prefetchUIACacheForPropertyIDs
  for all KakaoTalk UIA objects, preventing buildUpdatedCache() from
  blocking the NVDA main thread for 8-22 seconds
- Add KakaoBrailleSuppressed overlay for context menu objects (EVA_Menu)
  that skips braille.handler.handleGainFocus() to avoid querying 15+
  UIA properties via COM during menu display
- Add KakaoTalkMessageEdit overlay for message input field (RICHEDIT50W)
  that suppresses braille and IAccessible events causing Korean IME
  character composition breakage
- Add event_inputComposition handler to suppress Korean IME composition
  events that trigger focus instability
- Change isGoodUIAWindow from unconditional True to a whitelist approach,
  preventing EVA_Menu from being forced into UIA mode
- Add COMError try-except guards in event_UIA_elementSelected,
  _get_states, and _get_name to prevent cascading COM failures

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@VIPPotato VIPPotato merged commit fd7195b into VIPPotato:master Feb 14, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants