Fix Hotkeys

This commit is contained in:
Isaac Marovitz 2024-02-23 19:00:09 -05:00 committed by Isaac Marovitz
parent b7dcfb40b8
commit 6db29d6c20
7 changed files with 248 additions and 71 deletions

View file

@ -0,0 +1,133 @@
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Common.Configuration.Hid;
namespace Ryujinx.Ava.UI.Models.Input
{
public class HotkeysConfig : BaseModel
{
private Key _toggleVsync;
public Key ToggleVsync
{
get => _toggleVsync;
set
{
_toggleVsync = value;
OnPropertyChanged();
}
}
private Key _screenshot;
public Key Screenshot {
get => _screenshot;
set
{
_screenshot = value;
OnPropertyChanged();
}
}
private Key _showUI;
public Key ShowUI {
get => _showUI;
set
{
_showUI = value;
OnPropertyChanged();
}
}
private Key _pause;
public Key Pause {
get => _pause;
set
{
_pause = value;
OnPropertyChanged();
}
}
private Key _toggleMute;
public Key ToggleMute {
get => _toggleMute;
set
{
_toggleMute = value;
OnPropertyChanged();
}
}
private Key _resScaleUp;
public Key ResScaleUp {
get => _resScaleUp;
set
{
_resScaleUp = value;
OnPropertyChanged();
}
}
private Key _resScaleDown;
public Key ResScaleDown {
get => _resScaleDown;
set
{
_resScaleDown = value;
OnPropertyChanged();
}
}
private Key _volumeUp;
public Key VolumeUp {
get => _volumeUp;
set
{
_volumeUp = value;
OnPropertyChanged();
}
}
private Key _volumeDown;
public Key VolumeDown {
get => _volumeDown;
set
{
_volumeDown = value;
OnPropertyChanged();
}
}
public HotkeysConfig(KeyboardHotkeys config)
{
if (config != null)
{
ToggleVsync = config.ToggleVsync;
Screenshot = config.Screenshot;
ShowUI = config.ShowUI;
Pause = config.Pause;
ToggleMute = config.ToggleMute;
ResScaleUp = config.ResScaleUp;
ResScaleDown = config.ResScaleDown;
VolumeUp = config.VolumeUp;
VolumeDown = config.VolumeDown;
}
}
public KeyboardHotkeys GetConfig()
{
var config = new KeyboardHotkeys
{
ToggleVsync = ToggleVsync,
Screenshot = Screenshot,
ShowUI = ShowUI,
Pause = Pause,
ToggleMute = ToggleMute,
ResScaleUp = ResScaleUp,
ResScaleDown = ResScaleDown,
VolumeUp = VolumeUp,
VolumeDown = VolumeDown
};
return config;
}
}
}

View file

