浏览代码

Refactored Enter event and added unit tests

Tig 10 月之前
父节点
当前提交
e95ff61fef

+ 14 - 7
Terminal.Gui/Application/Application.Mouse.cs

@@ -1,4 +1,5 @@
 #nullable enable
+using System.ComponentModel;
 using System.Diagnostics;
 using Microsoft.CodeAnalysis;
 using Microsoft.CodeAnalysis.VisualBasic.Syntax;
@@ -344,20 +345,26 @@ public static partial class Application // Mouse handling
 
             _cachedViewsUnderMouse.Add (view);
 
-            if (view is Adornment adornmentView)
+            bool raise = false;
+            if (view is Adornment { Parent: { } } adornmentView)
             {
                 Point frameLoc = view.ScreenToFrame (me.ScreenPosition);
-                if (adornmentView.Parent is { } && !adornmentView.Contains (frameLoc))
-                {
-                    view.NewMouseEnterEvent (me);
-                }
+                raise = adornmentView.Contains (frameLoc);
             }
             else
             {
                 Point superViewLoc = view.SuperView?.ScreenToViewport (me.ScreenPosition) ?? me.ScreenPosition;
-                if (view.Contains (superViewLoc))
+                raise = view.Contains (superViewLoc);
+            }
+
+            if (raise)
+            {
+                CancelEventArgs eventArgs = new ();
+                bool? cancelled = view.NewMouseEnterEvent (eventArgs);
+
+                if (cancelled is true || eventArgs.Cancel)
                 {
-                    view.NewMouseEnterEvent (me);
+                    break;
                 }
             }
         }

+ 1 - 32
Terminal.Gui/View/Adornment/Adornment.cs

@@ -1,4 +1,5 @@
 #nullable enable
+using System.ComponentModel;
 using Terminal.Gui;
 using Attribute = Terminal.Gui.Attribute;
 
@@ -227,37 +228,5 @@ public class Adornment : View
         return Thickness.Contains (frame, location);
     }
 
-    /// <inheritdoc/>
-    protected internal override bool? OnMouseEnter (MouseEvent mouseEvent)
-    {
-        //// Invert Normal
-        //if (Diagnostics.HasFlag (ViewDiagnosticFlags.MouseEnter) && ColorScheme != null)
-        //{
-        //    var cs = new ColorScheme (ColorScheme)
-        //    {
-        //        Normal = new (ColorScheme.Normal.Background, ColorScheme.Normal.Foreground)
-        //    };
-        //    ColorScheme = cs;
-        //}
-
-        return base.OnMouseEnter (mouseEvent);
-    }
-
-    /// <inheritdoc/>   
-    protected internal override bool OnMouseLeave (MouseEvent mouseEvent)
-    {
-        //// Invert Normal
-        //if (Diagnostics.FastHasFlags (ViewDiagnosticFlags.MouseEnter) && ColorScheme != null)
-        //{
-        //    var cs = new ColorScheme (ColorScheme)
-        //    {
-        //        Normal = new (ColorScheme.Normal.Background, ColorScheme.Normal.Foreground)
-        //    };
-        //    ColorScheme = cs;
-        //}
-
-        return base.OnMouseLeave (mouseEvent);
-    }
-
     #endregion Mouse Support
 }

+ 89 - 76
Terminal.Gui/View/View.Mouse.cs

@@ -31,9 +31,6 @@ public partial class View // Mouse APIs
     /// </remarks>
     public event EventHandler<MouseEventEventArgs>? MouseClick;
 
-    /// <summary>Event fired when the mouse moves into the View's <see cref="Viewport"/>.</summary>
-    public event EventHandler<MouseEventEventArgs>? MouseEnter;
-
     /// <summary>Event fired when a mouse event occurs.</summary>
     /// <remarks>
     ///     <para>
@@ -140,25 +137,100 @@ public partial class View // Mouse APIs
     /// <value><see langword="true"/> if mouse position reports are wanted; otherwise, <see langword="false"/>.</value>
     public virtual bool WantMousePositionReports { get; set; }
 
+    #region MouseEnterLeave
+
     /// <summary>
-    ///     Called by <see cref="NewMouseEvent"/> when the mouse enters <see cref="Viewport"/>. The view will
-    ///     then receive mouse events until <see cref="OnMouseLeave"/> is called indicating the mouse has left
-    ///     the view.
+    ///     INTERNAL Called by <see cref="Application.OnMouseEvent"/> when the mouse moves over the View's <see cref="Frame"/>.
+    ///     <see cref="MouseLeave"/> will
+    ///     be raised when the mouse is no longer over the <see cref="Frame"/>. If another View occludes this View, the
+    ///     that View will also receive MouseEnter/Leave events.
+    /// </summary>
+    /// <param name="eventArgs"></param>
+    /// <returns>
+    ///     <see langword="true"/> if the event was canceled, <see langword="false"/> if not, <see langword="null"/> if the
+    ///     view is not visible. Cancelling the event
+    ///     prevents Views higher in the visible hierarchy from receiving Enter/Leave events.
+    /// </returns>
+    internal bool? NewMouseEnterEvent (CancelEventArgs eventArgs)
+    {
+        if (!CanBeVisible (this))
+        {
+            return null;
+        }
+
+        if (OnMouseEnter (eventArgs))
+        {
+            return true;
+        }
+
+        MouseEnter?.Invoke (this, eventArgs);
+
+#if HOVER
+        if (HighlightStyle.HasFlag(HighlightStyle.Hover))
+        {
+            if (SetHighlight (HighlightStyle.Hover))
+            {
+                return true;
+            }
+        }
+#endif
+
+        return eventArgs.Cancel;
+    }
+
+    /// <summary>
+    ///     Called when the mouse moves over the View's <see cref="Frame"/> and no other non-Subview occludes it. <see cref="MouseLeave"/> will
+    ///     be raised when the mouse is no longer over the <see cref="Frame"/>. 
     /// </summary>
     /// <remarks>
     ///     <para>
-    ///         Override this method or subscribe to <see cref="MouseEnter"/> to change the default enter behavior.
+    ///         A view must be visible to receive Enter events (Leave events are always received).
     ///     </para>
     ///     <para>
-    ///         The coordinates are relative to <see cref="View.Viewport"/>.
+    ///         If the event is cancelled, the mouse event will not be propagated to other views and <see cref="MouseEnter"/>
+    ///         will not be raised.
+    ///     </para>
+    ///     <para>
+    ///         Adornments receive MouseEnter/Leave events when the mouse is over the Adornment's <see cref="Thickness"/>.
+    ///     </para>
+    ///     <para>
+    ///         See <see cref="SetHighlight"/> for more information.
     ///     </para>
     /// </remarks>
-    /// <param name="mouseEvent"></param>
-    /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
-    protected internal virtual bool? OnMouseEnter (MouseEvent mouseEvent)
-    {
-        return false;
-    }
+    /// <param name="eventArgs"></param>
+    /// <returns>
+    ///     <see langword="true"/> if the event was canceled, <see langword="false"/> if not. Cancelling the event
+    ///     prevents Views higher in the visible hierarchy from receiving Enter/Leave events.
+    /// </returns>
+    protected virtual bool OnMouseEnter (CancelEventArgs eventArgs) { return false; }
+
+    /// <summary>
+    ///     Raised when the mouse moves over the View's <see cref="Frame"/>. <see cref="MouseLeave"/> will
+    ///     be raised when the mouse is no longer over the <see cref="Frame"/>. If another View occludes this View, the
+    ///     that View will also receive MouseEnter/Leave events.
+    /// </summary>
+    /// <remarks>
+    ///     <para>
+    ///         A view must be visible to receive Enter events (Leave events are always received).
+    ///     </para>
+    ///     <para>
+    ///         If the event is cancelled, the mouse event will not be propagated to other views.
+    ///     </para>
+    ///     <para>
+    ///         Adornments receive MouseEnter/Leave events when the mouse is over the Adornment's <see cref="Thickness"/>.
+    ///     </para>
+    ///     <para>
+    ///         Set <see cref="CancelEventArgs.Cancel"/> to <see langword="true"/> if the event was canceled,
+    ///         <see langword="false"/> if not. Cancelling the event
+    ///         prevents Views higher in the visible hierarchy from receiving Enter/Leave events.
+    ///     </para>
+    ///     <para>
+    ///         See <see cref="SetHighlight"/> for more information.
+    ///     </para>
+    /// </remarks>
+    public event EventHandler<CancelEventArgs>? MouseEnter;
+
+    #endregion MouseEnterLeave
 
     /// <summary>Called when a mouse event occurs within the view's <see cref="Viewport"/>.</summary>
     /// <remarks>
@@ -191,10 +263,7 @@ public partial class View // Mouse APIs
     /// </remarks>
     /// <param name="mouseEvent"></param>
     /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
-    protected internal virtual bool OnMouseLeave (MouseEvent mouseEvent)
-    {
-        return false;
-    }
+    protected internal virtual bool OnMouseLeave (MouseEvent mouseEvent) { return false; }
 
     /// <summary>
     ///     Called when the view is to be highlighted.
@@ -316,61 +385,6 @@ public partial class View // Mouse APIs
         return false;
     }
 
-    /// <summary>
-    ///     INTERNAL Called by <see cref="Application.OnMouseEvent"/> when the mouse moves over the View's <see cref="Frame"/>. <see cref="MouseLeave"/> will
-    ///     be raised when the mouse is no longer over the <see cref="Frame"/>. If another View occludes this View, the
-    ///     that View will also receive MouseEnter/Leave events.
-    /// </summary>
-    /// <remarks>
-    ///     <para>
-    ///         A view must be visible to receive Enter events (Leave events are always received).
-    ///     </para>
-    ///     <para>
-    ///         This method calls <see cref="OnMouseEnter"/> to raise the <see cref="MouseEnter"/> event.
-    ///     </para>
-    ///     <para>
-    ///         Adornments receive MouseEnter/Leave events when the mouse is over the Adornment's <see cref="Thickness"/>.
-    ///     </para>
-    ///     <para>
-    ///         See <see cref="SetHighlight"/> for more information.
-    ///     </para>
-    /// </remarks>
-    /// <param name="mouseEvent"></param>
-    /// <returns><see langword="true"/> if the event was handled, <see langword="false"/> otherwise. Handling the event
-    /// prevents Views higher in the visible hierarchy from receiving Enter/Leave events.</returns>
-    internal bool? NewMouseEnterEvent (MouseEvent mouseEvent)
-    {
-        if (!Enabled)
-        {
-            return false;
-        }
-
-        if (!CanBeVisible (this))
-        {
-            return false;
-        }
-
-        if (OnMouseEnter (mouseEvent) == true)
-        {
-            return true;
-        }
-
-        var args = new MouseEventEventArgs (mouseEvent);
-        MouseEnter?.Invoke (this, args);
-
-#if HOVER
-        if (HighlightStyle.HasFlag(HighlightStyle.Hover))
-        {
-            if (SetHighlight (HighlightStyle.Hover))
-            {
-                return true;
-            }
-        }
-#endif
-
-        return args.Handled;
-    }
-
     /// <summary>
     ///     INTERNAL Called by <see cref="Application.OnMouseEvent"/> when the mouse leaves <see cref="Frame"/>.
     /// </summary>
