From 638be5f296bf52943da4366699d33f1e8656e00c Mon Sep 17 00:00:00 2001
From: TSR Berry <20988865+TSRBerry@users.noreply.github.com>
Date: Sat, 21 Oct 2023 15:19:21 +0200
Subject: Revert "Ava UI: Input Menu Refactor (#4998)"

This reverts commit 49b37550cae6b3c69f59a9c7a44b17e3c12a813b.

This currently breaks the GTK GUI.
---
 src/Ryujinx.Ava/Assets/Locales/en_US.json          |  99 ---
 src/Ryujinx.Ava/Assets/Styles/Styles.xaml          |   5 +-
 src/Ryujinx.Ava/UI/Helpers/ButtonKeyAssigner.cs    |  28 +-
 src/Ryujinx.Ava/UI/Helpers/KeyValueConverter.cs    | 157 +---
 .../UI/Models/Input/ControllerInputConfig.cs       | 580 -------------
 .../UI/Models/Input/KeyboardInputConfig.cs         | 422 ----------
 src/Ryujinx.Ava/UI/Models/InputConfiguration.cs    | 456 +++++++++++
 .../UI/ViewModels/ControllerInputViewModel.cs      | 897 +++++++++++++++++++++
 .../ViewModels/Input/ControllerInputViewModel.cs   |  84 --
 .../UI/ViewModels/Input/InputViewModel.cs          | 890 --------------------
 .../UI/ViewModels/Input/KeyboardInputViewModel.cs  |  73 --
 .../UI/ViewModels/Input/MotionInputViewModel.cs    |  93 ---
 .../UI/ViewModels/Input/RumbleInputViewModel.cs    |  27 -
 .../UI/ViewModels/MotionInputViewModel.cs          |  93 +++
 .../UI/ViewModels/RumbleInputViewModel.cs          |  27 +
 .../UI/Views/Input/ControllerInputView.axaml       | 616 +++++++++++---
 .../UI/Views/Input/ControllerInputView.axaml.cs    | 160 ++--
 src/Ryujinx.Ava/UI/Views/Input/InputView.axaml     | 225 ------
 src/Ryujinx.Ava/UI/Views/Input/InputView.axaml.cs  |  61 --
 .../UI/Views/Input/KeyboardInputView.axaml         | 675 ----------------
 .../UI/Views/Input/KeyboardInputView.axaml.cs      | 210 -----
 .../UI/Views/Input/MotionInputView.axaml           |   2 +-
 .../UI/Views/Input/MotionInputView.axaml.cs        |   8 +-
 .../UI/Views/Input/RumbleInputView.axaml           |   2 +-
 .../UI/Views/Input/RumbleInputView.axaml.cs        |   8 +-
 .../UI/Views/Settings/SettingsInputView.axaml      |   4 +-
 .../UI/Views/Settings/SettingsInputView.axaml.cs   |   2 +-
 src/Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs |   2 +-
 .../Assigner/GamepadButtonAssigner.cs              |   6 +-
 src/Ryujinx.Input/Assigner/IButtonAssigner.cs      |   2 +-
 src/Ryujinx.Input/Assigner/KeyboardKeyAssigner.cs  |  10 +-
 src/Ryujinx.Input/ButtonValue.cs                   |  48 --
 src/Ryujinx/Ui/Windows/ControllerWindow.cs         |   2 +-
 33 files changed, 2105 insertions(+), 3869 deletions(-)
 delete mode 100644 src/Ryujinx.Ava/UI/Models/Input/ControllerInputConfig.cs
 delete mode 100644 src/Ryujinx.Ava/UI/Models/Input/KeyboardInputConfig.cs
 create mode 100644 src/Ryujinx.Ava/UI/Models/InputConfiguration.cs
 create mode 100644 src/Ryujinx.Ava/UI/ViewModels/ControllerInputViewModel.cs
 delete mode 100644 src/Ryujinx.Ava/UI/ViewModels/Input/ControllerInputViewModel.cs
 delete mode 100644 src/Ryujinx.Ava/UI/ViewModels/Input/InputViewModel.cs
 delete mode 100644 src/Ryujinx.Ava/UI/ViewModels/Input/KeyboardInputViewModel.cs
 delete mode 100644 src/Ryujinx.Ava/UI/ViewModels/Input/MotionInputViewModel.cs
 delete mode 100644 src/Ryujinx.Ava/UI/ViewModels/Input/RumbleInputViewModel.cs
 create mode 100644 src/Ryujinx.Ava/UI/ViewModels/MotionInputViewModel.cs
 create mode 100644 src/Ryujinx.Ava/UI/ViewModels/RumbleInputViewModel.cs
 delete mode 100644 src/Ryujinx.Ava/UI/Views/Input/InputView.axaml
 delete mode 100644 src/Ryujinx.Ava/UI/Views/Input/InputView.axaml.cs
 delete mode 100644 src/Ryujinx.Ava/UI/Views/Input/KeyboardInputView.axaml
 delete mode 100644 src/Ryujinx.Ava/UI/Views/Input/KeyboardInputView.axaml.cs
 delete mode 100644 src/Ryujinx.Input/ButtonValue.cs

(limited to 'src')

diff --git a/src/Ryujinx.Ava/Assets/Locales/en_US.json b/src/Ryujinx.Ava/Assets/Locales/en_US.json
index fc65fe4a..a67b796b 100644
--- a/src/Ryujinx.Ava/Assets/Locales/en_US.json
+++ b/src/Ryujinx.Ava/Assets/Locales/en_US.json
@@ -263,105 +263,6 @@
   "ControllerSettingsMotionGyroDeadzone": "Gyro Deadzone:",
   "ControllerSettingsSave": "Save",
   "ControllerSettingsClose": "Close",
-  "KeyUnknown": "Unknown",
-  "KeyShiftLeft": "Shift Left",
-  "KeyShiftRight": "Shift Right",
-  "KeyControlLeft": "Control Left",
-  "KeyControlRight": "Control Right",
-  "KeyAltLeft": "Alt Left",
-  "KeyAltRight": "Alt Right",
-  "KeyOptLeft": "⌥ Left",
-  "KeyOptRight": "⌥ Right",
-  "KeyWinLeft": "⊞ Left",
-  "KeyWinRight": "⊞ Right",
-  "KeyCmdLeft": "⌘ Left",
-  "KeyCmdRight": "⌘ Right",
-  "KeyMenu": "Menu",
-  "KeyUp": "Up",
-  "KeyDown": "Down",
-  "KeyLeft": "Left",
-  "KeyRight": "Right",
-  "KeyEnter": "Enter",
-  "KeyEscape": "Escape",
-  "KeySpace": "Space",
-  "KeyTab": "Tab",
-  "KeyBackSpace": "Backspace",
-  "KeyInsert": "Insert",
-  "KeyDelete": "Delete",
-  "KeyPageUp": "Page Up",
-  "KeyPageDown": "Page Down",
-  "KeyHome": "Home",
-  "KeyEnd": "End",
-  "KeyCapsLock": "Caps Lock",
-  "KeyScrollLock": "Scroll Lock",
-  "KeyPrintScreen": "Print Screen",
-  "KeyPause": "Pause",
-  "KeyNumLock": "Num Lock",
-  "KeyClear": "Clear",
-  "KeyKeypad0": "Keypad 0",
-  "KeyKeypad1": "Keypad 1",
-  "KeyKeypad2": "Keypad 2",
-  "KeyKeypad3": "Keypad 3",
-  "KeyKeypad4": "Keypad 4",
-  "KeyKeypad5": "Keypad 5",
-  "KeyKeypad6": "Keypad 6",
-  "KeyKeypad7": "Keypad 7",
-  "KeyKeypad8": "Keypad 8",
-  "KeyKeypad9": "Keypad 9",
-  "KeyKeypadDivide": "Keypad Divide",
-  "KeyKeypadMultiply": "Keypad Multiply",
-  "KeyKeypadSubtract": "Keypad Subtract",
-  "KeyKeypadAdd": "Keypad Add",
-  "KeyKeypadDecimal": "Keypad Decimal",
-  "KeyKeypadEnter": "Keypad Enter",
-  "KeyNumber0": "0",
-  "KeyNumber1": "1",
-  "KeyNumber2": "2",
-  "KeyNumber3": "3",
-  "KeyNumber4": "4",
-  "KeyNumber5": "5",
-  "KeyNumber6": "6",
-  "KeyNumber7": "7",
-  "KeyNumber8": "8",
-  "KeyNumber9": "9",
-  "KeyTilde": "~",
-  "KeyGrave": "`",
-  "KeyMinus": "-",
-  "KeyPlus": "+",
-  "KeyBracketLeft": "[",
-  "KeyBracketRight": "]",
-  "KeySemicolon": ";",
-  "KeyQuote": "\"",
-  "KeyComma": ",",
-  "KeyPeriod": ".",
-  "KeySlash": "/",
-  "KeyBackSlash": "\\",
-  "KeyUnbound": "Unbound",
-  "GamepadLeftStick": "Left Stick Button",
-  "GamepadRightStick": "Right Stick Button",
-  "GamepadLeftShoulder": "Left Shoulder",
-  "GamepadRightShoulder": "Right Shoulder",
-  "GamepadLeftTrigger": "Left Trigger",
-  "GamepadRightTrigger": "Right Trigger",
-  "GamepadDpadUp": "Up",
-  "GamepadDpadDown": "Down",
-  "GamepadDpadLeft": "Left",
-  "GamepadDpadRight": "Right",
-  "GamepadMinus": "-",
-  "GamepadPlus": "+",
-  "GamepadGuide": "Guide",
-  "GamepadMisc1": "Misc",
-  "GamepadPaddle1": "Paddle 1",
-  "GamepadPaddle2": "Paddle 2",
-  "GamepadPaddle3": "Paddle 3",
-  "GamepadPaddle4": "Paddle 4",
-  "GamepadTouchpad": "Touchpad",
-  "GamepadSingleLeftTrigger0": "Left Trigger 0",
-  "GamepadSingleRightTrigger0": "Right Trigger 0",
-  "GamepadSingleLeftTrigger1": "Left Trigger 1",
-  "GamepadSingleRightTrigger1": "Right Trigger 1",
-  "StickLeft": "Left Stick",
-  "StickRight": "Right Stick",
   "UserProfilesSelectedUserProfile": "Selected User Profile:",
   "UserProfilesSaveProfileName": "Save Profile Name",
   "UserProfilesChangeProfileImage": "Change Profile Image",
diff --git a/src/Ryujinx.Ava/Assets/Styles/Styles.xaml b/src/Ryujinx.Ava/Assets/Styles/Styles.xaml
index b3a6f59c..f7f64be2 100644
--- a/src/Ryujinx.Ava/Assets/Styles/Styles.xaml
+++ b/src/Ryujinx.Ava/Assets/Styles/Styles.xaml
@@ -15,7 +15,8 @@
                             <MenuItem Header="Test 2" />
                             <MenuItem Header="Test 3">
                                 <MenuItem.Icon>
-                                    <CheckBox Margin="0" />
+                                    <CheckBox Margin="0"
+                                              IsChecked="{ReflectionBinding Checkbox, Mode=TwoWay}" />
                                 </MenuItem.Icon>
                             </MenuItem>
                         </MenuItem>
@@ -392,4 +393,4 @@
         <x:Double x:Key="ContentDialogMaxWidth">600</x:Double>
         <x:Double x:Key="ContentDialogMaxHeight">756</x:Double>
     </Styles.Resources>
-</Styles>
+</Styles>
\ No newline at end of file
diff --git a/src/Ryujinx.Ava/UI/Helpers/ButtonKeyAssigner.cs b/src/Ryujinx.Ava/UI/Helpers/ButtonKeyAssigner.cs
index 54e0918a..7e8ba734 100644
--- a/src/Ryujinx.Ava/UI/Helpers/ButtonKeyAssigner.cs
+++ b/src/Ryujinx.Ava/UI/Helpers/ButtonKeyAssigner.cs
@@ -1,8 +1,11 @@
+using Avalonia.Controls;
 using Avalonia.Controls.Primitives;
+using Avalonia.LogicalTree;
 using Avalonia.Threading;
 using Ryujinx.Input;
 using Ryujinx.Input.Assigner;
 using System;
+using System.Linq;
 using System.Threading.Tasks;
 
 namespace Ryujinx.Ava.UI.Helpers
@@ -12,12 +15,12 @@ namespace Ryujinx.Ava.UI.Helpers
         internal class ButtonAssignedEventArgs : EventArgs
         {
             public ToggleButton Button { get; }
-            public ButtonValue? ButtonValue { get; }
+            public bool IsAssigned { get; }
 
-            public ButtonAssignedEventArgs(ToggleButton button, ButtonValue? buttonValue)
+            public ButtonAssignedEventArgs(ToggleButton button, bool isAssigned)
             {
                 Button = button;
-                ButtonValue = buttonValue;
+                IsAssigned = isAssigned;
             }
         }
 
@@ -75,11 +78,15 @@ namespace Ryujinx.Ava.UI.Helpers
 
             await Dispatcher.UIThread.InvokeAsync(() =>
             {
-                ButtonValue? pressedButton = assigner.GetPressedButton();
+                string pressedButton = assigner.GetPressedButton();
 
                 if (_shouldUnbind)
                 {
-                    pressedButton = null;
+                    SetButtonText(ToggledButton, "Unbound");
+                }
+                else if (pressedButton != "")
+                {
+                    SetButtonText(ToggledButton, pressedButton);
                 }
 
                 _shouldUnbind = false;
@@ -87,8 +94,17 @@ namespace Ryujinx.Ava.UI.Helpers
 
                 ToggledButton.IsChecked = false;
 
-                ButtonAssigned?.Invoke(this, new ButtonAssignedEventArgs(ToggledButton, pressedButton));
+                ButtonAssigned?.Invoke(this, new ButtonAssignedEventArgs(ToggledButton, pressedButton != null));
+
+                static void SetButtonText(ToggleButton button, string text)
+                {
+                    ILogical textBlock = button.GetLogicalDescendants().First(x => x is TextBlock);
 
+                    if (textBlock != null && textBlock is TextBlock block)
+                    {
+                        block.Text = text;
+                    }
+                }
             });
         }
 
diff --git a/src/Ryujinx.Ava/UI/Helpers/KeyValueConverter.cs b/src/Ryujinx.Ava/UI/Helpers/KeyValueConverter.cs
index 1c4aa7b2..028ed6bf 100644
--- a/src/Ryujinx.Ava/UI/Helpers/KeyValueConverter.cs
+++ b/src/Ryujinx.Ava/UI/Helpers/KeyValueConverter.cs
@@ -1,9 +1,7 @@
 using Avalonia.Data.Converters;
-using Ryujinx.Ava.Common.Locale;
 using Ryujinx.Common.Configuration.Hid;
 using Ryujinx.Common.Configuration.Hid.Controller;
 using System;
-using System.Collections.Generic;
 using System.Globalization;
 
 namespace Ryujinx.Ava.UI.Helpers
@@ -12,158 +10,37 @@ namespace Ryujinx.Ava.UI.Helpers
     {
         public static KeyValueConverter Instance = new();
 
-        private static readonly Dictionary<Key, LocaleKeys> _keysMap = new()
-        {
-            { Key.Unknown, LocaleKeys.KeyUnknown },
-            { Key.ShiftLeft, LocaleKeys.KeyShiftLeft },
-            { Key.ShiftRight, LocaleKeys.KeyShiftRight },
-            { Key.ControlLeft, LocaleKeys.KeyControlLeft },
-            { Key.ControlRight, LocaleKeys.KeyControlRight },
-            { Key.AltLeft, OperatingSystem.IsMacOS() ? LocaleKeys.KeyOptLeft : LocaleKeys.KeyAltLeft },
-            { Key.AltRight, OperatingSystem.IsMacOS() ? LocaleKeys.KeyOptRight : LocaleKeys.KeyAltRight },
-            { Key.WinLeft, OperatingSystem.IsMacOS() ? LocaleKeys.KeyCmdLeft : LocaleKeys.KeyWinLeft },
-            { Key.WinRight, OperatingSystem.IsMacOS() ? LocaleKeys.KeyCmdRight : LocaleKeys.KeyWinRight },
-            { Key.Up, LocaleKeys.KeyUp },
-            { Key.Down, LocaleKeys.KeyDown },
-            { Key.Left, LocaleKeys.KeyLeft },
-            { Key.Right, LocaleKeys.KeyRight },
-            { Key.Enter, LocaleKeys.KeyEnter },
-            { Key.Escape, LocaleKeys.KeyEscape },
-            { Key.Space, LocaleKeys.KeySpace },
-            { Key.Tab, LocaleKeys.KeyTab },
-            { Key.BackSpace, LocaleKeys.KeyBackSpace },
-            { Key.Insert, LocaleKeys.KeyInsert },
-            { Key.Delete, LocaleKeys.KeyDelete },
-            { Key.PageUp, LocaleKeys.KeyPageUp },
-            { Key.PageDown, LocaleKeys.KeyPageDown },
-            { Key.Home, LocaleKeys.KeyHome },
-            { Key.End, LocaleKeys.KeyEnd },
-            { Key.CapsLock, LocaleKeys.KeyCapsLock },
-            { Key.ScrollLock, LocaleKeys.KeyScrollLock },
-            { Key.PrintScreen, LocaleKeys.KeyPrintScreen },
-            { Key.Pause, LocaleKeys.KeyPause },
-            { Key.NumLock, LocaleKeys.KeyNumLock },
-            { Key.Clear, LocaleKeys.KeyClear },
-            { Key.Keypad0, LocaleKeys.KeyKeypad0 },
-            { Key.Keypad1, LocaleKeys.KeyKeypad1 },
-            { Key.Keypad2, LocaleKeys.KeyKeypad2 },
-            { Key.Keypad3, LocaleKeys.KeyKeypad3 },
-            { Key.Keypad4, LocaleKeys.KeyKeypad4 },
-            { Key.Keypad5, LocaleKeys.KeyKeypad5 },
-            { Key.Keypad6, LocaleKeys.KeyKeypad6 },
-            { Key.Keypad7, LocaleKeys.KeyKeypad7 },
-            { Key.Keypad8, LocaleKeys.KeyKeypad8 },
-            { Key.Keypad9, LocaleKeys.KeyKeypad9 },
-            { Key.KeypadDivide, LocaleKeys.KeyKeypadDivide },
-            { Key.KeypadMultiply, LocaleKeys.KeyKeypadMultiply },
-            { Key.KeypadSubtract, LocaleKeys.KeyKeypadSubtract },
-            { Key.KeypadAdd, LocaleKeys.KeyKeypadAdd },
-            { Key.KeypadDecimal, LocaleKeys.KeyKeypadDecimal },
-            { Key.KeypadEnter, LocaleKeys.KeyKeypadEnter },
-            { Key.Number0, LocaleKeys.KeyNumber0 },
-            { Key.Number1, LocaleKeys.KeyNumber1 },
-            { Key.Number2, LocaleKeys.KeyNumber2 },
-            { Key.Number3, LocaleKeys.KeyNumber3 },
-            { Key.Number4, LocaleKeys.KeyNumber4 },
-            { Key.Number5, LocaleKeys.KeyNumber5 },
-            { Key.Number6, LocaleKeys.KeyNumber6 },
-            { Key.Number7, LocaleKeys.KeyNumber7 },
-            { Key.Number8, LocaleKeys.KeyNumber8 },
-            { Key.Number9, LocaleKeys.KeyNumber9 },
-            { Key.Tilde, LocaleKeys.KeyTilde },
-            { Key.Grave, LocaleKeys.KeyGrave },
-            { Key.Minus, LocaleKeys.KeyMinus },
-            { Key.Plus, LocaleKeys.KeyPlus },
-            { Key.BracketLeft, LocaleKeys.KeyBracketLeft },
-            { Key.BracketRight, LocaleKeys.KeyBracketRight },
-            { Key.Semicolon, LocaleKeys.KeySemicolon },
-            { Key.Quote, LocaleKeys.KeyQuote },
-            { Key.Comma, LocaleKeys.KeyComma },
-            { Key.Period, LocaleKeys.KeyPeriod },
-            { Key.Slash, LocaleKeys.KeySlash },
-            { Key.BackSlash, LocaleKeys.KeyBackSlash },
-            { Key.Unbound, LocaleKeys.KeyUnbound },
-        };
-
-        private static readonly Dictionary<GamepadInputId, LocaleKeys> _gamepadInputIdMap = new()
+        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
         {
-            { GamepadInputId.LeftStick, LocaleKeys.GamepadLeftStick },
-            { GamepadInputId.RightStick, LocaleKeys.GamepadRightStick },
-            { GamepadInputId.LeftShoulder, LocaleKeys.GamepadLeftShoulder },
-            { GamepadInputId.RightShoulder, LocaleKeys.GamepadRightShoulder },
-            { GamepadInputId.LeftTrigger, LocaleKeys.GamepadLeftTrigger },
-            { GamepadInputId.RightTrigger, LocaleKeys.GamepadRightTrigger },
-            { GamepadInputId.DpadUp, LocaleKeys.GamepadDpadUp},
-            { GamepadInputId.DpadDown, LocaleKeys.GamepadDpadDown},
-            { GamepadInputId.DpadLeft, LocaleKeys.GamepadDpadLeft},
-            { GamepadInputId.DpadRight, LocaleKeys.GamepadDpadRight},
-            { GamepadInputId.Minus, LocaleKeys.GamepadMinus},
-            { GamepadInputId.Plus, LocaleKeys.GamepadPlus},
-            { GamepadInputId.Guide, LocaleKeys.GamepadGuide},
-            { GamepadInputId.Misc1, LocaleKeys.GamepadMisc1},
-            { GamepadInputId.Paddle1, LocaleKeys.GamepadPaddle1},
-            { GamepadInputId.Paddle2, LocaleKeys.GamepadPaddle2},
-            { GamepadInputId.Paddle3, LocaleKeys.GamepadPaddle3},
-            { GamepadInputId.Paddle4, LocaleKeys.GamepadPaddle4},
-            { GamepadInputId.Touchpad, LocaleKeys.GamepadTouchpad},
-            { GamepadInputId.SingleLeftTrigger0, LocaleKeys.GamepadSingleLeftTrigger0},
-            { GamepadInputId.SingleRightTrigger0, LocaleKeys.GamepadSingleRightTrigger0},
-            { GamepadInputId.SingleLeftTrigger1, LocaleKeys.GamepadSingleLeftTrigger1},
-            { GamepadInputId.SingleRightTrigger1, LocaleKeys.GamepadSingleRightTrigger1},
-            { GamepadInputId.Unbound, LocaleKeys.KeyUnbound},
-        };
+            if (value == null)
+            {
+                return null;
+            }
 
-        private static readonly Dictionary<StickInputId, LocaleKeys> _stickInputIdMap = new()
-        {
-            { StickInputId.Left, LocaleKeys.StickLeft},
-            { StickInputId.Right, LocaleKeys.StickRight},
-            { StickInputId.Unbound, LocaleKeys.KeyUnbound},
-        };
+            return value.ToString();
+        }
 
-        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
         {
-            string keyString = "";
+            object key = null;
 
-            if (value is Key key)
+            if (value != null)
             {
-                if (_keysMap.TryGetValue(key, out LocaleKeys localeKey))
+                if (targetType == typeof(Key))
                 {
-                    keyString = LocaleManager.Instance[localeKey];
+                    key = Enum.Parse<Key>(value.ToString());
                 }
-                else
+                else if (targetType == typeof(GamepadInputId))
                 {
-                    keyString = key.ToString();
+                    key = Enum.Parse<GamepadInputId>(value.ToString());
                 }
-            }
-            else if (value is GamepadInputId gamepadInputId)
-            {
-                if (_gamepadInputIdMap.TryGetValue(gamepadInputId, out LocaleKeys localeKey))
+                else if (targetType == typeof(StickInputId))
                 {
-                    keyString = LocaleManager.Instance[localeKey];
-                }
-                else
-                {
-                    keyString = gamepadInputId.ToString();
+                    key = Enum.Parse<StickInputId>(value.ToString());
                 }
             }
-            else if (value is StickInputId stickInputId)
-            {
-                if (_stickInputIdMap.TryGetValue(stickInputId, out LocaleKeys localeKey))
-                {
-                    keyString = LocaleManager.Instance[localeKey];
-                }
-                else
-                {
-                    keyString = stickInputId.ToString();
-                }
-            }
-
-            return keyString;
-        }
 
-        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
-        {
-            throw new NotSupportedException();
+            return key;
         }
     }
 }
