瀏覽代碼

Merge branch 'v2_develop' into v2_2432-DimAuto

Tig 1 年之前
父節點
當前提交
acaa326c51

+ 120 - 6
Terminal.Gui/Application.cs

@@ -1,7 +1,10 @@
+using System.Collections.Generic;
 using System.Diagnostics;
 using System.Globalization;
 using System.Reflection;
+using System.Reflection.Metadata.Ecma335;
 using System.Text.Json.Serialization;
+using static Unix.Terminal.Curses;
 
 namespace Terminal.Gui;
 
@@ -542,8 +545,11 @@ public static partial class Application
             toplevel.OnLoaded ();
             toplevel.SetNeedsDisplay ();
             toplevel.Draw ();
-            toplevel.PositionCursor ();
-            Driver.Refresh ();
+            Driver.UpdateScreen ();
+            if (PositionCursor (toplevel))
+            {
+                Driver.UpdateCursor ();
+            }
         }
 
         NotifyNewRunState?.Invoke (toplevel, new (rs));
@@ -551,6 +557,100 @@ public static partial class Application
         return rs;
     }
 
+    private static CursorVisibility _cachedCursorVisibility;
+
+    /// <summary>
+    /// Calls <see cref="View.PositionCursor"/> on the most focused view in the view starting with <paramref name="view"/>.
+    /// </summary>
+    /// <remarks>
+    /// Does nothing if <paramref name="view"/> is <see langword="null"/> or if the most focused view is not visible or enabled.
+    /// <para>
+    /// If the most focused view is not visible within it's superview, the cursor will be hidden.
+    /// </para>
+    /// </remarks>
+    /// <returns><see langword="true"/> if a view positioned the cursor and the position is visible.</returns>
+    internal static bool PositionCursor (View view)
+    {
+        if (view is null)
+        {
+            return false;
+        }
+
+        // Find the most focused view and position the cursor there.
+        View mostFocused = view.MostFocused;
+
+        if (mostFocused is null)
+        {
+            return false;
+        }
+
+        CursorVisibility cachedCursorVisibility;
+
+        // If the view is not visible or enabled, don't position the cursor
+        if (!mostFocused.Visible || !mostFocused.Enabled)
+        {
+            Driver.GetCursorVisibility (out cachedCursorVisibility);
+
+            if (cachedCursorVisibility != CursorVisibility.Invisible)
+            {
+                _cachedCursorVisibility = cachedCursorVisibility;
+                Driver.SetCursorVisibility (CursorVisibility.Invisible);
+            }
+
+            return false;
+        }
+
+        // If the view is not visible within it's superview, don't position the cursor
+        Rectangle mostFocusedViewport = mostFocused.ViewportToScreen (mostFocused.Viewport with { Location = Point.Empty });
+        Rectangle superViewViewport = mostFocused.SuperView?.ViewportToScreen (mostFocused.SuperView.Viewport with { Location = Point.Empty }) ?? Driver.Screen;
+        if (!superViewViewport.IntersectsWith (mostFocusedViewport))
+        {
+            return false;
+        }
+
+        Point? prevCursor = new (Driver.Row, Driver.Col);
+        Point? cursor = mostFocused.PositionCursor ();
+
+        // If the cursor is not in a visible location in the SuperView, hide it
+        if (cursor is { })
+        {
+            // Convert cursor to screen coords
+            cursor = mostFocused.ViewportToScreen (mostFocused.Viewport with { Location = cursor.Value }).Location;
+            if (!superViewViewport.Contains (cursor.Value))
+            {
+                Driver.GetCursorVisibility (out cachedCursorVisibility);
+
+                if (cachedCursorVisibility != CursorVisibility.Invisible)
+                {
+                    _cachedCursorVisibility = cachedCursorVisibility;
+                }
+
+                Driver.SetCursorVisibility (CursorVisibility.Invisible);
+
+                return false;
+            }
+
+            Driver.GetCursorVisibility (out cachedCursorVisibility);
+
+            if (cachedCursorVisibility == CursorVisibility.Invisible)
+            {
+                Driver.SetCursorVisibility (_cachedCursorVisibility);
+            }
+
+            return prevCursor != cursor;
+        }
+
+        Driver.GetCursorVisibility (out cachedCursorVisibility);
+
+        if (cachedCursorVisibility != CursorVisibility.Invisible)
+        {
+            _cachedCursorVisibility = cachedCursorVisibility;
+            Driver.SetCursorVisibility (CursorVisibility.Invisible);
+        }
+
+        return false;
+    }
+
     /// <summary>
     ///     Runs the application by creating a <see cref="Toplevel"/> object and calling
     ///     <see cref="Run(Toplevel, Func{Exception, bool}, ConsoleDriver)"/>.
@@ -764,7 +864,6 @@ public static partial class Application
             last = v;
         }
 
-        last?.PositionCursor ();
         Driver.Refresh ();
     }
 
@@ -877,11 +976,21 @@ public static partial class Application
         if (state.Toplevel.NeedsDisplay || state.Toplevel.SubViewNeedsDisplay || state.Toplevel.LayoutNeeded || OverlappedChildNeedsDisplay ())
         {
             state.Toplevel.Draw ();
-            state.Toplevel.PositionCursor ();
-            Driver.Refresh ();
+            Driver.UpdateScreen ();
+            //Driver.UpdateCursor ();
         }
-        else
+
+        if (PositionCursor (state.Toplevel))
+        {
+            Driver.UpdateCursor();
+        }
+
+        //        else
         {
+            //if (PositionCursor (state.Toplevel))
+            //{
+            //    Driver.Refresh ();
+            //}
             //Driver.UpdateCursor ();
         }
 
@@ -1315,6 +1424,11 @@ public static partial class Application
             t.LayoutSubviews ();
             t.PositionToplevels ();
             t.OnSizeChanging (new (args.Size));
+
+            if (PositionCursor (t))
+            {
+                Driver.UpdateCursor ();
+            }
         }
 
         Refresh ();

+ 21 - 24
Terminal.Gui/View/ViewSubViews.cs

@@ -494,7 +494,7 @@ public partial class View
         {
             return true;
         }
-        
+
         return false;
     }
 
@@ -512,7 +512,9 @@ public partial class View
             return true;
         }
 
-        Driver?.SetCursorVisibility (CursorVisibility.Invisible);
+        // BUGBUG: This is a hack to ensure that the cursor is hidden when the view loses focus.
+        // BUGBUG: This is not needed as the minloop will take care of this.
+        //Driver?.SetCursorVisibility (CursorVisibility.Invisible);
 
         return false;
     }
@@ -857,35 +859,30 @@ public partial class View
     /// a way of hiding the cursor, so it can be distracting to have the cursor left at
     /// the last focused view. Views should make sure that they place the cursor
     /// in a visually sensible place.
-    public virtual void PositionCursor ()
+    /// <returns>Viewport-relative cursor position.</returns>
+    public virtual Point? PositionCursor ()
     {
-        if (!CanBeVisible (this) || !Enabled)
+        if (!IsInitialized)
         {
-            return;
+            return null;
         }
 
-        // BUGBUG: v2 - This needs to support Subviews of Adornments too
+        // TODO: v2 - This needs to support Subviews of Adornments too
 
-        if (Focused is null && SuperView is { })
-        {
-            SuperView.EnsureFocus ();
-        }
-        else if (Focused is { Visible: true, Enabled: true, Frame: { Width: > 0, Height: > 0 } })
-        {
-            Focused.PositionCursor ();
-        }
-        else if (Focused?.Visible == true && Focused?.Enabled == false)
-        {
-            Focused = null;
-        }
-        else if (CanFocus && HasFocus && Visible && Frame.Width > 0 && Frame.Height > 0)
-        {
-            Move (TextFormatter.HotKeyPos == -1 ? 0 : TextFormatter.CursorPosition, 0);
-        }
-        else
+        // By default we will position the cursor at the top left corner of the Viewport.
+        // Overrides should return the position where the cursor has been placed.
+        Point location = Viewport.Location;
+
+        if (CanFocus && HasFocus && ContentSize != Size.Empty)
         {
-            Move (_frame.X, _frame.Y);
+            location.X = TextFormatter.HotKeyPos == -1 ? 0 : TextFormatter.CursorPosition;
+            location.Y = 0;
+            Move (location.X, location.Y);
+            return location;
         }
+
+        return null;
+
     }
 
     #endregion Focus

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

@@ -146,7 +146,7 @@ public class Button : View
     }
 
     /// <inheritdoc/>
-    public override void PositionCursor ()
+    public override Point? PositionCursor ()
     {
         if (HotKey.IsValid && Text != "")
         {
@@ -156,12 +156,12 @@ public class Button : View
                 {
                     Move (i, 0);
 
-                    return;
+                    return new (i,0);
                 }
             }
         }
 
-        base.PositionCursor ();
+        return base.PositionCursor ();
     }
 
     /// <inheritdoc/>

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

@@ -151,7 +151,7 @@ public class CheckBox : View
     }
 
     /// <inheritdoc/>
-    public override void PositionCursor () { Move (0, 0); }
+    public override Point? PositionCursor () { Move (0, 0); return Point.Empty; }
 
     /// <summary>Toggled event, raised when the <see cref="CheckBox"/> is toggled.</summary>
     /// <remarks>

+ 8 - 7
Terminal.Gui/Views/HexView.cs

@@ -547,7 +547,7 @@ public class HexView : View
     public event EventHandler<HexViewEventArgs> PositionChanged;
 
     ///<inheritdoc/>
-    public override void PositionCursor ()
+    public override Point? PositionCursor ()
     {
         var delta = (int)(position - displayStart);
         int line = delta / bytesPerLine;
@@ -555,14 +555,15 @@ public class HexView : View
         int block = item / bsize;
         int column = item % bsize * 3;
 
-        if (leftSide)
+        int x = displayWidth + block * 14 + column + (firstNibble ? 0 : 1);
+        int y = line;
+        if (!leftSide)
         {
-            Move (displayWidth + block * 14 + column + (firstNibble ? 0 : 1), line);
-        }
-        else
-        {
-            Move (displayWidth + bytesPerLine / bsize * 14 + item - 1, line);
+            x = displayWidth + bytesPerLine / bsize * 14 + item - 1;
         }
+
+        Move (x, y);
+        return new (x, y);
     }
 
     internal void SetDisplayStart (long value)