@@ -435,7 +449,7 @@ public partial class View // Mouse APIs
 
         // Enable override via virtual method and/or event
         HighlightStyle copy = HighlightStyle;
-        var args = new CancelEventArgs<HighlightStyle> (ref copy, ref newHighlightStyle);
+        CancelEventArgs<HighlightStyle> args = new (ref copy, ref newHighlightStyle);
 
         if (OnHighlight (args) == true)
         {
@@ -565,7 +579,7 @@ public partial class View // Mouse APIs
     }
 
     /// <summary>
-    ///    INTERNAL: Gets the Views that are under the mouse at <paramref name="location"/>, including Adornments.
+    ///     INTERNAL: Gets the Views that are under the mouse at <paramref name="location"/>, including Adornments.
     /// </summary>
     /// <param name="location"></param>
     /// <returns></returns>
@@ -636,5 +650,4 @@ public partial class View // Mouse APIs
 
         return viewsUnderMouse;
     }
-
 }

+ 3 - 1
Terminal.Gui/Views/ScrollView.cs

@@ -11,6 +11,8 @@
 // - Raise events
 // - Perhaps allow an option to not display the scrollbar arrow indicators?
 
+using System.ComponentModel;
+
 namespace Terminal.Gui;
 
 /// <summary>
@@ -743,7 +745,7 @@ public class ScrollView : View
         }
     }
 
