浏览代码

Fixed linux unit tests.
Backed out change that registered quitkey as application scope.
Beefed up tons of tests

Tig 1 年之前
父节点
当前提交
303573bdea

+ 1 - 1
Terminal.Gui/Input/KeyBindings.cs

@@ -38,7 +38,7 @@ public class KeyBindings
         else
         {
             Bindings.Add (key, binding);
-            if (binding.Scope.FastHasFlags (KeyBindingScope.Application))
+            if (binding.Scope.HasFlag (KeyBindingScope.Application))
             {
                 Application.AddKeyBinding (key, BoundView);
             }

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

@@ -392,7 +392,7 @@ public class ScrollView : View
             return true;
         }
 
-        bool? result = InvokeKeyBindings (a, KeyBindingScope.HotKey);
+        bool? result = InvokeKeyBindings (a, KeyBindingScope.HotKey | KeyBindingScope.Focused);
 
         if (result is { })
         {

+ 2 - 2
Terminal.Gui/Views/Toplevel.cs

@@ -106,7 +106,7 @@ public partial class Toplevel : View
                    );
 
         // Default keybindings for this view
-        KeyBindings.Add (Application.QuitKey, KeyBindingScope.Application, Command.QuitToplevel);
+        KeyBindings.Add (Application.QuitKey, Command.QuitToplevel);
 
         KeyBindings.Add (Key.CursorRight, Command.NextView);
         KeyBindings.Add (Key.CursorDown, Command.NextView);
@@ -119,7 +119,7 @@ public partial class Toplevel : View
         KeyBindings.Add (Key.Tab.WithShift.WithCtrl, Command.PreviousViewOrTop);
 
         // TODO: Refresh Key should be configurable
-        KeyBindings.Add (Key.F5, KeyBindingScope.Application, Command.Refresh);
+        KeyBindings.Add (Key.F5, Command.Refresh);
         KeyBindings.Add (Application.AlternateForwardKey, Command.NextViewOrTop); // Needed on Unix
         KeyBindings.Add (Application.AlternateBackwardKey, Command.PreviousViewOrTop); // Needed on Unix
 

+ 196 - 7
UnitTests/Application/ApplicationTests.cs

@@ -1,4 +1,5 @@
-using Xunit.Abstractions;
+using Microsoft.VisualBasic;
+using Xunit.Abstractions;
 
 // Alias Console to MockConsole so we don't accidentally use Console
 
@@ -147,8 +148,12 @@ public class ApplicationTests
         Shutdown ();
     }
 
-    [Fact]
-    public void Init_ResetState_Resets_Properties ()
+    [Theory]
+    [InlineData (typeof (FakeDriver))]
+    [InlineData (typeof (NetDriver))]
+    [InlineData (typeof (WindowsDriver))]
+    [InlineData (typeof (CursesDriver))]
+    public void Init_ResetState_Resets_Properties (Type driverType)
     {
         ConfigurationManager.ThrowOnJsonErrors = true;
 
@@ -156,7 +161,7 @@ public class ApplicationTests
 
         // Set some values
 
-        Application.Init ();
+        Application.Init (driverName: driverType.Name);
         Application._initialized = true;
 
         // Reset
@@ -228,7 +233,7 @@ public class ApplicationTests
         Application.AlternateBackwardKey = Key.A;
         Application.AlternateForwardKey = Key.B;
         Application.QuitKey = Key.C;
-        Application.AddKeyBinding(Key.A, new View ());
+        Application.AddKeyBinding (Key.A, new View ());
 
         //Application.OverlappedChildren = new List<View> ();
         //Application.OverlappedTop = 
@@ -266,6 +271,71 @@ public class ApplicationTests
 #endif
     }
 
