[Keyboard Manager] Enable App-specific shortcuts in the KBM backend (#4628)

* Enable app specific shortcut remapping

* Fixed lowercase function call

* Add test file

* Moved GetForegroundProcess to II and added tests

* Fixed runtime error while testing due to heap allocation across dll boundary

* Renamed function

* Remove unused code

* Changed process checking step to include substrings

* Changed back to exact match included match without file extension
This commit is contained in:
Arjun Balgovind
2020-07-06 16:45:53 -07:00
committed by GitHub
parent 70405045d7
commit 1533c9315f
15 changed files with 241 additions and 52 deletions

View File

@@ -1,5 +1,6 @@
#include "pch.h"
#include "Input.h"
#include <keyboardmanager/common/Helpers.h>
// Function to simulate input
UINT Input::SendVirtualInput(UINT cInputs, LPINPUT pInputs, int cbSize)
@@ -12,3 +13,9 @@ bool Input::GetVirtualKeyState(int key)
{
return (GetAsyncKeyState(key) & 0x8000);
}
// Function to get the foreground process name
void Input::GetForegroundProcess(_Out_ std::wstring& foregroundProcess)
{
foregroundProcess = KeyboardManagerHelper::GetCurrentApplication(false);
}

View File

@@ -11,4 +11,7 @@ public:
// Function to get the state of a particular key
bool GetVirtualKeyState(int key);
// Function to get the foreground process name
void GetForegroundProcess(_Out_ std::wstring& foregroundProcess);
};

View File

@@ -596,18 +596,40 @@ namespace KeyboardEventHandlers
// Check if the key event was generated by KeyboardManager to avoid remapping events generated by us.
if (data->lParam->dwExtraInfo != KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG)
{
std::wstring process_name = KeyboardManagerHelper::GetCurrentApplication(false);
std::wstring process_name;
// Allocate MAX_PATH amount of memory
process_name.resize(MAX_PATH);
ii.GetForegroundProcess(process_name);
// Remove elements after null character
process_name.erase(std::find(process_name.begin(), process_name.end(), L'\0'), process_name.end());
if (process_name.empty())
{
return 0;
}
// Convert process name to lower case
std::transform(process_name.begin(), process_name.end(), process_name.begin(), towlower);
std::unique_lock<std::mutex> lock(keyboardManagerState.appSpecificShortcutReMap_mutex);
auto it = keyboardManagerState.appSpecificShortcutReMap.find(process_name);
std::wstring query_string = process_name;
auto it = keyboardManagerState.appSpecificShortcutReMap.find(query_string);
// If no entry is found, search for the process name without it's file extension
if (it == keyboardManagerState.appSpecificShortcutReMap.end())
{
// Find index of the file extension
size_t extensionIndex = process_name.find_last_of(L".");
query_string = process_name.substr(0, extensionIndex);
it = keyboardManagerState.appSpecificShortcutReMap.find(query_string);
}
if (it != keyboardManagerState.appSpecificShortcutReMap.end())
{
lock.unlock();
bool result = HandleShortcutRemapEvent(ii, data, keyboardManagerState.appSpecificShortcutReMap[process_name], keyboardManagerState.appSpecificShortcutReMap_mutex);
bool result = HandleShortcutRemapEvent(ii, data, keyboardManagerState.appSpecificShortcutReMap[query_string], keyboardManagerState.appSpecificShortcutReMap_mutex);
return result;
}
}

View File

@@ -140,17 +140,6 @@ public:
}
}
// This function is used to add the hardcoded mappings
void init_map()
{
////App-specific shortcut remappings
//keyboardManagerState.appSpecificShortcutReMap[L"msedge.exe"][std::vector<DWORD>({ VK_LCONTROL, 0x43 })] = std::make_pair(std::vector<WORD>({ VK_LCONTROL, 0x56 }), false); // Ctrl+C to Ctrl+V
//keyboardManagerState.appSpecificShortcutReMap[L"msedge.exe"][std::vector<DWORD>({ VK_LMENU, 0x44 })] = std::make_pair(std::vector<WORD>({ VK_LCONTROL, 0x46 }), false); // Alt+D to Ctrl+F
//keyboardManagerState.appSpecificShortcutReMap[L"OUTLOOK.EXE"][std::vector<DWORD>({ VK_LCONTROL, 0x46 })] = std::make_pair(std::vector<WORD>({ VK_LCONTROL, 0x45 }), false); // Ctrl+F to Ctrl+E
//keyboardManagerState.appSpecificShortcutReMap[L"MicrosoftEdge.exe"][std::vector<DWORD>({ VK_LCONTROL, 0x58 })] = std::make_pair(std::vector<WORD>({ VK_LCONTROL, 0x56 }), false); // Ctrl+X to Ctrl+V
//keyboardManagerState.appSpecificShortcutReMap[L"Calculator.exe"][std::vector<DWORD>({ VK_LCONTROL, 0x47 })] = std::make_pair(std::vector<WORD>({ VK_LSHIFT, 0x32 }), false); // Ctrl+G to Shift+2
}
// Destroy the powertoy and free memory
virtual void destroy() override
{
@@ -372,27 +361,17 @@ public:
//// Remap a key to behave like a modifier instead of a toggle
//intptr_t SingleKeyToggleToModResult = KeyboardEventHandlers::HandleSingleKeyToggleToModEvent(inputHandler, data, keyboardManagerState);
//// Handle an app-specific shortcut remapping
//intptr_t AppSpecificShortcutRemapResult = KeyboardEventHandlers::HandleAppSpecificShortcutRemapEvent(inputHandler, data, keyboardManagerState);
// Handle an app-specific shortcut remapping
intptr_t AppSpecificShortcutRemapResult = KeyboardEventHandlers::HandleAppSpecificShortcutRemapEvent(inputHandler, data, keyboardManagerState);
//// If an app-specific shortcut is remapped then the os-level shortcut remapping should be suppressed.
//if (AppSpecificShortcutRemapResult == 1)
//{
// return 1;
//}
// Handle an os-level shortcut remapping
intptr_t OSLevelShortcutRemapResult = KeyboardEventHandlers::HandleOSLevelShortcutRemapEvent(inputHandler, data, keyboardManagerState);
// If any of the supported types of remappings took place, then suppress the key event
if ((SingleKeyRemapResult + OSLevelShortcutRemapResult) > 0)
// If an app-specific shortcut is remapped then the os-level shortcut remapping should be suppressed.
if (AppSpecificShortcutRemapResult == 1)
{
return 1;
}
else
{
return 0;
}
// Handle an os-level shortcut remapping
return KeyboardEventHandlers::HandleOSLevelShortcutRemapEvent(inputHandler, data, keyboardManagerState);
}
};