-    private void View_MouseEnter (object sender, MouseEventEventArgs e) { Application.GrabMouse (this); }
+    private void View_MouseEnter (object sender, CancelEventArgs e) { Application.GrabMouse (this); }
 
     private void View_MouseLeave (object sender, MouseEventEventArgs e)
     {

+ 2 - 1
UICatalog/Scenarios/Mouse.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.ObjectModel;
+using System.ComponentModel;
 using System.Linq;
 using Terminal.Gui;
 
@@ -245,7 +246,7 @@ public class Mouse : Scenario
                 Padding.MouseEnter += PaddingOnMouseEnter;
                 Padding.MouseLeave += PaddingOnMouseLeave;
 
-                void PaddingOnMouseEnter (object o, MouseEventEventArgs mouseEventEventArgs)
+                void PaddingOnMouseEnter (object o, CancelEventArgs e)
                 {
                     Padding.ColorScheme = Colors.ColorSchemes ["Error"];
                 }

+ 576 - 0
UnitTests/Application/Mouse/ApplicationMouseEnterLeaveTests.cs

@@ -0,0 +1,576 @@
+using System.ComponentModel;
+
+namespace Terminal.Gui.ViewMouseTests;
+
+[Trait ("Category", "Input")]
+public class ApplicationMouseEnterLeaveTests
+{
+    private class TestView : View
+    {
+        public TestView ()
+        {
+            X = 1;
+            Y = 1;
+            Width = 1;
+            Height = 1;
+        }
+
+        public bool CancelOnEnter { get; }
+        public int OnMouseEnterCalled { get; private set; }
+        public int OnMouseLeaveCalled { get; private set; }
+
+        protected override bool OnMouseEnter (CancelEventArgs eventArgs)
+        {
+            OnMouseEnterCalled++;
+            eventArgs.Cancel = CancelOnEnter;
+
+            base.OnMouseEnter (eventArgs);
+
+            return eventArgs.Cancel;
+        }
+
+        protected internal override bool OnMouseLeave (MouseEvent mouseEvent)
+        {
+            OnMouseLeaveCalled++;
+
+            base.OnMouseLeave (mouseEvent);
+
+            return mouseEvent.Handled;
+        }
+    }
+
+    [Fact]
+    public void RaiseMouseEnterLeaveEvents_MouseEntersView_CallsOnMouseEnter ()
+    {
+        // Arrange
+        Application.Top = new () { Frame = new (0, 0, 10, 10) };
+        var view = new TestView ();
+        Application.Top.Add (view);
+        var mousePosition = new Point (1, 1);
+        List<View> currentViewsUnderMouse = new () { view };
+
+        var mouseEvent = new MouseEvent
+        {
+            Position = mousePosition,
+            ScreenPosition = mousePosition
+        };
+
+        Application._cachedViewsUnderMouse.Clear ();
+
+        try
+        {
+            // Act
+            Application.RaiseMouseEnterLeaveEvents (mousePosition, currentViewsUnderMouse, mouseEvent);
+
+            // Assert
+            Assert.Equal (1, view.OnMouseEnterCalled);
+        }
+        finally
+        {
+            // Cleanup
+            Application.Top?.Dispose ();
+            Application.ResetState ();
+        }
+    }
+
+    [Fact]
+    public void RaiseMouseEnterLeaveEvents_MouseLeavesView_CallsOnMouseLeave ()
+    {
+        // Arrange
+        Application.Top = new () { Frame = new (0, 0, 10, 10) };
+        var view = new TestView ();
+        Application.Top.Add (view);
+        var mousePosition = new Point (0, 0);
+        List<View> currentViewsUnderMouse = new ();
+        var mouseEvent = new MouseEvent ();
+
+        Application._cachedViewsUnderMouse.Clear ();
+        Application._cachedViewsUnderMouse.Add (view);
+
+        try
+        {
+            // Act
+            Application.RaiseMouseEnterLeaveEvents (mousePosition, currentViewsUnderMouse, mouseEvent);
+
+            // Assert
+            Assert.Equal (0, view.OnMouseEnterCalled);
+            Assert.Equal (1, view.OnMouseLeaveCalled);
+        }
+        finally
+        {
+            // Cleanup
+            Application.Top?.Dispose ();
+            Application.ResetState ();
+        }
+    }
+
+    [Fact]
+    public void RaiseMouseEnterLeaveEvents_MouseMovesBetweenAdjacentViews_CallsOnMouseEnterAndLeave ()
+    {
+        // Arrange
+        Application.Top = new () { Frame = new (0, 0, 10, 10) };
+        var view1 = new TestView (); // at 1,1 to 2,2
+
+        var view2 = new TestView () // at 2,2 to 3,3
+        {
+            X = 2,
+            Y = 2
+        };
+        Application.Top.Add (view1);
+        Application.Top.Add (view2);
+
+        Application._cachedViewsUnderMouse.Clear ();
+
+        try
+        {
+            // Act
+            var mousePosition = new Point (0, 0);
+
+            Application.RaiseMouseEnterLeaveEvents (
+                                                    mousePosition,
+                                                    View.GetViewsUnderMouse (mousePosition),
+                                                    new()
+                                                    {
+                                                        Position = mousePosition,
+                                                        ScreenPosition = mousePosition
+                                                    });
+
+            // Assert
+            Assert.Equal (0, view1.OnMouseEnterCalled);
+            Assert.Equal (0, view1.OnMouseLeaveCalled);
+            Assert.Equal (0, view2.OnMouseEnterCalled);
+            Assert.Equal (0, view2.OnMouseLeaveCalled);
+
+            // Act
+            mousePosition = new (1, 1);
+
+            Application.RaiseMouseEnterLeaveEvents (
+                                                    mousePosition,
+                                                    View.GetViewsUnderMouse (mousePosition),
+                                                    new()
+                                                    {
+                                                        Position = mousePosition,
+                                                        ScreenPosition = mousePosition
+                                                    });
+
+            // Assert
+            Assert.Equal (1, view1.OnMouseEnterCalled);
+            Assert.Equal (0, view1.OnMouseLeaveCalled);
+            Assert.Equal (0, view2.OnMouseEnterCalled);
+            Assert.Equal (0, view2.OnMouseLeaveCalled);
+
+            // Act
+            mousePosition = new (2, 2);
+
+            Application.RaiseMouseEnterLeaveEvents (
+                                                    mousePosition,
+                                                    View.GetViewsUnderMouse (mousePosition),
+                                                    new()
+                                                    {
+                                                        Position = mousePosition,
+                                                        ScreenPosition = mousePosition
+                                                    });
+
+            // Assert
+            Assert.Equal (1, view1.OnMouseEnterCalled);
+            Assert.Equal (1, view1.OnMouseLeaveCalled);
+            Assert.Equal (1, view2.OnMouseEnterCalled);
+            Assert.Equal (0, view2.OnMouseLeaveCalled);
+
+            // Act
+            mousePosition = new (3, 3);
+
+            Application.RaiseMouseEnterLeaveEvents (
+                                                    mousePosition,
+                                                    View.GetViewsUnderMouse (mousePosition),
+                                                    new()
+                                                    {
+                                                        Position = mousePosition,
+                                                        ScreenPosition = mousePosition
+                                                    });
+
+            // Assert
+            Assert.Equal (1, view1.OnMouseEnterCalled);
+            Assert.Equal (1, view1.OnMouseLeaveCalled);
+            Assert.Equal (1, view2.OnMouseEnterCalled);
+            Assert.Equal (1, view2.OnMouseLeaveCalled);
+
+            // Act
+            mousePosition = new (0, 0);
+
+            Application.RaiseMouseEnterLeaveEvents (
+                                                    mousePosition,
+                                                    View.GetViewsUnderMouse (mousePosition),
+                                                    new()
+                                                    {
+                                                        Position = mousePosition,
+                                                        ScreenPosition = mousePosition
+                                                    });
+
+            // Assert
+            Assert.Equal (1, view1.OnMouseEnterCalled);
+            Assert.Equal (1, view1.OnMouseLeaveCalled);
+            Assert.Equal (1, view2.OnMouseEnterCalled);
+            Assert.Equal (1, view2.OnMouseLeaveCalled);
+        }
+        finally
+        {
+            // Cleanup
+            Application.Top?.Dispose ();
+            Application.ResetState ();
+        }
+    }
+
+    [Fact]
+    public void RaiseMouseEnterLeaveEvents_NoViewsUnderMouse_DoesNotCallOnMouseEnterOrLeave ()
+    {
+        // Arrange
+        Application.Top = new () { Frame = new (0, 0, 10, 10) };
+        var view = new TestView ();
+        Application.Top.Add (view);
+        var mousePosition = new Point (0, 0);
+        List<View> currentViewsUnderMouse = new ();
+        var mouseEvent = new MouseEvent ();
+
+        Application._cachedViewsUnderMouse.Clear ();
+
+        try
+        {
+            // Act
+            Application.RaiseMouseEnterLeaveEvents (mousePosition, currentViewsUnderMouse, mouseEvent);
+
+            // Assert
+            Assert.Equal (0, view.OnMouseEnterCalled);
+            Assert.Equal (0, view.OnMouseLeaveCalled);
+        }
+        finally
+        {
+            // Cleanup
+            Application.Top?.Dispose ();
+            Application.ResetState ();
+        }
+    }
+
+    [Fact]
+    public void RaiseMouseEnterLeaveEvents_MouseMovesBetweenOverlappingPeerViews_CallsOnMouseEnterAndLeave ()
+    {
+        // Arrange
+        Application.Top = new () { Frame = new (0, 0, 10, 10) };
+
+        var view1 = new TestView
+        {
+            Width = 2
+        }; // at 1,1 to 3,2
+
+        var view2 = new TestView () // at 2,2 to 4,3
+        {
+            Width = 2,
+            X = 2,
+            Y = 2
+        };
+        Application.Top.Add (view1);
+        Application.Top.Add (view2);
+
+        Application._cachedViewsUnderMouse.Clear ();
+
+        try
+        {
+            // Act
+            var mousePosition = new Point (0, 0);
+
+            Application.RaiseMouseEnterLeaveEvents (
+                                                    mousePosition,
+                                                    View.GetViewsUnderMouse (mousePosition),
+                                                    new()
+                                                    {
+                                                        Position = mousePosition,
+                                                        ScreenPosition = mousePosition
+                                                    });
+
+            // Assert
+            Assert.Equal (0, view1.OnMouseEnterCalled);
+            Assert.Equal (0, view1.OnMouseLeaveCalled);
+            Assert.Equal (0, view2.OnMouseEnterCalled);
+            Assert.Equal (0, view2.OnMouseLeaveCalled);
+
+            // Act
+            mousePosition = new (1, 1);
+
+            Application.RaiseMouseEnterLeaveEvents (
+                                                    mousePosition,
+                                                    View.GetViewsUnderMouse (mousePosition),
+                                                    new()
+                                                    {
+                                                        Position = mousePosition,
+                                                        ScreenPosition = mousePosition
+                                                    });
+
+            // Assert
+            Assert.Equal (1, view1.OnMouseEnterCalled);
+            Assert.Equal (0, view1.OnMouseLeaveCalled);
+            Assert.Equal (0, view2.OnMouseEnterCalled);
+            Assert.Equal (0, view2.OnMouseLeaveCalled);
+
+            // Act
+            mousePosition = new (2, 2);
+
+            Application.RaiseMouseEnterLeaveEvents (
+                                                    mousePosition,
+                                                    View.GetViewsUnderMouse (mousePosition),
+                                                    new()
+                                                    {
+                                                        Position = mousePosition,
+                                                        ScreenPosition = mousePosition
+                                                    });
+
+            // Assert
+            Assert.Equal (1, view1.OnMouseEnterCalled);
+            Assert.Equal (1, view1.OnMouseLeaveCalled);
+            Assert.Equal (1, view2.OnMouseEnterCalled);
+            Assert.Equal (0, view2.OnMouseLeaveCalled);
+
+            // Act
+            mousePosition = new (3, 3);
+
+            Application.RaiseMouseEnterLeaveEvents (
+                                                    mousePosition,
+                                                    View.GetViewsUnderMouse (mousePosition),
+                                                    new()
+                                                    {
+                                                        Position = mousePosition,
+                                                        ScreenPosition = mousePosition
+                                                    });
+
+            // Assert
+            Assert.Equal (1, view1.OnMouseEnterCalled);
+            Assert.Equal (1, view1.OnMouseLeaveCalled);
+            Assert.Equal (1, view2.OnMouseEnterCalled);
+            Assert.Equal (1, view2.OnMouseLeaveCalled);
+
+            // Act
+            mousePosition = new (0, 0);
+
+            Application.RaiseMouseEnterLeaveEvents (
+                                                    mousePosition,
+                                                    View.GetViewsUnderMouse (mousePosition),
+                                                    new()
+                                                    {
+                                                        Position = mousePosition,
+                                                        ScreenPosition = mousePosition
+                                                    });
+
+            // Assert
+            Assert.Equal (1, view1.OnMouseEnterCalled);
+            Assert.Equal (1, view1.OnMouseLeaveCalled);
+            Assert.Equal (1, view2.OnMouseEnterCalled);
+            Assert.Equal (1, view2.OnMouseLeaveCalled);
+
+            // Act
+            mousePosition = new (2, 2);
+
+            Application.RaiseMouseEnterLeaveEvents (
+                                                    mousePosition,
+                                                    View.GetViewsUnderMouse (mousePosition),
+                                                    new()
+                                                    {
+                                                        Position = mousePosition,
+                                                        ScreenPosition = mousePosition
+                                                    });
+
+            // Assert
+            Assert.Equal (1, view1.OnMouseEnterCalled);
+            Assert.Equal (1, view1.OnMouseLeaveCalled);
+            Assert.Equal (2, view2.OnMouseEnterCalled);
+            Assert.Equal (1, view2.OnMouseLeaveCalled);
+        }
+        finally
+        {
+            // Cleanup
+            Application.Top?.Dispose ();
+            Application.ResetState ();
+        }
+    }
+
+    [Fact]
+    public void RaiseMouseEnterLeaveEvents_MouseMovesBetweenOverlappingSubViews_CallsOnMouseEnterAndLeave ()
+    {
+        // Arrange
+        Application.Top = new () { Frame = new (0, 0, 10, 10) };
+
+        var view1 = new TestView
+        {
+            Width = 2,
+            Height = 2,
+            Arrangement = ViewArrangement.Overlapped
+        }; // at 1,1 to 3,3 (screen)
+
+        var subView = new TestView
+        {
+            Width = 2,
+            Height = 2,
+            X = 1,
+            Y = 1,
+            Arrangement = ViewArrangement.Overlapped
+        }; // at 2,2 to 4,4 (screen)
+        view1.Add (subView);
+        Application.Top.Add (view1);
+
+        Application._cachedViewsUnderMouse.Clear ();
+
+        try
+        {
+            Assert.Equal (1, view1.FrameToScreen ().X);
+            Assert.Equal (2, subView.FrameToScreen ().X);
+
+            // Act
+            var mousePosition = new Point (0, 0);
+
+            Application.RaiseMouseEnterLeaveEvents (
+                                                    mousePosition,
+                                                    View.GetViewsUnderMouse (mousePosition),
+                                                    new()
+                                                    {
+                                                        Position = mousePosition,
+                                                        ScreenPosition = mousePosition
+                                                    });
+
+            // Assert
+            Assert.Equal (0, view1.OnMouseEnterCalled);
+            Assert.Equal (0, view1.OnMouseLeaveCalled);
+            Assert.Equal (0, subView.OnMouseEnterCalled);
+            Assert.Equal (0, subView.OnMouseLeaveCalled);
+
+            // Act
+            mousePosition = new (1, 1);
+
+            Application.RaiseMouseEnterLeaveEvents (
+                                                    mousePosition,
+                                                    View.GetViewsUnderMouse (mousePosition),
+                                                    new()
+                                                    {
+                                                        Position = mousePosition,
+                                                        ScreenPosition = mousePosition
+                                                    });
+
+            // Assert
+            Assert.Equal (1, view1.OnMouseEnterCalled);
+            Assert.Equal (0, view1.OnMouseLeaveCalled);
+            Assert.Equal (0, subView.OnMouseEnterCalled);
+            Assert.Equal (0, subView.OnMouseLeaveCalled);
+
+            // Act
+            mousePosition = new (2, 2);
+
+            Application.RaiseMouseEnterLeaveEvents (
+                                                    mousePosition,
+                                                    View.GetViewsUnderMouse (mousePosition),
+                                                    new()
+                                                    {
+                                                        Position = mousePosition,
+                                                        ScreenPosition = mousePosition
+                                                    });
+
+            // Assert
+            Assert.Equal (2, view1.OnMouseEnterCalled);
+            Assert.Equal (0, view1.OnMouseLeaveCalled);
+            Assert.Equal (1, subView.OnMouseEnterCalled);
+            Assert.Equal (0, subView.OnMouseLeaveCalled);
+
+            // Act
+            mousePosition = new (0, 0);
+
+            Application.RaiseMouseEnterLeaveEvents (
+                                                    mousePosition,
+                                                    View.GetViewsUnderMouse (mousePosition),
+                                                    new()
+                                                    {
+                                                        Position = mousePosition,
+                                                        ScreenPosition = mousePosition
+                                                    });
+
+            // Assert
+            Assert.Equal (2, view1.OnMouseEnterCalled);
+            Assert.Equal (1, view1.OnMouseLeaveCalled);
+            Assert.Equal (1, subView.OnMouseEnterCalled);
+            Assert.Equal (1, subView.OnMouseLeaveCalled);
+
+            // Act
+            mousePosition = new (2, 2);
+
+            Application.RaiseMouseEnterLeaveEvents (
+                                                    mousePosition,
+                                                    View.GetViewsUnderMouse (mousePosition),
+                                                    new()
+                                                    {
+                                                        Position = mousePosition,
+                                                        ScreenPosition = mousePosition
+                                                    });
+
+            // Assert
+            Assert.Equal (3, view1.OnMouseEnterCalled);
+            Assert.Equal (1, view1.OnMouseLeaveCalled);
+            Assert.Equal (2, subView.OnMouseEnterCalled);
+            Assert.Equal (1, subView.OnMouseLeaveCalled);
+
+            // Act
+            mousePosition = new (3, 3);
+
+            Application.RaiseMouseEnterLeaveEvents (
+                                                    mousePosition,
+                                                    View.GetViewsUnderMouse (mousePosition),
+                                                    new()
+                                                    {
+                                                        Position = mousePosition,
+                                                        ScreenPosition = mousePosition
+                                                    });
+
+            // Assert
+            Assert.Equal (3, view1.OnMouseEnterCalled);
+            Assert.Equal (2, view1.OnMouseLeaveCalled);
+            Assert.Equal (2, subView.OnMouseEnterCalled);
+            Assert.Equal (1, subView.OnMouseLeaveCalled);
+
+            // Act
+            mousePosition = new (0, 0);
+
+            Application.RaiseMouseEnterLeaveEvents (
+                                                    mousePosition,
+                                                    View.GetViewsUnderMouse (mousePosition),
+                                                    new()
+                                                    {
+                                                        Position = mousePosition,
+                                                        ScreenPosition = mousePosition
+                                                    });
+
+            // Assert
+            Assert.Equal (3, view1.OnMouseEnterCalled);
+            Assert.Equal (2, view1.OnMouseLeaveCalled);
+            Assert.Equal (2, subView.OnMouseEnterCalled);
+            Assert.Equal (1, subView.OnMouseLeaveCalled);
+
+            // Act
+            mousePosition = new (2, 2);
+
+            Application.RaiseMouseEnterLeaveEvents (
+                                                    mousePosition,
+                                                    View.GetViewsUnderMouse (mousePosition),
+                                                    new()
+                                                    {
+                                                        Position = mousePosition,
+                                                        ScreenPosition = mousePosition
+                                                    });
+
+            // Assert
+            Assert.Equal (4, view1.OnMouseEnterCalled);
+            Assert.Equal (2, view1.OnMouseLeaveCalled);
+            Assert.Equal (3, subView.OnMouseEnterCalled);
+            Assert.Equal (1, subView.OnMouseLeaveCalled);
+        }
+        finally
+        {
+            // Cleanup
+            Application.Top?.Dispose ();
+            Application.ResetState ();
+        }
+    }
+}

+ 4 - 2
UnitTests/Application/Mouse/MouseTests.cs → UnitTests/Application/Mouse/ApplicationMouseTests.cs

@@ -4,11 +4,12 @@
 
 namespace Terminal.Gui.ApplicationTests;
 
-public class MouseTests
+[Trait ("Category", "Input")]
+public class ApplicationMouseTests
 {
     private readonly ITestOutputHelper _output;
 
-    public MouseTests (ITestOutputHelper output)
+    public ApplicationMouseTests (ITestOutputHelper output)
     {
         _output = output;
 #if DEBUG_IDISPOSABLE
@@ -401,5 +402,6 @@ public class MouseTests
         Assert.Equal (0, count);
         top.Dispose ();
     }
+
     #endregion
 }

+ 0 - 337
UnitTests/Application/Mouse/MouseEnterLeaveTests.cs

@@ -1,337 +0,0 @@
-namespace Terminal.Gui.ViewMouseTests;
-
-[Trait ("Category", "Input")]
-public class ApplicationMouseEnterLeaveTests
-{
-    private class TestView : View
-    {
-        public TestView ()
-        {
-            X = 1;
-            Y = 1;
-            Width = 1;
-            Height = 1;
-        }
-
-        public bool HandleOnEnter { get; }
-        public bool HandleOnLeave { get; }
-
-        public int OnMouseEnterCalled { get; private set; }
-        public int OnMouseLeaveCalled { get; private set; }
-
-        protected internal override bool? OnMouseEnter (MouseEvent mouseEvent)
-        {
-            OnMouseEnterCalled++;
-            mouseEvent.Handled = HandleOnEnter;
-
-            base.OnMouseEnter (mouseEvent);
-
-            return mouseEvent.Handled;
-        }
-
-        protected internal override bool OnMouseLeave (MouseEvent mouseEvent)
-        {
-            OnMouseLeaveCalled++;
-            mouseEvent.Handled = HandleOnLeave;
-
-            base.OnMouseLeave (mouseEvent);
-
-            return mouseEvent.Handled;
-        }
-    }
-
-    [Fact]
-    public void RaiseMouseEnterLeaveEvents_MouseEntersView_CallsOnMouseEnter ()
-    {
-        // Arrange
-        Application.Top = new () { Frame = new (0, 0, 10, 10) };
-        var view = new TestView ();
-        Application.Top.Add (view);
-        var mousePosition = new Point (1, 1);
-        List<View> currentViewsUnderMouse = new () { view };
-        var mouseEvent = new MouseEvent ()
-        {
-            Position = mousePosition,
-            ScreenPosition = mousePosition
-        };
-
-        Application._cachedViewsUnderMouse.Clear ();
-
-        try
-        {
-            // Act
-            Application.RaiseMouseEnterLeaveEvents (mousePosition, currentViewsUnderMouse, mouseEvent);
-
-            // Assert
-            Assert.Equal (1, view.OnMouseEnterCalled);
-        }
-        finally
-        {
-            // Cleanup
-            Application.Top?.Dispose ();
-            Application.ResetState ();
-        }
-    }
-
-    [Fact]
-    public void RaiseMouseEnterLeaveEvents_MouseLeavesView_CallsOnMouseLeave ()
-    {
-        // Arrange
-        Application.Top = new () { Frame = new (0, 0, 10, 10) };
-        var view = new TestView ();
-        Application.Top.Add (view);
-        var mousePosition = new Point (0, 0);
-        List<View> currentViewsUnderMouse = new ();
-        var mouseEvent = new MouseEvent ();
-
-        Application._cachedViewsUnderMouse.Clear ();
-        Application._cachedViewsUnderMouse.Add (view);
-
-        try
-        {
-            // Act
-            Application.RaiseMouseEnterLeaveEvents (mousePosition, currentViewsUnderMouse, mouseEvent);
-
-            // Assert
-            Assert.Equal (0, view.OnMouseEnterCalled);
-            Assert.Equal (1, view.OnMouseLeaveCalled);
-        }
-        finally
-        {
-            // Cleanup
-            Application.Top?.Dispose ();
-            Application.ResetState ();
-        }
-    }
-
-    [Fact]
-    public void RaiseMouseEnterLeaveEvents_MouseMovesBetweenAdjacentViews_CallsOnMouseEnterAndLeave ()
-    {
-        // Arrange
-        Application.Top = new () { Frame = new (0, 0, 10, 10) };
-        var view1 = new TestView (); // at 1,1 to 2,2
-        var view2 = new TestView () // at 2,2 to 3,3
-        {
-            X = 2,
-            Y = 2,
-        };
-        Application.Top.Add (view1);
-        Application.Top.Add (view2);
-
-
-
-        Application._cachedViewsUnderMouse.Clear ();
-
-        try
-        {
-            // Act
-            var mousePosition = new Point (0, 0);
-            Application.RaiseMouseEnterLeaveEvents (mousePosition, View.GetViewsUnderMouse (mousePosition), new MouseEvent ()
-            {
-                Position = mousePosition,
-                ScreenPosition = mousePosition
-            });
-
-            // Assert
-            Assert.Equal (0, view1.OnMouseEnterCalled);
-            Assert.Equal (0, view1.OnMouseLeaveCalled);
-            Assert.Equal (0, view2.OnMouseEnterCalled);
-            Assert.Equal (0, view2.OnMouseLeaveCalled);
-
-            // Act
-            mousePosition = new Point (1, 1);
-            Application.RaiseMouseEnterLeaveEvents (mousePosition, View.GetViewsUnderMouse (mousePosition), new MouseEvent ()
-            {
-                Position = mousePosition,
-                ScreenPosition = mousePosition
-            });
-
-            // Assert
-            Assert.Equal (1, view1.OnMouseEnterCalled);
-            Assert.Equal (0, view1.OnMouseLeaveCalled);
-            Assert.Equal (0, view2.OnMouseEnterCalled);
-            Assert.Equal (0, view2.OnMouseLeaveCalled);
-
-            // Act
-            mousePosition = new Point (2, 2);
-            Application.RaiseMouseEnterLeaveEvents (mousePosition, View.GetViewsUnderMouse (mousePosition), new MouseEvent ()
-            {
-                Position = mousePosition,
-                ScreenPosition = mousePosition
-            });
-
-            // Assert
-            Assert.Equal (1, view1.OnMouseEnterCalled);
-            Assert.Equal (1, view1.OnMouseLeaveCalled);
-            Assert.Equal (1, view2.OnMouseEnterCalled);
-            Assert.Equal (0, view2.OnMouseLeaveCalled);
-
-
-            // Act
-            mousePosition = new Point (3, 3);
-            Application.RaiseMouseEnterLeaveEvents (mousePosition, View.GetViewsUnderMouse (mousePosition), new MouseEvent ()
-            {
-                Position = mousePosition,
-                ScreenPosition = mousePosition
-            });
-
-            // Assert
-            Assert.Equal (1, view1.OnMouseEnterCalled);
-            Assert.Equal (1, view1.OnMouseLeaveCalled);
-            Assert.Equal (1, view2.OnMouseEnterCalled);
-            Assert.Equal (1, view2.OnMouseLeaveCalled);
-
-            // Act
-            mousePosition = new Point (0, 0);
-            Application.RaiseMouseEnterLeaveEvents (mousePosition, View.GetViewsUnderMouse (mousePosition), new MouseEvent ()
-            {
-                Position = mousePosition,
-                ScreenPosition = mousePosition
-            });
-
-            // Assert
-            Assert.Equal (1, view1.OnMouseEnterCalled);
-            Assert.Equal (1, view1.OnMouseLeaveCalled);
-            Assert.Equal (1, view2.OnMouseEnterCalled);
-            Assert.Equal (1, view2.OnMouseLeaveCalled);
-        }
-        finally
-        {
-            // Cleanup
-            Application.Top?.Dispose ();
-            Application.ResetState ();
-        }
-    }
-
-    [Fact]
-    public void RaiseMouseEnterLeaveEvents_NoViewsUnderMouse_DoesNotCallOnMouseEnterOrLeave ()
-    {
-        // Arrange
-        Application.Top = new () { Frame = new (0, 0, 10, 10) };
-        var view = new TestView ();
-        Application.Top.Add (view);
-        var mousePosition = new Point (0, 0);
-        List<View> currentViewsUnderMouse = new ();
-        var mouseEvent = new MouseEvent ();
-
-        Application._cachedViewsUnderMouse.Clear ();
-
-        try
-        {
-            // Act
-            Application.RaiseMouseEnterLeaveEvents (mousePosition, currentViewsUnderMouse, mouseEvent);
-
-            // Assert
-            Assert.Equal (0, view.OnMouseEnterCalled);
-            Assert.Equal (0, view.OnMouseLeaveCalled);
-        }
-        finally
-        {
-            // Cleanup
-            Application.Top?.Dispose ();
-            Application.ResetState ();
-        }
-    }
-
-
-    [Fact]
-    public void RaiseMouseEnterLeaveEvents_MouseMovesBetweenOverlappingViews_CallsOnMouseEnterAndLeave ()
-    {
-        // Arrange
-        Application.Top = new () { Frame = new (0, 0, 10, 10) };
-        var view1 = new TestView ()
-        {
-            Width = 2
-        }; // at 1,1 to 3,2
-        var view2 = new TestView () // at 2,2 to 4,3
-        {
-            Width = 2,
-            X = 2,
-            Y = 2,
-        };
-        Application.Top.Add (view1);
-        Application.Top.Add (view2);
-
-        Application._cachedViewsUnderMouse.Clear ();
-
-        try
-        {
-            // Act
-            var mousePosition = new Point (0, 0);
-            Application.RaiseMouseEnterLeaveEvents (mousePosition, View.GetViewsUnderMouse (mousePosition), new MouseEvent ()
-            {
-                Position = mousePosition,
-                ScreenPosition = mousePosition
-            });
-
-            // Assert
-            Assert.Equal (0, view1.OnMouseEnterCalled);
-            Assert.Equal (0, view1.OnMouseLeaveCalled);
-            Assert.Equal (0, view2.OnMouseEnterCalled);
-            Assert.Equal (0, view2.OnMouseLeaveCalled);
-
-            // Act
-            mousePosition = new Point (1, 1);
-            Application.RaiseMouseEnterLeaveEvents (mousePosition, View.GetViewsUnderMouse (mousePosition), new MouseEvent ()
-            {
-                Position = mousePosition,
-                ScreenPosition = mousePosition
-            });
-
-            // Assert
-            Assert.Equal (1, view1.OnMouseEnterCalled);
-            Assert.Equal (0, view1.OnMouseLeaveCalled);
-            Assert.Equal (0, view2.OnMouseEnterCalled);
-            Assert.Equal (0, view2.OnMouseLeaveCalled);
-
-            // Act
-            mousePosition = new Point (2, 2);
-            Application.RaiseMouseEnterLeaveEvents (mousePosition, View.GetViewsUnderMouse (mousePosition), new MouseEvent ()
-            {
-                Position = mousePosition,
-                ScreenPosition = mousePosition
-            });
-
-            // Assert
-            Assert.Equal (1, view1.OnMouseEnterCalled);
-            Assert.Equal (1, view1.OnMouseLeaveCalled);
-            Assert.Equal (1, view2.OnMouseEnterCalled);
-            Assert.Equal (0, view2.OnMouseLeaveCalled);
-
-
-            // Act
-            mousePosition = new Point (3, 3);
-            Application.RaiseMouseEnterLeaveEvents (mousePosition, View.GetViewsUnderMouse (mousePosition), new MouseEvent ()
-            {
-                Position = mousePosition,
-                ScreenPosition = mousePosition
-            });
-
-            // Assert
-            Assert.Equal (1, view1.OnMouseEnterCalled);
-            Assert.Equal (1, view1.OnMouseLeaveCalled);
-            Assert.Equal (1, view2.OnMouseEnterCalled);
-            Assert.Equal (1, view2.OnMouseLeaveCalled);
-
-            // Act
-            mousePosition = new Point (0, 0);
-            Application.RaiseMouseEnterLeaveEvents (mousePosition, View.GetViewsUnderMouse (mousePosition), new MouseEvent ()
-            {
-                Position = mousePosition,
-                ScreenPosition = mousePosition
-            });
-
-            // Assert
-            Assert.Equal (1, view1.OnMouseEnterCalled);
-            Assert.Equal (1, view1.OnMouseLeaveCalled);
-            Assert.Equal (1, view2.OnMouseEnterCalled);
-            Assert.Equal (1, view2.OnMouseLeaveCalled);
-        }
-        finally
-        {
-            // Cleanup
-            Application.Top?.Dispose ();
-            Application.ResetState ();
-        }
-    }
-}

+ 0 - 2
UnitTests/Input/ResponderTests.cs

@@ -235,8 +235,6 @@ public class ResponderTests
         Assert.False (r.OnKeyDown (new Key { KeyCode = KeyCode.Null }));
         Assert.False (r.OnKeyUp (new Key { KeyCode = KeyCode.Null }));
         Assert.False (r.NewMouseEvent (new MouseEvent { Flags = MouseFlags.AllEvents }));
-        Assert.False (r.NewMouseEnterEvent (new MouseEvent { Flags = MouseFlags.AllEvents }));
-        Assert.False (r.NewMouseLeaveEvent (new MouseEvent { Flags = MouseFlags.AllEvents }));
 
         var v = new View ();
         //Assert.False (r.OnEnter (v));

+ 173 - 114
UnitTests/View/Mouse/GetViewsUnderMouseTests.cs

@@ -2,6 +2,7 @@
 
 namespace Terminal.Gui.ViewMouseTests;
 
+[Trait ("Category", "Input")]
 public class GetViewsUnderMouseTests
 {
     [Theory]
@@ -57,21 +58,30 @@ public class GetViewsUnderMouseTests
     [InlineData (1, 1, 1, 1, 1, 8, 8, typeof (Padding))]
     [InlineData (1, 1, 1, 1, 1, 9, 9, typeof (Border))]
     [InlineData (1, 1, 1, 1, 1, 10, 10, typeof (Margin))]
-    public void GetViewsUnderMouse_Top_Adornments_Returns_Correct_View (int frameX, int frameY, int marginThickness, int borderThickness, int paddingThickness, int testX, int testY, Type? expectedViewType)
+    public void GetViewsUnderMouse_Top_Adornments_Returns_Correct_View (
+        int frameX,
+        int frameY,
+        int marginThickness,
+        int borderThickness,
+        int paddingThickness,
+        int testX,
+        int testY,
+        Type? expectedViewType
+    )
     {
         // Arrange
         Application.Top = new ()
         {
-            Frame = new Rectangle (frameX, frameY, 10, 10),
+            Frame = new (frameX, frameY, 10, 10)
         };
-        Application.Top.Margin.Thickness = new Thickness (marginThickness);
-        Application.Top.Border.Thickness = new Thickness (borderThickness);
-        Application.Top.Padding.Thickness = new Thickness (paddingThickness);
+        Application.Top.Margin.Thickness = new (marginThickness);
+        Application.Top.Border.Thickness = new (borderThickness);
+        Application.Top.Padding.Thickness = new (paddingThickness);
 
         var location = new Point (testX, testY);
 
         // Act
-        var viewsUnderMouse = View.GetViewsUnderMouse (location);
+        List<View?> viewsUnderMouse = View.GetViewsUnderMouse (location);
 
         // Assert
         if (expectedViewType == null)
@@ -82,8 +92,9 @@ public class GetViewsUnderMouseTests
         {
             Assert.Contains (viewsUnderMouse, v => v?.GetType () == expectedViewType);
         }
+
         Application.Top.Dispose ();
-        Application.ResetState (ignoreDisposed: true);
+        Application.ResetState (true);
     }
 
     [Theory]
@@ -95,18 +106,18 @@ public class GetViewsUnderMouseTests
         // Arrange
         Application.Top = new ()
         {
-            Frame = new Rectangle (0, 0, 10, 10)
+            Frame = new (0, 0, 10, 10)
         };
 
         var location = new Point (testX, testY);
 
         // Act
-        var viewsUnderMouse = View.GetViewsUnderMouse (location);
+        List<View?> viewsUnderMouse = View.GetViewsUnderMouse (location);
 
         // Assert
         Assert.Contains (viewsUnderMouse, v => v == Application.Top);
         Application.Top.Dispose ();
-        Application.ResetState (ignoreDisposed: true);
+        Application.ResetState (true);
     }
 
     [Theory]
@@ -118,13 +129,13 @@ public class GetViewsUnderMouseTests
         // Arrange
         var view = new View
         {
-            Frame = new Rectangle (0, 0, 10, 10)
+            Frame = new (0, 0, 10, 10)
         };
 
         var location = new Point (testX, testY);
 
         // Act
-        var viewsUnderMouse = View.GetViewsUnderMouse (location);
+        List<View?> viewsUnderMouse = View.GetViewsUnderMouse (location);
 
         // Assert
         Assert.Empty (viewsUnderMouse);
@@ -139,14 +150,14 @@ public class GetViewsUnderMouseTests
         // Arrange
         var view = new View
         {
-            Frame = new Rectangle (0, 0, 10, 10),
+            Frame = new (0, 0, 10, 10),
             Visible = false
         };
 
         var location = new Point (testX, testY);
 
         // Act
-        var viewsUnderMouse = View.GetViewsUnderMouse (location);
+        List<View?> viewsUnderMouse = View.GetViewsUnderMouse (location);
 
         // Assert
         Assert.Empty (viewsUnderMouse);
@@ -165,12 +176,12 @@ public class GetViewsUnderMouseTests
         // Arrange
         Application.Top = new ()
         {
-            Frame = new Rectangle (0, 0, 10, 10)
+            Frame = new (0, 0, 10, 10)
         };
 
         var subView = new View
         {
-            Frame = new Rectangle (1, 1, 8, 8)
+            Frame = new (1, 1, 8, 8)
         };
 
         Application.Top.Add (subView);
@@ -178,7 +189,7 @@ public class GetViewsUnderMouseTests
         var location = new Point (testX, testY);
 
         // Act
-        var viewsUnderMouse = View.GetViewsUnderMouse (location);
+        List<View?> viewsUnderMouse = View.GetViewsUnderMouse (location);
 
         // Assert
         if (expected)
@@ -189,39 +200,36 @@ public class GetViewsUnderMouseTests
         {
             Assert.DoesNotContain (viewsUnderMouse, v => v == subView);
         }
+
         Application.Top.Dispose ();
-        Application.ResetState (ignoreDisposed: true);
+        Application.ResetState (true);
     }
 
