Skip to content

Commit 23cc44c

Browse files
authored
Fixes #4129 - GetViewsUnderMouse does not return anything (#4130)
1 parent 1c04acf commit 23cc44c

File tree

5 files changed

+93
-9
lines changed

5 files changed

+93
-9
lines changed

Terminal.Gui/App/IPopover.cs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,26 @@ namespace Terminal.Gui.App;
2626
/// </list>
2727
/// </para>
2828
/// <para>
29-
/// To implement a custom popover, inherit from <see cref="PopoverBaseImpl"/> or implement this interface directly.
29+
/// <b>Focus and Input:</b><br/>
30+
/// When visible, a popover receives focus and input events. If the user clicks outside the popover (and not on a
31+
/// subview),
32+
/// presses <see cref="Application.QuitKey"/>, or another popover is shown, the popover will be hidden
33+
/// automatically.
34+
/// </para>
35+
/// <para>
36+
/// <b>Layout:</b><br/>
37+
/// When the popover becomes visible, it is automatically laid out to fill the screen by default. You can override
38+
/// this behavior
39+
/// by setting <see cref="View.Width"/> and <see cref="View.Height"/> in your derived class.
40+
/// </para>
41+
/// <para>
42+
/// <b>Mouse:</b><br/>
43+
/// Popovers are transparent to mouse events (see <see cref="ViewportSettingsFlags.TransparentMouse"/>),
44+
/// meaning mouse events in a popover that are not also within a subview of the popover will not be captured.
45+
/// </para>
46+
/// <para>
47+
/// <b>Custom Popovers:</b><br/>
48+
/// To create a custom popover, inherit from <see cref="PopoverBaseImpl"/> and add your own content and logic.
3049
/// </para>
3150
/// </remarks>
3251
public interface IPopover

Terminal.Gui/App/PopoverBaseImpl.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ namespace Terminal.Gui.App;
2626
/// by setting <see cref="View.Width"/> and <see cref="View.Height"/> in your derived class.
2727
/// </para>
2828
/// <para>
29+
/// <b>Mouse:</b><br/>
30+
/// Popovers are transparent to mouse events (see <see cref="ViewportSettingsFlags.TransparentMouse"/>),
31+
/// meaning mouse events in a popover that are not also within a subview of the popover will not be captured.
32+
/// </para>
33+
/// <para>
2934
/// <b>Custom Popovers:</b><br/>
3035
/// To create a custom popover, inherit from <see cref="PopoverBaseImpl"/> and add your own content and logic.
3136
/// </para>

Terminal.Gui/ViewBase/View.Layout.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1166,7 +1166,7 @@ out int ny
11661166

11671167
result.AddRange (GetViewsUnderLocation (visiblePopover, screenLocation, excludeViewportSettingsFlags));
11681168

1169-
if (result.Count > 1)
1169+
if (result.Count > 0)
11701170
{
11711171
return result;
11721172
}

Terminal.Gui/ViewBase/ViewportSettingsFlags.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,11 +153,9 @@ public enum ViewportSettingsFlags
153153
/// </summary>
154154
Transparent = 0b_0001_0000_0000,
155155

156-
// BUGBUG: The API docs here are wrong: If a TransparentMouse View has subviews, those subviews WILL get mouse events.
157-
// BUGBUG: That's an important feature that enables Popovers to work.
158156
/// <summary>
159-
/// 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
160-
/// Views below it.
157+
/// 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
158+
/// will not be captured by the View.
161159
/// <para>
162160
/// Combine this with <see cref="Transparent"/> to get a view that is both visually transparent and transparent to the mouse.
163161
/// </para>

Tests/UnitTests/Application/ApplicationPopoverTests.cs

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22

33
public class ApplicationPopoverTests
44
{
5-
6-
7-
85
[Fact]
96
public void Application_Init_Initializes_PopoverManager ()
107
{
@@ -203,6 +200,71 @@ public void Keyboard_Events_Go_Only_To_Popover_Associated_With_Toplevel ()
203200
Application.ResetState (true);
204201
}
205202

203+
// See: https://github.com/gui-cs/Terminal.Gui/issues/4122
204+
[Theory]
205+
[InlineData (0, 0, new [] { "top" })]
206+
[InlineData (10, 10, new string [] { })]
207+
[InlineData (1, 1, new [] { "top", "view" })]
208+
[InlineData (5, 5, new [] { "top" })]
209+
[InlineData (6, 6, new [] { "popoverSubView" })]
210+
[InlineData (7, 7, new [] { "top" })]
211+
[InlineData (3, 3, new [] { "top" })]
212+
public void GetViewsUnderMouse_Supports_ActivePopover (int mouseX, int mouseY, string [] viewIdStrings)
213+
{
214+
Application.ResetState (true);
215+
// Arrange
216+
Assert.Null (Application.Popover);
217+
Application.Init (new FakeDriver ());
218+
Application.Top = new ()
219+
{
220+
Frame = new (0, 0, 10, 10),
221+
Id = "top"
222+
};
223+
224+
View view = new ()
225+
{
226+
Id = "view",
227+
X = 1,
228+
Y = 1,
229+
Width = 2,
230+
Height = 2,
231+
}; // at 1,1 to 3,2 (screen)
232+
233+
Application.Top.Add (view);
234+
235+
PopoverTestClass popover = new ()
236+
{
237+
Id = "popover",
238+
X = 5,
239+
Y = 5,
240+
Width = 3,
241+
Height = 3,
242+
}; // at 5,5 to 8,8 (screen)
243+
244+
View popoverSubView = new ()
245+
{
246+
Id = "popoverSubView",
247+
X = 1,
248+
Y = 1,
249+
Width = 1,
250+
Height = 1,
251+
}; // at 6,6 to 7,7 (screen)
252+
253+
popover.Add (popoverSubView);
254+
255+
Application.Popover?.Show (popover);
256+
257+
List<View?> found = View.GetViewsUnderLocation (new (mouseX, mouseY), ViewportSettingsFlags.TransparentMouse);
258+
259+
string [] foundIds = found.Select (v => v!.Id).ToArray ();
260+
261+
Assert.Equal (viewIdStrings, foundIds);
262+
263+
popover.Dispose ();
264+
Application.Top.Dispose ();
265+
Application.ResetState (true);
266+
}
267+
206268
public class PopoverTestClass : PopoverBaseImpl
207269
{
208270
public List<Key> HandledKeys { get; } = [];

0 commit comments

Comments
 (0)