/ src / Ryujinx / UI / Helpers / ButtonKeyAssigner.cs
ButtonKeyAssigner.cs
  1  using Avalonia.Controls.Primitives;
  2  using Avalonia.Threading;
  3  using Ryujinx.Input;
  4  using Ryujinx.Input.Assigner;
  5  using System;
  6  using System.Threading.Tasks;
  7  
  8  namespace Ryujinx.Ava.UI.Helpers
  9  {
 10      internal class ButtonKeyAssigner
 11      {
 12          internal class ButtonAssignedEventArgs : EventArgs
 13          {
 14              public ToggleButton Button { get; }
 15              public Button? ButtonValue { get; }
 16  
 17              public ButtonAssignedEventArgs(ToggleButton button, Button? buttonValue)
 18              {
 19                  Button = button;
 20                  ButtonValue = buttonValue;
 21              }
 22          }
 23  
 24          public ToggleButton ToggledButton { get; set; }
 25  
 26          private bool _isWaitingForInput;
 27          private bool _shouldUnbind;
 28          public event EventHandler<ButtonAssignedEventArgs> ButtonAssigned;
 29  
 30          public ButtonKeyAssigner(ToggleButton toggleButton)
 31          {
 32              ToggledButton = toggleButton;
 33          }
 34  
 35          public async void GetInputAndAssign(IButtonAssigner assigner, IKeyboard keyboard = null)
 36          {
 37              Dispatcher.UIThread.Post(() =>
 38              {
 39                  ToggledButton.IsChecked = true;
 40              });
 41  
 42              if (_isWaitingForInput)
 43              {
 44                  Dispatcher.UIThread.Post(() =>
 45                  {
 46                      Cancel();
 47                  });
 48  
 49                  return;
 50              }
 51  
 52              _isWaitingForInput = true;
 53  
 54              assigner.Initialize();
 55  
 56              await Task.Run(async () =>
 57              {
 58                  while (true)
 59                  {
 60                      if (!_isWaitingForInput)
 61                      {
 62                          return;
 63                      }
 64  
 65                      await Task.Delay(10);
 66  
 67                      assigner.ReadInput();
 68  
 69                      if (assigner.IsAnyButtonPressed() || assigner.ShouldCancel() || (keyboard != null && keyboard.IsPressed(Key.Escape)))
 70                      {
 71                          break;
 72                      }
 73                  }
 74              });
 75  
 76              await Dispatcher.UIThread.InvokeAsync(() =>
 77              {
 78                  Button? pressedButton = assigner.GetPressedButton();
 79  
 80                  if (_shouldUnbind)
 81                  {
 82                      pressedButton = null;
 83                  }
 84  
 85                  _shouldUnbind = false;
 86                  _isWaitingForInput = false;
 87  
 88                  ToggledButton.IsChecked = false;
 89  
 90                  ButtonAssigned?.Invoke(this, new ButtonAssignedEventArgs(ToggledButton, pressedButton));
 91  
 92              });
 93          }
 94  
 95          public void Cancel(bool shouldUnbind = false)
 96          {
 97              _isWaitingForInput = false;
 98              ToggledButton.IsChecked = false;
 99              _shouldUnbind = shouldUnbind;
100          }
101      }
102  }