mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-07 03:36:44 +02:00
[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:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user