Skip to content

Commit 2f380ea

Browse files
authored
Merge branch 'develop' into fix-gha-smells
2 parents eae4ca9 + 2e1b1a8 commit 2f380ea

6 files changed

Lines changed: 128 additions & 60 deletions

File tree

‎Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -752,9 +752,9 @@ public override void UpdateOffScreen ()
752752
contents = new int [Rows, Cols, 3];
753753
for (int row = 0; row < Rows; row++) {
754754
for (int col = 0; col < Cols; col++) {
755-
//Curses.move (row, col);
756-
//Curses.attrset (Colors.TopLevel.Normal);
757-
//Curses.addch ((int)(uint)' ');
755+
Curses.move (row, col);
756+
Curses.attrset (Colors.TopLevel.Normal);
757+
Curses.addch ((int)(uint)' ');
758758
contents [row, col, 0] = ' ';
759759
contents [row, col, 1] = Colors.TopLevel.Normal;
760760
contents [row, col, 2] = 0;

‎Terminal.Gui/ConsoleDrivers/NetDriver.cs‎

Lines changed: 83 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,9 @@ internal class NetEvents {
113113
ConsoleDriver consoleDriver;
114114
volatile ConsoleKeyInfo [] cki = null;
115115
static volatile bool isEscSeq;
116-
bool stopTasks;
116+
117+
internal CancellationTokenSource TokenSource = new CancellationTokenSource ();
118+
117119
#if PROCESS_REQUEST
118120
bool neededProcessRequest;
119121
#endif
@@ -125,21 +127,13 @@ public NetEvents (ConsoleDriver consoleDriver)
125127
throw new ArgumentNullException ("Console driver instance must be provided.");
126128
}
127129
this.consoleDriver = consoleDriver;
128-
Task.Run (ProcessInputResultQueue);
129-
Task.Run (CheckWinChange);
130-
}
131-
132-
internal void StopTasks ()
133-
{
134-
stopTasks = true;
130+
Task.Run (ProcessInputResultQueue, TokenSource.Token);
131+
Task.Run (CheckWinChange, TokenSource.Token);
135132
}
136133

137134
public InputResult? ReadConsoleInput ()
138135
{
139-
while (true) {
140-
if (stopTasks) {
141-
return null;
142-
}
136+
while (!TokenSource.IsCancellationRequested) {
143137
waitForStart.Set ();
144138
winChange.Set ();
145139

@@ -154,11 +148,13 @@ internal void StopTasks ()
154148
return inputResultQueue.Dequeue ();
155149
}
156150
}
151+
152+
return null;
157153
}
158154

159155
void ProcessInputResultQueue ()
160156
{
161-
while (true) {
157+
while (!TokenSource.IsCancellationRequested) {
162158
waitForStart.Wait ();
163159
waitForStart.Reset ();
164160

@@ -176,8 +172,23 @@ void GetConsoleKey ()
176172
ConsoleModifiers mod = 0;
177173
ConsoleKeyInfo newConsoleKeyInfo = default;
178174

179-
while (true) {
180-
ConsoleKeyInfo consoleKeyInfo = Console.ReadKey (true);
175+
while (!TokenSource.IsCancellationRequested) {
176+
ConsoleKeyInfo consoleKeyInfo = default;
177+
178+
try {
179+
if (Console.KeyAvailable) {
180+
consoleKeyInfo = Console.ReadKey (true);
181+
} else {
182+
Task.Delay (100, TokenSource.Token).Wait (TokenSource.Token);
183+
if (Console.KeyAvailable) {
184+
consoleKeyInfo = Console.ReadKey (true);
185+
}
186+
}
187+
} catch (OperationCanceledException) {
188+
189+
return;
190+
}
191+
181192
if ((consoleKeyInfo.KeyChar == (char)Key.Esc && !isEscSeq)
182193
|| (consoleKeyInfo.KeyChar != (char)Key.Esc && isEscSeq)) {
183194
if (cki == null && consoleKeyInfo.KeyChar != (char)Key.Esc && isEscSeq) {
@@ -201,18 +212,19 @@ void GetConsoleKey ()
201212
}
202213
break;
203214
} else {
204-
GetConsoleInputType (consoleKeyInfo);
205-
break;
215+
if (consoleKeyInfo != default) {
216+
GetConsoleInputType (consoleKeyInfo);
217+
break;
218+
}
206219
}
220+
221+
TokenSource.Token.ThrowIfCancellationRequested ();
207222
}
208223
}
209224

210225
void CheckWinChange ()
211226
{
212-
while (true) {
213-
if (stopTasks) {
214-
return;
215-
}
227+
while (!TokenSource.IsCancellationRequested) {
216228
winChange.Wait ();
217229
winChange.Reset ();
218230
WaitWinChange ();
@@ -222,13 +234,16 @@ void CheckWinChange ()
222234

223235
void WaitWinChange ()
224236
{
225-
while (true) {
226-
// Wait for a while then check if screen has changed sizes
227-
Task.Delay (500).Wait ();
237+
while (!TokenSource.IsCancellationRequested) {
238+
try {
239+
// Wait for a while then check if screen has changed sizes
240+
Task.Delay (500, TokenSource.Token).Wait (TokenSource.Token);
241+
242+
} catch (OperationCanceledException) {
228243

229-
if (stopTasks) {
230244
return;
231245
}
246+
232247
int buffHeight, buffWidth;
233248
if (((NetDriver)consoleDriver).IsWinPlatform) {
234249
buffHeight = Math.Max (Console.BufferHeight, 0);
@@ -691,7 +706,7 @@ public override void AddStr (ustring str)
691706

692707
public override void End ()
693708
{
694-
mainLoop.netEvents.StopTasks ();
709+
mainLoop.Dispose ();
695710

696711
if (IsWinPlatform) {
697712
NetWinConsole.Cleanup ();
@@ -1019,8 +1034,28 @@ public override void StopReportingMouseMoves ()
10191034

10201035
public override void Suspend ()
10211036
{
1022-
}
1037+
if (Environment.OSVersion.Platform != PlatformID.Unix) {
1038+
return;
1039+
}
1040+
1041+
StopReportingMouseMoves ();
1042+
Console.ResetColor ();
1043+
Console.Clear ();
1044+
1045+
//Disable alternative screen buffer.
1046+
Console.Out.Write ("\x1b[?1049l");
1047+
1048+
//Set cursor key to cursor.
1049+
Console.Out.Write ("\x1b[?25h");
1050+
1051+
Platform.Suspend ();
1052+
1053+
//Enable alternative screen buffer.
1054+
Console.Out.Write ("\x1b[?1049h");
10231055

1056+
Application.Refresh ();
1057+
StartReportingMouseMoves ();
1058+
}
10241059

10251060
public override void SetAttribute (Attribute c)
10261061
{
@@ -1343,7 +1378,11 @@ public override bool GetCursorVisibility (out CursorVisibility visibility)
13431378
public override bool SetCursorVisibility (CursorVisibility visibility)
13441379
{
13451380
savedCursorVisibility = visibility;
1346-
return Console.CursorVisible = visibility == CursorVisibility.Default;
1381+
Console.Out.Write (visibility == CursorVisibility.Default
1382+
? "\x1b[?25h"
1383+
: "\x1b[?25l");
1384+
1385+
return visibility == CursorVisibility.Default;
13471386
}
13481387

13491388
/// <inheritdoc/>
@@ -1423,7 +1462,7 @@ public override void UncookMouse ()
14231462
/// <remarks>
14241463
/// This implementation is used for NetDriver.
14251464
/// </remarks>
1426-
internal class NetMainLoop : IMainLoopDriver {
1465+
internal class NetMainLoop : IMainLoopDriver, IDisposable {
14271466
ManualResetEventSlim keyReady = new ManualResetEventSlim (false);
14281467
ManualResetEventSlim waitForProbe = new ManualResetEventSlim (false);
14291468
Queue<NetEvents.InputResult?> inputResult = new Queue<NetEvents.InputResult?> ();
@@ -1453,27 +1492,25 @@ public NetMainLoop (ConsoleDriver consoleDriver = null)
14531492

14541493
void NetInputHandler ()
14551494
{
1456-
while (true) {
1495+
while (!tokenSource.IsCancellationRequested) {
14571496
waitForProbe.Wait ();
14581497
waitForProbe.Reset ();
14591498
if (inputResult.Count == 0) {
14601499
inputResult.Enqueue (netEvents.ReadConsoleInput ());
14611500
}
1462-
try {
1463-
while (inputResult.Peek () == null) {
1464-
inputResult.Dequeue ();
1465-
}
1466-
if (inputResult.Count > 0) {
1467-
keyReady.Set ();
1468-
}
1469-
} catch (InvalidOperationException) { }
1501+
while (inputResult.Count > 0 && inputResult.Peek () == null) {
1502+
inputResult.Dequeue ();
1503+
}
1504+
if (inputResult.Count > 0) {
1505+
keyReady.Set ();
1506+
}
14701507
}
14711508
}
14721509

14731510
void IMainLoopDriver.Setup (MainLoop mainLoop)
14741511
{
14751512
this.mainLoop = mainLoop;
1476-
Task.Run (NetInputHandler);
1513+
Task.Run (NetInputHandler, tokenSource.Token);
14771514
}
14781515

14791516
void IMainLoopDriver.Wakeup ()
@@ -1503,8 +1540,7 @@ bool IMainLoopDriver.EventsPending (bool wait)
15031540
return inputResult.Count > 0 || CheckTimers (wait, out _);
15041541
}
15051542

1506-
tokenSource.Dispose ();
1507-
tokenSource = new CancellationTokenSource ();
1543+
tokenSource.Token.ThrowIfCancellationRequested ();
15081544
return true;
15091545
}
15101546

@@ -1537,5 +1573,11 @@ void IMainLoopDriver.MainIteration ()
15371573
ProcessInput?.Invoke (inputResult.Dequeue ().Value);
15381574
}
15391575
}
1576+
1577+
public void Dispose ()
1578+
{
1579+
tokenSource.Cancel ();
1580+
netEvents.TokenSource.Cancel ();
1581+
}
15401582
}
15411583
}

‎Terminal.Gui/Core/Application.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1133,9 +1133,9 @@ static void ResetState ()
11331133

11341134
// BUGBUG: MdiTop is not cleared here, but it should be?
11351135

1136-
MainLoop = null;
11371136
Driver?.End ();
11381137
Driver = null;
1138+
MainLoop = null;
11391139
Iteration = null;
11401140
RootMouseEvent = null;
11411141
RootKeyEvent = null;

‎Terminal.Gui/Views/ListView.cs‎

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -601,10 +601,12 @@ public virtual bool MoveUp ()
601601
/// <returns></returns>
602602
public virtual bool MoveEnd ()
603603
{
604-
if (source.Count > 0 && selected != source.Count - 1) {
604+
if (source?.Count > 0 && selected != source.Count - 1) {
605605
selected = source.Count - 1;
606606
if (top + selected > Frame.Height - 1) {
607-
top = selected;
607+
top = selected < Frame.Height - 1
608+
? Math.Max (Frame.Height - selected + 1, 0)
609+
: Math.Max (selected - Frame.Height + 1, 0);
608610
}
609611
OnSelectedChanged ();
610612
SetNeedsDisplay ();
@@ -749,6 +751,11 @@ public override bool OnLeave (View view)
749751
public void EnsureSelectedItemVisible ()
750752
{
751753
SuperView?.LayoutSubviews ();
754+
// If last item is selected and is removed, ensures a valid selected item
755+
if (Source != null && selected > Source.Count - 1) {
756+
SelectedItem = Source.Count - 1;
757+
SetNeedsDisplay ();
758+
}
752759
if (selected < top) {
753760
top = selected;
754761
} else if (Frame.Height > 0 && selected >= top + Frame.Height) {
@@ -831,11 +838,30 @@ public ListWrapper (IList source)
831838
}
832839

833840
/// <inheritdoc/>
834-
public int Count => src != null ? src.Count : 0;
841+
public int Count {
842+
get {
843+
CheckAndResizeMarksIfRequired ();
844+
return src?.Count ?? 0;
845+
}
846+
}
835847

836848
/// <inheritdoc/>
837849
public int Length => len;
838850

851+
void CheckAndResizeMarksIfRequired ()
852+
{
853+
if (src != null && count != src.Count) {
854+
count = src.Count;
855+
BitArray newMarks = new BitArray (count);
856+
for (var i = 0; i < Math.Min (marks.Length, newMarks.Length); i++) {
857+
newMarks [i] = marks [i];
858+
}
859+
marks = newMarks;
860+
861+
len = GetMaxLengthItem ();
862+
}
863+
}
864+
839865
int GetMaxLengthItem ()
840866
{
841867
if (src == null || src?.Count == 0) {
@@ -896,15 +922,15 @@ public void Render (ListView container, ConsoleDriver driver, bool marked, int i
896922
/// <inheritdoc/>
897923
public bool IsMarked (int item)
898924
{
899-
if (item >= 0 && item < count)
925+
if (item >= 0 && item < Count)
900926
return marks [item];
901927
return false;
902928
}
903929

904930
/// <inheritdoc/>
905931
public void SetMark (int item, bool value)
906932
{
907-
if (item >= 0 && item < count)
933+
if (item >= 0 && item < Count)
908934
marks [item] = value;
909935
}
910936

‎UnitTests/UnitTests.csproj‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
</PropertyGroup>
2020
<ItemGroup>
2121
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
22-
<PackageReference Include="ReportGenerator" Version="5.3.4" />
22+
<PackageReference Include="ReportGenerator" Version="5.3.6" />
2323
<PackageReference Include="System.Collections" Version="4.3.0" />
2424
<PackageReference Include="xunit" Version="2.8.1" />
2525
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.1">

‎UnitTests/Views/ListViewTests.cs‎

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -300,16 +300,16 @@ public void Ensures_Visibility_SelectedItem_On_MoveDown_And_MoveUp ()
300300
Assert.Equal (19, lv.SelectedItem);
301301
TestHelpers.AssertDriverContentsWithFrameAre (@"
302302
┌──────────┐
303+
│Line10 │
304+
│Line11 │
305+
│Line12 │
306+
│Line13 │
307+
│Line14 │
308+
│Line15 │
309+
│Line16 │
310+
│Line17 │
311+
│Line18 │
303312
│Line19 │
304-
│ │
305-
│ │
306-
│ │
307-
│ │
308-
│ │
309-
│ │
310-
│ │
311-
│ │
312-
│ │
313313
└──────────┘", output);
314314

315315
Assert.True (lv.ScrollUp (20));

0 commit comments

Comments
 (0)