Refactor Shortcut remaps to distinguish modifiers and action keys (#1927)
* Added unique lock mutexes for thread safety * Fixed a bug in detect key logic * Changed dword to word * Added early unlock statements to fix issue with shortcut guide * Fixed type conversion warnings * Migrated detect shortcut window to use Shortcut class * made changes in Apply button logic * Revert thread safety changes * refactored code works on the UI side * Refactored remapping code to use new Shortcut class * Refactored to SetKeyEvent function * Moved function to cpp file and added more comments * Refactored map variable and handled common Win key * Remove debug code * Change arguments to const references
This commit is contained in:
parent
cf54a4919b
commit
52c12731cb
14 changed files with 1261 additions and 304 deletions
|
@ -93,11 +93,15 @@
|
|||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="RemapShortcut.cpp" />
|
||||
<ClCompile Include="Shortcut.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Helpers.h" />
|
||||
<ClInclude Include="KeyboardManagerState.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="RemapShortcut.h" />
|
||||
<ClInclude Include="Shortcut.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\common\common.vcxproj">
|
||||
|
|
|
@ -24,6 +24,12 @@
|
|||
<ClCompile Include="pch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Shortcut.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="RemapShortcut.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="KeyboardManagerState.h">
|
||||
|
@ -35,5 +41,11 @@
|
|||
<ClInclude Include="pch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Shortcut.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="RemapShortcut.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -55,7 +55,7 @@ void KeyboardManagerState::ResetUIState()
|
|||
currentShortcutTextBlock_lock.unlock();
|
||||
|
||||
std::unique_lock<std::mutex> detectedShortcut_lock(detectedShortcut_mutex);
|
||||
detectedShortcut.clear();
|
||||
detectedShortcut.Reset();
|
||||
detectedShortcut_lock.unlock();
|
||||
|
||||
// Reset all the single key remap UI stored variables.
|
||||
|
@ -83,7 +83,7 @@ void KeyboardManagerState::ClearSingleKeyRemaps()
|
|||
}
|
||||
|
||||
// Function to add a new OS level shortcut remapping
|
||||
bool KeyboardManagerState::AddOSLevelShortcut(const std::vector<DWORD>& originalSC, const std::vector<WORD>& newSC)
|
||||
bool KeyboardManagerState::AddOSLevelShortcut(const Shortcut& originalSC, const Shortcut& newSC)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(osLevelShortcutReMap_mutex);
|
||||
|
||||
|
@ -94,12 +94,12 @@ bool KeyboardManagerState::AddOSLevelShortcut(const std::vector<DWORD>& original
|
|||
return false;
|
||||
}
|
||||
|
||||
osLevelShortcutReMap[originalSC] = std::make_pair(newSC, false);
|
||||
osLevelShortcutReMap[originalSC] = RemapShortcut(newSC);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Function to add a new OS level shortcut remapping
|
||||
bool KeyboardManagerState::AddSingleKeyRemap(const DWORD& originalKey, const WORD& newRemapKey)
|
||||
bool KeyboardManagerState::AddSingleKeyRemap(const DWORD& originalKey, const DWORD& newRemapKey)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(singleKeyReMap_mutex);
|
||||
|
||||
|
@ -138,7 +138,7 @@ void KeyboardManagerState::UpdateDetectShortcutUI()
|
|||
}
|
||||
|
||||
std::unique_lock<std::mutex> detectedShortcut_lock(detectedShortcut_mutex);
|
||||
hstring shortcutString = convertVectorToHstring<DWORD>(detectedShortcut);
|
||||
hstring shortcutString = detectedShortcut.ToHstring();
|
||||
detectedShortcut_lock.unlock();
|
||||
|
||||
// Since this function is invoked from the back-end thread, in order to update the UI the dispatcher must be used.
|
||||
|
@ -167,15 +167,12 @@ void KeyboardManagerState::UpdateDetectSingleKeyRemapUI()
|
|||
}
|
||||
|
||||
// Function to return the currently detected shortcut which is displayed on the UI
|
||||
std::vector<DWORD> KeyboardManagerState::GetDetectedShortcut()
|
||||
Shortcut KeyboardManagerState::GetDetectedShortcut()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(currentShortcutTextBlock_mutex);
|
||||
hstring detectedShortcutString = currentShortcutTextBlock.Text();
|
||||
lock.unlock();
|
||||
|
||||
std::wstring detectedShortcutWstring = detectedShortcutString.c_str();
|
||||
std::vector<std::wstring> detectedShortcutVector = splitwstring(detectedShortcutWstring, L' ');
|
||||
return convertWStringVectorToIntegerVector<DWORD>(detectedShortcutVector);
|
||||
return Shortcut::CreateShortcut(detectedShortcutString);
|
||||
}
|
||||
|
||||
// Function to return the currently detected remap key which is displayed on the UI
|
||||
|
@ -227,12 +224,13 @@ bool KeyboardManagerState::DetectShortcutUIBackend(LowlevelKeyboardEvent* data)
|
|||
// Add the key if it is pressed down
|
||||
if (data->wParam == WM_KEYDOWN || data->wParam == WM_SYSKEYDOWN)
|
||||
{
|
||||
// Set the new key and store if a change occured
|
||||
std::unique_lock<std::mutex> lock(detectedShortcut_mutex);
|
||||
if (std::find(detectedShortcut.begin(), detectedShortcut.end(), data->lParam->vkCode) == detectedShortcut.end())
|
||||
{
|
||||
detectedShortcut.push_back(data->lParam->vkCode);
|
||||
lock.unlock();
|
||||
bool updateUI = detectedShortcut.SetKey(data->lParam->vkCode);
|
||||
lock.unlock();
|
||||
|
||||
if (updateUI)
|
||||
{
|
||||
// Update the UI. This function is called here because it should store the set of keys pressed till the last key which was pressed down.
|
||||
UpdateDetectShortcutUI();
|
||||
}
|
||||
|
@ -241,7 +239,7 @@ bool KeyboardManagerState::DetectShortcutUIBackend(LowlevelKeyboardEvent* data)
|
|||
else if (data->wParam == WM_KEYUP || data->wParam == WM_SYSKEYUP)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(detectedShortcut_mutex);
|
||||
detectedShortcut.erase(std::remove(detectedShortcut.begin(), detectedShortcut.end(), data->lParam->vkCode), detectedShortcut.end());
|
||||
detectedShortcut.ResetKey(data->lParam->vkCode);
|
||||
}
|
||||
|
||||
// Suppress the keyboard event
|
||||
|
@ -252,9 +250,9 @@ bool KeyboardManagerState::DetectShortcutUIBackend(LowlevelKeyboardEvent* data)
|
|||
else
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(detectedShortcut_mutex);
|
||||
if (!detectedShortcut.empty())
|
||||
if (!detectedShortcut.IsEmpty())
|
||||
{
|
||||
detectedShortcut.clear();
|
||||
detectedShortcut.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
#include "Helpers.h"
|
||||
#include "Shortcut.h"
|
||||
#include "RemapShortcut.h"
|
||||
#include <interface/lowlevel_keyboard_event_data.h>
|
||||
#include <mutex>
|
||||
#include <winrt/Windows.UI.Xaml.Controls.h>
|
||||
|
@ -28,8 +30,8 @@ private:
|
|||
HWND currentUIWindow;
|
||||
std::mutex currentUIWindow_mutex;
|
||||
|
||||
// Vector to store the shortcut detected in the detect shortcut UI window. This is used in both the backend and the UI.
|
||||
std::vector<DWORD> detectedShortcut;
|
||||
// Object to store the shortcut detected in the detect shortcut UI window. This is used in both the backend and the UI.
|
||||
Shortcut detectedShortcut;
|
||||
std::mutex detectedShortcut_mutex;
|
||||
|
||||
// Store detected remap key in the remap UI window. This is used in both the backend and the UI.
|
||||
|
@ -48,7 +50,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 initalised 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, WORD> singleKeyReMap;
|
||||
std::unordered_map<DWORD, DWORD> singleKeyReMap;
|
||||
std::mutex singleKeyReMap_mutex;
|
||||
|
||||
// Stores keys which need to be changed from toggle behaviour to modifier behaviour. Eg. Caps Lock
|
||||
|
@ -56,11 +58,11 @@ public:
|
|||
std::mutex singleKeyToggleToMod_mutex;
|
||||
|
||||
// Stores the os level shortcut remappings
|
||||
std::map<std::vector<DWORD>, std::pair<std::vector<WORD>, bool>> osLevelShortcutReMap;
|
||||
std::map<Shortcut, RemapShortcut> osLevelShortcutReMap;
|
||||
std::mutex osLevelShortcutReMap_mutex;
|
||||
|
||||
// Stores the app-specific shortcut remappings. Maps application name to the shortcut map
|
||||
std::map<std::wstring, std::map<std::vector<DWORD>, std::pair<std::vector<WORD>, bool>>> appSpecificShortcutReMap;
|
||||
std::map<std::wstring, std::map<Shortcut, RemapShortcut>> appSpecificShortcutReMap;
|
||||
std::mutex appSpecificShortcutReMap_mutex;
|
||||
|
||||
// Constructor
|
||||
|
@ -85,10 +87,10 @@ public:
|
|||
void ClearSingleKeyRemaps();
|
||||
|
||||
// Function to add a new single key remapping
|
||||
bool AddSingleKeyRemap(const DWORD& originalKey, const WORD& newRemapKey);
|
||||
bool AddSingleKeyRemap(const DWORD& originalKey, const DWORD& newRemapKey);
|
||||
|
||||
// Function to add a new OS level shortcut remapping
|
||||
bool AddOSLevelShortcut(const std::vector<DWORD>& originalSC, const std::vector<WORD>& newSC);
|
||||
bool AddOSLevelShortcut(const Shortcut& originalSC, const Shortcut& newSC);
|
||||
|
||||
// Function to set the textblock of the detect shortcut UI so that it can be accessed by the hook
|
||||
void ConfigureDetectShortcutUI(const TextBlock& textBlock);
|
||||
|
@ -103,7 +105,7 @@ public:
|
|||
void UpdateDetectSingleKeyRemapUI();
|
||||
|
||||
// Function to return the currently detected shortcut which is displayed on the UI
|
||||
std::vector<DWORD> GetDetectedShortcut();
|
||||
Shortcut GetDetectedShortcut();
|
||||
|
||||
// Function to return the currently detected remap key which is displayed on the UI
|
||||
DWORD GetDetectedSingleRemapKey();
|
||||
|
|
2
src/modules/keyboardmanager/common/RemapShortcut.cpp
Normal file
2
src/modules/keyboardmanager/common/RemapShortcut.cpp
Normal file
|
@ -0,0 +1,2 @@
|
|||
#include "pch.h"
|
||||
#include "RemapShortcut.h"
|
21
src/modules/keyboardmanager/common/RemapShortcut.h
Normal file
21
src/modules/keyboardmanager/common/RemapShortcut.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
#pragma once
|
||||
#include "Shortcut.h"
|
||||
|
||||
// This class stores all the variables associated with each shortcut remapping
|
||||
class RemapShortcut
|
||||
{
|
||||
public:
|
||||
Shortcut targetShortcut;
|
||||
bool isShortcutInvoked;
|
||||
ModifierKey winKeyInvoked;
|
||||
|
||||
RemapShortcut(const Shortcut& sc) :
|
||||
targetShortcut(sc), isShortcutInvoked(false), winKeyInvoked(ModifierKey::Disabled)
|
||||
{
|
||||
}
|
||||
|
||||
RemapShortcut() :
|
||||
isShortcutInvoked(false), winKeyInvoked(ModifierKey::Disabled)
|
||||
{
|
||||
}
|
||||
};
|
787
src/modules/keyboardmanager/common/Shortcut.cpp
Normal file
787
src/modules/keyboardmanager/common/Shortcut.cpp
Normal file
|
@ -0,0 +1,787 @@
|
|||
#include "pch.h"
|
||||
#include "Shortcut.h"
|
||||
|
||||
// Function to return the number of keys in the shortcut
|
||||
int Shortcut::Size() const
|
||||
{
|
||||
int size = 0;
|
||||
if (winKey != ModifierKey::Disabled)
|
||||
{
|
||||
size += 1;
|
||||
}
|
||||
if (ctrlKey != ModifierKey::Disabled)
|
||||
{
|
||||
size += 1;
|
||||
}
|
||||
if (altKey != ModifierKey::Disabled)
|
||||
{
|
||||
size += 1;
|
||||
}
|
||||
if (shiftKey != ModifierKey::Disabled)
|
||||
{
|
||||
size += 1;
|
||||
}
|
||||
if (actionKey != NULL)
|
||||
{
|
||||
size += 1;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
// Function to return true if the shortcut has no keys set
|
||||
bool Shortcut::IsEmpty() const
|
||||
{
|
||||
if (winKey == ModifierKey::Disabled && ctrlKey == ModifierKey::Disabled && altKey == ModifierKey::Disabled && shiftKey == ModifierKey::Disabled && actionKey == NULL)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Function to reset all the keys in the shortcut
|
||||
void Shortcut::Reset()
|
||||
{
|
||||
winKey = ModifierKey::Disabled;
|
||||
ctrlKey = ModifierKey::Disabled;
|
||||
altKey = ModifierKey::Disabled;
|
||||
shiftKey = ModifierKey::Disabled;
|
||||
actionKey = NULL;
|
||||
}
|
||||
|
||||
// Function to return true if the shortcut is valid. A valid shortcut has atleast one modifier, as well as an action key
|
||||
bool Shortcut::IsValidShortcut() const
|
||||
{
|
||||
if (actionKey != NULL)
|
||||
{
|
||||
if (winKey != ModifierKey::Disabled || ctrlKey != ModifierKey::Disabled || altKey != ModifierKey::Disabled || shiftKey != ModifierKey::Disabled)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Function to return the action key
|
||||
DWORD Shortcut::GetActionKey() const
|
||||
{
|
||||
return actionKey;
|
||||
}
|
||||
|
||||
// Function to return the virtual key code of the win key state expected in the shortcut. Argument is used to decide which win key to return in case of both. If the current shortcut doesn't use both win keys then arg is ignored. Return NULL if it is not a part of the shortcut
|
||||
DWORD Shortcut::GetWinKey(const ModifierKey& input) const
|
||||
{
|
||||
if (winKey == ModifierKey::Disabled)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else if (winKey == ModifierKey::Left)
|
||||
{
|
||||
return VK_LWIN;
|
||||
}
|
||||
else if (winKey == ModifierKey::Right)
|
||||
{
|
||||
return VK_RWIN;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Since VK_WIN does not exist if right windows key is to be sent based on the argument, then return VK_RWIN as the win key (since that will be used to release it).
|
||||
if (input == ModifierKey::Right)
|
||||
{
|
||||
return VK_RWIN;
|
||||
}
|
||||
else
|
||||
{
|
||||
//return VK_LWIN by default
|
||||
return VK_LWIN;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
{
|
||||
if (ctrlKey == ModifierKey::Disabled)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else if (ctrlKey == ModifierKey::Left)
|
||||
{
|
||||
return VK_LCONTROL;
|
||||
}
|
||||
else if (ctrlKey == ModifierKey::Right)
|
||||
{
|
||||
return VK_RCONTROL;
|
||||
}
|
||||
else
|
||||
{
|
||||
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
|
||||
{
|
||||
if (altKey == ModifierKey::Disabled)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else if (altKey == ModifierKey::Left)
|
||||
{
|
||||
return VK_LMENU;
|
||||
}
|
||||
else if (altKey == ModifierKey::Right)
|
||||
{
|
||||
return VK_RMENU;
|
||||
}
|
||||
else
|
||||
{
|
||||
return VK_MENU;
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
{
|
||||
if (shiftKey == ModifierKey::Disabled)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else if (shiftKey == ModifierKey::Left)
|
||||
{
|
||||
return VK_LSHIFT;
|
||||
}
|
||||
else if (shiftKey == ModifierKey::Right)
|
||||
{
|
||||
return VK_RSHIFT;
|
||||
}
|
||||
else
|
||||
{
|
||||
return VK_SHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
// Function to check if the input key matches the win key expected in the shortcut
|
||||
bool Shortcut::CheckWinKey(const DWORD& input) const
|
||||
{
|
||||
if (winKey == ModifierKey::Disabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (winKey == ModifierKey::Left)
|
||||
{
|
||||
return (VK_LWIN == input);
|
||||
}
|
||||
else if (winKey == ModifierKey::Right)
|
||||
{
|
||||
return (VK_RWIN == input);
|
||||
}
|
||||
// If ModifierKey::Both then return true if either left or right (VK_WIN does not exist)
|
||||
else
|
||||
{
|
||||
return (VK_LWIN == input) || (VK_RWIN == input);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to check if the input key matches the ctrl key expected in the shortcut
|
||||
bool Shortcut::CheckCtrlKey(const DWORD& input) const
|
||||
{
|
||||
if (ctrlKey == ModifierKey::Disabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (ctrlKey == ModifierKey::Left)
|
||||
{
|
||||
return (VK_LCONTROL == input);
|
||||
}
|
||||
else if (ctrlKey == ModifierKey::Right)
|
||||
{
|
||||
return (VK_RCONTROL == input);
|
||||
}
|
||||
// If ModifierKey::Both then return true if either left or right or common
|
||||
else
|
||||
{
|
||||
return (VK_CONTROL == input) || (VK_LCONTROL == input) || (VK_RCONTROL == input);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to check if the input key matches the alt key expected in the shortcut
|
||||
bool Shortcut::CheckAltKey(const DWORD& input) const
|
||||
{
|
||||
if (altKey == ModifierKey::Disabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (altKey == ModifierKey::Left)
|
||||
{
|
||||
return (VK_LMENU == input);
|
||||
}
|
||||
else if (altKey == ModifierKey::Right)
|
||||
{
|
||||
return (VK_RMENU == input);
|
||||
}
|
||||
// If ModifierKey::Both then return true if either left or right or common
|
||||
else
|
||||
{
|
||||
return (VK_MENU == input) || (VK_LMENU == input) || (VK_RMENU == input);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to check if the input key matches the shift key expected in the shortcut
|
||||
bool Shortcut::CheckShiftKey(const DWORD& input) const
|
||||
{
|
||||
if (shiftKey == ModifierKey::Disabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (shiftKey == ModifierKey::Left)
|
||||
{
|
||||
return (VK_LSHIFT == input);
|
||||
}
|
||||
else if (shiftKey == ModifierKey::Right)
|
||||
{
|
||||
return (VK_RSHIFT == input);
|
||||
}
|
||||
// If ModifierKey::Both then return true if either left or right or common
|
||||
else
|
||||
{
|
||||
return (VK_SHIFT == input) || (VK_LSHIFT == input) || (VK_RSHIFT == input);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to set a key in the shortcut based on the passed key code argument. Since there is no VK_WIN code, use the second argument for setting common win key. If isWinBoth is true then first arg is ignored. 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, const bool& isWinBoth)
|
||||
{
|
||||
// Since there isn't a key for a common Win key this is handled with a separate argument
|
||||
if (isWinBoth)
|
||||
{
|
||||
if (winKey == ModifierKey::Both)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
winKey = ModifierKey::Both;
|
||||
}
|
||||
else if (input == VK_LWIN)
|
||||
{
|
||||
if (winKey == ModifierKey::Left)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
winKey = ModifierKey::Left;
|
||||
}
|
||||
else if (input == VK_RWIN)
|
||||
{
|
||||
if (winKey == ModifierKey::Right)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
winKey = ModifierKey::Right;
|
||||
}
|
||||
else if (input == VK_LCONTROL)
|
||||
{
|
||||
if (ctrlKey == ModifierKey::Left)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
ctrlKey = ModifierKey::Left;
|
||||
}
|
||||
else if (input == VK_RCONTROL)
|
||||
{
|
||||
if (ctrlKey == ModifierKey::Right)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
ctrlKey = ModifierKey::Right;
|
||||
}
|
||||
else if (input == VK_CONTROL)
|
||||
{
|
||||
if (ctrlKey == ModifierKey::Both)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
ctrlKey = ModifierKey::Both;
|
||||
}
|
||||
else if (input == VK_LMENU)
|
||||
{
|
||||
if (altKey == ModifierKey::Left)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
altKey = ModifierKey::Left;
|
||||
}
|
||||
else if (input == VK_RMENU)
|
||||
{
|
||||
if (altKey == ModifierKey::Right)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
altKey = ModifierKey::Right;
|
||||
}
|
||||
else if (input == VK_MENU)
|
||||
{
|
||||
if (altKey == ModifierKey::Both)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
altKey = ModifierKey::Both;
|
||||
}
|
||||
else if (input == VK_LSHIFT)
|
||||
{
|
||||
if (shiftKey == ModifierKey::Left)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
shiftKey = ModifierKey::Left;
|
||||
}
|
||||
else if (input == VK_RSHIFT)
|
||||
{
|
||||
if (shiftKey == ModifierKey::Right)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
shiftKey = ModifierKey::Right;
|
||||
}
|
||||
else if (input == VK_SHIFT)
|
||||
{
|
||||
if (shiftKey == ModifierKey::Both)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
shiftKey = ModifierKey::Both;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (actionKey == input)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
actionKey = input;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 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, const bool& isWinBoth)
|
||||
{
|
||||
// Since there isn't a key for a common Win key this is handled with a separate argument.
|
||||
if (isWinBoth || input == VK_LWIN || input == VK_RWIN)
|
||||
{
|
||||
winKey = ModifierKey::Disabled;
|
||||
}
|
||||
else if (input == VK_LCONTROL || input == VK_RCONTROL || input == VK_CONTROL)
|
||||
{
|
||||
ctrlKey = ModifierKey::Disabled;
|
||||
}
|
||||
else if (input == VK_LMENU || input == VK_RMENU || input == VK_MENU)
|
||||
{
|
||||
altKey = ModifierKey::Disabled;
|
||||
}
|
||||
else if (input == VK_LSHIFT || input == VK_RSHIFT || input == VK_SHIFT)
|
||||
{
|
||||
shiftKey = ModifierKey::Disabled;
|
||||
}
|
||||
else
|
||||
{
|
||||
actionKey = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Function to return the string representation of the shortcut
|
||||
winrt::hstring Shortcut::ToHstring() const
|
||||
{
|
||||
winrt::hstring output;
|
||||
if (winKey != ModifierKey::Disabled)
|
||||
{
|
||||
output = output + ModifierKeyNameWithSide(winKey, L"Win") + winrt::to_hstring(L" ");
|
||||
}
|
||||
if (ctrlKey != ModifierKey::Disabled)
|
||||
{
|
||||
output = output + ModifierKeyNameWithSide(ctrlKey, L"Ctrl") + winrt::to_hstring(L" ");
|
||||
}
|
||||
if (altKey != ModifierKey::Disabled)
|
||||
{
|
||||
output = output + ModifierKeyNameWithSide(altKey, L"Alt") + winrt::to_hstring(L" ");
|
||||
}
|
||||
if (shiftKey != ModifierKey::Disabled)
|
||||
{
|
||||
output = output + ModifierKeyNameWithSide(shiftKey, L"Shift") + winrt::to_hstring(L" ");
|
||||
}
|
||||
if (actionKey != NULL)
|
||||
{
|
||||
output = output + winrt::to_hstring((unsigned int)actionKey);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
// Function to check if all the modifiers in the shortcut have been pressed down
|
||||
bool Shortcut::CheckModifiersKeyboardState() const
|
||||
{
|
||||
// Check the win key state
|
||||
if (winKey == ModifierKey::Both)
|
||||
{
|
||||
// Since VK_WIN does not exist, we check both VK_LWIN and VK_RWIN
|
||||
if ((!(GetAsyncKeyState(VK_LWIN) & 0x8000)) && (!(GetAsyncKeyState(VK_RWIN) & 0x8000)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (winKey == ModifierKey::Left)
|
||||
{
|
||||
if (!(GetAsyncKeyState(VK_LWIN) & 0x8000))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (winKey == ModifierKey::Right)
|
||||
{
|
||||
if (!(GetAsyncKeyState(VK_RWIN) & 0x8000))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check the ctrl key state
|
||||
if (ctrlKey == ModifierKey::Left)
|
||||
{
|
||||
if (!(GetAsyncKeyState(VK_LCONTROL) & 0x8000))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (ctrlKey == ModifierKey::Right)
|
||||
{
|
||||
if (!(GetAsyncKeyState(VK_RCONTROL) & 0x8000))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (ctrlKey == ModifierKey::Both)
|
||||
{
|
||||
if (!(GetAsyncKeyState(VK_CONTROL) & 0x8000))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check the alt key state
|
||||
if (altKey == ModifierKey::Left)
|
||||
{
|
||||
if (!(GetAsyncKeyState(VK_LMENU) & 0x8000))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (altKey == ModifierKey::Right)
|
||||
{
|
||||
if (!(GetAsyncKeyState(VK_RMENU) & 0x8000))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (altKey == ModifierKey::Both)
|
||||
{
|
||||
if (!(GetAsyncKeyState(VK_MENU) & 0x8000))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check the shift key state
|
||||
if (shiftKey == ModifierKey::Left)
|
||||
{
|
||||
if (!(GetAsyncKeyState(VK_LSHIFT) & 0x8000))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (shiftKey == ModifierKey::Right)
|
||||
{
|
||||
if (!(GetAsyncKeyState(VK_RSHIFT) & 0x8000))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (shiftKey == ModifierKey::Both)
|
||||
{
|
||||
if (!(GetAsyncKeyState(VK_SHIFT) & 0x8000))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Function to check if any keys are pressed down except those in the shortcut
|
||||
bool Shortcut::IsKeyboardStateClearExceptShortcut() const
|
||||
{
|
||||
// Iterate through all the virtual key codes
|
||||
for (int keyVal = 0; keyVal < 0x100; keyVal++)
|
||||
{
|
||||
// Skip mouse buttons. Keeping this could cause a remapping to fail if a mouse button is also pressed at the same time
|
||||
if (keyVal == VK_LBUTTON || keyVal == VK_RBUTTON || keyVal == VK_MBUTTON || keyVal == VK_XBUTTON1 || keyVal == VK_XBUTTON2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// Check state of the key. If the key is pressed down but it is not part of the shortcut then the keyboard state is not clear
|
||||
if (GetAsyncKeyState(keyVal) & 0x8000)
|
||||
{
|
||||
// If one of the win keys is pressed check if it is part of the shortcut
|
||||
if (keyVal == VK_LWIN)
|
||||
{
|
||||
if (winKey != ModifierKey::Left && winKey != ModifierKey::Both)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (keyVal == VK_RWIN)
|
||||
{
|
||||
if (winKey != ModifierKey::Right && winKey != ModifierKey::Both)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// If one of the ctrl keys is pressed check if it is part of the shortcut
|
||||
else if (keyVal == VK_LCONTROL)
|
||||
{
|
||||
if (ctrlKey != ModifierKey::Left && ctrlKey != ModifierKey::Both)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (keyVal == VK_RCONTROL)
|
||||
{
|
||||
if (ctrlKey != ModifierKey::Right && ctrlKey != ModifierKey::Both)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (keyVal == VK_CONTROL)
|
||||
{
|
||||
if (ctrlKey == ModifierKey::Disabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// If one of the alt keys is pressed check if it is part of the shortcut
|
||||
else if (keyVal == VK_LMENU)
|
||||
{
|
||||
if (altKey != ModifierKey::Left && altKey != ModifierKey::Both)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (keyVal == VK_RMENU)
|
||||
{
|
||||
if (altKey != ModifierKey::Right && altKey != ModifierKey::Both)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (keyVal == VK_MENU)
|
||||
{
|
||||
if (altKey == ModifierKey::Disabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// If one of the shift keys is pressed check if it is part of the shortcut
|
||||
else if (keyVal == VK_LSHIFT)
|
||||
{
|
||||
if (shiftKey != ModifierKey::Left && shiftKey != ModifierKey::Both)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (keyVal == VK_RSHIFT)
|
||||
{
|
||||
if (shiftKey != ModifierKey::Right && shiftKey != ModifierKey::Both)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (keyVal == VK_SHIFT)
|
||||
{
|
||||
if (shiftKey == ModifierKey::Disabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// If any other key is pressed check if it is the action key
|
||||
else if (keyVal != actionKey)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Function to get the number of modifiers that are common between the current shortcut and the shortcut in the argument
|
||||
int Shortcut::GetCommonModifiersCount(const Shortcut& input) const
|
||||
{
|
||||
int commonElements = 0;
|
||||
if ((winKey == input.winKey) && winKey != ModifierKey::Disabled)
|
||||
{
|
||||
commonElements += 1;
|
||||
}
|
||||
if ((ctrlKey == input.ctrlKey) && ctrlKey != ModifierKey::Disabled)
|
||||
{
|
||||
commonElements += 1;
|
||||
}
|
||||
if ((altKey == input.altKey) && altKey != ModifierKey::Disabled)
|
||||
{
|
||||
commonElements += 1;
|
||||
}
|
||||
if ((shiftKey == input.shiftKey) && shiftKey != ModifierKey::Disabled)
|
||||
{
|
||||
commonElements += 1;
|
||||
}
|
||||
|
||||
return commonElements;
|
||||
}
|
||||
|
||||
// Function to return the name of the key with L or R prefix depending on the first argument. Second argument should be the name of the key without any prefix (ex: Win, Ctrl)
|
||||
winrt::hstring Shortcut::ModifierKeyNameWithSide(const ModifierKey& key, const std::wstring& keyName) const
|
||||
{
|
||||
if (key == ModifierKey::Left)
|
||||
{
|
||||
return winrt::to_hstring(L"L") + winrt::to_hstring(keyName.c_str());
|
||||
}
|
||||
else if (key == ModifierKey::Right)
|
||||
{
|
||||
return winrt::to_hstring(L"R") + winrt::to_hstring(keyName.c_str());
|
||||
}
|
||||
else if (key == ModifierKey::Both)
|
||||
{
|
||||
return winrt::to_hstring(keyName.c_str());
|
||||
}
|
||||
|
||||
return winrt::hstring();
|
||||
}
|
||||
|
||||
// Function to return the virtual key code from the name of the key
|
||||
DWORD Shortcut::DecodeKey(const std::wstring& keyName)
|
||||
{
|
||||
if (keyName == L"LWin")
|
||||
{
|
||||
return VK_LWIN;
|
||||
}
|
||||
else if (keyName == L"RWin")
|
||||
{
|
||||
return VK_RWIN;
|
||||
}
|
||||
else if (keyName == L"LCtrl")
|
||||
{
|
||||
return VK_LCONTROL;
|
||||
}
|
||||
else if (keyName == L"RCtrl")
|
||||
{
|
||||
return VK_RCONTROL;
|
||||
}
|
||||
else if (keyName == L"Ctrl")
|
||||
{
|
||||
return VK_CONTROL;
|
||||
}
|
||||
else if (keyName == L"LAlt")
|
||||
{
|
||||
return VK_LMENU;
|
||||
}
|
||||
else if (keyName == L"RAlt")
|
||||
{
|
||||
return VK_RMENU;
|
||||
}
|
||||
else if (keyName == L"Alt")
|
||||
{
|
||||
return VK_MENU;
|
||||
}
|
||||
else if (keyName == L"LShift")
|
||||
{
|
||||
return VK_LSHIFT;
|
||||
}
|
||||
else if (keyName == L"RShift")
|
||||
{
|
||||
return VK_RSHIFT;
|
||||
}
|
||||
else if (keyName == L"Shift")
|
||||
{
|
||||
return VK_SHIFT;
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::stoi(keyName);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to create a shortcut object from its string representation
|
||||
Shortcut Shortcut::CreateShortcut(const winrt::hstring& input)
|
||||
{
|
||||
Shortcut newShortcut;
|
||||
std::wstring shortcutWstring = input.c_str();
|
||||
std::vector<std::wstring> shortcutVector = splitwstring(shortcutWstring, L' ');
|
||||
for (int i = 0; i < shortcutVector.size(); i++)
|
||||
{
|
||||
if (shortcutVector[i] == L"Win")
|
||||
{
|
||||
newShortcut.SetKey(NULL, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD keyCode = DecodeKey(shortcutVector[i]);
|
||||
newShortcut.SetKey(keyCode);
|
||||
}
|
||||
}
|
||||
|
||||
return newShortcut;
|
||||
}
|
157
src/modules/keyboardmanager/common/Shortcut.h
Normal file
157
src/modules/keyboardmanager/common/Shortcut.h
Normal file
|
@ -0,0 +1,157 @@
|
|||
#pragma once
|
||||
#include "Helpers.h"
|
||||
#include <interface/lowlevel_keyboard_event_data.h>
|
||||
|
||||
// Enum type to store different states of the win key
|
||||
enum class ModifierKey
|
||||
{
|
||||
Disabled,
|
||||
Left,
|
||||
Right,
|
||||
Both
|
||||
};
|
||||
|
||||
class Shortcut
|
||||
{
|
||||
private:
|
||||
ModifierKey winKey;
|
||||
ModifierKey ctrlKey;
|
||||
ModifierKey altKey;
|
||||
ModifierKey shiftKey;
|
||||
DWORD actionKey;
|
||||
|
||||
// Function to return the name of the key with L or R prefix depending on the first argument. Second argument should be the name of the key without any prefix (ex: Win, Ctrl)
|
||||
winrt::hstring ModifierKeyNameWithSide(const ModifierKey& key, const std::wstring& keyName) const;
|
||||
|
||||
public:
|
||||
// By default create an empty shortcut
|
||||
Shortcut() :
|
||||
winKey(ModifierKey::Disabled), ctrlKey(ModifierKey::Disabled), altKey(ModifierKey::Disabled), shiftKey(ModifierKey::Disabled), actionKey(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
// Less than operator must be defined to use with std::map.
|
||||
inline bool operator<(const Shortcut& sc) const
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Function to return the number of keys in the shortcut
|
||||
int Size() const;
|
||||
|
||||
// Function to return true if the shortcut has no keys set
|
||||
bool IsEmpty() const;
|
||||
|
||||
// Function to reset all the keys in the shortcut
|
||||
void Reset();
|
||||
|
||||
// Function to return true if the shortcut is valid. A valid shortcut has atleast one modifier, as well as an action key
|
||||
bool IsValidShortcut() const;
|
||||
|
||||
// Function to return the action key
|
||||
DWORD GetActionKey() const;
|
||||
|
||||
// Function to return the virtual key code of the win key state expected in the shortcut. Argument is used to decide which win key to return in case of both. If the current shortcut doesn't use both win keys then arg is ignored. Return NULL if it is not a part of the shortcut
|
||||
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;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
|
||||
// Function to check if the input key matches the win key expected in the shortcut
|
||||
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;
|
||||
|
||||
// Function to check if the input key matches the alt key expected in the shortcut
|
||||
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;
|
||||
|
||||
// Function to set a key in the shortcut based on the passed key code argument. Since there is no VK_WIN code, use the second argument for setting common win key. If isWinBoth is true then first arg is ignored. Returns false if it is already set to the same value. This can be used to avoid UI refreshing
|
||||
bool SetKey(const DWORD& input, const bool& isWinBoth = false);
|
||||
|
||||
// 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 ResetKey(const DWORD& input, const bool& isWinBoth = false);
|
||||
|
||||
// Function to return the string representation of the shortcut
|
||||
winrt::hstring ToHstring() const;
|
||||
|
||||
// Function to check if all the modifiers in the shortcut have been pressed down
|
||||
bool CheckModifiersKeyboardState() const;
|
||||
|
||||
// Function to check if any keys are pressed down except those in the shortcut
|
||||
bool IsKeyboardStateClearExceptShortcut() const;
|
||||
|
||||
// Function to get the number of modifiers that are common between the current shortcut and the shortcut in the argument
|
||||
int GetCommonModifiersCount(const Shortcut& input) const;
|
||||
|
||||
// Function to return the virtual key code from the name of the key
|
||||
static DWORD DecodeKey(const std::wstring& keyName);
|
||||
|
||||
// Function to create a shortcut object from its string representation
|
||||
static Shortcut CreateShortcut(const winrt::hstring& input);
|
||||
};
|
|
@ -7,6 +7,8 @@
|
|||
#include "resource.h"
|
||||
#include <keyboardmanager/ui/MainWindow.h>
|
||||
#include <keyboardmanager/common/KeyboardManagerState.h>
|
||||
#include <keyboardmanager/common/Shortcut.h>
|
||||
#include <keyboardmanager/common/RemapShortcut.h>
|
||||
|
||||
extern "C" IMAGE_DOS_HEADER __ImageBase;
|
||||
|
||||
|
@ -78,12 +80,15 @@ public:
|
|||
//keyboardManagerState.singleKeyReMap[0x42] = 0x43;
|
||||
//keyboardManagerState.singleKeyReMap[0x43] = 0x41;
|
||||
//keyboardManagerState.singleKeyReMap[VK_LWIN] = VK_LCONTROL;
|
||||
//keyboardManagerState.singleKeyReMap[VK_LCONTROL] = VK_LWIN;
|
||||
//keyboardManagerState.singleKeyReMap[VK_LCONTROL] = VK_RWIN;
|
||||
//keyboardManagerState.singleKeyReMap[VK_CAPITAL] = 0x0;
|
||||
//keyboardManagerState.singleKeyReMap[VK_LSHIFT] = VK_CAPITAL;
|
||||
//keyboardManagerState.singleKeyToggleToMod[VK_CAPITAL] = false;
|
||||
|
||||
//// OS-level shortcut remappings
|
||||
//Shortcut newShortcut = Shortcut::CreateShortcut(winrt::to_hstring(L"Win 65"));
|
||||
//Shortcut originalShortcut = Shortcut::CreateShortcut(winrt::to_hstring(L"Shift 65"));
|
||||
//keyboardManagerState.AddOSLevelShortcut(originalShortcut, newShortcut);
|
||||
//keyboardManagerState.osLevelShortcutReMap[std::vector<DWORD>({ VK_LMENU, 0x44 })] = std::make_pair(std::vector<WORD>({ VK_LCONTROL, 0x56 }), false);
|
||||
//keyboardManagerState.osLevelShortcutReMap[std::vector<DWORD>({ VK_LMENU, 0x45 })] = std::make_pair(std::vector<WORD>({ VK_LCONTROL, 0x58 }), false);
|
||||
//keyboardManagerState.osLevelShortcutReMap[std::vector<DWORD>({ VK_LWIN, 0x46 })] = std::make_pair(std::vector<WORD>({ VK_LWIN, 0x53 }), false);
|
||||
|
@ -307,6 +312,14 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void SetKeyEvent(LPINPUT keyEventArray, int index, DWORD inputType, WORD keyCode, DWORD flags, ULONG_PTR extraInfo)
|
||||
{
|
||||
keyEventArray[index].type = inputType;
|
||||
keyEventArray[index].ki.wVk = keyCode;
|
||||
keyEventArray[index].ki.dwFlags = flags;
|
||||
keyEventArray[index].ki.dwExtraInfo = extraInfo;
|
||||
}
|
||||
|
||||
// Function to a handle a single key remap
|
||||
intptr_t HandleSingleKeyRemapEvent(LowlevelKeyboardEvent* data) noexcept
|
||||
{
|
||||
|
@ -327,13 +340,13 @@ public:
|
|||
int key_count = 1;
|
||||
LPINPUT keyEventList = new INPUT[size_t(key_count)]();
|
||||
memset(keyEventList, 0, sizeof(keyEventList));
|
||||
keyEventList[0].type = INPUT_KEYBOARD;
|
||||
keyEventList[0].ki.wVk = it->second;
|
||||
keyEventList[0].ki.dwFlags = 0;
|
||||
keyEventList[0].ki.dwExtraInfo = KEYBOARDMANAGER_SINGLEKEY_FLAG;
|
||||
if (data->wParam == WM_KEYUP || data->wParam == WM_SYSKEYUP)
|
||||
{
|
||||
keyEventList[0].ki.dwFlags = KEYEVENTF_KEYUP;
|
||||
SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, (WORD)it->second, KEYEVENTF_KEYUP, KEYBOARDMANAGER_SINGLEKEY_FLAG);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, (WORD)it->second, 0, KEYBOARDMANAGER_SINGLEKEY_FLAG);
|
||||
}
|
||||
|
||||
lock.unlock();
|
||||
|
@ -373,14 +386,8 @@ public:
|
|||
int key_count = 2;
|
||||
LPINPUT keyEventList = new INPUT[size_t(key_count)]();
|
||||
memset(keyEventList, 0, sizeof(keyEventList));
|
||||
keyEventList[0].type = INPUT_KEYBOARD;
|
||||
keyEventList[0].ki.wVk = (WORD)data->lParam->vkCode;
|
||||
keyEventList[0].ki.dwFlags = 0;
|
||||
keyEventList[0].ki.dwExtraInfo = KEYBOARDMANAGER_SINGLEKEY_FLAG;
|
||||
keyEventList[1].type = INPUT_KEYBOARD;
|
||||
keyEventList[1].ki.wVk = (WORD)data->lParam->vkCode;
|
||||
keyEventList[1].ki.dwFlags = KEYEVENTF_KEYUP;
|
||||
keyEventList[1].ki.dwExtraInfo = KEYBOARDMANAGER_SINGLEKEY_FLAG;
|
||||
SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, (WORD)data->lParam->vkCode, 0, KEYBOARDMANAGER_SINGLEKEY_FLAG);
|
||||
SetKeyEvent(keyEventList, 1, INPUT_KEYBOARD, (WORD)data->lParam->vkCode, KEYEVENTF_KEYUP, KEYBOARDMANAGER_SINGLEKEY_FLAG);
|
||||
|
||||
lock.unlock();
|
||||
UINT res = SendInput(key_count, keyEventList, sizeof(INPUT));
|
||||
|
@ -401,205 +408,134 @@ public:
|
|||
return 0;
|
||||
}
|
||||
|
||||
// Function to check if any keys are pressed down except those passed in the argument
|
||||
bool IsKeyboardStateClearExceptArgs(const std::vector<DWORD>& args)
|
||||
{
|
||||
bool isIgnore = false;
|
||||
for (int keyVal = 0; keyVal < 0x100; keyVal++)
|
||||
{
|
||||
// Skip mouse buttons. Keeping this could cause a remapping to fail if a mouse button is also pressed at the same time
|
||||
if (keyVal == VK_LBUTTON || keyVal == VK_RBUTTON || keyVal == VK_MBUTTON || keyVal == VK_XBUTTON1 || keyVal == VK_XBUTTON2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// Check state of the key
|
||||
if (GetAsyncKeyState(keyVal) & 0x8000)
|
||||
{
|
||||
isIgnore = false;
|
||||
// If the key is not part of the argument then the keyboard state is not clear
|
||||
for (int i = 0; i < args.size(); i++)
|
||||
{
|
||||
// If the key matches one of the args, ignore
|
||||
if (args[i] == keyVal)
|
||||
{
|
||||
isIgnore = true;
|
||||
break;
|
||||
}
|
||||
// If the key is Control and either of the args is L/R Control, ignore
|
||||
else if ((args[i] == VK_LCONTROL || args[i] == VK_RCONTROL) && keyVal == VK_CONTROL)
|
||||
{
|
||||
isIgnore = true;
|
||||
break;
|
||||
}
|
||||
// If the key is Alt and either of the args is L/R Alt, ignore
|
||||
else if ((args[i] == VK_LMENU || args[i] == VK_RMENU) && keyVal == VK_MENU)
|
||||
{
|
||||
isIgnore = true;
|
||||
break;
|
||||
}
|
||||
// If the key is Shift and either of the args is L/R Shift, ignore
|
||||
else if ((args[i] == VK_LSHIFT || args[i] == VK_RSHIFT) && keyVal == VK_SHIFT)
|
||||
{
|
||||
isIgnore = true;
|
||||
break;
|
||||
}
|
||||
// If the key is L/R Control and either of the args is Control, ignore
|
||||
else if ((keyVal == VK_LCONTROL || keyVal == VK_RCONTROL) && args[i] == VK_CONTROL)
|
||||
{
|
||||
isIgnore = true;
|
||||
break;
|
||||
}
|
||||
// If the key is L/R Alt and either of the args is Alt, ignore
|
||||
else if ((keyVal == VK_LMENU || keyVal == VK_RMENU) && args[i] == VK_MENU)
|
||||
{
|
||||
isIgnore = true;
|
||||
break;
|
||||
}
|
||||
// If the key is L/R Shift and either of the args is Shift, ignore
|
||||
else if ((keyVal == VK_LSHIFT || keyVal == VK_RSHIFT) && args[i] == VK_SHIFT)
|
||||
{
|
||||
isIgnore = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isIgnore)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Function to check if the modifiers in the shortcut have been pressed down
|
||||
template<typename T>
|
||||
bool CheckModifiersKeyboardState(const std::vector<T>& args)
|
||||
{
|
||||
// Check all keys except last
|
||||
for (int i = 0; i < args.size() - 1; i++)
|
||||
{
|
||||
if (!(GetAsyncKeyState(args[i]) & 0x8000))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Function to check if all the modifiers in the first shorcut are present in the second shortcut, i.e. Modifiers(src) are a subset of Modifiers(dest)
|
||||
std::vector<DWORD> GetCommonModifiers(const std::vector<DWORD>& src, const std::vector<WORD>& dest)
|
||||
{
|
||||
std::vector<DWORD> commonElements;
|
||||
for (auto it = src.begin(); it != src.end() - 1; it++)
|
||||
{
|
||||
if (std::find(dest.begin(), dest.end() - 1, *it) != dest.end() - 1)
|
||||
{
|
||||
commonElements.push_back(*it);
|
||||
}
|
||||
}
|
||||
|
||||
return commonElements;
|
||||
}
|
||||
|
||||
// Function to a handle a shortcut remap
|
||||
intptr_t HandleShortcutRemapEvent(LowlevelKeyboardEvent* data, std::map<std::vector<DWORD>, std::pair<std::vector<WORD>, bool>>& reMap, std::mutex& map_mutex) noexcept
|
||||
intptr_t HandleShortcutRemapEvent(LowlevelKeyboardEvent* data, std::map<Shortcut, RemapShortcut>& reMap, std::mutex& map_mutex) noexcept
|
||||
{
|
||||
// The mutex should be unlocked before SendInput is called to avoid re-entry into the same mutex. More details can be found at https://github.com/microsoft/PowerToys/pull/1789#issuecomment-607555837
|
||||
std::unique_lock<std::mutex> lock(map_mutex);
|
||||
for (auto& it : reMap)
|
||||
{
|
||||
const size_t src_size = it.first.size();
|
||||
const size_t dest_size = it.second.first.size();
|
||||
const size_t src_size = it.first.Size();
|
||||
const size_t dest_size = it.second.targetShortcut.Size();
|
||||
|
||||
// If the shortcut has been pressed down
|
||||
if (!it.second.second && CheckModifiersKeyboardState<DWORD>(it.first))
|
||||
if (!it.second.isShortcutInvoked && it.first.CheckModifiersKeyboardState())
|
||||
{
|
||||
if (data->lParam->vkCode == it.first[src_size - 1] && (data->wParam == WM_KEYDOWN || data->wParam == WM_SYSKEYDOWN))
|
||||
if (data->lParam->vkCode == it.first.GetActionKey() && (data->wParam == WM_KEYDOWN || data->wParam == WM_SYSKEYDOWN))
|
||||
{
|
||||
// Check if any other keys have been pressed apart from the shortcut. If true, then check for the next shortcut
|
||||
if (!IsKeyboardStateClearExceptArgs(it.first))
|
||||
if (!it.first.IsKeyboardStateClearExceptShortcut())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t key_count;
|
||||
LPINPUT keyEventList;
|
||||
|
||||
// Remember which win key was pressed initially
|
||||
if (GetAsyncKeyState(VK_RWIN) & 0x8000)
|
||||
{
|
||||
it.second.winKeyInvoked = ModifierKey::Right;
|
||||
}
|
||||
else if (GetAsyncKeyState(VK_LWIN) & 0x8000)
|
||||
{
|
||||
it.second.winKeyInvoked = ModifierKey::Left;
|
||||
}
|
||||
|
||||
// Get the common keys between the two shortcuts
|
||||
std::vector<DWORD> commonKeys = GetCommonModifiers(it.first, it.second.first);
|
||||
int commonKeys = it.first.GetCommonModifiersCount(it.second.targetShortcut);
|
||||
|
||||
// If the original shortcut modifiers are a subset of the new shortcut
|
||||
if (commonKeys.size() == src_size - 1)
|
||||
if (commonKeys == src_size - 1)
|
||||
{
|
||||
// key down for all new shortcut keys except the common modifiers
|
||||
key_count = dest_size - commonKeys.size();
|
||||
key_count = dest_size - commonKeys;
|
||||
keyEventList = new INPUT[key_count]();
|
||||
memset(keyEventList, 0, sizeof(keyEventList));
|
||||
long long i = 0;
|
||||
long long j = 0;
|
||||
// Add a key down only for the non-common keys in the new shortcut
|
||||
while (i < (long long)key_count)
|
||||
int i = 0;
|
||||
|
||||
if ((it.second.targetShortcut.GetWinKey(it.second.winKeyInvoked) != it.first.GetWinKey(it.second.winKeyInvoked)) && it.second.targetShortcut.GetWinKey(it.second.winKeyInvoked) != NULL)
|
||||
{
|
||||
if (std::find(commonKeys.begin(), commonKeys.end(), it.second.first[j]) == commonKeys.end())
|
||||
{
|
||||
keyEventList[i].type = INPUT_KEYBOARD;
|
||||
keyEventList[i].ki.wVk = it.second.first[j];
|
||||
keyEventList[i].ki.dwFlags = 0;
|
||||
keyEventList[i].ki.dwExtraInfo = KEYBOARDMANAGER_SHORTCUT_FLAG;
|
||||
i++;
|
||||
}
|
||||
j++;
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.second.targetShortcut.GetWinKey(it.second.winKeyInvoked), 0, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
if ((it.second.targetShortcut.GetCtrlKey() != it.first.GetCtrlKey()) && it.second.targetShortcut.GetCtrlKey() != NULL)
|
||||
{
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.second.targetShortcut.GetCtrlKey(), 0, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
if ((it.second.targetShortcut.GetAltKey() != it.first.GetAltKey()) && it.second.targetShortcut.GetAltKey() != NULL)
|
||||
{
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.second.targetShortcut.GetAltKey(), 0, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
if ((it.second.targetShortcut.GetShiftKey() != it.first.GetShiftKey()) && it.second.targetShortcut.GetShiftKey() != NULL)
|
||||
{
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.second.targetShortcut.GetShiftKey(), 0, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.second.targetShortcut.GetActionKey(), 0, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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 = 1 + (src_size - 1) + (dest_size) - (2 * commonKeys.size());
|
||||
key_count = 1 + (src_size - 1) + (dest_size) - (2 * (size_t)commonKeys);
|
||||
keyEventList = new INPUT[key_count]();
|
||||
memset(keyEventList, 0, sizeof(keyEventList));
|
||||
|
||||
// Send dummy key
|
||||
keyEventList[0].type = INPUT_KEYBOARD;
|
||||
keyEventList[0].ki.wVk = (WORD)DUMMY_KEY;
|
||||
keyEventList[0].ki.dwFlags = KEYEVENTF_KEYUP;
|
||||
keyEventList[0].ki.dwExtraInfo = KEYBOARDMANAGER_SHORTCUT_FLAG;
|
||||
|
||||
int i = 0;
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)DUMMY_KEY, KEYEVENTF_KEYUP, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
// Release original shortcut state (release in reverse order of shortcut to be accurate)
|
||||
long long i = 1;
|
||||
long long j = (long long)src_size - 2;
|
||||
while (j >= 0)
|
||||
if ((it.second.targetShortcut.GetShiftKey() != it.first.GetShiftKey()) && it.first.GetShiftKey() != NULL)
|
||||
{
|
||||
// Release only those keys which are not common
|
||||
if (std::find(commonKeys.begin(), commonKeys.end(), it.first[j]) == commonKeys.end())
|
||||
{
|
||||
keyEventList[i].type = INPUT_KEYBOARD;
|
||||
keyEventList[i].ki.wVk = (WORD)it.first[j];
|
||||
keyEventList[i].ki.dwFlags = KEYEVENTF_KEYUP;
|
||||
keyEventList[i].ki.dwExtraInfo = KEYBOARDMANAGER_SHORTCUT_FLAG;
|
||||
i++;
|
||||
}
|
||||
j--;
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.first.GetShiftKey(), KEYEVENTF_KEYUP, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
if ((it.second.targetShortcut.GetAltKey() != it.first.GetAltKey()) && it.first.GetAltKey() != NULL)
|
||||
{
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.first.GetAltKey(), KEYEVENTF_KEYUP, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
if ((it.second.targetShortcut.GetCtrlKey() != it.first.GetCtrlKey()) && it.first.GetCtrlKey() != NULL)
|
||||
{
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.first.GetCtrlKey(), KEYEVENTF_KEYUP, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
if ((it.second.targetShortcut.GetWinKey(it.second.winKeyInvoked) != it.first.GetWinKey(it.second.winKeyInvoked)) && it.first.GetWinKey(it.second.winKeyInvoked) != NULL)
|
||||
{
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.first.GetWinKey(it.second.winKeyInvoked), KEYEVENTF_KEYUP, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
|
||||
// Set new shortcut key down state
|
||||
j = 0;
|
||||
while (i < (long long)key_count)
|
||||
if ((it.second.targetShortcut.GetWinKey(it.second.winKeyInvoked) != it.first.GetWinKey(it.second.winKeyInvoked)) && it.second.targetShortcut.GetWinKey(it.second.winKeyInvoked) != NULL)
|
||||
{
|
||||
// Key down only those keys which are not common
|
||||
if (std::find(commonKeys.begin(), commonKeys.end(), it.second.first[j]) == commonKeys.end())
|
||||
{
|
||||
keyEventList[i].type = INPUT_KEYBOARD;
|
||||
keyEventList[i].ki.wVk = it.second.first[j];
|
||||
keyEventList[i].ki.dwFlags = 0;
|
||||
keyEventList[i].ki.dwExtraInfo = KEYBOARDMANAGER_SHORTCUT_FLAG;
|
||||
i++;
|
||||
}
|
||||
j++;
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.second.targetShortcut.GetWinKey(it.second.winKeyInvoked), 0, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
if ((it.second.targetShortcut.GetCtrlKey() != it.first.GetCtrlKey()) && it.second.targetShortcut.GetCtrlKey() != NULL)
|
||||
{
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.second.targetShortcut.GetCtrlKey(), 0, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
if ((it.second.targetShortcut.GetAltKey() != it.first.GetAltKey()) && it.second.targetShortcut.GetAltKey() != NULL)
|
||||
{
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.second.targetShortcut.GetAltKey(), 0, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
if ((it.second.targetShortcut.GetShiftKey() != it.first.GetShiftKey()) && it.second.targetShortcut.GetShiftKey() != NULL)
|
||||
{
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.second.targetShortcut.GetShiftKey(), 0, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.second.targetShortcut.GetActionKey(), 0, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
|
||||
it.second.second = true;
|
||||
it.second.isShortcutInvoked = true;
|
||||
lock.unlock();
|
||||
UINT res = SendInput((UINT)key_count, keyEventList, sizeof(INPUT));
|
||||
delete[] keyEventList;
|
||||
|
@ -610,66 +546,81 @@ public:
|
|||
// There are 4 cases to be handled if the shortcut has been pressed down
|
||||
// 1. The user lets go of one of the modifier keys - reset the keyboard back to the state of the keys actually being pressed down
|
||||
// 2. The user keeps the shortcut pressed - the shortcut is repeated (for example you could hold down Ctrl+V and it will keep pasting)
|
||||
// 3. The user lets go of the last key - reset the keyboard back to the state of the keys actually being pressed down
|
||||
// 3. The user lets go of the action key - reset the keyboard back to the state of the keys actually being pressed down
|
||||
// 4. The user presses another key while holding the shortcut down - the system now sees all the new shortcut keys and this extra key pressed at the end. Not handled as resetting the state would trigger the original shortcut once more
|
||||
else if (it.second.second)
|
||||
else if (it.second.isShortcutInvoked)
|
||||
{
|
||||
// Get the common keys between the two shortcuts
|
||||
std::vector<DWORD> commonKeys = GetCommonModifiers(it.first, it.second.first);
|
||||
int commonKeys = it.first.GetCommonModifiersCount(it.second.targetShortcut);
|
||||
|
||||
// Case 1: If any of the modifier keys of the original shortcut are released before the normal key
|
||||
auto keyIt = std::find(it.first.begin(), it.first.end() - 1, data->lParam->vkCode);
|
||||
if (keyIt != (it.first.end() - 1) && (data->wParam == WM_KEYUP || data->wParam == WM_SYSKEYUP))
|
||||
if ((it.first.CheckWinKey(data->lParam->vkCode) || it.first.CheckCtrlKey(data->lParam->vkCode) || it.first.CheckAltKey(data->lParam->vkCode) || it.first.CheckShiftKey(data->lParam->vkCode)) && (data->wParam == WM_KEYUP || data->wParam == WM_SYSKEYUP))
|
||||
{
|
||||
// Release new shortcut, and set original shortcut keys except the one released
|
||||
size_t key_count;
|
||||
if (std::find(commonKeys.begin(), commonKeys.end(), data->lParam->vkCode) != commonKeys.end())
|
||||
// if the released key is present in both shortcuts' modifiers (i.e part of the common modifiers)
|
||||
if (it.second.targetShortcut.CheckWinKey(data->lParam->vkCode) || it.second.targetShortcut.CheckCtrlKey(data->lParam->vkCode) || it.second.targetShortcut.CheckAltKey(data->lParam->vkCode) || it.second.targetShortcut.CheckShiftKey(data->lParam->vkCode))
|
||||
{
|
||||
// release all new shortcut keys and the common released modifier except the other common modifiers, and add all original shortcut modifiers except the common ones
|
||||
key_count = (dest_size - commonKeys.size() + 1) + (src_size - 1 - commonKeys.size());
|
||||
key_count = (dest_size - commonKeys + 1) + (src_size - 1 - commonKeys);
|
||||
}
|
||||
else
|
||||
{
|
||||
// release all new shortcut keys except the common modifiers and add all original shortcut modifiers except the common ones
|
||||
key_count = dest_size + (src_size - 2) - (2 * commonKeys.size());
|
||||
key_count = dest_size + (src_size - 2) - (2 * (size_t)commonKeys);
|
||||
}
|
||||
LPINPUT keyEventList = new INPUT[key_count]();
|
||||
memset(keyEventList, 0, sizeof(keyEventList));
|
||||
|
||||
// Release new shortcut state (release in reverse order of shortcut to be accurate)
|
||||
long long i = 0;
|
||||
long long j = (long long)dest_size - 1;
|
||||
while (j >= 0)
|
||||
int i = 0;
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.second.targetShortcut.GetActionKey(), KEYEVENTF_KEYUP, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
if (((it.second.targetShortcut.GetShiftKey() != it.first.GetShiftKey()) || (it.second.targetShortcut.CheckShiftKey(data->lParam->vkCode))) && it.second.targetShortcut.GetShiftKey() != NULL)
|
||||
{
|
||||
// Do not release if it is a common modifier, except the case where a common modifier is released (second part of the if condition))
|
||||
if ((std::find(commonKeys.begin(), commonKeys.end(), it.second.first[j]) == commonKeys.end()) || it.second.first[j] == data->lParam->vkCode)
|
||||
{
|
||||
keyEventList[i].type = INPUT_KEYBOARD;
|
||||
keyEventList[i].ki.wVk = it.second.first[j];
|
||||
keyEventList[i].ki.dwFlags = KEYEVENTF_KEYUP;
|
||||
keyEventList[i].ki.dwExtraInfo = KEYBOARDMANAGER_SHORTCUT_FLAG;
|
||||
i++;
|
||||
}
|
||||
j--;
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.second.targetShortcut.GetShiftKey(), KEYEVENTF_KEYUP, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
if (((it.second.targetShortcut.GetAltKey() != it.first.GetAltKey()) || (it.second.targetShortcut.CheckAltKey(data->lParam->vkCode))) && it.second.targetShortcut.GetAltKey() != NULL)
|
||||
{
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.second.targetShortcut.GetAltKey(), KEYEVENTF_KEYUP, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
if (((it.second.targetShortcut.GetCtrlKey() != it.first.GetCtrlKey()) || (it.second.targetShortcut.CheckCtrlKey(data->lParam->vkCode))) && it.second.targetShortcut.GetCtrlKey() != NULL)
|
||||
{
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.second.targetShortcut.GetCtrlKey(), KEYEVENTF_KEYUP, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
if (((it.second.targetShortcut.GetWinKey(it.second.winKeyInvoked) != it.first.GetWinKey(it.second.winKeyInvoked)) || (it.second.targetShortcut.CheckWinKey(data->lParam->vkCode))) && it.second.targetShortcut.GetWinKey(it.second.winKeyInvoked) != NULL)
|
||||
{
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.second.targetShortcut.GetWinKey(it.second.winKeyInvoked), KEYEVENTF_KEYUP, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
|
||||
// Set original shortcut key down state except the last key and the released modifier
|
||||
j = 0;
|
||||
while (i < (long long)key_count)
|
||||
// Set original shortcut key down state except the action key and the released modifier
|
||||
if ((it.second.targetShortcut.GetWinKey(it.second.winKeyInvoked) != it.first.GetWinKey(it.second.winKeyInvoked)) && (!it.first.CheckWinKey(data->lParam->vkCode)) && it.first.GetWinKey(it.second.winKeyInvoked) != NULL)
|
||||
{
|
||||
// Do not set key down for the released modifier and for the common modifiers
|
||||
if (it.first[j] != data->lParam->vkCode && (std::find(commonKeys.begin(), commonKeys.end(), it.first[j]) == commonKeys.end()))
|
||||
{
|
||||
keyEventList[i].type = INPUT_KEYBOARD;
|
||||
keyEventList[i].ki.wVk = (WORD)it.first[j];
|
||||
keyEventList[i].ki.dwFlags = 0;
|
||||
keyEventList[i].ki.dwExtraInfo = KEYBOARDMANAGER_SHORTCUT_FLAG;
|
||||
i++;
|
||||
}
|
||||
j++;
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.first.GetWinKey(it.second.winKeyInvoked), 0, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
if ((it.second.targetShortcut.GetCtrlKey() != it.first.GetCtrlKey()) && (!it.first.CheckCtrlKey(data->lParam->vkCode)) && it.first.GetCtrlKey() != NULL)
|
||||
{
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.first.GetCtrlKey(), 0, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
if ((it.second.targetShortcut.GetAltKey() != it.first.GetAltKey()) && (!it.first.CheckAltKey(data->lParam->vkCode)) && it.first.GetAltKey() != NULL)
|
||||
{
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.first.GetAltKey(), 0, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
if ((it.second.targetShortcut.GetShiftKey() != it.first.GetShiftKey()) && (!it.first.CheckShiftKey(data->lParam->vkCode)) && it.first.GetShiftKey() != NULL)
|
||||
{
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.first.GetShiftKey(), 0, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
|
||||
it.second.second = false;
|
||||
it.second.isShortcutInvoked = false;
|
||||
it.second.winKeyInvoked = ModifierKey::Disabled;
|
||||
lock.unlock();
|
||||
UINT res = SendInput((UINT)key_count, keyEventList, sizeof(INPUT));
|
||||
delete[] keyEventList;
|
||||
|
@ -677,101 +628,122 @@ public:
|
|||
}
|
||||
|
||||
// The system will see the modifiers of the new shortcut as being held down because of the shortcut remap
|
||||
if (CheckModifiersKeyboardState<WORD>(it.second.first))
|
||||
if (it.second.targetShortcut.CheckModifiersKeyboardState())
|
||||
{
|
||||
// Case 2: If the original shortcut is still held down the keyboard will get a key down message of the last key in the original shortcut and the new shortcut's modifiers will be held down (keys held down send repeated keydown messages)
|
||||
if (data->lParam->vkCode == it.first[src_size - 1] && (data->wParam == WM_KEYDOWN || data->wParam == WM_SYSKEYDOWN))
|
||||
// Case 2: If the original shortcut is still held down the keyboard will get a key down message of the action key in the original shortcut and the new shortcut's modifiers will be held down (keys held down send repeated keydown messages)
|
||||
if (data->lParam->vkCode == it.first.GetActionKey() && (data->wParam == WM_KEYDOWN || data->wParam == WM_SYSKEYDOWN))
|
||||
{
|
||||
size_t key_count = 1;
|
||||
LPINPUT keyEventList = new INPUT[key_count]();
|
||||
memset(keyEventList, 0, sizeof(keyEventList));
|
||||
keyEventList[0].type = INPUT_KEYBOARD;
|
||||
keyEventList[0].ki.wVk = it.second.first[dest_size - 1];
|
||||
keyEventList[0].ki.dwFlags = 0;
|
||||
keyEventList[0].ki.dwExtraInfo = KEYBOARDMANAGER_SHORTCUT_FLAG;
|
||||
SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, (WORD)it.second.targetShortcut.GetActionKey(), 0, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
|
||||
it.second.second = true;
|
||||
it.second.isShortcutInvoked = true;
|
||||
lock.unlock();
|
||||
UINT res = SendInput((UINT)key_count, keyEventList, sizeof(INPUT));
|
||||
delete[] keyEventList;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Case 3: If the last key is released from the original shortcut then revert the keyboard state to just the original modifiers being held down
|
||||
if (data->lParam->vkCode == it.first[src_size - 1] && (data->wParam == WM_KEYUP || data->wParam == WM_SYSKEYUP))
|
||||
// Case 3: If the action key is released from the original shortcut then revert the keyboard state to just the original modifiers being held down
|
||||
if (data->lParam->vkCode == it.first.GetActionKey() && (data->wParam == WM_KEYUP || data->wParam == WM_SYSKEYUP))
|
||||
{
|
||||
size_t key_count;
|
||||
LPINPUT keyEventList;
|
||||
|
||||
// If the original shortcut is a subset of the new shortcut
|
||||
if (commonKeys.size() == src_size - 1)
|
||||
if (commonKeys == src_size - 1)
|
||||
{
|
||||
key_count = dest_size - commonKeys.size();
|
||||
key_count = dest_size - commonKeys;
|
||||
keyEventList = new INPUT[key_count]();
|
||||
memset(keyEventList, 0, sizeof(keyEventList));
|
||||
long long i = 0;
|
||||
long long j = (long long)dest_size - 1;
|
||||
while (i < (long long)key_count)
|
||||
|
||||
int i = 0;
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.second.targetShortcut.GetActionKey(), KEYEVENTF_KEYUP, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
if ((it.second.targetShortcut.GetShiftKey() != it.first.GetShiftKey()) && it.second.targetShortcut.GetShiftKey() != NULL)
|
||||
{
|
||||
if (std::find(commonKeys.begin(), commonKeys.end(), it.second.first[j]) == commonKeys.end())
|
||||
{
|
||||
keyEventList[i].type = INPUT_KEYBOARD;
|
||||
keyEventList[i].ki.wVk = it.second.first[j];
|
||||
keyEventList[i].ki.dwFlags = KEYEVENTF_KEYUP;
|
||||
keyEventList[i].ki.dwExtraInfo = KEYBOARDMANAGER_SHORTCUT_FLAG;
|
||||
i++;
|
||||
}
|
||||
j--;
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.second.targetShortcut.GetShiftKey(), KEYEVENTF_KEYUP, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
if ((it.second.targetShortcut.GetAltKey() != it.first.GetAltKey()) && it.second.targetShortcut.GetAltKey() != NULL)
|
||||
{
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.second.targetShortcut.GetAltKey(), KEYEVENTF_KEYUP, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
if ((it.second.targetShortcut.GetCtrlKey() != it.first.GetCtrlKey()) && it.second.targetShortcut.GetCtrlKey() != NULL)
|
||||
{
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.second.targetShortcut.GetCtrlKey(), KEYEVENTF_KEYUP, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
if ((it.second.targetShortcut.GetWinKey(it.second.winKeyInvoked) != it.first.GetWinKey(it.second.winKeyInvoked)) && it.second.targetShortcut.GetWinKey(it.second.winKeyInvoked) != NULL)
|
||||
{
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.second.targetShortcut.GetWinKey(it.second.winKeyInvoked), KEYEVENTF_KEYUP, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Key up for all new shortcut keys, key down for original shortcut modifiers and dummy key but common keys aren't repeated
|
||||
key_count = (dest_size) + (src_size - 1) + 1 - (2 * commonKeys.size());
|
||||
key_count = (dest_size) + (src_size - 1) + 1 - (2 * (size_t)commonKeys);
|
||||
keyEventList = new INPUT[key_count]();
|
||||
memset(keyEventList, 0, sizeof(keyEventList));
|
||||
|
||||
// Release new shortcut state (release in reverse order of shortcut to be accurate)
|
||||
long long i = 0;
|
||||
long long j = (long long)dest_size - 1;
|
||||
while (j >= 0 && i < (long long)(dest_size - commonKeys.size()))
|
||||
int i = 0;
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.second.targetShortcut.GetActionKey(), KEYEVENTF_KEYUP, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
if ((it.second.targetShortcut.GetShiftKey() != it.first.GetShiftKey()) && it.second.targetShortcut.GetShiftKey() != NULL)
|
||||
{
|
||||
// Release only those keys which are not common
|
||||
if (std::find(commonKeys.begin(), commonKeys.end(), it.second.first[j]) == commonKeys.end())
|
||||
{
|
||||
keyEventList[i].type = INPUT_KEYBOARD;
|
||||
keyEventList[i].ki.wVk = it.second.first[j];
|
||||
keyEventList[i].ki.dwFlags = KEYEVENTF_KEYUP;
|
||||
keyEventList[i].ki.dwExtraInfo = KEYBOARDMANAGER_SHORTCUT_FLAG;
|
||||
i++;
|
||||
}
|
||||
j--;
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.second.targetShortcut.GetShiftKey(), KEYEVENTF_KEYUP, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
if ((it.second.targetShortcut.GetAltKey() != it.first.GetAltKey()) && it.second.targetShortcut.GetAltKey() != NULL)
|
||||
{
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.second.targetShortcut.GetAltKey(), KEYEVENTF_KEYUP, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
if ((it.second.targetShortcut.GetCtrlKey() != it.first.GetCtrlKey()) && it.second.targetShortcut.GetCtrlKey() != NULL)
|
||||
{
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.second.targetShortcut.GetCtrlKey(), KEYEVENTF_KEYUP, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
if ((it.second.targetShortcut.GetWinKey(it.second.winKeyInvoked) != it.first.GetWinKey(it.second.winKeyInvoked)) && it.second.targetShortcut.GetWinKey(it.second.winKeyInvoked) != NULL)
|
||||
{
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.second.targetShortcut.GetWinKey(it.second.winKeyInvoked), KEYEVENTF_KEYUP, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
|
||||
// Set old shortcut key down state
|
||||
j = 0;
|
||||
while (i < (long long)key_count)
|
||||
|
||||
if ((it.second.targetShortcut.GetWinKey(it.second.winKeyInvoked) != it.first.GetWinKey(it.second.winKeyInvoked)) && it.first.GetWinKey(it.second.winKeyInvoked) != NULL)
|
||||
{
|
||||
// Key down only those keys which are not common
|
||||
if (std::find(commonKeys.begin(), commonKeys.end(), it.first[j]) == commonKeys.end())
|
||||
{
|
||||
keyEventList[i].type = INPUT_KEYBOARD;
|
||||
keyEventList[i].ki.wVk = (WORD)it.first[j];
|
||||
keyEventList[i].ki.dwFlags = 0;
|
||||
keyEventList[i].ki.dwExtraInfo = KEYBOARDMANAGER_SHORTCUT_FLAG;
|
||||
i++;
|
||||
}
|
||||
j++;
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.first.GetWinKey(it.second.winKeyInvoked), 0, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
if ((it.second.targetShortcut.GetCtrlKey() != it.first.GetCtrlKey()) && it.first.GetCtrlKey() != NULL)
|
||||
{
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.first.GetCtrlKey(), 0, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
if ((it.second.targetShortcut.GetAltKey() != it.first.GetAltKey()) && it.first.GetAltKey() != NULL)
|
||||
{
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.first.GetAltKey(), 0, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
if ((it.second.targetShortcut.GetShiftKey() != it.first.GetShiftKey()) && it.first.GetShiftKey() != NULL)
|
||||
{
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)it.first.GetShiftKey(), 0, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
|
||||
// Send dummy key
|
||||
keyEventList[key_count - 1].type = INPUT_KEYBOARD;
|
||||
keyEventList[key_count - 1].ki.wVk = (WORD)DUMMY_KEY;
|
||||
keyEventList[key_count - 1].ki.dwFlags = KEYEVENTF_KEYUP;
|
||||
keyEventList[key_count - 1].ki.dwExtraInfo = KEYBOARDMANAGER_SHORTCUT_FLAG;
|
||||
SetKeyEvent(keyEventList, i, INPUT_KEYBOARD, (WORD)DUMMY_KEY, KEYEVENTF_KEYUP, KEYBOARDMANAGER_SHORTCUT_FLAG);
|
||||
i++;
|
||||
}
|
||||
|
||||
it.second.second = false;
|
||||
it.second.isShortcutInvoked = false;
|
||||
it.second.winKeyInvoked = ModifierKey::Disabled;
|
||||
lock.unlock();
|
||||
UINT res = SendInput((UINT)key_count, keyEventList, sizeof(INPUT));
|
||||
delete[] keyEventList;
|
||||
|
@ -854,6 +826,7 @@ public:
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> lock(keyboardManagerState.appSpecificShortcutReMap_mutex);
|
||||
auto it = keyboardManagerState.appSpecificShortcutReMap.find(process_name);
|
||||
if (it != keyboardManagerState.appSpecificShortcutReMap.end())
|
||||
|
|
|
@ -133,17 +133,17 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa
|
|||
for (unsigned int i = 1; i < shortcutTable.Children().Size(); i++)
|
||||
{
|
||||
StackPanel currentRow = shortcutTable.Children().GetAt(i).as<StackPanel>();
|
||||
hstring originalShortcut = currentRow.Children().GetAt(0).as<StackPanel>().Children().GetAt(1).as<TextBlock>().Text();
|
||||
hstring newShortcut = currentRow.Children().GetAt(1).as<StackPanel>().Children().GetAt(1).as<TextBlock>().Text();
|
||||
if (!originalShortcut.empty() && !newShortcut.empty())
|
||||
hstring originalShortcutText = currentRow.Children().GetAt(0).as<StackPanel>().Children().GetAt(1).as<TextBlock>().Text();
|
||||
hstring newShortcutText = currentRow.Children().GetAt(1).as<StackPanel>().Children().GetAt(1).as<TextBlock>().Text();
|
||||
if (!originalShortcutText.empty() && !newShortcutText.empty())
|
||||
{
|
||||
std::vector<DWORD> originalKeys = convertWStringVectorToIntegerVector<DWORD>(splitwstring(originalShortcut.c_str(), L' '));
|
||||
std::vector<WORD> newKeys = convertWStringVectorToIntegerVector<WORD>(splitwstring(newShortcut.c_str(), L' '));
|
||||
Shortcut originalShortcut = Shortcut::CreateShortcut(originalShortcutText);
|
||||
Shortcut newShortcut = Shortcut::CreateShortcut(newShortcutText);
|
||||
|
||||
// Shortcut should consist of atleast two keys
|
||||
if (originalKeys.size() > 1 && newKeys.size() > 1)
|
||||
// Shortcut should be valid
|
||||
if (originalShortcut.IsValidShortcut() && originalShortcut.IsValidShortcut())
|
||||
{
|
||||
bool result = keyboardManagerState.AddOSLevelShortcut(originalKeys, newKeys);
|
||||
bool result = keyboardManagerState.AddOSLevelShortcut(originalShortcut, newShortcut);
|
||||
if (!result)
|
||||
{
|
||||
isSuccess = false;
|
||||
|
@ -186,7 +186,7 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa
|
|||
std::unique_lock<std::mutex> lock(keyboardManagerState.osLevelShortcutReMap_mutex);
|
||||
for (const auto& it : keyboardManagerState.osLevelShortcutReMap)
|
||||
{
|
||||
ShortcutControl::AddNewShortcutControlRow(shortcutTable, it.first, it.second.first);
|
||||
ShortcutControl::AddNewShortcutControlRow(shortcutTable, it.first, it.second.targetShortcut);
|
||||
}
|
||||
lock.unlock();
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ HWND ShortcutControl::EditShortcutsWindowHandle = nullptr;
|
|||
KeyboardManagerState* ShortcutControl::keyboardManagerState = nullptr;
|
||||
|
||||
// Function to add a new row to the shortcut table. If the originalKeys and newKeys args are provided, then the displayed shortcuts are set to those values.
|
||||
void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, const std::vector<DWORD>& originalKeys, const std::vector<WORD>& newKeys)
|
||||
void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, const Shortcut& originalKeys, const Shortcut& newKeys)
|
||||
{
|
||||
// Parent element for the row
|
||||
Windows::UI::Xaml::Controls::StackPanel tableRow;
|
||||
|
@ -23,10 +23,10 @@ void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, const std::ve
|
|||
tableRow.Children().Append(newSC.getShortcutControl());
|
||||
|
||||
// Set the shortcut text if the two vectors are not empty (i.e. default args)
|
||||
if (!originalKeys.empty() && !newKeys.empty())
|
||||
if (!originalKeys.IsEmpty() && !newKeys.IsEmpty())
|
||||
{
|
||||
originalSC.shortcutText.Text(convertVectorToHstring<DWORD>(originalKeys));
|
||||
newSC.shortcutText.Text(convertVectorToHstring<WORD>(newKeys));
|
||||
originalSC.shortcutText.Text(originalKeys.ToHstring());
|
||||
newSC.shortcutText.Text(newKeys.ToHstring());
|
||||
}
|
||||
|
||||
// Delete row button
|
||||
|
@ -71,8 +71,8 @@ void ShortcutControl::createDetectShortcutWindow(IInspectable const& sender, Xam
|
|||
// OK button
|
||||
detectShortcutBox.PrimaryButtonClick([=, &keyboardManagerState](Windows::UI::Xaml::Controls::ContentDialog const& sender, ContentDialogButtonClickEventArgs const&) {
|
||||
// Save the detected shortcut in the linked text block
|
||||
std::vector<DWORD> detectedShortcutKeys = keyboardManagerState.GetDetectedShortcut();
|
||||
linkedShortcutText.Text(convertVectorToHstring<DWORD>(detectedShortcutKeys));
|
||||
Shortcut detectedShortcutKeys = keyboardManagerState.GetDetectedShortcut();
|
||||
linkedShortcutText.Text(detectedShortcutKeys.ToHstring());
|
||||
|
||||
// Reset the keyboard manager UI state
|
||||
keyboardManagerState.ResetUIState();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include <keyboardmanager/common/KeyboardManagerState.h>
|
||||
#include <keyboardManager/common/Helpers.h>
|
||||
#include <keyboardmanager/common/Shortcut.h>
|
||||
|
||||
class ShortcutControl
|
||||
{
|
||||
|
@ -38,7 +39,7 @@ public:
|
|||
}
|
||||
|
||||
// Function to add a new row to the shortcut table. If the originalKeys and newKeys args are provided, then the displayed shortcuts are set to those values.
|
||||
static void AddNewShortcutControlRow(StackPanel& parent, const std::vector<DWORD>& originalKeys = std::vector<DWORD>(), const std::vector<WORD>& newKeys = std::vector<WORD>());
|
||||
static void AddNewShortcutControlRow(StackPanel& parent, const Shortcut& originalKeys = Shortcut(), const Shortcut& newKeys = Shortcut());
|
||||
|
||||
// Function to return the stack panel element of the ShortcutControl. This is the externally visible UI element which can be used to add it to other layouts
|
||||
StackPanel getShortcutControl();
|
||||
|
|
|
@ -6,7 +6,7 @@ HWND SingleKeyRemapControl::EditKeyboardWindowHandle = nullptr;
|
|||
KeyboardManagerState* SingleKeyRemapControl::keyboardManagerState = nullptr;
|
||||
|
||||
// Function to add a new row to the remap keys table. If the originalKey and newKey args are provided, then the displayed remap keys are set to those values.
|
||||
void SingleKeyRemapControl::AddNewControlKeyRemapRow(StackPanel& parent, const DWORD& originalKey, const WORD& newKey)
|
||||
void SingleKeyRemapControl::AddNewControlKeyRemapRow(StackPanel& parent, const DWORD& originalKey, const DWORD& newKey)
|
||||
{
|
||||
// Parent element for the row
|
||||
Windows::UI::Xaml::Controls::StackPanel tableRow;
|
||||
|
|
|
@ -39,7 +39,7 @@ public:
|
|||
}
|
||||
|
||||
// Function to add a new row to the remap keys table. If the originalKey and newKey args are provided, then the displayed remap keys are set to those values.
|
||||
static void AddNewControlKeyRemapRow(StackPanel& parent, const DWORD& originalKey = NULL, const WORD& newKey = NULL);
|
||||
static void AddNewControlKeyRemapRow(StackPanel& parent, const DWORD& originalKey = NULL, const DWORD& newKey = NULL);
|
||||
|
||||
// Function to return the stack panel element of the SingleKeyRemapControl. This is the externally visible UI element which can be used to add it to other layouts
|
||||
StackPanel getSingleKeyRemapControl();
|
||||
|
|
Loading…
Reference in a new issue