Add unicode naming for keys (dev/keyboardManager) (#1978)

* Added key names

* Display names in detect keyboard UI

* Added keyboard layout for edit keyboard window

* Removed commented code

* removed unused code

* fixed argument modifiers

* Added newline at EOF

* Added unicode changes to edit shortcuts window
This commit is contained in:
Arjun Balgovind
2020-04-09 09:20:19 -07:00
committed by Tomas Agustin Raies
parent 6fbed4ad5c
commit e0ddaa74d0
16 changed files with 309 additions and 233 deletions

View File

@@ -89,6 +89,7 @@
<ItemGroup>
<ClCompile Include="Helpers.cpp" />
<ClCompile Include="KeyboardManagerState.cpp" />
<ClCompile Include="LayoutMap.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
@@ -99,6 +100,7 @@
<ItemGroup>
<ClInclude Include="Helpers.h" />
<ClInclude Include="KeyboardManagerState.h" />
<ClInclude Include="LayoutMap.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="RemapShortcut.h" />
<ClInclude Include="Shortcut.h" />

View File

@@ -24,6 +24,9 @@
<ClCompile Include="pch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="LayoutMap.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Shortcut.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -41,6 +44,9 @@
<ClInclude Include="pch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="LayoutMap.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Shortcut.h">
<Filter>Header Files</Filter>
</ClInclude>

View File

@@ -58,6 +58,10 @@ void KeyboardManagerState::ResetUIState()
detectedShortcut.Reset();
detectedShortcut_lock.unlock();
std::unique_lock<std::mutex> currentShortcut_lock(currentShortcut_mutex);
currentShortcut.Reset();
currentShortcut_lock.unlock();
// Reset all the single key remap UI stored variables.
std::unique_lock<std::mutex> currentSingleKeyUI_lock(currentSingleKeyUI_mutex);
currentSingleKeyUI = nullptr;
@@ -158,8 +162,11 @@ void KeyboardManagerState::UpdateDetectShortcutUI()
std::unique_lock<std::mutex> detectedShortcut_lock(detectedShortcut_mutex);
std::vector<hstring> shortcut = detectedShortcut.GetKeyVector();
std::unique_lock<std::mutex> currentShortcut_lock(currentShortcut_mutex);
// Save the latest displayed shortcut
currentShortcut = detectedShortcut;
currentShortcut_lock.unlock();
std::vector<hstring> shortcut = detectedShortcut.GetKeyVector(keyboardMap);
detectedShortcut_lock.unlock();
@@ -184,7 +191,7 @@ void KeyboardManagerState::UpdateDetectSingleKeyRemapUI()
}
std::unique_lock<std::mutex> detectedRemapKey_lock(detectedRemapKey_mutex);
hstring key = winrt::to_hstring((unsigned int)detectedRemapKey);
hstring key = winrt::to_hstring(keyboardMap.GetKeyName(detectedRemapKey).c_str());
detectedRemapKey_lock.unlock();
// Since this function is invoked from the back-end thread, in order to update the UI the dispatcher must be used.
@@ -198,37 +205,15 @@ void KeyboardManagerState::UpdateDetectSingleKeyRemapUI()
// Function to return the currently detected shortcut which is displayed on the UI
Shortcut KeyboardManagerState::GetDetectedShortcut()
{
std::unique_lock<std::mutex> lock(currentShortcutUI_mutex);
std::vector<winrt::hstring> keys;
if (currentShortcutUI.Children().Size() > 0)
{
for (auto border : currentShortcutUI.Children())
{
auto keyString = border.as<Border>().Child().as<TextBlock>().Text();
keys.push_back(keyString);
}
}
lock.unlock();
return Shortcut::CreateShortcut(keys);
std::lock_guard<std::mutex> lock(currentShortcut_mutex);
return currentShortcut;
}
// Function to return the currently detected remap key which is displayed on the UI
DWORD KeyboardManagerState::GetDetectedSingleRemapKey()
{
std::unique_lock<std::mutex> lock(currentSingleKeyUI_mutex);
DWORD key = 0;
if (currentSingleKeyUI.Children().Size() > 0)
{
auto border = currentSingleKeyUI.Children().GetAt(0);
auto keyString = border.as<Border>().Child().as<TextBlock>().Text();
key = std::stoul(keyString.c_str());
}
lock.unlock();
return key;
std::lock_guard<std::mutex> lock(detectedRemapKey_mutex);
return detectedRemapKey;
}
// Function which can be used in HandleKeyboardHookEvent before the single key remap event to use the UI and suppress events while the remap window is active.