-     [Theory]
+    [Theory]
     [InlineData (0, 0, 0, 0, 0, -1, -1, null)]
     [InlineData (0, 0, 0, 0, 0, 0, 0, typeof (View))]
     [InlineData (0, 0, 0, 0, 0, 1, 1, typeof (View))]
     [InlineData (0, 0, 0, 0, 0, 4, 4, typeof (View))]
     [InlineData (0, 0, 0, 0, 0, 9, 9, typeof (View))]
     [InlineData (0, 0, 0, 0, 0, 10, 10, null)]
-
     [InlineData (1, 1, 0, 0, 0, -1, -1, null)]
     [InlineData (1, 1, 0, 0, 0, 0, 0, null)]
     [InlineData (1, 1, 0, 0, 0, 1, 1, typeof (View))]
     [InlineData (1, 1, 0, 0, 0, 4, 4, typeof (View))]
     [InlineData (1, 1, 0, 0, 0, 9, 9, typeof (View))]
     [InlineData (1, 1, 0, 0, 0, 10, 10, typeof (View))]
-
     [InlineData (0, 0, 1, 0, 0, -1, -1, null)]
     [InlineData (0, 0, 1, 0, 0, 0, 0, typeof (Margin))]
     [InlineData (0, 0, 1, 0, 0, 1, 1, typeof (View))]
     [InlineData (0, 0, 1, 0, 0, 4, 4, typeof (View))]
     [InlineData (0, 0, 1, 0, 0, 9, 9, typeof (Margin))]
     [InlineData (0, 0, 1, 0, 0, 10, 10, null)]
