diff --git a/src/Avalonia.Controls/Primitives/IPopupHost.cs b/src/Avalonia.Controls/Primitives/IPopupHost.cs
index e424bf683d..82a49c4189 100644
--- a/src/Avalonia.Controls/Primitives/IPopupHost.cs
+++ b/src/Avalonia.Controls/Primitives/IPopupHost.cs
@@ -1,6 +1,7 @@
using System;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives.PopupPositioning;
+using Avalonia.Input;
using Avalonia.VisualTree;
namespace Avalonia.Controls.Primitives
@@ -13,7 +14,7 @@ namespace Avalonia.Controls.Primitives
/// () or an which is created
/// on an .
///
- public interface IPopupHost : IDisposable
+ public interface IPopupHost : IDisposable, IFocusScope
{
///
/// Sets the control to display in the popup.
diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs b/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs
index d9176ca55d..53a8db2176 100644
--- a/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs
@@ -395,6 +395,53 @@ namespace Avalonia.Controls.UnitTests.Primitives
}
}
+ [Fact]
+ public void Focusable_Controls_In_Popup_Should_Get_Focus()
+ {
+ using (CreateServicesWithFocus())
+ {
+ var window = PreparedWindow();
+
+ var tb = new TextBox();
+ var b = new Button();
+ var p = new Popup
+ {
+ PlacementTarget = window,
+ Child = new StackPanel
+ {
+ Children =
+ {
+ tb,
+ b
+ }
+ }
+ };
+ ((ISetLogicalParent)p).SetParent(p.PlacementTarget);
+ window.Show();
+
+ p.Open();
+
+ if(p.Host is OverlayPopupHost host)
+ {
+ //Need to measure/arrange for visual children to show up
+ //in OverlayPopupHost
+ host.Measure(Size.Infinity);
+ host.Arrange(new Rect(host.DesiredSize));
+ }
+
+ tb.Focus();
+
+ Assert.True(FocusManager.Instance?.Current == tb);
+
+ //Ensure focus remains in the popup
+ var nextFocus = KeyboardNavigationHandler.GetNext(FocusManager.Instance.Current, NavigationDirection.Next);
+
+ Assert.True(nextFocus == b);
+
+ p.Close();
+ }
+ }
+
private IDisposable CreateServices()
{
return UnitTestApplication.Start(TestServices.StyledWindow.With(windowingPlatform:
@@ -407,6 +454,21 @@ namespace Avalonia.Controls.UnitTests.Primitives
})));
}
+ private IDisposable CreateServicesWithFocus()
+ {
+ return UnitTestApplication.Start(TestServices.StyledWindow.With(windowingPlatform:
+ new MockWindowingPlatform(null,
+ x =>
+ {
+ if (UsePopupHost)
+ return null;
+ return MockWindowingPlatform.CreatePopupMock(x).Object;
+ }),
+ focusManager: new FocusManager(),
+ keyboardDevice: () => new KeyboardDevice()));
+ }
+
+
private PointerPressedEventArgs CreatePointerPressedEventArgs(Window source, Point p)
{
var pointer = new Pointer(Pointer.GetNextFreeId(), PointerType.Mouse, true);