From 39ec2ebc908998fd6b3db19f237c0b4eca73a9bb Mon Sep 17 00:00:00 2001 From: zeromus Date: Sun, 20 Apr 2014 03:38:03 +0000 Subject: [PATCH] use buffered mode for keyboard input, so that it is impossible for quick keystrokes to get missed. also increase priority of input thread. --- BizHawk.Client.EmuHawk/Input/Input.cs | 34 ++++++++++-------- BizHawk.Client.EmuHawk/Input/Keyboard.cs | 45 ++++++++++++++++++------ 2 files changed, 55 insertions(+), 24 deletions(-) diff --git a/BizHawk.Client.EmuHawk/Input/Input.cs b/BizHawk.Client.EmuHawk/Input/Input.cs index 3fa45ce956..403d78577f 100644 --- a/BizHawk.Client.EmuHawk/Input/Input.cs +++ b/BizHawk.Client.EmuHawk/Input/Input.cs @@ -92,7 +92,11 @@ namespace BizHawk.Client.EmuHawk private Input() { #if WINDOWS - UpdateThread = new Thread(UpdateThreadProc) {IsBackground = true}; + UpdateThread = new Thread(UpdateThreadProc) + { + IsBackground = true, + Priority = ThreadPriority.AboveNormal //why not? this thread shouldn't be very heavy duty, and we want it to be responsive + }; UpdateThread.Start(); #endif } @@ -172,7 +176,8 @@ namespace BizHawk.Client.EmuHawk void HandleButton(string button, bool newState) { - if (EnableIgnoreModifiers && IgnoreKeys.Contains(button)) return; + bool isModifier = IgnoreKeys.Contains(button); + if (EnableIgnoreModifiers && isModifier) return; if (LastState[button] && newState) return; if (!LastState[button] && !newState) return; @@ -185,6 +190,15 @@ namespace BizHawk.Client.EmuHawk return; } + //apply + //NOTE: this is not quite right. if someone held leftshift+rightshift it would be broken. seems unlikely, though. + if (button == "LeftShift") { _Modifiers &= ~ModifierKey.Shift; if (newState) _Modifiers |= ModifierKey.Shift; } + if (button == "RightShift") { _Modifiers &= ~ModifierKey.Shift; if (newState) _Modifiers |= ModifierKey.Shift; } + if (button == "LeftControl"){ _Modifiers &= ~ModifierKey.Control; if (newState) _Modifiers |= ModifierKey.Control; } + if (button == "RightControl"){ _Modifiers &= ~ModifierKey.Control; if (newState) _Modifiers |= ModifierKey.Control; } + if (button == "LeftAlt") { _Modifiers &= ~ModifierKey.Alt; if (newState) _Modifiers |= ModifierKey.Alt; } + if (button == "RightAlt") { _Modifiers &= ~ModifierKey.Alt; if (newState) _Modifiers |= ModifierKey.Alt; } + //dont generate events for things like Ctrl+LeftControl ModifierKey mods = _Modifiers; if (button == "LeftShift") mods &= ~ModifierKey.Shift; @@ -219,7 +233,7 @@ namespace BizHawk.Client.EmuHawk LogicalButton alreadyReleased = ie.LogicalButton; var ieModified = new InputEvent { - LogicalButton = (LogicalButton) ModifierState[button], + LogicalButton = (LogicalButton)ModifierState[button], EventType = InputEventType.Release }; if (ieModified.LogicalButton != alreadyReleased) @@ -276,26 +290,18 @@ namespace BizHawk.Client.EmuHawk { for (; ; ) { - KeyInput.Update(); + var keyEvents = KeyInput.Update(); GamePad.UpdateAll(); GamePad360.UpdateAll(); - _Modifiers = KeyInput.GetModifierKeysAsKeys(); - //this block is going to massively modify data structures that the binding method uses, so we have to lock it all lock (this) { _NewEvents.Clear(); //analyze keys - var bleh = new HashSet(); - foreach (var k in KeyInput.State.PressedKeys) - bleh.Add(k); - foreach (var k in KeyInput.State.AllKeys) - if (bleh.Contains(k)) - HandleButton(k.ToString(), true); - else - HandleButton(k.ToString(), false); + foreach (var ke in keyEvents) + HandleButton(ke.Key.ToString(), ke.Pressed); lock (FloatValues) { diff --git a/BizHawk.Client.EmuHawk/Input/Keyboard.cs b/BizHawk.Client.EmuHawk/Input/Keyboard.cs index f350c808b7..8fc42ebeb1 100644 --- a/BizHawk.Client.EmuHawk/Input/Keyboard.cs +++ b/BizHawk.Client.EmuHawk/Input/Keyboard.cs @@ -1,4 +1,5 @@ -using SlimDX; +using System.Collections.Generic; +using SlimDX; using SlimDX.DirectInput; namespace BizHawk.Client.EmuHawk @@ -17,21 +18,45 @@ namespace BizHawk.Client.EmuHawk if (keyboard == null || keyboard.Disposed) keyboard = new Keyboard(dinput); keyboard.SetCooperativeLevel(GlobalWin.MainForm.Handle, CooperativeLevel.Background | CooperativeLevel.Nonexclusive); + keyboard.Properties.BufferSize = 8; } - public static void Update() + static List EmptyList = new List(); + static List EventList = new List(); + + public static IEnumerable Update() { - if (keyboard.Acquire().IsFailure) - return; - if (keyboard.Poll().IsFailure) - return; + EventList.Clear(); - keyboard.GetCurrentState(ref state); - if (Result.Last.IsFailure) - return; + if (keyboard.Acquire().IsFailure) + return EmptyList; + if (keyboard.Poll().IsFailure) + return EmptyList; + + for (; ; ) + { + var events = keyboard.GetBufferedData(); + if (Result.Last.IsFailure) + return EventList; + if (events.Count == 0) + break; + foreach (var e in events) + { + foreach (var k in e.PressedKeys) + EventList.Add(new KeyEvent { Key = k, Pressed = true }); + foreach (var k in e.ReleasedKeys) + EventList.Add(new KeyEvent { Key = k, Pressed = false }); + } + } + + return EventList; } - public static KeyboardState State { get { return state; } } + public struct KeyEvent + { + public Key Key; + public bool Pressed; + } public static bool IsPressed(Key key)