|
|
|
|
@@ -3,7 +3,6 @@
|
|
|
|
|
|
|
|
|
|
#include <common/interop/shared_constants.h>
|
|
|
|
|
|
|
|
|
|
#include <keyboardmanager/common/KeyboardManagerState.h>
|
|
|
|
|
#include <keyboardmanager/common/InputInterface.h>
|
|
|
|
|
#include <keyboardmanager/common/Helpers.h>
|
|
|
|
|
#include <keyboardmanager/KeyboardManagerEngineLibrary/trace.h>
|
|
|
|
|
@@ -11,12 +10,12 @@
|
|
|
|
|
namespace KeyboardEventHandlers
|
|
|
|
|
{
|
|
|
|
|
// Function to a handle a single key remap
|
|
|
|
|
intptr_t HandleSingleKeyRemapEvent(KeyboardManagerInput::InputInterface& ii, LowlevelKeyboardEvent* data, KeyboardManagerState& keyboardManagerState) noexcept
|
|
|
|
|
intptr_t HandleSingleKeyRemapEvent(KeyboardManagerInput::InputInterface& ii, LowlevelKeyboardEvent* data, State& state) noexcept
|
|
|
|
|
{
|
|
|
|
|
// Check if the key event was generated by KeyboardManager to avoid remapping events generated by us.
|
|
|
|
|
if (!(data->lParam->dwExtraInfo & CommonSharedConstants::KEYBOARDMANAGER_INJECTED_FLAG))
|
|
|
|
|
{
|
|
|
|
|
const auto remapping = keyboardManagerState.GetSingleKeyRemap(data->lParam->vkCode);
|
|
|
|
|
const auto remapping = state.GetSingleKeyRemap(data->lParam->vkCode);
|
|
|
|
|
if (remapping)
|
|
|
|
|
{
|
|
|
|
|
auto it = remapping.value();
|
|
|
|
|
@@ -50,11 +49,11 @@ namespace KeyboardEventHandlers
|
|
|
|
|
DWORD target;
|
|
|
|
|
if (remapToKey)
|
|
|
|
|
{
|
|
|
|
|
target = KeyboardManagerHelper::FilterArtificialKeys(std::get<DWORD>(it->second));
|
|
|
|
|
target = Helpers::FilterArtificialKeys(std::get<DWORD>(it->second));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
target = KeyboardManagerHelper::FilterArtificialKeys(std::get<Shortcut>(it->second).GetActionKey());
|
|
|
|
|
target = Helpers::FilterArtificialKeys(std::get<Shortcut>(it->second).GetActionKey());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If Ctrl/Alt/Shift is being remapped to Caps Lock, then reset the modifier key state to fix issues in certain IME keyboards where the IME shortcut gets invoked since it detects that the modifier and Caps Lock is pressed even though it is suppressed by the hook - More information at the GitHub issue https://github.com/microsoft/PowerToys/issues/3397
|
|
|
|
|
@@ -67,11 +66,11 @@ namespace KeyboardEventHandlers
|
|
|
|
|
{
|
|
|
|
|
if (data->wParam == WM_KEYUP || data->wParam == WM_SYSKEYUP)
|
|
|
|
|
{
|
|
|
|
|
KeyboardManagerHelper::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, (WORD)target, KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG);
|
|
|
|
|
Helpers::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, (WORD)target, KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
KeyboardManagerHelper::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, (WORD)target, 0, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG);
|
|
|
|
|
Helpers::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, (WORD)target, 0, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
@@ -80,16 +79,16 @@ namespace KeyboardEventHandlers
|
|
|
|
|
Shortcut targetShortcut = std::get<Shortcut>(it->second);
|
|
|
|
|
if (data->wParam == WM_KEYUP || data->wParam == WM_SYSKEYUP)
|
|
|
|
|
{
|
|
|
|
|
KeyboardManagerHelper::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)targetShortcut.GetActionKey(), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG);
|
|
|
|
|
Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)targetShortcut.GetActionKey(), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG);
|
|
|
|
|
i++;
|
|
|
|
|
KeyboardManagerHelper::SetModifierKeyEvents(targetShortcut, ModifierKey::Disabled, keyEventList, i, false, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG);
|
|
|
|
|
Helpers::SetModifierKeyEvents(targetShortcut, ModifierKey::Disabled, keyEventList, i, false, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG);
|
|
|
|
|
// Dummy key is not required here since SetModifierKeyEvents will only add key-up events for the modifiers here, and the action key key-up is already sent before it
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Dummy key is not required here since SetModifierKeyEvents will only add key-down events for the modifiers here, and the action key key-down is already sent after it
|
|
|
|
|
KeyboardManagerHelper::SetModifierKeyEvents(targetShortcut, ModifierKey::Disabled, keyEventList, i, true, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG);
|
|
|
|
|
KeyboardManagerHelper::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)targetShortcut.GetActionKey(), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG);
|
|
|
|
|
Helpers::SetModifierKeyEvents(targetShortcut, ModifierKey::Disabled, keyEventList, i, true, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG);
|
|
|
|
|
Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)targetShortcut.GetActionKey(), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG);
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -127,22 +126,22 @@ namespace KeyboardEventHandlers
|
|
|
|
|
/* This feature has not been enabled (code from proof of concept stage)
|
|
|
|
|
*
|
|
|
|
|
// Function to a change a key's behavior from toggle to modifier
|
|
|
|
|
__declspec(dllexport) intptr_t HandleSingleKeyToggleToModEvent(InputInterface& ii, LowlevelKeyboardEvent* data, KeyboardManagerState& keyboardManagerState) noexcept
|
|
|
|
|
__declspec(dllexport) intptr_t HandleSingleKeyToggleToModEvent(InputInterface& ii, LowlevelKeyboardEvent* data, State& State) noexcept
|
|
|
|
|
{
|
|
|
|
|
// Check if the key event was generated by KeyboardManager to avoid remapping events generated by us.
|
|
|
|
|
if (!(data->lParam->dwExtraInfo & CommonSharedConstants::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())
|
|
|
|
|
std::unique_lock<std::mutex> lock(State.singleKeyToggleToMod_mutex);
|
|
|
|
|
auto it = State.singleKeyToggleToMod.find(data->lParam->vkCode);
|
|
|
|
|
if (it != State.singleKeyToggleToMod.end())
|
|
|
|
|
{
|
|
|
|
|
// To avoid long presses (which leads to continuous keydown messages) from toggling the key on and off
|
|
|
|
|
if (data->wParam == WM_KEYDOWN || data->wParam == WM_SYSKEYDOWN)
|
|
|
|
|
{
|
|
|
|
|
if (it->second == false)
|
|
|
|
|
{
|
|
|
|
|
keyboardManagerState.singleKeyToggleToMod[data->lParam->vkCode] = true;
|
|
|
|
|
State.singleKeyToggleToMod[data->lParam->vkCode] = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
@@ -153,8 +152,8 @@ namespace KeyboardEventHandlers
|
|
|
|
|
int key_count = 2;
|
|
|
|
|
LPINPUT keyEventList = new INPUT[size_t(key_count)]();
|
|
|
|
|
memset(keyEventList, 0, sizeof(keyEventList));
|
|
|
|
|
KeyboardManagerHelper::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, (WORD)data->lParam->vkCode, 0, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG);
|
|
|
|
|
KeyboardManagerHelper::SetKeyEvent(keyEventList, 1, INPUT_KEYBOARD, (WORD)data->lParam->vkCode, KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG);
|
|
|
|
|
Helpers::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, (WORD)data->lParam->vkCode, 0, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG);
|
|
|
|
|
Helpers::SetKeyEvent(keyEventList, 1, INPUT_KEYBOARD, (WORD)data->lParam->vkCode, KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG);
|
|
|
|
|
|
|
|
|
|
lock.unlock();
|
|
|
|
|
UINT res = ii.SendVirtualInput(key_count, keyEventList, sizeof(INPUT));
|
|
|
|
|
@@ -164,7 +163,7 @@ namespace KeyboardEventHandlers
|
|
|
|
|
if (data->wParam == WM_KEYUP || data->wParam == WM_SYSKEYUP)
|
|
|
|
|
{
|
|
|
|
|
lock.lock();
|
|
|
|
|
keyboardManagerState.singleKeyToggleToMod[data->lParam->vkCode] = false;
|
|
|
|
|
State.singleKeyToggleToMod[data->lParam->vkCode] = false;
|
|
|
|
|
lock.unlock();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -177,16 +176,16 @@ namespace KeyboardEventHandlers
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// Function to a handle a shortcut remap
|
|
|
|
|
intptr_t HandleShortcutRemapEvent(KeyboardManagerInput::InputInterface& ii, LowlevelKeyboardEvent* data, KeyboardManagerState& keyboardManagerState, const std::optional<std::wstring>& activatedApp) noexcept
|
|
|
|
|
intptr_t HandleShortcutRemapEvent(KeyboardManagerInput::InputInterface& ii, LowlevelKeyboardEvent* data, State& state, const std::optional<std::wstring>& activatedApp) noexcept
|
|
|
|
|
{
|
|
|
|
|
// Check if any shortcut is currently in the invoked state
|
|
|
|
|
bool isShortcutInvoked = keyboardManagerState.CheckShortcutRemapInvoked(activatedApp);
|
|
|
|
|
bool isShortcutInvoked = state.CheckShortcutRemapInvoked(activatedApp);
|
|
|
|
|
|
|
|
|
|
// Get shortcut table for given activatedApp
|
|
|
|
|
ShortcutRemapTable& reMap = keyboardManagerState.GetShortcutRemapTable(activatedApp);
|
|
|
|
|
ShortcutRemapTable& reMap = state.GetShortcutRemapTable(activatedApp);
|
|
|
|
|
|
|
|
|
|
// Iterate through the shortcut remaps and apply whichever has been pressed
|
|
|
|
|
for (auto& itShortcut : keyboardManagerState.GetSortedShortcutRemapVector(activatedApp))
|
|
|
|
|
for (auto& itShortcut : state.GetSortedShortcutRemapVector(activatedApp))
|
|
|
|
|
{
|
|
|
|
|
const auto it = reMap.find(itShortcut);
|
|
|
|
|
|
|
|
|
|
@@ -239,8 +238,8 @@ namespace KeyboardEventHandlers
|
|
|
|
|
keyEventList = new INPUT[key_count]();
|
|
|
|
|
memset(keyEventList, 0, sizeof(keyEventList));
|
|
|
|
|
int i = 0;
|
|
|
|
|
KeyboardManagerHelper::SetModifierKeyEvents(std::get<Shortcut>(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, i, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first);
|
|
|
|
|
KeyboardManagerHelper::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)std::get<Shortcut>(it->second.targetShortcut).GetActionKey(), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
Helpers::SetModifierKeyEvents(std::get<Shortcut>(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, i, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first);
|
|
|
|
|
Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)std::get<Shortcut>(it->second.targetShortcut).GetActionKey(), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
@@ -252,14 +251,14 @@ namespace KeyboardEventHandlers
|
|
|
|
|
|
|
|
|
|
// Send a dummy key event to prevent modifier press+release from being triggered. Example: Win+A->Ctrl+V, press Win+A, since Win will be released here we need to send a dummy event before it
|
|
|
|
|
int i = 0;
|
|
|
|
|
KeyboardManagerHelper::SetDummyKeyEvent(keyEventList, i, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
Helpers::SetDummyKeyEvent(keyEventList, i, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
|
|
|
|
|
// Release original shortcut state (release in reverse order of shortcut to be accurate)
|
|
|
|
|
KeyboardManagerHelper::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, i, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get<Shortcut>(it->second.targetShortcut));
|
|
|
|
|
Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, i, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get<Shortcut>(it->second.targetShortcut));
|
|
|
|
|
|
|
|
|
|
// Set new shortcut key down state
|
|
|
|
|
KeyboardManagerHelper::SetModifierKeyEvents(std::get<Shortcut>(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, i, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first);
|
|
|
|
|
KeyboardManagerHelper::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)std::get<Shortcut>(it->second.targetShortcut).GetActionKey(), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
Helpers::SetModifierKeyEvents(std::get<Shortcut>(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, i, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first);
|
|
|
|
|
Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)std::get<Shortcut>(it->second.targetShortcut).GetActionKey(), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -291,22 +290,22 @@ namespace KeyboardEventHandlers
|
|
|
|
|
|
|
|
|
|
// Send a dummy key event to prevent modifier press+release from being triggered. Example: Win+A->V, press Win+A, since Win will be released here we need to send a dummy event before it
|
|
|
|
|
int i = 0;
|
|
|
|
|
KeyboardManagerHelper::SetDummyKeyEvent(keyEventList, i, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
Helpers::SetDummyKeyEvent(keyEventList, i, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
|
|
|
|
|
// Release original shortcut state (release in reverse order of shortcut to be accurate)
|
|
|
|
|
KeyboardManagerHelper::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, i, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, i, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
|
|
|
|
|
// Set target key down state
|
|
|
|
|
if (std::get<DWORD>(it->second.targetShortcut) != CommonSharedConstants::VK_DISABLED)
|
|
|
|
|
{
|
|
|
|
|
KeyboardManagerHelper::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)KeyboardManagerHelper::FilterArtificialKeys(std::get<DWORD>(it->second.targetShortcut)), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)Helpers::FilterArtificialKeys(std::get<DWORD>(it->second.targetShortcut)), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Modifier state reset might be required for this key depending on the shortcut's action and target modifier - ex: Win+Caps -> Ctrl
|
|
|
|
|
if (it->first.GetCtrlKey() == NULL && it->first.GetAltKey() == NULL && it->first.GetShiftKey() == NULL)
|
|
|
|
|
{
|
|
|
|
|
ResetIfModifierKeyForLowerLevelKeyHandlers(ii, (WORD)KeyboardManagerHelper::FilterArtificialKeys(std::get<DWORD>(it->second.targetShortcut)), data->lParam->vkCode);
|
|
|
|
|
ResetIfModifierKeyForLowerLevelKeyHandlers(ii, (WORD)Helpers::FilterArtificialKeys(std::get<DWORD>(it->second.targetShortcut)), data->lParam->vkCode);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -314,7 +313,7 @@ namespace KeyboardEventHandlers
|
|
|
|
|
// If app specific shortcut is invoked, store the target application
|
|
|
|
|
if (activatedApp)
|
|
|
|
|
{
|
|
|
|
|
keyboardManagerState.SetActivatedApp(*activatedApp);
|
|
|
|
|
state.SetActivatedApp(*activatedApp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UINT res = ii.SendVirtualInput((UINT)key_count, keyEventList, sizeof(INPUT));
|
|
|
|
|
@@ -375,16 +374,16 @@ namespace KeyboardEventHandlers
|
|
|
|
|
int i = 0;
|
|
|
|
|
if (isActionKeyPressed)
|
|
|
|
|
{
|
|
|
|
|
KeyboardManagerHelper::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)std::get<Shortcut>(it->second.targetShortcut).GetActionKey(), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)std::get<Shortcut>(it->second.targetShortcut).GetActionKey(), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
KeyboardManagerHelper::SetModifierKeyEvents(std::get<Shortcut>(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, i, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first, data->lParam->vkCode);
|
|
|
|
|
Helpers::SetModifierKeyEvents(std::get<Shortcut>(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, i, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first, data->lParam->vkCode);
|
|
|
|
|
|
|
|
|
|
// Set original shortcut key down state except the action key and the released modifier since the original action key may or may not be held down. If it is held down it will generate it's own key message
|
|
|
|
|
KeyboardManagerHelper::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, i, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get<Shortcut>(it->second.targetShortcut), data->lParam->vkCode);
|
|
|
|
|
Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, i, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get<Shortcut>(it->second.targetShortcut), data->lParam->vkCode);
|
|
|
|
|
|
|
|
|
|
// Send a dummy key event to prevent modifier press+release from being triggered. Example: Win+Ctrl+A->Ctrl+V, press Win+Ctrl+A and release A then Ctrl, since Win will be pressed here we need to send a dummy event after it
|
|
|
|
|
KeyboardManagerHelper::SetDummyKeyEvent(keyEventList, i, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
Helpers::SetDummyKeyEvent(keyEventList, i, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
@@ -397,7 +396,7 @@ namespace KeyboardEventHandlers
|
|
|
|
|
{
|
|
|
|
|
key_count--;
|
|
|
|
|
}
|
|
|
|
|
else if (ii.GetVirtualKeyState(KeyboardManagerHelper::FilterArtificialKeys(std::get<DWORD>(it->second.targetShortcut))))
|
|
|
|
|
else if (ii.GetVirtualKeyState(Helpers::FilterArtificialKeys(std::get<DWORD>(it->second.targetShortcut))))
|
|
|
|
|
{
|
|
|
|
|
isTargetKeyPressed = true;
|
|
|
|
|
}
|
|
|
|
|
@@ -414,15 +413,15 @@ namespace KeyboardEventHandlers
|
|
|
|
|
int i = 0;
|
|
|
|
|
if (std::get<DWORD>(it->second.targetShortcut) != CommonSharedConstants::VK_DISABLED && isTargetKeyPressed)
|
|
|
|
|
{
|
|
|
|
|
KeyboardManagerHelper::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)KeyboardManagerHelper::FilterArtificialKeys(std::get<DWORD>(it->second.targetShortcut)), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)Helpers::FilterArtificialKeys(std::get<DWORD>(it->second.targetShortcut)), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set original shortcut key down state except the action key and the released modifier since the original action key may or may not be held down. If it is held down it will generate it's own key message
|
|
|
|
|
KeyboardManagerHelper::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, i, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, Shortcut(), data->lParam->vkCode);
|
|
|
|
|
Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, i, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, Shortcut(), data->lParam->vkCode);
|
|
|
|
|
|
|
|
|
|
// Send a dummy key event to prevent modifier press+release from being triggered. Example: Win+Ctrl+A->V, press Win+Ctrl+A and release A then Ctrl, since Win will be pressed here we need to send a dummy event after it
|
|
|
|
|
KeyboardManagerHelper::SetDummyKeyEvent(keyEventList, i, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
Helpers::SetDummyKeyEvent(keyEventList, i, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Reset the remap state
|
|
|
|
|
@@ -433,7 +432,7 @@ namespace KeyboardEventHandlers
|
|
|
|
|
// If app specific shortcut has finished invoking, reset the target application
|
|
|
|
|
if (activatedApp)
|
|
|
|
|
{
|
|
|
|
|
keyboardManagerState.SetActivatedApp(KeyboardManagerConstants::NoActivatedApp);
|
|
|
|
|
state.SetActivatedApp(KeyboardManagerConstants::NoActivatedApp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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
|
|
|
|
|
@@ -464,11 +463,11 @@ namespace KeyboardEventHandlers
|
|
|
|
|
memset(keyEventList, 0, sizeof(keyEventList));
|
|
|
|
|
if (remapToShortcut)
|
|
|
|
|
{
|
|
|
|
|
KeyboardManagerHelper::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, (WORD)std::get<Shortcut>(it->second.targetShortcut).GetActionKey(), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
Helpers::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, (WORD)std::get<Shortcut>(it->second.targetShortcut).GetActionKey(), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
KeyboardManagerHelper::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, (WORD)KeyboardManagerHelper::FilterArtificialKeys(std::get<DWORD>(it->second.targetShortcut)), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
Helpers::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, (WORD)Helpers::FilterArtificialKeys(std::get<DWORD>(it->second.targetShortcut)), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UINT res = ii.SendVirtualInput((UINT)key_count, keyEventList, sizeof(INPUT));
|
|
|
|
|
@@ -485,7 +484,7 @@ namespace KeyboardEventHandlers
|
|
|
|
|
{
|
|
|
|
|
keyEventList = new INPUT[key_count]();
|
|
|
|
|
memset(keyEventList, 0, sizeof(keyEventList));
|
|
|
|
|
KeyboardManagerHelper::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, (WORD)std::get<Shortcut>(it->second.targetShortcut).GetActionKey(), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
Helpers::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, (WORD)std::get<Shortcut>(it->second.targetShortcut).GetActionKey(), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
}
|
|
|
|
|
else if (std::get<DWORD>(it->second.targetShortcut) == CommonSharedConstants::VK_DISABLED)
|
|
|
|
|
{
|
|
|
|
|
@@ -497,14 +496,14 @@ namespace KeyboardEventHandlers
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Check if the keyboard state is clear apart from the target remap key (by creating a temp Shortcut object with the target key)
|
|
|
|
|
bool isKeyboardStateClear = Shortcut(std::vector<int32_t>({ KeyboardManagerHelper::FilterArtificialKeys(std::get<DWORD>(it->second.targetShortcut)) })).IsKeyboardStateClearExceptShortcut(ii);
|
|
|
|
|
bool isKeyboardStateClear = Shortcut(std::vector<int32_t>({ Helpers::FilterArtificialKeys(std::get<DWORD>(it->second.targetShortcut)) })).IsKeyboardStateClearExceptShortcut(ii);
|
|
|
|
|
|
|
|
|
|
// If the keyboard state is clear, we release the target key but do not reset the remap state
|
|
|
|
|
if (isKeyboardStateClear)
|
|
|
|
|
{
|
|
|
|
|
keyEventList = new INPUT[key_count]();
|
|
|
|
|
memset(keyEventList, 0, sizeof(keyEventList));
|
|
|
|
|
KeyboardManagerHelper::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, (WORD)KeyboardManagerHelper::FilterArtificialKeys(std::get<DWORD>(it->second.targetShortcut)), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
Helpers::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, (WORD)Helpers::FilterArtificialKeys(std::get<DWORD>(it->second.targetShortcut)), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
@@ -519,14 +518,14 @@ namespace KeyboardEventHandlers
|
|
|
|
|
|
|
|
|
|
// Release new key state
|
|
|
|
|
int i = 0;
|
|
|
|
|
KeyboardManagerHelper::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)KeyboardManagerHelper::FilterArtificialKeys(std::get<DWORD>(it->second.targetShortcut)), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)Helpers::FilterArtificialKeys(std::get<DWORD>(it->second.targetShortcut)), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
i++;
|
|
|
|
|
|
|
|
|
|
// Set original shortcut key down state except the action key
|
|
|
|
|
KeyboardManagerHelper::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, i, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, i, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
|
|
|
|
|
// Send a dummy key event to prevent modifier press+release from being triggered. Example: Win+A->V, press Shift+Win+A and release A, since Win will be pressed here we need to send a dummy event after it
|
|
|
|
|
KeyboardManagerHelper::SetDummyKeyEvent(keyEventList, i, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
Helpers::SetDummyKeyEvent(keyEventList, i, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
|
|
|
|
|
// Reset the remap state
|
|
|
|
|
it->second.isShortcutInvoked = false;
|
|
|
|
|
@@ -536,7 +535,7 @@ namespace KeyboardEventHandlers
|
|
|
|
|
// If app specific shortcut has finished invoking, reset the target application
|
|
|
|
|
if (activatedApp != KeyboardManagerConstants::NoActivatedApp)
|
|
|
|
|
{
|
|
|
|
|
keyboardManagerState.SetActivatedApp(KeyboardManagerConstants::NoActivatedApp);
|
|
|
|
|
state.SetActivatedApp(KeyboardManagerConstants::NoActivatedApp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -561,7 +560,7 @@ namespace KeyboardEventHandlers
|
|
|
|
|
{
|
|
|
|
|
// If it is not remapped to Disable
|
|
|
|
|
// Modifier state reset might be required for this key depending on the target key - ex: Ctrl+A -> Caps
|
|
|
|
|
ResetIfModifierKeyForLowerLevelKeyHandlers(ii, data->lParam->vkCode, KeyboardManagerHelper::FilterArtificialKeys(std::get<DWORD>(it->second.targetShortcut)));
|
|
|
|
|
ResetIfModifierKeyForLowerLevelKeyHandlers(ii, data->lParam->vkCode, Helpers::FilterArtificialKeys(std::get<DWORD>(it->second.targetShortcut)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Suppress the modifier as it is already physically pressed
|
|
|
|
|
@@ -601,20 +600,20 @@ namespace KeyboardEventHandlers
|
|
|
|
|
int i = 0;
|
|
|
|
|
if (isActionKeyPressed)
|
|
|
|
|
{
|
|
|
|
|
KeyboardManagerHelper::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)std::get<Shortcut>(it->second.targetShortcut).GetActionKey(), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)std::get<Shortcut>(it->second.targetShortcut).GetActionKey(), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
KeyboardManagerHelper::SetModifierKeyEvents(std::get<Shortcut>(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, i, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first);
|
|
|
|
|
Helpers::SetModifierKeyEvents(std::get<Shortcut>(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, i, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first);
|
|
|
|
|
|
|
|
|
|
// key down for original shortcut action key with shortcut flag so that we don't invoke the same shortcut remap again
|
|
|
|
|
if (isActionKeyPressed)
|
|
|
|
|
{
|
|
|
|
|
KeyboardManagerHelper::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it->first.GetActionKey(), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it->first.GetActionKey(), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Send current key pressed without shortcut flag so that it can be reprocessed in case the physical keys pressed are a different remapped shortcut
|
|
|
|
|
KeyboardManagerHelper::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)data->lParam->vkCode, 0, 0);
|
|
|
|
|
Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)data->lParam->vkCode, 0, 0);
|
|
|
|
|
i++;
|
|
|
|
|
|
|
|
|
|
// Do not send a dummy key as we want the current key press to behave as normal i.e. it can do press+release functionality if required. Required to allow a shortcut to Win key remap invoked directly after shortcut to shortcut is released to open start menu
|
|
|
|
|
@@ -639,23 +638,23 @@ namespace KeyboardEventHandlers
|
|
|
|
|
int i = 0;
|
|
|
|
|
if (isActionKeyPressed)
|
|
|
|
|
{
|
|
|
|
|
KeyboardManagerHelper::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)std::get<Shortcut>(it->second.targetShortcut).GetActionKey(), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)std::get<Shortcut>(it->second.targetShortcut).GetActionKey(), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
KeyboardManagerHelper::SetModifierKeyEvents(std::get<Shortcut>(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, i, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first);
|
|
|
|
|
Helpers::SetModifierKeyEvents(std::get<Shortcut>(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, i, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first);
|
|
|
|
|
|
|
|
|
|
// Set old shortcut key down state
|
|
|
|
|
KeyboardManagerHelper::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, i, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get<Shortcut>(it->second.targetShortcut));
|
|
|
|
|
Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, i, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get<Shortcut>(it->second.targetShortcut));
|
|
|
|
|
|
|
|
|
|
// key down for original shortcut action key with shortcut flag so that we don't invoke the same shortcut remap again
|
|
|
|
|
if (isActionKeyPressed)
|
|
|
|
|
{
|
|
|
|
|
KeyboardManagerHelper::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it->first.GetActionKey(), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it->first.GetActionKey(), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Send current key pressed without shortcut flag so that it can be reprocessed in case the physical keys pressed are a different remapped shortcut
|
|
|
|
|
KeyboardManagerHelper::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)data->lParam->vkCode, 0, 0);
|
|
|
|
|
Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)data->lParam->vkCode, 0, 0);
|
|
|
|
|
i++;
|
|
|
|
|
|
|
|
|
|
// Do not send a dummy key as we want the current key press to behave as normal i.e. it can do press+release functionality if required. Required to allow a shortcut to Win key remap invoked directly after shortcut to shortcut is released to open start menu
|
|
|
|
|
@@ -669,7 +668,7 @@ namespace KeyboardEventHandlers
|
|
|
|
|
// If app specific shortcut has finished invoking, reset the target application
|
|
|
|
|
if (activatedApp)
|
|
|
|
|
{
|
|
|
|
|
keyboardManagerState.SetActivatedApp(KeyboardManagerConstants::NoActivatedApp);
|
|
|
|
|
state.SetActivatedApp(KeyboardManagerConstants::NoActivatedApp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UINT res = ii.SendVirtualInput((UINT)key_count, keyEventList, sizeof(INPUT));
|
|
|
|
|
@@ -681,7 +680,7 @@ namespace KeyboardEventHandlers
|
|
|
|
|
// For remap to key, if the original action key is not currently pressed, we should revert the keyboard state to the physical keys. If it is pressed we should not suppress the event so that shortcut to key remaps can be pressed with other keys. Example use-case: Alt+D->Win, allows Alt+D+A to perform Win+A
|
|
|
|
|
|
|
|
|
|
// Modifier state reset might be required for this key depending on the target key - ex: Ctrl+A -> Caps, Shift is pressed. System should not see Shift and Caps pressed together
|
|
|
|
|
ResetIfModifierKeyForLowerLevelKeyHandlers(ii, data->lParam->vkCode, KeyboardManagerHelper::FilterArtificialKeys(std::get<DWORD>(it->second.targetShortcut)));
|
|
|
|
|
ResetIfModifierKeyForLowerLevelKeyHandlers(ii, data->lParam->vkCode, Helpers::FilterArtificialKeys(std::get<DWORD>(it->second.targetShortcut)));
|
|
|
|
|
|
|
|
|
|
// If the shortcut is remapped to Disable then we have to revert the keyboard state to the physical keys
|
|
|
|
|
bool isRemapToDisable = (std::get<DWORD>(it->second.targetShortcut) == CommonSharedConstants::VK_DISABLED);
|
|
|
|
|
@@ -690,7 +689,7 @@ namespace KeyboardEventHandlers
|
|
|
|
|
if (!isRemapToDisable)
|
|
|
|
|
{
|
|
|
|
|
// If the remap target key is currently pressed, then we do not have to revert the keyboard state to the physical keys
|
|
|
|
|
if (ii.GetVirtualKeyState((KeyboardManagerHelper::FilterArtificialKeys(std::get<DWORD>(it->second.targetShortcut)))))
|
|
|
|
|
if (ii.GetVirtualKeyState((Helpers::FilterArtificialKeys(std::get<DWORD>(it->second.targetShortcut)))))
|
|
|
|
|
{
|
|
|
|
|
isOriginalActionKeyPressed = true;
|
|
|
|
|
}
|
|
|
|
|
@@ -710,13 +709,13 @@ namespace KeyboardEventHandlers
|
|
|
|
|
|
|
|
|
|
// Set original shortcut key down state
|
|
|
|
|
int i = 0;
|
|
|
|
|
KeyboardManagerHelper::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, i, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, i, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
|
|
|
|
|
// Send the original action key only if it is physically pressed. For remappings to keys other than disabled we already check earlier that it is not pressed in this scenario. For remap to disable
|
|
|
|
|
if (isRemapToDisable && isOriginalActionKeyPressed)
|
|
|
|
|
{
|
|
|
|
|
// Set original action key
|
|
|
|
|
KeyboardManagerHelper::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it->first.GetActionKey(), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it->first.GetActionKey(), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
@@ -725,7 +724,7 @@ namespace KeyboardEventHandlers
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Send current key pressed without shortcut flag so that it can be reprocessed in case the physical keys pressed are a different remapped shortcut
|
|
|
|
|
KeyboardManagerHelper::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)data->lParam->vkCode, 0, 0);
|
|
|
|
|
Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)data->lParam->vkCode, 0, 0);
|
|
|
|
|
i++;
|
|
|
|
|
|
|
|
|
|
// Do not send a dummy key as we want the current key press to behave as normal i.e. it can do press+release functionality if required. Required to allow a shortcut to Win key remap invoked directly after another shortcut to key remap is released to open start menu
|
|
|
|
|
@@ -738,7 +737,7 @@ namespace KeyboardEventHandlers
|
|
|
|
|
// If app specific shortcut has finished invoking, reset the target application
|
|
|
|
|
if (activatedApp != KeyboardManagerConstants::NoActivatedApp)
|
|
|
|
|
{
|
|
|
|
|
keyboardManagerState.SetActivatedApp(KeyboardManagerConstants::NoActivatedApp);
|
|
|
|
|
state.SetActivatedApp(KeyboardManagerConstants::NoActivatedApp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UINT res = ii.SendVirtualInput((UINT)key_count, keyEventList, sizeof(INPUT));
|
|
|
|
|
@@ -760,12 +759,12 @@ namespace KeyboardEventHandlers
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Function to a handle an os-level shortcut remap
|
|
|
|
|
intptr_t HandleOSLevelShortcutRemapEvent(KeyboardManagerInput::InputInterface& ii, LowlevelKeyboardEvent* data, KeyboardManagerState& keyboardManagerState) noexcept
|
|
|
|
|
intptr_t HandleOSLevelShortcutRemapEvent(KeyboardManagerInput::InputInterface& ii, LowlevelKeyboardEvent* data, State& state) noexcept
|
|
|
|
|
{
|
|
|
|
|
// 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);
|
|
|
|
|
bool result = HandleShortcutRemapEvent(ii, data, state);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -773,7 +772,7 @@ namespace KeyboardEventHandlers
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Function to a handle an app-specific shortcut remap
|
|
|
|
|
intptr_t HandleAppSpecificShortcutRemapEvent(KeyboardManagerInput::InputInterface& ii, LowlevelKeyboardEvent* data, KeyboardManagerState& keyboardManagerState) noexcept
|
|
|
|
|
intptr_t HandleAppSpecificShortcutRemapEvent(KeyboardManagerInput::InputInterface& ii, LowlevelKeyboardEvent* data, State& state) noexcept
|
|
|
|
|
{
|
|
|
|
|
// Check if the key event was generated by KeyboardManager to avoid remapping events generated by us.
|
|
|
|
|
if (data->lParam->dwExtraInfo != KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG)
|
|
|
|
|
@@ -800,29 +799,29 @@ namespace KeyboardEventHandlers
|
|
|
|
|
AppSpecificShortcutRemapTable::iterator it;
|
|
|
|
|
|
|
|
|
|
// Check if an app-specific shortcut is already activated
|
|
|
|
|
if (keyboardManagerState.GetActivatedApp() == KeyboardManagerConstants::NoActivatedApp)
|
|
|
|
|
if (state.GetActivatedApp() == KeyboardManagerConstants::NoActivatedApp)
|
|
|
|
|
{
|
|
|
|
|
query_string = process_name;
|
|
|
|
|
it = keyboardManagerState.appSpecificShortcutReMap.find(query_string);
|
|
|
|
|
it = state.appSpecificShortcutReMap.find(query_string);
|
|
|
|
|
|
|
|
|
|
// If no entry is found, search for the process name without it's file extension
|
|
|
|
|
if (it == keyboardManagerState.appSpecificShortcutReMap.end())
|
|
|
|
|
if (it == state.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);
|
|
|
|
|
it = state.appSpecificShortcutReMap.find(query_string);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
query_string = keyboardManagerState.GetActivatedApp();
|
|
|
|
|
it = keyboardManagerState.appSpecificShortcutReMap.find(query_string);
|
|
|
|
|
query_string = state.GetActivatedApp();
|
|
|
|
|
it = state.appSpecificShortcutReMap.find(query_string);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (it != keyboardManagerState.appSpecificShortcutReMap.end())
|
|
|
|
|
if (it != state.appSpecificShortcutReMap.end())
|
|
|
|
|
{
|
|
|
|
|
bool result = HandleShortcutRemapEvent(ii, data, keyboardManagerState, query_string);
|
|
|
|
|
bool result = HandleShortcutRemapEvent(ii, data, state, query_string);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -837,14 +836,14 @@ namespace KeyboardEventHandlers
|
|
|
|
|
if (target == VK_CAPITAL)
|
|
|
|
|
{
|
|
|
|
|
// If the argument is either of the Ctrl/Shift/Alt modifier key codes
|
|
|
|
|
if (KeyboardManagerHelper::IsModifierKey(key) && !(key == VK_LWIN || key == VK_RWIN || key == CommonSharedConstants::VK_WIN_BOTH))
|
|
|
|
|
if (Helpers::IsModifierKey(key) && !(key == VK_LWIN || key == VK_RWIN || key == CommonSharedConstants::VK_WIN_BOTH))
|
|
|
|
|
{
|
|
|
|
|
int key_count = 1;
|
|
|
|
|
LPINPUT keyEventList = new INPUT[size_t(key_count)]();
|
|
|
|
|
memset(keyEventList, 0, sizeof(keyEventList));
|
|
|
|
|
|
|
|
|
|
// Use the suppress flag to ensure these are not intercepted by any remapped keys or shortcuts
|
|
|
|
|
KeyboardManagerHelper::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, (WORD)key, KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SUPPRESS_FLAG);
|
|
|
|
|
Helpers::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, (WORD)key, KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SUPPRESS_FLAG);
|
|
|
|
|
UINT res = ii.SendVirtualInput((UINT)key_count, keyEventList, sizeof(INPUT));
|
|
|
|
|
delete[] keyEventList;
|
|
|
|
|
}
|
|
|
|
|
|