From efee03eb99732a28e7e861e612abd2cf4984fada Mon Sep 17 00:00:00 2001 From: Andrey Nekrasov Date: Wed, 23 Aug 2023 18:56:40 +0200 Subject: [PATCH] [KBM] Distinguish numpad keys (#28097) --- src/common/interop/keyboard_layout.cpp | 39 +++++-- .../KeyboardManagerEditor.cpp | 2 + .../KeyDropDownControl.cpp | 2 +- .../KeyboardEventHandlers.cpp | 64 +++++------ .../KeyboardManager.cpp | 5 +- .../keyboardmanager/common/Helpers.cpp | 47 +++++++- src/modules/keyboardmanager/common/Helpers.h | 6 ++ .../keyboardmanager/common/Shortcut.cpp | 14 +-- src/modules/keyboardmanager/common/Shortcut.h | 102 +++++------------- 9 files changed, 145 insertions(+), 136 deletions(-) diff --git a/src/common/interop/keyboard_layout.cpp b/src/common/interop/keyboard_layout.cpp index 87562d4bf3..6b40b66024 100644 --- a/src/common/interop/keyboard_layout.cpp +++ b/src/common/interop/keyboard_layout.cpp @@ -5,6 +5,8 @@ #include "keyboard_layout_impl.h" #include "shared_constants.h" +constexpr DWORD numpadOriginBit = 1ull << 31; + LayoutMap::LayoutMap() : impl(new LayoutMap::LayoutMapImpl()) { @@ -110,7 +112,6 @@ void LayoutMap::LayoutMapImpl::UpdateLayout() keyboardLayoutMap[VK_BACK] = L"Backspace"; keyboardLayoutMap[VK_TAB] = L"Tab"; keyboardLayoutMap[VK_CLEAR] = L"Clear"; - keyboardLayoutMap[VK_RETURN] = L"Enter"; keyboardLayoutMap[VK_SHIFT] = L"Shift"; keyboardLayoutMap[VK_CONTROL] = L"Ctrl"; keyboardLayoutMap[VK_MENU] = L"Alt"; @@ -118,20 +119,36 @@ void LayoutMap::LayoutMapImpl::UpdateLayout() keyboardLayoutMap[VK_CAPITAL] = L"Caps Lock"; keyboardLayoutMap[VK_ESCAPE] = L"Esc"; keyboardLayoutMap[VK_SPACE] = L"Space"; + + keyboardLayoutMap[VK_LEFT] = L"Left"; + keyboardLayoutMap[VK_RIGHT] = L"Right"; + keyboardLayoutMap[VK_UP] = L"Up"; + keyboardLayoutMap[VK_DOWN] = L"Down"; + keyboardLayoutMap[VK_INSERT] = L"Insert"; + keyboardLayoutMap[VK_DELETE] = L"Delete"; keyboardLayoutMap[VK_PRIOR] = L"PgUp"; keyboardLayoutMap[VK_NEXT] = L"PgDn"; - keyboardLayoutMap[VK_END] = L"End"; keyboardLayoutMap[VK_HOME] = L"Home"; - keyboardLayoutMap[VK_LEFT] = L"Left"; - keyboardLayoutMap[VK_UP] = L"Up"; - keyboardLayoutMap[VK_RIGHT] = L"Right"; - keyboardLayoutMap[VK_DOWN] = L"Down"; + keyboardLayoutMap[VK_END] = L"End"; + keyboardLayoutMap[VK_RETURN] = L"Enter"; + + keyboardLayoutMap[VK_LEFT | numpadOriginBit] = L"Left (Numpad)"; + keyboardLayoutMap[VK_RIGHT | numpadOriginBit] = L"Right (Numpad)"; + keyboardLayoutMap[VK_UP | numpadOriginBit] = L"Up (Numpad)"; + keyboardLayoutMap[VK_DOWN | numpadOriginBit] = L"Down (Numpad)"; + keyboardLayoutMap[VK_INSERT | numpadOriginBit] = L"Insert (Numpad)"; + keyboardLayoutMap[VK_DELETE | numpadOriginBit] = L"Delete (Numpad)"; + keyboardLayoutMap[VK_PRIOR | numpadOriginBit] = L"PgUp (Numpad)"; + keyboardLayoutMap[VK_NEXT | numpadOriginBit] = L"PgDn (Numpad)"; + keyboardLayoutMap[VK_HOME | numpadOriginBit] = L"Home (Numpad)"; + keyboardLayoutMap[VK_END | numpadOriginBit] = L"End (Numpad)"; + keyboardLayoutMap[VK_RETURN | numpadOriginBit] = L"Enter (Numpad)"; + keyboardLayoutMap[VK_DIVIDE | numpadOriginBit] = L"/ (Numpad)"; + keyboardLayoutMap[VK_SELECT] = L"Select"; keyboardLayoutMap[VK_PRINT] = L"Print"; keyboardLayoutMap[VK_EXECUTE] = L"Execute"; keyboardLayoutMap[VK_SNAPSHOT] = L"Print Screen"; - keyboardLayoutMap[VK_INSERT] = L"Insert"; - keyboardLayoutMap[VK_DELETE] = L"Delete"; keyboardLayoutMap[VK_HELP] = L"Help"; keyboardLayoutMap[VK_LWIN] = L"Win (Left)"; keyboardLayoutMap[VK_RWIN] = L"Win (Right)"; @@ -275,6 +292,12 @@ std::vector LayoutMap::LayoutMapImpl::GetKeyCodeList(const bool isShortcu } } + // Add numpad keys + for (auto it = keyboardLayoutMap.rbegin(); it->first & numpadOriginBit; ++it) + { + keyCodes.push_back(it->first); + } + // Sort the special keys in alphabetical order std::sort(specialKeys.begin(), specialKeys.end(), [&](const DWORD& lhs, const DWORD& rhs) { return keyboardLayoutMap[lhs] < keyboardLayoutMap[rhs]; diff --git a/src/modules/keyboardmanager/KeyboardManagerEditor/KeyboardManagerEditor.cpp b/src/modules/keyboardmanager/KeyboardManagerEditor/KeyboardManagerEditor.cpp index bb2cde24ad..54e2c7087d 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEditor/KeyboardManagerEditor.cpp +++ b/src/modules/keyboardmanager/KeyboardManagerEditor/KeyboardManagerEditor.cpp @@ -207,6 +207,8 @@ LRESULT KeyboardManagerEditor::KeyHookProc(int nCode, WPARAM wParam, LPARAM lPar { event.lParam = reinterpret_cast(lParam); event.wParam = wParam; + event.lParam->vkCode = Helpers::EncodeKeyNumpadOrigin(event.lParam->vkCode, event.lParam->flags & LLKHF_EXTENDED); + if (editor->HandleKeyboardHookEvent(&event) == 1) { // Reset Num Lock whenever a NumLock key down event is suppressed since Num Lock key state change occurs before it is intercepted by low level hooks diff --git a/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/KeyDropDownControl.cpp b/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/KeyDropDownControl.cpp index c847ad2a1b..991175019f 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/KeyDropDownControl.cpp +++ b/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/KeyDropDownControl.cpp @@ -27,7 +27,7 @@ DWORD KeyDropDownControl::GetSelectedValue(ComboBox comboBox) } auto value = winrt::unbox_value(dataContext); - return stoi(std::wstring(value)); + return stoul(std::wstring(value)); } void KeyDropDownControl::SetSelectedValue(std::wstring value) diff --git a/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/KeyboardEventHandlers.cpp b/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/KeyboardEventHandlers.cpp index be2a8cc02b..8528a7dd12 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/KeyboardEventHandlers.cpp +++ b/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/KeyboardEventHandlers.cpp @@ -42,8 +42,7 @@ namespace KeyboardEventHandlers key_count = std::get(it->second).Size(); } - LPINPUT keyEventList = new INPUT[size_t(key_count)](); - memset(keyEventList, 0, sizeof(keyEventList)); + LPINPUT keyEventList = new INPUT[size_t(key_count)]{}; // Handle remaps to VK_WIN_BOTH DWORD target; @@ -148,7 +147,6 @@ namespace KeyboardEventHandlers } int key_count = 2; LPINPUT keyEventList = new INPUT[size_t(key_count)](); - memset(keyEventList, 0, sizeof(keyEventList)); 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); @@ -232,8 +230,7 @@ namespace KeyboardEventHandlers { // key down for all new shortcut keys except the common modifiers key_count = dest_size - commonKeys; - keyEventList = new INPUT[key_count](); - memset(keyEventList, 0, sizeof(keyEventList)); + keyEventList = new INPUT[key_count]{}; int i = 0; Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, i, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first); Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, static_cast(std::get(it->second.targetShortcut).GetActionKey()), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); @@ -243,8 +240,7 @@ namespace KeyboardEventHandlers { // Dummy key, key up for all the original shortcut modifier keys and key down for all the new shortcut keys but common keys in each are not repeated key_count = KeyboardManagerConstants::DUMMY_KEY_EVENT_SIZE + (src_size - 1) + (dest_size) - (2 * static_cast(commonKeys)); - keyEventList = new INPUT[key_count](); - memset(keyEventList, 0, sizeof(keyEventList)); + keyEventList = new INPUT[key_count]{}; // 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; @@ -282,8 +278,7 @@ namespace KeyboardEventHandlers it->second.isOriginalActionKeyPressed = true; } - keyEventList = new INPUT[key_count](); - memset(keyEventList, 0, sizeof(keyEventList)); + keyEventList = new INPUT[key_count]{}; // 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; @@ -302,7 +297,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) { - ResetIfModifierKeyForLowerLevelKeyHandlers(ii,static_cast(Helpers::FilterArtificialKeys(std::get(it->second.targetShortcut))), data->lParam->vkCode); + ResetIfModifierKeyForLowerLevelKeyHandlers(ii, static_cast(Helpers::FilterArtificialKeys(std::get(it->second.targetShortcut))), data->lParam->vkCode); } } @@ -361,8 +356,7 @@ namespace KeyboardEventHandlers key_count += 1; } - keyEventList = new INPUT[key_count](); - memset(keyEventList, 0, sizeof(keyEventList)); + keyEventList = new INPUT[key_count]{}; // Release new shortcut state (release in reverse order of shortcut to be accurate) int i = 0; @@ -400,8 +394,7 @@ namespace KeyboardEventHandlers key_count--; } - keyEventList = new INPUT[key_count](); - memset(keyEventList, 0, sizeof(keyEventList)); + keyEventList = new INPUT[key_count]{}; // Release new key state int i = 0; @@ -453,8 +446,7 @@ namespace KeyboardEventHandlers } size_t key_count = 1; - LPINPUT keyEventList = new INPUT[key_count](); - memset(keyEventList, 0, sizeof(keyEventList)); + LPINPUT keyEventList = new INPUT[key_count]{}; if (remapToShortcut) { Helpers::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, static_cast(std::get(it->second.targetShortcut).GetActionKey()), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); @@ -476,13 +468,12 @@ namespace KeyboardEventHandlers LPINPUT keyEventList; if (remapToShortcut) { - keyEventList = new INPUT[key_count](); - memset(keyEventList, 0, sizeof(keyEventList)); + keyEventList = new INPUT[key_count]{}; Helpers::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, static_cast(std::get(it->second.targetShortcut).GetActionKey()), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); } else if (std::get(it->second.targetShortcut) == CommonSharedConstants::VK_DISABLED) { - // If remapped to disable, do nothing and suppress the key event + // If remapped to disable, do nothing and suppress the key event // Since the original shortcut's action key is released, set it to false it->second.isOriginalActionKeyPressed = false; return 1; @@ -491,13 +482,12 @@ namespace KeyboardEventHandlers { // 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({ Helpers::FilterArtificialKeys(std::get(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)); - Helpers::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD,static_cast(Helpers::FilterArtificialKeys(std::get(it->second.targetShortcut))), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); + keyEventList = new INPUT[key_count]{}; + Helpers::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, static_cast(Helpers::FilterArtificialKeys(std::get(it->second.targetShortcut))), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); } else { @@ -507,8 +497,7 @@ namespace KeyboardEventHandlers // 1 for releasing new key and original shortcut modifiers, and dummy key key_count = dest_size + (src_size - 1) + KeyboardManagerConstants::DUMMY_KEY_EVENT_SIZE; - keyEventList = new INPUT[key_count](); - memset(keyEventList, 0, sizeof(keyEventList)); + keyEventList = new INPUT[key_count]{}; // Release new key state int i = 0; @@ -574,7 +563,7 @@ namespace KeyboardEventHandlers size_t key_count; LPINPUT keyEventList = nullptr; - + // Check if a new remapping should be applied Shortcut currentlyPressed = it->first; currentlyPressed.actionKey = data->lParam->vkCode; @@ -588,8 +577,7 @@ namespace KeyboardEventHandlers DWORD to = std::get<0>(newRemapping.targetShortcut); bool isLastKeyStillPressed = ii.GetVirtualKeyState(static_cast(from.actionKey)); key_count = static_cast(from.Size()) - 1 + 1 + (isLastKeyStillPressed ? 1 : 0); - keyEventList = new INPUT[key_count](); - memset(keyEventList, 0, sizeof(keyEventList)); + keyEventList = new INPUT[key_count]{}; int i = 0; Helpers::SetModifierKeyEvents(from, it->second.winKeyInvoked, keyEventList, i, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); if (ii.GetVirtualKeyState(static_cast(from.actionKey))) @@ -599,7 +587,8 @@ namespace KeyboardEventHandlers i++; } Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, static_cast(to), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); - }else + } + else { Shortcut to = std::get(newRemapping.targetShortcut); bool isLastKeyStillPressed = ii.GetVirtualKeyState(static_cast(from.actionKey)); @@ -608,7 +597,7 @@ namespace KeyboardEventHandlers temp_key_count_calculation += static_cast(to.Size()) - 1; temp_key_count_calculation -= static_cast(2) * from.GetCommonModifiersCount(to); key_count = temp_key_count_calculation + 1 + (isLastKeyStillPressed ? 1 : 0); - keyEventList = new INPUT[key_count](); + keyEventList = new INPUT[key_count]{}; int i = 0; Helpers::SetModifierKeyEvents(from, it->second.winKeyInvoked, keyEventList, i, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, to); @@ -635,7 +624,7 @@ namespace KeyboardEventHandlers } else { - // Key up for all new shortcut keys, key down for original shortcut modifiers and current key press but common keys aren't repeated + // Key up for all new shortcut keys, key down for original shortcut modifiers and current key press but common keys aren't repeated key_count = (dest_size) + (src_size - 1) - (2 * static_cast(commonKeys)); // If the target shortcut's action key is pressed, then it should be released and original shortcut's action key should be set @@ -646,8 +635,7 @@ namespace KeyboardEventHandlers key_count += 2; } - keyEventList = new INPUT[key_count](); - memset(keyEventList, 0, sizeof(keyEventList)); + keyEventList = new INPUT[key_count]{}; // Release new shortcut state (release in reverse order of shortcut to be accurate) int i = 0; @@ -719,8 +707,7 @@ namespace KeyboardEventHandlers // Key down for original shortcut modifiers and action key, and current key press size_t key_count = src_size + 1; - LPINPUT keyEventList = new INPUT[key_count](); - memset(keyEventList, 0, sizeof(keyEventList)); + LPINPUT keyEventList = new INPUT[key_count]{}; // Set original shortcut key down state int i = 0; @@ -730,7 +717,7 @@ namespace KeyboardEventHandlers if (isRemapToDisable && isOriginalActionKeyPressed) { // Set original action key - Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD,static_cast(it->first.GetActionKey()), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); + Helpers::SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, static_cast(it->first.GetActionKey()), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); i++; } else @@ -812,7 +799,7 @@ namespace KeyboardEventHandlers std::wstring query_string; AppSpecificShortcutRemapTable::iterator it; - + // Check if an app-specific shortcut is already activated if (state.GetActivatedApp() == KeyboardManagerConstants::NoActivatedApp) { @@ -854,8 +841,7 @@ namespace KeyboardEventHandlers 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)); + LPINPUT keyEventList = new INPUT[size_t(key_count)]{}; // Use the suppress flag to ensure these are not intercepted by any remapped keys or shortcuts Helpers::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, static_cast(key), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SUPPRESS_FLAG); diff --git a/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/KeyboardManager.cpp b/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/KeyboardManager.cpp index 83369f2e32..4e9ce35ea0 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/KeyboardManager.cpp +++ b/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/KeyboardManager.cpp @@ -66,13 +66,14 @@ void KeyboardManager::LoadSettings() } } -LRESULT CALLBACK KeyboardManager::HookProc(int nCode, WPARAM wParam, LPARAM lParam) +LRESULT CALLBACK KeyboardManager::HookProc(int nCode, const WPARAM wParam, const LPARAM lParam) { LowlevelKeyboardEvent event; if (nCode == HC_ACTION) { event.lParam = reinterpret_cast(lParam); event.wParam = wParam; + event.lParam->vkCode = Helpers::EncodeKeyNumpadOrigin(event.lParam->vkCode, event.lParam->flags & LLKHF_EXTENDED); if (keyboardManagerObjectPtr->HandleKeyboardHookEvent(&event) == 1) { // Reset Num Lock whenever a NumLock key down event is suppressed since Num Lock key state change occurs before it is intercepted by low level hooks @@ -83,7 +84,7 @@ LRESULT CALLBACK KeyboardManager::HookProc(int nCode, WPARAM wParam, LPARAM lPar return 1; } } - + return CallNextHookEx(hookHandleCopy, nCode, wParam, lParam); } diff --git a/src/modules/keyboardmanager/common/Helpers.cpp b/src/modules/keyboardmanager/common/Helpers.cpp index e967d5ce98..00136c7ef5 100644 --- a/src/modules/keyboardmanager/common/Helpers.cpp +++ b/src/modules/keyboardmanager/common/Helpers.cpp @@ -9,6 +9,50 @@ namespace Helpers { + DWORD EncodeKeyNumpadOrigin(const DWORD key, const bool extended) + { + bool numpad_originated = false; + switch (key) + { + case VK_LEFT: + case VK_RIGHT: + case VK_UP: + case VK_DOWN: + case VK_INSERT: + case VK_DELETE: + case VK_PRIOR: + case VK_NEXT: + case VK_HOME: + case VK_END: + numpad_originated = !extended; + break; + case VK_RETURN: + case VK_DIVIDE: + numpad_originated = extended; + break; + } + + if (numpad_originated) + return key | GetNumpadOriginEncodingBit(); + else + return key; + } + + DWORD ClearKeyNumpadOrigin(const DWORD key) + { + return (key & ~GetNumpadOriginEncodingBit()); + } + + bool IsNumpadOriginated(const DWORD key) + { + return !!(key & GetNumpadOriginEncodingBit()); + } + DWORD GetNumpadOriginEncodingBit() + { + // Intentionally do not mimic KF_EXTENDED to avoid confusion, because it's not the same thing + // See EncodeKeyNumpadOrigin. + return 1ull << 31; + } // Function to check if the key is a modifier key bool IsModifierKey(DWORD key) { @@ -18,7 +62,8 @@ namespace Helpers // Function to get the combined key for modifier keys DWORD GetCombinedKey(DWORD key) { - switch (key) { + switch (key) + { case VK_LWIN: case VK_RWIN: return CommonSharedConstants::VK_WIN_BOTH; diff --git a/src/modules/keyboardmanager/common/Helpers.h b/src/modules/keyboardmanager/common/Helpers.h index 4040b11b4b..27005a0146 100644 --- a/src/modules/keyboardmanager/common/Helpers.h +++ b/src/modules/keyboardmanager/common/Helpers.h @@ -14,6 +14,12 @@ namespace Helpers Shift, Action }; + + // Functions to encode that a key is originated from numpad + DWORD EncodeKeyNumpadOrigin(const DWORD key, const bool extended); + DWORD ClearKeyNumpadOrigin(const DWORD key); + bool IsNumpadOriginated(const DWORD key); + DWORD GetNumpadOriginEncodingBit(); // Function to check if the key is a modifier key bool IsModifierKey(DWORD key); diff --git a/src/modules/keyboardmanager/common/Shortcut.cpp b/src/modules/keyboardmanager/common/Shortcut.cpp index acc7edde14..efe64e99b8 100644 --- a/src/modules/keyboardmanager/common/Shortcut.cpp +++ b/src/modules/keyboardmanager/common/Shortcut.cpp @@ -194,7 +194,7 @@ DWORD Shortcut::GetShiftKey() const } // Function to check if the input key matches the win key expected in the shortcut -bool Shortcut::CheckWinKey(const DWORD& input) const +bool Shortcut::CheckWinKey(const DWORD input) const { if (winKey == ModifierKey::Disabled) { @@ -216,7 +216,7 @@ bool Shortcut::CheckWinKey(const DWORD& input) const } // Function to check if the input key matches the ctrl key expected in the shortcut -bool Shortcut::CheckCtrlKey(const DWORD& input) const +bool Shortcut::CheckCtrlKey(const DWORD input) const { if (ctrlKey == ModifierKey::Disabled) { @@ -238,7 +238,7 @@ bool Shortcut::CheckCtrlKey(const DWORD& input) const } // Function to check if the input key matches the alt key expected in the shortcut -bool Shortcut::CheckAltKey(const DWORD& input) const +bool Shortcut::CheckAltKey(const DWORD input) const { if (altKey == ModifierKey::Disabled) { @@ -260,7 +260,7 @@ bool Shortcut::CheckAltKey(const DWORD& input) const } // Function to check if the input key matches the shift key expected in the shortcut -bool Shortcut::CheckShiftKey(const DWORD& input) const +bool Shortcut::CheckShiftKey(const DWORD input) const { if (shiftKey == ModifierKey::Disabled) { @@ -282,7 +282,7 @@ bool Shortcut::CheckShiftKey(const DWORD& input) const } // Function to set a key in the shortcut based on the passed key code argument. Returns false if it is already set to the same value. This can be used to avoid UI refreshing -bool Shortcut::SetKey(const DWORD& input) +bool Shortcut::SetKey(const DWORD input) { // Since there isn't a key for a common Win key we use the key code defined by us if (input == CommonSharedConstants::VK_WIN_BOTH) @@ -394,7 +394,7 @@ bool Shortcut::SetKey(const DWORD& input) } // Function to reset the state of a shortcut key based on the passed key code argument. Since there is no VK_WIN code, use the second argument for setting common win key. -void Shortcut::ResetKey(const DWORD& input) +void Shortcut::ResetKey(const DWORD input) { // Since there isn't a key for a common Win key this is handled with a separate argument. if (input == CommonSharedConstants::VK_WIN_BOTH || input == VK_LWIN || input == VK_RWIN) @@ -415,7 +415,7 @@ void Shortcut::ResetKey(const DWORD& input) } else { - actionKey = NULL; + actionKey = {}; } } diff --git a/src/modules/keyboardmanager/common/Shortcut.h b/src/modules/keyboardmanager/common/Shortcut.h index 16a0d0fd6c..f48d321764 100644 --- a/src/modules/keyboardmanager/common/Shortcut.h +++ b/src/modules/keyboardmanager/common/Shortcut.h @@ -1,5 +1,8 @@ #pragma once #include "ModifierKey.h" + +#include +#include #include namespace KeyboardManagerInput @@ -14,91 +17,34 @@ private: // Function to split a wstring based on a delimiter and return a vector of split strings std::vector splitwstring(const std::wstring& input, wchar_t delimiter); -public: - ModifierKey winKey; - ModifierKey ctrlKey; - ModifierKey altKey; - ModifierKey shiftKey; - DWORD actionKey; - - // By default create an empty shortcut - Shortcut() : - winKey(ModifierKey::Disabled), ctrlKey(ModifierKey::Disabled), altKey(ModifierKey::Disabled), shiftKey(ModifierKey::Disabled), actionKey(NULL) + inline auto comparator() const { + return std::make_tuple(winKey, ctrlKey, altKey, shiftKey, actionKey); } +public: + ModifierKey winKey = ModifierKey::Disabled; + ModifierKey ctrlKey = ModifierKey::Disabled; + ModifierKey altKey = ModifierKey::Disabled; + ModifierKey shiftKey = ModifierKey::Disabled; + DWORD actionKey = {}; + + Shortcut() = default; + // Constructor to initialize Shortcut from it's virtual key code string representation. Shortcut(const std::wstring& shortcutVK); // Constructor to initialize shortcut from a list of keys Shortcut(const std::vector& keys); - // == operator - inline bool operator==(const Shortcut& sc) const + inline friend auto operator<=>(const Shortcut& lhs, const Shortcut& rhs) noexcept { - return (winKey == sc.winKey && ctrlKey == sc.ctrlKey && altKey == sc.altKey && shiftKey == sc.shiftKey && actionKey == sc.actionKey); + return lhs.comparator() <=> rhs.comparator(); } - // Less than operator must be defined to use with std::map. - inline bool operator<(const Shortcut& sc) const + inline friend bool operator==(const Shortcut& lhs, const Shortcut& rhs) noexcept { - // Compare win key first - if (winKey < sc.winKey) - { - return true; - } - else if (winKey > sc.winKey) - { - return false; - } - else - { - // If win key is equal, then compare ctrl key - if (ctrlKey < sc.ctrlKey) - { - return true; - } - else if (ctrlKey > sc.ctrlKey) - { - return false; - } - else - { - // If ctrl key is equal, then compare alt key - if (altKey < sc.altKey) - { - return true; - } - else if (altKey > sc.altKey) - { - return false; - } - else - { - // If alt key is equal, then compare shift key - if (shiftKey < sc.shiftKey) - { - return true; - } - else if (shiftKey > sc.shiftKey) - { - return false; - } - else - { - // If shift key is equal, then compare action key - if (actionKey < sc.actionKey) - { - return true; - } - else - { - return false; - } - } - } - } - } + return lhs.comparator() == rhs.comparator(); } // Function to return the number of keys in the shortcut @@ -126,22 +72,22 @@ public: DWORD GetShiftKey() const; // Function to check if the input key matches the win key expected in the shortcut - bool CheckWinKey(const DWORD& input) const; + bool CheckWinKey(const DWORD input) const; // Function to check if the input key matches the ctrl key expected in the shortcut - bool CheckCtrlKey(const DWORD& input) const; + bool CheckCtrlKey(const DWORD input) const; // Function to check if the input key matches the alt key expected in the shortcut - bool CheckAltKey(const DWORD& input) const; + bool CheckAltKey(const DWORD input) const; // Function to check if the input key matches the shift key expected in the shortcut - bool CheckShiftKey(const DWORD& input) const; + bool CheckShiftKey(const DWORD input) const; // Function to set a key in the shortcut based on the passed key code argument. Returns false if it is already set to the same value. This can be used to avoid UI refreshing - bool SetKey(const DWORD& input); + bool SetKey(const DWORD input); // Function to reset the state of a shortcut key based on the passed key code argument - void ResetKey(const DWORD& input); + void ResetKey(const DWORD input); // Function to return the string representation of the shortcut in virtual key codes appended in a string by ";" separator. winrt::hstring ToHstringVK() const;