mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-05 10:46:33 +02:00
[Keyboard Manager] Fixed app-specific shortcut causing app to lose focus scenario (#4902)
* Fixed focus issue and added tests * Changed key names * Use constant instead of hardcoded empty string
This commit is contained in:
@@ -114,7 +114,7 @@ namespace KeyboardEventHandlers
|
||||
}
|
||||
|
||||
// Function to a handle a shortcut remap
|
||||
__declspec(dllexport) intptr_t HandleShortcutRemapEvent(InputInterface& ii, LowlevelKeyboardEvent* data, std::map<Shortcut, RemapShortcut>& reMap, std::mutex& map_mutex) noexcept
|
||||
__declspec(dllexport) intptr_t HandleShortcutRemapEvent(InputInterface& ii, LowlevelKeyboardEvent* data, std::map<Shortcut, RemapShortcut>& reMap, std::mutex& map_mutex, KeyboardManagerState& keyboardManagerState, const std::wstring& activatedApp) 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);
|
||||
@@ -260,6 +260,11 @@ namespace KeyboardEventHandlers
|
||||
}
|
||||
|
||||
it.second.isShortcutInvoked = true;
|
||||
// If app specific shortcut is invoked, store the target application
|
||||
if (activatedApp != KeyboardManagerConstants::NoActivatedApp)
|
||||
{
|
||||
keyboardManagerState.SetActivatedApp(activatedApp);
|
||||
}
|
||||
lock.unlock();
|
||||
UINT res = ii.SendVirtualInput((UINT)key_count, keyEventList, sizeof(INPUT));
|
||||
delete[] keyEventList;
|
||||
@@ -359,6 +364,11 @@ namespace KeyboardEventHandlers
|
||||
|
||||
it.second.isShortcutInvoked = false;
|
||||
it.second.winKeyInvoked = ModifierKey::Disabled;
|
||||
// If app specific shortcut has finished invoking, reset the target application
|
||||
if (activatedApp != KeyboardManagerConstants::NoActivatedApp)
|
||||
{
|
||||
keyboardManagerState.SetActivatedApp(KeyboardManagerConstants::NoActivatedApp);
|
||||
}
|
||||
lock.unlock();
|
||||
|
||||
// key count can be 0 if both shortcuts have same modifiers and the action key is not held down. delete will throw an error if keyEventList is empty
|
||||
@@ -559,6 +569,11 @@ namespace KeyboardEventHandlers
|
||||
|
||||
it.second.isShortcutInvoked = false;
|
||||
it.second.winKeyInvoked = ModifierKey::Disabled;
|
||||
// If app specific shortcut has finished invoking, reset the target application
|
||||
if (activatedApp != KeyboardManagerConstants::NoActivatedApp)
|
||||
{
|
||||
keyboardManagerState.SetActivatedApp(KeyboardManagerConstants::NoActivatedApp);
|
||||
}
|
||||
lock.unlock();
|
||||
UINT res = ii.SendVirtualInput((UINT)key_count, keyEventList, sizeof(INPUT));
|
||||
delete[] keyEventList;
|
||||
@@ -571,6 +586,11 @@ namespace KeyboardEventHandlers
|
||||
// If it was in isShortcutInvoked state and none of the above cases occur, then reset the flags
|
||||
it.second.isShortcutInvoked = false;
|
||||
it.second.winKeyInvoked = ModifierKey::Disabled;
|
||||
// If app specific shortcut has finished invoking, reset the target application
|
||||
if (activatedApp != KeyboardManagerConstants::NoActivatedApp)
|
||||
{
|
||||
keyboardManagerState.SetActivatedApp(KeyboardManagerConstants::NoActivatedApp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -583,7 +603,7 @@ 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)
|
||||
{
|
||||
bool result = HandleShortcutRemapEvent(ii, data, keyboardManagerState.osLevelShortcutReMap, keyboardManagerState.osLevelShortcutReMap_mutex);
|
||||
bool result = HandleShortcutRemapEvent(ii, data, keyboardManagerState.osLevelShortcutReMap, keyboardManagerState.osLevelShortcutReMap_mutex, keyboardManagerState);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -614,22 +634,34 @@ namespace KeyboardEventHandlers
|
||||
std::transform(process_name.begin(), process_name.end(), process_name.begin(), towlower);
|
||||
|
||||
std::unique_lock<std::mutex> lock(keyboardManagerState.appSpecificShortcutReMap_mutex);
|
||||
std::wstring query_string = process_name;
|
||||
auto it = keyboardManagerState.appSpecificShortcutReMap.find(query_string);
|
||||
std::wstring query_string;
|
||||
|
||||
// If no entry is found, search for the process name without it's file extension
|
||||
if (it == keyboardManagerState.appSpecificShortcutReMap.end())
|
||||
std::map<std::wstring, std::map<Shortcut, RemapShortcut>>::iterator it;
|
||||
// Check if an app-specific shortcut is already activated
|
||||
if (keyboardManagerState.GetActivatedApp() == KeyboardManagerConstants::NoActivatedApp)
|
||||
{
|
||||
// Find index of the file extension
|
||||
size_t extensionIndex = process_name.find_last_of(L".");
|
||||
query_string = process_name.substr(0, extensionIndex);
|
||||
query_string = process_name;
|
||||
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);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
query_string = keyboardManagerState.GetActivatedApp();
|
||||
it = keyboardManagerState.appSpecificShortcutReMap.find(query_string);
|
||||
}
|
||||
|
||||
if (it != keyboardManagerState.appSpecificShortcutReMap.end())
|
||||
{
|
||||
lock.unlock();
|
||||
bool result = HandleShortcutRemapEvent(ii, data, keyboardManagerState.appSpecificShortcutReMap[query_string], keyboardManagerState.appSpecificShortcutReMap_mutex);
|
||||
bool result = HandleShortcutRemapEvent(ii, data, keyboardManagerState.appSpecificShortcutReMap[query_string], keyboardManagerState.appSpecificShortcutReMap_mutex, keyboardManagerState, query_string);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace KeyboardEventHandlers
|
||||
__declspec(dllexport) intptr_t HandleSingleKeyToggleToModEvent(InputInterface& ii, LowlevelKeyboardEvent* data, KeyboardManagerState& keyboardManagerState) noexcept;
|
||||
|
||||
// Function to a handle a shortcut remap
|
||||
__declspec(dllexport) intptr_t HandleShortcutRemapEvent(InputInterface& ii, LowlevelKeyboardEvent* data, std::map<Shortcut, RemapShortcut>& reMap, std::mutex& map_mutex) noexcept;
|
||||
__declspec(dllexport) intptr_t HandleShortcutRemapEvent(InputInterface& ii, LowlevelKeyboardEvent* data, std::map<Shortcut, RemapShortcut>& reMap, std::mutex& map_mutex, KeyboardManagerState& keyboardManagerState, const std::wstring& activatedApp = KeyboardManagerConstants::NoActivatedApp) noexcept;
|
||||
|
||||
// Function to a handle an os-level shortcut remap
|
||||
__declspec(dllexport) intptr_t HandleOSLevelShortcutRemapEvent(InputInterface& ii, LowlevelKeyboardEvent* data, KeyboardManagerState& keyboardManagerState) noexcept;
|
||||
|
||||
Reference in New Issue
Block a user