+ 8 - 7
Terminal.Gui/Views/ListView.cs

@@ -781,16 +781,17 @@ public class ListView : View
     public event EventHandler<ListViewItemEventArgs> OpenSelectedItem;
 
     /// <inheritdoc/>
-    public override void PositionCursor ()
+    public override Point? PositionCursor ()
     {
-        if (_allowsMarking)
-        {
-            Move (0, _selected - Viewport.Y);
-        }
-        else
+        int x = 0;
+        int y = _selected - Viewport.Y;
+        if (!_allowsMarking)
         {
-            Move (Viewport.Width - 1, _selected - Viewport.Y);
+            x = Viewport.Width - 1;
         }
+
+        Move (x, y);
+        return new Point (x, y);
     }
 
     /// <summary>This event is invoked when this <see cref="ListView"/> is being drawn before rendering.</summary>

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

@@ -946,23 +946,22 @@ internal sealed class Menu : View
         }
     }
 
-    public override void PositionCursor ()
+    public override Point? PositionCursor ()
     {
         if (_host?.IsMenuOpen != false)
         {
             if (_barItems.IsTopLevel)
             {
-                _host?.PositionCursor ();
+                return _host?.PositionCursor ();
             }
             else
             {
                 Move (2, 1 + _currentChild);
+                return new (2, 1 + _currentChild);
             }
         }
-        else
-        {
-            _host?.PositionCursor ();
-        }
+
+        return _host?.PositionCursor ();
     }
 
     public void Run (Action action)

+ 3 - 2
Terminal.Gui/Views/Menu/MenuBar.cs

@@ -605,7 +605,7 @@ public class MenuBar : View
     }
 
     /// <inheritdoc/>
-    public override void PositionCursor ()
+    public override Point? PositionCursor ()
     {
         if (_selected == -1 && HasFocus && Menus.Length > 0)
         {
@@ -621,7 +621,7 @@ public class MenuBar : View
                 pos++;
                 Move (pos + 1, 0);
 
-                return;
+                return new (pos +1, 0);
             }
 
             pos += _leftPadding
@@ -631,6 +631,7 @@ public class MenuBar : View
                           : 0)
                    + _rightPadding;
         }
+        return null;
     }
 
     // Activates the menu, handles either first focus, or activating an entry when it was already active

+ 11 - 3
Terminal.Gui/Views/RadioGroup.cs

@@ -351,19 +351,27 @@ public class RadioGroup : View
     public event EventHandler<OrientationEventArgs> OrientationChanged;
 
     /// <inheritdoc/>
-    public override void PositionCursor ()
+    public override Point? PositionCursor ()
     {
+        int x = 0;
+        int y = 0;
         switch (Orientation)
         {
             case Orientation.Vertical:
-                Move (0, _cursor);
+                y = _cursor;
 
                 break;
             case Orientation.Horizontal:
-                Move (_horizontal [_cursor].pos, 0);
+                x = _horizontal [_cursor].pos;
 
                 break;
+
+            default:
+                return null;
         }
+
+        Move (x, y);
+        return new Point (x, y);
     }
 
     /// <summary>Allow to invoke the <see cref="SelectedItemChanged"/> after their creation.</summary>

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

@@ -455,16 +455,14 @@ public class ScrollView : View
     }
 
     /// <inheritdoc/>
-    public override void PositionCursor ()
+    public override Point? PositionCursor ()
     {
         if (InternalSubviews.Count == 0)
         {
             Move (0, 0);
+            return Point.Empty;
         }
-        else
-        {
-            base.PositionCursor ();
-        }
+        return base.PositionCursor ();
     }
 
     /// <summary>Removes the view from the scrollview.</summary>

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

@@ -983,7 +983,7 @@ public class Slider<T> : View
     #region Cursor and Drawing
 
     /// <inheritdoc/>
-    public override void PositionCursor ()
+    public override Point? PositionCursor ()
     {
         //base.PositionCursor ();
 
@@ -1001,8 +1001,11 @@ public class Slider<T> : View
             if (IsInitialized && Viewport.Contains (position.x, position.y))
             {
                 Move (position.x, position.y);
+
+                return new (position.x, position.x);
             }
         }
+        return null;
     }
 
     /// <inheritdoc/>

+ 5 - 4
Terminal.Gui/Views/TableView/TableView.cs

@@ -1017,13 +1017,11 @@ public class TableView : View
     ///     Positions the cursor in the area of the screen in which the start of the active cell is rendered.  Calls base
     ///     implementation if active cell is not visible due to scrolling or table is loaded etc
     /// </summary>
-    public override void PositionCursor ()
+    public override Point? PositionCursor ()
     {
         if (TableIsNullOrInvisible ())
         {
-            base.PositionCursor ();
-
-            return;
+            return base.PositionCursor ();
         }
 
         Point? screenPoint = CellToScreen (SelectedColumn, SelectedRow);
@@ -1031,7 +1029,10 @@ public class TableView : View
         if (screenPoint is { })
         {
             Move (screenPoint.Value.X, screenPoint.Value.Y);
+            return screenPoint;
         }
+
+        return null;
     }
 
     /// <summary>

+ 4 - 85
Terminal.Gui/Views/TextField.cs

@@ -9,10 +9,8 @@ namespace Terminal.Gui;
 public class TextField : View
 {
     private readonly HistoryText _historyText;
-    private readonly CursorVisibility _savedCursorVisibility;
     private CultureInfo _currentCulture;
     private int _cursorPosition;
-    private CursorVisibility _desiredCursorVisibility;
     private bool _isButtonPressed;
     private bool _isButtonReleased;
     private bool _isDrawing;
@@ -21,7 +19,6 @@ public class TextField : View
     private string _selectedText;
     private int _start;
     private List<Rune> _text;
-    private CursorVisibility _visibility;
 
     /// <summary>
     ///     Initializes a new instance of the <see cref="TextField"/> class using <see cref="LayoutStyle.Computed"/>
@@ -30,7 +27,6 @@ public class TextField : View
     public TextField ()
     {
         _historyText = new HistoryText ();
-        _desiredCursorVisibility = CursorVisibility.Default;
         _isButtonReleased = true;
         _selectedStart = -1;
         _text = new List<Rune> ();
@@ -42,7 +38,6 @@ public class TextField : View
         CanFocus = true;
         Used = true;
         WantMousePositionReports = true;
-        _savedCursorVisibility = _desiredCursorVisibility;
 
         _historyText.ChangeText += HistoryText_ChangeText;
 
@@ -469,21 +464,6 @@ public class TextField : View
         }
     }
 
-    /// <summary>Get / Set the wished cursor when the field is focused</summary>
-    public CursorVisibility DesiredCursorVisibility
-    {
-        get => _desiredCursorVisibility;
-        set
-        {
-            if ((_desiredCursorVisibility != value || _visibility != value) && HasFocus)
-            {
-                Application.Driver.SetCursorVisibility (value);
-            }
-
-            _desiredCursorVisibility = _visibility = value;
-        }
-    }
-
     /// <summary>
     ///     Indicates whatever the text has history changes or not. <see langword="true"/> if the text has history changes
     ///     <see langword="false"/> otherwise.
@@ -1060,7 +1040,7 @@ public class TextField : View
     {
         if (IsInitialized)
         {
-            Application.Driver.SetCursorVisibility (DesiredCursorVisibility);
+            Application.Driver.SetCursorVisibility (CursorVisibility.Default);
         }
 
         return base.OnEnter (view);
@@ -1172,13 +1152,8 @@ public class TextField : View
     }
 
     /// <summary>Sets the cursor position.</summary>
-    public override void PositionCursor ()
+    public override Point? PositionCursor ()
     {
-        if (!IsInitialized)
-        {
-            return;
-        }
-
         ProcessAutocomplete ();
 
         var col = 0;
@@ -1195,31 +1170,8 @@ public class TextField : View
         }
 
         int pos = _cursorPosition - ScrollOffset + Math.Min (Frame.X, 0);
-        int offB = OffSetBackground ();
-        Rectangle containerFrame = SuperView?.ViewportToScreen (SuperView.Viewport) ?? default (Rectangle);
-        Rectangle thisFrame = ViewportToScreen (Viewport);
-
-        if (pos > -1
-            && col >= pos
-            && pos < Frame.Width + offB
-            && containerFrame.IntersectsWith (thisFrame))
-        {
-            RestoreCursorVisibility ();
-            Move (col, 0);
-        }
-        else
-        {
-            HideCursorVisibility ();
-
-            if (pos < 0)
-            {
-                Move (pos, 0);
-            }
-            else
-            {
-                Move (pos - offB, 0);
-            }
-        }
+        Move (pos, 0);
+        return new Point (pos, 0);
     }
 
     /// <summary>Redoes the latest changes.</summary>
@@ -1231,21 +1183,6 @@ public class TextField : View
         }
 
         _historyText.Redo ();
-
-        //if (string.IsNullOrEmpty (Clipboard.Contents))
-        //	return true;
-        //var clip = TextModel.ToRunes (Clipboard.Contents);
-        //if (clip is null)
-        //	return true;
-
-        //if (point == text.Count) {
-        //	point = text.Count;
-        //	SetText(text.Concat(clip).ToList());
-        //} else {
-        //	point += clip.Count;
-        //	SetText(text.GetRange(0, oldCursorPos).Concat(clip).Concat(text.GetRange(oldCursorPos, text.Count - oldCursorPos)));
-        //}
-        //Adjust ();
     }
 
     /// <summary>Selects all text.</summary>
@@ -1465,14 +1402,6 @@ public class TextField : View
         return new Attribute (cs.Disabled.Foreground, cs.Focus.Background);
     }
 
-    private void HideCursorVisibility ()
-    {
-        if (_desiredCursorVisibility != CursorVisibility.Invisible)
-        {
-            DesiredCursorVisibility = CursorVisibility.Invisible;
-        }
-    }
-
     private void HistoryText_ChangeText (object sender, HistoryText.HistoryTextItem obj)
     {
         if (obj is null)
@@ -1886,16 +1815,6 @@ public class TextField : View
         Driver.AddStr (render);
     }
 
