nvda
675efe05 - Optimize Highlighter performance using dirty rectangles. (#19344)

Commit
59 days ago
Optimize Highlighter performance using dirty rectangles. (#19344) Fixed: #17434 ### Summary of the issue: Previously, we called `InvalidateRect` every 100 milliseconds to refresh the entire window. This caused `dwm.exe` to perform extensive calculations, resulting in high GPU or CPU utilization—particularly noticeable on low-performance machines. ### Description of user facing changes: Enabling the highlighter does not cause `dwm.exe` to consume excessive resources continuously, especially when no objects are being updated. ### Description of developer facing changes: * **Type Hinting Improvements:** Updated type hints across `autoSettings.py`, `mouseHandler.py`, and `NVDAHighlighter.py` to use modern Python syntax (e.g., standard collection generics like `list[...]` instead of `typing.List`, and `type` aliases). Added `override` decorators where appropriate. * **Formatting import** Use ruff to format import statement. * **NVDAHighlighter Refactor:** * `HighlightStyle` is now a `NamedTuple` with explicit type annotations. * Refactored `HighlightWindow` to separate logic for coordinate mapping (`_mapRectToClient`) and determining draw targets (`_getDrawRects`). * Introduced state tracking (`_prevContextRects`) to the highlighter window to facilitate delta updates. ### Description of development approach: To address the performance issue with `dwm.exe`: 1. **Dirty Rectangle Invalidation:** Instead of blindly invalidating the entire screen overlay window every refresh cycle (`InvalidateRect(..., None, ...)`), the approach was changed to calculate specific "dirty" regions. 2. **State Tracking:** The `HighlightWindow` now caches the rectangles rendered in the previous frame. 3. **Delta Calculation:** During `refresh()`: * The current required rectangles are calculated. * They are compared with the cached previous state. * If a context's rectangle has changed or was removed, the **old** screen region is invalidated (to clear the artifact). * If a context's rectangle is new or changed, the **new** screen region is invalidated (to draw the new highlight). 4. **Region Calculation:** A helper method `_invalidateContextRect` maps the logical object rectangle to client coordinates and adds necessary padding (accounting for the pen width and anti-aliasing) to ensure the invalidation rect covers the entire visual drawing. This minimizes the surface area that the Windows DWM needs to recompose, drastically reducing GPU/CPU usage. ### Testing strategy: Manual Testing: 1. Build and install the self-signed launcher. 2. Enable the highlighter tool and move the focus to check for drawing errors. (especially drawn on the start menu)
Author
Parents
Loading