[Keyboard Manager] Added in Shortcut to Key and Key to Shortcut remapping (#5070)

* Added union class

* Added key to shortcut backend implementation

* Added tests

* Added tests for CapsLock/modifier workaround for key to shortcut

* Added correct JSON loading step

* Cleaned shortcut remap code to use helper function for modifier keys

* Removed RemapKey class

* Enable Key to Shortcut in UI along with Type Shortcut in Remap key window

* Fixed orphaning and unsuccessful remap dialog

* Fixed column width

* Renamed second type key button

* Fixed Type Shortcut issues

* Fixed shortcut to key backend logic and manually tested most scenarios

* Added s2k in UI, manually verified its working

* Added one more k2s test

* Added tests for s2k

* Added tests for Caps Lock workaround in shortcut remaps

* Fixed formatting

* Fixed formatting

* Removed safety code since it can cause issues with code generated key up events

* Added test for key up scenario

* Tweaked warning text

* Tweaked text

* Tweaked text to fit in two lines

* telemetry additions
This commit is contained in:
Arjun Balgovind
2020-07-23 16:43:49 -07:00
committed by GitHub
parent 53c4c6cbb8
commit ff1e04b957
32 changed files with 2322 additions and 686 deletions

View File

@@ -138,13 +138,13 @@ namespace KeyboardManagerHelper
case ErrorType::NoError:
return L"Remapping successful";
case ErrorType::SameKeyPreviouslyMapped:
return L"Cannot remap a key more than once";
return L"Cannot remap a key more than once for the same target app";
case ErrorType::MapToSameKey:
return L"Cannot remap a key to itself";
case ErrorType::ConflictingModifierKey:
return L"Cannot remap this key as it conflicts with another remapped key";
case ErrorType::SameShortcutPreviouslyMapped:
return L"Cannot remap a shortcut more than once";
return L"Cannot remap a shortcut more than once for the same target app";
case ErrorType::MapToSameShortcut:
return L"Cannot remap a shortcut to itself";
case ErrorType::ConflictingModifierShortcut:
@@ -215,7 +215,7 @@ namespace KeyboardManagerHelper
{
std::wstring process_path = get_process_path(current_window_handle);
process_name = process_path;
// Get process name from path
PathStripPath(&process_path[0]);
@@ -248,4 +248,81 @@ namespace KeyboardManagerHelper
return process_name;
}
// 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 modfifier or if the shortcutToBeSent's modifier matches the keyToBeReleased
void SetModifierKeyEvents(const Shortcut& shortcutToBeSent, const ModifierKey& winKeyInvoked, LPINPUT keyEventArray, int& index, 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 modfifier 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)))
{
KeyboardManagerHelper::SetKeyEvent(keyEventArray, index, INPUT_KEYBOARD, (WORD)shortcutToBeSent.GetWinKey(winKeyInvoked), 0, extraInfoFlag);
index++;
}
if (shortcutToBeSent.GetCtrlKey() != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetCtrlKey() != shortcutToCompare.GetCtrlKey()) && (keyToBeReleased == NULL || !shortcutToBeSent.CheckCtrlKey(keyToBeReleased)))
{
KeyboardManagerHelper::SetKeyEvent(keyEventArray, index, INPUT_KEYBOARD, (WORD)shortcutToBeSent.GetCtrlKey(), 0, extraInfoFlag);
index++;
}
if (shortcutToBeSent.GetAltKey() != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetAltKey() != shortcutToCompare.GetAltKey()) && (keyToBeReleased == NULL || !shortcutToBeSent.CheckAltKey(keyToBeReleased)))
{
KeyboardManagerHelper::SetKeyEvent(keyEventArray, index, INPUT_KEYBOARD, (WORD)shortcutToBeSent.GetAltKey(), 0, extraInfoFlag);
index++;
}
if (shortcutToBeSent.GetShiftKey() != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetShiftKey() != shortcutToCompare.GetShiftKey()) && (keyToBeReleased == NULL || !shortcutToBeSent.CheckShiftKey(keyToBeReleased)))
{
KeyboardManagerHelper::SetKeyEvent(keyEventArray, index, INPUT_KEYBOARD, (WORD)shortcutToBeSent.GetShiftKey(), 0, extraInfoFlag);
index++;
}
}
// If key up is to be sent, send in the order Shift, Alt, Ctrl, Win
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 modfifier or if the shortcutToBeSent's modifier matches the keyToBeReleased
if (shortcutToBeSent.GetShiftKey() != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetShiftKey() != shortcutToCompare.GetShiftKey() || shortcutToBeSent.CheckShiftKey(keyToBeReleased)))
{
KeyboardManagerHelper::SetKeyEvent(keyEventArray, index, INPUT_KEYBOARD, (WORD)shortcutToBeSent.GetShiftKey(), KEYEVENTF_KEYUP, extraInfoFlag);
index++;
}
if (shortcutToBeSent.GetAltKey() != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetAltKey() != shortcutToCompare.GetAltKey() || shortcutToBeSent.CheckAltKey(keyToBeReleased)))
{
KeyboardManagerHelper::SetKeyEvent(keyEventArray, index, INPUT_KEYBOARD, (WORD)shortcutToBeSent.GetAltKey(), KEYEVENTF_KEYUP, extraInfoFlag);
index++;
}
if (shortcutToBeSent.GetCtrlKey() != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetCtrlKey() != shortcutToCompare.GetCtrlKey() || shortcutToBeSent.CheckCtrlKey(keyToBeReleased)))
{
KeyboardManagerHelper::SetKeyEvent(keyEventArray, index, INPUT_KEYBOARD, (WORD)shortcutToBeSent.GetCtrlKey(), KEYEVENTF_KEYUP, extraInfoFlag);
index++;
}
if (shortcutToBeSent.GetWinKey(winKeyInvoked) != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetWinKey(winKeyInvoked) != shortcutToCompare.GetWinKey(winKeyInvoked) || shortcutToBeSent.CheckWinKey(keyToBeReleased)))
{
KeyboardManagerHelper::SetKeyEvent(keyEventArray, index, INPUT_KEYBOARD, (WORD)shortcutToBeSent.GetWinKey(winKeyInvoked), KEYEVENTF_KEYUP, extraInfoFlag);
index++;
}
}
}
// Function to filter the key codes for artificial key codes
DWORD FilterArtificialKeys(const DWORD& key)
{
switch (key)
{
// If a key is remapped to VK_WIN_BOTH, we send VK_LWIN instead
case CommonSharedConstants::VK_WIN_BOTH:
return VK_LWIN;
}
return key;
}
// Function to sort a vector of shortcuts based on it's size
void SortShortcutVectorBasedOnSize(std::vector<Shortcut>& shortcutVector)
{
std::sort(shortcutVector.begin(), shortcutVector.end(), [](Shortcut first, Shortcut second) {
return first.Size() > second.Size();
});
}
}

