Skip to content

Commit

Permalink
Merge pull request #3327 from BDisp/v2_menu-mouse-fix_3326
Browse files Browse the repository at this point in the history
Fixes #3326. Menu is responding even outside the limits, not moving to the view that has the mouse.
  • Loading branch information
tig authored Mar 16, 2024
2 parents a5b1d68 + 2b3a67c commit f9332fd
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 6 deletions.
10 changes: 6 additions & 4 deletions Terminal.Gui/Views/Menu/Menu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -714,7 +714,7 @@ public override void OnVisibleChanged ()

private void Application_RootMouseEvent (object sender, MouseEventEventArgs a)
{
if (a.MouseEvent.View is MenuBar)
if (a.MouseEvent.View is { } and (MenuBar or not Menu))
{
return;
}
Expand All @@ -724,17 +724,19 @@ private void Application_RootMouseEvent (object sender, MouseEventEventArgs a)
throw new InvalidOperationException ("This shouldn't running on a invisible menu!");
}

Point boundsPoint = ScreenToBounds (a.MouseEvent.X, a.MouseEvent.Y);
View view = a.MouseEvent.View ?? this;

Point boundsPoint = view.ScreenToBounds (a.MouseEvent.X, a.MouseEvent.Y);
var me = new MouseEvent
{
X = boundsPoint.X,
Y = boundsPoint.Y,
Flags = a.MouseEvent.Flags,
ScreenPosition = new (a.MouseEvent.X, a.MouseEvent.Y),
View = this
View = view
};

if (OnMouseEvent (me) || a.MouseEvent.Flags == MouseFlags.Button1Pressed || a.MouseEvent.Flags == MouseFlags.Button1Released)
if (view.OnMouseEvent (me) || a.MouseEvent.Flags == MouseFlags.Button1Pressed || a.MouseEvent.Flags == MouseFlags.Button1Released)
{
a.MouseEvent.Handled = true;
}
Expand Down
123 changes: 121 additions & 2 deletions UnitTests/Views/ContextMenuTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1306,9 +1306,10 @@ public void UseSubMenusSingleFrame_True_By_Mouse ()
_output
);

// X=5 is the border and so need to use at least one more
Application.OnMouseEvent (
new MouseEventEventArgs (
new MouseEvent { X = 5, Y = 13, Flags = MouseFlags.Button1Clicked }
new MouseEvent { X = 6, Y = 13, Flags = MouseFlags.Button1Clicked }
)
);

Expand All @@ -1330,7 +1331,7 @@ public void UseSubMenusSingleFrame_True_By_Mouse ()

Application.OnMouseEvent (
new MouseEventEventArgs (
new MouseEvent { X = 5, Y = 12, Flags = MouseFlags.Button1Clicked }
new MouseEvent { X = 6, Y = 12, Flags = MouseFlags.Button1Clicked }
)
);

Expand All @@ -1351,6 +1352,124 @@ public void UseSubMenusSingleFrame_True_By_Mouse ()
Application.End (rs);
}

[Fact]
[AutoInitShutdown]
public void UseSubMenusSingleFrame_False_By_Mouse ()
{
var cm = new ContextMenu
{
Position = new Point (5, 10),
MenuItems = new MenuBarItem (
"Numbers",
[
new MenuItem ("One", "", null),
new MenuBarItem (
"Two",
[
new MenuItem (
"Two-Menu 1",
"",
null
),
new MenuItem ("Two-Menu 2", "", null)
]
),
new MenuBarItem ("Three",
[
new MenuItem (
"Three-Menu 1",
"",
null
),
new MenuItem ("Three-Menu 2", "", null)
]
)
]
)
};

cm.Show ();
RunState rs = Application.Begin (Application.Top);

Assert.Equal (new Rectangle (5, 11, 10, 5), Application.Top.Subviews [0].Frame);

TestHelpers.AssertDriverContentsWithFrameAre (
@"
┌────────┐
│ One │
│ Two ►│
│ Three ►│
└────────┘",
_output
);

Application.OnMouseEvent (
new MouseEventEventArgs (
new MouseEvent { X = 6, Y = 13, Flags = MouseFlags.ReportMousePosition }
)
);

var firstIteration = false;
Application.RunIteration (ref rs, ref firstIteration);
Assert.Equal (new Rectangle (5, 11, 10, 5), Application.Top.Subviews [0].Frame);

TestHelpers.AssertDriverContentsWithFrameAre (
@"
┌────────┐
│ One │
│ Two ►│┌─────────────┐
│ Three ►││ Two-Menu 1 │
└────────┘│ Two-Menu 2 │
└─────────────┘",
_output
);

Application.OnMouseEvent (
new MouseEventEventArgs (
new MouseEvent { X = 6, Y = 14, Flags = MouseFlags.ReportMousePosition }
)
);

firstIteration = false;
Application.RunIteration (ref rs, ref firstIteration);
Assert.Equal (new Rectangle (5, 11, 10, 5), Application.Top.Subviews [0].Frame);

TestHelpers.AssertDriverContentsWithFrameAre (
@"
┌────────┐
│ One │
│ Two ►│
│ Three ►│┌───────────────┐
└────────┘│ Three-Menu 1 │
│ Three-Menu 2 │
└───────────────┘",
_output
);

Application.OnMouseEvent (
new MouseEventEventArgs (
new MouseEvent { X = 6, Y = 13, Flags = MouseFlags.ReportMousePosition }
)
);

firstIteration = false;
Application.RunIteration (ref rs, ref firstIteration);
Assert.Equal (new Rectangle (5, 11, 10, 5), Application.Top.Subviews [0].Frame);

TestHelpers.AssertDriverContentsWithFrameAre (
@"
┌────────┐
│ One │
│ Two ►│┌─────────────┐
│ Three ►││ Two-Menu 1 │
└────────┘│ Two-Menu 2 │
└─────────────┘",
_output
);

Application.End (rs);
}

private ContextMenu Create_ContextMenu_With_Two_MenuItem (int x, int y)
{
return new ContextMenu
Expand Down
22 changes: 22 additions & 0 deletions UnitTests/Views/MenuBarTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3658,4 +3658,26 @@ public CustomWindow ()
Add (menu);
}
}

[Fact]
[AutoInitShutdown]
public void Click_Another_View_Close_An_Open_Menu ()
{
var menu = new MenuBar
{
Menus =
[
new MenuBarItem ("File", new MenuItem [] { new ("New", "", null) })
]
};

var btnClicked = false;
var btn = new Button { Y = 4, Text = "Test" };
btn.Accept += (s, e) => btnClicked = true;
Application.Top.Add (menu, btn);
Application.Begin (Application.Top);

Application.OnMouseEvent (new (new () { X = 0, Y = 4, Flags = MouseFlags.Button1Clicked }));
Assert.True (btnClicked);
}
}

0 comments on commit f9332fd

Please sign in to comment.