-    private void RestoreCursorVisibility ()
-    {
-        Application.Driver.GetCursorVisibility (out _visibility);
-
-        if (_desiredCursorVisibility != _savedCursorVisibility || _visibility != _savedCursorVisibility)
-        {
-            DesiredCursorVisibility = _savedCursorVisibility;
-        }
-    }
-
     private void SetClipboard (IEnumerable<Rune> text)
     {
         if (!Secret)

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

@@ -640,7 +640,7 @@ namespace Terminal.Gui
         }
 
         /// <inheritdoc/>
-        public override void PositionCursor ()
+        public override Point? PositionCursor ()
         {
             (int left, _) = GetMargins (Viewport.Width);
 
@@ -652,13 +652,12 @@ namespace Terminal.Gui
             if (_provider?.Fixed == false && TextAlignment == TextAlignment.Right)
             {
                 curPos = _cursorPosition + left - 1;
-                Move (curPos, 0);
             }
             else
             {
                 curPos = _cursorPosition + left;
-                Move (curPos, 0);
             }
+            Move (curPos, 0);
 
             if (curPos < 0 || curPos >= Viewport.Width)
             {
@@ -668,6 +667,7 @@ namespace Terminal.Gui
             {
                 Application.Driver.SetCursorVisibility (CursorVisibility.Default);
             }
+            return new (curPos, 0);
         }
 
         /// <summary>Delete char at cursor position - 1, moving the cursor.</summary>

+ 178 - 206
Terminal.Gui/Views/TextView.cs

@@ -67,7 +67,7 @@ internal class TextModel
         }
 
         FilePath = null;
-        _lines = new List<List<RuneCell>> ();
+        _lines = new ();
 
         return true;
     }
@@ -89,7 +89,7 @@ internal class TextModel
             return _lines [Count - 1];
         }
 
-        _lines.Add (new List<RuneCell> ());
+        _lines.Add (new ());
 
         return _lines [0];
     }
@@ -153,7 +153,7 @@ internal class TextModel
             throw new ArgumentNullException (nameof (input));
         }
 
-        _lines = new List<List<RuneCell>> ();
+        _lines = new ();
         var buff = new BufferedStream (input);
         int v;
         List<byte> line = new ();
@@ -215,7 +215,7 @@ internal class TextModel
     {
         if (_lines.Count > 0 && pos < _lines.Count)
         {
-            _lines [pos] = new List<RuneCell> (runes);
+            _lines [pos] = new (runes);
         }
         else if (_lines.Count == 0 || (_lines.Count > 0 && pos >= _lines.Count))
         {
@@ -243,7 +243,7 @@ internal class TextModel
 
         foreach (Rune rune in str.EnumerateRunes ())
         {
-            cells.Add (new RuneCell { Rune = rune, ColorScheme = colorScheme });
+            cells.Add (new() { Rune = rune, ColorScheme = colorScheme });
         }
 
         return cells;
@@ -759,7 +759,7 @@ internal class TextModel
                                                   _lines.Count - 1,
                                                   matchCase,
                                                   matchWholeWord,
-                                                  new Point (_lines [_lines.Count - 1].Count, _lines.Count)
+                                                  new (_lines [_lines.Count - 1].Count, _lines.Count)
                                                  );
         }
 
@@ -850,7 +850,7 @@ internal class TextModel
                     _lines [i] = ToRuneCellList (ReplaceText (x, textToReplace!, matchText, col));
                     x = _lines [i];
                     txt = GetText (x);
-                    pos = new Point (col, i);
+                    pos = new (col, i);
                     col += textToReplace!.Length - matchText.Length;
                 }
 
@@ -906,7 +906,7 @@ internal class TextModel
 
         foreach (Rune rune in str.ToRunes ())
         {
-            cells.Add (new RuneCell { Rune = rune, ColorScheme = colorScheme });
+            cells.Add (new() { Rune = rune, ColorScheme = colorScheme });
         }
 
         return cells;
@@ -918,7 +918,7 @@ internal class TextModel
 
         foreach (Rune rune in runes)
         {
-            cells.Add (new RuneCell { Rune = rune, ColorScheme = colorScheme });
+            cells.Add (new() { Rune = rune, ColorScheme = colorScheme });
         }
 
         return cells;
@@ -981,7 +981,7 @@ internal class TextModel
 
             if (col > -1 && ((i == start.Y && col >= start.X) || i > start.Y) && txt.Contains (matchText))
             {
-                return (new Point (col, i), true);
+                return (new (col, i), true);
             }
 
             if (col == -1 && start.X > 0)
@@ -1026,7 +1026,7 @@ internal class TextModel
 
             if (col > -1 && ((i <= linesCount && col <= start.X) || i < start.Y) && txt.Contains (matchText))
             {
-                return (new Point (col, i), true);
+                return (new (col, i), true);
             }
         }
 
@@ -1292,7 +1292,7 @@ internal partial class HistoryText
                                           );
         }
 
-        _historyTextItems.Add (new HistoryTextItem (lines, curPos, lineStatus));
+        _historyTextItems.Add (new (lines, curPos, lineStatus));
         _idxHistoryText++;
     }
 
@@ -1370,7 +1370,7 @@ internal partial class HistoryText
                     _idxHistoryText--;
                 }
 
-                historyTextItem = new HistoryTextItem (_historyTextItems [_idxHistoryText]);
+                historyTextItem = new (_historyTextItems [_idxHistoryText]);
                 historyTextItem.IsUndoing = true;
                 historyTextItem.FinalCursorPosition = historyTextItem.CursorPosition;
             }
@@ -1378,7 +1378,7 @@ internal partial class HistoryText
             if (historyTextItem.LineStatus == LineStatus.Removed && _historyTextItems [_idxHistoryText + 1].LineStatus == LineStatus.Added)
             {
                 historyTextItem.RemovedOnAdded =
-                    new HistoryTextItem (_historyTextItems [_idxHistoryText + 1]);
+                    new (_historyTextItems [_idxHistoryText + 1]);
             }
 
             if ((historyTextItem.LineStatus == LineStatus.Added && _historyTextItems [_idxHistoryText - 1].LineStatus == LineStatus.Original)
@@ -1390,7 +1390,7 @@ internal partial class HistoryText
                     && historyTextItem.CursorPosition == _historyTextItems [_idxHistoryText - 1].CursorPosition)
                 {
                     historyTextItem.Lines [0] =
-                        new List<RuneCell> (_historyTextItems [_idxHistoryText - 1].Lines [0]);
+                        new (_historyTextItems [_idxHistoryText - 1].Lines [0]);
                 }
 
                 if (historyTextItem.LineStatus == LineStatus.Added && _historyTextItems [_idxHistoryText - 1].LineStatus == LineStatus.Removed)
@@ -1425,7 +1425,7 @@ internal partial class HistoryText
                     || _historyTextItems [_idxHistoryText + 1].LineStatus == LineStatus.Removed))
             {
                 _idxHistoryText++;
-                historyTextItem = new HistoryTextItem (_historyTextItems [_idxHistoryText]);
+                historyTextItem = new (_historyTextItems [_idxHistoryText]);
                 historyTextItem.IsUndoing = false;
                 historyTextItem.FinalCursorPosition = historyTextItem.CursorPosition;
             }
@@ -1433,7 +1433,7 @@ internal partial class HistoryText
             if (historyTextItem.LineStatus == LineStatus.Added && _historyTextItems [_idxHistoryText - 1].LineStatus == LineStatus.Removed)
             {
                 historyTextItem.RemovedOnAdded =
-                    new HistoryTextItem (_historyTextItems [_idxHistoryText - 1]);
+                    new (_historyTextItems [_idxHistoryText - 1]);
             }
 
             if ((historyTextItem.LineStatus == LineStatus.Removed && _historyTextItems [_idxHistoryText + 1].LineStatus == LineStatus.Replaced)
@@ -1445,7 +1445,7 @@ internal partial class HistoryText
                                        .SequenceEqual (_historyTextItems [_idxHistoryText + 1].Lines [0]))
                 {
                     historyTextItem.Lines [0] =
-                        new List<RuneCell> (_historyTextItems [_idxHistoryText + 1].Lines [0]);
+                        new (_historyTextItems [_idxHistoryText + 1].Lines [0]);
                 }
 
                 historyTextItem.FinalCursorPosition =
@@ -1962,15 +1962,14 @@ public class TextView : View
     private bool _copyWithoutSelection;
     private string? _currentCaller;
     private CultureInfo? _currentCulture;
-    private CursorVisibility _desiredCursorVisibility = CursorVisibility.Default;
     private bool _isButtonShift;
+    private bool _isButtonReleased;
     private bool _isDrawing;
     private bool _isReadOnly;
     private bool _lastWasKill;
     private int _leftColumn;
     private TextModel _model = new ();
     private bool _multiline = true;
-    private CursorVisibility _savedCursorVisibility;
     private Dim? _savedHeight;
     private int _selectionStartColumn, _selectionStartRow;
     private bool _shiftSelecting;
@@ -1980,6 +1979,10 @@ public class TextView : View
     private WordWrapManager? _wrapManager;
     private bool _wrapNeeded;
 
+    /// <summary>Get or sets the cursor to be used when the text view has focus.</summary>
+
+    public CursorVisibility DesiredCursorVisibility { get; set; } = CursorVisibility.Default;
+
     /// <summary>
     ///     Initializes a <see cref="TextView"/> on the specified area, with dimensions controlled with the X, Y, Width
     ///     and Height properties.
@@ -2398,10 +2401,10 @@ public class TextView : View
                     Command.ShowContextMenu,
                     () =>
                     {
-                        ContextMenu!.Position = new Point (
-                                                           CursorPosition.X - _leftColumn + 2,
-                                                           CursorPosition.Y - _topRow + 2
-                                                          );
+                        ContextMenu!.Position = new (
+                                                     CursorPosition.X - _leftColumn + 2,
+                                                     CursorPosition.Y - _topRow + 2
+                                                    );
                         ShowContextMenu ();
 
                         return true;
@@ -2509,7 +2512,7 @@ public class TextView : View
 
         _currentCulture = Thread.CurrentThread.CurrentUICulture;
 
-        ContextMenu = new ContextMenu { MenuItems = BuildContextMenuBarItem () };
+        ContextMenu = new() { MenuItems = BuildContextMenuBarItem () };
         ContextMenu.KeyChanged += ContextMenu_KeyChanged!;
 
         KeyBindings.Add ((KeyCode)ContextMenu.Key, KeyBindingScope.HotKey, Command.ShowContextMenu);
@@ -2626,21 +2629,6 @@ public class TextView : View
         }
     }
 