-
     [InlineData (0, 0, 1, 1, 0, -1, -1, null)]
     [InlineData (0, 0, 1, 1, 0, 0, 0, typeof (Margin))]
     [InlineData (0, 0, 1, 1, 0, 1, 1, typeof (Border))]
     [InlineData (0, 0, 1, 1, 0, 4, 4, typeof (View))]
     [InlineData (0, 0, 1, 1, 0, 9, 9, typeof (Margin))]
     [InlineData (0, 0, 1, 1, 0, 10, 10, null)]
-
     [InlineData (0, 0, 1, 1, 1, -1, -1, null)]
     [InlineData (0, 0, 1, 1, 1, 0, 0, typeof (Margin))]
     [InlineData (0, 0, 1, 1, 1, 1, 1, typeof (Border))]
@@ -229,7 +237,6 @@ public class GetViewsUnderMouseTests
     [InlineData (0, 0, 1, 1, 1, 4, 4, typeof (View))]
     [InlineData (0, 0, 1, 1, 1, 9, 9, typeof (Margin))]
     [InlineData (0, 0, 1, 1, 1, 10, 10, null)]
-
     [InlineData (1, 1, 1, 0, 0, -1, -1, null)]
     [InlineData (1, 1, 1, 0, 0, 0, 0, null)]
     [InlineData (1, 1, 1, 0, 0, 1, 1, typeof (Margin))]