+    [Theory]
+    [InlineData (typeof (FakeDriver))]
+    [InlineData (typeof (NetDriver))]
+    [InlineData (typeof (WindowsDriver))]
+    [InlineData (typeof (CursesDriver))]
+    public void Init_Shutdown_Fire_InitializedChanged (Type driverType)
+    {
+        bool initialized = false;
+        bool shutdown = false;
+
+        Application.InitializedChanged += OnApplicationOnInitializedChanged;
+
+        Application.Init (driverName: driverType.Name);
+        Assert.True (initialized);
+        Assert.False (shutdown);
+
+        Application.Shutdown ();
+        Assert.True (initialized);
+        Assert.True (shutdown);
+
+        Application.InitializedChanged -= OnApplicationOnInitializedChanged;
+
+        return;
+
+        void OnApplicationOnInitializedChanged (object s, StateEventArgs<bool> a)
+        {
+            if (a.NewValue)
+            {
+                initialized = true;
+            }
+            else
+            {
+                shutdown = true;
+            }
+        }
+    }
+
+
+    [Fact]
+    public void Run_Iteration_Fires ()
+    {
+        int iteration = 0;
+
+        Application.Init (new FakeDriver ());
+
+        Application.Iteration += Application_Iteration;
+        Application.Run<Toplevel> ().Dispose ();
+
+        Assert.Equal (1, iteration);
+        Application.Shutdown ();
+
+        return;
+
+        void Application_Iteration (object sender, IterationEventArgs e)
+        {
+            if (iteration > 0)
+            {
+                Assert.Fail ();
+            }
+            iteration++;
+            Application.RequestStop ();
+        }
+    }
+
+
     [Fact]
     public void Init_Unbalanced_Throws ()
     {
@@ -826,10 +896,10 @@ public class ApplicationTests
 
         Application.OnMouseEvent (new () { Flags = MouseFlags.Button1Pressed });
         Assert.Equal (w.Border, Application.MouseGrabView);
-        Assert.Equal (new Point (0,0), w.Frame.Location);
+        Assert.Equal (new Point (0, 0), w.Frame.Location);
 
         // Move down and to the right.
-        Application.OnMouseEvent (new () { Position = new (1,1), Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition });
+        Application.OnMouseEvent (new () { Position = new (1, 1), Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition });
         Assert.Equal (new Point (1, 1), w.Frame.Location);
 
         Application.End (rs);
@@ -1024,4 +1094,123 @@ public class ApplicationTests
     }
 
     #endregion
+
+
+    private object _timeoutLock;
+
+    [Fact]
+    public void AddTimeout_Fires ()
+    {
+        Assert.Null (_timeoutLock);
+        _timeoutLock = new object ();
+
+        uint timeoutTime = 250;
+        bool initialized = false;
+        int iteration = 0;
+        bool shutdown = false;
+        object timeout = null;
+        int timeoutCount = 0;
+
+        Application.InitializedChanged += OnApplicationOnInitializedChanged;
+
+        Application.Init (new FakeDriver ());
+        Assert.True (initialized);
+        Assert.False (shutdown);
+
+        _output.WriteLine ("Application.Run<Toplevel> ().Dispose ()..");
+        Application.Run<Toplevel> ().Dispose ();
+        _output.WriteLine ("Back from Application.Run<Toplevel> ().Dispose ()");
+
+        Assert.True (initialized);
+        Assert.False (shutdown);
+
+        Assert.Equal (1, timeoutCount);
+        Application.Shutdown ();
+
+        Application.InitializedChanged -= OnApplicationOnInitializedChanged;
+
+        lock (_timeoutLock)
+        {
+            if (timeout is { })
+            {
+                Application.RemoveTimeout (timeout);
+                timeout = null;
+            }
+        }
+
+        Assert.True (initialized);
+        Assert.True (shutdown);
+
+#if DEBUG_IDISPOSABLE
+        Assert.Empty (Responder.Instances);
+#endif
+        lock (_timeoutLock)
+        {
+            _timeoutLock = null;
+        }
+
+        return;
+
+        void OnApplicationOnInitializedChanged (object s, StateEventArgs<bool> a)
+        {
+            if (a.NewValue)
+            {
+                Application.Iteration += OnApplicationOnIteration;
+                initialized = true;
+
+                lock (_timeoutLock)
+                {
+                    _output.WriteLine ($"Setting timeout for {timeoutTime}ms");
+                    timeout = Application.AddTimeout (TimeSpan.FromMilliseconds (timeoutTime), TimeoutCallback);
+                }
+
+            }
+            else
+            {
+                Application.Iteration -= OnApplicationOnIteration;
+                shutdown = true;
+            }
+        }
+
+        bool TimeoutCallback ()
+        {
+            lock (_timeoutLock)
+            {
+                _output.WriteLine ($"TimeoutCallback. Count: {++timeoutCount}. Application Iteration: {iteration}");
+                if (timeout is { })
+                {
+                    _output.WriteLine ($"  Nulling timeout.");
+                    timeout = null;
+                }
+            }
+
+            // False means "don't re-do timer and remove it"
+            return false;
+        }
+
+        void OnApplicationOnIteration (object s, IterationEventArgs a)
+        {
+            lock (_timeoutLock)
+            {
+                if (timeoutCount > 0)
+                {
+                    _output.WriteLine ($"Iteration #{iteration} - Timeout fired. Calling Application.RequestStop.");
+                    Application.RequestStop ();
+
+                    return;
+                }
+            }
+            iteration++;
+
+            // Simulate a delay
+            Thread.Sleep ((int)timeoutTime / 10);
+
+            // Worst case scenario - something went wrong
+            if (Application._initialized && iteration > 25)
+            {
+                _output.WriteLine ($"Too many iterations ({iteration}): Calling Application.RequestStop.");
+                Application.RequestStop ();
+            }
+        }
+    }
 }

