Input: Changed the way keyboard is handled. Removes some limitations in the previous model and should also work properly under Linux

This commit is contained in:
Souryo 2016-07-28 17:45:18 -04:00
parent 062d22ae80
commit 8cb1b03949
11 changed files with 444 additions and 331 deletions

View File

@ -19,4 +19,7 @@ public:
virtual uint32_t GetPressedKey() = 0;
virtual string GetKeyName(uint32_t keyCode) = 0;
virtual uint32_t GetKeyCode(string keyName) = 0;
virtual void SetKeyState(uint16_t scanCode, bool state) = 0;
virtual void ResetKeyState() = 0;
};

View File

@ -28,8 +28,6 @@ namespace Mesen.GUI.Config
//Create new config file and save it to disk
_config = new Configuration();
_dirtyConfig = new Configuration();
_config.InitializeDefaults();
_dirtyConfig.InitializeDefaults();
SaveConfig();
}
}

View File

@ -88,7 +88,6 @@ namespace Mesen.GUI.Config
config = new Configuration();
}
config.InitializeDefaults();
return config;
}

View File

@ -3,24 +3,25 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
namespace Mesen.GUI.Config
{
public class KeyMappings
{
public string A;
public string B;
public string Select;
public string Start;
public string Up;
public string Down;
public string Left;
public string Right;
public UInt32 A;
public UInt32 B;
public UInt32 Select;
public UInt32 Start;
public UInt32 Up;
public UInt32 Down;
public UInt32 Left;
public UInt32 Right;
public string TurboA;
public string TurboB;
public string TurboStart;
public string TurboSelect;
public UInt32 TurboA;
public UInt32 TurboB;
public UInt32 TurboStart;
public UInt32 TurboSelect;
public KeyMappings()
{
@ -30,83 +31,83 @@ namespace Mesen.GUI.Config
{
if(controllerIndex == 0) {
if(keySetIndex == 0) {
A = "A";
B = "S";
Select = "Q";
Start = "W";
Up = "Up Arrow";
Down = "Down Arrow";
Left = "Left Arrow";
Right = "Right Arrow";
A = InteropEmu.GetKeyCode("A");
B = InteropEmu.GetKeyCode("S");
Select = InteropEmu.GetKeyCode("Q");
Start = InteropEmu.GetKeyCode("W");
Up = InteropEmu.GetKeyCode("Up Arrow");
Down = InteropEmu.GetKeyCode("Down Arrow");
Left = InteropEmu.GetKeyCode("Left Arrow");
Right = InteropEmu.GetKeyCode("Right Arrow");
TurboA = "Z";
TurboB = "X";
TurboA = InteropEmu.GetKeyCode("Z");
TurboB = InteropEmu.GetKeyCode("X");
} else if(keySetIndex == 1) {
//XInput Default (Xbox controllers)
A = "Pad1 A";
B = "Pad1 X";
Select = "Pad1 Back";
Start = "Pad1 Start";
Up = "Pad1 Up";
Down = "Pad1 Down";
Left = "Pad1 Left";
Right = "Pad1 Right";
A = InteropEmu.GetKeyCode("Pad1 A");
B = InteropEmu.GetKeyCode("Pad1 X");
Select = InteropEmu.GetKeyCode("Pad1 Back");
Start = InteropEmu.GetKeyCode("Pad1 Start");
Up = InteropEmu.GetKeyCode("Pad1 Up");
Down = InteropEmu.GetKeyCode("Pad1 Down");
Left = InteropEmu.GetKeyCode("Pad1 Left");
Right = InteropEmu.GetKeyCode("Pad1 Right");
TurboA = "Pad1 B";
TurboB = "Pad1 Y";
TurboA = InteropEmu.GetKeyCode("Pad1 B");
TurboB = InteropEmu.GetKeyCode("Pad1 Y");
} else if(keySetIndex == 2) {
//DirectInput Default (Used PS4 controller as a default)
A = "Joy1 But2";
B = "Joy1 But1";
Select = "Joy1 But9";
Start = "Joy1 But10";
Up = "Joy1 DPad Up";
Down = "Joy1 DPad Down";
Left = "Joy1 DPad Left";
Right = "Joy1 DPad Right";
A = InteropEmu.GetKeyCode("Joy1 But2");
B = InteropEmu.GetKeyCode("Joy1 But1");
Select = InteropEmu.GetKeyCode("Joy1 But9");
Start = InteropEmu.GetKeyCode("Joy1 But10");
Up = InteropEmu.GetKeyCode("Joy1 DPad Up");
Down = InteropEmu.GetKeyCode("Joy1 DPad Down");
Left = InteropEmu.GetKeyCode("Joy1 DPad Left");
Right = InteropEmu.GetKeyCode("Joy1 DPad Right");
TurboA = "Joy1 But3";
TurboB = "Joy1 But4";
TurboA = InteropEmu.GetKeyCode("Joy1 But3");
TurboB = InteropEmu.GetKeyCode("Joy1 But4");
}
} else if(controllerIndex == 1) {
if(keySetIndex == 0) {
A = "G";
B = "H";
Select = "T";
Start = "Y";
Up = "I";
Down = "K";
Left = "J";
Right = "L";
A = InteropEmu.GetKeyCode("G");
B = InteropEmu.GetKeyCode("H");
Select = InteropEmu.GetKeyCode("T");
Start = InteropEmu.GetKeyCode("Y");
Up = InteropEmu.GetKeyCode("I");
Down = InteropEmu.GetKeyCode("K");
Left = InteropEmu.GetKeyCode("J");
Right = InteropEmu.GetKeyCode("L");
TurboA = "B";
TurboB = "N";
TurboA = InteropEmu.GetKeyCode("B");
TurboB = InteropEmu.GetKeyCode("N");
} else if(keySetIndex == 1) {
//XInput Default (Xbox controllers)
A = "Pad2 A";
B = "Pad2 X";
Select = "Pad2 Back";
Start = "Pad2 Start";
Up = "Pad2 Up";
Down = "Pad2 Down";
Left = "Pad2 Left";
Right = "Pad2 Right";
A = InteropEmu.GetKeyCode("Pad2 A");
B = InteropEmu.GetKeyCode("Pad2 X");
Select = InteropEmu.GetKeyCode("Pad2 Back");
Start = InteropEmu.GetKeyCode("Pad2 Start");
Up = InteropEmu.GetKeyCode("Pad2 Up");
Down = InteropEmu.GetKeyCode("Pad2 Down");
Left = InteropEmu.GetKeyCode("Pad2 Left");
Right = InteropEmu.GetKeyCode("Pad2 Right");
TurboA = "Pad2 B";
TurboB = "Pad2 Y";
TurboA = InteropEmu.GetKeyCode("Pad2 B");
TurboB = InteropEmu.GetKeyCode("Pad2 Y");
} else if(keySetIndex == 2) {
//DirectInput Default (Used PS4 controller as a default)
A = "Joy2 But2";
B = "Joy2 But1";
Select = "Joy2 But9";
Start = "Joy2 But10";
Up = "Joy2 DPad Up";
Down = "Joy2 DPad Down";
Left = "Joy2 DPad Left";
Right = "Joy2 DPad Right";
A = InteropEmu.GetKeyCode("Joy2 But2");
B = InteropEmu.GetKeyCode("Joy2 But1");
Select = InteropEmu.GetKeyCode("Joy2 But9");
Start = InteropEmu.GetKeyCode("Joy2 But10");
Up = InteropEmu.GetKeyCode("Joy2 DPad Up");
Down = InteropEmu.GetKeyCode("Joy2 DPad Down");
Left = InteropEmu.GetKeyCode("Joy2 DPad Left");
Right = InteropEmu.GetKeyCode("Joy2 DPad Right");
TurboA = "Joy2 But3";
TurboB = "Joy2 But4";
TurboA = InteropEmu.GetKeyCode("Joy2 But3");
TurboB = InteropEmu.GetKeyCode("Joy2 But4");
}
}
}
@ -115,18 +116,18 @@ namespace Mesen.GUI.Config
{
InteropEmu.KeyMapping mapping = new InteropEmu.KeyMapping();
mapping.A = InteropEmu.GetKeyCode(A);
mapping.B = InteropEmu.GetKeyCode(B);
mapping.Start = InteropEmu.GetKeyCode(Start);
mapping.Select = InteropEmu.GetKeyCode(Select);
mapping.Up = InteropEmu.GetKeyCode(Up);
mapping.Down = InteropEmu.GetKeyCode(Down);
mapping.Left = InteropEmu.GetKeyCode(Left);
mapping.Right = InteropEmu.GetKeyCode(Right);
mapping.TurboA = InteropEmu.GetKeyCode(TurboA);
mapping.TurboB = InteropEmu.GetKeyCode(TurboB);
mapping.TurboStart = InteropEmu.GetKeyCode(TurboStart);
mapping.TurboSelect = InteropEmu.GetKeyCode(TurboSelect);
mapping.A = A;
mapping.B = B;
mapping.Start = Start;
mapping.Select = Select;
mapping.Up = Up;
mapping.Down = Down;
mapping.Left = Left;
mapping.Right = Right;
mapping.TurboA = TurboA;
mapping.TurboB = TurboB;
mapping.TurboStart = TurboStart;
mapping.TurboSelect = TurboSelect;
return mapping;
}
@ -135,6 +136,7 @@ namespace Mesen.GUI.Config
public class ControllerInfo
{
public InteropEmu.ControllerType ControllerType = InteropEmu.ControllerType.StandardController;
[XmlElement(ElementName = "KeyMappings")]
public List<KeyMappings> Keys = new List<KeyMappings>();
public UInt32 TurboSpeed = 2;

View File

@ -18,56 +18,63 @@ namespace Mesen.GUI.Forms.Config
InitializeComponent();
}
private void InitButton(Button btn, UInt32 scanCode)
{
btn.Text = InteropEmu.GetKeyName(scanCode);
btn.Tag = scanCode;
}
public void Initialize(KeyMappings mappings)
{
btnA.Text = mappings.A;
btnB.Text = mappings.B;
btnStart.Text = mappings.Start;
btnSelect.Text = mappings.Select;
btnUp.Text = mappings.Up;
btnDown.Text = mappings.Down;
btnLeft.Text = mappings.Left;
btnRight.Text = mappings.Right;
btnTurboA.Text = mappings.TurboA;
btnTurboB.Text = mappings.TurboB;
InitButton(btnA, mappings.A);
InitButton(btnB, mappings.B);
InitButton(btnStart, mappings.Start);
InitButton(btnSelect, mappings.Select);
InitButton(btnUp, mappings.Up);
InitButton(btnDown, mappings.Down);
InitButton(btnLeft, mappings.Left);
InitButton(btnRight, mappings.Right);
InitButton(btnTurboA, mappings.TurboA);
InitButton(btnTurboB, mappings.TurboB);
}
public void ClearKeys()
{
btnA.Text = "";
btnB.Text = "";
btnStart.Text = "";
btnSelect.Text = "";
btnUp.Text = "";
btnDown.Text = "";
btnLeft.Text = "";
btnRight.Text = "";
btnTurboA.Text = "";
btnTurboB.Text = "";
InitButton(btnA, 0);
InitButton(btnB, 0);
InitButton(btnStart, 0);
InitButton(btnSelect, 0);
InitButton(btnUp, 0);
InitButton(btnDown, 0);
InitButton(btnLeft, 0);
InitButton(btnRight, 0);
InitButton(btnTurboA, 0);
InitButton(btnTurboB, 0);
}
private void btnMapping_Click(object sender, EventArgs e)
{
frmGetKey frm = new frmGetKey();
frm.ShowDialog();
((Button)sender).Text = frm.BindedKey;
((Button)sender).Text = frm.BindedKeyName;
((Button)sender).Tag = frm.BindedKeyCode;
}
public KeyMappings GetKeyMappings()
{
KeyMappings mappings = new KeyMappings() {
A = btnA.Text,
B = btnB.Text,
Start = btnStart.Text,
Select = btnSelect.Text,
Up = btnUp.Text,
Down = btnDown.Text,
Left = btnLeft.Text,
Right = btnRight.Text,
TurboA = btnTurboA.Text,
TurboB = btnTurboB.Text,
TurboSelect = string.Empty,
TurboStart = string.Empty,
A = (UInt32)btnA.Tag,
B = (UInt32)btnB.Tag,
Start = (UInt32)btnStart.Tag,
Select = (UInt32)btnSelect.Tag,
Up = (UInt32)btnUp.Tag,
Down = (UInt32)btnDown.Tag,
Left = (UInt32)btnLeft.Tag,
Right = (UInt32)btnRight.Tag,
TurboA = (UInt32)btnTurboA.Tag,
TurboB = (UInt32)btnTurboB.Tag,
TurboSelect = 0,
TurboStart = 0,
};
return mappings;
}

View File

@ -10,21 +10,52 @@ using System.Windows.Forms;
namespace Mesen.GUI.Forms.Config
{
public partial class frmGetKey : BaseForm
public partial class frmGetKey : BaseForm, IMessageFilter
{
const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x101;
public frmGetKey()
{
InitializeComponent();
InteropEmu.UpdateInputDevices();
InteropEmu.ResetKeyState();
Application.AddMessageFilter(this);
this.FormClosed += (s, e) => Application.RemoveMessageFilter(this);
}
public string BindedKey { get; set; }
bool IMessageFilter.PreFilterMessage(ref Message m)
{
if(m.Msg == WM_KEYUP) {
int virtualKeyCode = (Int32)m.WParam;
int scanCode = (Int32)(((Int64)m.LParam & 0x1FF0000) >> 16);
InteropEmu.SetKeyState(scanCode, false);
}
return false;
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if(msg.Msg == WM_KEYDOWN) {
int virtualKeyCode = (Int32)((Int64)msg.WParam & 0xFF);
int scanCode = (Int32)(((Int64)msg.LParam & 0x1FF0000) >> 16);
InteropEmu.SetKeyState(scanCode, true);
}
return base.ProcessCmdKey(ref msg, keyData);
}
public string BindedKeyName { get; set; }
public UInt32 BindedKeyCode { get; set; }
private void tmrCheckKey_Tick(object sender, EventArgs e)
{
string pressedKey = InteropEmu.GetKeyName(InteropEmu.GetPressedKey());
UInt32 scanCode = InteropEmu.GetPressedKey();
string pressedKey = InteropEmu.GetKeyName(scanCode);
if(!string.IsNullOrWhiteSpace(pressedKey)) {
BindedKey = pressedKey;
BindedKeyName = pressedKey;
BindedKeyCode = scanCode;
this.Close();
}
}

View File

@ -20,7 +20,7 @@ using Mesen.GUI.GoogleDriveIntegration;
namespace Mesen.GUI.Forms
{
public partial class frmMain : BaseForm
public partial class frmMain : BaseForm, IMessageFilter
{
private InteropEmu.NotificationListener _notifListener;
private Thread _emuThread;
@ -60,6 +60,9 @@ namespace Mesen.GUI.Forms
}
InitializeComponent();
Application.AddMessageFilter(this);
this.FormClosed += (s, e) => Application.RemoveMessageFilter(this);
}
public void ProcessCommandLineArguments(string[] args)
@ -108,6 +111,18 @@ namespace Mesen.GUI.Forms
CheckForUpdates(false);
}
}
protected override void OnDeactivate(EventArgs e)
{
base.OnDeactivate(e);
InteropEmu.ResetKeyState();
}
protected override void OnActivated(EventArgs e)
{
base.OnActivated(e);
InteropEmu.ResetKeyState();
}
protected override void OnShown(EventArgs e)
{
@ -177,6 +192,9 @@ namespace Mesen.GUI.Forms
InteropEmu.AddKnowGameFolder(Path.GetDirectoryName(recentItem.Path).ToLowerInvariant());
}
ConfigManager.Config.InitializeDefaults();
ConfigManager.ApplyChanges();
ConfigManager.Config.ApplyConfig();
UpdateEmulationFlags();
@ -672,8 +690,28 @@ namespace Mesen.GUI.Forms
InteropEmu.Reset();
}
const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x101;
bool IMessageFilter.PreFilterMessage(ref Message m)
{
if(m.Msg == WM_KEYUP) {
int virtualKeyCode = (Int32)m.WParam;
int scanCode = (Int32)(((Int64)m.LParam & 0x1FF0000) >> 16);
InteropEmu.SetKeyState(scanCode, false);
}
return false;
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if(msg.Msg == WM_KEYDOWN) {
int virtualKeyCode = (Int32)((Int64)msg.WParam & 0xFF);
int scanCode = (Int32)(((Int64)msg.LParam & 0x1FF0000) >> 16);
InteropEmu.SetKeyState(scanCode, true);
}
if(!this.menuStrip.Enabled) {
//Make sure we disable all shortcut keys while the bar is disabled (i.e when running tests)
return false;

View File

@ -50,7 +50,8 @@ namespace Mesen.GUI
[DllImport(DLLPath)] public static extern UInt32 GetPressedKey();
[DllImport(DLLPath)] public static extern UInt32 GetKeyCode([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string keyName);
[DllImport(DLLPath, EntryPoint="GetKeyName")] private static extern IntPtr GetKeyNameWrapper(UInt32 key);
[DllImport(DLLPath)] public static extern void SetKeyState(Int32 scanCode, [MarshalAs(UnmanagedType.I1)]bool pressed);
[DllImport(DLLPath)] public static extern void ResetKeyState();
[DllImport(DLLPath)] public static extern void Run();
[DllImport(DLLPath)] public static extern void Pause();

View File

@ -116,6 +116,8 @@ namespace InteropEmu {
DllExport void __stdcall UpdateInputDevices() { if(_keyManager) { _keyManager->UpdateDevices(); } }
DllExport uint32_t __stdcall GetPressedKey() { return ControlManager::GetPressedKey(); }
DllExport void __stdcall SetKeyState(int32_t scanCode, bool state) { if(_keyManager) { _keyManager->SetKeyState(scanCode, state); } }
DllExport void __stdcall ResetKeyState() { if(_keyManager) { _keyManager->ResetKeyState(); } }
DllExport const char* __stdcall GetKeyName(uint32_t keyCode)
{
_returnString = ControlManager::GetKeyName(keyCode);

View File

@ -4,207 +4,209 @@
#include "../Core/Console.h"
static vector<KeyDefinition> _keyDefinitions = {
//{ "VK_LBUTTON", 0x01, "Left mouse button" },
//{ "VK_RBUTTON", 0x02, "Right mouse button" },
{ "VK_CANCEL", 0x03, "Control-break processing" },
//{ "VK_MBUTTON", 0x04, "Middle mouse button (three-button mouse)" },
//{ "VK_XBUTTON1", 0x05, "X1 mouse button" },
//{ "VK_XBUTTON2", 0x06, "X2 mouse button" },
{ "-", 0x07, "Undefined" },
{ "VK_BACK", 0x08, "Backspace" },
{ "VK_TAB", 0x09, "Tab" },
//{ "-", 0x0A - 0B, "Reserved" },
{ "VK_CLEAR", 0x0C, "Clear" },
{ "VK_RETURN", 0x0D, "Enter" },
//{ "-", 0x0E - 0F, "Undefined" },
{ "VK_SHIFT", 0x10, "Shift" },
{ "VK_CONTROL", 0x11, "Ctrl" },
{ "VK_MENU", 0x12, "Alt" },
{ "VK_PAUSE", 0x13, "Pause" },
{ "VK_CAPITAL", 0x14, "Caps Lock" },
{ "VK_KANA", 0x15, "IME Kana mode" },
{ "VK_HANGUEL", 0x15, "IME Hanguel mode" },
{ "VK_HANGUL", 0x15, "IME Hangul mode" },
//{ "-", 0x16, "Undefined" },
{ "VK_JUNJA", 0x17, "IME Junja mode" },
{ "VK_FINAL", 0x18, "IME final mode" },
{ "VK_HANJA", 0x19, "IME Hanja mode" },
{ "VK_KANJI", 0x19, "IME Kanji mode" },
//{ "-", 0x1A, "Undefined" },
{ "VK_ESCAPE", 0x1B, "Esc" },
{ "VK_CONVERT", 0x1C, "IME convert" },
{ "VK_NONCONVERT", 0x1D, "IME nonconvert" },
{ "VK_ACCEPT", 0x1E, "IME accept" },
{ "VK_MODECHANGE", 0x1F, "IME mode change request" },
{ "VK_SPACE", 0x20, "Spacebar" },
{ "VK_PRIOR", 0x21, "Page Up" },
{ "VK_NEXT", 0x22, "Page Down" },
{ "VK_END", 0x23, "End" },
{ "VK_HOME", 0x24, "Home" },
{ "VK_LEFT", 0x25, "Left Arrow" },
{ "VK_UP", 0x26, "Up Arrow" },
{ "VK_RIGHT", 0x27, "Right Arrow" },
{ "VK_DOWN", 0x28, "Down Arrow" },
{ "VK_SELECT", 0x29, "Select" },
{ "VK_PRINT", 0x2A, "Print" },
{ "VK_EXECUTE", 0x2B, "Execute" },
{ "VK_SNAPSHOT", 0x2C, "Print Screen" },
{ "VK_INSERT", 0x2D, "Ins" },
{ "VK_DELETE", 0x2E, "Del" },
{ "VK_HELP", 0x2F, "Help" },
{ "0", 0x30, "0" },
{ "1", 0x31, "1" },
{ "2", 0x32, "2" },
{ "3", 0x33, "3" },
{ "4", 0x34, "4" },
{ "5", 0x35, "5" },
{ "6", 0x36, "6" },
{ "7", 0x37, "7" },
{ "8", 0x38, "8" },
{ "9", 0x39, "9" },
//{ "undefined", 0x3A - 40, "undefined" },
{ "A", 0x41, "A" },
{ "B", 0x42, "B" },
{ "C", 0x43, "C" },
{ "D", 0x44, "D" },
{ "E", 0x45, "E" },
{ "F", 0x46, "F" },
{ "G", 0x47, "G" },
{ "H", 0x48, "H" },
{ "I", 0x49, "I" },
{ "J", 0x4A, "J" },
{ "K", 0x4B, "K" },
{ "L", 0x4C, "L" },
{ "M", 0x4D, "M" },
{ "N", 0x4E, "N" },
{ "O", 0x4F, "O" },
{ "P", 0x50, "P" },
{ "Q", 0x51, "Q" },
{ "R", 0x52, "R" },
{ "S", 0x53, "S" },
{ "T", 0x54, "T" },
{ "U", 0x55, "U" },
{ "V", 0x56, "V" },
{ "W", 0x57, "W" },
{ "X", 0x58, "X" },
{ "Y", 0x59, "Y" },
{ "Z", 0x5A, "Z" },
{ "VK_LWIN", 0x5B, "Left Windows" },
{ "VK_RWIN", 0x5C, "Right Windows" },
{ "VK_APPS", 0x5D, "Applications Key" },
//{ "-", 0x5E, "Reserved" },
{ "VK_SLEEP", 0x5F, "Computer Sleep" },
{ "VK_NUMPAD0", 0x60, "Keypad 0" },
{ "VK_NUMPAD1", 0x61, "Keypad 1" },
{ "VK_NUMPAD2", 0x62, "Keypad 2" },
{ "VK_NUMPAD3", 0x63, "Keypad 3" },
{ "VK_NUMPAD4", 0x64, "Keypad 4" },
{ "VK_NUMPAD5", 0x65, "Keypad 5" },
{ "VK_NUMPAD6", 0x66, "Keypad 6" },
{ "VK_NUMPAD7", 0x67, "Keypad 7" },
{ "VK_NUMPAD8", 0x68, "Keypad 8" },
{ "VK_NUMPAD9", 0x69, "Keypad 9" },
{ "VK_MULTIPLY", 0x6A, "Multiply" },
{ "VK_ADD", 0x6B, "Add" },
{ "VK_SEPARATOR", 0x6C, "Separator" },
{ "VK_SUBTRACT", 0x6D, "Subtract" },
{ "VK_DECIMAL", 0x6E, "Decimal" },
{ "VK_DIVIDE", 0x6F, "Divide" },
{ "VK_F1", 0x70, "F1" },
{ "VK_F2", 0x71, "F2" },
{ "VK_F3", 0x72, "F3" },
{ "VK_F4", 0x73, "F4" },
{ "VK_F5", 0x74, "F5" },
{ "VK_F6", 0x75, "F6" },
{ "VK_F7", 0x76, "F7" },
{ "VK_F8", 0x77, "F8" },
{ "VK_F9", 0x78, "F9" },
{ "VK_F10", 0x79, "F10" },
{ "VK_F11", 0x7A, "F11" },
{ "VK_F12", 0x7B, "F12" },
{ "VK_F13", 0x7C, "F13" },
{ "VK_F14", 0x7D, "F14" },
{ "VK_F15", 0x7E, "F15" },
{ "VK_F16", 0x7F, "F16" },
{ "VK_F17", 0x80, "F17" },
{ "VK_F18", 0x81, "F18" },
{ "VK_F19", 0x82, "F19" },
{ "VK_F20", 0x83, "F20" },
{ "VK_F21", 0x84, "F21" },
{ "VK_F22", 0x85, "F22" },
{ "VK_F23", 0x86, "F23" },
{ "VK_F24", 0x87, "F24" },
//{ "-", 0x88 - 8F, "Unassigned" },
{ "VK_NUMLOCK", 0x90, "Num Lock" },
{ "VK_SCROLL", 0x91, "Scroll Lock" },
//{ "VK_LBUTTON", 0x01, "Left mouse button", "" },
//{ "VK_RBUTTON", 0x02, "Right mouse button", "" },
{ "VK_CANCEL", 0x03, "Control-break processing", "" },
//{ "VK_MBUTTON", 0x04, "Middle mouse button (three-button mouse)", "" },
//{ "VK_XBUTTON1", 0x05, "X1 mouse button", "" },
//{ "VK_XBUTTON2", 0x06, "X2 mouse button", "" },
{ "-", 0x07, "Undefined", "" },
{ "VK_BACK", 0x08, "Backspace", "" },
{ "VK_TAB", 0x09, "Tab", "" },
//{ "-", 0x0A - 0B, "Reserved", "" },
{ "VK_CLEAR", 0x0C, "Numpad 5", "" },
{ "VK_RETURN", 0x0D, "Enter", "Numpad Enter" },
//{ "-", 0x0E - 0F, "Undefined", "" },
{ "VK_SHIFT", 0x10, "Shift", "" },
{ "VK_CONTROL", 0x11, "Ctrl", "" },
{ "VK_MENU", 0x12, "Alt", "" },
{ "VK_PAUSE", 0x13, "Pause", "" },
{ "VK_CAPITAL", 0x14, "Caps Lock", "" },
{ "VK_KANA", 0x15, "IME Kana mode", "" },
{ "VK_HANGUEL", 0x15, "IME Hanguel mode", "" },
{ "VK_HANGUL", 0x15, "IME Hangul mode", "" },
//{ "-", 0x16, "Undefined", "" },
{ "VK_JUNJA", 0x17, "IME Junja mode", "" },
{ "VK_FINAL", 0x18, "IME final mode", "" },
{ "VK_HANJA", 0x19, "IME Hanja mode", "" },
{ "VK_KANJI", 0x19, "IME Kanji mode", "" },
//{ "-", 0x1A, "Undefined", "" },
{ "VK_ESCAPE", 0x1B, "Esc", "" },
{ "VK_CONVERT", 0x1C, "IME convert", "" },
{ "VK_NONCONVERT", 0x1D, "IME nonconvert", "" },
{ "VK_ACCEPT", 0x1E, "IME accept", "" },
{ "VK_MODECHANGE", 0x1F, "IME mode change request", "" },
{ "VK_SPACE", 0x20, "Spacebar", "" },
{ "VK_PRIOR", 0x21, "Numpad 9", "Page Up" },
{ "VK_NEXT", 0x22, "Numpad 3", "Page Down" },
{ "VK_END", 0x23, "Numpad 1", "End" },
{ "VK_HOME", 0x24, "Numpad 7", "Home" },
{ "VK_LEFT", 0x25, "Numpad 4", "Left Arrow" },
{ "VK_UP", 0x26, "Numpad 8", "Up Arrow" },
{ "VK_RIGHT", 0x27, "Numpad 6", "Right Arrow" },
{ "VK_DOWN", 0x28, "Numpad 2", "Down Arrow" },
{ "VK_SELECT", 0x29, "Select", "" },
{ "VK_PRINT", 0x2A, "Print", "" },
{ "VK_EXECUTE", 0x2B, "Execute", "" },
{ "VK_SNAPSHOT", 0x2C, "Print Screen", "" },
{ "VK_INSERT", 0x2D, "Numpad 0", "Ins" },
{ "VK_DELETE", 0x2E, "Numpad .", "Del" },
{ "VK_HELP", 0x2F, "Help", "" },
{ "0", 0x30, "0", "" },
{ "1", 0x31, "1", "" },
{ "2", 0x32, "2", "" },
{ "3", 0x33, "3", "" },
{ "4", 0x34, "4", "" },
{ "5", 0x35, "5", "" },
{ "6", 0x36, "6", "" },
{ "7", 0x37, "7", "" },
{ "8", 0x38, "8", "" },
{ "9", 0x39, "9", "" },
//{ "undefined", 0x3A - 40, "undefined", "" },
{ "A", 0x41, "A", "" },
{ "B", 0x42, "B", "" },
{ "C", 0x43, "C", "" },
{ "D", 0x44, "D", "" },
{ "E", 0x45, "E", "" },
{ "F", 0x46, "F", "" },
{ "G", 0x47, "G", "" },
{ "H", 0x48, "H", "" },
{ "I", 0x49, "I", "" },
{ "J", 0x4A, "J", "" },
{ "K", 0x4B, "K", "" },
{ "L", 0x4C, "L", "" },
{ "M", 0x4D, "M", "" },
{ "N", 0x4E, "N", "" },
{ "O", 0x4F, "O", "" },
{ "P", 0x50, "P", "" },
{ "Q", 0x51, "Q", "" },
{ "R", 0x52, "R", "" },
{ "S", 0x53, "S", "" },
{ "T", 0x54, "T", "" },
{ "U", 0x55, "U", "" },
{ "V", 0x56, "V", "" },
{ "W", 0x57, "W", "" },
{ "X", 0x58, "X", "" },
{ "Y", 0x59, "Y", "" },
{ "Z", 0x5A, "Z", "" },
{ "VK_LWIN", 0x5B, "Left Windows", "" },
{ "VK_RWIN", 0x5C, "Right Windows", "" },
{ "VK_APPS", 0x5D, "Applications Key", "" },
//{ "-", 0x5E, "Reserved", "" },
{ "VK_SLEEP", 0x5F, "Computer Sleep", "" },
{ "VK_NUMPAD0", 0x60, "Keypad 0", "" },
{ "VK_NUMPAD1", 0x61, "Keypad 1", "" },
{ "VK_NUMPAD2", 0x62, "Keypad 2", "" },
{ "VK_NUMPAD3", 0x63, "Keypad 3", "" },
{ "VK_NUMPAD4", 0x64, "Keypad 4", "" },
{ "VK_NUMPAD5", 0x65, "Keypad 5", "" },
{ "VK_NUMPAD6", 0x66, "Keypad 6", "" },
{ "VK_NUMPAD7", 0x67, "Keypad 7", "" },
{ "VK_NUMPAD8", 0x68, "Keypad 8", "" },
{ "VK_NUMPAD9", 0x69, "Keypad 9", "" },
{ "VK_MULTIPLY", 0x6A, "Numpad *", "" },
{ "VK_ADD", 0x6B, "Numpad +", "" },
{ "VK_SEPARATOR", 0x6C, "Separator", "" },
{ "VK_SUBTRACT", 0x6D, "Numpad -", "" },
{ "VK_DECIMAL", 0x6E, "Decimal", "" },
{ "VK_DIVIDE", 0x6F, "Numpad /", "" },
{ "VK_F1", 0x70, "F1", "" },
{ "VK_F2", 0x71, "F2", "" },
{ "VK_F3", 0x72, "F3", "" },
{ "VK_F4", 0x73, "F4", "" },
{ "VK_F5", 0x74, "F5", "" },
{ "VK_F6", 0x75, "F6", "" },
{ "VK_F7", 0x76, "F7", "" },
{ "VK_F8", 0x77, "F8", "" },
{ "VK_F9", 0x78, "F9", "" },
{ "VK_F10", 0x79, "F10", "" },
{ "VK_F11", 0x7A, "F11", "" },
{ "VK_F12", 0x7B, "F12", "" },
{ "VK_F13", 0x7C, "F13", "" },
{ "VK_F14", 0x7D, "F14", "" },
{ "VK_F15", 0x7E, "F15", "" },
{ "VK_F16", 0x7F, "F16", "" },
{ "VK_F17", 0x80, "F17", "" },
{ "VK_F18", 0x81, "F18", "" },
{ "VK_F19", 0x82, "F19", "" },
{ "VK_F20", 0x83, "F20", "" },
{ "VK_F21", 0x84, "F21", "" },
{ "VK_F22", 0x85, "F22", "" },
{ "VK_F23", 0x86, "F23", "" },
{ "VK_F24", 0x87, "F24", "" },
//{ "-", 0x88 - 8F, "Unassigned", "" },
{ "VK_NUMLOCK", 0x90, "Pause", "Num Lock" },
{ "VK_SCROLL", 0x91, "Scroll Lock", "" },
//{"-", 0x92-96,"OEM specific"},
//{ "-", 0x97 - 9F, "Unassigned" },
{ "VK_LSHIFT", 0xA0, "Left Shift" },
{ "VK_RSHIFT", 0xA1, "Right Shift" },
{ "VK_LCONTROL", 0xA2, "Left Control" },
{ "VK_RCONTROL", 0xA3, "Right Control" },
{ "VK_LMENU", 0xA4, "Left Menu" },
{ "VK_RMENU", 0xA5, "Right Menu" },
{ "VK_BROWSER_BACK", 0xA6, "Browser Back" },
{ "VK_BROWSER_FORWARD", 0xA7, "Browser Forward" },
{ "VK_BROWSER_REFRESH", 0xA8, "Browser Refresh" },
{ "VK_BROWSER_STOP", 0xA9, "Browser Stop" },
{ "VK_BROWSER_SEARCH", 0xAA, "Browser Search" },
{ "VK_BROWSER_FAVORITES", 0xAB, "Browser Favorites" },
{ "VK_BROWSER_HOME", 0xAC, "Browser Start and Home" },
{ "VK_VOLUME_MUTE", 0xAD, "Volume Mute" },
{ "VK_VOLUME_DOWN", 0xAE, "Volume Down" },
{ "VK_VOLUME_UP", 0xAF, "Volume Up" },
{ "VK_MEDIA_NEXT_TRACK", 0xB0, "Next Track" },
{ "VK_MEDIA_PREV_TRACK", 0xB1, "Previous Track" },
{ "VK_MEDIA_STOP", 0xB2, "Stop Media" },
{ "VK_MEDIA_PLAY_PAUSE", 0xB3, "Play/Pause Media" },
{ "VK_LAUNCH_MAIL", 0xB4, "Start Mail" },
{ "VK_LAUNCH_MEDIA_SELECT", 0xB5, "Select Media" },
{ "VK_LAUNCH_APP1", 0xB6, "Start Application 1" },
{ "VK_LAUNCH_APP2", 0xB7, "Start Application 2" },
//{ "-", 0xB8 - B9, "Reserved" },
{ "VK_OEM_1", 0xBA, "Used for miscellaneous characters; it can vary by keyboard. For the US standard keyboard, the \';:\' key VK_OEM_PLUS" },
{ "VK_OEM_PLUS", 0xBB, "+" },
{ "VK_OEM_COMMA", 0xBC, "," },
{ "VK_OEM_MINUS", 0xBD, "-" },
{ "VK_OEM_PERIOD", 0xBE, "." },
{ "VK_OEM_2", 0xBF, "/" },
{ "VK_OEM_3", 0xC0, "`" },
//{ "-", 0xC1 - D7, "Reserved" },
//{ "-", 0xD8 - DA, "Unassigned" },
{ "VK_OEM_4", 0xDB, "[" },
{ "VK_OEM_5", 0xDC, "\\" },
{ "VK_OEM_6", 0xDD, "]" },
{ "VK_OEM_7", 0xDE, "'" },
{ "VK_OEM_8", 0xDF, "Used for miscellaneous characters; it can vary by keyboard." },
//{ "-", 0xE0, "Reserved" },
//{ "-", 0xE1, "OEM specific" },
{ "VK_OEM_102", 0xE2, "Either the angle bracket key or the backslash key on the RT 102-key keyboard" },
//{ "-", 0xE3 - E4, "OEM specific" },
{ "VK_PROCESSKEY", 0xE5, "IME PROCESS" },
//{ "-", 0xE6, "OEM specific" },
{ "VK_PACKET", 0xE7, "Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT, SendInput, WM_KEYDOWN, and WM_KEYUP" },
//{ "-", 0xE8, "Unassigned" },
//{ "-", 0x97 - 9F, "Unassigned", "" },
{ "VK_LSHIFT", 0xA0, "Left Shift", "" },
{ "VK_RSHIFT", 0xA1, "Right Shift", "" },
{ "VK_LCONTROL", 0xA2, "Left Control", "" },
{ "VK_RCONTROL", 0xA3, "Right Control", "" },
{ "VK_LMENU", 0xA4, "Left Menu", "" },
{ "VK_RMENU", 0xA5, "Right Menu", "" },
{ "VK_BROWSER_BACK", 0xA6, "Browser Back", "" },
{ "VK_BROWSER_FORWARD", 0xA7, "Browser Forward", "" },
{ "VK_BROWSER_REFRESH", 0xA8, "Browser Refresh", "" },
{ "VK_BROWSER_STOP", 0xA9, "Browser Stop", "" },
{ "VK_BROWSER_SEARCH", 0xAA, "Browser Search", "" },
{ "VK_BROWSER_FAVORITES", 0xAB, "Browser Favorites", "" },
{ "VK_BROWSER_HOME", 0xAC, "Browser Start and Home", "" },
{ "VK_VOLUME_MUTE", 0xAD, "Volume Mute", "" },
{ "VK_VOLUME_DOWN", 0xAE, "Volume Down", "" },
{ "VK_VOLUME_UP", 0xAF, "Volume Up", "" },
{ "VK_MEDIA_NEXT_TRACK", 0xB0, "Next Track", "" },
{ "VK_MEDIA_PREV_TRACK", 0xB1, "Previous Track", "" },
{ "VK_MEDIA_STOP", 0xB2, "Stop Media", "" },
{ "VK_MEDIA_PLAY_PAUSE", 0xB3, "Play/Pause Media", "" },
{ "VK_LAUNCH_MAIL", 0xB4, "Start Mail", "" },
{ "VK_LAUNCH_MEDIA_SELECT", 0xB5, "Select Media", "" },
{ "VK_LAUNCH_APP1", 0xB6, "Start Application 1", "" },
{ "VK_LAUNCH_APP2", 0xB7, "Start Application 2", "" },
//{ "-", 0xB8 - B9, "Reserved", "" },
{ "VK_OEM_1", 0xBA, ";", "" },
{ "VK_OEM_PLUS", 0xBB, "+", "" },
{ "VK_OEM_COMMA", 0xBC, ",", "" },
{ "VK_OEM_MINUS", 0xBD, "-", "" },
{ "VK_OEM_PERIOD", 0xBE, ".", "" },
{ "VK_OEM_2", 0xBF, "/", "Numpad /" },
{ "VK_OEM_3", 0xC0, "`", "" },
//{ "-", 0xC1 - D7, "Reserved", "" },
//{ "-", 0xD8 - DA, "Unassigned", "" },
{ "VK_OEM_4", 0xDB, "[", "" },
{ "VK_OEM_5", 0xDC, "\\", "" },
{ "VK_OEM_6", 0xDD, "]", "" },
{ "VK_OEM_7", 0xDE, "'", "" },
{ "VK_OEM_8", 0xDF, "Used for miscellaneous characters; it can vary by keyboard.", "" },
//{ "-", 0xE0, "Reserved", "" },
//{ "-", 0xE1, "OEM specific", "" },
{ "VK_OEM_102", 0xE2, "\\", "" },
//{ "-", 0xE3 - E4, "OEM specific", "" },
{ "VK_PROCESSKEY", 0xE5, "IME PROCESS", "" },
//{ "-", 0xE6, "OEM specific", "" },
{ "VK_PACKET", 0xE7, "Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT, SendInput, WM_KEYDOWN, and WM_KEYUP", "" },
//{ "-", 0xE8, "Unassigned", "" },
// {"-",0xE6,"OEM specific"},
{ "VK_PACKET", 0xE7, "Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT, SendInput, WM_KEYDOWN, and WM_KEYUP" },
{ "VK_PACKET", 0xE7, "Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT, SendInput, WM_KEYDOWN, and WM_KEYUP", "" },
// {"-",0xE8,"Unassigned"},
//{ "-", 0xE9 - F5, "OEM specific" },
{ "VK_ATTN", 0xF6, "Attn" },
{ "VK_CRSEL", 0xF7, "CrSel" },
{ "VK_EXSEL", 0xF8, "ExSel" },
{ "VK_EREOF", 0xF9, "Erase EOF" },
{ "VK_PLAY", 0xFA, "Play" },
{ "VK_ZOOM", 0xFB, "Zoom" },
{ "VK_NONAME", 0xFC, "Reserved" },
{ "VK_PA1", 0xFD, "PA1" },
{ "VK_OEM_CLEAR", 0xFE, "Clear" }
//{ "-", 0xE9 - F5, "OEM specific", "" },
{ "VK_ATTN", 0xF6, "Attn", "" },
{ "VK_CRSEL", 0xF7, "CrSel", "" },
{ "VK_EXSEL", 0xF8, "ExSel", "" },
{ "VK_EREOF", 0xF9, "Erase EOF", "Menu" },
{ "VK_PLAY", 0xFA, "Play", "" },
{ "VK_ZOOM", 0xFB, "Zoom", "" },
{ "VK_NONAME", 0xFC, "Reserved", "" },
{ "VK_PA1", 0xFD, "PA1", "" },
{ "VK_OEM_CLEAR", 0xFE, "Clear", "" }
};
WindowsKeyManager::WindowsKeyManager(HWND hWnd)
{
_hWnd = hWnd;
_keyState.insert(_keyState.end(), 0x200, 0);
//Init XInput buttons
vector<string> buttonNames = { "Up", "Down", "Left", "Right", "Start", "Back", "L3", "R3", "L1", "R1", "?", "?", "A", "B", "X", "Y", "L2", "R2", "RT Up", "RT Down", "RT Up", "RT Left", "RT Right" };
for(int i = 0; i < 4; i++) {
@ -225,6 +227,17 @@ WindowsKeyManager::WindowsKeyManager(HWND hWnd)
}
}
for(KeyDefinition &keyDef : _keyDefinitions) {
_keyNames[keyDef.keyCode] = keyDef.description;
_keyExtendedNames[keyDef.keyCode] = keyDef.extDescription.empty() ? "Ext " + keyDef.description : keyDef.extDescription;
uint32_t keyCode = keyDef.keyCode <= 0xFFFF ? MapVirtualKeyEx(keyDef.keyCode & 0xFF, MAPVK_VK_TO_VSC, nullptr) : keyDef.keyCode;
_keyCodes[keyDef.description] = keyCode;
if(!keyDef.extDescription.empty()) {
_keyCodes[keyDef.extDescription] = 0x100 | keyCode;
}
}
_xInput.reset(new XInputManager());
_directInput.reset(new DirectInputManager(hWnd));
}
@ -259,8 +272,8 @@ bool WindowsKeyManager::IsKeyPressed(uint32_t key)
uint8_t gamepadButton = (key - 0xFFFF) % 0x100;
return _xInput->IsPressed(gamepadPort, gamepadButton);
}
} else {
return (GetAsyncKeyState(key) & 0x8000) == 0x8000;
} else if(key < 0x200) {
return _keyState[key] != 0;
}
return false;
}
@ -297,30 +310,30 @@ uint32_t WindowsKeyManager::GetPressedKey()
}
}
for(int i = 0; i < 0xFF; i++) {
if((GetAsyncKeyState(i) & 0x8000) == 0x8000) {
for(int i = 0; i < 0x200; i++) {
if(_keyState[i]) {
return i;
}
}
return 0;
}
string WindowsKeyManager::GetKeyName(uint32_t key)
string WindowsKeyManager::GetKeyName(uint32_t scanCode)
{
for(KeyDefinition keyDef : _keyDefinitions) {
if(keyDef.keyCode == key) {
return keyDef.description;
}
uint32_t keyCode = scanCode <= 0xFFFF ? MapVirtualKeyEx(scanCode & 0xFF, MAPVK_VSC_TO_VK, nullptr) : scanCode;
bool extendedKey = (scanCode <= 0xFFFF && scanCode & 0x100);
auto keyDef = (extendedKey ? _keyExtendedNames : _keyNames).find(keyCode);
if(keyDef != (extendedKey ? _keyExtendedNames : _keyNames).end()) {
return keyDef->second;
}
return "";
}
uint32_t WindowsKeyManager::GetKeyCode(string keyName)
{
for(KeyDefinition keyDef : _keyDefinitions) {
if(keyName.compare(keyDef.description) == 0) {
return keyDef.keyCode;
}
auto keyDef = _keyCodes.find(keyName);
if(keyDef != _keyCodes.end()) {
return keyDef->second;
}
return 0;
}
@ -332,3 +345,13 @@ void WindowsKeyManager::UpdateDevices()
_directInput->UpdateDeviceList();
Console::Resume();
}
void WindowsKeyManager::SetKeyState(uint16_t scanCode, bool state)
{
_keyState[scanCode & 0x1FF] = state ? 1 : 0;
}
void WindowsKeyManager::ResetKeyState()
{
memset(_keyState.data(), 0, 0x200);
}

View File

@ -1,6 +1,7 @@
#pragma once
#include "stdafx.h"
#include <unordered_map>
#include "../Core/IKeyManager.h"
#include "../Utilities/Timer.h"
#include "XInputManager.h"
@ -10,6 +11,7 @@ struct KeyDefinition {
string name;
uint32_t keyCode;
string description;
string extDescription;
};
class WindowsKeyManager : public IKeyManager
@ -17,8 +19,12 @@ class WindowsKeyManager : public IKeyManager
private:
Timer _timer;
HWND _hWnd;
vector<uint32_t> _keyState;
unique_ptr<DirectInputManager> _directInput;
unique_ptr<XInputManager> _xInput;
std::unordered_map<uint32_t, string> _keyNames;
std::unordered_map<uint32_t, string> _keyExtendedNames;
std::unordered_map<string, uint32_t> _keyCodes;
public:
WindowsKeyManager(HWND hWnd);
@ -31,5 +37,8 @@ class WindowsKeyManager : public IKeyManager
string GetKeyName(uint32_t key);
uint32_t GetKeyCode(string keyName);
void SetKeyState(uint16_t scanCode, bool state);
void ResetKeyState();
void UpdateDevices();
};