-    /// <summary>Get / Set the wished cursor when the field is focused</summary>
-    public CursorVisibility DesiredCursorVisibility
-    {
-        get => _desiredCursorVisibility;
-        set
-        {
-            if (HasFocus)
-            {
-                Application.Driver.SetCursorVisibility (value);
-            }
-
-            _desiredCursorVisibility = value;
-            SetNeedsDisplay ();
-        }
-    }
 
     /// <summary>
     ///     Indicates whatever the text has history changes or not. <see langword="true"/> if the text has history changes
@@ -2862,17 +2850,17 @@ public class TextView : View
         }
         set
         {
-            var old = Text;
+            string old = Text;
             ResetPosition ();
             _model.LoadString (value);
 
             if (_wordWrap)
             {
-                _wrapManager = new WordWrapManager (_model);
+                _wrapManager = new (_model);
                 _model = _wrapManager.WrapModel (_frameWidth, out _, out _, out _, out _);
             }
 
-            OnTextChanged (old,Text);
+            OnTextChanged (old, Text);
             SetNeedsDisplay ();
 
             _historyText.Clear (Text);
@@ -2913,7 +2901,7 @@ public class TextView : View
 
             if (_wordWrap)
             {
-                _wrapManager = new WordWrapManager (_model);
+                _wrapManager = new (_model);
                 _model = _wrapManager.WrapModel (_frameWidth, out _, out _, out _, out _);
             }
             else if (!_wordWrap && _wrapManager is { })
@@ -2982,7 +2970,7 @@ public class TextView : View
             ClearRegion ();
 
             _historyText.Add (
-                              new List<List<RuneCell>> { new (GetCurrentLine ()) },
+                              new() { new (GetCurrentLine ()) },
                               CursorPosition,
                               HistoryText.LineStatus.Replaced
                              );
@@ -3021,14 +3009,14 @@ public class TextView : View
 
         if (Selecting)
         {
-            _historyText.Add (new List<List<RuneCell>> { new (GetCurrentLine ()) }, CursorPosition);
+            _historyText.Add (new() { new (GetCurrentLine ()) }, CursorPosition);
 
             ClearSelectedRegion ();
 
             List<RuneCell> currentLine = GetCurrentLine ();
 
             _historyText.Add (
-                              new List<List<RuneCell>> { new (currentLine) },
+                              new() { new (currentLine) },
                               CursorPosition,
                               HistoryText.LineStatus.Replaced
                              );
@@ -3065,14 +3053,14 @@ public class TextView : View
 
         if (Selecting)
         {
-            _historyText.Add (new List<List<RuneCell>> { new (GetCurrentLine ()) }, CursorPosition);
+            _historyText.Add (new() { new (GetCurrentLine ()) }, CursorPosition);
 
             ClearSelectedRegion ();
 
             List<RuneCell> currentLine = GetCurrentLine ();
 
             _historyText.Add (
-                              new List<List<RuneCell>> { new (currentLine) },
+                              new() { new (currentLine) },
                               CursorPosition,
                               HistoryText.LineStatus.Replaced
                              );
@@ -3204,7 +3192,7 @@ public class TextView : View
 
         if (ColorScheme is null)
         {
-            cs = new ColorScheme ();
+            cs = new ();
         }
 
         return Enabled ? cs.Focus : cs.Disabled;
@@ -3223,7 +3211,7 @@ public class TextView : View
 
             try
             {
-                key = new Key (ch);
+                key = new (ch);
             }
             catch (Exception)
             {
@@ -3312,7 +3300,7 @@ public class TextView : View
     }
 
     /// <inheritdoc/>
-    protected internal override bool OnMouseEvent  (MouseEvent ev)
+    protected internal override bool OnMouseEvent (MouseEvent ev)
     {
         if (!ev.Flags.HasFlag (MouseFlags.Button1Clicked)
             && !ev.Flags.HasFlag (MouseFlags.Button1Pressed)
@@ -3349,6 +3337,13 @@ public class TextView : View
 
         if (ev.Flags == MouseFlags.Button1Clicked)
         {
+            if (_isButtonReleased)
+            {
+                _isButtonReleased = false;
+
+                return true;
+            }
+
             if (_shiftSelecting && !_isButtonShift)
             {
                 StopSelecting ();
@@ -3476,6 +3471,7 @@ public class TextView : View
         }
         else if (ev.Flags.HasFlag (MouseFlags.Button1Released))
         {
+            _isButtonReleased = true;
             Application.UngrabMouse ();
         }
         else if (ev.Flags.HasFlag (MouseFlags.Button1DoubleClicked))
@@ -3544,7 +3540,7 @@ public class TextView : View
         }
         else if (ev.Flags == ContextMenu!.MouseFlags)
         {
-            ContextMenu.Position = new Point (ev.X + 2, ev.Y + 2);
+            ContextMenu.Position = new (ev.X + 2, ev.Y + 2);
             ShowContextMenu ();
         }
 
@@ -3579,7 +3575,7 @@ public class TextView : View
     /// </summary>
     public virtual void OnContentsChanged ()
     {
-        ContentsChanged?.Invoke (this, new ContentsChangedEventArgs (CurrentRow, CurrentColumn));
+        ContentsChanged?.Invoke (this, new (CurrentRow, CurrentColumn));
 
         ProcessInheritsPreviousColorScheme (CurrentRow, CurrentColumn);
         ProcessAutocomplete ();
@@ -3762,7 +3758,7 @@ public class TextView : View
             col = _wrapManager.GetModelColFromWrappedLines (CurrentRow, CurrentColumn);
         }
 
-        UnwrappedCursorPosition?.Invoke (this, new PointEventArgs (new Point ((int)col, (int)row)));
+        UnwrappedCursorPosition?.Invoke (this, new (new ((int)col, (int)row)));
     }
 
     /// <summary>Paste the clipboard contents into the current selected position.</summary>
@@ -3778,15 +3774,15 @@ public class TextView : View
 
         if (_copyWithoutSelection && contents.FirstOrDefault (x => x == '\n' || x == '\r') == 0)
         {
-            List<RuneCell> runeList = contents is null ? new List<RuneCell> () : TextModel.ToRuneCellList (contents);
+            List<RuneCell> runeList = contents is null ? new () : TextModel.ToRuneCellList (contents);
             List<RuneCell> currentLine = GetCurrentLine ();
 
-            _historyText.Add (new List<List<RuneCell>> { new (currentLine) }, CursorPosition);
+            _historyText.Add (new() { new (currentLine) }, CursorPosition);
 
-            List<List<RuneCell>> addedLine = new () { new List<RuneCell> (currentLine), runeList };
+            List<List<RuneCell>> addedLine = new () { new (currentLine), runeList };
 
             _historyText.Add (
-                              new List<List<RuneCell>> (addedLine),
+                              new (addedLine),
                               CursorPosition,
                               HistoryText.LineStatus.Added
                              );
@@ -3795,7 +3791,7 @@ public class TextView : View
             CurrentRow++;
 
             _historyText.Add (
-                              new List<List<RuneCell>> { new (GetCurrentLine ()) },
+                              new() { new (GetCurrentLine ()) },
                               CursorPosition,
                               HistoryText.LineStatus.Replaced
                              );
@@ -3816,7 +3812,7 @@ public class TextView : View
             if (Selecting)
             {
                 _historyText.ReplaceLast (
-                                          new List<List<RuneCell>> { new (GetCurrentLine ()) },
+                                          new() { new (GetCurrentLine ()) },
                                           CursorPosition,
                                           HistoryText.LineStatus.Original
                                          );
@@ -3831,13 +3827,13 @@ public class TextView : View
     }
 
     /// <summary>Positions the cursor on the current row and column</summary>
-    public override void PositionCursor ()
+    public override Point? PositionCursor ()
     {
         ProcessAutocomplete ();
 
         if (!CanFocus || !Enabled || Application.Driver is null)
         {
-            return;
+            return null;
         }
 
         if (Selecting)
@@ -3882,13 +3878,11 @@ public class TextView : View
 
         if (posX > -1 && col >= posX && posX < Frame.Width - RightOffset && _topRow <= CurrentRow && posY < Frame.Height - BottomOffset)
         {
-            ResetCursorVisibility ();
             Move (col, CurrentRow - _topRow);
+            return new (col, CurrentRow - _topRow);
         }
-        else
-        {
-            SaveCursorVisibility ();
-        }
+
+        return null;
     }
 
     /// <summary>Redoes the latest changes.</summary>
@@ -4042,11 +4036,11 @@ public class TextView : View
 
         if (colorScheme!.Disabled.Foreground == colorScheme.Focus.Background)
         {
-            attribute = new Attribute (colorScheme.Focus.Foreground, colorScheme.Focus.Background);
+            attribute = new (colorScheme.Focus.Foreground, colorScheme.Focus.Background);
         }
         else
         {
-            attribute = new Attribute (colorScheme.Disabled.Foreground, colorScheme.Focus.Background);
+            attribute = new (colorScheme.Disabled.Foreground, colorScheme.Focus.Background);
         }
 
         Driver.SetAttribute (attribute);
@@ -4072,16 +4066,16 @@ public class TextView : View
             ColorScheme? colorScheme = line [idxCol].ColorScheme;
 
             Driver.SetAttribute (
-                                 new Attribute (colorScheme!.Focus.Background, colorScheme.Focus.Foreground)
+                                 new (colorScheme!.Focus.Background, colorScheme.Focus.Foreground)
                                 );
         }
         else
         {
             Driver.SetAttribute (
-                                 new Attribute (
-                                                ColorScheme.Focus.Background,
-                                                ColorScheme.Focus.Foreground
-                                               )
+                                 new (
+                                      ColorScheme.Focus.Background,
+                                      ColorScheme.Focus.Foreground
+                                     )
                                 );
         }
     }
@@ -4190,67 +4184,67 @@ public class TextView : View
 
     private MenuBarItem BuildContextMenuBarItem ()
     {
-        return new MenuBarItem (
-                                new MenuItem []
-                                {
-                                    new (
-                                         Strings.ctxSelectAll,
-                                         "",
-                                         SelectAll,
-                                         null,
-                                         null,
-                                         (KeyCode)KeyBindings.GetKeyFromCommands (Command.SelectAll)
-                                        ),
-                                    new (
-                                         Strings.ctxDeleteAll,
-                                         "",
-                                         DeleteAll,
-                                         null,
-                                         null,
-                                         (KeyCode)KeyBindings.GetKeyFromCommands (Command.DeleteAll)
-                                        ),
-                                    new (
-                                         Strings.ctxCopy,
-                                         "",
-                                         Copy,
-                                         null,
-                                         null,
-                                         (KeyCode)KeyBindings.GetKeyFromCommands (Command.Copy)
-                                        ),
-                                    new (
-                                         Strings.ctxCut,
-                                         "",
-                                         Cut,
-                                         null,
-                                         null,
-                                         (KeyCode)KeyBindings.GetKeyFromCommands (Command.Cut)
-                                        ),
-                                    new (
-                                         Strings.ctxPaste,
-                                         "",
-                                         Paste,
-                                         null,
-                                         null,
-                                         (KeyCode)KeyBindings.GetKeyFromCommands (Command.Paste)
-                                        ),
-                                    new (
-                                         Strings.ctxUndo,
-                                         "",
-                                         Undo,
-                                         null,
-                                         null,
-                                         (KeyCode)KeyBindings.GetKeyFromCommands (Command.Undo)
-                                        ),
-                                    new (
-                                         Strings.ctxRedo,
-                                         "",
-                                         Redo,
-                                         null,
-                                         null,
-                                         (KeyCode)KeyBindings.GetKeyFromCommands (Command.Redo)
-                                        )
-                                }
-                               );
+        return new (
+                    new MenuItem []
+                    {
+                        new (
+                             Strings.ctxSelectAll,
+                             "",
+                             SelectAll,
+                             null,
+                             null,
+                             (KeyCode)KeyBindings.GetKeyFromCommands (Command.SelectAll)
+                            ),
+                        new (
+                             Strings.ctxDeleteAll,
+                             "",
+                             DeleteAll,
+                             null,
+                             null,
+                             (KeyCode)KeyBindings.GetKeyFromCommands (Command.DeleteAll)
+                            ),
+                        new (
+                             Strings.ctxCopy,
+                             "",
+                             Copy,
+                             null,
+                             null,
+                             (KeyCode)KeyBindings.GetKeyFromCommands (Command.Copy)
+                            ),
+                        new (
+                             Strings.ctxCut,
+                             "",
+                             Cut,
+                             null,
+                             null,
+                             (KeyCode)KeyBindings.GetKeyFromCommands (Command.Cut)
+                            ),
+                        new (
+                             Strings.ctxPaste,
+                             "",
+                             Paste,
+                             null,
+                             null,
+                             (KeyCode)KeyBindings.GetKeyFromCommands (Command.Paste)
+                            ),
+                        new (
+                             Strings.ctxUndo,
+                             "",
+                             Undo,
+                             null,
+                             null,
+                             (KeyCode)KeyBindings.GetKeyFromCommands (Command.Undo)
+                            ),
+                        new (
+                             Strings.ctxRedo,
+                             "",
+                             Redo,
+                             null,
+                             null,
+                             (KeyCode)KeyBindings.GetKeyFromCommands (Command.Redo)
+                            )
+                    }
+                   );
     }
 
     private void ClearRegion (int left, int top, int right, int bottom)
@@ -4282,13 +4276,13 @@ public class TextView : View
         var endCol = (int)(end & 0xffffffff);
         List<RuneCell> line = _model.GetLine (startRow);
 
-        _historyText.Add (new List<List<RuneCell>> { new (line) }, new Point (startCol, startRow));
+        _historyText.Add (new() { new (line) }, new (startCol, startRow));
 
         List<List<RuneCell>> removedLines = new ();
 
         if (startRow == maxrow)
         {
-            removedLines.Add (new List<RuneCell> (line));
+            removedLines.Add (new (line));
 
             line.RemoveRange (startCol, endCol - startCol);
             CurrentColumn = startCol;
@@ -4306,7 +4300,7 @@ public class TextView : View
             }
 
             _historyText.Add (
-                              new List<List<RuneCell>> (removedLines),
+                              new (removedLines),
                               CursorPosition,
                               HistoryText.LineStatus.Removed
                              );
@@ -4316,7 +4310,7 @@ public class TextView : View
             return;
         }
 
-        removedLines.Add (new List<RuneCell> (line));
+        removedLines.Add (new (line));
 
         line.RemoveRange (startCol, line.Count - startCol);
         List<RuneCell> line2 = _model.GetLine (maxrow);
@@ -4324,7 +4318,7 @@ public class TextView : View
 
         for (int row = startRow + 1; row <= maxrow; row++)
         {
-            removedLines.Add (new List<RuneCell> (_model.GetLine (startRow + 1)));
+            removedLines.Add (new (_model.GetLine (startRow + 1)));
 
             _model.RemoveLine (startRow + 1);
         }
@@ -4337,7 +4331,7 @@ public class TextView : View
         CurrentColumn = startCol;
 
         _historyText.Add (
-                          new List<List<RuneCell>> (removedLines),
+                          new (removedLines),
                           CursorPosition,
                           HistoryText.LineStatus.Removed
                          );
@@ -4372,7 +4366,7 @@ public class TextView : View
             // Delete backwards 
             List<RuneCell> currentLine = GetCurrentLine ();
 
-            _historyText.Add (new List<List<RuneCell>> { new (currentLine) }, CursorPosition);
+            _historyText.Add (new() { new (currentLine) }, CursorPosition);
 
             currentLine.RemoveAt (CurrentColumn - 1);
 
@@ -4384,7 +4378,7 @@ public class TextView : View
             CurrentColumn--;
 
             _historyText.Add (
-                              new List<List<RuneCell>> { new (currentLine) },
+                              new() { new (currentLine) },
                               CursorPosition,
                               HistoryText.LineStatus.Replaced
                              );
@@ -4412,15 +4406,15 @@ public class TextView : View
             int prowIdx = CurrentRow - 1;
             List<RuneCell> prevRow = _model.GetLine (prowIdx);
 
-            _historyText.Add (new List<List<RuneCell>> { new (prevRow) }, CursorPosition);
+            _historyText.Add (new() { new (prevRow) }, CursorPosition);
 
-            List<List<RuneCell>> removedLines = new () { new List<RuneCell> (prevRow) };
+            List<List<RuneCell>> removedLines = new () { new (prevRow) };
 
-            removedLines.Add (new List<RuneCell> (GetCurrentLine ()));
+            removedLines.Add (new (GetCurrentLine ()));
 
             _historyText.Add (
                               removedLines,
-                              new Point (CurrentColumn, prowIdx),
+                              new (CurrentColumn, prowIdx),
                               HistoryText.LineStatus.Removed
                              );
 
@@ -4436,8 +4430,8 @@ public class TextView : View
             CurrentRow--;
 
             _historyText.Add (
-                              new List<List<RuneCell>> { GetCurrentLine () },
-                              new Point (CurrentColumn, prowIdx),
+                              new() { GetCurrentLine () },
+                              new (CurrentColumn, prowIdx),
                               HistoryText.LineStatus.Replaced
                              );
 
@@ -4465,13 +4459,13 @@ public class TextView : View
                 return true;
             }
 
-            _historyText.Add (new List<List<RuneCell>> { new (currentLine) }, CursorPosition);
+            _historyText.Add (new() { new (currentLine) }, CursorPosition);
 
-            List<List<RuneCell>> removedLines = new () { new List<RuneCell> (currentLine) };
+            List<List<RuneCell>> removedLines = new () { new (currentLine) };
 
             List<RuneCell> nextLine = _model.GetLine (CurrentRow + 1);
 
-            removedLines.Add (new List<RuneCell> (nextLine));
+            removedLines.Add (new (nextLine));
 
             _historyText.Add (removedLines, CursorPosition, HistoryText.LineStatus.Removed);
 
@@ -4479,7 +4473,7 @@ public class TextView : View
             _model.RemoveLine (CurrentRow + 1);
 
             _historyText.Add (
-                              new List<List<RuneCell>> { new (currentLine) },
+                              new() { new (currentLine) },
                               CursorPosition,
                               HistoryText.LineStatus.Replaced
                              );
@@ -4586,13 +4580,13 @@ public class TextView : View
         List<RuneCell> currentLine = GetCurrentLine ();
         int cursorPosition = Math.Min (CurrentColumn, currentLine.Count);
 
-        Autocomplete.Context = new AutocompleteContext (
-                                                        currentLine,
-                                                        cursorPosition,
-                                                        Autocomplete.Context != null
-                                                            ? Autocomplete.Context.Canceled
-                                                            : false
-                                                       );
+        Autocomplete.Context = new (
+                                    currentLine,
+                                    cursorPosition,
+                                    Autocomplete.Context != null
+                                        ? Autocomplete.Context.Canceled
+                                        : false
+                                   );
 
         Autocomplete.GenerateSuggestions (
                                           Autocomplete.Context
@@ -4830,7 +4824,7 @@ public class TextView : View
 
         List<RuneCell> line = GetCurrentLine ();
 
-        _historyText.Add (new List<List<RuneCell>> { new (line) }, CursorPosition);
+        _historyText.Add (new() { new (line) }, CursorPosition);
 
         // Optimize single line
         if (lines.Count == 1)
@@ -4839,7 +4833,7 @@ public class TextView : View
             CurrentColumn += lines [0].Count;
 
             _historyText.Add (
-                              new List<List<RuneCell>> { new (line) },
+                              new() { new (line) },
                               CursorPosition,
                               HistoryText.LineStatus.Replaced
                              );
@@ -4883,13 +4877,13 @@ public class TextView : View
 
         //model.AddLine (currentRow, lines [0]);
 
-        List<List<RuneCell>> addedLines = new () { new List<RuneCell> (line) };
+        List<List<RuneCell>> addedLines = new () { new (line) };
 
         for (var i = 1; i < lines.Count; i++)
         {
             _model.AddLine (CurrentRow + i, lines [i]);
 
-            addedLines.Add (new List<RuneCell> (lines [i]));
+            addedLines.Add (new (lines [i]));
         }
 
         if (rest is { })
@@ -4909,7 +4903,7 @@ public class TextView : View
         Adjust ();
 
         _historyText.Add (
-                          new List<List<RuneCell>> { new (line) },
+                          new() { new (line) },
                           CursorPosition,
                           HistoryText.LineStatus.Replaced
                          );
@@ -4928,7 +4922,7 @@ public class TextView : View
 
         SetWrapModel ();
 
-        _historyText.Add (new List<List<RuneCell>> { new (GetCurrentLine ()) }, CursorPosition);
+        _historyText.Add (new() { new (GetCurrentLine ()) }, CursorPosition);
 
         if (Selecting)
         {
@@ -4937,7 +4931,7 @@ public class TextView : View
 
         if ((uint)a.KeyCode == '\n')
         {
-            _model.AddLine (CurrentRow + 1, new List<RuneCell> ());
+            _model.AddLine (CurrentRow + 1, new ());
             CurrentRow++;
             CurrentColumn = 0;
         }
@@ -4949,7 +4943,7 @@ public class TextView : View
         {
             if (Used)
             {
-                Insert (new RuneCell { Rune = a.AsRune, ColorScheme = colorScheme });
+                Insert (new() { Rune = a.AsRune, ColorScheme = colorScheme });
                 CurrentColumn++;
 
                 if (CurrentColumn >= _leftColumn + Frame.Width)
@@ -4960,13 +4954,13 @@ public class TextView : View
             }
             else
             {
-                Insert (new RuneCell { Rune = a.AsRune, ColorScheme = colorScheme });
+                Insert (new() { Rune = a.AsRune, ColorScheme = colorScheme });
                 CurrentColumn++;
             }
         }
 
         _historyText.Add (
-                          new List<List<RuneCell>> { new (GetCurrentLine ()) },
+                          new() { new (GetCurrentLine ()) },
                           CursorPosition,
                           HistoryText.LineStatus.Replaced
                          );
@@ -5004,20 +4998,20 @@ public class TextView : View
             return;
         }
 
-        _historyText.Add (new List<List<RuneCell>> { new (currentLine) }, CursorPosition);
+        _historyText.Add (new() { new (currentLine) }, CursorPosition);
 
         if (currentLine.Count == 0)
         {
             if (CurrentRow < _model.Count - 1)
             {
-                List<List<RuneCell>> removedLines = new () { new List<RuneCell> (currentLine) };
+                List<List<RuneCell>> removedLines = new () { new (currentLine) };
 
                 _model.RemoveLine (CurrentRow);
 
-                removedLines.Add (new List<RuneCell> (GetCurrentLine ()));
+                removedLines.Add (new (GetCurrentLine ()));
 
                 _historyText.Add (
-                                  new List<List<RuneCell>> (removedLines),
+                                  new (removedLines),
                                   CursorPosition,
                                   HistoryText.LineStatus.Removed
                                  );
@@ -5671,13 +5665,13 @@ public class TextView : View
 
             if (currentLine.Count > 0 && currentLine [CurrentColumn - 1].Rune.Value == '\t')
             {
-                _historyText.Add (new List<List<RuneCell>> { new (currentLine) }, CursorPosition);
+                _historyText.Add (new() { new (currentLine) }, CursorPosition);
 
                 currentLine.RemoveAt (CurrentColumn - 1);
                 CurrentColumn--;
 
                 _historyText.Add (
-                                  new List<List<RuneCell>> { new (GetCurrentLine ()) },
+                                  new() { new (GetCurrentLine ()) },
                                   CursorPosition,
                                   HistoryText.LineStatus.Replaced
                                  );
@@ -6118,7 +6112,7 @@ public class TextView : View
 
         List<RuneCell> currentLine = GetCurrentLine ();
 
-        _historyText.Add (new List<List<RuneCell>> { new (currentLine) }, CursorPosition);
+        _historyText.Add (new() { new (currentLine) }, CursorPosition);
 
         if (Selecting)
         {
@@ -6130,11 +6124,11 @@ public class TextView : View
         List<RuneCell> rest = currentLine.GetRange (CurrentColumn, restCount);
         currentLine.RemoveRange (CurrentColumn, restCount);
 
-        List<List<RuneCell>> addedLines = new () { new List<RuneCell> (currentLine) };
+        List<List<RuneCell>> addedLines = new () { new (currentLine) };
 
         _model.AddLine (CurrentRow + 1, rest);
 
-        addedLines.Add (new List<RuneCell> (_model.GetLine (CurrentRow + 1)));
+        addedLines.Add (new (_model.GetLine (CurrentRow + 1)));
 
         _historyText.Add (addedLines, CursorPosition, HistoryText.LineStatus.Added);
 
@@ -6151,7 +6145,7 @@ public class TextView : View
         CurrentColumn = 0;
 
         _historyText.Add (
-                          new List<List<RuneCell>> { new (GetCurrentLine ()) },
+                          new() { new (GetCurrentLine ()) },
                           CursorPosition,
                           HistoryText.LineStatus.Replaced
                          );
@@ -6231,7 +6225,7 @@ public class TextView : View
         {
             int col = Selecting ? _selectionStartColumn : CurrentColumn;
             int row = Selecting ? _selectionStartRow : CurrentRow;
-            _model.ResetContinuousFind (new Point (col, row));
+            _model.ResetContinuousFind (new (col, row));
         }
     }
 
@@ -6243,33 +6237,11 @@ public class TextView : View
         _continuousFind = false;
     }
 
-    private void ResetCursorVisibility ()
-    {
-        if (_savedCursorVisibility != 0)
-        {
-            DesiredCursorVisibility = _savedCursorVisibility;
-            _savedCursorVisibility = 0;
-        }
-    }
 
     private void ResetPosition ()
     {
         _topRow = _leftColumn = CurrentRow = CurrentColumn = 0;
         StopSelecting ();
-        ResetCursorVisibility ();
-    }
-
-    private void SaveCursorVisibility ()
-    {
-        if (_desiredCursorVisibility != CursorVisibility.Invisible)
-        {
-            if (_savedCursorVisibility == 0)
-            {
-                _savedCursorVisibility = _desiredCursorVisibility;
-            }
-
-            DesiredCursorVisibility = CursorVisibility.Invisible;
-        }
     }
 
     private void SetClipboard (string text)
@@ -6342,7 +6314,7 @@ public class TextView : View
     {
         // BUGBUG: (v2 truecolor) This code depends on 8-bit color names; disabling for now
         //if ((colorScheme!.HotNormal.Foreground & colorScheme.Focus.Background) == colorScheme.Focus.Foreground) {
-        Driver.SetAttribute (new Attribute (colorScheme.Focus.Background, colorScheme.Focus.Foreground));
+        Driver.SetAttribute (new (colorScheme.Focus.Background, colorScheme.Focus.Foreground));
     }
 
     /// <summary>Restore from original model.</summary>
@@ -6558,6 +6530,6 @@ public class TextViewAutocomplete : PopupAutocomplete
     protected override void SetCursorPosition (int column)
     {
         ((TextView)HostControl).CursorPosition =
-            new Point (column, ((TextView)HostControl).CurrentRow);
+            new (column, ((TextView)HostControl).CurrentRow);
     }
 }

+ 2 - 1
Terminal.Gui/Views/TileView.cs

@@ -987,12 +987,13 @@ public class TileView : View
             return base.OnEnter (view);
         }
 
-        public override void PositionCursor ()
+        public override Point? PositionCursor ()
         {
             base.PositionCursor ();
 
             Point location = moveRuneRenderLocation ?? new Point (Viewport.Width / 2, Viewport.Height / 2);
             Move (location.X, location.Y);
+            return location;
         }
 
         /// <summary>

+ 8 - 6
Terminal.Gui/Views/Toplevel.cs

@@ -333,12 +333,10 @@ public partial class Toplevel : View
     }
 
     /// <inheritdoc/>
-    public override void PositionCursor ()
+    public override Point? PositionCursor ()
     {
         if (!IsOverlappedContainer)
         {
-            base.PositionCursor ();
-
             if (Focused is null)
             {
                 EnsureFocus ();
@@ -349,28 +347,32 @@ public partial class Toplevel : View
                 }
             }
 
-            return;
+            return null;
         }
 
+        // This code path only happens when the Toplevel is an Overlapped container
+
         if (Focused is null)
         {
+            // TODO: this is an Overlapped hack
             foreach (Toplevel top in Application.OverlappedChildren)
             {
                 if (top != this && top.Visible)
                 {
                     top.SetFocus ();
 
-                    return;
+                    return null;
                 }
             }
         }
 
-        base.PositionCursor ();
+        var cursor2 = base.PositionCursor ();
 
         if (Focused is null)
         {
             Driver.SetCursorVisibility (CursorVisibility.Invisible);
         }
+        return cursor2;
     }
 
     /// <summary>

