Browse Source

Merge branch 'v2_develop' into ansi-parser

Thomas Nind 9 months ago
parent
commit
d56daac2b0
100 changed files with 2009 additions and 1740 deletions
  1. 0 4
      .gitignore
  2. 0 9
      NativeAot/PackTerminalGui.ps1
  3. 0 11
      NativeAot/PackTerminalGui.sh
  4. 0 9
      SelfContained/PackTerminalGui.ps1
  5. 0 11
      SelfContained/PackTerminalGui.sh
  6. 3 3
      Terminal.Gui/Application/Application.Initialization.cs
  7. 75 191
      Terminal.Gui/Application/Application.Keyboard.cs
  8. 40 29
      Terminal.Gui/Application/Application.Mouse.cs
  9. 79 0
      Terminal.Gui/Application/Application.Navigation.cs
  10. 42 7
      Terminal.Gui/Application/Application.Run.cs
  11. 14 1
      Terminal.Gui/Application/ApplicationNavigation.cs
  12. 2 2
      Terminal.Gui/ConsoleDrivers/ConsoleDriver.cs
  13. 1 1
      Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs
  14. 3 3
      Terminal.Gui/ConsoleDrivers/NetDriver.cs
  15. 5 5
      Terminal.Gui/ConsoleDrivers/WindowsDriver.cs
  16. 3 0
      Terminal.Gui/Drawing/Glyphs.cs
  17. 5 0
      Terminal.Gui/Input/Command.cs
  18. 101 0
      Terminal.Gui/Input/MouseEventArgs.cs
  19. 0 32
      Terminal.Gui/Input/MouseEventEventArgs.cs
  20. 2 49
      Terminal.Gui/Input/MouseFlags.cs
  21. 0 173
      Terminal.Gui/Input/ShortcutHelper.cs
  22. 33 1
      Terminal.Gui/Terminal.Gui.csproj
  23. 1 1
      Terminal.Gui/Text/Autocomplete/AppendAutocomplete.cs
  24. 1 1
      Terminal.Gui/Text/Autocomplete/AutocompleteBase.cs
  25. 1 1
      Terminal.Gui/Text/Autocomplete/IAutocomplete.cs
  26. 1 1
      Terminal.Gui/Text/Autocomplete/PopupAutocomplete.PopUp.cs
  27. 2 2
      Terminal.Gui/Text/Autocomplete/PopupAutocomplete.cs
  28. 2 7
      Terminal.Gui/View/Adornment/Border.cs
  29. 1 1
      Terminal.Gui/View/Adornment/Padding.cs
  30. 1 1
      Terminal.Gui/View/Adornment/ShadowView.cs
  31. 11 0
      Terminal.Gui/View/CancelEventArgs.cs
  32. 18 0
      Terminal.Gui/View/Navigation/AdvanceFocusEventArgs.cs
  33. 1 1
      Terminal.Gui/View/Navigation/FocusEventArgs.cs
  34. 2 4
      Terminal.Gui/View/Orientation/OrientationHelper.cs
  35. 7 0
      Terminal.Gui/View/View.Hierarchy.cs
  36. 141 182
      Terminal.Gui/View/View.Keyboard.cs
  37. 0 1
      Terminal.Gui/View/View.Layout.cs
  38. 96 85
      Terminal.Gui/View/View.Mouse.cs
  39. 202 63
      Terminal.Gui/View/View.Navigation.cs
  40. 5 5
      Terminal.Gui/Views/Bar.cs
  41. 1 1
      Terminal.Gui/Views/Button.cs
  42. 2 3
      Terminal.Gui/Views/ColorBar.cs
  43. 2 2
      Terminal.Gui/Views/ColorPicker.16.cs
  44. 6 5
      Terminal.Gui/Views/ComboBox.cs
  45. 9 6
      Terminal.Gui/Views/DateField.cs
  46. 13 13
      Terminal.Gui/Views/FileDialog.cs
  47. 1 1
      Terminal.Gui/Views/FrameView.cs
  48. 394 237
      Terminal.Gui/Views/HexView.cs
  49. 15 15
      Terminal.Gui/Views/HexViewEventArgs.cs
  50. 1 1
      Terminal.Gui/Views/Label.cs
  51. 56 4
      Terminal.Gui/Views/ListView.cs
  52. 9 15
      Terminal.Gui/Views/Menu/Menu.cs
  53. 4 4
      Terminal.Gui/Views/Menu/MenuBar.cs
  54. 5 5
      Terminal.Gui/Views/RadioGroup.cs
  55. 8 8
      Terminal.Gui/Views/ScrollBarView.cs
  56. 8 8
      Terminal.Gui/Views/ScrollView.cs
  57. 1 1
      Terminal.Gui/Views/Shortcut.cs
  58. 2 4
      Terminal.Gui/Views/Slider.cs
  59. 3 3
      Terminal.Gui/Views/TabMouseEventArgs.cs
  60. 6 14
      Terminal.Gui/Views/TabView.cs
  61. 3 3
      Terminal.Gui/Views/TableView/CheckBoxTableSourceWrapper.cs
  62. 14 12
      Terminal.Gui/Views/TableView/TableView.cs
  63. 2 2
      Terminal.Gui/Views/TableView/TreeTableSource.cs
  64. 16 34
      Terminal.Gui/Views/TextField.cs
  65. 2 2
      Terminal.Gui/Views/TextValidateField.cs
  66. 84 94
      Terminal.Gui/Views/TextView.cs
  67. 3 3
      Terminal.Gui/Views/TileView.cs
  68. 9 6
      Terminal.Gui/Views/TimeField.cs
  69. 1 1
      Terminal.Gui/Views/Toplevel.cs
  70. 8 15
      Terminal.Gui/Views/TreeView/TreeView.cs
  71. 2 2
      Terminal.Gui/Views/Wizard/Wizard.cs
  72. 4 4
      UICatalog/Scenarios/ASCIICustomButton.cs
  73. 1 1
      UICatalog/Scenarios/AdornmentsEditor.cs
  74. 1 1
      UICatalog/Scenarios/ArrangementEditor.cs
  75. 8 8
      UICatalog/Scenarios/Bars.cs
  76. 9 11
      UICatalog/Scenarios/CharacterMap.cs
  77. 5 5
      UICatalog/Scenarios/ContentScrolling.cs
  78. 3 3
      UICatalog/Scenarios/ContextMenus.cs
  79. 110 71
      UICatalog/Scenarios/HexEditor.cs
  80. 92 70
      UICatalog/Scenarios/Keys.cs
  81. 12 8
      UICatalog/Scenarios/LineDrawing.cs
  82. 1 1
      UICatalog/Scenarios/ListColumns.cs
  83. 3 3
      UICatalog/Scenarios/Mouse.cs
  84. 5 5
      UICatalog/Scenarios/Snake.cs
  85. 5 5
      UICatalog/Scenarios/TableEditor.cs
  86. 1 1
      UICatalog/Scenarios/Text.cs
  87. 5 5
      UICatalog/Scenarios/TreeViewFileSystem.cs
  88. 3 3
      UICatalog/Scenarios/VkeyPacketSimulator.cs
  89. 23 22
      UICatalog/UICatalog.cs
  90. 3 3
      UnitTests/Application/Application.NavigationTests.cs
  91. 7 7
      UnitTests/Application/ApplicationTests.cs
  92. 45 45
      UnitTests/Application/KeyboardTests.cs
  93. 3 3
      UnitTests/Application/Mouse/ApplicationMouseEnterLeaveTests.cs
  94. 16 16
      UnitTests/Application/Mouse/ApplicationMouseTests.cs
  95. 5 5
      UnitTests/Dialogs/MessageBoxTests.cs
  96. 6 4
      UnitTests/FileServices/FileDialogTests.cs
  97. 2 2
      UnitTests/Input/EscSeqUtilsTests.cs
  98. 6 6
      UnitTests/Input/ResponderTests.cs
  99. 33 0
      UnitTests/LocalPackagesTests.cs
  100. 1 1
      UnitTests/UICatalog/ScenarioTests.cs

+ 0 - 4
.gitignore

@@ -34,9 +34,6 @@ _ReSharper.**
 ~$*
 ~$*
 *~
 *~
 
 
-# NuGet Stuff
-*.nupkg
-*.snupkg
 # Exclude everything in packages directory except the packages/build directory
 # Exclude everything in packages directory except the packages/build directory
 **/[Pp]ackages/*
 **/[Pp]ackages/*
 !**/[Pp]ackages/build/
 !**/[Pp]ackages/build/
@@ -61,4 +58,3 @@ demo.*
 *.tui/
 *.tui/
 
 
 *.dotCover
 *.dotCover
-/local_packages/

+ 0 - 9
NativeAot/PackTerminalGui.ps1

@@ -1,9 +0,0 @@
-# Step 1: Build and pack Terminal.Gui
-dotnet build ../Terminal.Gui/Terminal.Gui.csproj --configuration Release
-dotnet pack ../Terminal.Gui/Terminal.Gui.csproj --configuration Release --output ../local_packages
-
-# Step 2: Restore NativeAot with the new package
-dotnet restore ./NativeAot.csproj --source ./local_packages
-
-# Step 3: Build NativeAot
-dotnet build ./NativeAot.csproj --configuration Release

+ 0 - 11
NativeAot/PackTerminalGui.sh

@@ -1,11 +0,0 @@
-#!/bin/bash
-
-# Step 1: Build and pack Terminal.Gui
-dotnet build ../Terminal.Gui/Terminal.Gui.csproj --configuration Release
-dotnet pack ../Terminal.Gui/Terminal.Gui.csproj --configuration Release --output ../local_packages
-
-# Step 2: Restore NativeAot with the new package
-dotnet restore ./NativeAot.csproj --source ./local_packages
-
-# Step 3: Build NativeAot
-dotnet build ./NativeAot.csproj --configuration Release

+ 0 - 9
SelfContained/PackTerminalGui.ps1

@@ -1,9 +0,0 @@
-# Step 1: Build and pack Terminal.Gui
-dotnet build ../Terminal.Gui/Terminal.Gui.csproj --configuration Release
-dotnet pack ../Terminal.Gui/Terminal.Gui.csproj --configuration Release --output ../local_packages
-
-# Step 2: Restore SelfContained with the new package
-dotnet restore ./SelfContained.csproj --source ./local_packages
-
-# Step 3: Build SelfContained
-dotnet build ./SelfContained.csproj --configuration Release

+ 0 - 11
SelfContained/PackTerminalGui.sh

@@ -1,11 +0,0 @@
-#!/bin/bash
-
-# Step 1: Build and pack Terminal.Gui
-dotnet build ../Terminal.Gui/Terminal.Gui.csproj --configuration Release
-dotnet pack ../Terminal.Gui/Terminal.Gui.csproj --configuration Release --output ../local_packages
-
-# Step 2: Restore SelfContained with the new package
-dotnet restore ./SelfContained.csproj --source ./local_packages
-
-# Step 3: Build SelfContained
-dotnet build ./SelfContained.csproj --configuration Release

+ 3 - 3
Terminal.Gui/Application/Application.Initialization.cs

@@ -178,9 +178,9 @@ public static partial class Application // Initialization (Init/Shutdown)
     }
     }
 
 
     private static void Driver_SizeChanged (object? sender, SizeChangedEventArgs e) { OnSizeChanging (e); }
     private static void Driver_SizeChanged (object? sender, SizeChangedEventArgs e) { OnSizeChanging (e); }
-    private static void Driver_KeyDown (object? sender, Key e) { OnKeyDown (e); }
-    private static void Driver_KeyUp (object? sender, Key e) { OnKeyUp (e); }
-    private static void Driver_MouseEvent (object? sender, MouseEvent e) { OnMouseEvent (e); }
+    private static void Driver_KeyDown (object? sender, Key e) { RaiseKeyDownEvent (e); }
+    private static void Driver_KeyUp (object? sender, Key e) { RaiseKeyUpEvent (e); }
+    private static void Driver_MouseEvent (object? sender, MouseEventArgs e) { RaiseMouseEvent (e); }
 
 
     /// <summary>Gets of list of <see cref="ConsoleDriver"/> types that are available.</summary>
     /// <summary>Gets of list of <see cref="ConsoleDriver"/> types that are available.</summary>
     /// <returns></returns>
     /// <returns></returns>

+ 75 - 191
Terminal.Gui/Application/Application.Keyboard.cs

@@ -3,94 +3,19 @@ namespace Terminal.Gui;
 
 
 public static partial class Application // Keyboard handling
 public static partial class Application // Keyboard handling
 {
 {
-    private static Key _nextTabGroupKey = Key.F6; // Resources/config.json overrrides
-    private static Key _nextTabKey = Key.Tab; // Resources/config.json overrrides
-    private static Key _prevTabGroupKey = Key.F6.WithShift; // Resources/config.json overrrides
-    private static Key _prevTabKey = Key.Tab.WithShift; // Resources/config.json overrrides
-    private static Key _quitKey = Key.Esc; // Resources/config.json overrrides
-    private static Key _arrangeKey = Key.F5.WithCtrl; // Resources/config.json overrrides
-
-    static Application () { AddApplicationKeyBindings (); }
-
-    /// <summary>Gets the key bindings for this view.</summary>
-    public static KeyBindings KeyBindings { get; internal set; } = new ();
-
-    /// <summary>
-    ///     Event fired when the user presses a key. Fired by <see cref="OnKeyDown"/>.
-    ///     <para>
-    ///         Set <see cref="Key.Handled"/> to <see langword="true"/> to indicate the key was handled and to prevent
-    ///         additional processing.
-    ///     </para>
-    /// </summary>
-    /// <remarks>
-    ///     All drivers support firing the <see cref="KeyDown"/> event. Some drivers (Curses) do not support firing the
-    ///     <see cref="KeyDown"/> and <see cref="KeyUp"/> events.
-    ///     <para>Fired after <see cref="KeyDown"/> and before <see cref="KeyUp"/>.</para>
-    /// </remarks>
-    public static event EventHandler<Key>? KeyDown;
-
     /// <summary>
     /// <summary>
-    ///     Event fired when the user releases a key. Fired by <see cref="OnKeyUp"/>.
-    ///     <para>
-    ///         Set <see cref="Key.Handled"/> to <see langword="true"/> to indicate the key was handled and to prevent
-    ///         additional processing.
-    ///     </para>
-    /// </summary>
-    /// <remarks>
-    ///     All drivers support firing the <see cref="KeyDown"/> event. Some drivers (Curses) do not support firing the
-    ///     <see cref="KeyDown"/> and <see cref="KeyUp"/> events.
-    ///     <para>Fired after <see cref="KeyDown"/>.</para>
-    /// </remarks>
-    public static event EventHandler<Key>? KeyUp;
-
-    /// <summary>Alternative key to navigate forwards through views. Ctrl+Tab is the primary key.</summary>
-    [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
-    public static Key NextTabGroupKey
-    {
-        get => _nextTabGroupKey;
-        set
-        {
-            if (_nextTabGroupKey != value)
-            {
-                ReplaceKey (_nextTabGroupKey, value);
-                _nextTabGroupKey = value;
-            }
-        }
-    }
-
-    /// <summary>Alternative key to navigate forwards through views. Ctrl+Tab is the primary key.</summary>
-    [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
-    public static Key NextTabKey
-    {
-        get => _nextTabKey;
-        set
-        {
-            if (_nextTabKey != value)
-            {
-                ReplaceKey (_nextTabKey, value);
-                _nextTabKey = value;
-            }
-        }
-    }
-
-    /// <summary>
-    ///     Called by the <see cref="ConsoleDriver"/> when the user presses a key. Fires the <see cref="KeyDown"/> event
-    ///     then calls <see cref="View.NewKeyDownEvent"/> on all top level views. Called after <see cref="OnKeyDown"/> and
-    ///     before <see cref="OnKeyUp"/>.
+    ///     Called when the user presses a key (by the <see cref="ConsoleDriver"/>). Raises the cancelable
+    ///     <see cref="KeyDown"/> event, then calls <see cref="View.NewKeyDownEvent"/> on all top level views, and finally
+    ///     if the key was not handled, invokes any Application-scoped <see cref="KeyBindings"/>.
     /// </summary>
     /// </summary>
     /// <remarks>Can be used to simulate key press events.</remarks>
     /// <remarks>Can be used to simulate key press events.</remarks>
-    /// <param name="keyEvent"></param>
+    /// <param name="key"></param>
     /// <returns><see langword="true"/> if the key was handled.</returns>
     /// <returns><see langword="true"/> if the key was handled.</returns>
-    public static bool OnKeyDown (Key keyEvent)
+    public static bool RaiseKeyDownEvent (Key key)
     {
     {
-        //if (!IsInitialized)
-        //{
-        //    return true;
-        //}
+        KeyDown?.Invoke (null, key);
 
 
-        KeyDown?.Invoke (null, keyEvent);
-
-        if (keyEvent.Handled)
+        if (key.Handled)
         {
         {
             return true;
             return true;
         }
         }
@@ -99,7 +24,7 @@ public static partial class Application // Keyboard handling
         {
         {
             foreach (Toplevel topLevel in TopLevels.ToList ())
             foreach (Toplevel topLevel in TopLevels.ToList ())
             {
             {
-                if (topLevel.NewKeyDownEvent (keyEvent))
+                if (topLevel.NewKeyDownEvent (key))
                 {
                 {
                     return true;
                     return true;
                 }
                 }
@@ -112,7 +37,7 @@ public static partial class Application // Keyboard handling
         }
         }
         else
         else
         {
         {
-            if (Top.NewKeyDownEvent (keyEvent))
+            if (Top.NewKeyDownEvent (key))
             {
             {
                 return true;
                 return true;
             }
             }
@@ -120,7 +45,7 @@ public static partial class Application // Keyboard handling
 
 
         // Invoke any Application-scoped KeyBindings.
         // Invoke any Application-scoped KeyBindings.
         // The first view that handles the key will stop the loop.
         // The first view that handles the key will stop the loop.
-        foreach (KeyValuePair<Key, KeyBinding> binding in KeyBindings.Bindings.Where (b => b.Key == keyEvent.KeyCode))
+        foreach (KeyValuePair<Key, KeyBinding> binding in KeyBindings.Bindings.Where (b => b.Key == key.KeyCode))
         {
         {
             if (binding.Value.BoundView is { })
             if (binding.Value.BoundView is { })
             {
             {
@@ -133,7 +58,7 @@ public static partial class Application // Keyboard handling
             }
             }
             else
             else
             {
             {
-                if (!KeyBindings.TryGet (keyEvent, KeyBindingScope.Application, out KeyBinding appBinding))
+                if (!KeyBindings.TryGet (key, KeyBindingScope.Application, out KeyBinding appBinding))
                 {
                 {
                     continue;
                     continue;
                 }
                 }
@@ -142,7 +67,7 @@ public static partial class Application // Keyboard handling
 
 
                 foreach (Command command in appBinding.Commands)
                 foreach (Command command in appBinding.Commands)
                 {
                 {
-                    toReturn = InvokeCommand (command, keyEvent, appBinding);
+                    toReturn = InvokeCommand (command, key, appBinding);
                 }
                 }
 
 
                 return toReturn ?? true;
                 return toReturn ?? true;
@@ -150,59 +75,66 @@ public static partial class Application // Keyboard handling
         }
         }
 
 
         return false;
         return false;
-    }
 
 
-    /// <summary>
-    ///     INTENRAL method to invoke one of the commands in <see cref="CommandImplementations"/>
-    /// </summary>
-    /// <param name="command"></param>
-    /// <param name="keyEvent"></param>
-    /// <param name="appBinding"></param>
-    /// <returns></returns>
-    /// <exception cref="NotSupportedException"></exception>
-    private static bool? InvokeCommand (Command command, Key keyEvent, KeyBinding appBinding)
-    {
-        if (!CommandImplementations!.ContainsKey (command))
+        static bool? InvokeCommand (Command command, Key key, KeyBinding appBinding)
         {
         {
-            throw new NotSupportedException (
-                                             @$"A KeyBinding was set up for the command {command} ({keyEvent}) but that command is not supported by Application."
-                                            );
-        }
+            if (!CommandImplementations!.ContainsKey (command))
+            {
+                throw new NotSupportedException (
+                                                 @$"A KeyBinding was set up for the command {command} ({key}) but that command is not supported by Application."
+                                                );
+            }
 
 
-        if (CommandImplementations.TryGetValue (command, out View.CommandImplementation? implementation))
-        {
-            var context = new CommandContext (command, keyEvent, appBinding); // Create the context here
+            if (CommandImplementations.TryGetValue (command, out View.CommandImplementation? implementation))
+            {
+                var context = new CommandContext (command, key, appBinding); // Create the context here
 
 
-            return implementation (context);
-        }
+                return implementation (context);
+            }
 
 
-        return false;
+            return false;
+        }
     }
     }
 
 
     /// <summary>
     /// <summary>
-    ///     Called by the <see cref="ConsoleDriver"/> when the user releases a key. Fires the <see cref="KeyUp"/> event
-    ///     then calls <see cref="View.NewKeyUpEvent"/> on all top level views. Called after <see cref="OnKeyDown"/>.
+    ///     Raised when the user presses a key.
+    ///     <para>
+    ///         Set <see cref="Key.Handled"/> to <see langword="true"/> to indicate the key was handled and to prevent
+    ///         additional processing.
+    ///     </para>
     /// </summary>
     /// </summary>
-    /// <remarks>Can be used to simulate key press events.</remarks>
-    /// <param name="a"></param>
+    /// <remarks>
+    ///     All drivers support firing the <see cref="KeyDown"/> event. Some drivers (Curses) do not support firing the
+    ///     <see cref="KeyDown"/> and <see cref="KeyUp"/> events.
+    ///     <para>Fired after <see cref="KeyDown"/> and before <see cref="KeyUp"/>.</para>
+    /// </remarks>
+    public static event EventHandler<Key>? KeyDown;
+
+    /// <summary>
+    ///     Called when the user releases a key (by the <see cref="ConsoleDriver"/>). Raises the cancelable <see cref="KeyUp"/>
+    ///     event
+    ///     then calls <see cref="View.NewKeyUpEvent"/> on all top level views. Called after <see cref="RaiseKeyDownEvent"/>.
+    /// </summary>
+    /// <remarks>Can be used to simulate key release events.</remarks>
+    /// <param name="key"></param>
     /// <returns><see langword="true"/> if the key was handled.</returns>
     /// <returns><see langword="true"/> if the key was handled.</returns>
-    public static bool OnKeyUp (Key a)
+    public static bool RaiseKeyUpEvent (Key key)
     {
     {
         if (!IsInitialized)
         if (!IsInitialized)
         {
         {
             return true;
             return true;
         }
         }
 
 
-        KeyUp?.Invoke (null, a);
+        KeyUp?.Invoke (null, key);
 
 
-        if (a.Handled)
+        if (key.Handled)
         {
         {
             return true;
             return true;
         }
         }
 
 
         foreach (Toplevel topLevel in TopLevels.ToList ())
         foreach (Toplevel topLevel in TopLevels.ToList ())
         {
         {
-            if (topLevel.NewKeyUpEvent (a))
+            if (topLevel.NewKeyUpEvent (key))
             {
             {
                 return true;
                 return true;
             }
             }
@@ -216,65 +148,12 @@ public static partial class Application // Keyboard handling
         return false;
         return false;
     }
     }
 
 
-    /// <summary>Alternative key to navigate backwards through views. Shift+Ctrl+Tab is the primary key.</summary>
-    [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
-    public static Key PrevTabGroupKey
-    {
-        get => _prevTabGroupKey;
-        set
-        {
-            if (_prevTabGroupKey != value)
-            {
-                ReplaceKey (_prevTabGroupKey, value);
-                _prevTabGroupKey = value;
-            }
-        }
-    }
-
-    /// <summary>Alternative key to navigate backwards through views. Shift+Ctrl+Tab is the primary key.</summary>
-    [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
-    public static Key PrevTabKey
-    {
-        get => _prevTabKey;
-        set
-        {
-            if (_prevTabKey != value)
-            {
-                ReplaceKey (_prevTabKey, value);
-                _prevTabKey = value;
-            }
-        }
-    }
+    #region Application-scoped KeyBindings
 
 
-    /// <summary>Gets or sets the key to quit the application.</summary>
-    [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
-    public static Key QuitKey
-    {
-        get => _quitKey;
-        set
-        {
-            if (_quitKey != value)
-            {
-                ReplaceKey (_quitKey, value);
-                _quitKey = value;
-            }
-        }
-    }
+    static Application () { AddApplicationKeyBindings (); }
 
 
-    /// <summary>Gets or sets the key to activate arranging views using the keyboard.</summary>
-    [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
-    public static Key ArrangeKey
-    {
-        get => _arrangeKey;
-        set
-        {
-            if (_arrangeKey != value)
-            {
-                ReplaceKey (_arrangeKey, value);
-                _arrangeKey = value;
-            }
-        }
-    }
+    /// <summary>Gets the Application-scoped key bindings.</summary>
+    public static KeyBindings KeyBindings { get; internal set; } = new ();
 
 
     internal static void AddApplicationKeyBindings ()
     internal static void AddApplicationKeyBindings ()
     {
     {
@@ -286,6 +165,7 @@ public static partial class Application // Keyboard handling
                     static () =>
                     static () =>
                     {
                     {
                         RequestStop ();
                         RequestStop ();
+
                         return true;
                         return true;
                     }
                     }
                    );
                    );
@@ -348,7 +228,7 @@ public static partial class Application // Keyboard handling
 
 
         KeyBindings.Clear ();
         KeyBindings.Clear ();
 
 
-        // Resources/config.json overrrides
+        // Resources/config.json overrides
         NextTabKey = Key.Tab;
         NextTabKey = Key.Tab;
         PrevTabKey = Key.Tab.WithShift;
         PrevTabKey = Key.Tab.WithShift;
         NextTabGroupKey = Key.F6;
         NextTabGroupKey = Key.F6;
@@ -397,6 +277,26 @@ public static partial class Application // Keyboard handling
                           .ToList ();
                           .ToList ();
     }
     }
 
 
+    private static void ReplaceKey (Key oldKey, Key newKey)
+    {
+        if (KeyBindings.Bindings.Count == 0)
+        {
+            return;
+        }
+
+        if (newKey == Key.Empty)
+        {
+            KeyBindings.Remove (oldKey);
+        }
+        else
+        {
+            KeyBindings.ReplaceKey (oldKey, newKey);
+        }
+    }
+
+
+    #endregion Application-scoped KeyBindings
+
     /// <summary>
     /// <summary>
     ///     <para>
     ///     <para>
     ///         Sets the function that will be invoked for a <see cref="Command"/>.
     ///         Sets the function that will be invoked for a <see cref="Command"/>.
@@ -420,20 +320,4 @@ public static partial class Application // Keyboard handling
     /// </summary>
     /// </summary>
     private static Dictionary<Command, View.CommandImplementation>? CommandImplementations { get; set; }
     private static Dictionary<Command, View.CommandImplementation>? CommandImplementations { get; set; }
 
 
-    private static void ReplaceKey (Key oldKey, Key newKey)
-    {
-        if (KeyBindings.Bindings.Count == 0)
-        {
-            return;
-        }
-
-        if (newKey == Key.Empty)
-        {
-            KeyBindings.Remove (oldKey);
-        }
-        else
-        {
-            KeyBindings.ReplaceKey (oldKey, newKey);
-        }
-    }
 }
 }

+ 40 - 29
Terminal.Gui/Application/Application.Mouse.cs

@@ -1,6 +1,5 @@
 #nullable enable
 #nullable enable
 using System.ComponentModel;
 using System.ComponentModel;
-using System.Diagnostics;
 
 
 namespace Terminal.Gui;
 namespace Terminal.Gui;
 
 
@@ -45,12 +44,12 @@ public static partial class Application // Mouse handling
     /// <param name="view">View that will receive all mouse events until <see cref="UngrabMouse"/> is invoked.</param>
     /// <param name="view">View that will receive all mouse events until <see cref="UngrabMouse"/> is invoked.</param>
     public static void GrabMouse (View? view)
     public static void GrabMouse (View? view)
     {
     {
-        if (view is null || OnGrabbingMouse (view))
+        if (view is null || RaiseGrabbingMouseEvent (view))
         {
         {
             return;
             return;
         }
         }
 
 
-        OnGrabbedMouse (view);
+        RaiseGrabbedMouseEvent (view);
         MouseGrabView = view;
         MouseGrabView = view;
     }
     }
 
 
@@ -66,16 +65,16 @@ public static partial class Application // Mouse handling
         ObjectDisposedException.ThrowIf (MouseGrabView.WasDisposed, MouseGrabView);
         ObjectDisposedException.ThrowIf (MouseGrabView.WasDisposed, MouseGrabView);
 #endif
 #endif
 
 
-        if (!OnUnGrabbingMouse (MouseGrabView))
+        if (!RaiseUnGrabbingMouseEvent (MouseGrabView))
         {
         {
             View view = MouseGrabView;
             View view = MouseGrabView;
             MouseGrabView = null;
             MouseGrabView = null;
-            OnUnGrabbedMouse (view);
+            RaiseUnGrabbedMouseEvent (view);
         }
         }
     }
     }
 
 
     /// <exception cref="Exception">A delegate callback throws an exception.</exception>
     /// <exception cref="Exception">A delegate callback throws an exception.</exception>
-    private static bool OnGrabbingMouse (View? view)
+    private static bool RaiseGrabbingMouseEvent (View? view)
     {
     {
         if (view is null)
         if (view is null)
         {
         {
@@ -89,7 +88,7 @@ public static partial class Application // Mouse handling
     }
     }
 
 
     /// <exception cref="Exception">A delegate callback throws an exception.</exception>
     /// <exception cref="Exception">A delegate callback throws an exception.</exception>
-    private static bool OnUnGrabbingMouse (View? view)
+    private static bool RaiseUnGrabbingMouseEvent (View? view)
     {
     {
         if (view is null)
         if (view is null)
         {
         {
@@ -103,7 +102,7 @@ public static partial class Application // Mouse handling
     }
     }
 
 
     /// <exception cref="Exception">A delegate callback throws an exception.</exception>
     /// <exception cref="Exception">A delegate callback throws an exception.</exception>
-    private static void OnGrabbedMouse (View? view)
+    private static void RaiseGrabbedMouseEvent (View? view)
     {
     {
         if (view is null)
         if (view is null)
         {
         {
@@ -114,7 +113,7 @@ public static partial class Application // Mouse handling
     }
     }
 
 
     /// <exception cref="Exception">A delegate callback throws an exception.</exception>
     /// <exception cref="Exception">A delegate callback throws an exception.</exception>
-    private static void OnUnGrabbedMouse (View? view)
+    private static void RaiseUnGrabbedMouseEvent (View? view)
     {
     {
         if (view is null)
         if (view is null)
         {
         {
@@ -124,20 +123,14 @@ public static partial class Application // Mouse handling
         UnGrabbedMouse?.Invoke (view, new (view));
         UnGrabbedMouse?.Invoke (view, new (view));
     }
     }
 
 
-    /// <summary>Event fired when a mouse move or click occurs. Coordinates are screen relative.</summary>
-    /// <remarks>
-    ///     <para>
-    ///         Use this event to receive mouse events in screen coordinates. Use <see cref="MouseEvent"/> to
-    ///         receive mouse events relative to a <see cref="View.Viewport"/>.
-    ///     </para>
-    ///     <para>The <see cref="MouseEvent.View"/> will contain the <see cref="View"/> that contains the mouse coordinates.</para>
-    /// </remarks>
-    public static event EventHandler<MouseEvent>? MouseEvent;
 
 
-    /// <summary>Called when a mouse event is raised by the driver.</summary>
+    /// <summary>
+    ///     INTERNAL API: Called when a mouse event is raised by the driver. Determines the view under the mouse and
+    ///     calls the appropriate View mouse event handlers.
+    /// </summary>
     /// <remarks>This method can be used to simulate a mouse event, e.g. in unit tests.</remarks>
     /// <remarks>This method can be used to simulate a mouse event, e.g. in unit tests.</remarks>
     /// <param name="mouseEvent">The mouse event with coordinates relative to the screen.</param>
     /// <param name="mouseEvent">The mouse event with coordinates relative to the screen.</param>
-    internal static void OnMouseEvent (MouseEvent mouseEvent)
+    internal static void RaiseMouseEvent (MouseEventArgs mouseEvent)
     {
     {
         _lastMousePosition = mouseEvent.ScreenPosition;
         _lastMousePosition = mouseEvent.ScreenPosition;
 
 
@@ -177,9 +170,6 @@ public static partial class Application // Mouse handling
             return;
             return;
         }
         }
 
 
-        // We can combine this into the switch expression to reduce cognitive complexity even more and likely
-        // avoid one or two of these checks in the process, as well.
-
         WantContinuousButtonPressedView = deepestViewUnderMouse switch
         WantContinuousButtonPressedView = deepestViewUnderMouse switch
         {
         {
             { WantContinuousButtonPressed: true } => deepestViewUnderMouse,
             { WantContinuousButtonPressed: true } => deepestViewUnderMouse,
@@ -194,7 +184,7 @@ public static partial class Application // Mouse handling
         }
         }
 
 
         // Create a view-relative mouse event to send to the view that is under the mouse.
         // Create a view-relative mouse event to send to the view that is under the mouse.
-        MouseEvent? viewMouseEvent;
+        MouseEventArgs? viewMouseEvent;
 
 
         if (deepestViewUnderMouse is Adornment adornment)
         if (deepestViewUnderMouse is Adornment adornment)
         {
         {
@@ -208,7 +198,7 @@ public static partial class Application // Mouse handling
                 View = deepestViewUnderMouse
                 View = deepestViewUnderMouse
             };
             };
         }
         }
-        else if (deepestViewUnderMouse.ViewportToScreen (Rectangle.Empty with { Size = deepestViewUnderMouse.Viewport.Size }).Contains (mouseEvent.Position))
+        else if (deepestViewUnderMouse.ViewportToScreen (Rectangle.Empty with { Size = deepestViewUnderMouse.Viewport.Size }).Contains (mouseEvent.ScreenPosition))
         {
         {
             Point viewportLocation = deepestViewUnderMouse.ScreenToViewport (mouseEvent.ScreenPosition);
             Point viewportLocation = deepestViewUnderMouse.ScreenToViewport (mouseEvent.ScreenPosition);
 
 
@@ -224,7 +214,7 @@ public static partial class Application // Mouse handling
         {
         {
             // The mouse was outside any View's Viewport.
             // The mouse was outside any View's Viewport.
 
 
-           // Debug.Fail ("This should never happen. If it does please file an Issue!!");
+            // Debug.Fail ("This should never happen. If it does please file an Issue!!");
 
 
             return;
             return;
         }
         }
@@ -261,7 +251,29 @@ public static partial class Application // Mouse handling
         }
         }
     }
     }
 
 
-    internal static bool HandleMouseGrab (View? deepestViewUnderMouse, MouseEvent mouseEvent)
+
+#pragma warning disable CS1574 // XML comment has cref attribute that could not be resolved
+    /// <summary>
+    /// Raised when a mouse event occurs. Can be cancelled by setting <see cref="MouseEventArgs.Handled"/> to <see langword="true"/>.
+    /// </summary>
+    /// <remarks>
+    ///     <para>
+    ///         <see cref="MouseEventArgs.ScreenPosition"/> coordinates are screen-relative.
+    ///     </para>
+    ///     <para>
+    ///         <see cref="MouseEventArgs.View"/> will be the deepest view under the under the mouse.
+    ///     </para>
+    ///     <para>
+    ///         <see cref="MouseEventArgs.Position"/> coordinates are view-relative. Only valid if <see cref="MouseEventArgs.View"/> is set.
+    ///     </para>
+    ///     <para>
+    ///         Use this evento to handle mouse events at the application level, before View-specific handling.
+    ///     </para>
+    /// </remarks>
+    public static event EventHandler<MouseEventArgs>? MouseEvent;
+#pragma warning restore CS1574 // XML comment has cref attribute that could not be resolved
+
+    internal static bool HandleMouseGrab (View? deepestViewUnderMouse, MouseEventArgs mouseEvent)
     {
     {
         if (MouseGrabView is { })
         if (MouseGrabView is { })
         {
         {
@@ -276,7 +288,7 @@ public static partial class Application // Mouse handling
             // The coordinates are relative to the Bounds of the view that grabbed the mouse.
             // The coordinates are relative to the Bounds of the view that grabbed the mouse.
             Point frameLoc = MouseGrabView.ScreenToViewport (mouseEvent.ScreenPosition);
             Point frameLoc = MouseGrabView.ScreenToViewport (mouseEvent.ScreenPosition);
 
 
-            var viewRelativeMouseEvent = new MouseEvent
+            var viewRelativeMouseEvent = new MouseEventArgs
             {
             {
                 Position = frameLoc,
                 Position = frameLoc,
                 Flags = mouseEvent.Flags,
                 Flags = mouseEvent.Flags,
@@ -303,7 +315,6 @@ public static partial class Application // Mouse handling
 
 
     internal static readonly List<View?> _cachedViewsUnderMouse = new ();
     internal static readonly List<View?> _cachedViewsUnderMouse = new ();
 
 
-    // TODO: Refactor MouseEnter/LeaveEvents to not take MouseEvent param.
     /// <summary>
     /// <summary>
     ///     INTERNAL: Raises the MouseEnter and MouseLeave events for the views that are under the mouse.
     ///     INTERNAL: Raises the MouseEnter and MouseLeave events for the views that are under the mouse.
     /// </summary>
     /// </summary>

+ 79 - 0
Terminal.Gui/Application/Application.Navigation.cs

@@ -7,4 +7,83 @@ public static partial class Application // Navigation stuff
     ///     Gets the <see cref="ApplicationNavigation"/> instance for the current <see cref="Application"/>.
     ///     Gets the <see cref="ApplicationNavigation"/> instance for the current <see cref="Application"/>.
     /// </summary>
     /// </summary>
     public static ApplicationNavigation? Navigation { get; internal set; }
     public static ApplicationNavigation? Navigation { get; internal set; }
+
+    private static Key _nextTabGroupKey = Key.F6; // Resources/config.json overrides
+    private static Key _nextTabKey = Key.Tab; // Resources/config.json overrides
+    private static Key _prevTabGroupKey = Key.F6.WithShift; // Resources/config.json overrides
+    private static Key _prevTabKey = Key.Tab.WithShift; // Resources/config.json overrides
+
+    /// <summary>Alternative key to navigate forwards through views. Ctrl+Tab is the primary key.</summary>
+    [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
+    public static Key NextTabGroupKey
+    {
+        get => _nextTabGroupKey;
+        set
+        {
+            if (_nextTabGroupKey != value)
+            {
+                ReplaceKey (_nextTabGroupKey, value);
+                _nextTabGroupKey = value;
+            }
+        }
+    }
+
+    /// <summary>Alternative key to navigate forwards through views. Ctrl+Tab is the primary key.</summary>
+    [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
+    public static Key NextTabKey
+    {
+        get => _nextTabKey;
+        set
+        {
+            if (_nextTabKey != value)
+            {
+                ReplaceKey (_nextTabKey, value);
+                _nextTabKey = value;
+            }
+        }
+    }
+
+
+    /// <summary>
+    ///     Raised when the user releases a key.
+    ///     <para>
+    ///         Set <see cref="Key.Handled"/> to <see langword="true"/> to indicate the key was handled and to prevent
+    ///         additional processing.
+    ///     </para>
+    /// </summary>
+    /// <remarks>
+    ///     All drivers support firing the <see cref="KeyDown"/> event. Some drivers (Curses) do not support firing the
+    ///     <see cref="KeyDown"/> and <see cref="KeyUp"/> events.
+    ///     <para>Fired after <see cref="KeyDown"/>.</para>
+    /// </remarks>
+    public static event EventHandler<Key>? KeyUp;
+    /// <summary>Alternative key to navigate backwards through views. Shift+Ctrl+Tab is the primary key.</summary>
+    [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
+    public static Key PrevTabGroupKey
+    {
+        get => _prevTabGroupKey;
+        set
+        {
+            if (_prevTabGroupKey != value)
+            {
+                ReplaceKey (_prevTabGroupKey, value);
+                _prevTabGroupKey = value;
+            }
+        }
+    }
+
+    /// <summary>Alternative key to navigate backwards through views. Shift+Ctrl+Tab is the primary key.</summary>
+    [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
+    public static Key PrevTabKey
+    {
+        get => _prevTabKey;
+        set
+        {
+            if (_prevTabKey != value)
+            {
+                ReplaceKey (_prevTabKey, value);
+                _prevTabKey = value;
+            }
+        }
+    }
 }
 }

+ 42 - 7
Terminal.Gui/Application/Application.Run.cs

@@ -6,6 +6,41 @@ namespace Terminal.Gui;
 
 
 public static partial class Application // Run (Begin, Run, End, Stop)
 public static partial class Application // Run (Begin, Run, End, Stop)
 {
 {
+    private static Key _quitKey = Key.Esc; // Resources/config.json overrides
+
+    /// <summary>Gets or sets the key to quit the application.</summary>
+    [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
+    public static Key QuitKey
+    {
+        get => _quitKey;
+        set
+        {
+            if (_quitKey != value)
+            {
+                ReplaceKey (_quitKey, value);
+                _quitKey = value;
+            }
+        }
+    }
+
+    private static Key _arrangeKey = Key.F5.WithCtrl; // Resources/config.json overrides
+
+
+    /// <summary>Gets or sets the key to activate arranging views using the keyboard.</summary>
+    [SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
+    public static Key ArrangeKey
+    {
+        get => _arrangeKey;
+        set
+        {
+            if (_arrangeKey != value)
+            {
+                ReplaceKey (_arrangeKey, value);
+                _arrangeKey = value;
+            }
+        }
+    }
+
     // When `End ()` is called, it is possible `RunState.Toplevel` is a different object than `Top`.
     // When `End ()` is called, it is possible `RunState.Toplevel` is a different object than `Top`.
     // This variable is set in `End` in this case so that `Begin` correctly sets `Top`.
     // This variable is set in `End` in this case so that `Begin` correctly sets `Top`.
     private static Toplevel? _cachedRunStateToplevel;
     private static Toplevel? _cachedRunStateToplevel;
@@ -45,14 +80,14 @@ public static partial class Application // Run (Begin, Run, End, Stop)
     {
     {
         ArgumentNullException.ThrowIfNull (toplevel);
         ArgumentNullException.ThrowIfNull (toplevel);
 
 
-#if DEBUG_IDISPOSABLE
-        Debug.Assert (!toplevel.WasDisposed);
+//#if DEBUG_IDISPOSABLE
+//        Debug.Assert (!toplevel.WasDisposed);
 
 
-        if (_cachedRunStateToplevel is { } && _cachedRunStateToplevel != toplevel)
-        {
-            Debug.Assert (_cachedRunStateToplevel.WasDisposed);
-        }
-#endif
+//        if (_cachedRunStateToplevel is { } && _cachedRunStateToplevel != toplevel)
+//        {
+//            Debug.Assert (_cachedRunStateToplevel.WasDisposed);
+//        }
+//#endif
 
 
         // Ensure the mouse is ungrabbed.
         // Ensure the mouse is ungrabbed.
         MouseGrabView = null;
         MouseGrabView = null;

+ 14 - 1
Terminal.Gui/Application/ApplicationNavigation.cs

@@ -27,7 +27,19 @@ public class ApplicationNavigation
     /// <summary>
     /// <summary>
     ///     Gets the most focused <see cref="View"/> in the application, if there is one.
     ///     Gets the most focused <see cref="View"/> in the application, if there is one.
     /// </summary>
     /// </summary>
-    public View? GetFocused () { return _focused; }
+    public View? GetFocused ()
+    {
+        return _focused;
+
+        if (_focused is { CanFocus: true, HasFocus: true })
+        {
+            return _focused;
+        }
+
+        _focused = null;
+
+        return null;
+    }
 
 
     /// <summary>
     /// <summary>
     ///     Gets whether <paramref name="view"/> is in the Subview hierarchy of <paramref name="start"/>.
     ///     Gets whether <paramref name="view"/> is in the Subview hierarchy of <paramref name="start"/>.
@@ -77,6 +89,7 @@ public class ApplicationNavigation
         {
         {
             return;
             return;
         }
         }
+        Debug.Assert (value is null or { CanFocus: true, HasFocus: true });
 
 
         _focused = value;
         _focused = value;
 
 

+ 2 - 2
Terminal.Gui/ConsoleDrivers/ConsoleDriver.cs

@@ -588,11 +588,11 @@ public abstract class ConsoleDriver : IConsoleDriver
     public void OnKeyUp (Key a) { KeyUp?.Invoke (this, a); }
     public void OnKeyUp (Key a) { KeyUp?.Invoke (this, a); }
 
 
     /// <summary>Event fired when a mouse event occurs.</summary>
     /// <summary>Event fired when a mouse event occurs.</summary>
-    public event EventHandler<MouseEvent>? MouseEvent;
+    public event EventHandler<MouseEventArgs>? MouseEvent;
 
 
     /// <summary>Called when a mouse event occurs. Fires the <see cref="MouseEvent"/> event.</summary>
     /// <summary>Called when a mouse event occurs. Fires the <see cref="MouseEvent"/> event.</summary>
     /// <param name="a"></param>
     /// <param name="a"></param>
-    public void OnMouseEvent (MouseEvent a)
+    public void OnMouseEvent (MouseEventArgs a)
     {
     {
         // Ensure ScreenPosition is set
         // Ensure ScreenPosition is set
         a.ScreenPosition = a.Position;
         a.ScreenPosition = a.Position;

+ 1 - 1
Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs

@@ -1022,7 +1022,7 @@ internal class CursesDriver : ConsoleDriver
 
 
         _lastMouseFlags = mouseFlag;
         _lastMouseFlags = mouseFlag;
 
 
-        var me = new MouseEvent { Flags = mouseFlag, Position = pos };
+        var me = new MouseEventArgs { Flags = mouseFlag, Position = pos };
         //Debug.WriteLine ($"CursesDriver: ({me.Position}) - {me.Flags}");
         //Debug.WriteLine ($"CursesDriver: ({me.Position}) - {me.Flags}");
 
 
         OnMouseEvent (me);
         OnMouseEvent (me);

+ 3 - 3
Terminal.Gui/ConsoleDrivers/NetDriver.cs

@@ -1175,7 +1175,7 @@ internal class NetDriver : ConsoleDriver
 
 
                 break;
                 break;
             case EventType.Mouse:
             case EventType.Mouse:
-                MouseEvent me = ToDriverMouse (inputEvent.MouseEvent);
+                MouseEventArgs me = ToDriverMouse (inputEvent.MouseEvent);
                 //Debug.WriteLine ($"NetDriver: ({me.X},{me.Y}) - {me.Flags}");
                 //Debug.WriteLine ($"NetDriver: ({me.X},{me.Y}) - {me.Flags}");
                 OnMouseEvent (me);
                 OnMouseEvent (me);
 
 
@@ -1414,7 +1414,7 @@ internal class NetDriver : ConsoleDriver
         }
         }
     }
     }
 
 
-    private MouseEvent ToDriverMouse (NetEvents.MouseEvent me)
+    private MouseEventArgs ToDriverMouse (NetEvents.MouseEvent me)
     {
     {
        //System.Diagnostics.Debug.WriteLine ($"X: {me.Position.X}; Y: {me.Position.Y}; ButtonState: {me.ButtonState}");
        //System.Diagnostics.Debug.WriteLine ($"X: {me.Position.X}; Y: {me.Position.Y}; ButtonState: {me.ButtonState}");
 
 
@@ -1560,7 +1560,7 @@ internal class NetDriver : ConsoleDriver
             mouseFlag |= MouseFlags.ButtonAlt;
             mouseFlag |= MouseFlags.ButtonAlt;
         }
         }
 
 
-        return new MouseEvent { Position = me.Position, Flags = mouseFlag };
+        return new MouseEventArgs { Position = me.Position, Flags = mouseFlag };
     }
     }
 
 
     #endregion Mouse Handling
     #endregion Mouse Handling

+ 5 - 5
Terminal.Gui/ConsoleDrivers/WindowsDriver.cs

@@ -1500,7 +1500,7 @@ internal class WindowsDriver : ConsoleDriver
                 break;
                 break;
 
 
             case WindowsConsole.EventType.Mouse:
             case WindowsConsole.EventType.Mouse:
-                MouseEvent me = ToDriverMouse (inputEvent.MouseEvent);
+                MouseEventArgs me = ToDriverMouse (inputEvent.MouseEvent);
 
 
                 if (me is null || me.Flags == MouseFlags.None)
                 if (me is null || me.Flags == MouseFlags.None)
                 {
                 {
@@ -1882,9 +1882,9 @@ internal class WindowsDriver : ConsoleDriver
             }
             }
             await Task.Delay (delay);
             await Task.Delay (delay);
 
 
-            var me = new MouseEvent
+            var me = new MouseEventArgs
             {
             {
-                Position = _pointMove,
+                ScreenPosition = _pointMove,
                 Flags = mouseFlag
                 Flags = mouseFlag
             };
             };
 
 
@@ -1938,7 +1938,7 @@ internal class WindowsDriver : ConsoleDriver
     }
     }
 
 
     [CanBeNull]
     [CanBeNull]
-    private MouseEvent ToDriverMouse (WindowsConsole.MouseEventRecord mouseEvent)
+    private MouseEventArgs ToDriverMouse (WindowsConsole.MouseEventRecord mouseEvent)
     {
     {
         var mouseFlag = MouseFlags.AllEvents;
         var mouseFlag = MouseFlags.AllEvents;
 
 
@@ -2182,7 +2182,7 @@ internal class WindowsDriver : ConsoleDriver
         //System.Diagnostics.Debug.WriteLine (
         //System.Diagnostics.Debug.WriteLine (
         //	$"point.X:{(point is { } ? ((Point)point).X : -1)};point.Y:{(point is { } ? ((Point)point).Y : -1)}");
         //	$"point.X:{(point is { } ? ((Point)point).X : -1)};point.Y:{(point is { } ? ((Point)point).Y : -1)}");
 
 
-        return new MouseEvent
+        return new MouseEventArgs
         {
         {
             Position = new (mouseEvent.MousePosition.X, mouseEvent.MousePosition.Y),
             Position = new (mouseEvent.MousePosition.X, mouseEvent.MousePosition.Y),
             Flags = mouseFlag
             Flags = mouseFlag

+ 3 - 0
Terminal.Gui/Drawing/Glyphs.cs

@@ -97,6 +97,9 @@ public class GlyphDefinitions
     /// <summary>Dot. Default is (U+2219) - ∙.</summary>
     /// <summary>Dot. Default is (U+2219) - ∙.</summary>
     public Rune Dot { get; set; } = (Rune)'∙';
     public Rune Dot { get; set; } = (Rune)'∙';
 
 
+    /// <summary>Dotted Square - ⬚ U+02b1a┝</summary>
+    public Rune DottedSquare { get; set; } = (Rune)'⬚';
+
     /// <summary>Black Circle . Default is (U+025cf) - ●.</summary>
     /// <summary>Black Circle . Default is (U+025cf) - ●.</summary>
     public Rune BlackCircle { get; set; } = (Rune)'●'; // Black Circle - ● U+025cf
     public Rune BlackCircle { get; set; } = (Rune)'●'; // Black Circle - ● U+025cf
 
 

+ 5 - 0
Terminal.Gui/Input/Command.cs

@@ -166,6 +166,11 @@ public enum Command
     /// </summary>
     /// </summary>
     EnableOverwrite,
     EnableOverwrite,
 
 
+    /// <summary>
+    ///     Inserts a character.
+    /// </summary>
+    Insert,
+
     /// <summary>Disables overwrite mode (<see cref="EnableOverwrite"/>)</summary>
     /// <summary>Disables overwrite mode (<see cref="EnableOverwrite"/>)</summary>
     DisableOverwrite,
     DisableOverwrite,
 
 

+ 101 - 0
Terminal.Gui/Input/MouseEventArgs.cs

@@ -0,0 +1,101 @@
+#nullable enable
+using System.ComponentModel;
+
+namespace Terminal.Gui;
+
+/// <summary>
+///     Specifies the event arguments for <see cref="Terminal.Gui.MouseEventArgs"/>. This is a higher-level construct than
+///     the wrapped <see cref="Terminal.Gui.MouseEventArgs"/> class and is used for the events defined on
+///     <see cref="View"/> and subclasses
+///     of View (e.g. <see cref="View.MouseEnter"/> and <see cref="View.MouseClick"/>).
+/// </summary>
+public class MouseEventArgs : HandledEventArgs
+{
+    /// <summary>
+    ///     Flags indicating the state of the mouse buttons and the type of event that occurred.
+    /// </summary>
+    public MouseFlags Flags { get; set; }
+
+    /// <summary>
+    ///     The screen-relative mouse position.
+    /// </summary>
+    public Point ScreenPosition { get; set; }
+
+    /// <summary>The deepest View who's <see cref="View.Frame"/> contains <see cref="ScreenPosition"/>.</summary>
+    public View? View { get; set; }
+
+    /// <summary>
+    ///     The position of the mouse in <see cref="View"/>'s Viewport-relative coordinates. Only valid if <see cref="View"/>
+    ///     is set.
+    /// </summary>
+    public Point Position { get; set; }
+
+    /// <summary>
+    ///     Gets whether <see cref="Flags"/> contains any of the button pressed related flags.
+    /// </summary>
+    public bool IsPressed => Flags.HasFlag (MouseFlags.Button1Pressed)
+                             || Flags.HasFlag (MouseFlags.Button2Pressed)
+                             || Flags.HasFlag (MouseFlags.Button3Pressed)
+                             || Flags.HasFlag (MouseFlags.Button4Pressed);
+
+    /// <summary>
+    ///     Gets whether <see cref="Flags"/> contains any of the button released related flags.
+    /// </summary>
+    public bool IsReleased => Flags.HasFlag (MouseFlags.Button1Released)
+                              || Flags.HasFlag (MouseFlags.Button2Released)
+                              || Flags.HasFlag (MouseFlags.Button3Released)
+                              || Flags.HasFlag (MouseFlags.Button4Released);
+
+    /// <summary>
+    ///     Gets whether <see cref="Flags"/> contains any of the single-clicked related flags.
+    /// </summary>
+    public bool IsSingleClicked => Flags.HasFlag (MouseFlags.Button1Clicked)
+                                   || Flags.HasFlag (MouseFlags.Button2Clicked)
+                                   || Flags.HasFlag (MouseFlags.Button3Clicked)
+                                   || Flags.HasFlag (MouseFlags.Button4Clicked);
+
+    /// <summary>
+    ///     Gets whether <see cref="Flags"/> contains any of the double-clicked related flags.
+    /// </summary>
+    public bool IsDoubleClicked => Flags.HasFlag (MouseFlags.Button1DoubleClicked)
+                                   || Flags.HasFlag (MouseFlags.Button2DoubleClicked)
+                                   || Flags.HasFlag (MouseFlags.Button3DoubleClicked)
+                                   || Flags.HasFlag (MouseFlags.Button4DoubleClicked);
+
+    /// <summary>
+    ///     Gets whether <see cref="Flags"/> contains any of the triple-clicked related flags.
+    /// </summary>
+    public bool IsTripleClicked => Flags.HasFlag (MouseFlags.Button1TripleClicked)
+                                   || Flags.HasFlag (MouseFlags.Button2TripleClicked)
+                                   || Flags.HasFlag (MouseFlags.Button3TripleClicked)
+                                   || Flags.HasFlag (MouseFlags.Button4TripleClicked);
+
+    /// <summary>
+    ///     Gets whether <see cref="Flags"/> contains any of the mouse button clicked related flags.
+    /// </summary>
+    public bool IsSingleDoubleOrTripleClicked =>
+        Flags.HasFlag (MouseFlags.Button1Clicked)
+        || Flags.HasFlag (MouseFlags.Button2Clicked)
+        || Flags.HasFlag (MouseFlags.Button3Clicked)
+        || Flags.HasFlag (MouseFlags.Button4Clicked)
+        || Flags.HasFlag (MouseFlags.Button1DoubleClicked)
+        || Flags.HasFlag (MouseFlags.Button2DoubleClicked)
+        || Flags.HasFlag (MouseFlags.Button3DoubleClicked)
+        || Flags.HasFlag (MouseFlags.Button4DoubleClicked)
+        || Flags.HasFlag (MouseFlags.Button1TripleClicked)
+        || Flags.HasFlag (MouseFlags.Button2TripleClicked)
+        || Flags.HasFlag (MouseFlags.Button3TripleClicked)
+        || Flags.HasFlag (MouseFlags.Button4TripleClicked);
+
+    /// <summary>
+    ///     Gets whether <see cref="Flags"/> contains any of the mouse wheel related flags.
+    /// </summary>
+    public bool IsWheel => Flags.HasFlag (MouseFlags.WheeledDown)
+                           || Flags.HasFlag (MouseFlags.WheeledUp)
+                           || Flags.HasFlag (MouseFlags.WheeledLeft)
+                           || Flags.HasFlag (MouseFlags.WheeledRight);
+
+    /// <summary>Returns a <see cref="T:System.String"/> that represents the current <see cref="Terminal.Gui.MouseEventArgs"/>.</summary>
+    /// <returns>A <see cref="T:System.String"/> that represents the current <see cref="Terminal.Gui.MouseEventArgs"/>.</returns>
+    public override string ToString () { return $"({ScreenPosition}):{Flags}:{View?.Id}:{Position}"; }
+}

+ 0 - 32
Terminal.Gui/Input/MouseEventEventArgs.cs

@@ -1,32 +0,0 @@
-namespace Terminal.Gui;
-
-/// <summary>
-///     Specifies the event arguments for <see cref="Terminal.Gui.MouseEvent"/>. This is a higher-level construct than
-///     the wrapped <see cref="MouseEvent"/> class and is used for the events defined on <see cref="View"/> and subclasses
-///     of View (e.g. <see cref="View.MouseEnter"/> and <see cref="View.MouseClick"/>).
-/// </summary>
-public class MouseEventEventArgs : EventArgs
-{
-    /// <summary>Constructs.</summary>
-    /// <param name="me">The mouse event.</param>
-    public MouseEventEventArgs (MouseEvent me) { MouseEvent = me; }
-
-    /// <summary>
-    ///     Indicates if the current mouse event has already been processed and the driver should stop notifying any other
-    ///     event subscriber. It's important to set this value to true specially when updating any View's layout from inside the
-    ///     subscriber method.
-    /// </summary>
-    /// <remarks>
-    ///     This property forwards to the <see cref="MouseEvent.Handled"/> property and is provided as a convenience and
-    ///     for backwards compatibility
-    /// </remarks>
-    public bool Handled
-    {
-        get => MouseEvent.Handled;
-        set => MouseEvent.Handled = value;
-    }
-
-    // TODO: Merge MouseEvent and MouseEventEventArgs into a single class.
-    /// <summary>The <see cref="Terminal.Gui.MouseEvent"/> for the event.</summary>
-    public MouseEvent MouseEvent { get; set; }
-}

+ 2 - 49
Terminal.Gui/Input/Mouse.cs → Terminal.Gui/Input/MouseFlags.cs

@@ -1,12 +1,12 @@
 namespace Terminal.Gui;
 namespace Terminal.Gui;
 
 
-/// <summary>Mouse flags reported in <see cref="MouseEvent"/>.</summary>
+/// <summary>Mouse flags reported in <see cref="MouseEventArgs"/>.</summary>
 /// <remarks>They just happen to map to the ncurses ones.</remarks>
 /// <remarks>They just happen to map to the ncurses ones.</remarks>
 [Flags]
 [Flags]
 public enum MouseFlags
 public enum MouseFlags
 {
 {
     /// <summary>
     /// <summary>
-    ///    No mouse event. This is the default value for <see cref="MouseEvent.Flags"/> when no mouse event is being reported.
+    ///    No mouse event. This is the default value for <see cref="Terminal.Gui.MouseEventArgs.Flags"/> when no mouse event is being reported.
     /// </summary>
     /// </summary>
     None = 0,
     None = 0,
 
 
@@ -97,50 +97,3 @@ public enum MouseFlags
     /// <summary>Mask that captures all the events.</summary>
     /// <summary>Mask that captures all the events.</summary>
     AllEvents = 0x7ffffff
     AllEvents = 0x7ffffff
 }
 }
-
-// TODO: Merge MouseEvent and MouseEventEventArgs into a single class.
-
-/// <summary>
-///     Conveys the details of mouse events, such as coordinates and button state, from
-///     ConsoleDrivers up to <see cref="Application"/> and Views.
-/// </summary>
-/// <remarks>
-///     The <see cref="Application"/> class includes the <see cref="Application.MouseEvent"/> event which takes a
-///     MouseEvent argument.
-/// </remarks>
-public class MouseEvent
-{
-    /// <summary>Flags indicating the kind of mouse event that is being posted.</summary>
-    public MouseFlags Flags { get; set; }
-
-    /// <summary>The View at the location for the mouse event.</summary>
-    public View View { get; set; }
-
-    /// <summary>The position of the mouse in <see cref="Gui.View.Viewport"/>-relative coordinates.</summary>
-    public Point Position { get; set; }
-
-    /// <summary>
-    ///     The screen-relative mouse position.
-    /// </summary>
-    /// <remarks>
-    ///     <para>
-    ///         <see cref="Position"/> is <see cref="Gui.View.Viewport"/>-relative. When the mouse is grabbed by a view,
-    ///         <see cref="ScreenPosition"/> provides the mouse position screen-relative coordinates, enabling the grabbed view to know how much the
-    ///         mouse has moved.
-    ///     </para>
-    ///     <para>
-    ///         Calculated and processed in <see cref="Application.OnMouseEvent(MouseEvent)"/>.
-    ///     </para>
-    /// </remarks>
-    public Point ScreenPosition { get; set; }
-
-    /// <summary>
-    ///     Indicates if the current mouse event has been processed. Set this value to <see langword="true"/> to indicate the mouse
-    ///     event was handled.
-    /// </summary>
-    public bool Handled { get; set; }
-
-    /// <summary>Returns a <see cref="T:System.String"/> that represents the current <see cref="MouseEvent"/>.</summary>
-    /// <returns>A <see cref="T:System.String"/> that represents the current <see cref="MouseEvent"/>.</returns>
-    public override string ToString () { return $"({Position}):{Flags}"; }
-}

+ 0 - 173
Terminal.Gui/Input/ShortcutHelper.cs

@@ -1,173 +0,0 @@
-using System.Diagnostics;
-
-namespace Terminal.Gui;
-
-// TODO: Nuke when #2975 is completed
-/// <summary>Represents a helper to manipulate shortcut keys used on views.</summary>
-public class ShortcutHelper
-{
-    // TODO: Update this to use Key, not KeyCode
-    private KeyCode shortcut;
-
-    /// <summary>This is the global setting that can be used as a global shortcut to invoke the action on the view.</summary>
-    public virtual KeyCode Shortcut
-    {
-        get => shortcut;
-        set
-        {
-            if (shortcut != value && (PostShortcutValidation (value) || value is KeyCode.Null))
-            {
-                shortcut = value;
-            }
-        }
-    }
-
-    /// <summary>The keystroke combination used in the <see cref="Shortcut"/> as string.</summary>
-    public virtual string ShortcutTag => Key.ToString (shortcut, Key.Separator);
-
-    /// <summary>Lookup for a <see cref="KeyCode"/> on range of keys.</summary>
-    /// <param name="key">The source key.</param>
-    /// <param name="first">First key in range.</param>
-    /// <param name="last">Last key in range.</param>
-    public static bool CheckKeysFlagRange (KeyCode key, KeyCode first, KeyCode last)
-    {
-        for (var i = (uint)first; i < (uint)last; i++)
-        {
-            if ((key | (KeyCode)i) == key)
-            {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    /// <summary>Allows to retrieve a <see cref="KeyCode"/> from a <see cref="ShortcutTag"/></summary>
-    /// <param name="tag">The key as string.</param>
-    /// <param name="delimiter">The delimiter string.</param>
-    public static KeyCode GetShortcutFromTag (string tag, Rune delimiter = default)
-    {
-        string sCut = tag;
-
-        if (string.IsNullOrEmpty (sCut))
-        {
-            return default (KeyCode);
-        }
-
-        var key = KeyCode.Null;
-
-        //var hasCtrl = false;
-        if (delimiter == default (Rune))
-        {
-            delimiter = Key.Separator;
-        }
-
-        string [] keys = sCut.Split (delimiter.ToString ());
-
-        for (var i = 0; i < keys.Length; i++)
-        {
-            string k = keys [i];
-
-            if (k == "Ctrl")
-            {
-                //hasCtrl = true;
-                key |= KeyCode.CtrlMask;
-            }
-            else if (k == "Shift")
-            {
-                key |= KeyCode.ShiftMask;
-            }
-            else if (k == "Alt")
-            {
-                key |= KeyCode.AltMask;
-            }
-            else if (k.StartsWith ("F") && k.Length > 1)
-            {
-                int.TryParse (k.Substring (1), out int n);
-
-                for (var j = (uint)KeyCode.F1; j <= (uint)KeyCode.F12; j++)
-                {
-                    int.TryParse (((KeyCode)j).ToString ().Substring (1), out int f);
-
-                    if (f == n)
-                    {
-                        key |= (KeyCode)j;
-                    }
-                }
-            }
-            else
-            {
-                key |= (KeyCode)Enum.Parse (typeof (KeyCode), k);
-            }
-        }
-
-        return key;
-    }
-
-    /// <summary>Used at key up validation.</summary>
-    /// <param name="key">The key to validate.</param>
-    /// <returns><c>true</c> if is valid.<c>false</c>otherwise.</returns>
-    public static bool PostShortcutValidation (KeyCode key)
-    {
-        GetKeyToString (key, out KeyCode knm);
-
-        if (CheckKeysFlagRange (key, KeyCode.F1, KeyCode.F12) || ((key & (KeyCode.CtrlMask | KeyCode.ShiftMask | KeyCode.AltMask)) != 0 && knm != KeyCode.Null))
-        {
-            return true;
-        }
-
-        return false;
-    }
-
-    /// <summary>Used at key down or key press validation.</summary>
-    /// <param name="key">The key to validate.</param>
-    /// <returns><c>true</c> if is valid.<c>false</c>otherwise.</returns>
-    public static bool PreShortcutValidation (KeyCode key)
-    {
-        if ((key & (KeyCode.CtrlMask | KeyCode.ShiftMask | KeyCode.AltMask)) == 0
-            && !CheckKeysFlagRange (key, KeyCode.F1, KeyCode.F12))
-        {
-            return false;
-        }
-
-        return true;
-    }
-
-    /// <summary>Return key as string.</summary>
-    /// <param name="key">The key to extract.</param>
-    /// <param name="knm">Correspond to the non modifier key.</param>
-    private static string GetKeyToString (KeyCode key, out KeyCode knm)
-    {
-        if (key == KeyCode.Null)
-        {
-            knm = KeyCode.Null;
-
-            return "";
-        }
-
-        knm = key;
-        KeyCode mK = key & (KeyCode.AltMask | KeyCode.CtrlMask | KeyCode.ShiftMask);
-        knm &= ~mK;
-
-        for (var i = (uint)KeyCode.F1; i < (uint)KeyCode.F12; i++)
-        {
-            if (knm == (KeyCode)i)
-            {
-                mK |= (KeyCode)i;
-            }
-        }
-
-        knm &= ~mK;
-        uint.TryParse (knm.ToString (), out uint c);
-        string s = mK == KeyCode.Null ? "" : mK.ToString ();
-
-        if (s != "" && (knm != KeyCode.Null || c > 0))
-        {
-            s += ",";
-        }
-
-        s += c == 0 ? knm == KeyCode.Null ? "" : knm.ToString () : ((char)c).ToString ();
-
-        return s;
-    }
-}

+ 33 - 1
Terminal.Gui/Terminal.Gui.csproj

@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
   <!-- =================================================================== -->
   <!-- =================================================================== -->
   <!-- Version numbers -->
   <!-- Version numbers -->
   <!-- Automatically updated by gitversion (run `dotnet-gitversion /updateprojectfiles`)  -->
   <!-- Automatically updated by gitversion (run `dotnet-gitversion /updateprojectfiles`)  -->
@@ -142,4 +142,36 @@
     <Authors>Miguel de Icaza, Tig Kindel (@tig), @BDisp</Authors>
     <Authors>Miguel de Icaza, Tig Kindel (@tig), @BDisp</Authors>
   </PropertyGroup>
   </PropertyGroup>
   <ProjectExtensions><VisualStudio><UserProperties resources_4config_1json__JsonSchema="../../docfx/schemas/tui-config-schema.json" /></VisualStudio></ProjectExtensions>
   <ProjectExtensions><VisualStudio><UserProperties resources_4config_1json__JsonSchema="../../docfx/schemas/tui-config-schema.json" /></VisualStudio></ProjectExtensions>
+
+  <Target Name="CopyNuGetPackagesToLocalPackagesFolder"
+          AfterTargets="Pack"
+          Condition="'$(Configuration)' == 'Release'">
+      <PropertyGroup>
+          <!-- Define the path for local_packages relative to the project directory -->
+          <LocalPackagesPath>$(MSBuildThisFileDirectory)..\local_packages\</LocalPackagesPath>
+          <!-- Output path without framework-specific folders -->
+          <PackageOutputPath>$(MSBuildThisFileDirectory)bin\$(Configuration)\</PackageOutputPath>
+      </PropertyGroup>
+
+      <!-- Ensure the local_packages folder exists -->
+      <Message Text="Checking if $(LocalPackagesPath) exists, creating if necessary." Importance="high" />
+      <MakeDir Directories="$(LocalPackagesPath)" />
+
+      <!-- Collect .nupkg and .snupkg files into an item group -->
+      <ItemGroup>
+          <NuGetPackages Include="$(PackageOutputPath)*.nupkg;$(PackageOutputPath)*.snupkg" />
+      </ItemGroup>
+
+      <!-- Check if any packages were found -->
+      <Message Text="Found packages: @(NuGetPackages)" Importance="high" />
+
+      <!-- Copy files only if found -->
+      <Copy SourceFiles="@(NuGetPackages)"
+            DestinationFolder="$(LocalPackagesPath)"
+            SkipUnchangedFiles="false"
+            Condition="@(NuGetPackages) != ''" />
+
+      <!-- Log success -->
+      <Message Text="Copy completed successfully." Importance="high" />
+  </Target>
 </Project>
 </Project>

+ 1 - 1
Terminal.Gui/Text/Autocomplete/AppendAutocomplete.cs

@@ -59,7 +59,7 @@ public class AppendAutocomplete : AutocompleteBase
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public override bool OnMouseEvent (MouseEvent me, bool fromHost = false) { return false; }
+    public override bool OnMouseEvent (MouseEventArgs me, bool fromHost = false) { return false; }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
     public override bool ProcessKey (Key a)
     public override bool ProcessKey (Key a)

+ 1 - 1
Terminal.Gui/Text/Autocomplete/AutocompleteBase.cs

@@ -49,7 +49,7 @@ public abstract class AutocompleteBase : IAutocomplete
     public virtual AutocompleteContext Context { get; set; }
     public virtual AutocompleteContext Context { get; set; }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public abstract bool OnMouseEvent (MouseEvent me, bool fromHost = false);
+    public abstract bool OnMouseEvent (MouseEventArgs me, bool fromHost = false);
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
     public abstract bool ProcessKey (Key a);
     public abstract bool ProcessKey (Key a);

+ 1 - 1
Terminal.Gui/Text/Autocomplete/IAutocomplete.cs

@@ -45,7 +45,7 @@ public interface IAutocomplete
     /// <param name="me">The mouse event.</param>
     /// <param name="me">The mouse event.</param>
     /// <param name="fromHost">If was called from the popup or from the host.</param>
     /// <param name="fromHost">If was called from the popup or from the host.</param>
     /// <returns><c>true</c>if the mouse can be handled <c>false</c>otherwise.</returns>
     /// <returns><c>true</c>if the mouse can be handled <c>false</c>otherwise.</returns>
-    bool OnMouseEvent (MouseEvent me, bool fromHost = false);
+    bool OnMouseEvent (MouseEventArgs me, bool fromHost = false);
 
 
     /// <summary>Gets or sets where the popup will be displayed.</summary>
     /// <summary>Gets or sets where the popup will be displayed.</summary>
     bool PopupInsideContainer { get; set; }
     bool PopupInsideContainer { get; set; }

+ 1 - 1
Terminal.Gui/Text/Autocomplete/PopupAutocomplete.PopUp.cs

@@ -25,6 +25,6 @@ public abstract partial class PopupAutocomplete
             _autoComplete.RenderOverlay (_autoComplete.LastPopupPos.Value);
             _autoComplete.RenderOverlay (_autoComplete.LastPopupPos.Value);
         }
         }
 
 
-        protected internal override bool OnMouseEvent (MouseEvent mouseEvent) { return _autoComplete.OnMouseEvent (mouseEvent); }
+        protected override bool OnMouseEvent (MouseEventArgs mouseEvent) { return _autoComplete.OnMouseEvent (mouseEvent); }
     }
     }
 }
 }

+ 2 - 2
Terminal.Gui/Text/Autocomplete/PopupAutocomplete.cs

@@ -105,7 +105,7 @@ public abstract partial class PopupAutocomplete : AutocompleteBase
     /// <param name="me">The mouse event.</param>
     /// <param name="me">The mouse event.</param>
     /// <param name="fromHost">If was called from the popup or from the host.</param>
     /// <param name="fromHost">If was called from the popup or from the host.</param>
     /// <returns><c>true</c>if the mouse can be handled <c>false</c>otherwise.</returns>
     /// <returns><c>true</c>if the mouse can be handled <c>false</c>otherwise.</returns>
-    public override bool OnMouseEvent (MouseEvent me, bool fromHost = false)
+    public override bool OnMouseEvent (MouseEventArgs me, bool fromHost = false)
     {
     {
         if (fromHost)
         if (fromHost)
         {
         {
@@ -488,7 +488,7 @@ public abstract partial class PopupAutocomplete : AutocompleteBase
 
 
     /// <summary>Render the current selection in the Autocomplete context menu by the mouse reporting.</summary>
     /// <summary>Render the current selection in the Autocomplete context menu by the mouse reporting.</summary>
     /// <param name="me"></param>
     /// <param name="me"></param>
-    protected void RenderSelectedIdxByMouse (MouseEvent me)
+    protected void RenderSelectedIdxByMouse (MouseEventArgs me)
     {
     {
         if (SelectedIdx != me.Position.Y - ScrollOffset)
         if (SelectedIdx != me.Position.Y - ScrollOffset)
         {
         {

+ 2 - 7
Terminal.Gui/View/Adornment/Border.cs

@@ -262,13 +262,8 @@ public class Border : Adornment
     private Point _startGrabPoint;
     private Point _startGrabPoint;
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    protected internal override bool OnMouseEvent (MouseEvent mouseEvent)
+    protected override bool OnMouseEvent (MouseEventArgs mouseEvent)
     {
     {
-        if (base.OnMouseEvent (mouseEvent))
-        {
-            return true;
-        }
-
         // BUGBUG: See https://github.com/gui-cs/Terminal.Gui/issues/3312
         // BUGBUG: See https://github.com/gui-cs/Terminal.Gui/issues/3312
         if (!_dragPosition.HasValue && mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed)
         if (!_dragPosition.HasValue && mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed)
                                     // HACK: Prevents Window from being draggable if it's Top
                                     // HACK: Prevents Window from being draggable if it's Top
@@ -1370,7 +1365,7 @@ public class Border : Adornment
         KeyBindings.Add (Key.Tab.WithShift, KeyBindingScope.HotKey, Command.BackTab);
         KeyBindings.Add (Key.Tab.WithShift, KeyBindingScope.HotKey, Command.BackTab);
     }
     }
 
 
-    private void ApplicationOnMouseEvent (object? sender, MouseEvent e)
+    private void ApplicationOnMouseEvent (object? sender, MouseEventArgs e)
     {
     {
         if (e.Flags != MouseFlags.Button1Clicked)
         if (e.Flags != MouseFlags.Button1Clicked)
         {
         {

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

@@ -50,7 +50,7 @@ public class Padding : Adornment
     /// </remarks>
     /// </remarks>
     /// <param name="mouseEvent"></param>
     /// <param name="mouseEvent"></param>
     /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
     /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
-    protected internal override bool OnMouseEvent (MouseEvent mouseEvent)
+    protected override bool OnMouseEvent (MouseEventArgs mouseEvent)
     {
     {
         if (Parent is null)
         if (Parent is null)
         {
         {

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

@@ -109,7 +109,7 @@ internal class ShadowView : View
         Rectangle screen = ViewportToScreen (viewport);
         Rectangle screen = ViewportToScreen (viewport);
 
 
         // Fill the rest of the rectangle - note we skip the last since vertical will draw it
         // Fill the rest of the rectangle - note we skip the last since vertical will draw it
-        for (int i = screen.X + 1; i < screen.X + screen.Width - 1; i++)
+        for (int i = Math.Max(0, screen.X + 1); i < screen.X + screen.Width - 1; i++)
         {
         {
             Driver.Move (i, screen.Y);
             Driver.Move (i, screen.Y);
 
 

+ 11 - 0
Terminal.Gui/View/CancelEventArgs.cs

@@ -27,6 +27,17 @@ public class CancelEventArgs<T> : CancelEventArgs where T : notnull
         NewValue = newValue;
         NewValue = newValue;
     }
     }
 
 
+    /// <summary>
+    ///     Initializes a new instance of the <see cref="CancelEventArgs{T}"/> class.
+    /// </summary>
+    /// <param name="currentValue">The current (old) value of the property.</param>
+    /// <param name="newValue">The value the property will be set to if the event is not cancelled.</param>
+    protected CancelEventArgs (T currentValue, T newValue)
+    {
+        CurrentValue = currentValue;
+        NewValue = newValue;
+    }
+
     /// <summary>The current value of the property.</summary>
     /// <summary>The current value of the property.</summary>
     public T CurrentValue { get; }
     public T CurrentValue { get; }
 
 

+ 18 - 0
Terminal.Gui/View/Navigation/AdvanceFocusEventArgs.cs

@@ -0,0 +1,18 @@
+namespace Terminal.Gui;
+
+/// <summary>The event arguments for <see cref="View.AdvanceFocus"/> events.</summary>
+public class AdvanceFocusEventArgs : CancelEventArgs<bool>
+{
+    /// <summary>Initializes a new instance.</summary>
+    public AdvanceFocusEventArgs (NavigationDirection direction, TabBehavior? behavior) : base (false, false)
+    {
+        Direction = direction;
+        Behavior = behavior;
+    }
+
+    /// <summary>Gets or sets the view that is losing focus.</summary>
+    public NavigationDirection Direction { get; set; }
+
+    /// <summary>Gets or sets the view that is gaining focus.</summary>
+    public TabBehavior? Behavior { get; set; }
+}

+ 1 - 1
Terminal.Gui/View/Navigation/FocusEventArgs.cs

@@ -20,4 +20,4 @@ public class HasFocusEventArgs : CancelEventArgs<bool>
     /// <summary>Gets or sets the view that is gaining focus.</summary>
     /// <summary>Gets or sets the view that is gaining focus.</summary>
     public View NewFocused { get; set; }
     public View NewFocused { get; set; }
 
 
-}
+}

+ 2 - 4
Terminal.Gui/View/Orientation/OrientationHelper.cs

@@ -69,7 +69,7 @@ public class OrientationHelper
                 return;
                 return;
             }
             }
 
 
-            // Best practice is to invoke the virtual method first.
+            // Best practice is to call the virtual method first.
             // This allows derived classes to handle the event and potentially cancel it.
             // This allows derived classes to handle the event and potentially cancel it.
             if (_owner?.OnOrientationChanging (value, _orientation) ?? false)
             if (_owner?.OnOrientationChanging (value, _orientation) ?? false)
             {
             {
@@ -98,10 +98,8 @@ public class OrientationHelper
                 }
                 }
             }
             }
 
 
-            // Best practice is to invoke the virtual method first.
+            // Best practice is to call the virtual method first, then raise the event.
             _owner?.OnOrientationChanged (_orientation);
             _owner?.OnOrientationChanged (_orientation);
-
-            // Even though Changed is not cancelable, it is still a good practice to raise the event after.
             OrientationChanged?.Invoke (_owner, new (in _orientation));
             OrientationChanged?.Invoke (_owner, new (in _orientation));
         }
         }
     }
     }

+ 7 - 0
Terminal.Gui/View/View.Hierarchy.cs

@@ -169,6 +169,13 @@ public partial class View // SuperView/SubView hierarchy management (SuperView,
         Debug.Assert (!view.HasFocus);
         Debug.Assert (!view.HasFocus);
 
 
         _subviews.Remove (view);
         _subviews.Remove (view);
+
+        // Clean up focus stuff
+        _previouslyFocused = null;
+        if (view._superView is { } && view._superView._previouslyFocused == this)
+        {
+            view._superView._previouslyFocused = null;
+        }
         view._superView = null;
         view._superView = null;
 
 
         SetNeedsLayout ();
         SetNeedsLayout ();

+ 141 - 182
Terminal.Gui/View/View.Keyboard.cs

@@ -26,7 +26,7 @@ public partial class View // Keyboard APIs
 
 
     #region HotKey Support
     #region HotKey Support
 
 
-    /// <summary>Invoked when the <see cref="HotKey"/> is changed.</summary>
+    /// <summary>Raised when the <see cref="HotKey"/> is changed.</summary>
     public event EventHandler<KeyChangedEventArgs>? HotKeyChanged;
     public event EventHandler<KeyChangedEventArgs>? HotKeyChanged;
 
 
     private Key _hotKey = new ();
     private Key _hotKey = new ();
@@ -73,7 +73,7 @@ public partial class View // Keyboard APIs
     ///     <para>If the hot key is changed, the <see cref="HotKeyChanged"/> event is fired.</para>
     ///     <para>If the hot key is changed, the <see cref="HotKeyChanged"/> event is fired.</para>
     ///     <para>Set to <see cref="Key.Empty"/> to disable the hot key.</para>
     ///     <para>Set to <see cref="Key.Empty"/> to disable the hot key.</para>
     /// </remarks>
     /// </remarks>
-    public virtual Key HotKey
+    public Key HotKey
     {
     {
         get => _hotKey;
         get => _hotKey;
         set
         set
@@ -218,7 +218,7 @@ public partial class View // Keyboard APIs
 
 
     private void SetHotKeyFromTitle ()
     private void SetHotKeyFromTitle ()
     {
     {
-        if (TitleTextFormatter == null || HotKeySpecifier == new Rune ('\xFFFF'))
+        if (HotKeySpecifier == new Rune ('\xFFFF'))
         {
         {
             return; // throw new InvalidOperationException ("Can't set HotKey unless a TextFormatter has been created");
             return; // throw new InvalidOperationException ("Can't set HotKey unless a TextFormatter has been created");
         }
         }
@@ -243,7 +243,8 @@ public partial class View // Keyboard APIs
     #region Key Down Event
     #region Key Down Event
 
 
     /// <summary>
     /// <summary>
-    ///     If the view is enabled, processes a new key down event and returns <see langword="true"/> if the event was
+    ///     If the view is enabled, raises the related key down events on the view, and returns <see langword="true"/> if the
+    ///     event was
     ///     handled.
     ///     handled.
     /// </summary>
     /// </summary>
     /// <remarks>
     /// <remarks>
@@ -252,74 +253,95 @@ public partial class View // Keyboard APIs
     ///         first.
     ///         first.
     ///     </para>
     ///     </para>
     ///     <para>
     ///     <para>
-    ///         If the focused sub view does not handle the key press, this method calls <see cref="OnKeyDown"/> to allow the
-    ///         view to pre-process the key press. If <see cref="OnKeyDown"/> returns <see langword="false"/>, this method then
-    ///         calls <see cref="OnInvokingKeyBindings"/> to invoke any key bindings. Then, only if no key bindings are
-    ///         handled, <see cref="OnProcessKeyDown"/> will be called allowing the view to process the key press.
+    ///         If a more focused subview does not handle the key press, this method raises <see cref="OnKeyDown"/>/
+    ///         <see cref="KeyDown"/> to allow the
+    ///         view to pre-process the key press. If <see cref="OnKeyDown"/>/<see cref="KeyDown"/> is not handled any commands bound to the key will be invoked.
+    ///         Then, only if no key bindings are
+    ///         handled, <see cref="OnKeyDownNotHandled"/>/<see cref="KeyDownNotHandled"/> will be raised allowing the view to
+    ///         process the key press.
+    ///     </para>
+    ///     <para>
+    ///         Calling this method for a key bound to the view via an Application-scoped keybinding will have no effect.
+    ///         Instead,
+    ///         use <see cref="Application.RaiseKeyDownEvent"/>.
     ///     </para>
     ///     </para>
     ///     <para>See <see href="../docs/keyboard.md">for an overview of Terminal.Gui keyboard APIs.</see></para>
     ///     <para>See <see href="../docs/keyboard.md">for an overview of Terminal.Gui keyboard APIs.</see></para>
     /// </remarks>
     /// </remarks>
-    /// <param name="keyEvent"></param>
+    /// <param name="key"></param>
     /// <returns><see langword="true"/> if the event was handled.</returns>
     /// <returns><see langword="true"/> if the event was handled.</returns>
-    public bool NewKeyDownEvent (Key keyEvent)
+    public bool NewKeyDownEvent (Key key)
     {
     {
         if (!Enabled)
         if (!Enabled)
         {
         {
             return false;
             return false;
         }
         }
 
 
-        // By default the KeyBindingScope is View
-
-        if (Focused?.NewKeyDownEvent (keyEvent) == true)
+        // If there's a Focused subview, give it a chance (this recurses down the hierarchy)
+        if (Focused?.NewKeyDownEvent (key) == true)
         {
         {
             return true;
             return true;
         }
         }
 
 
         // Before (fire the cancellable event)
         // Before (fire the cancellable event)
-        if (OnKeyDown (keyEvent))
+        if (RaiseKeyDown (key) || key.Handled)
         {
         {
             return true;
             return true;
         }
         }
 
 
         // During (this is what can be cancelled)
         // During (this is what can be cancelled)
-        InvokingKeyBindings?.Invoke (this, keyEvent);
 
 
-        if (keyEvent.Handled)
+        // TODO: NewKeyDownEvent returns bool. It should be bool? so state of InvokeCommands can be reflected up stack
+        if (InvokeCommandsBoundToKey (key) is true || key.Handled)
         {
         {
             return true;
             return true;
         }
         }
 
 
-        // TODO: NewKeyDownEvent returns bool. It should be bool? so state of InvokeCommand can be reflected up stack
-
-        bool? handled = OnInvokingKeyBindings (keyEvent, KeyBindingScope.HotKey | KeyBindingScope.Focused);
-
-        if (handled is { } && (bool)handled)
+        // After
+        if (RaiseKeyDownNotHandled (key) || key.Handled)
         {
         {
             return true;
             return true;
         }
         }
 
 
-        // TODO: The below is not right. OnXXX handlers are supposed to fire the events.
-        // TODO: But I've moved it outside of the v-function to test something.
-        // After (fire the cancellable event)
-        // fire event
-        ProcessKeyDown?.Invoke (this, keyEvent);
+        return key.Handled;
 
 
-        if (!keyEvent.Handled && OnProcessKeyDown (keyEvent))
+        bool RaiseKeyDown (Key k)
         {
         {
-            return true;
+            // Before (fire the cancellable event)
+            if (OnKeyDown (k) || k.Handled)
+            {
+                return true;
+            }
+
+            // fire event
+            KeyDown?.Invoke (this, k);
+
+            return k.Handled;
         }
         }
 
 
-        return keyEvent.Handled;
+        bool RaiseKeyDownNotHandled (Key k)
+        {
+            if (OnKeyDownNotHandled (k) || k.Handled)
+            {
+                return true;
+            }
+
+            KeyDownNotHandled?.Invoke (this, k);
+
+            return false;
+        }
     }
     }
 
 
     /// <summary>
     /// <summary>
-    ///     Low-level API called when the user presses a key, allowing a view to pre-process the key down event. This is
-    ///     called from <see cref="NewKeyDownEvent"/> before <see cref="OnInvokingKeyBindings"/>.
+    ///     Called when the user presses a key, allowing subscribers to pre-process the key down event. Called
+    ///     before key bindings are invoked and <see cref="KeyDownNotHandled"/> is raised. Set
+    ///     <see cref="Key.Handled"/>
+    ///     to true to
+    ///     stop the key from being processed further.
     /// </summary>
     /// </summary>
-    /// <param name="keyEvent">Contains the details about the key that produced the event.</param>
+    /// <param name="key">The key that produced the event.</param>
     /// <returns>
     /// <returns>
-    ///     <see langword="false"/> if the key press was not handled. <see langword="true"/> if the keypress was handled
-    ///     and no other view should see it.
+    ///     <see langword="false"/> if the key down event was not handled. <see langword="true"/> if the event was handled
+    ///     and processing should stop.
     /// </returns>
     /// </returns>
     /// <remarks>
     /// <remarks>
     ///     <para>
     ///     <para>
@@ -328,18 +350,14 @@ public partial class View // Keyboard APIs
     ///     </para>
     ///     </para>
     ///     <para>Fires the <see cref="KeyDown"/> event.</para>
     ///     <para>Fires the <see cref="KeyDown"/> event.</para>
     /// </remarks>
     /// </remarks>
-    public virtual bool OnKeyDown (Key keyEvent)
-    {
-        // fire event
-        KeyDown?.Invoke (this, keyEvent);
-
-        return keyEvent.Handled;
-    }
+    protected virtual bool OnKeyDown (Key key) { return false; }
 
 
     /// <summary>
     /// <summary>
-    ///     Invoked when the user presses a key, allowing subscribers to pre-process the key down event. This is fired
-    ///     from <see cref="OnKeyDown"/> before <see cref="OnInvokingKeyBindings"/>. Set <see cref="Key.Handled"/> to true to
-    ///     stop the key from being processed by other views.
+    ///     Raised when the user presses a key, allowing subscribers to pre-process the key down event. Called
+    ///     before key bindings are invoked and <see cref="KeyDownNotHandled"/> is raised. Set
+    ///     <see cref="Key.Handled"/>
+    ///     to true to
+    ///     stop the key from being processed further.
     /// </summary>
     /// </summary>
     /// <remarks>
     /// <remarks>
     ///     <para>
     ///     <para>
@@ -351,60 +369,49 @@ public partial class View // Keyboard APIs
     public event EventHandler<Key>? KeyDown;
     public event EventHandler<Key>? KeyDown;
 
 
     /// <summary>
     /// <summary>
-    ///     Low-level API called when the user presses a key, allowing views do things during key down events. This is
-    ///     called from <see cref="NewKeyDownEvent"/> after <see cref="OnInvokingKeyBindings"/>.
+    ///     Called when the user has pressed key it wasn't handled by <see cref="KeyDown"/> and was not bound to a key binding.
     /// </summary>
     /// </summary>
-    /// <param name="keyEvent">Contains the details about the key that produced the event.</param>
-    /// <returns>
-    ///     <see langword="false"/> if the key press was not handled. <see langword="true"/> if the keypress was handled
-    ///     and no other view should see it.
-    /// </returns>
     /// <remarks>
     /// <remarks>
     ///     <para>
     ///     <para>
-    ///         Override <see cref="OnProcessKeyDown"/> to override the behavior of how the base class processes key down
-    ///         events.
-    ///     </para>
-    ///     <para>
     ///         For processing <see cref="HotKey"/>s and commands, use <see cref="Command"/> and
     ///         For processing <see cref="HotKey"/>s and commands, use <see cref="Command"/> and
     ///         <see cref="KeyBindings.Add(Key, Command[])"/>instead.
     ///         <see cref="KeyBindings.Add(Key, Command[])"/>instead.
     ///     </para>
     ///     </para>
-    ///     <para>Fires the <see cref="ProcessKeyDown"/> event.</para>
     ///     <para>
     ///     <para>
     ///         Not all terminals support distinct key up notifications; applications should avoid depending on distinct
     ///         Not all terminals support distinct key up notifications; applications should avoid depending on distinct
     ///         KeyUp events.
     ///         KeyUp events.
     ///     </para>
     ///     </para>
     /// </remarks>
     /// </remarks>
-    public virtual bool OnProcessKeyDown (Key keyEvent)
-    {
-        //ProcessKeyDown?.Invoke (this, keyEvent);
-        return keyEvent.Handled;
-    }
+    /// <param name="key">Contains the details about the key that produced the event.</param>
+    /// <returns>
+    ///     <see langword="false"/> if the key press was not handled. <see langword="true"/> if the keypress was handled
+    ///     and no other view should see it.
+    /// </returns>
+    protected virtual bool OnKeyDownNotHandled (Key key) { return key.Handled; }
 
 
     /// <summary>
     /// <summary>
-    ///     Invoked when the user presses a key, allowing subscribers to do things during key down events. Set
-    ///     <see cref="Key.Handled"/> to true to stop the key from being processed by other views. Invoked after
-    ///     <see cref="KeyDown"/> and before <see cref="InvokingKeyBindings"/>.
+    ///     Raised when the user has pressed key it wasn't handled by <see cref="KeyDown"/> and was not bound to a key binding.
     /// </summary>
     /// </summary>
     /// <remarks>
     /// <remarks>
     ///     <para>
     ///     <para>
-    ///         SubViews can use the <see cref="ProcessKeyDown"/> of their super view override the default behavior of when
-    ///         key bindings are invoked.
+    ///         For processing <see cref="HotKey"/>s and commands, use <see cref="Command"/> and
+    ///         <see cref="KeyBindings.Add(Key, Command[])"/>instead.
     ///     </para>
     ///     </para>
     ///     <para>
     ///     <para>
-    ///         Not all terminals support distinct key up notifications; applications should avoid depending on distinct
-    ///         KeyUp events.
+    ///         SubViews can use the <see cref="KeyDownNotHandled"/> of their super view override the default behavior of when
+    ///         key bindings are invoked.
     ///     </para>
     ///     </para>
     ///     <para>See <see href="../docs/keyboard.md">for an overview of Terminal.Gui keyboard APIs.</see></para>
     ///     <para>See <see href="../docs/keyboard.md">for an overview of Terminal.Gui keyboard APIs.</see></para>
     /// </remarks>
     /// </remarks>
-    public event EventHandler<Key>? ProcessKeyDown;
+    public event EventHandler<Key>? KeyDownNotHandled;
 
 
     #endregion KeyDown Event
     #endregion KeyDown Event
 
 
     #region KeyUp Event
     #region KeyUp Event
 
 
     /// <summary>
     /// <summary>
-    ///     If the view is enabled, processes a new key up event and returns <see langword="true"/> if the event was
-    ///     handled. Called before <see cref="NewKeyDownEvent"/>.
+    ///     If the view is enabled, raises the related key up events on the view, and returns <see langword="true"/> if the
+    ///     event was
+    ///     handled.
     /// </summary>
     /// </summary>
     /// <remarks>
     /// <remarks>
     ///     <para>
     ///     <para>
@@ -416,44 +423,52 @@ public partial class View // Keyboard APIs
     ///         first.
     ///         first.
     ///     </para>
     ///     </para>
     ///     <para>
     ///     <para>
-    ///         If the focused sub view does not handle the key press, this method calls <see cref="OnKeyUp"/>, which is
-    ///         cancellable.
+    ///         If the focused sub view does not handle the key press, this method raises <see cref="OnKeyUp"/>/
+    ///         <see cref="KeyUp"/> to allow the
+    ///         view to pre-process the key press.
     ///     </para>
     ///     </para>
     ///     <para>See <see href="../docs/keyboard.md">for an overview of Terminal.Gui keyboard APIs.</see></para>
     ///     <para>See <see href="../docs/keyboard.md">for an overview of Terminal.Gui keyboard APIs.</see></para>
     /// </remarks>
     /// </remarks>
-    /// <param name="keyEvent"></param>
+    /// <param name="key"></param>
     /// <returns><see langword="true"/> if the event was handled.</returns>
     /// <returns><see langword="true"/> if the event was handled.</returns>
-    public bool NewKeyUpEvent (Key keyEvent)
+    public bool NewKeyUpEvent (Key key)
     {
     {
         if (!Enabled)
         if (!Enabled)
         {
         {
             return false;
             return false;
         }
         }
 
 
-        if (Focused?.NewKeyUpEvent (keyEvent) == true)
+        // Before
+        if (RaiseKeyUp (key) || key.Handled)
         {
         {
             return true;
             return true;
         }
         }
 
 
-        // Before (fire the cancellable event)
-        if (OnKeyUp (keyEvent))
-        {
-            return true;
-        }
-
-        // During (this is what can be cancelled)
-        // TODO: Until there's a clear use-case, we will not define 'during' event (e.g. OnDuringKeyUp). 
+        // During
 
 
-        // After (fire the cancellable event InvokingKeyBindings)
-        // TODO: Until there's a clear use-case, we will not define an 'after' event (e.g. OnAfterKeyUp). 
+        // After
 
 
         return false;
         return false;
+
+        bool RaiseKeyUp (Key k)
+        {
+            // Before (fire the cancellable event)
+            if (OnKeyUp (k) || k.Handled)
+            {
+                return true;
+            }
+
+            // fire event
+            KeyUp?.Invoke (this, k);
+
+            return k.Handled;
+        }
     }
     }
 
 
-    /// <summary>Method invoked when a key is released. This method is called from <see cref="NewKeyUpEvent"/>.</summary>
-    /// <param name="keyEvent">Contains the details about the key that produced the event.</param>
+    /// <summary>Called when a key is released. This method is called from <see cref="NewKeyUpEvent"/>.</summary>
+    /// <param name="key">Contains the details about the key that produced the event.</param>
     /// <returns>
     /// <returns>
-    ///     <see langword="false"/> if the key stroke was not handled. <see langword="true"/> if no other view should see
+    ///     <see langword="false"/> if the keys up event was not handled. <see langword="true"/> if no other view should see
     ///     it.
     ///     it.
     /// </returns>
     /// </returns>
     /// <remarks>
     /// <remarks>
@@ -465,21 +480,10 @@ public partial class View // Keyboard APIs
     ///     </para>
     ///     </para>
     ///     <para>See <see href="../docs/keyboard.md">for an overview of Terminal.Gui keyboard APIs.</see></para>
     ///     <para>See <see href="../docs/keyboard.md">for an overview of Terminal.Gui keyboard APIs.</see></para>
     /// </remarks>
     /// </remarks>
-    public virtual bool OnKeyUp (Key keyEvent)
-    {
-        // fire event
-        KeyUp?.Invoke (this, keyEvent);
-
-        if (keyEvent.Handled)
-        {
-            return true;
-        }
-
-        return false;
-    }
+    public virtual bool OnKeyUp (Key key) { return false; }
 
 
     /// <summary>
     /// <summary>
-    ///     Invoked when a key is released. Set <see cref="Key.Handled"/> to true to stop the key up event from being processed
+    ///     Raised when a key is released. Set <see cref="Key.Handled"/> to true to stop the key up event from being processed
     ///     by other views.
     ///     by other views.
     ///     <remarks>
     ///     <remarks>
     ///         Not all terminals support key distinct down/up notifications, Applications should avoid depending on
     ///         Not all terminals support key distinct down/up notifications, Applications should avoid depending on
@@ -501,32 +505,20 @@ public partial class View // Keyboard APIs
     private Dictionary<Command, CommandImplementation> CommandImplementations { get; } = new ();
     private Dictionary<Command, CommandImplementation> CommandImplementations { get; } = new ();
 
 
     /// <summary>
     /// <summary>
-    ///     Low-level API called when a user presses a key; invokes any key bindings set on the view. This is called
-    ///     during <see cref="NewKeyDownEvent"/> after <see cref="OnKeyDown"/> has returned.
+    ///     INTERNAL API: Invokes any commands bound to <paramref name="key"/> on this view, adornments, and subviews.
     /// </summary>
     /// </summary>
-    /// <remarks>
-    ///     <para>Fires the <see cref="InvokingKeyBindings"/> event.</para>
-    ///     <para>See <see href="../docs/keyboard.md">for an overview of Terminal.Gui keyboard APIs.</see></para>
-    /// </remarks>
-    /// <param name="keyEvent">Contains the details about the key that produced the event.</param>
-    /// <param name="scope">The scope.</param>
+    /// <param name="key"></param>
     /// <returns>
     /// <returns>
-    ///     <see langword="null"/> if no event was raised; input proessing should continue.
-    ///     <see langword="false"/> if the event was raised and was not handled (or cancelled); input proessing should continue.
-    ///     <see langword="true"/> if the event was raised and handled (or cancelled); input proessing should stop.
+    ///     <see langword="null"/> if no command was invoked or there was no matching key binding; input processing should
+    ///     continue.
+    ///     <see langword="false"/> if a command was invoked and was not handled (or cancelled); input processing should
+    ///     continue.
+    ///     <see langword="true"/> if at least one command was invoked and handled (or
+    ///     cancelled); input processing should stop.
     /// </returns>
     /// </returns>
-    public virtual bool? OnInvokingKeyBindings (Key keyEvent, KeyBindingScope scope)
+    internal bool? InvokeCommandsBoundToKey (Key key)
     {
     {
-        // fire event only if there's a hotkey binding for the key
-        if (KeyBindings.TryGet (keyEvent, scope, out KeyBinding kb))
-        {
-            InvokingKeyBindings?.Invoke (this, keyEvent);
-
-            if (keyEvent.Handled)
-            {
-                return true;
-            }
-        }
+        KeyBindingScope scope = KeyBindingScope.Focused | KeyBindingScope.HotKey;
 
 
         // * If no key binding was found, `InvokeKeyBindings` returns `null`.
         // * If no key binding was found, `InvokeKeyBindings` returns `null`.
         //   Continue passing the event (return `false` from `OnInvokeKeyBindings`).
         //   Continue passing the event (return `false` from `OnInvokeKeyBindings`).
@@ -534,31 +526,31 @@ public partial class View // Keyboard APIs
         //   `InvokeKeyBindings` returns `false`. Continue passing the event (return `false` from `OnInvokeKeyBindings`)..
         //   `InvokeKeyBindings` returns `false`. Continue passing the event (return `false` from `OnInvokeKeyBindings`)..
         // * If key bindings were found, and any handled the key (at least one `Command` returned `true`),
         // * If key bindings were found, and any handled the key (at least one `Command` returned `true`),
         //   `InvokeKeyBindings` returns `true`. Continue passing the event (return `false` from `OnInvokeKeyBindings`).
         //   `InvokeKeyBindings` returns `true`. Continue passing the event (return `false` from `OnInvokeKeyBindings`).
-        bool? handled = InvokeKeyBindings (keyEvent, scope);
+        bool?  handled = InvokeCommands (key, scope);
 
 
-        if (handled is { } && (bool)handled)
+        if (handled is true)
         {
         {
             // Stop processing if any key binding handled the key.
             // Stop processing if any key binding handled the key.
             // DO NOT stop processing if there are no matching key bindings or none of the key bindings handled the key
             // DO NOT stop processing if there are no matching key bindings or none of the key bindings handled the key
-            return true;
+            return handled;
         }
         }
 
 
-        if (Margin is { } && ProcessAdornmentKeyBindings (Margin, keyEvent, scope, ref handled))
+        if (Margin is { } && InvokeCommandsBoundToKeyOnAdornment (Margin, key, scope, ref handled))
         {
         {
             return true;
             return true;
         }
         }
 
 
-        if (Padding is { } && ProcessAdornmentKeyBindings (Padding, keyEvent, scope, ref handled))
+        if (Padding is { } && InvokeCommandsBoundToKeyOnAdornment (Padding, key, scope, ref handled))
         {
         {
             return true;
             return true;
         }
         }
 
 
-        if (Border is { } && ProcessAdornmentKeyBindings (Border, keyEvent, scope, ref handled))
+        if (Border is { } && InvokeCommandsBoundToKeyOnAdornment (Border, key, scope, ref handled))
         {
         {
             return true;
             return true;
         }
         }
 
 
-        if (ProcessSubViewKeyBindings (keyEvent, scope, ref handled))
+        if (InvokeCommandsBoundToKeyOnSubviews (key, scope, ref handled))
         {
         {
             return true;
             return true;
         }
         }
@@ -566,9 +558,9 @@ public partial class View // Keyboard APIs
         return handled;
         return handled;
     }
     }
 
 
-    private bool ProcessAdornmentKeyBindings (Adornment adornment, Key keyEvent, KeyBindingScope scope, ref bool? handled)
+    private static bool InvokeCommandsBoundToKeyOnAdornment (Adornment adornment, Key key, KeyBindingScope scope, ref bool? handled)
     {
     {
-        bool? adornmentHandled = adornment.OnInvokingKeyBindings (keyEvent, scope);
+        bool? adornmentHandled = adornment.InvokeCommandsBoundToKey (key);
 
 
         if (adornmentHandled is true)
         if (adornmentHandled is true)
         {
         {
@@ -582,7 +574,7 @@ public partial class View // Keyboard APIs
 
 
         foreach (View subview in adornment.Subviews)
         foreach (View subview in adornment.Subviews)
         {
         {
-            bool? subViewHandled = subview.OnInvokingKeyBindings (keyEvent, scope);
+            bool? subViewHandled = subview.InvokeCommandsBoundToKey (key);
 
 
             if (subViewHandled is { })
             if (subViewHandled is { })
             {
             {
@@ -598,7 +590,7 @@ public partial class View // Keyboard APIs
         return false;
         return false;
     }
     }
 
 
-    private bool ProcessSubViewKeyBindings (Key keyEvent, KeyBindingScope scope, ref bool? handled, bool invoke = true)
+    private bool InvokeCommandsBoundToKeyOnSubviews (Key key, KeyBindingScope scope, ref bool? handled, bool invoke = true)
     {
     {
         // Now, process any key bindings in the subviews that are tagged to KeyBindingScope.HotKey.
         // Now, process any key bindings in the subviews that are tagged to KeyBindingScope.HotKey.
         foreach (View subview in Subviews)
         foreach (View subview in Subviews)
@@ -608,7 +600,7 @@ public partial class View // Keyboard APIs
                 continue;
                 continue;
             }
             }
 
 
-            if (subview.KeyBindings.TryGet (keyEvent, scope, out KeyBinding binding))
+            if (subview.KeyBindings.TryGet (key, scope, out KeyBinding binding))
             {
             {
                 if (binding.Scope == KeyBindingScope.Focused && !subview.HasFocus)
                 if (binding.Scope == KeyBindingScope.Focused && !subview.HasFocus)
                 {
                 {
@@ -620,7 +612,7 @@ public partial class View // Keyboard APIs
                     return true;
                     return true;
                 }
                 }
 
 
-                bool? subViewHandled = subview.OnInvokingKeyBindings (keyEvent, scope);
+                bool? subViewHandled = subview.InvokeCommandsBoundToKey (key);
 
 
                 if (subViewHandled is { })
                 if (subViewHandled is { })
                 {
                 {
@@ -633,7 +625,7 @@ public partial class View // Keyboard APIs
                 }
                 }
             }
             }
 
 
-            bool recurse = subview.ProcessSubViewKeyBindings (keyEvent, scope, ref handled, invoke);
+            bool recurse = subview.InvokeCommandsBoundToKeyOnSubviews (key, scope, ref handled, invoke);
 
 
             if (recurse || (handled is { } && (bool)handled))
             if (recurse || (handled is { } && (bool)handled))
             {
             {
@@ -653,7 +645,7 @@ public partial class View // Keyboard APIs
     /// <param name="key">The key to test.</param>
     /// <param name="key">The key to test.</param>
     /// <param name="boundView">Returns the view the key is bound to.</param>
     /// <param name="boundView">Returns the view the key is bound to.</param>
     /// <returns></returns>
     /// <returns></returns>
-    public bool IsHotKeyKeyBound (Key key, out View? boundView)
+    public bool IsHotKeyBound (Key key, out View? boundView)
     {
     {
         // recurse through the subviews to find the views that has the key bound
         // recurse through the subviews to find the views that has the key bound
         boundView = null;
         boundView = null;
@@ -667,7 +659,7 @@ public partial class View // Keyboard APIs
                 return true;
                 return true;
             }
             }
 
 
-            if (subview.IsHotKeyKeyBound (key, out boundView))
+            if (subview.IsHotKeyBound (key, out boundView))
             {
             {
                 return true;
                 return true;
             }
             }
@@ -677,26 +669,20 @@ public partial class View // Keyboard APIs
     }
     }
 
 
     /// <summary>
     /// <summary>
-    ///     Raised when a key is pressed that may be mapped to a key binding. Set <see cref="Key.Handled"/> to true to
-    ///     stop the key from being processed by other views.
-    /// </summary>
-    public event EventHandler<Key>? InvokingKeyBindings;
-
-    /// <summary>
-    ///     Invokes any binding that is registered on this <see cref="View"/> and matches the <paramref name="key"/>
+    ///     Invokes the Commands bound to <paramref name="key"/>.
     ///     <para>See <see href="../docs/keyboard.md">for an overview of Terminal.Gui keyboard APIs.</see></para>
     ///     <para>See <see href="../docs/keyboard.md">for an overview of Terminal.Gui keyboard APIs.</see></para>
     /// </summary>
     /// </summary>
     /// <param name="key">The key event passed.</param>
     /// <param name="key">The key event passed.</param>
     /// <param name="scope">The scope.</param>
     /// <param name="scope">The scope.</param>
     /// <returns>
     /// <returns>
-    ///     <see langword="null"/> if no command was invoked; input proessing should continue.
-    ///     <see langword="false"/> if at least one command was invoked and was not handled (or cancelled); input proessing should continue.
-    ///     <see langword="true"/> if at least one command was invoked and handled (or cancelled); input proessing should stop.
+    ///     <see langword="null"/> if no command was invoked; input processing should continue.
+    ///     <see langword="false"/> if at least one command was invoked and was not handled (or cancelled); input processing
+    ///     should continue.
+    ///     <see langword="true"/> if at least one command was invoked and handled (or cancelled); input processing should
+    ///     stop.
     /// </returns>
     /// </returns>
-    protected bool? InvokeKeyBindings (Key key, KeyBindingScope scope)
+    protected bool? InvokeCommands (Key key, KeyBindingScope scope)
     {
     {
-        bool? toReturn = null;
-
         if (!KeyBindings.TryGet (key, scope, out KeyBinding binding))
         if (!KeyBindings.TryGet (key, scope, out KeyBinding binding))
         {
         {
             return null;
             return null;
@@ -704,49 +690,22 @@ public partial class View // Keyboard APIs
 
 
 #if DEBUG
 #if DEBUG
 
 
-        // TODO: Determine if App scope bindings should be fired first or last (currently last).
         if (Application.KeyBindings.TryGet (key, KeyBindingScope.Focused | KeyBindingScope.HotKey, out KeyBinding b))
         if (Application.KeyBindings.TryGet (key, KeyBindingScope.Focused | KeyBindingScope.HotKey, out KeyBinding b))
         {
         {
-            //var boundView = views [0];
-            //var commandBinding = boundView.KeyBindings.Get (key);
             Debug.WriteLine (
             Debug.WriteLine (
-                             $"WARNING: InvokeKeyBindings ({key}) - An Application scope binding exists for this key. The registered view will not invoke Command."); //{commandBinding.Commands [0]}: {boundView}.");
+                             $"WARNING: InvokeKeyBindings ({key}) - An Application scope binding exists for this key. The registered view will not invoke Command.");
         }
         }
 
 
         // TODO: This is a "prototype" debug check. It may be too annoying vs. useful.
         // TODO: This is a "prototype" debug check. It may be too annoying vs. useful.
         // Scour the bindings up our View hierarchy
         // Scour the bindings up our View hierarchy
         // to ensure that the key is not already bound to a different set of commands.
         // to ensure that the key is not already bound to a different set of commands.
-        if (SuperView?.IsHotKeyKeyBound (key, out View? previouslyBoundView) ?? false)
+        if (SuperView?.IsHotKeyBound (key, out View? previouslyBoundView) ?? false)
         {
         {
             Debug.WriteLine ($"WARNING: InvokeKeyBindings ({key}) - A subview or peer has bound this Key and will not see it: {previouslyBoundView}.");
             Debug.WriteLine ($"WARNING: InvokeKeyBindings ({key}) - A subview or peer has bound this Key and will not see it: {previouslyBoundView}.");
         }
         }
 
 
 #endif
 #endif
         return InvokeCommands (binding.Commands, key, binding);
         return InvokeCommands (binding.Commands, key, binding);
-
-        foreach (Command command in binding.Commands)
-        {
-            if (!CommandImplementations.ContainsKey (command))
-            {
-                throw new NotSupportedException (
-                                                 @$"A KeyBinding was set up for the command {command} ({key}) but that command is not supported by this View ({GetType ().Name})"
-                                                );
-            }
-
-            // each command has its own return value
-            bool? thisReturn = InvokeCommand (command, key, binding);
-
-            // if we haven't got anything yet, the current command result should be used
-            toReturn ??= thisReturn;
-
-            // if ever see a true then that's what we will return
-            if (thisReturn ?? false)
-            {
-                toReturn = true;
-            }
-        }
-
-        return toReturn;
     }
     }
 
 
     #endregion Key Bindings
     #endregion Key Bindings

+ 0 - 1
Terminal.Gui/View/View.Layout.cs

@@ -28,7 +28,6 @@ public partial class View // Layout APIs
     /// <param name="targetY">The target y location.</param>
     /// <param name="targetY">The target y location.</param>
     /// <param name="nx">The new x location that will ensure <paramref name="viewToMove"/> will be fully visible.</param>
     /// <param name="nx">The new x location that will ensure <paramref name="viewToMove"/> will be fully visible.</param>
     /// <param name="ny">The new y location that will ensure <paramref name="viewToMove"/> will be fully visible.</param>
     /// <param name="ny">The new y location that will ensure <paramref name="viewToMove"/> will be fully visible.</param>
-    /// <param name="statusBar">The new top most statusBar</param>
     /// <returns>
     /// <returns>
     ///     Either <see cref="Application.Top"/> (if <paramref name="viewToMove"/> does not have a Super View) or
     ///     Either <see cref="Application.Top"/> (if <paramref name="viewToMove"/> does not have a Super View) or
     ///     <paramref name="viewToMove"/>'s SuperView. This can be used to ensure LayoutSubviews is called on the correct View.
     ///     <paramref name="viewToMove"/>'s SuperView. This can be used to ensure LayoutSubviews is called on the correct View.

+ 96 - 85
Terminal.Gui/View/View.Mouse.cs

@@ -11,7 +11,7 @@ public partial class View // Mouse APIs
     private ColorScheme? _savedNonHoverColorScheme;
     private ColorScheme? _savedNonHoverColorScheme;
 
 
     /// <summary>
     /// <summary>
-    ///     INTERNAL Called by <see cref="Application.OnMouseEvent"/> when the mouse moves over the View's <see cref="Frame"/>.
+    ///     INTERNAL Called by <see cref="Application.RaiseMouseEvent"/> when the mouse moves over the View's <see cref="Frame"/>.
     ///     <see cref="MouseLeave"/> will
     ///     <see cref="MouseLeave"/> will
     ///     be raised when the mouse is no longer over the <see cref="Frame"/>. If another View occludes this View, the
     ///     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.
     ///     that View will also receive MouseEnter/Leave events.
@@ -126,7 +126,7 @@ public partial class View // Mouse APIs
     public event EventHandler<CancelEventArgs>? MouseEnter;
     public event EventHandler<CancelEventArgs>? MouseEnter;
 
 
     /// <summary>
     /// <summary>
-    ///     INTERNAL Called by <see cref="Application.OnMouseEvent"/> when the mouse leaves <see cref="Frame"/>, or is occluded
+    ///     INTERNAL Called by <see cref="Application.RaiseMouseEvent"/> when the mouse leaves <see cref="Frame"/>, or is occluded
     ///     by another non-SubView.
     ///     by another non-SubView.
     /// </summary>
     /// </summary>
     /// <remarks>
     /// <remarks>
@@ -196,16 +196,15 @@ public partial class View // Mouse APIs
 
 
     #region Low Level Mouse Events
     #region Low Level Mouse Events
 
 
-    /// <summary>Event fired when a mouse event occurs.</summary>
-    /// <remarks>
-    ///     <para>
-    ///         The coordinates are relative to <see cref="View.Viewport"/>.
-    ///     </para>
-    /// </remarks>
-    public event EventHandler<MouseEventEventArgs>? MouseEvent;
+    /// <summary>Gets or sets whether the <see cref="View"/> wants continuous button pressed events.</summary>
+    public virtual bool WantContinuousButtonPressed { get; set; }
+
+    /// <summary>Gets or sets whether the <see cref="View"/> wants mouse position reports.</summary>
+    /// <value><see langword="true"/> if mouse position reports are wanted; otherwise, <see langword="false"/>.</value>
+    public bool WantMousePositionReports { get; set; }
 
 
     /// <summary>
     /// <summary>
-    ///     Processes a <see cref="MouseEvent"/>. This method is called by <see cref="Application.OnMouseEvent"/> when a mouse
+    ///     Processes a new <see cref="MouseEvent"/>. This method is called by <see cref="Application.RaiseMouseEvent"/> when a mouse
     ///     event occurs.
     ///     event occurs.
     /// </summary>
     /// </summary>
     /// <remarks>
     /// <remarks>
@@ -213,20 +212,20 @@ public partial class View // Mouse APIs
     ///         A view must be both enabled and visible to receive mouse events.
     ///         A view must be both enabled and visible to receive mouse events.
     ///     </para>
     ///     </para>
     ///     <para>
     ///     <para>
-    ///         This method calls <see cref="OnMouseEvent"/> to process the event. If the event is not handled, and one of the
-    ///         mouse buttons was clicked, it calls <see cref="OnMouseClick"/> to process the click.
+    ///         This method raises <see cref="RaiseMouseEvent"/>/<see cref="MouseEvent"/>; if not handled, and one of the
+    ///         mouse buttons was clicked, the <see cref="RaiseMouseClickEvent"/>/<see cref="MouseClick"/> event will be raised
     ///     </para>
     ///     </para>
     ///     <para>
     ///     <para>
     ///         See <see cref="SetPressedHighlight"/> for more information.
     ///         See <see cref="SetPressedHighlight"/> for more information.
     ///     </para>
     ///     </para>
     ///     <para>
     ///     <para>
-    ///         If <see cref="WantContinuousButtonPressed"/> is <see langword="true"/>, the <see cref="OnMouseClick"/> event
-    ///         will be invoked repeatedly while the button is pressed.
+    ///         If <see cref="WantContinuousButtonPressed"/> is <see langword="true"/>, the <see cref="RaiseMouseEvent"/>/<see cref="MouseEvent"/> event
+    ///         will be raised on any new mouse event where <see cref="Terminal.Gui.MouseEventArgs.Flags"/> indicates a button is pressed.
     ///     </para>
     ///     </para>
     /// </remarks>
     /// </remarks>
     /// <param name="mouseEvent"></param>
     /// <param name="mouseEvent"></param>
     /// <returns><see langword="true"/> if the event was handled, <see langword="false"/> otherwise.</returns>
     /// <returns><see langword="true"/> if the event was handled, <see langword="false"/> otherwise.</returns>
-    public bool? NewMouseEvent (MouseEvent mouseEvent)
+    public bool? NewMouseEvent (MouseEventArgs mouseEvent)
     {
     {
         // Pre-conditions
         // Pre-conditions
         if (!Enabled)
         if (!Enabled)
@@ -246,17 +245,13 @@ public partial class View // Mouse APIs
         }
         }
 
 
         // Cancellable event
         // Cancellable event
-        if (OnMouseEvent (mouseEvent))
+        if (RaiseMouseEvent (mouseEvent) || mouseEvent.Handled)
         {
         {
-            // Technically mouseEvent.Handled should already be true if implementers of OnMouseEvent
-            // follow the rules. But we'll update it just in case.
-            return mouseEvent.Handled = true;
+            return true;
         }
         }
 
 
-        // BUGBUG: MouseEvent should be fired from here. Fix this in https://github.com/gui-cs/Terminal.Gui/issues/3029
-
         // Post-Conditions
         // Post-Conditions
-        if (HighlightStyle != HighlightStyle.None || (WantContinuousButtonPressed && WantMousePositionReports))
+        if (HighlightStyle != HighlightStyle.None || WantContinuousButtonPressed)
         {
         {
             if (WhenGrabbedHandlePressed (mouseEvent))
             if (WhenGrabbedHandlePressed (mouseEvent))
             {
             {
@@ -274,35 +269,33 @@ public partial class View // Mouse APIs
             }
             }
         }
         }
 
 
-        if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Clicked)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button2Clicked)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button3Clicked)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button4Clicked)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button1DoubleClicked)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button2DoubleClicked)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button3DoubleClicked)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button4DoubleClicked)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button1TripleClicked)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button2TripleClicked)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button3TripleClicked)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button4TripleClicked)
-           )
+        if (mouseEvent.IsSingleDoubleOrTripleClicked)
         {
         {
             // If it's a click, and we didn't handle it, then we need to generate a click event
             // If it's a click, and we didn't handle it, then we need to generate a click event
             // We get here if the view did not handle the mouse event via OnMouseEvent/MouseEvent and
             // We get here if the view did not handle the mouse event via OnMouseEvent/MouseEvent and
             // it did not handle the press/release/clicked events via HandlePress/HandleRelease/HandleClicked
             // it did not handle the press/release/clicked events via HandlePress/HandleRelease/HandleClicked
-            return OnMouseClick (new (mouseEvent));
+            return RaiseMouseClickEvent (mouseEvent);
         }
         }
 
 
         return false;
         return false;
     }
     }
 
 
-    /// <summary>Gets or sets whether the <see cref="View"/> wants continuous button pressed events.</summary>
-    public virtual bool WantContinuousButtonPressed { get; set; }
+    /// <summary>
+    ///     Raises the <see cref="RaiseMouseEvent"/>/<see cref="MouseEvent"/> event.
+    /// </summary>
+    /// <param name="mouseEvent"></param>
+    /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
+    public bool RaiseMouseEvent (MouseEventArgs mouseEvent)
+    {
+        if (OnMouseEvent (mouseEvent) || mouseEvent.Handled == true)
+        {
+            return true;
+        }
 
 
-    /// <summary>Gets or sets whether the <see cref="View"/> wants mouse position reports.</summary>
-    /// <value><see langword="true"/> if mouse position reports are wanted; otherwise, <see langword="false"/>.</value>
-    public virtual bool WantMousePositionReports { get; set; }
+        MouseEvent?.Invoke (this, mouseEvent);
+
+        return mouseEvent.Handled;
+    }
 
 
     /// <summary>Called when a mouse event occurs within the view's <see cref="Viewport"/>.</summary>
     /// <summary>Called when a mouse event occurs within the view's <see cref="Viewport"/>.</summary>
     /// <remarks>
     /// <remarks>
@@ -312,44 +305,36 @@ public partial class View // Mouse APIs
     /// </remarks>
     /// </remarks>
     /// <param name="mouseEvent"></param>
     /// <param name="mouseEvent"></param>
     /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
     /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
-    protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent)
+    protected virtual bool OnMouseEvent (MouseEventArgs mouseEvent)
     {
     {
-        var args = new MouseEventEventArgs (mouseEvent);
-
-        MouseEvent?.Invoke (this, args);
-
-        return args.Handled;
+        return false;
     }
     }
 
 
-    #endregion Low Level Mouse Events
-
-    #region Mouse Click Events
-
-    /// <summary>Event fired when a mouse click occurs.</summary>
-    /// 
+    /// <summary>Raised when a mouse event occurs.</summary>
     /// <remarks>
     /// <remarks>
     ///     <para>
     ///     <para>
-    ///         Fired when the mouse is either clicked or double-clicked. Check
-    ///         <see cref="MouseEvent.Flags"/> to see which button was clicked.
-    ///     </para>
-    ///     <para>
     ///         The coordinates are relative to <see cref="View.Viewport"/>.
     ///         The coordinates are relative to <see cref="View.Viewport"/>.
     ///     </para>
     ///     </para>
     /// </remarks>
     /// </remarks>
-    public event EventHandler<MouseEventEventArgs>? MouseClick;
+    public event EventHandler<MouseEventArgs>? MouseEvent;
+
+    #endregion Low Level Mouse Events
 
 
-    /// <summary>Invokes the MouseClick event.</summary>
+    #region Mouse Click Events
+
+    /// <summary>Raises the <see cref="OnMouseClick"/>/<see cref="MouseClick"/> event.</summary>
     /// <remarks>
     /// <remarks>
     ///     <para>
     ///     <para>
-    ///         Called when the mouse is either clicked or double-clicked. Check
-    ///         <see cref="MouseEvent.Flags"/> to see which button was clicked.
+    ///         Called when the mouse is either clicked or double-clicked.
+    ///     </para>
+    ///     <para>
+    ///         If <see cref="WantContinuousButtonPressed"/> is <see langword="true"/>, will be invoked on every mouse event where
+    ///         the mouse button is pressed.
     ///     </para>
     ///     </para>
     /// </remarks>
     /// </remarks>
     /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
     /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
-    protected bool OnMouseClick (MouseEventEventArgs args)
+    protected bool RaiseMouseClickEvent (MouseEventArgs args)
     {
     {
-        // BUGBUG: This should be named NewMouseClickEvent. Fix this in https://github.com/gui-cs/Terminal.Gui/issues/3029
-
         // Pre-conditions
         // Pre-conditions
         if (!Enabled)
         if (!Enabled)
         {
         {
@@ -359,7 +344,10 @@ public partial class View // Mouse APIs
 
 
         // Cancellable event
         // Cancellable event
 
 
-        // BUGBUG: There should be a call to a protected virtual OnMouseClick here. Fix this in https://github.com/gui-cs/Terminal.Gui/issues/3029
+        if (OnMouseClick (args) || args.Handled)
+        {
+            return args.Handled;
+        }
 
 
         MouseClick?.Invoke (this, args);
         MouseClick?.Invoke (this, args);
 
 
@@ -372,11 +360,39 @@ public partial class View // Mouse APIs
 
 
         // Always invoke Select command on MouseClick
         // Always invoke Select command on MouseClick
         // By default, this will raise Selecting/OnSelecting - Subclasses can override this via AddCommand (Command.Select ...).
         // By default, this will raise Selecting/OnSelecting - Subclasses can override this via AddCommand (Command.Select ...).
-        args.Handled = InvokeCommand (Command.Select, ctx: new (Command.Select, key: null, data: args.MouseEvent)) == true;
+        args.Handled = InvokeCommand (Command.Select, ctx: new (Command.Select, key: null, data: args)) == true;
 
 
         return args.Handled;
         return args.Handled;
     }
     }
 
 
+    /// <summary>
+    ///     Called when a mouse click occurs. Check <see cref="MouseEventArgs.Flags"/> to see which button was clicked.
+    /// </summary>
+    /// <remarks>
+    ///     <para>
+    ///         Called when the mouse is either clicked or double-clicked.
+    ///     </para>
+    ///     <para>
+    ///         If <see cref="WantContinuousButtonPressed"/> is <see langword="true"/>, will be called on every mouse event where
+    ///         the mouse button is pressed.
+    ///     </para>
+    /// </remarks>
+    /// <param name="args"></param>
+    /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
+    protected virtual bool OnMouseClick (MouseEventArgs args) { return false; }
+
+    /// <summary>Raised when a mouse click occurs.</summary>
+    /// <remarks>
+    ///     <para>
+    ///         Raised when the mouse is either clicked or double-clicked.
+    ///     </para>
+    ///     <para>
+    ///         If <see cref="WantContinuousButtonPressed"/> is <see langword="true"/>, will be raised on every mouse event where
+    ///         the mouse button is pressed.
+    ///     </para>
+    /// </remarks>
+    public event EventHandler<MouseEventArgs>? MouseClick;
+
     /// <summary>
     /// <summary>
     ///     INTERNAL For cases where the view is grabbed and the mouse is clicked, this method handles the click event (typically
     ///     INTERNAL For cases where the view is grabbed and the mouse is clicked, this method handles the click event (typically
     ///     when <see cref="WantContinuousButtonPressed"/> or <see cref="HighlightStyle"/> are set).
     ///     when <see cref="WantContinuousButtonPressed"/> or <see cref="HighlightStyle"/> are set).
@@ -386,13 +402,11 @@ public partial class View // Mouse APIs
     /// </remarks>
     /// </remarks>
     /// <param name="mouseEvent"></param>
     /// <param name="mouseEvent"></param>
     /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
     /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
-    internal bool WhenGrabbedHandleClicked (MouseEvent mouseEvent)
+    internal bool WhenGrabbedHandleClicked (MouseEventArgs mouseEvent)
     {
     {
-        if (Application.MouseGrabView == this
-            && (mouseEvent.Flags.HasFlag (MouseFlags.Button1Clicked)
-                || mouseEvent.Flags.HasFlag (MouseFlags.Button2Clicked)
-                || mouseEvent.Flags.HasFlag (MouseFlags.Button3Clicked)
-                || mouseEvent.Flags.HasFlag (MouseFlags.Button4Clicked)))
+        mouseEvent.Handled = false;
+
+        if (Application.MouseGrabView == this && mouseEvent.IsSingleClicked)
         {
         {
             // We're grabbed. Clicked event comes after the last Release. This is our signal to ungrab
             // We're grabbed. Clicked event comes after the last Release. This is our signal to ungrab
             Application.UngrabMouse ();
             Application.UngrabMouse ();
@@ -405,7 +419,7 @@ public partial class View // Mouse APIs
             // If mouse is still in bounds, generate a click
             // If mouse is still in bounds, generate a click
             if (!WantMousePositionReports && Viewport.Contains (mouseEvent.Position))
             if (!WantMousePositionReports && Viewport.Contains (mouseEvent.Position))
             {
             {
-                return OnMouseClick (new (mouseEvent));
+                return RaiseMouseClickEvent (mouseEvent);
             }
             }
 
 
             return mouseEvent.Handled = true;
             return mouseEvent.Handled = true;
@@ -423,12 +437,11 @@ public partial class View // Mouse APIs
     /// </remarks>
     /// </remarks>
     /// <param name="mouseEvent"></param>
     /// <param name="mouseEvent"></param>
     /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
     /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
-    internal bool WhenGrabbedHandleReleased (MouseEvent mouseEvent)
+    internal bool WhenGrabbedHandleReleased (MouseEventArgs mouseEvent)
     {
     {
-        if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Released)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button2Released)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button3Released)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button4Released))
+        mouseEvent.Handled = false;
+
+        if (mouseEvent.IsReleased)
         {
         {
             if (Application.MouseGrabView == this)
             if (Application.MouseGrabView == this)
             {
             {
@@ -452,12 +465,11 @@ public partial class View // Mouse APIs
     /// </remarks>
     /// </remarks>
     /// <param name="mouseEvent"></param>
     /// <param name="mouseEvent"></param>
     /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
     /// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
-    private bool WhenGrabbedHandlePressed (MouseEvent mouseEvent)
+    private bool WhenGrabbedHandlePressed (MouseEventArgs mouseEvent)
     {
     {
-        if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button2Pressed)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button3Pressed)
-            || mouseEvent.Flags.HasFlag (MouseFlags.Button4Pressed))
+        mouseEvent.Handled = false;
+
+        if (mouseEvent.IsPressed)
         {
         {
             // The first time we get pressed event, grab the mouse and set focus
             // The first time we get pressed event, grab the mouse and set focus
             if (Application.MouseGrabView != this)
             if (Application.MouseGrabView != this)
@@ -493,8 +505,7 @@ public partial class View // Mouse APIs
 
 
             if (WantContinuousButtonPressed && Application.MouseGrabView == this)
             if (WantContinuousButtonPressed && Application.MouseGrabView == this)
             {
             {
-                // If this is not the first pressed event, generate a click
-                return OnMouseClick (new (mouseEvent));
+                return RaiseMouseClickEvent (mouseEvent);
             }
             }
 
 
             return mouseEvent.Handled = true;
             return mouseEvent.Handled = true;

+ 202 - 63
Terminal.Gui/View/View.Navigation.cs

@@ -1,6 +1,5 @@
 #nullable enable
 #nullable enable
 using System.Diagnostics;
 using System.Diagnostics;
-using System.Reflection.PortableExecutable;
 
 
 namespace Terminal.Gui;
 namespace Terminal.Gui;
 
 
@@ -18,7 +17,8 @@ public partial class View // Focus and cross-view navigation management (TabStop
     ///         If there is no next/previous view to advance to, the focus is set to the view itself.
     ///         If there is no next/previous view to advance to, the focus is set to the view itself.
     ///     </para>
     ///     </para>
     ///     <para>
     ///     <para>
-    ///         See the View Navigation Deep Dive for more information: <see href="https://gui-cs.github.io/Terminal.GuiV2Docs/docs/navigation.html"/>
+    ///         See the View Navigation Deep Dive for more information:
+    ///         <see href="https://gui-cs.github.io/Terminal.GuiV2Docs/docs/navigation.html"/>
     ///     </para>
     ///     </para>
     /// </remarks>
     /// </remarks>
     /// <param name="direction"></param>
     /// <param name="direction"></param>
@@ -34,6 +34,11 @@ public partial class View // Focus and cross-view navigation management (TabStop
             return false;
             return false;
         }
         }
 
 
+        if (RaiseAdvancingFocus (direction, behavior))
+        {
+            return true;
+        }
+
         View? focused = Focused;
         View? focused = Focused;
 
 
         if (focused is { } && focused.AdvanceFocus (direction, behavior))
         if (focused is { } && focused.AdvanceFocus (direction, behavior))
@@ -128,6 +133,14 @@ public partial class View // Focus and cross-view navigation management (TabStop
         if (view.HasFocus)
         if (view.HasFocus)
         {
         {
             // We could not advance
             // We could not advance
+            if (view != this)
+            {
+                // Tell it to try the other way.
+                return view.RaiseAdvancingFocus (
+                                                 direction == NavigationDirection.Forward ? NavigationDirection.Backward : NavigationDirection.Forward,
+                                                 behavior);
+            }
+
             return view == this;
             return view == this;
         }
         }
 
 
@@ -137,10 +150,61 @@ public partial class View // Focus and cross-view navigation management (TabStop
         return focusSet;
         return focusSet;
     }
     }
 
 
+    private bool RaiseAdvancingFocus (NavigationDirection direction, TabBehavior? behavior)
+    {
+        // Call the virtual method
+        if (OnAdvancingFocus (direction, behavior))
+        {
+            // The event was cancelled
+            return true;
+        }
+
+        var args = new AdvanceFocusEventArgs (direction, behavior);
+        AdvancingFocus?.Invoke (this, args);
+
+        if (args.Cancel)
+        {
+            // The event was cancelled
+            return true;
+        }
+
+        return false;
+    }
+
+    /// <summary>
+    ///     Called when <see cref="View.AdvanceFocus"/> is about to advance focus.
+    /// </summary>
+    /// <remarks>
+    ///     <para>
+    ///         If a view cancels the event and the focus could not otherwise advance, the Navigation direction will be
+    ///         reversed and the event will be raised again.
+    ///     </para>
+    /// </remarks>
+    /// <returns>
+    ///     <see langword="true"/>, if the focus advance is to be cancelled, <see langword="false"/>
+    ///     otherwise.
+    /// </returns>
+    protected virtual bool OnAdvancingFocus (NavigationDirection direction, TabBehavior? behavior) { return false; }
+
+    /// <summary>
+    ///     Raised when <see cref="View.AdvanceFocus"/> is about to advance focus.
+    /// </summary>
+    /// <remarks>
+    ///     <para>
+    ///         Cancel the event to prevent the focus from advancing.
+    ///     </para>
+    ///     <para>
+    ///         If a view cancels the event and the focus could not otherwise advance, the Navigation direction will be
+    ///         reversed and the event will be raised again.
+    ///     </para>
+    /// </remarks>
+    public event EventHandler<AdvanceFocusEventArgs>? AdvancingFocus;
+
     /// <summary>Gets or sets a value indicating whether this <see cref="View"/> can be focused.</summary>
     /// <summary>Gets or sets a value indicating whether this <see cref="View"/> can be focused.</summary>
     /// <remarks>
     /// <remarks>
     ///     <para>
     ///     <para>
-    ///         See the View Navigation Deep Dive for more information: <see href="https://gui-cs.github.io/Terminal.GuiV2Docs/docs/navigation.html"/>
+    ///         See the View Navigation Deep Dive for more information:
+    ///         <see href="https://gui-cs.github.io/Terminal.GuiV2Docs/docs/navigation.html"/>
     ///     </para>
     ///     </para>
     ///     <para>
     ///     <para>
     ///         <see cref="SuperView"/> must also have <see cref="CanFocus"/> set to <see langword="true"/>.
     ///         <see cref="SuperView"/> must also have <see cref="CanFocus"/> set to <see langword="true"/>.
@@ -180,7 +244,8 @@ public partial class View // Focus and cross-view navigation management (TabStop
             if (!_canFocus && HasFocus)
             if (!_canFocus && HasFocus)
             {
             {
                 // If CanFocus is set to false and this view has focus, make it leave focus
                 // If CanFocus is set to false and this view has focus, make it leave focus
-                HasFocus = false;
+                // Set transversing down so we don't go back up the hierarchy...
+                SetHasFocusFalse (null, false);
             }
             }
 
 
             if (_canFocus && !HasFocus && Visible && SuperView is { Focused: null })
             if (_canFocus && !HasFocus && Visible && SuperView is { Focused: null })
@@ -296,7 +361,12 @@ public partial class View // Focus and cross-view navigation management (TabStop
 
 
         if (Focused is null && _previouslyFocused is { } && indicies.Contains (_previouslyFocused))
         if (Focused is null && _previouslyFocused is { } && indicies.Contains (_previouslyFocused))
         {
         {
-            return _previouslyFocused.SetFocus ();
+            if (_previouslyFocused.SetFocus ())
+            {
+                return true;
+            }
+
+            _previouslyFocused = null;
         }
         }
 
 
         return false;
         return false;
@@ -324,7 +394,8 @@ public partial class View // Focus and cross-view navigation management (TabStop
     /// </summary>
     /// </summary>
     /// <remarks>
     /// <remarks>
     ///     <para>
     ///     <para>
-    ///         See the View Navigation Deep Dive for more information: <see href="https://gui-cs.github.io/Terminal.GuiV2Docs/docs/navigation.html"/>
+    ///         See the View Navigation Deep Dive for more information:
+    ///         <see href="https://gui-cs.github.io/Terminal.GuiV2Docs/docs/navigation.html"/>
     ///     </para>
     ///     </para>
     ///     <para>
     ///     <para>
     ///         Only Views that are visible, enabled, and have <see cref="CanFocus"/> set to <see langword="true"/> are
     ///         Only Views that are visible, enabled, and have <see cref="CanFocus"/> set to <see langword="true"/> are
@@ -375,6 +446,8 @@ public partial class View // Focus and cross-view navigation management (TabStop
             {
             {
                 SetHasFocusFalse (null);
                 SetHasFocusFalse (null);
 
 
+                Debug.Assert (!_hasFocus);
+
                 if (_hasFocus)
                 if (_hasFocus)
                 {
                 {
                     // force it.
                     // force it.
@@ -391,7 +464,8 @@ public partial class View // Focus and cross-view navigation management (TabStop
     /// </summary>
     /// </summary>
     /// <remarks>
     /// <remarks>
     ///     <para>
     ///     <para>
-    ///         See the View Navigation Deep Dive for more information: <see href="https://gui-cs.github.io/Terminal.GuiV2Docs/docs/navigation.html"/>
+    ///         See the View Navigation Deep Dive for more information:
+    ///         <see href="https://gui-cs.github.io/Terminal.GuiV2Docs/docs/navigation.html"/>
     ///     </para>
     ///     </para>
     /// </remarks>
     /// </remarks>
     /// <returns><see langword="true"/> if the focus changed; <see langword="true"/> false otherwise.</returns>
     /// <returns><see langword="true"/> if the focus changed; <see langword="true"/> false otherwise.</returns>
@@ -412,14 +486,14 @@ public partial class View // Focus and cross-view navigation management (TabStop
     ///     other methods that
     ///     other methods that
     ///     set or remove focus from a view.
     ///     set or remove focus from a view.
     /// </summary>
     /// </summary>
-    /// <param name="previousFocusedView">
-    ///     The previously focused view. If <see langword="null"/> there is no previously focused
+    /// <param name="currentFocusedView">
+    ///     The currently focused view. If <see langword="null"/> there is no previously focused
     ///     view.
     ///     view.
     /// </param>
     /// </param>
     /// <param name="traversingUp"></param>
     /// <param name="traversingUp"></param>
     /// <returns><see langword="true"/> if <see cref="HasFocus"/> was changed to <see langword="true"/>.</returns>
     /// <returns><see langword="true"/> if <see cref="HasFocus"/> was changed to <see langword="true"/>.</returns>
     /// <exception cref="InvalidOperationException"></exception>
     /// <exception cref="InvalidOperationException"></exception>
-    private (bool focusSet, bool cancelled) SetHasFocusTrue (View? previousFocusedView, bool traversingUp = false)
+    private (bool focusSet, bool cancelled) SetHasFocusTrue (View? currentFocusedView, bool traversingUp = false)
     {
     {
         Debug.Assert (SuperView is null || ApplicationNavigation.IsInHierarchy (SuperView, this));
         Debug.Assert (SuperView is null || ApplicationNavigation.IsInHierarchy (SuperView, this));
 
 
@@ -429,6 +503,11 @@ public partial class View // Focus and cross-view navigation management (TabStop
             return (false, false);
             return (false, false);
         }
         }
 
 
+        if (currentFocusedView is { HasFocus: false })
+        {
+            throw new ArgumentException ("SetHasFocusTrue: currentFocusedView must HasFocus.");
+        }
+
         var thisAsAdornment = this as Adornment;
         var thisAsAdornment = this as Adornment;
         View? superViewOrParent = thisAsAdornment?.Parent ?? SuperView;
         View? superViewOrParent = thisAsAdornment?.Parent ?? SuperView;
 
 
@@ -451,7 +530,7 @@ public partial class View // Focus and cross-view navigation management (TabStop
 
 
         bool previousValue = HasFocus;
         bool previousValue = HasFocus;
 
 
-        bool cancelled = NotifyFocusChanging (false, true, previousFocusedView, this);
+        bool cancelled = RaiseFocusChanging (false, true, currentFocusedView, this);
 
 
         if (cancelled)
         if (cancelled)
         {
         {
@@ -462,7 +541,7 @@ public partial class View // Focus and cross-view navigation management (TabStop
         // Any of them may cancel gaining focus. In which case we need to back out.
         // Any of them may cancel gaining focus. In which case we need to back out.
         if (superViewOrParent is { HasFocus: false } sv)
         if (superViewOrParent is { HasFocus: false } sv)
         {
         {
-            (bool focusSet, bool svCancelled) = sv.SetHasFocusTrue (previousFocusedView, true);
+            (bool focusSet, bool svCancelled) = sv.SetHasFocusTrue (currentFocusedView, true);
 
 
             if (!focusSet)
             if (!focusSet)
             {
             {
@@ -488,31 +567,32 @@ public partial class View // Focus and cross-view navigation management (TabStop
 
 
         if (!traversingUp)
         if (!traversingUp)
         {
         {
-            // Restore focus to the previously focused subview 
+            // Restore focus to the previously focused subview, if any
             if (!RestoreFocus ())
             if (!RestoreFocus ())
             {
             {
-                // Couldn't restore focus, so use Advance to navigate to the next focusable subview
-                if (!AdvanceFocus (NavigationDirection.Forward, null))
-                {
-                    // Couldn't advance, so we're the most focused view in the application
-                    Application.Navigation?.SetFocused (this);
-                }
+                // Couldn't restore focus, so use Advance to navigate to the next focusable subview, if any
+                AdvanceFocus (NavigationDirection.Forward, null);
             }
             }
         }
         }
 
 
-        if (previousFocusedView is { HasFocus: true } && GetFocusChain (NavigationDirection.Forward, TabStop).Contains (previousFocusedView))
+        // Now make sure the old focused view loses focus
+        if (currentFocusedView is { HasFocus: true } && GetFocusChain (NavigationDirection.Forward, TabStop).Contains (currentFocusedView))
         {
         {
-            previousFocusedView.SetHasFocusFalse (this);
+            currentFocusedView.SetHasFocusFalse (this);
         }
         }
 
 
-        _previouslyFocused = null;
+        if (_previouslyFocused is { })
+        {
+            _previouslyFocused = null;
+        }
 
 
         if (Arrangement.HasFlag (ViewArrangement.Overlapped))
         if (Arrangement.HasFlag (ViewArrangement.Overlapped))
         {
         {
             SuperView?.MoveSubviewToEnd (this);
             SuperView?.MoveSubviewToEnd (this);
         }
         }
 
 
-        NotifyFocusChanged (HasFocus, previousFocusedView, this);
+        // Focus work is done. Notify.
+        RaiseFocusChanged (HasFocus, currentFocusedView, this);
 
 
         SetNeedsDisplay ();
         SetNeedsDisplay ();
 
 
@@ -525,8 +605,11 @@ public partial class View // Focus and cross-view navigation management (TabStop
         return (true, false);
         return (true, false);
     }
     }
 
 
-    private bool NotifyFocusChanging (bool currentHasFocus, bool newHasFocus, View? currentFocused, View? newFocused)
+    private bool RaiseFocusChanging (bool currentHasFocus, bool newHasFocus, View? currentFocused, View? newFocused)
     {
     {
+        Debug.Assert (currentFocused is null || currentFocused is { HasFocus: true });
+        Debug.Assert (newFocused is null || newFocused is { CanFocus: true });
+
         // Call the virtual method
         // Call the virtual method
         if (OnHasFocusChanging (currentHasFocus, newHasFocus, currentFocused, newFocused))
         if (OnHasFocusChanging (currentHasFocus, newHasFocus, currentFocused, newFocused))
         {
         {
@@ -543,6 +626,20 @@ public partial class View // Focus and cross-view navigation management (TabStop
             return true;
             return true;
         }
         }
 
 
+        View? appFocused = Application.Navigation?.GetFocused ();
+
+        if (appFocused == currentFocused)
+        {
+            if (newFocused is { HasFocus: true })
+            {
+                Application.Navigation?.SetFocused (newFocused);
+            }
+            else
+            {
+                Application.Navigation?.SetFocused (null);
+            }
+        }
+
         return false;
         return false;
     }
     }
 
 
@@ -586,8 +683,9 @@ public partial class View // Focus and cross-view navigation management (TabStop
     ///     focused.
     ///     focused.
     /// </param>
     /// </param>
     /// <param name="traversingDown">
     /// <param name="traversingDown">
-    ///     Set to true to indicate method is being called recurively, traversing down the focus
-    ///     chain.
+    ///     Set to true to traverse down the focus
+    ///     chain only. If false, the method will attempt to AdvanceFocus on the superview or restorefocus on
+    ///     Application.Navigation.GetFocused().
     /// </param>
     /// </param>
     /// <exception cref="InvalidOperationException"></exception>
     /// <exception cref="InvalidOperationException"></exception>
     private void SetHasFocusFalse (View? newFocusedView, bool traversingDown = false)
     private void SetHasFocusFalse (View? newFocusedView, bool traversingDown = false)
@@ -598,45 +696,86 @@ public partial class View // Focus and cross-view navigation management (TabStop
             throw new InvalidOperationException ("SetHasFocusFalse should not be called if the view does not have focus.");
             throw new InvalidOperationException ("SetHasFocusFalse should not be called if the view does not have focus.");
         }
         }
 
 
+        if (newFocusedView is { HasFocus: false })
+        {
+            throw new InvalidOperationException ("SetHasFocusFalse new focused view does not have focus.");
+        }
+
         var thisAsAdornment = this as Adornment;
         var thisAsAdornment = this as Adornment;
         View? superViewOrParent = thisAsAdornment?.Parent ?? SuperView;
         View? superViewOrParent = thisAsAdornment?.Parent ?? SuperView;
 
 
         // If newFocusedVew is null, we need to find the view that should get focus, and SetFocus on it.
         // If newFocusedVew is null, we need to find the view that should get focus, and SetFocus on it.
         if (!traversingDown && newFocusedView is null)
         if (!traversingDown && newFocusedView is null)
         {
         {
-            if (superViewOrParent?._previouslyFocused is { })
+            // Restore focus?
+            if (superViewOrParent?._previouslyFocused is { CanFocus: true })
             {
             {
-                if (superViewOrParent._previouslyFocused != this)
+                // TODO: Why don't we call RestoreFocus here?
+                if (superViewOrParent._previouslyFocused != this && superViewOrParent._previouslyFocused.SetFocus ())
                 {
                 {
-                    superViewOrParent?._previouslyFocused?.SetFocus ();
-
                     // The above will cause SetHasFocusFalse, so we can return
                     // The above will cause SetHasFocusFalse, so we can return
+                    Debug.Assert (!_hasFocus);
+
                     return;
                     return;
                 }
                 }
             }
             }
 
 
-            if (superViewOrParent is { })
+            // AdvanceFocus?
+            if (superViewOrParent is { CanFocus: true })
             {
             {
                 if (superViewOrParent.AdvanceFocus (NavigationDirection.Forward, TabStop))
                 if (superViewOrParent.AdvanceFocus (NavigationDirection.Forward, TabStop))
                 {
                 {
-                    // The above will cause SetHasFocusFalse, so we can return
-                    return;
+                    // The above might have SetHasFocusFalse, so we can return
+                    if (!_hasFocus)
+                    {
+                        return;
+                    }
                 }
                 }
 
 
-                newFocusedView = superViewOrParent;
+                if (superViewOrParent is { HasFocus: true, CanFocus: true })
+                {
+                    newFocusedView = superViewOrParent;
+                }
             }
             }
 
 
-            if (Application.Navigation is { } && Application.Top is { })
+            // Application.Navigation.GetFocused?
+            View? applicationFocused = Application.Navigation?.GetFocused ();
+
+            if (newFocusedView is null && applicationFocused != this && applicationFocused is { CanFocus: true })
             {
             {
                 // Temporarily ensure this view can't get focus
                 // Temporarily ensure this view can't get focus
                 bool prevCanFocus = _canFocus;
                 bool prevCanFocus = _canFocus;
                 _canFocus = false;
                 _canFocus = false;
-                bool restoredFocus = Application.Top!.RestoreFocus ();
+                bool restoredFocus = applicationFocused!.RestoreFocus ();
                 _canFocus = prevCanFocus;
                 _canFocus = prevCanFocus;
 
 
                 if (restoredFocus)
                 if (restoredFocus)
                 {
                 {
                     // The above caused SetHasFocusFalse, so we can return
                     // The above caused SetHasFocusFalse, so we can return
+                    Debug.Assert (!_hasFocus);
+
+                    return;
+                }
+            }
+
+            // Application.Top?
+            if (newFocusedView is null && Application.Top is { CanFocus: true, HasFocus: false })
+            {
+                // Temporarily ensure this view can't get focus
+                bool prevCanFocus = _canFocus;
+                _canFocus = false;
+                bool restoredFocus = Application.Top.RestoreFocus ();
+                _canFocus = prevCanFocus;
+
+                if (Application.Top is { CanFocus: true, HasFocus: true })
+                {
+                    newFocusedView = Application.Top;
+                }
+                else if (restoredFocus)
+                {
+                    // The above caused SetHasFocusFalse, so we can return
+                    Debug.Assert (!_hasFocus);
+
                     return;
                     return;
                 }
                 }
             }
             }
@@ -644,6 +783,7 @@ public partial class View // Focus and cross-view navigation management (TabStop
             // No other focusable view to be found. Just "leave" us...
             // No other focusable view to be found. Just "leave" us...
         }
         }
 
 
+        Debug.Assert (_hasFocus);
 
 
         // Before we can leave focus, we need to make sure that all views down the subview-hierarchy have left focus.
         // Before we can leave focus, we need to make sure that all views down the subview-hierarchy have left focus.
         View? mostFocused = MostFocused;
         View? mostFocused = MostFocused;
@@ -665,15 +805,7 @@ public partial class View // Focus and cross-view navigation management (TabStop
                 bottom = bottom.SuperView;
                 bottom = bottom.SuperView;
             }
             }
 
 
-            if (bottom == this && bottom.SuperView is Adornment a)
-            {
-                //a.SetHasFocusFalse (newFocusedView, true);
-
-                Debug.Assert (_hasFocus);
-            }
-
             Debug.Assert (_hasFocus);
             Debug.Assert (_hasFocus);
-
         }
         }
 
 
         if (superViewOrParent is { })
         if (superViewOrParent is { })
@@ -683,8 +815,17 @@ public partial class View // Focus and cross-view navigation management (TabStop
 
 
         bool previousValue = HasFocus;
         bool previousValue = HasFocus;
 
 
+        Debug.Assert (_hasFocus);
+
         // Note, can't be cancelled.
         // Note, can't be cancelled.
-        NotifyFocusChanging (HasFocus, !HasFocus, newFocusedView, this);
+        RaiseFocusChanging (HasFocus, !HasFocus, this, newFocusedView);
+
+        // Even though the change can't be cancelled, some listener may have changed the focus to another view.
+        if (!_hasFocus)
+        {
+            // Notify caused HasFocus to change to false.
+            return;
+        }
 
 
         // Get whatever peer has focus, if any so we can update our superview's _previouslyMostFocused
         // Get whatever peer has focus, if any so we can update our superview's _previouslyMostFocused
         View? focusedPeer = superViewOrParent?.Focused;
         View? focusedPeer = superViewOrParent?.Focused;
@@ -692,17 +833,7 @@ public partial class View // Focus and cross-view navigation management (TabStop
         // Set HasFocus false
         // Set HasFocus false
         _hasFocus = false;
         _hasFocus = false;
 
 
-        if (Application.Navigation is { })
-        {
-            View? appFocused = Application.Navigation.GetFocused ();
-
-            if (appFocused is { } || appFocused == this)
-            {
-                Application.Navigation.SetFocused (newFocusedView ?? superViewOrParent);
-            }
-        }
-
-        NotifyFocusChanged (HasFocus, this, newFocusedView);
+        RaiseFocusChanged (HasFocus, this, newFocusedView);
 
 
         if (_hasFocus)
         if (_hasFocus)
         {
         {
@@ -719,8 +850,13 @@ public partial class View // Focus and cross-view navigation management (TabStop
         SetNeedsDisplay ();
         SetNeedsDisplay ();
     }
     }
 
 
-    private void NotifyFocusChanged (bool newHasFocus, View? previousFocusedView, View? focusedVew)
+    private void RaiseFocusChanged (bool newHasFocus, View? previousFocusedView, View? focusedVew)
     {
     {
+        if (newHasFocus && focusedVew?.Focused is null)
+        {
+            Application.Navigation?.SetFocused (focusedVew);
+        }
+
         // Call the virtual method
         // Call the virtual method
         OnHasFocusChanged (newHasFocus, previousFocusedView, focusedVew);
         OnHasFocusChanged (newHasFocus, previousFocusedView, focusedVew);
 
 
@@ -756,7 +892,8 @@ public partial class View // Focus and cross-view navigation management (TabStop
     #region Tab/Focus Handling
     #region Tab/Focus Handling
 
 
     /// <summary>
     /// <summary>
-    ///     Gets the subviews and Adornments of this view that are scoped to the specified behavior and direction. If behavior is null, all focusable subviews and
+    ///     Gets the subviews and Adornments of this view that are scoped to the specified behavior and direction. If behavior
+    ///     is null, all focusable subviews and
     ///     Adornments are returned.
     ///     Adornments are returned.
     /// </summary>
     /// </summary>
     /// <param name="direction"></param>
     /// <param name="direction"></param>
@@ -775,7 +912,6 @@ public partial class View // Focus and cross-view navigation management (TabStop
             filteredSubviews = _subviews?.Where (v => v is { CanFocus: true, Visible: true, Enabled: true });
             filteredSubviews = _subviews?.Where (v => v is { CanFocus: true, Visible: true, Enabled: true });
         }
         }
 
 
-
         // How about in Adornments? 
         // How about in Adornments? 
         if (Padding is { CanFocus: true, Visible: true, Enabled: true } && Padding.TabStop == behavior)
         if (Padding is { CanFocus: true, Visible: true, Enabled: true } && Padding.TabStop == behavior)
         {
         {
@@ -806,11 +942,14 @@ public partial class View // Focus and cross-view navigation management (TabStop
     ///     Gets or sets the behavior of <see cref="AdvanceFocus"/> for keyboard navigation.
     ///     Gets or sets the behavior of <see cref="AdvanceFocus"/> for keyboard navigation.
     /// </summary>
     /// </summary>
     /// <remarks>
     /// <remarks>
-    /// <remarks>
+    ///     <remarks>
+    ///         <para>
+    ///             See the View Navigation Deep Dive for more information:
+    ///             <see href="https://gui-cs.github.io/Terminal.GuiV2Docs/docs/navigation.html"/>
+    ///         </para>
+    ///     </remarks>
+    ///     ///
     ///     <para>
     ///     <para>
-    ///         See the View Navigation Deep Dive for more information: <see href="https://gui-cs.github.io/Terminal.GuiV2Docs/docs/navigation.html"/>
-    ///     </para>
-    /// </remarks>    ///     <para>
     ///         If <see langword="null"/> the tab stop has not been set and setting <see cref="CanFocus"/> to true will set it
     ///         If <see langword="null"/> the tab stop has not been set and setting <see cref="CanFocus"/> to true will set it
     ///         to
     ///         to
     ///         <see cref="TabBehavior.TabStop"/>.
     ///         <see cref="TabBehavior.TabStop"/>.

+ 5 - 5
Terminal.Gui/Views/Bar.cs

@@ -45,27 +45,27 @@ public class Bar : View, IOrientation, IDesignable
         }
         }
     }
     }
 
 
-    private void OnMouseEvent (object? sender, MouseEventEventArgs e)
+    private void OnMouseEvent (object? sender, MouseEventArgs e)
     {
     {
         NavigationDirection direction = NavigationDirection.Backward;
         NavigationDirection direction = NavigationDirection.Backward;
 
 
-        if (e.MouseEvent.Flags == MouseFlags.WheeledDown)
+        if (e.Flags == MouseFlags.WheeledDown)
         {
         {
             e.Handled = true;
             e.Handled = true;
         }
         }
 
 
-        if (e.MouseEvent.Flags == MouseFlags.WheeledUp)
+        if (e.Flags == MouseFlags.WheeledUp)
         {
         {
             direction = NavigationDirection.Forward;
             direction = NavigationDirection.Forward;
             e.Handled = true;
             e.Handled = true;
         }
         }
 
 
-        if (e.MouseEvent.Flags == MouseFlags.WheeledRight)
+        if (e.Flags == MouseFlags.WheeledRight)
         {
         {
             e.Handled = true;
             e.Handled = true;
         }
         }
 
 
-        if (e.MouseEvent.Flags == MouseFlags.WheeledLeft)
+        if (e.Flags == MouseFlags.WheeledLeft)
         {
         {
             direction = NavigationDirection.Forward;
             direction = NavigationDirection.Forward;
             e.Handled = true;
             e.Handled = true;

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

@@ -125,7 +125,7 @@ public class Button : View, IDesignable
         }
         }
     }
     }
 
 
-    private void Button_MouseClick (object sender, MouseEventEventArgs e)
+    private void Button_MouseClick (object sender, MouseEventArgs e)
     {
     {
         if (e.Handled)
         if (e.Handled)
         {
         {

+ 2 - 3
Terminal.Gui/Views/ColorBar.cs

@@ -110,7 +110,7 @@ internal abstract class ColorBar : View, IColorBar
     public event EventHandler<EventArgs<int>>? ValueChanged;
     public event EventHandler<EventArgs<int>>? ValueChanged;
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    protected internal override bool OnMouseEvent (MouseEvent mouseEvent)
+    protected override bool OnMouseEvent (MouseEventArgs mouseEvent)
     {
     {
         if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed))
         if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed))
         {
         {
@@ -123,10 +123,9 @@ internal abstract class ColorBar : View, IColorBar
             mouseEvent.Handled = true;
             mouseEvent.Handled = true;
             SetFocus ();
             SetFocus ();
 
 
-            return true;
         }
         }
 
 
-        return base.OnMouseEvent (mouseEvent);
+        return mouseEvent.Handled;
     }
     }
 
 
     /// <summary>
     /// <summary>

+ 2 - 2
Terminal.Gui/Views/ColorPicker.16.cs

@@ -181,11 +181,11 @@ public class ColorPicker16 : View
 
 
     // TODO: Decouple Cursor from SelectedColor so that mouse press-and-hold can show the color under the cursor.
     // TODO: Decouple Cursor from SelectedColor so that mouse press-and-hold can show the color under the cursor.
 
 
-    private void ColorPicker_MouseClick (object sender, MouseEventEventArgs me)
+    private void ColorPicker_MouseClick (object sender, MouseEventArgs me)
     {
     {
         // if (CanFocus)
         // if (CanFocus)
         {
         {
-            Cursor = new (me.MouseEvent.Position.X / _boxWidth, me.MouseEvent.Position.Y / _boxHeight);
+            Cursor = new (me.Position.X / _boxWidth, me.Position.Y / _boxHeight);
             SetFocus ();
             SetFocus ();
             me.Handled = true;
             me.Handled = true;
         }
         }

+ 6 - 5
Terminal.Gui/Views/ComboBox.cs

@@ -253,7 +253,7 @@ public class ComboBox : View, IDesignable
     public event EventHandler Expanded;
     public event EventHandler Expanded;
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    protected internal override bool OnMouseEvent (MouseEvent me)
+    protected override bool OnMouseEvent (MouseEventArgs me)
     {
     {
         if (me.Position.X == Viewport.Right - 1
         if (me.Position.X == Viewport.Right - 1
             && me.Position.Y == Viewport.Top
             && me.Position.Y == Viewport.Top
@@ -836,14 +836,15 @@ public class ComboBox : View, IDesignable
             set => _hideDropdownListOnClick = WantContinuousButtonPressed = value;
             set => _hideDropdownListOnClick = WantContinuousButtonPressed = value;
         }
         }
 
 
-        // BUGBUG: OnMouseEvent is internal!
-        protected internal override bool OnMouseEvent (MouseEvent me)
+        protected override bool OnMouseEvent (MouseEventArgs me)
         {
         {
-            var res = false;
             bool isMousePositionValid = IsMousePositionValid (me);
             bool isMousePositionValid = IsMousePositionValid (me);
 
 
+            var res = false;
+
             if (isMousePositionValid)
             if (isMousePositionValid)
             {
             {
+                // We're derived from ListView and it overrides OnMouseEvent, so we need to call it
                 res = base.OnMouseEvent (me);
                 res = base.OnMouseEvent (me);
             }
             }
 
 
@@ -984,7 +985,7 @@ public class ComboBox : View, IDesignable
             return res;
             return res;
         }
         }
 
 
-        private bool IsMousePositionValid (MouseEvent me)
+        private bool IsMousePositionValid (MouseEventArgs me)
         {
         {
             if (me.Position.X >= 0 && me.Position.X < Frame.Width && me.Position.Y >= 0 && me.Position.Y < Frame.Height)
             if (me.Position.X >= 0 && me.Position.X < Frame.Width && me.Position.Y >= 0 && me.Position.Y < Frame.Height)
             {
             {

+ 9 - 6
Terminal.Gui/Views/DateField.cs

@@ -114,16 +114,19 @@ public class DateField : TextField
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    protected internal override bool OnMouseEvent  (MouseEvent ev)
+    protected override bool OnMouseEvent  (MouseEventArgs ev)
     {
     {
-        bool result = base.OnMouseEvent (ev);
+        if (base.OnMouseEvent (ev) || ev.Handled)
+        {
+            return true;
+        }
 
 
-        if (result && SelectedLength == 0 && ev.Flags.HasFlag (MouseFlags.Button1Pressed))
+        if (SelectedLength == 0 && ev.Flags.HasFlag (MouseFlags.Button1Pressed))
         {
         {
             AdjCursorPosition (ev.Position.X);
             AdjCursorPosition (ev.Position.X);
         }
         }
 
 
-        return result;
+        return ev.Handled;
     }
     }
 
 
     /// <summary>Event firing method for the <see cref="DateChanged"/> event.</summary>
     /// <summary>Event firing method for the <see cref="DateChanged"/> event.</summary>
@@ -131,7 +134,7 @@ public class DateField : TextField
     public virtual void OnDateChanged (DateTimeEventArgs<DateTime> args) { DateChanged?.Invoke (this, args); }
     public virtual void OnDateChanged (DateTimeEventArgs<DateTime> args) { DateChanged?.Invoke (this, args); }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public override bool OnProcessKeyDown (Key a)
+    protected override bool OnKeyDownNotHandled (Key a)
     {
     {
         // Ignore non-numeric characters.
         // Ignore non-numeric characters.
         if (a >= Key.D0 && a <= Key.D9)
         if (a >= Key.D0 && a <= Key.D9)
@@ -169,7 +172,7 @@ public class DateField : TextField
             CursorPosition = newPoint;
             CursorPosition = newPoint;
         }
         }
 
 
-        while (Text [CursorPosition].ToString () == _separator)
+        while (CursorPosition < Text.GetColumns () - 1 && Text [CursorPosition].ToString () == _separator)
         {
         {
             if (increment)
             if (increment)
             {
             {

+ 13 - 13
Terminal.Gui/Views/FileDialog.cs

@@ -233,7 +233,7 @@ public class FileDialog : Dialog
         _tbPath.TextChanged += (s, e) => PathChanged ();
         _tbPath.TextChanged += (s, e) => PathChanged ();
 
 
         _tableView.CellActivated += CellActivate;
         _tableView.CellActivated += CellActivate;
-        _tableView.KeyUp += (s, k) => k.Handled = TableView_KeyUp (k);
+        _tableView.KeyDown += (s, k) => k.Handled = TableView_KeyUp (k);
         _tableView.SelectedCellChanged += TableView_SelectedCellChanged;
         _tableView.SelectedCellChanged += TableView_SelectedCellChanged;
 
 
         _tableView.KeyBindings.ReplaceCommands (Key.Home, Command.Start);
         _tableView.KeyBindings.ReplaceCommands (Key.Home, Command.Start);
@@ -670,11 +670,11 @@ public class FileDialog : Dialog
         FinishAccept ();
         FinishAccept ();
     }
     }
 
 
-    private void AcceptIf (Key keyEvent, KeyCode isKey)
+    private void AcceptIf (Key key, KeyCode isKey)
     {
     {
-        if (!keyEvent.Handled && keyEvent.KeyCode == isKey)
+        if (!key.Handled && key.KeyCode == isKey)
         {
         {
-            keyEvent.Handled = true;
+            key.Handled = true;
 
 
             // User hit Enter in text box so probably wants the
             // User hit Enter in text box so probably wants the
             // contents of the text box as their selection not
             // contents of the text box as their selection not
@@ -1007,18 +1007,18 @@ public class FileDialog : Dialog
         }
         }
     }
     }
 
 
-    private void OnTableViewMouseClick (object sender, MouseEventEventArgs e)
+    private void OnTableViewMouseClick (object sender, MouseEventArgs e)
     {
     {
-        Point? clickedCell = _tableView.ScreenToCell (e.MouseEvent.Position.X, e.MouseEvent.Position.Y, out int? clickedCol);
+        Point? clickedCell = _tableView.ScreenToCell (e.Position.X, e.Position.Y, out int? clickedCol);
 
 
         if (clickedCol is { })
         if (clickedCol is { })
         {
         {
-            if (e.MouseEvent.Flags.HasFlag (MouseFlags.Button1Clicked))
+            if (e.Flags.HasFlag (MouseFlags.Button1Clicked))
             {
             {
                 // left click in a header
                 // left click in a header
                 SortColumn (clickedCol.Value);
                 SortColumn (clickedCol.Value);
             }
             }
-            else if (e.MouseEvent.Flags.HasFlag (MouseFlags.Button3Clicked))
+            else if (e.Flags.HasFlag (MouseFlags.Button3Clicked))
             {
             {
                 // right click in a header
                 // right click in a header
                 ShowHeaderContextMenu (clickedCol.Value, e);
                 ShowHeaderContextMenu (clickedCol.Value, e);
@@ -1026,7 +1026,7 @@ public class FileDialog : Dialog
         }
         }
         else
         else
         {
         {
-            if (clickedCell is { } && e.MouseEvent.Flags.HasFlag (MouseFlags.Button3Clicked))
+            if (clickedCell is { } && e.Flags.HasFlag (MouseFlags.Button3Clicked))
             {
             {
                 // right click in rest of table
                 // right click in rest of table
                 ShowCellContextMenu (clickedCell, e);
                 ShowCellContextMenu (clickedCell, e);
@@ -1198,7 +1198,7 @@ public class FileDialog : Dialog
 
 
     private FileSystemInfoStats RowToStats (int rowIndex) { return State?.Children [rowIndex]; }
     private FileSystemInfoStats RowToStats (int rowIndex) { return State?.Children [rowIndex]; }
 
 
-    private void ShowCellContextMenu (Point? clickedCell, MouseEventEventArgs e)
+    private void ShowCellContextMenu (Point? clickedCell, MouseEventArgs e)
     {
     {
         if (clickedCell is null)
         if (clickedCell is null)
         {
         {
@@ -1207,7 +1207,7 @@ public class FileDialog : Dialog
 
 
         var contextMenu = new ContextMenu
         var contextMenu = new ContextMenu
         {
         {
-            Position = new Point (e.MouseEvent.Position.X + 1, e.MouseEvent.Position.Y + 1)
+            Position = new Point (e.Position.X + 1, e.Position.Y + 1)
         };
         };
 
 
         var menuItems = new MenuBarItem (
         var menuItems = new MenuBarItem (
@@ -1222,13 +1222,13 @@ public class FileDialog : Dialog
         contextMenu.Show (menuItems);
         contextMenu.Show (menuItems);
     }
     }
 
 
-    private void ShowHeaderContextMenu (int clickedCol, MouseEventEventArgs e)
+    private void ShowHeaderContextMenu (int clickedCol, MouseEventArgs e)
     {
     {
         string sort = GetProposedNewSortOrder (clickedCol, out bool isAsc);
         string sort = GetProposedNewSortOrder (clickedCol, out bool isAsc);
 
 
         var contextMenu = new ContextMenu
         var contextMenu = new ContextMenu
         {
         {
-            Position = new Point (e.MouseEvent.Position.X + 1, e.MouseEvent.Position.Y + 1)
+            Position = new Point (e.Position.X + 1, e.Position.Y + 1)
         };
         };
 
 
         var menuItems = new MenuBarItem (
         var menuItems = new MenuBarItem (

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

@@ -22,7 +22,7 @@ public class FrameView : View
         MouseClick += FrameView_MouseClick;
         MouseClick += FrameView_MouseClick;
     }
     }
 
 
-    private void FrameView_MouseClick (object sender, MouseEventEventArgs e)
+    private void FrameView_MouseClick (object sender, MouseEventArgs e)
     {
     {
         // base sets focus on HotKey
         // base sets focus on HotKey
         e.Handled = InvokeCommand (Command.HotKey, ctx: new (Command.HotKey, key: null, data: this)) == true;
         e.Handled = InvokeCommand (Command.HotKey, ctx: new (Command.HotKey, key: null, data: this)) == true;

File diff suppressed because it is too large
+ 394 - 237
Terminal.Gui/Views/HexView.cs


+ 15 - 15
Terminal.Gui/Views/HexViewEventArgs.cs

@@ -12,41 +12,41 @@ namespace Terminal.Gui;
 public class HexViewEventArgs : EventArgs
 public class HexViewEventArgs : EventArgs
 {
 {
     /// <summary>Initializes a new instance of <see cref="HexViewEventArgs"/></summary>
     /// <summary>Initializes a new instance of <see cref="HexViewEventArgs"/></summary>
-    /// <param name="pos">The character position.</param>
-    /// <param name="cursor">The cursor position.</param>
+    /// <param name="address">The byte position in the steam.</param>
+    /// <param name="position">The edit position.</param>
     /// <param name="lineLength">Line bytes length.</param>
     /// <param name="lineLength">Line bytes length.</param>
-    public HexViewEventArgs (long pos, Point cursor, int lineLength)
+    public HexViewEventArgs (long address, Point position, int lineLength)
     {
     {
-        Position = pos;
-        CursorPosition = cursor;
+        Address = address;
+        Position = position;
         BytesPerLine = lineLength;
         BytesPerLine = lineLength;
     }
     }
 
 
     /// <summary>The bytes length per line.</summary>
     /// <summary>The bytes length per line.</summary>
     public int BytesPerLine { get; private set; }
     public int BytesPerLine { get; private set; }
 
 
-    /// <summary>Gets the current cursor position starting at one for both, line and column.</summary>
-    public Point CursorPosition { get; private set; }
+    /// <summary>Gets the current edit position.</summary>
+    public Point Position { get; private set; }
 
 
-    /// <summary>Gets the current character position starting at one, related to the <see cref="Stream"/>.</summary>
-    public long Position { get; private set; }
+    /// <summary>Gets the byte position in the <see cref="Stream"/>.</summary>
+    public long Address { get; private set; }
 }
 }
 
 
 /// <summary>Defines the event arguments for <see cref="HexView.Edited"/> event.</summary>
 /// <summary>Defines the event arguments for <see cref="HexView.Edited"/> event.</summary>
 public class HexViewEditEventArgs : EventArgs
 public class HexViewEditEventArgs : EventArgs
 {
 {
     /// <summary>Creates a new instance of the <see cref="HexViewEditEventArgs"/> class.</summary>
     /// <summary>Creates a new instance of the <see cref="HexViewEditEventArgs"/> class.</summary>
-    /// <param name="position"></param>
+    /// <param name="address"></param>
     /// <param name="newValue"></param>
     /// <param name="newValue"></param>
-    public HexViewEditEventArgs (long position, byte newValue)
+    public HexViewEditEventArgs (long address, byte newValue)
     {
     {
-        Position = position;
+        Address = address;
         NewValue = newValue;
         NewValue = newValue;
     }
     }
 
 
-    /// <summary>Gets the new value for that <see cref="Position"/>.</summary>
+    /// <summary>Gets the new value for that <see cref="Address"/>.</summary>
     public byte NewValue { get; }
     public byte NewValue { get; }
 
 
-    /// <summary>Gets the location of the edit.</summary>
-    public long Position { get; }
+    /// <summary>Gets the address of the edit in the stream.</summary>
+    public long Address { get; }
 }
 }

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

@@ -32,7 +32,7 @@ public class Label : View, IDesignable
     }
     }
 
 
     // TODO: base raises Select, but we want to raise HotKey. This can be simplified?
     // TODO: base raises Select, but we want to raise HotKey. This can be simplified?
-    private void Label_MouseClick (object sender, MouseEventEventArgs e)
+    private void Label_MouseClick (object sender, MouseEventArgs e)
     {
     {
         if (!CanFocus)
         if (!CanFocus)
         {
         {

+ 56 - 4
Terminal.Gui/Views/ListView.cs

@@ -147,7 +147,7 @@ public class ListView : View, IDesignable
 
 
                                         if (OnOpenSelectedItem ())
                                         if (OnOpenSelectedItem ())
                                         {
                                         {
-                                                return true;
+                                            return true;
                                         }
                                         }
 
 
                                         return false;
                                         return false;
@@ -189,6 +189,7 @@ public class ListView : View, IDesignable
                                         return !SetFocus ();
                                         return !SetFocus ();
                                     });
                                     });
 
 
+        AddCommand (Command.SelectAll, (ctx) => MarkAll((bool)ctx.KeyBinding?.Context!));
 
 
         // Default keybindings for all ListViews
         // Default keybindings for all ListViews
         KeyBindings.Add (Key.CursorUp, Command.Up);
         KeyBindings.Add (Key.CursorUp, Command.Up);
@@ -205,6 +206,13 @@ public class ListView : View, IDesignable
         KeyBindings.Add (Key.Home, Command.Start);
         KeyBindings.Add (Key.Home, Command.Start);
 
 
         KeyBindings.Add (Key.End, Command.End);
         KeyBindings.Add (Key.End, Command.End);
+
+        // Key.Space is already bound to Command.Select; this gives us select then move down
+        KeyBindings.Add (Key.Space.WithShift, [Command.Select, Command.Down]);
+
+        // Use the form of Add that lets us pass context to the handler
+        KeyBindings.Add (Key.A.WithCtrl, new KeyBinding ([Command.SelectAll], KeyBindingScope.Focused, true));
+        KeyBindings.Add (Key.U.WithCtrl, new KeyBinding ([Command.SelectAll], KeyBindingScope.Focused, false));
     }
     }
 
 
     /// <summary>Gets or sets whether this <see cref="ListView"/> allows items to be marked.</summary>
     /// <summary>Gets or sets whether this <see cref="ListView"/> allows items to be marked.</summary>
@@ -370,6 +378,31 @@ public class ListView : View, IDesignable
         }
         }
     }
     }
 
 
+    /// <summary>
+    ///     If <see cref="AllowsMarking"/> and <see cref="AllowsMultipleSelection"/> are both <see langword="true"/>,
+    ///     marks all items.
+    /// </summary>
+    /// <param name="mark"><see langword="true"/> marks all items; otherwise unmarks all items.</param>
+    /// <returns><see langword="true"/> if marking was successful.</returns>
+    public bool MarkAll (bool mark)
+    {
+        if (!_allowsMarking)
+        {
+            return false;
+        }
+
+        if (AllowsMultipleSelection)
+        {
+            for (var i = 0; i < Source.Count; i++)
+            {
+                Source.SetMark (i, mark);
+            }
+            return true;
+        }
+
+        return false;
+    }
+
     /// <summary>
     /// <summary>
     ///     If <see cref="AllowsMarking"/> and <see cref="AllowsMultipleSelection"/> are both <see langword="true"/>,
     ///     If <see cref="AllowsMarking"/> and <see cref="AllowsMultipleSelection"/> are both <see langword="true"/>,
     ///     unmarks all marked items other than <see cref="SelectedItem"/>.
     ///     unmarks all marked items other than <see cref="SelectedItem"/>.
@@ -439,7 +472,7 @@ public class ListView : View, IDesignable
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    protected internal override bool OnMouseEvent (MouseEvent me)
+    protected override bool OnMouseEvent (MouseEventArgs me)
     {
     {
         if (!me.Flags.HasFlag (MouseFlags.Button1Clicked)
         if (!me.Flags.HasFlag (MouseFlags.Button1Clicked)
             && !me.Flags.HasFlag (MouseFlags.Button1DoubleClicked)
             && !me.Flags.HasFlag (MouseFlags.Button1DoubleClicked)
@@ -784,7 +817,6 @@ public class ListView : View, IDesignable
         }
         }
     }
     }
 
 
-    // TODO: This should be cancelable
     /// <summary>Invokes the <see cref="OpenSelectedItem"/> event if it is defined.</summary>
     /// <summary>Invokes the <see cref="OpenSelectedItem"/> event if it is defined.</summary>
     /// <returns><see langword="true"/> if the <see cref="OpenSelectedItem"/> event was fired.</returns>
     /// <returns><see langword="true"/> if the <see cref="OpenSelectedItem"/> event was fired.</returns>
     public bool OnOpenSelectedItem ()
     public bool OnOpenSelectedItem ()
@@ -803,8 +835,28 @@ public class ListView : View, IDesignable
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public override bool OnProcessKeyDown (Key a)
+    protected override bool OnKeyDown (Key a)
     {
     {
+        // If marking is enabled and the user presses the space key don't let CollectionNavigator
+        // at it
+        if (AllowsMarking)
+        {
+            var keys = KeyBindings.GetKeysFromCommands (Command.Select);
+
+            if (keys.Contains (a))
+            {
+                return false;
+            }
+
+            keys = KeyBindings.GetKeysFromCommands ([Command.Select, Command.Down]);
+
+            if (keys.Contains (a))
+            {
+                return false;
+            }
+
+        }
+
         // Enable user to find & select an item by typing text
         // Enable user to find & select an item by typing text
         if (CollectionNavigatorBase.IsCompatibleKey (a))
         if (CollectionNavigatorBase.IsCompatibleKey (a))
         {
         {

+ 9 - 15
Terminal.Gui/Views/Menu/Menu.cs

@@ -1,5 +1,7 @@
 #nullable enable
 #nullable enable
 
 
+using static System.Formats.Asn1.AsnWriter;
+
 namespace Terminal.Gui;
 namespace Terminal.Gui;
 
 
 /// <summary>
 /// <summary>
@@ -305,19 +307,11 @@ internal sealed class Menu : View
         return true;
         return true;
     }
     }
 
 
-    /// <inheritdoc/>
-    public override bool? OnInvokingKeyBindings (Key keyEvent, KeyBindingScope scope)
+    /// <inheritdoc />
+    protected override bool OnKeyDownNotHandled (Key keyEvent)
     {
     {
-        bool? handled = base.OnInvokingKeyBindings (keyEvent, scope);
-
-        if (handled is { } && (bool)handled)
-        {
-            return true;
-        }
-
-        // TODO: Determine if there's a cleaner way to handle this.
-        // This supports the case where the menu bar is a context menu
-        return _host.OnInvokingKeyBindings (keyEvent, scope);
+        // We didn't handle the key, pass it on to host
+        return _host.InvokeCommandsBoundToKey (keyEvent) == true;
     }
     }
 
 
     private void Current_TerminalResized (object? sender, SizeChangedEventArgs e)
     private void Current_TerminalResized (object? sender, SizeChangedEventArgs e)
@@ -343,7 +337,7 @@ internal sealed class Menu : View
         }
         }
     }
     }
 
 
-    private void Application_RootMouseEvent (object? sender, MouseEvent a)
+    private void Application_RootMouseEvent (object? sender, MouseEventArgs a)
     {
     {
         if (a.View is { } and (MenuBar or not Menu))
         if (a.View is { } and (MenuBar or not Menu))
         {
         {
@@ -359,7 +353,7 @@ internal sealed class Menu : View
 
 
         Point boundsPoint = view.ScreenToViewport (new (a.Position.X, a.Position.Y));
         Point boundsPoint = view.ScreenToViewport (new (a.Position.X, a.Position.Y));
 
 
-        var me = new MouseEvent
+        var me = new MouseEventArgs
         {
         {
             Position = boundsPoint,
             Position = boundsPoint,
             Flags = a.Flags,
             Flags = a.Flags,
@@ -814,7 +808,7 @@ internal sealed class Menu : View
         _host.SetNeedsDisplay ();
         _host.SetNeedsDisplay ();
     }
     }
 
 
-    protected internal override bool OnMouseEvent (MouseEvent me)
+    protected override bool OnMouseEvent (MouseEventArgs me)
     {
     {
         if (!_host._handled && !_host.HandleGrabView (me, this))
         if (!_host._handled && !_host.HandleGrabView (me, this))
         {
         {

+ 4 - 4
Terminal.Gui/Views/Menu/MenuBar.cs

@@ -137,7 +137,7 @@ public class MenuBar : View, IDesignable
                                                   });
                                                   });
         AddCommand (Command.Select, ctx =>
         AddCommand (Command.Select, ctx =>
                                     {
                                     {
-                                        if (ctx.Data is MouseEvent)
+                                        if (ctx.Data is MouseEventArgs)
                                         {
                                         {
                                             // HACK: Work around the fact that View.MouseClick always invokes Select
                                             // HACK: Work around the fact that View.MouseClick always invokes Select
                                             return false;
                                             return false;
@@ -1400,7 +1400,7 @@ public class MenuBar : View, IDesignable
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    protected internal override bool OnMouseEvent (MouseEvent me)
+    protected override bool OnMouseEvent (MouseEventArgs me)
     {
     {
         if (!_handled && !HandleGrabView (me, this))
         if (!_handled && !HandleGrabView (me, this))
         {
         {
@@ -1513,7 +1513,7 @@ public class MenuBar : View, IDesignable
     internal bool _isContextMenuLoading;
     internal bool _isContextMenuLoading;
     private MenuBarItem [] _menus = [];
     private MenuBarItem [] _menus = [];
 
 
-    internal bool HandleGrabView (MouseEvent me, View current)
+    internal bool HandleGrabView (MouseEventArgs me, View current)
     {
     {
         if (Application.MouseGrabView is { })
         if (Application.MouseGrabView is { })
         {
         {
@@ -1541,7 +1541,7 @@ public class MenuBar : View, IDesignable
                     Application.UngrabMouse ();
                     Application.UngrabMouse ();
                     View v = me.View;
                     View v = me.View;
                     Application.GrabMouse (v);
                     Application.GrabMouse (v);
-                    MouseEvent nme;
+                    MouseEventArgs nme;
 
 
                     if (me.Position.Y > -1)
                     if (me.Position.Y > -1)
                     {
                     {

+ 5 - 5
Terminal.Gui/Views/RadioGroup.cs

@@ -220,12 +220,12 @@ public class RadioGroup : View, IDesignable, IOrientation
     /// </remarks>
     /// </remarks>
     public bool DoubleClickAccepts { get; set; } = true;
     public bool DoubleClickAccepts { get; set; } = true;
 
 
-    private void RadioGroup_MouseClick (object? sender, MouseEventEventArgs e)
+    private void RadioGroup_MouseClick (object? sender, MouseEventArgs e)
     {
     {
-        if (e.MouseEvent.Flags.HasFlag (MouseFlags.Button1Clicked))
+        if (e.Flags.HasFlag (MouseFlags.Button1Clicked))
         {
         {
-            int viewportX = e.MouseEvent.Position.X;
-            int viewportY = e.MouseEvent.Position.Y;
+            int viewportX = e.Position.X;
+            int viewportY = e.Position.Y;
 
 
             int pos = Orientation == Orientation.Horizontal ? viewportX : viewportY;
             int pos = Orientation == Orientation.Horizontal ? viewportX : viewportY;
 
 
@@ -249,7 +249,7 @@ public class RadioGroup : View, IDesignable, IOrientation
             return;
             return;
         }
         }
 
 
-        if (DoubleClickAccepts && e.MouseEvent.Flags.HasFlag (MouseFlags.Button1DoubleClicked))
+        if (DoubleClickAccepts && e.Flags.HasFlag (MouseFlags.Button1DoubleClicked))
         {
         {
             // NOTE: Drivers ALWAYS generate a Button1Clicked event before Button1DoubleClicked
             // NOTE: Drivers ALWAYS generate a Button1Clicked event before Button1DoubleClicked
             // NOTE: So, we've already selected an item.
             // NOTE: So, we've already selected an item.

+ 8 - 8
Terminal.Gui/Views/ScrollBarView.cs

@@ -270,7 +270,7 @@ public class ScrollBarView : View
     public event EventHandler ChangedPosition;
     public event EventHandler ChangedPosition;
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    protected internal override bool OnMouseEvent (MouseEvent mouseEvent)
+    protected override bool OnMouseEvent (MouseEventArgs mouseEvent)
     {
     {
         if (mouseEvent.Flags != MouseFlags.Button1Pressed
         if (mouseEvent.Flags != MouseFlags.Button1Pressed
             && mouseEvent.Flags != MouseFlags.Button1DoubleClicked
             && mouseEvent.Flags != MouseFlags.Button1DoubleClicked
@@ -777,16 +777,16 @@ public class ScrollBarView : View
     //	}
     //	}
     //}
     //}
 
 
-    private void ContentBottomRightCorner_MouseClick (object sender, MouseEventEventArgs me)
+    private void ContentBottomRightCorner_MouseClick (object sender, MouseEventArgs me)
     {
     {
-        if (me.MouseEvent.Flags == MouseFlags.WheeledDown
-            || me.MouseEvent.Flags == MouseFlags.WheeledUp
-            || me.MouseEvent.Flags == MouseFlags.WheeledRight
-            || me.MouseEvent.Flags == MouseFlags.WheeledLeft)
+        if (me.Flags == MouseFlags.WheeledDown
+            || me.Flags == MouseFlags.WheeledUp
+            || me.Flags == MouseFlags.WheeledRight
+            || me.Flags == MouseFlags.WheeledLeft)
         {
         {
-            NewMouseEvent (me.MouseEvent);
+            NewMouseEvent (me);
         }
         }
-        else if (me.MouseEvent.Flags == MouseFlags.Button1Clicked)
+        else if (me.Flags == MouseFlags.Button1Clicked)
         {
         {
             Host.SetFocus ();
             Host.SetFocus ();
         }
         }

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

@@ -388,14 +388,14 @@ public class ScrollView : View
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public override bool OnKeyDown (Key a)
+    protected override bool OnKeyDown (Key a)
     {
     {
         if (base.OnKeyDown (a))
         if (base.OnKeyDown (a))
         {
         {
             return true;
             return true;
         }
         }
 
 
-        bool? result = InvokeKeyBindings (a, KeyBindingScope.HotKey | KeyBindingScope.Focused);
+        bool? result = InvokeCommands (a, KeyBindingScope.HotKey | KeyBindingScope.Focused);
 
 
         if (result is { })
         if (result is { })
         {
         {
@@ -406,7 +406,7 @@ public class ScrollView : View
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    protected internal override bool OnMouseEvent (MouseEvent me)
+    protected override bool OnMouseEvent (MouseEventArgs me)
     {
     {
         if (!Enabled)
         if (!Enabled)
         {
         {
@@ -416,19 +416,19 @@ public class ScrollView : View
 
 
         if (me.Flags == MouseFlags.WheeledDown && ShowVerticalScrollIndicator)
         if (me.Flags == MouseFlags.WheeledDown && ShowVerticalScrollIndicator)
         {
         {
-            ScrollDown (1);
+            return ScrollDown (1);
         }
         }
         else if (me.Flags == MouseFlags.WheeledUp && ShowVerticalScrollIndicator)
         else if (me.Flags == MouseFlags.WheeledUp && ShowVerticalScrollIndicator)
         {
         {
-            ScrollUp (1);
+            return ScrollUp (1);
         }
         }
         else if (me.Flags == MouseFlags.WheeledRight && _showHorizontalScrollIndicator)
         else if (me.Flags == MouseFlags.WheeledRight && _showHorizontalScrollIndicator)
         {
         {
-            ScrollRight (1);
+            return ScrollRight (1);
         }
         }
         else if (me.Flags == MouseFlags.WheeledLeft && ShowVerticalScrollIndicator)
         else if (me.Flags == MouseFlags.WheeledLeft && ShowVerticalScrollIndicator)
         {
         {
-            ScrollLeft (1);
+            return ScrollLeft (1);
         }
         }
         else if (me.Position.X == _vertical.Frame.X && ShowVerticalScrollIndicator)
         else if (me.Position.X == _vertical.Frame.X && ShowVerticalScrollIndicator)
         {
         {
@@ -443,7 +443,7 @@ public class ScrollView : View
             Application.UngrabMouse ();
             Application.UngrabMouse ();
         }
         }
 
 
-        return base.OnMouseEvent (me);
+        return me.Handled;
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>

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

@@ -58,7 +58,7 @@ public class Shortcut : View, IOrientation, IDesignable
     ///     </para>
     ///     </para>
     /// </remarks>
     /// </remarks>
     /// <param name="targetView">
     /// <param name="targetView">
-    ///     The View that <paramref name="command"/> will be invoked when user does something that causes the Shortcut's Accept
+    ///     The View that <paramref name="command"/> will be invoked on when user does something that causes the Shortcut's Accept
     ///     event to be raised.
     ///     event to be raised.
     /// </param>
     /// </param>
     /// <param name="command">
     /// <param name="command">

+ 2 - 4
Terminal.Gui/Views/Slider.cs

@@ -1282,7 +1282,7 @@ public class Slider<T> : View, IOrientation
     private Point? _moveRenderPosition;
     private Point? _moveRenderPosition;
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    protected internal override bool OnMouseEvent (MouseEvent mouseEvent)
+    protected override bool OnMouseEvent (MouseEventArgs mouseEvent)
     {
     {
         // Note(jmperricone): Maybe we click to focus the cursor, and on next click we set the option.
         // Note(jmperricone): Maybe we click to focus the cursor, and on next click we set the option.
         //                    That will make OptionFocused Event more relevant.
         //                    That will make OptionFocused Event more relevant.
@@ -1381,11 +1381,9 @@ public class Slider<T> : View, IOrientation
 
 
             mouseEvent.Handled = true;
             mouseEvent.Handled = true;
 
 
-            // BUGBUG: OnMouseClick is/should be internal. 
-            return OnMouseClick (new (mouseEvent));
         }
         }
 
 
-        return false;
+        return mouseEvent.Handled;
 
 
         Point ClampMovePosition (Point position)
         Point ClampMovePosition (Point position)
         {
         {

+ 3 - 3
Terminal.Gui/Views/TabMouseEventArgs.cs

@@ -6,17 +6,17 @@ public class TabMouseEventArgs : EventArgs
     /// <summary>Creates a new instance of the <see cref="TabMouseEventArgs"/> class.</summary>
     /// <summary>Creates a new instance of the <see cref="TabMouseEventArgs"/> class.</summary>
     /// <param name="tab"><see cref="Tab"/> that the mouse was over when the event occurred.</param>
     /// <param name="tab"><see cref="Tab"/> that the mouse was over when the event occurred.</param>
     /// <param name="mouseEvent">The mouse activity being reported</param>
     /// <param name="mouseEvent">The mouse activity being reported</param>
-    public TabMouseEventArgs (Tab tab, MouseEvent mouseEvent)
+    public TabMouseEventArgs (Tab tab, MouseEventArgs mouseEvent)
     {
     {
         Tab = tab;
         Tab = tab;
         MouseEvent = mouseEvent;
         MouseEvent = mouseEvent;
     }
     }
 
 
     /// <summary>
     /// <summary>
-    ///     Gets the actual mouse event.  Use <see cref="MouseEvent.Handled"/> to cancel this event and perform custom
+    ///     Gets the actual mouse event.  Use <see cref="MouseEventArgs.Handled"/> to cancel this event and perform custom
     ///     behavior (e.g. show a context menu).
     ///     behavior (e.g. show a context menu).
     /// </summary>
     /// </summary>
-    public MouseEvent MouseEvent { get; }
+    public MouseEventArgs MouseEvent { get; }
 
 
     /// <summary>Gets the <see cref="Tab"/> (if any) that the mouse was over when the <see cref="MouseEvent"/> occurred.</summary>
     /// <summary>Gets the <see cref="Tab"/> (if any) that the mouse was over when the <see cref="MouseEvent"/> occurred.</summary>
     /// <remarks>This will be null if the click is after last tab or before first.</remarks>
     /// <remarks>This will be null if the click is after last tab or before first.</remarks>

+ 6 - 14
Terminal.Gui/Views/TabView.cs

@@ -508,9 +508,9 @@ public class TabView : View
         return Style.ShowTopLine ? 3 : 2;
         return Style.ShowTopLine ? 3 : 2;
     }
     }
 
 
-    private void Tab_MouseClick (object sender, MouseEventEventArgs e)
+    private void Tab_MouseClick (object sender, MouseEventArgs e)
     {
     {
-        e.Handled = _tabsBar.NewMouseEvent (e.MouseEvent) == true;
+        e.Handled = _tabsBar.NewMouseEvent (e) == true;
     }
     }
 
 
     private void UnSetCurrentTabs ()
     private void UnSetCurrentTabs ()
@@ -569,15 +569,11 @@ public class TabView : View
             Add (_rightScrollIndicator, _leftScrollIndicator);
             Add (_rightScrollIndicator, _leftScrollIndicator);
         }
         }
 
 
-        protected internal override bool OnMouseEvent (MouseEvent me)
+        protected override bool OnMouseEvent (MouseEventArgs me)
         {
         {
             Tab hit = me.View is Tab ? (Tab)me.View : null;
             Tab hit = me.View is Tab ? (Tab)me.View : null;
 
 
-            bool isClick = me.Flags.HasFlag (MouseFlags.Button1Clicked)
-                           || me.Flags.HasFlag (MouseFlags.Button2Clicked)
-                           || me.Flags.HasFlag (MouseFlags.Button3Clicked);
-
-            if (isClick)
+            if (me.IsSingleClicked)
             {
             {
                 _host.OnTabClicked (new TabMouseEventArgs (hit, me));
                 _host.OnTabClicked (new TabMouseEventArgs (hit, me));
 
 
@@ -588,9 +584,7 @@ public class TabView : View
                 }
                 }
             }
             }
 
 
-            if (!me.Flags.HasFlag (MouseFlags.Button1Clicked)
-                && !me.Flags.HasFlag (MouseFlags.Button1DoubleClicked)
-                && !me.Flags.HasFlag (MouseFlags.Button1TripleClicked))
+            if (!me.IsSingleDoubleOrTripleClicked)
             {
             {
                 return false;
                 return false;
             }
             }
@@ -600,9 +594,7 @@ public class TabView : View
                 SetFocus ();
                 SetFocus ();
             }
             }
 
 
-            if (me.Flags.HasFlag (MouseFlags.Button1Clicked)
-                || me.Flags.HasFlag (MouseFlags.Button1DoubleClicked)
-                || me.Flags.HasFlag (MouseFlags.Button1TripleClicked))
+            if (me.IsSingleDoubleOrTripleClicked)
             {
             {
                 var scrollIndicatorHit = 0;
                 var scrollIndicatorHit = 0;
 
 

+ 3 - 3
Terminal.Gui/Views/TableView/CheckBoxTableSourceWrapper.cs

@@ -150,15 +150,15 @@ public abstract class CheckBoxTableSourceWrapperBase : ITableSource
         tableView.SetNeedsDisplay ();
         tableView.SetNeedsDisplay ();
     }
     }
 
 
-    private void TableView_MouseClick (object sender, MouseEventEventArgs e)
+    private void TableView_MouseClick (object sender, MouseEventArgs e)
     {
     {
         // we only care about clicks (not movements)
         // we only care about clicks (not movements)
-        if (!e.MouseEvent.Flags.HasFlag (MouseFlags.Button1Clicked))
+        if (!e.Flags.HasFlag (MouseFlags.Button1Clicked))
         {
         {
             return;
             return;
         }
         }
 
 
-        Point? hit = tableView.ScreenToCell (e.MouseEvent.Position.X, e.MouseEvent.Position.Y, out int? headerIfAny);
+        Point? hit = tableView.ScreenToCell (e.Position.X, e.Position.Y, out int? headerIfAny);
 
 
         if (headerIfAny.HasValue && headerIfAny.Value == 0)
         if (headerIfAny.HasValue && headerIfAny.Value == 0)
         {
         {

+ 14 - 12
Terminal.Gui/Views/TableView/TableView.cs

@@ -801,7 +801,7 @@ public class TableView : View
     }
     }
 
 
     ///<inheritdoc/>
     ///<inheritdoc/>
-    protected internal override bool OnMouseEvent (MouseEvent me)
+    protected override bool OnMouseEvent (MouseEventArgs me)
     {
     {
         if (!me.Flags.HasFlag (MouseFlags.Button1Clicked)
         if (!me.Flags.HasFlag (MouseFlags.Button1Clicked)
             && !me.Flags.HasFlag (MouseFlags.Button1DoubleClicked)
             && !me.Flags.HasFlag (MouseFlags.Button1DoubleClicked)
@@ -902,11 +902,11 @@ public class TableView : View
 
 
             if (hit is { })
             if (hit is { })
             {
             {
-                OnCellActivated (new CellActivatedEventArgs (Table, hit.Value.X, hit.Value.Y));
+                return OnCellActivated (new CellActivatedEventArgs (Table, hit.Value.X, hit.Value.Y));
             }
             }
         }
         }
 
 
-        return base.OnMouseEvent (me);
+        return me.Handled;
     }
     }
 
 
     ///<inheritdoc/>
     ///<inheritdoc/>
@@ -988,7 +988,7 @@ public class TableView : View
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public override bool OnProcessKeyDown (Key keyEvent)
+    protected override bool OnKeyDown (Key key)
     {
     {
         if (TableIsNullOrInvisible ())
         if (TableIsNullOrInvisible ())
         {
         {
@@ -998,12 +998,14 @@ public class TableView : View
         if (CollectionNavigator != null
         if (CollectionNavigator != null
             && HasFocus
             && HasFocus
             && Table.Rows != 0
             && Table.Rows != 0
-            && CollectionNavigatorBase.IsCompatibleKey (keyEvent)
-            && !keyEvent.KeyCode.HasFlag (KeyCode.CtrlMask)
-            && !keyEvent.KeyCode.HasFlag (KeyCode.AltMask)
-            && Rune.IsLetterOrDigit ((Rune)keyEvent))
+            && key != KeyBindings.GetKeyFromCommands (Command.Accept)
+            && key != CellActivationKey
+            && CollectionNavigatorBase.IsCompatibleKey (key)
+            && !key.KeyCode.HasFlag (KeyCode.CtrlMask)
+            && !key.KeyCode.HasFlag (KeyCode.AltMask)
+            && Rune.IsLetterOrDigit ((Rune)key))
         {
         {
-            return CycleToNextTableEntryBeginningWith (keyEvent);
+            return CycleToNextTableEntryBeginningWith (key);
         }
         }
 
 
         return false;
         return false;
@@ -1561,7 +1563,7 @@ public class TableView : View
     /// <returns></returns>
     /// <returns></returns>
     private TableSelection CreateTableSelection (int x, int y) { return CreateTableSelection (x, y, x, y); }
     private TableSelection CreateTableSelection (int x, int y) { return CreateTableSelection (x, y, x, y); }
 
 
-    private bool CycleToNextTableEntryBeginningWith (Key keyEvent)
+    private bool CycleToNextTableEntryBeginningWith (Key key)
     {
     {
         int row = SelectedRow;
         int row = SelectedRow;
 
 
@@ -1571,7 +1573,7 @@ public class TableView : View
             return false;
             return false;
         }
         }
 
 
-        int match = CollectionNavigator.GetNextMatchingItem (row, (char)keyEvent);
+        int match = CollectionNavigator.GetNextMatchingItem (row, (char)key);
 
 
         if (match != -1)
         if (match != -1)
         {
         {
@@ -1644,7 +1646,7 @@ public class TableView : View
         return colStyle is { } ? colStyle.GetRepresentation (value) : value.ToString ();
         return colStyle is { } ? colStyle.GetRepresentation (value) : value.ToString ();
     }
     }
 
 
-    private bool HasControlOrAlt (MouseEvent me) { return me.Flags.HasFlag (MouseFlags.ButtonAlt) || me.Flags.HasFlag (MouseFlags.ButtonCtrl); }
+    private bool HasControlOrAlt (MouseEventArgs me) { return me.Flags.HasFlag (MouseFlags.ButtonAlt) || me.Flags.HasFlag (MouseFlags.ButtonCtrl); }
 
 
     /// <summary>
     /// <summary>
     ///     Returns true if the given <paramref name="columnIndex"/> indexes a visible column otherwise false.  Returns
     ///     Returns true if the given <paramref name="columnIndex"/> indexes a visible column otherwise false.  Returns

+ 2 - 2
Terminal.Gui/Views/TableView/TreeTableSource.cs

@@ -166,9 +166,9 @@ public class TreeTableSource<T> : IEnumerableTableSource<T>, IDisposable where T
         }
         }
     }
     }
 
 
-    private void Table_MouseClick (object sender, MouseEventEventArgs e)
+    private void Table_MouseClick (object sender, MouseEventArgs e)
     {
     {
-        Point? hit = _tableView.ScreenToCell (e.MouseEvent.Position.X, e.MouseEvent.Position.Y, out int? headerIfAny, out int? offsetX);
+        Point? hit = _tableView.ScreenToCell (e.Position.X, e.Position.Y, out int? headerIfAny, out int? offsetX);
 
 
         if (hit is null || headerIfAny is { } || !IsInTreeColumn (hit.Value.X, false) || offsetX is null)
         if (hit is null || headerIfAny is { } || !IsInTreeColumn (hit.Value.X, false) || offsetX is null)
         {
         {

+ 16 - 34
Terminal.Gui/Views/TextField.cs

@@ -798,16 +798,15 @@ public class TextField : View
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    protected internal override bool OnMouseEvent (MouseEvent ev)
+    protected override bool OnMouseEvent (MouseEventArgs ev)
     {
     {
-        if (!ev.Flags.HasFlag (MouseFlags.Button1Pressed)
+        if (ev is { IsPressed: false, IsReleased: false }
             && !ev.Flags.HasFlag (MouseFlags.ReportMousePosition)
             && !ev.Flags.HasFlag (MouseFlags.ReportMousePosition)
-            && !ev.Flags.HasFlag (MouseFlags.Button1Released)
             && !ev.Flags.HasFlag (MouseFlags.Button1DoubleClicked)
             && !ev.Flags.HasFlag (MouseFlags.Button1DoubleClicked)
             && !ev.Flags.HasFlag (MouseFlags.Button1TripleClicked)
             && !ev.Flags.HasFlag (MouseFlags.Button1TripleClicked)
             && !ev.Flags.HasFlag (ContextMenu.MouseFlags))
             && !ev.Flags.HasFlag (ContextMenu.MouseFlags))
         {
         {
-            return base.OnMouseEvent (ev);
+            return false;
         }
         }
 
 
         if (!CanFocus)
         if (!CanFocus)
@@ -1014,48 +1013,31 @@ public class TextField : View
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public override bool? OnInvokingKeyBindings (Key a, KeyBindingScope scope)
+    protected override void OnHasFocusChanged (bool newHasFocus, View previousFocusedView, View view)
     {
     {
-        // Give autocomplete first opportunity to respond to key presses
-        if (SelectedLength == 0 && Autocomplete.Suggestions.Count > 0 && Autocomplete.ProcessKey (a))
+        if (Application.MouseGrabView is { } && Application.MouseGrabView == this)
         {
         {
-            return true;
+            Application.UngrabMouse ();
         }
         }
 
 
-        return base.OnInvokingKeyBindings (a, scope);
+        //if (SelectedLength != 0 && !(Application.MouseGrabView is MenuBar))
+        //	ClearAllSelection ();
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    protected override void OnHasFocusChanged (bool newHasFocus, View previousFocusedView, View view)
+    protected override bool OnKeyDown (Key key)
     {
     {
-        if (Application.MouseGrabView is { } && Application.MouseGrabView == this)
+        // Give autocomplete first opportunity to respond to key presses
+        if (SelectedLength == 0 && Autocomplete.Suggestions.Count > 0 && Autocomplete.ProcessKey (key))
         {
         {
-            Application.UngrabMouse ();
+            return true;
         }
         }
 
 
-        //if (SelectedLength != 0 && !(Application.MouseGrabView is MenuBar))
-        //	ClearAllSelection ();
+        return false;
     }
     }
 
 
-    /// TODO: Flush out these docs
-    /// <summary>
-    ///     Processes key presses for the <see cref="TextField"/>.
-    ///     <remarks>
-    ///         The <see cref="TextField"/> control responds to the following keys:
-    ///         <list type="table">
-    ///             <listheader>
-    ///                 <term>Keys</term> <description>Function</description>
-    ///             </listheader>
-    ///             <item>
-    ///                 <term><see cref="Key.Delete"/>, <see cref="Key.Backspace"/></term>
-    ///                 <description>Deletes the character before cursor.</description>
-    ///             </item>
-    ///         </list>
-    ///     </remarks>
-    /// </summary>
-    /// <param name="a"></param>
-    /// <returns></returns>
-    public override bool OnProcessKeyDown (Key a)
+    /// <inheritdoc />
+    protected override bool OnKeyDownNotHandled (Key a)
     {
     {
         // Remember the cursor position because the new calculated cursor position is needed
         // Remember the cursor position because the new calculated cursor position is needed
         // to be set BEFORE the TextChanged event is triggered.
         // to be set BEFORE the TextChanged event is triggered.
@@ -1662,7 +1644,7 @@ public class TextField : View
         return 0; //offB;
         return 0; //offB;
     }
     }
 
 
-    private int PositionCursor (MouseEvent ev) { return PositionCursor (TextModel.GetColFromX (_text, ScrollOffset, ev.Position.X), false); }
+    private int PositionCursor (MouseEventArgs ev) { return PositionCursor (TextModel.GetColFromX (_text, ScrollOffset, ev.Position.X), false); }
 
 
     private int PositionCursor (int x, bool getX = true)
     private int PositionCursor (int x, bool getX = true)
     {
     {

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

@@ -531,7 +531,7 @@ namespace Terminal.Gui
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        protected internal override bool OnMouseEvent (MouseEvent mouseEvent)
+        protected override bool OnMouseEvent (MouseEventArgs mouseEvent)
         {
         {
             if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed))
             if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed))
             {
             {
@@ -597,7 +597,7 @@ namespace Terminal.Gui
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
-        public override bool OnProcessKeyDown (Key a)
+        protected override bool OnKeyDownNotHandled (Key a)
         {
         {
             if (_provider is null)
             if (_provider is null)
             {
             {

+ 84 - 94
Terminal.Gui/Views/TextView.cs

@@ -1,10 +1,8 @@
 #nullable enable
 #nullable enable
 
 
 // TextView.cs: multi-line text editing
 // TextView.cs: multi-line text editing
-using System.Diagnostics;
 using System.Globalization;
 using System.Globalization;
 using System.Runtime.CompilerServices;
 using System.Runtime.CompilerServices;
-using System.Text.Json.Serialization;
 using Terminal.Gui.Resources;
 using Terminal.Gui.Resources;
 
 
 namespace Terminal.Gui;
 namespace Terminal.Gui;
@@ -106,7 +104,7 @@ internal class TextModel
 
 
     public void LoadCells (List<Cell> cells, Attribute? attribute)
     public void LoadCells (List<Cell> cells, Attribute? attribute)
     {
     {
-        _lines = Cell.ToCells ((List<Cell>)cells);
+        _lines = Cell.ToCells (cells);
         SetAttributes (attribute);
         SetAttributes (attribute);
         OnLinesLoaded ();
         OnLinesLoaded ();
     }
     }
@@ -180,7 +178,7 @@ internal class TextModel
     {
     {
         if (_lines.Count > 0 && pos < _lines.Count)
         if (_lines.Count > 0 && pos < _lines.Count)
         {
         {
-            _lines [pos] = [..runes];
+            _lines [pos] = [.. runes];
         }
         }
         else if (_lines.Count == 0 || (_lines.Count > 0 && pos >= _lines.Count))
         else if (_lines.Count == 0 || (_lines.Count > 0 && pos >= _lines.Count))
         {
         {
@@ -188,8 +186,6 @@ internal class TextModel
         }
         }
     }
     }
 
 
-
-
     public override string ToString ()
     public override string ToString ()
     {
     {
         var sb = new StringBuilder ();
         var sb = new StringBuilder ();
@@ -608,8 +604,7 @@ internal class TextModel
 
 
     internal Size GetDisplaySize ()
     internal Size GetDisplaySize ()
     {
     {
-        Size size = Size.Empty;
-
+        var size = Size.Empty;
 
 
         return size;
         return size;
     }
     }
@@ -799,7 +794,7 @@ internal class TextModel
 
 
         string GetText (List<Cell> x)
         string GetText (List<Cell> x)
         {
         {
-            string txt = Cell.ToString (x);
+            var txt = Cell.ToString (x);
 
 
             if (!matchCase)
             if (!matchCase)
             {
             {
@@ -872,7 +867,7 @@ internal class TextModel
         for (int i = start.Y; i < linesCount; i++)
         for (int i = start.Y; i < linesCount; i++)
         {
         {
             List<Cell> x = _lines [i];
             List<Cell> x = _lines [i];
-            string txt = Cell.ToString (x);
+            var txt = Cell.ToString (x);
 
 
             if (!matchCase)
             if (!matchCase)
             {
             {
@@ -912,7 +907,7 @@ internal class TextModel
         for (int i = linesCount; i >= 0; i--)
         for (int i = linesCount; i >= 0; i--)
         {
         {
             List<Cell> x = _lines [i];
             List<Cell> x = _lines [i];
-            string txt = Cell.ToString (x);
+            var txt = Cell.ToString (x);
 
 
             if (!matchCase)
             if (!matchCase)
             {
             {
@@ -1075,7 +1070,7 @@ internal class TextModel
 
 
     private string ReplaceText (List<Cell> source, string textToReplace, string matchText, int col)
     private string ReplaceText (List<Cell> source, string textToReplace, string matchText, int col)
     {
     {
-        string origTxt = Cell.ToString (source);
+        var origTxt = Cell.ToString (source);
         (_, int len) = DisplaySize (source, 0, col, false);
         (_, int len) = DisplaySize (source, 0, col, false);
         (_, int len2) = DisplaySize (source, col, col + matchText.Length, false);
         (_, int len2) = DisplaySize (source, col, col + matchText.Length, false);
         (_, int len3) = DisplaySize (source, col + matchText.Length, origTxt.GetRuneCount (), false);
         (_, int len3) = DisplaySize (source, col + matchText.Length, origTxt.GetRuneCount (), false);
@@ -1171,10 +1166,11 @@ internal partial class HistoryText
         _historyTextItems.Clear ();
         _historyTextItems.Clear ();
         _idxHistoryText = -1;
         _idxHistoryText = -1;
         _originalCellsList.Clear ();
         _originalCellsList.Clear ();
+
         // Save a copy of the original, not the reference
         // Save a copy of the original, not the reference
         foreach (List<Cell> cells in cellsList)
         foreach (List<Cell> cells in cellsList)
         {
         {
-            _originalCellsList.Add ([..cells]);
+            _originalCellsList.Add ([.. cells]);
         }
         }
 
 
         OnChangeText (null);
         OnChangeText (null);
@@ -1678,15 +1674,15 @@ internal class WordWrapManager
             List<Cell> line = Model.GetLine (i);
             List<Cell> line = Model.GetLine (i);
 
 
             List<List<Cell>> wrappedLines = ToListRune (
             List<List<Cell>> wrappedLines = ToListRune (
-                                                            TextFormatter.Format (
-                                                                                  Cell.ToString (line),
-                                                                                  width,
-                                                                                  Alignment.Start,
-                                                                                  true,
-                                                                                  preserveTrailingSpaces,
-                                                                                  tabWidth
-                                                                                 )
-                                                           );
+                                                        TextFormatter.Format (
+                                                                              Cell.ToString (line),
+                                                                              width,
+                                                                              Alignment.Start,
+                                                                              true,
+                                                                              preserveTrailingSpaces,
+                                                                              tabWidth
+                                                                             )
+                                                       );
             var sumColWidth = 0;
             var sumColWidth = 0;
 
 
             for (var j = 0; j < wrappedLines.Count; j++)
             for (var j = 0; j < wrappedLines.Count; j++)
@@ -1885,7 +1881,6 @@ public class TextView : View
     private WordWrapManager? _wrapManager;
     private WordWrapManager? _wrapManager;
     private bool _wrapNeeded;
     private bool _wrapNeeded;
 
 
-
     /// <summary>
     /// <summary>
     ///     Initializes a <see cref="TextView"/> on the specified area, with dimensions controlled with the X, Y, Width
     ///     Initializes a <see cref="TextView"/> on the specified area, with dimensions controlled with the X, Y, Width
     ///     and Height properties.
     ///     and Height properties.
@@ -1911,7 +1906,7 @@ public class TextView : View
         // Things this view knows how to do
         // Things this view knows how to do
 
 
         // Note - NewLine is only bound to Enter if Multiline is true
         // Note - NewLine is only bound to Enter if Multiline is true
-        AddCommand (Command.NewLine, (ctx) => ProcessEnterKey (ctx));
+        AddCommand (Command.NewLine, ctx => ProcessEnterKey (ctx));
 
 
         AddCommand (
         AddCommand (
                     Command.PageDown,
                     Command.PageDown,
@@ -2376,7 +2371,7 @@ public class TextView : View
         KeyBindings.Add (Key.C.WithCtrl, Command.Copy);
         KeyBindings.Add (Key.C.WithCtrl, Command.Copy);
 
 
         KeyBindings.Add (Key.W.WithCtrl, Command.Cut); // Move to Unix?
         KeyBindings.Add (Key.W.WithCtrl, Command.Cut); // Move to Unix?
-        KeyBindings.Add (Key.X.WithCtrl, Command.Cut); 
+        KeyBindings.Add (Key.X.WithCtrl, Command.Cut);
 
 
         KeyBindings.Add (Key.CursorLeft.WithCtrl, Command.WordLeft);
         KeyBindings.Add (Key.CursorLeft.WithCtrl, Command.WordLeft);
 
 
@@ -2422,10 +2417,7 @@ public class TextView : View
         KeyBindings.Add ((KeyCode)ContextMenu.Key, KeyBindingScope.HotKey, Command.Context);
         KeyBindings.Add ((KeyCode)ContextMenu.Key, KeyBindingScope.HotKey, Command.Context);
     }
     }
 
 
-    private void TextView_Added1 (object? sender, SuperViewChangedEventArgs e)
-    {
-        throw new NotImplementedException ();
-    }
+    private void TextView_Added1 (object? sender, SuperViewChangedEventArgs e) { throw new NotImplementedException (); }
 
 
     // BUGBUG: AllowsReturn is mis-named. It should be EnterKeyAccepts.
     // BUGBUG: AllowsReturn is mis-named. It should be EnterKeyAccepts.
     /// <summary>
     /// <summary>
@@ -2435,11 +2427,13 @@ public class TextView : View
     /// <remarks>
     /// <remarks>
     ///     <para>
     ///     <para>
     ///         Setting this property alters <see cref="Multiline"/>.
     ///         Setting this property alters <see cref="Multiline"/>.
-    ///         If <see cref="AllowsReturn"/> is set to <see langword="true"/>, then <see cref="Multiline"/> is also set to `true` and
+    ///         If <see cref="AllowsReturn"/> is set to <see langword="true"/>, then <see cref="Multiline"/> is also set to
+    ///         `true` and
     ///         vice-versa.
     ///         vice-versa.
     ///     </para>
     ///     </para>
     ///     <para>
     ///     <para>
-    ///         If <see cref="AllowsReturn"/> is set to <see langword="false"/>, then <see cref="AllowsTab"/> gets set to <see langword="false"/>.
+    ///         If <see cref="AllowsReturn"/> is set to <see langword="false"/>, then <see cref="AllowsTab"/> gets set to
+    ///         <see langword="false"/>.
     ///     </para>
     ///     </para>
     /// </remarks>
     /// </remarks>
     public bool AllowsReturn
     public bool AllowsReturn
@@ -2458,6 +2452,7 @@ public class TextView : View
             if (!_allowsReturn && _multiline)
             if (!_allowsReturn && _multiline)
             {
             {
                 Multiline = false;
                 Multiline = false;
+
                 // BUGBUG: Setting properties should not have side-effects like this. Multiline and AllowsTab should be independent.
                 // BUGBUG: Setting properties should not have side-effects like this. Multiline and AllowsTab should be independent.
                 AllowsTab = false;
                 AllowsTab = false;
             }
             }
@@ -2532,7 +2527,6 @@ public class TextView : View
         }
         }
     }
     }
 
 
-
     /// <summary>
     /// <summary>
     ///     Indicates whatever the text has history changes or not. <see langword="true"/> if the text has history changes
     ///     Indicates whatever the text has history changes or not. <see langword="true"/> if the text has history changes
     ///     <see langword="false"/> otherwise.
     ///     <see langword="false"/> otherwise.
@@ -2604,7 +2598,7 @@ public class TextView : View
                 CurrentRow = 0;
                 CurrentRow = 0;
                 _savedHeight = Height;
                 _savedHeight = Height;
 
 
-                Height = Dim.Auto (DimAutoStyle.Text, minimumContentDim: 1);
+                Height = Dim.Auto (DimAutoStyle.Text, 1);
 
 
                 if (!IsInitialized)
                 if (!IsInitialized)
                 {
                 {
@@ -2805,7 +2799,6 @@ public class TextView : View
         }
         }
     }
     }
 
 
-
     /// <summary>Allows clearing the <see cref="HistoryText.HistoryTextItemEventArgs"/> items updating the original text.</summary>
     /// <summary>Allows clearing the <see cref="HistoryText.HistoryTextItemEventArgs"/> items updating the original text.</summary>
     public void ClearHistoryChanges () { _historyText?.Clear (_model.GetAllLines ()); }
     public void ClearHistoryChanges () { _historyText?.Clear (_model.GetAllLines ()); }
 
 
@@ -2855,7 +2848,7 @@ public class TextView : View
                     line [c] = cell; // Assign the modified copy back
                     line [c] = cell; // Assign the modified copy back
                 }
                 }
 
 
-                selectedCellsChanged.Add ([..GetLine (r)]);
+                selectedCellsChanged.Add ([.. GetLine (r)]);
             }
             }
 
 
             GetSelectedRegion ();
             GetSelectedRegion ();
@@ -2906,10 +2899,10 @@ public class TextView : View
     public void PromptForColors ()
     public void PromptForColors ()
     {
     {
         if (!ColorPicker.Prompt (
         if (!ColorPicker.Prompt (
-                                     "Colors",
-                                     GetSelectedCellAttribute (),
-                                     out Attribute newAttribute
-                                    ))
+                                 "Colors",
+                                 GetSelectedCellAttribute (),
+                                 out Attribute newAttribute
+                                ))
         {
         {
             return;
             return;
         }
         }
@@ -3177,10 +3170,7 @@ public class TextView : View
     public List<Cell> GetLine (int line) { return _model.GetLine (line); }
     public List<Cell> GetLine (int line) { return _model.GetLine (line); }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public override Attribute GetNormalColor ()
-    {
-        return GetFocusColor ();
-    }
+    public override Attribute GetNormalColor () { return GetFocusColor (); }
 
 
     /// <summary>
     /// <summary>
     ///     Inserts the given <paramref name="toAdd"/> text at the current cursor position exactly as if the user had just
     ///     Inserts the given <paramref name="toAdd"/> text at the current cursor position exactly as if the user had just
@@ -3284,21 +3274,15 @@ public class TextView : View
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    protected internal override bool OnMouseEvent (MouseEvent ev)
+    protected override bool OnMouseEvent (MouseEventArgs ev)
     {
     {
-        if (!ev.Flags.HasFlag (MouseFlags.Button1Clicked)
-            && !ev.Flags.HasFlag (MouseFlags.Button1Pressed)
+        if (ev is { IsSingleDoubleOrTripleClicked: false, IsPressed: false, IsReleased: false, IsWheel: false }
             && !ev.Flags.HasFlag (MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition)
             && !ev.Flags.HasFlag (MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition)
-            && !ev.Flags.HasFlag (MouseFlags.Button1Released)
             && !ev.Flags.HasFlag (MouseFlags.Button1Pressed | MouseFlags.ButtonShift)
             && !ev.Flags.HasFlag (MouseFlags.Button1Pressed | MouseFlags.ButtonShift)
-            && !ev.Flags.HasFlag (MouseFlags.WheeledDown)
-            && !ev.Flags.HasFlag (MouseFlags.WheeledUp)
-            && !ev.Flags.HasFlag (MouseFlags.Button1DoubleClicked)
             && !ev.Flags.HasFlag (MouseFlags.Button1DoubleClicked | MouseFlags.ButtonShift)
             && !ev.Flags.HasFlag (MouseFlags.Button1DoubleClicked | MouseFlags.ButtonShift)
-            && !ev.Flags.HasFlag (MouseFlags.Button1TripleClicked)
             && !ev.Flags.HasFlag (ContextMenu!.MouseFlags))
             && !ev.Flags.HasFlag (ContextMenu!.MouseFlags))
         {
         {
-            return base.OnMouseEvent (ev);
+            return false;
         }
         }
 
 
         if (!CanFocus)
         if (!CanFocus)
@@ -3563,7 +3547,6 @@ public class TextView : View
 
 
         ProcessInheritsPreviousColorScheme (CurrentRow, CurrentColumn);
         ProcessInheritsPreviousColorScheme (CurrentRow, CurrentColumn);
         ProcessAutocomplete ();
         ProcessAutocomplete ();
-
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
@@ -3628,6 +3611,7 @@ public class TextView : View
                 else
                 else
                 {
                 {
                     AddRune (col, row, rune);
                     AddRune (col, row, rune);
+
                     // Ensures that cols less than 0 to be 1 because it will be converted to a printable rune
                     // Ensures that cols less than 0 to be 1 because it will be converted to a printable rune
                     cols = Math.Max (cols, 1);
                     cols = Math.Max (cols, 1);
                 }
                 }
@@ -3664,46 +3648,33 @@ public class TextView : View
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public override bool? OnInvokingKeyBindings (Key a, KeyBindingScope scope)
+    protected override void OnHasFocusChanged (bool newHasFocus, View? previousFocusedView, View? view)
     {
     {
-        if (!a.IsValid)
-        {
-            return false;
-        }
-
-        // Give autocomplete first opportunity to respond to key presses
-        if (SelectedLength == 0 && Autocomplete.Suggestions.Count > 0 && Autocomplete.ProcessKey (a))
+        if (Application.MouseGrabView is { } && Application.MouseGrabView == this)
         {
         {
-            return true;
+            Application.UngrabMouse ();
         }
         }
-
-        return base.OnInvokingKeyBindings (a, scope);
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public override bool OnKeyUp (Key key)
+    protected override bool OnKeyDown (Key key)
     {
     {
-        if (key == Key.Space.WithCtrl)
+        if (!key.IsValid)
         {
         {
-            return true;
+            return false;
         }
         }
 
 
-        return base.OnKeyUp (key);
-    }
-
-    /// <inheritdoc/>
-    protected override void OnHasFocusChanged (bool newHasFocus, View? previousFocusedView, View? view)
-    {
-        if (Application.MouseGrabView is { } && Application.MouseGrabView == this)
+        // Give autocomplete first opportunity to respond to key presses
+        if (SelectedLength == 0 && Autocomplete.Suggestions.Count > 0 && Autocomplete.ProcessKey (key))
         {
         {
-            Application.UngrabMouse ();
+            return true;
         }
         }
 
 
-        return;
+        return false;
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public override bool OnProcessKeyDown (Key a)
+    protected override bool OnKeyDownNotHandled (Key a)
     {
     {
         if (!CanFocus)
         if (!CanFocus)
         {
         {
@@ -3724,6 +3695,17 @@ public class TextView : View
         return true;
         return true;
     }
     }
 
 
+    /// <inheritdoc/>
+    public override bool OnKeyUp (Key key)
+    {
+        if (key == Key.Space.WithCtrl)
+        {
+            return true;
+        }
+
+        return false;
+    }
+
     /// <summary>Invoke the <see cref="UnwrappedCursorPosition"/> event with the unwrapped <see cref="CursorPosition"/>.</summary>
     /// <summary>Invoke the <see cref="UnwrappedCursorPosition"/> event with the unwrapped <see cref="CursorPosition"/>.</summary>
     public virtual void OnUnwrappedCursorPosition (int? cRow = null, int? cCol = null)
     public virtual void OnUnwrappedCursorPosition (int? cRow = null, int? cCol = null)
     {
     {
@@ -3760,7 +3742,7 @@ public class TextView : View
             List<List<Cell>> addedLine = [new (currentLine), runeList];
             List<List<Cell>> addedLine = [new (currentLine), runeList];
 
 
             _historyText.Add (
             _historyText.Add (
-                              [..addedLine],
+                              [.. addedLine],
                               CursorPosition,
                               CursorPosition,
                               HistoryText.LineStatus.Added
                               HistoryText.LineStatus.Added
                              );
                              );
@@ -3862,6 +3844,7 @@ public class TextView : View
         if (posX > -1 && col >= posX && posX < Viewport.Width && _topRow <= CurrentRow && posY < Viewport.Height)
         if (posX > -1 && col >= posX && posX < Viewport.Width && _topRow <= CurrentRow && posY < Viewport.Height)
         {
         {
             Move (col, CurrentRow - _topRow);
             Move (col, CurrentRow - _topRow);
+
             return new (col, CurrentRow - _topRow);
             return new (col, CurrentRow - _topRow);
         }
         }
 
 
@@ -4481,12 +4464,12 @@ public class TextView : View
         }
         }
         else
         else
         {
         {
-            _historyText.Add ([ [.. currentLine]], CursorPosition);
+            _historyText.Add ([[.. currentLine]], CursorPosition);
 
 
             currentLine.RemoveAt (CurrentColumn);
             currentLine.RemoveAt (CurrentColumn);
 
 
             _historyText.Add (
             _historyText.Add (
-                              [ [.. currentLine]],
+                              [[.. currentLine]],
                               CursorPosition,
                               CursorPosition,
                               HistoryText.LineStatus.Replaced
                               HistoryText.LineStatus.Replaced
                              );
                              );
@@ -4656,6 +4639,7 @@ public class TextView : View
         {
         {
             cells = line.GetRange (startCol, endCol - startCol);
             cells = line.GetRange (startCol, endCol - startCol);
             cellsList.Add (cells);
             cellsList.Add (cells);
+
             return StringFromRunes (cells);
             return StringFromRunes (cells);
         }
         }
 
 
@@ -4668,6 +4652,7 @@ public class TextView : View
             cellsList.AddRange ([]);
             cellsList.AddRange ([]);
             cells = model == null ? _model.GetLine (row) : model.GetLine (row);
             cells = model == null ? _model.GetLine (row) : model.GetLine (row);
             cellsList.Add (cells);
             cellsList.Add (cells);
+
             res = res
             res = res
                   + Environment.NewLine
                   + Environment.NewLine
                   + StringFromRunes (cells);
                   + StringFromRunes (cells);
@@ -4703,7 +4688,7 @@ public class TextView : View
 
 
         OnUnwrappedCursorPosition (cRow, cCol);
         OnUnwrappedCursorPosition (cRow, cCol);
 
 
-        return GetRegion (out _, sRow: startRow, sCol: startCol, cRow: cRow, cCol: cCol, model: model);
+        return GetRegion (out _, startRow, startCol, cRow, cCol, model);
     }
     }
 
 
     private (int Row, int Col) GetUnwrappedPosition (int line, int col)
     private (int Row, int Col) GetUnwrappedPosition (int line, int col)
@@ -4897,7 +4882,7 @@ public class TextView : View
         {
         {
             _model.AddLine (CurrentRow + i, lines [i]);
             _model.AddLine (CurrentRow + i, lines [i]);
 
 
-            addedLines.Add ([..lines [i]]);
+            addedLines.Add ([.. lines [i]]);
         }
         }
 
 
         if (rest is { })
         if (rest is { })
@@ -5071,7 +5056,7 @@ public class TextView : View
         }
         }
 
 
         _historyText.Add (
         _historyText.Add (
-                          [ [.. GetCurrentLine ()]],
+                          [[.. GetCurrentLine ()]],
                           CursorPosition,
                           CursorPosition,
                           HistoryText.LineStatus.Replaced
                           HistoryText.LineStatus.Replaced
                          );
                          );
@@ -5111,7 +5096,7 @@ public class TextView : View
             return;
             return;
         }
         }
 
 
-        _historyText.Add ([ [.. currentLine]], CursorPosition);
+        _historyText.Add ([[.. currentLine]], CursorPosition);
 
 
         if (currentLine.Count == 0)
         if (currentLine.Count == 0)
         {
         {
@@ -5178,7 +5163,7 @@ public class TextView : View
         }
         }
 
 
         _historyText.Add (
         _historyText.Add (
-                          [ [.. GetCurrentLine ()]],
+                          [[.. GetCurrentLine ()]],
                           CursorPosition,
                           CursorPosition,
                           HistoryText.LineStatus.Replaced
                           HistoryText.LineStatus.Replaced
                          );
                          );
@@ -5202,14 +5187,14 @@ public class TextView : View
 
 
         List<Cell> currentLine = GetCurrentLine ();
         List<Cell> currentLine = GetCurrentLine ();
 
 
-        _historyText.Add ([ [.. GetCurrentLine ()]], CursorPosition);
+        _historyText.Add ([[.. GetCurrentLine ()]], CursorPosition);
 
 
         if (CurrentColumn == 0)
         if (CurrentColumn == 0)
         {
         {
             DeleteTextBackwards ();
             DeleteTextBackwards ();
 
 
             _historyText.ReplaceLast (
             _historyText.ReplaceLast (
-                                      [ [.. GetCurrentLine ()]],
+                                      [[.. GetCurrentLine ()]],
                                       CursorPosition,
                                       CursorPosition,
                                       HistoryText.LineStatus.Replaced
                                       HistoryText.LineStatus.Replaced
                                      );
                                      );
@@ -5248,7 +5233,7 @@ public class TextView : View
         }
         }
 
 
         _historyText.Add (
         _historyText.Add (
-                          [ [.. GetCurrentLine ()]],
+                          [[.. GetCurrentLine ()]],
                           CursorPosition,
                           CursorPosition,
                           HistoryText.LineStatus.Replaced
                           HistoryText.LineStatus.Replaced
                          );
                          );
@@ -5270,14 +5255,14 @@ public class TextView : View
 
 
         List<Cell> currentLine = GetCurrentLine ();
         List<Cell> currentLine = GetCurrentLine ();
 
 
-        _historyText.Add ([ [.. GetCurrentLine ()]], CursorPosition);
+        _historyText.Add ([[.. GetCurrentLine ()]], CursorPosition);
 
 
         if (currentLine.Count == 0 || CurrentColumn == currentLine.Count)
         if (currentLine.Count == 0 || CurrentColumn == currentLine.Count)
         {
         {
             DeleteTextForwards ();
             DeleteTextForwards ();
 
 
             _historyText.ReplaceLast (
             _historyText.ReplaceLast (
-                                      [ [.. GetCurrentLine ()]],
+                                      [[.. GetCurrentLine ()]],
                                       CursorPosition,
                                       CursorPosition,
                                       HistoryText.LineStatus.Replaced
                                       HistoryText.LineStatus.Replaced
                                      );
                                      );
@@ -5307,7 +5292,7 @@ public class TextView : View
         }
         }
 
 
         _historyText.Add (
         _historyText.Add (
-                          [ [.. GetCurrentLine ()]],
+                          [[.. GetCurrentLine ()]],
                           CursorPosition,
                           CursorPosition,
                           HistoryText.LineStatus.Replaced
                           HistoryText.LineStatus.Replaced
                          );
                          );
@@ -5579,6 +5564,7 @@ public class TextView : View
         }
         }
 
 
         DoNeededAction ();
         DoNeededAction ();
+
         return true;
         return true;
     }
     }
 
 
@@ -5883,7 +5869,7 @@ public class TextView : View
         KillWordForward ();
         KillWordForward ();
     }
     }
 
 
-    private void ProcessMouseClick (MouseEvent ev, out List<Cell> line)
+    private void ProcessMouseClick (MouseEventArgs ev, out List<Cell> line)
     {
     {
         List<Cell>? r = null;
         List<Cell>? r = null;
 
 
@@ -5919,6 +5905,7 @@ public class TextView : View
     private bool ProcessMoveDown ()
     private bool ProcessMoveDown ()
     {
     {
         ResetContinuousFindTrack ();
         ResetContinuousFindTrack ();
+
         if (_shiftSelecting && IsSelecting)
         if (_shiftSelecting && IsSelecting)
         {
         {
             StopSelecting ();
             StopSelecting ();
@@ -5961,8 +5948,10 @@ public class TextView : View
             if (IsSelecting)
             if (IsSelecting)
             {
             {
                 StopSelecting ();
                 StopSelecting ();
+
                 return true;
                 return true;
             }
             }
+
             // do not respond (this lets the key press fall through to navigation system - which usually changes focus backward)
             // do not respond (this lets the key press fall through to navigation system - which usually changes focus backward)
             return false;
             return false;
         }
         }
@@ -6001,8 +5990,10 @@ public class TextView : View
             {
             {
                 // In which case clear
                 // In which case clear
                 StopSelecting ();
                 StopSelecting ();
+
                 return true;
                 return true;
             }
             }
+
             return false;
             return false;
         }
         }
 
 
@@ -6296,7 +6287,6 @@ public class TextView : View
         _continuousFind = false;
         _continuousFind = false;
     }
     }
 
 
-
     private void ResetPosition ()
     private void ResetPosition ()
     {
     {
         _topRow = _leftColumn = CurrentRow = CurrentColumn = 0;
         _topRow = _leftColumn = CurrentRow = CurrentColumn = 0;
@@ -6461,13 +6451,13 @@ public class TextView : View
         }
         }
     }
     }
 
 
-
     private void TextView_Initialized (object sender, EventArgs e)
     private void TextView_Initialized (object sender, EventArgs e)
     {
     {
         if (Autocomplete.HostControl is null)
         if (Autocomplete.HostControl is null)
         {
         {
             Autocomplete.HostControl = this;
             Autocomplete.HostControl = this;
         }
         }
+
         OnContentsChanged ();
         OnContentsChanged ();
     }
     }
 
 

+ 3 - 3
Terminal.Gui/Views/TileView.cs

@@ -286,11 +286,11 @@ public class TileView : View
 
 
     //// BUGBUG: Why is this not handled by a key binding???
     //// BUGBUG: Why is this not handled by a key binding???
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public override bool OnProcessKeyDown (Key keyEvent)
+    protected override bool OnKeyDownNotHandled (Key key)
     {
     {
         var focusMoved = false;
         var focusMoved = false;
 
 
-        if (keyEvent.KeyCode == ToggleResizable)
+        if (key.KeyCode == ToggleResizable)
         {
         {
             foreach (TileViewLineView l in _splitterLines)
             foreach (TileViewLineView l in _splitterLines)
             {
             {
@@ -910,7 +910,7 @@ public class TileView : View
             }
             }
         }
         }
 
 
-        protected internal override bool OnMouseEvent (MouseEvent mouseEvent)
+        protected override bool OnMouseEvent (MouseEventArgs mouseEvent)
         {
         {
             if (!dragPosition.HasValue && mouseEvent.Flags == MouseFlags.Button1Pressed)
             if (!dragPosition.HasValue && mouseEvent.Flags == MouseFlags.Button1Pressed)
             {
             {

+ 9 - 6
Terminal.Gui/Views/TimeField.cs

@@ -163,21 +163,24 @@ public class TimeField : TextField
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    protected internal override bool OnMouseEvent  (MouseEvent ev)
+    protected override bool OnMouseEvent  (MouseEventArgs ev)
     {
     {
-        bool result = base.OnMouseEvent (ev);
+        if (base.OnMouseEvent (ev) || ev.Handled)
+        {
+            return true;
+        }
 
 
-        if (result && SelectedLength == 0 && ev.Flags.HasFlag (MouseFlags.Button1Pressed))
+        if (SelectedLength == 0 && ev.Flags.HasFlag (MouseFlags.Button1Pressed))
         {
         {
             int point = ev.Position.X;
             int point = ev.Position.X;
             AdjCursorPosition (point);
             AdjCursorPosition (point);
         }
         }
 
 
-        return result;
+        return ev.Handled;
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public override bool OnProcessKeyDown (Key a)
+    protected override bool OnKeyDownNotHandled (Key a)
     {
     {
         // Ignore non-numeric characters.
         // Ignore non-numeric characters.
         if (a.KeyCode is >= (KeyCode)(int)KeyCode.D0 and <= (KeyCode)(int)KeyCode.D9)
         if (a.KeyCode is >= (KeyCode)(int)KeyCode.D0 and <= (KeyCode)(int)KeyCode.D9)
@@ -227,7 +230,7 @@ public class TimeField : TextField
             CursorPosition = newPoint;
             CursorPosition = newPoint;
         }
         }
 
 
-        while (Text [CursorPosition] == _sepChar [0])
+        while (CursorPosition < Text.GetColumns() -1 && Text [CursorPosition] == _sepChar [0])
         {
         {
             if (increment)
             if (increment)
             {
             {

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

@@ -62,7 +62,7 @@ public partial class Toplevel : View
     /// </summary>
     /// </summary>
     public bool Modal { get; set; }
     public bool Modal { get; set; }
 
 
-    private void Toplevel_MouseClick (object? sender, MouseEventEventArgs e) { e.Handled = InvokeCommand (Command.HotKey) == true; }
+    private void Toplevel_MouseClick (object? sender, MouseEventArgs e) { e.Handled = InvokeCommand (Command.HotKey) == true; }
 
 
     #endregion
     #endregion
 
 

+ 8 - 15
Terminal.Gui/Views/TreeView/TreeView.cs

@@ -990,18 +990,14 @@ public class TreeView<T> : View, ITreeView where T : class
 
 
     // BUGBUG: OnMouseEvent is internal. TreeView should not be overriding.
     // BUGBUG: OnMouseEvent is internal. TreeView should not be overriding.
     ///<inheritdoc/>
     ///<inheritdoc/>
-    protected internal override bool OnMouseEvent (MouseEvent me)
+    protected override bool OnMouseEvent (MouseEventArgs me)
     {
     {
         // If it is not an event we care about
         // If it is not an event we care about
-        if (!me.Flags.HasFlag (MouseFlags.Button1Clicked)
-            && !me.Flags.HasFlag (ObjectActivationButton ?? MouseFlags.Button1DoubleClicked)
-            && !me.Flags.HasFlag (MouseFlags.WheeledDown)
-            && !me.Flags.HasFlag (MouseFlags.WheeledUp)
-            && !me.Flags.HasFlag (MouseFlags.WheeledRight)
-            && !me.Flags.HasFlag (MouseFlags.WheeledLeft))
+        if (me is { IsSingleClicked: false, IsPressed: false, IsReleased: false, IsWheel: false }
+            && !me.Flags.HasFlag (ObjectActivationButton ?? MouseFlags.Button1DoubleClicked))
         {
         {
             // do nothing
             // do nothing
-            return base.OnMouseEvent (me);
+            return false;
         }
         }
 
 
         if (!HasFocus && CanFocus)
         if (!HasFocus && CanFocus)
@@ -1182,26 +1178,23 @@ public class TreeView<T> : View, ITreeView where T : class
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public override bool OnProcessKeyDown (Key keyEvent)
+    protected override bool OnKeyDown (Key key)
     {
     {
         if (!Enabled)
         if (!Enabled)
         {
         {
             return false;
             return false;
         }
         }
 
 
-        // BUGBUG: this should move to OnInvokingKeyBindings
         // If not a keybinding, is the key a searchable key press?
         // If not a keybinding, is the key a searchable key press?
-        if (CollectionNavigatorBase.IsCompatibleKey (keyEvent) && AllowLetterBasedNavigation)
+        if (CollectionNavigatorBase.IsCompatibleKey (key) && AllowLetterBasedNavigation)
         {
         {
-            IReadOnlyCollection<Branch<T>> map;
-
             // If there has been a call to InvalidateMap since the last time
             // If there has been a call to InvalidateMap since the last time
             // we need a new one to reflect the new exposed tree state
             // we need a new one to reflect the new exposed tree state
-            map = BuildLineMap ();
+            IReadOnlyCollection<Branch<T>> map = BuildLineMap ();
 
 
             // Find the current selected object within the tree
             // Find the current selected object within the tree
             int current = map.IndexOf (b => b.Model == SelectedObject);
             int current = map.IndexOf (b => b.Model == SelectedObject);
-            int? newIndex = KeystrokeNavigator?.GetNextMatchingItem (current, (char)keyEvent);
+            int? newIndex = KeystrokeNavigator?.GetNextMatchingItem (current, (char)key);
 
 
             if (newIndex is int && newIndex != -1)
             if (newIndex is int && newIndex != -1)
             {
             {

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

@@ -381,12 +381,12 @@ public class Wizard : Dialog
     /// <summary>
     /// <summary>
     ///     <see cref="Wizard"/> is derived from <see cref="Dialog"/> and Dialog causes <c>Esc</c> to call
     ///     <see cref="Wizard"/> is derived from <see cref="Dialog"/> and Dialog causes <c>Esc</c> to call
     ///     <see cref="Application.RequestStop(Toplevel)"/>, closing the Dialog. Wizard overrides
     ///     <see cref="Application.RequestStop(Toplevel)"/>, closing the Dialog. Wizard overrides
-    ///     <see cref="OnProcessKeyDown"/> to instead fire the <see cref="Cancelled"/> event when Wizard is being used as a
+    ///     <see cref="OnKeyDownNotHandled"/> to instead fire the <see cref="Cancelled"/> event when Wizard is being used as a
     ///     non-modal (see <see cref="Wizard.Modal"/>).
     ///     non-modal (see <see cref="Wizard.Modal"/>).
     /// </summary>
     /// </summary>
     /// <param name="key"></param>
     /// <param name="key"></param>
     /// <returns></returns>
     /// <returns></returns>
-    public override bool OnProcessKeyDown (Key key)
+    protected override bool OnKeyDownNotHandled (Key key)
     {
     {
         //// BUGBUG: Why is this not handled by a key binding???
         //// BUGBUG: Why is this not handled by a key binding???
         if (!Modal)
         if (!Modal)

+ 4 - 4
UICatalog/Scenarios/ASCIICustomButton.cs

@@ -127,7 +127,7 @@ public class ASCIICustomButtonTest : Scenario
         }
         }
 
 
         public event Action<ASCIICustomButton> PointerEnter;
         public event Action<ASCIICustomButton> PointerEnter;
-        private void This_MouseClick (object sender, MouseEventEventArgs obj) { NewMouseEvent (obj.MouseEvent); }
+        private void This_MouseClick (object sender, MouseEventArgs obj) { NewMouseEvent (obj); }
     }
     }
 
 
     public class ScrollViewTestWindow : Window
     public class ScrollViewTestWindow : Window
@@ -310,9 +310,9 @@ public class ASCIICustomButtonTest : Scenario
             }
             }
         }
         }
 
 
-        private void Button_MouseClick (object sender, MouseEventEventArgs obj)
+        private void Button_MouseClick (object sender, MouseEventArgs obj)
         {
         {
-            if (obj.MouseEvent.Flags == MouseFlags.WheeledDown)
+            if (obj.Flags == MouseFlags.WheeledDown)
             {
             {
                 _scrollView.ContentOffset = new Point (
                 _scrollView.ContentOffset = new Point (
                                                        _scrollView.ContentOffset.X,
                                                        _scrollView.ContentOffset.X,
@@ -320,7 +320,7 @@ public class ASCIICustomButtonTest : Scenario
                                                       );
                                                       );
                 obj.Handled = true;
                 obj.Handled = true;
             }
             }
-            else if (obj.MouseEvent.Flags == MouseFlags.WheeledUp)
+            else if (obj.Flags == MouseFlags.WheeledUp)
             {
             {
                 _scrollView.ContentOffset = new Point (
                 _scrollView.ContentOffset = new Point (
                                                        _scrollView.ContentOffset.X,
                                                        _scrollView.ContentOffset.X,

+ 1 - 1
UICatalog/Scenarios/AdornmentsEditor.cs

@@ -108,7 +108,7 @@ public class AdornmentsEditor : View
         ViewToEdit = Application.Navigation!.GetFocused ();
         ViewToEdit = Application.Navigation!.GetFocused ();
     }
     }
 
 
-    private void ApplicationOnMouseEvent (object? sender, MouseEvent e)
+    private void ApplicationOnMouseEvent (object? sender, MouseEventArgs e)
     {
     {
         if (e.Flags != MouseFlags.Button1Clicked || !AutoSelectViewToEdit)
         if (e.Flags != MouseFlags.Button1Clicked || !AutoSelectViewToEdit)
         {
         {

+ 1 - 1
UICatalog/Scenarios/ArrangementEditor.cs

@@ -147,7 +147,7 @@ public sealed class ArrangementEditor : View
         }
         }
     }
     }
 
 
-    private void ApplicationOnMouseEvent (object? sender, MouseEvent e)
+    private void ApplicationOnMouseEvent (object? sender, MouseEventArgs e)
     {
     {
         if (e.Flags != MouseFlags.Button1Clicked || !AutoSelectViewToEdit)
         if (e.Flags != MouseFlags.Button1Clicked || !AutoSelectViewToEdit)
         {
         {

+ 8 - 8
UICatalog/Scenarios/Bars.cs

@@ -187,12 +187,12 @@ public class Bars : Scenario
 
 
         menuLikeExamples.MouseClick += MenuLikeExamplesMouseClick;
         menuLikeExamples.MouseClick += MenuLikeExamplesMouseClick;
 
 
-        void MenuLikeExamplesMouseClick (object sender, MouseEventEventArgs e)
+        void MenuLikeExamplesMouseClick (object sender, MouseEventArgs e)
         {
         {
-            if (e.MouseEvent.Flags.HasFlag (MouseFlags.Button3Clicked))
+            if (e.Flags.HasFlag (MouseFlags.Button3Clicked))
             {
             {
-                popOverMenu.X = e.MouseEvent.Position.X;
-                popOverMenu.Y = e.MouseEvent.Position.Y;
+                popOverMenu.X = e.Position.X;
+                popOverMenu.Y = e.Position.Y;
                 popOverMenu.Visible = true;
                 popOverMenu.Visible = true;
                 //popOverMenu.Enabled = popOverMenu.Visible;
                 //popOverMenu.Enabled = popOverMenu.Visible;
                 popOverMenu.SetFocus ();
                 popOverMenu.SetFocus ();
@@ -275,7 +275,7 @@ public class Bars : Scenario
 
 
     //private void ShowContextMenu (object s, MouseEventEventArgs e)
     //private void ShowContextMenu (object s, MouseEventEventArgs e)
     //{
     //{
-    //    if (e.MouseEvent.Flags != MouseFlags.Button3Clicked)
+    //    if (e.Flags != MouseFlags.Button3Clicked)
     //    {
     //    {
     //        return;
     //        return;
     //    }
     //    }
@@ -283,8 +283,8 @@ public class Bars : Scenario
     //    var contextMenu = new Bar
     //    var contextMenu = new Bar
     //    {
     //    {
     //        Id = "contextMenu",
     //        Id = "contextMenu",
-    //        X = e.MouseEvent.Position.X,
-    //        Y = e.MouseEvent.Position.Y,
+    //        X = e.Position.X,
+    //        Y = e.Position.Y,
     //        Width = Dim.Auto (DimAutoStyle.Content),
     //        Width = Dim.Auto (DimAutoStyle.Content),
     //        Height = Dim.Auto (DimAutoStyle.Content),
     //        Height = Dim.Auto (DimAutoStyle.Content),
     //        Orientation = Orientation.Vertical,
     //        Orientation = Orientation.Vertical,
@@ -387,7 +387,7 @@ public class Bars : Scenario
 
 
     //    contextMenu.Initialized += Menu_Initialized;
     //    contextMenu.Initialized += Menu_Initialized;
 
 
-    //    void Application_MouseEvent (object sender, MouseEvent e)
+    //    void Application_MouseEvent (object sender, MouseEventArgs e)
     //    {
     //    {
     //        // If user clicks outside of the menuWindow, close it
     //        // If user clicks outside of the menuWindow, close it
     //        if (!contextMenu.Frame.Contains (e.Position.X, e.Position.Y))
     //        if (!contextMenu.Frame.Contains (e.Position.X, e.Position.Y))

+ 9 - 11
UICatalog/Scenarios/CharacterMap.cs

@@ -98,9 +98,9 @@ public class CharacterMap : Scenario
         // if user clicks the mouse in TableView
         // if user clicks the mouse in TableView
         _categoryList.MouseClick += (s, e) =>
         _categoryList.MouseClick += (s, e) =>
                                     {
                                     {
-                                        _categoryList.ScreenToCell (e.MouseEvent.Position, out int? clickedCol);
+                                        _categoryList.ScreenToCell (e.Position, out int? clickedCol);
 
 
-                                        if (clickedCol != null && e.MouseEvent.Flags.HasFlag (MouseFlags.Button1Clicked))
+                                        if (clickedCol != null && e.Flags.HasFlag (MouseFlags.Button1Clicked))
                                         {
                                         {
                                             EnumerableTableSource<UnicodeRange> table = (EnumerableTableSource<UnicodeRange>)_categoryList.Table;
                                             EnumerableTableSource<UnicodeRange> table = (EnumerableTableSource<UnicodeRange>)_categoryList.Table;
                                             string prevSelection = table.Data.ElementAt (_categoryList.SelectedRow).Category;
                                             string prevSelection = table.Data.ElementAt (_categoryList.SelectedRow).Category;
@@ -527,9 +527,9 @@ internal class CharMap : View
         Padding.Add (up, down, left, right);
         Padding.Add (up, down, left, right);
     }
     }
 
 
-    private void Handle_MouseEvent (object sender, MouseEventEventArgs e)
+    private void Handle_MouseEvent (object sender, MouseEventArgs e)
     {
     {
-        if (e.MouseEvent.Flags == MouseFlags.WheeledDown)
+        if (e.Flags == MouseFlags.WheeledDown)
         {
         {
             ScrollVertical (1);
             ScrollVertical (1);
             e.Handled = true;
             e.Handled = true;
@@ -537,7 +537,7 @@ internal class CharMap : View
             return;
             return;
         }
         }
 
 
-        if (e.MouseEvent.Flags == MouseFlags.WheeledUp)
+        if (e.Flags == MouseFlags.WheeledUp)
         {
         {
             ScrollVertical (-1);
             ScrollVertical (-1);
             e.Handled = true;
             e.Handled = true;
@@ -545,7 +545,7 @@ internal class CharMap : View
             return;
             return;
         }
         }
 
 
-        if (e.MouseEvent.Flags == MouseFlags.WheeledRight)
+        if (e.Flags == MouseFlags.WheeledRight)
         {
         {
             ScrollHorizontal (1);
             ScrollHorizontal (1);
             e.Handled = true;
             e.Handled = true;
@@ -553,7 +553,7 @@ internal class CharMap : View
             return;
             return;
         }
         }
 
 
-        if (e.MouseEvent.Flags == MouseFlags.WheeledLeft)
+        if (e.Flags == MouseFlags.WheeledLeft)
         {
         {
             ScrollHorizontal (-1);
             ScrollHorizontal (-1);
             e.Handled = true;
             e.Handled = true;
@@ -839,10 +839,8 @@ internal class CharMap : View
     private void CopyCodePoint () { Clipboard.Contents = $"U+{SelectedCodePoint:x5}"; }
     private void CopyCodePoint () { Clipboard.Contents = $"U+{SelectedCodePoint:x5}"; }
     private void CopyGlyph () { Clipboard.Contents = $"{new Rune (SelectedCodePoint)}"; }
     private void CopyGlyph () { Clipboard.Contents = $"{new Rune (SelectedCodePoint)}"; }
 
 
-    private void Handle_MouseClick (object sender, MouseEventEventArgs args)
+    private void Handle_MouseClick (object sender, MouseEventArgs me)
     {
     {
-        MouseEvent me = args.MouseEvent;
-
         if (me.Flags != MouseFlags.ReportMousePosition && me.Flags != MouseFlags.Button1Clicked && me.Flags != MouseFlags.Button1DoubleClicked)
         if (me.Flags != MouseFlags.ReportMousePosition && me.Flags != MouseFlags.Button1Clicked && me.Flags != MouseFlags.Button1DoubleClicked)
         {
         {
             return;
             return;
@@ -883,7 +881,7 @@ internal class CharMap : View
             SetFocus ();
             SetFocus ();
         }
         }
 
 
-        args.Handled = true;
+        me.Handled = true;
 
 
         if (me.Flags == MouseFlags.Button1Clicked)
         if (me.Flags == MouseFlags.Button1Clicked)
         {
         {

+ 5 - 5
UICatalog/Scenarios/ContentScrolling.cs

@@ -52,30 +52,30 @@ public class ContentScrolling : Scenario
             MouseEvent += VirtualDemoView_MouseEvent;
             MouseEvent += VirtualDemoView_MouseEvent;
         }
         }
 
 
-        private void VirtualDemoView_MouseEvent (object sender, MouseEventEventArgs e)
+        private void VirtualDemoView_MouseEvent (object sender, MouseEventArgs e)
         {
         {
-            if (e.MouseEvent.Flags == MouseFlags.WheeledDown)
+            if (e.Flags == MouseFlags.WheeledDown)
             {
             {
                 ScrollVertical (1);
                 ScrollVertical (1);
 
 
                 return;
                 return;
             }
             }
 
 
-            if (e.MouseEvent.Flags == MouseFlags.WheeledUp)
+            if (e.Flags == MouseFlags.WheeledUp)
             {
             {
                 ScrollVertical (-1);
                 ScrollVertical (-1);
 
 
                 return;
                 return;
             }
             }
 
 
-            if (e.MouseEvent.Flags == MouseFlags.WheeledRight)
+            if (e.Flags == MouseFlags.WheeledRight)
             {
             {
                 ScrollHorizontal (1);
                 ScrollHorizontal (1);
 
 
                 return;
                 return;
             }
             }
 
 
-            if (e.MouseEvent.Flags == MouseFlags.WheeledLeft)
+            if (e.Flags == MouseFlags.WheeledLeft)
             {
             {
                 ScrollHorizontal (-1);
                 ScrollHorizontal (-1);
             }
             }

+ 3 - 3
UICatalog/Scenarios/ContextMenus.cs

@@ -75,16 +75,16 @@ public class ContextMenus : Scenario
 
 
         appWindow.MouseClick += (s, e) =>
         appWindow.MouseClick += (s, e) =>
                                 {
                                 {
-                                    if (e.MouseEvent.Flags == _contextMenu.MouseFlags)
+                                    if (e.Flags == _contextMenu.MouseFlags)
                                     {
                                     {
-                                        ShowContextMenu (e.MouseEvent.Position.X, e.MouseEvent.Position.Y);
+                                        ShowContextMenu (e.Position.X, e.Position.Y);
                                         e.Handled = true;
                                         e.Handled = true;
                                     }
                                     }
                                 };
                                 };
 
 
         Application.MouseEvent += ApplicationMouseEvent;
         Application.MouseEvent += ApplicationMouseEvent;
 
 
-        void ApplicationMouseEvent (object sender, MouseEvent a) { mousePos = a.Position; }
+        void ApplicationMouseEvent (object sender, MouseEventArgs a) { mousePos = a.Position; }
 
 
         appWindow.WantMousePositionReports = true;
         appWindow.WantMousePositionReports = true;
 
 

+ 110 - 71
UICatalog/Scenarios/HexEditor.cs

@@ -16,20 +16,23 @@ public class HexEditor : Scenario
     private HexView _hexView;
     private HexView _hexView;
     private MenuItem _miAllowEdits;
     private MenuItem _miAllowEdits;
     private bool _saved = true;
     private bool _saved = true;
-    private Shortcut _siPositionChanged;
+    private Shortcut _scAddress;
+    private Shortcut _scInfo;
+    private Shortcut _scPosition;
     private StatusBar _statusBar;
     private StatusBar _statusBar;
 
 
     public override void Main ()
     public override void Main ()
     {
     {
         Application.Init ();
         Application.Init ();
-        Toplevel app = new Toplevel ()
+
+        var app = new Toplevel
         {
         {
             ColorScheme = Colors.ColorSchemes ["Base"]
             ColorScheme = Colors.ColorSchemes ["Base"]
         };
         };
 
 
         CreateDemoFile (_fileName);
         CreateDemoFile (_fileName);
 
 
-        _hexView = new HexView (new MemoryStream (Encoding.UTF8.GetBytes ("Demo text.")))
+        _hexView = new (new MemoryStream (Encoding.UTF8.GetBytes ("Demo text.")))
         {
         {
             X = 0,
             X = 0,
             Y = 1,
             Y = 1,
@@ -46,71 +49,97 @@ public class HexEditor : Scenario
         {
         {
             Menus =
             Menus =
             [
             [
-                new MenuBarItem (
-                                 "_File",
-                                 new MenuItem []
-                                 {
-                                     new ("_New", "", () => New ()),
-                                     new ("_Open", "", () => Open ()),
-                                     new ("_Save", "", () => Save ()),
-                                     null,
-                                     new ("_Quit", "", () => Quit ())
-                                 }
-                                ),
-                new MenuBarItem (
-                                 "_Edit",
-                                 new MenuItem []
-                                 {
-                                     new ("_Copy", "", () => Copy ()),
-                                     new ("C_ut", "", () => Cut ()),
-                                     new ("_Paste", "", () => Paste ())
-                                 }
-                                ),
-                new MenuBarItem (
-                                 "_Options",
-                                 new []
-                                 {
-                                     _miAllowEdits = new MenuItem (
-                                                                   "_AllowEdits",
-                                                                   "",
-                                                                   () => ToggleAllowEdits ()
-                                                                  )
-                                     {
-                                         Checked = _hexView.AllowEdits,
-                                         CheckType = MenuItemCheckStyle
-                                             .Checked
-                                     }
-                                 }
-                                )
+                new (
+                     "_File",
+                     new MenuItem []
+                     {
+                         new ("_New", "", () => New ()),
+                         new ("_Open", "", () => Open ()),
+                         new ("_Save", "", () => Save ()),
+                         null,
+                         new ("_Quit", "", () => Quit ())
+                     }
+                    ),
+                new (
+                     "_Edit",
+                     new MenuItem []
+                     {
+                         new ("_Copy", "", () => Copy ()),
+                         new ("C_ut", "", () => Cut ()),
+                         new ("_Paste", "", () => Paste ())
+                     }
+                    ),
+                new (
+                     "_Options",
+                     new []
+                     {
+                         _miAllowEdits = new (
+                                              "_AllowEdits",
+                                              "",
+                                              () => ToggleAllowEdits ()
+                                             )
+                         {
+                             Checked = _hexView.AllowEdits,
+                             CheckType = MenuItemCheckStyle
+                                 .Checked
+                         }
+                     }
+                    )
             ]
             ]
         };
         };
         app.Add (menu);
         app.Add (menu);
 
 
-        _statusBar = new StatusBar (
-                                    new []
-                                    {
-                                        new (Key.F2, "Open", () => Open ()),
-                                        new (Key.F3, "Save", () => Save ()),
-                                        new (
-                                             Application.QuitKey,
-                                             $"Quit",
-                                             () => Quit ()
-                                            ),
-                                        _siPositionChanged = new Shortcut (
-                                                                             Key.Empty,
-                                                                             $"Position: {
-                                                                                 _hexView.Position
-                                                                             } Line: {
-                                                                                 _hexView.CursorPosition.Y
-                                                                             } Col: {
-                                                                                 _hexView.CursorPosition.X
-                                                                             } Line length: {
-                                                                                 _hexView.BytesPerLine
-                                                                             }",
-                                                                             () => { }
-                                                                            )
-                                    }
-                                   )
+        var addressWidthUpDown = new NumericUpDown
+        {
+            Value = _hexView.AddressWidth
+        };
+
+        NumericUpDown<long> addressUpDown = new NumericUpDown<long>
+        {
+            Value = _hexView.Address,
+            Format = $"0x{{0:X{_hexView.AddressWidth}}}"
+        };
+
+        addressWidthUpDown.ValueChanging += (sender, args) =>
+                                            {
+                                                args.Cancel = args.NewValue is < 0 or > 8;
+
+                                                if (!args.Cancel)
+                                                {
+                                                    _hexView.AddressWidth = args.NewValue;
+
+                                                    // ReSharper disable once AccessToDisposedClosure
+                                                    addressUpDown.Format = $"0x{{0:X{_hexView.AddressWidth}}}";
+                                                }
+                                            };
+
+        addressUpDown.ValueChanging += (sender, args) =>
+                                       {
+                                           args.Cancel = args.NewValue is < 0;
+
+                                           if (!args.Cancel)
+                                           {
+                                               _hexView.Address = args.NewValue;
+                                           }
+                                       };
+
+        _statusBar = new (
+                          [
+                              new (Key.F2, "Open", Open),
+                              new (Key.F3, "Save", Save),
+                              new ()
+                              {
+                                  CommandView = addressWidthUpDown,
+                                  HelpText = "Address Width"
+                              },
+                              _scAddress = new ()
+                              {
+                                  CommandView = addressUpDown,
+                                  HelpText = "Address:"
+                              },
+                              _scInfo = new (Key.Empty, string.Empty, () => { }),
+                              _scPosition = new (Key.Empty, string.Empty, () => { })
+                          ])
         {
         {
             AlignmentModes = AlignmentModes.IgnoreFirstOrLast
             AlignmentModes = AlignmentModes.IgnoreFirstOrLast
         };
         };
@@ -119,6 +148,8 @@ public class HexEditor : Scenario
         _hexView.Source = LoadFile ();
         _hexView.Source = LoadFile ();
 
 
         Application.Run (app);
         Application.Run (app);
+        addressUpDown.Dispose ();
+        addressWidthUpDown.Dispose ();
         app.Dispose ();
         app.Dispose ();
         Application.Shutdown ();
         Application.Shutdown ();
     }
     }
@@ -127,8 +158,15 @@ public class HexEditor : Scenario
 
 
     private void _hexView_PositionChanged (object sender, HexViewEventArgs obj)
     private void _hexView_PositionChanged (object sender, HexViewEventArgs obj)
     {
     {
-        _siPositionChanged.Title =
-            $"Position: {obj.Position} Line: {obj.CursorPosition.Y} Col: {obj.CursorPosition.X} Line length: {obj.BytesPerLine}";
+        _scInfo.Title =
+            $"Bytes: {_hexView.Source!.Length}";
+        _scPosition.Title =
+            $"L: {obj.Position.Y} C: {obj.Position.X} Per Line: {obj.BytesPerLine}";
+
+        if (_scAddress.CommandView is NumericUpDown<long> addrNumericUpDown)
+        {
+            addrNumericUpDown.Value = obj.Address;
+        }
     }
     }
 
 
     private void Copy () { MessageBox.ErrorQuery ("Not Implemented", "Functionality not yet implemented.", "Ok"); }
     private void Copy () { MessageBox.ErrorQuery ("Not Implemented", "Functionality not yet implemented.", "Ok"); }
@@ -147,7 +185,7 @@ public class HexEditor : Scenario
     private void CreateUnicodeDemoFile (string fileName)
     private void CreateUnicodeDemoFile (string fileName)
     {
     {
         var sb = new StringBuilder ();
         var sb = new StringBuilder ();
-        sb.Append ("Hello world.\n");
+        sb.Append ("Hello world with wide codepoints: 𝔹Aℝ𝔽.\n");
         sb.Append ("This is a test of the Emergency Broadcast System.\n");
         sb.Append ("This is a test of the Emergency Broadcast System.\n");
 
 
         byte [] buffer = Encoding.Unicode.GetBytes (sb.ToString ());
         byte [] buffer = Encoding.Unicode.GetBytes (sb.ToString ());
@@ -169,8 +207,8 @@ public class HexEditor : Scenario
             if (MessageBox.ErrorQuery (
             if (MessageBox.ErrorQuery (
                                        "Save",
                                        "Save",
                                        "The changes were not saved. Want to open without saving?",
                                        "The changes were not saved. Want to open without saving?",
-                                       "Yes",
-                                       "No"
+                                       "_Yes",
+                                       "_No"
                                       )
                                       )
                 == 1)
                 == 1)
             {
             {
@@ -190,7 +228,7 @@ public class HexEditor : Scenario
         }
         }
         else
         else
         {
         {
-            _hexView.Title = (_fileName ?? "Untitled");
+            _hexView.Title = _fileName ?? "Untitled";
         }
         }
 
 
         return stream;
         return stream;
@@ -213,10 +251,11 @@ public class HexEditor : Scenario
             _hexView.Source = LoadFile ();
             _hexView.Source = LoadFile ();
             _hexView.DisplayStart = 0;
             _hexView.DisplayStart = 0;
         }
         }
+
         d.Dispose ();
         d.Dispose ();
     }
     }
 
 
-    private void Paste () { MessageBox.ErrorQuery ("Not Implemented", "Functionality not yet implemented.", "Ok"); }
+    private void Paste () { MessageBox.ErrorQuery ("Not Implemented", "Functionality not yet implemented.", "_Ok"); }
     private void Quit () { Application.RequestStop (); }
     private void Quit () { Application.RequestStop (); }
 
 
     private void Save ()
     private void Save ()

+ 92 - 70
UICatalog/Scenarios/Keys.cs

@@ -10,120 +10,142 @@ public class Keys : Scenario
     public override void Main ()
     public override void Main ()
     {
     {
         Application.Init ();
         Application.Init ();
-        ObservableCollection<string> keyPressedList = [];
-        ObservableCollection<string> invokingKeyBindingsList = new ();
+        ObservableCollection<string> keyDownList = [];
+        ObservableCollection<string> keyDownNotHandledList = new ();
 
 
         var win = new Window { Title = GetQuitKeyAndName () };
         var win = new Window { Title = GetQuitKeyAndName () };
-        var editLabel = new Label { X = 0, Y = 0, Text = "Type text here:" };
-        win.Add (editLabel);
 
 
-        var edit = new TextField { X = Pos.Right (editLabel) + 1, Y = Pos.Top (editLabel), Width = Dim.Fill (2) };
+        var label = new Label
+        {
+            X = 0,
+            Y = 0,
+            Text = "_Type text here:"
+        };
+        win.Add (label);
+
+        var edit = new TextField
+        {
+            X = Pos.Right (label) + 1,
+            Y = Pos.Top (label),
+            Width = Dim.Fill (2),
+            Height = 1,
+        };
         win.Add (edit);
         win.Add (edit);
 
 
-        edit.KeyDown += (s, a) => { keyPressedList.Add (a.ToString ()); };
+        label = new Label
+        {
+            X = 0,
+            Y = Pos.Bottom (label),
+            Text = "Last _Application.KeyDown:"
+        };
+        win.Add (label);
+        var labelAppKeypress = new Label
+        {
+            X = Pos.Right (label) + 1,
+            Y = Pos.Top (label)
+        };
+        win.Add (labelAppKeypress);
 
 
-        edit.InvokingKeyBindings += (s, a) =>
-                                    {
-                                        if (edit.KeyBindings.TryGet (a, out KeyBinding binding))
-                                        {
-                                            invokingKeyBindingsList.Add ($"{a}: {string.Join (",", binding.Commands)}");
-                                        }
-                                    };
+        Application.KeyDown += (s, e) => labelAppKeypress.Text = e.ToString ();
 
 
-        // Last KeyPress: ______
-        var keyPressedLabel = new Label
+        label = new ()
         {
         {
-            X = Pos.Left (editLabel), Y = Pos.Top (editLabel) + 1, Text = "Last TextView.KeyPressed:"
+            X = 0,
+            Y = Pos.Bottom (label),
+            Text = "_Last TextField.KeyDown:"
         };
         };
-        win.Add (keyPressedLabel);
-        var labelTextViewKeypress = new Label { X = Pos.Right (keyPressedLabel) + 1, Y = Pos.Top (keyPressedLabel) };
-        win.Add (labelTextViewKeypress);
-
-        edit.KeyDown += (s, e) => labelTextViewKeypress.Text = e.ToString ();
+        win.Add (label);
 
 
-        keyPressedLabel = new Label
+        var lastTextFieldKeyDownLabel = new Label
         {
         {
-            X = Pos.Left (keyPressedLabel), Y = Pos.Bottom (keyPressedLabel), Text = "Last Application.KeyDown:"
+            X = Pos.Right (label) + 1,
+            Y = Pos.Top (label),
+            Height = 1,
         };
         };
-        win.Add (keyPressedLabel);
-        var labelAppKeypress = new Label { X = Pos.Right (keyPressedLabel) + 1, Y = Pos.Top (keyPressedLabel) };
-        win.Add (labelAppKeypress);
+        win.Add (lastTextFieldKeyDownLabel);
 
 
-        Application.KeyDown += (s, e) => labelAppKeypress.Text = e.ToString ();
+        edit.KeyDown += (s, e) => lastTextFieldKeyDownLabel.Text = e.ToString ();
 
 
-        // Key stroke log:
-        var keyLogLabel = new Label
+        // Application key event log:
+        label = new Label
         {
         {
-            X = Pos.Left (editLabel), Y = Pos.Top (editLabel) + 4, Text = "Application Key Events:"
+            X = 0,
+            Y = Pos.Bottom (label) + 1,
+            Text = "Application Key Events:"
         };
         };
-        win.Add (keyLogLabel);
+        win.Add (label);
         int maxKeyString = Key.CursorRight.WithAlt.WithCtrl.WithShift.ToString ().Length;
         int maxKeyString = Key.CursorRight.WithAlt.WithCtrl.WithShift.ToString ().Length;
-        var yOffset = 1;
-        ObservableCollection<string> keyEventlist = new ();
 
 
-        var keyEventListView = new ListView
+        ObservableCollection<string> keyList = new ();
+
+        var appKeyListView = new ListView
         {
         {
             X = 0,
             X = 0,
-            Y = Pos.Top (keyLogLabel) + yOffset,
-            Width = "Key Down:".Length + maxKeyString,
+            Y = Pos.Bottom (label),
+            Width = "KeyDown:".Length + maxKeyString,
             Height = Dim.Fill (),
             Height = Dim.Fill (),
-            Source = new ListWrapper<string> (keyEventlist)
+            Source = new ListWrapper<string> (keyList)
         };
         };
-        keyEventListView.ColorScheme = Colors.ColorSchemes ["TopLevel"];
-        win.Add (keyEventListView);
+        appKeyListView.ColorScheme = Colors.ColorSchemes ["TopLevel"];
+        win.Add (appKeyListView);
+
+        // View key events...
+        edit.KeyDown += (s, a) => { keyDownList.Add (a.ToString ()); };
+
+        edit.KeyDownNotHandled += (s, a) =>
+                                  {
+                                      keyDownNotHandledList.Add ($"{a}");
+                                  };
 
 
-        // OnKeyPressed
-        var onKeyPressedLabel = new Label
+        // KeyDown
+        label = new Label
         {
         {
-            X = Pos.Right (keyEventListView) + 1, Y = Pos.Top (editLabel) + 4, Text = "TextView KeyDown:"
+            X = Pos.Right (appKeyListView) + 1,
+            Y = Pos.Top (label),
+            Text = "TextView Key Down:"
         };
         };
-        win.Add (onKeyPressedLabel);
+        win.Add (label);
 
 
-        yOffset = 1;
-
-        var onKeyPressedListView = new ListView
+        var onKeyDownListView = new ListView
         {
         {
-            X = Pos.Left (onKeyPressedLabel),
-            Y = Pos.Top (onKeyPressedLabel) + yOffset,
+            X = Pos.Left (label),
+            Y = Pos.Bottom (label),
             Width = maxKeyString,
             Width = maxKeyString,
             Height = Dim.Fill (),
             Height = Dim.Fill (),
-            Source = new ListWrapper<string> (keyPressedList)
+            Source = new ListWrapper<string> (keyDownList)
         };
         };
-        onKeyPressedListView.ColorScheme = Colors.ColorSchemes ["TopLevel"];
-        win.Add (onKeyPressedListView);
+        onKeyDownListView.ColorScheme = Colors.ColorSchemes ["TopLevel"];
+        win.Add (onKeyDownListView);
 
 
-        // OnInvokeKeyBindings
-        var onInvokingKeyBindingsLabel = new Label
+        // KeyDownNotHandled
+        label = new Label
         {
         {
-            X = Pos.Right (onKeyPressedListView) + 1,
-            Y = Pos.Top (editLabel) + 4,
-            Text = "TextView InvokingKeyBindings:"
+            X = Pos.Right (onKeyDownListView) + 1,
+            Y = Pos.Top (label),
+            Text = "TextView KeyDownNotHandled:"
         };
         };
-        win.Add (onInvokingKeyBindingsLabel);
+        win.Add (label);
 
 
-        var onInvokingKeyBindingsListView = new ListView
+        var onKeyDownNotHandledListView = new ListView
         {
         {
-            X = Pos.Left (onInvokingKeyBindingsLabel),
-            Y = Pos.Top (onInvokingKeyBindingsLabel) + yOffset,
-            Width = Dim.Fill (1),
+            X = Pos.Left (label),
+            Y = Pos.Bottom (label),
+            Width = maxKeyString,
             Height = Dim.Fill (),
             Height = Dim.Fill (),
-            Source = new ListWrapper<string> (invokingKeyBindingsList)
+            Source = new ListWrapper<string> (keyDownNotHandledList)
         };
         };
-        onInvokingKeyBindingsListView.ColorScheme = Colors.ColorSchemes ["TopLevel"];
-        win.Add (onInvokingKeyBindingsListView);
+        onKeyDownNotHandledListView.ColorScheme = Colors.ColorSchemes ["TopLevel"];
+        win.Add (onKeyDownNotHandledListView);
 
 
-        //Application.KeyDown += (s, a) => KeyDownPressUp (a, "Down");
         Application.KeyDown += (s, a) => KeyDownPressUp (a, "Down");
         Application.KeyDown += (s, a) => KeyDownPressUp (a, "Down");
         Application.KeyUp += (s, a) => KeyDownPressUp (a, "Up");
         Application.KeyUp += (s, a) => KeyDownPressUp (a, "Up");
 
 
         void KeyDownPressUp (Key args, string updown)
         void KeyDownPressUp (Key args, string updown)
         {
         {
-            // BUGBUG: KeyEvent.ToString is badly broken
             var msg = $"Key{updown,-7}: {args}";
             var msg = $"Key{updown,-7}: {args}";
-            keyEventlist.Add (msg);
-            keyEventListView.MoveDown ();
-            onKeyPressedListView.MoveDown ();
-            onInvokingKeyBindingsListView.MoveDown ();
+            keyList.Add (msg);
+            appKeyListView.MoveDown ();
+            onKeyDownNotHandledListView.MoveDown ();
         }
         }
 
 
         Application.Run (win);
         Application.Run (win);

+ 12 - 8
UICatalog/Scenarios/LineDrawing.cs

@@ -8,7 +8,7 @@ namespace UICatalog.Scenarios;
 
 
 public interface ITool
 public interface ITool
 {
 {
-    void OnMouseEvent (DrawingArea area, MouseEvent mouseEvent);
+    void OnMouseEvent (DrawingArea area, MouseEventArgs mouseEvent);
 }
 }
 
 
 internal class DrawLineTool : ITool
 internal class DrawLineTool : ITool
@@ -17,7 +17,7 @@ internal class DrawLineTool : ITool
     public LineStyle LineStyle { get; set; } = LineStyle.Single;
     public LineStyle LineStyle { get; set; } = LineStyle.Single;
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    public void OnMouseEvent (DrawingArea area, MouseEvent mouseEvent)
+    public void OnMouseEvent (DrawingArea area, MouseEventArgs mouseEvent)
     {
     {
         if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed))
         if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed))
         {
         {
@@ -96,6 +96,8 @@ internal class DrawLineTool : ITool
                 area.SetNeedsDisplay ();
                 area.SetNeedsDisplay ();
             }
             }
         }
         }
+
+        mouseEvent.Handled = true;
     }
     }
 }
 }
 
 
@@ -121,7 +123,7 @@ public class LineDrawing : Scenario
         tools.CurrentColor = canvas.GetNormalColor ();
         tools.CurrentColor = canvas.GetNormalColor ();
         canvas.CurrentAttribute = tools.CurrentColor;
         canvas.CurrentAttribute = tools.CurrentColor;
 
 
-        win.KeyDown += (s, e) => { e.Handled = canvas.OnKeyDown (e); };
+        win.KeyDown += (s, e) => { e.Handled = canvas.NewKeyDownEvent (e); };
 
 
         Application.Run (win);
         Application.Run (win);
         win.Dispose ();
         win.Dispose ();
@@ -290,7 +292,7 @@ public class DrawingArea : View
     }
     }
 
 
     //// BUGBUG: Why is this not handled by a key binding???
     //// BUGBUG: Why is this not handled by a key binding???
-    public override bool OnKeyDown (Key e)
+    protected override bool OnKeyDown (Key e)
     {
     {
         // BUGBUG: These should be implemented with key bindings
         // BUGBUG: These should be implemented with key bindings
         if (e.KeyCode == (KeyCode.Z | KeyCode.CtrlMask))
         if (e.KeyCode == (KeyCode.Z | KeyCode.CtrlMask))
@@ -321,11 +323,11 @@ public class DrawingArea : View
         return false;
         return false;
     }
     }
 
 
-    protected override bool OnMouseEvent (MouseEvent mouseEvent)
+    protected override bool OnMouseEvent (MouseEventArgs mouseEvent)
     {
     {
         CurrentTool.OnMouseEvent (this, mouseEvent);
         CurrentTool.OnMouseEvent (this, mouseEvent);
 
 
-        return base.OnMouseEvent (mouseEvent);
+        return mouseEvent.Handled;
     }
     }
 
 
     internal void AddLayer ()
     internal void AddLayer ()
@@ -429,7 +431,7 @@ public class AttributeView : View
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
-    protected override bool OnMouseEvent (MouseEvent mouseEvent)
+    protected override bool OnMouseEvent (MouseEventArgs mouseEvent)
     {
     {
         if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Clicked))
         if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Clicked))
         {
         {
@@ -441,9 +443,11 @@ public class AttributeView : View
             {
             {
                 ClickedInBackground ();
                 ClickedInBackground ();
             }
             }
+
+            mouseEvent.Handled = true;
         }
         }
 
 
-        return base.OnMouseEvent (mouseEvent);
+        return mouseEvent.Handled;
     }
     }
 
 
     private bool IsForegroundPoint (int x, int y) { return ForegroundPoints.Contains ((x, y)); }
     private bool IsForegroundPoint (int x, int y) { return ForegroundPoints.Contains ((x, y)); }

+ 1 - 1
UICatalog/Scenarios/ListColumns.cs

@@ -248,7 +248,7 @@ public class ListColumns : Scenario
         };
         };
 
 
         // if user clicks the mouse in TableView
         // if user clicks the mouse in TableView
-        _listColView.MouseClick += (s, e) => { _listColView.ScreenToCell (e.MouseEvent.Position, out int? clickedCol); };
+        _listColView.MouseClick += (s, e) => { _listColView.ScreenToCell (e.Position, out int? clickedCol); };
 
 
         _listColView.KeyBindings.ReplaceCommands (Key.Space, Command.Accept);
         _listColView.KeyBindings.ReplaceCommands (Key.Space, Command.Accept);
 
 

+ 3 - 3
UICatalog/Scenarios/Mouse.cs

@@ -251,18 +251,18 @@ public class Mouse : Scenario
 
 
         win.MouseEvent += (sender, a) =>
         win.MouseEvent += (sender, a) =>
                           {
                           {
-                              int i = filterSlider.Options.FindIndex (o => o.Data == a.MouseEvent.Flags);
+                              int i = filterSlider.Options.FindIndex (o => o.Data == a.Flags);
 
 
                               if (filterSlider.GetSetOptions ().Contains (i))
                               if (filterSlider.GetSetOptions ().Contains (i))
                               {
                               {
-                                  winLogList.Add ($"MouseEvent: ({a.MouseEvent.Position}) - {a.MouseEvent.Flags} {count++}");
+                                  winLogList.Add ($"MouseEvent: ({a.Position}) - {a.Flags} {count++}");
                                   winLog.MoveDown ();
                                   winLog.MoveDown ();
                               }
                               }
                           };
                           };
 
 
         win.MouseClick += (sender, a) =>
         win.MouseClick += (sender, a) =>
                           {
                           {
-                              winLogList.Add ($"MouseClick: ({a.MouseEvent.Position}) - {a.MouseEvent.Flags} {count++}");
+                              winLogList.Add ($"MouseClick: ({a.Position}) - {a.Flags} {count++}");
                               winLog.MoveDown ();
                               winLog.MoveDown ();
                           };
                           };
 
 

+ 5 - 5
UICatalog/Scenarios/Snake.cs

@@ -357,30 +357,30 @@ public class Snake : Scenario
         }
         }
 
 
         // BUGBUG: Should (can) this use key bindings instead.
         // BUGBUG: Should (can) this use key bindings instead.
-        public override bool OnKeyDown (Key keyEvent)
+        protected override bool OnKeyDown (Key key)
         {
         {
-            if (keyEvent.KeyCode == KeyCode.CursorUp)
+            if (key.KeyCode == KeyCode.CursorUp)
             {
             {
                 State.PlannedDirection = Direction.Up;
                 State.PlannedDirection = Direction.Up;
 
 
                 return true;
                 return true;
             }
             }
 
 
-            if (keyEvent.KeyCode == KeyCode.CursorDown)
+            if (key.KeyCode == KeyCode.CursorDown)
             {
             {
                 State.PlannedDirection = Direction.Down;
                 State.PlannedDirection = Direction.Down;
 
 
                 return true;
                 return true;
             }
             }
 
 
-            if (keyEvent.KeyCode == KeyCode.CursorLeft)
+            if (key.KeyCode == KeyCode.CursorLeft)
             {
             {
                 State.PlannedDirection = Direction.Left;
                 State.PlannedDirection = Direction.Left;
 
 
                 return true;
                 return true;
             }
             }
 
 
-            if (keyEvent.KeyCode == KeyCode.CursorRight)
+            if (key.KeyCode == KeyCode.CursorRight)
             {
             {
                 State.PlannedDirection = Direction.Right;
                 State.PlannedDirection = Direction.Right;
 
 

+ 5 - 5
UICatalog/Scenarios/TableEditor.cs

@@ -752,16 +752,16 @@ public class TableEditor : Scenario
                                          return;
                                          return;
                                      }
                                      }
 
 
-                                     _tableView.ScreenToCell (e.MouseEvent.Position, out int? clickedCol);
+                                     _tableView.ScreenToCell (e.Position, out int? clickedCol);
 
 
                                      if (clickedCol != null)
                                      if (clickedCol != null)
                                      {
                                      {
-                                         if (e.MouseEvent.Flags.HasFlag (MouseFlags.Button1Clicked))
+                                         if (e.Flags.HasFlag (MouseFlags.Button1Clicked))
                                          {
                                          {
                                              // left click in a header
                                              // left click in a header
                                              SortColumn (clickedCol.Value);
                                              SortColumn (clickedCol.Value);
                                          }
                                          }
-                                         else if (e.MouseEvent.Flags.HasFlag (MouseFlags.Button3Clicked))
+                                         else if (e.Flags.HasFlag (MouseFlags.Button3Clicked))
                                          {
                                          {
                                              // right click in a header
                                              // right click in a header
                                              ShowHeaderContextMenu (clickedCol.Value, e);
                                              ShowHeaderContextMenu (clickedCol.Value, e);
@@ -1254,7 +1254,7 @@ public class TableEditor : Scenario
         _tableView.Update ();
         _tableView.Update ();
     }
     }
 
 
-    private void ShowHeaderContextMenu (int clickedCol, MouseEventEventArgs e)
+    private void ShowHeaderContextMenu (int clickedCol, MouseEventArgs e)
     {
     {
         if (HasCheckboxes () && clickedCol == 0)
         if (HasCheckboxes () && clickedCol == 0)
         {
         {
@@ -1266,7 +1266,7 @@ public class TableEditor : Scenario
 
 
         var contextMenu = new ContextMenu
         var contextMenu = new ContextMenu
         {
         {
-            Position = new (e.MouseEvent.Position.X + 1, e.MouseEvent.Position.Y + 1)
+            Position = new (e.Position.X + 1, e.Position.Y + 1)
         };
         };
 
 
         MenuBarItem menuItems = new (
         MenuBarItem menuItems = new (

+ 1 - 1
UICatalog/Scenarios/Text.cs

@@ -177,7 +177,7 @@ public class Text : Scenario
                          new MemoryStream (Encoding.UTF8.GetBytes ("HexEditor Unicode that shouldn't 𝔹Aℝ𝔽!"))
                          new MemoryStream (Encoding.UTF8.GetBytes ("HexEditor Unicode that shouldn't 𝔹Aℝ𝔽!"))
                         )
                         )
             {
             {
-                X = Pos.Right (label) + 1, Y = Pos.Bottom (chxMultiline) + 1, Width = Dim.Percent (50) - 1, Height = Dim.Percent (30)
+                X = Pos.Right (label) + 1, Y = Pos.Bottom (chxMultiline) + 1, Width = Dim.Percent (50) - 1, Height = Dim.Percent (30),
             };
             };
         win.Add (hexEditor);
         win.Add (hexEditor);
 
 

+ 5 - 5
UICatalog/Scenarios/TreeViewFileSystem.cs

@@ -484,12 +484,12 @@ public class TreeViewFileSystem : Scenario
         }
         }
     }
     }
 
 
-    private void TreeViewFiles_MouseClick (object sender, MouseEventEventArgs obj)
+    private void TreeViewFiles_MouseClick (object sender, MouseEventArgs obj)
     {
     {
         // if user right clicks
         // if user right clicks
-        if (obj.MouseEvent.Flags.HasFlag (MouseFlags.Button3Clicked))
+        if (obj.Flags.HasFlag (MouseFlags.Button3Clicked))
         {
         {
-            IFileSystemInfo rightClicked = _treeViewFiles.GetObjectOnRow (obj.MouseEvent.Position.Y);
+            IFileSystemInfo rightClicked = _treeViewFiles.GetObjectOnRow (obj.Position.Y);
 
 
             // nothing was clicked
             // nothing was clicked
             if (rightClicked == null)
             if (rightClicked == null)
@@ -499,8 +499,8 @@ public class TreeViewFileSystem : Scenario
 
 
             ShowContextMenu (
             ShowContextMenu (
                              new Point (
                              new Point (
-                                        obj.MouseEvent.Position.X + _treeViewFiles.Frame.X,
-                                        obj.MouseEvent.Position.Y + _treeViewFiles.Frame.Y + 2
+                                        obj.Position.X + _treeViewFiles.Frame.X,
+                                        obj.Position.Y + _treeViewFiles.Frame.Y + 2
                                        ),
                                        ),
                              rightClicked
                              rightClicked
                             );
                             );

+ 3 - 3
UICatalog/Scenarios/VkeyPacketSimulator.cs

@@ -108,11 +108,11 @@ public class VkeyPacketSimulator : Scenario
                                 if (_outputStarted)
                                 if (_outputStarted)
                                 {
                                 {
                                     // If the key wasn't handled by the TextView will popup a Dialog with the keys pressed.
                                     // If the key wasn't handled by the TextView will popup a Dialog with the keys pressed.
-                                    bool? handled = tvOutput.OnInvokingKeyBindings (e, KeyBindingScope.HotKey | KeyBindingScope.Focused);
+                                    bool? handled = tvOutput.NewKeyDownEvent (e);
 
 
                                     if (handled == null || handled == false)
                                     if (handled == null || handled == false)
                                     {
                                     {
-                                        if (!tvOutput.OnProcessKeyDown (e))
+                                        if (!tvOutput.NewKeyDownEvent (e))
                                         {
                                         {
                                             Application.Invoke (
                                             Application.Invoke (
                                                                 () => MessageBox.Query (
                                                                 () => MessageBox.Query (
@@ -148,7 +148,7 @@ public class VkeyPacketSimulator : Scenario
                                }
                                }
                            };
                            };
 
 
-        tvInput.InvokingKeyBindings += (s, e) =>
+        tvInput.KeyDownNotHandled += (s, e) =>
                                        {
                                        {
                                            Key ev = e;
                                            Key ev = e;
 
 

+ 23 - 22
UICatalog/UICatalog.cs

@@ -387,6 +387,7 @@ public class UICatalogApp
         // 'app' closed cleanly.
         // 'app' closed cleanly.
         foreach (Responder? inst in Responder.Instances)
         foreach (Responder? inst in Responder.Instances)
         {
         {
+            
             Debug.Assert (inst.WasDisposed);
             Debug.Assert (inst.WasDisposed);
         }
         }
 
 
@@ -620,28 +621,28 @@ public class UICatalogApp
                                                 );
                                                 );
             ScenarioList.Style.ColumnStyles.Add (1, new () { MaxWidth = 1 });
             ScenarioList.Style.ColumnStyles.Add (1, new () { MaxWidth = 1 });
 
 
-            // Enable user to find & select a scenario by typing text
-            // TableView does not (currently) have built-in CollectionNavigator support (the ability for the 
-            // user to type and the items that match get selected). We implement it in the app instead. 
-            ScenarioList.KeyDown += (s, a) =>
-                                    {
-                                        if (CollectionNavigatorBase.IsCompatibleKey (a))
-                                        {
-                                            int? newItem =
-                                                _scenarioCollectionNav?.GetNextMatchingItem (
-                                                                                             ScenarioList.SelectedRow,
-                                                                                             (char)a
-                                                                                            );
-
-                                            if (newItem is int v && newItem != -1)
-                                            {
-                                                ScenarioList.SelectedRow = v;
-                                                ScenarioList.EnsureSelectedCellIsVisible ();
-                                                ScenarioList.SetNeedsDisplay ();
-                                                a.Handled = true;
-                                            }
-                                        }
-                                    };
+            //// Enable user to find & select a scenario by typing text
+            //// TableView does not (currently) have built-in CollectionNavigator support (the ability for the 
+            //// user to type and the items that match get selected). We implement it in the app instead. 
+            //ScenarioList.KeyDown += (s, a) =>
+            //                        {
+            //                            if (CollectionNavigatorBase.IsCompatibleKey (a))
+            //                            {
+            //                                int? newItem =
+            //                                    _scenarioCollectionNav?.GetNextMatchingItem (
+            //                                                                                 ScenarioList.SelectedRow,
+            //                                                                                 (char)a
+            //                                                                                );
+
+            //                                if (newItem is int v && newItem != -1)
+            //                                {
+            //                                    ScenarioList.SelectedRow = v;
+            //                                    ScenarioList.EnsureSelectedCellIsVisible ();
+            //                                    ScenarioList.SetNeedsDisplay ();
+            //                                    a.Handled = true;
+            //                                }
+            //                            }
+            //                        };
             ScenarioList.CellActivated += ScenarioView_OpenSelectedItem;
             ScenarioList.CellActivated += ScenarioView_OpenSelectedItem;
 
 
             // TableView typically is a grid where nav keys are biased for moving left/right.
             // TableView typically is a grid where nav keys are biased for moving left/right.

+ 3 - 3
UnitTests/Application/Application.NavigationTests.cs

@@ -68,7 +68,7 @@ public class ApplicationNavigationTests (ITestOutputHelper output)
 
 
         Application.Navigation.FocusedChanged += ApplicationNavigationOnFocusedChanged;
         Application.Navigation.FocusedChanged += ApplicationNavigationOnFocusedChanged;
 
 
-        Application.Navigation.SetFocused (new ());
+        Application.Navigation.SetFocused (new () { CanFocus = true, HasFocus = true });
 
 
         Assert.True (raised);
         Assert.True (raised);
 
 
@@ -89,7 +89,7 @@ public class ApplicationNavigationTests (ITestOutputHelper output)
     {
     {
         Application.Navigation = new ();
         Application.Navigation = new ();
 
 
-        Application.Top = new()
+        Application.Top = new ()
         {
         {
             Id = "top",
             Id = "top",
             CanFocus = true
             CanFocus = true
@@ -125,7 +125,7 @@ public class ApplicationNavigationTests (ITestOutputHelper output)
     {
     {
         Application.Navigation = new ();
         Application.Navigation = new ();
 
 
-        Application.Top = new()
+        Application.Top = new ()
         {
         {
             Id = "top",
             Id = "top",
             CanFocus = true
             CanFocus = true

+ 7 - 7
UnitTests/Application/ApplicationTests.cs

@@ -856,7 +856,7 @@ public class ApplicationTests
                                      }
                                      }
                                      else if (iteration < 3)
                                      else if (iteration < 3)
                                      {
                                      {
-                                         Application.OnMouseEvent (new () { Flags = MouseFlags.ReportMousePosition });
+                                         Application.RaiseMouseEvent (new () { Flags = MouseFlags.ReportMousePosition });
                                          Assert.False (top.NeedsDisplay);
                                          Assert.False (top.NeedsDisplay);
                                          Assert.False (top.SubViewNeedsDisplay);
                                          Assert.False (top.SubViewNeedsDisplay);
                                          Assert.False (top.LayoutNeeded);
                                          Assert.False (top.LayoutNeeded);
@@ -895,12 +895,12 @@ public class ApplicationTests
         // Don't use visuals to test as style of border can change over time.
         // Don't use visuals to test as style of border can change over time.
         Assert.Equal (new (0, 0), w.Frame.Location);
         Assert.Equal (new (0, 0), w.Frame.Location);
 
 
-        Application.OnMouseEvent (new () { Flags = MouseFlags.Button1Pressed });
+        Application.RaiseMouseEvent (new () { Flags = MouseFlags.Button1Pressed });
         Assert.Equal (w.Border, Application.MouseGrabView);
         Assert.Equal (w.Border, Application.MouseGrabView);
         Assert.Equal (new (0, 0), w.Frame.Location);
         Assert.Equal (new (0, 0), w.Frame.Location);
 
 
         // Move down and to the right.
         // Move down and to the right.
-        Application.OnMouseEvent (new () { ScreenPosition = new (1, 1), Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition });
+        Application.RaiseMouseEvent (new () { ScreenPosition = new (1, 1), Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition });
         Assert.Equal (new (1, 1), w.Frame.Location);
         Assert.Equal (new (1, 1), w.Frame.Location);
 
 
         Application.End (rs);
         Application.End (rs);
@@ -939,10 +939,10 @@ public class ApplicationTests
         w.Dispose ();
         w.Dispose ();
         Assert.True (w.WasDisposed);
         Assert.True (w.WasDisposed);
 
 
-        exception = Record.Exception (
-                                      () => Application.Run (
-                                                             w)); // Invalid - w has been disposed. Run it in debug mode will throw, otherwise the user may want to run it again
-        Assert.NotNull (exception);
+        //exception = Record.Exception (
+        //                              () => Application.Run (
+        //                                                     w)); // Invalid - w has been disposed. Run it in debug mode will throw, otherwise the user may want to run it again
+        //Assert.NotNull (exception);
 
 
         exception = Record.Exception (() => Assert.Equal (string.Empty, w.Title)); // Invalid - w has been disposed and cannot be accessed
         exception = Record.Exception (() => Assert.Equal (string.Empty, w.Title)); // Invalid - w has been disposed and cannot be accessed
         Assert.NotNull (exception);
         Assert.NotNull (exception);

+ 45 - 45
UnitTests/Application/KeyboardTests.cs

@@ -64,14 +64,14 @@ public class KeyboardTests
         Assert.True (win2.HasFocus);
         Assert.True (win2.HasFocus);
         Assert.Equal ("win2", ((Window)top.Subviews [^1]).Title);
         Assert.Equal ("win2", ((Window)top.Subviews [^1]).Title);
 
 
-        Application.OnKeyDown (Key.F6);
+        Application.RaiseKeyDownEvent (Key.F6);
         Assert.True (win2.CanFocus);
         Assert.True (win2.CanFocus);
         Assert.False (win.HasFocus);
         Assert.False (win.HasFocus);
         Assert.True (win2.CanFocus);
         Assert.True (win2.CanFocus);
         Assert.True (win2.HasFocus);
         Assert.True (win2.HasFocus);
         Assert.Equal ("win2", ((Window)top.Subviews [^1]).Title);
         Assert.Equal ("win2", ((Window)top.Subviews [^1]).Title);
 
 
-        Application.OnKeyDown (Key.F6);
+        Application.RaiseKeyDownEvent (Key.F6);
         Assert.False (win.CanFocus);
         Assert.False (win.CanFocus);
         Assert.False (win.HasFocus);
         Assert.False (win.HasFocus);
         Assert.True (win2.CanFocus);
         Assert.True (win2.CanFocus);
@@ -117,14 +117,14 @@ public class KeyboardTests
         Assert.False (win2.HasFocus);
         Assert.False (win2.HasFocus);
         Assert.Equal ("win", ((Window)top.Subviews [^1]).Title);
         Assert.Equal ("win", ((Window)top.Subviews [^1]).Title);
 
 
-        Application.OnKeyDown (Key.F6);
+        Application.RaiseKeyDownEvent (Key.F6);
         Assert.True (win.CanFocus);
         Assert.True (win.CanFocus);
         Assert.False (win.HasFocus);
         Assert.False (win.HasFocus);
         Assert.True (win2.CanFocus);
         Assert.True (win2.CanFocus);
         Assert.True (win2.HasFocus);
         Assert.True (win2.HasFocus);
         Assert.Equal ("win2", ((Window)top.Subviews [^1]).Title);
         Assert.Equal ("win2", ((Window)top.Subviews [^1]).Title);
 
 
-        Application.OnKeyDown (Key.F6);
+        Application.RaiseKeyDownEvent (Key.F6);
         Assert.True (win.CanFocus);
         Assert.True (win.CanFocus);
         Assert.True (win.HasFocus);
         Assert.True (win.HasFocus);
         Assert.True (win2.CanFocus);
         Assert.True (win2.CanFocus);
@@ -163,39 +163,39 @@ public class KeyboardTests
     public void KeyBinding_OnKeyDown ()
     public void KeyBinding_OnKeyDown ()
     {
     {
         var view = new ScopedKeyBindingView ();
         var view = new ScopedKeyBindingView ();
-        var invoked = false;
-        view.InvokingKeyBindings += (s, e) => invoked = true;
+        var keyWasHandled = false;
+        view.KeyDownNotHandled += (s, e) => keyWasHandled = true;
 
 
         var top = new Toplevel ();
         var top = new Toplevel ();
         top.Add (view);
         top.Add (view);
         Application.Begin (top);
         Application.Begin (top);
 
 
-        Application.OnKeyDown (Key.A);
-        Assert.False (invoked);
+        Application.RaiseKeyDownEvent (Key.A);
+        Assert.False (keyWasHandled);
         Assert.True (view.ApplicationCommand);
         Assert.True (view.ApplicationCommand);
 
 
-        invoked = false;
+        keyWasHandled = false;
         view.ApplicationCommand = false;
         view.ApplicationCommand = false;
         Application.KeyBindings.Remove (KeyCode.A);
         Application.KeyBindings.Remove (KeyCode.A);
-        Application.OnKeyDown (Key.A); // old
-        Assert.False (invoked);
+        Application.RaiseKeyDownEvent (Key.A); // old
+        Assert.False (keyWasHandled);
         Assert.False (view.ApplicationCommand);
         Assert.False (view.ApplicationCommand);
         Application.KeyBindings.Add (Key.A.WithCtrl, view, Command.Save);
         Application.KeyBindings.Add (Key.A.WithCtrl, view, Command.Save);
-        Application.OnKeyDown (Key.A); // old
-        Assert.False (invoked);
+        Application.RaiseKeyDownEvent (Key.A); // old
+        Assert.False (keyWasHandled);
         Assert.False (view.ApplicationCommand);
         Assert.False (view.ApplicationCommand);
-        Application.OnKeyDown (Key.A.WithCtrl); // new
-        Assert.False (invoked);
+        Application.RaiseKeyDownEvent (Key.A.WithCtrl); // new
+        Assert.False (keyWasHandled);
         Assert.True (view.ApplicationCommand);
         Assert.True (view.ApplicationCommand);
 
 
-        invoked = false;
-        Application.OnKeyDown (Key.H);
-        Assert.True (invoked);
+        keyWasHandled = false;
+        Application.RaiseKeyDownEvent (Key.H);
+        Assert.False (keyWasHandled);
 
 
-        invoked = false;
+        keyWasHandled = false;
         Assert.False (view.HasFocus);
         Assert.False (view.HasFocus);
-        Application.OnKeyDown (Key.F);
-        Assert.False (invoked);
+        Application.RaiseKeyDownEvent (Key.F);
+        Assert.False (keyWasHandled);
 
 
         Assert.True (view.ApplicationCommand);
         Assert.True (view.ApplicationCommand);
         Assert.True (view.HotKeyCommand);
         Assert.True (view.HotKeyCommand);
@@ -208,23 +208,23 @@ public class KeyboardTests
     public void KeyBinding_OnKeyDown_Negative ()
     public void KeyBinding_OnKeyDown_Negative ()
     {
     {
         var view = new ScopedKeyBindingView ();
         var view = new ScopedKeyBindingView ();
-        var invoked = false;
-        view.InvokingKeyBindings += (s, e) => invoked = true;
+        var keyWasHandled = false;
+        view.KeyDownNotHandled += (s, e) => keyWasHandled = true;
 
 
         var top = new Toplevel ();
         var top = new Toplevel ();
         top.Add (view);
         top.Add (view);
         Application.Begin (top);
         Application.Begin (top);
 
 
-        Application.OnKeyDown (Key.A.WithCtrl);
-        Assert.False (invoked);
+        Application.RaiseKeyDownEvent (Key.A.WithCtrl);
+        Assert.False (keyWasHandled);
         Assert.False (view.ApplicationCommand);
         Assert.False (view.ApplicationCommand);
         Assert.False (view.HotKeyCommand);
         Assert.False (view.HotKeyCommand);
         Assert.False (view.FocusedCommand);
         Assert.False (view.FocusedCommand);
 
 
-        invoked = false;
+        keyWasHandled = false;
         Assert.False (view.HasFocus);
         Assert.False (view.HasFocus);
-        Application.OnKeyDown (Key.Z);
-        Assert.False (invoked);
+        Application.RaiseKeyDownEvent (Key.Z);
+        Assert.False (keyWasHandled);
         Assert.False (view.ApplicationCommand);
         Assert.False (view.ApplicationCommand);
         Assert.False (view.HotKeyCommand);
         Assert.False (view.HotKeyCommand);
         Assert.False (view.FocusedCommand);
         Assert.False (view.FocusedCommand);
@@ -399,7 +399,7 @@ public class KeyboardTests
         Assert.True (subView1.HasFocus);
         Assert.True (subView1.HasFocus);
 
 
         // Act
         // Act
-        Application.OnKeyDown (Application.NextTabGroupKey);
+        Application.RaiseKeyDownEvent (Application.NextTabGroupKey);
 
 
         // Assert
         // Assert
         Assert.True (view2.HasFocus);
         Assert.True (view2.HasFocus);
@@ -432,24 +432,24 @@ public class KeyboardTests
                                      Assert.True (v1.HasFocus);
                                      Assert.True (v1.HasFocus);
 
 
                                      // Across TabGroups
                                      // Across TabGroups
-                                     Application.OnKeyDown (Key.F6);
+                                     Application.RaiseKeyDownEvent (Key.F6);
                                      Assert.True (v3.HasFocus);
                                      Assert.True (v3.HasFocus);
-                                     Application.OnKeyDown (Key.F6);
+                                     Application.RaiseKeyDownEvent (Key.F6);
                                      Assert.True (v1.HasFocus);
                                      Assert.True (v1.HasFocus);
 
 
-                                     Application.OnKeyDown (Key.F6.WithShift);
+                                     Application.RaiseKeyDownEvent (Key.F6.WithShift);
                                      Assert.True (v3.HasFocus);
                                      Assert.True (v3.HasFocus);
-                                     Application.OnKeyDown (Key.F6.WithShift);
+                                     Application.RaiseKeyDownEvent (Key.F6.WithShift);
                                      Assert.True (v1.HasFocus);
                                      Assert.True (v1.HasFocus);
 
 
                                      // Restore?
                                      // Restore?
-                                     Application.OnKeyDown (Key.Tab);
+                                     Application.RaiseKeyDownEvent (Key.Tab);
                                      Assert.True (v2.HasFocus);
                                      Assert.True (v2.HasFocus);
 
 
-                                     Application.OnKeyDown (Key.F6);
+                                     Application.RaiseKeyDownEvent (Key.F6);
                                      Assert.True (v3.HasFocus);
                                      Assert.True (v3.HasFocus);
 
 
-                                     Application.OnKeyDown (Key.F6);
+                                     Application.RaiseKeyDownEvent (Key.F6);
                                      Assert.True (v1.HasFocus);
                                      Assert.True (v1.HasFocus);
 
 
                                      Application.RequestStop ();
                                      Application.RequestStop ();
@@ -485,7 +485,7 @@ public class KeyboardTests
         view1.SetFocus ();
         view1.SetFocus ();
 
 
         // Act
         // Act
-        Application.OnKeyDown (Application.NextTabKey);
+        Application.RaiseKeyDownEvent (Application.NextTabKey);
 
 
         // Assert
         // Assert
         Assert.True (view2.HasFocus);
         Assert.True (view2.HasFocus);
@@ -539,7 +539,7 @@ public class KeyboardTests
         Assert.True (subView1.HasFocus);
         Assert.True (subView1.HasFocus);
 
 
         // Act
         // Act
-        Application.OnKeyDown (Application.PrevTabGroupKey);
+        Application.RaiseKeyDownEvent (Application.PrevTabGroupKey);
 
 
         // Assert
         // Assert
         Assert.True (view2.HasFocus);
         Assert.True (view2.HasFocus);
@@ -562,7 +562,7 @@ public class KeyboardTests
         view1.SetFocus ();
         view1.SetFocus ();
 
 
         // Act
         // Act
-        Application.OnKeyDown (Application.NextTabKey);
+        Application.RaiseKeyDownEvent (Application.NextTabKey);
 
 
         // Assert
         // Assert
         Assert.True (view2.HasFocus);
         Assert.True (view2.HasFocus);
@@ -605,21 +605,21 @@ public class KeyboardTests
 
 
         Key prevKey = Application.QuitKey;
         Key prevKey = Application.QuitKey;
 
 
-        Application.OnKeyDown (Application.QuitKey);
+        Application.RaiseKeyDownEvent (Application.QuitKey);
         Assert.True (isQuiting);
         Assert.True (isQuiting);
 
 
         isQuiting = false;
         isQuiting = false;
-        Application.OnKeyDown (Application.QuitKey);
+        Application.RaiseKeyDownEvent (Application.QuitKey);
         Assert.True (isQuiting);
         Assert.True (isQuiting);
 
 
         isQuiting = false;
         isQuiting = false;
         Application.QuitKey = Key.C.WithCtrl;
         Application.QuitKey = Key.C.WithCtrl;
-        Application.OnKeyDown (prevKey); // Should not quit
+        Application.RaiseKeyDownEvent (prevKey); // Should not quit
         Assert.False (isQuiting);
         Assert.False (isQuiting);
-        Application.OnKeyDown (Key.Q.WithCtrl); // Should not quit
+        Application.RaiseKeyDownEvent (Key.Q.WithCtrl); // Should not quit
         Assert.False (isQuiting);
         Assert.False (isQuiting);
 
 
-        Application.OnKeyDown (Application.QuitKey);
+        Application.RaiseKeyDownEvent (Application.QuitKey);
         Assert.True (isQuiting);
         Assert.True (isQuiting);
 
 
         // Reset the QuitKey to avoid throws errors on another tests
         // Reset the QuitKey to avoid throws errors on another tests
@@ -728,7 +728,7 @@ public class KeyboardTests
             if (Application.IsInitialized)
             if (Application.IsInitialized)
             {
             {
                 _output.WriteLine ("  Pressing QuitKey");
                 _output.WriteLine ("  Pressing QuitKey");
-                Application.OnKeyDown (Application.QuitKey);
+                Application.RaiseKeyDownEvent (Application.QuitKey);
             }
             }
         }
         }
     }
     }

+ 3 - 3
UnitTests/Application/Mouse/ApplicationMouseEnterLeaveTests.cs

@@ -47,7 +47,7 @@ public class ApplicationMouseEnterLeaveTests
         var mousePosition = new Point (1, 1);
         var mousePosition = new Point (1, 1);
         List<View> currentViewsUnderMouse = new () { view };
         List<View> currentViewsUnderMouse = new () { view };
 
 
-        var mouseEvent = new MouseEvent
+        var mouseEvent = new MouseEventArgs
         {
         {
             Position = mousePosition,
             Position = mousePosition,
             ScreenPosition = mousePosition
             ScreenPosition = mousePosition
@@ -80,7 +80,7 @@ public class ApplicationMouseEnterLeaveTests
         Application.Top.Add (view);
         Application.Top.Add (view);
         var mousePosition = new Point (0, 0);
         var mousePosition = new Point (0, 0);
         List<View> currentViewsUnderMouse = new ();
         List<View> currentViewsUnderMouse = new ();
-        var mouseEvent = new MouseEvent ();
+        var mouseEvent = new MouseEventArgs ();
 
 
         Application._cachedViewsUnderMouse.Clear ();
         Application._cachedViewsUnderMouse.Clear ();
         Application._cachedViewsUnderMouse.Add (view);
         Application._cachedViewsUnderMouse.Add (view);
@@ -203,7 +203,7 @@ public class ApplicationMouseEnterLeaveTests
         Application.Top.Add (view);
         Application.Top.Add (view);
         var mousePosition = new Point (0, 0);
         var mousePosition = new Point (0, 0);
         List<View> currentViewsUnderMouse = new ();
         List<View> currentViewsUnderMouse = new ();
-        var mouseEvent = new MouseEvent ();
+        var mouseEvent = new MouseEventArgs ();
 
 
         Application._cachedViewsUnderMouse.Clear ();
         Application._cachedViewsUnderMouse.Clear ();
 
 

+ 16 - 16
UnitTests/Application/Mouse/ApplicationMouseTests.cs

@@ -42,10 +42,10 @@ public class ApplicationMouseTests
         bool expectedClicked
         bool expectedClicked
     )
     )
     {
     {
-        var mouseEvent = new MouseEvent { ScreenPosition = new (clickX, clickY), Flags = MouseFlags.Button1Pressed };
+        var mouseEvent = new MouseEventArgs { ScreenPosition = new (clickX, clickY), Flags = MouseFlags.Button1Pressed };
         var clicked = false;
         var clicked = false;
 
 
-        void OnApplicationOnMouseEvent (object s, MouseEvent e)
+        void OnApplicationOnMouseEvent (object s, MouseEventArgs e)
         {
         {
             Assert.Equal (expectedX, e.ScreenPosition.X);
             Assert.Equal (expectedX, e.ScreenPosition.X);
             Assert.Equal (expectedY, e.ScreenPosition.Y);
             Assert.Equal (expectedY, e.ScreenPosition.Y);
@@ -54,7 +54,7 @@ public class ApplicationMouseTests
 
 
         Application.MouseEvent += OnApplicationOnMouseEvent;
         Application.MouseEvent += OnApplicationOnMouseEvent;
 
 
-        Application.OnMouseEvent (mouseEvent);
+        Application.RaiseMouseEvent (mouseEvent);
         Assert.Equal (expectedClicked, clicked);
         Assert.Equal (expectedClicked, clicked);
         Application.MouseEvent -= OnApplicationOnMouseEvent;
         Application.MouseEvent -= OnApplicationOnMouseEvent;
     }
     }
@@ -116,12 +116,12 @@ public class ApplicationMouseTests
             Height = size.Height
             Height = size.Height
         };
         };
 
 
-        var mouseEvent = new MouseEvent { ScreenPosition = new (clickX, clickY), Flags = MouseFlags.Button1Clicked };
+        var mouseEvent = new MouseEventArgs { ScreenPosition = new (clickX, clickY), Flags = MouseFlags.Button1Clicked };
 
 
         view.MouseClick += (s, e) =>
         view.MouseClick += (s, e) =>
                            {
                            {
-                               Assert.Equal (expectedX, e.MouseEvent.Position.X);
-                               Assert.Equal (expectedY, e.MouseEvent.Position.Y);
+                               Assert.Equal (expectedX, e.Position.X);
+                               Assert.Equal (expectedY, e.Position.Y);
                                clicked = true;
                                clicked = true;
                            };
                            };
 
 
@@ -129,7 +129,7 @@ public class ApplicationMouseTests
         top.Add (view);
         top.Add (view);
         Application.Begin (top);
         Application.Begin (top);
 
 
-        Application.OnMouseEvent (mouseEvent);
+        Application.RaiseMouseEvent (mouseEvent);
         Assert.Equal (expectedClicked, clicked);
         Assert.Equal (expectedClicked, clicked);
         top.Dispose ();
         top.Dispose ();
     }
     }
@@ -218,16 +218,16 @@ public class ApplicationMouseTests
 
 
         Application.Top.Add (view);
         Application.Top.Add (view);
 
 
-        var mouseEvent = new MouseEvent { Position = new (clickX, clickY), ScreenPosition = new (clickX, clickY), Flags = MouseFlags.Button1Clicked };
+        var mouseEvent = new MouseEventArgs { Position = new (clickX, clickY), ScreenPosition = new (clickX, clickY), Flags = MouseFlags.Button1Clicked };
 
 
         view.MouseClick += (s, e) =>
         view.MouseClick += (s, e) =>
                            {
                            {
-                               Assert.Equal (expectedX, e.MouseEvent.Position.X);
-                               Assert.Equal (expectedY, e.MouseEvent.Position.Y);
+                               Assert.Equal (expectedX, e.Position.X);
+                               Assert.Equal (expectedY, e.Position.Y);
                                clicked = true;
                                clicked = true;
                            };
                            };
 
 
-        Application.OnMouseEvent (mouseEvent);
+        Application.RaiseMouseEvent (mouseEvent);
         Assert.Equal (expectedClicked, clicked);
         Assert.Equal (expectedClicked, clicked);
         Application.Top.Dispose ();
         Application.Top.Dispose ();
         Application.ResetState (ignoreDisposed: true);
         Application.ResetState (ignoreDisposed: true);
@@ -261,7 +261,7 @@ public class ApplicationMouseTests
                                          Assert.True (tf.HasFocus);
                                          Assert.True (tf.HasFocus);
                                          Assert.Null (Application.MouseGrabView);
                                          Assert.Null (Application.MouseGrabView);
 
 
-                                         Application.OnMouseEvent (new () { ScreenPosition = new (5, 5), Flags = MouseFlags.ReportMousePosition });
+                                         Application.RaiseMouseEvent (new () { ScreenPosition = new (5, 5), Flags = MouseFlags.ReportMousePosition });
 
 
                                          Assert.Equal (sv, Application.MouseGrabView);
                                          Assert.Equal (sv, Application.MouseGrabView);
 
 
@@ -275,15 +275,15 @@ public class ApplicationMouseTests
                                          // another toplevel (Dialog) was opened
                                          // another toplevel (Dialog) was opened
                                          Assert.Null (Application.MouseGrabView);
                                          Assert.Null (Application.MouseGrabView);
 
 
-                                         Application.OnMouseEvent (new () { ScreenPosition = new (5, 5), Flags = MouseFlags.ReportMousePosition });
+                                         Application.RaiseMouseEvent (new () { ScreenPosition = new (5, 5), Flags = MouseFlags.ReportMousePosition });
 
 
                                          Assert.Null (Application.MouseGrabView);
                                          Assert.Null (Application.MouseGrabView);
 
 
-                                         Application.OnMouseEvent (new () { ScreenPosition = new (40, 12), Flags = MouseFlags.ReportMousePosition });
+                                         Application.RaiseMouseEvent (new () { ScreenPosition = new (40, 12), Flags = MouseFlags.ReportMousePosition });
 
 
                                          Assert.Null (Application.MouseGrabView);
                                          Assert.Null (Application.MouseGrabView);
 
 
-                                         Application.OnMouseEvent (new () { ScreenPosition = new (0, 0), Flags = MouseFlags.Button1Pressed });
+                                         Application.RaiseMouseEvent (new () { ScreenPosition = new (0, 0), Flags = MouseFlags.Button1Pressed });
 
 
                                          Assert.Null (Application.MouseGrabView);
                                          Assert.Null (Application.MouseGrabView);
 
 
@@ -402,7 +402,7 @@ public class ApplicationMouseTests
         Assert.True (view.WasDisposed);
         Assert.True (view.WasDisposed);
 #endif
 #endif
 
 
-        Application.OnMouseEvent (new () { ScreenPosition = new (0, 0), Flags = MouseFlags.Button1Pressed });
+        Application.RaiseMouseEvent (new () { ScreenPosition = new (0, 0), Flags = MouseFlags.Button1Pressed });
         Assert.Null (Application.MouseGrabView);
         Assert.Null (Application.MouseGrabView);
         Assert.Equal (0, count);
         Assert.Equal (0, count);
         top.Dispose ();
         top.Dispose ();

+ 5 - 5
UnitTests/Dialogs/MessageBoxTests.cs

@@ -33,14 +33,14 @@ public class MessageBoxTests
 
 
                                          case 2:
                                          case 2:
                                              // Tab to btn2
                                              // Tab to btn2
-                                             Application.OnKeyDown (Key.Tab);
+                                             Application.RaiseKeyDownEvent (Key.Tab);
 
 
                                              Button btn = Application.Navigation!.GetFocused () as Button;
                                              Button btn = Application.Navigation!.GetFocused () as Button;
 
 
                                              btn.Accepting += (sender, e) => { btnAcceptCount++; };
                                              btn.Accepting += (sender, e) => { btnAcceptCount++; };
 
 
                                              // Click
                                              // Click
-                                             Application.OnKeyDown (Key.Enter);
+                                             Application.RaiseKeyDownEvent (Key.Enter);
 
 
                                              break;
                                              break;
 
 
@@ -77,7 +77,7 @@ public class MessageBoxTests
                                              break;
                                              break;
 
 
                                          case 2:
                                          case 2:
-                                             Application.OnKeyDown (Key.Esc);
+                                             Application.RaiseKeyDownEvent (Key.Esc);
 
 
                                              break;
                                              break;
 
 
@@ -116,13 +116,13 @@ public class MessageBoxTests
 
 
                                          case 2:
                                          case 2:
                                              // Tab to btn2
                                              // Tab to btn2
-                                             Application.OnKeyDown (Key.Tab);
+                                             Application.RaiseKeyDownEvent (Key.Tab);
 
 
                                              Button btn = Application.Navigation!.GetFocused () as Button;
                                              Button btn = Application.Navigation!.GetFocused () as Button;
 
 
                                              btn.Accepting += (sender, e) => { btnAcceptCount++; };
                                              btn.Accepting += (sender, e) => { btnAcceptCount++; };
 
 
-                                             Application.OnKeyDown (Key.Space);
+                                             Application.RaiseKeyDownEvent (Key.Space);
 
 
                                              break;
                                              break;
 
 

+ 6 - 4
UnitTests/FileServices/FileDialogTests.cs

@@ -140,7 +140,7 @@ public class FileDialogTests ()
         AssertIsTheStartingDirectory (dlg.Path);
         AssertIsTheStartingDirectory (dlg.Path);
 
 
         Assert.IsType<TextField> (dlg.MostFocused);
         Assert.IsType<TextField> (dlg.MostFocused);
-        Send ('v', ConsoleKey.DownArrow);
+        Application.RaiseKeyDownEvent (Key.CursorDown);
 
 
         var tv = GetTableView(dlg);
         var tv = GetTableView(dlg);
         tv.SetFocus ();
         tv.SetFocus ();
@@ -152,15 +152,17 @@ public class FileDialogTests ()
         AssertIsTheStartingDirectory (dlg.Path);
         AssertIsTheStartingDirectory (dlg.Path);
 
 
         // Accept navigation up a directory
         // Accept navigation up a directory
-        Send ('\n', ConsoleKey.Enter);
+        Application.RaiseKeyDownEvent (Key.Enter);
 
 
         AssertIsTheRootDirectory (dlg.Path);
         AssertIsTheRootDirectory (dlg.Path);
 
 
         Assert.True (dlg.Canceled);
         Assert.True (dlg.Canceled);
         Assert.False (selected);
         Assert.False (selected);
 
 
-        // Now press the back button (in table view)
-        Send ('<', ConsoleKey.Backspace);
+        Assert.IsType<TableView> (dlg.MostFocused);
+
+        // Now press Backspace (in table view)
+        Application.RaiseKeyDownEvent (Key.Backspace);
 
 
         // Should move us back to the root
         // Should move us back to the root
         AssertIsTheStartingDirectory (dlg.Path);
         AssertIsTheStartingDirectory (dlg.Path);

+ 2 - 2
UnitTests/Input/EscSeqUtilsTests.cs

@@ -696,7 +696,7 @@ public class EscSeqUtilsTests
         top.Add (view);
         top.Add (view);
         Application.Begin (top);
         Application.Begin (top);
 
 
-        Application.OnMouseEvent (new() { Position = new (0, 0), Flags = 0 });
+        Application.RaiseMouseEvent (new() { Position = new (0, 0), Flags = 0 });
 
 
         ClearAll ();
         ClearAll ();
 
 
@@ -753,7 +753,7 @@ public class EscSeqUtilsTests
                                          // set Application.WantContinuousButtonPressedView to null
                                          // set Application.WantContinuousButtonPressedView to null
                                          view.WantContinuousButtonPressed = false;
                                          view.WantContinuousButtonPressed = false;
 
 
-                                         Application.OnMouseEvent (new() { Position = new (0, 0), Flags = 0 });
+                                         Application.RaiseMouseEvent (new() { Position = new (0, 0), Flags = 0 });
 
 
                                          Application.RequestStop ();
                                          Application.RequestStop ();
                                      }
                                      }

+ 6 - 6
UnitTests/Input/ResponderTests.cs

@@ -205,11 +205,11 @@ public class ResponderTests
         var r = new View ();
         var r = new View ();
         var args = new Key { KeyCode = KeyCode.Null };
         var args = new Key { KeyCode = KeyCode.Null };
 
 
-        Assert.False (r.OnKeyDown (args));
+        Assert.False (r.NewKeyDownEvent (args));
         Assert.False (args.Handled);
         Assert.False (args.Handled);
 
 
         r.KeyDown += (s, a) => a.Handled = true;
         r.KeyDown += (s, a) => a.Handled = true;
-        Assert.True (r.OnKeyDown (args));
+        Assert.True (r.NewKeyDownEvent (args));
         Assert.True (args.Handled);
         Assert.True (args.Handled);
 
 
         r.Dispose ();
         r.Dispose ();
@@ -232,9 +232,9 @@ public class ResponderTests
         var r = new View ();
         var r = new View ();
 
 
         //Assert.False (r.OnKeyDown (new KeyEventArgs () { Key = Key.Unknown }));
         //Assert.False (r.OnKeyDown (new KeyEventArgs () { Key = Key.Unknown }));
-        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.NewKeyDownEvent (new Key { KeyCode = KeyCode.Null }));
+        Assert.False (r.NewKeyDownEvent (new Key { KeyCode = KeyCode.Null }));
+        Assert.False (r.NewMouseEvent (new MouseEventArgs { Flags = MouseFlags.AllEvents }));
 
 
         var v = new View ();
         var v = new View ();
         //Assert.False (r.OnEnter (v));
         //Assert.False (r.OnEnter (v));
@@ -293,6 +293,6 @@ public class ResponderTests
 
 
     public class DerivedView : View
     public class DerivedView : View
     {
     {
-        public override bool OnKeyDown (Key keyEvent) { return true; }
+        protected override bool OnKeyDown (Key keyEvent) { return true; }
     }
     }
 }
 }

+ 33 - 0
UnitTests/LocalPackagesTests.cs

@@ -0,0 +1,33 @@
+namespace Terminal.Gui;
+
+public class LocalPackagesTests
+{
+    private readonly string _localPackagesPath;
+
+    public LocalPackagesTests ()
+    {
+        // Define the local_packages path relative to the solution directory
+        _localPackagesPath = Path.Combine (Directory.GetCurrentDirectory (), "..", "..", "..", "..", "local_packages");
+    }
+
+    [Fact]
+    public void LocalPackagesFolderExists ()
+    {
+        Assert.True (Directory.Exists (_localPackagesPath),
+                     $"The local_packages folder does not exist: {_localPackagesPath}");
+    }
+
+    [Fact]
+    public void NupkgFilesExist ()
+    {
+        var nupkgFiles = Directory.GetFiles (_localPackagesPath, "*.nupkg");
+        Assert.NotEmpty (nupkgFiles);
+    }
+
+    [Fact]
+    public void SnupkgFilesExist ()
+    {
+        var snupkgFiles = Directory.GetFiles (_localPackagesPath, "*.snupkg");
+        Assert.NotEmpty (snupkgFiles);
+    }
+}

+ 1 - 1
UnitTests/UICatalog/ScenarioTests.cs

@@ -132,7 +132,7 @@ public class ScenarioTests : TestsAllViews
             {
             {
                 // Press QuitKey 
                 // Press QuitKey 
                 //_output.WriteLine ($"Forcing Quit with {Application.QuitKey}");
                 //_output.WriteLine ($"Forcing Quit with {Application.QuitKey}");
-                Application.OnKeyDown (Application.QuitKey);
+                Application.RaiseKeyDownEvent (Application.QuitKey);
             }
             }
         }
         }
     }
     }

Some files were not shown because too many files changed in this diff