+ 119 - 1
UnitTests/Application/KeyboardTests.cs

@@ -1,4 +1,5 @@
-using Xunit.Abstractions;
+using UICatalog;
+using Xunit.Abstractions;
 
 namespace Terminal.Gui.ApplicationTests;
 
@@ -58,6 +59,123 @@ public class KeyboardTests
         top.Dispose ();
     }
 
+    [Fact]
+    public void QuitKey_Default_Is_CtrlQ ()
+    {
+        Application.ResetState (true);
+        // Before Init
+        Assert.Equal (Key.Empty, Application.QuitKey);
+
+        Application.Init (new FakeDriver ());
+        // After Init
+        Assert.Equal (Key.Q.WithCtrl, Application.QuitKey);
+
+        Application.Shutdown();
+    }
+
+    private object _timeoutLock;
+
+    [Fact]
+    public void QuitKey_Quits ()
+    {
+        Assert.Null (_timeoutLock);
+        _timeoutLock = new object ();
+
+        uint abortTime = 500;
+        bool initialized = false;
+        int iteration = 0;
+        bool shutdown = false;
+        object timeout = null;
+
+        Application.InitializedChanged += OnApplicationOnInitializedChanged;
+
+        Application.Init (new FakeDriver ());
+        Assert.True (initialized);
+        Assert.False (shutdown);
+
+        _output.WriteLine ("Application.Run<Toplevel> ().Dispose ()..");
+        Application.Run<Toplevel> ().Dispose ();
+        _output.WriteLine ("Back from Application.Run<Toplevel> ().Dispose ()");
+
+        Assert.True (initialized);
+        Assert.False (shutdown);
+
+        Assert.Equal (1, iteration);
+
+        Application.Shutdown ();
+
+        Application.InitializedChanged -= OnApplicationOnInitializedChanged;
+
+        lock (_timeoutLock)
+        {
+            if (timeout is { })
+            {
+                Application.RemoveTimeout (timeout);
+                timeout = null;
+            }
+        }
+
+        Assert.True (initialized);
+        Assert.True (shutdown);
+
+#if DEBUG_IDISPOSABLE
+        Assert.Empty (Responder.Instances);
+#endif
+        lock (_timeoutLock)
+        {
+            _timeoutLock = null;
+        }
+
+        return;
+
+        void OnApplicationOnInitializedChanged (object s, StateEventArgs<bool> a)
+        {
+            _output.WriteLine ("OnApplicationOnInitializedChanged: {0}", a.NewValue);
+            if (a.NewValue)
+            {
+                Application.Iteration += OnApplicationOnIteration;
+                initialized = true;
+                lock (_timeoutLock)
+                {
+                    timeout = Application.AddTimeout (TimeSpan.FromMilliseconds (abortTime), ForceCloseCallback);
+                }
+            }
+            else
+            {
+                Application.Iteration -= OnApplicationOnIteration;
+                shutdown = true;
+            }
+        }
+
+        bool ForceCloseCallback ()
+        {
+            lock (_timeoutLock)
+            {
+                _output.WriteLine ($"ForceCloseCallback. iteration: {iteration}");
+                if (timeout is { })
+                {
+                    timeout = null;
+                }
+            }
+            Application.ResetState (true);
+            Assert.Fail ($"Failed to Quit with {Application.QuitKey} after {abortTime}ms. Force quit.");
+
+            return false;
+        }
+
+        void OnApplicationOnIteration (object s, IterationEventArgs a)
+        {
+            _output.WriteLine ("Iteration: {0}", iteration);
+            iteration++;
+            Assert.True (iteration < 2, "Too many iterations, something is wrong.");
+            if (Application._initialized)
+            {
+                _output.WriteLine ("  Pressing QuitKey");
+                Application.OnKeyDown (Application.QuitKey);
+            }
+        }
+    }
+
     [Fact]
     public void AlternateForwardKey_AlternateBackwardKey_Tests ()
     {

+ 13 - 5
UnitTests/Application/MainLoopTests.cs

@@ -1,4 +1,5 @@
 using System.Diagnostics;
+using System.IO;
 
 // Alias Console to MockConsole so we don't accidentally use Console
 
@@ -619,16 +620,22 @@ public class MainLoopTests
                        );
     }
 
