diff --git a/Terminal.Gui/Core/Toplevel.cs b/Terminal.Gui/Core/Toplevel.cs
index 881b974260..02691b84f2 100644
--- a/Terminal.Gui/Core/Toplevel.cs
+++ b/Terminal.Gui/Core/Toplevel.cs
@@ -908,6 +908,12 @@ public override void PositionCursor ()
{
if (!IsMdiContainer) {
base.PositionCursor ();
+ if (Focused == null) {
+ EnsureFocus ();
+ if (Focused == null) {
+ Driver.SetCursorVisibility (CursorVisibility.Invisible);
+ }
+ }
return;
}
@@ -920,6 +926,9 @@ public override void PositionCursor ()
}
}
base.PositionCursor ();
+ if (Focused == null) {
+ Driver.SetCursorVisibility (CursorVisibility.Invisible);
+ }
}
///
diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs
index adf368c81e..018cf1384f 100644
--- a/Terminal.Gui/Core/View.cs
+++ b/Terminal.Gui/Core/View.cs
@@ -951,6 +951,10 @@ public virtual void Add (View view)
view.tabIndex = tabIndexes.IndexOf (view);
addingView = false;
}
+ if (view.Enabled && !Enabled) {
+ view.oldEnabled = true;
+ view.Enabled = false;
+ }
SetNeedsLayout ();
SetNeedsDisplay ();
OnAdded (view);
@@ -1303,14 +1307,16 @@ public virtual void PositionCursor ()
return;
}
- if (focused?.Visible == true && focused?.Enabled == true && focused?.Frame.Width > 0 && focused.Frame.Height > 0) {
+ if (focused == null && SuperView != null) {
+ SuperView.EnsureFocus ();
+ } else if (focused?.Visible == true && focused?.Enabled == true && focused?.Frame.Width > 0 && focused.Frame.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 {
- if (CanFocus && HasFocus && Visible && Frame.Width > 0 && Frame.Height > 0) {
- Move (TextFormatter.HotKeyPos == -1 ? 0 : TextFormatter.CursorPosition, 0);
- } else {
- Move (frame.X, frame.Y);
- }
+ Move (frame.X, frame.Y);
}
}
@@ -1504,13 +1510,13 @@ public virtual void Redraw (Rect bounds)
var clipRect = new Rect (Point.Empty, frame.Size);
if (ColorScheme != null) {
- Driver.SetAttribute (HasFocus ? ColorScheme.Focus : ColorScheme.Normal);
+ Driver.SetAttribute (HasFocus ? GetFocusColor () : GetNormalColor ());
}
if (!IgnoreBorderPropertyOnRedraw && Border != null) {
Border.DrawContent (this);
} else if (ustring.IsNullOrEmpty (TextFormatter.Text) &&
- (GetType ().IsNestedPublic) && !IsOverridden (this, "Redraw") &&
+ (GetType ().IsNestedPublic && !IsOverridden (this, "Redraw") || GetType ().Name == "View") &&
(!NeedDisplay.IsEmpty || ChildNeedsDisplay || LayoutNeeded)) {
Clear ();
@@ -1525,8 +1531,8 @@ public virtual void Redraw (Rect bounds)
if (TextFormatter != null) {
TextFormatter.NeedsFormat = true;
}
- TextFormatter?.Draw (ViewToScreen (Bounds), HasFocus ? ColorScheme.Focus : GetNormalColor (),
- HasFocus ? ColorScheme.HotFocus : Enabled ? ColorScheme.HotNormal : ColorScheme.Disabled,
+ TextFormatter?.Draw (ViewToScreen (Bounds), HasFocus ? GetFocusColor () : GetNormalColor (),
+ HasFocus ? ColorScheme.HotFocus : GetHotNormalColor (),
containerBounds);
}
@@ -2617,7 +2623,13 @@ public override bool Enabled {
get => base.Enabled;
set {
if (base.Enabled != value) {
- base.Enabled = value;
+ if (value) {
+ if (SuperView == null || SuperView?.Enabled == true) {
+ base.Enabled = value;
+ }
+ } else {
+ base.Enabled = value;
+ }
if (!value && HasFocus) {
SetHasFocus (false, this);
}
@@ -2684,7 +2696,7 @@ public virtual Border Border {
/// to draw the view's border. If no border is drawn (and the view is expected to draw the border
/// itself).
///
- public virtual bool IgnoreBorderPropertyOnRedraw { get; set; } = false;
+ public virtual bool IgnoreBorderPropertyOnRedraw { get; set; }
///
/// Pretty prints the View
@@ -3109,6 +3121,17 @@ public virtual Attribute GetNormalColor ()
return Enabled ? ColorScheme.Normal : ColorScheme.Disabled;
}
+ ///
+ /// Determines the current based on the value.
+ ///
+ /// if is
+ /// or if is .
+ /// If it's overridden can return other values.
+ public virtual Attribute GetFocusColor ()
+ {
+ return Enabled ? ColorScheme.Focus : ColorScheme.Disabled;
+ }
+
///
/// Determines the current based on the value.
///
diff --git a/UnitTests/TopLevels/ToplevelTests.cs b/UnitTests/TopLevels/ToplevelTests.cs
index 88f9181dd2..e39a73a2c3 100644
--- a/UnitTests/TopLevels/ToplevelTests.cs
+++ b/UnitTests/TopLevels/ToplevelTests.cs
@@ -1011,5 +1011,25 @@ public void OnEnter_OnLeave_Triggered_On_Application_Begin_End ()
Assert.True (isEnter);
Assert.False (isLeave);
}
+
+ [Fact, AutoInitShutdown]
+ public void PositionCursor_SetCursorVisibility_To_Invisible_If_Focused_Is_Null ()
+ {
+ var tf = new TextField ("test") { Width = 5 };
+ var view = new View () { Width = 10, Height = 10 };
+ view.Add (tf);
+ Application.Top.Add (view);
+ Application.Begin (Application.Top);
+
+ Assert.True (tf.HasFocus);
+ Application.Driver.GetCursorVisibility (out CursorVisibility cursor);
+ Assert.Equal (CursorVisibility.Default, cursor);
+
+ view.Enabled = false;
+ Assert.False (tf.HasFocus);
+ Application.Refresh ();
+ Application.Driver.GetCursorVisibility (out cursor);
+ Assert.Equal (CursorVisibility.Invisible, cursor);
+ }
}
}
\ No newline at end of file
diff --git a/UnitTests/Views/ViewTests.cs b/UnitTests/Views/ViewTests.cs
index 1cfc1296bd..396bf7bded 100644
--- a/UnitTests/Views/ViewTests.cs
+++ b/UnitTests/Views/ViewTests.cs
@@ -1,5 +1,6 @@
using NStack;
using System;
+using System.Collections.Generic;
using Terminal.Gui.Graphs;
using Xunit;
using Xunit.Abstractions;
@@ -4209,6 +4210,7 @@ public void Clear_Does_Not_Spillover_Its_Parent (bool label)
v.CanFocus = true;
Assert.False (v.HasFocus);
v.SetFocus ();
+ Assert.True (v.HasFocus);
Application.Refresh ();
TestHelpers.AssertDriverColorsAre (@"
111111111111111111110", attributes);
@@ -4491,6 +4493,7 @@ A text with some long width
A text witith two lines. ", output);
}
+
[Fact, AutoInitShutdown]
public void Test_Nested_Views_With_Height_Equal_To_One ()
{