Skip to content

V2 of External win event limiter - #20653

Open
codeofdusk wants to merge 5 commits into
nvaccess:masterfrom
codeofdusk:externalWinEventLimiter
Open

V2 of External win event limiter#20653
codeofdusk wants to merge 5 commits into
nvaccess:masterfrom
codeofdusk:externalWinEventLimiter

Conversation

@codeofdusk

Copy link
Copy Markdown
Contributor

Link to issue number:

Supersedes #10556.

Summary of the issue:

There is some suspicion that NVDA may be missing some events by not handling windows events callbacks fast enough. Not only this, but processing and queuing events takes up time on the main thread when it isn't necessary to do so.

Description of how this pull request fixes the issue:

This PR modernizes the external winEvent limiter first developed experimentally in 2019 by @feerrenrut. When enabled, winEventLimiter.dll receives, preprocesses and limits winEvents outside NVDA's main Python event loop. NVDA then fetches the surviving events in chronological order during its normal core pump.

The external limiter is disabled by default. It can be enabled from the new "Microsoft Active Accessibility" group in the Advanced settings panel. If the DLL cannot be loaded or started, NVDA falls back to its existing internal winEvent hooks.

This PR also:

  • Renames the native component from eventHandler to winEventLimiter. This avoids a name collision with NVDA's Python eventHandler module;
  • Updates the component for NVDA's current build environment: the Visual Studio projects target v145 and x64, SCons builds and signs the DLL for the applicable NVDA core architectures;
  • Fixes an uninitialized notifier state that could prevent NVDA from being notified of new events;
  • Fixes show/hide cancellation, which previously invalidated the newly added event instead of its opposite;
  • Restores reliable focus reporting by retaining up to four focus candidates and returning events chronologically. This lets pumpAll try the newest valid focus candidate without producing reverse-order focus speech;
  • Makes duplicate events move forward in time and applies the per-thread limit at flush time, matching the internal limiter's semantics;
  • Processes destroy events on NVDA's main thread. They are buffered separately, fetched before focus is captured, and handled before regular events. If destroy events must be discarded, NVDA invalidates the affected object cache conservatively;
  • Bounds native event queues at MAX_BUFFERED_EVENTS. On overflow, queues are trimmed toward half capacity, discarding older generic events first and preferentially retaining focus, foreground, destroy, and focused-object events;
  • Cleans up partial initialization, balances successful COM initialization, invalidates callbacks before stopping threads and resets all module state so the DLL can be started again after being stopped;
  • Hooks only the event IDs supported by current NVDA, preventing unsupported EVENT_OBJECT_REORDER events from reaching pumpAll;
  • Exempts events for the focused object from the per-thread limit via winEventLimiter_setAlwaysAllowedObject (Don't filter out MSAA events for the currently focused object, even if the winEvent limit has been exceeded for that thread #11520);
  • Records the true thread ID for ConsoleWindowClass windows and exposes it through winEventLimiter_getConsoleThreadID for both console NVDAObject implementations (Speak typed characters in Windows consoles in the correct language (second try) #10554);
  • Ignores UIA-proxied EXCEL7 winEvents (Ignore redundant winEvents proxied from UIA on EXCEL7 windows #11818);
  • Removes obsolete Mozilla-specific transformations (Clean up Mozilla specific code #11120);
  • Fetches complete flushed batches and requests an immediate core pump for focus events (Improve responsiveness of input and focus by pumping immediately instead of after a delay. #14928).

Testing strategy:

Manually tested for several weeks in a running copy of NVDA, including Chrome, Edgium, Firefox, and various MSAA applications. The external limiter is behind a feature flag and has no impact on the running NVDA when disabled (default behaviour) to allow for wider testing.

Automated testing:

  • A new runcxxtests.bat: event ordering and limiting, focus handling, duplicate and show/hide semantics, notifications, buffer overflow, destroy-event recovery and current pipeline parity.
    • A new cxxUnitTests CI job runs the native tests.
  • rununittests.bat -k test_externalWinEventLimiter: event fetching and injection, main-thread destroy processing, fallback behaviour, lifecycle handling, console thread lookup, focus ordering, and feature-flag handling.

Known issues with pull request:

None known.

Code Review Checklist:

  • Documentation:
    • Change log entry
    • User Documentation
    • Developer / Technical Documentation
    • Context sensitive help for GUI changes
  • Testing:
    • Unit tests
    • System (end to end) tests
    • Manual testing
  • UX of all users considered:
    • Speech
    • Braille
    • Low Vision
    • Different web browsers
    • Localization in other languages / culture than English
  • API is compatible with existing add-ons.
  • Security precautions taken.

@codeofdusk
codeofdusk force-pushed the externalWinEventLimiter branch 3 times, most recently from 89b8c5b to bccf41e Compare August 13, 2026 13:34
@codeofdusk
codeofdusk force-pushed the externalWinEventLimiter branch from bccf41e to be31555 Compare August 13, 2026 14:07
@codeofdusk
codeofdusk marked this pull request as ready for review August 13, 2026 14:42
Copilot AI lite review requested due to automatic review settings August 13, 2026 14:42
@codeofdusk
codeofdusk requested review from a team as code owners August 13, 2026 14:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

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.

3 participants