@@ -251,18 +258,28 @@ public class GetViewsUnderMouseTests
     [InlineData (1, 1, 1, 1, 1, 8, 8, typeof (Padding))]
     [InlineData (1, 1, 1, 1, 1, 9, 9, typeof (Border))]
     [InlineData (1, 1, 1, 1, 1, 10, 10, typeof (Margin))]
-    public void Contains (int frameX, int frameY, int marginThickness, int borderThickness, int paddingThickness, int testX, int testY, Type? expectedAdornmentType)
+    public void Contains (
+        int frameX,
+        int frameY,
+        int marginThickness,
+        int borderThickness,
+        int paddingThickness,
+        int testX,
+        int testY,
+        Type? expectedAdornmentType
+    )
     {
-        var view = new View ()
+        var view = new View
         {
             X = frameX, Y = frameY,
-            Width = 10, Height = 10,
+            Width = 10, Height = 10
         };
-        view.Margin.Thickness = new Thickness (marginThickness);
-        view.Border.Thickness = new Thickness (borderThickness);
-        view.Padding.Thickness = new Thickness (paddingThickness);
+        view.Margin.Thickness = new (marginThickness);
+        view.Border.Thickness = new (borderThickness);
+        view.Padding.Thickness = new (paddingThickness);
 
         Type? containedType = null;
+
         if (view.Contains (new (testX, testY)))
         {
             containedType = view.GetType ();
@@ -282,8 +299,8 @@ public class GetViewsUnderMouseTests
         {
             containedType = view.Padding.GetType ();
         }
-        Assert.Equal (expectedAdornmentType, containedType);
 
+        Assert.Equal (expectedAdornmentType, containedType);
     }
 
     // Test that GetViewsUnderMouse returns the correct view if the start view has no subviews
@@ -295,12 +312,12 @@ public class GetViewsUnderMouseTests
     {
         Application.Top = new ()
         {
-            Width = 10, Height = 10,
+            Width = 10, Height = 10
         };
 
-        Assert.Same (Application.Top, View.GetViewsUnderMouse(new Point(testX, testY)).LastOrDefault());
+        Assert.Same (Application.Top, View.GetViewsUnderMouse (new (testX, testY)).LastOrDefault ());
         Application.Top.Dispose ();
-        Application.ResetState (ignoreDisposed: true);
+        Application.ResetState (true);
     }
 
     // Test that GetViewsUnderMouse returns null if the start view has no subviews and coords are outside the view
@@ -313,12 +330,12 @@ public class GetViewsUnderMouseTests
         Application.Top = new ()
         {
             X = 1, Y = 2,
-            Width = 10, Height = 10,
+            Width = 10, Height = 10
         };
 
-        Assert.Null (View.GetViewsUnderMouse(new Point(testX, testY)).LastOrDefault());
+        Assert.Null (View.GetViewsUnderMouse (new (testX, testY)).LastOrDefault ());
         Application.Top.Dispose ();
-        Application.ResetState (ignoreDisposed: true);
+        Application.ResetState (true);
     }
 
     [Theory]
@@ -331,12 +348,12 @@ public class GetViewsUnderMouseTests
         {
             X = 1, Y = 2,
             Width = 10, Height = 10,
-            Visible = false,
+            Visible = false
         };
 
-        Assert.Null (View.GetViewsUnderMouse(new Point(testX, testY)).LastOrDefault());
+        Assert.Null (View.GetViewsUnderMouse (new (testX, testY)).LastOrDefault ());
         Application.Top.Dispose ();
-        Application.ResetState (ignoreDisposed: true);
+        Application.ResetState (true);
     }
 
     // Test that GetViewsUnderMouse returns the correct view if the start view has subviews
@@ -346,28 +363,27 @@ public class GetViewsUnderMouseTests
     [InlineData (9, 9, false)]
     [InlineData (10, 10, false)]
     [InlineData (6, 7, false)]
-
     [InlineData (1, 2, true)]
     [InlineData (5, 6, true)]
     public void Returns_Correct_If_SubViews (int testX, int testY, bool expectedSubViewFound)
     {
         Application.Top = new ()
         {
-            Width = 10, Height = 10,
+            Width = 10, Height = 10
         };
 
-        var subview = new View ()
+        var subview = new View
         {
             X = 1, Y = 2,
-            Width = 5, Height = 5,
+            Width = 5, Height = 5
         };
         Application.Top.Add (subview);
 
-        var found = View.GetViewsUnderMouse(new Point(testX, testY)).LastOrDefault();
+        View? found = View.GetViewsUnderMouse (new (testX, testY)).LastOrDefault ();
 
         Assert.Equal (expectedSubViewFound, found == subview);
         Application.Top.Dispose ();
-        Application.ResetState (ignoreDisposed: true);
+        Application.ResetState (true);
     }
 
     [Theory]
@@ -382,10 +398,10 @@ public class GetViewsUnderMouseTests
     {
         Application.Top = new ()
         {
-            Width = 10, Height = 10,
+            Width = 10, Height = 10
         };
 
-        var subview = new View ()
+        var subview = new View
         {
             X = 1, Y = 2,
             Width = 5, Height = 5,
@@ -393,14 +409,13 @@ public class GetViewsUnderMouseTests
         };
         Application.Top.Add (subview);
 
-        var found = View.GetViewsUnderMouse(new Point(testX, testY)).LastOrDefault();
+        View? found = View.GetViewsUnderMouse (new (testX, testY)).LastOrDefault ();
 
         Assert.Equal (expectedSubViewFound, found == subview);
         Application.Top.Dispose ();
-        Application.ResetState (ignoreDisposed: true);
+        Application.ResetState (true);
     }
 
-
     [Theory]
     [InlineData (0, 0, false)]
     [InlineData (1, 1, false)]
@@ -417,20 +432,20 @@ public class GetViewsUnderMouseTests
             Visible = false
         };
 
-        var subview = new View ()
+        var subview = new View
         {
             X = 1, Y = 2,
-            Width = 5, Height = 5,
+            Width = 5, Height = 5
         };
         Application.Top.Add (subview);
         subview.Visible = true;
         Assert.True (subview.Visible);
         Assert.False (Application.Top.Visible);
-        var found = View.GetViewsUnderMouse(new Point(testX, testY)).LastOrDefault();
+        View? found = View.GetViewsUnderMouse (new (testX, testY)).LastOrDefault ();
 
         Assert.Equal (expectedSubViewFound, found == subview);
         Application.Top.Dispose ();
-        Application.ResetState (ignoreDisposed: true);
+        Application.ResetState (true);
     }
 
     // Test that GetViewsUnderMouse works if the start view has positive Adornments
@@ -441,7 +456,6 @@ public class GetViewsUnderMouseTests
     [InlineData (10, 10, false)]
     [InlineData (7, 8, false)]
     [InlineData (1, 2, false)]
-
     [InlineData (2, 3, true)]
     [InlineData (5, 6, true)]
     [InlineData (6, 7, true)]
@@ -449,22 +463,22 @@ public class GetViewsUnderMouseTests
     {
         Application.Top = new ()
         {
-            Width = 10, Height = 10,
+            Width = 10, Height = 10
         };
-        Application.Top.Margin.Thickness = new Thickness (1);
+        Application.Top.Margin.Thickness = new (1);
 
-        var subview = new View ()
+        var subview = new View
         {
             X = 1, Y = 2,
-            Width = 5, Height = 5,
+            Width = 5, Height = 5
         };
         Application.Top.Add (subview);
 
-        var found = View.GetViewsUnderMouse(new Point(testX, testY)).LastOrDefault();
+        View? found = View.GetViewsUnderMouse (new (testX, testY)).LastOrDefault ();
 
         Assert.Equal (expectedSubViewFound, found == subview);
         Application.Top.Dispose ();
-        Application.ResetState (ignoreDisposed: true);
+        Application.ResetState (true);
     }
 
     // Test that GetViewsUnderMouse works if the start view has offset Viewport location
@@ -472,7 +486,6 @@ public class GetViewsUnderMouseTests
     [InlineData (1, 0, 0, true)]
     [InlineData (1, 1, 1, true)]
     [InlineData (1, 2, 2, false)]
-
     [InlineData (-1, 3, 3, true)]
     [InlineData (-1, 2, 2, true)]
     [InlineData (-1, 1, 1, false)]
@@ -486,18 +499,18 @@ public class GetViewsUnderMouseTests
         };
         Application.Top.Viewport = new (offset, offset, 10, 10);
 
-        var subview = new View ()
+        var subview = new View
         {
             X = 1, Y = 1,
-            Width = 2, Height = 2,
+            Width = 2, Height = 2
         };
         Application.Top.Add (subview);
 
-        var found = View.GetViewsUnderMouse(new Point(testX, testY)).LastOrDefault();
+        View? found = View.GetViewsUnderMouse (new (testX, testY)).LastOrDefault ();
 
         Assert.Equal (expectedSubViewFound, found == subview);
         Application.Top.Dispose ();
-        Application.ResetState (ignoreDisposed: true);
+        Application.ResetState (true);
     }
 
     [Theory]
