From 662f04ed34da0fb8e074a6912e85b9afefd03371 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionu=C8=9B=20Man=C8=9Ba?= Date: Mon, 14 Apr 2025 01:48:10 -0700 Subject: [PATCH] [KeyboardManager] Fix modifier Key (Not right or left) stuck (#37930) * Fix ctr,alt,shift getting stuck * more changes * Update src/modules/keyboardmanager/common/Helpers.h Co-authored-by: Hao Liu --------- Co-authored-by: Hao Liu --- .../EditorHelpers.cpp | 6 +- .../KeyboardEventHandlers.cpp | 94 +++++++++++-------- .../KeyboardManagerEngineLibrary/trace.cpp | 6 +- .../keyboardmanager/common/Helpers.cpp | 34 +++---- src/modules/keyboardmanager/common/Helpers.h | 4 +- .../common/KeyboardManagerCommon.vcxproj | 1 + .../KeyboardManagerCommon.vcxproj.filters | 3 + .../keyboardmanager/common/Modifiers.h | 26 +++++ .../keyboardmanager/common/RemapShortcut.h | 11 ++- .../keyboardmanager/common/Shortcut.cpp | 42 +++++++-- src/modules/keyboardmanager/common/Shortcut.h | 7 +- 11 files changed, 153 insertions(+), 81 deletions(-) create mode 100644 src/modules/keyboardmanager/common/Modifiers.h diff --git a/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditorHelpers.cpp b/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditorHelpers.cpp index 059d8931cc..1874899c1b 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditorHelpers.cpp +++ b/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditorHelpers.cpp @@ -117,15 +117,15 @@ namespace EditorHelpers } if (shortcut.ctrlKey != ModifierKey::Disabled) { - keys.push_back(winrt::to_hstring(keyboardMap.GetKeyName(shortcut.GetCtrlKey()).c_str())); + keys.push_back(winrt::to_hstring(keyboardMap.GetKeyName(shortcut.GetCtrlKey(ModifierKey::Both)).c_str())); } if (shortcut.altKey != ModifierKey::Disabled) { - keys.push_back(winrt::to_hstring(keyboardMap.GetKeyName(shortcut.GetAltKey()).c_str())); + keys.push_back(winrt::to_hstring(keyboardMap.GetKeyName(shortcut.GetAltKey(ModifierKey::Both)).c_str())); } if (shortcut.shiftKey != ModifierKey::Disabled) { - keys.push_back(winrt::to_hstring(keyboardMap.GetKeyName(shortcut.GetShiftKey()).c_str())); + keys.push_back(winrt::to_hstring(keyboardMap.GetKeyName(shortcut.GetShiftKey(ModifierKey::Both)).c_str())); } if (shortcut.actionKey != NULL) { diff --git a/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/KeyboardEventHandlers.cpp b/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/KeyboardEventHandlers.cpp index 537e9016ac..080fcc16c2 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/KeyboardEventHandlers.cpp +++ b/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/KeyboardEventHandlers.cpp @@ -158,13 +158,13 @@ namespace KeyboardEventHandlers if (data->wParam == WM_KEYUP || data->wParam == WM_SYSKEYUP) { Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(targetShortcut.GetActionKey()), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG); - Helpers::SetModifierKeyEvents(targetShortcut, ModifierKey::Disabled, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG); + Helpers::SetModifierKeyEvents(targetShortcut, Modifiers(), keyEventList, 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 - Helpers::SetModifierKeyEvents(targetShortcut, ModifierKey::Disabled, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG); + Helpers::SetModifierKeyEvents(targetShortcut, Modifiers(), keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG); Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(targetShortcut.GetActionKey()), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG); } } @@ -371,11 +371,35 @@ namespace KeyboardEventHandlers // Remember which win key was pressed initially if (ii.GetVirtualKeyState(VK_RWIN)) { - it->second.winKeyInvoked = ModifierKey::Right; + it->second.modifierKeysInvoked.winKey = ModifierKey::Right; } else if (ii.GetVirtualKeyState(VK_LWIN)) { - it->second.winKeyInvoked = ModifierKey::Left; + it->second.modifierKeysInvoked.winKey = ModifierKey::Left; + } + if (ii.GetVirtualKeyState(VK_RCONTROL)) + { + it->second.modifierKeysInvoked.ctrlKey = ModifierKey::Right; + } + else if (ii.GetVirtualKeyState(VK_LCONTROL)) + { + it->second.modifierKeysInvoked.ctrlKey = ModifierKey::Left; + } + if (ii.GetVirtualKeyState(VK_RSHIFT)) + { + it->second.modifierKeysInvoked.shiftKey = ModifierKey::Right; + } + else if (ii.GetVirtualKeyState(VK_LSHIFT)) + { + it->second.modifierKeysInvoked.shiftKey = ModifierKey::Left; + } + if (ii.GetVirtualKeyState(VK_RMENU)) + { + it->second.modifierKeysInvoked.altKey = ModifierKey::Right; + } + else if (ii.GetVirtualKeyState(VK_LMENU)) + { + it->second.modifierKeysInvoked.altKey = ModifierKey::Left; } if (isRunProgram) @@ -450,7 +474,7 @@ namespace KeyboardEventHandlers { // key down for all new shortcut keys except the common modifiers keyEventList = std::vector{}; - Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first); + Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.modifierKeysInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first); Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(std::get(it->second.targetShortcut).GetActionKey()), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); } else @@ -460,15 +484,15 @@ namespace KeyboardEventHandlers Helpers::SetDummyKeyEvent(keyEventList, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); // Release original shortcut state (release in reverse order of shortcut to be accurate) - Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get(it->second.targetShortcut)); + Helpers::SetModifierKeyEvents(it->first, it->second.modifierKeysInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get(it->second.targetShortcut)); // Set new shortcut key down state - Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first); + Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.modifierKeysInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first); Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(std::get(it->second.targetShortcut).GetActionKey()), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); } // Modifier state reset might be required for this key depending on the shortcut's action and target modifiers - ex: Win+Caps -> Ctrl+A - if (it->first.GetCtrlKey() == NULL && it->first.GetAltKey() == NULL && it->first.GetShiftKey() == NULL) + if (it->first.GetCtrlKey(it->second.modifierKeysInvoked.ctrlKey) == NULL && it->first.GetAltKey(it->second.modifierKeysInvoked.altKey) == NULL && it->first.GetShiftKey(it->second.modifierKeysInvoked.shiftKey) == NULL) { Shortcut temp = std::get(it->second.targetShortcut); for (auto keys : temp.GetKeyCodes()) @@ -490,7 +514,7 @@ namespace KeyboardEventHandlers Helpers::SetDummyKeyEvent(keyEventList, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); // Release original shortcut state (release in reverse order of shortcut to be accurate) - Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); + Helpers::SetModifierKeyEvents(it->first, it->second.modifierKeysInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); // Set target key down state if (std::get(it->second.targetShortcut) != CommonSharedConstants::VK_DISABLED) @@ -499,7 +523,7 @@ namespace KeyboardEventHandlers } // 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) + if (it->first.GetCtrlKey(it->second.modifierKeysInvoked.ctrlKey) == NULL && it->first.GetAltKey(it->second.modifierKeysInvoked.altKey) == NULL && it->first.GetShiftKey(it->second.modifierKeysInvoked.shiftKey) == NULL) { ResetIfModifierKeyForLowerLevelKeyHandlers(ii, static_cast(Helpers::FilterArtificialKeys(std::get(it->second.targetShortcut))), data->lParam->vkCode); } @@ -512,7 +536,7 @@ namespace KeyboardEventHandlers Helpers::SetDummyKeyEvent(keyEventList, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); // Release original shortcut state (release in reverse order of shortcut to be accurate) - Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); + Helpers::SetModifierKeyEvents(it->first, it->second.modifierKeysInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); Helpers::SetTextKeyEvents(keyEventList, remapping); } @@ -614,12 +638,12 @@ namespace KeyboardEventHandlers Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(std::get(it->second.targetShortcut).GetActionKey()), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); } - Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first, data->lParam->vkCode); + Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.modifierKeysInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first, data->lParam->vkCode); if (!isAltRightKeyInvoked) { // 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 its own key message - Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get(it->second.targetShortcut), data->lParam->vkCode); + Helpers::SetModifierKeyEvents(it->first, it->second.modifierKeysInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get(it->second.targetShortcut), data->lParam->vkCode); } else { @@ -643,7 +667,7 @@ namespace KeyboardEventHandlers if (!isAltRightKeyInvoked) { // 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 its own key message - Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, Shortcut(), data->lParam->vkCode); + Helpers::SetModifierKeyEvents(it->first, it->second.modifierKeysInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, Shortcut(), data->lParam->vkCode); } else { @@ -656,7 +680,7 @@ namespace KeyboardEventHandlers // Reset the remap state it->second.isShortcutInvoked = false; - it->second.winKeyInvoked = ModifierKey::Disabled; + it->second.modifierKeysInvoked.Reset(); it->second.isOriginalActionKeyPressed = false; // If app specific shortcut has finished invoking, reset the target application @@ -719,14 +743,14 @@ namespace KeyboardEventHandlers Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(std::get(it->second.targetShortcut).GetActionKey()), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); // Release new shortcut state (release in reverse order of shortcut to be accurate) - Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first); + Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.modifierKeysInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first); // Set old shortcut key down state - Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get(it->second.targetShortcut)); + Helpers::SetModifierKeyEvents(it->first, it->second.modifierKeysInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get(it->second.targetShortcut)); // Reset the remap state it->second.isShortcutInvoked = false; - it->second.winKeyInvoked = ModifierKey::Disabled; + it->second.modifierKeysInvoked.Reset(); it->second.isOriginalActionKeyPressed = false; // If app specific shortcut has finished invoking, reset the target application @@ -763,7 +787,7 @@ namespace KeyboardEventHandlers if (!isAltRightKeyInvoked) { // Set original shortcut key down state except the action key - Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); + Helpers::SetModifierKeyEvents(it->first, it->second.modifierKeysInvoked, keyEventList, 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 @@ -773,7 +797,7 @@ namespace KeyboardEventHandlers { // Reset the remap state it->second.isShortcutInvoked = false; - it->second.winKeyInvoked = ModifierKey::Disabled; + it->second.modifierKeysInvoked.Reset(); it->second.isOriginalActionKeyPressed = false; } @@ -795,7 +819,7 @@ namespace KeyboardEventHandlers if (remapToShortcut) { // Modifier state reset might be required for this key depending on the target shortcut action key - ex: Ctrl+A -> Win+Caps - if (std::get(it->second.targetShortcut).GetCtrlKey() == NULL && std::get(it->second.targetShortcut).GetAltKey() == NULL && std::get(it->second.targetShortcut).GetShiftKey() == NULL) + if (std::get(it->second.targetShortcut).GetCtrlKey(it->second.modifierKeysInvoked.ctrlKey) == NULL && std::get(it->second.targetShortcut).GetAltKey(it->second.modifierKeysInvoked.altKey) == NULL && std::get(it->second.targetShortcut).GetShiftKey(it->second.modifierKeysInvoked.shiftKey) == NULL) { ResetIfModifierKeyForLowerLevelKeyHandlers(ii, data->lParam->vkCode, std::get(it->second.targetShortcut).GetActionKey()); } @@ -817,7 +841,7 @@ namespace KeyboardEventHandlers if (remapToShortcut) { // Modifier state reset might be required for this key depending on the target shortcut action key - ex: Ctrl+A -> Win+Caps, Shift is pressed. System should not see Shift and Caps pressed together - if (std::get(it->second.targetShortcut).GetCtrlKey() == NULL && std::get(it->second.targetShortcut).GetAltKey() == NULL && std::get(it->second.targetShortcut).GetShiftKey() == NULL) + if (std::get(it->second.targetShortcut).GetCtrlKey(it->second.modifierKeysInvoked.ctrlKey) == NULL && std::get(it->second.targetShortcut).GetAltKey(it->second.modifierKeysInvoked.altKey) == NULL && std::get(it->second.targetShortcut).GetShiftKey(it->second.modifierKeysInvoked.shiftKey) == NULL) { ResetIfModifierKeyForLowerLevelKeyHandlers(ii, data->lParam->vkCode, std::get(it->second.targetShortcut).GetActionKey()); } @@ -837,7 +861,7 @@ namespace KeyboardEventHandlers DWORD to = std::get<0>(newRemapping.targetShortcut); if (!isAltRightKeyInvoked) { - Helpers::SetModifierKeyEvents(from, it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); + Helpers::SetModifierKeyEvents(from, it->second.modifierKeysInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); } if (ii.GetVirtualKeyState(static_cast(from.actionKey))) { @@ -851,7 +875,7 @@ namespace KeyboardEventHandlers Shortcut to = std::get(newRemapping.targetShortcut); if (!isAltRightKeyInvoked) { - Helpers::SetModifierKeyEvents(from, it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, to); + Helpers::SetModifierKeyEvents(from, it->second.modifierKeysInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, to); } if (ii.GetVirtualKeyState(static_cast(from.actionKey))) { @@ -860,21 +884,11 @@ namespace KeyboardEventHandlers } if (!isAltRightKeyInvoked) { - Helpers::SetModifierKeyEvents(to, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, from); + Helpers::SetModifierKeyEvents(to, it->second.modifierKeysInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, from); } Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(to.actionKey), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); newRemapping.isShortcutInvoked = true; } - - // Remember which win key was pressed initially - if (ii.GetVirtualKeyState(VK_RWIN)) - { - newRemapping.winKeyInvoked = ModifierKey::Right; - } - else if (ii.GetVirtualKeyState(VK_LWIN)) - { - newRemapping.winKeyInvoked = ModifierKey::Left; - } } else { @@ -888,10 +902,10 @@ namespace KeyboardEventHandlers } if (!isAltRightKeyInvoked) { - Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first); + Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.modifierKeysInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first); // Set old shortcut key down state - Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get(it->second.targetShortcut)); + Helpers::SetModifierKeyEvents(it->first, it->second.modifierKeysInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get(it->second.targetShortcut)); } // key down for original shortcut action key with shortcut flag so that we don't invoke the same shortcut remap again @@ -910,7 +924,7 @@ namespace KeyboardEventHandlers { // Reset the remap state it->second.isShortcutInvoked = false; - it->second.winKeyInvoked = ModifierKey::Disabled; + it->second.modifierKeysInvoked.Reset(); it->second.isOriginalActionKeyPressed = false; } @@ -960,7 +974,7 @@ namespace KeyboardEventHandlers if (!isAltRightKeyInvoked) { // Set original shortcut key down state - Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); + Helpers::SetModifierKeyEvents(it->first, it->second.modifierKeysInvoked, keyEventList, 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 @@ -979,7 +993,7 @@ namespace KeyboardEventHandlers { // Reset the remap state it->second.isShortcutInvoked = false; - it->second.winKeyInvoked = ModifierKey::Disabled; + it->second.modifierKeysInvoked.Reset(); it->second.isOriginalActionKeyPressed = false; } diff --git a/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/trace.cpp b/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/trace.cpp index ab3e49cb87..76a7355bff 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/trace.cpp +++ b/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/trace.cpp @@ -145,15 +145,15 @@ std::wstring GetShortcutHumanReadableString(Shortcut const& shortcut, LayoutMap& } if (shortcut.ctrlKey != ModifierKey::Disabled) { - humanReadableShortcut += keyboardMap.GetKeyName(shortcut.GetCtrlKey()) + L" + "; + humanReadableShortcut += keyboardMap.GetKeyName(shortcut.GetCtrlKey(ModifierKey::Both)) + L" + "; } if (shortcut.altKey != ModifierKey::Disabled) { - humanReadableShortcut += keyboardMap.GetKeyName(shortcut.GetAltKey()) + L" + "; + humanReadableShortcut += keyboardMap.GetKeyName(shortcut.GetAltKey(ModifierKey::Both)) + L" + "; } if (shortcut.shiftKey != ModifierKey::Disabled) { - humanReadableShortcut += keyboardMap.GetKeyName(shortcut.GetShiftKey()) + L" + "; + humanReadableShortcut += keyboardMap.GetKeyName(shortcut.GetShiftKey(ModifierKey::Both)) + L" + "; } if (shortcut.actionKey != NULL) { diff --git a/src/modules/keyboardmanager/common/Helpers.cpp b/src/modules/keyboardmanager/common/Helpers.cpp index fb2cefd98a..b619ae73d3 100644 --- a/src/modules/keyboardmanager/common/Helpers.cpp +++ b/src/modules/keyboardmanager/common/Helpers.cpp @@ -262,27 +262,27 @@ namespace Helpers } // Function to set key events for modifier keys: When shortcutToCompare is passed (non-empty shortcut), then the key event is sent only if both shortcut's don't have the same modifier key. When keyToBeReleased is passed (non-NULL), then the key event is sent if either the shortcuts don't have the same modifier or if the shortcutToBeSent's modifier matches the keyToBeReleased - void SetModifierKeyEvents(const Shortcut& shortcutToBeSent, const ModifierKey& winKeyInvoked, std::vector& keyEventArray, bool isKeyDown, ULONG_PTR extraInfoFlag, const Shortcut& shortcutToCompare, const DWORD& keyToBeReleased) + void SetModifierKeyEvents(const Shortcut& shortcutToBeSent, const Modifiers& modifiersKeys, std::vector& keyEventArray, bool isKeyDown, ULONG_PTR extraInfoFlag, const Shortcut& shortcutToCompare, const DWORD& keyToBeReleased) { // If key down is to be sent, send in the order Win, Ctrl, Alt, Shift if (isKeyDown) { // If shortcutToCompare is non-empty, then the key event is sent only if both shortcut's don't have the same modifier key. If keyToBeReleased is non-NULL, then the key event is sent if either the shortcuts don't have the same modifier or if the shortcutToBeSent's modifier matches the keyToBeReleased - if (shortcutToBeSent.GetWinKey(winKeyInvoked) != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetWinKey(winKeyInvoked) != shortcutToCompare.GetWinKey(winKeyInvoked)) && (keyToBeReleased == NULL || !shortcutToBeSent.CheckWinKey(keyToBeReleased))) + if (shortcutToBeSent.GetWinKey(modifiersKeys.winKey) != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetWinKey(modifiersKeys.winKey) != shortcutToCompare.GetWinKey(modifiersKeys.winKey)) && (keyToBeReleased == NULL || !shortcutToBeSent.CheckWinKey(keyToBeReleased))) { - Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetWinKey(winKeyInvoked)), 0, extraInfoFlag); + Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetWinKey(modifiersKeys.winKey)), 0, extraInfoFlag); } - if (shortcutToBeSent.GetCtrlKey() != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetCtrlKey() != shortcutToCompare.GetCtrlKey()) && (keyToBeReleased == NULL || !shortcutToBeSent.CheckCtrlKey(keyToBeReleased))) + if (shortcutToBeSent.GetCtrlKey(modifiersKeys.ctrlKey) != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetCtrlKey(modifiersKeys.ctrlKey) != shortcutToCompare.GetCtrlKey(modifiersKeys.ctrlKey)) && (keyToBeReleased == NULL || !shortcutToBeSent.CheckCtrlKey(keyToBeReleased))) { - Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetCtrlKey()), 0, extraInfoFlag); + Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetCtrlKey(modifiersKeys.ctrlKey)), 0, extraInfoFlag); } - if (shortcutToBeSent.GetAltKey() != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetAltKey() != shortcutToCompare.GetAltKey()) && (keyToBeReleased == NULL || !shortcutToBeSent.CheckAltKey(keyToBeReleased))) + if (shortcutToBeSent.GetAltKey(modifiersKeys.altKey) != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetAltKey(modifiersKeys.altKey) != shortcutToCompare.GetAltKey(modifiersKeys.altKey)) && (keyToBeReleased == NULL || !shortcutToBeSent.CheckAltKey(keyToBeReleased))) { - Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetAltKey()), 0, extraInfoFlag); + Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetAltKey(modifiersKeys.altKey)), 0, extraInfoFlag); } - if (shortcutToBeSent.GetShiftKey() != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetShiftKey() != shortcutToCompare.GetShiftKey()) && (keyToBeReleased == NULL || !shortcutToBeSent.CheckShiftKey(keyToBeReleased))) + if (shortcutToBeSent.GetShiftKey(modifiersKeys.shiftKey) != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetShiftKey(modifiersKeys.shiftKey) != shortcutToCompare.GetShiftKey(modifiersKeys.shiftKey)) && (keyToBeReleased == NULL || !shortcutToBeSent.CheckShiftKey(keyToBeReleased))) { - Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetShiftKey()), 0, extraInfoFlag); + Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetShiftKey(modifiersKeys.shiftKey)), 0, extraInfoFlag); } } @@ -290,21 +290,21 @@ namespace Helpers else { // If shortcutToCompare is non-empty, then the key event is sent only if both shortcut's don't have the same modifier key. If keyToBeReleased is non-NULL, then the key event is sent if either the shortcuts don't have the same modifier or if the shortcutToBeSent's modifier matches the keyToBeReleased - if (shortcutToBeSent.GetShiftKey() != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetShiftKey() != shortcutToCompare.GetShiftKey() || shortcutToBeSent.CheckShiftKey(keyToBeReleased))) + if (shortcutToBeSent.GetShiftKey(modifiersKeys.shiftKey) != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetShiftKey(modifiersKeys.shiftKey) != shortcutToCompare.GetShiftKey(modifiersKeys.shiftKey) || shortcutToBeSent.CheckShiftKey(keyToBeReleased))) { - Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetShiftKey()), KEYEVENTF_KEYUP, extraInfoFlag); + Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetShiftKey(modifiersKeys.shiftKey)), KEYEVENTF_KEYUP, extraInfoFlag); } - if (shortcutToBeSent.GetAltKey() != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetAltKey() != shortcutToCompare.GetAltKey() || shortcutToBeSent.CheckAltKey(keyToBeReleased))) + if (shortcutToBeSent.GetAltKey(modifiersKeys.altKey) != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetAltKey(modifiersKeys.altKey) != shortcutToCompare.GetAltKey(modifiersKeys.altKey) || shortcutToBeSent.CheckAltKey(keyToBeReleased))) { - Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetAltKey()), KEYEVENTF_KEYUP, extraInfoFlag); + Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetAltKey(modifiersKeys.altKey)), KEYEVENTF_KEYUP, extraInfoFlag); } - if (shortcutToBeSent.GetCtrlKey() != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetCtrlKey() != shortcutToCompare.GetCtrlKey() || shortcutToBeSent.CheckCtrlKey(keyToBeReleased))) + if (shortcutToBeSent.GetCtrlKey(modifiersKeys.ctrlKey) != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetCtrlKey(modifiersKeys.ctrlKey) != shortcutToCompare.GetCtrlKey(modifiersKeys.ctrlKey) || shortcutToBeSent.CheckCtrlKey(keyToBeReleased))) { - Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetCtrlKey()), KEYEVENTF_KEYUP, extraInfoFlag); + Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetCtrlKey(modifiersKeys.ctrlKey)), KEYEVENTF_KEYUP, extraInfoFlag); } - if (shortcutToBeSent.GetWinKey(winKeyInvoked) != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetWinKey(winKeyInvoked) != shortcutToCompare.GetWinKey(winKeyInvoked) || shortcutToBeSent.CheckWinKey(keyToBeReleased))) + if (shortcutToBeSent.GetWinKey(modifiersKeys.winKey) != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetWinKey(modifiersKeys.winKey) != shortcutToCompare.GetWinKey(modifiersKeys.winKey) || shortcutToBeSent.CheckWinKey(keyToBeReleased))) { - Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetWinKey(winKeyInvoked)), KEYEVENTF_KEYUP, extraInfoFlag); + Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetWinKey(modifiersKeys.winKey)), KEYEVENTF_KEYUP, extraInfoFlag); } } } diff --git a/src/modules/keyboardmanager/common/Helpers.h b/src/modules/keyboardmanager/common/Helpers.h index bd878a3942..8f38bbbbe4 100644 --- a/src/modules/keyboardmanager/common/Helpers.h +++ b/src/modules/keyboardmanager/common/Helpers.h @@ -1,5 +1,6 @@ #pragma once #include "Shortcut.h" +#include "RemapShortcut.h" class LayoutMap; @@ -47,7 +48,8 @@ namespace Helpers std::wstring GetCurrentApplication(bool keepPath); // Function to set key events for modifier keys: When shortcutToCompare is passed (non-empty shortcut), then the key event is sent only if both shortcut's don't have the same modifier key. When keyToBeReleased is passed (non-NULL), then the key event is sent if either the shortcuts don't have the same modifier or if the shortcutToBeSent's modifier matches the keyToBeReleased - void SetModifierKeyEvents(const Shortcut& shortcutToBeSent, const ModifierKey& winKeyInvoked, std::vector& keyEventArray, bool isKeyDown, ULONG_PTR extraInfoFlag, const Shortcut& shortcutToCompare = Shortcut(), const DWORD& keyToBeReleased = NULL); + void SetModifierKeyEvents(const Shortcut& shortcutToBeSent, const Modifiers& modifiersKeys, std::vector& keyEventArray, bool isKeyDown, ULONG_PTR extraInfoFlag, const Shortcut& shortcutToCompare = Shortcut(), const DWORD& keyToBeReleased = NULL); + // Function to filter the key codes for artificial key codes int32_t FilterArtificialKeys(const int32_t& key); diff --git a/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj b/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj index 36e76f971c..36c1238949 100644 --- a/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj +++ b/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj @@ -54,6 +54,7 @@ + diff --git a/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj.filters b/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj.filters index d1df33fa5e..287017e312 100644 --- a/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj.filters +++ b/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj.filters @@ -65,6 +65,9 @@ Header Files + + Header Files + diff --git a/src/modules/keyboardmanager/common/Modifiers.h b/src/modules/keyboardmanager/common/Modifiers.h new file mode 100644 index 0000000000..17dc5612e8 --- /dev/null +++ b/src/modules/keyboardmanager/common/Modifiers.h @@ -0,0 +1,26 @@ +#pragma once +#include "ModifierKey.h" + +#include + +class Modifiers +{ +public: + ModifierKey winKey = ModifierKey::Disabled; + ModifierKey ctrlKey = ModifierKey::Disabled; + ModifierKey altKey = ModifierKey::Disabled; + ModifierKey shiftKey = ModifierKey::Disabled; + + void Reset() + { + winKey = ModifierKey::Disabled; + ctrlKey = ModifierKey::Disabled; + altKey = ModifierKey::Disabled; + shiftKey = ModifierKey::Disabled; + } + + inline bool operator==(const Modifiers& other) const + { + return winKey == other.winKey && ctrlKey == other.ctrlKey && altKey == other.altKey && shiftKey == other.shiftKey; + } +}; diff --git a/src/modules/keyboardmanager/common/RemapShortcut.h b/src/modules/keyboardmanager/common/RemapShortcut.h index 8690630b4c..de12867903 100644 --- a/src/modules/keyboardmanager/common/RemapShortcut.h +++ b/src/modules/keyboardmanager/common/RemapShortcut.h @@ -1,6 +1,8 @@ #pragma once #include "Shortcut.h" +#include "Modifiers.h" #include +#include // This class stores all the variables associated with each shortcut remapping class RemapShortcut @@ -8,23 +10,24 @@ class RemapShortcut public: KeyShortcutTextUnion targetShortcut; bool isShortcutInvoked; - ModifierKey winKeyInvoked; + + Modifiers modifierKeysInvoked; // This bool value is only required for remapping shortcuts to Disable bool isOriginalActionKeyPressed; RemapShortcut(const KeyShortcutTextUnion& sc) : - targetShortcut(sc), isShortcutInvoked(false), winKeyInvoked(ModifierKey::Disabled), isOriginalActionKeyPressed(false) + targetShortcut(sc), isShortcutInvoked(false), isOriginalActionKeyPressed(false) { } RemapShortcut() : - targetShortcut(Shortcut()), isShortcutInvoked(false), winKeyInvoked(ModifierKey::Disabled), isOriginalActionKeyPressed(false) + targetShortcut(Shortcut()), isShortcutInvoked(false), isOriginalActionKeyPressed(false) { } inline bool operator==(const RemapShortcut& sc) const { - return targetShortcut == sc.targetShortcut && isShortcutInvoked == sc.isShortcutInvoked && winKeyInvoked == sc.winKeyInvoked; + return targetShortcut == sc.targetShortcut && isShortcutInvoked == sc.isShortcutInvoked && modifierKeysInvoked == sc.modifierKeysInvoked; } bool RemapToKey() diff --git a/src/modules/keyboardmanager/common/Shortcut.cpp b/src/modules/keyboardmanager/common/Shortcut.cpp index 38550199f4..08f161e08c 100644 --- a/src/modules/keyboardmanager/common/Shortcut.cpp +++ b/src/modules/keyboardmanager/common/Shortcut.cpp @@ -185,7 +185,7 @@ DWORD Shortcut::GetWinKey(const ModifierKey& input) const } // Function to return the virtual key code of the ctrl key state expected in the shortcut. Return NULL if it is not a part of the shortcut -DWORD Shortcut::GetCtrlKey() const +DWORD Shortcut::GetCtrlKey(const ModifierKey& input) const { if (ctrlKey == ModifierKey::Disabled) { @@ -201,12 +201,20 @@ DWORD Shortcut::GetCtrlKey() const } else { + if (input == ModifierKey::Right) + { + return VK_RCONTROL; + } + if (input == ModifierKey::Left) + { + return VK_LCONTROL; + } return VK_CONTROL; } } // Function to return the virtual key code of the alt key state expected in the shortcut. Return NULL if it is not a part of the shortcut -DWORD Shortcut::GetAltKey() const +DWORD Shortcut::GetAltKey(const ModifierKey& input) const { if (altKey == ModifierKey::Disabled) { @@ -220,6 +228,14 @@ DWORD Shortcut::GetAltKey() const { return VK_RMENU; } + if (input == ModifierKey::Right) + { + return VK_RMENU; + } + else if (input == ModifierKey::Left || input == ModifierKey::Disabled) + { + return VK_LMENU; + } else { return VK_MENU; @@ -227,7 +243,7 @@ DWORD Shortcut::GetAltKey() const } // Function to return the virtual key code of the shift key state expected in the shortcut. Return NULL if it is not a part of the shortcut -DWORD Shortcut::GetShiftKey() const +DWORD Shortcut::GetShiftKey(const ModifierKey& input) const { if (shiftKey == ModifierKey::Disabled) { @@ -243,6 +259,14 @@ DWORD Shortcut::GetShiftKey() const } else { + if (input == ModifierKey::Right) + { + return VK_RSHIFT; + } + if (input == ModifierKey::Left) + { + return VK_LSHIFT; + } return VK_SHIFT; } } @@ -493,15 +517,15 @@ winrt::hstring Shortcut::ToHstringVK() const } if (ctrlKey != ModifierKey::Disabled) { - output = output + winrt::to_hstring(static_cast(GetCtrlKey())) + winrt::to_hstring(L";"); + output = output + winrt::to_hstring(static_cast(GetCtrlKey(ModifierKey::Both))) + winrt::to_hstring(L";"); } if (altKey != ModifierKey::Disabled) { - output = output + winrt::to_hstring(static_cast(GetAltKey())) + winrt::to_hstring(L";"); + output = output + winrt::to_hstring(static_cast(GetAltKey(ModifierKey::Both))) + winrt::to_hstring(L";"); } if (shiftKey != ModifierKey::Disabled) { - output = output + winrt::to_hstring(static_cast(GetShiftKey())) + winrt::to_hstring(L";"); + output = output + winrt::to_hstring(static_cast(GetShiftKey(ModifierKey::Both))) + winrt::to_hstring(L";"); } if (actionKey != NULL) { @@ -531,15 +555,15 @@ std::vector Shortcut::GetKeyCodes() } if (ctrlKey != ModifierKey::Disabled) { - keys.push_back(GetCtrlKey()); + keys.push_back(GetCtrlKey(ModifierKey::Both)); } if (altKey != ModifierKey::Disabled) { - keys.push_back(GetAltKey()); + keys.push_back(GetAltKey(ModifierKey::Both)); } if (shiftKey != ModifierKey::Disabled) { - keys.push_back(GetShiftKey()); + keys.push_back(GetShiftKey(ModifierKey::Both)); } if (actionKey != NULL) { diff --git a/src/modules/keyboardmanager/common/Shortcut.h b/src/modules/keyboardmanager/common/Shortcut.h index d9a61ff433..439559c9d0 100644 --- a/src/modules/keyboardmanager/common/Shortcut.h +++ b/src/modules/keyboardmanager/common/Shortcut.h @@ -4,7 +4,6 @@ #include #include #include - namespace KeyboardManagerInput { class InputInterface; @@ -142,13 +141,13 @@ public: DWORD GetWinKey(const ModifierKey& input) const; // Function to return the virtual key code of the ctrl key state expected in the shortcut. Return NULL if it is not a part of the shortcut - DWORD GetCtrlKey() const; + DWORD GetCtrlKey(const ModifierKey& input) const; // Function to return the virtual key code of the alt key state expected in the shortcut. Return NULL if it is not a part of the shortcut - DWORD GetAltKey() const; + DWORD GetAltKey(const ModifierKey& input) const; // Function to return the virtual key code of the shift key state expected in the shortcut. Return NULL if it is not a part of the shortcut - DWORD GetShiftKey() const; + DWORD GetShiftKey(const ModifierKey& input) const; // Function to check if the input key matches the win key expected in the shortcut bool CheckWinKey(const DWORD input) const;