diff --git a/Terminal.Gui/App/IPopover.cs b/Terminal.Gui/App/IPopover.cs
index 652ca4614..7e86ffe77 100644
--- a/Terminal.Gui/App/IPopover.cs
+++ b/Terminal.Gui/App/IPopover.cs
@@ -26,7 +26,26 @@ namespace Terminal.Gui.App;
///
///
///
-/// To implement a custom popover, inherit from or implement this interface directly.
+/// Focus and Input:
+/// When visible, a popover receives focus and input events. If the user clicks outside the popover (and not on a
+/// subview),
+/// presses , or another popover is shown, the popover will be hidden
+/// automatically.
+///
+///
+/// Layout:
+/// When the popover becomes visible, it is automatically laid out to fill the screen by default. You can override
+/// this behavior
+/// by setting and in your derived class.
+///
+///
+/// Mouse:
+/// Popovers are transparent to mouse events (see ),
+/// meaning mouse events in a popover that are not also within a subview of the popover will not be captured.
+///
+///
+/// Custom Popovers:
+/// To create a custom popover, inherit from and add your own content and logic.
///
///
public interface IPopover
diff --git a/Terminal.Gui/App/PopoverBaseImpl.cs b/Terminal.Gui/App/PopoverBaseImpl.cs
index 8c426a2db..1e9aacb71 100644
--- a/Terminal.Gui/App/PopoverBaseImpl.cs
+++ b/Terminal.Gui/App/PopoverBaseImpl.cs
@@ -26,6 +26,11 @@ namespace Terminal.Gui.App;
/// by setting and in your derived class.
///
///
+/// Mouse:
+/// Popovers are transparent to mouse events (see ),
+/// meaning mouse events in a popover that are not also within a subview of the popover will not be captured.
+///
+///
/// Custom Popovers:
/// To create a custom popover, inherit from and add your own content and logic.
///
diff --git a/Terminal.Gui/ViewBase/View.Layout.cs b/Terminal.Gui/ViewBase/View.Layout.cs
index e9fc65fa7..9ec26a23a 100644
--- a/Terminal.Gui/ViewBase/View.Layout.cs
+++ b/Terminal.Gui/ViewBase/View.Layout.cs
@@ -1166,7 +1166,7 @@ public partial class View // Layout APIs
result.AddRange (GetViewsUnderLocation (visiblePopover, screenLocation, excludeViewportSettingsFlags));
- if (result.Count > 1)
+ if (result.Count > 0)
{
return result;
}
diff --git a/Terminal.Gui/ViewBase/ViewportSettingsFlags.cs b/Terminal.Gui/ViewBase/ViewportSettingsFlags.cs
index 10c0d763a..5eee4493b 100644
--- a/Terminal.Gui/ViewBase/ViewportSettingsFlags.cs
+++ b/Terminal.Gui/ViewBase/ViewportSettingsFlags.cs
@@ -153,11 +153,9 @@ public enum ViewportSettingsFlags
///
Transparent = 0b_0001_0000_0000,
- // BUGBUG: The API docs here are wrong: If a TransparentMouse View has subviews, those subviews WILL get mouse events.
- // BUGBUG: That's an important feature that enables Popovers to work.
///
- /// If set the View will be transparent to mouse events: Any mouse event that occurs over the View (and it's SubViews) will be passed to the
- /// Views below it.
+ /// If set the View will be transparent to mouse events: Specifically, any mouse event that occurs over the View that is NOT occupied by a SubView
+ /// will not be captured by the View.
///
/// Combine this with to get a view that is both visually transparent and transparent to the mouse.
///
diff --git a/Tests/UnitTests/Application/ApplicationPopoverTests.cs b/Tests/UnitTests/Application/ApplicationPopoverTests.cs
index 66395840a..798899cf4 100644
--- a/Tests/UnitTests/Application/ApplicationPopoverTests.cs
+++ b/Tests/UnitTests/Application/ApplicationPopoverTests.cs
@@ -2,9 +2,6 @@
public class ApplicationPopoverTests
{
-
-
-
[Fact]
public void Application_Init_Initializes_PopoverManager ()
{
@@ -203,6 +200,71 @@ public class ApplicationPopoverTests
Application.ResetState (true);
}
+ // See: https://github.com/gui-cs/Terminal.Gui/issues/4122
+ [Theory]
+ [InlineData (0, 0, new [] { "top" })]
+ [InlineData (10, 10, new string [] { })]
+ [InlineData (1, 1, new [] { "top", "view" })]
+ [InlineData (5, 5, new [] { "top" })]
+ [InlineData (6, 6, new [] { "popoverSubView" })]
+ [InlineData (7, 7, new [] { "top" })]
+ [InlineData (3, 3, new [] { "top" })]
+ public void GetViewsUnderMouse_Supports_ActivePopover (int mouseX, int mouseY, string [] viewIdStrings)
+ {
+ Application.ResetState (true);
+ // Arrange
+ Assert.Null (Application.Popover);
+ Application.Init (new FakeDriver ());
+ Application.Top = new ()
+ {
+ Frame = new (0, 0, 10, 10),
+ Id = "top"
+ };
+
+ View view = new ()
+ {
+ Id = "view",
+ X = 1,
+ Y = 1,
+ Width = 2,
+ Height = 2,
+ }; // at 1,1 to 3,2 (screen)
+
+ Application.Top.Add (view);
+
+ PopoverTestClass popover = new ()
+ {
+ Id = "popover",
+ X = 5,
+ Y = 5,
+ Width = 3,
+ Height = 3,
+ }; // at 5,5 to 8,8 (screen)
+
+ View popoverSubView = new ()
+ {
+ Id = "popoverSubView",
+ X = 1,
+ Y = 1,
+ Width = 1,
+ Height = 1,
+ }; // at 6,6 to 7,7 (screen)
+
+ popover.Add (popoverSubView);
+
+ Application.Popover?.Show (popover);
+
+ List found = View.GetViewsUnderLocation (new (mouseX, mouseY), ViewportSettingsFlags.TransparentMouse);
+
+ string [] foundIds = found.Select (v => v!.Id).ToArray ();
+
+ Assert.Equal (viewIdStrings, foundIds);
+
+ popover.Dispose ();
+ Application.Top.Dispose ();
+ Application.ResetState (true);
+ }
+
public class PopoverTestClass : PopoverBaseImpl
{
public List HandledKeys { get; } = [];