Make braille and vision follow caret in browse mode (#20465)
Closes #3287
Summary of the issue:
During say all with the caret cursor in browse mode, braille and vision framework did not follow the spoken text. The display stayed on the line where say all started, and only moved if braille happened to be tethered to review.
This happens because _CaretTextReader.updateCaret moved the caret via updater.updateCaret(). In browse mode the caret is virtual, so this does not fire an OS caret event. Braille and the vision handlers are normally notified off that event, so they were never told the caret had moved.
Description of user facing changes:
During say all in browse mode, braille and the magnifier now follow the spoken text line by line, regardless of the braille tether setting.
Description of developer facing changes:
None. No public API changes.
Description of development approach:
_CaretTextReader.updateCaret now detects cursor managers via api.isCursorManager(obj) and, for those, explicitly calls braille.handler.handleCaretMove(obj) and vision.handler.handleCaretMove(obj) after moving the caret. Objects that fire an OS caret event are left on the existing path, since that event already drives the handlers.