Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/Filee.App/Controls/DonutMenu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,11 @@ public DonutMenu()
FlowDirection = FlowDirection.LeftToRight;
ClipToBounds = false;
Cursor = new Cursor(StandardCursorType.Hand);
// The live click-mode donut handles Tab, arrows, Enter and Escape itself. It must be the focused control
// after a context-menu/shortcut launch; otherwise Avalonia has no focused target to which the key events can
// be routed. It is focused explicitly by RadialController, so it must not participate in normal Tab order.
Focusable = true;
IsTabStop = false;
}

public IReadOnlyList<DonutItem>? Items { get => GetValue(ItemsProperty); set => SetValue(ItemsProperty, value); }
Expand Down
6 changes: 6 additions & 0 deletions src/Filee.App/Services/RadialController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,13 @@ private void PlaceAndShow(RadialWindow window, int x, int y, bool activate)
}
_visible = true;
if (activate)
{
window.Activate();
// ShowActivated is false because the same window is also used during an OS drag, where taking focus would
// break Explorer's drag. Click mode is different: the donut owns the keyboard until it closes, so focus it
// explicitly for Tab/arrow/Enter handling.
window.DonutControl.Focus();
}
}

private static bool SameFiles(IReadOnlyList<string> a, IReadOnlyList<string> b) =>
Expand Down
22 changes: 22 additions & 0 deletions tests/Filee.App.Tests/RadialControllerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
// the gesture ends without files, even after a conversion left the ring behind (issue: desktop icons stopped reacting
// to clicks until Filee quit).

using Avalonia.Headless;
using Avalonia.Headless.XUnit;
using Avalonia.Input;
using Filee.App.Controls;
using Filee.App.Services;
using Filee.Core.Presets;
Expand Down Expand Up @@ -59,6 +61,26 @@ public void Esc_closes_a_donut_whose_ring_already_finished()
Assert.False(radial.Window.IsVisible);
}

[AvaloniaFact]
public void Click_mode_focuses_the_donut_for_tab_flip()
{
TestServices.EnsureInitialized("en");
var radial = AppHost.Get<RadialController>();
try
{
radial.ShowForFiles(400, 400, [@"C:\photos\a.jpg"]);
var window = radial.Window!;

Assert.True(window.DonutControl.IsFocused);
window.KeyPress(Key.Tab, RawInputModifiers.None, PhysicalKey.Tab, null);
Assert.True(AppHost.Get<Filee.App.ViewModels.RadialViewModel>().IsBackFace);
}
finally
{
radial.Close(animate: false);
}
}

[Fact]
public void Folders_only_go_into_one_archive()
{
Expand Down
Loading