diff --git a/Terminal.Gui/Core/Application.cs b/Terminal.Gui/Core/Application.cs
index 33ca8f0eb..f0d59ae81 100644
--- a/Terminal.Gui/Core/Application.cs
+++ b/Terminal.Gui/Core/Application.cs
@@ -110,6 +110,15 @@ namespace Terminal.Gui {
}
}
+ ///
+ /// Alternative key to navigate forwards through all views. Ctrl+Tab is always used.
+ ///
+ public static Key AlternateForwardKey { get; set; } = Key.PageDown | Key.CtrlMask;
+ ///
+ /// Alternative key to navigate backwards through all views. Shift+Ctrl+Tab is always used.
+ ///
+ public static Key AlternateBackwardKey { get; set; } = Key.PageUp | Key.CtrlMask;
+
///
/// The driver for the application
///
diff --git a/Terminal.Gui/Core/Toplevel.cs b/Terminal.Gui/Core/Toplevel.cs
index 69f75e3a3..a933f9a05 100644
--- a/Terminal.Gui/Core/Toplevel.cs
+++ b/Terminal.Gui/Core/Toplevel.cs
@@ -238,10 +238,18 @@ namespace Terminal.Gui {
}
return true;
case Key.Tab | Key.CtrlMask:
+ case Key key when key == Application.AlternateForwardKey: // Needed on Unix
Application.Top.FocusNext ();
+ if (Application.Top.Focused == null) {
+ Application.Top.FocusNext ();
+ }
return true;
case Key.Tab | Key.ShiftMask | Key.CtrlMask:
+ case Key key when key == Application.AlternateBackwardKey: // Needed on Unix
Application.Top.FocusPrev ();
+ if (Application.Top.Focused == null) {
+ Application.Top.FocusPrev ();
+ }
return true;
case Key.L | Key.CtrlMask:
Application.Refresh ();
diff --git a/Terminal.Gui/Views/TextView.cs b/Terminal.Gui/Views/TextView.cs
index 9717ad193..62d583c42 100644
--- a/Terminal.Gui/Views/TextView.cs
+++ b/Terminal.Gui/Views/TextView.cs
@@ -2017,7 +2017,7 @@ namespace Terminal.Gui {
StopSelecting ();
}
int nPageDnShift = Frame.Height - 1;
- if (currentRow > 0 && currentRow < model.Count) {
+ if (currentRow >= 0 && currentRow < model.Count) {
if (columnTrack == -1)
columnTrack = currentColumn;
currentRow = (currentRow + nPageDnShift) > model.Count
diff --git a/UnitTests/ApplicationTests.cs b/UnitTests/ApplicationTests.cs
index a7f5f597e..f35eaea51 100644
--- a/UnitTests/ApplicationTests.cs
+++ b/UnitTests/ApplicationTests.cs
@@ -4,7 +4,7 @@ using System.Threading;
using System.Threading.Tasks;
using Xunit;
-// Alais Console to MockConsole so we don't accidentally use Console
+// Alias Console to MockConsole so we don't accidentally use Console
using Console = Terminal.Gui.FakeConsole;
namespace Terminal.Gui.Core {
@@ -19,7 +19,7 @@ namespace Terminal.Gui.Core {
[Fact]
public void Init_Shutdown_Cleans_Up ()
{
- // Verify inital state is per spec
+ // Verify initial state is per spec
Pre_Init_State ();
Application.Init (new FakeDriver (), new FakeMainLoop (() => FakeConsole.ReadKey (true)));
@@ -175,7 +175,7 @@ namespace Terminal.Gui.Core {
// Setup Mock driver
Init ();
- // Setup some fake kepresses (This)
+ // Setup some fake keypresses (This)
var input = "Tests";
// Put a control-q in at the end
@@ -268,5 +268,106 @@ namespace Terminal.Gui.Core {
Application.Shutdown ();
Assert.Null (SynchronizationContext.Current);
}
+
+ [Fact]
+ public void AlternateForwardKey_AlternateBackwardKey_Tests ()
+ {
+ Init ();
+
+ var top = Application.Top;
+ var w1 = new Window ();
+ var v1 = new TextField ();
+ var v2 = new TextView ();
+ w1.Add (v1, v2);
+
+ var w2 = new Window ();
+ var v3 = new CheckBox ();
+ var v4 = new Button ();
+ w2.Add (v3, v4);
+
+ top.Add (w1, w2);
+
+ Application.Iteration += () => {
+ Assert.True (v1.HasFocus);
+ // Using default keys.
+ top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.Tab,
+ new KeyModifiers () { Ctrl = true }));
+ Assert.True (v2.HasFocus);
+ top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.Tab,
+ new KeyModifiers () { Ctrl = true }));
+ Assert.True (v3.HasFocus);
+ top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.Tab,
+ new KeyModifiers () { Ctrl = true }));
+ Assert.True (v4.HasFocus);
+ top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.Tab,
+ new KeyModifiers () { Ctrl = true }));
+ Assert.True (v1.HasFocus);
+
+ top.ProcessKey (new KeyEvent (Key.ShiftMask | Key.CtrlMask | Key.Tab,
+ new KeyModifiers () { Shift = true, Ctrl = true }));
+ Assert.True (v4.HasFocus);
+ top.ProcessKey (new KeyEvent (Key.ShiftMask | Key.CtrlMask | Key.Tab,
+ new KeyModifiers () { Shift = true, Ctrl = true }));
+ Assert.True (v3.HasFocus);
+ top.ProcessKey (new KeyEvent (Key.ShiftMask | Key.CtrlMask | Key.Tab,
+ new KeyModifiers () { Shift = true, Ctrl = true }));
+ Assert.True (v2.HasFocus);
+ top.ProcessKey (new KeyEvent (Key.ShiftMask | Key.CtrlMask | Key.Tab,
+ new KeyModifiers () { Shift = true, Ctrl = true }));
+ Assert.True (v1.HasFocus);
+
+ top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.PageDown,
+ new KeyModifiers () { Ctrl = true }));
+ Assert.True (v2.HasFocus);
+ top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.PageDown,
+ new KeyModifiers () { Ctrl = true }));
+ Assert.True (v3.HasFocus);
+ top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.PageDown,
+ new KeyModifiers () { Ctrl = true }));
+ Assert.True (v4.HasFocus);
+ top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.PageDown,
+ new KeyModifiers () { Ctrl = true }));
+ Assert.True (v1.HasFocus);
+
+ top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.PageUp,
+ new KeyModifiers () { Ctrl = true }));
+ Assert.True (v4.HasFocus);
+ top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.PageUp,
+ new KeyModifiers () { Ctrl = true }));
+ Assert.True (v3.HasFocus);
+ top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.PageUp,
+ new KeyModifiers () { Ctrl = true }));
+ Assert.True (v2.HasFocus);
+ top.ProcessKey (new KeyEvent (Key.CtrlMask | Key.PageUp,
+ new KeyModifiers () { Ctrl = true }));
+ Assert.True (v1.HasFocus);
+
+ // Using another's alternate keys.
+ Application.AlternateForwardKey = Key.F7;
+ Application.AlternateBackwardKey = Key.F6;
+
+ top.ProcessKey (new KeyEvent (Key.F7, new KeyModifiers ()));
+ Assert.True (v2.HasFocus);
+ top.ProcessKey (new KeyEvent (Key.F7, new KeyModifiers ()));
+ Assert.True (v3.HasFocus);
+ top.ProcessKey (new KeyEvent (Key.F7, new KeyModifiers ()));
+ Assert.True (v4.HasFocus);
+ top.ProcessKey (new KeyEvent (Key.F7, new KeyModifiers ()));
+ Assert.True (v1.HasFocus);
+
+ top.ProcessKey (new KeyEvent (Key.F6, new KeyModifiers ()));
+ Assert.True (v4.HasFocus);
+ top.ProcessKey (new KeyEvent (Key.F6, new KeyModifiers ()));
+ Assert.True (v3.HasFocus);
+ top.ProcessKey (new KeyEvent (Key.F6, new KeyModifiers ()));
+ Assert.True (v2.HasFocus);
+ top.ProcessKey (new KeyEvent (Key.F6, new KeyModifiers ()));
+ Assert.True (v1.HasFocus);
+
+ Application.RequestStop ();
+ };
+
+ Application.Run (top);
+ }
}
}