+ 4 - 10
Terminal.Gui/Views/TreeView/TreeView.cs

@@ -1002,7 +1002,7 @@ public class TreeView<T> : View, ITreeView where T : class
     public bool IsSelected (T model) { return Equals (SelectedObject, model) || (MultiSelect && multiSelectedRegions.Any (s => s.Contains (model))); }
 
     ///<inheritdoc/>
-    protected internal override bool OnMouseEvent  (MouseEvent me)
+    protected internal override bool OnMouseEvent (MouseEvent me)
     {
         // If it is not an event we care about
         if (!me.Flags.HasFlag (MouseFlags.Button1Clicked)
@@ -1239,7 +1239,7 @@ public class TreeView<T> : View, ITreeView where T : class
     }
 
     /// <summary>Positions the cursor at the start of the selected objects line (if visible).</summary>
-    public override void PositionCursor ()
+    public override Point? PositionCursor ()
     {
         if (CanFocus && HasFocus && Visible && SelectedObject is { })
         {
@@ -1250,16 +1250,10 @@ public class TreeView<T> : View, ITreeView where T : class
             if (idx - ScrollOffsetVertical >= 0 && idx - ScrollOffsetVertical < Viewport.Height)
             {
                 Move (0, idx - ScrollOffsetVertical);
+                return new Point (0, idx - ScrollOffsetVertical);
             }
-            else
-            {
-                base.PositionCursor ();
-            }
-        }
-        else
-        {
-            base.PositionCursor ();
         }
+        return base.PositionCursor ();
     }
 
     /// <summary>

+ 10 - 7
UICatalog/Scenarios/CharacterMap.cs

@@ -824,7 +824,7 @@ internal class CharMap : View
         return base.OnLeave (view);
     }
 
