Skip to content

Commit f88c5dd

Browse files
committed
Fixed focus issues
1 parent 453151c commit f88c5dd

File tree

6 files changed

+64
-5
lines changed

6 files changed

+64
-5
lines changed

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/Toolbar.xaml

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

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

694697
<!-- Header -->
@@ -700,6 +703,7 @@
700703
<!-- Details -->
701704
<RadioButton
702705
AutomationProperties.Name="{x:Bind Commands.LayoutDetails.AutomationName}"
706+
Click="LayoutButton_Click"
703707
Command="{x:Bind Commands.LayoutDetails}"
704708
GroupName="LayoutRadio"
705709
IsChecked="{x:Bind ViewModel.IsDetailsLayout, Mode=OneWay}"
@@ -723,6 +727,7 @@
723727
<!-- List -->
724728
<RadioButton
725729
AutomationProperties.Name="{x:Bind Commands.LayoutList.AutomationName}"
730+
Click="LayoutButton_Click"
726731
Command="{x:Bind Commands.LayoutList}"
727732
GroupName="LayoutRadio"
728733
IsChecked="{x:Bind ViewModel.IsListLayout, Mode=OneWay}"
@@ -747,6 +752,7 @@
747752
<!-- Cards -->
748753
<RadioButton
749754
AutomationProperties.Name="{x:Bind Commands.LayoutCards.AutomationName}"
755+
Click="LayoutButton_Click"
750756
Command="{x:Bind Commands.LayoutCards}"
751757
GroupName="LayoutRadio"
752758
IsChecked="{x:Bind ViewModel.IsCardsLayout, Mode=OneWay}"
@@ -771,6 +777,7 @@
771777
<!-- Grid -->
772778
<RadioButton
773779
AutomationProperties.Name="{x:Bind Commands.LayoutGrid.AutomationName}"
780+
Click="LayoutButton_Click"
774781
Command="{x:Bind Commands.LayoutGrid}"
775782
GroupName="LayoutRadio"
776783
IsChecked="{x:Bind ViewModel.IsGridLayout, Mode=OneWay}"
@@ -795,6 +802,7 @@
795802
<!-- Columns -->
796803
<RadioButton
797804
AutomationProperties.Name="{x:Bind Commands.LayoutColumns.AutomationName}"
805+
Click="LayoutButton_Click"
798806
Command="{x:Bind Commands.LayoutColumns}"
799807
GroupName="LayoutRadio"
800808
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
@@ -116,5 +116,11 @@ private void RootGrid_PointerReleased(object sender, PointerRoutedEventArgs e)
116116
// shortcuts from working, see https://github.com/microsoft/microsoft-ui-xaml/issues/6467
117117
DispatcherQueue.TryEnqueue(() => ContentPageContext.ShellPage!.PaneHolder.FocusActivePane());
118118
}
119+
120+
private void LayoutButton_Click(object sender, RoutedEventArgs e)
121+
{
122+
// Hide flyout after choosing a layout
123+
LayoutFlyout.Hide();
124+
}
119125
}
120126
}

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+
// from happening, the pane is locked and focus is restored when file loading
589+
// completes, this occurs 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+
// from happening, the pane is locked and focus is restored when file loading
1245+
// completes, the locking occurs in the `LayoutModeChangeRequested()` method in ShellViewModel.cs.
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/ShellPanesPage.xaml.cs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,17 @@ public bool IsCurrentInstance
228228
}
229229
}
230230

231+
private bool _IsActivePaneLocked;
232+
public bool IsActivePaneLocked
233+
{
234+
get => _IsActivePaneLocked;
235+
set
236+
{
237+
if (_IsActivePaneLocked != value)
238+
_IsActivePaneLocked = value;
239+
}
240+
}
241+
231242
// Events
232243

233244
public static event EventHandler<ShellPanesPage>? CurrentInstanceChanged;
@@ -378,6 +389,12 @@ public void FocusActivePane()
378389
GetPane(1)?.Focus(FocusState.Programmatic);
379390
}
380391

392+
/// <inheritdoc/>
393+
public void LockActivePane()
394+
{
395+
IsActivePaneLocked = true;
396+
}
397+
381398
/// <inheritdoc/>
382399
public IEnumerable<ModernShellPage> GetPanes()
383400
{
@@ -656,9 +673,19 @@ private void Pane_Loaded(object sender, RoutedEventArgs e)
656673

657674
private void Pane_GettingFocus(UIElement sender, GettingFocusEventArgs args)
658675
{
659-
// Workaround for https://github.com/files-community/Files/issues/15397
660-
if (args?.NewFocusedElement is not null && args.NewFocusedElement is not (ListViewItem or GridViewItem or ListView or GridView or TextBox))
676+
// Layout changes can cause the active pane to lose focus, to prevent this
677+
// from happening, the pane is locked and focus is restored when file loading
678+
// completes.
679+
// The locking occurs in the `LayoutModeChangeRequested()` method in ShellViewModel.cs.
680+
// The focus is restored in the `RefreshItem()` method in BaseLayoutPage.cs
681+
// See https://github.com/files-community/Files/issues/15397
682+
// See https://github.com/files-community/Files/issues/16530
683+
684+
if (IsActivePaneLocked)
685+
{
686+
IsActivePaneLocked = false;
661687
args.TryCancel();
688+
}
662689
}
663690

664691
private void Pane_ContentChanged(object? sender, TabBarItemParameter e)

0 commit comments

Comments
 (0)