Skip to content

Commit a1b843b

Browse files
authored
Code Quality: Fixed keyboard shortcuts when refocusing window (#17502)
1 parent 23eec92 commit a1b843b

File tree

12 files changed

+80
-10
lines changed

12 files changed

+80
-10
lines changed

src/Files.App/Actions/Navigation/NextTabAction.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace Files.App.Actions
99
internal sealed partial class NextTabAction : ObservableObject, IAction
1010
{
1111
private readonly IMultitaskingContext multitaskingContext;
12+
private readonly IContentPageContext contentPageContext = Ioc.Default.GetRequiredService<IContentPageContext>();
1213

1314
public string Label
1415
=> Strings.NextTab.GetLocalizedResource();
@@ -37,7 +38,7 @@ public async Task ExecuteAsync(object? parameter = null)
3738
await Task.Delay(500);
3839

3940
// Focus the content of the selected tab item (needed for keyboard navigation)
40-
(multitaskingContext.CurrentTabItem.TabItemContent as Control)?.Focus(FocusState.Programmatic);
41+
contentPageContext.ShellPage!.PaneHolder.FocusActivePane();
4142
}
4243

4344
private void MultitaskingContext_PropertyChanged(object? sender, PropertyChangedEventArgs e)

src/Files.App/Actions/Navigation/PreviousTabAction.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace Files.App.Actions
99
internal sealed partial class PreviousTabAction : ObservableObject, IAction
1010
{
1111
private readonly IMultitaskingContext multitaskingContext;
12+
private readonly IContentPageContext contentPageContext = Ioc.Default.GetRequiredService<IContentPageContext>();
1213

1314
public string Label
1415
=> Strings.PreviousTab.GetLocalizedResource();
@@ -40,7 +41,7 @@ public async Task ExecuteAsync(object? parameter = null)
4041
await Task.Delay(500);
4142

4243
// Focus the content of the selected tab item (needed for keyboard navigation)
43-
(multitaskingContext.CurrentTabItem.TabItemContent as Control)?.Focus(FocusState.Programmatic);
44+
contentPageContext.ShellPage!.PaneHolder.FocusActivePane();
4445
}
4546

4647
private void MultitaskingContext_PropertyChanged(object? sender, PropertyChangedEventArgs e)

src/Files.App/Data/Contracts/IShellPanesPage.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ public interface IShellPanesPage : IDisposable, INotifyPropertyChanged
6969
/// </summary>
7070
public void FocusActivePane();
7171

72+
/// <summary>
73+
/// Locks the active pane.
74+
/// </summary>
75+
public void LockActivePane();
76+
7277
/// <summary>
7378
/// Gets open panes.
7479
/// </summary>

src/Files.App/UserControls/TabBar/TabBar.xaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@
145145
x:Name="SplitPaneMenuItem"
146146
x:Load="{x:Bind Commands.SplitPaneHorizontally.IsExecutable, Mode=OneWay}"
147147
Text="{helpers:ResourceString Name=SplitPane}">
148-
<MenuFlyoutSubItem.Items>
148+
<MenuFlyoutSubItem.Items>
149149
<!-- Vertical -->
150150
<uc:MenuFlyoutItemWithThemedIcon
151151
x:Name="AddVerticalPaneTabActionButton"

src/Files.App/UserControls/Toolbar.xaml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -687,7 +687,10 @@
687687
<controls:ThemedIcon Style="{x:Bind ViewModel.LayoutThemedIcon, Mode=OneWay}" />
688688

689689
<AppBarButton.Flyout>
690-
<Flyout contract8Present:ShouldConstrainToRootBounds="False" Placement="Bottom">
690+
<Flyout
691+
x:Name="LayoutFlyout"
692+
contract8Present:ShouldConstrainToRootBounds="False"
693+
Placement="Bottom">
691694
<StackPanel Spacing="12">
692695

693696
<!-- Header -->
@@ -699,6 +702,7 @@
699702
<!-- Details -->
700703
<RadioButton
701704
AutomationProperties.Name="{x:Bind Commands.LayoutDetails.AutomationName}"
705+
Click="LayoutButton_Click"
702706
Command="{x:Bind Commands.LayoutDetails}"
703707
GroupName="LayoutRadio"
704708
IsChecked="{x:Bind ViewModel.IsDetailsLayout, Mode=OneWay}"
@@ -722,6 +726,7 @@
722726
<!-- List -->
723727
<RadioButton
724728
AutomationProperties.Name="{x:Bind Commands.LayoutList.AutomationName}"
729+
Click="LayoutButton_Click"
725730
Command="{x:Bind Commands.LayoutList}"
726731
GroupName="LayoutRadio"
727732
IsChecked="{x:Bind ViewModel.IsListLayout, Mode=OneWay}"
@@ -746,6 +751,7 @@
746751
<!-- Cards -->
747752
<RadioButton
748753
AutomationProperties.Name="{x:Bind Commands.LayoutCards.AutomationName}"
754+
Click="LayoutButton_Click"
749755
Command="{x:Bind Commands.LayoutCards}"
750756
GroupName="LayoutRadio"
751757
IsChecked="{x:Bind ViewModel.IsCardsLayout, Mode=OneWay}"
@@ -770,6 +776,7 @@
770776
<!-- Grid -->
771777
<RadioButton
772778
AutomationProperties.Name="{x:Bind Commands.LayoutGrid.AutomationName}"
779+
Click="LayoutButton_Click"
773780
Command="{x:Bind Commands.LayoutGrid}"
774781
GroupName="LayoutRadio"
775782
IsChecked="{x:Bind ViewModel.IsGridLayout, Mode=OneWay}"
@@ -794,6 +801,7 @@
794801
<!-- Columns -->
795802
<RadioButton
796803
AutomationProperties.Name="{x:Bind Commands.LayoutColumns.AutomationName}"
804+
Click="LayoutButton_Click"
797805
Command="{x:Bind Commands.LayoutColumns}"
798806
GroupName="LayoutRadio"
799807
IsChecked="{x:Bind ViewModel.IsColumnLayout, Mode=OneWay}"

src/Files.App/UserControls/Toolbar.xaml.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,5 +108,11 @@ private void AppBarButton_AccessKeyInvoked(UIElement sender, AccessKeyInvokedEve
108108
if (VisualTreeHelper.GetOpenPopupsForXamlRoot(MainWindow.Instance.Content.XamlRoot).Any())
109109
args.Handled = true;
110110
}
111+
112+
private void LayoutButton_Click(object sender, RoutedEventArgs e)
113+
{
114+
// Hide flyout after choosing a layout
115+
LayoutFlyout.Hide();
116+
}
111117
}
112118
}

