Avoid unnecessary sleep when handling caret movement to improve responsiveness. (#14708)
NVDA frequently takes 30 to 45 ms to respond to cursor movement (arrow keys, etc.) in a text box. This doesn't seem like much, but anything we can do to improve responsiveness here makes for a better experience for the user.
Description of user facing changes
NVDA responds faster when moving the cursor in edit controls.
Description of development approach
1. Don't sleep or yield in KeyboardInputGesture.send. We sleep for 10 ms, which is at the upper end of acceptable audio latency for "instantaneous". Furthermore, the Windows timer resolution is only accurate to about 15.6 ms most of the time.
This sleep was apparently added to ensure NVDA's keyboard hook ignored the injected keys. In my testing, removing this didn't seem to have any negative impact. If this does turn out to be a problem, we could watch for the last injected key in the keyboard event hook and fire a Windows event when it arrives. This will be faster to wake than a 10-16 ms sleep.
2. When waiting for caret movement, spin the first few tries rather than sleeping. Again, we might sleep longer than we need to and sometimes apps respond much faster than we previously allowed for. Spinning for a very short while improves responsiveness without excessive resource usage.
3. The caret movement waiting code was also refactored a bit to better calculate the elapsed time. We were previously relying on multiplying the sleep amount, which was inaccurate because sleep is inaccurate. For example, if we retried 3 times with a 10 ms retry interval, we would report 30 ms elapsed. However, each 10 ms could have been up to 16 ms in reality, resulting an actual elapsed time of 48 ms. It also didn't account for the time it took to query the control. Now we use the system clock to measure the elapsed time.
4. Increase the use events timeout from 10 ms to 60 ms. As noted in 3), we were previously multiplying the sleep amount, which meant our supposed elapsed time was actually less than what had truly elapsed. This just updates the timeout to reflect reality. Without this, backspacing occasionally failed in UIA Notepad and the search box in File Explorer.
Note that this does alter some class variables in EditableText. However, these were private (underscore prefixed), so I don't think this should be considered API breaking.