View File

@@ -1,5 +1,6 @@
#pragma once
#include "Helpers.h"
#include "LayoutMap.h"
#include "Shortcut.h"
#include "RemapShortcut.h"
#include <interface/lowlevel_keyboard_event_data.h>
@@ -30,10 +31,14 @@ private:
HWND currentUIWindow;
std::mutex currentUIWindow_mutex;
// Object to store the shortcut detected in the detect shortcut UI window. This is used in both the backend and the UI.
// Object to store the shortcut detected in the detect shortcut UI window. Gets cleared on releasing keys. This is used in both the backend and the UI.
Shortcut detectedShortcut;
std::mutex detectedShortcut_mutex;
// Object to store the shortcut state displayed in the UI window. Always stores last displayed shortcut irrespective of releasing keys. This is used in both the backend and the UI.
Shortcut currentShortcut;
std::mutex currentShortcut_mutex;
// Store detected remap key in the remap UI window. This is used in both the backend and the UI.
DWORD detectedRemapKey;
std::mutex detectedRemapKey_mutex;
@@ -67,6 +72,9 @@ public:
std::map<std::wstring, std::map<Shortcut, RemapShortcut>> appSpecificShortcutReMap;
std::mutex appSpecificShortcutReMap_mutex;
// Stores the keyboard layout
LayoutMap keyboardMap;
// Constructor
KeyboardManagerState();

View File

@@ -0,0 +1,14 @@
#include "pch.h"
#include "LayoutMap.h"
std::wstring LayoutMap::GetKeyName(DWORD key)
{
std::wstring result = L"Undefined";
std::lock_guard<std::mutex> lock(keyboardLayoutMap_mutex);
auto it = keyboardLayoutMap.find(key);
if (it != keyboardLayoutMap.end())
{
result = it->second;
}
return result;
}

View File

