Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Continuing Implementation of #3692 - Second round of ConsoleDriver cleanup #3737

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
126 commits
Select commit Hold shift + click to select a range
1cbe2f5
Turn on nullability context for this file
dodexahedron Aug 23, 2024
186f384
Seal these
dodexahedron Aug 23, 2024
aa3672b
Owner must dispose
dodexahedron Aug 23, 2024
7dbfee2
Use LibraryImport instead of DllImport
dodexahedron Aug 23, 2024
da27984
Use SafeHandles
dodexahedron Aug 23, 2024
b235843
Implement IDisposable for this, with Finalizer to release handles
dodexahedron Aug 23, 2024
fb8c158
Add fancy new throw helpers and use one right here
dodexahedron Aug 23, 2024
8c5bd3b
Explicit types and target-typed new
dodexahedron Aug 23, 2024
7ecf871
Move this here
dodexahedron Aug 24, 2024
0d34452
Separate these to one type per file
dodexahedron Aug 24, 2024
5805460
Target-typed new everywhere in this file
dodexahedron Aug 24, 2024
f38f324
Add this because xUnit is terrible
dodexahedron Aug 24, 2024
e4b0505
Enable graph build
dodexahedron Aug 24, 2024
fd8ddcc
Add some helper methods to DRY things out
dodexahedron Aug 24, 2024
3a31088
These are pre-conditions. Test should be inconclusive - not fail.
dodexahedron Aug 24, 2024
ae1aaae
Take advantage of those new helpers a bit
dodexahedron Aug 24, 2024
afdd8c4
Categorize a bunch of tests
dodexahedron Aug 24, 2024
2e9901f
Turn on null analysis for this file and annotate a bunch of stuff
dodexahedron Aug 24, 2024
75bfb74
Fix warning for deprecated test declaration style
dodexahedron Aug 24, 2024
c385fdc
Make these tests repeatable
dodexahedron Aug 24, 2024
c6d95ea
Add generic forms of these methods
dodexahedron Aug 24, 2024
cdf2390
Add this to the base so we can actually test it.
dodexahedron Aug 24, 2024
867fb23
Cleanup
dodexahedron Aug 24, 2024
3a84fb1
Deal with nulls a little better
dodexahedron Aug 24, 2024
bcea74b
Make a note of what looks like a bug
dodexahedron Aug 24, 2024
2efe1ce
More null safety, ref magic, and shortening chopped lines
dodexahedron Aug 24, 2024
c4524b2
Use a pattern match to in-line that
dodexahedron Aug 24, 2024
74760dc
Slight xmldoc improvement and make this get only once to avoid even m…
dodexahedron Aug 24, 2024
fd66c35
Mark this as must dispose
dodexahedron Aug 24, 2024
7ae4be4
0 is already default for int
dodexahedron Aug 24, 2024
d3421fd
Note some buggy locking behavior
dodexahedron Aug 24, 2024
78fe581
Take the rune by reference and tell the compiler to inline it like it…
dodexahedron Aug 24, 2024
f2f5dea
Make a note about how this appears to be doing several unnecessary th…
dodexahedron Aug 24, 2024
1d2bb14
Carry base change through to these and fix up xmldoc
dodexahedron Aug 24, 2024
b7deea7
Make use of generic method calls.
dodexahedron Aug 24, 2024
92d9ba8
This helps avoid test and build failures because of locked files.
dodexahedron Aug 24, 2024
d298852
These make a lot more sense as IOException because of what is happening.
dodexahedron Aug 24, 2024
b2e1b0a
And that lets us address this with much better precision
dodexahedron Aug 24, 2024
7bff9a2
Run formatting rules
dodexahedron Aug 24, 2024
a3f4993
Those can just be in-lined
dodexahedron Aug 24, 2024
87bd4e2
Target-typed new
dodexahedron Aug 24, 2024
f0148a3
Nullability
dodexahedron Aug 24, 2024
200ed1b
Turning this up for visibility
dodexahedron Aug 26, 2024
c4465ee
Add BOOL type for Win32 interop
dodexahedron Aug 26, 2024
3af8852
Add CONSOLE_MODE type for Win32 interop
dodexahedron Aug 26, 2024
b438585
Add HANDLE type for Win32 interop.
dodexahedron Aug 26, 2024
93fc2be
Make BOOL mo betta
dodexahedron Aug 31, 2024
84c37fa
Add STD_HANDLE enum for console IO stream handle constants
dodexahedron Aug 26, 2024
cdb3602
Adding localized strings in english and es-mx for some new exceptions
dodexahedron Aug 28, 2024
10045e3
Just in case anyone ain't paying attention
dodexahedron Aug 31, 2024
150221e
OK, so we don't need this. since SafeFileHandle already has a custom …
dodexahedron Aug 31, 2024
b8c7bc1
Add a couple more (localized) strings and fix missing punctuation.
dodexahedron Aug 31, 2024
24e696d
Bump minimums on these to current release
dodexahedron Aug 31, 2024
a2baa5b
Include all of this. I'll refine it later.
dodexahedron Aug 31, 2024
a29be62
Put that in a more logical order
dodexahedron Aug 31, 2024
6675ce0
That is nullable
dodexahedron Aug 31, 2024
1cd3438
Add separate file for ReSpeller spelling dictionary
dodexahedron Aug 31, 2024
d7275b8
Optimization and cleanup
dodexahedron Aug 31, 2024
9659a0a
Move these again after rebase on updated v2_develop.
dodexahedron Aug 31, 2024
ddf1a97
Add the new PInvoke class for Windows
dodexahedron Aug 31, 2024
b120709
Behold! The new NetWinVTConsole using FileStream and minimal PInvoke
dodexahedron Aug 31, 2024
8342d79
XmlDoc tweaks
dodexahedron Aug 31, 2024
ace93f8
Make that generic
dodexahedron Aug 31, 2024
785dc83
Add annotation for IDisposable type
dodexahedron Aug 31, 2024
84cc1a6
Simplify
dodexahedron Aug 31, 2024
ed503a4
Move that to the end
dodexahedron Aug 31, 2024
0cabf39
Fix and annotate a couple of tests
dodexahedron Aug 31, 2024
48cd8cd
Improve/fix this test
dodexahedron Aug 31, 2024
7f9fc38
Seal this
dodexahedron Aug 31, 2024
2df6461
Set the record straight
dodexahedron Aug 31, 2024
32a06ed
Some cleanup and notes.
dodexahedron Aug 31, 2024
506e042
Only dispose once
dodexahedron Aug 31, 2024
3a192ba
Let these use the helpers too
dodexahedron Aug 31, 2024
1440a9b
Note a GetType that needs to die
dodexahedron Sep 2, 2024
9319591
Questions answered in PR
dodexahedron Sep 1, 2024
a7ffd98
Address some sporadically broken tests after rebase
dodexahedron Sep 4, 2024
d3e4bc8
Clean this up before tackling whatever is wrong with it in CI
dodexahedron Sep 4, 2024
42f3250
Rename resource file (case sensitivity)
dodexahedron Sep 4, 2024
0bc7c5b
Ok, so let's put these in the test project then
dodexahedron Sep 4, 2024
782c604
Fix typo and convert to MemberData for future test improvements
dodexahedron Sep 4, 2024
211560b
Cleaned up and put shifted and unshifted in same order
dodexahedron Sep 5, 2024
bcb5ed1
Remove these two comments as no longer relevant after reorg
dodexahedron Sep 5, 2024
6b27e09
Categorize these
dodexahedron Sep 5, 2024
fc87cf1
Cleanup so it quits complaining about these 16 lines 😆
dodexahedron Sep 5, 2024
70f3b0a
Address the comment I added earlier by making it compile-time constan…
dodexahedron Sep 5, 2024
5b47c9c
Always true
dodexahedron Sep 5, 2024
bdbb1e1
Minor XmlDoc tweak
dodexahedron Sep 5, 2024
54e2570
That needs a null check or it's going to end up throwing on null anyway
dodexahedron Sep 5, 2024
1724878
Turn on null analysis, annotate appropriately, and run formatter
dodexahedron Sep 5, 2024
34bbb1e
Formalize this a bit more
dodexahedron Sep 5, 2024
ec1b284
Actually use BOOL and remove STD_HANDLE
dodexahedron Sep 5, 2024
5b898d9
Remove no longer necessary constant
dodexahedron Sep 5, 2024
3d0743f
Fix invalid diff application after rebase
dodexahedron Sep 6, 2024
bcfa233
Document, enhance, and add some tests for BOOL
dodexahedron Sep 8, 2024
80e6561
Fix marshal incompatibility
dodexahedron Sep 8, 2024
207880f
While I'm at it, may as well make it fully correct here too
dodexahedron Sep 8, 2024
8483df2
Add pre-conditions to this test for stronger validity.
dodexahedron Sep 11, 2024
cde7d6c
Mark this as only supporting windows as a bit of a stronger deterrent…
dodexahedron Sep 11, 2024
f5625fc
Flip parameter order since Yoda Xunit is.
dodexahedron Sep 11, 2024
e2cb741
Delegate CompareTo to one implementation and add a test for it
dodexahedron Sep 9, 2024
eafb306
Clean that up since it ended up not being used after BOOL was made pu…
dodexahedron Sep 9, 2024
2d1f5b9
Tag a note and mark this obsolete for visibility since I'll be replac…
dodexahedron Sep 9, 2024
d7f495f
Address a couple of nullability warnings
dodexahedron Sep 11, 2024
cb0474d
Some platform support attributes for Roslyn
dodexahedron Sep 11, 2024
2d40626
A word for the dictionary
dodexahedron Sep 11, 2024
11eb466
These are static
dodexahedron Sep 11, 2024
b9d35ba
Fix an invalid handle
dodexahedron Sep 11, 2024
cea8e9f
Somewhat better disposal
dodexahedron Sep 11, 2024
e633e4d
Fix some disallowed whitespace warnings
dodexahedron Sep 11, 2024
ee3695f
Add some TODO comments
dodexahedron Sep 11, 2024
bb8ce1c
Add some notes and use the .net 8 constants for these
dodexahedron Sep 11, 2024
68a1df5
Use the same names for parameters as the overridden members.
dodexahedron Sep 11, 2024
e0129fb
Update to match
dodexahedron Sep 11, 2024
820dddc
Suppress these because they're not wrong.
dodexahedron Sep 11, 2024
b4f8451
Nuke several more nullability warnings
dodexahedron Sep 11, 2024
978671d
Quick cleanup and annotation pass on this before making functional ch…
dodexahedron Sep 6, 2024
d8e400e
Move that for now
dodexahedron Sep 6, 2024
221011f
One type per file
dodexahedron Sep 6, 2024
2b2882b
Run cleanup rules on this before working on it.
dodexahedron Sep 6, 2024
2eb0402
Move WindowsConsole to its own file
dodexahedron Sep 9, 2024
4820ef5
Add SetConsoleWindowInfo to windows PInvoke class
dodexahedron Sep 9, 2024
bb93787
Move SmallRect to its own file and give it a constructor for a common…
dodexahedron Sep 9, 2024
5660b2b
Switch SmallRect to explicit layout
dodexahedron Sep 9, 2024
73aed6d
This is about to get re-used, so rename it to be more generic
dodexahedron Sep 9, 2024
cd30900
Add another PInvoke used by WindowsConsole
dodexahedron Sep 9, 2024
19f177e
CONSOLE_MODE is now a struct with a mind of its own
dodexahedron Sep 13, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_preserve_single_line_blocks = true
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
dotnet_style_require_accessibility_modifiers = for_non_interface_members:warning
csharp_prefer_braces = true:warning
csharp_space_between_method_call_name_and_opening_parenthesis = true
csharp_space_between_method_declaration_name_and_open_parenthesis = true
Expand Down
47 changes: 38 additions & 9 deletions Terminal.Gui/Application/Application.Initialization.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,40 @@ public static partial class Application // Initialization (Init/Shutdown)
[RequiresDynamicCode ("AOT")]
public static void Init (ConsoleDriver? driver = null, string? driverName = null) { InternalInit (driver, driverName); }