-    [Fact]
-    public async Task InvokeLeakTest ()
+    [Theory]
+    [InlineData (typeof (FakeDriver))]
+    //[InlineData (typeof (NetDriver))] // BUGBUG: NetDriver never exits in this test
+
+    //[InlineData (typeof (ANSIDriver))]
+    //[InlineData (typeof (WindowsDriver))] // BUGBUG: NetDriver never exits in this test
+    //[InlineData (typeof (CursesDriver))] // BUGBUG: CursesDriver never exits in this test
+    public async Task InvokeLeakTest (Type driverType)
     {
-        Application.Init ();
+        Application.Init (driverName: driverType.Name);
         Random r = new ();
         TextField tf = new ();
         var top = new Toplevel ();
         top.Add (tf);
 
-        const int numPasses = 5;
+        const int numPasses = 2;
         const int numIncrements = 500;
         const int pollMs = 2500;
 
@@ -658,7 +665,8 @@ public class MainLoopTests
         int pfour
     )
     {
-        Application.Init ();
+        // TODO: Expand this test to test all drivers
+        Application.Init (new FakeDriver());
 
         total = 0;
         btn = null;

+ 7 - 3
UnitTests/Application/SynchronizatonContextTests.cs

@@ -18,10 +18,14 @@ public class SyncrhonizationContextTests
         Application.Shutdown ();
     }
 