-    public override void PositionCursor ()
+    public override Point? PositionCursor ()
     {
         if (HasFocus
             && Cursor.X >= RowLabelWidth
@@ -839,6 +839,8 @@ internal class CharMap : View
         {
             Driver.SetCursorVisibility (CursorVisibility.Invisible);
         }
+
+        return Cursor;
     }
 
     public event EventHandler<ListViewItemEventArgs> SelectedCodePointChanged;
@@ -870,16 +872,11 @@ internal class CharMap : View
             return;
         }
 
-        args.Handled = true;
-
         if (me.Y == 0)
         {
             me.Y = Cursor.Y;
         }
 
-        if (me.Y > 0)
-        { }
-
         if (me.X < RowLabelWidth || me.X > RowLabelWidth + 16 * COLUMN_WIDTH - 1)
         {
             me.X = Cursor.X;
@@ -905,10 +902,16 @@ internal class CharMap : View
             Hover?.Invoke (this, new (val, null));
         }
 
+        if (!HasFocus && CanFocus)
+        {
+            SetFocus ();
+        }
+
+        args.Handled = true;
+
         if (me.Flags == MouseFlags.Button1Clicked)
         {
             SelectedCodePoint = val;
-
             return;
         }
 

+ 93 - 0
UnitTests/View/Layout/ViewportTests.cs

