AvaloniaDynamicTextInputHandler.cs 5.6 KB

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