View File

@@ -1,4 +1,6 @@
#pragma once
#include "Shortcut.h"
namespace winrt
{
struct hstring;
@@ -88,4 +90,13 @@ namespace KeyboardManagerHelper
// Function to return the executable name of the application in focus
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 modfifier or if the shortcutToBeSent's modifier matches the keyToBeReleased
void SetModifierKeyEvents(const Shortcut& shortcutToBeSent, const ModifierKey& winKeyInvoked, LPINPUT keyEventArray, int& index, bool isKeyDown, ULONG_PTR extraInfoFlag, const Shortcut& shortcutToCompare = Shortcut(), const DWORD& keyToBeReleased = NULL);
// Function to filter the key codes for artificial key codes
DWORD FilterArtificialKeys(const DWORD& key);
// Function to sort a vector of shortcuts based on it's size
void SortShortcutVectorBasedOnSize(std::vector<Shortcut>& shortcutVector);
}

View File

@@ -121,6 +121,7 @@
<ClCompile Include="trace.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="ModifierKey.h" />
<ClInclude Include="InputInterface.h" />
<ClInclude Include="Helpers.h" />
<ClInclude Include="KeyboardManagerConstants.h" />

View File

@@ -65,6 +65,9 @@
<ClInclude Include="InputInterface.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ModifierKey.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />

