Open philippeitis opened 2 years ago
Thank you for the thorough post. I'm actually rewriting a few things right now that might make focusing easier to do than it currently is. Specifically I'm rewriting the hooks system, and how reactive rendering works. Right now any state change will trigger a full re-render, even if component properties haven't changed. I'm trying to make it such that only the component whose state has changed is re-rendered. It's probably going to take me at least a few weeks, and so I probably won't be able to go through your post in detail until then.
Sure, that's fine with me. To support partial re-rendering, it seems like you'd need to be able to pass messages from the modified widget to the containing widget and neighboring widgets, since changes to the widget content might affect the layout for flex widgets.
If you implement support for child elements sending messages to parent widgets, that should be a big part of what the focus system needs to work, since it would allow a child widget to send key-events (and focus-switching events) to the parent widget.
I'm taking most of my inspiration from this document: https://docs.flutter.dev/development/ui/advanced/focus
Essentially, they describe a system of focus handling as follows:
TAB
To implement this functionality, two key requirements stand out:
Option<FocusTree>
- and recursively builds the focus treeWe can either use Rc / Weak style references, or track IDs which correspond to each focus node:
I think that tracking IDs is the best/simplest solution, though it requires some consideration W.R.T. concurrency.
Focus hook system:
Trait based focus tree:
Bubbling approach to handling key events:
The snippets I've outlined allow describing the focus tree (explicit) / focus chain (implicit), active focus node (explicit).
The focus scope is relatively easy to implement, as a plain focus node. Focus traversal could be done using the focus tree and visiting parents in order of increasing ID - again, certain implementation details would need to be figured out, but this should be doable.
Again - I'd be happy to implement this, but I'd like to get an idea for what overall design you think is best before I go ahead and implement this functionality. I should be able to implement an MVP relatively quickly - likely under an
experimental_components::focus
module.