-    [Fact]
-    public void SynchronizationContext_Post ()
+    [Theory]
+    [InlineData (typeof (FakeDriver))]
+    //[InlineData (typeof (NetDriver))]
+    [InlineData (typeof (WindowsDriver))]
+    //[InlineData (typeof (CursesDriver))]
+    public void SynchronizationContext_Post (Type driverType)
     {
-        Application.Init ();
+        Application.Init (driverName: driverType.Name);
         SynchronizationContext context = SynchronizationContext.Current;
 
         var success = false;

+ 9 - 0
UnitTests/Configuration/ConfigurationMangerTests.cs

@@ -1,5 +1,6 @@
 using System.Reflection;
 using System.Text.Json;
+using Xunit.Abstractions;
 using static Terminal.Gui.ConfigurationManager;
 #pragma warning disable IDE1006
 
@@ -7,6 +8,13 @@ namespace Terminal.Gui.ConfigurationTests;
 
 public class ConfigurationManagerTests
 {
+    private readonly ITestOutputHelper _output;
+
+    public ConfigurationManagerTests (ITestOutputHelper output)
+    {
+        _output = output;
+    }
+
     public static readonly JsonSerializerOptions _jsonOptions = new ()
     {
         Converters = { new AttributeJsonConverter (), new ColorJsonConverter () }
@@ -402,6 +410,7 @@ public class ConfigurationManagerTests
         // Application is a static class
         PropertyInfo pi = typeof (Application).GetProperty ("QuitKey");
         Assert.Equal (pi, Settings ["Application.QuitKey"].PropertyInfo);
+        
 
         // FrameView is not a static class and DefaultBorderStyle is Scope.Scheme
         pi = typeof (FrameView).GetProperty ("DefaultBorderStyle");

+ 41 - 24
UnitTests/UICatalog/ScenarioTests.cs

@@ -23,7 +23,7 @@ public class ScenarioTests : TestsAllViews
                      .Where (type => type.IsClass && !type.IsAbstract && type.IsSubclassOf (typeof (Scenario)))
                      .Select (type => new object [] { type });
 
-    private readonly object _timeoutLock = new object ();
+    private object _timeoutLock;
 
     /// <summary>
     ///     <para>This runs through all Scenarios defined in UI Catalog, calling Init, Setup, and Run.</para>
@@ -33,41 +33,27 @@ public class ScenarioTests : TestsAllViews
     [MemberData (nameof (AllScenarioTypes))]
     public void All_Scenarios_Quit_And_Init_Shutdown_Properly (Type scenarioType)
     {
+        Assert.Null (_timeoutLock);
+        _timeoutLock = new object ();
+
         // If a previous test failed, this will ensure that the Application is in a clean state
         Application.ResetState (true);
 
         _output.WriteLine ($"Running Scenario '{scenarioType}'");
         Scenario scenario = (Scenario)Activator.CreateInstance (scenarioType);
 
-        uint abortTime = 500;
+        uint abortTime = 1500;
         bool initialized = false;
         bool shutdown = false;
         object timeout = null;
 
-        void OnApplicationOnInitializedChanged (object s, StateEventArgs<bool> a)
-        {
-            if (a.NewValue)
-            {
-                lock (_timeoutLock)
-                {
-                    timeout = Application.AddTimeout (TimeSpan.FromMilliseconds (abortTime), ForceCloseCallback);
-                }
-
-                Application.Iteration += OnApplicationOnIteration;
-                initialized = true;
-            }
-            else
-            {
-                Application.Iteration -= OnApplicationOnIteration;
-                shutdown = true;
-            }
-        }
-
         Application.InitializedChanged += OnApplicationOnInitializedChanged;
 
+        Application.ForceDriver = "FakeDriver";
         scenario.Main ();
         scenario.Dispose ();
         scenario = null;
+        Application.ForceDriver = string.Empty;
 
         Application.InitializedChanged -= OnApplicationOnInitializedChanged;
 
@@ -75,7 +61,6 @@ public class ScenarioTests : TestsAllViews
         {
             if (timeout is { })
             {
-                Application.RemoveTimeout (timeout);
                 timeout = null;
             }
         }
@@ -87,8 +72,40 @@ public class ScenarioTests : TestsAllViews
 #if DEBUG_IDISPOSABLE
         Assert.Empty (Responder.Instances);
 #endif
+
+        lock (_timeoutLock)
+        {
+            _timeoutLock = null;
+        }
+
         return;
 
+
+        void OnApplicationOnInitializedChanged (object s, StateEventArgs<bool> a)
+        {
+            if (a.NewValue)
+            {
+                Assert.Equal (Key.Q.WithCtrl, Application.QuitKey);
+
+                Application.Iteration += OnApplicationOnIteration;
+                initialized = true;
+                lock (_timeoutLock)
+                {
+                    timeout = Application.AddTimeout (TimeSpan.FromMilliseconds (abortTime), ForceCloseCallback);
+                }
+                _output.WriteLine ($"Initialized '{Application.Driver}'");
+                //Dictionary<Key, List<View>> bindings = Application.GetKeyBindings ();
+                //Assert.NotEmpty (bindings);
+                //_output.WriteLine ($"bindings: {string.Join (",", bindings.Keys)}");
+                //Assert.True (bindings.ContainsKey (Application.QuitKey));
+            }
+            else
+            {
+                Application.Iteration -= OnApplicationOnIteration;
+                shutdown = true;
+            }
+        }
+
         // If the scenario doesn't close within 500ms, this will force it to quit
         bool ForceCloseCallback ()
         {
@@ -96,14 +113,13 @@ public class ScenarioTests : TestsAllViews
             {
                 if (timeout is { })
                 {
-                    Application.RemoveTimeout (timeout);
                     timeout = null;
                 }
             }
-            Application.ResetState (true);
             Assert.Fail (
                          $"'{scenario.GetName ()}' failed to Quit with {Application.QuitKey} after {abortTime}ms. Force quit.");
 
+            Application.ResetState (true);
             return false;
         }
 
@@ -112,6 +128,7 @@ public class ScenarioTests : TestsAllViews
             if (Application._initialized)
             {
                 // Press QuitKey 
+                //_output.WriteLine ($"Forcing Quit with {Application.QuitKey}");
                 Application.OnKeyDown (Application.QuitKey);
             }
         }

+ 91 - 3
UnitTests/Views/ButtonTests.cs

@@ -258,6 +258,93 @@ public class ButtonTests (ITestOutputHelper output)
         Assert.True (clicked);
     }
 
+    [Theory]
+    [InlineData (false, 0)]
+    [InlineData (true, 1)]
+    public void Space_Fires_Accept (bool focused, int expected)
+    {
+        View superView = new View ()
+        {
+            CanFocus = true,
+        };
+
+        Button button = new ();
+
+        button.CanFocus = focused;
+
+        int acceptInvoked = 0;
+        button.Accept += (s, e) => acceptInvoked++;
+
+        superView.Add (button);
+        button.SetFocus ();
+        Assert.Equal (focused, button.HasFocus);
+
+        superView.NewKeyDownEvent (Key.Space);
+
+        Assert.Equal (expected, acceptInvoked);
+
+        superView.Dispose ();
+    }
+
+    [Theory]
+    [InlineData (false, 0)]
+    [InlineData (true, 1)]
+    public void Enter_Fires_Accept (bool focused, int expected)
+    {
+        View superView = new View ()
+        {
+            CanFocus = true,
+        };
+
+        Button button = new ();
+
+        button.CanFocus = focused;
+
+        int acceptInvoked = 0;
+        button.Accept += (s, e) => acceptInvoked++;
+
+        superView.Add (button);
+        button.SetFocus ();
+        Assert.Equal (focused, button.HasFocus);
+
+        superView.NewKeyDownEvent (Key.Enter);
+
+        Assert.Equal (expected, acceptInvoked);
+
+        superView.Dispose ();
+    }
+
+    [Theory]
+    [InlineData (false, 1)]
+    [InlineData (true, 1)]
+    public void HotKey_Fires_Accept (bool focused, int expected)
+    {
+        View superView = new View ()
+        {
+            CanFocus = true,
+        };
+
+        Button button = new ()
+        {
+            HotKey = Key.A
+        };
+
+        button.CanFocus = focused;
+
+        int acceptInvoked = 0;
+        button.Accept += (s, e) => acceptInvoked++;
+
+        superView.Add (button);
+        button.SetFocus ();
+        Assert.Equal (focused, button.HasFocus);
+
+        superView.NewKeyDownEvent (Key.A);
+
+        Assert.Equal (expected, acceptInvoked);
+
+        superView.Dispose ();
+    }
+
     /// <summary>
     ///     This test demonstrates how to change the activation key for Button as described in the README.md keyboard
     ///     handling section
@@ -279,7 +366,9 @@ public class ButtonTests (ITestOutputHelper output)
         top.Add (btn);
         Application.Begin (top);
 
-        // default keybinding is Space which results in keypress
+        Assert.True (btn.HasFocus);
+
+        // default keybinding is Space which results in Command.Accept (when focused)
         Application.OnKeyDown (new ((KeyCode)' '));
         Assert.Equal (1, pressed);
 
@@ -292,8 +381,7 @@ public class ButtonTests (ITestOutputHelper output)
         Assert.Equal (1, pressed);
 
         // Set a new binding of b for the click (Accept) event
-        btn.KeyBindings.Add (Key.B, Command.HotKey);
-        btn.KeyBindings.Add (Key.B, Command.Accept);
+        btn.KeyBindings.Add (Key.B, Command.HotKey); // b will now trigger the Accept command (when focused or not)
 
         // now pressing B should call the button click event
         Application.OnKeyDown (Key.B);

+ 19 - 21
UnitTests/Views/ToplevelTests.cs

@@ -627,42 +627,40 @@ public class ToplevelTests (ITestOutputHelper output)
         Assert.Equal (win1, Application.Current);
         Assert.Equal (win1, Application.OverlappedChildren [0]);
         win1.Running = true;
-        Assert.True (Application.OverlappedChildren [0].NewKeyDownEvent (Application.QuitKey));
+        Assert.True (Application.OnKeyDown (Application.QuitKey));
         Assert.False (isRunning);
         Assert.False (win1.Running);
         Assert.Equal (win1, Application.OverlappedChildren [0]);
 
         Assert.True (
-                     Application.OverlappedChildren [0].NewKeyDownEvent (Key.Z.WithCtrl)
+                     Application.OnKeyDown (Key.Z.WithCtrl)
                     );
 
-        Assert.True (Application.OverlappedChildren [0].NewKeyDownEvent (Key.F5)); // refresh
+        Assert.True (Application.OnKeyDown (Key.F5)); // refresh
 
-        Assert.True (Application.OverlappedChildren [0].NewKeyDownEvent (Key.Tab));
+        Assert.True (Application.OnKeyDown (Key.Tab));
         Assert.True (win1.IsCurrentTop);
         Assert.Equal (tvW1, win1.MostFocused);
-        Assert.True (Application.OverlappedChildren [0].NewKeyDownEvent (Key.Tab));
+        Assert.True (Application.OnKeyDown (Key.Tab));
         Assert.Equal ($"\tFirst line Win1{Environment.NewLine}Second line Win1", tvW1.Text);
 
         Assert.True (
-                     Application.OverlappedChildren [0]
-                                .NewKeyDownEvent (Key.Tab.WithShift)
+                     Application.OnKeyDown (Key.Tab.WithShift)
                     );
         Assert.Equal ($"First line Win1{Environment.NewLine}Second line Win1", tvW1.Text);
 
         Assert.True (
-                     Application.OverlappedChildren [0]
-                                .NewKeyDownEvent (Key.Tab.WithCtrl)
+                     Application.OnKeyDown (Key.Tab.WithCtrl)
                     );
         Assert.Equal (win1, Application.OverlappedChildren [0]);
         Assert.Equal (tf2W1, win1.MostFocused);
-        Assert.True (Application.OverlappedChildren [0].NewKeyDownEvent (Key.Tab));
+        Assert.True (Application.OnKeyDown (Key.Tab));
         Assert.Equal (win1, Application.OverlappedChildren [0]);
         Assert.Equal (tf1W1, win1.MostFocused);
-        Assert.True (Application.OverlappedChildren [0].NewKeyDownEvent (Key.CursorRight));
+        Assert.True (Application.OnKeyDown (Key.CursorRight));
         Assert.Equal (win1, Application.OverlappedChildren [0]);
         Assert.Equal (tf1W1, win1.MostFocused);
-        Assert.True (Application.OverlappedChildren [0].NewKeyDownEvent (Key.CursorDown));
+        Assert.True (Application.OnKeyDown (Key.CursorDown));
         Assert.Equal (win1, Application.OverlappedChildren [0]);
         Assert.Equal (tvW1, win1.MostFocused);
 #if UNIX_KEY_BINDINGS
@@ -676,13 +674,13 @@ public class ToplevelTests (ITestOutputHelper output)
                     );
         Assert.Equal (win1, Application.OverlappedChildren [0]);
         Assert.Equal (tvW1, win1.MostFocused);
-        Assert.True (Application.OverlappedChildren [0].NewKeyDownEvent (Key.CursorLeft));
+        Assert.True (Application.OnKeyDown (Key.CursorLeft));
         Assert.Equal (win1, Application.OverlappedChildren [0]);
         Assert.Equal (tf1W1, win1.MostFocused);
-        Assert.True (Application.OverlappedChildren [0].NewKeyDownEvent (Key.CursorUp));
+        Assert.True (Application.OnKeyDown (Key.CursorUp));
         Assert.Equal (win1, Application.OverlappedChildren [0]);
         Assert.Equal (tf2W1, win1.MostFocused);
-        Assert.True (Application.OverlappedChildren [0].NewKeyDownEvent (Key.Tab));
+        Assert.True (Application.OnKeyDown (Key.Tab));
         Assert.Equal (win1, Application.OverlappedChildren [0]);
         Assert.Equal (tf1W1, win1.MostFocused);
 
@@ -701,23 +699,23 @@ public class ToplevelTests (ITestOutputHelper output)
                     );
         Assert.Equal (win1, Application.OverlappedChildren [0]);
         Assert.Equal (tf1W1, win1.MostFocused);
