From 380b95bc59e7dc419f89df951cdc086e792cb0ff Mon Sep 17 00:00:00 2001 From: Caian Benedicto Date: Tue, 12 Oct 2021 16:54:21 -0300 Subject: Inline software keyboard without input pop up dialog (#2180) * Initial implementation * Refactor dynamic text input keys out to facilitate configuration via UI * Fix code styling * Add per applet indirect layer handles * Remove static functions from SoftwareKeyboardRenderer * Remove inline keyboard reset delay * Remove inline keyboard V2 responses * Add inline keyboard soft-lock recovering * Add comments * Forward accept and cancel key names to the keyboard and add soft-lock prevention line * Add dummy window to handle paste events * Rework inline keyboard state machine and graphics * Implement IHostUiHandler interfaces on headless WindowBase class * Add inline keyboard assets * Fix coding style * Fix coding style * Change mode cycling shortcut to F6 * Fix invalid calc size error in games using extended calc * Remove unnecessary namespaces --- .../HeadlessDynamicTextInputHandler.cs | 51 ++++++++++++++++++++++ Ryujinx.Headless.SDL2/HeadlessHostUiTheme.cs | 17 ++++++++ Ryujinx.Headless.SDL2/WindowBase.cs | 12 ++++- 3 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 Ryujinx.Headless.SDL2/HeadlessDynamicTextInputHandler.cs create mode 100644 Ryujinx.Headless.SDL2/HeadlessHostUiTheme.cs (limited to 'Ryujinx.Headless.SDL2') diff --git a/Ryujinx.Headless.SDL2/HeadlessDynamicTextInputHandler.cs b/Ryujinx.Headless.SDL2/HeadlessDynamicTextInputHandler.cs new file mode 100644 index 00000000..7e624152 --- /dev/null +++ b/Ryujinx.Headless.SDL2/HeadlessDynamicTextInputHandler.cs @@ -0,0 +1,51 @@ +using Ryujinx.HLE.Ui; +using System.Threading; +using System.Threading.Tasks; + +namespace Ryujinx.Headless.SDL2 +{ + /// + /// Headless text processing class, right now there is no way to forward the input to it. + /// + internal class HeadlessDynamicTextInputHandler : IDynamicTextInputHandler + { + private bool _canProcessInput; + + public event DynamicTextChangedHandler TextChangedEvent; + public event KeyPressedHandler KeyPressedEvent { add { } remove { } } + public event KeyReleasedHandler KeyReleasedEvent { add { } remove { } } + + public bool TextProcessingEnabled + { + get + { + return Volatile.Read(ref _canProcessInput); + } + + set + { + Volatile.Write(ref _canProcessInput, value); + + // Launch a task to update the text. + Task.Run(() => + { + Thread.Sleep(100); + TextChangedEvent?.Invoke("Ryujinx", 7, 7, false); + }); + } + } + + public HeadlessDynamicTextInputHandler() + { + // Start with input processing turned off so the text box won't accumulate text + // if the user is playing on the keyboard. + _canProcessInput = false; + } + + public void SetText(string text, int cursorBegin) { } + + public void SetText(string text, int cursorBegin, int cursorEnd) { } + + public void Dispose() { } + } +} \ No newline at end of file diff --git a/Ryujinx.Headless.SDL2/HeadlessHostUiTheme.cs b/Ryujinx.Headless.SDL2/HeadlessHostUiTheme.cs new file mode 100644 index 00000000..4ef00b3c --- /dev/null +++ b/Ryujinx.Headless.SDL2/HeadlessHostUiTheme.cs @@ -0,0 +1,17 @@ +using Ryujinx.HLE.Ui; + +namespace Ryujinx.Headless.SDL2 +{ + internal class HeadlessHostUiTheme : IHostUiTheme + { + public string FontFamily => "sans-serif"; + + public ThemeColor DefaultBackgroundColor => new ThemeColor(1, 0, 0, 0); + public ThemeColor DefaultForegroundColor => new ThemeColor(1, 1, 1, 1); + public ThemeColor DefaultBorderColor => new ThemeColor(1, 1, 1, 1); + public ThemeColor SelectionBackgroundColor => new ThemeColor(1, 1, 1, 1); + public ThemeColor SelectionForegroundColor => new ThemeColor(1, 0, 0, 0); + + public HeadlessHostUiTheme() { } + } +} \ No newline at end of file diff --git a/Ryujinx.Headless.SDL2/WindowBase.cs b/Ryujinx.Headless.SDL2/WindowBase.cs index 858b0801..3fbd9bc3 100644 --- a/Ryujinx.Headless.SDL2/WindowBase.cs +++ b/Ryujinx.Headless.SDL2/WindowBase.cs @@ -4,10 +4,9 @@ using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Logging; using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL.Multithreading; -using Ryujinx.HLE; using Ryujinx.HLE.HOS.Applets; using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types; -using Ryujinx.HLE.HOS.Services.Hid; +using Ryujinx.HLE.Ui; using Ryujinx.Input; using Ryujinx.Input.HLE; using Ryujinx.SDL2.Common; @@ -35,6 +34,9 @@ namespace Ryujinx.Headless.SDL2 public event EventHandler StatusUpdatedEvent; protected IntPtr WindowHandle { get; set; } + + public IHostUiTheme HostUiTheme { get; } + protected SDL2MouseDriver MouseDriver; private InputManager _inputManager; private IKeyboard _keyboardInterface; @@ -67,6 +69,7 @@ namespace Ryujinx.Headless.SDL2 _exitEvent = new ManualResetEvent(false); _aspectRatio = aspectRatio; _enableMouse = enableMouse; + HostUiTheme = new HeadlessHostUiTheme(); SDL2Driver.Instance.Initialize(); } @@ -353,6 +356,11 @@ namespace Ryujinx.Headless.SDL2 return DisplayMessageDialog("Controller Applet", message); } + public IDynamicTextInputHandler CreateDynamicTextInputHandler() + { + return new HeadlessDynamicTextInputHandler(); + } + public void ExecuteProgram(Switch device, ProgramSpecifyKind kind, ulong value) { device.Configuration.UserChannelPersistence.ExecuteProgram(kind, value); -- cgit v1.2.3