use buffered mode for keyboard input, so that it is impossible for quick keystrokes to get missed. also increase priority of input thread.

This commit is contained in:
zeromus 2014-04-20 03:38:03 +00:00
parent 06ffa9601c
commit 39ec2ebc90
2 changed files with 55 additions and 24 deletions

View File

@ -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<Key>();
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)
{

View File

@ -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<KeyEvent> EmptyList = new List<KeyEvent>();
static List<KeyEvent> EventList = new List<KeyEvent>();
public static IEnumerable<KeyEvent> 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)