@@ -359,4 +359,97 @@ public class ViewportTests (ITestOutputHelper output)
         Assert.Equal (view.Viewport.Size, view.ContentSize);
     }
 
+    //[Theory]
+    //[InlineData (0, 0, true)]
+    //[InlineData (-1, 0, true)]
+    //[InlineData (0, -1, true)]
+    //[InlineData (-1, -1, true)]
+    //[InlineData (-2, -2, true)]
+    //[InlineData (-3, -3, true)]
+    //[InlineData (-4, -4, true)]
+    //[InlineData (-5, -4, false)]
+    //[InlineData (-4, -5, false)]
+    //[InlineData (-5, -5, false)]
+
+    //[InlineData (1, 1, true)]
+    //[InlineData (2, 2, true)]
+    //[InlineData (3, 3, true)]
+    //[InlineData (4, 4, true)]
+    //[InlineData (5, 4, false)]
+    //[InlineData (4, 5, false)]
+    //[InlineData (5, 5, false)]
+    //public void IsVisibleInSuperView_No_Driver_No_SuperView (int x, int y, bool expected)
+    //{
+    //    var view = new View { X = 1, Y = 1, Width = 5, Height = 5 };
+    //    Assert.True (view.IsVisibleInSuperView (x, y) == expected);
+    //}
+
+    //[Theory]
+    //[InlineData (0, 0, true)]
+    //[InlineData (-1, 0, true)]
+    //[InlineData (0, -1, true)]
+    //[InlineData (-1, -1, true)]
+    //[InlineData (-2, -2, true)]
+    //[InlineData (-3, -3, true)]
+    //[InlineData (-4, -4, true)]
+    //[InlineData (-5, -4, true)]
+    //[InlineData (-4, -5, true)]
+    //[InlineData (-5, -5, true)]
+    //[InlineData (-6, -5, false)]
+    //[InlineData (-5, -6, false)]
+    //[InlineData (-6, -6, false)]
+
+    //[InlineData (1, 1, true)]
+    //[InlineData (2, 2, true)]
+    //[InlineData (3, 3, true)]
+    //[InlineData (4, 4, true)]
+    //[InlineData (5, 4, true)]
+    //[InlineData (4, 5, true)]
+    //[InlineData (5, 5, true)]
+    //[InlineData (6, 5, true)]
+    //[InlineData (6, 6, true)]
+    //[InlineData (7, 7, true)]
+    //[InlineData (8, 8, true)]
+    //[InlineData (9, 8, false)]
+    //[InlineData (8, 9, false)]
+    //[InlineData (9, 9, false)]
+    //public void IsVisibleInSuperView_No_Driver_With_SuperView (int x, int y, bool expected)
+    //{
+    //    var view = new View { X = 1, Y = 1, Width = 5, Height = 5 };
+    //    var top = new Toplevel { Width = 10, Height = 10 };
+    //    top.Add (view);
+
+    //    Assert.True (view.IsVisibleInSuperView (x, y) == expected);
+    //}
+
+    //[SetupFakeDriver]
+    //[Theory]
+    //[InlineData (0, 0, true)]
+    //[InlineData (-1, 0, false)]
+    //[InlineData (0, -1, false)]
+    //[InlineData (-1, -1, false)]
+
+    //[InlineData (1, 0, true)]
+    //[InlineData (0, 1, true)]
+    //[InlineData (1, 1, true)]
+    //[InlineData (2, 2, true)]
+    //[InlineData (3, 3, true)]
+    //[InlineData (4, 4, true)]
+    //[InlineData (5, 4, false)]
+    //[InlineData (4, 5, false)]
+    //[InlineData (5, 5, false)]
+    //public void IsVisibleInSuperView_With_Driver (int x, int y, bool expected)
+    //{
+    //    ((FakeDriver)Application.Driver).SetBufferSize (10, 10);
+
+    //    var view = new View { X = 1, Y = 1, Width = 5, Height = 5 };
+    //    var top = new Toplevel ();
+    //    top.Add (view);
+    //    Application.Begin (top);
+
+    //    Assert.True (view.IsVisibleInSuperView (x, y) == expected);
+
+    //    top.Dispose ();
+    //    Application.Shutdown ();
+    //}
 }

+ 32 - 12
UnitTests/Views/TextViewTests.cs

@@ -1065,34 +1065,44 @@ This is the second line.
 
         var tv = new TextView { Width = 10, Height = 10 };
         tv.Text = text;
+        var top = new Toplevel ();
+        top.Add (tv);
+        Application.Begin (top);
 
         Assert.Equal (0, tv.LeftColumn);
-        tv.PositionCursor ();
+        Assert.Equal (Point.Empty, tv.CursorPosition);
+        Application.PositionCursor (top);
         Assert.Equal (CursorVisibility.Default, tv.DesiredCursorVisibility);
 
         for (var i = 0; i < 12; i++)
         {
             tv.NewMouseEvent (new MouseEvent { Flags = MouseFlags.WheeledRight });
-            tv.PositionCursor ();
             Assert.Equal (Math.Min (i + 1, 11), tv.LeftColumn);
-            Assert.Equal (CursorVisibility.Invisible, tv.DesiredCursorVisibility);
+            Application.PositionCursor (top);
+            Application.Driver.GetCursorVisibility (out CursorVisibility cursorVisibility);
+            Assert.Equal (CursorVisibility.Invisible, cursorVisibility);
         }
 
         for (var i = 11; i > 0; i--)
         {
             tv.NewMouseEvent (new MouseEvent { Flags = MouseFlags.WheeledLeft });
-            tv.PositionCursor ();
             Assert.Equal (i - 1, tv.LeftColumn);
 
+            Application.PositionCursor (top);
+            Application.Driver.GetCursorVisibility (out CursorVisibility cursorVisibility);
+
             if (i - 1 == 0)
             {
-                Assert.Equal (CursorVisibility.Default, tv.DesiredCursorVisibility);
+                Assert.Equal (CursorVisibility.Default, cursorVisibility);
             }
             else
             {
-                Assert.Equal (CursorVisibility.Invisible, tv.DesiredCursorVisibility);
+                Assert.Equal (CursorVisibility.Invisible, cursorVisibility);
             }
         }
+
+        top.Dispose ();
+        Application.Shutdown ();
     }
 
     [Fact]
@@ -1108,34 +1118,44 @@ This is the second line.
 
         var tv = new TextView { Width = 10, Height = 10 };
         tv.Text = text;
+        var top = new Toplevel ();
+        top.Add (tv);
+        Application.Begin (top);
 
         Assert.Equal (0, tv.TopRow);
-        tv.PositionCursor ();
+        Application.PositionCursor (top);
         Assert.Equal (CursorVisibility.Default, tv.DesiredCursorVisibility);
 
         for (var i = 0; i < 12; i++)
         {
             tv.NewMouseEvent (new MouseEvent { Flags = MouseFlags.WheeledDown });
-            tv.PositionCursor ();
+            Application.PositionCursor (top);
             Assert.Equal (i + 1, tv.TopRow);
-            Assert.Equal (CursorVisibility.Invisible, tv.DesiredCursorVisibility);
+            Application.Driver.GetCursorVisibility (out CursorVisibility cursorVisibility);
+            Assert.Equal (CursorVisibility.Invisible, cursorVisibility);
         }
 
         for (var i = 12; i > 0; i--)
         {
             tv.NewMouseEvent (new MouseEvent { Flags = MouseFlags.WheeledUp });
-            tv.PositionCursor ();
+            Application.PositionCursor (top);
             Assert.Equal (i - 1, tv.TopRow);
 
+            Application.PositionCursor (top);
+            Application.Driver.GetCursorVisibility (out CursorVisibility cursorVisibility);
+
             if (i - 1 == 0)
             {
-                Assert.Equal (CursorVisibility.Default, tv.DesiredCursorVisibility);
+                Assert.Equal (CursorVisibility.Default, cursorVisibility);
             }
             else
             {
-                Assert.Equal (CursorVisibility.Invisible, tv.DesiredCursorVisibility);
+                Assert.Equal (CursorVisibility.Invisible, cursorVisibility);
             }
         }
