From 5b490a8c8f77f735cc492df813aa34c1ef92108e Mon Sep 17 00:00:00 2001 From: BDisp Date: Fri, 7 May 2021 22:38:05 +0100 Subject: [PATCH] Fixes #1266. Using Ctrl+PageUp/PageDown to allowing navigate through windows. (#1283) * Fixes #1266. Using Ctrl+PageUp/PageDown to allowing navigate through windows. * No need to change TextView. * Added configurable navigations keys. --- Terminal.Gui/Core/Application.cs | 9 +++ Terminal.Gui/Core/Toplevel.cs | 8 +++ Terminal.Gui/Views/TextView.cs | 2 +- UnitTests/ApplicationTests.cs | 107 ++++++++++++++++++++++++++++++- 4 files changed, 122 insertions(+), 4 deletions(-) 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); + } } }