diff --git a/src/Ryujinx.Ava/UI/Models/Input/ControllerInputConfig.cs b/src/Ryujinx.Ava/UI/Models/Input/ControllerInputConfig.cs
deleted file mode 100644
index 4929e582..00000000
--- a/src/Ryujinx.Ava/UI/Models/Input/ControllerInputConfig.cs
+++ /dev/null
@@ -1,580 +0,0 @@
-using Ryujinx.Ava.UI.ViewModels;
-using Ryujinx.Common.Configuration.Hid;
-using Ryujinx.Common.Configuration.Hid.Controller;
-using Ryujinx.Common.Configuration.Hid.Controller.Motion;
-using System;
-
-namespace Ryujinx.Ava.UI.Models.Input
-{
-    public class ControllerInputConfig : BaseModel
-    {
-        public bool EnableCemuHookMotion { get; set; }
-        public string DsuServerHost { get; set; }
-        public int DsuServerPort { get; set; }
-        public int Slot { get; set; }
-        public int AltSlot { get; set; }
-        public bool MirrorInput { get; set; }
-        public int Sensitivity { get; set; }
-        public double GyroDeadzone { get; set; }
-
-        public float WeakRumble { get; set; }
-        public float StrongRumble { get; set; }
-
-        public string Id { get; set; }
-        public ControllerType ControllerType { get; set; }
-        public PlayerIndex PlayerIndex { get; set; }
-
-        private StickInputId _leftJoystick;
-        public StickInputId LeftJoystick
-        {
-            get => _leftJoystick;
-            set
-            {
-                _leftJoystick = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private bool _leftInvertStickX;
-        public bool LeftInvertStickX
-        {
-            get => _leftInvertStickX;
-            set
-            {
-                _leftInvertStickX = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private bool _leftInvertStickY;
-        public bool LeftInvertStickY
-        {
-            get => _leftInvertStickY;
-            set
-            {
-                _leftInvertStickY = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private bool _leftRotate90;
-        public bool LeftRotate90
-        {
-            get => _leftRotate90;
-            set
-            {
-                _leftRotate90 = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private GamepadInputId _leftStickButton;
-        public GamepadInputId LeftStickButton
-        {
-            get => _leftStickButton;
-            set
-            {
-                _leftStickButton = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private StickInputId _rightJoystick;
-        public StickInputId RightJoystick
-        {
-            get => _rightJoystick;
-            set
-            {
-                _rightJoystick = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private bool _rightInvertStickX;
-        public bool RightInvertStickX
-        {
-            get => _rightInvertStickX;
-            set
-            {
-                _rightInvertStickX = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private bool _rightInvertStickY;
-        public bool RightInvertStickY
-        {
-            get => _rightInvertStickY;
-            set
-            {
-                _rightInvertStickY = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private bool _rightRotate90;
-        public bool RightRotate90
-        {
-            get => _rightRotate90;
-            set
-            {
-                _rightRotate90 = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private GamepadInputId _rightStickButton;
-        public GamepadInputId RightStickButton
-        {
-            get => _rightStickButton;
-            set
-            {
-                _rightStickButton = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private GamepadInputId _dpadUp;
-        public GamepadInputId DpadUp
-        {
-            get => _dpadUp;
-            set
-            {
-                _dpadUp = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private GamepadInputId _dpadDown;
-        public GamepadInputId DpadDown
-        {
-            get => _dpadDown;
-            set
-            {
-                _dpadDown = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private GamepadInputId _dpadLeft;
-        public GamepadInputId DpadLeft
-        {
-            get => _dpadLeft;
-            set
-            {
-                _dpadLeft = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private GamepadInputId _dpadRight;
-        public GamepadInputId DpadRight
-        {
-            get => _dpadRight;
-            set
-            {
-                _dpadRight = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private GamepadInputId _buttonL;
-        public GamepadInputId ButtonL
-        {
-            get => _buttonL;
-            set
-            {
-                _buttonL = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private GamepadInputId _buttonMinus;
-        public GamepadInputId ButtonMinus
-        {
-            get => _buttonMinus;
-            set
-            {
-                _buttonMinus = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private GamepadInputId _leftButtonSl;
-        public GamepadInputId LeftButtonSl
-        {
-            get => _leftButtonSl;
-            set
-            {
-                _leftButtonSl = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private GamepadInputId _leftButtonSr;
-        public GamepadInputId LeftButtonSr
-        {
-            get => _leftButtonSr;
-            set
-            {
-                _leftButtonSr = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private GamepadInputId _buttonZl;
-        public GamepadInputId ButtonZl
-        {
-            get => _buttonZl;
-            set
-            {
-                _buttonZl = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private GamepadInputId _buttonA;
-        public GamepadInputId ButtonA
-        {
-            get => _buttonA;
-            set
-            {
-                _buttonA = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private GamepadInputId _buttonB;
-        public GamepadInputId ButtonB
-        {
-            get => _buttonB;
-            set
-            {
-                _buttonB = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private GamepadInputId _buttonX;
-        public GamepadInputId ButtonX
-        {
-            get => _buttonX;
-            set
-            {
-                _buttonX = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private GamepadInputId _buttonY;
-        public GamepadInputId ButtonY
-        {
-            get => _buttonY;
-            set
-            {
-                _buttonY = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private GamepadInputId _buttonR;
-        public GamepadInputId ButtonR
-        {
-            get => _buttonR;
-            set
-            {
-                _buttonR = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private GamepadInputId _buttonPlus;
-        public GamepadInputId ButtonPlus
-        {
-            get => _buttonPlus;
-            set
-            {
-                _buttonPlus = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private GamepadInputId _rightButtonSl;
-        public GamepadInputId RightButtonSl
-        {
-            get => _rightButtonSl;
-            set
-            {
-                _rightButtonSl = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private GamepadInputId _rightButtonSr;
-        public GamepadInputId RightButtonSr
-        {
-            get => _rightButtonSr;
-            set
-            {
-                _rightButtonSr = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private GamepadInputId _buttonZr;
-        public GamepadInputId ButtonZr
-        {
-            get => _buttonZr;
-            set
-            {
-                _buttonZr = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private float _deadzoneLeft;
-        public float DeadzoneLeft
-        {
-            get => _deadzoneLeft;
-            set
-            {
-                _deadzoneLeft = MathF.Round(value, 3);
-                OnPropertyChanged();
-            }
-        }
-
-        private float _deadzoneRight;
-        public float DeadzoneRight
-        {
-            get => _deadzoneRight;
-            set
-            {
-                _deadzoneRight = MathF.Round(value, 3);
-                OnPropertyChanged();
-            }
-        }
-
-        private float _rangeLeft;
-        public float RangeLeft
-        {
-            get => _rangeLeft;
-            set
-            {
-                _rangeLeft = MathF.Round(value, 3);
-                OnPropertyChanged();
-            }
-        }
-
-        private float _rangeRight;
-        public float RangeRight
-        {
-            get => _rangeRight;
-            set
-            {
-                _rangeRight = MathF.Round(value, 3);
-                OnPropertyChanged();
-            }
-        }
-
-        private float _triggerThreshold;
-        public float TriggerThreshold
-        {
-            get => _triggerThreshold;
-            set
-            {
-                _triggerThreshold = MathF.Round(value, 3);
-                OnPropertyChanged();
-            }
-        }
-
-        private bool _enableMotion;
-        public bool EnableMotion
-        {
-            get => _enableMotion;
-            set
-            {
-                _enableMotion = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private bool _enableRumble;
-        public bool EnableRumble
-        {
-            get => _enableRumble;
-            set
-            {
-                _enableRumble = value;
-                OnPropertyChanged();
-            }
-        }
-
-        public ControllerInputConfig(InputConfig config)
-        {
-            if (config != null)
-            {
-                Id = config.Id;
-                ControllerType = config.ControllerType;
-                PlayerIndex = config.PlayerIndex;
-
-                if (config is not StandardControllerInputConfig controllerInput)
-                {
-                    return;
-                }
-
-                LeftJoystick = controllerInput.LeftJoyconStick.Joystick;
-                LeftInvertStickX = controllerInput.LeftJoyconStick.InvertStickX;
-                LeftInvertStickY = controllerInput.LeftJoyconStick.InvertStickY;
-                LeftRotate90 = controllerInput.LeftJoyconStick.Rotate90CW;
-                LeftStickButton = controllerInput.LeftJoyconStick.StickButton;
-
-                RightJoystick = controllerInput.RightJoyconStick.Joystick;
-                RightInvertStickX = controllerInput.RightJoyconStick.InvertStickX;
-                RightInvertStickY = controllerInput.RightJoyconStick.InvertStickY;
-                RightRotate90 = controllerInput.RightJoyconStick.Rotate90CW;
-                RightStickButton = controllerInput.RightJoyconStick.StickButton;
-
-                DpadUp = controllerInput.LeftJoycon.DpadUp;
-                DpadDown = controllerInput.LeftJoycon.DpadDown;
-                DpadLeft = controllerInput.LeftJoycon.DpadLeft;
-                DpadRight = controllerInput.LeftJoycon.DpadRight;
-                ButtonL = controllerInput.LeftJoycon.ButtonL;
-                ButtonMinus = controllerInput.LeftJoycon.ButtonMinus;
-                LeftButtonSl = controllerInput.LeftJoycon.ButtonSl;
-                LeftButtonSr = controllerInput.LeftJoycon.ButtonSr;
-                ButtonZl = controllerInput.LeftJoycon.ButtonZl;
-
-                ButtonA = controllerInput.RightJoycon.ButtonA;
-                ButtonB = controllerInput.RightJoycon.ButtonB;
-                ButtonX = controllerInput.RightJoycon.ButtonX;
-                ButtonY = controllerInput.RightJoycon.ButtonY;
-                ButtonR = controllerInput.RightJoycon.ButtonR;
-                ButtonPlus = controllerInput.RightJoycon.ButtonPlus;
-                RightButtonSl = controllerInput.RightJoycon.ButtonSl;
-                RightButtonSr = controllerInput.RightJoycon.ButtonSr;
-                ButtonZr = controllerInput.RightJoycon.ButtonZr;
-
-                DeadzoneLeft = controllerInput.DeadzoneLeft;
-                DeadzoneRight = controllerInput.DeadzoneRight;
-                RangeLeft = controllerInput.RangeLeft;
-                RangeRight = controllerInput.RangeRight;
-                TriggerThreshold = controllerInput.TriggerThreshold;
-
-                if (controllerInput.Motion != null)
-                {
-                    EnableMotion = controllerInput.Motion.EnableMotion;
-                    GyroDeadzone = controllerInput.Motion.GyroDeadzone;
-                    Sensitivity = controllerInput.Motion.Sensitivity;
-
-                    if (controllerInput.Motion is CemuHookMotionConfigController cemuHook)
-                    {
-                        EnableCemuHookMotion = true;
-                        DsuServerHost = cemuHook.DsuServerHost;
-                        DsuServerPort = cemuHook.DsuServerPort;
-                        Slot = cemuHook.Slot;
-                        AltSlot = cemuHook.AltSlot;
-                        MirrorInput = cemuHook.MirrorInput;
-                    }
-                }
-
-                if (controllerInput.Rumble != null)
-                {
-                    EnableRumble = controllerInput.Rumble.EnableRumble;
-                    WeakRumble = controllerInput.Rumble.WeakRumble;
-                    StrongRumble = controllerInput.Rumble.StrongRumble;
-                }
-            }
-        }
-
-        public InputConfig GetConfig()
-        {
-            var config = new StandardControllerInputConfig
-            {
-                Id = Id,
-                Backend = InputBackendType.GamepadSDL2,
-                PlayerIndex = PlayerIndex,
-                ControllerType = ControllerType,
-                LeftJoycon = new LeftJoyconCommonConfig<GamepadInputId>
-                {
-                    DpadUp = DpadUp,
-                    DpadDown = DpadDown,
-                    DpadLeft = DpadLeft,
-                    DpadRight = DpadRight,
-                    ButtonL = ButtonL,
-                    ButtonMinus = ButtonMinus,
-                    ButtonSl = LeftButtonSl,
-                    ButtonSr = LeftButtonSr,
-                    ButtonZl = ButtonZl
-                },
-                RightJoycon = new RightJoyconCommonConfig<GamepadInputId>
-                {
-                    ButtonA = ButtonA,
-                    ButtonB = ButtonB,
-                    ButtonX = ButtonX,
-                    ButtonY = ButtonY,
-                    ButtonPlus = ButtonPlus,
-                    ButtonSl = RightButtonSl,
-                    ButtonSr = RightButtonSr,
-                    ButtonR = ButtonR,
-                    ButtonZr = ButtonZr
-                },
-                LeftJoyconStick = new JoyconConfigControllerStick<GamepadInputId, StickInputId>
-                {
-                    Joystick = LeftJoystick,
-                    InvertStickX = LeftInvertStickX,
-                    InvertStickY = LeftInvertStickY,
-                    Rotate90CW = LeftRotate90,
-                    StickButton = LeftStickButton
-                },
-                RightJoyconStick = new JoyconConfigControllerStick<GamepadInputId, StickInputId>
-                {
-                    Joystick = RightJoystick,
-                    InvertStickX = RightInvertStickX,
-                    InvertStickY = RightInvertStickY,
-                    Rotate90CW = RightRotate90,
-                    StickButton = RightStickButton
-                },
-                Rumble = new RumbleConfigController
-                {
-                    EnableRumble = EnableRumble,
-                    WeakRumble = WeakRumble,
-                    StrongRumble = StrongRumble
-                },
-                Version = InputConfig.CurrentVersion,
-                DeadzoneLeft = DeadzoneLeft,
-                DeadzoneRight = DeadzoneRight,
-                RangeLeft = RangeLeft,
-                RangeRight = RangeRight,
-                TriggerThreshold = TriggerThreshold
-            };
-
-            if (EnableCemuHookMotion)
-            {
-                config.Motion = new CemuHookMotionConfigController
-                {
-                    EnableMotion = EnableMotion,
-                    MotionBackend = MotionInputBackendType.CemuHook,
-                    GyroDeadzone = GyroDeadzone,
-                    Sensitivity = Sensitivity,
-                    DsuServerHost = DsuServerHost,
-                    DsuServerPort = DsuServerPort,
-                    Slot = Slot,
-                    AltSlot = AltSlot,
-                    MirrorInput = MirrorInput
-                };
-            }
-            else
-            {
-                config.Motion = new MotionConfigController
-                {
-                    EnableMotion = EnableMotion,
-                    MotionBackend = MotionInputBackendType.GamepadDriver,
-                    GyroDeadzone = GyroDeadzone,
-                    Sensitivity = Sensitivity
-                };
-            }
-
-            return config;
-        }
-    }
-}
diff --git a/src/Ryujinx.Ava/UI/Models/Input/KeyboardInputConfig.cs b/src/Ryujinx.Ava/UI/Models/Input/KeyboardInputConfig.cs
deleted file mode 100644
index 02956521..00000000
--- a/src/Ryujinx.Ava/UI/Models/Input/KeyboardInputConfig.cs
+++ /dev/null
@@ -1,422 +0,0 @@
-using Ryujinx.Ava.UI.ViewModels;
-using Ryujinx.Common.Configuration.Hid;
-using Ryujinx.Common.Configuration.Hid.Keyboard;
-
-namespace Ryujinx.Ava.UI.Models.Input
-{
-    public class KeyboardInputConfig : BaseModel
-    {
-        public string Id { get; set; }
-        public ControllerType ControllerType { get; set; }
-        public PlayerIndex PlayerIndex { get; set; }
-
-        private Key _leftStickUp;
-        public Key LeftStickUp
-        {
-            get => _leftStickUp;
-            set
-            {
-                _leftStickUp = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private Key _leftStickDown;
-        public Key LeftStickDown
-        {
-            get => _leftStickDown;
-            set
-            {
-                _leftStickDown = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private Key _leftStickLeft;
-        public Key LeftStickLeft
-        {
-            get => _leftStickLeft;
-            set
-            {
-                _leftStickLeft = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private Key _leftStickRight;
-        public Key LeftStickRight
-        {
-            get => _leftStickRight;
-            set
-            {
-                _leftStickRight = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private Key _leftStickButton;
-        public Key LeftStickButton
-        {
-            get => _leftStickButton;
-            set
-            {
-                _leftStickButton = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private Key _rightStickUp;
-        public Key RightStickUp
-        {
-            get => _rightStickUp;
-            set
-            {
-                _rightStickUp = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private Key _rightStickDown;
-        public Key RightStickDown
-        {
-            get => _rightStickDown;
-            set
-            {
-                _rightStickDown = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private Key _rightStickLeft;
-        public Key RightStickLeft
-        {
-            get => _rightStickLeft;
-            set
-            {
-                _rightStickLeft = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private Key _rightStickRight;
-        public Key RightStickRight
-        {
-            get => _rightStickRight;
-            set
-            {
-                _rightStickRight = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private Key _rightStickButton;
-        public Key RightStickButton
-        {
-            get => _rightStickButton;
-            set
-            {
-                _rightStickButton = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private Key _dpadUp;
-        public Key DpadUp
-        {
-            get => _dpadUp;
-            set
-            {
-                _dpadUp = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private Key _dpadDown;
-        public Key DpadDown
-        {
-            get => _dpadDown;
-            set
-            {
-                _dpadDown = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private Key _dpadLeft;
-        public Key DpadLeft
-        {
-            get => _dpadLeft;
-            set
-            {
-                _dpadLeft = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private Key _dpadRight;
-        public Key DpadRight
-        {
-            get => _dpadRight;
-            set
-            {
-                _dpadRight = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private Key _buttonL;
-        public Key ButtonL
-        {
-            get => _buttonL;
-            set
-            {
-                _buttonL = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private Key _buttonMinus;
-        public Key ButtonMinus
-        {
-            get => _buttonMinus;
-            set
-            {
-                _buttonMinus = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private Key _leftButtonSl;
-        public Key LeftButtonSl
-        {
-            get => _leftButtonSl;
-            set
-            {
-                _leftButtonSl = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private Key _leftButtonSr;
-        public Key LeftButtonSr
-        {
-            get => _leftButtonSr;
-            set
-            {
-                _leftButtonSr = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private Key _buttonZl;
-        public Key ButtonZl
-        {
-            get => _buttonZl;
-            set
-            {
-                _buttonZl = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private Key _buttonA;
-        public Key ButtonA
-        {
-            get => _buttonA;
-            set
-            {
-                _buttonA = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private Key _buttonB;
-        public Key ButtonB
-        {
-            get => _buttonB;
-            set
-            {
-                _buttonB = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private Key _buttonX;
-        public Key ButtonX
-        {
-            get => _buttonX;
-            set
-            {
-                _buttonX = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private Key _buttonY;
-        public Key ButtonY
-        {
-            get => _buttonY;
-            set
-            {
-                _buttonY = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private Key _buttonR;
-        public Key ButtonR
-        {
-            get => _buttonR;
-            set
-            {
-                _buttonR = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private Key _buttonPlus;
-        public Key ButtonPlus
-        {
-            get => _buttonPlus;
-            set
-            {
-                _buttonPlus = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private Key _rightButtonSl;
-        public Key RightButtonSl
-        {
-            get => _rightButtonSl;
-            set
-            {
-                _rightButtonSl = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private Key _rightButtonSr;
-        public Key RightButtonSr
-        {
-            get => _rightButtonSr;
-            set
-            {
-                _rightButtonSr = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private Key _buttonZr;
-        public Key ButtonZr
-        {
-            get => _buttonZr;
-            set
-            {
-                _buttonZr = value;
-                OnPropertyChanged();
-            }
-        }
-
-        public KeyboardInputConfig(InputConfig config)
-        {
-            if (config != null)
-            {
-                Id = config.Id;
-                ControllerType = config.ControllerType;
-                PlayerIndex = config.PlayerIndex;
-
-                if (config is not StandardKeyboardInputConfig keyboardConfig)
-                {
-                    return;
-                }
-
-                LeftStickUp = keyboardConfig.LeftJoyconStick.StickUp;
-                LeftStickDown = keyboardConfig.LeftJoyconStick.StickDown;
-                LeftStickLeft = keyboardConfig.LeftJoyconStick.StickLeft;
-                LeftStickRight = keyboardConfig.LeftJoyconStick.StickRight;
-                LeftStickButton = keyboardConfig.LeftJoyconStick.StickButton;
-
-                RightStickUp = keyboardConfig.RightJoyconStick.StickUp;
-                RightStickDown = keyboardConfig.RightJoyconStick.StickDown;
-                RightStickLeft = keyboardConfig.RightJoyconStick.StickLeft;
-                RightStickRight = keyboardConfig.RightJoyconStick.StickRight;
-                RightStickButton = keyboardConfig.RightJoyconStick.StickButton;
-
-                DpadUp = keyboardConfig.LeftJoycon.DpadUp;
-                DpadDown = keyboardConfig.LeftJoycon.DpadDown;
-                DpadLeft = keyboardConfig.LeftJoycon.DpadLeft;
-                DpadRight = keyboardConfig.LeftJoycon.DpadRight;
-                ButtonL = keyboardConfig.LeftJoycon.ButtonL;
-                ButtonMinus = keyboardConfig.LeftJoycon.ButtonMinus;
-                LeftButtonSl = keyboardConfig.LeftJoycon.ButtonSl;
-                LeftButtonSr = keyboardConfig.LeftJoycon.ButtonSr;
-                ButtonZl = keyboardConfig.LeftJoycon.ButtonZl;
-
-                ButtonA = keyboardConfig.RightJoycon.ButtonA;
-                ButtonB = keyboardConfig.RightJoycon.ButtonB;
-                ButtonX = keyboardConfig.RightJoycon.ButtonX;
-                ButtonY = keyboardConfig.RightJoycon.ButtonY;
-                ButtonR = keyboardConfig.RightJoycon.ButtonR;
-                ButtonPlus = keyboardConfig.RightJoycon.ButtonPlus;
-                RightButtonSl = keyboardConfig.RightJoycon.ButtonSl;
-                RightButtonSr = keyboardConfig.RightJoycon.ButtonSr;
-                ButtonZr = keyboardConfig.RightJoycon.ButtonZr;
-            }
-        }
-
-        public InputConfig GetConfig()
-        {
-            var config = new StandardKeyboardInputConfig
-            {
-                Id = Id,
-                Backend = InputBackendType.WindowKeyboard,
-                PlayerIndex = PlayerIndex,
-                ControllerType = ControllerType,
-                LeftJoycon = new LeftJoyconCommonConfig<Key>
-                {
-                    DpadUp = DpadUp,
-                    DpadDown = DpadDown,
-                    DpadLeft = DpadLeft,
-                    DpadRight = DpadRight,
-                    ButtonL = ButtonL,
-                    ButtonMinus = ButtonMinus,
-                    ButtonZl = ButtonZl,
-                    ButtonSl = LeftButtonSl,
-                    ButtonSr = LeftButtonSr
-                },
-                RightJoycon = new RightJoyconCommonConfig<Key>
-                {
-                    ButtonA = ButtonA,
-                    ButtonB = ButtonB,
-                    ButtonX = ButtonX,
-                    ButtonY = ButtonY,
-                    ButtonPlus = ButtonPlus,
-                    ButtonSl = RightButtonSl,
-                    ButtonSr = RightButtonSr,
-                    ButtonR = ButtonR,
-                    ButtonZr = ButtonZr
-                },
-                LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
-                {
-                    StickUp = LeftStickUp,
-                    StickDown = LeftStickDown,
-                    StickRight = LeftStickRight,
-                    StickLeft = LeftStickLeft,
-                    StickButton = LeftStickButton
-                },
-                RightJoyconStick = new JoyconConfigKeyboardStick<Key>
-                {
-                    StickUp = RightStickUp,
-                    StickDown = RightStickDown,
-                    StickLeft = RightStickLeft,
-                    StickRight = RightStickRight,
-                    StickButton = RightStickButton
-                },
-                Version = InputConfig.CurrentVersion
-            };
-
-            return config;
-        }
-    }
-}
diff --git a/src/Ryujinx.Ava/UI/Models/InputConfiguration.cs b/src/Ryujinx.Ava/UI/Models/InputConfiguration.cs
new file mode 100644
index 00000000..f1352c6d
--- /dev/null
+++ b/src/Ryujinx.Ava/UI/Models/InputConfiguration.cs
@@ -0,0 +1,456 @@
+using Ryujinx.Ava.UI.ViewModels;
+using Ryujinx.Common.Configuration.Hid;
+using Ryujinx.Common.Configuration.Hid.Controller;
+using Ryujinx.Common.Configuration.Hid.Controller.Motion;
+using Ryujinx.Common.Configuration.Hid.Keyboard;
+using System;
+
+namespace Ryujinx.Ava.UI.Models
+{
+    internal class InputConfiguration<TKey, TStick> : BaseModel
+    {
+        private float _deadzoneRight;
+        private float _triggerThreshold;
+        private float _deadzoneLeft;
+        private double _gyroDeadzone;
+        private int _sensitivity;
+        private bool _enableMotion;
+        private float _weakRumble;
+        private float _strongRumble;
+        private float _rangeLeft;
+        private float _rangeRight;
+
+        public InputBackendType Backend { get; set; }
+
+        /// <summary>
+        /// Controller id
+        /// </summary>
+        public string Id { get; set; }
+
+        /// <summary>
+        ///  Controller's Type
+        /// </summary>
+        public ControllerType ControllerType { get; set; }
+
+        /// <summary>
+        ///  Player's Index for the controller
+        /// </summary>
+        public PlayerIndex PlayerIndex { get; set; }
+
+        public TStick LeftJoystick { get; set; }
+        public bool LeftInvertStickX { get; set; }
+        public bool LeftInvertStickY { get; set; }
+        public bool RightRotate90 { get; set; }
+        public TKey LeftControllerStickButton { get; set; }
+
+        public TStick RightJoystick { get; set; }
+        public bool RightInvertStickX { get; set; }
+        public bool RightInvertStickY { get; set; }
+        public bool LeftRotate90 { get; set; }
+        public TKey RightControllerStickButton { get; set; }
+
+        public float DeadzoneLeft
+        {
+            get => _deadzoneLeft;
+            set
+            {
+                _deadzoneLeft = MathF.Round(value, 3);
+
+                OnPropertyChanged();
+            }
+        }
+
+        public float RangeLeft
+        {
+            get => _rangeLeft;
+            set
+            {
+                _rangeLeft = MathF.Round(value, 3);
+
+                OnPropertyChanged();
+            }
+        }
+
+        public float DeadzoneRight
+        {
+            get => _deadzoneRight;
+            set
+            {
+                _deadzoneRight = MathF.Round(value, 3);
+
+                OnPropertyChanged();
+            }
+        }
+
+        public float RangeRight
+        {
+            get => _rangeRight;
+            set
+            {
+                _rangeRight = MathF.Round(value, 3);
+
+                OnPropertyChanged();
+            }
+        }
+
+        public float TriggerThreshold
+        {
+            get => _triggerThreshold;
+            set
+            {
+                _triggerThreshold = MathF.Round(value, 3);
+
+                OnPropertyChanged();
+            }
+        }
+
+        public MotionInputBackendType MotionBackend { get; set; }
+
+        public TKey ButtonMinus { get; set; }
+        public TKey ButtonL { get; set; }
+        public TKey ButtonZl { get; set; }
+        public TKey LeftButtonSl { get; set; }
+        public TKey LeftButtonSr { get; set; }
+        public TKey DpadUp { get; set; }
+        public TKey DpadDown { get; set; }
+        public TKey DpadLeft { get; set; }
+        public TKey DpadRight { get; set; }
+
+        public TKey ButtonPlus { get; set; }
+        public TKey ButtonR { get; set; }
+        public TKey ButtonZr { get; set; }
+        public TKey RightButtonSl { get; set; }
+        public TKey RightButtonSr { get; set; }
+        public TKey ButtonX { get; set; }
+        public TKey ButtonB { get; set; }
+        public TKey ButtonY { get; set; }
+        public TKey ButtonA { get; set; }
+
+        public TKey LeftStickUp { get; set; }
+        public TKey LeftStickDown { get; set; }
+        public TKey LeftStickLeft { get; set; }
+        public TKey LeftStickRight { get; set; }
+        public TKey LeftKeyboardStickButton { get; set; }
+
+        public TKey RightStickUp { get; set; }
+        public TKey RightStickDown { get; set; }
+        public TKey RightStickLeft { get; set; }
+        public TKey RightStickRight { get; set; }
+        public TKey RightKeyboardStickButton { get; set; }
+
+        public int Sensitivity
+        {
+            get => _sensitivity;
+            set
+            {
+                _sensitivity = value;
+
+                OnPropertyChanged();
+            }
+        }
+
+        public double GyroDeadzone
+        {
+            get => _gyroDeadzone;
+            set
+            {
+                _gyroDeadzone = Math.Round(value, 3);
+
+                OnPropertyChanged();
+            }
+        }
+
+        public bool EnableMotion
+        {
+            get => _enableMotion; set
+            {
+                _enableMotion = value;
+
+                OnPropertyChanged();
+            }
+        }
+
+        public bool EnableCemuHookMotion { get; set; }
+        public int Slot { get; set; }
+        public int AltSlot { get; set; }
+        public bool MirrorInput { get; set; }
+        public string DsuServerHost { get; set; }
+        public int DsuServerPort { get; set; }
+
+        public bool EnableRumble { get; set; }
+        public float WeakRumble
+        {
+            get => _weakRumble; set
+            {
+                _weakRumble = value;
+
+                OnPropertyChanged();
+            }
+        }
+        public float StrongRumble
+        {
+            get => _strongRumble; set
+            {
+                _strongRumble = value;
+
+                OnPropertyChanged();
+            }
+        }
+
+        public InputConfiguration(InputConfig config)
+        {
+            if (config != null)
+            {
+                Backend = config.Backend;
+                Id = config.Id;
+                ControllerType = config.ControllerType;
+                PlayerIndex = config.PlayerIndex;
+
+                if (config is StandardKeyboardInputConfig keyboardConfig)
+                {
+                    LeftStickUp = (TKey)(object)keyboardConfig.LeftJoyconStick.StickUp;
+                    LeftStickDown = (TKey)(object)keyboardConfig.LeftJoyconStick.StickDown;
+                    LeftStickLeft = (TKey)(object)keyboardConfig.LeftJoyconStick.StickLeft;
+                    LeftStickRight = (TKey)(object)keyboardConfig.LeftJoyconStick.StickRight;
+                    LeftKeyboardStickButton = (TKey)(object)keyboardConfig.LeftJoyconStick.StickButton;
+
+                    RightStickUp = (TKey)(object)keyboardConfig.RightJoyconStick.StickUp;
+                    RightStickDown = (TKey)(object)keyboardConfig.RightJoyconStick.StickDown;
+                    RightStickLeft = (TKey)(object)keyboardConfig.RightJoyconStick.StickLeft;
+                    RightStickRight = (TKey)(object)keyboardConfig.RightJoyconStick.StickRight;
+                    RightKeyboardStickButton = (TKey)(object)keyboardConfig.RightJoyconStick.StickButton;
+
+                    ButtonA = (TKey)(object)keyboardConfig.RightJoycon.ButtonA;
+                    ButtonB = (TKey)(object)keyboardConfig.RightJoycon.ButtonB;
+                    ButtonX = (TKey)(object)keyboardConfig.RightJoycon.ButtonX;
+                    ButtonY = (TKey)(object)keyboardConfig.RightJoycon.ButtonY;
+                    ButtonR = (TKey)(object)keyboardConfig.RightJoycon.ButtonR;
+                    RightButtonSl = (TKey)(object)keyboardConfig.RightJoycon.ButtonSl;
+                    RightButtonSr = (TKey)(object)keyboardConfig.RightJoycon.ButtonSr;
+                    ButtonZr = (TKey)(object)keyboardConfig.RightJoycon.ButtonZr;
+                    ButtonPlus = (TKey)(object)keyboardConfig.RightJoycon.ButtonPlus;
+
+                    DpadUp = (TKey)(object)keyboardConfig.LeftJoycon.DpadUp;
+                    DpadDown = (TKey)(object)keyboardConfig.LeftJoycon.DpadDown;
+                    DpadLeft = (TKey)(object)keyboardConfig.LeftJoycon.DpadLeft;
+                    DpadRight = (TKey)(object)keyboardConfig.LeftJoycon.DpadRight;
+                    ButtonMinus = (TKey)(object)keyboardConfig.LeftJoycon.ButtonMinus;
+                    LeftButtonSl = (TKey)(object)keyboardConfig.LeftJoycon.ButtonSl;
+                    LeftButtonSr = (TKey)(object)keyboardConfig.LeftJoycon.ButtonSr;
+                    ButtonZl = (TKey)(object)keyboardConfig.LeftJoycon.ButtonZl;
+                    ButtonL = (TKey)(object)keyboardConfig.LeftJoycon.ButtonL;
+                }
+                else if (config is StandardControllerInputConfig controllerConfig)
+                {
+                    LeftJoystick = (TStick)(object)controllerConfig.LeftJoyconStick.Joystick;
+                    LeftInvertStickX = controllerConfig.LeftJoyconStick.InvertStickX;
+                    LeftInvertStickY = controllerConfig.LeftJoyconStick.InvertStickY;
+                    LeftRotate90 = controllerConfig.LeftJoyconStick.Rotate90CW;
+                    LeftControllerStickButton = (TKey)(object)controllerConfig.LeftJoyconStick.StickButton;
+
+                    RightJoystick = (TStick)(object)controllerConfig.RightJoyconStick.Joystick;
+                    RightInvertStickX = controllerConfig.RightJoyconStick.InvertStickX;
+                    RightInvertStickY = controllerConfig.RightJoyconStick.InvertStickY;
+                    RightRotate90 = controllerConfig.RightJoyconStick.Rotate90CW;
+                    RightControllerStickButton = (TKey)(object)controllerConfig.RightJoyconStick.StickButton;
+
+                    ButtonA = (TKey)(object)controllerConfig.RightJoycon.ButtonA;
+                    ButtonB = (TKey)(object)controllerConfig.RightJoycon.ButtonB;
+                    ButtonX = (TKey)(object)controllerConfig.RightJoycon.ButtonX;
+                    ButtonY = (TKey)(object)controllerConfig.RightJoycon.ButtonY;
+                    ButtonR = (TKey)(object)controllerConfig.RightJoycon.ButtonR;
+                    RightButtonSl = (TKey)(object)controllerConfig.RightJoycon.ButtonSl;
+                    RightButtonSr = (TKey)(object)controllerConfig.RightJoycon.ButtonSr;
+                    ButtonZr = (TKey)(object)controllerConfig.RightJoycon.ButtonZr;
+                    ButtonPlus = (TKey)(object)controllerConfig.RightJoycon.ButtonPlus;
+
+                    DpadUp = (TKey)(object)controllerConfig.LeftJoycon.DpadUp;
+                    DpadDown = (TKey)(object)controllerConfig.LeftJoycon.DpadDown;
+                    DpadLeft = (TKey)(object)controllerConfig.LeftJoycon.DpadLeft;
+                    DpadRight = (TKey)(object)controllerConfig.LeftJoycon.DpadRight;
+                    ButtonMinus = (TKey)(object)controllerConfig.LeftJoycon.ButtonMinus;
+                    LeftButtonSl = (TKey)(object)controllerConfig.LeftJoycon.ButtonSl;
+                    LeftButtonSr = (TKey)(object)controllerConfig.LeftJoycon.ButtonSr;
+                    ButtonZl = (TKey)(object)controllerConfig.LeftJoycon.ButtonZl;
+                    ButtonL = (TKey)(object)controllerConfig.LeftJoycon.ButtonL;
+
+                    DeadzoneLeft = controllerConfig.DeadzoneLeft;
+                    DeadzoneRight = controllerConfig.DeadzoneRight;
+                    RangeLeft = controllerConfig.RangeLeft;
+                    RangeRight = controllerConfig.RangeRight;
+                    TriggerThreshold = controllerConfig.TriggerThreshold;
+
+                    if (controllerConfig.Motion != null)
+                    {
+                        EnableMotion = controllerConfig.Motion.EnableMotion;
+                        MotionBackend = controllerConfig.Motion.MotionBackend;
+                        GyroDeadzone = controllerConfig.Motion.GyroDeadzone;
+                        Sensitivity = controllerConfig.Motion.Sensitivity;
+
+                        if (controllerConfig.Motion is CemuHookMotionConfigController cemuHook)
+                        {
+                            EnableCemuHookMotion = true;
+                            DsuServerHost = cemuHook.DsuServerHost;
+                            DsuServerPort = cemuHook.DsuServerPort;
+                            Slot = cemuHook.Slot;
+                            AltSlot = cemuHook.AltSlot;
+                            MirrorInput = cemuHook.MirrorInput;
+                        }
+
+                        if (controllerConfig.Rumble != null)
+                        {
+                            EnableRumble = controllerConfig.Rumble.EnableRumble;
+                            WeakRumble = controllerConfig.Rumble.WeakRumble;
+                            StrongRumble = controllerConfig.Rumble.StrongRumble;
+                        }
+                    }
+                }
+            }
+        }
+
+        public InputConfiguration()
+        {
+        }
+
+        public InputConfig GetConfig()
+        {
+            if (Backend == InputBackendType.WindowKeyboard)
+            {
+                return new StandardKeyboardInputConfig
+                {
+                    Id = Id,
+                    Backend = Backend,
+                    PlayerIndex = PlayerIndex,
+                    ControllerType = ControllerType,
+                    LeftJoycon = new LeftJoyconCommonConfig<Key>
+                    {
+                        DpadUp = (Key)(object)DpadUp,
+                        DpadDown = (Key)(object)DpadDown,
+                        DpadLeft = (Key)(object)DpadLeft,
+                        DpadRight = (Key)(object)DpadRight,
+                        ButtonL = (Key)(object)ButtonL,
+                        ButtonZl = (Key)(object)ButtonZl,
+                        ButtonSl = (Key)(object)LeftButtonSl,
+                        ButtonSr = (Key)(object)LeftButtonSr,
+                        ButtonMinus = (Key)(object)ButtonMinus,
+                    },
+                    RightJoycon = new RightJoyconCommonConfig<Key>
+                    {
+                        ButtonA = (Key)(object)ButtonA,
+                        ButtonB = (Key)(object)ButtonB,
+                        ButtonX = (Key)(object)ButtonX,
+                        ButtonY = (Key)(object)ButtonY,
+                        ButtonPlus = (Key)(object)ButtonPlus,
+                        ButtonSl = (Key)(object)RightButtonSl,
+                        ButtonSr = (Key)(object)RightButtonSr,
+                        ButtonR = (Key)(object)ButtonR,
+                        ButtonZr = (Key)(object)ButtonZr,
+                    },
+                    LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
+                    {
+                        StickUp = (Key)(object)LeftStickUp,
+                        StickDown = (Key)(object)LeftStickDown,
+                        StickRight = (Key)(object)LeftStickRight,
+                        StickLeft = (Key)(object)LeftStickLeft,
+                        StickButton = (Key)(object)LeftKeyboardStickButton,
+                    },
+                    RightJoyconStick = new JoyconConfigKeyboardStick<Key>
+                    {
+                        StickUp = (Key)(object)RightStickUp,
+                        StickDown = (Key)(object)RightStickDown,
+                        StickLeft = (Key)(object)RightStickLeft,
+                        StickRight = (Key)(object)RightStickRight,
+                        StickButton = (Key)(object)RightKeyboardStickButton,
+                    },
+                    Version = InputConfig.CurrentVersion,
+                };
+
+            }
+
+            if (Backend == InputBackendType.GamepadSDL2)
+            {
+                var config = new StandardControllerInputConfig
+                {
+                    Id = Id,
+                    Backend = Backend,
+                    PlayerIndex = PlayerIndex,
+                    ControllerType = ControllerType,
+                    LeftJoycon = new LeftJoyconCommonConfig<GamepadInputId>
+                    {
+                        DpadUp = (GamepadInputId)(object)DpadUp,
+                        DpadDown = (GamepadInputId)(object)DpadDown,
+                        DpadLeft = (GamepadInputId)(object)DpadLeft,
+                        DpadRight = (GamepadInputId)(object)DpadRight,
+                        ButtonL = (GamepadInputId)(object)ButtonL,
+                        ButtonZl = (GamepadInputId)(object)ButtonZl,
+                        ButtonSl = (GamepadInputId)(object)LeftButtonSl,
+                        ButtonSr = (GamepadInputId)(object)LeftButtonSr,
+                        ButtonMinus = (GamepadInputId)(object)ButtonMinus,
+                    },
+                    RightJoycon = new RightJoyconCommonConfig<GamepadInputId>
+                    {
+                        ButtonA = (GamepadInputId)(object)ButtonA,
+                        ButtonB = (GamepadInputId)(object)ButtonB,
+                        ButtonX = (GamepadInputId)(object)ButtonX,
+                        ButtonY = (GamepadInputId)(object)ButtonY,
+                        ButtonPlus = (GamepadInputId)(object)ButtonPlus,
+                        ButtonSl = (GamepadInputId)(object)RightButtonSl,
+                        ButtonSr = (GamepadInputId)(object)RightButtonSr,
+                        ButtonR = (GamepadInputId)(object)ButtonR,
+                        ButtonZr = (GamepadInputId)(object)ButtonZr,
+                    },
+                    LeftJoyconStick = new JoyconConfigControllerStick<GamepadInputId, StickInputId>
+                    {
+                        Joystick = (StickInputId)(object)LeftJoystick,
+                        InvertStickX = LeftInvertStickX,
+                        InvertStickY = LeftInvertStickY,
+                        Rotate90CW = LeftRotate90,
+                        StickButton = (GamepadInputId)(object)LeftControllerStickButton,
+                    },
+                    RightJoyconStick = new JoyconConfigControllerStick<GamepadInputId, StickInputId>
+                    {
+                        Joystick = (StickInputId)(object)RightJoystick,
+                        InvertStickX = RightInvertStickX,
+                        InvertStickY = RightInvertStickY,
+                        Rotate90CW = RightRotate90,
+                        StickButton = (GamepadInputId)(object)RightControllerStickButton,
+                    },
+                    Rumble = new RumbleConfigController
+                    {
+                        EnableRumble = EnableRumble,
+                        WeakRumble = WeakRumble,
+                        StrongRumble = StrongRumble,
+                    },
+                    Version = InputConfig.CurrentVersion,
+                    DeadzoneLeft = DeadzoneLeft,
+                    DeadzoneRight = DeadzoneRight,
+                    RangeLeft = RangeLeft,
+                    RangeRight = RangeRight,
+                    TriggerThreshold = TriggerThreshold,
+                    Motion = EnableCemuHookMotion
+                        ? new CemuHookMotionConfigController
+                        {
+                            DsuServerHost = DsuServerHost,
+                            DsuServerPort = DsuServerPort,
+                            Slot = Slot,
+                            AltSlot = AltSlot,
+                            MirrorInput = MirrorInput,
+                            MotionBackend = MotionInputBackendType.CemuHook,
+                        }
+                        : new StandardMotionConfigController
+                        {
+                            MotionBackend = MotionInputBackendType.GamepadDriver,
+                        },
+                };
+
+                config.Motion.Sensitivity = Sensitivity;
+                config.Motion.EnableMotion = EnableMotion;
+                config.Motion.GyroDeadzone = GyroDeadzone;
+
+                return config;
+            }
+
+            return null;
+        }
+    }
+}
diff --git a/src/Ryujinx.Ava/UI/ViewModels/ControllerInputViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/ControllerInputViewModel.cs
new file mode 100644
index 00000000..c0c62532
--- /dev/null
+++ b/src/Ryujinx.Ava/UI/ViewModels/ControllerInputViewModel.cs
@@ -0,0 +1,897 @@
+using Avalonia;
+using Avalonia.Collections;
+using Avalonia.Controls;
+using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Svg.Skia;
+using Avalonia.Threading;
+using Ryujinx.Ava.Common.Locale;
+using Ryujinx.Ava.Input;
+using Ryujinx.Ava.UI.Helpers;
+using Ryujinx.Ava.UI.Models;
+using Ryujinx.Ava.UI.Views.Input;
+using Ryujinx.Ava.UI.Windows;
+using Ryujinx.Common;
+using Ryujinx.Common.Configuration;
+using Ryujinx.Common.Configuration.Hid;
+using Ryujinx.Common.Configuration.Hid.Controller;
+using Ryujinx.Common.Configuration.Hid.Controller.Motion;
+using Ryujinx.Common.Configuration.Hid.Keyboard;
+using Ryujinx.Common.Logging;
+using Ryujinx.Common.Utilities;
+using Ryujinx.Input;
+using Ryujinx.Ui.Common.Configuration;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.IO;
+using System.Linq;
+using System.Text.Json;
+using ConfigGamepadInputId = Ryujinx.Common.Configuration.Hid.Controller.GamepadInputId;
+using ConfigStickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
+using Key = Ryujinx.Common.Configuration.Hid.Key;
+
+namespace Ryujinx.Ava.UI.ViewModels
+{
+    public class ControllerInputViewModel : BaseModel, IDisposable
+    {
+        private const string Disabled = "disabled";
+        private const string ProControllerResource = "Ryujinx.Ui.Common/Resources/Controller_ProCon.svg";
+        private const string JoyConPairResource = "Ryujinx.Ui.Common/Resources/Controller_JoyConPair.svg";
+        private const string JoyConLeftResource = "Ryujinx.Ui.Common/Resources/Controller_JoyConLeft.svg";
+        private const string JoyConRightResource = "Ryujinx.Ui.Common/Resources/Controller_JoyConRight.svg";
+        private const string KeyboardString = "keyboard";
+        private const string ControllerString = "controller";
+        private readonly MainWindow _mainWindow;
+
+        private PlayerIndex _playerId;
+        private int _controller;
+        private int _controllerNumber;
+        private string _controllerImage;
+        private int _device;
+        private object _configuration;
+        private string _profileName;
+        private bool _isLoaded;
+
+        private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
+
+        public IGamepadDriver AvaloniaKeyboardDriver { get; }
+        public IGamepad SelectedGamepad { get; private set; }
+
+        public ObservableCollection<PlayerModel> PlayerIndexes { get; set; }
+        public ObservableCollection<(DeviceType Type, string Id, string Name)> Devices { get; set; }
+        internal ObservableCollection<ControllerModel> Controllers { get; set; }
+        public AvaloniaList<string> ProfilesList { get; set; }
+        public AvaloniaList<string> DeviceList { get; set; }
+
+        // XAML Flags
+        public bool ShowSettings => _device > 0;
+        public bool IsController => _device > 1;
+        public bool IsKeyboard => !IsController;
+        public bool IsRight { get; set; }
+        public bool IsLeft { get; set; }
+
+        public bool IsModified { get; set; }
+
+        public object Configuration
+        {
+            get => _configuration;
+            set
+            {
+                _configuration = value;
+
+                OnPropertyChanged();
+            }
+        }
+
+        public PlayerIndex PlayerId
+        {
+            get => _playerId;
+            set
+            {
+                if (IsModified)
+                {
+                    return;
+                }
+
+                IsModified = false;
+                _playerId = value;
+
+                if (!Enum.IsDefined(typeof(PlayerIndex), _playerId))
+                {
+                    _playerId = PlayerIndex.Player1;
+                }
+
+                LoadConfiguration();
+                LoadDevice();
+                LoadProfiles();
+
+                _isLoaded = true;
+
+                OnPropertyChanged();
+            }
+        }
+
+        public int Controller
+        {
+            get => _controller;
+            set
+            {
+                _controller = value;
+
+                if (_controller == -1)
+                {
+                    _controller = 0;
+                }
+
+                if (Controllers.Count > 0 && value < Controllers.Count && _controller > -1)
+                {
+                    ControllerType controller = Controllers[_controller].Type;
+
+                    IsLeft = true;
+                    IsRight = true;
+
+                    switch (controller)
+                    {
+                        case ControllerType.Handheld:
+                            ControllerImage = JoyConPairResource;
+                            break;
+                        case ControllerType.ProController:
+                            ControllerImage = ProControllerResource;
+                            break;
+                        case ControllerType.JoyconPair:
+                            ControllerImage = JoyConPairResource;
+                            break;
+                        case ControllerType.JoyconLeft:
+                            ControllerImage = JoyConLeftResource;
+                            IsRight = false;
+                            break;
+                        case ControllerType.JoyconRight:
+                            ControllerImage = JoyConRightResource;
+                            IsLeft = false;
+                            break;
+                    }
+
+                    LoadInputDriver();
+                    LoadProfiles();
+                }
+
+                OnPropertyChanged();
+                NotifyChanges();
+            }
+        }
+
+        public string ControllerImage
+        {
+            get => _controllerImage;
+            set
+            {
+                _controllerImage = value;
+
+                OnPropertyChanged();
+                OnPropertyChanged(nameof(Image));
+            }
+        }
+
+        public SvgImage Image
+        {
+            get
+            {
+                SvgImage image = new();
+
+                if (!string.IsNullOrWhiteSpace(_controllerImage))
+                {
+                    SvgSource source = new();
+
+                    source.Load(EmbeddedResources.GetStream(_controllerImage));
+
+                    image.Source = source;
+                }
+
+                return image;
+            }
+        }
+
+        public string ProfileName
+        {
+            get => _profileName; set
+            {
+                _profileName = value;
+
+                OnPropertyChanged();
+            }
+        }
+
+        public int Device
+        {
+            get => _device;
+            set
+            {
+                _device = value < 0 ? 0 : value;
+
+                if (_device >= Devices.Count)
+                {
+                    return;
+                }
+
+                var selected = Devices[_device].Type;
+
+                if (selected != DeviceType.None)
+                {
+                    LoadControllers();
+
+                    if (_isLoaded)
+                    {
+                        LoadConfiguration(LoadDefaultConfiguration());
+                    }
+                }
+
+                OnPropertyChanged();
+                NotifyChanges();
+            }
+        }
+
+        public InputConfig Config { get; set; }
+
+        public ControllerInputViewModel(UserControl owner) : this()
+        {
+            if (Program.PreviewerDetached)
+            {
+                _mainWindow =
+                    (MainWindow)((IClassicDesktopStyleApplicationLifetime)Application.Current
+                        .ApplicationLifetime).MainWindow;
+
+                AvaloniaKeyboardDriver = new AvaloniaKeyboardDriver(owner);
+
+                _mainWindow.InputManager.GamepadDriver.OnGamepadConnected += HandleOnGamepadConnected;
+                _mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected;
+
+                _mainWindow.ViewModel.AppHost?.NpadManager.BlockInputUpdates();
+
+                _isLoaded = false;
+
+                LoadDevices();
+
+                PlayerId = PlayerIndex.Player1;
+            }
+        }
+
+        public ControllerInputViewModel()
+        {
+            PlayerIndexes = new ObservableCollection<PlayerModel>();
+            Controllers = new ObservableCollection<ControllerModel>();
+            Devices = new ObservableCollection<(DeviceType Type, string Id, string Name)>();
+            ProfilesList = new AvaloniaList<string>();
+            DeviceList = new AvaloniaList<string>();
+
+            ControllerImage = ProControllerResource;
+
+            PlayerIndexes.Add(new(PlayerIndex.Player1, LocaleManager.Instance[LocaleKeys.ControllerSettingsPlayer1]));
+            PlayerIndexes.Add(new(PlayerIndex.Player2, LocaleManager.Instance[LocaleKeys.ControllerSettingsPlayer2]));
+            PlayerIndexes.Add(new(PlayerIndex.Player3, LocaleManager.Instance[LocaleKeys.ControllerSettingsPlayer3]));
+            PlayerIndexes.Add(new(PlayerIndex.Player4, LocaleManager.Instance[LocaleKeys.ControllerSettingsPlayer4]));
+            PlayerIndexes.Add(new(PlayerIndex.Player5, LocaleManager.Instance[LocaleKeys.ControllerSettingsPlayer5]));
+            PlayerIndexes.Add(new(PlayerIndex.Player6, LocaleManager.Instance[LocaleKeys.ControllerSettingsPlayer6]));
+            PlayerIndexes.Add(new(PlayerIndex.Player7, LocaleManager.Instance[LocaleKeys.ControllerSettingsPlayer7]));
+            PlayerIndexes.Add(new(PlayerIndex.Player8, LocaleManager.Instance[LocaleKeys.ControllerSettingsPlayer8]));
+            PlayerIndexes.Add(new(PlayerIndex.Handheld, LocaleManager.Instance[LocaleKeys.ControllerSettingsHandheld]));
+        }
+
+        private void LoadConfiguration(InputConfig inputConfig = null)
+        {
+            Config = inputConfig ?? ConfigurationState.Instance.Hid.InputConfig.Value.Find(inputConfig => inputConfig.PlayerIndex == _playerId);
+
+            if (Config is StandardKeyboardInputConfig keyboardInputConfig)
+            {
+                Configuration = new InputConfiguration<Key, ConfigStickInputId>(keyboardInputConfig);
+            }
+
+            if (Config is StandardControllerInputConfig controllerInputConfig)
+            {
+                Configuration = new InputConfiguration<ConfigGamepadInputId, ConfigStickInputId>(controllerInputConfig);
+            }
+        }
+
+        public void LoadDevice()
+        {
+            if (Config == null || Config.Backend == InputBackendType.Invalid)
+            {
+                Device = 0;
+            }
+            else
+            {
+                var type = DeviceType.None;
+
+                if (Config is StandardKeyboardInputConfig)
+                {
+                    type = DeviceType.Keyboard;
+                }
+
+                if (Config is StandardControllerInputConfig)
+                {
+                    type = DeviceType.Controller;
+                }
+
+                var item = Devices.FirstOrDefault(x => x.Type == type && x.Id == Config.Id);
+                if (item != default)
+                {
+                    Device = Devices.ToList().FindIndex(x => x.Id == item.Id);
+                }
+                else
+                {
+                    Device = 0;
+                }
+            }
+        }
+
+        public async void ShowMotionConfig()
+        {
+            await MotionInputView.Show(this);
+        }
+
+        public async void ShowRumbleConfig()
+        {
+            await RumbleInputView.Show(this);
+        }
+
+        private void LoadInputDriver()
+        {
+            if (_device < 0)
+            {
+                return;
+            }
+
+            string id = GetCurrentGamepadId();
+            var type = Devices[Device].Type;
+
+            if (type == DeviceType.None)
+            {
+                return;
+            }
+
+            if (type == DeviceType.Keyboard)
+            {
+                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...
+                    SelectedGamepad = AvaloniaKeyboardDriver.GetGamepad(id);
+                }
+                else
+                {
+                    SelectedGamepad = _mainWindow.InputManager.KeyboardDriver.GetGamepad(id);
+                }
+            }
+            else
+            {
+                SelectedGamepad = _mainWindow.InputManager.GamepadDriver.GetGamepad(id);
+            }
+        }
+
+        private void HandleOnGamepadDisconnected(string id)
+        {
+            Dispatcher.UIThread.Post(() =>
+            {
+                LoadDevices();
+            });
+        }
+
+        private void HandleOnGamepadConnected(string id)
+        {
+            Dispatcher.UIThread.Post(() =>
+            {
+                LoadDevices();
+            });
+        }
+
+        private string GetCurrentGamepadId()
+        {
+            if (_device < 0)
+            {
+                return string.Empty;
+            }
+
+            var device = Devices[Device];
+
+            if (device.Type == DeviceType.None)
+            {
+                return null;
+            }
+
+            return device.Id.Split(" ")[0];
+        }
+
+        public void LoadControllers()
+        {
+            Controllers.Clear();
+
+            if (_playerId == PlayerIndex.Handheld)
+            {
+                Controllers.Add(new(ControllerType.Handheld, LocaleManager.Instance[LocaleKeys.ControllerSettingsControllerTypeHandheld]));
+
+                Controller = 0;
+            }
+            else
+            {
+                Controllers.Add(new(ControllerType.ProController, LocaleManager.Instance[LocaleKeys.ControllerSettingsControllerTypeProController]));
+                Controllers.Add(new(ControllerType.JoyconPair, LocaleManager.Instance[LocaleKeys.ControllerSettingsControllerTypeJoyConPair]));
+                Controllers.Add(new(ControllerType.JoyconLeft, LocaleManager.Instance[LocaleKeys.ControllerSettingsControllerTypeJoyConLeft]));
+                Controllers.Add(new(ControllerType.JoyconRight, LocaleManager.Instance[LocaleKeys.ControllerSettingsControllerTypeJoyConRight]));
+
+                if (Config != null && Controllers.ToList().FindIndex(x => x.Type == Config.ControllerType) != -1)
+                {
+                    Controller = Controllers.ToList().FindIndex(x => x.Type == Config.ControllerType);
+                }
+                else
+                {
+                    Controller = 0;
+                }
+            }
+        }
+
+        private static string GetShortGamepadName(string str)
+        {
+            const string Ellipsis = "...";
+            const int MaxSize = 50;
+
+            if (str.Length > MaxSize)
+            {
+                return $"{str.AsSpan(0, MaxSize - Ellipsis.Length)}{Ellipsis}";
+            }
+
+            return str;
+        }
+
+        private static string GetShortGamepadId(string str)
+        {
+            const string Hyphen = "-";
+            const int Offset = 1;
+
+            return str[(str.IndexOf(Hyphen) + Offset)..];
+        }
+
+        public void LoadDevices()
+        {
+            lock (Devices)
+            {
+                Devices.Clear();
+                DeviceList.Clear();
+                Devices.Add((DeviceType.None, Disabled, LocaleManager.Instance[LocaleKeys.ControllerSettingsDeviceDisabled]));
+
+                foreach (string id in _mainWindow.InputManager.KeyboardDriver.GamepadsIds)
+                {
+                    using IGamepad gamepad = _mainWindow.InputManager.KeyboardDriver.GetGamepad(id);
+
+                    if (gamepad != null)
+                    {
+                        Devices.Add((DeviceType.Keyboard, id, $"{GetShortGamepadName(gamepad.Name)}"));
+                    }
+                }
+
+                foreach (string id in _mainWindow.InputManager.GamepadDriver.GamepadsIds)
+                {
+                    using IGamepad gamepad = _mainWindow.InputManager.GamepadDriver.GetGamepad(id);
+
+                    if (gamepad != null)
+                    {
+                        if (Devices.Any(controller => GetShortGamepadId(controller.Id) == GetShortGamepadId(gamepad.Id)))
+                        {
+                            _controllerNumber++;
+                        }
+
+                        Devices.Add((DeviceType.Controller, id, $"{GetShortGamepadName(gamepad.Name)} ({_controllerNumber})"));
+                    }
+                }
+
+                _controllerNumber = 0;
+
+                DeviceList.AddRange(Devices.Select(x => x.Name));
+                Device = Math.Min(Device, DeviceList.Count);
+            }
+        }
+
+        private string GetProfileBasePath()
+        {
+            string path = AppDataManager.ProfilesDirPath;
+            var type = Devices[Device == -1 ? 0 : Device].Type;
+
+            if (type == DeviceType.Keyboard)
+            {
+                path = Path.Combine(path, KeyboardString);
+            }
+            else if (type == DeviceType.Controller)
+            {
+                path = Path.Combine(path, ControllerString);
+            }
+
+            return path;
+        }
+
+        private void LoadProfiles()
+        {
+            ProfilesList.Clear();
+
+            string basePath = GetProfileBasePath();
+
+            if (!Directory.Exists(basePath))
+            {
+                Directory.CreateDirectory(basePath);
+            }
+
+            ProfilesList.Add((LocaleManager.Instance[LocaleKeys.ControllerSettingsProfileDefault]));
+
+            foreach (string profile in Directory.GetFiles(basePath, "*.json", SearchOption.AllDirectories))
+            {
+                ProfilesList.Add(Path.GetFileNameWithoutExtension(profile));
+            }
+
+            if (string.IsNullOrWhiteSpace(ProfileName))
+            {
+                ProfileName = LocaleManager.Instance[LocaleKeys.ControllerSettingsProfileDefault];
+            }
+        }
+
+        public InputConfig LoadDefaultConfiguration()
+        {
+            var activeDevice = Devices.FirstOrDefault();
+
+            if (Devices.Count > 0 && Device < Devices.Count && Device >= 0)
+            {
+                activeDevice = Devices[Device];
+            }
+
+            InputConfig config;
+            if (activeDevice.Type == DeviceType.Keyboard)
+            {
+                string id = activeDevice.Id;
+
+                config = new StandardKeyboardInputConfig
+                {
+                    Version = InputConfig.CurrentVersion,
+                    Backend = InputBackendType.WindowKeyboard,
+                    Id = id,
+                    ControllerType = ControllerType.ProController,
+                    LeftJoycon = new LeftJoyconCommonConfig<Key>
+                    {
+                        DpadUp = Key.Up,
+                        DpadDown = Key.Down,
+                        DpadLeft = Key.Left,
+                        DpadRight = Key.Right,
+                        ButtonMinus = Key.Minus,
+                        ButtonL = Key.E,
+                        ButtonZl = Key.Q,
+                        ButtonSl = Key.Unbound,
+                        ButtonSr = Key.Unbound,
+                    },
+                    LeftJoyconStick =
+                        new JoyconConfigKeyboardStick<Key>
+                        {
+                            StickUp = Key.W,
+                            StickDown = Key.S,
+                            StickLeft = Key.A,
+                            StickRight = Key.D,
+                            StickButton = Key.F,
+                        },
+                    RightJoycon = new RightJoyconCommonConfig<Key>
+                    {
+                        ButtonA = Key.Z,
+                        ButtonB = Key.X,
+                        ButtonX = Key.C,
+                        ButtonY = Key.V,
+                        ButtonPlus = Key.Plus,
+                        ButtonR = Key.U,
+                        ButtonZr = Key.O,
+                        ButtonSl = Key.Unbound,
+                        ButtonSr = Key.Unbound,
+                    },
+                    RightJoyconStick = new JoyconConfigKeyboardStick<Key>
+                    {
+                        StickUp = Key.I,
+                        StickDown = Key.K,
+                        StickLeft = Key.J,
+                        StickRight = Key.L,
+                        StickButton = Key.H,
+                    },
+                };
+            }
+            else if (activeDevice.Type == DeviceType.Controller)
+            {
+                bool isNintendoStyle = Devices.ToList().Find(x => x.Id == activeDevice.Id).Name.Contains("Nintendo");
+
+                string id = activeDevice.Id.Split(" ")[0];
+
+                config = new StandardControllerInputConfig
+                {
+                    Version = InputConfig.CurrentVersion,
+                    Backend = InputBackendType.GamepadSDL2,
+                    Id = id,
+                    ControllerType = ControllerType.ProController,
+                    DeadzoneLeft = 0.1f,
+                    DeadzoneRight = 0.1f,
+                    RangeLeft = 1.0f,
+                    RangeRight = 1.0f,
+                    TriggerThreshold = 0.5f,
+                    LeftJoycon = new LeftJoyconCommonConfig<ConfigGamepadInputId>
+                    {
+                        DpadUp = ConfigGamepadInputId.DpadUp,
+                        DpadDown = ConfigGamepadInputId.DpadDown,
+                        DpadLeft = ConfigGamepadInputId.DpadLeft,
+                        DpadRight = ConfigGamepadInputId.DpadRight,
+                        ButtonMinus = ConfigGamepadInputId.Minus,
+                        ButtonL = ConfigGamepadInputId.LeftShoulder,
+                        ButtonZl = ConfigGamepadInputId.LeftTrigger,
+                        ButtonSl = ConfigGamepadInputId.Unbound,
+                        ButtonSr = ConfigGamepadInputId.Unbound,
+                    },
+                    LeftJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
+                    {
+                        Joystick = ConfigStickInputId.Left,
+                        StickButton = ConfigGamepadInputId.LeftStick,
+                        InvertStickX = false,
+                        InvertStickY = false,
+                    },
+                    RightJoycon = new RightJoyconCommonConfig<ConfigGamepadInputId>
+                    {
+                        ButtonA = isNintendoStyle ? ConfigGamepadInputId.A : ConfigGamepadInputId.B,
+                        ButtonB = isNintendoStyle ? ConfigGamepadInputId.B : ConfigGamepadInputId.A,
+                        ButtonX = isNintendoStyle ? ConfigGamepadInputId.X : ConfigGamepadInputId.Y,
+                        ButtonY = isNintendoStyle ? ConfigGamepadInputId.Y : ConfigGamepadInputId.X,
+                        ButtonPlus = ConfigGamepadInputId.Plus,
+                        ButtonR = ConfigGamepadInputId.RightShoulder,
+                        ButtonZr = ConfigGamepadInputId.RightTrigger,
+                        ButtonSl = ConfigGamepadInputId.Unbound,
+                        ButtonSr = ConfigGamepadInputId.Unbound,
+                    },
+                    RightJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
+                    {
+                        Joystick = ConfigStickInputId.Right,
+                        StickButton = ConfigGamepadInputId.RightStick,
+                        InvertStickX = false,
+                        InvertStickY = false,
+                    },
+                    Motion = new StandardMotionConfigController
+                    {
+                        MotionBackend = MotionInputBackendType.GamepadDriver,
+                        EnableMotion = true,
+                        Sensitivity = 100,
+                        GyroDeadzone = 1,
+                    },
+                    Rumble = new RumbleConfigController
+                    {
+                        StrongRumble = 1f,
+                        WeakRumble = 1f,
+                        EnableRumble = false,
+                    },
+                };
+            }
+            else
+            {
+                config = new InputConfig();
+            }
+
+            config.PlayerIndex = _playerId;
+
+            return config;
+        }
+
+        public async void LoadProfile()
+        {
+            if (Device == 0)
+            {
+                return;
+            }
+
+            InputConfig config = null;
+
+            if (string.IsNullOrWhiteSpace(ProfileName))
+            {
+                return;
+            }
+
+            if (ProfileName == LocaleManager.Instance[LocaleKeys.ControllerSettingsProfileDefault])
+            {
+                config = LoadDefaultConfiguration();
+            }
+            else
+            {
+                string path = Path.Combine(GetProfileBasePath(), ProfileName + ".json");
+
+                if (!File.Exists(path))
+                {
+                    var index = ProfilesList.IndexOf(ProfileName);
+                    if (index != -1)
+                    {
+                        ProfilesList.RemoveAt(index);
+                    }
+                    return;
+                }
+
+                try
+                {
+                    config = JsonHelper.DeserializeFromFile(path, _serializerContext.InputConfig);
+                }
+                catch (JsonException) { }
+                catch (InvalidOperationException)
+                {
+                    Logger.Error?.Print(LogClass.Configuration, $"Profile {ProfileName} is incompatible with the current input configuration system.");
+
+                    await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogProfileInvalidProfileErrorMessage, ProfileName));
+
+                    return;
+                }
+            }
+
+            if (config != null)
+            {
+                _isLoaded = false;
+
+                LoadConfiguration(config);
+
+                LoadDevice();
+
+                _isLoaded = true;
+
+                NotifyChanges();
+            }
+        }
+
+        public async void SaveProfile()
+        {
+            if (Device == 0)
+            {
+                return;
+            }
+
+            if (Configuration == null)
+            {
+                return;
+            }
+
+            if (ProfileName == LocaleManager.Instance[LocaleKeys.ControllerSettingsProfileDefault])
+            {
+                await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogProfileDefaultProfileOverwriteErrorMessage]);
+
+                return;
+            }
+
+            bool validFileName = ProfileName.IndexOfAny(Path.GetInvalidFileNameChars()) == -1;
+
+            if (validFileName)
+            {
+                string path = Path.Combine(GetProfileBasePath(), ProfileName + ".json");
+
+                InputConfig config = null;
+
+                if (IsKeyboard)
+                {
+                    config = (Configuration as InputConfiguration<Key, ConfigStickInputId>).GetConfig();
+                }
+                else if (IsController)
+                {
+                    config = (Configuration as InputConfiguration<GamepadInputId, ConfigStickInputId>).GetConfig();
+                }
+
+                config.ControllerType = Controllers[_controller].Type;
+
+                string jsonString = JsonHelper.Serialize(config, _serializerContext.InputConfig);
+
+                await File.WriteAllTextAsync(path, jsonString);
+
+                LoadProfiles();
+            }
+            else
+            {
+                await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogProfileInvalidProfileNameErrorMessage]);
+            }
+        }
+
+        public async void RemoveProfile()
+        {
+            if (Device == 0 || ProfileName == LocaleManager.Instance[LocaleKeys.ControllerSettingsProfileDefault] || ProfilesList.IndexOf(ProfileName) == -1)
+            {
+                return;
+            }
+
+            UserResult result = await ContentDialogHelper.CreateConfirmationDialog(
+                LocaleManager.Instance[LocaleKeys.DialogProfileDeleteProfileTitle],
+                LocaleManager.Instance[LocaleKeys.DialogProfileDeleteProfileMessage],
+                LocaleManager.Instance[LocaleKeys.InputDialogYes],
+                LocaleManager.Instance[LocaleKeys.InputDialogNo],
+                LocaleManager.Instance[LocaleKeys.RyujinxConfirm]);
+
+            if (result == UserResult.Yes)
+            {
+                string path = Path.Combine(GetProfileBasePath(), ProfileName + ".json");
+
+                if (File.Exists(path))
+                {
+                    File.Delete(path);
+                }
+
+                LoadProfiles();
+            }
+        }
+
+        public void Save()
+        {
+            IsModified = false;
+
+            List<InputConfig> newConfig = new();
+
+            newConfig.AddRange(ConfigurationState.Instance.Hid.InputConfig.Value);
+
+            newConfig.Remove(newConfig.Find(x => x == null));
+
+            if (Device == 0)
+            {
+                newConfig.Remove(newConfig.Find(x => x.PlayerIndex == this.PlayerId));
+            }
+            else
+            {
+                var device = Devices[Device];
+
+                if (device.Type == DeviceType.Keyboard)
+                {
+                    var inputConfig = Configuration as InputConfiguration<Key, ConfigStickInputId>;
+                    inputConfig.Id = device.Id;
+                }
+                else
+                {
+                    var inputConfig = Configuration as InputConfiguration<GamepadInputId, ConfigStickInputId>;
+                    inputConfig.Id = device.Id.Split(" ")[0];
+                }
+
+                var config = !IsController
+                    ? (Configuration as InputConfiguration<Key, ConfigStickInputId>).GetConfig()
+                    : (Configuration as InputConfiguration<GamepadInputId, ConfigStickInputId>).GetConfig();
+                config.ControllerType = Controllers[_controller].Type;
+                config.PlayerIndex = _playerId;
+
+                int i = newConfig.FindIndex(x => x.PlayerIndex == PlayerId);
+                if (i == -1)
+                {
+                    newConfig.Add(config);
+                }
+                else
+                {
+                    newConfig[i] = config;
+                }
+            }
+
+            _mainWindow.ViewModel.AppHost?.NpadManager.ReloadConfiguration(newConfig, ConfigurationState.Instance.Hid.EnableKeyboard, ConfigurationState.Instance.Hid.EnableMouse);
+
+            // Atomically replace and signal input change.
+            // NOTE: Do not modify InputConfig.Value directly as other code depends on the on-change event.
+            ConfigurationState.Instance.Hid.InputConfig.Value = newConfig;
+
+            ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
+        }
+
+        public void NotifyChange(string property)
+        {
+            OnPropertyChanged(property);
+        }
+
+        public void NotifyChanges()
+        {
+            OnPropertyChanged(nameof(Configuration));
+            OnPropertyChanged(nameof(IsController));
+            OnPropertyChanged(nameof(ShowSettings));
+            OnPropertyChanged(nameof(IsKeyboard));
+            OnPropertyChanged(nameof(IsRight));
+            OnPropertyChanged(nameof(IsLeft));
+        }
+
+        public void Dispose()
+        {
+            GC.SuppressFinalize(this);
+
+            _mainWindow.InputManager.GamepadDriver.OnGamepadConnected -= HandleOnGamepadConnected;
+            _mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected -= HandleOnGamepadDisconnected;
+
+            _mainWindow.ViewModel.AppHost?.NpadManager.UnblockInputUpdates();
+
+            SelectedGamepad?.Dispose();
+
+            AvaloniaKeyboardDriver.Dispose();
+        }
+    }
+}
diff --git a/src/Ryujinx.Ava/UI/ViewModels/Input/ControllerInputViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/Input/ControllerInputViewModel.cs
deleted file mode 100644
index 0e23dfa7..00000000
--- a/src/Ryujinx.Ava/UI/ViewModels/Input/ControllerInputViewModel.cs
+++ /dev/null
@@ -1,84 +0,0 @@
-using Avalonia.Svg.Skia;
-using Ryujinx.Ava.UI.Models.Input;
-using Ryujinx.Ava.UI.Views.Input;
-
-namespace Ryujinx.Ava.UI.ViewModels.Input
-{
-    public class ControllerInputViewModel : BaseModel
-    {
-        private ControllerInputConfig _config;
-        public ControllerInputConfig Config
-        {
-            get => _config;
-            set
-            {
-                _config = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private bool _isLeft;
-        public bool IsLeft
-        {
-            get => _isLeft;
-            set
-            {
-                _isLeft = value;
-                OnPropertyChanged();
-                OnPropertyChanged(nameof(HasSides));
-            }
-        }
-
-        private bool _isRight;
-        public bool IsRight
-        {
-            get => _isRight;
-            set
-            {
-                _isRight = value;
-                OnPropertyChanged();
-                OnPropertyChanged(nameof(HasSides));
-            }
-        }
-
-        public bool HasSides => IsLeft ^ IsRight;
-
-        private SvgImage _image;
-        public SvgImage Image
-        {
-            get => _image;
-            set
-            {
-                _image = value;
-                OnPropertyChanged();
-            }
-        }
-
-        public InputViewModel parentModel;
-
-        public ControllerInputViewModel(InputViewModel model, ControllerInputConfig config)
-        {
-            parentModel = model;
-            model.NotifyChangesEvent += OnParentModelChanged;
-            OnParentModelChanged();
-            Config = config;
-        }
-
-        public async void ShowMotionConfig()
-        {
-            await MotionInputView.Show(this);
-        }
-
-        public async void ShowRumbleConfig()
-        {
-            await RumbleInputView.Show(this);
-        }
-
-        public void OnParentModelChanged()
-        {
-            IsLeft = parentModel.IsLeft;
-            IsRight = parentModel.IsRight;
-            Image = parentModel.Image;
-        }
-    }
-}
diff --git a/src/Ryujinx.Ava/UI/ViewModels/Input/InputViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/Input/InputViewModel.cs
deleted file mode 100644
index ef8ffd50..00000000
--- a/src/Ryujinx.Ava/UI/ViewModels/Input/InputViewModel.cs
+++ /dev/null
@@ -1,890 +0,0 @@
-using Avalonia;
-using Avalonia.Collections;
-using Avalonia.Controls;
-using Avalonia.Controls.ApplicationLifetimes;
-using Avalonia.Svg.Skia;
-using Avalonia.Threading;
-using Ryujinx.Ava.Common.Locale;
-using Ryujinx.Ava.Input;
-using Ryujinx.Ava.UI.Helpers;
-using Ryujinx.Ava.UI.Models;
-using Ryujinx.Ava.UI.Models.Input;
-using Ryujinx.Ava.UI.Windows;
-using Ryujinx.Common;
-using Ryujinx.Common.Configuration;
-using Ryujinx.Common.Configuration.Hid;
-using Ryujinx.Common.Configuration.Hid.Controller;
-using Ryujinx.Common.Configuration.Hid.Controller.Motion;
-using Ryujinx.Common.Configuration.Hid.Keyboard;
-using Ryujinx.Common.Logging;
-using Ryujinx.Common.Utilities;
-using Ryujinx.Input;
-using Ryujinx.Ui.Common.Configuration;
-using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.IO;
-using System.Linq;
-using System.Text.Json;
-using ConfigGamepadInputId = Ryujinx.Common.Configuration.Hid.Controller.GamepadInputId;
-using ConfigStickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
-using Key = Ryujinx.Common.Configuration.Hid.Key;
-
-namespace Ryujinx.Ava.UI.ViewModels.Input
-{
-    public class InputViewModel : BaseModel, IDisposable
-    {
-        private const string Disabled = "disabled";
-        private const string ProControllerResource = "Ryujinx.Ui.Common/Resources/Controller_ProCon.svg";
-        private const string JoyConPairResource = "Ryujinx.Ui.Common/Resources/Controller_JoyConPair.svg";
-        private const string JoyConLeftResource = "Ryujinx.Ui.Common/Resources/Controller_JoyConLeft.svg";
-        private const string JoyConRightResource = "Ryujinx.Ui.Common/Resources/Controller_JoyConRight.svg";
-        private const string KeyboardString = "keyboard";
-        private const string ControllerString = "controller";
-        private readonly MainWindow _mainWindow;
-
-        private PlayerIndex _playerId;
-        private int _controller;
-        private int _controllerNumber;
-        private string _controllerImage;
-        private int _device;
-        private object _configViewModel;
-        private string _profileName;
-        private bool _isLoaded;
-
-        private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
-
-        public IGamepadDriver AvaloniaKeyboardDriver { get; }
-        public IGamepad SelectedGamepad { get; private set; }
-
-        public ObservableCollection<PlayerModel> PlayerIndexes { get; set; }
-        public ObservableCollection<(DeviceType Type, string Id, string Name)> Devices { get; set; }
-        internal ObservableCollection<ControllerModel> Controllers { get; set; }
-        public AvaloniaList<string> ProfilesList { get; set; }
-        public AvaloniaList<string> DeviceList { get; set; }
-
-        // XAML Flags
-        public bool ShowSettings => _device > 0;
-        public bool IsController => _device > 1;
-        public bool IsKeyboard => !IsController;
-        public bool IsRight { get; set; }
-        public bool IsLeft { get; set; }
-
-        public bool IsModified { get; set; }
-        public event Action NotifyChangesEvent;
-
-        public object ConfigViewModel
-        {
-            get => _configViewModel;
-            set
-            {
-                _configViewModel = value;
-
-                OnPropertyChanged();
-            }
-        }
-
-        public PlayerIndex PlayerId
-        {
-            get => _playerId;
-            set
-            {
-                if (IsModified)
-                {
-                    return;
-                }
-
-                IsModified = false;
-                _playerId = value;
-
-                if (!Enum.IsDefined(typeof(PlayerIndex), _playerId))
-                {
-                    _playerId = PlayerIndex.Player1;
-                }
-
-                LoadConfiguration();
-                LoadDevice();
-                LoadProfiles();
-
-                _isLoaded = true;
-
-                OnPropertyChanged();
-            }
-        }
-
-        public int Controller
-        {
-            get => _controller;
-            set
-            {
-                _controller = value;
-
-                if (_controller == -1)
-                {
-                    _controller = 0;
-                }
-
-                if (Controllers.Count > 0 && value < Controllers.Count && _controller > -1)
-                {
-                    ControllerType controller = Controllers[_controller].Type;
-
-                    IsLeft = true;
-                    IsRight = true;
-
-                    switch (controller)
-                    {
-                        case ControllerType.Handheld:
-                            ControllerImage = JoyConPairResource;
-                            break;
-                        case ControllerType.ProController:
-                            ControllerImage = ProControllerResource;
-                            break;
-                        case ControllerType.JoyconPair:
-                            ControllerImage = JoyConPairResource;
-                            break;
-                        case ControllerType.JoyconLeft:
-                            ControllerImage = JoyConLeftResource;
-                            IsRight = false;
-                            break;
-                        case ControllerType.JoyconRight:
-                            ControllerImage = JoyConRightResource;
-                            IsLeft = false;
-                            break;
-                    }
-
-                    LoadInputDriver();
-                    LoadProfiles();
-                }
-
-                OnPropertyChanged();
-                NotifyChanges();
-            }
-        }
-
-        public string ControllerImage
-        {
-            get => _controllerImage;
-            set
-            {
-                _controllerImage = value;
-
-                OnPropertyChanged();
-                OnPropertyChanged(nameof(Image));
-            }
-        }
-
-        public SvgImage Image
-        {
-            get
-            {
-                SvgImage image = new();
-
-                if (!string.IsNullOrWhiteSpace(_controllerImage))
-                {
-                    SvgSource source = new();
-
-                    source.Load(EmbeddedResources.GetStream(_controllerImage));
-
-                    image.Source = source;
-                }
-
-                return image;
-            }
-        }
-
-        public string ProfileName
-        {
-            get => _profileName; set
-            {
-                _profileName = value;
-
-                OnPropertyChanged();
-            }
-        }
-
-        public int Device
-        {
-            get => _device;
-            set
-            {
-                _device = value < 0 ? 0 : value;
-
-                if (_device >= Devices.Count)
-                {
-                    return;
-                }
-
-                var selected = Devices[_device].Type;
-
-                if (selected != DeviceType.None)
-                {
-                    LoadControllers();
-
-                    if (_isLoaded)
-                    {
-                        LoadConfiguration(LoadDefaultConfiguration());
-                    }
-                }
-
-                OnPropertyChanged();
-                NotifyChanges();
-            }
-        }
-
-        public InputConfig Config { get; set; }
-
-        public InputViewModel(UserControl owner) : this()
-        {
-            if (Program.PreviewerDetached)
-            {
-                _mainWindow =
-                    (MainWindow)((IClassicDesktopStyleApplicationLifetime)Application.Current
-                        .ApplicationLifetime).MainWindow;
-
-                AvaloniaKeyboardDriver = new AvaloniaKeyboardDriver(owner);
-
-                _mainWindow.InputManager.GamepadDriver.OnGamepadConnected += HandleOnGamepadConnected;
-                _mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected;
-                _mainWindow.ViewModel.AppHost?.NpadManager.BlockInputUpdates();
-
-                _isLoaded = false;
-
-                LoadDevices();
-
-                PlayerId = PlayerIndex.Player1;
-            }
-        }
-
-        public InputViewModel()
-        {
-            PlayerIndexes = new ObservableCollection<PlayerModel>();
-            Controllers = new ObservableCollection<ControllerModel>();
-            Devices = new ObservableCollection<(DeviceType Type, string Id, string Name)>();
-            ProfilesList = new AvaloniaList<string>();
-            DeviceList = new AvaloniaList<string>();
-
-            ControllerImage = ProControllerResource;
-
-            PlayerIndexes.Add(new(PlayerIndex.Player1, LocaleManager.Instance[LocaleKeys.ControllerSettingsPlayer1]));
-            PlayerIndexes.Add(new(PlayerIndex.Player2, LocaleManager.Instance[LocaleKeys.ControllerSettingsPlayer2]));
-            PlayerIndexes.Add(new(PlayerIndex.Player3, LocaleManager.Instance[LocaleKeys.ControllerSettingsPlayer3]));
-            PlayerIndexes.Add(new(PlayerIndex.Player4, LocaleManager.Instance[LocaleKeys.ControllerSettingsPlayer4]));
-            PlayerIndexes.Add(new(PlayerIndex.Player5, LocaleManager.Instance[LocaleKeys.ControllerSettingsPlayer5]));
-            PlayerIndexes.Add(new(PlayerIndex.Player6, LocaleManager.Instance[LocaleKeys.ControllerSettingsPlayer6]));
-            PlayerIndexes.Add(new(PlayerIndex.Player7, LocaleManager.Instance[LocaleKeys.ControllerSettingsPlayer7]));
-            PlayerIndexes.Add(new(PlayerIndex.Player8, LocaleManager.Instance[LocaleKeys.ControllerSettingsPlayer8]));
-            PlayerIndexes.Add(new(PlayerIndex.Handheld, LocaleManager.Instance[LocaleKeys.ControllerSettingsHandheld]));
-        }
-
-        private void LoadConfiguration(InputConfig inputConfig = null)
-        {
-            Config = inputConfig ?? ConfigurationState.Instance.Hid.InputConfig.Value.Find(inputConfig => inputConfig.PlayerIndex == _playerId);
-
-            if (Config is StandardKeyboardInputConfig keyboardInputConfig)
-            {
-                ConfigViewModel = new KeyboardInputViewModel(this, new KeyboardInputConfig(keyboardInputConfig));
-            }
-
-            if (Config is StandardControllerInputConfig controllerInputConfig)
-            {
-                ConfigViewModel = new ControllerInputViewModel(this, new ControllerInputConfig(controllerInputConfig));
-            }
-        }
-
-        public void LoadDevice()
-        {
-            if (Config == null || Config.Backend == InputBackendType.Invalid)
-            {
-                Device = 0;
-            }
-            else
-            {
-                var type = DeviceType.None;
-
-                if (Config is StandardKeyboardInputConfig)
-                {
-                    type = DeviceType.Keyboard;
-                }
-
-                if (Config is StandardControllerInputConfig)
-                {
-                    type = DeviceType.Controller;
-                }
-
-                var item = Devices.FirstOrDefault(x => x.Type == type && x.Id == Config.Id);
-                if (item != default)
-                {
-                    Device = Devices.ToList().FindIndex(x => x.Id == item.Id);
-                }
-                else
-                {
-                    Device = 0;
-                }
-            }
-        }
-
-        private void LoadInputDriver()
-        {
-            if (_device < 0)
-            {
-                return;
-            }
-
-            string id = GetCurrentGamepadId();
-            var type = Devices[Device].Type;
-
-            if (type == DeviceType.None)
-            {
-                return;
-            }
-
-            if (type == DeviceType.Keyboard)
-            {
-                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...
-                    SelectedGamepad = AvaloniaKeyboardDriver.GetGamepad(id);
-                }
-                else
-                {
-                    SelectedGamepad = _mainWindow.InputManager.KeyboardDriver.GetGamepad(id);
-                }
-            }
-            else
-            {
-                SelectedGamepad = _mainWindow.InputManager.GamepadDriver.GetGamepad(id);
-            }
-        }
-
-        private void HandleOnGamepadDisconnected(string id)
-        {
-            Dispatcher.UIThread.Post(() =>
-            {
-                LoadDevices();
-            });
-        }
-
-        private void HandleOnGamepadConnected(string id)
-        {
-            Dispatcher.UIThread.Post(() =>
-            {
-                LoadDevices();
-            });
-        }
-
-        private string GetCurrentGamepadId()
-        {
-            if (_device < 0)
-            {
-                return string.Empty;
-            }
-
-            var device = Devices[Device];
-
-            if (device.Type == DeviceType.None)
-            {
-                return null;
-            }
-
-            return device.Id.Split(" ")[0];
-        }
-
-        public void LoadControllers()
-        {
-            Controllers.Clear();
-
-            if (_playerId == PlayerIndex.Handheld)
-            {
-                Controllers.Add(new(ControllerType.Handheld, LocaleManager.Instance[LocaleKeys.ControllerSettingsControllerTypeHandheld]));
-
-                Controller = 0;
-            }
-            else
-            {
-                Controllers.Add(new(ControllerType.ProController, LocaleManager.Instance[LocaleKeys.ControllerSettingsControllerTypeProController]));
-                Controllers.Add(new(ControllerType.JoyconPair, LocaleManager.Instance[LocaleKeys.ControllerSettingsControllerTypeJoyConPair]));
-                Controllers.Add(new(ControllerType.JoyconLeft, LocaleManager.Instance[LocaleKeys.ControllerSettingsControllerTypeJoyConLeft]));
-                Controllers.Add(new(ControllerType.JoyconRight, LocaleManager.Instance[LocaleKeys.ControllerSettingsControllerTypeJoyConRight]));
-
-                if (Config != null && Controllers.ToList().FindIndex(x => x.Type == Config.ControllerType) != -1)
-                {
-                    Controller = Controllers.ToList().FindIndex(x => x.Type == Config.ControllerType);
-                }
-                else
-                {
-                    Controller = 0;
-                }
-            }
-        }
-
-        private static string GetShortGamepadName(string str)
-        {
-            const string Ellipsis = "...";
-            const int MaxSize = 50;
-
-            if (str.Length > MaxSize)
-            {
-                return $"{str.AsSpan(0, MaxSize - Ellipsis.Length)}{Ellipsis}";
-            }
-
-            return str;
-        }
-
-        private static string GetShortGamepadId(string str)
-        {
-            const string Hyphen = "-";
-            const int Offset = 1;
-
-            return str[(str.IndexOf(Hyphen) + Offset)..];
-        }
-
-        public void LoadDevices()
-        {
-            lock (Devices)
-            {
-                Devices.Clear();
-                DeviceList.Clear();
-                Devices.Add((DeviceType.None, Disabled, LocaleManager.Instance[LocaleKeys.ControllerSettingsDeviceDisabled]));
-
-                foreach (string id in _mainWindow.InputManager.KeyboardDriver.GamepadsIds)
-                {
-                    using IGamepad gamepad = _mainWindow.InputManager.KeyboardDriver.GetGamepad(id);
-
-                    if (gamepad != null)
-                    {
-                        Devices.Add((DeviceType.Keyboard, id, $"{GetShortGamepadName(gamepad.Name)}"));
-                    }
-                }
-
-                foreach (string id in _mainWindow.InputManager.GamepadDriver.GamepadsIds)
-                {
-                    using IGamepad gamepad = _mainWindow.InputManager.GamepadDriver.GetGamepad(id);
-
-                    if (gamepad != null)
-                    {
-                        if (Devices.Any(controller => GetShortGamepadId(controller.Id) == GetShortGamepadId(gamepad.Id)))
-                        {
-                            _controllerNumber++;
-                        }
-
-                        Devices.Add((DeviceType.Controller, id, $"{GetShortGamepadName(gamepad.Name)} ({_controllerNumber})"));
-                    }
-                }
-
-                _controllerNumber = 0;
-
-                DeviceList.AddRange(Devices.Select(x => x.Name));
-                Device = Math.Min(Device, DeviceList.Count);
-            }
-        }
-
-        private string GetProfileBasePath()
-        {
-            string path = AppDataManager.ProfilesDirPath;
-            var type = Devices[Device == -1 ? 0 : Device].Type;
-
-            if (type == DeviceType.Keyboard)
-            {
-                path = Path.Combine(path, KeyboardString);
-            }
-            else if (type == DeviceType.Controller)
-            {
-                path = Path.Combine(path, ControllerString);
-            }
-
-            return path;
-        }
-
-        private void LoadProfiles()
-        {
-            ProfilesList.Clear();
-
-            string basePath = GetProfileBasePath();
-
-            if (!Directory.Exists(basePath))
-            {
-                Directory.CreateDirectory(basePath);
-            }
-
-            ProfilesList.Add((LocaleManager.Instance[LocaleKeys.ControllerSettingsProfileDefault]));
-
-            foreach (string profile in Directory.GetFiles(basePath, "*.json", SearchOption.AllDirectories))
-            {
-                ProfilesList.Add(Path.GetFileNameWithoutExtension(profile));
-            }
-
-            if (string.IsNullOrWhiteSpace(ProfileName))
-            {
-                ProfileName = LocaleManager.Instance[LocaleKeys.ControllerSettingsProfileDefault];
-            }
-        }
-
-        public InputConfig LoadDefaultConfiguration()
-        {
-            var activeDevice = Devices.FirstOrDefault();
-
-            if (Devices.Count > 0 && Device < Devices.Count && Device >= 0)
-            {
-                activeDevice = Devices[Device];
-            }
-
-            InputConfig config;
-            if (activeDevice.Type == DeviceType.Keyboard)
-            {
-                string id = activeDevice.Id;
-
-                config = new StandardKeyboardInputConfig
-                {
-                    Version = InputConfig.CurrentVersion,
-                    Backend = InputBackendType.WindowKeyboard,
-                    Id = id,
-                    ControllerType = ControllerType.ProController,
-                    LeftJoycon = new LeftJoyconCommonConfig<Key>
-                    {
-                        DpadUp = Key.Up,
-                        DpadDown = Key.Down,
-                        DpadLeft = Key.Left,
-                        DpadRight = Key.Right,
-                        ButtonMinus = Key.Minus,
-                        ButtonL = Key.E,
-                        ButtonZl = Key.Q,
-                        ButtonSl = Key.Unbound,
-                        ButtonSr = Key.Unbound,
-                    },
-                    LeftJoyconStick =
-                        new JoyconConfigKeyboardStick<Key>
-                        {
-                            StickUp = Key.W,
-                            StickDown = Key.S,
-                            StickLeft = Key.A,
-                            StickRight = Key.D,
-                            StickButton = Key.F,
-                        },
-                    RightJoycon = new RightJoyconCommonConfig<Key>
-                    {
-                        ButtonA = Key.Z,
-                        ButtonB = Key.X,
-                        ButtonX = Key.C,
-                        ButtonY = Key.V,
-                        ButtonPlus = Key.Plus,
-                        ButtonR = Key.U,
-                        ButtonZr = Key.O,
-                        ButtonSl = Key.Unbound,
-                        ButtonSr = Key.Unbound,
-                    },
-                    RightJoyconStick = new JoyconConfigKeyboardStick<Key>
-                    {
-                        StickUp = Key.I,
-                        StickDown = Key.K,
-                        StickLeft = Key.J,
-                        StickRight = Key.L,
-                        StickButton = Key.H,
-                    },
-                };
-            }
-            else if (activeDevice.Type == DeviceType.Controller)
-            {
-                bool isNintendoStyle = Devices.ToList().Find(x => x.Id == activeDevice.Id).Name.Contains("Nintendo");
-
-                string id = activeDevice.Id.Split(" ")[0];
-
-                config = new StandardControllerInputConfig
-                {
-                    Version = InputConfig.CurrentVersion,
-                    Backend = InputBackendType.GamepadSDL2,
-                    Id = id,
-                    ControllerType = ControllerType.ProController,
-                    DeadzoneLeft = 0.1f,
-                    DeadzoneRight = 0.1f,
-                    RangeLeft = 1.0f,
-                    RangeRight = 1.0f,
-                    TriggerThreshold = 0.5f,
-                    LeftJoycon = new LeftJoyconCommonConfig<ConfigGamepadInputId>
-                    {
-                        DpadUp = ConfigGamepadInputId.DpadUp,
-                        DpadDown = ConfigGamepadInputId.DpadDown,
-                        DpadLeft = ConfigGamepadInputId.DpadLeft,
-                        DpadRight = ConfigGamepadInputId.DpadRight,
-                        ButtonMinus = ConfigGamepadInputId.Minus,
-                        ButtonL = ConfigGamepadInputId.LeftShoulder,
-                        ButtonZl = ConfigGamepadInputId.LeftTrigger,
-                        ButtonSl = ConfigGamepadInputId.Unbound,
-                        ButtonSr = ConfigGamepadInputId.Unbound,
-                    },
-                    LeftJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
-                    {
-                        Joystick = ConfigStickInputId.Left,
-                        StickButton = ConfigGamepadInputId.LeftStick,
-                        InvertStickX = false,
-                        InvertStickY = false,
-                    },
-                    RightJoycon = new RightJoyconCommonConfig<ConfigGamepadInputId>
-                    {
-                        ButtonA = isNintendoStyle ? ConfigGamepadInputId.A : ConfigGamepadInputId.B,
-                        ButtonB = isNintendoStyle ? ConfigGamepadInputId.B : ConfigGamepadInputId.A,
-                        ButtonX = isNintendoStyle ? ConfigGamepadInputId.X : ConfigGamepadInputId.Y,
-                        ButtonY = isNintendoStyle ? ConfigGamepadInputId.Y : ConfigGamepadInputId.X,
-                        ButtonPlus = ConfigGamepadInputId.Plus,
-                        ButtonR = ConfigGamepadInputId.RightShoulder,
-                        ButtonZr = ConfigGamepadInputId.RightTrigger,
-                        ButtonSl = ConfigGamepadInputId.Unbound,
-                        ButtonSr = ConfigGamepadInputId.Unbound,
-                    },
-                    RightJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
-                    {
-                        Joystick = ConfigStickInputId.Right,
-                        StickButton = ConfigGamepadInputId.RightStick,
-                        InvertStickX = false,
-                        InvertStickY = false,
-                    },
-                    Motion = new StandardMotionConfigController
-                    {
-                        MotionBackend = MotionInputBackendType.GamepadDriver,
-                        EnableMotion = true,
-                        Sensitivity = 100,
-                        GyroDeadzone = 1,
-                    },
-                    Rumble = new RumbleConfigController
-                    {
-                        StrongRumble = 1f,
-                        WeakRumble = 1f,
-                        EnableRumble = false,
-                    },
-                };
-            }
-            else
-            {
-                config = new InputConfig();
-            }
-
-            config.PlayerIndex = _playerId;
-
-            return config;
-        }
-
-        public async void LoadProfile()
-        {
-            if (Device == 0)
-            {
-                return;
-            }
-
-            InputConfig config = null;
-
-            if (string.IsNullOrWhiteSpace(ProfileName))
-            {
-                return;
-            }
-
-            if (ProfileName == LocaleManager.Instance[LocaleKeys.ControllerSettingsProfileDefault])
-            {
-                config = LoadDefaultConfiguration();
-            }
-            else
-            {
-                string path = Path.Combine(GetProfileBasePath(), ProfileName + ".json");
-
-                if (!File.Exists(path))
-                {
-                    var index = ProfilesList.IndexOf(ProfileName);
-                    if (index != -1)
-                    {
-                        ProfilesList.RemoveAt(index);
-                    }
-                    return;
-                }
-
-                try
-                {
-                    config = JsonHelper.DeserializeFromFile(path, _serializerContext.InputConfig);
-                }
-                catch (JsonException) { }
-                catch (InvalidOperationException)
-                {
-                    Logger.Error?.Print(LogClass.Configuration, $"Profile {ProfileName} is incompatible with the current input configuration system.");
-
-                    await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogProfileInvalidProfileErrorMessage, ProfileName));
-
-                    return;
-                }
-            }
-
-            if (config != null)
-            {
-                _isLoaded = false;
-
-                LoadConfiguration(config);
-
-                LoadDevice();
-
-                _isLoaded = true;
-
-                NotifyChanges();
-            }
-        }
-
-        public async void SaveProfile()
-        {
-            if (Device == 0)
-            {
-                return;
-            }
-
-            if (ConfigViewModel == null)
-            {
-                return;
-            }
-
-            if (ProfileName == LocaleManager.Instance[LocaleKeys.ControllerSettingsProfileDefault])
-            {
-                await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogProfileDefaultProfileOverwriteErrorMessage]);
-
-                return;
-            }
-            else
-            {
-                bool validFileName = ProfileName.IndexOfAny(Path.GetInvalidFileNameChars()) == -1;
-
-                if (validFileName)
-                {
-                    string path = Path.Combine(GetProfileBasePath(), ProfileName + ".json");
-
-                    InputConfig config = null;
-
-                    if (IsKeyboard)
-                    {
-                        config = (ConfigViewModel as KeyboardInputViewModel).Config.GetConfig();
-                    }
-                    else if (IsController)
-                    {
-                        config = (ConfigViewModel as ControllerInputViewModel).Config.GetConfig();
-                    }
-
-                    config.ControllerType = Controllers[_controller].Type;
-
-                    string jsonString = JsonHelper.Serialize(config, _serializerContext.InputConfig);
-
-                    await File.WriteAllTextAsync(path, jsonString);
-
-                    LoadProfiles();
-                }
-                else
-                {
-                    await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogProfileInvalidProfileNameErrorMessage]);
-                }
-            }
-        }
-
-        public async void RemoveProfile()
-        {
-            if (Device == 0 || ProfileName == LocaleManager.Instance[LocaleKeys.ControllerSettingsProfileDefault] || ProfilesList.IndexOf(ProfileName) == -1)
-            {
-                return;
-            }
-
-            UserResult result = await ContentDialogHelper.CreateConfirmationDialog(
-                LocaleManager.Instance[LocaleKeys.DialogProfileDeleteProfileTitle],
-                LocaleManager.Instance[LocaleKeys.DialogProfileDeleteProfileMessage],
-                LocaleManager.Instance[LocaleKeys.InputDialogYes],
-                LocaleManager.Instance[LocaleKeys.InputDialogNo],
-                LocaleManager.Instance[LocaleKeys.RyujinxConfirm]);
-
-            if (result == UserResult.Yes)
-            {
-                string path = Path.Combine(GetProfileBasePath(), ProfileName + ".json");
-
-                if (File.Exists(path))
-                {
-                    File.Delete(path);
-                }
-
-                LoadProfiles();
-            }
-        }
-
-        public void Save()
-        {
-            IsModified = false;
-
-            List<InputConfig> newConfig = new();
-
-            newConfig.AddRange(ConfigurationState.Instance.Hid.InputConfig.Value);
-
-            newConfig.Remove(newConfig.Find(x => x == null));
-
-            if (Device == 0)
-            {
-                newConfig.Remove(newConfig.Find(x => x.PlayerIndex == this.PlayerId));
-            }
-            else
-            {
-                var device = Devices[Device];
-
-                if (device.Type == DeviceType.Keyboard)
-                {
-                    var inputConfig = (ConfigViewModel as KeyboardInputViewModel).Config;
-                    inputConfig.Id = device.Id;
-                }
-                else
-                {
-                    var inputConfig = (ConfigViewModel as ControllerInputViewModel).Config;
-                    inputConfig.Id = device.Id.Split(" ")[0];
-                }
-
-                var config = !IsController
-                    ? (ConfigViewModel as KeyboardInputViewModel).Config.GetConfig()
-                    : (ConfigViewModel as ControllerInputViewModel).Config.GetConfig();
-                config.ControllerType = Controllers[_controller].Type;
-                config.PlayerIndex = _playerId;
-
-                int i = newConfig.FindIndex(x => x.PlayerIndex == PlayerId);
-                if (i == -1)
-                {
-                    newConfig.Add(config);
-                }
-                else
-                {
-                    newConfig[i] = config;
-                }
-            }
-
-            _mainWindow.ViewModel.AppHost?.NpadManager.ReloadConfiguration(newConfig, ConfigurationState.Instance.Hid.EnableKeyboard, ConfigurationState.Instance.Hid.EnableMouse);
-
-            // Atomically replace and signal input change.
-            // NOTE: Do not modify InputConfig.Value directly as other code depends on the on-change event.
-            ConfigurationState.Instance.Hid.InputConfig.Value = newConfig;
-
-            ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
-        }
-
-        public void NotifyChange(string property)
-        {
-            OnPropertyChanged(property);
-        }
-
-        public void NotifyChanges()
-        {
-            OnPropertyChanged(nameof(ConfigViewModel));
-            OnPropertyChanged(nameof(IsController));
-            OnPropertyChanged(nameof(ShowSettings));
-            OnPropertyChanged(nameof(IsKeyboard));
-            OnPropertyChanged(nameof(IsRight));
-            OnPropertyChanged(nameof(IsLeft));
-            NotifyChangesEvent?.Invoke();
-        }
-
-        public void Dispose()
-        {
-            GC.SuppressFinalize(this);
-
-            _mainWindow.InputManager.GamepadDriver.OnGamepadConnected -= HandleOnGamepadConnected;
-            _mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected -= HandleOnGamepadDisconnected;
-
-            _mainWindow.ViewModel.AppHost?.NpadManager.UnblockInputUpdates();
-
-            SelectedGamepad?.Dispose();
-
-            AvaloniaKeyboardDriver.Dispose();
-        }
-    }
-}
diff --git a/src/Ryujinx.Ava/UI/ViewModels/Input/KeyboardInputViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/Input/KeyboardInputViewModel.cs
deleted file mode 100644
index a9387306..00000000
--- a/src/Ryujinx.Ava/UI/ViewModels/Input/KeyboardInputViewModel.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-using Avalonia.Svg.Skia;
-using Ryujinx.Ava.UI.Models.Input;
-
-namespace Ryujinx.Ava.UI.ViewModels.Input
-{
-    public class KeyboardInputViewModel : BaseModel
-    {
-        private KeyboardInputConfig _config;
-        public KeyboardInputConfig Config
-        {
-            get => _config;
-            set
-            {
-                _config = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private bool _isLeft;
-        public bool IsLeft
-        {
-            get => _isLeft;
-            set
-            {
-                _isLeft = value;
-                OnPropertyChanged();
-                OnPropertyChanged(nameof(HasSides));
-            }
-        }
-
-        private bool _isRight;
-        public bool IsRight
-        {
-            get => _isRight;
-            set
-            {
-                _isRight = value;
-                OnPropertyChanged();
-                OnPropertyChanged(nameof(HasSides));
-            }
-        }
-
-        public bool HasSides => IsLeft ^ IsRight;
-
-        private SvgImage _image;
-        public SvgImage Image
-        {
-            get => _image;
-            set
-            {
-                _image = value;
-                OnPropertyChanged();
-            }
-        }
-
-        public InputViewModel parentModel;
-
-        public KeyboardInputViewModel(InputViewModel model, KeyboardInputConfig config)
-        {
-            parentModel = model;
-            model.NotifyChangesEvent += OnParentModelChanged;
-            OnParentModelChanged();
-            Config = config;
-        }
-
-        public void OnParentModelChanged()
-        {
-            IsLeft = parentModel.IsLeft;
-            IsRight = parentModel.IsRight;
-            Image = parentModel.Image;
-        }
-    }
-}
diff --git a/src/Ryujinx.Ava/UI/ViewModels/Input/MotionInputViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/Input/MotionInputViewModel.cs
deleted file mode 100644
index c9ed8f2d..00000000
--- a/src/Ryujinx.Ava/UI/ViewModels/Input/MotionInputViewModel.cs
+++ /dev/null
@@ -1,93 +0,0 @@
-namespace Ryujinx.Ava.UI.ViewModels.Input
-{
-    public class MotionInputViewModel : BaseModel
-    {
-        private int _slot;
-        public int Slot
-        {
-            get => _slot;
-            set
-            {
-                _slot = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private int _altSlot;
-        public int AltSlot
-        {
-            get => _altSlot;
-            set
-            {
-                _altSlot = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private string _dsuServerHost;
-        public string DsuServerHost
-        {
-            get => _dsuServerHost;
-            set
-            {
-                _dsuServerHost = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private int _dsuServerPort;
-        public int DsuServerPort
-        {
-            get => _dsuServerPort;
-            set
-            {
-                _dsuServerPort = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private bool _mirrorInput;
-        public bool MirrorInput
-        {
-            get => _mirrorInput;
-            set
-            {
-                _mirrorInput = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private int _sensitivity;
-        public int Sensitivity
-        {
-            get => _sensitivity;
-            set
-            {
-                _sensitivity = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private double _gryoDeadzone;
-        public double GyroDeadzone
-        {
-            get => _gryoDeadzone;
-            set
-            {
-                _gryoDeadzone = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private bool _enableCemuHookMotion;
-        public bool EnableCemuHookMotion
-        {
-            get => _enableCemuHookMotion;
-            set
-            {
-                _enableCemuHookMotion = value;
-                OnPropertyChanged();
-            }
-        }
-    }
-}
diff --git a/src/Ryujinx.Ava/UI/ViewModels/Input/RumbleInputViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/Input/RumbleInputViewModel.cs
deleted file mode 100644
index 8ad33cf4..00000000
--- a/src/Ryujinx.Ava/UI/ViewModels/Input/RumbleInputViewModel.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-namespace Ryujinx.Ava.UI.ViewModels.Input
-{
-    public class RumbleInputViewModel : BaseModel
-    {
-        private float _strongRumble;
-        public float StrongRumble
-        {
-            get => _strongRumble;
-            set
-            {
-                _strongRumble = value;
-                OnPropertyChanged();
-            }
-        }
-
-        private float _weakRumble;
-        public float WeakRumble
-        {
-            get => _weakRumble;
-            set
-            {
-                _weakRumble = value;
-                OnPropertyChanged();
-            }
-        }
-    }
-}
diff --git a/src/Ryujinx.Ava/UI/ViewModels/MotionInputViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/MotionInputViewModel.cs
new file mode 100644
index 00000000..0b12a51f
--- /dev/null
+++ b/src/Ryujinx.Ava/UI/ViewModels/MotionInputViewModel.cs
@@ -0,0 +1,93 @@
+namespace Ryujinx.Ava.UI.ViewModels
+{
+    public class MotionInputViewModel : BaseModel
+    {
+        private int _slot;
+        public int Slot
+        {
+            get => _slot;
+            set
+            {
+                _slot = value;
+                OnPropertyChanged();
+            }
+        }
+
+        private int _altSlot;
+        public int AltSlot
+        {
+            get => _altSlot;
+            set
+            {
+                _altSlot = value;
+                OnPropertyChanged();
+            }
+        }
+
+        private string _dsuServerHost;
+        public string DsuServerHost
+        {
+            get => _dsuServerHost;
+            set
+            {
+                _dsuServerHost = value;
+                OnPropertyChanged();
+            }
+        }
+
+        private int _dsuServerPort;
+        public int DsuServerPort
+        {
+            get => _dsuServerPort;
+            set
+            {
+                _dsuServerPort = value;
+                OnPropertyChanged();
+            }
+        }
+
+        private bool _mirrorInput;
+        public bool MirrorInput
+        {
+            get => _mirrorInput;
+            set
+            {
+                _mirrorInput = value;
+                OnPropertyChanged();
+            }
+        }
+
+        private int _sensitivity;
+        public int Sensitivity
+        {
+            get => _sensitivity;
+            set
+            {
+                _sensitivity = value;
+                OnPropertyChanged();
+            }
+        }
+
+        private double _gryoDeadzone;
+        public double GyroDeadzone
+        {
+            get => _gryoDeadzone;
+            set
+            {
+                _gryoDeadzone = value;
+                OnPropertyChanged();
+            }
+        }
+
+        private bool _enableCemuHookMotion;
+        public bool EnableCemuHookMotion
+        {
+            get => _enableCemuHookMotion;
+            set
+            {
+                _enableCemuHookMotion = value;
+                OnPropertyChanged();
+            }
+        }
+    }
+}
diff --git a/src/Ryujinx.Ava/UI/ViewModels/RumbleInputViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/RumbleInputViewModel.cs
new file mode 100644
index 00000000..49de1993
--- /dev/null
+++ b/src/Ryujinx.Ava/UI/ViewModels/RumbleInputViewModel.cs
@@ -0,0 +1,27 @@
+namespace Ryujinx.Ava.UI.ViewModels
+{
+    public class RumbleInputViewModel : BaseModel
+    {
+        private float _strongRumble;
+        public float StrongRumble
+        {
+            get => _strongRumble;
+            set
+            {
+                _strongRumble = value;
+                OnPropertyChanged();
+            }
+        }
+
+        private float _weakRumble;
+        public float WeakRumble
+        {
+            get => _weakRumble;
+            set
+            {
+                _weakRumble = value;
+                OnPropertyChanged();
+            }
+        }
+    }
+}
diff --git a/src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml b/src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml
index 08bdf90f..d636873a 100644
--- a/src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml
+++ b/src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml
@@ -1,11 +1,13 @@
 <UserControl
     xmlns="https://github.com/avaloniaui"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+    xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
     xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
-    xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels.Input"
+    xmlns:models="clr-namespace:Ryujinx.Ava.UI.Models"
+    xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
     xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
     HorizontalAlignment="Stretch"
     VerticalAlignment="Stretch"
@@ -13,7 +15,6 @@
     d:DesignWidth="800"
     x:Class="Ryujinx.Ava.UI.Views.Input.ControllerInputView"
     x:DataType="viewModels:ControllerInputViewModel"
-    x:CompileBindings="True"
     mc:Ignorable="d"
     Focusable="True">
     <Design.DataContext>
@@ -33,10 +34,191 @@
         HorizontalAlignment="Stretch"
         VerticalAlignment="Stretch"
         Orientation="Vertical">
+        <StackPanel
+            Margin="0 0 0 5"
+            Orientation="Vertical"
+            Spacing="5">
+            <Grid>
+                <Grid.ColumnDefinitions>
+                    <ColumnDefinition Width="*" />
+                    <ColumnDefinition Width="10" />
+                    <ColumnDefinition Width="*" />
+                </Grid.ColumnDefinitions>
+                <!-- Player Selection -->
+                <Grid
+                    Grid.Column="0"
+                    Margin="2"
+                    HorizontalAlignment="Stretch"
+                    VerticalAlignment="Center">
+                    <Grid.ColumnDefinitions>
+                        <ColumnDefinition Width="Auto"/>
+                        <ColumnDefinition Width="*" />
+                    </Grid.ColumnDefinitions>
+                    <TextBlock
+                        Margin="5,0,10,0"
+                        Width="90"
+                        HorizontalAlignment="Left"
+                        VerticalAlignment="Center"
+                        Text="{locale:Locale ControllerSettingsPlayer}" />
+                    <ComboBox
+                        Grid.Column="1"
+                        Name="PlayerIndexBox"
+                        HorizontalAlignment="Stretch"
+                        VerticalAlignment="Center"
+                        SelectionChanged="PlayerIndexBox_OnSelectionChanged"
+                        ItemsSource="{Binding PlayerIndexes}"
+                        SelectedIndex="{Binding PlayerId}">
+                        <ComboBox.ItemTemplate>
+                            <DataTemplate>
+                                <TextBlock Text="{Binding Name}" />
+                            </DataTemplate>
+                        </ComboBox.ItemTemplate>
+                    </ComboBox>
+                </Grid>
+                <!-- Profile Selection -->
+                <Grid
+                    Grid.Column="2"
+                    Margin="2"
+                    HorizontalAlignment="Stretch"
+                    VerticalAlignment="Center">
+                    <Grid.ColumnDefinitions>
+                        <ColumnDefinition Width="Auto"/>
+                        <ColumnDefinition Width="*" />
+                        <ColumnDefinition Width="Auto"/>
+                        <ColumnDefinition Width="Auto"/>
+                        <ColumnDefinition Width="Auto"/>
+                    </Grid.ColumnDefinitions>
+                    <TextBlock
+                        Margin="5,0,10,0"
+                        Width="90"
+                        HorizontalAlignment="Left"
+                        VerticalAlignment="Center"
+                        Text="{locale:Locale ControllerSettingsProfile}" />
+                    <ui:FAComboBox
+                        Grid.Column="1"
+                        IsEditable="True"
+                        Name="ProfileBox"
+                        HorizontalAlignment="Stretch"
+                        VerticalAlignment="Center"
+                        SelectedIndex="0"
+                        ItemsSource="{Binding ProfilesList}" 
+                        Text="{Binding ProfileName, Mode=TwoWay}" />
+                    <Button
+                        Grid.Column="2"
+                        MinWidth="0"
+                        Margin="5,0,0,0"
+                        VerticalAlignment="Center"
+                        ToolTip.Tip="{locale:Locale ControllerSettingsLoadProfileToolTip}"
+                        Command="{ReflectionBinding LoadProfile}">
+                        <ui:SymbolIcon
+                            Symbol="Upload"
+                            FontSize="15"
+                            Height="20" />
+                    </Button>
+                    <Button
+                        Grid.Column="3"
+                            MinWidth="0"
+                            Margin="5,0,0,0"
+                            VerticalAlignment="Center"
+                            ToolTip.Tip="{locale:Locale ControllerSettingsSaveProfileToolTip}"
+                            Command="{ReflectionBinding SaveProfile}">
+                        <ui:SymbolIcon
+                            Symbol="Save"
+                            FontSize="15"
+                            Height="20" />
+                    </Button>
+                    <Button
+                        Grid.Column="4"
+                            MinWidth="0"
+                            Margin="5,0,0,0"
+                            VerticalAlignment="Center"
+                            ToolTip.Tip="{locale:Locale ControllerSettingsRemoveProfileToolTip}"
+                            Command="{ReflectionBinding RemoveProfile}">
+                        <ui:SymbolIcon
+                            Symbol="Delete"
+                            FontSize="15"
+                            Height="20" />
+                    </Button>
+                </Grid>
+            </Grid>
+            <Separator />
+            <Grid>
+                <Grid.ColumnDefinitions>
+                    <ColumnDefinition Width="*" />
+                    <ColumnDefinition Width="10" />
+                    <ColumnDefinition Width="*" />
+                </Grid.ColumnDefinitions>
+                <!-- Input Device -->
+                <Grid
+                    Grid.Column="0"
+                    Margin="2"
+                    HorizontalAlignment="Stretch">
+                    <Grid.ColumnDefinitions>
+                        <ColumnDefinition Width="Auto"/>
+                        <ColumnDefinition Width="*"/>
+                        <ColumnDefinition Width="Auto" />
+                    </Grid.ColumnDefinitions>
+                    <TextBlock
+                        Grid.Column="0"
+                        Margin="5,0,10,0"
+                        Width="90"
+                        HorizontalAlignment="Left"
+                        VerticalAlignment="Center"
+                        Text="{locale:Locale ControllerSettingsInputDevice}" />
+                    <ComboBox
+                        Grid.Column="1"
+                        Name="DeviceBox"
+                        HorizontalAlignment="Stretch"
+                        VerticalAlignment="Center"
+                        ItemsSource="{Binding DeviceList}"
+                        SelectedIndex="{Binding Device}" />
+                    <Button
+                        Grid.Column="2"
+                        MinWidth="0"
+                        Margin="5,0,0,0"
+                        VerticalAlignment="Center"
+                        Command="{ReflectionBinding LoadDevices}">
+                        <ui:SymbolIcon
+                            Symbol="Refresh"
+                            FontSize="15"
+                            Height="20"/>
+                    </Button>
+                </Grid>
+                <!-- Controller Type -->
+                <Grid
+                    Grid.Column="2"
+                    Margin="2"
+                    HorizontalAlignment="Stretch"
+                    VerticalAlignment="Center">
+                    <Grid.ColumnDefinitions>
+                        <ColumnDefinition Width="Auto"/>
+                        <ColumnDefinition Width="*" />
+                    </Grid.ColumnDefinitions>
+                    <TextBlock
+                        Margin="5,0,10,0"
+                        Width="90"
+                        HorizontalAlignment="Left"
+                        VerticalAlignment="Center"
+                        Text="{locale:Locale ControllerSettingsControllerType}" />
+                    <ComboBox
+                        Grid.Column="1"
+                        HorizontalAlignment="Stretch"
+                        ItemsSource="{Binding Controllers}"
+                        SelectedIndex="{Binding Controller}">
+                        <ComboBox.ItemTemplate>
+                            <DataTemplate DataType="models:ControllerModel">
+                                <TextBlock Text="{Binding Name}" />
+                            </DataTemplate>
+                        </ComboBox.ItemTemplate>
+                    </ComboBox>
+                </Grid>
+            </Grid>
+        </StackPanel>
         <!-- Button / JoyStick Settings -->
         <Grid
             Name="SettingButtons"
-            MinHeight="450">
+            MinHeight="450"
+            IsVisible="{Binding ShowSettings}">
             <Grid.ColumnDefinitions>
                 <ColumnDefinition Width="Auto" />
                 <ColumnDefinition Width="*" />
@@ -75,9 +257,9 @@
                                 VerticalAlignment="Center"
                                 Text="{locale:Locale ControllerSettingsTriggerZL}"
                                 TextAlignment="Center" />
-                            <ToggleButton Name="ButtonZl">
+                            <ToggleButton>
                                 <TextBlock
-                                    Text="{Binding Config.ButtonZl, Converter={StaticResource Key}}"
+                                    Text="{ReflectionBinding Configuration.ButtonZl, Mode=TwoWay, Converter={StaticResource Key}}"
                                     TextAlignment="Center" />
                             </ToggleButton>
                         </StackPanel>
@@ -91,9 +273,9 @@
                                 VerticalAlignment="Center"
                                 Text="{locale:Locale ControllerSettingsTriggerL}"
                                 TextAlignment="Center" />
-                            <ToggleButton Name="ButtonL">
+                            <ToggleButton>
                                 <TextBlock
-                                    Text="{Binding Config.ButtonL, Converter={StaticResource Key}}"
+                                    Text="{ReflectionBinding Configuration.ButtonL, Mode=TwoWay, Converter={StaticResource Key}}"
                                     TextAlignment="Center" />
                             </ToggleButton>
                         </StackPanel>
@@ -107,9 +289,9 @@
                                 VerticalAlignment="Center"
                                 Text="{locale:Locale ControllerSettingsButtonMinus}"
                                 TextAlignment="Center" />
-                            <ToggleButton Name="ButtonMinus">
+                            <ToggleButton>
                                 <TextBlock
-                                    Text="{Binding Config.ButtonMinus, Converter={StaticResource Key}}"
+                                    Text="{ReflectionBinding Configuration.ButtonMinus, Mode=TwoWay, Converter={StaticResource Key}}"
                                     TextAlignment="Center" />
                             </ToggleButton>
                         </StackPanel>
@@ -129,8 +311,100 @@
                             Margin="0,0,0,10"
                             HorizontalAlignment="Center"
                             Text="{locale:Locale ControllerSettingsLStick}" />
+                        <!-- Left Joystick Keyboard -->
+                        <StackPanel
+                            IsVisible="{Binding !IsController}"
+                            Orientation="Vertical">
+                            <!-- Left Joystick Button -->
+                            <StackPanel
+                                Margin="0,0,0,4"
+                                Orientation="Horizontal">
+                                <TextBlock
+                                    Margin="0,0,10,0"
+                                    Width="120"
+                                    HorizontalAlignment="Center"
+                                    VerticalAlignment="Center"
+                                    Text="{locale:Locale ControllerSettingsStickButton}"
+                                    TextAlignment="Center" />
+                                <ToggleButton>
+                                    <TextBlock
+                                        Text="{ReflectionBinding Configuration.LeftKeyboardStickButton, Mode=TwoWay, Converter={StaticResource Key}}"
+                                        TextAlignment="Center" />
+                                </ToggleButton>
+                            </StackPanel>
+                            <!-- Left Joystick Up -->
+                            <StackPanel
+                                Margin="0,0,0,4"
+                                Orientation="Horizontal">
+                                <TextBlock
+                                    Margin="0,0,10,0"
+                                    Width="120"
+                                    HorizontalAlignment="Center"
+                                    VerticalAlignment="Center"
+                                    Text="{locale:Locale ControllerSettingsStickUp}"
+                                    TextAlignment="Center" />
+                                <ToggleButton>
+                                    <TextBlock
+                                        Text="{ReflectionBinding Configuration.LeftStickUp, Mode=TwoWay, Converter={StaticResource Key}}"
+                                        TextAlignment="Center" />
+                                </ToggleButton>
+                            </StackPanel>
+                            <!-- Left Joystick Down -->
+                            <StackPanel
+                                Margin="0,0,0,4"
+                                Orientation="Horizontal">
+                                <TextBlock
+                                    Margin="0,0,10,0"
+                                    Width="120"
+                                    HorizontalAlignment="Center"
+                                    VerticalAlignment="Center"
+                                    Text="{locale:Locale ControllerSettingsStickDown}"
+                                    TextAlignment="Center" />
+                                <ToggleButton>
+                                    <TextBlock
+                                        Text="{ReflectionBinding Configuration.LeftStickDown, Mode=TwoWay, Converter={StaticResource Key}}"
+                                        TextAlignment="Center" />
+                                </ToggleButton>
+                            </StackPanel>
+                            <!-- Left Joystick Left -->
+                            <StackPanel
+                                Margin="0,0,0,4"
+                                Orientation="Horizontal">
+                                <TextBlock
+                                    Margin="0,0,10,0"
+                                    Width="120"
+                                    HorizontalAlignment="Center"
+                                    VerticalAlignment="Center"
+                                    Text="{locale:Locale ControllerSettingsStickLeft}"
+                                    TextAlignment="Center" />
+                                <ToggleButton>
+                                    <TextBlock
+                                        Text="{ReflectionBinding Configuration.LeftStickLeft, Mode=TwoWay, Converter={StaticResource Key}}"
+                                        TextAlignment="Center" />
+                                </ToggleButton>
+                            </StackPanel>
+                            <!-- Left Joystick Right -->
+                            <StackPanel
+                                Margin="0,0,0,4"
+                                Orientation="Horizontal">
+                                <TextBlock
+                                    Margin="0,0,10,0"
+                                    Width="120"
+                                    HorizontalAlignment="Center"
+                                    VerticalAlignment="Center"
+                                    Text="{locale:Locale ControllerSettingsStickRight}"
+                                    TextAlignment="Center" />
+                                <ToggleButton>
+                                    <TextBlock
+                                        Text="{ReflectionBinding Configuration.LeftStickRight, Mode=TwoWay, Converter={StaticResource Key}}"
+                                        TextAlignment="Center" />
+                                </ToggleButton>
+                            </StackPanel>
+                        </StackPanel>
                         <!-- Left Joystick Controller -->
-                        <StackPanel Orientation="Vertical">
+                        <StackPanel
+                            IsVisible="{Binding IsController}"
+                            Orientation="Vertical">
                             <!-- Left Joystick Button -->
                             <StackPanel
                                 Orientation="Horizontal">
@@ -141,9 +415,9 @@
                                     VerticalAlignment="Center"
                                     Text="{locale:Locale ControllerSettingsStickButton}"
                                     TextAlignment="Center" />
-                                <ToggleButton Name="LeftStickButton">
+                                <ToggleButton>
                                     <TextBlock
-                                        Text="{Binding Config.LeftStickButton, Converter={StaticResource Key}}"
+                                        Text="{ReflectionBinding Configuration.LeftControllerStickButton, Mode=TwoWay, Converter={StaticResource Key}}"
                                         TextAlignment="Center" />
                                 </ToggleButton>
                             </StackPanel>
@@ -158,22 +432,22 @@
                                     VerticalAlignment="Center"
                                     Text="{locale:Locale ControllerSettingsStickStick}"
                                     TextAlignment="Center" />
-                                <ToggleButton Name="LeftJoystick" Tag="stick">
+                                <ToggleButton Tag="stick">
                                     <TextBlock
-                                        Text="{Binding Config.LeftJoystick, Converter={StaticResource Key}}"
+                                        Text="{ReflectionBinding Configuration.LeftJoystick, Mode=TwoWay, Converter={StaticResource Key}}"
                                         TextAlignment="Center" />
                                 </ToggleButton>
                             </StackPanel>
                             <Separator
                                 Margin="0,8,0,8"
                                 Height="1" />
-                            <CheckBox IsChecked="{Binding Config.LeftInvertStickX}">
+                            <CheckBox IsChecked="{ReflectionBinding Configuration.LeftInvertStickX}">
                                 <TextBlock Text="{locale:Locale ControllerSettingsStickInvertXAxis}" />
                             </CheckBox>
-                            <CheckBox IsChecked="{Binding Config.LeftInvertStickY}">
+                            <CheckBox IsChecked="{ReflectionBinding Configuration.LeftInvertStickY}">
                                 <TextBlock Text="{locale:Locale ControllerSettingsStickInvertYAxis}" />
                             </CheckBox>
-                            <CheckBox IsChecked="{Binding Config.LeftRotate90}">
+                            <CheckBox IsChecked="{ReflectionBinding Configuration.LeftRotate90}">
                                 <TextBlock Text="{locale:Locale ControllerSettingsRotate90}" />
                             </CheckBox>
                             <Separator
@@ -194,11 +468,11 @@
                                         IsSnapToTickEnabled="True"
                                         SmallChange="0.01"
                                         Minimum="0"
-                                        Value="{Binding Config.DeadzoneLeft, Mode=TwoWay}" />
+                                        Value="{ReflectionBinding Configuration.DeadzoneLeft, Mode=TwoWay}" />
                                     <TextBlock
                                         VerticalAlignment="Center"
                                         Width="25"
-                                        Text="{Binding Config.DeadzoneLeft, StringFormat=\{0:0.00\}}" />
+                                        Text="{ReflectionBinding Configuration.DeadzoneLeft, StringFormat=\{0:0.00\}}" />
                                 </StackPanel>
                                 <TextBlock
                                     HorizontalAlignment="Center"
@@ -214,11 +488,11 @@
                                         IsSnapToTickEnabled="True"
                                         SmallChange="0.01"
                                         Minimum="0"
-                                        Value="{Binding Config.RangeLeft, Mode=TwoWay}" />
+                                        Value="{ReflectionBinding Configuration.RangeLeft, Mode=TwoWay}" />
                                     <TextBlock
                                         VerticalAlignment="Center"
                                         Width="25"
-                                        Text="{Binding Config.RangeLeft, StringFormat=\{0:0.00\}}" />
+                                        Text="{ReflectionBinding Configuration.RangeLeft, StringFormat=\{0:0.00\}}" />
                                 </StackPanel>
                             </StackPanel>
                         </StackPanel>
@@ -251,9 +525,9 @@
                                     VerticalAlignment="Center"
                                     Text="{locale:Locale ControllerSettingsDPadUp}"
                                     TextAlignment="Center" />
-                                <ToggleButton Name="DpadUp">
+                                <ToggleButton>
                                     <TextBlock
-                                        Text="{Binding Config.DpadUp, Converter={StaticResource Key}}"
+                                        Text="{ReflectionBinding Configuration.DpadUp, Mode=TwoWay, Converter={StaticResource Key}}"
                                         TextAlignment="Center" />
                                 </ToggleButton>
                             </StackPanel>
@@ -268,9 +542,9 @@
                                     VerticalAlignment="Center"
                                     Text="{locale:Locale ControllerSettingsDPadDown}"
                                     TextAlignment="Center" />
-                                <ToggleButton Name="DpadDown">
+                                <ToggleButton>
                                     <TextBlock
-                                        Text="{Binding Config.DpadDown, Converter={StaticResource Key}}"
+                                        Text="{ReflectionBinding Configuration.DpadDown, Mode=TwoWay, Converter={StaticResource Key}}"
                                         TextAlignment="Center" />
                                 </ToggleButton>
                             </StackPanel>
@@ -285,9 +559,9 @@
                                     VerticalAlignment="Center"
                                     Text="{locale:Locale ControllerSettingsDPadLeft}"
                                     TextAlignment="Center" />
-                                <ToggleButton Name="DpadLeft">
+                                <ToggleButton>
                                     <TextBlock
-                                        Text="{Binding Config.DpadLeft, Converter={StaticResource Key}}"
+                                        Text="{ReflectionBinding Configuration.DpadLeft, Mode=TwoWay, Converter={StaticResource Key}}"
                                         TextAlignment="Center" />
                                 </ToggleButton>
                             </StackPanel>
@@ -302,9 +576,9 @@
                                     VerticalAlignment="Center"
                                     Text="{locale:Locale ControllerSettingsDPadRight}"
                                     TextAlignment="Center" />
-                                <ToggleButton Name="DpadRight">
+                                <ToggleButton>
                                     <TextBlock
-                                        Text="{Binding Config.DpadRight, Converter={StaticResource Key}}"
+                                        Text="{ReflectionBinding Configuration.DpadRight, Mode=TwoWay, Converter={StaticResource Key}}"
                                         TextAlignment="Center" />
                                 </ToggleButton>
                             </StackPanel>
@@ -317,13 +591,6 @@
                 Grid.Column="1"
                 HorizontalAlignment="Stretch"
                 VerticalAlignment="Stretch">
-                <!-- Controller Picture -->
-                <Image
-                    Margin="0,10"
-                    MaxHeight="300"
-                    HorizontalAlignment="Stretch"
-                    VerticalAlignment="Stretch"
-                    Source="{Binding Image}" />
                 <Border
                     BorderBrush="{DynamicResource ThemeControlBorderColor}"
                     BorderThickness="1"
@@ -345,89 +612,92 @@
                                 IsSnapToTickEnabled="True"
                                 SmallChange="0.01"
                                 Minimum="0"
-                                Value="{Binding Config.TriggerThreshold, Mode=TwoWay}" />
+                                Value="{ReflectionBinding Configuration.TriggerThreshold, Mode=TwoWay}" />
                             <TextBlock
                               Width="25"
-                              Text="{Binding Config.TriggerThreshold, StringFormat=\{0:0.00\}}" />
+                              Text="{ReflectionBinding Configuration.TriggerThreshold, StringFormat=\{0:0.00\}}" />
                         </StackPanel>
                         <StackPanel
-                            Orientation="Vertical"
-                            IsVisible="{Binding HasSides}">
-                            <StackPanel
-                                Margin="0,4,0,0"
+                            Margin="0,4,0,0"
+                            HorizontalAlignment="Center"
+                            VerticalAlignment="Center"
+                            IsVisible="{Binding !IsRight}"
+                            Orientation="Horizontal">
+                            <TextBlock
+                                Width="20"
                                 HorizontalAlignment="Center"
                                 VerticalAlignment="Center"
-                                IsVisible="{Binding IsLeft}"
-                                Orientation="Horizontal">
+                                Text="{locale:Locale ControllerSettingsLeftSR}"
+                                TextAlignment="Center" />
+                            <ToggleButton>
                                 <TextBlock
-                                    Width="20"
-                                    HorizontalAlignment="Center"
-                                    VerticalAlignment="Center"
-                                    Text="{locale:Locale ControllerSettingsLeftSR}"
+                                    Text="{ReflectionBinding Configuration.LeftButtonSr, Mode=TwoWay, Converter={StaticResource Key}}"
                                     TextAlignment="Center" />
-                                <ToggleButton Name="LeftButtonSr">
-                                    <TextBlock
-                                        Text="{Binding Config.LeftButtonSr, Converter={StaticResource Key}}"
-                                        TextAlignment="Center" />
-                                </ToggleButton>
-                            </StackPanel>
-                            <StackPanel
-                                Margin="0,4,0,0"
+                            </ToggleButton>
+                        </StackPanel>
+                        <StackPanel
+                            Margin="0,4,0,0"
+                            HorizontalAlignment="Center"
+                            VerticalAlignment="Center"
+                            IsVisible="{Binding !IsRight}"
+                            Orientation="Horizontal">
+                            <TextBlock
+                                Width="20"
                                 HorizontalAlignment="Center"
                                 VerticalAlignment="Center"
-                                IsVisible="{Binding IsLeft}"
-                                Orientation="Horizontal">
+                                Text="{locale:Locale ControllerSettingsLeftSL}"
+                                TextAlignment="Center" />
+                            <ToggleButton>
                                 <TextBlock
-                                    Width="20"
-                                    HorizontalAlignment="Center"
-                                    VerticalAlignment="Center"
-                                    Text="{locale:Locale ControllerSettingsLeftSL}"
+                                    Text="{ReflectionBinding Configuration.LeftButtonSl, Mode=TwoWay, Converter={StaticResource Key}}"
                                     TextAlignment="Center" />
-                                <ToggleButton Name="LeftButtonSl">
-                                    <TextBlock
-                                        Text="{Binding Config.LeftButtonSl, Converter={StaticResource Key}}"
-                                        TextAlignment="Center" />
-                                </ToggleButton>
-                            </StackPanel>
-                            <StackPanel
-                                Margin="0,4,0,0"
+                            </ToggleButton>
+                        </StackPanel>
+                        <StackPanel
+                            Margin="0,4,0,0"
+                            HorizontalAlignment="Center"
+                            VerticalAlignment="Center"
+                            IsVisible="{Binding !IsLeft}"
+                            Orientation="Horizontal">
+                            <TextBlock
+                                Width="20"
                                 HorizontalAlignment="Center"
                                 VerticalAlignment="Center"
-                                IsVisible="{Binding IsRight}"
-                                Orientation="Horizontal">
+                                Text="{locale:Locale ControllerSettingsRightSR}"
+                                TextAlignment="Center" />
+                            <ToggleButton>
                                 <TextBlock
-                                    Width="20"
-                                    HorizontalAlignment="Center"
-                                    VerticalAlignment="Center"
-                                    Text="{locale:Locale ControllerSettingsRightSR}"
+                                    Text="{ReflectionBinding Configuration.RightButtonSr, Mode=TwoWay, Converter={StaticResource Key}}"
                                     TextAlignment="Center" />
-                                <ToggleButton Name="RightButtonSr">
-                                    <TextBlock
-                                        Text="{Binding Config.RightButtonSr, Converter={StaticResource Key}}"
-                                        TextAlignment="Center" />
-                                </ToggleButton>
-                            </StackPanel>
-                            <StackPanel
-                                Margin="0,4,0,0"
+                            </ToggleButton>
+                        </StackPanel>
+                        <StackPanel
+                            Margin="0,4,0,0"
+                            HorizontalAlignment="Center"
+                            VerticalAlignment="Center"
+                            IsVisible="{Binding !IsLeft}"
+                            Orientation="Horizontal">
+                            <TextBlock
+                                Width="20"
                                 HorizontalAlignment="Center"
                                 VerticalAlignment="Center"
-                                IsVisible="{Binding IsRight}"
-                                Orientation="Horizontal">
+                                Text="{locale:Locale ControllerSettingsRightSL}"
+                                TextAlignment="Center" />
+                            <ToggleButton>
                                 <TextBlock
-                                    Width="20"
-                                    HorizontalAlignment="Center"
-                                    VerticalAlignment="Center"
-                                    Text="{locale:Locale ControllerSettingsRightSL}"
+                                    Text="{ReflectionBinding Configuration.RightButtonSl, Mode=TwoWay, Converter={StaticResource Key}}"
                                     TextAlignment="Center" />
-                                <ToggleButton Name="RightButtonSl">
-                                    <TextBlock
-                                        Text="{Binding Config.RightButtonSl, Converter={StaticResource Key}}"
-                                        TextAlignment="Center" />
-                                </ToggleButton>
-                            </StackPanel>
+                            </ToggleButton>
                         </StackPanel>
                     </StackPanel>
                 </Border>
+                <!-- Controller Picture -->
+                <Image
+                    Margin="0,10,0,0"
+                    MaxHeight="300"
+                    HorizontalAlignment="Stretch"
+                    VerticalAlignment="Stretch"
+                    Source="{Binding Image}" />
                 <!-- Motion + Rumble -->
                 <StackPanel
                     Margin="0,10,0,0"
@@ -439,7 +709,8 @@
                         BorderThickness="1"
                         CornerRadius="5"
                         VerticalAlignment="Bottom"
-                        HorizontalAlignment="Stretch">
+                        HorizontalAlignment="Stretch"
+                        IsVisible="{Binding IsController}">
                         <Grid>
                             <Grid.ColumnDefinitions>
                                 <ColumnDefinition Width="*" />
@@ -449,7 +720,7 @@
                                 Margin="10"
                                 MinWidth="0"
                                 Grid.Column="0"
-                                IsChecked="{Binding Config.EnableMotion, Mode=TwoWay}">
+                                IsChecked="{ReflectionBinding Configuration.EnableMotion, Mode=TwoWay}">
                                 <TextBlock Text="{locale:Locale ControllerSettingsMotion}" />
                             </CheckBox>
                             <Button
@@ -465,6 +736,7 @@
                         BorderThickness="1"
                         CornerRadius="5"
                         HorizontalAlignment="Stretch"
+                        IsVisible="{Binding IsController}"
                         Margin="0,-1,0,0">
                         <Grid>
                             <Grid.ColumnDefinitions>
@@ -475,7 +747,7 @@
                                 Margin="10"
                                 MinWidth="0"
                                 Grid.Column="0"
-                                IsChecked="{Binding Config.EnableRumble, Mode=TwoWay}">
+                                IsChecked="{ReflectionBinding Configuration.EnableRumble, Mode=TwoWay}">
                                 <TextBlock Text="{locale:Locale ControllerSettingsRumble}" />
                             </CheckBox>
                             <Button
@@ -521,9 +793,9 @@
                                 VerticalAlignment="Center"
                                 Text="{locale:Locale ControllerSettingsTriggerZR}"
                                 TextAlignment="Center" />
-                            <ToggleButton Name="ButtonZr">
+                            <ToggleButton>
                                 <TextBlock
-                                    Text="{Binding Config.ButtonZr, Converter={StaticResource Key}}"
+                                    Text="{ReflectionBinding Configuration.ButtonZr, Mode=TwoWay, Converter={StaticResource Key}}"
                                     TextAlignment="Center" />
                             </ToggleButton>
                         </StackPanel>
@@ -539,9 +811,9 @@
                                 VerticalAlignment="Center"
                                 Text="{locale:Locale ControllerSettingsTriggerR}"
                                 TextAlignment="Center" />
-                            <ToggleButton Name="ButtonR">
+                            <ToggleButton>
                                 <TextBlock
-                                    Text="{Binding Config.ButtonR, Converter={StaticResource Key}}"
+                                    Text="{ReflectionBinding Configuration.ButtonR, Mode=TwoWay, Converter={StaticResource Key}}"
                                     TextAlignment="Center" />
                             </ToggleButton>
                         </StackPanel>
@@ -557,15 +829,15 @@
                                 VerticalAlignment="Center"
                                 Text="{locale:Locale ControllerSettingsButtonPlus}"
                                 TextAlignment="Center" />
-                            <ToggleButton Name="ButtonPlus">
+                            <ToggleButton>
                                 <TextBlock
-                                    Text="{Binding Config.ButtonPlus, Converter={StaticResource Key}}"
+                                    Text="{ReflectionBinding Configuration.ButtonPlus, Mode=TwoWay, Converter={StaticResource Key}}"
                                     TextAlignment="Center" />
                             </ToggleButton>
                         </StackPanel>
                     </Grid>
                 </Border>
-                <!-- Right Buttons -->
+                <!-- Right Joystick -->
                 <Border
                     BorderBrush="{DynamicResource ThemeControlBorderColor}"
                     BorderThickness="1"
@@ -592,9 +864,9 @@
                                     VerticalAlignment="Center"
                                     Text="{locale:Locale ControllerSettingsButtonA}"
                                     TextAlignment="Center" />
-                                <ToggleButton Name="ButtonA">
+                                <ToggleButton>
                                     <TextBlock
-                                        Text="{Binding Config.ButtonA, Converter={StaticResource Key}}"
+                                        Text="{ReflectionBinding Configuration.ButtonA, Mode=TwoWay, Converter={StaticResource Key}}"
                                         TextAlignment="Center" />
                                 </ToggleButton>
                             </StackPanel>
@@ -609,9 +881,9 @@
                                     VerticalAlignment="Center"
                                     Text="{locale:Locale ControllerSettingsButtonB}"
                                     TextAlignment="Center" />
-                                <ToggleButton Name="ButtonB">
+                                <ToggleButton>
                                     <TextBlock
-                                        Text="{Binding Config.ButtonB, Converter={StaticResource Key}}"
+                                        Text="{ReflectionBinding Configuration.ButtonB, Mode=TwoWay, Converter={StaticResource Key}}"
                                         TextAlignment="Center" />
                                 </ToggleButton>
                             </StackPanel>
@@ -626,9 +898,9 @@
                                     VerticalAlignment="Center"
                                     Text="{locale:Locale ControllerSettingsButtonX}"
                                     TextAlignment="Center" />
-                                <ToggleButton Name="ButtonX">
+                                <ToggleButton>
                                     <TextBlock
-                                        Text="{Binding Config.ButtonX, Converter={StaticResource Key}}"
+                                        Text="{ReflectionBinding Configuration.ButtonX, Mode=TwoWay, Converter={StaticResource Key}}"
                                         TextAlignment="Center" />
                                 </ToggleButton>
                             </StackPanel>
@@ -643,9 +915,9 @@
                                     VerticalAlignment="Center"
                                     Text="{locale:Locale ControllerSettingsButtonY}"
                                     TextAlignment="Center" />
-                                <ToggleButton Name="ButtonY">
+                                <ToggleButton>
                                     <TextBlock
-                                        Text="{Binding Config.ButtonY, Converter={StaticResource Key}}"
+                                        Text="{ReflectionBinding Configuration.ButtonY, Mode=TwoWay, Converter={StaticResource Key}}"
                                         TextAlignment="Center" />
                                 </ToggleButton>
                             </StackPanel>
@@ -665,8 +937,100 @@
                             Margin="0,0,0,10"
                             HorizontalAlignment="Center"
                             Text="{locale:Locale ControllerSettingsRStick}" />
+                        <!-- Right Joystick Keyboard -->
+                        <StackPanel
+                            IsVisible="{Binding !IsController}"
+                            Orientation="Vertical">
+                            <!-- Right Joystick Button -->
+                            <StackPanel
+                                Margin="0,0,0,4"
+                                Orientation="Horizontal">
+                                <TextBlock
+                                    Margin="0,0,10,0"
+                                    Width="120"
+                                    HorizontalAlignment="Center"
+                                    VerticalAlignment="Center"
+                                    Text="{locale:Locale ControllerSettingsStickButton}"
+                                    TextAlignment="Center" />
+                                <ToggleButton>
+                                    <TextBlock
+                                        Text="{ReflectionBinding Configuration.RightKeyboardStickButton, Mode=TwoWay, Converter={StaticResource Key}}"
+                                        TextAlignment="Center" />
+                                </ToggleButton>
+                            </StackPanel>
+                            <!-- Right Joystick Up -->
+                            <StackPanel
+                                Margin="0,0,0,4"
+                                Orientation="Horizontal">
+                                <TextBlock
+                                    Margin="0,0,10,0"
+                                    Width="120"
+                                    HorizontalAlignment="Center"
+                                    VerticalAlignment="Center"
+                                    Text="{locale:Locale ControllerSettingsStickUp}"
+                                    TextAlignment="Center" />
+                                <ToggleButton>
+                                    <TextBlock
+                                        Text="{ReflectionBinding Configuration.RightStickUp, Mode=TwoWay, Converter={StaticResource Key}}"
+                                        TextAlignment="Center" />
+                                </ToggleButton>
+                            </StackPanel>
+                            <!-- Right Joystick Down -->
+                            <StackPanel
+                                Margin="0,0,0,4"
+                                Orientation="Horizontal">
+                                <TextBlock
+                                    Margin="0,0,10,0"
+                                    Width="120"
+                                    HorizontalAlignment="Center"
+                                    VerticalAlignment="Center"
+                                    Text="{locale:Locale ControllerSettingsStickDown}"
+                                    TextAlignment="Center" />
+                                <ToggleButton>
+                                    <TextBlock
+                                        Text="{ReflectionBinding Configuration.RightStickDown, Mode=TwoWay, Converter={StaticResource Key}}"
+                                        TextAlignment="Center" />
+                                </ToggleButton>
+                            </StackPanel>
+                            <!-- Right Joystick Left -->
+                            <StackPanel
+                                Margin="0,0,0,4"
+                                Orientation="Horizontal">
+                                <TextBlock
+                                    Margin="0,0,10,0"
+                                    Width="120"
+                                    HorizontalAlignment="Center"
+                                    VerticalAlignment="Center"
+                                    Text="{locale:Locale ControllerSettingsStickLeft}"
+                                    TextAlignment="Center" />
+                                <ToggleButton>
+                                    <TextBlock
+                                        Text="{ReflectionBinding Configuration.RightStickLeft, Mode=TwoWay, Converter={StaticResource Key}}"
+                                        TextAlignment="Center" />
+                                </ToggleButton>
+                            </StackPanel>
+                            <!-- Right Joystick Right -->
+                            <StackPanel
+                                Margin="0,0,0,4"
+                                Orientation="Horizontal">
+                                <TextBlock
+                                    Margin="0,0,10,0"
+                                    Width="120"
+                                    HorizontalAlignment="Center"
+                                    VerticalAlignment="Center"
+                                    Text="{locale:Locale ControllerSettingsStickRight}"
+                                    TextAlignment="Center" />
+                                <ToggleButton>
+                                    <TextBlock
+                                        Text="{ReflectionBinding Configuration.RightStickRight, Mode=TwoWay, Converter={StaticResource Key}}"
+                                        TextAlignment="Center" />
+                                </ToggleButton>
+                            </StackPanel>
+                        </StackPanel>
                         <!-- Right Joystick Controller -->
-                        <StackPanel Orientation="Vertical">
+                        <StackPanel
+                            IsVisible="{Binding IsController}"
+                            Orientation="Vertical">
                             <!-- Right Joystick Button -->
                             <StackPanel
                                 Orientation="Horizontal">
@@ -677,9 +1041,9 @@
                                     VerticalAlignment="Center"
                                     Text="{locale:Locale ControllerSettingsStickButton}"
                                     TextAlignment="Center" />
-                                <ToggleButton Name="RightStickButton">
+                                <ToggleButton>
                                     <TextBlock
-                                        Text="{Binding Config.RightStickButton, Converter={StaticResource Key}}"
+                                        Text="{ReflectionBinding Configuration.RightControllerStickButton, Mode=TwoWay, Converter={StaticResource Key}}"
                                         TextAlignment="Center" />
                                 </ToggleButton>
                             </StackPanel>
@@ -695,20 +1059,20 @@
                                     VerticalAlignment="Center"
                                     Text="{locale:Locale ControllerSettingsStickStick}"
                                     TextAlignment="Center" />
-                                <ToggleButton Name="RightJoystick" Tag="stick">
+                                <ToggleButton Tag="stick">
                                     <TextBlock
-                                        Text="{Binding Config.RightJoystick, Converter={StaticResource Key}}"
+                                        Text="{ReflectionBinding Configuration.RightJoystick, Mode=TwoWay, Converter={StaticResource Key}}"
                                         TextAlignment="Center" />
                                 </ToggleButton>
                             </StackPanel>
                             <Separator Margin="0,8,0,8" Height="1" />
-                            <CheckBox IsChecked="{Binding Config.RightInvertStickX}">
+                            <CheckBox IsChecked="{ReflectionBinding Configuration.RightInvertStickX}">
                                 <TextBlock Text="{locale:Locale ControllerSettingsStickInvertXAxis}" />
                             </CheckBox>
-                            <CheckBox IsChecked="{Binding Config.RightInvertStickY}">
+                            <CheckBox IsChecked="{ReflectionBinding Configuration.RightInvertStickY}">
                                 <TextBlock Text="{locale:Locale ControllerSettingsStickInvertYAxis}" />
                             </CheckBox>
-                            <CheckBox IsChecked="{Binding Config.RightRotate90}">
+                            <CheckBox IsChecked="{ReflectionBinding Configuration.RightRotate90}">
                                 <TextBlock Text="{locale:Locale ControllerSettingsRotate90}" />
                             </CheckBox>
                             <Separator Margin="0,8,0,8" Height="1" />
@@ -729,11 +1093,11 @@
                                         Padding="0"
                                         VerticalAlignment="Center"
                                         Minimum="0"
-                                        Value="{Binding Config.DeadzoneRight, Mode=TwoWay}" />
+                                        Value="{ReflectionBinding Configuration.DeadzoneRight, Mode=TwoWay}" />
                                     <TextBlock
                                         VerticalAlignment="Center"
                                         Width="25"
-                                        Text="{Binding Config.DeadzoneRight, StringFormat=\{0:0.00\}}" />
+                                        Text="{ReflectionBinding Configuration.DeadzoneRight, StringFormat=\{0:0.00\}}" />
                                 </StackPanel>
                                 <TextBlock
                                     HorizontalAlignment="Center"
@@ -749,11 +1113,11 @@
                                         IsSnapToTickEnabled="True"
                                         SmallChange="0.01"
                                         Minimum="0"
-                                        Value="{Binding Config.RangeRight, Mode=TwoWay}" />
+                                        Value="{ReflectionBinding Configuration.RangeRight, Mode=TwoWay}" />
                                     <TextBlock
                                         VerticalAlignment="Center"
                                         Width="25"
-                                        Text="{Binding Config.RangeRight, StringFormat=\{0:0.00\}}" />
+                                        Text="{ReflectionBinding Configuration.RangeRight, StringFormat=\{0:0.00\}}" />
                                 </StackPanel>
                             </StackPanel>
                         </StackPanel>
diff --git a/src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml.cs
index 52fc6238..35129706 100644
--- a/src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Views/Input/ControllerInputView.axaml.cs
@@ -1,28 +1,35 @@
-using Avalonia;
 using Avalonia.Controls;
 using Avalonia.Controls.Primitives;
 using Avalonia.Input;
 using Avalonia.Interactivity;
 using Avalonia.LogicalTree;
+using Ryujinx.Ava.Common.Locale;
 using Ryujinx.Ava.UI.Helpers;
-using Ryujinx.Ava.UI.ViewModels.Input;
+using Ryujinx.Ava.UI.Models;
+using Ryujinx.Ava.UI.ViewModels;
 using Ryujinx.Common.Configuration.Hid.Controller;
 using Ryujinx.Input;
 using Ryujinx.Input.Assigner;
+using System;
 
 namespace Ryujinx.Ava.UI.Views.Input
 {
     public partial class ControllerInputView : UserControl
     {
+        private bool _dialogOpen;
+
         private ButtonKeyAssigner _currentAssigner;
+        internal ControllerInputViewModel ViewModel { get; set; }
 
         public ControllerInputView()
         {
+            DataContext = ViewModel = new ControllerInputViewModel(this);
+
             InitializeComponent();
 
             foreach (ILogical visual in SettingButtons.GetLogicalDescendants())
             {
-                if (visual is ToggleButton button and not CheckBox)
+                if (visual is ToggleButton button && visual is not CheckBox)
                 {
                     button.IsCheckedChanged += Button_IsCheckedChanged;
                 }
@@ -52,7 +59,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);
 
@@ -60,86 +67,14 @@ namespace Ryujinx.Ava.UI.Views.Input
 
                         PointerPressed += MouseClick;
 
-                        IKeyboard keyboard = (IKeyboard)(DataContext as ControllerInputViewModel).parentModel.AvaloniaKeyboardDriver.GetGamepad("0"); // Open Avalonia keyboard for cancel operations.
+                        IKeyboard keyboard = (IKeyboard)ViewModel.AvaloniaKeyboardDriver.GetGamepad("0"); // Open Avalonia keyboard for cancel operations.
                         IButtonAssigner assigner = CreateButtonAssigner(isStick);
 
                         _currentAssigner.ButtonAssigned += (sender, e) =>
                         {
-                            if (e.ButtonValue.HasValue)
+                            if (e.IsAssigned)
                             {
-                                var viewModel = (DataContext as ControllerInputViewModel);
-                                var buttonValue = e.ButtonValue.Value;
-                                viewModel.parentModel.IsModified = true;
-
-                                switch (button.Name)
-                                {
-                                    case "ButtonZl":
-                                        viewModel.Config.ButtonZl = buttonValue.AsGamepadButtonInputId();
-                                        break;
-                                    case "ButtonL":
-                                        viewModel.Config.ButtonL = buttonValue.AsGamepadButtonInputId();
-                                        break;
-                                    case "ButtonMinus":
-                                        viewModel.Config.ButtonMinus = buttonValue.AsGamepadButtonInputId();
-                                        break;
-                                    case "LeftStickButton":
-                                        viewModel.Config.LeftStickButton = buttonValue.AsGamepadButtonInputId();
-                                        break;
-                                    case "LeftJoystick":
-                                        viewModel.Config.LeftJoystick = buttonValue.AsGamepadStickId();
-                                        break;
-                                    case "DpadUp":
-                                        viewModel.Config.DpadUp = buttonValue.AsGamepadButtonInputId();
-                                        break;
-                                    case "DpadDown":
-                                        viewModel.Config.DpadDown = buttonValue.AsGamepadButtonInputId();
-                                        break;
-                                    case "DpadLeft":
-                                        viewModel.Config.DpadLeft = buttonValue.AsGamepadButtonInputId();
-                                        break;
-                                    case "DpadRight":
-                                        viewModel.Config.DpadRight = buttonValue.AsGamepadButtonInputId();
-                                        break;
-                                    case "LeftButtonSr":
-                                        viewModel.Config.LeftButtonSr = buttonValue.AsGamepadButtonInputId();
-                                        break;
-                                    case "LeftButtonSl":
-                                        viewModel.Config.LeftButtonSl = buttonValue.AsGamepadButtonInputId();
-                                        break;
-                                    case "RightButtonSr":
-                                        viewModel.Config.RightButtonSr = buttonValue.AsGamepadButtonInputId();
-                                        break;
-                                    case "RightButtonSl":
-                                        viewModel.Config.RightButtonSl = buttonValue.AsGamepadButtonInputId();
-                                        break;
-                                    case "ButtonZr":
-                                        viewModel.Config.ButtonZr = buttonValue.AsGamepadButtonInputId();
-                                        break;
-                                    case "ButtonR":
-                                        viewModel.Config.ButtonR = buttonValue.AsGamepadButtonInputId();
-                                        break;
-                                    case "ButtonPlus":
-                                        viewModel.Config.ButtonPlus = buttonValue.AsGamepadButtonInputId();
-                                        break;
-                                    case "ButtonA":
-                                        viewModel.Config.ButtonA = buttonValue.AsGamepadButtonInputId();
-                                        break;
-                                    case "ButtonB":
-                                        viewModel.Config.ButtonB = buttonValue.AsGamepadButtonInputId();
-                                        break;
-                                    case "ButtonX":
-                                        viewModel.Config.ButtonX = buttonValue.AsGamepadButtonInputId();
-                                        break;
-                                    case "ButtonY":
-                                        viewModel.Config.ButtonY = buttonValue.AsGamepadButtonInputId();
-                                        break;
-                                    case "RightStickButton":
-                                        viewModel.Config.RightStickButton = buttonValue.AsGamepadButtonInputId();
-                                        break;
-                                    case "RightJoystick":
-                                        viewModel.Config.RightJoystick = buttonValue.AsGamepadStickId();
-                                        break;
-                                }
+                                ViewModel.IsModified = true;
                             }
                         };
 
@@ -165,29 +100,82 @@ namespace Ryujinx.Ava.UI.Views.Input
             }
         }
 
+        public void SaveCurrentProfile()
+        {
+            ViewModel.Save();
+        }
+
+        private IButtonAssigner CreateButtonAssigner(bool forStick)
+        {
+            IButtonAssigner assigner;
+
+            var device = ViewModel.Devices[ViewModel.Device];
+
+            if (device.Type == DeviceType.Keyboard)
+            {
+                assigner = new KeyboardKeyAssigner((IKeyboard)ViewModel.SelectedGamepad);
+            }
+            else if (device.Type == DeviceType.Controller)
+            {
+                assigner = new GamepadButtonAssigner(ViewModel.SelectedGamepad, (ViewModel.Config as StandardControllerInputConfig).TriggerThreshold, forStick);
+            }
+            else
+            {
+                throw new Exception("Controller not supported");
+            }
+
+            return assigner;
+        }
+
         private void MouseClick(object sender, PointerPressedEventArgs e)
         {
-            bool shouldUnbind = e.GetCurrentPoint(this).Properties.IsMiddleButtonPressed;
+            bool shouldUnbind = false;
+
+            if (e.GetCurrentPoint(this).Properties.IsMiddleButtonPressed)
+            {
+                shouldUnbind = true;
+            }
 
             _currentAssigner?.Cancel(shouldUnbind);
 
             PointerPressed -= MouseClick;
         }
 
-        private IButtonAssigner CreateButtonAssigner(bool forStick)
+        private async void PlayerIndexBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
         {
-            IButtonAssigner assigner;
+            if (ViewModel.IsModified && !_dialogOpen)
+            {
+                _dialogOpen = true;
 
-            assigner = new GamepadButtonAssigner((DataContext as ControllerInputViewModel).parentModel.SelectedGamepad, ((DataContext as ControllerInputViewModel).parentModel.Config as StandardControllerInputConfig).TriggerThreshold, forStick);
+                var result = await ContentDialogHelper.CreateConfirmationDialog(
+                    LocaleManager.Instance[LocaleKeys.DialogControllerSettingsModifiedConfirmMessage],
+                    LocaleManager.Instance[LocaleKeys.DialogControllerSettingsModifiedConfirmSubMessage],
+                    LocaleManager.Instance[LocaleKeys.InputDialogYes],
+                    LocaleManager.Instance[LocaleKeys.InputDialogNo],
+                    LocaleManager.Instance[LocaleKeys.RyujinxConfirm]);
 
-            return assigner;
+                if (result == UserResult.Yes)
+                {
+                    ViewModel.Save();
+                }
+
+                _dialogOpen = false;
+
+                ViewModel.IsModified = false;
+
+                if (e.AddedItems.Count > 0)
+                {
+                    var player = (PlayerModel)e.AddedItems[0];
+                    ViewModel.PlayerId = player.Id;
+                }
+            }
         }
 
-        protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
+        public void Dispose()
         {
-            base.OnDetachedFromVisualTree(e);
             _currentAssigner?.Cancel();
             _currentAssigner = null;
+            ViewModel.Dispose();
         }
     }
 }
diff --git a/src/Ryujinx.Ava/UI/Views/Input/InputView.axaml b/src/Ryujinx.Ava/UI/Views/Input/InputView.axaml
deleted file mode 100644
index b4940941..00000000
--- a/src/Ryujinx.Ava/UI/Views/Input/InputView.axaml
+++ /dev/null
@@ -1,225 +0,0 @@
-<UserControl
-    xmlns="https://github.com/avaloniaui"
-    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
-    xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
-    xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
-    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
-    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
-    xmlns:models="clr-namespace:Ryujinx.Ava.UI.Models"
-    xmlns:views="clr-namespace:Ryujinx.Ava.UI.Views.Input"
-    xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels.Input"
-    HorizontalAlignment="Stretch"
-    VerticalAlignment="Stretch"
-    d:DesignHeight="800"
-    d:DesignWidth="800"
-    x:Class="Ryujinx.Ava.UI.Views.Input.InputView"
-    x:DataType="viewModels:InputViewModel"
-    x:CompileBindings="True"
-    mc:Ignorable="d"
-    Focusable="True">
-    <Design.DataContext>
-        <viewModels:InputViewModel />
-    </Design.DataContext>
-    <UserControl.Styles>
-        <Style Selector="ToggleButton">
-            <Setter Property="Width" Value="90" />
-            <Setter Property="Height" Value="27" />
-            <Setter Property="HorizontalAlignment" Value="Stretch" />
-        </Style>
-    </UserControl.Styles>
-    <StackPanel
-        HorizontalAlignment="Stretch"
-        VerticalAlignment="Stretch"
-        Orientation="Vertical">
-        <StackPanel
-            Margin="0 0 0 5"
-            Orientation="Vertical"
-            Spacing="5">
-            <Grid>
-                <Grid.ColumnDefinitions>
-                    <ColumnDefinition Width="*" />
-                    <ColumnDefinition Width="10" />
-                    <ColumnDefinition Width="*" />
-                </Grid.ColumnDefinitions>
-                <!-- Player Selection -->
-                <Grid
-                    Grid.Column="0"
-                    Margin="2"
-                    HorizontalAlignment="Stretch"
-                    VerticalAlignment="Center">
-                    <Grid.ColumnDefinitions>
-                        <ColumnDefinition Width="Auto"/>
-                        <ColumnDefinition Width="*" />
-                    </Grid.ColumnDefinitions>
-                    <TextBlock
-                        Margin="5,0,10,0"
-                        Width="90"
-                        HorizontalAlignment="Left"
-                        VerticalAlignment="Center"
-                        Text="{locale:Locale ControllerSettingsPlayer}" />
-                    <ComboBox
-                        Grid.Column="1"
-                        Name="PlayerIndexBox"
-                        HorizontalAlignment="Stretch"
-                        VerticalAlignment="Center"
-                        SelectionChanged="PlayerIndexBox_OnSelectionChanged"
-                        ItemsSource="{Binding PlayerIndexes}"
-                        SelectedIndex="{Binding PlayerId}">
-                        <ComboBox.ItemTemplate>
-                            <DataTemplate>
-                                <TextBlock Text="{Binding Name}" />
-                            </DataTemplate>
-                        </ComboBox.ItemTemplate>
-                    </ComboBox>
-                </Grid>
-                <!-- Profile Selection -->
-                <Grid
-                    Grid.Column="2"
-                    Margin="2"
-                    HorizontalAlignment="Stretch"
-                    VerticalAlignment="Center">
-                    <Grid.ColumnDefinitions>
-                        <ColumnDefinition Width="Auto"/>
-                        <ColumnDefinition Width="*" />
-                        <ColumnDefinition Width="Auto"/>
-                        <ColumnDefinition Width="Auto"/>
-                        <ColumnDefinition Width="Auto"/>
-                    </Grid.ColumnDefinitions>
-                    <TextBlock
-                        Margin="5,0,10,0"
-                        Width="90"
-                        HorizontalAlignment="Left"
-                        VerticalAlignment="Center"
-                        Text="{locale:Locale ControllerSettingsProfile}" />
-                    <ui:FAComboBox
-                        Grid.Column="1"
-                        IsEditable="True"
-                        Name="ProfileBox"
-                        HorizontalAlignment="Stretch"
-                        VerticalAlignment="Center"
-                        SelectedIndex="0"
-                        ItemsSource="{Binding ProfilesList}"
-                        Text="{Binding ProfileName, Mode=TwoWay}" />
-                    <Button
-                        Grid.Column="2"
-                        MinWidth="0"
-                        Margin="5,0,0,0"
-                        VerticalAlignment="Center"
-                        ToolTip.Tip="{locale:Locale ControllerSettingsLoadProfileToolTip}"
-                        Command="{Binding LoadProfile}">
-                        <ui:SymbolIcon
-                            Symbol="Upload"
-                            FontSize="15"
-                            Height="20" />
-                    </Button>
-                    <Button
-                        Grid.Column="3"
-                            MinWidth="0"
-                            Margin="5,0,0,0"
-                            VerticalAlignment="Center"
-                            ToolTip.Tip="{locale:Locale ControllerSettingsSaveProfileToolTip}"
-                            Command="{Binding SaveProfile}">
-                        <ui:SymbolIcon
-                            Symbol="Save"
-                            FontSize="15"
-                            Height="20" />
-                    </Button>
-                    <Button
-                        Grid.Column="4"
-                            MinWidth="0"
-                            Margin="5,0,0,0"
-                            VerticalAlignment="Center"
-                            ToolTip.Tip="{locale:Locale ControllerSettingsRemoveProfileToolTip}"
-                            Command="{Binding RemoveProfile}">
-                        <ui:SymbolIcon
-                            Symbol="Delete"
-                            FontSize="15"
-                            Height="20" />
-                    </Button>
-                </Grid>
-            </Grid>
-            <Separator />
-            <Grid>
-                <Grid.ColumnDefinitions>
-                    <ColumnDefinition Width="*" />
-                    <ColumnDefinition Width="10" />
-                    <ColumnDefinition Width="*" />
-                </Grid.ColumnDefinitions>
-                <!-- Input Device -->
-                <Grid
-                    Grid.Column="0"
-                    Margin="2"
-                    HorizontalAlignment="Stretch">
-                    <Grid.ColumnDefinitions>
-                        <ColumnDefinition Width="Auto"/>
-                        <ColumnDefinition Width="*"/>
-                        <ColumnDefinition Width="Auto" />
-                    </Grid.ColumnDefinitions>
-                    <TextBlock
-                        Grid.Column="0"
-                        Margin="5,0,10,0"
-                        Width="90"
-                        HorizontalAlignment="Left"
-                        VerticalAlignment="Center"
-                        Text="{locale:Locale ControllerSettingsInputDevice}" />
-                    <ComboBox
-                        Grid.Column="1"
-                        Name="DeviceBox"
-                        HorizontalAlignment="Stretch"
-                        VerticalAlignment="Center"
-                        ItemsSource="{Binding DeviceList}"
-                        SelectedIndex="{Binding Device}" />
-                    <Button
-                        Grid.Column="2"
-                        MinWidth="0"
-                        Margin="5,0,0,0"
-                        VerticalAlignment="Center"
-                        Command="{Binding LoadDevices}">
-                        <ui:SymbolIcon
-                            Symbol="Refresh"
-                            FontSize="15"
-                            Height="20"/>
-                    </Button>
-                </Grid>
-                <!-- Controller Type -->
-                <Grid
-                    Grid.Column="2"
-                    Margin="2"
-                    HorizontalAlignment="Stretch"
-                    VerticalAlignment="Center">
-                    <Grid.ColumnDefinitions>
-                        <ColumnDefinition Width="Auto"/>
-                        <ColumnDefinition Width="*" />
-                    </Grid.ColumnDefinitions>
-                    <TextBlock
-                        Margin="5,0,10,0"
-                        Width="90"
-                        HorizontalAlignment="Left"
-                        VerticalAlignment="Center"
-                        Text="{locale:Locale ControllerSettingsControllerType}" />
-                    <ComboBox
-                        Grid.Column="1"
-                        HorizontalAlignment="Stretch"
-                        ItemsSource="{Binding Controllers}"
-                        SelectedIndex="{Binding Controller}">
-                        <ComboBox.ItemTemplate>
-                            <DataTemplate DataType="models:ControllerModel">
-                                <TextBlock Text="{Binding Name}" />
-                            </DataTemplate>
-                        </ComboBox.ItemTemplate>
-                    </ComboBox>
-                </Grid>
-            </Grid>
-        </StackPanel>
-        <ContentControl Content="{Binding ConfigViewModel}" IsVisible="{Binding ShowSettings}">
-            <ContentControl.DataTemplates>
-                <DataTemplate DataType="viewModels:ControllerInputViewModel">
-                    <views:ControllerInputView />
-                </DataTemplate>
-                <DataTemplate DataType="viewModels:KeyboardInputViewModel">
-                    <views:KeyboardInputView />
-                </DataTemplate>
-            </ContentControl.DataTemplates>
-        </ContentControl>
-    </StackPanel>
-</UserControl>
diff --git a/src/Ryujinx.Ava/UI/Views/Input/InputView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Input/InputView.axaml.cs
deleted file mode 100644
index 356381a8..00000000
--- a/src/Ryujinx.Ava/UI/Views/Input/InputView.axaml.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-using Avalonia.Controls;
-using Ryujinx.Ava.Common.Locale;
-using Ryujinx.Ava.UI.Helpers;
-using Ryujinx.Ava.UI.Models;
-using Ryujinx.Ava.UI.ViewModels.Input;
-
-namespace Ryujinx.Ava.UI.Views.Input
-{
-    public partial class InputView : UserControl
-    {
-        private bool _dialogOpen;
-        private InputViewModel ViewModel { get; set; }
-
-        public InputView()
-        {
-            DataContext = ViewModel = new InputViewModel(this);
-
-            InitializeComponent();
-        }
-
-        public void SaveCurrentProfile()
-        {
-            ViewModel.Save();
-        }
-
-        private async void PlayerIndexBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
-        {
-            if (ViewModel.IsModified && !_dialogOpen)
-            {
-                _dialogOpen = true;
-
-                var result = await ContentDialogHelper.CreateConfirmationDialog(
-                    LocaleManager.Instance[LocaleKeys.DialogControllerSettingsModifiedConfirmMessage],
-                    LocaleManager.Instance[LocaleKeys.DialogControllerSettingsModifiedConfirmSubMessage],
-                    LocaleManager.Instance[LocaleKeys.InputDialogYes],
-                    LocaleManager.Instance[LocaleKeys.InputDialogNo],
-                    LocaleManager.Instance[LocaleKeys.RyujinxConfirm]);
-
-                if (result == UserResult.Yes)
-                {
-                    ViewModel.Save();
-                }
-
-                _dialogOpen = false;
-
-                ViewModel.IsModified = false;
-
-                if (e.AddedItems.Count > 0)
-                {
-                    var player = (PlayerModel)e.AddedItems[0];
-                    ViewModel.PlayerId = player.Id;
-                }
-            }
-        }
-
-        public void Dispose()
-        {
-            ViewModel.Dispose();
-        }
-    }
-}
diff --git a/src/Ryujinx.Ava/UI/Views/Input/KeyboardInputView.axaml b/src/Ryujinx.Ava/UI/Views/Input/KeyboardInputView.axaml
deleted file mode 100644
index e4566f46..00000000
--- a/src/Ryujinx.Ava/UI/Views/Input/KeyboardInputView.axaml
+++ /dev/null
@@ -1,675 +0,0 @@
-<UserControl
-    xmlns="https://github.com/avaloniaui"
-    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
-    xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
-    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
-    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
-    xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels.Input"
-    xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
-    HorizontalAlignment="Stretch"
-    VerticalAlignment="Stretch"
-    d:DesignHeight="800"
-    d:DesignWidth="800"
-    x:Class="Ryujinx.Ava.UI.Views.Input.KeyboardInputView"
-    x:DataType="viewModels:KeyboardInputViewModel"
-    x:CompileBindings="True"
-    mc:Ignorable="d"
-    Focusable="True">
-    <Design.DataContext>
-        <viewModels:KeyboardInputViewModel />
-    </Design.DataContext>
-    <UserControl.Resources>
-        <helpers:KeyValueConverter x:Key="Key" />
-    </UserControl.Resources>
-    <UserControl.Styles>
-        <Style Selector="ToggleButton">
-            <Setter Property="Width" Value="90" />
-            <Setter Property="Height" Value="27" />
-            <Setter Property="HorizontalAlignment" Value="Stretch" />
-        </Style>
-    </UserControl.Styles>
-    <StackPanel
-        HorizontalAlignment="Stretch"
-        VerticalAlignment="Stretch"
-        Orientation="Vertical">
-        <!-- Button / JoyStick Settings -->
-        <Grid
-            Name="SettingButtons"
-            MinHeight="450">
-            <Grid.ColumnDefinitions>
-                <ColumnDefinition Width="Auto" />
-                <ColumnDefinition Width="*" />
-                <ColumnDefinition Width="Auto" />
-            </Grid.ColumnDefinitions>
-            <!-- Left Controls -->
-            <StackPanel
-                Orientation="Vertical"
-                Margin="0,0,5,0"
-                Grid.Column="0">
-                <!-- Left Triggers -->
-                <Border
-                    BorderBrush="{DynamicResource ThemeControlBorderColor}"
-                    BorderThickness="1"
-                    IsVisible="{Binding IsLeft}"
-                    MinHeight="90"
-                    CornerRadius="5">
-                    <Grid
-                        Margin="10"
-                        HorizontalAlignment="Stretch">
-                        <Grid.ColumnDefinitions>
-                            <ColumnDefinition />
-                            <ColumnDefinition />
-                        </Grid.ColumnDefinitions>
-                        <Grid.RowDefinitions>
-                            <RowDefinition />
-                            <RowDefinition />
-                        </Grid.RowDefinitions>
-                        <StackPanel
-                            Grid.Column="0"
-                            Grid.Row="0"
-                            Orientation="Horizontal">
-                            <TextBlock
-                                Width="20"
-                                HorizontalAlignment="Center"
-                                VerticalAlignment="Center"
-                                Text="{locale:Locale ControllerSettingsTriggerZL}"
-                                TextAlignment="Center" />
-                            <ToggleButton Name="ButtonZl">
-                                <TextBlock
-                                    Text="{Binding Config.ButtonZl, Converter={StaticResource Key}}"
-                                    TextAlignment="Center" />
-                            </ToggleButton>
-                        </StackPanel>
-                        <StackPanel
-                            Grid.Column="0"
-                            Grid.Row="1"
-                            Orientation="Horizontal">
-                            <TextBlock
-                                Width="20"
-                                HorizontalAlignment="Center"
-                                VerticalAlignment="Center"
-                                Text="{locale:Locale ControllerSettingsTriggerL}"
-                                TextAlignment="Center" />
-                            <ToggleButton Name="ButtonL">
-                                <TextBlock
-                                    Text="{Binding Config.ButtonL, Converter={StaticResource Key}}"
-                                    TextAlignment="Center" />
-                            </ToggleButton>
-                        </StackPanel>
-                        <StackPanel
-                            Grid.Column="1"
-                            Grid.Row="1"
-                            Orientation="Horizontal">
-                            <TextBlock
-                                Width="20"
-                                HorizontalAlignment="Center"
-                                VerticalAlignment="Center"
-                                Text="{locale:Locale ControllerSettingsButtonMinus}"
-                                TextAlignment="Center" />
-                            <ToggleButton Name="ButtonMinus">
-                                <TextBlock
-                                    Text="{Binding Config.ButtonMinus, Converter={StaticResource Key}}"
-                                    TextAlignment="Center" />
-                            </ToggleButton>
-                        </StackPanel>
-                    </Grid>
-                </Border>
-                <!-- Left Joystick -->
-                <Border
-                    BorderBrush="{DynamicResource ThemeControlBorderColor}"
-                    BorderThickness="1"
-                    IsVisible="{Binding IsLeft}"
-                    Margin="0,5,0,0"
-                    CornerRadius="5">
-                    <StackPanel
-                        Margin="10"
-                        Orientation="Vertical">
-                        <TextBlock
-                            Margin="0,0,0,10"
-                            HorizontalAlignment="Center"
-                            Text="{locale:Locale ControllerSettingsLStick}" />
-                        <!-- Left Joystick Keyboard -->
-                        <StackPanel Orientation="Vertical">
-                            <!-- Left Joystick Button -->
-                            <StackPanel
-                                Margin="0,0,0,4"
-                                Orientation="Horizontal">
-                                <TextBlock
-                                    Margin="0,0,10,0"
-                                    Width="120"
-                                    HorizontalAlignment="Center"
-                                    VerticalAlignment="Center"
-                                    Text="{locale:Locale ControllerSettingsStickButton}"
-                                    TextAlignment="Center" />
-                                <ToggleButton Name="LeftStickButton">
-                                    <TextBlock
-                                        Text="{Binding Config.LeftStickButton, Converter={StaticResource Key}}"
-                                        TextAlignment="Center" />
-                                </ToggleButton>
-                            </StackPanel>
-                            <!-- Left Joystick Up -->
-                            <StackPanel
-                                Margin="0,0,0,4"
-                                Orientation="Horizontal">
-                                <TextBlock
-                                    Margin="0,0,10,0"
-                                    Width="120"
-                                    HorizontalAlignment="Center"
-                                    VerticalAlignment="Center"
-                                    Text="{locale:Locale ControllerSettingsStickUp}"
-                                    TextAlignment="Center" />
-                                <ToggleButton Name="LeftStickUp">
-                                    <TextBlock
-                                        Text="{Binding Config.LeftStickUp, Converter={StaticResource Key}}"
-                                        TextAlignment="Center" />
-                                </ToggleButton>
-                            </StackPanel>
-                            <!-- Left Joystick Down -->
-                            <StackPanel
-                                Margin="0,0,0,4"
-                                Orientation="Horizontal">
-                                <TextBlock
-                                    Margin="0,0,10,0"
-                                    Width="120"
-                                    HorizontalAlignment="Center"
-                                    VerticalAlignment="Center"
-                                    Text="{locale:Locale ControllerSettingsStickDown}"
-                                    TextAlignment="Center" />
-                                <ToggleButton Name="LeftStickDown">
-                                    <TextBlock
-                                        Text="{Binding Config.LeftStickDown, Converter={StaticResource Key}}"
-                                        TextAlignment="Center" />
-                                </ToggleButton>
-                            </StackPanel>
-                            <!-- Left Joystick Left -->
-                            <StackPanel
-                                Margin="0,0,0,4"
-                                Orientation="Horizontal">
-                                <TextBlock
-                                    Margin="0,0,10,0"
-                                    Width="120"
-                                    HorizontalAlignment="Center"
-                                    VerticalAlignment="Center"
-                                    Text="{locale:Locale ControllerSettingsStickLeft}"
-                                    TextAlignment="Center" />
-                                <ToggleButton Name="LeftStickLeft">
-                                    <TextBlock
-                                        Text="{Binding Config.LeftStickLeft, Converter={StaticResource Key}}"
-                                        TextAlignment="Center" />
-                                </ToggleButton>
-                            </StackPanel>
-                            <!-- Left Joystick Right -->
-                            <StackPanel
-                                Margin="0,0,0,4"
-                                Orientation="Horizontal">
-                                <TextBlock
-                                    Margin="0,0,10,0"
-                                    Width="120"
-                                    HorizontalAlignment="Center"
-                                    VerticalAlignment="Center"
-                                    Text="{locale:Locale ControllerSettingsStickRight}"
-                                    TextAlignment="Center" />
-                                <ToggleButton Name="LeftStickRight">
-                                    <TextBlock
-                                        Text="{Binding Config.LeftStickRight, Converter={StaticResource Key}}"
-                                        TextAlignment="Center" />
-                                </ToggleButton>
-                            </StackPanel>
-                        </StackPanel>
-                    </StackPanel>
-                </Border>
-                <!-- Left DPad -->
-                <Border
-                    BorderBrush="{DynamicResource ThemeControlBorderColor}"
-                    BorderThickness="1"
-                    VerticalAlignment="Top"
-                    IsVisible="{Binding IsLeft}"
-                    Margin="0,5,0,0"
-                    CornerRadius="5">
-                    <StackPanel
-                        Margin="10"
-                        Orientation="Vertical">
-                        <TextBlock
-                            Margin="0,0,0,10"
-                            HorizontalAlignment="Center"
-                            Text="{locale:Locale ControllerSettingsDPad}" />
-                        <StackPanel Orientation="Vertical">
-                            <!-- Left DPad Up -->
-                            <StackPanel
-                                Margin="0,0,0,4"
-                                Orientation="Horizontal">
-                                <TextBlock
-                                    Margin="0,0,10,0"
-                                    Width="120"
-                                    HorizontalAlignment="Center"
-                                    VerticalAlignment="Center"
-                                    Text="{locale:Locale ControllerSettingsDPadUp}"
-                                    TextAlignment="Center" />
-                                <ToggleButton Name="DpadUp">
-                                    <TextBlock
-                                        Text="{Binding Config.DpadUp, Converter={StaticResource Key}}"
-                                        TextAlignment="Center" />
-                                </ToggleButton>
-                            </StackPanel>
-                            <!-- Left DPad Down -->
-                            <StackPanel
-                                Margin="0,0,0,4"
-                                Orientation="Horizontal">
-                                <TextBlock
-                                    Margin="0,0,10,0"
-                                    Width="120"
-                                    HorizontalAlignment="Center"
-                                    VerticalAlignment="Center"
-                                    Text="{locale:Locale ControllerSettingsDPadDown}"
-                                    TextAlignment="Center" />
-                                <ToggleButton Name="DpadDown">
-                                    <TextBlock
-                                        Text="{Binding Config.DpadDown, Converter={StaticResource Key}}"
-                                        TextAlignment="Center" />
-                                </ToggleButton>
-                            </StackPanel>
-                            <!-- Left DPad Left -->
-                            <StackPanel
-                                Margin="0,0,0,4"
-                                Orientation="Horizontal">
-                                <TextBlock
-                                    Margin="0,0,10,0"
-                                    Width="120"
-                                    HorizontalAlignment="Center"
-                                    VerticalAlignment="Center"
-                                    Text="{locale:Locale ControllerSettingsDPadLeft}"
-                                    TextAlignment="Center" />
-                                <ToggleButton Name="DpadLeft">
-                                    <TextBlock
-                                        Text="{Binding Config.DpadLeft, Converter={StaticResource Key}}"
-                                        TextAlignment="Center" />
-                                </ToggleButton>
-                            </StackPanel>
-                            <!-- Left DPad Right -->
-                            <StackPanel
-                                Margin="0,0,0,4"
-                                Orientation="Horizontal">
-                                <TextBlock
-                                    Margin="0,0,10,0"
-                                    Width="120"
-                                    HorizontalAlignment="Center"
-                                    VerticalAlignment="Center"
-                                    Text="{locale:Locale ControllerSettingsDPadRight}"
-                                    TextAlignment="Center" />
-                                <ToggleButton Name="DpadRight">
-                                    <TextBlock
-                                        Text="{Binding Config.DpadRight, Converter={StaticResource Key}}"
-                                        TextAlignment="Center" />
-                                </ToggleButton>
-                            </StackPanel>
-                        </StackPanel>
-                    </StackPanel>
-                </Border>
-            </StackPanel>
-            <!-- Triggers & Side Buttons -->
-            <StackPanel
-                Grid.Column="1"
-                HorizontalAlignment="Stretch"
-                VerticalAlignment="Stretch">
-                <!-- Controller Picture -->
-                <Image
-                    Margin="0,10"
-                    MaxHeight="300"
-                    HorizontalAlignment="Stretch"
-                    VerticalAlignment="Stretch"
-                    Source="{Binding Image}" />
-                <Border
-                    BorderBrush="{DynamicResource ThemeControlBorderColor}"
-                    BorderThickness="1"
-                    CornerRadius="5"
-                    MinHeight="90"
-                    IsVisible="{Binding HasSides}">
-                    <StackPanel
-                        Margin="8"
-                        Orientation="Vertical">
-                        <StackPanel
-                            Margin="0,4,0,0"
-                            HorizontalAlignment="Center"
-                            VerticalAlignment="Center"
-                            IsVisible="{Binding IsLeft}"
-                            Orientation="Horizontal">
-                            <TextBlock
-                                Width="20"
-                                HorizontalAlignment="Center"
-                                VerticalAlignment="Center"
-                                Text="{locale:Locale ControllerSettingsLeftSR}"
-                                TextAlignment="Center" />
-                            <ToggleButton Name="LeftButtonSr">
-                                <TextBlock
-                                    Text="{Binding Config.LeftButtonSr, Converter={StaticResource Key}}"
-                                    TextAlignment="Center" />
-                            </ToggleButton>
-                        </StackPanel>
-                        <StackPanel
-                            Margin="0,4,0,0"
-                            HorizontalAlignment="Center"
-                            VerticalAlignment="Center"
-                            IsVisible="{Binding IsLeft}"
-                            Orientation="Horizontal">
-                            <TextBlock
-                                Width="20"
-                                HorizontalAlignment="Center"
-                                VerticalAlignment="Center"
-                                Text="{locale:Locale ControllerSettingsLeftSL}"
-                                TextAlignment="Center" />
-                            <ToggleButton Name="LeftButtonSl">
-                                <TextBlock
-                                    Text="{Binding Config.LeftButtonSl, Converter={StaticResource Key}}"
-                                    TextAlignment="Center" />
-                            </ToggleButton>
-                        </StackPanel>
-                        <StackPanel
-                            Margin="0,4,0,0"
-                            HorizontalAlignment="Center"
-                            VerticalAlignment="Center"
-                            IsVisible="{Binding IsRight}"
-                            Orientation="Horizontal">
-                            <TextBlock
-                                Width="20"
-                                HorizontalAlignment="Center"
-                                VerticalAlignment="Center"
-                                Text="{locale:Locale ControllerSettingsRightSR}"
-                                TextAlignment="Center" />
-                            <ToggleButton Name="RightButtonSr">
-                                <TextBlock
-                                    Text="{Binding Config.RightButtonSr, Converter={StaticResource Key}}"
-                                    TextAlignment="Center" />
-                            </ToggleButton>
-                        </StackPanel>
-                        <StackPanel
-                            Margin="0,4,0,0"
-                            HorizontalAlignment="Center"
-                            VerticalAlignment="Center"
-                            IsVisible="{Binding IsRight}"
-                            Orientation="Horizontal">
-                            <TextBlock
-                                Width="20"
-                                HorizontalAlignment="Center"
-                                VerticalAlignment="Center"
-                                Text="{locale:Locale ControllerSettingsRightSL}"
-                                TextAlignment="Center" />
-                            <ToggleButton Name="RightButtonSl">
-                                <TextBlock
-                                    Text="{Binding Config.RightButtonSl, Converter={StaticResource Key}}"
-                                    TextAlignment="Center" />
-                            </ToggleButton>
-                        </StackPanel>
-                    </StackPanel>
-                </Border>
-            </StackPanel>
-            <!-- Right Controls -->
-            <StackPanel
-                Orientation="Vertical"
-                Margin="5,0,0,0"
-                Grid.Column="2">
-                <!-- Right Triggers -->
-                <Border
-                    BorderBrush="{DynamicResource ThemeControlBorderColor}"
-                    BorderThickness="1"
-                    IsVisible="{Binding IsRight}"
-                    MinHeight="90"
-                    CornerRadius="5">
-                    <Grid
-                        Margin="10"
-                        HorizontalAlignment="Stretch">
-                        <Grid.ColumnDefinitions>
-                            <ColumnDefinition />
-                            <ColumnDefinition />
-                        </Grid.ColumnDefinitions>
-                        <Grid.RowDefinitions>
-                            <RowDefinition />
-                            <RowDefinition />
-                        </Grid.RowDefinitions>
-                        <StackPanel
-                            Grid.Column="1"
-                            Grid.Row="0"
-                            Orientation="Horizontal">
-                            <TextBlock
-                                Width="20"
-                                HorizontalAlignment="Center"
-                                VerticalAlignment="Center"
-                                Text="{locale:Locale ControllerSettingsTriggerZR}"
-                                TextAlignment="Center" />
-                            <ToggleButton Name="ButtonZr">
-                                <TextBlock
-                                    Text="{Binding Config.ButtonZr, Converter={StaticResource Key}}"
-                                    TextAlignment="Center" />
-                            </ToggleButton>
-                        </StackPanel>
-                        <StackPanel
-                            Grid.Column="1"
-                            Grid.Row="1"
-                            HorizontalAlignment="Center"
-                            VerticalAlignment="Center"
-                            Orientation="Horizontal">
-                            <TextBlock
-                                Width="20"
-                                HorizontalAlignment="Center"
-                                VerticalAlignment="Center"
-                                Text="{locale:Locale ControllerSettingsTriggerR}"
-                                TextAlignment="Center" />
-                            <ToggleButton Name="ButtonR">
-                                <TextBlock
-                                    Text="{Binding Config.ButtonR, Converter={StaticResource Key}}"
-                                    TextAlignment="Center" />
-                            </ToggleButton>
-                        </StackPanel>
-                        <StackPanel
-                            Grid.Column="0"
-                            Grid.Row="1"
-                            HorizontalAlignment="Right"
-                            VerticalAlignment="Center"
-                            Orientation="Horizontal">
-                            <TextBlock
-                                Width="20"
-                                HorizontalAlignment="Center"
-                                VerticalAlignment="Center"
-                                Text="{locale:Locale ControllerSettingsButtonPlus}"
-                                TextAlignment="Center" />
-                            <ToggleButton Name="ButtonPlus">
-                                <TextBlock
-                                    Text="{Binding Config.ButtonPlus, Converter={StaticResource Key}}"
-                                    TextAlignment="Center" />
-                            </ToggleButton>
-                        </StackPanel>
-                    </Grid>
-                </Border>
-                <!-- Right Buttons -->
-                <Border
-                    BorderBrush="{DynamicResource ThemeControlBorderColor}"
-                    BorderThickness="1"
-                    IsVisible="{Binding IsRight}"
-                    Margin="0,5,0,0"
-                    CornerRadius="5">
-                    <StackPanel
-                        Margin="10"
-                        Orientation="Vertical">
-                        <TextBlock
-                            Margin="0,0,0,10"
-                            HorizontalAlignment="Center"
-                            Text="{locale:Locale ControllerSettingsButtons}" />
-                        <StackPanel
-                            Orientation="Vertical">
-                            <!-- Right Buttons A -->
-                            <StackPanel
-                                Margin="0,0,0,4"
-                                Orientation="Horizontal">
-                                <TextBlock
-                                    Width="120"
-                                    Margin="0,0,10,0"
-                                    HorizontalAlignment="Center"
-                                    VerticalAlignment="Center"
-                                    Text="{locale:Locale ControllerSettingsButtonA}"
-                                    TextAlignment="Center" />
-                                <ToggleButton Name="ButtonA">
-                                    <TextBlock
-                                        Text="{Binding Config.ButtonA, Converter={StaticResource Key}}"
-                                        TextAlignment="Center" />
-                                </ToggleButton>
-                            </StackPanel>
-                            <!-- Right Buttons B -->
-                            <StackPanel
-                                Margin="0,0,0,4"
-                                Orientation="Horizontal">
-                                <TextBlock
-                                    Width="120"
-                                    Margin="0,0,10,0"
-                                    HorizontalAlignment="Center"
-                                    VerticalAlignment="Center"
-                                    Text="{locale:Locale ControllerSettingsButtonB}"
-                                    TextAlignment="Center" />
-                                <ToggleButton Name="ButtonB">
-                                    <TextBlock
-                                        Text="{Binding Config.ButtonB, Converter={StaticResource Key}}"
-                                        TextAlignment="Center" />
-                                </ToggleButton>
-                            </StackPanel>
-                            <!-- Right Buttons X -->
-                            <StackPanel
-                                Margin="0,0,0,4"
-                                Orientation="Horizontal">
-                                <TextBlock
-                                    Width="120"
-                                    Margin="0,0,10,0"
-                                    HorizontalAlignment="Center"
-                                    VerticalAlignment="Center"
-                                    Text="{locale:Locale ControllerSettingsButtonX}"
-                                    TextAlignment="Center" />
-                                <ToggleButton Name="ButtonX">
-                                    <TextBlock
-                                        Text="{Binding Config.ButtonX, Converter={StaticResource Key}}"
-                                        TextAlignment="Center" />
-                                </ToggleButton>
-                            </StackPanel>
-                            <!-- Right Buttons Y -->
-                            <StackPanel
-                                Margin="0,0,0,4"
-                                Orientation="Horizontal">
-                                <TextBlock
-                                    Width="120"
-                                    Margin="0,0,10,0"
-                                    HorizontalAlignment="Center"
-                                    VerticalAlignment="Center"
-                                    Text="{locale:Locale ControllerSettingsButtonY}"
-                                    TextAlignment="Center" />
-                                <ToggleButton Name="ButtonY">
-                                    <TextBlock
-                                        Text="{Binding Config.ButtonY, Converter={StaticResource Key}}"
-                                        TextAlignment="Center" />
-                                </ToggleButton>
-                            </StackPanel>
-                        </StackPanel>
-                    </StackPanel>
-                </Border>
-                <!-- Right DPad -->
-                <Border
-                    Padding="10"
-                    BorderBrush="{DynamicResource ThemeControlBorderColor}"
-                    BorderThickness="1"
-                    CornerRadius="5"
-                    IsVisible="{Binding IsRight}"
-                    Margin="0,5,0,0">
-                    <StackPanel Orientation="Vertical">
-                        <TextBlock
-                            Margin="0,0,0,10"
-                            HorizontalAlignment="Center"
-                            Text="{locale:Locale ControllerSettingsRStick}" />
-                        <!-- Right Joystick Keyboard -->
-                        <StackPanel Orientation="Vertical">
-                            <!-- Right Joystick Button -->
-                            <StackPanel
-                                Margin="0,0,0,4"
-                                Orientation="Horizontal">
-                                <TextBlock
-                                    Margin="0,0,10,0"
-                                    Width="120"
-                                    HorizontalAlignment="Center"
-                                    VerticalAlignment="Center"
-                                    Text="{locale:Locale ControllerSettingsStickButton}"
-                                    TextAlignment="Center" />
-                                <ToggleButton Name="RightStickButton">
-                                    <TextBlock
-                                        Text="{Binding Config.RightStickButton, Converter={StaticResource Key}}"
-                                        TextAlignment="Center" />
-                                </ToggleButton>
-                            </StackPanel>
-                            <!-- Right Joystick Up -->
-                            <StackPanel
-                                Margin="0,0,0,4"
-                                Orientation="Horizontal">
-                                <TextBlock
-                                    Margin="0,0,10,0"
-                                    Width="120"
-                                    HorizontalAlignment="Center"
-                                    VerticalAlignment="Center"
-                                    Text="{locale:Locale ControllerSettingsStickUp}"
-                                    TextAlignment="Center" />
-                                <ToggleButton Name="RightStickUp">
-                                    <TextBlock
-                                        Text="{Binding Config.RightStickUp, Converter={StaticResource Key}}"
-                                        TextAlignment="Center" />
-                                </ToggleButton>
-                            </StackPanel>
-                            <!-- Right Joystick Down -->
-                            <StackPanel
-                                Margin="0,0,0,4"
-                                Orientation="Horizontal">
-                                <TextBlock
-                                    Margin="0,0,10,0"
-                                    Width="120"
-                                    HorizontalAlignment="Center"
-                                    VerticalAlignment="Center"
-                                    Text="{locale:Locale ControllerSettingsStickDown}"
-                                    TextAlignment="Center" />
-                                <ToggleButton Name="RightStickDown">
-                                    <TextBlock
-                                        Text="{Binding Config.RightStickDown, Converter={StaticResource Key}}"
-                                        TextAlignment="Center" />
-                                </ToggleButton>
-                            </StackPanel>
-                            <!-- Right Joystick Left -->
-                            <StackPanel
-                                Margin="0,0,0,4"
-                                Orientation="Horizontal">
-                                <TextBlock
-                                    Margin="0,0,10,0"
-                                    Width="120"
-                                    HorizontalAlignment="Center"
-                                    VerticalAlignment="Center"
-                                    Text="{locale:Locale ControllerSettingsStickLeft}"
-                                    TextAlignment="Center" />
-                                <ToggleButton Name="RightStickLeft">
-                                    <TextBlock
-                                        Text="{Binding Config.RightStickLeft, Converter={StaticResource Key}}"
-                                        TextAlignment="Center" />
-                                </ToggleButton>
-                            </StackPanel>
-                            <!-- Right Joystick Right -->
-                            <StackPanel
-                                Margin="0,0,0,4"
-                                Orientation="Horizontal">
-                                <TextBlock
-                                    Margin="0,0,10,0"
-                                    Width="120"
-                                    HorizontalAlignment="Center"
-                                    VerticalAlignment="Center"
-                                    Text="{locale:Locale ControllerSettingsStickRight}"
-                                    TextAlignment="Center" />
-                                <ToggleButton Name="RightStickRight">
-                                    <TextBlock
-                                        Text="{Binding Config.RightStickRight, Converter={StaticResource Key}}"
-                                        TextAlignment="Center" />
-                                </ToggleButton>
-                            </StackPanel>
-                        </StackPanel>
-                    </StackPanel>
-                </Border>
-            </StackPanel>
-        </Grid>
-    </StackPanel>
-</UserControl>
\ No newline at end of file
diff --git a/src/Ryujinx.Ava/UI/Views/Input/KeyboardInputView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Input/KeyboardInputView.axaml.cs
deleted file mode 100644
index f7024c5d..00000000
--- a/src/Ryujinx.Ava/UI/Views/Input/KeyboardInputView.axaml.cs
+++ /dev/null
@@ -1,210 +0,0 @@
-using Avalonia;
-using Avalonia.Controls;
-using Avalonia.Controls.Primitives;
-using Avalonia.Input;
-using Avalonia.Interactivity;
-using Avalonia.LogicalTree;
-using Ryujinx.Ava.UI.Helpers;
-using Ryujinx.Ava.UI.ViewModels.Input;
-using Ryujinx.Input;
-using Ryujinx.Input.Assigner;
-
-namespace Ryujinx.Ava.UI.Views.Input
-{
-    public partial class KeyboardInputView : UserControl
-    {
-        private ButtonKeyAssigner _currentAssigner;
-
-        public KeyboardInputView()
-        {
-            InitializeComponent();
-
-            foreach (ILogical visual in SettingButtons.GetLogicalDescendants())
-            {
-                if (visual is ToggleButton button and not CheckBox)
-                {
-                    button.IsCheckedChanged += Button_IsCheckedChanged;
-                }
-            }
-        }
-
-        protected override void OnPointerReleased(PointerReleasedEventArgs e)
-        {
-            base.OnPointerReleased(e);
-
-            if (_currentAssigner != null && _currentAssigner.ToggledButton != null && !_currentAssigner.ToggledButton.IsPointerOver)
-            {
-                _currentAssigner.Cancel();
-            }
-        }
-
-        private void Button_IsCheckedChanged(object sender, RoutedEventArgs e)
-        {
-            if (sender is ToggleButton button)
-            {
-                if ((bool)button.IsChecked)
-                {
-                    if (_currentAssigner != null && button == _currentAssigner.ToggledButton)
-                    {
-                        return;
-                    }
-
-                    bool isStick = button.Tag != null && button.Tag.ToString() == "stick";
-
-                    if (_currentAssigner == null && (bool)button.IsChecked)
-                    {
-                        _currentAssigner = new ButtonKeyAssigner(button);
-
-                        this.Focus(NavigationMethod.Pointer);
-
-                        PointerPressed += MouseClick;
-
-                        IKeyboard keyboard = (IKeyboard)(DataContext as KeyboardInputViewModel).parentModel.AvaloniaKeyboardDriver.GetGamepad("0"); // Open Avalonia keyboard for cancel operations.
-                        IButtonAssigner assigner = CreateButtonAssigner(isStick);
-
-                        _currentAssigner.ButtonAssigned += (sender, e) =>
-                        {
-                            if (e.ButtonValue.HasValue)
-                            {
-                                var viewModel = (DataContext as KeyboardInputViewModel);
-                                var buttonValue = e.ButtonValue.Value;
-                                viewModel.parentModel.IsModified = true;
-
-                                switch (button.Name)
-                                {
-                                    case "ButtonZl":
-                                        viewModel.Config.ButtonZl = buttonValue.AsKey();
-                                        break;
-                                    case "ButtonL":
-                                        viewModel.Config.ButtonL = buttonValue.AsKey();
-                                        break;
-                                    case "ButtonMinus":
-                                        viewModel.Config.ButtonMinus = buttonValue.AsKey();
-                                        break;
-                                    case "LeftStickButton":
-                                        viewModel.Config.LeftStickButton = buttonValue.AsKey();
-                                        break;
-                                    case "LeftStickUp":
-                                        viewModel.Config.LeftStickUp = buttonValue.AsKey();
-                                        break;
-                                    case "LeftStickDown":
-                                        viewModel.Config.LeftStickDown = buttonValue.AsKey();
-                                        break;
-                                    case "LeftStickRight":
-                                        viewModel.Config.LeftStickRight = buttonValue.AsKey();
-                                        break;
-                                    case "LeftStickLeft":
-                                        viewModel.Config.LeftStickLeft = buttonValue.AsKey();
-                                        break;
-                                    case "DpadUp":
-                                        viewModel.Config.DpadUp = buttonValue.AsKey();
-                                        break;
-                                    case "DpadDown":
-                                        viewModel.Config.DpadDown = buttonValue.AsKey();
-                                        break;
-                                    case "DpadLeft":
-                                        viewModel.Config.DpadLeft = buttonValue.AsKey();
-                                        break;
-                                    case "DpadRight":
-                                        viewModel.Config.DpadRight = buttonValue.AsKey();
-                                        break;
-                                    case "LeftButtonSr":
-                                        viewModel.Config.LeftButtonSr = buttonValue.AsKey();
-                                        break;
-                                    case "LeftButtonSl":
-                                        viewModel.Config.LeftButtonSl = buttonValue.AsKey();
-                                        break;
-                                    case "RightButtonSr":
-                                        viewModel.Config.RightButtonSr = buttonValue.AsKey();
-                                        break;
-                                    case "RightButtonSl":
-                                        viewModel.Config.RightButtonSl = buttonValue.AsKey();
-                                        break;
-                                    case "ButtonZr":
-                                        viewModel.Config.ButtonZr = buttonValue.AsKey();
-                                        break;
-                                    case "ButtonR":
-                                        viewModel.Config.ButtonR = buttonValue.AsKey();
-                                        break;
-                                    case "ButtonPlus":
-                                        viewModel.Config.ButtonPlus = buttonValue.AsKey();
-                                        break;
-                                    case "ButtonA":
-                                        viewModel.Config.ButtonA = buttonValue.AsKey();
-                                        break;
-                                    case "ButtonB":
-                                        viewModel.Config.ButtonB = buttonValue.AsKey();
-                                        break;
-                                    case "ButtonX":
-                                        viewModel.Config.ButtonX = buttonValue.AsKey();
-                                        break;
-                                    case "ButtonY":
-                                        viewModel.Config.ButtonY = buttonValue.AsKey();
-                                        break;
-                                    case "RightStickButton":
-                                        viewModel.Config.RightStickButton = buttonValue.AsKey();
-                                        break;
-                                    case "RightStickUp":
-                                        viewModel.Config.RightStickUp = buttonValue.AsKey();
-                                        break;
-                                    case "RightStickDown":
-                                        viewModel.Config.RightStickDown = buttonValue.AsKey();
-                                        break;
-                                    case "RightStickRight":
-                                        viewModel.Config.RightStickRight = buttonValue.AsKey();
-                                        break;
-                                    case "RightStickLeft":
-                                        viewModel.Config.RightStickLeft = buttonValue.AsKey();
-                                        break;
-                                }
-                            }
-                        };
-
-                        _currentAssigner.GetInputAndAssign(assigner, keyboard);
-                    }
-                    else
-                    {
-                        if (_currentAssigner != null)
-                        {
-                            ToggleButton oldButton = _currentAssigner.ToggledButton;
-
-                            _currentAssigner.Cancel();
-                            _currentAssigner = null;
-                            button.IsChecked = false;
-                        }
-                    }
-                }
-                else
-                {
-                    _currentAssigner?.Cancel();
-                    _currentAssigner = null;
-                }
-            }
-        }
-
-        private void MouseClick(object sender, PointerPressedEventArgs e)
-        {
-            bool shouldUnbind = e.GetCurrentPoint(this).Properties.IsMiddleButtonPressed;
-
-            _currentAssigner?.Cancel(shouldUnbind);
-
-            PointerPressed -= MouseClick;
-        }
-
-        private IButtonAssigner CreateButtonAssigner(bool forStick)
-        {
-            IButtonAssigner assigner;
-
-            assigner = new KeyboardKeyAssigner((IKeyboard)(DataContext as KeyboardInputViewModel).parentModel.SelectedGamepad);
-
-            return assigner;
-        }
-
-        protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
-        {
-            base.OnDetachedFromVisualTree(e);
-            _currentAssigner?.Cancel();
-            _currentAssigner = null;
-        }
-    }
-}
diff --git a/src/Ryujinx.Ava/UI/Views/Input/MotionInputView.axaml b/src/Ryujinx.Ava/UI/Views/Input/MotionInputView.axaml
index 0d018e29..a6b587f6 100644
--- a/src/Ryujinx.Ava/UI/Views/Input/MotionInputView.axaml
+++ b/src/Ryujinx.Ava/UI/Views/Input/MotionInputView.axaml
@@ -6,7 +6,7 @@
     xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
     xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
     xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
-    xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels.Input"
+    xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
     mc:Ignorable="d"
     x:Class="Ryujinx.Ava.UI.Views.Input.MotionInputView"
     x:DataType="viewModels:MotionInputViewModel"
diff --git a/src/Ryujinx.Ava/UI/Views/Input/MotionInputView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Input/MotionInputView.axaml.cs
index 2304364b..1b340752 100644
--- a/src/Ryujinx.Ava/UI/Views/Input/MotionInputView.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Views/Input/MotionInputView.axaml.cs
@@ -1,7 +1,9 @@
 using Avalonia.Controls;
 using FluentAvalonia.UI.Controls;
 using Ryujinx.Ava.Common.Locale;
-using Ryujinx.Ava.UI.ViewModels.Input;
+using Ryujinx.Ava.UI.Models;
+using Ryujinx.Ava.UI.ViewModels;
+using Ryujinx.Common.Configuration.Hid.Controller;
 using System.Threading.Tasks;
 
 namespace Ryujinx.Ava.UI.Views.Input
@@ -17,7 +19,7 @@ namespace Ryujinx.Ava.UI.Views.Input
 
         public MotionInputView(ControllerInputViewModel viewModel)
         {
-            var config = viewModel.Config;
+            var config = viewModel.Configuration as InputConfiguration<GamepadInputId, StickInputId>;
 
             _viewModel = new MotionInputViewModel
             {
@@ -49,7 +51,7 @@ namespace Ryujinx.Ava.UI.Views.Input
             };
             contentDialog.PrimaryButtonClick += (sender, args) =>
             {
-                var config = viewModel.Config;
+                var config = viewModel.Configuration as InputConfiguration<GamepadInputId, StickInputId>;
                 config.Slot = content._viewModel.Slot;
                 config.Sensitivity = content._viewModel.Sensitivity;
                 config.GyroDeadzone = content._viewModel.GyroDeadzone;
diff --git a/src/Ryujinx.Ava/UI/Views/Input/RumbleInputView.axaml b/src/Ryujinx.Ava/UI/Views/Input/RumbleInputView.axaml
index 1beb1f06..5b7087a4 100644
--- a/src/Ryujinx.Ava/UI/Views/Input/RumbleInputView.axaml
+++ b/src/Ryujinx.Ava/UI/Views/Input/RumbleInputView.axaml
@@ -5,7 +5,7 @@
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
-    xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels.Input"
+    xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
     mc:Ignorable="d"
     x:Class="Ryujinx.Ava.UI.Views.Input.RumbleInputView"
     x:DataType="viewModels:RumbleInputViewModel"
diff --git a/src/Ryujinx.Ava/UI/Views/Input/RumbleInputView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Input/RumbleInputView.axaml.cs
index 58a4b416..9307f872 100644
--- a/src/Ryujinx.Ava/UI/Views/Input/RumbleInputView.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Views/Input/RumbleInputView.axaml.cs
@@ -1,7 +1,9 @@
 using Avalonia.Controls;
 using FluentAvalonia.UI.Controls;
 using Ryujinx.Ava.Common.Locale;
-using Ryujinx.Ava.UI.ViewModels.Input;
+using Ryujinx.Ava.UI.Models;
+using Ryujinx.Ava.UI.ViewModels;
+using Ryujinx.Common.Configuration.Hid.Controller;
 using System.Threading.Tasks;
 
 namespace Ryujinx.Ava.UI.Views.Input
@@ -17,7 +19,7 @@ namespace Ryujinx.Ava.UI.Views.Input
 
         public RumbleInputView(ControllerInputViewModel viewModel)
         {
-            var config = viewModel.Config;
+            var config = viewModel.Configuration as InputConfiguration<GamepadInputId, StickInputId>;
 
             _viewModel = new RumbleInputViewModel
             {
@@ -45,7 +47,7 @@ namespace Ryujinx.Ava.UI.Views.Input
 
             contentDialog.PrimaryButtonClick += (sender, args) =>
             {
-                var config = viewModel.Config;
+                var config = viewModel.Configuration as InputConfiguration<GamepadInputId, StickInputId>;
                 config.StrongRumble = content._viewModel.StrongRumble;
                 config.WeakRumble = content._viewModel.WeakRumble;
             };
diff --git a/src/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml b/src/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml
index 55c2ed6e..81f4b68b 100644
--- a/src/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml
+++ b/src/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml
@@ -27,9 +27,9 @@
                         <RowDefinition Height="*" />
                         <RowDefinition Height="Auto" />
                     </Grid.RowDefinitions>
-                    <views:InputView
+                    <views:ControllerInputView
                         Grid.Row="0"
-                        Name="InputView" />
+                        Name="ControllerSettings" />
                     <StackPanel
                         Orientation="Vertical"
                         Grid.Row="2">
diff --git a/src/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml.cs b/src/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml.cs
index 85ccffcc..8a0cb8ab 100644
--- a/src/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Views/Settings/SettingsInputView.axaml.cs
@@ -11,7 +11,7 @@ namespace Ryujinx.Ava.UI.Views.Settings
 
         public void Dispose()
         {
-            InputView.Dispose();
+            ControllerSettings.Dispose();
         }
     }
 }
diff --git a/src/Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs b/src/Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs
index 314501c5..d7bb0b88 100644
--- a/src/Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs
+++ b/src/Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs
@@ -37,7 +37,7 @@ namespace Ryujinx.Ava.UI.Windows
 
         public void SaveSettings()
         {
-            InputPage.InputView?.SaveCurrentProfile();
+            InputPage.ControllerSettings?.SaveCurrentProfile();
 
             if (Owner is MainWindow window && ViewModel.DirectoryChanged)
             {
diff --git a/src/Ryujinx.Input/Assigner/GamepadButtonAssigner.cs b/src/Ryujinx.Input/Assigner/GamepadButtonAssigner.cs
index bf8319a6..388ebcc0 100644
--- a/src/Ryujinx.Input/Assigner/GamepadButtonAssigner.cs
+++ b/src/Ryujinx.Input/Assigner/GamepadButtonAssigner.cs
@@ -59,16 +59,16 @@ namespace Ryujinx.Input.Assigner
             return _gamepad == null || !_gamepad.IsConnected;
         }
 
-        public ButtonValue? GetPressedButton()
+        public string GetPressedButton()
         {
             IEnumerable<GamepadButtonInputId> pressedButtons = _detector.GetPressedButtons();
 
             if (pressedButtons.Any())
             {
-                return !_forStick ? new(pressedButtons.First()) : new(((StickInputId)pressedButtons.First()));
+                return !_forStick ? pressedButtons.First().ToString() : ((StickInputId)pressedButtons.First()).ToString();
             }
 
-            return null;
+            return "";
         }
 
         private void CollectButtonStats()
diff --git a/src/Ryujinx.Input/Assigner/IButtonAssigner.cs b/src/Ryujinx.Input/Assigner/IButtonAssigner.cs
index 65371713..76a9fece 100644
--- a/src/Ryujinx.Input/Assigner/IButtonAssigner.cs
+++ b/src/Ryujinx.Input/Assigner/IButtonAssigner.cs
@@ -31,6 +31,6 @@ namespace Ryujinx.Input.Assigner
         /// Get the pressed button that was read in <see cref="ReadInput"/> by the button assigner.
         /// </summary>
         /// <returns>The pressed button that was read</returns>
-        ButtonValue? GetPressedButton();
+        string GetPressedButton();
     }
 }
diff --git a/src/Ryujinx.Input/Assigner/KeyboardKeyAssigner.cs b/src/Ryujinx.Input/Assigner/KeyboardKeyAssigner.cs
index c66812ba..e52ef4a2 100644
--- a/src/Ryujinx.Input/Assigner/KeyboardKeyAssigner.cs
+++ b/src/Ryujinx.Input/Assigner/KeyboardKeyAssigner.cs
@@ -23,7 +23,7 @@ namespace Ryujinx.Input.Assigner
 
         public bool HasAnyButtonPressed()
         {
-            return GetPressedButton() is not null;
+            return GetPressedButton().Length != 0;
         }
 
         public bool ShouldCancel()
@@ -31,20 +31,20 @@ namespace Ryujinx.Input.Assigner
             return _keyboardState.IsPressed(Key.Escape);
         }
 
-        public ButtonValue? GetPressedButton()
+        public string GetPressedButton()
         {
-            ButtonValue? keyPressed = null;
+            string keyPressed = "";
 
             for (Key key = Key.Unknown; key < Key.Count; key++)
             {
                 if (_keyboardState.IsPressed(key))
                 {
-                    keyPressed = new(key);
+                    keyPressed = key.ToString();
                     break;
                 }
             }
 
-            return !ShouldCancel() ? keyPressed : null;
+            return !ShouldCancel() ? keyPressed : "";
         }
     }
 }
diff --git a/src/Ryujinx.Input/ButtonValue.cs b/src/Ryujinx.Input/ButtonValue.cs
deleted file mode 100644
index f037e6b6..00000000
--- a/src/Ryujinx.Input/ButtonValue.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-using System.Diagnostics;
-
-namespace Ryujinx.Input
-{
-    public enum ButtonValueType { Key, GamepadButtonInputId, StickId }
-
-    public readonly struct ButtonValue
-    {
-        private readonly ButtonValueType _type;
-        private readonly uint _rawValue;
-
-        public ButtonValue(Key key)
-        {
-            _type = ButtonValueType.Key;
-            _rawValue = (uint)key;
-        }
-
-        public ButtonValue(GamepadButtonInputId gamepad)
-        {
-            _type = ButtonValueType.GamepadButtonInputId;
-            _rawValue = (uint)gamepad;
-        }
-
-        public ButtonValue(StickInputId stick)
-        {
-            _type = ButtonValueType.StickId;
-            _rawValue = (uint)stick;
-        }
-
-        public Common.Configuration.Hid.Key AsKey()
-        {
-            Debug.Assert(_type == ButtonValueType.Key);
-            return (Common.Configuration.Hid.Key)_rawValue;
-        }
-
-        public Common.Configuration.Hid.Controller.GamepadInputId AsGamepadButtonInputId()
-        {
-            Debug.Assert(_type == ButtonValueType.GamepadButtonInputId);
-            return (Common.Configuration.Hid.Controller.GamepadInputId)_rawValue;
-        }
-
-        public Common.Configuration.Hid.Controller.StickInputId AsGamepadStickId()
-        {
-            Debug.Assert(_type == ButtonValueType.StickId);
-            return (Common.Configuration.Hid.Controller.StickInputId)_rawValue;
-        }
-    }
-}
diff --git a/src/Ryujinx/Ui/Windows/ControllerWindow.cs b/src/Ryujinx/Ui/Windows/ControllerWindow.cs
index 52cad5c8..ebf22ab6 100644
--- a/src/Ryujinx/Ui/Windows/ControllerWindow.cs
+++ b/src/Ryujinx/Ui/Windows/ControllerWindow.cs
@@ -893,7 +893,7 @@ namespace Ryujinx.Ui.Windows
                     }
                 }
 
-                string pressedButton = assigner.GetPressedButton().ToString();
+                string pressedButton = assigner.GetPressedButton();
 
                 Application.Invoke(delegate
                 {
-- 
cgit v1.2.3-70-g09d2