/ src / Ryujinx.Gtk3 / UI / Applet / GtkHostUIHandler.cs
GtkHostUIHandler.cs
  1  using Gtk;
  2  using Ryujinx.HLE.HOS.Applets;
  3  using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types;
  4  using Ryujinx.HLE.UI;
  5  using Ryujinx.UI.Widgets;
  6  using System;
  7  using System.Threading;
  8  
  9  namespace Ryujinx.UI.Applet
 10  {
 11      internal class GtkHostUIHandler : IHostUIHandler
 12      {
 13          private readonly Window _parent;
 14  
 15          public IHostUITheme HostUITheme { get; }
 16  
 17          public GtkHostUIHandler(Window parent)
 18          {
 19              _parent = parent;
 20  
 21              HostUITheme = new GtkHostUITheme(parent);
 22          }
 23  
 24          public bool DisplayMessageDialog(ControllerAppletUIArgs args)
 25          {
 26              string playerCount = args.PlayerCountMin == args.PlayerCountMax ? $"exactly {args.PlayerCountMin}" : $"{args.PlayerCountMin}-{args.PlayerCountMax}";
 27  
 28              string message = $"Application requests <b>{playerCount}</b> player(s) with:\n\n"
 29                             + $"<tt><b>TYPES:</b> {args.SupportedStyles}</tt>\n\n"
 30                             + $"<tt><b>PLAYERS:</b> {string.Join(", ", args.SupportedPlayers)}</tt>\n\n"
 31                             + (args.IsDocked ? "Docked mode set. <tt>Handheld</tt> is also invalid.\n\n" : "")
 32                             + "<i>Please reconfigure Input now and then press OK.</i>";
 33  
 34              return DisplayMessageDialog("Controller Applet", message);
 35          }
 36  
 37          public bool DisplayMessageDialog(string title, string message)
 38          {
 39              ManualResetEvent dialogCloseEvent = new(false);
 40  
 41              bool okPressed = false;
 42  
 43              Application.Invoke(delegate
 44              {
 45                  MessageDialog msgDialog = null;
 46  
 47                  try
 48                  {
 49                      msgDialog = new MessageDialog(_parent, DialogFlags.DestroyWithParent, MessageType.Info, ButtonsType.Ok, null)
 50                      {
 51                          Title = title,
 52                          Text = message,
 53                          UseMarkup = true,
 54                      };
 55  
 56                      msgDialog.SetDefaultSize(400, 0);
 57  
 58                      msgDialog.Response += (object o, ResponseArgs args) =>
 59                      {
 60                          if (args.ResponseId == ResponseType.Ok)
 61                          {
 62                              okPressed = true;
 63                          }
 64  
 65                          dialogCloseEvent.Set();
 66                          msgDialog?.Dispose();
 67                      };
 68  
 69                      msgDialog.Show();
 70                  }
 71                  catch (Exception ex)
 72                  {
 73                      GtkDialog.CreateErrorDialog($"Error displaying Message Dialog: {ex}");
 74  
 75                      dialogCloseEvent.Set();
 76                  }
 77              });
 78  
 79              dialogCloseEvent.WaitOne();
 80  
 81              return okPressed;
 82          }
 83  
 84          public bool DisplayInputDialog(SoftwareKeyboardUIArgs args, out string userText)
 85          {
 86              ManualResetEvent dialogCloseEvent = new(false);
 87  
 88              bool okPressed = false;
 89              bool error = false;
 90              string inputText = args.InitialText ?? "";
 91  
 92              Application.Invoke(delegate
 93              {
 94                  try
 95                  {
 96                      var swkbdDialog = new SwkbdAppletDialog(_parent)
 97                      {
 98                          Title = "Software Keyboard",
 99                          Text = args.HeaderText,
100                          SecondaryText = args.SubtitleText,
101                      };
102  
103                      swkbdDialog.InputEntry.Text = inputText;
104                      swkbdDialog.InputEntry.PlaceholderText = args.GuideText;
105                      swkbdDialog.OkButton.Label = args.SubmitText;
106  
107                      swkbdDialog.SetInputLengthValidation(args.StringLengthMin, args.StringLengthMax);
108                      swkbdDialog.SetInputValidation(args.KeyboardMode);
109  
110                      ((MainWindow)_parent).RendererWidget.NpadManager.BlockInputUpdates();
111  
112                      if (swkbdDialog.Run() == (int)ResponseType.Ok)
113                      {
114                          inputText = swkbdDialog.InputEntry.Text;
115                          okPressed = true;
116                      }
117  
118                      swkbdDialog.Dispose();
119                  }
120                  catch (Exception ex)
121                  {
122                      error = true;
123  
124                      GtkDialog.CreateErrorDialog($"Error displaying Software Keyboard: {ex}");
125                  }
126                  finally
127                  {
128                      dialogCloseEvent.Set();
129                  }
130              });
131  
132              dialogCloseEvent.WaitOne();
133              ((MainWindow)_parent).RendererWidget.NpadManager.UnblockInputUpdates();
134  
135              userText = error ? null : inputText;
136  
137              return error || okPressed;
138          }
139  
140          public void ExecuteProgram(HLE.Switch device, ProgramSpecifyKind kind, ulong value)
141          {
142              device.Configuration.UserChannelPersistence.ExecuteProgram(kind, value);
143              ((MainWindow)_parent).RendererWidget?.Exit();
144          }
145  
146          public bool DisplayErrorAppletDialog(string title, string message, string[] buttons)
147          {
148              ManualResetEvent dialogCloseEvent = new(false);
149  
150              bool showDetails = false;
151  
152              Application.Invoke(delegate
153              {
154                  try
155                  {
156                      ErrorAppletDialog msgDialog = new(_parent, DialogFlags.DestroyWithParent, MessageType.Error, buttons)
157                      {
158                          Title = title,
159                          Text = message,
160                          UseMarkup = true,
161                          WindowPosition = WindowPosition.CenterAlways,
162                      };
163  
164                      msgDialog.SetDefaultSize(400, 0);
165  
166                      msgDialog.Response += (object o, ResponseArgs args) =>
167                      {
168                          if (buttons != null)
169                          {
170                              if (buttons.Length > 1)
171                              {
172                                  if (args.ResponseId != (ResponseType)(buttons.Length - 1))
173                                  {
174                                      showDetails = true;
175                                  }
176                              }
177                          }
178  
179                          dialogCloseEvent.Set();
180                          msgDialog?.Dispose();
181                      };
182  
183                      msgDialog.Show();
184                  }
185                  catch (Exception ex)
186                  {
187                      GtkDialog.CreateErrorDialog($"Error displaying ErrorApplet Dialog: {ex}");
188  
189                      dialogCloseEvent.Set();
190                  }
191              });
192  
193              dialogCloseEvent.WaitOne();
194  
195              return showDetails;
196          }
197  
198          public IDynamicTextInputHandler CreateDynamicTextInputHandler()
199          {
200              return new GtkDynamicTextInputHandler(_parent);
201          }
202      }
203  }