@@ -0,0 +1,152 @@
#pragma once
#include <interface/lowlevel_keyboard_event_data.h>
#include <string>
#include <map>
#include <mutex>
// Wrapper class to handle keyboard layout
class LayoutMap
{
private:
// Stores mappings for all the virtual key codes to the name of the key
std::map<DWORD, std::wstring> keyboardLayoutMap;
std::mutex keyboardLayoutMap_mutex;
public:
LayoutMap()
{
// Get keyboard layout for current thread
HKL layout = GetKeyboardLayout(0);
unsigned char btKeys[256] = { 0 };
GetKeyboardState(btKeys);
// Iterate over all the virtual key codes
for (int i = 0; i < 256; i++)
{
// Get the scan code from the virtual key code
UINT scanCode = MapVirtualKeyExW(i, MAPVK_VK_TO_VSC, layout);
// Get the unicode representation from the virtual key code and scan code pair to
wchar_t szBuffer[3] = { 0 };
int result = ToUnicodeEx(i, scanCode, (BYTE*)btKeys, szBuffer, 3, 0, layout);
// If a representation is returned
if (result > 0)
{
keyboardLayoutMap[i] = szBuffer;
}
else
{
// Store the virtual key code as string
keyboardLayoutMap[i] = L"VK " + std::to_wstring(i);
}
}
// Override special key names like Shift, Ctrl etc because they don't have unicode mappings and key names like Enter, Space as they appear as "\r", " "
// To do: localization
keyboardLayoutMap[VK_CANCEL] = L"Break";
keyboardLayoutMap[VK_BACK] = L"Backspace";
keyboardLayoutMap[VK_TAB] = L"Tab";
keyboardLayoutMap[VK_CLEAR] = L"Clear";
keyboardLayoutMap[VK_RETURN] = L"Enter";
keyboardLayoutMap[VK_SHIFT] = L"Shift";
keyboardLayoutMap[VK_CONTROL] = L"Ctrl";
keyboardLayoutMap[VK_MENU] = L"Alt";
keyboardLayoutMap[VK_PAUSE] = L"Pause";
keyboardLayoutMap[VK_CAPITAL] = L"Caps Lock";
keyboardLayoutMap[VK_ESCAPE] = L"Esc";
keyboardLayoutMap[VK_SPACE] = L"Space";
keyboardLayoutMap[VK_PRIOR] = L"PgUp";
keyboardLayoutMap[VK_NEXT] = L"PgDn";
keyboardLayoutMap[VK_END] = L"End";
keyboardLayoutMap[VK_HOME] = L"Home";
keyboardLayoutMap[VK_LEFT] = L"Left";
keyboardLayoutMap[VK_UP] = L"Up";
keyboardLayoutMap[VK_RIGHT] = L"Right";
keyboardLayoutMap[VK_DOWN] = L"Down";
keyboardLayoutMap[VK_SELECT] = L"Select";
keyboardLayoutMap[VK_PRINT] = L"Print";
keyboardLayoutMap[VK_EXECUTE] = L"Execute";
keyboardLayoutMap[VK_SNAPSHOT] = L"Print Screen";
keyboardLayoutMap[VK_INSERT] = L"Insert";
keyboardLayoutMap[VK_DELETE] = L"Delete";
keyboardLayoutMap[VK_HELP] = L"Help";
keyboardLayoutMap[VK_LWIN] = L"LWin";
keyboardLayoutMap[VK_RWIN] = L"RWin";
keyboardLayoutMap[VK_APPS] = L"Menu";
keyboardLayoutMap[VK_SLEEP] = L"Sleep";
keyboardLayoutMap[VK_NUMPAD0] = L"NumPad 0";
keyboardLayoutMap[VK_NUMPAD1] = L"NumPad 1";
keyboardLayoutMap[VK_NUMPAD2] = L"NumPad 2";
keyboardLayoutMap[VK_NUMPAD3] = L"NumPad 3";
keyboardLayoutMap[VK_NUMPAD4] = L"NumPad 4";
keyboardLayoutMap[VK_NUMPAD5] = L"NumPad 5";
keyboardLayoutMap[VK_NUMPAD6] = L"NumPad 6";
keyboardLayoutMap[VK_NUMPAD7] = L"NumPad 7";
keyboardLayoutMap[VK_NUMPAD8] = L"NumPad 8";
keyboardLayoutMap[VK_NUMPAD9] = L"NumPad 9";
keyboardLayoutMap[VK_SEPARATOR] = L"Separator";
keyboardLayoutMap[VK_F1] = L"F1";
keyboardLayoutMap[VK_F2] = L"F2";
keyboardLayoutMap[VK_F3] = L"F3";
keyboardLayoutMap[VK_F4] = L"F4";
keyboardLayoutMap[VK_F5] = L"F5";
keyboardLayoutMap[VK_F6] = L"F6";
keyboardLayoutMap[VK_F7] = L"F7";
keyboardLayoutMap[VK_F8] = L"F8";
keyboardLayoutMap[VK_F9] = L"F9";
keyboardLayoutMap[VK_F10] = L"F10";
keyboardLayoutMap[VK_F11] = L"F11";
keyboardLayoutMap[VK_F12] = L"F12";
keyboardLayoutMap[VK_F13] = L"F13";
keyboardLayoutMap[VK_F14] = L"F14";
keyboardLayoutMap[VK_F15] = L"F15";
keyboardLayoutMap[VK_F16] = L"F16";
keyboardLayoutMap[VK_F17] = L"F17";
keyboardLayoutMap[VK_F18] = L"F18";
keyboardLayoutMap[VK_F19] = L"F19";
keyboardLayoutMap[VK_F20] = L"F20";
keyboardLayoutMap[VK_F21] = L"F21";
keyboardLayoutMap[VK_F22] = L"F22";
keyboardLayoutMap[VK_F23] = L"F23";
keyboardLayoutMap[VK_F24] = L"F24";
keyboardLayoutMap[VK_NUMLOCK] = L"Num Lock";
keyboardLayoutMap[VK_SCROLL] = L"Scroll Lock";
keyboardLayoutMap[VK_LSHIFT] = L"LShift";
keyboardLayoutMap[VK_RSHIFT] = L"RShift";
keyboardLayoutMap[VK_LCONTROL] = L"LCtrl";
keyboardLayoutMap[VK_RCONTROL] = L"RCtrl";
keyboardLayoutMap[VK_LMENU] = L"LAlt";
keyboardLayoutMap[VK_RMENU] = L"RAlt";
keyboardLayoutMap[VK_BROWSER_BACK] = L"Browser Back";
keyboardLayoutMap[VK_BROWSER_FORWARD] = L"Browser Forward";
keyboardLayoutMap[VK_BROWSER_REFRESH] = L"Browser Refresh";
keyboardLayoutMap[VK_BROWSER_STOP] = L"Browser Stop";
keyboardLayoutMap[VK_BROWSER_SEARCH] = L"Browser Search";
keyboardLayoutMap[VK_BROWSER_FAVORITES] = L"Browser Favorites";
keyboardLayoutMap[VK_BROWSER_HOME] = L"Browser Start & Home";
keyboardLayoutMap[VK_VOLUME_MUTE] = L"Volume Mute";
keyboardLayoutMap[VK_VOLUME_DOWN] = L"Volume Down";
keyboardLayoutMap[VK_VOLUME_UP] = L"Volume Up";
keyboardLayoutMap[VK_MEDIA_NEXT_TRACK] = L"Next Track";
keyboardLayoutMap[VK_MEDIA_PREV_TRACK] = L"Previous Track";
keyboardLayoutMap[VK_MEDIA_STOP] = L"Stop Media";
keyboardLayoutMap[VK_MEDIA_PLAY_PAUSE] = L"Play/Pause Media";
keyboardLayoutMap[VK_LAUNCH_MAIL] = L"Start Mail";
keyboardLayoutMap[VK_LAUNCH_MEDIA_SELECT] = L"Select Media";
keyboardLayoutMap[VK_LAUNCH_APP1] = L"Start Application 1";
keyboardLayoutMap[VK_LAUNCH_APP2] = L"Start Application 2";
keyboardLayoutMap[VK_PACKET] = L"Packet";
keyboardLayoutMap[VK_ATTN] = L"Attn";
keyboardLayoutMap[VK_CRSEL] = L"CrSel";
keyboardLayoutMap[VK_EXSEL] = L"ExSel";
keyboardLayoutMap[VK_EREOF] = L"Erase EOF";
keyboardLayoutMap[VK_PLAY] = L"Play";
keyboardLayoutMap[VK_ZOOM] = L"Zoom";
keyboardLayoutMap[VK_PA1] = L"PA1";
keyboardLayoutMap[VK_OEM_CLEAR] = L"Clear";
keyboardLayoutMap[0xFF] = L"Undefined";
// To do: Add IME key names
}
// Function to return the unicode string name of the key
std::wstring GetKeyName(DWORD key);
};