src/Files.App/ViewModels/MainPageViewModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ private async void ExecuteNavigateToNumberedTabKeyboardAcceleratorCommand(Keyboa
391391
await Task.Delay(500);
392392

393393
// Focus the content of the selected tab item (needed for keyboard navigation)
394-
(SelectedTabItem?.TabItemContent as Control)?.Focus(FocusState.Programmatic);
394+
context.ShellPage!.PaneHolder.FocusActivePane();
395395
}
396396

397397
e.Handled = true;

src/Files.App/ViewModels/ShellViewModel.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,13 @@ public ShellViewModel(LayoutPreferencesManager folderSettingsViewModel)
584584

585585
private async void LayoutModeChangeRequested(object? sender, LayoutModeEventArgs e)
586586
{
587+
// Layout changes can cause the active pane to lose focus. To prevent this,
588+
// the pane is locked here and focus is restored when file loading completes
589+
// in the RefreshItem() method in BaseLayoutPage.cs.
590+
// See https://github.com/files-community/Files/issues/15397
591+
// See https://github.com/files-community/Files/issues/16530
592+
ContentPageContext.ShellPage!.PaneHolder.LockActivePane();
593+
587594
await dispatcherQueue.EnqueueOrInvokeAsync(CheckForBackgroundImage, Microsoft.UI.Dispatching.DispatcherQueuePriority.Low);
588595
}
589596

src/Files.App/Views/Layouts/BaseLayoutPage.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,8 +1240,14 @@ private void RefreshItem(SelectorItem container, object item, bool inRecycleQueu
12401240
if (ParentShellPageInstance.ShellViewModel.EnabledGitProperties is not GitProperties.None && listedItem is IGitItem gitItem)
12411241
await ParentShellPageInstance.ShellViewModel.LoadGitPropertiesAsync(gitItem);
12421242

1243-
// Focus file list when items finish loading (#16530)
1244-
ItemManipulationModel.FocusFileList();
1243+
// Layout changes can cause the active pane to lose focus. To prevent this,
1244+
// the pane is locked in LayoutModeChangeRequested() and focus is restored here
1245+
// when file loading completes.
1246+
// See https://github.com/files-community/Files/issues/15397
1247+
// See https://github.com/files-community/Files/issues/16530
1248+
1249+
if (ParentShellPageInstance.IsCurrentPane && !ParentShellPageInstance.IsColumnView)
1250+
ItemManipulationModel.FocusFileList();
12451251
});
12461252
}
12471253
}

src/Files.App/Views/MainPage.xaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
KeyboardAcceleratorPlacementMode="Hidden"
2323
Loaded="Page_Loaded"
2424
NavigationCacheMode="Required"
25+
PointerReleased="Page_PointerReleased"
2526
SizeChanged="Page_SizeChanged"
2627
mc:Ignorable="d">
2728

0 commit comments

Comments
 (0)