This PR aims to fix a bug inside the settings window that caused the Controller Stick visualizer to run at extremely degraded performance when the selected profile had a rainbow LED configuration:
Old behaviour : <video src="/attachments/1915ab74-6e1b-4e2f-9182-820cbed5359b" title="Screen Recording 2026-05-30 105859" controls></video>
New / updated behaviour : <video src="/attachments/dd293402-19e7-439e-8aa6-114d4ee22404" title="Screen Recording 2026-05-30 110338" controls></video>
The issue was that the input settings page automatically subscribed controllers to rainbow LED updates when a saved profile with rainbow LEDs enabled was loaded.
Reopening input settings on a non-default controller profile could immediately start the rainbow LED update loop from the settings UI, which caused the stick visualizer to become sluggish or jittery on affected controllers. The preview handler is now only registered when the rainbow LED option is changed in the settings UI, and it uses a stable handler so duplicate callbacks are not stacked.
Reviewed-on: https://git.ryujinx.app/projects/Ryubing/pulls/119
This PR refactors keyboard handling to use physical key mappings for all gameplay input, ensuring controls remain consistent across different OS keyboard layouts.
I'd like to give out an ENORMOUS thank you to @Neo for his very generous help on getting MacOS caps lock behaviour working, but as well for taking the time for extensive testing, planning and discussions, and finally for writing this PR message :) Keep being awsome pal 👊
### New Features :
* **New**: Gameplay input now uses physical key positions instead of OS layouts, ensuring the same physical key triggers the same action across keyboard layouts.
* Key rebinding stores physical keys and config compatibility is preserved, with physical keys now the primary gameplay‑binding format.
* Physical‑key model is now consistent across platforms, including updated SDL/headless behavior.
* **Added**: New Input setting "Reset keybinds to default", with a new confirmation dialog appears when changes are being overwritten.
* **Fractured**: Keyboard‑related locales to the newly created `KeyboardLayout.json`.
* New input device settings/actions use clearer labels and tooltips.
* UI Key Labels (such as Left Shift and Right Shift) are more accurate and standardized, with clearer symbols, consistent naming, dynamic learning of printable labels from real key events, and persistence across restarts.
### Improvements :
* **Reduced**: Incorrect key labels by using observed host symbols instead of language assumptions.
* **Reduced**: Stuck/stale keys by using binary pressed‑key tracking, fixing rebinding/gameplay paths, better held‑key recovery after focus changes, and clearing keyboard state when Ryujinx/settings windows lose focus.
* **Improved**: Device handling → refreshing no longer clears the selector, disconnect fallback is consistent, reconnect restores controllers automatically, and the UI avoids invalid/empty device states.
* **Improved**: Async input‑assignment callbacks are now guarded when switching views/devices, preventing stale callbacks from hitting detached views.
* **Adjusted**: Input visualiser to be more robust when switching sources or handling controller disconnect/reconnect, without needing to reopen settings.
* **Improved**: Modification (changes to input controls) tracking
* Rebinding to the same value, reverting to original config, restoring defaults without differences, or reloading equivalent profiles no longer leaves Player marked as modified.
* **Reduced**: Keyboard LED noise in logs and added optional UI keyboard‑state/rebinding diagnostics.
### Fixes :
* **Special Keys**:
* AltGr and other special keys behave correctly, including proper Ctrl+Alt → AltRight handling and more consistent normalization of special/synthetic keys.
* Caps Lock is now reliably bindable on all platforms (Windows/Linux register every press; macOS every other).
* **Fixed**: Certain cases where keyboard input broke after pointer interactions
### Current Limitations
These are planned on being fixed/improved upon in future PRs:
* Hotkeys still use semantic (Key) mappings.
* Software keyboard / text input still uses the semantic path
* Printable key labels may fall back to defaults until observed from host input.
* Full semantic/physical split currently implemented only in the Avalonia driver.
Co-authored-by: _Neo_ <ursamajorjanus2819@gmail.com>
Reviewed-on: https://git.ryujinx.app/projects/Ryubing/pulls/13
This allows the user to change the controller LED while using Ryujinx.
Useful for PS4 and PS5 controllers as an example.
You can also use a spectrum-cycling Rainbow color option, or turn the LED off for DualSense controllers.
---------
Co-authored-by: Evan Husted <greem@greemdev.net>