View File

@@ -99,7 +99,6 @@ DWORD Shortcut::GetWinKey(const ModifierKey& input) const
//return VK_LWIN by default
return VK_LWIN;
}
}
}
@@ -393,10 +392,10 @@ void Shortcut::ResetKey(const DWORD& input, const bool& isWinBoth)
}
// Function to return the string representation of the shortcut
winrt::hstring Shortcut::ToHstring() const
winrt::hstring Shortcut::ToHstring(LayoutMap& keyboardMap)
{
std::vector<winrt::hstring> keys = GetKeyVector();
std::vector<winrt::hstring> keys = GetKeyVector(keyboardMap);
winrt::hstring output;
for (auto& key : keys)
{
@@ -404,7 +403,7 @@ winrt::hstring Shortcut::ToHstring() const
}
if (keys.size() > 1)
{
return winrt::hstring(output.c_str(), output.size() - 1);
return winrt::hstring(output.c_str(), output.size() - 1);
}
else
{
@@ -412,28 +411,28 @@ winrt::hstring Shortcut::ToHstring() const
}
}
std::vector<winrt::hstring> Shortcut::GetKeyVector() const
std::vector<winrt::hstring> Shortcut::GetKeyVector(LayoutMap& keyboardMap)
{
std::vector<winrt::hstring> keys;
if (winKey != ModifierKey::Disabled)
{
keys.push_back(ModifierKeyNameWithSide(winKey, L"Win"));
keys.push_back(winrt::to_hstring(keyboardMap.GetKeyName(GetWinKey(ModifierKey::Left)).c_str()));
}
if (ctrlKey != ModifierKey::Disabled)
{
keys.push_back(ModifierKeyNameWithSide(ctrlKey, L"Ctrl"));
keys.push_back(winrt::to_hstring(keyboardMap.GetKeyName(GetCtrlKey()).c_str()));
}
if (altKey != ModifierKey::Disabled)
{
keys.push_back(ModifierKeyNameWithSide(altKey, L"Alt"));
keys.push_back(winrt::to_hstring(keyboardMap.GetKeyName(GetAltKey()).c_str()));
}
if (shiftKey != ModifierKey::Disabled)
{
keys.push_back(ModifierKeyNameWithSide(shiftKey, L"Shift"));
keys.push_back(winrt::to_hstring(keyboardMap.GetKeyName(GetShiftKey()).c_str()));
}
if (actionKey != NULL)
{
keys.push_back(winrt::to_hstring((unsigned int)actionKey));
keys.push_back(winrt::to_hstring(keyboardMap.GetKeyName(actionKey).c_str()));
}
return keys;
}
@@ -710,101 +709,3 @@ int Shortcut::GetCommonModifiersCount(const Shortcut& input) const
return commonElements;
}
// Function to return the name of the key with L or R prefix depending on the first argument. Second argument should be the name of the key without any prefix (ex: Win, Ctrl)
winrt::hstring Shortcut::ModifierKeyNameWithSide(const ModifierKey& key, const std::wstring& keyName) const
{
if (key == ModifierKey::Left)
{
return winrt::to_hstring(L"L") + winrt::to_hstring(keyName.c_str());
}
else if (key == ModifierKey::Right)
{
return winrt::to_hstring(L"R") + winrt::to_hstring(keyName.c_str());
}
else if (key == ModifierKey::Both)
{
return winrt::to_hstring(keyName.c_str());
}
return winrt::hstring();
}
// Function to return the virtual key code from the name of the key
DWORD Shortcut::DecodeKey(const std::wstring& keyName)
{
if (keyName == L"LWin")
{
return VK_LWIN;
}
else if (keyName == L"RWin")
{
return VK_RWIN;
}
else if (keyName == L"LCtrl")
{
return VK_LCONTROL;
}
else if (keyName == L"RCtrl")
{
return VK_RCONTROL;
}
else if (keyName == L"Ctrl")
{
return VK_CONTROL;
}
else if (keyName == L"LAlt")
{
return VK_LMENU;
}
else if (keyName == L"RAlt")
{
return VK_RMENU;
}
else if (keyName == L"Alt")
{
return VK_MENU;
}
else if (keyName == L"LShift")
{
return VK_LSHIFT;
}
else if (keyName == L"RShift")
{
return VK_RSHIFT;
}
else if (keyName == L"Shift")
{
return VK_SHIFT;
}
else
{
return std::stoi(keyName);
}
}
// Function to create a shortcut object from its string representation
Shortcut Shortcut::CreateShortcut(const std::vector<winrt::hstring>& keys)
{
Shortcut newShortcut;
for (int i = 0; i < keys.size(); i++)
{
if (keys[i] == L"Win")
{
newShortcut.SetKey(NULL, true);
}
else
{
DWORD keyCode = DecodeKey(keys[i].c_str());
newShortcut.SetKey(keyCode);
}
}
return newShortcut;
}
Shortcut Shortcut::CreateShortcut(const winrt::hstring& input)
{
std::vector<std::wstring> shortcut = splitwstring(input.c_str(), L' ');
return CreateShortcut(std::vector<winrt::hstring>(shortcut.begin(), shortcut.end()));
}

