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

Pause io #110

Merged
merged 13 commits into from
Nov 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 src/.editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false
csharp_style_namespace_declarations = file_scoped:suggestion
csharp_style_namespace_declarations = block_scoped:suggestion
csharp_style_var_for_built_in_types = false:suggestion
csharp_using_directive_placement = outside_namespace:silent
dotnet_diagnostic.bc40000.severity = warning
Expand Down
2 changes: 1 addition & 1 deletion src/Consolonia.Core/ApplicationStartup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public static ClassicDesktopStyleApplicationLifetime BuildLifetime<TApp>(IConsol
private static ClassicDesktopStyleApplicationLifetime CreateLifetime<T>(T builder, string[] args)
where T : AppBuilderBase<T>, new()
{
var lifetime = new ClassicDesktopStyleApplicationLifetime
var lifetime = new ConsoloniaLifetime
{
Args = args,
ShutdownMode = ShutdownMode.OnMainWindowClose
Expand Down
28 changes: 14 additions & 14 deletions src/Consolonia.Core/Infrastructure/ConsoleWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,30 @@ namespace Consolonia.Core.Infrastructure
{
internal class ConsoleWindow : IWindowImpl
{
[NotNull] private readonly IConsole _console;
private readonly IKeyboardDevice _myKeyboardDevice;
[NotNull] internal readonly IConsole Console;
internal readonly List<Rect> InvalidatedRects = new(50);
private IInputRoot _inputRoot;

public ConsoleWindow()
{
_myKeyboardDevice = AvaloniaLocator.Current.GetService<IKeyboardDevice>();
MouseDevice = AvaloniaLocator.Current.GetService<IMouseDevice>();
_console = AvaloniaLocator.Current.GetService<IConsole>() ?? throw new NotImplementedException();
_console.Resized += OnConsoleOnResized;
_console.KeyEvent += ConsoleOnKeyEvent;
_console.MouseEvent += ConsoleOnMouseEvent;
_console.FocusEvent += ConsoleOnFocusEvent;
Console = AvaloniaLocator.Current.GetService<IConsole>() ?? throw new NotImplementedException();
Console.Resized += OnConsoleOnResized;
Console.KeyEvent += ConsoleOnKeyEvent;
Console.MouseEvent += ConsoleOnMouseEvent;
Console.FocusEvent += ConsoleOnFocusEvent;
}

public void Dispose()
{
Closed?.Invoke();
_console.Resized -= OnConsoleOnResized;
_console.KeyEvent -= ConsoleOnKeyEvent;
_console.MouseEvent -= ConsoleOnMouseEvent;
_console.FocusEvent -= ConsoleOnFocusEvent;
_console.Dispose();
Console.Resized -= OnConsoleOnResized;
Console.KeyEvent -= ConsoleOnKeyEvent;
Console.MouseEvent -= ConsoleOnMouseEvent;
Console.FocusEvent -= ConsoleOnFocusEvent;
Console.Dispose();
}

public IRenderer CreateRenderer(IRenderRoot root)
Expand Down Expand Up @@ -114,7 +114,7 @@ public Size ClientSize
{
get
{
PixelBufferSize pixelBufferSize = _console.Size;
PixelBufferSize pixelBufferSize = Console.Size;
return new Size(pixelBufferSize.Width, pixelBufferSize.Height);
}
}
Expand Down Expand Up @@ -181,7 +181,7 @@ public void SetTopmost(bool value)

public void SetTitle(string title)
{
_console.SetTitle(title);
Console.SetTitle(title);
}

public void SetParent(IWindowImpl parent)
Expand Down Expand Up @@ -316,7 +316,7 @@ private void OnConsoleOnResized()
{
Dispatcher.UIThread.Post(() =>
{
PixelBufferSize pixelBufferSize = _console.Size;
PixelBufferSize pixelBufferSize = Console.Size;
var size = new Size(pixelBufferSize.Width, pixelBufferSize.Height);
Resized(size, PlatformResizeReason.Unspecified);
//todo; Invalidate(new Rect(size));
Expand Down
35 changes: 35 additions & 0 deletions src/Consolonia.Core/Infrastructure/ConsoloniaLifetime.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System.Threading;
using System.Threading.Tasks;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Threading;

namespace Consolonia.Core.Infrastructure
{
public class ConsoloniaLifetime : ClassicDesktopStyleApplicationLifetime
{
/// <summary>
/// returned task indicates that console is successfully paused
/// </summary>
public Task DisconnectFromConsoleAsync(CancellationToken cancellationToken)
{
var taskToWaitFor = new TaskCompletionSource();
cancellationToken.Register(() => taskToWaitFor.SetResult());

var mainWindowPlatformImpl = (ConsoleWindow)MainWindow.PlatformImpl;
IConsole console = mainWindowPlatformImpl.Console;

Task pauseTask = taskToWaitFor.Task;

console.PauseIO(pauseTask);

pauseTask.ContinueWith(_ =>
{
mainWindowPlatformImpl.Console.ClearOutput();

Dispatcher.UIThread.Post(() => { MainWindow.InvalidateVisual(); });
}, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Default);

return Dispatcher.UIThread.InvokeAsync(() => { });
}
}
}
23 changes: 22 additions & 1 deletion src/Consolonia.Core/Infrastructure/DefaultNetConsole.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Avalonia.Input;
using Consolonia.Core.InternalHelpers;

Expand Down Expand Up @@ -49,13 +51,32 @@ protected override void Dispose(bool disposing)
RaiseFocusEvent(false);
}

public override void PauseIO(Task task)
{
base.PauseIO(task);

TextReader defaultIn = Console.In;
Console.SetIn(new StringReader(string.Empty));
Console.SetIn(defaultIn);
}

private void StartInputReading()
{
ThreadPool.QueueUserWorkItem(_ =>
{
while (!Disposed)
{
ConsoleKeyInfo consoleKeyInfo = Console.ReadKey(true);
PauseTask?.Wait();

ConsoleKeyInfo consoleKeyInfo;
try
{
consoleKeyInfo = Console.ReadKey(true);
}
catch (InvalidOperationException)
{
continue;
}

Key key = ConvertToKey(consoleKeyInfo.Key);

Expand Down
3 changes: 3 additions & 0 deletions src/Consolonia.Core/Infrastructure/IConsole.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
using Avalonia;
using Avalonia.Input;
using Avalonia.Input.Raw;
Expand Down Expand Up @@ -27,5 +28,7 @@ void Print(PixelBufferCoordinate bufferPoint, ConsoleColor backgroundColor, Cons
event Action<RawPointerEventType, Point, Vector?, RawInputModifiers> MouseEvent;

event Action<bool> FocusEvent;
void PauseIO(Task task);
void ClearOutput();
}
}
27 changes: 23 additions & 4 deletions src/Consolonia.Core/Infrastructure/InputLessDefaultNetConsole.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ public class InputLessDefaultNetConsole : IConsole
protected InputLessDefaultNetConsole()
{
Console.CursorVisible = false;
ActualizeTheSize();
ActualizeSize();
}

protected bool Disposed { get; private set; }

protected Task PauseTask { get; private set; }

public bool CaretVisible
{
get => _caretVisible;
Expand Down Expand Up @@ -67,6 +69,7 @@ public PixelBufferCoordinate GetCaretPosition()
public void Print(PixelBufferCoordinate bufferPoint, ConsoleColor backgroundColor, ConsoleColor foregroundColor,
string str)
{
PauseTask?.Wait();
SetCaretPosition(bufferPoint);

if (_headBackground != backgroundColor)
Expand Down Expand Up @@ -103,23 +106,35 @@ public void Print(PixelBufferCoordinate bufferPoint, ConsoleColor backgroundColo
public event Action<RawPointerEventType, Point, Vector?, RawInputModifiers> MouseEvent;
public event Action<bool> FocusEvent;

public virtual void PauseIO(Task task)
{
task.ContinueWith(_ => { PauseTask = null; }, TaskScheduler.Default);
PauseTask = task;
}

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

public void ClearOutput()
{
// this is hack, but somehow it does not work when just calling ActualizeSize with same size
Size = new PixelBufferSize(1, 1);
Resized?.Invoke();
}

// ReSharper disable once MemberCanBePrivate.Global
protected bool CheckActualizeTheSize()
{
if (Size.Width == Console.WindowWidth && Size.Height == Console.WindowHeight) return false;
ActualizeTheSize();
ActualizeSize();
return true;
}

protected void ActualizeTheSize()
protected void ActualizeSize()
{
Console.Clear();
Size = new PixelBufferSize((ushort)Console.WindowWidth, (ushort)Console.WindowHeight);
Resized?.Invoke();
}
Expand Down Expand Up @@ -151,6 +166,10 @@ protected void StartSizeCheckTimerAsync(uint slowInterval = 1500)
{
while (!Disposed)
{
Task pauseTask = PauseTask;
if (pauseTask != null)
await pauseTask.ConfigureAwait(false);

int timeout = (int)(CheckActualizeTheSize() ? 1 : slowInterval);
await Task.Delay(timeout).ConfigureAwait(false);
}
Expand Down
Loading
Loading