There seem to be a small handful of cases where we want this--controls that gain focus immediately after a dialog appears, for instance. We allow these edge cases to indicate that the next focus shouldn't stop speech, then clear it on cases where speech isn't stopped. This is a bit hacky, but seems cleaner than anything else I came up with.
This causes scrolling through trees, lists, and just about everything else where focus doesn't change to a new widget to fail. Clearly another solution is needed.
This reverts commit c459a35f0d.
* Remove indiscriminant speech stop on focus events.
* Only stop speech on input events that are keypresses.
* Don't interrupt speech when a dialog is presented.
Now dialogs present in their entirety without having their labels explicitly focused. This allows for Godot's default behavior, where the _OK_ button is automatically focused when the dialog appears, to speak the dialog text and the button as a screen reader user would expect.
Trees appear to eat "ui_accept" before `gui_input` receives it. This makes certain use cases--triggering buttons in cells--impossible via the keyboard.
Here, `ScreenReader` attempts to intercept recent presses of "ui_accept" and, if a button in a cell should receive focus, redirects the `InputEvent` to the custom handler for `Tree`.
Unfortunately, this loses the ability to click buttons in cells in the editor's node tree for some reason. It restores, or maybe gets working in the first place, clicking on the _Remove_ button in the input mapping screen. Not sure how to restore the former functionality--these trees are complex and not well-documented.
* Labels themselves don't have labels, so `guess_label()` on a `Label` returns null.
* Remove unused `is_in_bar()` function.
* Prepend `_` to more private function names.
* Don't manipulate selection in any way. Leave that to Godot, and I'll fix issues in the engine if needed.
* Unify speech rendering of tree rows. This results in more useful announcements of buttons and such when tree items receive focus.
* Only handle `ui_up` and `ui_down` to ensure that focus won't leave a tree when the top-most or bottom-most row is arrowed past.
* Add a bit of handling to strip out duplicate collapse/focus events generated by the remote `SceneTree` in an active game.
`Accessible` is now a child of its `Control`. This helps to ensure that everything gets cleaned up as it should. Further, node additions no longer scrape the entire scene.
This may introduce regressions and has only been lightly tested, but without it, `ScreenReader` leaked in various circumstances, including some that caused segfaults on exit.
On one hand, it's a bit confusing that UIs can be arrowed around independently of tab/shift-tab. Arrow navigation doesn't feel as intuitive, as it isn't obvious where you'll land.
On the other, it's quicker to navigate between areas of the editor UI by arrowing up/down between controls, and may solve the issue of having to tab a million times to traverse all controls. This also allows for in-game UIs to be traversed using arrows and, quite probably, gamepads as well.
This eliminates the need to track and iterate through a separate array of `Accessible`s in `ScreenReader`.
The previous performance issues are resolved by ensuring that any nodes processed aren't children of the `ScreenReader` node. I don't know of another way to avoid triggering signals on a child node than checking ancestry and failing fast.
Tested with `HSlider` and has basic support for other widget types, but I'm only adding support for what I'm immediately using or can access via the editor.
This can barely be called "support." It reads all text as a single block. I'd like to at least be able to unfocus the `TextEdit`, but it's going to require a custom key. Ctrl-tab and Ctrl-shift-tab seem like good candidates, but the editor grabs those already.