AvaloniaDynamicTextInputHandler.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. using Avalonia;
  2. using Avalonia.Controls;
  3. using Avalonia.Input;
  4. using Avalonia.Threading;
  5. using Ryujinx.Ava.Input;
  6. using Ryujinx.Ava.Ui.Controls;
  7. using Ryujinx.Ava.Ui.Windows;
  8. using Ryujinx.HLE.Ui;
  9. using System;
  10. using System.Threading;
  11. using HidKey = Ryujinx.Common.Configuration.Hid.Key;
  12. namespace Ryujinx.Ava.Ui.Applet
  13. {
  14. class AvaloniaDynamicTextInputHandler : IDynamicTextInputHandler
  15. {
  16. private MainWindow _parent;
  17. private OffscreenTextBox _hiddenTextBox;
  18. private bool _canProcessInput;
  19. private IDisposable _textChangedSubscription;
  20. private IDisposable _selectionStartChangedSubscription;
  21. private IDisposable _selectionEndtextChangedSubscription;
  22. public AvaloniaDynamicTextInputHandler(MainWindow parent)
  23. {
  24. _parent = parent;
  25. (_parent.InputManager.KeyboardDriver as AvaloniaKeyboardDriver).KeyPressed += AvaloniaDynamicTextInputHandler_KeyPressed;
  26. (_parent.InputManager.KeyboardDriver as AvaloniaKeyboardDriver).KeyRelease += AvaloniaDynamicTextInputHandler_KeyRelease;
  27. (_parent.InputManager.KeyboardDriver as AvaloniaKeyboardDriver).TextInput += AvaloniaDynamicTextInputHandler_TextInput;
  28. _hiddenTextBox = _parent.HiddenTextBox;
  29. Dispatcher.UIThread.Post(() =>
  30. {
  31. _textChangedSubscription = _hiddenTextBox.GetObservable(TextBox.TextProperty).Subscribe(TextChanged);
  32. _selectionStartChangedSubscription = _hiddenTextBox.GetObservable(TextBox.SelectionStartProperty).Subscribe(SelectionChanged);
  33. _selectionEndtextChangedSubscription = _hiddenTextBox.GetObservable(TextBox.SelectionEndProperty).Subscribe(SelectionChanged);
  34. });
  35. }
  36. private void TextChanged(string text)
  37. {
  38. TextChangedEvent?.Invoke(text ?? string.Empty, _hiddenTextBox.SelectionStart, _hiddenTextBox.SelectionEnd, true);
  39. }
  40. private void SelectionChanged(int selection)
  41. {
  42. if (_hiddenTextBox.SelectionEnd < _hiddenTextBox.SelectionStart)
  43. {
  44. _hiddenTextBox.SelectionStart = _hiddenTextBox.SelectionEnd;
  45. }
  46. TextChangedEvent?.Invoke(_hiddenTextBox.Text ?? string.Empty, _hiddenTextBox.SelectionStart, _hiddenTextBox.SelectionEnd, true);
  47. }
  48. private void AvaloniaDynamicTextInputHandler_TextInput(object sender, string text)
  49. {
  50. Dispatcher.UIThread.InvokeAsync(() =>
  51. {
  52. if (_canProcessInput)
  53. {
  54. _hiddenTextBox.SendText(text);
  55. }
  56. });
  57. }
  58. private void AvaloniaDynamicTextInputHandler_KeyRelease(object sender, Avalonia.Input.KeyEventArgs e)
  59. {
  60. var key = (HidKey)AvaloniaMappingHelper.ToInputKey(e.Key);
  61. if (!(KeyReleasedEvent?.Invoke(key)).GetValueOrDefault(true))
  62. {
  63. return;
  64. }
  65. e.RoutedEvent = _hiddenTextBox.GetKeyUpRoutedEvent();
  66. Dispatcher.UIThread.InvokeAsync(() =>
  67. {
  68. if (_canProcessInput)
  69. {
  70. _hiddenTextBox.SendKeyUpEvent(e);
  71. }
  72. });
  73. }
  74. private void AvaloniaDynamicTextInputHandler_KeyPressed(object sender, KeyEventArgs e)
  75. {
  76. var key = (HidKey)AvaloniaMappingHelper.ToInputKey(e.Key);
  77. if (!(KeyPressedEvent?.Invoke(key)).GetValueOrDefault(true))
  78. {
  79. return;
  80. }
  81. e.RoutedEvent = _hiddenTextBox.GetKeyUpRoutedEvent();
  82. Dispatcher.UIThread.InvokeAsync(() =>
  83. {
  84. if (_canProcessInput)
  85. {
  86. _hiddenTextBox.SendKeyDownEvent(e);
  87. }
  88. });
  89. }
  90. public bool TextProcessingEnabled
  91. {
  92. get
  93. {
  94. return Volatile.Read(ref _canProcessInput);
  95. }
  96. set
  97. {
  98. Volatile.Write(ref _canProcessInput, value);
  99. }
  100. }
  101. public event DynamicTextChangedHandler TextChangedEvent;
  102. public event KeyPressedHandler KeyPressedEvent;
  103. public event KeyReleasedHandler KeyReleasedEvent;
  104. public void Dispose()
  105. {
  106. (_parent.InputManager.KeyboardDriver as AvaloniaKeyboardDriver).KeyPressed -= AvaloniaDynamicTextInputHandler_KeyPressed;
  107. (_parent.InputManager.KeyboardDriver as AvaloniaKeyboardDriver).KeyRelease -= AvaloniaDynamicTextInputHandler_KeyRelease;
  108. (_parent.InputManager.KeyboardDriver as AvaloniaKeyboardDriver).TextInput -= AvaloniaDynamicTextInputHandler_TextInput;
  109. _textChangedSubscription?.Dispose();
  110. _selectionStartChangedSubscription?.Dispose();
  111. _selectionEndtextChangedSubscription?.Dispose();
  112. Dispatcher.UIThread.Post(() =>
  113. {
  114. _hiddenTextBox.Clear();
  115. _parent.GlRenderer.Focus();
  116. _parent = null;
  117. });
  118. }
  119. public void SetText(string text, int cursorBegin)
  120. {
  121. Dispatcher.UIThread.Post(() =>
  122. {
  123. _hiddenTextBox.Text = text;
  124. _hiddenTextBox.CaretIndex = cursorBegin;
  125. });
  126. }
  127. public void SetText(string text, int cursorBegin, int cursorEnd)
  128. {
  129. Dispatcher.UIThread.Post(() =>
  130. {
  131. _hiddenTextBox.Text = text;
  132. _hiddenTextBox.SelectionStart = cursorBegin;
  133. _hiddenTextBox.SelectionEnd = cursorEnd;
  134. });
  135. }
  136. }
  137. }