Skip to content

Commit 6b20777

Browse files
committed
refactor ProcessInput to simplify logic and remove the distinction "internal hotkeys"; all hotkeys go to the hotkey controller now even if we don't expect to read that hotkey from the controller.
Fix: Hotkey overrides input would cause an input to continue after a button was released if the input is bound to a combination such as Shift+A and an "internal hotkey" is bound to a single button (such as A). Also input bound to Alt would not have the alt ignored by menus. Passes tests HotkeyOverrideDoesNotEatReleaseEvents and InputIsNotSeenAsUnbound
1 parent c3248dc commit 6b20777

File tree

4 files changed

+73
-134
lines changed

4 files changed

+73
-134
lines changed

src/BizHawk.Client.Common/inputAdapters/InputManager.cs

Lines changed: 24 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ private static AutofireController BindToDefinitionAF(
155155
/// <param name="processUnboundInput">Events that did not do anything are forwarded out here.
156156
/// This allows things like Windows' standard alt hotkeys (for menu items) to be handled by the
157157
/// caller if the input didn't alrady do something else.</param>
158-
public void ProcessInput(IInputSource source, Func<string, bool> processHotkey, Config config, Action<InputEvent> processUnboundInput, Func<string, bool> isInternalHotkey)
158+
public void ProcessInput(IInputSource source, Func<string, bool> processHotkey, Config config, Action<InputEvent> processUnboundInput)
159159
{
160160
// loop through all available events
161161
InputEvent ie;
@@ -166,76 +166,33 @@ public void ProcessInput(IInputSource source, Func<string, bool> processHotkey,
166166

167167
// TODO - wonder what happens if we pop up something interactive as a response to one of these hotkeys? may need to purge further processing
168168

169-
// look for hotkey bindings for this key
170-
var triggers = ClientControls.SearchBindings(ie.LogicalButton.ToString());
171-
if (triggers.Count == 0)
169+
var hotkeyTriggers = ClientControls.SearchBindings(ie.LogicalButton.ToString());
170+
bool isEmuInput = ie.LogicalButton.ToString().Split('+').Any(ActiveController.HasBinding);
171+
172+
bool shouldDoHotkey = config.InputHotkeyOverrideOptions != 1;
173+
bool shouldDoEmuInput = config.InputHotkeyOverrideOptions != 2;
174+
if (shouldDoEmuInput && !isEmuInput) shouldDoHotkey = true;
175+
176+
bool didHotkey = false;
177+
if (shouldDoHotkey)
172178
{
173-
processUnboundInput(ie);
179+
if (ie.EventType is InputEventType.Press)
180+
{
181+
didHotkey = hotkeyTriggers.Aggregate(false, (current, trigger) => current | processHotkey(trigger));
182+
}
183+
_hotkeyCoalescer.Receive(ie);
174184
}
175185

176-
switch (config.InputHotkeyOverrideOptions)
186+
if (!didHotkey) shouldDoEmuInput = true;
187+
if (shouldDoEmuInput)
177188
{
178-
default:
179-
case 0: // Both allowed
180-
{
181-
ControllerInputCoalescer.Receive(ie);
182-
183-
var handled = false;
184-
if (ie.EventType is InputEventType.Press)
185-
{
186-
handled = triggers.Aggregate(handled, (current, trigger) => current | processHotkey(trigger));
187-
}
188-
189-
// hotkeys which aren't handled as actions get coalesced as pollable virtual client buttons
190-
if (!handled)
191-
{
192-
_hotkeyCoalescer.Receive(ie);
193-
}
194-
195-
break;
196-
}
197-
case 1: // Input overrides Hotkeys
198-
{
199-
ControllerInputCoalescer.Receive(ie);
200-
if (!ie.LogicalButton.ToString().Split('+').Any(ActiveController.HasBinding))
201-
{
202-
var handled = false;
203-
if (ie.EventType is InputEventType.Press)
204-
{
205-
handled = triggers.Aggregate(false, (current, trigger) => current | processHotkey(trigger));
206-
}
207-
208-
// hotkeys which aren't handled as actions get coalesced as pollable virtual client buttons
209-
if (!handled)
210-
{
211-
_hotkeyCoalescer.Receive(ie);
212-
}
213-
}
214-
215-
break;
216-
}
217-
case 2: // Hotkeys override Input
218-
{
219-
var handled = false;
220-
if (ie.EventType is InputEventType.Press)
221-
{
222-
handled = triggers.Aggregate(false, (current, trigger) => current | processHotkey(trigger));
223-
}
224-
225-
// hotkeys which aren't handled as actions get coalesced as pollable virtual client buttons
226-
if (!handled)
227-
{
228-
_hotkeyCoalescer.Receive(ie);
229-
230-
// Check for hotkeys that may not be handled through processHotkey() method, reject controller input mapped to these
231-
if (!triggers.Exists((t) => isInternalHotkey(t)))
232-
{
233-
ControllerInputCoalescer.Receive(ie);
234-
}
235-
}
236-
237-
break;
238-
}
189+
ControllerInputCoalescer.Receive(ie);
190+
}
191+
bool didEmuInput = shouldDoEmuInput;
192+
193+
if (!didHotkey && !didEmuInput)
194+
{
195+
processUnboundInput(ie);
239196
}
240197
} // foreach event
241198

src/BizHawk.Client.EmuHawk/MainForm.Hotkey.cs

Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,24 @@ void SelectAndLoadFromSlot(int slot)
2626
default:
2727
return false;
2828

29+
// Hotkeys handled elsewhere, via the hotkey controller
30+
case "Autohold":
31+
case "Autofire":
32+
case "Frame Advance":
33+
case "Turbo":
34+
case "Rewind":
35+
case "Fast Forward":
36+
case "Open RA Overlay":
37+
break;
38+
2939
// General
3040
case "Pause":
3141
TogglePause();
3242
break;
3343
case "Frame Inch":
3444
//special! allow this key to get handled as Frame Advance, too
3545
FrameInch = true;
36-
return false;
46+
break;
3747
case "Toggle Throttle":
3848
ToggleUnthrottled();
3949
break;
@@ -549,32 +559,5 @@ void SelectAndLoadFromSlot(int slot)
549559

550560
return true;
551561
}
552-
553-
// Determines if the value is a hotkey that would be handled outside of the CheckHotkey method
554-
private bool IsInternalHotkey(string trigger)
555-
{
556-
switch (trigger)
557-
{
558-
default:
559-
return false;
560-
case "Autohold":
561-
case "Autofire":
562-
case "Frame Advance":
563-
case "Turbo":
564-
case "Rewind":
565-
case "Fast Forward":
566-
case "Open RA Overlay":
567-
return true;
568-
case "RA Up":
569-
case "RA Down":
570-
case "RA Left":
571-
case "RA Right":
572-
case "RA Confirm":
573-
case "RA Cancel":
574-
case "RA Quit":
575-
// don't consider these keys outside of RAIntegration overlay being active
576-
return RA is RAIntegration { OverlayActive: true };
577-
}
578-
}
579562
}
580563
}

src/BizHawk.Client.EmuHawk/MainForm.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -941,7 +941,7 @@ public int ProgramRunLoop()
941941
{
942942
MainFormContextMenu.Show(PointToScreen(new(0, MainformMenu.Height)));
943943
}
944-
}, IsInternalHotkey);
944+
});
945945

946946
// translate mouse coordinates
947947
// NOTE: these must go together, because in the case of screen rotation, X and Y are transformed together
@@ -2085,7 +2085,7 @@ private void InitControls()
20852085
foreach (var (k, v) in Config.HotkeyBindings) controls.BindMulti(k, v);
20862086

20872087
InputManager.ClientControls = controls;
2088-
InputManager.ControllerInputCoalescer = new(); // ctor initialises values for host haptics
2088+
InputManager.ControllerInputCoalescer = new();
20892089
}
20902090

20912091
private void LoadMoviesFromRecent(string path)

0 commit comments

Comments
 (0)