rawinput: modifiers (key combinations) (#813)

## Link to GitHub Issue or related Pull Request, if one exists
Fixes #635

## Description of change
Adds optional **button modifiers**, allowing a binding to require one or
more "modifier" buttons to be held before it activates.

- New "Modifiers" controller page in the overlay config to bind the
Modifier 1–4 source buttons.
- Each binding gains a 4-bit modifier_mask (Modifier 1-4). It is
persisted as an optional modifiers XML attribute on button nodes and
controller-preset entries. The attribute is optional and defaults to 0,
so existing config files and presets load unchanged and the feature is
off unless the user opts in.
- The button Edit properties popup gains a "Modifiers" dropdown to pick
which modifiers a binding requires. Doesn't apply to MIDI though.
- Input evaluation skips a binding whose required modifiers are not
held, falling through to its alternatives; velocity reporting uses the
same gated path.
- Controller-preset templates gain a "Modifiers" group for importing and
exporting.

## Testing
This commit is contained in:
bicarus
2026-07-21 00:26:36 -07:00
committed by GitHub
parent 623e1e3998
commit ed7318c270
11 changed files with 393 additions and 48 deletions
@@ -19,6 +19,7 @@ namespace overlay::windows {
double debounce_down = 0.0;
int bat_threshold = 0;
unsigned short velocity_threshold = 0;
uint8_t modifier_mask = 0;
bool is_naive() const { return device_identifier.empty() && vKey != INVALID_VKEY; }
bool is_device() const { return !device_identifier.empty(); }
@@ -34,6 +35,7 @@ namespace overlay::windows {
e.debounce_down = btn.getDebounceDown();
e.bat_threshold = btn.getBatThreshold();
e.velocity_threshold = btn.getVelocityThreshold();
e.modifier_mask = btn.getModifierMask();
return e;
}
};
@@ -123,6 +125,7 @@ namespace overlay::windows {
std::string game_name;
bool is_builtin = false;
std::vector<TemplateButtonBinding> buttons;
std::vector<TemplateButtonBinding> modifier_buttons;
std::vector<TemplateButtonBinding> keypad_buttons;
std::vector<TemplateAnalogBinding> analogs;
std::vector<TemplateLightBinding> lights;
@@ -150,6 +153,7 @@ namespace overlay::windows {
bool save_user_template(
const ControllerTemplate &tmpl,
const bool save_buttons,
const bool save_modifiers,
const bool save_keypads,
const bool save_analogs,
const bool save_lights);