/// <summary>Initializes a new instance of <see cref="Terminal.Gui"/> Application.</summary>
/// <para>Call this method once per instance (or after <see cref="Shutdown"/> has been called).</para>
/// <para>
/// This function loads the right <see cref="ConsoleDriver"/> for the platform, Creates a <see cref="Toplevel"/>. and
/// assigns it to <see cref="Top"/>
/// </para>
/// <para>
/// <see cref="Shutdown"/> must be called when the application is closing (typically after
/// <see cref="Run{T}"/> has returned) to ensure resources are cleaned up and
/// terminal settings
/// restored.
/// </para>
/// <para>
/// The <see cref="Run{T}"/> function combines
/// <see cref="Init(Terminal.Gui.ConsoleDriver,string)"/> and <see cref="Run(Toplevel, Func{Exception, bool})"/>
/// into a single
/// call. An application cam use <see cref="Run{T}"/> without explicitly calling
/// <see cref="Init(Terminal.Gui.ConsoleDriver,string)"/>.
/// </para>
/// <typeparam name="TDriver">
/// The <see cref="ConsoleDriver"/>-derived type to use. A default instance will be created.
/// </typeparam>
public static void Init<TDriver> () where TDriver : ConsoleDriver, new () { InternalInit (new TDriver ()); }