+
+        top.Dispose ();
+        Application.Shutdown ();
     }
 
     [Fact]

+ 2 - 1
UnitTests/Views/ToplevelTests.cs

@@ -1261,12 +1261,13 @@ public class ToplevelTests
         Application.Begin (top);
 
         Assert.True (tf.HasFocus);
+        Application.PositionCursor (top);
         Application.Driver.GetCursorVisibility (out CursorVisibility cursor);
         Assert.Equal (CursorVisibility.Default, cursor);
 
         view.Enabled = false;
         Assert.False (tf.HasFocus);
-        Application.Refresh ();
+        Application.PositionCursor (top);
         Application.Driver.GetCursorVisibility (out cursor);
         Assert.Equal (CursorVisibility.Invisible, cursor);
     }

+ 162 - 0
docfx/docs/cursor.md

@@ -0,0 +1,162 @@
+# Proposed Design for a modern Cursor system in v2
+
+See end for list of issues this design addresses.
+
+## Tenets for Cursor Support (Unless you know better ones...)
+
+1. **More GUI than Command Line**. The concept of a cursor on the command line of a terminal is intrinsically tied to enabling the user to know where keybaord import is going to impact text editing. TUI apps have many more modalities than text editing where the keyboard is used (e.g. scrolling through a `ColorPicker`). Terminal.Gui's cursor system is biased towards the broader TUI experiences.
+
+2. **Be Consistent With the User's Platform** - Users get to choose the platform they run *Terminal.Gui* apps on and the cursor should behave in a way consistent with the terminal.
+
+## Lexicon & Taxonomy
+
+- Cursor - A visual indicator to the user where keyboard input will have an impact. There is one Cursor per terminal sesssion.
+- Cursor Location - The top-left corner of the Cursor. In text entry scenarios, new text will be inserted to the left/top of the Cursor Location. 
+- Cursor Size - The width and height of the cursor. Currently the size is limited to 1x1.
+- Cursor Style - How the cursor renders. Some terminals support various cursor styles such as Block and Underline.
+- Cursor Visibilty - Whether the cursor is visible to the user or not. NOTE: Some ConsoleDrivers overload Cursor Style and Cursor Visibility, making "invisible" a style. Terminal.Gui HIDES this from developers and changing the visibilty of the cursor does NOT change the style.
+- Caret - Visual indicator that  where text entry will occur. 
+- Selection - A visual indicator to the user that something is selected. It is common for the Selection and Cursor to be the same. It is also common for the Selection and Cursor to be distinct. In a `ListView` the Cursor and Selection (`SelectedItem`) are the same, but the `Cursor` is not visible. In a `TextView` with text selected, the `Cursor` is at either the start or end of the `Selection`. A `TableView' supports mutliple things being selected at once.
+
+## Requirements
+
+- No flickering. The Cursor should blink/pulse at the rate dictated by the terminal. Typing, moving the mouse, view layout, etc... should not caue the cursor to flicker.
+- By default, the Cursor should not be visible. A View or View subclass should have to do anything (this is already the case) to keep the Cursor invisible.
+- Views that just want to show the cursor at a particular location in the Viewport should only have to:
+  - Optionally, declare a desired Cursor Style. Set `Application.CursorStyle`.
+  - Indicate the Cursor Locaiton when internal state dictates the location has changed (debatable if this should be in content or viewport-relative coords). Just set `this.CursorPosition`.
+  - To hide the cursor, simply set `this.CursorPostion` to `null`.
+- The Cursor should only be visible in Views where
+  - `Enabled == true`
+  - `Visible == true`
+  - `CanFocus == true`
+  - `this == SuperView.MostFocused`
+- If a `ConsoleDriver` supports Cursor Styles other than Default, they should be supported per-application (NOT View). 
+- Ensuring the cursor is visible or not should be handled by `Application`, not `View`.
+- General V2 Requirement: View sub-class code should NEVER call a `Driver.` API. Only `Application` and the `View` base class should call `ConsoleDriver` APIs; before we ship v2, all `ConsoleDriver` APIs will be made `internal`.
+
+## Design
+
+### `View` Focus Changes
+
+It doesn't make sense the every View instance has it's own notion of `MostFocused`. The current implemention is overly complicated and fragile because the concept of "MostFocused" is handled by `View`. There can be only ONE "most focused" view in an application. `MostFocused` should be a property on `Application`.
+
+* Remove `View.MostFocused`
+* Change all references to access `Application.MostFocusedView` (see `Application` below)
+* Find all instances of `view._hasFocus = ` and change them to use `SetHasFocus` (today, anyplace that sets `_hasFocus` is a BUG!!).
+* Change `SetFocus`/`SetHasFocus` etc... such that if the focus is changed to a different view heirarchy, `Application.MostFocusedView` gets set appropriately. 
+
+**MORE THOUGHT REQUIRED HERE** - There be dragons given how `Toplevel` has `OnEnter/OnLeave` overrrides. The above needs more study, but is directioally correct.
+
+### `View` Cursor Changes
+* Add `public Point? CursorPosition`
+    - Backed with `private Point? _cursorPosition`
+    - If `!HasValue` the cursor is not visible
+    - If `HasValue` the cursor is visible at the Point.
+    - On set, if `value != _cursorPosition`, call `OnCursorPositionChanged()`
+* Add `public event EventHandler<LocaitonChangedEventArgs>? CursorPositionChanged`
+* Add `internal void OnCursorPositionChanged(LocationChangedEventArgs a)`
+  * Not virtual
+  * Fires `CursorPositionChanged`
+
+### `ConsoleDriver`s
+
+* Remove `Refresh` and have `UpdateScreen` and `UpdateCursor` be called separately. The fact that `Refresh` in all drivers currently calls both is a source of flicker.
+
+* Remove the `xxxCursorVisibility` APIs and replace with:
+  * `internal int CursorStyle {get; internal set; }`
+    - Backed with `private int _cursorStyle`
+    - On set, calls `OnCursorStyleChanged()`
+  * Add `internal abstract void OnCursorStyleChanged()`
+    - Called by `base` whenever the cursor style changes, but ONLY if `value != _cursorStyle`.
+
+  * Add `internal virtual (int Id, string StyleName) []  GetCursorStyles()`
+    - Returns an array of styles supported by the driver, NOT including Invisible. 
+    - The first item in array is always "Default".
+    - Base implementation returns `{ 0, "Default" }`
+    - `CursesDriver` and `WindowsDriver` will need to implement overrides.
+
+  * Add `internal Point? CursorPosition {get; internal set; }`
+    - Backed with `private Point? _cursorPosition`
+    - If `!HasValue` the cursor is not visible
+    - If `HasValue` the cursor is visible at the Point.
+    - On set, calls `OnCursorPositionChanged` ONLY if `value != _cursorPosition`.
+  * Add `internal abstract void OnCursorPositionChanged()`
+    - Called by `base` whenever the cursor position changes. 
+    - Depending on the value of `CursorPosition`:
+        - If `!HasValue` the cursor is not visible - does whatever is needed to make the cursor invisible.
+        - If `HasValue` the cursor is visible at the `CursorPosition` - does whatever is needed to make the cursor visible (using `CursorStyle`).
+
+  * Make sure the drivers only make the cursor visible (or leave it visible) when `CursorPosition` changes!
+
+### `Application`
+
+* 
+
+* Add `internal static View FocusedView {get; private set;}` 
+  - Backed by `private static _focusedView`
+  - On set, 
+    - if `value != _focusedView` 
+        - Unsubscribe from `_focusedView.CursorPositionChanged`
+        - Subscribe to `value.CursorPositionChanged += CursorPositionChanged`        
+        - `_focusedView = value`
+        - Call `UpdateCursor` 
+
+* Add `internal bool CursorPositionChanged (object sender, LocationChangedEventArgs a)`
+
+    Called when:
+
+    - `FocusedView`
+        - Has changed to another View (should cover `FocusedView.Visible/Enable` changes)
+        - Has changed layout - 
+        - Has changeed it's `CursorPosition`
+    - `CursorStyle` has changed
+
+    Does:
+
+    - If `FocusedView is {}` and `FocusedView.CursorPosition` is visible (e.g. w/in `FocusedView.SuperView.Viewport`) 
+        - Does `Driver.CursorPosition = ToScreen(FocusedView.CursorPosition)`
+    - Else
+        - Makes driver cursor invisible with `Driver.CursorPosition = null`
+
+* Add `public static int CursorStyle {get; internal set; }`
+  - Backed with `private static int _cursorStyle
+  - If `value != _cursorStyle`
+    - Calls `ConsoleDriver.CursorStyle = _cursorStyle` 
+    - Calls `UpdateCursor`
+
+* Add `public (int Id, string StyleName) []  GetCursorStyles()`
+  - Calls through to `ConsoleDriver.GetCursorStyles()`
+
+
+
+# Issues with Current Design
+
+## `Driver.Row/Pos`, which are changed via `Move` serves two purposes that confuse each other:
+
+a) Where the next `AddRune` will put the next rune
+b) The current "Cursor Location"
+
+If most TUI apps acted like a command line where the visible cursor was always visible, this might make sense. But the fact that only a very few View subclasses we've seen actually care to show the cursor illustrates a problem:
+
+Any drawing causes the "Cursor Position" to be changed/lost. This means we have a ton of code that is constantly repositioning the cursor every MainLoop iteration.
+
+## The actual cursor position RARELY changes (relative to `Mainloop.Iteration`).
+
+Derived from abo`ve, the current design means we need to call `View.PositionCursor` every iteration. For some views this is a low-cost operation. For others it involves a lot of math. 
+
+This is just stupid. 
+
+## Flicker
+
+Related to the above, we need constantly Show/Hide the cursor every iteration. This causes ridiculous cursor flicker. 
+
+## `View.PositionCursor` is poorly spec'd and confusing to implement correctly
+
+Should a view call `base.PositionCursor`? If so, before or after doing stuff? 
+
+## Setting cursor visibility in `OnEnter` actually makes no sense
+
+First, leaving it up to views to do this is fragile.
+
+Second, when a View gets focus is but one of many places where cursor visibilty should be updated.