@samitouri / QOSAMI-WSL / commits / 63fa9f3e

Accessibility Bug Fix: After selecting from the navigation list, keyboard focus is not transferred to page content (#14289)

* bug fix * Update src/windows/wslsettings/Views/Settings/OptionalFeaturesPage.xaml.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/windows/wslsettings/Views/Settings/NetworkingPage.xaml.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/windows/wslsettings/Views/Settings/MemAndProcPage.xaml.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/windows/wslsettings/Views/Settings/FileSystemPage.xaml.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/windows/wslsettings/Views/Settings/DeveloperPage.xaml.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

ssparach committed Feb 26, 2026 at 14:10 UTC 63fa9f3e1323a9dce2373caa3cde38637f0cc4c2
11 files changed +53 -10
src/windows/wslsettings/Views/Settings/DeveloperPage.xaml
+5 -2
@@ -7,13 +7,16 @@
7 xmlns:controls="using:WslSettings.Controls"
8 behaviors:NavigationViewHeaderBehavior.HeaderMode="Never">
9
10 - <Grid Margin="{ThemeResource ContentPageMargin}">
10 + <Grid Margin="{ThemeResource ContentPageMargin}"
11 + IsTabStop="True"
12 + AutomationProperties.LandmarkType="Main"
13 + x:Name="DeveloperPageRoot">
14 <Grid.RowDefinitions>
15 <RowDefinition Height="Auto" />
16 <RowDefinition Height="Auto" />
17 <RowDefinition Height="*" />
18 </Grid.RowDefinitions>
16 - <TextBlock x:Uid="Settings_DeveloperPageTitle" Style="{ThemeResource PageHeaderTextBlockStyle}" Margin="{StaticResource MediumSmallBottomMargin}" HorizontalAlignment="Left"/>
19 + <TextBlock x:Uid="Settings_DeveloperPageTitle" Style="{ThemeResource PageHeaderTextBlockStyle}" Margin="{StaticResource MediumSmallBottomMargin}" HorizontalAlignment="Left" AutomationProperties.HeadingLevel="Level1"/>
20 <TextBlock x:Uid="Settings_ErrorTryAgainLater" x:Name="Settings_ErrorTryAgainLater" Grid.Row="1" HorizontalAlignment="Left" AutomationProperties.LiveSetting="Assertive"
21 Visibility="{x:Bind ViewModel.ErrorVisibility, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource BooleanToVisibilityConverter}}"/>
22 <ScrollViewer Grid.Row="2" VerticalScrollBarVisibility="Auto"
src/windows/wslsettings/Views/Settings/DeveloperPage.xaml.cs
+1
@@ -33,6 +33,7 @@ public sealed partial class DeveloperPage : Page
33
34 private void OnPageLoaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
35 {
36 + DeveloperPageRoot.Focus(FocusState.Programmatic);
37 RuntimeHelper.SetupExpanderFocusManagementByName(this, "CustomKernelPathExpander", "CustomKernelPathTextBox");
38 RuntimeHelper.SetupExpanderFocusManagementByName(this, "CustomKernelModulesPathExpander", "CustomKernelModulesPathTextBox");
39 RuntimeHelper.SetupExpanderFocusManagementByName(this, "CustomSystemDistroPathExpander", "CustomSystemDistroPathTextBox");
src/windows/wslsettings/Views/Settings/FileSystemPage.xaml
+5 -2
@@ -6,13 +6,16 @@
6 xmlns:behaviors="using:WslSettings.Behaviors"
7 behaviors:NavigationViewHeaderBehavior.HeaderMode="Never">
8
9 - <Grid Margin="{ThemeResource ContentPageMargin}">
9 + <Grid Margin="{ThemeResource ContentPageMargin}"
10 + IsTabStop="True"
11 + AutomationProperties.LandmarkType="Main"
12 + x:Name="FileSystemPageRoot">
13 <Grid.RowDefinitions>
14 <RowDefinition Height="Auto" />
15 <RowDefinition Height="Auto" />
16 <RowDefinition Height="*" />
17 </Grid.RowDefinitions>
15 - <TextBlock x:Uid="Settings_FileSystemPageTitle" Style="{ThemeResource PageHeaderTextBlockStyle}" Margin="{StaticResource MediumSmallBottomMargin}" HorizontalAlignment="Left"/>
18 + <TextBlock x:Uid="Settings_FileSystemPageTitle" Style="{ThemeResource PageHeaderTextBlockStyle}" Margin="{StaticResource MediumSmallBottomMargin}" HorizontalAlignment="Left" AutomationProperties.HeadingLevel="Level1"/>
19 <TextBlock x:Uid="Settings_ErrorTryAgainLater" x:Name="Settings_ErrorTryAgainLater" Grid.Row="1" HorizontalAlignment="Left" AutomationProperties.LiveSetting="Assertive"
20 Visibility="{x:Bind ViewModel.ErrorVisibility, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource BooleanToVisibilityConverter}}"/>
21 <ScrollViewer Grid.Row="2" VerticalScrollBarVisibility="Auto"
src/windows/wslsettings/Views/Settings/FileSystemPage.xaml.cs
+2
@@ -1,6 +1,7 @@
1 // Copyright (C) Microsoft Corporation. All rights reserved.
2
3 using CommunityToolkit.WinUI.Controls;
4 +using Microsoft.UI.Xaml;
5 using Microsoft.UI.Xaml.Automation.Peers;
6 using Microsoft.UI.Xaml.Controls;
7 using Microsoft.UI.Xaml.Navigation;
@@ -60,6 +61,7 @@ public sealed partial class FileSystemPage : Page
61
62 private void OnPageLoaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
63 {
64 + FileSystemPageRoot.Focus(FocusState.Programmatic);
65 var expander = this.FindName("DefaultVHDSizeExpander") as SettingsExpander;
66 var textBox = this.FindName("DefaultVHDSizeTextBox") as TextBox;
67
src/windows/wslsettings/Views/Settings/MemAndProcPage.xaml
+5 -2
@@ -6,13 +6,16 @@
6 xmlns:behaviors="using:WslSettings.Behaviors"
7 behaviors:NavigationViewHeaderBehavior.HeaderMode="Never">
8
9 - <Grid Margin="{ThemeResource ContentPageMargin}">
9 + <Grid Margin="{ThemeResource ContentPageMargin}"
10 + IsTabStop="True"
11 + AutomationProperties.LandmarkType="Main"
12 + x:Name="MemAndProcPageRoot">
13 <Grid.RowDefinitions>
14 <RowDefinition Height="Auto" />
15 <RowDefinition Height="Auto" />
16 <RowDefinition Height="*" />
17 </Grid.RowDefinitions>
15 - <TextBlock x:Uid="Settings_MemAndProcPageTitle" Style="{ThemeResource PageHeaderTextBlockStyle}" Margin="{StaticResource MediumSmallBottomMargin}" HorizontalAlignment="Left"/>
18 + <TextBlock x:Uid="Settings_MemAndProcPageTitle" Style="{ThemeResource PageHeaderTextBlockStyle}" Margin="{StaticResource MediumSmallBottomMargin}" HorizontalAlignment="Left" AutomationProperties.HeadingLevel="Level1"/>
19 <TextBlock x:Uid="Settings_ErrorTryAgainLater" x:Name="Settings_ErrorTryAgainLater" Grid.Row="1" HorizontalAlignment="Left" AutomationProperties.LiveSetting="Assertive"
20 Visibility="{x:Bind ViewModel.ErrorVisibility, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource BooleanToVisibilityConverter}}"/>
21 <ScrollViewer Grid.Row="2" VerticalScrollBarVisibility="Auto"
src/windows/wslsettings/Views/Settings/MemAndProcPage.xaml.cs
+1
@@ -33,6 +33,7 @@ public sealed partial class MemAndProcPage : Page
33
34 private void OnPageLoaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
35 {
36 + MemAndProcPageRoot.Focus(FocusState.Programmatic);
37 RuntimeHelper.SetupExpanderFocusManagementByName(this, "ProcCountExpander", "ProcCountTextBox");
38 RuntimeHelper.SetupExpanderFocusManagementByName(this, "MemorySizeExpander", "MemorySizeTextBox");
39 RuntimeHelper.SetupExpanderFocusManagementByName(this, "SwapSizeExpander", "SwapSizeTextBox");
src/windows/wslsettings/Views/Settings/NetworkingPage.xaml
+5 -2
@@ -6,13 +6,16 @@
6 xmlns:behaviors="using:WslSettings.Behaviors"
7 behaviors:NavigationViewHeaderBehavior.HeaderMode="Never">
8
9 - <Grid Margin="{ThemeResource ContentPageMargin}">
9 + <Grid Margin="{ThemeResource ContentPageMargin}"
10 + IsTabStop="True"
11 + AutomationProperties.LandmarkType="Main"
12 + x:Name="NetworkingPageRoot">
13 <Grid.RowDefinitions>
14 <RowDefinition Height="Auto" />
15 <RowDefinition Height="Auto" />
16 <RowDefinition Height="*" />
17 </Grid.RowDefinitions>
15 - <TextBlock x:Uid="Settings_NetworkingPageTitle" Style="{ThemeResource PageHeaderTextBlockStyle}" Margin="{StaticResource MediumSmallBottomMargin}" HorizontalAlignment="Left"/>
18 + <TextBlock x:Uid="Settings_NetworkingPageTitle" Style="{ThemeResource PageHeaderTextBlockStyle}" Margin="{StaticResource MediumSmallBottomMargin}" HorizontalAlignment="Left" AutomationProperties.HeadingLevel="Level1"/>
19 <TextBlock x:Uid="Settings_ErrorTryAgainLater" x:Name="Settings_ErrorTryAgainLater" Grid.Row="1" HorizontalAlignment="Left" AutomationProperties.LiveSetting="Assertive"
20 Visibility="{x:Bind ViewModel.ErrorVisibility, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource BooleanToVisibilityConverter}}"/>
21 <ScrollViewer Grid.Row="2" VerticalScrollBarVisibility="Auto"
src/windows/wslsettings/Views/Settings/NetworkingPage.xaml.cs
+2
@@ -1,5 +1,6 @@
1 // Copyright (C) Microsoft Corporation. All rights reserved.
2
3 +using Microsoft.UI.Xaml;
4 using Microsoft.UI.Xaml.Automation.Peers;
5 using Microsoft.UI.Xaml.Controls;
6 using Microsoft.UI.Xaml.Navigation;
@@ -32,6 +33,7 @@ public sealed partial class NetworkingPage : Page
33
34 private void OnPageLoaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
35 {
36 + NetworkingPageRoot.Focus(FocusState.Programmatic);
37 RuntimeHelper.SetupExpanderFocusManagementByName(this, "IgnoredPortsExpander", "IgnoredPortsTextBox");
38 RuntimeHelper.SetupExpanderFocusManagementByName(this, "InitialAutoProxyTimeoutExpander", "InitialAutoProxyTimeoutTextBox");
39 }
src/windows/wslsettings/Views/Settings/OptionalFeaturesPage.xaml
+5 -2
@@ -7,13 +7,16 @@
7 xmlns:controls="using:WslSettings.Controls"
8 behaviors:NavigationViewHeaderBehavior.HeaderMode="Never">
9
10 - <Grid Margin="{ThemeResource ContentPageMargin}">
10 + <Grid Margin="{ThemeResource ContentPageMargin}"
11 + IsTabStop="True"
12 + AutomationProperties.LandmarkType="Main"
13 + x:Name="OptionalFeaturesPageRoot">
14 <Grid.RowDefinitions>
15 <RowDefinition Height="Auto" />
16 <RowDefinition Height="Auto" />
17 <RowDefinition Height="*" />
18 </Grid.RowDefinitions>
16 - <TextBlock x:Uid="Settings_OptionalFeaturesPageTitle" Style="{ThemeResource PageHeaderTextBlockStyle}" Margin="{StaticResource MediumSmallBottomMargin}" HorizontalAlignment="Left"/>
19 + <TextBlock x:Uid="Settings_OptionalFeaturesPageTitle" Style="{ThemeResource PageHeaderTextBlockStyle}" Margin="{StaticResource MediumSmallBottomMargin}" HorizontalAlignment="Left" AutomationProperties.HeadingLevel="Level1"/>
20 <TextBlock x:Uid="Settings_ErrorTryAgainLater" x:Name="Settings_ErrorTryAgainLater" Grid.Row="1" HorizontalAlignment="Left" AutomationProperties.LiveSetting="Assertive"
21 Visibility="{x:Bind ViewModel.ErrorVisibility, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource BooleanToVisibilityConverter}}"/>
22 <ScrollViewer Grid.Row="2" VerticalScrollBarVisibility="Auto"
src/windows/wslsettings/Views/Settings/OptionalFeaturesPage.xaml.cs
+2
@@ -1,5 +1,6 @@
1 // Copyright (C) Microsoft Corporation. All rights reserved.
2
3 +using Microsoft.UI.Xaml;
4 using Microsoft.UI.Xaml.Automation.Peers;
5 using Microsoft.UI.Xaml.Controls;
6 using Microsoft.UI.Xaml.Navigation;
@@ -32,6 +33,7 @@ public sealed partial class OptionalFeaturesPage : Page
33
34 private void OnPageLoaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
35 {
36 + OptionalFeaturesPageRoot.Focus(FocusState.Programmatic);
37 RuntimeHelper.SetupExpanderFocusManagementByName(this, "SystemdSettingsExpander", "InitTextBox");
38 RuntimeHelper.SetupExpanderFocusManagementByName(this, "VMIdleTimeoutExpander", "VMIdleTimeoutTextBox");
39 }
src/windows/wslsettings/Views/Settings/ShellPage.xaml.cs
+20
@@ -44,6 +44,7 @@ public sealed partial class ShellPage : Page
44 App.MainWindow.SetTitleBar(AppTitleBar);
45 App.MainWindow.Activated += MainWindow_Activated;
46 AppTitleBarText.Text = "Settings_AppDisplayName".GetLocalized();
47 + NavigationFrame.LostFocus += NavigationFrame_LostFocus;
48 }
49
50 private void OnLoaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
@@ -129,4 +130,23 @@ public sealed partial class ShellPage : Page
130
131 args.Handled = result;
132 }
133 +
134 + private void NavigationFrame_LostFocus(object sender, RoutedEventArgs e)
135 + {
136 + DispatcherQueue.TryEnqueue(() =>
137 + {
138 + var focused = FocusManager.GetFocusedElement(NavigationViewControl.XamlRoot);
139 +
140 + // If focus is transferred to the selected page itself, do nothing
141 + if (focused is not NavigationViewItem && focused is not NavigationView)
142 + {
143 + return;
144 + }
145 +
146 + // Restore focus to the selected navigation item
147 + var selected = NavigationViewControl.SelectedItem;
148 + var container = NavigationViewControl.ContainerFromMenuItem(selected) as Control;
149 + container?.Focus(FocusState.Keyboard);
150 + });
151 + }
152 }