diff --git a/src/Consolonia.Core/Dummy/DummyConsole.cs b/src/Consolonia.Core/Dummy/DummyConsole.cs index b5ad80d3..f3fc6efc 100644 --- a/src/Consolonia.Core/Dummy/DummyConsole.cs +++ b/src/Consolonia.Core/Dummy/DummyConsole.cs @@ -33,6 +33,7 @@ public bool CaretVisible } public bool SupportsComplexEmoji => true; + public bool SupportsAltSolo => false; public void ClearOutput() { diff --git a/src/Consolonia.Core/Helpers/Extensions.cs b/src/Consolonia.Core/Helpers/Extensions.cs index 02cf618c..6a9b34e9 100644 --- a/src/Consolonia.Core/Helpers/Extensions.cs +++ b/src/Consolonia.Core/Helpers/Extensions.cs @@ -16,11 +16,11 @@ namespace Consolonia.Core.Helpers { public static class Extensions { - public static void SubscribeAction( + public static IDisposable SubscribeAction( this IObservable> observable, Action> action) { - observable.Subscribe(new AnonymousObserver>(action)); + return observable.Subscribe(new AnonymousObserver>(action)); } public static void AddConsoloniaDesignMode(this Application application) diff --git a/src/Consolonia.Core/Infrastructure/ConsoleWindow.cs b/src/Consolonia.Core/Infrastructure/ConsoleWindow.cs index 3dc48c69..e31f5f76 100644 --- a/src/Consolonia.Core/Infrastructure/ConsoleWindow.cs +++ b/src/Consolonia.Core/Infrastructure/ConsoleWindow.cs @@ -7,6 +7,7 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Controls.Platform; +using Avalonia.Controls.Primitives; using Avalonia.Input; using Avalonia.Input.Platform; using Avalonia.Input.Raw; @@ -15,12 +16,15 @@ using Avalonia.Rendering.Composition; using Avalonia.Threading; using Consolonia.Core.Drawing.PixelBufferImplementation; +using Consolonia.Core.Helpers; using Consolonia.Core.Text; namespace Consolonia.Core.Infrastructure { public class ConsoleWindow : IWindowImpl { + private readonly bool _accessKeysAlwaysOn; + private readonly IDisposable _accessKeysAlwaysOnDisposable; private readonly IKeyboardDevice _myKeyboardDevice; private readonly TimeSpan _resizeDelay = TimeSpan.FromMilliseconds(100); [NotNull] internal readonly IConsole Console; @@ -39,6 +43,10 @@ public ConsoleWindow() Console.FocusEvent += ConsoleOnFocusEvent; Handle = null!; PixelBuffer = new PixelBuffer(Console.Size); + _accessKeysAlwaysOn = !Console.SupportsAltSolo; + if (_accessKeysAlwaysOn) + _accessKeysAlwaysOnDisposable = + AccessText.ShowAccessKeyProperty.Changed.SubscribeAction(OnShowAccessKeyPropertyChanged); } public PixelBuffer PixelBuffer { get; private set; } @@ -49,6 +57,8 @@ public ConsoleWindow() public void SetInputRoot(IInputRoot inputRoot) { _inputRoot = inputRoot; + if (_accessKeysAlwaysOn) + _inputRoot.ShowAccessKeys = true; } public Point PointToClient(PixelPoint point) @@ -296,6 +306,14 @@ public void Dispose() GC.SuppressFinalize(this); } + private void OnShowAccessKeyPropertyChanged(AvaloniaPropertyChangedEventArgs args) + { + if (args.Sender != _inputRoot) return; + if (args.GetNewValue()) return; + + _inputRoot.ShowAccessKeys = true; + } + private void ConsoleOnMouseEvent(RawPointerEventType type, Point point, Vector? wheelDelta, RawInputModifiers modifiers) { @@ -429,6 +447,7 @@ protected virtual void Dispose(bool disposing) { // TODO: dispose managed state (managed objects) Closed?.Invoke(); + _accessKeysAlwaysOnDisposable?.Dispose(); Console.Resized -= OnConsoleOnResized; Console.KeyEvent -= ConsoleOnKeyEvent; Console.MouseEvent -= ConsoleOnMouseEvent; diff --git a/src/Consolonia.Core/Infrastructure/DefaultNetConsole.cs b/src/Consolonia.Core/Infrastructure/DefaultNetConsole.cs index 2354baa3..3437cd57 100644 --- a/src/Consolonia.Core/Infrastructure/DefaultNetConsole.cs +++ b/src/Consolonia.Core/Infrastructure/DefaultNetConsole.cs @@ -47,6 +47,8 @@ public DefaultNetConsole() StartInputReading(); } + public override bool SupportsAltSolo => false; + protected override void Dispose(bool disposing) { base.Dispose(disposing); diff --git a/src/Consolonia.Core/Infrastructure/IConsole.cs b/src/Consolonia.Core/Infrastructure/IConsole.cs index fb49195a..d4975340 100644 --- a/src/Consolonia.Core/Infrastructure/IConsole.cs +++ b/src/Consolonia.Core/Infrastructure/IConsole.cs @@ -21,6 +21,8 @@ public interface IConsole : IDisposable /// bool SupportsComplexEmoji { get; } + bool SupportsAltSolo { get; } + void SetTitle(string title); void SetCaretPosition(PixelBufferCoordinate bufferPoint); diff --git a/src/Consolonia.Core/Infrastructure/InputLessDefaultNetConsole.cs b/src/Consolonia.Core/Infrastructure/InputLessDefaultNetConsole.cs index b2b42f91..fb59bfab 100644 --- a/src/Consolonia.Core/Infrastructure/InputLessDefaultNetConsole.cs +++ b/src/Consolonia.Core/Infrastructure/InputLessDefaultNetConsole.cs @@ -11,7 +11,7 @@ namespace Consolonia.Core.Infrastructure { - public class InputLessDefaultNetConsole : IConsole + public abstract class InputLessDefaultNetConsole : IConsole { private const string TestEmoji = "๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ"; private bool _caretVisible; @@ -48,6 +48,7 @@ public bool CaretVisible public PixelBufferSize Size { get; private set; } public bool SupportsComplexEmoji => _supportEmoji ?? false; + public abstract bool SupportsAltSolo { get; } public void SetTitle(string title) { diff --git a/src/Consolonia.NUnit/UnitTestConsole.cs b/src/Consolonia.NUnit/UnitTestConsole.cs index c42cd357..66017930 100644 --- a/src/Consolonia.NUnit/UnitTestConsole.cs +++ b/src/Consolonia.NUnit/UnitTestConsole.cs @@ -39,6 +39,7 @@ public void Dispose() bool IConsole.CaretVisible { get; set; } public bool SupportsComplexEmoji => true; + public bool SupportsAltSolo => true; public void SetTitle(string title) { diff --git a/src/Consolonia.PlatformSupport/CursesConsole.cs b/src/Consolonia.PlatformSupport/CursesConsole.cs index e5281f74..809fed4b 100644 --- a/src/Consolonia.PlatformSupport/CursesConsole.cs +++ b/src/Consolonia.PlatformSupport/CursesConsole.cs @@ -115,6 +115,8 @@ public CursesConsole() StartEventLoop(); } + public override bool SupportsAltSolo => false; + private void StartEventLoop() { //todo: cleanup diff --git a/src/Consolonia.PlatformSupport/WindowsConsole.cs b/src/Consolonia.PlatformSupport/WindowsConsole.cs index ee5bcbcc..596e37db 100644 --- a/src/Consolonia.PlatformSupport/WindowsConsole.cs +++ b/src/Consolonia.PlatformSupport/WindowsConsole.cs @@ -61,6 +61,8 @@ public Win32Console() StartEventLoop(); } + public override bool SupportsAltSolo => true; + public override void PauseIO(Task task) { base.PauseIO(task);