@@ -514,59 +527,55 @@ public class GetViewsUnderMouseTests
     {
         Application.Top = new ()
         {
-            Width = 10, Height = 10,
+            Width = 10, Height = 10
         };
-        Application.Top.Padding.Thickness = new Thickness (1);
+        Application.Top.Padding.Thickness = new (1);
 
-        var subview = new View ()
+        var subview = new View
         {
             X = Pos.AnchorEnd (1), Y = Pos.AnchorEnd (1),
-            Width = 1, Height = 1,
+            Width = 1, Height = 1
         };
         Application.Top.Padding.Add (subview);
         Application.Top.BeginInit ();
         Application.Top.EndInit ();
 
-        var found = View.GetViewsUnderMouse(new Point(testX, testY)).LastOrDefault();
+        View? found = View.GetViewsUnderMouse (new (testX, testY)).LastOrDefault ();
 
         Assert.Equal (expectedSubViewFound, found == subview);
         Application.Top.Dispose ();
-        Application.ResetState (ignoreDisposed: true);
+        Application.ResetState (true);
     }
 
-
     [Theory]
     [InlineData (0, 0, typeof (Margin))]
     [InlineData (9, 9, typeof (Margin))]
-
     [InlineData (1, 1, typeof (Border))]
     [InlineData (8, 8, typeof (Border))]
-
     [InlineData (2, 2, typeof (Padding))]
     [InlineData (7, 7, typeof (Padding))]
-
     [InlineData (5, 5, typeof (Toplevel))]
     public void Returns_Adornment_If_Start_Has_Adornments (int testX, int testY, Type expectedAdornmentType)
     {
         Application.Top = new ()
         {
-            Width = 10, Height = 10,
+            Width = 10, Height = 10
         };
-        Application.Top.Margin.Thickness = new Thickness (1);
-        Application.Top.Border.Thickness = new Thickness (1);
-        Application.Top.Padding.Thickness = new Thickness (1);
+        Application.Top.Margin.Thickness = new (1);
+        Application.Top.Border.Thickness = new (1);
+        Application.Top.Padding.Thickness = new (1);
 
-        var subview = new View ()
+        var subview = new View
         {
             X = 1, Y = 1,
-            Width = 1, Height = 1,
+            Width = 1, Height = 1
         };
         Application.Top.Add (subview);
 
-        var found = View.GetViewsUnderMouse(new Point(testX, testY)).LastOrDefault();
+        View? found = View.GetViewsUnderMouse (new (testX, testY)).LastOrDefault ();
         Assert.Equal (expectedAdornmentType, found!.GetType ());
         Application.Top.Dispose ();
-        Application.ResetState (ignoreDisposed: true);
+        Application.ResetState (true);
     }
 
     // Test that GetViewsUnderMouse works if the subview has positive Adornments
@@ -579,28 +588,27 @@ public class GetViewsUnderMouseTests
     [InlineData (6, 7, false)]
     [InlineData (1, 2, false)]
     [InlineData (5, 6, false)]
-
     [InlineData (2, 3, true)]
     public void Returns_Correct_If_SubView_Has_Adornments (int testX, int testY, bool expectedSubViewFound)
     {
         Application.Top = new ()
         {
-            Width = 10, Height = 10,
+            Width = 10, Height = 10
         };
 
-        var subview = new View ()
+        var subview = new View
         {
             X = 1, Y = 2,
-            Width = 5, Height = 5,
+            Width = 5, Height = 5
         };
-        subview.Margin.Thickness = new Thickness (1);
+        subview.Margin.Thickness = new (1);
         Application.Top.Add (subview);
 
-        var found = View.GetViewsUnderMouse(new Point(testX, testY)).LastOrDefault();
+        View? found = View.GetViewsUnderMouse (new (testX, testY)).LastOrDefault ();
 
         Assert.Equal (expectedSubViewFound, found == subview);
         Application.Top.Dispose ();
-        Application.ResetState (ignoreDisposed: true);
+        Application.ResetState (true);
     }
 
     [Theory]
@@ -618,36 +626,36 @@ public class GetViewsUnderMouseTests
     {
         Application.Top = new ()
         {
-            Width = 10, Height = 10,
+            Width = 10, Height = 10
         };
 
         // A subview with + Padding
-        var subview = new View ()
+        var subview = new View
         {
             X = 1, Y = 1,
-            Width = 5, Height = 5,
+            Width = 5, Height = 5
         };
         subview.Padding.Thickness = new (1);
 
         // This subview will be at the bottom-right-corner of subview
         // So screen-relative location will be X + Width - 1 = 5
-        var paddingSubview = new View ()
+        var paddingSubview = new View
         {
             X = Pos.AnchorEnd (1),
             Y = Pos.AnchorEnd (1),
             Width = 1,
-            Height = 1,
+            Height = 1
         };
         subview.Padding.Add (paddingSubview);
         Application.Top.Add (subview);
         Application.Top.BeginInit ();
         Application.Top.EndInit ();
 
-        var found = View.GetViewsUnderMouse(new Point(testX, testY)).LastOrDefault();
+        View? found = View.GetViewsUnderMouse (new (testX, testY)).LastOrDefault ();
 
         Assert.Equal (expectedSubViewFound, found == paddingSubview);
         Application.Top.Dispose ();
-        Application.ResetState (ignoreDisposed: true);
+        Application.ResetState (true);
     }
 
     [Theory]
@@ -665,14 +673,14 @@ public class GetViewsUnderMouseTests
     {
         Application.Top = new ()
         {
-            Width = 10, Height = 10,
+            Width = 10, Height = 10
         };
 
         // A subview with + Padding
-        var subview = new View ()
+        var subview = new View
         {
             X = 1, Y = 1,
-            Width = 5, Height = 5,
+            Width = 5, Height = 5
         };
         subview.Padding.Thickness = new (1);
 
@@ -682,23 +690,23 @@ public class GetViewsUnderMouseTests
 
         // This subview will be at the bottom-right-corner of subview
         // So screen-relative location will be X + Width - 1 = 5
-        var paddingSubview = new View ()
+        var paddingSubview = new View
         {
             X = Pos.AnchorEnd (1),
             Y = Pos.AnchorEnd (1),
             Width = 1,
-            Height = 1,
+            Height = 1
         };
         subview.Padding.Add (paddingSubview);
         Application.Top.Add (subview);
         Application.Top.BeginInit ();
         Application.Top.EndInit ();
 
-        var found = View.GetViewsUnderMouse(new (testX, testY)).LastOrDefault();
+        View? found = View.GetViewsUnderMouse (new (testX, testY)).LastOrDefault ();
 
         Assert.Equal (expectedSubViewFound, found == paddingSubview);
         Application.Top.Dispose ();
-        Application.ResetState (ignoreDisposed: true);
+        Application.ResetState (true);
     }
 
     // Test that GetViewsUnderMouse works with nested subviews
@@ -706,7 +714,6 @@ public class GetViewsUnderMouseTests
     [InlineData (0, 0, -1)]
     [InlineData (9, 9, -1)]
     [InlineData (10, 10, -1)]
-
     [InlineData (1, 1, 0)]
     [InlineData (1, 2, 0)]
     [InlineData (2, 2, 1)]
@@ -719,14 +726,15 @@ public class GetViewsUnderMouseTests
             Width = 10, Height = 10
         };
 
-        int numSubViews = 3;
-        List<View> subviews = new List<View> ();
-        for (int i = 0; i < numSubViews; i++)
+        var numSubViews = 3;
+        List<View> subviews = new ();
+
+        for (var i = 0; i < numSubViews; i++)
         {
-            var subview = new View ()
+            var subview = new View
             {
                 X = 1, Y = 1,
-                Width = 5, Height = 5,
+                Width = 5, Height = 5
             };
             subviews.Add (subview);
 
@@ -738,9 +746,60 @@ public class GetViewsUnderMouseTests
 
         Application.Top.Add (subviews [0]);
 
-        var found = View.GetViewsUnderMouse(new (testX, testY)).LastOrDefault();
+        View? found = View.GetViewsUnderMouse (new (testX, testY)).LastOrDefault ();
         Assert.Equal (expectedSubViewFound, subviews.IndexOf (found!));
         Application.Top.Dispose ();
-        Application.ResetState (ignoreDisposed: true);
+        Application.ResetState (true);
+    }
+
+    [Theory]
+    [InlineData (0, 0, new [] { "top" })]
+    [InlineData (9, 9, new [] { "top" })]
+    [InlineData (10, 10, new string [] { })]
+    [InlineData (1, 1, new [] { "top", "view" })]
+    [InlineData (1, 2, new [] { "top", "view" })]
+    [InlineData (2, 1, new [] { "top", "view" })]
+    [InlineData (2, 2, new [] { "top", "view", "subView" })]
+    [InlineData (3, 3, new [] { "top" })] // clipped
+    [InlineData (2, 3, new [] { "top" })] // clipped
+    public void GetViewsUnderMouse_Tiled_Subviews (int mouseX, int mouseY, string [] viewIdStrings)
+    {
+        // Arrange
+        Application.Top = new ()
+        {
+            Frame = new (0, 0, 10, 10),
+            Id = "top"
+        };
+
+        var view = new View
+        {
+            Id = "view",
+            X = 1,
+            Y = 1,
+            Width = 2,
+            Height = 2,
+            Arrangement = ViewArrangement.Overlapped
+        }; // at 1,1 to 3,2 (screen)
+
+        var subView = new View
+        {
+            Id = "subView",
+            X = 1,
+            Y = 1,
+            Width = 2,
+            Height = 2,
+            Arrangement = ViewArrangement.Overlapped
+        }; // at 2,2 to 4,3 (screen)
+        view.Add (subView);
+        Application.Top.Add (view);
+
+        List<View?> found = View.GetViewsUnderMouse (new (mouseX, mouseY));
+
+        string [] foundIds = found.Select (v => v.Id).ToArray ();
+
+        Assert.Equal (viewIdStrings, foundIds);
+
+        Application.Top.Dispose ();
+        Application.ResetState (true);
     }
 }

+ 61 - 68
UnitTests/View/Mouse/MouseEnterLeaveTests.cs

@@ -1,3 +1,5 @@
+using System.ComponentModel;
+
 namespace Terminal.Gui.ViewMouseTests;
 
 [Trait ("Category", "Input")]
@@ -11,29 +13,26 @@ public class MouseEnterLeaveTests
             MouseLeave += OnMouseLeaveHandler;
         }
 
-        public bool HandleOnEnter { get; init; }
-        public bool HandleOnLeave { get; }
+        public bool CancelOnEnter { get; init; }
 
-        public bool HandleEnterEvent { get; init; }
-        public bool HandleLeaveEvent { get; }
+        public bool CancelEnterEvent { get; init; }
 
         public bool OnMouseEnterCalled { get; private set; }
         public bool OnMouseLeaveCalled { get; private set; }
 
