Skip to content

Commit

Permalink
feat(FocusVisuals): SystemFocusVisual control
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinZikmund committed Apr 20, 2021
1 parent b70c4f4 commit 66293ac
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 0 deletions.
24 changes: 24 additions & 0 deletions src/Uno.UI/UI/Xaml/Controls/FocusVisual/SystemFocusVisual.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace Uno.UI.Xaml.Controls
{
public partial class SystemFocusVisual : Control
{
public SystemFocusVisual()
{
DefaultStyleKey = typeof(SystemFocusVisual);
}

protected override void OnApplyTemplate() => base.OnApplyTemplate();

public FrameworkElement FocusedElement
{
get => (FrameworkElement)GetValue(FocusedElementProperty);
set => SetValue(FocusedElementProperty, value);
}

public static readonly DependencyProperty FocusedElementProperty =
DependencyProperty.Register(nameof(FocusedElement), typeof(FrameworkElement), typeof(SystemFocusVisual), new PropertyMetadata(default));
}
}
37 changes: 37 additions & 0 deletions src/Uno.UI/UI/Xaml/Controls/FocusVisual/SystemFocusVisual.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:contract7Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,7)"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Uno.UI.Xaml.Controls">

<Style TargetType="local:SystemFocusVisual">
<Setter Property="AllowFocusOnInteraction" Value="False" />
<Setter Property="IsHitTestVisible" Value="False" />
<Setter Property="IsTapEnabled" Value="False" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:SystemFocusVisual">
<Border
Width="{Binding Path=FocusedElement.ActualWidth, RelativeSource={RelativeSource TemplatedParent}}"
Height="{Binding Path=FocusedElement.ActualHeight, RelativeSource={RelativeSource TemplatedParent}}">
<Border
Background="{x:Null}"
BorderBrush="{Binding Path=FocusedElement.FocusVisualPrimaryBrush, RelativeSource={RelativeSource TemplatedParent}}"
BorderThickness="{Binding Path=FocusedElement.FocusVisualPrimaryThickness, RelativeSource={RelativeSource TemplatedParent}}"
CornerRadius="{Binding Path=FocusedElement.CornerRadius, RelativeSource={RelativeSource TemplatedParent}}"
Margin="{Binding Path=FocusedElement.FocusVisualMargin, RelativeSource={RelativeSource TemplatedParent}}">
<Border
Background="Red"
BorderBrush="{Binding Path=FocusedElement.FocusVisualSecondaryBrush, RelativeSource={RelativeSource TemplatedParent}}"
BorderThickness="{Binding Path=FocusedElement.FocusVisualSecondaryThickness, RelativeSource={RelativeSource TemplatedParent}}"
CornerRadius="{Binding Path=FocusedElement.CornerRadius, RelativeSource={RelativeSource TemplatedParent}}">
</Border>
</Border>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

</ResourceDictionary>
30 changes: 30 additions & 0 deletions src/Uno.UI/UI/Xaml/Input/FocusManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Windows.UI.Core;
using Windows.UI.ViewManagement;
using Microsoft.Extensions.Logging;
using Uno.UI.Xaml.Controls;

namespace Windows.UI.Xaml.Input
{
Expand Down Expand Up @@ -132,6 +133,7 @@ private static bool UpdateFocus(DependencyObject newFocus, FocusNavigationDirect
(newFocus as Control)?.UpdateFocusState(focusState);

FocusNative(newFocus as Control);
UpdateFocusVisual(newFocus, focusState);

if (oldFocusedElement != null)
{
Expand All @@ -146,6 +148,34 @@ private static bool UpdateFocus(DependencyObject newFocus, FocusNavigationDirect
return true;
}

private static void UpdateFocusVisual(DependencyObject newFocus, FocusState focusState)
{
var focusVisualLayer = Window.Current.FocusVisualLayer;
SystemFocusVisual focusVisual;
if (focusVisualLayer.Children.Count == 0)
{
focusVisualLayer.Children.Add(new SystemFocusVisual());
}

focusVisual = (SystemFocusVisual)focusVisualLayer.Children[0];
if (newFocus is FrameworkElement element && focusState == FocusState.Keyboard)
{
focusVisual.FocusedElement = element;
focusVisual.Visibility = Visibility.Visible;
focusVisual.Width = element.ActualWidth;
focusVisual.Height = element.ActualHeight;
var transformToRoot = element.TransformToVisual(Windows.UI.Xaml.Window.Current.Content);
var point = transformToRoot.TransformPoint(new Windows.Foundation.Point(0, 0));
Canvas.SetLeft(focusVisual, point.X);
Canvas.SetTop(focusVisual, point.Y);
}
else
{
focusVisual.FocusedElement = null;
focusVisual.Visibility = Visibility.Collapsed;
}
}

private static void RaiseLostFocusEvent(object oldFocus)
{
void OnLostFocus()
Expand Down

0 comments on commit 66293ac

Please sign in to comment.