diff --git a/src/BizHawk.Client.Common/input/ClientInputFocus.cs b/src/BizHawk.Client.Common/input/ClientInputFocus.cs
deleted file mode 100644
index 94578ba98d..0000000000
--- a/src/BizHawk.Client.Common/input/ClientInputFocus.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-#nullable enable
-
-using System;
-
-namespace BizHawk.Client.Common
-{
- [Flags]
- public enum ClientInputFocus
- {
- None = 0,
- Mouse = 1,
- Keyboard = 2,
- Pad = 4
- }
-}
diff --git a/src/BizHawk.Client.Common/input/InputCoalescerControllers.cs b/src/BizHawk.Client.Common/input/InputCoalescerControllers.cs
new file mode 100644
index 0000000000..2cfc1bdd8f
--- /dev/null
+++ b/src/BizHawk.Client.Common/input/InputCoalescerControllers.cs
@@ -0,0 +1,31 @@
+#nullable enable
+
+using System.Linq;
+
+namespace BizHawk.Client.Common
+{
+ public class InputCoalescer : SimpleController
+ {
+ protected virtual void ProcessSubsets(string button, bool state) {}
+
+ public void Receive(InputEvent ie)
+ {
+ var state = ie.EventType is InputEventType.Press;
+ var button = ie.LogicalButton.ToString();
+ Buttons[button] = state;
+ ProcessSubsets(button, state);
+ if (state) return;
+ // when a button is released, all modified variants of it are released as well
+ foreach (var k in Buttons.Keys.Where(k => k.EndsWith($"+{ie.LogicalButton.Button}")).ToList()) Buttons[k] = false;
+ }
+ }
+
+ public sealed class ControllerInputCoalescer : InputCoalescer
+ {
+ protected override void ProcessSubsets(string button, bool state)
+ {
+ // For controller input, we want Shift+X to register as both Shift and X (for Keyboard controllers)
+ foreach (var s in button.Split('+')) Buttons[s] = state;
+ }
+ }
+}
diff --git a/src/BizHawk.Client.Common/input/InputEvent.cs b/src/BizHawk.Client.Common/input/InputEvent.cs
new file mode 100644
index 0000000000..ae842802bd
--- /dev/null
+++ b/src/BizHawk.Client.Common/input/InputEvent.cs
@@ -0,0 +1,69 @@
+#nullable enable
+
+using System;
+
+namespace BizHawk.Client.Common
+{
+ [Flags]
+ public enum ClientInputFocus
+ {
+ None = 0,
+ Mouse = 1,
+ Keyboard = 2,
+ Pad = 4
+ }
+
+ public class InputEvent
+ {
+ public InputEventType EventType;
+
+ public LogicalButton LogicalButton;
+
+ public ClientInputFocus Source;
+
+ public override string ToString() => $"{EventType}:{LogicalButton}";
+ }
+
+ public enum InputEventType
+ {
+ Press, Release
+ }
+
+ public readonly struct LogicalButton
+ {
+ public static bool operator ==(LogicalButton lhs, LogicalButton rhs)
+ => lhs.Button == rhs.Button && lhs.Modifiers == rhs.Modifiers;
+
+ public static bool operator !=(LogicalButton lhs, LogicalButton rhs) => !(lhs == rhs);
+
+ public bool Alt => (Modifiers & ModifierKey.Alt) != 0;
+
+ public readonly string Button;
+
+ public bool Control => (Modifiers & ModifierKey.Control) != 0;
+
+ public readonly ModifierKey Modifiers;
+
+ public bool Shift => (Modifiers & ModifierKey.Shift) != 0;
+
+ public LogicalButton(string button, ModifierKey modifiers)
+ {
+ Button = button;
+ Modifiers = modifiers;
+ }
+
+ public override readonly bool Equals(object? obj) => obj is not null && (LogicalButton) obj == this; //TODO safe type check?
+
+ public override readonly int GetHashCode() => Button.GetHashCode() ^ Modifiers.GetHashCode();
+
+ public override readonly string ToString()
+ {
+ var ret = "";
+ if (Control) ret += "Ctrl+";
+ if (Alt) ret += "Alt+";
+ if (Shift) ret += "Shift+";
+ ret += Button;
+ return ret;
+ }
+ }
+}
diff --git a/src/BizHawk.Client.Common/input/MiscInputEnums.cs b/src/BizHawk.Client.Common/input/MiscInputEnums.cs
new file mode 100644
index 0000000000..e4a288b09b
--- /dev/null
+++ b/src/BizHawk.Client.Common/input/MiscInputEnums.cs
@@ -0,0 +1,26 @@
+using System;
+
+namespace BizHawk.Client.Common
+{
+ public enum AllowInput
+ {
+ None = 0,
+ All = 1,
+ OnlyController = 2
+ }
+
+ [Flags]
+ public enum ModifierKey
+ {
+ /// The bitmask to extract modifiers from a key value.
+ Modifiers = -65536,
+ /// No key pressed.
+ None = 0,
+ /// The SHIFT modifier key.
+ Shift = 65536,
+ /// The CTRL modifier key.
+ Control = 131072,
+ /// The ALT modifier key.
+ Alt = 262144,
+ }
+}
diff --git a/src/BizHawk.Client.Common/inputAdapters/InputManager.cs b/src/BizHawk.Client.Common/inputAdapters/InputManager.cs
index 96e91f53fb..9fe2f93986 100644
--- a/src/BizHawk.Client.Common/inputAdapters/InputManager.cs
+++ b/src/BizHawk.Client.Common/inputAdapters/InputManager.cs
@@ -43,7 +43,7 @@ namespace BizHawk.Client.Common
// Input state for game controller inputs are coalesced here
// This relies on a client specific implementation!
- public SimpleController ControllerInputCoalescer { get; set; }
+ public ControllerInputCoalescer ControllerInputCoalescer { get; set; }
public Controller ClientControls { get; set; }
diff --git a/src/BizHawk.Client.EmuHawk/CustomControls/InputWidget.cs b/src/BizHawk.Client.EmuHawk/CustomControls/InputWidget.cs
index f479b8dde6..f2381c2117 100644
--- a/src/BizHawk.Client.EmuHawk/CustomControls/InputWidget.cs
+++ b/src/BizHawk.Client.EmuHawk/CustomControls/InputWidget.cs
@@ -4,6 +4,7 @@ using System.Drawing;
using System.Linq;
using System.Windows.Forms;
+using BizHawk.Client.Common;
using BizHawk.Common;
namespace BizHawk.Client.EmuHawk
@@ -14,7 +15,7 @@ namespace BizHawk.Client.EmuHawk
private readonly Timer _timer = new Timer();
private readonly List _bindings = new List();
- private Input.InputEvent _lastPress;
+ private InputEvent _lastPress;
public InputCompositeWidget CompositeWidget { get; set; }
diff --git a/src/BizHawk.Client.EmuHawk/Input/Input.cs b/src/BizHawk.Client.EmuHawk/Input/Input.cs
index d4f454256b..eac60d8b5b 100644
--- a/src/BizHawk.Client.EmuHawk/Input/Input.cs
+++ b/src/BizHawk.Client.EmuHawk/Input/Input.cs
@@ -11,64 +11,8 @@ using BizHawk.Client.Common;
namespace BizHawk.Client.EmuHawk
{
- // coalesces events back into instantaneous states
- public class InputCoalescer : SimpleController
- {
- public void Receive(Input.InputEvent ie)
- {
- bool state = ie.EventType == Input.InputEventType.Press;
-
- string button = ie.LogicalButton.ToString();
- Buttons[button] = state;
-
- //when a button is released, all modified variants of it are released as well
- if (!state)
- {
- var releases = Buttons.Where(kvp => kvp.Key.Contains("+") && kvp.Key.EndsWith(ie.LogicalButton.Button)).ToArray();
- foreach (var kvp in releases)
- Buttons[kvp.Key] = false;
- }
- }
- }
-
- public class ControllerInputCoalescer : SimpleController
- {
- public void Receive(Input.InputEvent ie)
- {
- bool state = ie.EventType == Input.InputEventType.Press;
-
- string button = ie.LogicalButton.ToString();
- Buttons[button] = state;
-
- //For controller input, we want Shift+X to register as both Shift and X (for Keyboard controllers)
- string[] subgroups = button.Split('+');
- if (subgroups.Length > 0)
- {
- foreach (string s in subgroups)
- {
- Buttons[s] = state;
- }
- }
-
- //when a button is released, all modified variants of it are released as well
- if (!state)
- {
- var releases = Buttons.Where((kvp) => kvp.Key.Contains("+") && kvp.Key.EndsWith(ie.LogicalButton.Button)).ToArray();
- foreach (var kvp in releases)
- Buttons[kvp.Key] = false;
- }
- }
- }
-
public class Input
{
- public enum AllowInput
- {
- None = 0,
- All = 1,
- OnlyController = 2
- }
-
///
/// If your form needs this kind of input focus, be sure to say so.
/// Really, this only makes sense for mouse, but I've started building it out for other things
@@ -83,30 +27,6 @@ namespace BizHawk.Client.EmuHawk
private readonly HashSet _wantingMouseFocus = new HashSet();
- [Flags]
- public enum ModifierKey
- {
- // Summary:
- // The bitmask to extract modifiers from a key value.
- Modifiers = -65536,
- //
- // Summary:
- // No key pressed.
- None = 0,
- //
- // Summary:
- // The SHIFT modifier key.
- Shift = 65536,
- //
- // Summary:
- // The CTRL modifier key.
- Control = 131072,
- //
- // Summary:
- // The ALT modifier key.
- Alt = 262144
- }
-
public static Input Instance;
private readonly Thread _updateThread;
@@ -138,67 +58,6 @@ namespace BizHawk.Client.EmuHawk
_updateThread.Start();
}
- public enum InputEventType
- {
- Press, Release
- }
- public struct LogicalButton
- {
- public LogicalButton(string button, ModifierKey modifiers)
- {
- Button = button;
- Modifiers = modifiers;
- }
- public readonly string Button;
- public readonly ModifierKey Modifiers;
-
- public bool Alt => (Modifiers & ModifierKey.Alt) != 0;
- public bool Control => (Modifiers & ModifierKey.Control) != 0;
- public bool Shift => (Modifiers & ModifierKey.Shift) != 0;
-
- public override string ToString()
- {
- string ret = "";
- if (Control) ret += "Ctrl+";
- if (Alt) ret += "Alt+";
- if (Shift) ret += "Shift+";
- ret += Button;
- return ret;
- }
- public override bool Equals(object obj)
- {
- if (obj is null)
- {
- return false;
- }
-
- var other = (LogicalButton)obj;
- return other == this;
- }
- public override int GetHashCode()
- {
- return Button.GetHashCode() ^ Modifiers.GetHashCode();
- }
- public static bool operator ==(LogicalButton lhs, LogicalButton rhs)
- {
- return lhs.Button == rhs.Button && lhs.Modifiers == rhs.Modifiers;
- }
- public static bool operator !=(LogicalButton lhs, LogicalButton rhs)
- {
- return !(lhs == rhs);
- }
- }
- public class InputEvent
- {
- public LogicalButton LogicalButton;
- public InputEventType EventType;
- public ClientInputFocus Source;
- public override string ToString()
- {
- return $"{EventType}:{LogicalButton}";
- }
- }
-
private readonly Dictionary _modifierState = new Dictionary();
private readonly WorkingDictionary _lastState = new WorkingDictionary();
private readonly WorkingDictionary _axisValues = new WorkingDictionary();
diff --git a/src/BizHawk.Client.EmuHawk/MainForm.cs b/src/BizHawk.Client.EmuHawk/MainForm.cs
index 6bc291e74a..026c967804 100644
--- a/src/BizHawk.Client.EmuHawk/MainForm.cs
+++ b/src/BizHawk.Client.EmuHawk/MainForm.cs
@@ -447,14 +447,14 @@ namespace BizHawk.Client.EmuHawk
{
null => Config.AcceptBackgroundInput // none of our forms are focused, check the background input config
? Config.AcceptBackgroundInputControllerOnly
- ? Input.AllowInput.OnlyController
- : Input.AllowInput.All
- : Input.AllowInput.None,
- TAStudio when yieldAlt => Input.AllowInput.None,
- FormBase { BlocksInputWhenFocused: false } => Input.AllowInput.All,
- ControllerConfig => Input.AllowInput.All,
- HotkeyConfig => Input.AllowInput.All,
- _ => Input.AllowInput.None
+ ? AllowInput.OnlyController
+ : AllowInput.All
+ : AllowInput.None,
+ TAStudio when yieldAlt => AllowInput.None,
+ FormBase { BlocksInputWhenFocused: false } => AllowInput.All,
+ ControllerConfig => AllowInput.All,
+ HotkeyConfig => AllowInput.All,
+ _ => AllowInput.None
}
);
InitControls();
@@ -701,7 +701,7 @@ namespace BizHawk.Client.EmuHawk
// handle events and dispatch as a hotkey action, or a hotkey button, or an input button
// ...but prepare haptics first, those get read in ProcessInput
- var finalHostController = (ControllerInputCoalescer) InputManager.ControllerInputCoalescer;
+ var finalHostController = InputManager.ControllerInputCoalescer;
InputManager.ActiveController.PrepareHapticsForHost(finalHostController);
ProcessInput(
_hotkeyCoalescer,
@@ -982,7 +982,7 @@ namespace BizHawk.Client.EmuHawk
Input.Instance.Adapter.SetHaptics(finalHostController.GetHapticsSnapshot());
// loop through all available events
- Input.InputEvent ie;
+ InputEvent ie;
while ((ie = Input.Instance.DequeueEvent()) != null)
{
// useful debugging:
@@ -995,7 +995,7 @@ namespace BizHawk.Client.EmuHawk
if (triggers.Count == 0)
{
// Maybe it is a system alt-key which hasn't been overridden
- if (ie.EventType == Input.InputEventType.Press)
+ if (ie.EventType is InputEventType.Press)
{
if (ie.LogicalButton.Alt && ie.LogicalButton.Button.Length == 1)
{
@@ -1026,7 +1026,7 @@ namespace BizHawk.Client.EmuHawk
finalHostController.Receive(ie);
handled = false;
- if (ie.EventType == Input.InputEventType.Press)
+ if (ie.EventType is InputEventType.Press)
{
handled = triggers.Aggregate(handled, (current, trigger) => current | CheckHotkey(trigger));
}
@@ -1043,7 +1043,7 @@ namespace BizHawk.Client.EmuHawk
if (!activeControllerHasBinding(ie.LogicalButton.ToString()))
{
handled = false;
- if (ie.EventType == Input.InputEventType.Press)
+ if (ie.EventType is InputEventType.Press)
{
handled = triggers.Aggregate(false, (current, trigger) => current | CheckHotkey(trigger));
}
@@ -1058,7 +1058,7 @@ namespace BizHawk.Client.EmuHawk
break;
case 2: // Hotkeys override Input
handled = false;
- if (ie.EventType == Input.InputEventType.Press)
+ if (ie.EventType is InputEventType.Press)
{
handled = triggers.Aggregate(false, (current, trigger) => current | CheckHotkey(trigger));
}
@@ -2110,7 +2110,7 @@ namespace BizHawk.Client.EmuHawk
}
InputManager.ClientControls = controls;
- InputManager.ControllerInputCoalescer = new ControllerInputCoalescer(); // ctor initialises values for host haptics
+ InputManager.ControllerInputCoalescer = new(); // ctor initialises values for host haptics
_autofireNullControls = new AutofireController(
Emulator,
Config.AutofireOn,
diff --git a/src/BizHawk.Client.EmuHawk/config/InputCompositeWidget.cs b/src/BizHawk.Client.EmuHawk/config/InputCompositeWidget.cs
index 71ada81f95..91c6fbdef2 100644
--- a/src/BizHawk.Client.EmuHawk/config/InputCompositeWidget.cs
+++ b/src/BizHawk.Client.EmuHawk/config/InputCompositeWidget.cs
@@ -1,6 +1,8 @@
using System;
using System.Windows.Forms;
+using BizHawk.Client.Common;
+
namespace BizHawk.Client.EmuHawk
{
public partial class InputCompositeWidget : UserControl
@@ -80,24 +82,24 @@ namespace BizHawk.Client.EmuHawk
private void DropdownMenu_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
- Input.ModifierKey mods = new Input.ModifierKey();
+ var mods = ModifierKey.None;
if ((ModifierKeys & Keys.Shift) != 0)
{
- mods |= Input.ModifierKey.Shift;
+ mods |= ModifierKey.Shift;
}
if ((ModifierKeys & Keys.Control) != 0)
{
- mods |= Input.ModifierKey.Control;
+ mods |= ModifierKey.Control;
}
if ((ModifierKeys & Keys.Alt) != 0)
{
- mods |= Input.ModifierKey.Alt;
+ mods |= ModifierKey.Alt;
}
- var lb = new Input.LogicalButton(e.ClickedItem.Text, mods);
+ LogicalButton lb = new(e.ClickedItem.Text, mods);
widget.SetBinding(lb.ToString());
}