diff --git a/BizHawk.MultiClient/Input/Input.cs b/BizHawk.MultiClient/Input/Input.cs index a30ecc5042..b8c0c2ec68 100644 --- a/BizHawk.MultiClient/Input/Input.cs +++ b/BizHawk.MultiClient/Input/Input.cs @@ -109,7 +109,7 @@ namespace BizHawk.MultiClient { return Button.GetHashCode() ^ Modifiers.GetHashCode(); } - public static bool operator==(LogicalButton lhs, LogicalButton rhs) + public static bool operator ==(LogicalButton lhs, LogicalButton rhs) { return lhs.Button == rhs.Button && lhs.Modifiers == rhs.Modifiers; } @@ -130,6 +130,7 @@ namespace BizHawk.MultiClient WorkingDictionary ModifierState = new WorkingDictionary(); WorkingDictionary LastState = new WorkingDictionary(); + WorkingDictionary UnpressState = new WorkingDictionary(); HashSet IgnoreKeys = new HashSet(new[] { "LeftShift", "RightShift", "LeftControl", "RightControl", "LeftAlt", "RightAlt" }); void HandleButton(string button, bool newState) @@ -137,11 +138,28 @@ namespace BizHawk.MultiClient if (EnableIgnoreModifiers && IgnoreKeys.Contains(button)) return; if (LastState[button] && newState) return; if (!LastState[button] && !newState) return; + + if (UnpressState.ContainsKey(button)) + { + if (newState) return; + Console.WriteLine("Removing Unpress {0} with newState {1}", button, newState); + UnpressState.Remove(button); + LastState[button] = false; + return; + } + + //dont generate events for things like Ctrl+LeftControl + ModifierKey mods = _Modifiers; + if (button == "LeftShift") mods &= ~ModifierKey.Shift; + if (button == "RightShift") mods &= ~ModifierKey.Shift; + if (button == "LeftControl") mods &= ~ModifierKey.Control; + if (button == "RightControl") mods &= ~ModifierKey.Control; + if (button == "LeftAlt") mods &= ~ModifierKey.Alt; + if (button == "RightAlt") mods &= ~ModifierKey.Alt; var ie = new InputEvent(); ie.EventType = newState ? InputEventType.Press : InputEventType.Release; - ie.LogicalButton = new LogicalButton(button, _Modifiers); - _NewEvents.Add(ie); + ie.LogicalButton = new LogicalButton(button, mods); LastState[button] = newState; //track the pressed events with modifiers that we send so that we can send corresponding unpresses with modifiers @@ -153,21 +171,23 @@ namespace BizHawk.MultiClient //so, i am adding it as of 11-sep-2011 if (newState) { - ModifierState[button] = ie.LogicalButton; + ModifierState[button] = ie.LogicalButton; } else { - if (ModifierState[button] != null) - { - LogicalButton alreadyReleased = ie.LogicalButton; - ie = new InputEvent(); - ie.LogicalButton = (LogicalButton)ModifierState[button]; - ie.EventType = InputEventType.Release; - if(ie.LogicalButton != alreadyReleased) - _NewEvents.Add(ie); - } - ModifierState[button] = null; + if (ModifierState[button] != null) + { + LogicalButton alreadyReleased = ie.LogicalButton; + var ieModified = new InputEvent(); + ieModified.LogicalButton = (LogicalButton)ModifierState[button]; + ieModified.EventType = InputEventType.Release; + if (ieModified.LogicalButton != alreadyReleased) + _NewEvents.Add(ieModified); + } + ModifierState[button] = null; } + + _NewEvents.Add(ie); } ModifierKey _Modifiers; @@ -182,7 +202,7 @@ namespace BizHawk.MultiClient } } - Queue InputEvents = new Queue(); + Queue InputEvents = new Queue(); public InputEvent DequeueEvent() { lock (this) @@ -205,15 +225,15 @@ namespace BizHawk.MultiClient for (; ; ) { KeyInput.Update(); - GamePad.UpdateAll(); - GamePad360.UpdateAll(); + GamePad.UpdateAll(); + GamePad360.UpdateAll(); _Modifiers = KeyInput.GetModifierKeysAsKeys(); _NewEvents.Clear(); //analyze keys var bleh = new HashSet(); - foreach(var k in KeyInput.State.PressedKeys) + foreach (var k in KeyInput.State.PressedKeys) bleh.Add(k); foreach (var k in KeyInput.State.AllKeys) if (bleh.Contains(k)) @@ -221,22 +241,22 @@ namespace BizHawk.MultiClient else HandleButton(k.ToString(), false); - //analyze xinput - for (int i = 0; i < GamePad360.Devices.Count; i++) - { - var pad = GamePad360.Devices[i]; - string xname = "X" + (i + 1) + " "; - for (int b = 0; b < pad.NumButtons; b++) - HandleButton(xname + pad.ButtonName(b), pad.Pressed(b)); - } + //analyze xinput + for (int i = 0; i < GamePad360.Devices.Count; i++) + { + var pad = GamePad360.Devices[i]; + string xname = "X" + (i + 1) + " "; + for (int b = 0; b < pad.NumButtons; b++) + HandleButton(xname + pad.ButtonName(b), pad.Pressed(b)); + } //analyze joysticks for (int i = 0; i < GamePad.Devices.Count; i++) { var pad = GamePad.Devices[i]; string jname = "J" + (i + 1) + " "; - - for (int b = 0; b < pad.NumButtons; b++) + + for (int b = 0; b < pad.NumButtons; b++) HandleButton(jname + pad.ButtonName(b), pad.Pressed(b)); } @@ -264,12 +284,41 @@ namespace BizHawk.MultiClient } //returns the next Press event, if available. should be useful - public string GetNextPressedButtonOrNull() + public string GetNextBindEvent() { - InputEvent ie = DequeueEvent(); - if (ie == null) return null; - if (ie.EventType == InputEventType.Release) return null; - return ie.LogicalButton.ToString(); + if (InputEvents.Count == 0) return null; + + //we only listen to releases for input binding, because we need to distinguish releases of pure modifierkeys from modified keys + //if you just pressed ctrl, wanting to bind ctrl, we'd see: pressed:ctrl, unpressed:ctrl + //if you just pressed ctrl+c, wanting to bind ctrl+c, we'd see: pressed:ctrl, pressed:ctrl+c, unpressed:ctrl+c, unpressed:ctrl + //so its the first unpress we need to listen for + + while (InputEvents.Count != 0) + { + var ie = DequeueEvent(); + + //as a special perk, we'll accept escape immediately + if (ie.EventType == InputEventType.Press && ie.LogicalButton.Button == "Escape") + goto ACCEPT; + + if (ie.EventType == InputEventType.Press) continue; + + ACCEPT: + Console.WriteLine("Bind Event: {0} ", ie); + + foreach (var kvp in LastState) + if (kvp.Value) + { + Console.WriteLine("Unpressing " + kvp.Key); + UnpressState[kvp.Key] = true; + } + + InputEvents.Clear(); + + return ie.LogicalButton.ToString(); + } + + return null; } //controls whether modifier keys will be ignored as key press events diff --git a/BizHawk.MultiClient/config/ControllerConfig.cs b/BizHawk.MultiClient/config/ControllerConfig.cs index 89a9c391d7..c936fa3c7a 100644 --- a/BizHawk.MultiClient/config/ControllerConfig.cs +++ b/BizHawk.MultiClient/config/ControllerConfig.cs @@ -97,14 +97,14 @@ namespace BizHawk.MultiClient protected override void OnShown(EventArgs e) { - Input.Instance.EnableIgnoreModifiers = true; + //Input.Instance.EnableIgnoreModifiers = true; base.OnShown(e); } protected override void OnClosed(EventArgs e) { base.OnClosed(e); - Input.Instance.EnableIgnoreModifiers = false; + //Input.Instance.EnableIgnoreModifiers = false; } private void SetAutoTab(bool setting) diff --git a/BizHawk.MultiClient/config/HotkeyWindow.cs b/BizHawk.MultiClient/config/HotkeyWindow.cs index fb81eaf2c3..35f1eaee35 100644 --- a/BizHawk.MultiClient/config/HotkeyWindow.cs +++ b/BizHawk.MultiClient/config/HotkeyWindow.cs @@ -122,14 +122,14 @@ namespace BizHawk.MultiClient protected override void OnShown(EventArgs e) { - Input.Instance.EnableIgnoreModifiers = true; + //Input.Instance.EnableIgnoreModifiers = true; base.OnShown(e); } protected override void OnClosed(EventArgs e) { base.OnClosed(e); - Input.Instance.EnableIgnoreModifiers = false; + //Input.Instance.EnableIgnoreModifiers = false; } private void IDB_SAVE_Click(object sender, EventArgs e) diff --git a/BizHawk.MultiClient/config/InputConfig.cs b/BizHawk.MultiClient/config/InputConfig.cs index 98d2206160..3b95274488 100644 --- a/BizHawk.MultiClient/config/InputConfig.cs +++ b/BizHawk.MultiClient/config/InputConfig.cs @@ -68,14 +68,14 @@ namespace BizHawk.MultiClient protected override void OnShown(EventArgs e) { - Input.Instance.EnableIgnoreModifiers = true; + //Input.Instance.EnableIgnoreModifiers = true; base.OnShown(e); } protected override void OnClosed(EventArgs e) { base.OnClosed(e); - Input.Instance.EnableIgnoreModifiers = false; + //Input.Instance.EnableIgnoreModifiers = false; } private void Do(string platform) diff --git a/BizHawk.MultiClient/config/InputWidget.cs b/BizHawk.MultiClient/config/InputWidget.cs index ca4136341a..bc5d3beb91 100644 --- a/BizHawk.MultiClient/config/InputWidget.cs +++ b/BizHawk.MultiClient/config/InputWidget.cs @@ -90,7 +90,7 @@ namespace BizHawk.MultiClient //Input.Update(); //zero: ??? what is this all about ??? - wasPressed = Input.Instance.GetNextPressedButtonOrNull(); + wasPressed = Input.Instance.GetNextBindEvent(); } protected override void OnLeave(EventArgs e) @@ -115,7 +115,7 @@ namespace BizHawk.MultiClient private void ReadKeys() { Input.Instance.Update(); - string TempBindingStr = Input.Instance.GetNextPressedButtonOrNull(); + string TempBindingStr = Input.Instance.GetNextBindEvent(); if (wasPressed != "" && TempBindingStr == wasPressed) { return;