mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2025-01-28 21:30:32 +00:00
Add missing hotkeys, allow modifiers and controller button mappings on Avalonia
This commit is contained in:
parent
ecee34a50c
commit
17b0a77916
26 changed files with 901 additions and 148 deletions
|
@ -19,6 +19,7 @@ using Ryujinx.Ava.UI.ViewModels;
|
|||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.SystemInterop;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
|
@ -44,6 +45,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using static Ryujinx.Ava.UI.Helpers.Win32NativeInterop;
|
||||
|
@ -77,6 +79,7 @@ namespace Ryujinx.Ava
|
|||
|
||||
private readonly MainWindowViewModel _viewModel;
|
||||
private readonly IKeyboard _keyboardInterface;
|
||||
private readonly List<IGamepad> _gamepadInterfaces;
|
||||
private readonly TopLevel _topLevel;
|
||||
public RendererHost _rendererHost;
|
||||
|
||||
|
@ -84,6 +87,8 @@ namespace Ryujinx.Ava
|
|||
private float _newVolume;
|
||||
private KeyboardHotkeyState _prevHotkeyState;
|
||||
|
||||
private int _gamepadsChanged;
|
||||
|
||||
private long _lastCursorMoveTime;
|
||||
private bool _isCursorInRenderer;
|
||||
|
||||
|
@ -139,6 +144,13 @@ namespace Ryujinx.Ava
|
|||
|
||||
_keyboardInterface = (IKeyboard)_inputManager.KeyboardDriver.GetGamepad("0");
|
||||
|
||||
_gamepadInterfaces = new List<IGamepad>();
|
||||
|
||||
_inputManager.GamepadDriver.OnGamepadConnected += GamepadConnected;
|
||||
_inputManager.GamepadDriver.OnGamepadDisconnected += GamepadDisconnected;
|
||||
|
||||
RefreshGamepads();
|
||||
|
||||
NpadManager = _inputManager.CreateNpadManager();
|
||||
TouchScreenManager = _inputManager.CreateTouchScreenManager();
|
||||
ApplicationPath = applicationPath;
|
||||
|
@ -916,6 +928,11 @@ namespace Ryujinx.Ava
|
|||
return false;
|
||||
}
|
||||
|
||||
if (Interlocked.Exchange(ref _gamepadsChanged, 0) == 1)
|
||||
{
|
||||
RefreshGamepads();
|
||||
}
|
||||
|
||||
NpadManager.Update(ConfigurationState.Instance.Graphics.AspectRatio.Value.ToFloat());
|
||||
|
||||
if (_viewModel.IsActive)
|
||||
|
@ -960,15 +977,11 @@ namespace Ryujinx.Ava
|
|||
{
|
||||
switch (currentHotkeyState)
|
||||
{
|
||||
case KeyboardHotkeyState.ToggleVSync:
|
||||
Device.EnableDeviceVsync = !Device.EnableDeviceVsync;
|
||||
|
||||
case KeyboardHotkeyState.None:
|
||||
(_keyboardInterface as AvaloniaKeyboard).Clear();
|
||||
break;
|
||||
case KeyboardHotkeyState.Screenshot:
|
||||
ScreenshotRequested = true;
|
||||
break;
|
||||
case KeyboardHotkeyState.ShowUi:
|
||||
_viewModel.ShowMenuAndStatusBar = true;
|
||||
case KeyboardHotkeyState.Exit:
|
||||
_viewModel.ExitCurrentState();
|
||||
break;
|
||||
case KeyboardHotkeyState.Pause:
|
||||
if (_viewModel.IsPaused)
|
||||
|
@ -980,6 +993,24 @@ namespace Ryujinx.Ava
|
|||
Pause();
|
||||
}
|
||||
break;
|
||||
case KeyboardHotkeyState.ResScaleUp:
|
||||
GraphicsConfig.ResScale = GraphicsConfig.ResScale % MaxResolutionScale + 1;
|
||||
break;
|
||||
case KeyboardHotkeyState.ResScaleDown:
|
||||
GraphicsConfig.ResScale = (MaxResolutionScale + GraphicsConfig.ResScale - 2) % MaxResolutionScale + 1;
|
||||
break;
|
||||
case KeyboardHotkeyState.Screenshot:
|
||||
ScreenshotRequested = true;
|
||||
break;
|
||||
case KeyboardHotkeyState.ShowUi:
|
||||
_viewModel.ShowMenuAndStatusBar = true;
|
||||
break;
|
||||
case KeyboardHotkeyState.ToggleDockedMode:
|
||||
_viewModel.ToggleDockMode();
|
||||
break;
|
||||
case KeyboardHotkeyState.ToggleFullscreen:
|
||||
_viewModel.ToggleFullscreen();
|
||||
break;
|
||||
case KeyboardHotkeyState.ToggleMute:
|
||||
if (Device.IsAudioMuted())
|
||||
{
|
||||
|
@ -992,12 +1023,8 @@ namespace Ryujinx.Ava
|
|||
|
||||
_viewModel.Volume = Device.GetVolume();
|
||||
break;
|
||||
case KeyboardHotkeyState.ResScaleUp:
|
||||
GraphicsConfig.ResScale = GraphicsConfig.ResScale % MaxResolutionScale + 1;
|
||||
break;
|
||||
case KeyboardHotkeyState.ResScaleDown:
|
||||
GraphicsConfig.ResScale =
|
||||
(MaxResolutionScale + GraphicsConfig.ResScale - 2) % MaxResolutionScale + 1;
|
||||
case KeyboardHotkeyState.ToggleVSync:
|
||||
Device.EnableDeviceVsync = !Device.EnableDeviceVsync;
|
||||
break;
|
||||
case KeyboardHotkeyState.VolumeUp:
|
||||
_newVolume = MathF.Round((Device.GetVolume() + VolumeDelta), 2);
|
||||
|
@ -1011,9 +1038,6 @@ namespace Ryujinx.Ava
|
|||
|
||||
_viewModel.Volume = Device.GetVolume();
|
||||
break;
|
||||
case KeyboardHotkeyState.None:
|
||||
(_keyboardInterface as AvaloniaKeyboard).Clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1048,44 +1072,112 @@ namespace Ryujinx.Ava
|
|||
{
|
||||
KeyboardHotkeyState state = KeyboardHotkeyState.None;
|
||||
|
||||
if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ToggleVsync))
|
||||
if (IsHotkeyPressed(ConfigurationState.Instance.Hid.Hotkeys.Value.Exit))
|
||||
{
|
||||
state = KeyboardHotkeyState.ToggleVSync;
|
||||
state = KeyboardHotkeyState.Exit;
|
||||
}
|
||||
else if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Screenshot))
|
||||
{
|
||||
state = KeyboardHotkeyState.Screenshot;
|
||||
}
|
||||
else if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ShowUi))
|
||||
{
|
||||
state = KeyboardHotkeyState.ShowUi;
|
||||
}
|
||||
else if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Pause))
|
||||
else if (IsHotkeyPressed(ConfigurationState.Instance.Hid.Hotkeys.Value.Pause))
|
||||
{
|
||||
state = KeyboardHotkeyState.Pause;
|
||||
}
|
||||
else if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ToggleMute))
|
||||
{
|
||||
state = KeyboardHotkeyState.ToggleMute;
|
||||
}
|
||||
else if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ResScaleUp))
|
||||
else if (IsHotkeyPressed(ConfigurationState.Instance.Hid.Hotkeys.Value.ResScaleUp))
|
||||
{
|
||||
state = KeyboardHotkeyState.ResScaleUp;
|
||||
}
|
||||
else if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ResScaleDown))
|
||||
else if (IsHotkeyPressed(ConfigurationState.Instance.Hid.Hotkeys.Value.ResScaleDown))
|
||||
{
|
||||
state = KeyboardHotkeyState.ResScaleDown;
|
||||
}
|
||||
else if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.VolumeUp))
|
||||
else if (IsHotkeyPressed(ConfigurationState.Instance.Hid.Hotkeys.Value.Screenshot))
|
||||
{
|
||||
state = KeyboardHotkeyState.Screenshot;
|
||||
}
|
||||
else if (IsHotkeyPressed(ConfigurationState.Instance.Hid.Hotkeys.Value.ShowUi))
|
||||
{
|
||||
state = KeyboardHotkeyState.ShowUi;
|
||||
}
|
||||
else if (IsHotkeyPressed(ConfigurationState.Instance.Hid.Hotkeys.Value.ToggleDockedMode))
|
||||
{
|
||||
state = KeyboardHotkeyState.ToggleDockedMode;
|
||||
}
|
||||
else if (IsHotkeyPressed(ConfigurationState.Instance.Hid.Hotkeys.Value.ToggleFullscreen))
|
||||
{
|
||||
state = KeyboardHotkeyState.ToggleFullscreen;
|
||||
}
|
||||
else if (IsHotkeyPressed(ConfigurationState.Instance.Hid.Hotkeys.Value.ToggleMute))
|
||||
{
|
||||
state = KeyboardHotkeyState.ToggleMute;
|
||||
}
|
||||
else if (IsHotkeyPressed(ConfigurationState.Instance.Hid.Hotkeys.Value.ToggleVsync))
|
||||
{
|
||||
state = KeyboardHotkeyState.ToggleVSync;
|
||||
}
|
||||
else if (IsHotkeyPressed(ConfigurationState.Instance.Hid.Hotkeys.Value.VolumeUp))
|
||||
{
|
||||
state = KeyboardHotkeyState.VolumeUp;
|
||||
}
|
||||
else if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.VolumeDown))
|
||||
else if (IsHotkeyPressed(ConfigurationState.Instance.Hid.Hotkeys.Value.VolumeDown))
|
||||
{
|
||||
state = KeyboardHotkeyState.VolumeDown;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
private void GamepadConnected(string id)
|
||||
{
|
||||
Interlocked.Exchange(ref _gamepadsChanged, 1);
|
||||
}
|
||||
|
||||
private void GamepadDisconnected(string id)
|
||||
{
|
||||
Interlocked.Exchange(ref _gamepadsChanged, 1);
|
||||
}
|
||||
|
||||
private void RefreshGamepads()
|
||||
{
|
||||
_gamepadInterfaces.Clear();
|
||||
|
||||
foreach (string id in _inputManager.GamepadDriver.GamepadsIds)
|
||||
{
|
||||
_gamepadInterfaces.Add(_inputManager.GamepadDriver.GetGamepad(id));
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsHotkeyPressed(Hotkey hotkey)
|
||||
{
|
||||
if (hotkey.HasKeyboard() &&
|
||||
(_keyboardInterface as AvaloniaKeyboard).IsPressed((Ryujinx.Input.Key)hotkey.Key, hotkey.Modifier))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hotkey.HasGamepad())
|
||||
{
|
||||
foreach (IGamepad gamepad in _gamepadInterfaces)
|
||||
{
|
||||
ulong mask = hotkey.GamepadInputMask;
|
||||
|
||||
while (mask != 0UL)
|
||||
{
|
||||
int bit = BitOperations.TrailingZeroCount(mask);
|
||||
|
||||
if (!gamepad.IsPressed((GamepadButtonInputId)bit))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
mask &= ~(1UL << bit);
|
||||
}
|
||||
|
||||
if (mask == 0UL)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -565,6 +565,9 @@
|
|||
"RyujinxUpdater": "Ryujinx Updater",
|
||||
"SettingsTabHotkeys": "Keyboard Hotkeys",
|
||||
"SettingsTabHotkeysHotkeys": "Keyboard Hotkeys",
|
||||
"SettingsTabHotkeysExitHotkey": "Exit:",
|
||||
"SettingsTabHotkeysToggleDockedModeHotkey": "Toggle Docked Mode:",
|
||||
"SettingsTabHotkeysToggleFullscreenHotkey": "Toggle Fullscreen:",
|
||||
"SettingsTabHotkeysToggleVsyncHotkey": "Toggle VSync:",
|
||||
"SettingsTabHotkeysScreenshotHotkey": "Screenshot:",
|
||||
"SettingsTabHotkeysShowUiHotkey": "Show UI:",
|
||||
|
|
|
@ -3,13 +3,16 @@
|
|||
public enum KeyboardHotkeyState
|
||||
{
|
||||
None,
|
||||
ToggleVSync,
|
||||
Screenshot,
|
||||
ShowUi,
|
||||
Exit,
|
||||
Pause,
|
||||
ToggleMute,
|
||||
ResScaleUp,
|
||||
ResScaleDown,
|
||||
Screenshot,
|
||||
ShowUi,
|
||||
ToggleDockedMode,
|
||||
ToggleFullscreen,
|
||||
ToggleMute,
|
||||
ToggleVSync,
|
||||
VolumeUp,
|
||||
VolumeDown
|
||||
}
|
||||
|
|
|
@ -112,6 +112,18 @@ namespace Ryujinx.Ava.Input
|
|||
}
|
||||
}
|
||||
|
||||
public bool IsPressed(Key key, KeyModifier modifier)
|
||||
{
|
||||
try
|
||||
{
|
||||
return _driver.IsPressed(key, modifier);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetConfiguration(InputConfig configuration)
|
||||
{
|
||||
lock (_userMappingLock)
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
using Ryujinx.Common.Configuration.Hid.Keyboard;
|
||||
using Ryujinx.Input;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
@ -13,23 +15,23 @@ namespace Ryujinx.Ava.Input
|
|||
internal class AvaloniaKeyboardDriver : IGamepadDriver
|
||||
{
|
||||
private static readonly string[] _keyboardIdentifers = new string[1] { "0" };
|
||||
private readonly Control _control;
|
||||
private readonly HashSet<AvaKey> _pressedKeys;
|
||||
private readonly Control _control;
|
||||
private readonly Dictionary<AvaKey, KeyModifiers> _pressedKeys;
|
||||
|
||||
public event EventHandler<KeyEventArgs> KeyPressed;
|
||||
public event EventHandler<KeyEventArgs> KeyRelease;
|
||||
public event EventHandler<string> TextInput;
|
||||
public event EventHandler<string> TextInput;
|
||||
|
||||
public string DriverName => "AvaloniaKeyboardDriver";
|
||||
public string DriverName => "AvaloniaKeyboardDriver";
|
||||
public ReadOnlySpan<string> GamepadsIds => _keyboardIdentifers;
|
||||
|
||||
public AvaloniaKeyboardDriver(Control control)
|
||||
{
|
||||
_control = control;
|
||||
_pressedKeys = new HashSet<AvaKey>();
|
||||
_control = control;
|
||||
_pressedKeys = new Dictionary<AvaKey, KeyModifiers>();
|
||||
|
||||
_control.KeyDown += OnKeyPress;
|
||||
_control.KeyUp += OnKeyRelease;
|
||||
_control.KeyDown += OnKeyPress;
|
||||
_control.KeyUp += OnKeyRelease;
|
||||
_control.TextInput += Control_TextInput;
|
||||
_control.AddHandler(InputElement.TextInputEvent, Control_LastChanceTextInput, RoutingStrategies.Bubble);
|
||||
}
|
||||
|
@ -47,13 +49,13 @@ namespace Ryujinx.Ava.Input
|
|||
|
||||
public event Action<string> OnGamepadConnected
|
||||
{
|
||||
add { }
|
||||
add { }
|
||||
remove { }
|
||||
}
|
||||
|
||||
public event Action<string> OnGamepadDisconnected
|
||||
{
|
||||
add { }
|
||||
add { }
|
||||
remove { }
|
||||
}
|
||||
|
||||
|
@ -71,14 +73,14 @@ namespace Ryujinx.Ava.Input
|
|||
{
|
||||
if (disposing)
|
||||
{
|
||||
_control.KeyUp -= OnKeyPress;
|
||||
_control.KeyUp -= OnKeyPress;
|
||||
_control.KeyDown -= OnKeyRelease;
|
||||
}
|
||||
}
|
||||
|
||||
protected void OnKeyPress(object sender, KeyEventArgs args)
|
||||
{
|
||||
_pressedKeys.Add(args.Key);
|
||||
_pressedKeys[args.Key] = args.KeyModifiers;
|
||||
|
||||
KeyPressed?.Invoke(this, args);
|
||||
}
|
||||
|
@ -99,7 +101,42 @@ namespace Ryujinx.Ava.Input
|
|||
|
||||
AvaloniaKeyboardMappingHelper.TryGetAvaKey(key, out var nativeKey);
|
||||
|
||||
return _pressedKeys.Contains(nativeKey);
|
||||
return _pressedKeys.TryGetValue(nativeKey, out _);
|
||||
}
|
||||
|
||||
internal bool IsPressed(Key key, KeyModifier modifier)
|
||||
{
|
||||
if (key == Key.Unbound || key == Key.Unknown)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
AvaloniaKeyboardMappingHelper.TryGetAvaKey(key, out var nativeKey);
|
||||
bool keyPressed = _pressedKeys.TryGetValue(nativeKey, out var modifiers);
|
||||
|
||||
KeyModifiers avaModifiers = KeyModifiers.None;
|
||||
|
||||
if (modifier.HasFlag(KeyModifier.Alt))
|
||||
{
|
||||
avaModifiers |= KeyModifiers.Alt;
|
||||
}
|
||||
|
||||
if (modifier.HasFlag(KeyModifier.Control))
|
||||
{
|
||||
avaModifiers |= KeyModifiers.Control;
|
||||
}
|
||||
|
||||
if (modifier.HasFlag(KeyModifier.Shift))
|
||||
{
|
||||
avaModifiers |= KeyModifiers.Shift;
|
||||
}
|
||||
|
||||
if (modifier.HasFlag(KeyModifier.Meta))
|
||||
{
|
||||
avaModifiers |= KeyModifiers.Meta;
|
||||
}
|
||||
|
||||
return keyPressed && (modifiers & avaModifiers) == avaModifiers;
|
||||
}
|
||||
|
||||
public void ResetKeys()
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||
IsAssigned = isAssigned;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public ToggleButton ToggledButton { get; set; }
|
||||
|
||||
private bool _isWaitingForInput;
|
||||
|
|
150
Ryujinx.Ava/UI/Helpers/HotkeyButtonKeyAssigner.cs
Normal file
150
Ryujinx.Ava/UI/Helpers/HotkeyButtonKeyAssigner.cs
Normal file
|
@ -0,0 +1,150 @@
|
|||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Threading;
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
using Ryujinx.Input.Assigner;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using HidKey = Ryujinx.Common.Configuration.Hid.Key;
|
||||
using Key = Ryujinx.Input.Key;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Helpers
|
||||
{
|
||||
internal class HotkeyButtonKeyAssigner
|
||||
{
|
||||
internal class ButtonAssignedEventArgs : EventArgs
|
||||
{
|
||||
public ToggleButton Button { get; }
|
||||
public bool IsAssigned { get; }
|
||||
|
||||
public ButtonAssignedEventArgs(ToggleButton button, bool isAssigned)
|
||||
{
|
||||
Button = button;
|
||||
IsAssigned = isAssigned;
|
||||
}
|
||||
}
|
||||
|
||||
public ToggleButton ToggledButton { get; set; }
|
||||
|
||||
private readonly Action<string, Hotkey> _updateHotkeyCallback;
|
||||
private bool _isWaitingForInput;
|
||||
private bool _shouldUnbind;
|
||||
public event EventHandler<ButtonAssignedEventArgs> ButtonAssigned;
|
||||
|
||||
public HotkeyButtonKeyAssigner(ToggleButton toggleButton, Action<string, Hotkey> updateHotkeyCallback)
|
||||
{
|
||||
ToggledButton = toggleButton;
|
||||
_updateHotkeyCallback = updateHotkeyCallback;
|
||||
}
|
||||
|
||||
public async void GetInputAndAssign(IButtonAssigner assigner)
|
||||
{
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
ToggledButton.IsChecked = true;
|
||||
});
|
||||
|
||||
if (_isWaitingForInput)
|
||||
{
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
Cancel();
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
_isWaitingForInput = true;
|
||||
|
||||
assigner.Initialize();
|
||||
|
||||
await Task.Run(async () =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (!_isWaitingForInput)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await Task.Delay(10);
|
||||
|
||||
assigner.ReadInput();
|
||||
|
||||
if (assigner.HasAnyButtonPressed() || assigner.ShouldCancel())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
await Dispatcher.UIThread.InvokeAsync(() =>
|
||||
{
|
||||
IEnumerable<PressedButton> pressedButtons = assigner.GetPressedButtons();
|
||||
bool isAssigned = pressedButtons.Any();
|
||||
|
||||
if (_shouldUnbind)
|
||||
{
|
||||
_updateHotkeyCallback((string)ToggledButton.Tag, new Hotkey(HidKey.Unbound));
|
||||
}
|
||||
else if (isAssigned)
|
||||
{
|
||||
_updateHotkeyCallback((string)ToggledButton.Tag, CreateHotkey(pressedButtons));
|
||||
}
|
||||
|
||||
_shouldUnbind = false;
|
||||
_isWaitingForInput = false;
|
||||
|
||||
ToggledButton.IsChecked = false;
|
||||
|
||||
ButtonAssigned?.Invoke(this, new ButtonAssignedEventArgs(ToggledButton, isAssigned));
|
||||
});
|
||||
}
|
||||
|
||||
private Hotkey CreateHotkey(IEnumerable<PressedButton> buttons)
|
||||
{
|
||||
Key pressedKey = Key.Unknown;
|
||||
KeyModifier modifier = KeyModifier.None;
|
||||
ulong gamepadInputMask = 0UL;
|
||||
|
||||
foreach (PressedButton button in buttons)
|
||||
{
|
||||
if (button.Type == PressedButtonType.Key)
|
||||
{
|
||||
Key key = button.AsKey();
|
||||
|
||||
if (key == Key.ControlLeft || key == Key.ControlRight)
|
||||
{
|
||||
modifier |= KeyModifier.Control;
|
||||
}
|
||||
else if (key == Key.AltLeft || key == Key.AltRight)
|
||||
{
|
||||
modifier |= KeyModifier.Alt;
|
||||
}
|
||||
else if (key == Key.ShiftLeft || key == Key.ShiftRight)
|
||||
{
|
||||
modifier |= KeyModifier.Shift;
|
||||
}
|
||||
else
|
||||
{
|
||||
pressedKey = key;
|
||||
}
|
||||
}
|
||||
else if (button.Type == PressedButtonType.Button)
|
||||
{
|
||||
gamepadInputMask |= 1UL << (int)button.AsGamepadButtonInputId();
|
||||
}
|
||||
}
|
||||
|
||||
return new Hotkey((HidKey)pressedKey, modifier, gamepadInputMask);
|
||||
}
|
||||
|
||||
public void Cancel(bool shouldUnbind = false)
|
||||
{
|
||||
_isWaitingForInput = false;
|
||||
ToggledButton.IsChecked = false;
|
||||
_shouldUnbind = shouldUnbind;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,11 +3,8 @@ using Avalonia.Controls;
|
|||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Svg.Skia;
|
||||
using Avalonia.Threading;
|
||||
using LibHac.Bcat;
|
||||
using LibHac.Tools.Fs;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Input;
|
||||
using Ryujinx.Ava.UI.Controls;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
|
@ -238,9 +235,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
|
||||
if (Program.PreviewerDetached)
|
||||
{
|
||||
_mainWindow =
|
||||
(MainWindow)((IClassicDesktopStyleApplicationLifetime)Avalonia.Application.Current
|
||||
.ApplicationLifetime).MainWindow;
|
||||
_mainWindow = (MainWindow)((IClassicDesktopStyleApplicationLifetime)Avalonia.Application.Current.ApplicationLifetime).MainWindow;
|
||||
|
||||
AvaloniaKeyboardDriver = new AvaloniaKeyboardDriver(owner);
|
||||
|
||||
|
|
|
@ -1220,17 +1220,17 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
|
||||
public void LoadConfigurableHotKeys()
|
||||
{
|
||||
if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Ryujinx.Input.Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ShowUi, out var showUiKey))
|
||||
if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Ryujinx.Input.Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ShowUi.Key, out var showUiKey))
|
||||
{
|
||||
ShowUiKey = new KeyGesture(showUiKey);
|
||||
}
|
||||
|
||||
if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Ryujinx.Input.Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Screenshot, out var screenshotKey))
|
||||
if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Ryujinx.Input.Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Screenshot.Key, out var screenshotKey))
|
||||
{
|
||||
ScreenshotKey = new KeyGesture(screenshotKey);
|
||||
}
|
||||
|
||||
if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Ryujinx.Input.Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Pause, out var pauseKey))
|
||||
if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Ryujinx.Input.Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Pause.Key, out var pauseKey))
|
||||
{
|
||||
PauseKey = new KeyGesture(pauseKey);
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ using Ryujinx.Ava.UI.Helpers;
|
|||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Configuration.Hid;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||
using Ryujinx.Common.GraphicsDriver;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Graphics.Vulkan;
|
||||
|
@ -22,6 +23,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
using TimeZone = Ryujinx.Ava.UI.Models.TimeZone;
|
||||
|
||||
|
@ -240,6 +242,19 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
public AvaloniaList<string> GameDirectories { get; set; }
|
||||
public ObservableCollection<ComboBoxItem> AvailableGpus { get; set; }
|
||||
|
||||
public string ExitHotkey => GetButtonName(_keyboardHotkeys.Exit);
|
||||
public string PauseHotkey => GetButtonName(_keyboardHotkeys.Pause);
|
||||
public string ResScaleUpHotkey => GetButtonName(_keyboardHotkeys.ResScaleUp);
|
||||
public string ResScaleDownHotkey => GetButtonName(_keyboardHotkeys.ResScaleDown);
|
||||
public string ScreenshotHotkey => GetButtonName(_keyboardHotkeys.Screenshot);
|
||||
public string ShowUiHotkey => GetButtonName(_keyboardHotkeys.ShowUi);
|
||||
public string ToggleDockedModeHotkey => GetButtonName(_keyboardHotkeys.ToggleDockedMode);
|
||||
public string ToggleFullscreenHotkey => GetButtonName(_keyboardHotkeys.ToggleFullscreen);
|
||||
public string ToggleMuteHotkey => GetButtonName(_keyboardHotkeys.ToggleMute);
|
||||
public string ToggleVsyncHotkey => GetButtonName(_keyboardHotkeys.ToggleVsync);
|
||||
public string VolumeUpHotkey => GetButtonName(_keyboardHotkeys.VolumeUp);
|
||||
public string VolumeDownHotkey => GetButtonName(_keyboardHotkeys.VolumeDown);
|
||||
|
||||
public KeyboardHotkeys KeyboardHotkeys
|
||||
{
|
||||
get => _keyboardHotkeys;
|
||||
|
@ -277,6 +292,135 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
}
|
||||
}
|
||||
|
||||
public void UpdateHotkey(string name, Hotkey hotkey)
|
||||
{
|
||||
switch (name)
|
||||
{
|
||||
case "ExitHotkey":
|
||||
_keyboardHotkeys.Exit = UpdateHotkey(_keyboardHotkeys.Exit, hotkey);
|
||||
break;
|
||||
case "PauseHotkey":
|
||||
_keyboardHotkeys.Pause = UpdateHotkey(_keyboardHotkeys.Pause, hotkey);
|
||||
break;
|
||||
case "ResScaleUpHotkey":
|
||||
_keyboardHotkeys.ResScaleUp = UpdateHotkey(_keyboardHotkeys.ResScaleUp, hotkey);
|
||||
break;
|
||||
case "ResScaleDownHotkey":
|
||||
_keyboardHotkeys.ResScaleDown = UpdateHotkey(_keyboardHotkeys.ResScaleDown, hotkey);
|
||||
break;
|
||||
case "ScreenshotHotkey":
|
||||
_keyboardHotkeys.Screenshot = UpdateHotkey(_keyboardHotkeys.Screenshot, hotkey);
|
||||
break;
|
||||
case "ShowUiHotkey":
|
||||
_keyboardHotkeys.ShowUi = UpdateHotkey(_keyboardHotkeys.ShowUi, hotkey);
|
||||
break;
|
||||
case "ToggleDockedModeHotkey":
|
||||
_keyboardHotkeys.ToggleDockedMode = UpdateHotkey(_keyboardHotkeys.ToggleDockedMode, hotkey);
|
||||
break;
|
||||
case "ToggleFullscreenHotkey":
|
||||
_keyboardHotkeys.ToggleFullscreen = UpdateHotkey(_keyboardHotkeys.ToggleFullscreen, hotkey);
|
||||
break;
|
||||
case "ToggleMuteHotkey":
|
||||
_keyboardHotkeys.ToggleMute = UpdateHotkey(_keyboardHotkeys.ToggleMute, hotkey);
|
||||
break;
|
||||
case "ToggleVsyncHotkey":
|
||||
_keyboardHotkeys.ToggleVsync = UpdateHotkey(_keyboardHotkeys.ToggleVsync, hotkey);
|
||||
break;
|
||||
case "VolumeUpHotkey":
|
||||
_keyboardHotkeys.VolumeUp = UpdateHotkey(_keyboardHotkeys.VolumeUp, hotkey);
|
||||
break;
|
||||
case "VolumeDownHotkey":
|
||||
_keyboardHotkeys.VolumeDown = UpdateHotkey(_keyboardHotkeys.VolumeDown, hotkey);
|
||||
break;
|
||||
}
|
||||
|
||||
OnPropertyChanged(name);
|
||||
}
|
||||
|
||||
private Hotkey UpdateHotkey(Hotkey hotkey, Hotkey newHotkey)
|
||||
{
|
||||
if (newHotkey.HasKeyboard())
|
||||
{
|
||||
hotkey.Key = newHotkey.Key;
|
||||
hotkey.Modifier = newHotkey.Modifier;
|
||||
}
|
||||
else if (newHotkey.HasGamepad())
|
||||
{
|
||||
hotkey.GamepadInputMask = newHotkey.GamepadInputMask;
|
||||
}
|
||||
else
|
||||
{
|
||||
hotkey = new Hotkey(Key.Unbound);
|
||||
}
|
||||
|
||||
return hotkey;
|
||||
}
|
||||
|
||||
private static string GetButtonName(Hotkey hotkey)
|
||||
{
|
||||
string keyboardBinding = null;
|
||||
string gamepadBinding = null;
|
||||
|
||||
if (hotkey.HasKeyboard())
|
||||
{
|
||||
int keyCount = 1 + BitOperations.PopCount((uint)hotkey.Modifier);
|
||||
int index = 0;
|
||||
|
||||
string[] keys = new string[keyCount];
|
||||
|
||||
if (hotkey.Modifier.HasFlag(KeyModifier.Control))
|
||||
{
|
||||
keys[index++] = KeyModifier.Control.ToString();
|
||||
}
|
||||
|
||||
if (hotkey.Modifier.HasFlag(KeyModifier.Meta))
|
||||
{
|
||||
keys[index++] = KeyModifier.Meta.ToString();
|
||||
}
|
||||
|
||||
if (hotkey.Modifier.HasFlag(KeyModifier.Alt))
|
||||
{
|
||||
keys[index++] = KeyModifier.Alt.ToString();
|
||||
}
|
||||
|
||||
if (hotkey.Modifier.HasFlag(KeyModifier.Shift))
|
||||
{
|
||||
keys[index++] = KeyModifier.Shift.ToString();
|
||||
}
|
||||
|
||||
keys[index] = hotkey.Key.ToString();
|
||||
|
||||
keyboardBinding = string.Join(" + ", keys);
|
||||
}
|
||||
|
||||
if (hotkey.HasGamepad())
|
||||
{
|
||||
int buttonCount = BitOperations.PopCount(hotkey.GamepadInputMask);
|
||||
int index = 0;
|
||||
|
||||
string[] buttons = new string[buttonCount];
|
||||
ulong mask = hotkey.GamepadInputMask;
|
||||
|
||||
while (mask != 0UL)
|
||||
{
|
||||
int bit = BitOperations.TrailingZeroCount(mask);
|
||||
|
||||
buttons[index++] = ((GamepadInputId)bit).ToString();
|
||||
|
||||
mask &= ~(1UL << bit);
|
||||
}
|
||||
|
||||
gamepadBinding = string.Join(" + ", buttons);
|
||||
}
|
||||
|
||||
if (keyboardBinding != null && gamepadBinding != null)
|
||||
{
|
||||
return $"{keyboardBinding} or {gamepadBinding}";
|
||||
}
|
||||
|
||||
return keyboardBinding ?? gamepadBinding ?? "Unbound";
|
||||
}
|
||||
|
||||
public void CheckSoundBackends()
|
||||
{
|
||||
IsOpenAlEnabled = OpenALHardwareDeviceDriver.IsSupported;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<UserControl
|
||||
<UserControl
|
||||
x:Class="Ryujinx.Ava.UI.Views.Settings.SettingsHotkeysView"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
|
@ -17,7 +17,7 @@
|
|||
<UserControl.Resources>
|
||||
<helpers:KeyValueConverter x:Key="Key" />
|
||||
</UserControl.Resources>
|
||||
<ScrollViewer
|
||||
<ScrollViewer
|
||||
Name="HotkeysPage"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
|
@ -27,74 +27,98 @@
|
|||
<StackPanel Margin="10" Orientation="Vertical" Spacing="10">
|
||||
<TextBlock Classes="h1" Text="{locale:Locale SettingsTabHotkeysHotkeys}" />
|
||||
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
|
||||
<TextBlock VerticalAlignment="Center" Text="{locale:Locale SettingsTabHotkeysToggleVsyncHotkey}" Width="230" />
|
||||
<ToggleButton Width="90" Height="27" Checked="Button_Checked" Unchecked="Button_Unchecked">
|
||||
<TextBlock VerticalAlignment="Center" Text="{locale:Locale SettingsTabHotkeysExitHotkey}" Width="250" />
|
||||
<ToggleButton Tag="ExitHotkey" Width="350" Height="27" Checked="Button_Checked" Unchecked="Button_Unchecked">
|
||||
<TextBlock
|
||||
Text="{Binding KeyboardHotkeys.ToggleVsync, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding ExitHotkey}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
|
||||
<TextBlock VerticalAlignment="Center" Text="{locale:Locale SettingsTabHotkeysScreenshotHotkey}" Width="230" />
|
||||
<ToggleButton Width="90" Height="27" Checked="Button_Checked" Unchecked="Button_Unchecked">
|
||||
<TextBlock VerticalAlignment="Center" Text="{locale:Locale SettingsTabHotkeysPauseHotkey}" Width="250" />
|
||||
<ToggleButton Tag="PauseHotkey" Width="350" Height="27" Checked="Button_Checked" Unchecked="Button_Unchecked">
|
||||
<TextBlock
|
||||
Text="{Binding KeyboardHotkeys.Screenshot, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding PauseHotkey}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
|
||||
<TextBlock VerticalAlignment="Center" Text="{locale:Locale SettingsTabHotkeysShowUiHotkey}" Width="230" />
|
||||
<ToggleButton Width="90" Height="27" Checked="Button_Checked" Unchecked="Button_Unchecked">
|
||||
<TextBlock VerticalAlignment="Center" Text="{locale:Locale SettingsTabHotkeysResScaleUpHotkey}" Width="250" />
|
||||
<ToggleButton Tag="ResScaleUpHotkey" Width="350" Height="27" Checked="Button_Checked" Unchecked="Button_Unchecked">
|
||||
<TextBlock
|
||||
Text="{Binding KeyboardHotkeys.ShowUi, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding ResScaleUpHotkey}}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
|
||||
<TextBlock VerticalAlignment="Center" Text="{locale:Locale SettingsTabHotkeysPauseHotkey}" Width="230" />
|
||||
<ToggleButton Width="90" Height="27" Checked="Button_Checked" Unchecked="Button_Unchecked">
|
||||
<TextBlock VerticalAlignment="Center" Text="{locale:Locale SettingsTabHotkeysResScaleDownHotkey}" Width="250" />
|
||||
<ToggleButton Tag="ResScaleDownHotkey" Width="350" Height="27" Checked="Button_Checked" Unchecked="Button_Unchecked">
|
||||
<TextBlock
|
||||
Text="{Binding KeyboardHotkeys.Pause, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding ResScaleDownHotkey}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
|
||||
<TextBlock VerticalAlignment="Center" Text="{locale:Locale SettingsTabHotkeysToggleMuteHotkey}" Width="230" />
|
||||
<ToggleButton Width="90" Height="27" Checked="Button_Checked" Unchecked="Button_Unchecked">
|
||||
<TextBlock VerticalAlignment="Center" Text="{locale:Locale SettingsTabHotkeysScreenshotHotkey}" Width="250" />
|
||||
<ToggleButton Tag="ScreenshotHotkey" Width="350" Height="27" Checked="Button_Checked" Unchecked="Button_Unchecked">
|
||||
<TextBlock
|
||||
Text="{Binding KeyboardHotkeys.ToggleMute, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding ScreenshotHotkey}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
|
||||
<TextBlock VerticalAlignment="Center" Text="{locale:Locale SettingsTabHotkeysResScaleUpHotkey}" Width="230" />
|
||||
<ToggleButton Width="90" Height="27" Checked="Button_Checked" Unchecked="Button_Unchecked">
|
||||
<TextBlock VerticalAlignment="Center" Text="{locale:Locale SettingsTabHotkeysShowUiHotkey}" Width="250" />
|
||||
<ToggleButton Tag="ShowUiHotkey" Width="350" Height="27" Checked="Button_Checked" Unchecked="Button_Unchecked">
|
||||
<TextBlock
|
||||
Text="{Binding KeyboardHotkeys.ResScaleUp, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding ShowUiHotkey}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
|
||||
<TextBlock VerticalAlignment="Center" Text="{locale:Locale SettingsTabHotkeysResScaleDownHotkey}" Width="230" />
|
||||
<ToggleButton Width="90" Height="27" Checked="Button_Checked" Unchecked="Button_Unchecked">
|
||||
<TextBlock VerticalAlignment="Center" Text="{locale:Locale SettingsTabHotkeysToggleDockedModeHotkey}" Width="250" />
|
||||
<ToggleButton Tag="ToggleDockedModeHotkey" Width="350" Height="27" Checked="Button_Checked" Unchecked="Button_Unchecked">
|
||||
<TextBlock
|
||||
Text="{Binding KeyboardHotkeys.ResScaleDown, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding ToggleDockedModeHotkey}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
|
||||
<TextBlock VerticalAlignment="Center" Text="{locale:Locale SettingsTabHotkeysVolumeUpHotkey}" Width="230" />
|
||||
<ToggleButton Width="90" Height="27" Checked="Button_Checked" Unchecked="Button_Unchecked">
|
||||
<TextBlock VerticalAlignment="Center" Text="{locale:Locale SettingsTabHotkeysToggleFullscreenHotkey}" Width="250" />
|
||||
<ToggleButton Tag="ToggleFullscreenHotkey" Width="350" Height="27" Checked="Button_Checked" Unchecked="Button_Unchecked">
|
||||
<TextBlock
|
||||
Text="{Binding KeyboardHotkeys.VolumeUp, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding ToggleFullscreenHotkey}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
|
||||
<TextBlock VerticalAlignment="Center" Text="{locale:Locale SettingsTabHotkeysVolumeDownHotkey}" Width="230" />
|
||||
<ToggleButton Width="90" Height="27" Checked="Button_Checked" Unchecked="Button_Unchecked">
|
||||
<TextBlock VerticalAlignment="Center" Text="{locale:Locale SettingsTabHotkeysToggleMuteHotkey}" Width="250" />
|
||||
<ToggleButton Tag="ToggleMuteHotkey" Width="350" Height="27" Checked="Button_Checked" Unchecked="Button_Unchecked">
|
||||
<TextBlock
|
||||
Text="{Binding KeyboardHotkeys.VolumeDown, Mode=TwoWay, Converter={StaticResource Key}}"
|
||||
Text="{Binding ToggleMuteHotkey}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
|
||||
<TextBlock VerticalAlignment="Center" Text="{locale:Locale SettingsTabHotkeysToggleVsyncHotkey}" Width="250" />
|
||||
<ToggleButton Tag="ToggleVsyncHotkey" Width="350" Height="27" Checked="Button_Checked" Unchecked="Button_Unchecked">
|
||||
<TextBlock
|
||||
Text="{Binding ToggleVsyncHotkey}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
|
||||
<TextBlock VerticalAlignment="Center" Text="{locale:Locale SettingsTabHotkeysVolumeUpHotkey}" Width="250" />
|
||||
<ToggleButton Tag="VolumeUpHotkey" Width="350" Height="27" Checked="Button_Checked" Unchecked="Button_Unchecked">
|
||||
<TextBlock
|
||||
Text="{Binding VolumeUpHotkey}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
<StackPanel Margin="10,0,0,0" Orientation="Horizontal">
|
||||
<TextBlock VerticalAlignment="Center" Text="{locale:Locale SettingsTabHotkeysVolumeDownHotkey}" Width="250" />
|
||||
<ToggleButton Tag="VolumeDownHotkey" Width="350" Height="27" Checked="Button_Checked" Unchecked="Button_Unchecked">
|
||||
<TextBlock
|
||||
Text="{Binding VolumeDownHotkey}"
|
||||
TextAlignment="Center" />
|
||||
</ToggleButton>
|
||||
</StackPanel>
|
||||
|
|
|
@ -1,23 +1,32 @@
|
|||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Ryujinx.Ava.Input;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Input;
|
||||
using Ryujinx.Input.Assigner;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Ava.UI.Views.Settings
|
||||
{
|
||||
public partial class SettingsHotkeysView : UserControl
|
||||
{
|
||||
private ButtonKeyAssigner _currentAssigner;
|
||||
private IGamepadDriver AvaloniaKeyboardDriver;
|
||||
|
||||
public SettingsViewModel ViewModel;
|
||||
|
||||
private HotkeyButtonKeyAssigner _currentAssigner;
|
||||
private readonly MainWindow _mainWindow;
|
||||
private readonly IGamepadDriver _avaloniaKeyboardDriver;
|
||||
|
||||
public SettingsHotkeysView()
|
||||
{
|
||||
InitializeComponent();
|
||||
AvaloniaKeyboardDriver = new AvaloniaKeyboardDriver(this);
|
||||
|
||||
_mainWindow = (MainWindow)((IClassicDesktopStyleApplicationLifetime)Avalonia.Application.Current.ApplicationLifetime).MainWindow;
|
||||
_avaloniaKeyboardDriver = new AvaloniaKeyboardDriver(this);
|
||||
}
|
||||
|
||||
private void MouseClick(object sender, PointerPressedEventArgs e)
|
||||
|
@ -28,7 +37,7 @@ namespace Ryujinx.Ava.UI.Views.Settings
|
|||
|
||||
PointerPressed -= MouseClick;
|
||||
}
|
||||
|
||||
|
||||
private void Button_Checked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is ToggleButton button)
|
||||
|
@ -40,16 +49,13 @@ namespace Ryujinx.Ava.UI.Views.Settings
|
|||
|
||||
if (_currentAssigner == null && button.IsChecked != null && (bool)button.IsChecked)
|
||||
{
|
||||
_currentAssigner = new ButtonKeyAssigner(button);
|
||||
_currentAssigner = new HotkeyButtonKeyAssigner(button, ViewModel.UpdateHotkey);
|
||||
|
||||
FocusManager.Instance?.Focus(this, NavigationMethod.Pointer);
|
||||
|
||||
PointerPressed += MouseClick;
|
||||
|
||||
var keyboard = (IKeyboard)AvaloniaKeyboardDriver.GetGamepad(AvaloniaKeyboardDriver.GamepadsIds[0]);
|
||||
IButtonAssigner assigner = new KeyboardKeyAssigner(keyboard);
|
||||
|
||||
_currentAssigner.GetInputAndAssign(assigner);
|
||||
_currentAssigner.GetInputAndAssign(CreateButtonAssigner());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -66,6 +72,36 @@ namespace Ryujinx.Ava.UI.Views.Settings
|
|||
}
|
||||
}
|
||||
|
||||
private IButtonAssigner CreateButtonAssigner()
|
||||
{
|
||||
List<IButtonAssigner> assigners = new List<IButtonAssigner>();
|
||||
|
||||
IGamepadDriver keyboardDriver;
|
||||
IGamepadDriver gamepadDriver = _mainWindow.InputManager.GamepadDriver;
|
||||
|
||||
if (_mainWindow.InputManager.KeyboardDriver is AvaloniaKeyboardDriver)
|
||||
{
|
||||
// NOTE: To get input in this window, we need to bind a custom keyboard driver instead of using the InputManager one as the main window isn't focused...
|
||||
keyboardDriver = _avaloniaKeyboardDriver;
|
||||
}
|
||||
else
|
||||
{
|
||||
keyboardDriver = _mainWindow.InputManager.KeyboardDriver;
|
||||
}
|
||||
|
||||
foreach (string id in keyboardDriver.GamepadsIds)
|
||||
{
|
||||
assigners.Add(new KeyboardKeyAssigner((IKeyboard)keyboardDriver.GetGamepad(id), allowModifiers: true));
|
||||
}
|
||||
|
||||
foreach (string id in gamepadDriver.GamepadsIds)
|
||||
{
|
||||
assigners.Add(new GamepadButtonAssigner(gamepadDriver.GetGamepad(id), 0.2f, forStick: false));
|
||||
}
|
||||
|
||||
return new MultiButtonAssigner(assigners);
|
||||
}
|
||||
|
||||
private void Button_Unchecked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_currentAssigner?.Cancel();
|
||||
|
|
|
@ -66,6 +66,7 @@ namespace Ryujinx.Ava.UI.Windows
|
|||
NavPanel.Content = InputPage;
|
||||
break;
|
||||
case "HotkeysPage":
|
||||
HotkeysPage.ViewModel = ViewModel;
|
||||
NavPanel.Content = HotkeysPage;
|
||||
break;
|
||||
case "SystemPage":
|
||||
|
|
30
Ryujinx.Common/Configuration/Hid/Hotkey.cs
Normal file
30
Ryujinx.Common/Configuration/Hid/Hotkey.cs
Normal file
|
@ -0,0 +1,30 @@
|
|||
namespace Ryujinx.Common.Configuration.Hid
|
||||
{
|
||||
public struct Hotkey
|
||||
{
|
||||
public Key Key { get; set; }
|
||||
public KeyModifier Modifier { get; set; }
|
||||
public ulong GamepadInputMask { get; set; }
|
||||
|
||||
public Hotkey(Key key, KeyModifier modifier, ulong gamepadInputMask)
|
||||
{
|
||||
Key = key;
|
||||
Modifier = modifier;
|
||||
GamepadInputMask = gamepadInputMask;
|
||||
}
|
||||
|
||||
public Hotkey(Key key) : this(key, KeyModifier.None, 0UL)
|
||||
{
|
||||
}
|
||||
|
||||
public bool HasKeyboard()
|
||||
{
|
||||
return Key != Key.Unknown && Key != Key.Unbound;
|
||||
}
|
||||
|
||||
public bool HasGamepad()
|
||||
{
|
||||
return GamepadInputMask != 0UL;
|
||||
}
|
||||
}
|
||||
}
|
14
Ryujinx.Common/Configuration/Hid/KeyModifier.cs
Normal file
14
Ryujinx.Common/Configuration/Hid/KeyModifier.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
|
||||
namespace Ryujinx.Common.Configuration.Hid
|
||||
{
|
||||
[Flags]
|
||||
public enum KeyModifier
|
||||
{
|
||||
None = 0,
|
||||
Alt = 1 << 0,
|
||||
Control = 1 << 1,
|
||||
Shift = 1 << 2,
|
||||
Meta = 1 << 3
|
||||
}
|
||||
}
|
|
@ -2,14 +2,17 @@
|
|||
{
|
||||
public class KeyboardHotkeys
|
||||
{
|
||||
public Key ToggleVsync { get; set; }
|
||||
public Key Screenshot { get; set; }
|
||||
public Key ShowUi { get; set; }
|
||||
public Key Pause { get; set; }
|
||||
public Key ToggleMute { get; set; }
|
||||
public Key ResScaleUp { get; set; }
|
||||
public Key ResScaleDown { get; set; }
|
||||
public Key VolumeUp { get; set; }
|
||||
public Key VolumeDown { get; set; }
|
||||
public Hotkey Exit { get; set; }
|
||||
public Hotkey Pause { get; set; }
|
||||
public Hotkey ResScaleUp { get; set; }
|
||||
public Hotkey ResScaleDown { get; set; }
|
||||
public Hotkey Screenshot { get; set; }
|
||||
public Hotkey ShowUi { get; set; }
|
||||
public Hotkey ToggleDockedMode { get; set; }
|
||||
public Hotkey ToggleFullscreen { get; set; }
|
||||
public Hotkey ToggleMute { get; set; }
|
||||
public Hotkey ToggleVsync { get; set; }
|
||||
public Hotkey VolumeUp { get; set; }
|
||||
public Hotkey VolumeDown { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ namespace Ryujinx.Input.Assigner
|
|||
private IGamepad _gamepad;
|
||||
|
||||
private GamepadStateSnapshot _currState;
|
||||
|
||||
private GamepadStateSnapshot _prevState;
|
||||
|
||||
private JoystickButtonDetector _detector;
|
||||
|
@ -35,7 +34,7 @@ namespace Ryujinx.Input.Assigner
|
|||
{
|
||||
_currState = _gamepad.GetStateSnapshot();
|
||||
_prevState = _currState;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ReadInput()
|
||||
|
@ -71,6 +70,15 @@ namespace Ryujinx.Input.Assigner
|
|||
return "";
|
||||
}
|
||||
|
||||
public IEnumerable<PressedButton> GetPressedButtons()
|
||||
{
|
||||
IEnumerable<GamepadButtonInputId> pressedButtons = _detector.GetPressedButtons();
|
||||
|
||||
return _forStick
|
||||
? pressedButtons.Select(x => new PressedButton((StickInputId)x))
|
||||
: pressedButtons.Select(x => new PressedButton(x));
|
||||
}
|
||||
|
||||
private void CollectButtonStats()
|
||||
{
|
||||
if (_forStick)
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Input.Assigner
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -32,5 +34,11 @@ namespace Ryujinx.Input.Assigner
|
|||
/// </summary>
|
||||
/// <returns>The pressed button that was read</returns>
|
||||
string GetPressedButton();
|
||||
|
||||
/// <summary>
|
||||
/// Get the pressed button that was read in <see cref="ReadInput"/> by the button assigner.
|
||||
/// </summary>
|
||||
/// <returns>The pressed button that was read</returns>
|
||||
IEnumerable<PressedButton> GetPressedButtons();
|
||||
}
|
||||
}
|
|
@ -1,3 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Ryujinx.Input.Assigner
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -5,13 +8,15 @@ namespace Ryujinx.Input.Assigner
|
|||
/// </summary>
|
||||
public class KeyboardKeyAssigner : IButtonAssigner
|
||||
{
|
||||
private IKeyboard _keyboard;
|
||||
private readonly IKeyboard _keyboard;
|
||||
private readonly bool _allowModifiers;
|
||||
|
||||
private KeyboardStateSnapshot _keyboardState;
|
||||
|
||||
public KeyboardKeyAssigner(IKeyboard keyboard)
|
||||
public KeyboardKeyAssigner(IKeyboard keyboard, bool allowModifiers = false)
|
||||
{
|
||||
_keyboard = keyboard;
|
||||
_allowModifiers = allowModifiers;
|
||||
}
|
||||
|
||||
public void Initialize() { }
|
||||
|
@ -23,7 +28,38 @@ namespace Ryujinx.Input.Assigner
|
|||
|
||||
public bool HasAnyButtonPressed()
|
||||
{
|
||||
return GetPressedButton().Length != 0;
|
||||
for (Key key = Key.Unknown; key < Key.Count; key++)
|
||||
{
|
||||
// If modifiers are allowed, we should wait until a non-modifier key
|
||||
// is pressed and return the full combo.
|
||||
if (_allowModifiers && IsModifierKey(key))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_keyboardState.IsPressed(key))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool IsModifierKey(Key key)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case Key.AltLeft:
|
||||
case Key.AltRight:
|
||||
case Key.ControlLeft:
|
||||
case Key.ControlRight:
|
||||
case Key.ShiftLeft:
|
||||
case Key.ShiftRight:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool ShouldCancel()
|
||||
|
@ -46,5 +82,25 @@ namespace Ryujinx.Input.Assigner
|
|||
|
||||
return !ShouldCancel() ? keyPressed : "";
|
||||
}
|
||||
|
||||
public IEnumerable<PressedButton> GetPressedButtons()
|
||||
{
|
||||
if (ShouldCancel())
|
||||
{
|
||||
return Enumerable.Empty<PressedButton>();
|
||||
}
|
||||
|
||||
List<PressedButton> pressedKeys = new List<PressedButton>();
|
||||
|
||||
for (Key key = Key.Unknown; key < Key.Count; key++)
|
||||
{
|
||||
if (_keyboardState.IsPressed(key))
|
||||
{
|
||||
pressedKeys.Add(new PressedButton(key));
|
||||
}
|
||||
}
|
||||
|
||||
return pressedKeys;
|
||||
}
|
||||
}
|
||||
}
|
72
Ryujinx.Input/Assigner/MultiButtonAssigner.cs
Normal file
72
Ryujinx.Input/Assigner/MultiButtonAssigner.cs
Normal file
|
@ -0,0 +1,72 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Ryujinx.Input.Assigner
|
||||
{
|
||||
/// <summary>
|
||||
/// Assigner for buttons from multiple input devices.
|
||||
/// </summary>
|
||||
public class MultiButtonAssigner : IButtonAssigner
|
||||
{
|
||||
private readonly IEnumerable<IButtonAssigner> _assigners;
|
||||
|
||||
public MultiButtonAssigner(IEnumerable<IButtonAssigner> assigners)
|
||||
{
|
||||
_assigners = assigners;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
foreach (IButtonAssigner assigner in _assigners)
|
||||
{
|
||||
assigner.Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
public void ReadInput()
|
||||
{
|
||||
foreach (IButtonAssigner assigner in _assigners)
|
||||
{
|
||||
assigner.ReadInput();
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasAnyButtonPressed()
|
||||
{
|
||||
return _assigners.Any(x => x.HasAnyButtonPressed());
|
||||
}
|
||||
|
||||
public bool ShouldCancel()
|
||||
{
|
||||
return _assigners.All(x => x.ShouldCancel());
|
||||
}
|
||||
|
||||
public string GetPressedButton()
|
||||
{
|
||||
foreach (IButtonAssigner assigner in _assigners)
|
||||
{
|
||||
string pressedButton = assigner.GetPressedButton();
|
||||
|
||||
if (!string.IsNullOrEmpty(pressedButton))
|
||||
{
|
||||
return pressedButton;
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
public IEnumerable<PressedButton> GetPressedButtons()
|
||||
{
|
||||
foreach (IButtonAssigner assigner in _assigners)
|
||||
{
|
||||
if (assigner.HasAnyButtonPressed())
|
||||
{
|
||||
return assigner.GetPressedButtons();
|
||||
}
|
||||
}
|
||||
|
||||
return Enumerable.Empty<PressedButton>();
|
||||
}
|
||||
}
|
||||
}
|
55
Ryujinx.Input/Assigner/PressedButton.cs
Normal file
55
Ryujinx.Input/Assigner/PressedButton.cs
Normal file
|
@ -0,0 +1,55 @@
|
|||
namespace Ryujinx.Input.Assigner
|
||||
{
|
||||
public struct PressedButton
|
||||
{
|
||||
public PressedButtonType Type { get; }
|
||||
|
||||
private readonly byte _value;
|
||||
|
||||
internal PressedButton(PressedButtonType type)
|
||||
{
|
||||
Type = type;
|
||||
}
|
||||
|
||||
internal PressedButton(Key key) : this(PressedButtonType.Key)
|
||||
{
|
||||
_value = (byte)key;
|
||||
}
|
||||
|
||||
internal PressedButton(GamepadButtonInputId button) : this(PressedButtonType.Button)
|
||||
{
|
||||
_value = (byte)button;
|
||||
}
|
||||
|
||||
internal PressedButton(StickInputId stick) : this(PressedButtonType.Stick)
|
||||
{
|
||||
_value = (byte)stick;
|
||||
}
|
||||
|
||||
public Key AsKey()
|
||||
{
|
||||
return (Key)_value;
|
||||
}
|
||||
|
||||
public GamepadButtonInputId AsGamepadButtonInputId()
|
||||
{
|
||||
return (GamepadButtonInputId)_value;
|
||||
}
|
||||
|
||||
public StickInputId AsStickInputId()
|
||||
{
|
||||
return (StickInputId)_value;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Type switch
|
||||
{
|
||||
PressedButtonType.Key => AsKey().ToString(),
|
||||
PressedButtonType.Button => AsGamepadButtonInputId().ToString(),
|
||||
PressedButtonType.Stick => AsStickInputId().ToString(),
|
||||
_ => string.Empty
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
10
Ryujinx.Input/Assigner/PressedButtonType.cs
Normal file
10
Ryujinx.Input/Assigner/PressedButtonType.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
namespace Ryujinx.Input.Assigner
|
||||
{
|
||||
public enum PressedButtonType : byte
|
||||
{
|
||||
None,
|
||||
Key,
|
||||
Button,
|
||||
Stick
|
||||
}
|
||||
}
|
|
@ -21,8 +21,8 @@ namespace Ryujinx.Input
|
|||
|
||||
/// <summary>
|
||||
/// Motion
|
||||
/// <remarks>Also named sixaxis</remarks>
|
||||
/// </summary>
|
||||
/// <remarks>Also named sixaxis</remarks>
|
||||
Motion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/// <summary>
|
||||
/// Represent a key from a keyboard.
|
||||
/// </summary>
|
||||
public enum Key
|
||||
public enum Key : byte
|
||||
{
|
||||
Unknown,
|
||||
ShiftLeft,
|
||||
|
|
|
@ -716,15 +716,15 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||
Hid.EnableMouse.Value = false;
|
||||
Hid.Hotkeys.Value = new KeyboardHotkeys
|
||||
{
|
||||
ToggleVsync = Key.F1,
|
||||
ToggleMute = Key.F2,
|
||||
Screenshot = Key.F8,
|
||||
ShowUi = Key.F4,
|
||||
Pause = Key.F5,
|
||||
ResScaleUp = Key.Unbound,
|
||||
ResScaleDown = Key.Unbound,
|
||||
VolumeUp = Key.Unbound,
|
||||
VolumeDown = Key.Unbound
|
||||
ToggleVsync = new Hotkey(Key.F1),
|
||||
ToggleMute = new Hotkey(Key.F2),
|
||||
Screenshot = new Hotkey(Key.F8),
|
||||
ShowUi = new Hotkey(Key.F4),
|
||||
Pause = new Hotkey(Key.F5),
|
||||
ResScaleUp = new Hotkey(Key.Unbound),
|
||||
ResScaleDown = new Hotkey(Key.Unbound),
|
||||
VolumeUp = new Hotkey(Key.Unbound),
|
||||
VolumeDown = new Hotkey(Key.Unbound)
|
||||
};
|
||||
Hid.InputConfig.Value = new List<InputConfig>
|
||||
{
|
||||
|
@ -854,7 +854,7 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||
|
||||
configurationFileFormat.Hotkeys = new KeyboardHotkeys
|
||||
{
|
||||
ToggleVsync = Key.F1
|
||||
ToggleVsync = new Hotkey(Key.F1)
|
||||
};
|
||||
|
||||
configurationFileUpdated = true;
|
||||
|
@ -1035,8 +1035,8 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||
|
||||
configurationFileFormat.Hotkeys = new KeyboardHotkeys
|
||||
{
|
||||
ToggleVsync = Key.F1,
|
||||
Screenshot = Key.F8
|
||||
ToggleVsync = new Hotkey(Key.F1),
|
||||
Screenshot = new Hotkey(Key.F8)
|
||||
};
|
||||
|
||||
configurationFileUpdated = true;
|
||||
|
@ -1048,9 +1048,9 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||
|
||||
configurationFileFormat.Hotkeys = new KeyboardHotkeys
|
||||
{
|
||||
ToggleVsync = Key.F1,
|
||||
Screenshot = Key.F8,
|
||||
ShowUi = Key.F4
|
||||
ToggleVsync = new Hotkey(Key.F1),
|
||||
Screenshot = new Hotkey(Key.F8),
|
||||
ShowUi = new Hotkey(Key.F4)
|
||||
};
|
||||
|
||||
configurationFileUpdated = true;
|
||||
|
@ -1094,7 +1094,7 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||
ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync,
|
||||
Screenshot = configurationFileFormat.Hotkeys.Screenshot,
|
||||
ShowUi = configurationFileFormat.Hotkeys.ShowUi,
|
||||
Pause = Key.F5
|
||||
Pause = new Hotkey(Key.F5)
|
||||
};
|
||||
|
||||
configurationFileUpdated = true;
|
||||
|
@ -1110,7 +1110,7 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||
Screenshot = configurationFileFormat.Hotkeys.Screenshot,
|
||||
ShowUi = configurationFileFormat.Hotkeys.ShowUi,
|
||||
Pause = configurationFileFormat.Hotkeys.Pause,
|
||||
ToggleMute = Key.F2
|
||||
ToggleMute = new Hotkey(Key.F2)
|
||||
};
|
||||
|
||||
configurationFileFormat.AudioVolume = 1;
|
||||
|
@ -1185,8 +1185,8 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||
ShowUi = configurationFileFormat.Hotkeys.ShowUi,
|
||||
Pause = configurationFileFormat.Hotkeys.Pause,
|
||||
ToggleMute = configurationFileFormat.Hotkeys.ToggleMute,
|
||||
ResScaleUp = Key.Unbound,
|
||||
ResScaleDown = Key.Unbound
|
||||
ResScaleUp = new Hotkey(Key.Unbound),
|
||||
ResScaleDown = new Hotkey(Key.Unbound)
|
||||
};
|
||||
|
||||
configurationFileUpdated = true;
|
||||
|
@ -1216,8 +1216,8 @@ namespace Ryujinx.Ui.Common.Configuration
|
|||
ToggleMute = configurationFileFormat.Hotkeys.ToggleMute,
|
||||
ResScaleUp = configurationFileFormat.Hotkeys.ResScaleUp,
|
||||
ResScaleDown = configurationFileFormat.Hotkeys.ResScaleDown,
|
||||
VolumeUp = Key.Unbound,
|
||||
VolumeDown = Key.Unbound
|
||||
VolumeUp = new Hotkey(Key.Unbound),
|
||||
VolumeDown = new Hotkey(Key.Unbound)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -731,47 +731,47 @@ namespace Ryujinx.Ui
|
|||
{
|
||||
KeyboardHotkeyState state = KeyboardHotkeyState.None;
|
||||
|
||||
if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ToggleVsync))
|
||||
if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ToggleVsync.Key))
|
||||
{
|
||||
state |= KeyboardHotkeyState.ToggleVSync;
|
||||
}
|
||||
|
||||
if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Screenshot))
|
||||
if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Screenshot.Key))
|
||||
{
|
||||
state |= KeyboardHotkeyState.Screenshot;
|
||||
}
|
||||
|
||||
if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ShowUi))
|
||||
if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ShowUi.Key))
|
||||
{
|
||||
state |= KeyboardHotkeyState.ShowUi;
|
||||
}
|
||||
|
||||
if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Pause))
|
||||
if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Pause.Key))
|
||||
{
|
||||
state |= KeyboardHotkeyState.Pause;
|
||||
}
|
||||
|
||||
if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ToggleMute))
|
||||
if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ToggleMute.Key))
|
||||
{
|
||||
state |= KeyboardHotkeyState.ToggleMute;
|
||||
}
|
||||
|
||||
if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ResScaleUp))
|
||||
if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ResScaleUp.Key))
|
||||
{
|
||||
state |= KeyboardHotkeyState.ResScaleUp;
|
||||
}
|
||||
|
||||
if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ResScaleDown))
|
||||
if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ResScaleDown.Key))
|
||||
{
|
||||
state |= KeyboardHotkeyState.ResScaleDown;
|
||||
}
|
||||
|
||||
if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.VolumeUp))
|
||||
if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.VolumeUp.Key))
|
||||
{
|
||||
state |= KeyboardHotkeyState.VolumeUp;
|
||||
}
|
||||
|
||||
if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.VolumeDown))
|
||||
if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.VolumeDown.Key))
|
||||
{
|
||||
state |= KeyboardHotkeyState.VolumeDown;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue