aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx/Ui
diff options
context:
space:
mode:
authormageven <62494521+mageven@users.noreply.github.com>2020-08-03 07:00:58 +0530
committerGitHub <noreply@github.com>2020-08-03 03:30:58 +0200
commitc11855565e0ce2bac228610cbaa92c8c7f082c70 (patch)
tree76f4ee1c3c4c15997d27c9cf8d963bac4405c915 /Ryujinx/Ui
parentf0c91d9efb7eff0b8bbe8fc8d4901af5a9d59005 (diff)
Implement Software Keyboard GTK frontend (#1434)
* Implement SwKbd GUI * Relocate UI handler to Emu Context from Config Also create a common interface for UI handlers in the context and specialize for Gtk Add basic input length validation in InputDialog * Add Transfer Memory support to AppletCreator Read Initial Text for SwKbd using Transfer Memory * Improve InputDialog widget Improve length validation Has extra label to show validition info Handle potential errors and log them * Misc improvements * Improve string validation * Improve error handling * Remove tuple in struct * Address formatting nits * Add proper Cancel functionality Also handle GUI errors in UI handler * Address jD's comments * Fix _uiHandler init * Address AcK's comments
Diffstat (limited to 'Ryujinx/Ui')
-rw-r--r--Ryujinx/Ui/GtkHostUiHandler.cs69
-rw-r--r--Ryujinx/Ui/InputDialog.cs69
-rw-r--r--Ryujinx/Ui/MainWindow.cs9
3 files changed, 146 insertions, 1 deletions
diff --git a/Ryujinx/Ui/GtkHostUiHandler.cs b/Ryujinx/Ui/GtkHostUiHandler.cs
new file mode 100644
index 00000000..7b7b3647
--- /dev/null
+++ b/Ryujinx/Ui/GtkHostUiHandler.cs
@@ -0,0 +1,69 @@
+using Gtk;
+using Ryujinx.Common.Logging;
+using Ryujinx.HLE;
+using Ryujinx.HLE.HOS.Applets;
+using System;
+using System.Threading;
+
+namespace Ryujinx.Ui
+{
+ internal class GtkHostUiHandler : IHostUiHandler
+ {
+ private readonly Window _parent;
+
+ public GtkHostUiHandler(Window parent)
+ {
+ _parent = parent;
+ }
+
+ public bool DisplayInputDialog(SoftwareKeyboardUiArgs args, out string userText)
+ {
+ ManualResetEvent dialogCloseEvent = new ManualResetEvent(false);
+ bool okPressed = false;
+ bool error = false;
+ string inputText = args.InitialText ?? "";
+
+ Application.Invoke(delegate
+ {
+ try
+ {
+ var swkbdDialog = new InputDialog(_parent)
+ {
+ Title = "Software Keyboard",
+ Text = args.HeaderText,
+ SecondaryText = args.SubtitleText
+ };
+
+ swkbdDialog.InputEntry.Text = inputText;
+ swkbdDialog.InputEntry.PlaceholderText = args.GuideText;
+ swkbdDialog.OkButton.Label = args.SubmitText;
+
+ swkbdDialog.SetInputLengthValidation(args.StringLengthMin, args.StringLengthMax);
+
+ if (swkbdDialog.Run() == (int)ResponseType.Ok)
+ {
+ inputText = swkbdDialog.InputEntry.Text;
+ okPressed = true;
+ }
+
+ swkbdDialog.Dispose();
+ }
+ catch (Exception e)
+ {
+ error = true;
+ Logger.PrintError(LogClass.Application, $"Error displaying Software Keyboard: {e}");
+ }
+ finally
+ {
+ dialogCloseEvent.Set();
+ }
+ });
+
+ dialogCloseEvent.WaitOne();
+
+ userText = error ? null : inputText;
+
+ return error || okPressed;
+ }
+ }
+}
diff --git a/Ryujinx/Ui/InputDialog.cs b/Ryujinx/Ui/InputDialog.cs
new file mode 100644
index 00000000..a8dc80bf
--- /dev/null
+++ b/Ryujinx/Ui/InputDialog.cs
@@ -0,0 +1,69 @@
+using Gtk;
+using System;
+
+namespace Ryujinx.Ui
+{
+ public class InputDialog : MessageDialog
+ {
+ private int _inputMin, _inputMax;
+ private Predicate<int> _checkLength;
+ private Label _validationInfo;
+
+ public Entry InputEntry { get; }
+ public Button OkButton { get; }
+ public Button CancelButton { get; }
+
+ public InputDialog(Window parent)
+ : base(parent, DialogFlags.Modal | DialogFlags.DestroyWithParent, MessageType.Question, ButtonsType.None, null)
+ {
+ SetDefaultSize(300, 0);
+
+ _validationInfo = new Label() { Visible = false };
+
+ InputEntry = new Entry() { Visible = true };
+ InputEntry.Activated += (object sender, EventArgs e) => { if (OkButton.IsSensitive) Respond(ResponseType.Ok); };
+ InputEntry.Changed += OnInputChanged;
+
+ OkButton = (Button)AddButton("OK", ResponseType.Ok);
+ CancelButton = (Button)AddButton("Cancel", ResponseType.Cancel);
+
+ ((Box)MessageArea).PackEnd(_validationInfo, true, true, 0);
+ ((Box)MessageArea).PackEnd(InputEntry, true, true, 4);
+
+ SetInputLengthValidation(0, int.MaxValue); // disable by default
+ }
+
+ public void SetInputLengthValidation(int min, int max)
+ {
+ _inputMin = Math.Min(min, max);
+ _inputMax = Math.Max(min, max);
+
+ _validationInfo.Visible = false;
+
+ if (_inputMin <= 0 && _inputMax == int.MaxValue) // disable
+ {
+ _validationInfo.Visible = false;
+ _checkLength = (length) => true;
+ }
+ else if (_inputMin > 0 && _inputMax == int.MaxValue)
+ {
+ _validationInfo.Visible = true;
+ _validationInfo.Markup = $"<i>Must be at least {_inputMin} characters long</i>";
+ _checkLength = (length) => _inputMin <= length;
+ }
+ else
+ {
+ _validationInfo.Visible = true;
+ _validationInfo.Markup = $"<i>Must be {_inputMin}-{_inputMax} characters long</i>";
+ _checkLength = (length) => _inputMin <= length && length <= _inputMax;
+ }
+
+ OnInputChanged(this, EventArgs.Empty);
+ }
+
+ private void OnInputChanged(object sender, EventArgs e)
+ {
+ OkButton.Sensitive = _checkLength(InputEntry.Text.Length);
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx/Ui/MainWindow.cs b/Ryujinx/Ui/MainWindow.cs
index 42870107..2e288ac9 100644
--- a/Ryujinx/Ui/MainWindow.cs
+++ b/Ryujinx/Ui/MainWindow.cs
@@ -5,6 +5,7 @@ using LibHac.Ns;
using Ryujinx.Audio;
using Ryujinx.Common.Logging;
using Ryujinx.Configuration;
+using Ryujinx.Configuration.System;
using Ryujinx.Debugger.Profiler;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.OpenGL;
@@ -31,6 +32,7 @@ namespace Ryujinx.Ui
private static HLE.Switch _emulationContext;
private static GlRenderer _glWidget;
+ private static GtkHostUiHandler _uiHandler;
private static AutoResetEvent _deviceExitStatus = new AutoResetEvent(false);
@@ -191,6 +193,8 @@ namespace Ryujinx.Ui
Task.Run(RefreshFirmwareLabel);
_statusBar.Hide();
+
+ _uiHandler = new GtkHostUiHandler(this);
}
private void MainWindow_WindowStateEvent(object o, WindowStateEventArgs args)
@@ -318,7 +322,10 @@ namespace Ryujinx.Ui
{
_virtualFileSystem.Reload();
- HLE.Switch instance = new HLE.Switch(_virtualFileSystem, _contentManager, InitializeRenderer(), InitializeAudioEngine());
+ HLE.Switch instance = new HLE.Switch(_virtualFileSystem, _contentManager, InitializeRenderer(), InitializeAudioEngine())
+ {
+ UiHandler = _uiHandler
+ };
instance.Initialize();