@ -7,9 +7,9 @@ using Ryujinx.Audio.Backends.SDL2;
using Ryujinx.Audio.Backends.SoundIo;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Models.Input;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Configuration.Multiplayer;
using Ryujinx.Common.GraphicsDriver;
using Ryujinx.Common.Logging;
@ -46,7 +46,6 @@ namespace Ryujinx.Ava.UI.ViewModels
private bool _isVulkanAvailable = true;
private bool _directoryChanged;
private readonly List<string> _gpuIds = new();
private KeyboardHotkeys _keyboardHotkeys;
private int _graphicsBackendIndex;
private int _scalingFilter;
private int _scalingFilterLevel;
@ -242,16 +241,7 @@ namespace Ryujinx.Ava.UI.ViewModels
get => new(Enum.GetNames<MultiplayerMode>());
}
public KeyboardHotkeys KeyboardHotkeys
{
get => _keyboardHotkeys;
set
{
_keyboardHotkeys = value;
OnPropertyChanged();
}
}
public HotkeysConfig KeyboardHotkeys { get; set; }
public int NetworkInterfaceIndex
{
@ -418,7 +408,7 @@ namespace Ryujinx.Ava.UI.ViewModels
EnableMouse = config.Hid.EnableMouse;
// Keyboard Hotkeys
KeyboardHotkeys = config.Hid.Hotkeys.Value;
KeyboardHotkeys = new HotkeysConfig(config.Hid.Hotkeys.Value);
// System
Region = (int)config.System.Region.Value;
@ -505,7 +495,7 @@ namespace Ryujinx.Ava.UI.ViewModels
config.Hid.EnableMouse.Value = EnableMouse;
// Keyboard Hotkeys
config.Hid.Hotkeys.Value = KeyboardHotkeys;
config.Hid.Hotkeys.Value = KeyboardHotkeys.GetConfig();
// System
config.System.Region.Value = (Region)Region;

View file

@ -52,7 +52,7 @@ namespace Ryujinx.Ava.UI.Views.Input
bool isStick = button.Tag != null && button.Tag.ToString() == "stick";
if (_currentAssigner == null && (bool)button.IsChecked)
if (_currentAssigner == null)
{
_currentAssigner = new ButtonKeyAssigner(button);
@ -149,8 +149,6 @@ namespace Ryujinx.Ava.UI.Views.Input
{
if (_currentAssigner != null)
{
ToggleButton oldButton = _currentAssigner.ToggledButton;
_currentAssigner.Cancel();
_currentAssigner = null;
button.IsChecked = false;

View file

@ -49,9 +49,7 @@ namespace Ryujinx.Ava.UI.Views.Input
return;
}
bool isStick = button.Tag != null && button.Tag.ToString() == "stick";
if (_currentAssigner == null && (bool)button.IsChecked)
if (_currentAssigner == null)
{
_currentAssigner = new ButtonKeyAssigner(button);
@ -60,7 +58,7 @@ namespace Ryujinx.Ava.UI.Views.Input
PointerPressed += MouseClick;
IKeyboard keyboard = (IKeyboard)(DataContext as KeyboardInputViewModel).parentModel.AvaloniaKeyboardDriver.GetGamepad("0"); // Open Avalonia keyboard for cancel operations.
IButtonAssigner assigner = CreateButtonAssigner(isStick);
IButtonAssigner assigner = CreateButtonAssigner();
_currentAssigner.ButtonAssigned += (sender, e) =>
{
@ -166,8 +164,6 @@ namespace Ryujinx.Ava.UI.Views.Input
{
if (_currentAssigner != null)
{
ToggleButton oldButton = _currentAssigner.ToggledButton;
_currentAssigner.Cancel();
_currentAssigner = null;
button.IsChecked = false;
@ -191,7 +187,7 @@ namespace Ryujinx.Ava.UI.Views.Input
PointerPressed -= MouseClick;
}
private IButtonAssigner CreateButtonAssigner(bool forStick)
private IButtonAssigner CreateButtonAssigner()
{
IButtonAssigner assigner;

View file

@ -9,6 +9,7 @@
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
mc:Ignorable="d"
x:DataType="viewModels:SettingsViewModel"
x:CompileBindings="True"
Focusable="True">
<Design.DataContext>
<viewModels:SettingsViewModel />
@ -50,56 +51,56 @@
Text="{locale:Locale SettingsTabHotkeysHotkeys}" />
<StackPanel>
<TextBlock Text="{locale:Locale SettingsTabHotkeysToggleVsyncHotkey}" />
<ToggleButton>
<TextBlock Text="{Binding KeyboardHotkeys.ToggleVsync, Mode=TwoWay, Converter={StaticResource Key}}" />
<ToggleButton Name="ToggleVsync">
<TextBlock Text="{Binding KeyboardHotkeys.ToggleVsync, Converter={StaticResource Key}}" />
</ToggleButton>
</StackPanel>
<StackPanel>
<TextBlock Text="{locale:Locale SettingsTabHotkeysScreenshotHotkey}" />
<ToggleButton>
<TextBlock Text="{Binding KeyboardHotkeys.Screenshot, Mode=TwoWay, Converter={StaticResource Key}}" />
<ToggleButton Name="Screenshot">
<TextBlock Text="{Binding KeyboardHotkeys.Screenshot, Converter={StaticResource Key}}" />
</ToggleButton>
</StackPanel>
<StackPanel>
<TextBlock Text="{locale:Locale SettingsTabHotkeysShowUiHotkey}" />
<ToggleButton>
<TextBlock Text="{Binding KeyboardHotkeys.ShowUI, Mode=TwoWay, Converter={StaticResource Key}}" />
<ToggleButton Name="ShowUI">
<TextBlock Text="{Binding KeyboardHotkeys.ShowUI, Converter={StaticResource Key}}" />
</ToggleButton>
</StackPanel>
<StackPanel>
<TextBlock Text="{locale:Locale SettingsTabHotkeysPauseHotkey}" />
<ToggleButton>
<TextBlock Text="{Binding KeyboardHotkeys.Pause, Mode=TwoWay, Converter={StaticResource Key}}" />
<ToggleButton Name="Pause">
<TextBlock Text="{Binding KeyboardHotkeys.Pause, Converter={StaticResource Key}}" />
</ToggleButton>
</StackPanel>
<StackPanel>
<TextBlock Text="{locale:Locale SettingsTabHotkeysToggleMuteHotkey}" />
<ToggleButton>
<TextBlock Text="{Binding KeyboardHotkeys.ToggleMute, Mode=TwoWay, Converter={StaticResource Key}}" />
<ToggleButton Name="ToggleMute">
<TextBlock Text="{Binding KeyboardHotkeys.ToggleMute, Converter={StaticResource Key}}" />
</ToggleButton>
</StackPanel>
<StackPanel>
<TextBlock Text="{locale:Locale SettingsTabHotkeysResScaleUpHotkey}" />
<ToggleButton>
<TextBlock Text="{Binding KeyboardHotkeys.ResScaleUp, Mode=TwoWay, Converter={StaticResource Key}}" />
<ToggleButton Name="ResScaleUp">
<TextBlock Text="{Binding KeyboardHotkeys.ResScaleUp, Converter={StaticResource Key}}" />
</ToggleButton>
</StackPanel>
<StackPanel>
<TextBlock Text="{locale:Locale SettingsTabHotkeysResScaleDownHotkey}" />
<ToggleButton>
<TextBlock Text="{Binding KeyboardHotkeys.ResScaleDown, Mode=TwoWay, Converter={StaticResource Key}}" />
<ToggleButton Name="ResScaleDown">
<TextBlock Text="{Binding KeyboardHotkeys.ResScaleDown, Converter={StaticResource Key}}" />
</ToggleButton>
</StackPanel>
<StackPanel>
<TextBlock Text="{locale:Locale SettingsTabHotkeysVolumeUpHotkey}" />
<ToggleButton>
<TextBlock Text="{Binding KeyboardHotkeys.VolumeUp, Mode=TwoWay, Converter={StaticResource Key}}" />
<ToggleButton Name="VolumeUp">
<TextBlock Text="{Binding KeyboardHotkeys.VolumeUp, Converter={StaticResource Key}}" />
</ToggleButton>
</StackPanel>
<StackPanel>
<TextBlock Text="{locale:Locale SettingsTabHotkeysVolumeDownHotkey}" />
<ToggleButton>
<TextBlock Text="{Binding KeyboardHotkeys.VolumeDown, Mode=TwoWay, Converter={StaticResource Key}}" />
<ToggleButton Name="VolumeDown">
<TextBlock Text="{Binding KeyboardHotkeys.VolumeDown, Converter={StaticResource Key}}" />
</ToggleButton>
</StackPanel>
</StackPanel>

View file

@ -2,8 +2,10 @@ using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.LogicalTree;
using Ryujinx.Ava.Input;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Input;
using Ryujinx.Input.Assigner;
@ -17,9 +19,27 @@ namespace Ryujinx.Ava.UI.Views.Settings
public SettingsHotkeysView()
{
InitializeComponent();
foreach (ILogical visual in SettingButtons.GetLogicalDescendants())
{
if (visual is ToggleButton button and not CheckBox)
{
button.IsCheckedChanged += Button_IsCheckedChanged;
}
}
_avaloniaKeyboardDriver = new AvaloniaKeyboardDriver(this);
}
protected override void OnPointerReleased(PointerReleasedEventArgs e)
{
base.OnPointerReleased(e);
if (_currentAssigner != null && _currentAssigner.ToggledButton != null && !_currentAssigner.ToggledButton.IsPointerOver)
{
_currentAssigner.Cancel();
}
}
private void MouseClick(object sender, PointerPressedEventArgs e)
{
bool shouldUnbind = e.GetCurrentPoint(this).Properties.IsMiddleButtonPressed;
@ -29,16 +49,18 @@ namespace Ryujinx.Ava.UI.Views.Settings
PointerPressed -= MouseClick;
}
private void Button_Checked(object sender, RoutedEventArgs e)
private void Button_IsCheckedChanged(object sender, RoutedEventArgs e)
{
if (sender is ToggleButton button)
{
if ((bool)button.IsChecked)
{
if (_currentAssigner != null && button == _currentAssigner.ToggledButton)
{
return;
}
if (_currentAssigner == null && button.IsChecked != null && (bool)button.IsChecked)
if (_currentAssigner == null)
{
_currentAssigner = new ButtonKeyAssigner(button);
@ -46,36 +68,75 @@ namespace Ryujinx.Ava.UI.Views.Settings
PointerPressed += MouseClick;
var keyboard = (IKeyboard)_avaloniaKeyboardDriver.GetGamepad(_avaloniaKeyboardDriver.GamepadsIds[0]);
var keyboard = (IKeyboard)_avaloniaKeyboardDriver.GetGamepad("0");
IButtonAssigner assigner = new KeyboardKeyAssigner(keyboard);
_currentAssigner.GetInputAndAssign(assigner);
_currentAssigner.ButtonAssigned += (sender, e) =>
{
if (e.ButtonValue.HasValue)
{
var viewModel = (DataContext) as SettingsViewModel;
var buttonValue = e.ButtonValue.Value;
switch (button.Name)
{
case "ToggleVsync":
viewModel.KeyboardHotkeys.ToggleVsync = buttonValue.AsKey();
break;
case "Screenshot":
viewModel.KeyboardHotkeys.Screenshot = buttonValue.AsKey();
break;
case "ShowUI":
viewModel.KeyboardHotkeys.ShowUI = buttonValue.AsKey();
break;
case "Pause":
viewModel.KeyboardHotkeys.Pause = buttonValue.AsKey();
break;
case "ToggleMute":
viewModel.KeyboardHotkeys.ToggleMute = buttonValue.AsKey();
break;
case "ResScaleUp":
viewModel.KeyboardHotkeys.ResScaleUp = buttonValue.AsKey();
break;
case "ResScaleDown":
viewModel.KeyboardHotkeys.ResScaleDown = buttonValue.AsKey();
break;
case "VolumeUp":
viewModel.KeyboardHotkeys.VolumeUp = buttonValue.AsKey();
break;
case "VolumeDown":
viewModel.KeyboardHotkeys.VolumeDown = buttonValue.AsKey();
break;
}
}
};
_currentAssigner.GetInputAndAssign(assigner, keyboard);
}
else
{
if (_currentAssigner != null)
{
ToggleButton oldButton = _currentAssigner.ToggledButton;
_currentAssigner.Cancel();
_currentAssigner = null;
button.IsChecked = false;
}
}
}
}
private void Button_Unchecked(object sender, RoutedEventArgs e)
else
{
_currentAssigner?.Cancel();
_currentAssigner = null;
}
}
}
public void Dispose()
{
_currentAssigner?.Cancel();
_currentAssigner = null;
_avaloniaKeyboardDriver.Dispose();
}
}
}

View file

@ -1,7 +1,5 @@
namespace Ryujinx.Common.Configuration.Hid
{
// NOTE: Please don't change this to struct.
// This breaks Avalonia's TwoWay binding, which makes us unable to save new KeyboardHotkeys.
public class KeyboardHotkeys
{
public Key ToggleVsync { get; set; }