internal static bool IsInitialized { get; set; }
internal static int MainThreadId { get; set; } = -1;

/// <summary>
/// Internal method to call <see cref="InternalInit"/> with a default instance of the driver type specified in <typeparamref name="TDriver"/>.
/// </summary>
/// <typeparam name="TDriver">The <see cref="ConsoleDriver"/>-derived type to create and pass to <see cref="InternalInit"/>.</typeparam>
/// <param name="calledViaRunT">If false (default) all state will be reset. If true the state will not be reset.</param>
internal static void InternalInit<TDriver> (bool calledViaRunT = false) where TDriver : ConsoleDriver, new () { InternalInit (new TDriver ()); }

// INTERNAL function for initializing an app with a Toplevel factory object, driver, and mainloop.
//
// Called from:
Expand All @@ -58,14 +89,12 @@ internal static void InternalInit (
bool calledViaRunT = false
)
{
if (IsInitialized && driver is null)
{
return;
}

if (IsInitialized)
switch (IsInitialized)
{
throw new InvalidOperationException ("Init has already been called and must be bracketed by Shutdown.");
case true when driver is null:
return;
case true:
throw new InvalidOperationException ("Init has already been called and must be bracketed by Shutdown.");
}

if (!calledViaRunT)
Expand Down Expand Up @@ -117,7 +146,7 @@ internal static void InternalInit (
else
{
List<Type?> drivers = GetDriverTypes ();
Type? driverType = drivers.FirstOrDefault (t => t!.Name.Equals (ForceDriver, StringComparison.InvariantCultureIgnoreCase));
Type? driverType = drivers.FirstOrDefault (static t => t!.Name.Equals (ForceDriver, StringComparison.InvariantCultureIgnoreCase));

if (driverType is { })
{
Expand All @@ -134,7 +163,7 @@ internal static void InternalInit (

try
{
MainLoop = Driver!.Init ();
MainLoop = Driver.Init ();
}
catch (InvalidOperationException ex)
{
Expand Down
2 changes: 1 addition & 1 deletion Terminal.Gui/Application/Application.Run.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public static partial class Application // Run (Begin, Run, End, Stop)
/// in the screen. This is usually followed by executing the <see cref="RunLoop"/> method, and then the
/// <see cref="End(RunState)"/> method upon termination which will undo these changes.
/// </remarks>
public static RunState Begin (Toplevel toplevel)
public static RunState Begin (Toplevel? toplevel)
{
ArgumentNullException.ThrowIfNull (toplevel);

Expand Down
26 changes: 22 additions & 4 deletions Terminal.Gui/ConsoleDrivers/ConsoleDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

namespace Terminal.Gui;

using System.Runtime.CompilerServices;

/// <summary>Base class for Terminal.Gui ConsoleDriver implementations.</summary>
/// <remarks>
/// There are currently four implementations: - <see cref="CursesDriver"/> (for Unix and Mac) -
Expand Down Expand Up @@ -73,7 +75,7 @@ internal set
public Cell [,]? Contents { get; internal set; }

/// <summary>The leftmost column in the terminal.</summary>
public virtual int Left { get; internal set; } = 0;
public virtual int Left { get; internal set; }

/// <summary>
/// Gets the row last set by <see cref="Move"/>. <see cref="Col"/> and <see cref="Row"/> are used by
Expand Down Expand Up @@ -135,6 +137,7 @@ public void AddRune (Rune rune)
rune = rune.MakePrintable ();
runeWidth = rune.GetColumns ();

// BUG: CONCURRENCY: This is broken.
lock (Contents)
{
if (runeWidth == 0 && rune.IsCombiningMark ())
Expand Down Expand Up @@ -266,6 +269,7 @@ public void AddRune (Rune rune)

if (validLocation && Col < Clip.Right)
{
// BUG: CONCURRENCY: This is broken.
lock (Contents!)
{
// This is a double-width character, and we are not at the end of the line.
Expand Down Expand Up @@ -314,7 +318,7 @@ public void AddStr (string str)
public void ClearContents ()
{
Contents = new Cell [Rows, Cols];
//CONCURRENCY: Unsynchronized access to Clip isn't safe.
// CONCURRENCY: Unsynchronized access to Clip isn't safe.
// TODO: ClearContents should not clear the clip; it should only clear the contents. Move clearing it elsewhere.
Clip = Screen;
_dirtyLines = new bool [Rows];
Expand All @@ -332,6 +336,7 @@ public void ClearContents ()
IsDirty = true
};
}

_dirtyLines [row] = true;
}
}
Expand All @@ -351,6 +356,7 @@ public void SetContentsAsDirty ()
{
Contents [row, c].IsDirty = true;
}

_dirtyLines! [row] = true;
}
}
Expand All @@ -369,6 +375,8 @@ public void SetContentsAsDirty ()
public void FillRect (Rectangle rect, Rune rune = default)
{
rect = Rectangle.Intersect (rect, Clip);

// BUG: CONCURRENCY: This is broken.
lock (Contents!)
{
for (int r = rect.Y; r < rect.Y + rect.Height; r++)
Expand Down Expand Up @@ -401,15 +409,16 @@ public void FillRect (Rectangle rect, Rune rune = default)

/// <summary>Returns the name of the driver and relevant library version information.</summary>
/// <returns></returns>
public virtual string GetVersionInfo () { return GetType ().Name; }
public abstract string GetVersionInfo ();

/// <summary>Tests if the specified rune is supported by the driver.</summary>
/// <param name="rune"></param>
/// <returns>
/// <see langword="true"/> if the rune can be properly presented; <see langword="false"/> if the driver does not
/// support displaying this rune.
/// </returns>
public virtual bool IsRuneSupported (Rune rune) { return Rune.IsValid (rune.Value); }
[MethodImpl (MethodImplOptions.AggressiveInlining)]
public virtual bool IsRuneSupported (in Rune rune) => Rune.IsValid (rune.Value);

/// <summary>Tests whether the specified coordinate are valid for drawing.</summary>
/// <param name="col">The column.</param>
Expand All @@ -420,6 +429,13 @@ public void FillRect (Rectangle rect, Rune rune = default)
/// </returns>
public bool IsValidLocation (int col, int row)
{
// TODO: Remove this commentary or implement when partial-screen is supported.
// Screen is hard-coded to have origin at 0,0.
// Screen is also hard-coded to be Cols x Rows in size.
// Clip intersects it.
// Therefore, the call to Clip.Contains(col, row) already covers col >= 0 and row >= 0.
// The checks for col < Cols and row < Rows can also be eliminated by making the entire line be:
// return Clip.Contains (col + 1, row + 1);
return col >= 0 && row >= 0 && col < Cols && row < Rows && Clip.Contains (col, row);
}

Expand Down Expand Up @@ -455,6 +471,8 @@ public virtual void Move (int col, int row)
/// <returns><see langword="true"/> upon success</returns>
public abstract bool SetCursorVisibility (CursorVisibility visibility);

public abstract void SetWindowPosition (int left, int top);

/// <summary>The event fired when the terminal is resized.</summary>
public event EventHandler<SizeChangedEventArgs>? SizeChanged;

Expand Down
Loading
Loading