-        protected internal override bool? OnMouseEnter (MouseEvent mouseEvent)
+        protected override bool OnMouseEnter (CancelEventArgs eventArgs)
         {
             OnMouseEnterCalled = true;
-            mouseEvent.Handled = HandleOnEnter;
+            eventArgs.Cancel = CancelOnEnter;
 
-            base.OnMouseEnter (mouseEvent);
+            base.OnMouseEnter (eventArgs);
 
-            return mouseEvent.Handled;
+            return eventArgs.Cancel;
         }
 
         protected internal override bool OnMouseLeave (MouseEvent mouseEvent)
         {
             OnMouseLeaveCalled = true;
-            mouseEvent.Handled = HandleOnLeave;
 
             base.OnMouseLeave (mouseEvent);
 
@@ -43,25 +42,17 @@ public class MouseEnterLeaveTests
         public bool MouseEnterRaised { get; private set; }
         public bool MouseLeaveRaised { get; private set; }
 
-        private void OnMouseEnterHandler (object s, MouseEventEventArgs e)
+        private void OnMouseEnterHandler (object s, CancelEventArgs e)
         {
             MouseEnterRaised = true;
 
-            if (HandleEnterEvent)
+            if (CancelEnterEvent)
             {
-                e.Handled = true;
+                e.Cancel = true;
             }
         }
 
-        private void OnMouseLeaveHandler (object s, MouseEventEventArgs e)
-        {
-            MouseLeaveRaised = true;
-
-            if (HandleLeaveEvent)
-            {
-                e.Handled = true;
-            }
-        }
+        private void OnMouseLeaveHandler (object s, MouseEventEventArgs e) { MouseLeaveRaised = true; }
     }
 
     [Fact]
@@ -76,20 +67,22 @@ public class MouseEnterLeaveTests
 
         var mouseEvent = new MouseEvent ();
 
+        var eventArgs = new CancelEventArgs ();
+
         // Act
-        bool? handled = view.NewMouseEnterEvent (mouseEvent);
+        bool? cancelled = view.NewMouseEnterEvent (eventArgs);
 
         // Assert
         Assert.True (view.OnMouseEnterCalled);
-        Assert.False (handled);
-        Assert.False (mouseEvent.Handled);
+        Assert.False (cancelled);
+        Assert.False (eventArgs.Cancel);
 
         // Cleanup
         view.Dispose ();
     }
 
     [Fact]
-    public void NewMouseEnterEvent_ViewIsDisabled_DoesNotCallOnMouseEnter ()
+    public void NewMouseEnterEvent_ViewIsDisabled_CallsOnMouseEnter ()
     {
         // Arrange
         var view = new TestView
@@ -98,15 +91,15 @@ public class MouseEnterLeaveTests
             Visible = true
         };
 
-        var mouseEvent = new MouseEvent ();
+        var eventArgs = new CancelEventArgs ();
 
         // Act
-        bool? handled = view.NewMouseEnterEvent (mouseEvent);
+        bool? cancelled = view.NewMouseEnterEvent (eventArgs);
 
         // Assert
-        Assert.False (view.OnMouseEnterCalled);
-        Assert.False (handled);
-        Assert.False (mouseEvent.Handled);
+        Assert.True (view.OnMouseEnterCalled);
+        Assert.False (cancelled);
+        Assert.False (eventArgs.Cancel);
 
         // Cleanup
         view.Dispose ();
@@ -122,15 +115,15 @@ public class MouseEnterLeaveTests
             Visible = false
         };
 
-        var mouseEvent = new MouseEvent ();
+        var eventArgs = new CancelEventArgs ();
 
         // Act
-        bool? handled = view.NewMouseEnterEvent (mouseEvent);
+        bool? cancelled = view.NewMouseEnterEvent (eventArgs);
 
         // Assert
         Assert.False (view.OnMouseEnterCalled);
-        Assert.False (handled);
-        Assert.False (mouseEvent.Handled);
+        Assert.Null (cancelled);
+        Assert.False (eventArgs.Cancel);
 
         // Cleanup
         view.Dispose ();
@@ -148,11 +141,11 @@ public class MouseEnterLeaveTests
         var mouseEvent = new MouseEvent ();
 
         // Act
-        bool? handled = view.NewMouseLeaveEvent (mouseEvent);
+        bool? cancelled = view.NewMouseLeaveEvent (mouseEvent);
 
         // Assert
         Assert.True (view.OnMouseLeaveCalled);
-        Assert.False (handled);
+        Assert.False (cancelled);
         Assert.False (mouseEvent.Handled);
 
         // Cleanup
@@ -172,11 +165,11 @@ public class MouseEnterLeaveTests
         var mouseEvent = new MouseEvent ();
 
         // Act
-        bool? handled = view.NewMouseLeaveEvent (mouseEvent);
+        bool? cancelled = view.NewMouseLeaveEvent (mouseEvent);
 
         // Assert
         Assert.True (view.OnMouseLeaveCalled);
-        Assert.False (handled);
+        Assert.False (cancelled);
         Assert.False (mouseEvent.Handled);
 
         // Cleanup
@@ -195,22 +188,22 @@ public class MouseEnterLeaveTests
             Visible = true
         };
 
-        var mouseEvent = new MouseEvent ();
+        var eventArgs = new CancelEventArgs ();
 
         // Act
-        bool? handled = view.NewMouseEnterEvent (mouseEvent);
+        bool? cancelled = view.NewMouseEnterEvent (eventArgs);
 
         // Assert
         Assert.True (view.MouseEnterRaised);
-        Assert.False (handled);
-        Assert.False (mouseEvent.Handled);
+        Assert.False (cancelled);
+        Assert.False (eventArgs.Cancel);
 
         // Cleanup
         view.Dispose ();
     }
 
     [Fact]
-    public void NewMouseEnterEvent_ViewIsDisabled_DoesNotRaiseMouseEnter ()
+    public void NewMouseEnterEvent_ViewIsDisabled_RaisesMouseEnter ()
     {
         // Arrange
         var view = new TestView
@@ -219,15 +212,15 @@ public class MouseEnterLeaveTests
             Visible = true
         };
 
-        var mouseEvent = new MouseEvent ();
+        var eventArgs = new CancelEventArgs ();
 
         // Act
-        bool? handled = view.NewMouseEnterEvent (mouseEvent);
+        bool? cancelled = view.NewMouseEnterEvent (eventArgs);
 
         // Assert
-        Assert.False (view.MouseEnterRaised);
-        Assert.False (handled);
-        Assert.False (mouseEvent.Handled);
+        Assert.True (view.MouseEnterRaised);
+        Assert.False (cancelled);
+        Assert.False (eventArgs.Cancel);
 
         // Cleanup
         view.Dispose ();
@@ -243,15 +236,15 @@ public class MouseEnterLeaveTests
             Visible = false
         };
 
-        var mouseEvent = new MouseEvent ();
+        var eventArgs = new CancelEventArgs ();
 
         // Act
-        bool? handled = view.NewMouseEnterEvent (mouseEvent);
+        bool? cancelled = view.NewMouseEnterEvent (eventArgs);
 
         // Assert
         Assert.False (view.MouseEnterRaised);
-        Assert.False (handled);
-        Assert.False (mouseEvent.Handled);
+        Assert.Null (cancelled);
+        Assert.False (eventArgs.Cancel);
 
         // Cleanup
         view.Dispose ();
@@ -263,18 +256,18 @@ public class MouseEnterLeaveTests
         // Arrange
         var view = new TestView
         {
-            Enabled = true, 
+            Enabled = true,
             Visible = true
         };
 
         var mouseEvent = new MouseEvent ();
 
         // Act
-        bool? handled = view.NewMouseLeaveEvent (mouseEvent);
+        bool? cancelled = view.NewMouseLeaveEvent (mouseEvent);
 
         // Assert
         Assert.True (view.MouseLeaveRaised);
-        Assert.False (handled);
+        Assert.False (cancelled);
         Assert.False (mouseEvent.Handled);
 
         // Cleanup
@@ -282,7 +275,7 @@ public class MouseEnterLeaveTests
     }
 
     [Fact]
-    public void NewMouseLeaveEvent_ViewIsNotVisible_DoesNotRaiseMouseLeave ()
+    public void NewMouseLeaveEvent_ViewIsNotVisible_RaisesMouseLeave ()
     {
         // Arrange
         var view = new TestView
@@ -294,11 +287,11 @@ public class MouseEnterLeaveTests
         var mouseEvent = new MouseEvent ();
 
         // Act
-        bool? handled = view.NewMouseLeaveEvent (mouseEvent);
+        bool? cancelled = view.NewMouseLeaveEvent (mouseEvent);
 
         // Assert
         Assert.True (view.MouseLeaveRaised);
-        Assert.False (handled);
+        Assert.False (cancelled);
         Assert.False (mouseEvent.Handled);
 
         // Cleanup
@@ -314,18 +307,18 @@ public class MouseEnterLeaveTests
         {
             Enabled = true,
             Visible = true,
-            HandleOnEnter = true
+            CancelOnEnter = true
         };
 
-        var mouseEvent = new MouseEvent ();
+        var eventArgs = new CancelEventArgs ();
 
         // Act
-        bool? handled = view.NewMouseEnterEvent (mouseEvent);
+        bool? cancelled = view.NewMouseEnterEvent (eventArgs);
 
         // Assert
         Assert.True (view.OnMouseEnterCalled);
-        Assert.True (handled);
-        Assert.True (mouseEvent.Handled);
+        Assert.True (cancelled);
+        Assert.True (eventArgs.Cancel);
 
         Assert.False (view.MouseEnterRaised);
 
@@ -341,18 +334,18 @@ public class MouseEnterLeaveTests
         {
             Enabled = true,
             Visible = true,
-            HandleEnterEvent = true
+            CancelEnterEvent = true
         };
 
-        var mouseEvent = new MouseEvent ();
+        var eventArgs = new CancelEventArgs ();
 
         // Act
-        bool? handled = view.NewMouseEnterEvent (mouseEvent);
+        bool? cancelled = view.NewMouseEnterEvent (eventArgs);
 
         // Assert
         Assert.True (view.OnMouseEnterCalled);
-        Assert.True (handled);
-        Assert.True (mouseEvent.Handled);
+        Assert.True (cancelled);
+        Assert.True (eventArgs.Cancel);
 
         Assert.True (view.MouseEnterRaised);
 

+ 0 - 2
UnitTests/View/ViewTests.cs

@@ -874,8 +874,6 @@ At 0,0
         //Assert.False (r.OnKeyDown (new KeyEventArgs () { Key = Key.Unknown }));
         Assert.False (r.OnKeyUp (new() { KeyCode = KeyCode.Null }));
         Assert.False (r.NewMouseEvent (new() { Flags = MouseFlags.AllEvents }));
-        Assert.False (r.NewMouseEnterEvent (new() { Flags = MouseFlags.AllEvents }));
-        Assert.False (r.NewMouseLeaveEvent (new() { Flags = MouseFlags.AllEvents }));
 
         r.Dispose ();