AvaloniaUI / Avalonia

Develop Desktop, Embedded, Mobile and WebAssembly apps with C# and XAML. The most popular .NET UI client technology
https://avaloniaui.net
MIT License
26.09k stars 2.26k forks source link

SplitView open overlay pane doesn't properly obscure/clip controls for XYFocus navigation #14985

Open IanRawley opened 8 months ago

IanRawley commented 8 months ago

Describe the bug

When a SplitView is set to CompactOverlay mode and the pane opened, controls either partially or fully obscured by the pane are still considered as candidates for XYFocus navigation based on their full bounds, not the visible portion. This leads to attempting navigation between controls within the pane selecting controls hidden under it in preference to fully visible but more distance controls in the same axis.

To Reproduce

  1. Clone this repository. This provides a representative environment from an app I'm working on.
  2. Using only XY navigation, try to navigate around the pane. For example navigating Up from the toggle switch or button at the bottom will select the last Textbox in the main view rather than the Settings or Save buttons. Navigating Right from the Data button selects the first Textbox rather than the HOME button, etc.

Expected behavior

The part of a control's bounds hidden under a SplitView overlay are ignored for the purposes of XY Navigation.

Avalonia version

11.1.0-beta1

OS

Windows, Android

Additional context

This is especially troublesome when the obscured control is a ListBox, as then the ListBox handles all the arrow key navigation and effectively traps keyboard focus within it. The documentation suggests that's a known issue, and on the To-Do list somewhere at least.

IanRawley commented 8 months ago

I've been trying to dig into why, and the only lead I've come up with so far is that XYFocusOptions sets IgnoreClipping to true by default.

IanRawley commented 8 months ago

As an aside, is there any way to restrict XYFocus to within controls like there is with Tab navigation by setting KeyboardNavigation.TabNavigation="Contained"?

maxkatz6 commented 8 months ago

As an aside, is there any way to restrict XYFocus to within controls like there is with Tab navigation by setting KeyboardNavigation.TabNavigation="Contained"?

You can set XYFocus,NavigationModes only on specific subtree. https://docs.avaloniaui.net/docs/concepts/input/focus#directional-focus-navigation-

We still need to implement some kind of focus engagement, as it was in UWP, to simplify "inner loops of focus": https://learn.microsoft.com/en-us/windows/apps/design/input/gamepad-and-remote-interactions#focus-engagement

But tab navigation concepts in general can't be applied as much, since user only has limited number of controls - arrow keys, space (enter) and escape (back button).

IanRawley commented 8 months ago

As an aside, is there any way to restrict XYFocus to within controls like there is with Tab navigation by setting KeyboardNavigation.TabNavigation="Contained"?

You can set XYFocus,NavigationModes only on specific subtree. https://docs.avaloniaui.net/docs/concepts/input/focus#directional-focus-navigation-

We still need to implement some kind of focus engagement, as it was in UWP, to simplify "inner loops of focus": https://learn.microsoft.com/en-us/windows/apps/design/input/gamepad-and-remote-interactions#focus-engagement

But tab navigation concepts in general can't be applied as much, since user only has limited number of controls - arrow keys, space (enter) and escape (back button).

Right, Focus Engagement would help with the ListBox issue.

I maybe didn't word things so well. When I said Restrict, it was in the temporary sense of while within a particular tree. I want everything to be XY navigable overall. However at the moment the DialogHost controls I use don't stop XYFocus from selecting controls outside the dialog to focus, making them a bit awkward to use. Previously, when I was hacking things together to work with Tab navigation it was a simple matter of setting "Contained" on the dialog tree and ensuring focus got into it with a way to close the dialog. Is there a simple equivalent, or am I going to have to programmatically turn XYFocus on and off on the main view whenever a dialog opens or closes?