View File

@@ -96,7 +96,7 @@ namespace KeyboardManagerConstants
// String constant for the default app name in Remap shortcuts
inline const std::wstring DefaultAppName = L"All Apps";
// String constant to represent no activated application in app-specific shortcuts
inline const std::wstring NoActivatedApp = L"";
}

View File

@@ -1,7 +1,10 @@
#include "pch.h"
#include "KeyboardManagerState.h"
#include "Shortcut.h"
#include "RemapShortcut.h"
#include <../common/settings_helpers.h>
#include "KeyDelay.h"
#include "Helpers.h"
// Constructor
KeyboardManagerState::KeyboardManagerState() :
@@ -103,6 +106,7 @@ void KeyboardManagerState::ClearOSLevelShortcuts()
{
std::lock_guard<std::mutex> lock(osLevelShortcutReMap_mutex);
osLevelShortcutReMap.clear();
osLevelShortcutReMapSortedKeys.clear();
}
// Function to clear the Keys remapping table.
@@ -117,10 +121,11 @@ void KeyboardManagerState::ClearAppSpecificShortcuts()
{
std::lock_guard<std::mutex> lock(appSpecificShortcutReMap_mutex);
appSpecificShortcutReMap.clear();
appSpecificShortcutReMapSortedKeys.clear();
}
// Function to add a new OS level shortcut remapping
bool KeyboardManagerState::AddOSLevelShortcut(const Shortcut& originalSC, const Shortcut& newSC)
bool KeyboardManagerState::AddOSLevelShortcut(const Shortcut& originalSC, const std::variant<DWORD, Shortcut>& newSC)
{
std::lock_guard<std::mutex> lock(osLevelShortcutReMap_mutex);
@@ -132,11 +137,14 @@ bool KeyboardManagerState::AddOSLevelShortcut(const Shortcut& originalSC, const
}
osLevelShortcutReMap[originalSC] = RemapShortcut(newSC);
osLevelShortcutReMapSortedKeys.push_back(originalSC);
KeyboardManagerHelper::SortShortcutVectorBasedOnSize(osLevelShortcutReMapSortedKeys);
return true;
}
// Function to add a new OS level shortcut remapping
bool KeyboardManagerState::AddSingleKeyRemap(const DWORD& originalKey, const DWORD& newRemapKey)
// Function to add a new single key to key/shortcut remapping
bool KeyboardManagerState::AddSingleKeyRemap(const DWORD& originalKey, const std::variant<DWORD, Shortcut>& newRemapKey)
{
std::lock_guard<std::mutex> lock(singleKeyReMap_mutex);
@@ -152,28 +160,34 @@ bool KeyboardManagerState::AddSingleKeyRemap(const DWORD& originalKey, const DWO
}
// Function to add a new App specific shortcut remapping
bool KeyboardManagerState::AddAppSpecificShortcut(const std::wstring& app, const Shortcut& originalSC, const Shortcut& newSC)
bool KeyboardManagerState::AddAppSpecificShortcut(const std::wstring& app, const Shortcut& originalSC, const std::variant<DWORD, Shortcut>& newSC)
{
std::lock_guard<std::mutex> lock(appSpecificShortcutReMap_mutex);
// Check if there are any app specific shortcuts for this app
auto appIt = appSpecificShortcutReMap.find(app);
if (appIt != appSpecificShortcutReMap.end())
{
// Check if the shortcut is already remapped
auto shortcutIt = appSpecificShortcutReMap[app].find(originalSC);
if (shortcutIt != appSpecificShortcutReMap[app].end())
{
return false;
}
}
// Convert app name to lower case
std::wstring process_name;
process_name.resize(app.length());
std::transform(app.begin(), app.end(), process_name.begin(), towlower);
// Check if there are any app specific shortcuts for this app
auto appIt = appSpecificShortcutReMap.find(process_name);
if (appIt != appSpecificShortcutReMap.end())
{
// Check if the shortcut is already remapped
auto shortcutIt = appSpecificShortcutReMap[process_name].find(originalSC);
if (shortcutIt != appSpecificShortcutReMap[process_name].end())
{
return false;
}
}
else
{
appSpecificShortcutReMapSortedKeys[process_name] = std::vector<Shortcut>();
}
appSpecificShortcutReMap[process_name][originalSC] = RemapShortcut(newSC);
appSpecificShortcutReMapSortedKeys[process_name].push_back(originalSC);
KeyboardManagerHelper::SortShortcutVectorBasedOnSize(appSpecificShortcutReMapSortedKeys[process_name]);
return true;
}
@@ -349,10 +363,10 @@ KeyboardManagerHelper::KeyboardHookDecision KeyboardManagerState::DetectSingleRe
}
// Function which can be used in HandleKeyboardHookEvent before the os level shortcut remap event to use the UI and suppress events while the remap window is active.
KeyboardManagerHelper::KeyboardHookDecision KeyboardManagerState::DetectShortcutUIBackend(LowlevelKeyboardEvent* data)
KeyboardManagerHelper::KeyboardHookDecision KeyboardManagerState::DetectShortcutUIBackend(LowlevelKeyboardEvent* data, bool isRemapKey)
{
// Check if the detect shortcut UI window has been activated
if (CheckUIState(KeyboardManagerUIState::DetectShortcutWindowActivated))
if ((!isRemapKey && CheckUIState(KeyboardManagerUIState::DetectShortcutWindowActivated)) || (isRemapKey && CheckUIState(KeyboardManagerUIState::DetectShortcutWindowInEditKeyboardWindowActivated)))
{
if (HandleKeyDelayEvent(data))
{
@@ -375,7 +389,7 @@ KeyboardManagerHelper::KeyboardHookDecision KeyboardManagerState::DetectShortcut
}
// If the detect shortcut UI window is not activated, then clear the shortcut buffer if it isn't empty
else
else if (!CheckUIState(KeyboardManagerUIState::DetectShortcutWindowActivated) && !CheckUIState(KeyboardManagerUIState::DetectShortcutWindowInEditKeyboardWindowActivated))
{
std::lock_guard<std::mutex> lock(detectedShortcut_mutex);
if (!detectedShortcut.IsEmpty())
@@ -385,7 +399,7 @@ KeyboardManagerHelper::KeyboardHookDecision KeyboardManagerState::DetectShortcut
}
// If the settings window is up, shortcut remappings should not be applied, but we should not suppress events in the hook
if (CheckUIState(KeyboardManagerUIState::EditShortcutsWindowActivated))
if (!isRemapKey && (CheckUIState(KeyboardManagerUIState::EditShortcutsWindowActivated)) || (isRemapKey && uiState == KeyboardManagerUIState::DetectShortcutWindowInEditKeyboardWindowActivated))
{
return KeyboardManagerHelper::KeyboardHookDecision::SkipHook;
}
@@ -452,7 +466,18 @@ bool KeyboardManagerState::SaveConfigToFile()
{
json::JsonObject keys;
keys.SetNamedValue(KeyboardManagerConstants::OriginalKeysSettingName, json::value(winrt::to_hstring((unsigned int)it.first)));
keys.SetNamedValue(KeyboardManagerConstants::NewRemapKeysSettingName, json::value(winrt::to_hstring((unsigned int)it.second)));
// For key to key remapping
if (it.second.index() == 0)
{
keys.SetNamedValue(KeyboardManagerConstants::NewRemapKeysSettingName, json::value(winrt::to_hstring((unsigned int)std::get<DWORD>(it.second))));
}
// For key to shortcut remapping
else
{
keys.SetNamedValue(KeyboardManagerConstants::NewRemapKeysSettingName, json::value(std::get<Shortcut>(it.second).ToHstringVK()));
}
inProcessRemapKeysArray.Append(keys);
}
@@ -463,12 +488,23 @@ bool KeyboardManagerState::SaveConfigToFile()
{
json::JsonObject keys;
keys.SetNamedValue(KeyboardManagerConstants::OriginalKeysSettingName, json::value(it.first.ToHstringVK()));
keys.SetNamedValue(KeyboardManagerConstants::NewRemapKeysSettingName, json::value(it.second.targetShortcut.ToHstringVK()));
// For shortcut to key remapping
if (it.second.targetShortcut.index() == 0)
{
keys.SetNamedValue(KeyboardManagerConstants::NewRemapKeysSettingName, json::value(winrt::to_hstring((unsigned int)std::get<DWORD>(it.second.targetShortcut))));
}
// For shortcut to shortcut remapping
else
{
keys.SetNamedValue(KeyboardManagerConstants::NewRemapKeysSettingName, json::value(std::get<Shortcut>(it.second.targetShortcut).ToHstringVK()));
}
globalRemapShortcutsArray.Append(keys);
}
lockOsLevelShortcutReMap.unlock();
std::unique_lock<std::mutex> lockAppSpecificShortcutReMap(appSpecificShortcutReMap_mutex);
for (const auto& itApp : appSpecificShortcutReMap)
{
@@ -477,12 +513,23 @@ bool KeyboardManagerState::SaveConfigToFile()
{
json::JsonObject keys;
keys.SetNamedValue(KeyboardManagerConstants::OriginalKeysSettingName, json::value(itKeys.first.ToHstringVK()));
keys.SetNamedValue(KeyboardManagerConstants::NewRemapKeysSettingName, json::value(itKeys.second.targetShortcut.ToHstringVK()));
// For shortcut to key remapping
if (itKeys.second.targetShortcut.index() == 0)
{
keys.SetNamedValue(KeyboardManagerConstants::NewRemapKeysSettingName, json::value(winrt::to_hstring((unsigned int)std::get<DWORD>(itKeys.second.targetShortcut))));
}
// For shortcut to shortcut remapping
else
{
keys.SetNamedValue(KeyboardManagerConstants::NewRemapKeysSettingName, json::value(std::get<Shortcut>(itKeys.second.targetShortcut).ToHstringVK()));
}
keys.SetNamedValue(KeyboardManagerConstants::TargetAppSettingName, json::value(itApp.first));
appSpecificRemapShortcutsArray.Append(keys);
appSpecificRemapShortcutsArray.Append(keys);
}
}
lockAppSpecificShortcutReMap.unlock();

View File

@@ -1,15 +1,20 @@
#pragma once
#include "Helpers.h"
#include "Shortcut.h"
#include "RemapShortcut.h"
#include <mutex>
#include "KeyboardManagerConstants.h"
#include "../common/keyboard_layout.h"
#include <functional>
#include <interface/lowlevel_keyboard_event_data.h>
#include <variant>
#include "Shortcut.h"
#include "RemapShortcut.h"
class KeyDelay;
namespace KeyboardManagerHelper
{
enum class KeyboardHookDecision;
}
namespace winrt::Windows::UI::Xaml::Controls
{
struct StackPanel;
@@ -22,6 +27,8 @@ enum class KeyboardManagerUIState
Deactivated,
// If set to this value then the detect key window is currently active and it requires a hook
DetectSingleKeyRemapWindowActivated,
// If set to this value then the detect shortcut window in edit keyboard window is currently active and it requires a hook
DetectShortcutWindowInEditKeyboardWindowActivated,
// If set to this value then the edit keyboard window is currently active and remaps should not be applied
EditKeyboardWindowActivated,
// If set to this value then the detect shortcut window is currently active and it requires a hook
@@ -84,7 +91,7 @@ public:
// The map members and their mutexes are left as public since the maps are used extensively in dllmain.cpp.
// Maps which store the remappings for each of the features. The bool fields should be initialized to false. They are used to check the current state of the shortcut (i.e is that particular shortcut currently pressed down or not).
// Stores single key remappings
std::unordered_map<DWORD, DWORD> singleKeyReMap;
std::unordered_map<DWORD, std::variant<DWORD, Shortcut>> singleKeyReMap;
std::mutex singleKeyReMap_mutex;
// Stores keys which need to be changed from toggle behavior to modifier behavior. Eg. Caps Lock
@@ -93,10 +100,12 @@ public:
// Stores the os level shortcut remappings
std::map<Shortcut, RemapShortcut> osLevelShortcutReMap;
std::vector<Shortcut> osLevelShortcutReMapSortedKeys;
std::mutex osLevelShortcutReMap_mutex;
// Stores the app-specific shortcut remappings. Maps application name to the shortcut map
std::map<std::wstring, std::map<Shortcut, RemapShortcut>> appSpecificShortcutReMap;
std::map<std::wstring, std::vector<Shortcut>> appSpecificShortcutReMapSortedKeys;
std::mutex appSpecificShortcutReMap_mutex;
// Stores the keyboard layout
@@ -129,14 +138,14 @@ public:
// Function to clear the App specific shortcut remapping table
void ClearAppSpecificShortcuts();
// Function to add a new single key remapping
bool AddSingleKeyRemap(const DWORD& originalKey, const DWORD& newRemapKey);
// Function to add a new single key to key remapping
bool AddSingleKeyRemap(const DWORD& originalKey, const std::variant<DWORD, Shortcut>& newRemapKey);
// Function to add a new OS level shortcut remapping
bool AddOSLevelShortcut(const Shortcut& originalSC, const Shortcut& newSC);
bool AddOSLevelShortcut(const Shortcut& originalSC, const std::variant<DWORD, Shortcut>& newSC);
// Function to add a new App specific level shortcut remapping
bool AddAppSpecificShortcut(const std::wstring& app, const Shortcut& originalSC, const Shortcut& newSC);
bool AddAppSpecificShortcut(const std::wstring& app, const Shortcut& originalSC, const std::variant<DWORD, Shortcut>& newSC);
// Function to set the textblock of the detect shortcut UI so that it can be accessed by the hook
void ConfigureDetectShortcutUI(const winrt::Windows::UI::Xaml::Controls::StackPanel& textBlock1, const winrt::Windows::UI::Xaml::Controls::StackPanel& textBlock2);
@@ -160,7 +169,7 @@ public:
KeyboardManagerHelper::KeyboardHookDecision DetectSingleRemapKeyUIBackend(LowlevelKeyboardEvent* data);
// Function which can be used in HandleKeyboardHookEvent before the os level shortcut remap event to use the UI and suppress events while the remap window is active.
KeyboardManagerHelper::KeyboardHookDecision DetectShortcutUIBackend(LowlevelKeyboardEvent* data);
KeyboardManagerHelper::KeyboardHookDecision DetectShortcutUIBackend(LowlevelKeyboardEvent* data, bool isRemapKey);
// Add a KeyDelay object to get delayed key presses events for a given virtual key
// NOTE: this will throw an exception if a virtual key is registered twice.

View File

@@ -0,0 +1,10 @@
#pragma once
// Enum type to store different states of the win key
enum class ModifierKey
{
Disabled,
Left,
Right,
Both
};

View File

@@ -1,21 +1,22 @@
#pragma once
#include "Shortcut.h"
#include <variant>
// This class stores all the variables associated with each shortcut remapping
class RemapShortcut
{
public:
Shortcut targetShortcut;
std::variant<DWORD, Shortcut> targetShortcut;
bool isShortcutInvoked;
ModifierKey winKeyInvoked;
RemapShortcut(const Shortcut& sc) :
RemapShortcut(const std::variant<DWORD, Shortcut>& sc) :
targetShortcut(sc), isShortcutInvoked(false), winKeyInvoked(ModifierKey::Disabled)
{
}
RemapShortcut() :
isShortcutInvoked(false), winKeyInvoked(ModifierKey::Disabled)
targetShortcut(Shortcut()), isShortcutInvoked(false), winKeyInvoked(ModifierKey::Disabled)
{
}
};

View File

@@ -1,5 +1,5 @@
#pragma once
#include "ModifierKey.h"
class InputInterface;
class LayoutMap;
namespace KeyboardManagerHelper
@@ -7,15 +7,6 @@ namespace KeyboardManagerHelper
enum class ErrorType;
}
// Enum type to store different states of the win key
enum class ModifierKey
{
Disabled,
Left,
Right,
Both
};
class Shortcut
{
private:

View File

@@ -30,34 +30,40 @@ void Trace::EnableKeyboardManager(const bool enabled) noexcept
}
// Log number of key remaps when the user uses Edit Keyboard and saves settings
void Trace::KeyRemapCount(const DWORD count) noexcept
void Trace::KeyRemapCount(const DWORD keyToKeyCount, const DWORD keyToShortcutCount) noexcept
{
TraceLoggingWrite(
g_hProvider,
"KeyboardManager_KeyRemapCount",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
TraceLoggingValue(count, "KeyRemapCount"));
TraceLoggingValue(keyToKeyCount + keyToShortcutCount, "KeyRemapCount"),
TraceLoggingValue(keyToKeyCount, "KeyToKeyRemapCount"),
TraceLoggingValue(keyToShortcutCount, "KeyToShortcutRemapCount"));
}
// Log number of os level shortcut remaps when the user uses Edit Shortcuts and saves settings
void Trace::OSLevelShortcutRemapCount(const DWORD count) noexcept
void Trace::OSLevelShortcutRemapCount(const DWORD shortcutToShortcutCount, const DWORD shortcutToKeyCount) noexcept
{
TraceLoggingWrite(
g_hProvider,
"KeyboardManager_OSLevelShortcutRemapCount",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
TraceLoggingValue(count, "OSLevelShortcutRemapCount"));
TraceLoggingValue(shortcutToShortcutCount + shortcutToKeyCount, "OSLevelShortcutRemapCount"),
TraceLoggingValue(shortcutToShortcutCount, "OSLevelShortcutToShortcutRemapCount"),
TraceLoggingValue(shortcutToKeyCount, "OSLevelShortcutToKeyRemapCount"));
}
// Log number of app specific shortcut remaps when the user uses Edit Shortcuts and saves settings
void Trace::AppSpecificShortcutRemapCount(const DWORD count) noexcept
void Trace::AppSpecificShortcutRemapCount(const DWORD shortcutToShortcutCount, const DWORD shortcutToKeyCount) noexcept
{
TraceLoggingWrite(
g_hProvider,
"KeyboardManager_AppSpecificShortcutRemapCount",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
TraceLoggingValue(count, "AppSpecificShortcutRemapCount"));
TraceLoggingValue(shortcutToShortcutCount + shortcutToKeyCount, "AppSpecificShortcutRemapCount"),
TraceLoggingValue(shortcutToShortcutCount, "AppSpecificShortcutToShortcutRemapCount"),
TraceLoggingValue(shortcutToKeyCount, "AppSpecificShortcutToKeyRemapCount"));
}

View File

@@ -10,11 +10,11 @@ public:
static void EnableKeyboardManager(const bool enabled) noexcept;
// Log number of key remaps when the user uses Edit Keyboard and saves settings
static void KeyRemapCount(const DWORD count) noexcept;
static void KeyRemapCount(const DWORD keyToKeyCount, const DWORD keyToShortcutCount) noexcept;
// Log number of os level shortcut remaps when the user uses Edit Shortcuts and saves settings
static void OSLevelShortcutRemapCount(const DWORD count) noexcept;
static void OSLevelShortcutRemapCount(const DWORD shortcutToShortcutCount, const DWORD shortcutToKeyCount) noexcept;
// Log number of app specific shortcut remaps when the user uses Edit Shortcuts and saves settings
static void AppSpecificShortcutRemapCount(const DWORD count) noexcept;
static void AppSpecificShortcutRemapCount(const DWORD shortcutToShortcutCount, const DWORD shortcutToKeyCount) noexcept;
};