Added unique lock mutexes to KeyboardManagerState (dev/keyboardManager) (#1789)

* Added unique lock mutexes for thread safety

* Fixed a bug in detect key logic

* Added early unlock statements to fix issue with shortcut guide

* Added comments for unlocks before SendInput and changed some unique_locks to lock_guards
This commit is contained in:
Arjun Balgovind
2020-04-03 10:57:46 -07:00
committed by Udit Singh
parent 467cf919be
commit ac26818005
6 changed files with 134 additions and 25 deletions

View File

@@ -313,6 +313,8 @@ public:
// Check if the key event was generated by KeyboardManager to avoid remapping events generated by us.
if (!(data->lParam->dwExtraInfo & KEYBOARDMANAGER_INJECTED_FLAG))
{
// The mutex should be unlocked before SendInput is called to avoid re-entry into the same mutex. More details can be found at https://github.com/microsoft/PowerToys/pull/1789#issuecomment-607555837
std::unique_lock<std::mutex> lock(keyboardManagerState.singleKeyReMap_mutex);
auto it = keyboardManagerState.singleKeyReMap.find(data->lParam->vkCode);
if (it != keyboardManagerState.singleKeyReMap.end())
{
@@ -334,6 +336,7 @@ public:
keyEventList[0].ki.dwFlags = KEYEVENTF_KEYUP;
}
lock.unlock();
UINT res = SendInput(key_count, keyEventList, sizeof(INPUT));
delete[] keyEventList;
return 1;
@@ -349,6 +352,8 @@ public:
// Check if the key event was generated by KeyboardManager to avoid remapping events generated by us.
if (!(data->lParam->dwExtraInfo & KEYBOARDMANAGER_INJECTED_FLAG))
{
// The mutex should be unlocked before SendInput is called to avoid re-entry into the same mutex. More details can be found at https://github.com/microsoft/PowerToys/pull/1789#issuecomment-607555837
std::unique_lock<std::mutex> lock(keyboardManagerState.singleKeyToggleToMod_mutex);
auto it = keyboardManagerState.singleKeyToggleToMod.find(data->lParam->vkCode);
if (it != keyboardManagerState.singleKeyToggleToMod.end())
{
@@ -361,6 +366,7 @@ public:
}
else
{
lock.unlock();
return 1;
}
}
@@ -376,14 +382,18 @@ public:
keyEventList[1].ki.dwFlags = KEYEVENTF_KEYUP;
keyEventList[1].ki.dwExtraInfo = KEYBOARDMANAGER_SINGLEKEY_FLAG;
lock.unlock();
UINT res = SendInput(key_count, keyEventList, sizeof(INPUT));
delete[] keyEventList;
// Reset the long press flag when the key has been lifted.
if (data->wParam == WM_KEYUP || data->wParam == WM_SYSKEYUP)
{
lock.lock();
keyboardManagerState.singleKeyToggleToMod[data->lParam->vkCode] = false;
lock.unlock();
}
return 1;
}
}
@@ -495,8 +505,10 @@ public:
}
// Function to a handle a shortcut remap
intptr_t HandleShortcutRemapEvent(LowlevelKeyboardEvent* data, std::map<std::vector<DWORD>, std::pair<std::vector<WORD>, bool>>& reMap) noexcept
intptr_t HandleShortcutRemapEvent(LowlevelKeyboardEvent* data, std::map<std::vector<DWORD>, std::pair<std::vector<WORD>, bool>>& reMap, std::mutex& map_mutex) noexcept
{
// The mutex should be unlocked before SendInput is called to avoid re-entry into the same mutex. More details can be found at https://github.com/microsoft/PowerToys/pull/1789#issuecomment-607555837
std::unique_lock<std::mutex> lock(map_mutex);
for (auto& it : reMap)
{
const size_t src_size = it.first.size();
@@ -588,6 +600,7 @@ public:
}
it.second.second = true;
lock.unlock();
UINT res = SendInput((UINT)key_count, keyEventList, sizeof(INPUT));
delete[] keyEventList;
return 1;
@@ -657,8 +670,8 @@ public:
}
it.second.second = false;
lock.unlock();
UINT res = SendInput((UINT)key_count, keyEventList, sizeof(INPUT));
delete[] keyEventList;
return 1;
}
@@ -678,6 +691,7 @@ public:
keyEventList[0].ki.dwExtraInfo = KEYBOARDMANAGER_SHORTCUT_FLAG;
it.second.second = true;
lock.unlock();
UINT res = SendInput((UINT)key_count, keyEventList, sizeof(INPUT));
delete[] keyEventList;
return 1;
@@ -758,6 +772,7 @@ public:
}
it.second.second = false;
lock.unlock();
UINT res = SendInput((UINT)key_count, keyEventList, sizeof(INPUT));
delete[] keyEventList;
return 1;
@@ -775,7 +790,8 @@ public:
// Check if the key event was generated by KeyboardManager to avoid remapping events generated by us.
if (data->lParam->dwExtraInfo != KEYBOARDMANAGER_SHORTCUT_FLAG)
{
return HandleShortcutRemapEvent(data, keyboardManagerState.osLevelShortcutReMap);
bool result = HandleShortcutRemapEvent(data, keyboardManagerState.osLevelShortcutReMap, keyboardManagerState.osLevelShortcutReMap_mutex);
return result;
}
return 0;
@@ -838,11 +854,13 @@ public:
{
return 0;
}
std::unique_lock<std::mutex> lock(keyboardManagerState.appSpecificShortcutReMap_mutex);
auto it = keyboardManagerState.appSpecificShortcutReMap.find(process_name);
if (it != keyboardManagerState.appSpecificShortcutReMap.end())
{
return HandleShortcutRemapEvent(data, keyboardManagerState.appSpecificShortcutReMap[process_name]);
lock.unlock();
bool result = HandleShortcutRemapEvent(data, keyboardManagerState.appSpecificShortcutReMap[process_name], keyboardManagerState.appSpecificShortcutReMap_mutex);
return result;
}
}