-        Assert.True (Application.OverlappedChildren [0].NewKeyDownEvent (Application.AlternateForwardKey));
+        Assert.True (Application.OnKeyDown (Application.AlternateForwardKey));
         Assert.Equal (win2, Application.OverlappedChildren [0]);
         Assert.Equal (tf2W2, win2.MostFocused);
-        Assert.True (Application.OverlappedChildren [0].NewKeyDownEvent (Application.AlternateBackwardKey));
+        Assert.True (Application.OnKeyDown (Application.AlternateBackwardKey));
         Assert.Equal (win1, Application.OverlappedChildren [0]);
         Assert.Equal (tf1W1, win1.MostFocused);
-        Assert.True (Application.OverlappedChildren [0].NewKeyDownEvent (Key.CursorDown));
+        Assert.True (Application.OnKeyDown (Key.CursorDown));
         Assert.Equal (win1, Application.OverlappedChildren [0]);
         Assert.Equal (tvW1, win1.MostFocused);
 #if UNIX_KEY_BINDINGS
         Assert.True (Application.OverlappedChildren [0].ProcessKeyDown (new (Key.B.WithCtrl)));
 #else
-        Assert.True (Application.OverlappedChildren [0].NewKeyDownEvent (Key.CursorLeft));
+        Assert.True (Application.OnKeyDown (Key.CursorLeft));
 #endif
         Assert.Equal (win1, Application.OverlappedChildren [0]);
         Assert.Equal (tf1W1, win1.MostFocused);
-        Assert.True (Application.OverlappedChildren [0].NewKeyDownEvent (Key.CursorDown));
+        Assert.True (Application.OnKeyDown (Key.CursorDown));
         Assert.Equal (win1, Application.OverlappedChildren [0]);
         Assert.Equal (tvW1, win1.MostFocused);
         Assert.Equal (Point.Empty, tvW1.CursorPosition);
@@ -732,7 +730,7 @@ public class ToplevelTests (ITestOutputHelper output)
 #if UNIX_KEY_BINDINGS
         Assert.True (Application.OverlappedChildren [0].ProcessKeyDown (new (Key.F.WithCtrl)));
 #else
-        Assert.True (Application.OverlappedChildren [0].NewKeyDownEvent (Key.CursorRight));
+        Assert.True (Application.OnKeyDown (Key.CursorRight));
 #endif
         Assert.Equal (win1, Application.OverlappedChildren [0]);
         Assert.Equal (tf2W1, win1.MostFocused);