diff --git a/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs b/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs
index 8a443133e..d79f5007b 100644
--- a/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs
+++ b/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs
@@ -391,6 +391,7 @@ namespace Terminal.Gui {
keyHandler (new KeyEvent (map, keyModifiers));
keyUpHandler (new KeyEvent (map, keyModifiers));
+ keyModifiers = new KeyModifiers ();
};
}
diff --git a/Terminal.Gui/Core/Event.cs b/Terminal.Gui/Core/Event.cs
index 04ae3b961..83ccffe61 100644
--- a/Terminal.Gui/Core/Event.cs
+++ b/Terminal.Gui/Core/Event.cs
@@ -392,7 +392,7 @@ namespace Terminal.Gui {
/// Gets a value indicating whether the Shift key was pressed.
///
/// true if is shift; otherwise, false.
- public bool IsShift => keyModifiers.Shift;
+ public bool IsShift => keyModifiers.Shift || Key == Key.BackTab;
///
/// Gets a value indicating whether the Alt key was pressed (real or synthesized)
diff --git a/Terminal.Gui/Core/Toplevel.cs b/Terminal.Gui/Core/Toplevel.cs
index 19b133ef9..69f75e3a3 100644
--- a/Terminal.Gui/Core/Toplevel.cs
+++ b/Terminal.Gui/Core/Toplevel.cs
@@ -195,7 +195,7 @@ namespace Terminal.Gui {
if (base.ProcessKey (keyEvent))
return true;
- switch (keyEvent.Key) {
+ switch (ShortcutHelper.GetModifiersKey (keyEvent)) {
case Key.Q | Key.CtrlMask:
// FIXED: stop current execution of this container
Application.RequestStop ();
@@ -217,27 +217,32 @@ namespace Terminal.Gui {
var old = GetDeepestFocusedSubview (Focused);
if (!FocusNext ())
FocusNext ();
- if (old != Focused) {
+ if (old != Focused && old != Focused?.Focused) {
old?.SetNeedsDisplay ();
Focused?.SetNeedsDisplay ();
} else {
- FocusNearestView (GetToplevelSubviews (true));
+ FocusNearestView (SuperView?.TabIndexes, Direction.Forward);
}
return true;
+ case Key.BackTab | Key.ShiftMask:
case Key.CursorLeft:
case Key.CursorUp:
- case Key.BackTab:
old = GetDeepestFocusedSubview (Focused);
if (!FocusPrev ())
FocusPrev ();
- if (old != Focused) {
+ if (old != Focused && old != Focused?.Focused) {
old?.SetNeedsDisplay ();
Focused?.SetNeedsDisplay ();
} else {
- FocusNearestView (GetToplevelSubviews (false));
+ FocusNearestView (SuperView?.TabIndexes?.Reverse(), Direction.Backward);
}
return true;
-
+ case Key.Tab | Key.CtrlMask:
+ Application.Top.FocusNext ();
+ return true;
+ case Key.Tab | Key.ShiftMask | Key.CtrlMask:
+ Application.Top.FocusPrev ();
+ return true;
case Key.L | Key.CtrlMask:
Application.Refresh ();
return true;
@@ -272,39 +277,34 @@ namespace Terminal.Gui {
return view;
}
- IEnumerable GetToplevelSubviews (bool isForward)
- {
- if (SuperView == null) {
- return null;
- }
-
- HashSet views = new HashSet ();
-
- foreach (var v in SuperView.Subviews) {
- views.Add (v);
- }
-
- return isForward ? views : views.Reverse ();
- }
-
- void FocusNearestView (IEnumerable views)
+ void FocusNearestView (IEnumerable views, Direction direction)
{
if (views == null) {
return;
}
bool found = false;
+ bool focusProcessed = false;
+ int idx = 0;
foreach (var v in views) {
if (v == this) {
found = true;
}
if (found && v != this) {
- v.EnsureFocus ();
+ if (direction == Direction.Forward) {
+ SuperView?.FocusNext ();
+ } else {
+ SuperView?.FocusPrev ();
+ }
+ focusProcessed = true;
if (SuperView.Focused != null && SuperView.Focused != this) {
return;
}
+ } else if (found && !focusProcessed && idx == views.Count () - 1) {
+ views.ToList () [0].SetFocus ();
}
+ idx++;
}
}
diff --git a/UICatalog/Scenarios/WindowsAndFrameViews.cs b/UICatalog/Scenarios/WindowsAndFrameViews.cs
index 0d7f108c3..df590328c 100644
--- a/UICatalog/Scenarios/WindowsAndFrameViews.cs
+++ b/UICatalog/Scenarios/WindowsAndFrameViews.cs
@@ -108,7 +108,7 @@ namespace UICatalog {
var frameView = new FrameView ("This is a Sub-FrameView") {
X = Pos.Percent (50),
Y = 1,
- Width = Dim.Percent (100),
+ Width = Dim.Percent (100, true), // Or Dim.Percent (50)
Height = 5,
ColorScheme = Colors.Base,
Text = "The Text in the FrameView",
diff --git a/UnitTests/ViewTests.cs b/UnitTests/ViewTests.cs
index dfb45df8b..990e3f9c9 100644
--- a/UnitTests/ViewTests.cs
+++ b/UnitTests/ViewTests.cs
@@ -6,7 +6,7 @@ using System.Linq;
using Terminal.Gui;
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 {
@@ -27,9 +27,9 @@ namespace Terminal.Gui {
Assert.Null (r.ColorScheme);
Assert.Equal (Dim.Sized (0), r.Width);
Assert.Equal (Dim.Sized (0), r.Height);
- // BUGBUG: Pos needs eqality implemented
- //Assert.Equal (Pos.At (0), r.X);
- //Assert.Equal (Pos.At (0), r.Y);
+ // FIXED: Pos needs equality implemented
+ Assert.Equal (Pos.At (0), r.X);
+ Assert.Equal (Pos.At (0), r.Y);
Assert.False (r.IsCurrentTop);
Assert.Empty (r.Id);
Assert.Empty (r.Subviews);
@@ -1077,5 +1077,37 @@ namespace Terminal.Gui {
Assert.True (view.Frame.IsEmpty);
Assert.True (view.Bounds.IsEmpty);
}
+
+ [Fact]
+ public void FocusNearestView_Ensure_Focus_Ordered ()
+ {
+ var top = new Toplevel ();
+
+ var win = new Window ();
+ var winSubview = new View ("WindowSubview") {
+ CanFocus = true
+ };
+ win.Add (winSubview);
+ top.Add (win);
+
+ var frm = new FrameView ();
+ var frmSubview = new View ("FrameSubview") {
+ CanFocus = true
+ };
+ frm.Add (frmSubview);
+ top.Add (frm);
+
+ top.ProcessKey (new KeyEvent (Key.Tab, new KeyModifiers ()));
+ Assert.Equal ($"WindowSubview", top.MostFocused.Text);
+ top.ProcessKey (new KeyEvent (Key.Tab, new KeyModifiers ()));
+ Assert.Equal ("FrameSubview", top.MostFocused.Text);
+ top.ProcessKey (new KeyEvent (Key.Tab, new KeyModifiers ()));
+ Assert.Equal ($"WindowSubview", top.MostFocused.Text);
+
+ top.ProcessKey (new KeyEvent (Key.BackTab | Key.ShiftMask, new KeyModifiers ()));
+ Assert.Equal ("FrameSubview", top.MostFocused.Text);
+ top.ProcessKey (new KeyEvent (Key.BackTab | Key.ShiftMask, new KeyModifiers ()));
+ Assert.Equal ($"WindowSubview", top.MostFocused.Text);
+ }
}
}