View File

@@ -1,5 +1,6 @@
#pragma once
#include "Helpers.h"
#include "LayoutMap.h"
#include <interface/lowlevel_keyboard_event_data.h>
// Enum type to store different states of the win key
@@ -20,10 +21,8 @@ private:
ModifierKey shiftKey;
DWORD actionKey;
// Function to return the name of the key with L or R prefix depending on the first argument. Second argument should be the name of the key without any prefix (ex: Win, Ctrl)
winrt::hstring ModifierKeyNameWithSide(const ModifierKey& key, const std::wstring& keyName) const;
public:
// By default create an empty shortcut
Shortcut() :
winKey(ModifierKey::Disabled), ctrlKey(ModifierKey::Disabled), altKey(ModifierKey::Disabled), shiftKey(ModifierKey::Disabled), actionKey(NULL)
@@ -138,10 +137,10 @@ public:
void ResetKey(const DWORD& input, const bool& isWinBoth = false);
// Function to return the string representation of the shortcut
winrt::hstring ToHstring() const;
winrt::hstring ToHstring(LayoutMap& keyboardMap);
// Function to return a vector of hstring for each key, in the same order as ToHstring()
std::vector<winrt::hstring> GetKeyVector() const;
std::vector<winrt::hstring> GetKeyVector(LayoutMap& keyboardMap);
// Function to check if all the modifiers in the shortcut have been pressed down
bool CheckModifiersKeyboardState() const;
@@ -151,13 +150,4 @@ public:
// Function to get the number of modifiers that are common between the current shortcut and the shortcut in the argument
int GetCommonModifiersCount(const Shortcut& input) const;
// Function to return the virtual key code from the name of the key
static DWORD DecodeKey(const std::wstring& keyName);
// Function to create a shortcut object from its string vector representation
static Shortcut CreateShortcut(const std::vector<winrt::hstring>& keys);
// Function to create a shortcut object from its string representation
static Shortcut CreateShortcut(const winrt::hstring& input);
};