提交 109a5729 编写于 作者: M Martin Zikmund

fix: Enable When_VerifyEnabledXYKeyboardNavigation in Uno Islands

上级 9b795df0
......@@ -50,6 +50,13 @@ namespace Windows.UI.Xaml.Tests.MUXControls.ApiTests.RepeaterTests
return;
}
#if HAS_UNO
if (TestServices.WindowHelper.IsXamlIsland)
{
return;
}
#endif
ItemsRepeater repeater = null;
ScrollViewer scrollViewer = null;
var data = new ObservableCollection<string>(Enumerable.Range(0, 50).Select(i => "Item #" + i));
......
......@@ -47,7 +47,7 @@ public class Given_UnoFocusInputHandler
centerButton.Focus(FocusState.Programmatic);
var inputHandler = new UnoFocusInputHandler(VisualTree.GetRootForElement(centerButton));
var inputHandler = new UnoFocusInputHandler(VisualTree.GetRootOrIslandForElement(centerButton));
var result = inputHandler.TryHandleDirectionalFocus(key);
Assert.AreEqual(shouldSucceed, result);
......
......@@ -37,12 +37,8 @@ namespace Windows.UI.Xaml.Input
}
}
private static bool InIslandsMode()
{
//TODO Uno: Islands mode should be applied for "WinUI" mode as it limits some APIs for
//multi-window use. For now choosing not limiting.
return false;
}
// TODO Uno: This should probably apply to multi-window as well #8341.
private static bool InIslandsMode() => CoreServices.Instance.InitializationType == InitializationType.IslandsOnly;
private static object? FindNextFocus(
FocusNavigationDirection focusNavigationDirection,
......@@ -54,7 +50,7 @@ namespace Windows.UI.Xaml.Input
}
var core = DXamlCore.Current;
if (core == null)
if (core is null)
{
throw new InvalidOperationException("XamlCore is not set.");
}
......@@ -77,7 +73,7 @@ namespace Windows.UI.Xaml.Input
var contentRootCoordinator = core.GetHandle().ContentRootCoordinator;
var contentRoot = contentRootCoordinator?.CoreWindowContentRoot;
if (contentRoot == null)
if (contentRoot is null)
{
return null;
}
......@@ -85,7 +81,7 @@ namespace Windows.UI.Xaml.Input
focusManager = contentRoot.FocusManager;
}
if (focusManager == null)
if (focusManager is null)
{
return null;
}
......
......@@ -5,127 +5,126 @@ using Windows.System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Input;
namespace Uno.UI.Xaml.Input
namespace Uno.UI.Xaml.Input;
internal class UnoFocusInputHandler
{
internal class UnoFocusInputHandler
{
private readonly RootVisual _rootVisual;
private readonly UIElement _rootElement;
private bool _isShiftDown;
private bool _isShiftDown;
public UnoFocusInputHandler(UIElement rootElement)
{
_rootElement = rootElement;
_rootElement.KeyDown += OnKeyDown;
_rootElement.KeyUp += OnKeyUp;
}
public UnoFocusInputHandler(RootVisual rootVisual)
private void OnKeyUp(object sender, KeyRoutedEventArgs e)
{
if (e.OriginalKey == VirtualKey.Shift ||
e.OriginalKey == VirtualKey.LeftShift ||
e.OriginalKey == VirtualKey.RightShift)
{
_rootVisual = rootVisual;
_rootVisual.KeyDown += OnKeyDown;
_rootVisual.KeyUp += OnKeyUp;
_isShiftDown = false;
}
}
private void OnKeyUp(object sender, KeyRoutedEventArgs e)
private void OnKeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.OriginalKey == VirtualKey.Shift ||
e.OriginalKey == VirtualKey.LeftShift ||
e.OriginalKey == VirtualKey.RightShift)
{
if (e.OriginalKey == VirtualKey.Shift ||
e.OriginalKey == VirtualKey.LeftShift ||
e.OriginalKey == VirtualKey.RightShift)
{
_isShiftDown = false;
}
_isShiftDown = true;
}
private void OnKeyDown(object sender, KeyRoutedEventArgs e)
if (e.Handled)
{
if (e.OriginalKey == VirtualKey.Shift ||
e.OriginalKey == VirtualKey.LeftShift ||
e.OriginalKey == VirtualKey.RightShift)
{
_isShiftDown = true;
}
if (e.Handled)
{
return;
}
return;
}
if (e.OriginalKey == VirtualKey.Tab)
{
e.Handled = TryHandleTabFocus(_isShiftDown);
}
if (e.OriginalKey == VirtualKey.Tab)
{
e.Handled = TryHandleTabFocus(_isShiftDown);
}
if (e.OriginalKey == VirtualKey.Up ||
e.OriginalKey == VirtualKey.Down ||
e.OriginalKey == VirtualKey.Left ||
e.OriginalKey == VirtualKey.Right)
{
e.Handled = TryHandleDirectionalFocus(e.OriginalKey);
}
if (e.OriginalKey == VirtualKey.Up ||
e.OriginalKey == VirtualKey.Down ||
e.OriginalKey == VirtualKey.Left ||
e.OriginalKey == VirtualKey.Right)
{
e.Handled = TryHandleDirectionalFocus(e.OriginalKey);
}
}
internal bool TryHandleTabFocus(bool isShiftDown)
internal bool TryHandleTabFocus(bool isShiftDown)
{
var direction = isShiftDown ? FocusNavigationDirection.Previous : FocusNavigationDirection.Next;
var contentRoot = VisualTree.GetContentRootForElement(_rootElement);
if (contentRoot == null)
{
var direction = isShiftDown ? FocusNavigationDirection.Previous : FocusNavigationDirection.Next;
var contentRoot = VisualTree.GetContentRootForElement(_rootVisual);
if (contentRoot == null)
{
return false;
}
return false;
}
contentRoot.InputManager.LastInputDeviceType = InputDeviceType.Keyboard;
contentRoot.InputManager.LastInputDeviceType = InputDeviceType.Keyboard;
var focusManager = VisualTree.GetFocusManagerForElement(_rootVisual);
var focusMovement = new FocusMovement(XYFocusOptions.Default, direction, null);
focusMovement.IsShiftPressed = _isShiftDown;
focusMovement.IsProcessingTab = true;
var result = focusManager?.FindAndSetNextFocus(focusMovement);
return result?.WasMoved == true;
}
var focusManager = VisualTree.GetFocusManagerForElement(_rootElement);
var focusMovement = new FocusMovement(XYFocusOptions.Default, direction, null);
focusMovement.IsShiftPressed = _isShiftDown;
focusMovement.IsProcessingTab = true;
var result = focusManager?.FindAndSetNextFocus(focusMovement);
return result?.WasMoved == true;
}
internal bool TryHandleDirectionalFocus(VirtualKey originalKey)
internal bool TryHandleDirectionalFocus(VirtualKey originalKey)
{
var contentRoot = VisualTree.GetContentRootForElement(_rootElement);
if (contentRoot == null)
{
var contentRoot = VisualTree.GetContentRootForElement(_rootVisual);
if (contentRoot == null)
{
return false;
}
contentRoot.InputManager.LastInputDeviceType = InputDeviceType.Keyboard;
var focusManager = VisualTree.GetFocusManagerForElement(_rootVisual);
var focusDirection = FocusSelection.GetNavigationDirectionForKeyboardArrow(originalKey);
return false;
}
contentRoot.InputManager.LastInputDeviceType = InputDeviceType.Keyboard;
if (focusManager == null || focusDirection == FocusNavigationDirection.None)
{
return false;
}
var focusManager = VisualTree.GetFocusManagerForElement(_rootElement);
var focusDirection = FocusSelection.GetNavigationDirectionForKeyboardArrow(originalKey);
var source = focusManager.FocusedElement; // Uno specific: This should actually bubble up with the event from the source element to the root visual.
if (focusManager == null || focusDirection == FocusNavigationDirection.None)
{
return false;
}
var directionalFocusEnabled = false;
var focusCandidateFound = false;
bool handled = false;
while (source != null && !focusCandidateFound)
{
var directionalFocusInfo = FocusSelection.TryDirectionalFocus(focusManager, focusDirection, source);
handled |= directionalFocusInfo.Handled;
var source = focusManager.FocusedElement; // Uno specific: This should actually bubble up with the event from the source element to the root visual.
focusCandidateFound |= directionalFocusInfo.FocusCandidateFound;
directionalFocusEnabled |= directionalFocusInfo.DirectionalFocusEnabled;
var directionalFocusEnabled = false;
var focusCandidateFound = false;
bool handled = false;
while (source != null && !focusCandidateFound)
{
var directionalFocusInfo = FocusSelection.TryDirectionalFocus(focusManager, focusDirection, source);
handled |= directionalFocusInfo.Handled;
if (!directionalFocusInfo.ShouldBubble)
{
break;
}
focusCandidateFound |= directionalFocusInfo.FocusCandidateFound;
directionalFocusEnabled |= directionalFocusInfo.DirectionalFocusEnabled;
if (!focusCandidateFound)
{
source = source.GetParent() as DependencyObject;
}
if (!directionalFocusInfo.ShouldBubble)
{
break;
}
// Only raise NoFocusCandidateFound if XYDirectionalFocus was ever set to enabled and a
// focus candidate was never found.
if (directionalFocusEnabled && !focusCandidateFound)
if (!focusCandidateFound)
{
focusManager.RaiseNoFocusCandidateFoundEvent(focusDirection);
source = source.GetParent() as DependencyObject;
}
}
return handled;
// Only raise NoFocusCandidateFound if XYDirectionalFocus was ever set to enabled and a
// focus candidate was never found.
if (directionalFocusEnabled && !focusCandidateFound)
{
focusManager.RaiseNoFocusCandidateFoundEvent(focusDirection);
}
return handled;
}
}
......@@ -83,9 +83,9 @@ namespace Uno.UI.Xaml.Core
RootVisual.AssociatedVisualTree = this;
RootVisual.SetBackgroundColor(backgroundColor);
RootElement = RootVisual;
_focusInputHandler = new UnoFocusInputHandler(RootVisual);
}
_focusInputHandler = new UnoFocusInputHandler(RootElement);
}
internal UnoFocusInputHandler? UnoFocusInputHandler => _focusInputHandler;
......@@ -352,10 +352,8 @@ namespace Uno.UI.Xaml.Core
/// </summary>
/// <param name="pObject">Element.</param>
/// <returns>Root visual or null.</returns>
internal static RootVisual? GetRootForElement(DependencyObject? pObject)
{
return pObject?.GetContext().MainRootVisual;
}
internal static RootVisual? GetRootForElement(DependencyObject? pObject) =>
VisualTree.GetForElement(pObject)?.RootVisual;
/// <summary>
/// Static helper function that encapsulates getting the FocusManager
......
......@@ -525,7 +525,7 @@ namespace Windows.UI.Xaml
internal Rect GetGlobalBoundsLogical(bool ignoreClipping = false, bool useTargetInformation = false)
{
//TODO Uno specific: This implementation is significantly simplified from the actual WinUI implementation.
var rootVisual = VisualTree.GetRootForElement(this);
var rootVisual = VisualTree.GetRootForElement(this) ?? VisualTree.GetRootOrIslandForElement(this);
if (rootVisual == null)
{
return Rect.Empty;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册