nvda
dd8a44cf - Avoid UIA event flooding in NvDA by moving UIA event handler COM objects into c++ (#14888)

Commit
2 years ago
Avoid UIA event flooding in NvDA by moving UIA event handler COM objects into c++ (#14888) If NVDA is flooded with UI Automation events, such as textChange events from Windows consoles, NVDA may seem to freeze, and or UIA focus tracking completely stops. Description of user facing changes NVDA should remain responsive when being flooded with many UI Automation events, E.g. large amounts of text being written to a Windows console. Description of development approach Implement a new UI Automation event handler COM object in c++ which avoids calling into Python, and instead stores the events, and requests NvDA's main thread to later wake and read off the events when it can. This COM object also coalesces duplicate automation and propertyChange events for the same element, so that NVDA is no longer flooded with duplicate events, E.g. textChange events in Windows consoles. The path for a UI Automation event is now as follows: • In an MTA thread, the new c++ UIA event handler COM object receives the event via its handle*Event method from UI Automation core. • The event is stored in a list of events. • If the event type supports coalescing (automation and propertyChange events), An existing duplicate event is looked up in a map, and if one exists, the existing event is removed from the list, and the map entry is then pointed to the newest event. • If there was no existing event, a new entry is added to the map for this event. • In other words: the events are stored in the list in order they were received, but any duplicate events are removed, leaving only the latest ones. Ecentually an ordered dictionary. • If this event type does not support coalescing (E.g. focusChange event), NVDA is requested to wake and flush the event queue on its main thread as soon as it can. • If this event does support coalescing, and this is the first event since the last flush, then NVDA is requested to wake and flush the event queue in around 30 ms, giving time for more events to possibly be received and coalesced. • When NvDA wakes on its main thread, It requests the rate limited UIA event handler to flush its event list, emitting all the stored events out to our original Python UIA event handler COM object for normal handling. These changes mean that UIA core in the MTA is never blocked waiting for the Python GIL, and from its perspective, event handling is instantanious. Thus UIA core should never feel the need to kill off events, including focus change events. This pr also provides a couple of extra optimizations for UIA handling in Python: • UIAHandler events: avoid needlessly creating an NVDAObject when the event is for the focus object. • UIA event handlers: pass windowHandle into NvDAObject constructor if we already have it.
Parents
Loading