Skip to content

Commit

Permalink
Add unicode naming for keys (dev/keyboardManager) (#1978)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
arjunbalgovind authored and traies committed Apr 13, 2020
1 parent 6fbed4a commit e0ddaa7
Show file tree
Hide file tree
Showing 16 changed files with 309 additions and 233 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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>
Expand Down
43 changes: 14 additions & 29 deletions src/modules/keyboardmanager/common/KeyboardManagerState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();

Expand All @@ -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.
Expand All @@ -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.
Expand Down
10 changes: 9 additions & 1 deletion src/modules/keyboardmanager/common/KeyboardManagerState.h
Original file line number Diff line number Diff line change
@@ -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>
Expand Down Expand Up @@ -30,10 +31,14 @@ class KeyboardManagerState
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;
Expand Down Expand Up @@ -67,6 +72,9 @@ class KeyboardManagerState
std::map<std::wstring, std::map<Shortcut, RemapShortcut>> appSpecificShortcutReMap;
std::mutex appSpecificShortcutReMap_mutex;

// Stores the keyboard layout
LayoutMap keyboardMap;

// Constructor
KeyboardManagerState();

Expand Down
14 changes: 14 additions & 0 deletions src/modules/keyboardmanager/common/LayoutMap.cpp
Original file line number Diff line number Diff line change
@@ -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;
}
152 changes: 152 additions & 0 deletions src/modules/keyboardmanager/common/LayoutMap.h
Original file line number Diff line number Diff line change
@@ -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);
};

0 comments on commit e0ddaa7

Please sign in to comment.