Commit Graph

10 Commits

Author SHA1 Message Date
Alice Cecile
ff5b63426a
Beef up the InputFocusVisible docs (#16889)
# Objective

The docs for InputFocusVisible could do a better job explaining how the
resource is intended to be used.

## Solution

Add more detail and do an editing pass. Link to the `IsFocused` trait
for breadcrumbs too.
2024-12-18 23:22:16 +00:00
Alice Cecile
d8796ae8b6
Polish and improve docs for bevy_input_focus (#16887)
# Objective

`bevy_input_focus` needs some love before we ship it to users. There's a
few missing helper methods, the docs could be improved, and `AutoFocus`
should be more generally available.

## Solution

The changes here are broken down by commit, and should generally be
uncontroversial. The ones to focus on during review are:

- Make navigate take a & InputFocus argument: this makes the intended
pattern clearer to users
- Remove TabGroup requirement from `AutoFocus`: I want auto-focusing
even with gamepad-style focus navigation!
- Handle case where tab group is None more gracefully: I think we can
try harder to provide something usable, and shouldn't just fail to
navigate

## Testing

The `tab_navigation` example continues to work.
2024-12-18 20:29:26 +00:00
Alice Cecile
b9123e74b6
Generalize bubbling focus input events to other kinds of input (#16876)
# Objective

The new `bevy_input_focus` crates has a tool to bubble input events up
the entity hierarchy, ending with the window, based on the currently
focused entity. Right now though, this only works for keyboard events!

Both `bevy_ui` buttons and `bevy_egui` should hook into this system
(primarily for contextual hotkeys), and we would like to drive
`leafwing_input_manager` via these events, to help resolve longstanding
pain around "absorbing" / "consuming" inputs based on focus. In order to
make that work properly though, we need gamepad support!

## Solution

The logic backing this has been changed to be generic for any cloneable
event types, and the machinery to make use of this externally has been
made `pub`.

Within the engine itself, I've added support for gamepad button and
scroll events, but nothing else. Mouse button / touch bubbling is
handled via bevy_picking, and mouse / gamepad motion doesn't really make
sense to bubble.

## Testing

The `tab_navigation` example continues to work, and CI is green.

## Future Work

I would like to add more complex UI examples to stress test this, but
not here please.

We should take advantage of the bubbled mouse scrolling when defining
scrolled widgets.
2024-12-18 01:04:50 +00:00
Alice Cecile
e55f0e74ea
Document input focus helper methods (#16875)
# Objective

I am suspicious of the command / world helpers for input focus, since
they just provide a trivial helper for setting a resource value.

## Solution

Document that there's nothing magic about them. These can live another
day, but I would also remove them completely if y'all convince me it's
the right choice.
2024-12-18 00:16:39 +00:00
Alice Cecile
fa6cabd432
Replace bevy_a11y::Focus with InputFocus (#16863)
# Objective

Bevy now has first-class input focus handling! We should use this for
accessibility purpose via accesskit too.

## Solution

- Removed bevy_a11y::Focus.
- Replaced all usages of Focus with InputFocus
- Changed the dependency tree so bevy_a11y relies on bevy_input_focus
- Moved initialization of the focus (starts with the primary window)
from bevy_window to bevy_input_focus to avoid circular dependencies (and
it's cleaner)

## Testing

TODO

## Migration Guide

`bevy_a11y::Focus` has been replaced with `bevy_input_focus::Focus`.
2024-12-18 00:16:19 +00:00
Winds
6ca1e756dc
Expose text field from winit in KeyboardInput (#16864)
# Objective

Allow handling of dead keys on some keyboard layouts.

In some cases, dead keys were impossible to get using the
`KeyboardInput` event. This information is already present in the
underlying winit `KeyEvent`, but it wasn't exposed.

## Solution

Expose the `text` field from winit's `KeyEvent` in `KeyboardInput`.

This logic is inspired egui's implementation here:
adfc0bebfc/crates/egui-winit/src/lib.rs (L790-L807)

## Testing

This is a new field, so it shouldn't break any existing functionality. I
tested that this change works by running the modified `text_input`
example on different keyboard layouts.

## Example

Using a Portuguese/ABNT2 keyboard layout on windows and pressing
<kbd>\~</kbd> followed by
<kbd>a</kbd>/<kbd>Space</kbd>/<kbd>d</kbd>/<kbd>\~</kbd> now generates
the following events:
```
KeyboardInput { key_code: Quote, logical_key: Dead(Some('~')), state: Pressed, text: None, repeat: false, window: 0v1#4294967296 }
KeyboardInput { key_code: KeyA, logical_key: Character("ã"), state: Pressed, text: Some("ã"), repeat: false, window: 0v1#4294967296 }

KeyboardInput { key_code: Quote, logical_key: Dead(Some('~')), state: Pressed, text: None, repeat: false, window: 0v1#4294967296 }
KeyboardInput { key_code: Space, logical_key: Space, state: Pressed, text: Some("~"), repeat: false, window: 0v1#4294967296 }

KeyboardInput { key_code: Quote, logical_key: Dead(Some('~')), state: Pressed, text: None, repeat: false, window: 0v1#4294967296 }
KeyboardInput { key_code: KeyD, logical_key: Character("d"), state: Pressed, text: Some("~d"), repeat: false, window: 0v1#4294967296 }

KeyboardInput { key_code: Quote, logical_key: Dead(Some('~')), state: Pressed, text: None, repeat: false, window: 0v1#4294967296 }
KeyboardInput { key_code: Quote, logical_key: Dead(Some('~')), state: Pressed, text: Some("~~"), repeat: false, window: 0v1#4294967296 }
```

The logic for getting an input is pretty simple: check if `text` is
`Some`. If it is, this is actual input text, otherwise it isn't.

There's a small caveat: certain keys generate control characters in the
input text, which needs to be filtered out:
```
KeyboardInput { key_code: Escape, logical_key: Escape, state: Pressed, text: Some("\u{1b}"), repeat: false, window: 0v1#4294967296 }
```

I've updated the text_input example to include egui's solution to this,
which works well.

## Migration Guide

The `KeyboardInput` event now has a new `text` field.
2024-12-17 22:42:54 +00:00
Talin
5c67cfc8b7
Tab navigation framework for bevy_input_focus. (#16795)
# Objective

This PR continues the work of `bevy_input_focus` by adding a pluggable
tab navigation framework.

As part of this work, `FocusKeyboardEvent` now propagates to the window
after exhausting all ancestors.

## Testing

Unit tests and manual tests.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-12-16 23:54:53 +00:00
Erick Z
ced6159d93
Improve bevy_input_focus (#16749)
# Objective

I was curious to use the newly created `bevy_input_focus`, but I found
some issues with it
  - It was only implementing traits for `World`.
  - Lack of tests
  - `is_focus_within` logic was incorrect.


## Solution
 This PR includes some improvements to the `bevy_input_focus` crate: 
- Add new `IsFocusedHelper` that doesn't require access to `&World`. It
implements `IsFocused`
- Remove `IsFocused` impl for `DeferredWorld`. Since it already
implements `Deref<Target=World>` it was just duplication of code.
- impl `SetInputFocus` for `Commands`. There was no way to use
`SetFocusCommand` directly. This allows it.
- The `is_focus_within` logic has been fixed to check descendants.
Previously it was checking if any of the ancestors had focus which is
not correct according to the documentation.
  - Added a bunch of unit tests to verify the logic of the crate.

## Testing

- Did you test these changes? If so, how? Yes, running newly added unit
tests.

---
2024-12-12 19:15:08 +00:00
Talin
bc572cd270
bevy_input_focus improvements (follow-up PR) (#16665)
This adds a few minor items which were left out of the previous PR:

- Added synchronization from bevy_input_focus to bevy_a11y.
- Initialize InputFocusVisible resource.
- Make `input_focus` available from `bevy` module.

I've tested this using VoiceOver on Mac OS. It works, but it needs
considerable polish.
2024-12-06 01:16:52 +00:00
Talin
ea33fc04ab
Add "bevy_input_focus" crate. (#15611)
# Objective

Define a framework for handling keyboard focus and bubbled keyboard
events, as discussed in #15374.

## Solution

Introduces a new crate, `bevy_input_focus`. This crate provides:

* A resource for tracking which entity has keyboard focus.
* Methods for getting and setting keyboard focus.
* Event definitions for triggering bubble-able keyboard input events to
the focused entity.
* A system for dispatching keyboard input events to the focused entity.

This crate does *not* provide any integration with UI widgets, or
provide functions for
tab navigation or gamepad-based focus navigation, as those are typically
application-specific.

## Testing

Most of the code has been copied from a different project, one that has
been well tested. However, most of what's in this module consists of
type definitions, with relatively small amounts of executable code. That
being said, I expect that there will be substantial bikeshedding on the
design, and I would prefer to hold off writing tests until after things
have settled.

I think that an example would be appropriate, however I'm waiting on a
few other pending changes to Bevy before doing so. In particular, I can
see a simple example with four buttons, with focus navigation between
them, and which can be triggered by the keyboard.

@alice-i-cecile
2024-12-05 18:08:31 +00:00