-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improving FocusManager and keyboard navigation #7607
Comments
Note, current keyboard navigation was ported from WPF. It has inconveniences, but should be enough most of the time (there are still problems like TreeView). UWP has way more flexible API, so it would be nice to consider it. |
Yep, makes a lot of sense to follow UWP here.
Not really, it's kind of a pile of hack upon hack starting from the very beginning of Avalonia (before WPF was open-sourced) and is well due a refactor! |
Also: one thing that Avalonia has that UWP doesn't have is focus scopes. I'm not sure how necessary these are. |
As I see it, focus scopes help in the case of multiple windows, which I think is how they're implemented now (really only on TopLevels), but probably not really necessary since you could just redefine the scope as the root visual/top level. |
WinUI Cycle -> behaves the same Contained isn't present - but its similar to cycle except it doesn't wrap around, and I think we'd be ok to drop that. IMO it's better to cycle/wrap around than deadlock keyboard nav at the end of a container. 2- Should
|
Update: I am currently working on porting what I can of the WinUI focus manager. Since the code isn't open-sourced yet, I'm adapting the WinUI API, but recycling the existing logic that was ported from WPF - which actually seems to work well, so the WPF logic isn't a million miles away from what UWP uses - at least from my early tests implementing this. But I think the modern API will help solidify the focus APIs and make things easier moving forward - and clean up the scattered logic that currently exists. My current plan is to get the initial FocusManager changes in and then do XYFocus as a separate PR. The FocusManager changes are actually quite significant and XYFocus is complex, so I think it's best to separate them. First PR (which hopefully I'll get a PR started within the next day or so) will target:
From my above comment (now striked-out): |
Is your feature request related to a problem? Please describe.
Handling focus and keyboard navigation in Avalonia is somewhat lacking and often (when porting controls from WinUI) leads to re-inventing the wheel to get a desired behavior. Some panels implement
INavigableContainer
to try to make it easier, and there's alsoICustomKeyboardNavigation
, but these feel more like temporary solutions. They also require you to create an entirely new control to get a desired behavior. It'd be a much better solution to implement a better FocusManager and port XYFocusKeyboardNavigation over to make most of this work out of the box. There's also other things like focus type isn't preserved when moving focus scopes (launch a popup with the keyboard, and focus moves as normal pointer/programmatic focus)I've been reading the UWP docs on all this so I'm mostly raising this issue (besides starting an API spec) to see if there were plans to do this for 11.0 - as I don't want to start looking into this if there are plans already underway. Otherwise, or if nothings been started, I want to look to see how hard it would be and if successful I'll make a PR.
Looking at UWP/WinUI's API for this:
The events in FocusManager also exist in
UIElement
and are raised in the order, where UIElement bubbles up to the FocusManager.1- UIElement.LosingFocus ->FocusManager.LosingFocus
2- UIElement.GettingFocus -> FocusManager.GettingFocus
3- UIElement.LostFocus (raised by element that lost focus)
4- FocusManager.LostFocus (raised even if UIElement.LostFocus is handled)
5- UIElement.GotFocus (raised by element that received focus)
6- FocusManager.GotFocus (raised even if UIElement.GotFocus is handled)
The duplicate events in UIElement and FocusManger are to handle the case where focus changes scope from main window to a popup, since a new visual tree is created for the popup and the event bubbling wouldn't properly propagate:
https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.input.focusmanager?view=winrt-22000
More on focus:
https://github.com/MicrosoftDocs/windows-uwp/blob/docs/hub/apps/design/input/focus-navigation-programmatic.md
XYFocusKeyboardNavigation
provides an easy way to activate navigation via the keyboard arrows (or gamepad in UWP) within a specified scope, for example a grid. It can be set to Auto: inherited from a parent control, Disabled: no arrow key 2D navigation, or Enabled: use arrow keys for 2D navigation.Different strategies exist and can be set for determining how focus moves within an app
Auto
: Indicates that navigation strategy is inherited from the element's ancestors. If all ancestors have a value of Auto, the fallback strategy is Projection.NavigationDirectionDistance
: Indicates that focus moves to the element closest to the axis of the navigation direction.Projection
: Indicates that focus moves to the first element encountered when projecting the edge of the currently focused element in the direction of navigation.RectilinearDistance
: Indicates that focus moves to the closest element based on the shortest 2D distance (Manhattan metric).And for more complex navigation scenarios,
XYFocusLeft
,XYFocusRight
,XYFocusDown
, andXYFocusUp
exist to specify how XYFocus should move in the given navigation directionMore:
https://docs.microsoft.com/en-us/windows/apps/design/input/gamepad-and-remote-interactions#xy-focus-navigation-and-interaction
The text was updated successfully, but these errors were encountered: