GtkDynamicTextInputHandler.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. using Gtk;
  2. using Ryujinx.HLE.Ui;
  3. using Ryujinx.Input.GTK3;
  4. using Ryujinx.Ui.Widgets;
  5. using System.Threading;
  6. namespace Ryujinx.Ui.Applet
  7. {
  8. /// <summary>
  9. /// Class that forwards key events to a GTK Entry so they can be processed into text.
  10. /// </summary>
  11. internal class GtkDynamicTextInputHandler : IDynamicTextInputHandler
  12. {
  13. private readonly Window _parent;
  14. private readonly OffscreenWindow _inputToTextWindow = new OffscreenWindow();
  15. private readonly RawInputToTextEntry _inputToTextEntry = new RawInputToTextEntry();
  16. private bool _canProcessInput;
  17. public event DynamicTextChangedHandler TextChangedEvent;
  18. public event KeyPressedHandler KeyPressedEvent;
  19. public event KeyReleasedHandler KeyReleasedEvent;
  20. public bool TextProcessingEnabled
  21. {
  22. get
  23. {
  24. return Volatile.Read(ref _canProcessInput);
  25. }
  26. set
  27. {
  28. Volatile.Write(ref _canProcessInput, value);
  29. }
  30. }
  31. public GtkDynamicTextInputHandler(Window parent)
  32. {
  33. _parent = parent;
  34. _parent.KeyPressEvent += HandleKeyPressEvent;
  35. _parent.KeyReleaseEvent += HandleKeyReleaseEvent;
  36. _inputToTextWindow.Add(_inputToTextEntry);
  37. _inputToTextEntry.TruncateMultiline = true;
  38. // Start with input processing turned off so the text box won't accumulate text
  39. // if the user is playing on the keyboard.
  40. _canProcessInput = false;
  41. }
  42. [GLib.ConnectBefore()]
  43. private void HandleKeyPressEvent(object o, KeyPressEventArgs args)
  44. {
  45. var key = (Common.Configuration.Hid.Key)GTK3MappingHelper.ToInputKey(args.Event.Key);
  46. if (!(KeyPressedEvent?.Invoke(key)).GetValueOrDefault(true))
  47. {
  48. return;
  49. }
  50. if (_canProcessInput)
  51. {
  52. _inputToTextEntry.SendKeyPressEvent(o, args);
  53. _inputToTextEntry.GetSelectionBounds(out int selectionStart, out int selectionEnd);
  54. TextChangedEvent?.Invoke(_inputToTextEntry.Text, selectionStart, selectionEnd, _inputToTextEntry.OverwriteMode);
  55. }
  56. }
  57. [GLib.ConnectBefore()]
  58. private void HandleKeyReleaseEvent(object o, KeyReleaseEventArgs args)
  59. {
  60. var key = (Common.Configuration.Hid.Key)GTK3MappingHelper.ToInputKey(args.Event.Key);
  61. if (!(KeyReleasedEvent?.Invoke(key)).GetValueOrDefault(true))
  62. {
  63. return;
  64. }
  65. if (_canProcessInput)
  66. {
  67. // TODO (caian): This solution may have problems if the pause is sent after a key press
  68. // and before a key release. But for now GTK Entry does not seem to use release events.
  69. _inputToTextEntry.SendKeyReleaseEvent(o, args);
  70. _inputToTextEntry.GetSelectionBounds(out int selectionStart, out int selectionEnd);
  71. TextChangedEvent?.Invoke(_inputToTextEntry.Text, selectionStart, selectionEnd, _inputToTextEntry.OverwriteMode);
  72. }
  73. }
  74. public void SetText(string text, int cursorBegin)
  75. {
  76. _inputToTextEntry.Text = text;
  77. _inputToTextEntry.Position = cursorBegin;
  78. }
  79. public void SetText(string text, int cursorBegin, int cursorEnd)
  80. {
  81. _inputToTextEntry.Text = text;
  82. _inputToTextEntry.SelectRegion(cursorBegin, cursorEnd);
  83. }
  84. public void Dispose()
  85. {
  86. _parent.KeyPressEvent -= HandleKeyPressEvent;
  87. _parent.KeyReleaseEvent -= HandleKeyReleaseEvent;
  88. }
  89. }
  90. }