mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-05 10:46:33 +02:00
[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:
@@ -1,8 +1,44 @@
|
||||
#include "pch.h"
|
||||
#include "Dialog.h"
|
||||
#include <set>
|
||||
|
||||
using namespace winrt::Windows::Foundation;
|
||||
|
||||
KeyboardManagerHelper::ErrorType Dialog::CheckIfRemappingsAreValid(const std::vector<std::pair<std::vector<std::variant<DWORD, Shortcut>>, std::wstring>>& remappings)
|
||||
{
|
||||
KeyboardManagerHelper::ErrorType isSuccess = KeyboardManagerHelper::ErrorType::NoError;
|
||||
std::map<std::wstring, std::set<std::variant<DWORD, Shortcut>>> ogKeys;
|
||||
for (int i = 0; i < remappings.size(); i++)
|
||||
{
|
||||
std::variant<DWORD, Shortcut> ogKey = remappings[i].first[0];
|
||||
std::variant<DWORD, Shortcut> newKey = remappings[i].first[1];
|
||||
std::wstring appName = remappings[i].second;
|
||||
|
||||
bool ogKeyValidity = (ogKey.index() == 0 && std::get<DWORD>(ogKey) != NULL) || (ogKey.index() == 1 && std::get<Shortcut>(ogKey).IsValidShortcut());
|
||||
bool newKeyValidity = (newKey.index() == 0 && std::get<DWORD>(newKey) != NULL) || (newKey.index() == 1 && std::get<Shortcut>(newKey).IsValidShortcut());
|
||||
|
||||
// Add new set for a new target app name
|
||||
if (ogKeys.find(appName) == ogKeys.end())
|
||||
{
|
||||
ogKeys[appName] = std::set<std::variant<DWORD, Shortcut>>();
|
||||
}
|
||||
|
||||
if (ogKeyValidity && newKeyValidity && ogKeys[appName].find(ogKey) == ogKeys[appName].end())
|
||||
{
|
||||
ogKeys[appName].insert(ogKey);
|
||||
}
|
||||
else if (ogKeyValidity && newKeyValidity && ogKeys[appName].find(ogKey) != ogKeys[appName].end())
|
||||
{
|
||||
isSuccess = KeyboardManagerHelper::ErrorType::RemapUnsuccessful;
|
||||
}
|
||||
else
|
||||
{
|
||||
isSuccess = KeyboardManagerHelper::ErrorType::RemapUnsuccessful;
|
||||
}
|
||||
}
|
||||
return isSuccess;
|
||||
}
|
||||
|
||||
IAsyncOperation<bool> Dialog::PartialRemappingConfirmationDialog(XamlRoot root, std::wstring dialogTitle)
|
||||
{
|
||||
ContentDialog confirmationDialog;
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <keyboardmanager/common/Helpers.h>
|
||||
#include <set>
|
||||
#include <variant>
|
||||
|
||||
namespace winrt::Windows::UI::Xaml
|
||||
{
|
||||
@@ -19,33 +18,7 @@ namespace winrt::Windows::UI::Xaml
|
||||
|
||||
namespace Dialog
|
||||
{
|
||||
template<typename T>
|
||||
KeyboardManagerHelper::ErrorType CheckIfRemappingsAreValid(
|
||||
const std::vector<std::vector<T>>& remappings,
|
||||
std::function<bool(T)> isValid)
|
||||
{
|
||||
KeyboardManagerHelper::ErrorType isSuccess = KeyboardManagerHelper::ErrorType::NoError;
|
||||
std::set<T> ogKeys;
|
||||
for (int i = 0; i < remappings.size(); i++)
|
||||
{
|
||||
T ogKey = remappings[i][0];
|
||||
T newKey = remappings[i][1];
|
||||
|
||||
if (isValid(ogKey) && isValid(newKey) && ogKeys.find(ogKey) == ogKeys.end())
|
||||
{
|
||||
ogKeys.insert(ogKey);
|
||||
}
|
||||
else if (isValid(ogKey) && isValid(newKey) && ogKeys.find(ogKey) != ogKeys.end())
|
||||
{
|
||||
isSuccess = KeyboardManagerHelper::ErrorType::RemapUnsuccessful;
|
||||
}
|
||||
else
|
||||
{
|
||||
isSuccess = KeyboardManagerHelper::ErrorType::RemapUnsuccessful;
|
||||
}
|
||||
}
|
||||
return isSuccess;
|
||||
}
|
||||
KeyboardManagerHelper::ErrorType CheckIfRemappingsAreValid(const std::vector<std::pair<std::vector<std::variant<DWORD, Shortcut>>, std::wstring>>& remappings);
|
||||
|
||||
winrt::Windows::Foundation::IAsyncOperation<bool> PartialRemappingConfirmationDialog(winrt::Windows::UI::Xaml::XamlRoot root, std::wstring dialogTitle);
|
||||
};
|
||||
|
||||
@@ -35,12 +35,18 @@ static std::vector<DWORD> GetOrphanedKeys()
|
||||
|
||||
for (int i = 0; i < SingleKeyRemapControl::singleKeyRemapBuffer.size(); i++)
|
||||
{
|
||||
DWORD ogKey = SingleKeyRemapControl::singleKeyRemapBuffer[i][0];
|
||||
DWORD newKey = SingleKeyRemapControl::singleKeyRemapBuffer[i][1];
|
||||
if (ogKey != 0 && newKey != 0)
|
||||
DWORD ogKey = std::get<DWORD>(SingleKeyRemapControl::singleKeyRemapBuffer[i].first[0]);
|
||||
std::variant<DWORD, Shortcut> newKey = SingleKeyRemapControl::singleKeyRemapBuffer[i].first[1];
|
||||
|
||||
if (ogKey != NULL && ((newKey.index() == 0 && std::get<DWORD>(newKey) != 0) || (newKey.index() == 1 && std::get<Shortcut>(newKey).IsValidShortcut())))
|
||||
{
|
||||
ogKeys.insert(ogKey);
|
||||
newKeys.insert(newKey);
|
||||
|
||||
// newKey should be added only if the target is a key
|
||||
if (SingleKeyRemapControl::singleKeyRemapBuffer[i].first[1].index() == 0)
|
||||
{
|
||||
newKeys.insert(std::get<DWORD>(newKey));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,11 +92,8 @@ static IAsyncOperation<bool> OrphanKeysConfirmationDialog(
|
||||
|
||||
static IAsyncAction OnClickAccept(KeyboardManagerState& keyboardManagerState, XamlRoot root, std::function<void()> ApplyRemappings)
|
||||
{
|
||||
KeyboardManagerHelper::ErrorType isSuccess = Dialog::CheckIfRemappingsAreValid<DWORD>(
|
||||
SingleKeyRemapControl::singleKeyRemapBuffer,
|
||||
[](DWORD key) {
|
||||
return key != 0;
|
||||
});
|
||||
KeyboardManagerHelper::ErrorType isSuccess = Dialog::CheckIfRemappingsAreValid(SingleKeyRemapControl::singleKeyRemapBuffer);
|
||||
|
||||
if (isSuccess != KeyboardManagerHelper::ErrorType::NoError)
|
||||
{
|
||||
if (!co_await Dialog::PartialRemappingConfirmationDialog(root, L"Some of the keys could not be remapped. Do you want to continue anyway?"))
|
||||
@@ -98,6 +101,7 @@ static IAsyncAction OnClickAccept(KeyboardManagerState& keyboardManagerState, Xa
|
||||
co_return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for orphaned keys
|
||||
// Draw content Dialog
|
||||
std::vector<DWORD> orphanedKeys = GetOrphanedKeys();
|
||||
@@ -112,7 +116,7 @@ static IAsyncAction OnClickAccept(KeyboardManagerState& keyboardManagerState, Xa
|
||||
}
|
||||
|
||||
// Function to combine remappings if the L and R version of the modifier is mapped to the same key
|
||||
void CombineRemappings(std::unordered_map<DWORD, DWORD>& table, DWORD leftKey, DWORD rightKey, DWORD combinedKey)
|
||||
void CombineRemappings(std::unordered_map<DWORD, std::variant<DWORD, Shortcut>>& table, DWORD leftKey, DWORD rightKey, DWORD combinedKey)
|
||||
{
|
||||
if (table.find(leftKey) != table.end() && table.find(rightKey) != table.end())
|
||||
{
|
||||
@@ -127,7 +131,7 @@ void CombineRemappings(std::unordered_map<DWORD, DWORD>& table, DWORD leftKey, D
|
||||
}
|
||||
|
||||
// Function to pre process the remap table before loading it into the UI
|
||||
void PreProcessRemapTable(std::unordered_map<DWORD, DWORD>& table)
|
||||
void PreProcessRemapTable(std::unordered_map<DWORD, std::variant<DWORD, Shortcut>>& table)
|
||||
{
|
||||
// Pre process the table to combine L and R versions of Ctrl/Alt/Shift/Win that are mapped to the same key
|
||||
CombineRemappings(table, VK_LCONTROL, VK_RCONTROL, VK_CONTROL);
|
||||
@@ -234,13 +238,13 @@ void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMan
|
||||
|
||||
// Text block for information about remap key section.
|
||||
TextBlock keyRemapInfoHeader;
|
||||
keyRemapInfoHeader.Text(L"Select the key you want to change (Key) and the key you want it to become (Mapped To).");
|
||||
keyRemapInfoHeader.Text(L"Select the key you want to change (Key) and then the key or shortcut you want it to become (Mapped To).");
|
||||
keyRemapInfoHeader.Margin({ 10, 0, 0, 10 });
|
||||
keyRemapInfoHeader.FontWeight(Text::FontWeights::SemiBold());
|
||||
keyRemapInfoHeader.TextWrapping(TextWrapping::Wrap);
|
||||
|
||||
TextBlock keyRemapInfoExample;
|
||||
keyRemapInfoExample.Text(L"For example, if you want to press A and get B, Key A would be your \"Key\" and Key B would be your \"Mapped To\".");
|
||||
keyRemapInfoExample.Text(L"For example, if you want to press A and get \"Ctrl+C\", key \"A\" would be your \"Key\" column and the shortcut \"Ctrl+C\" would be your \"Mapped To\" column.");
|
||||
keyRemapInfoExample.Margin({ 10, 0, 0, 20 });
|
||||
keyRemapInfoExample.FontStyle(Text::FontStyle::Italic);
|
||||
keyRemapInfoExample.TextWrapping(TextWrapping::Wrap);
|
||||
@@ -253,8 +257,8 @@ void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMan
|
||||
ColumnDefinition arrowColumn;
|
||||
arrowColumn.MinWidth(KeyboardManagerConstants::TableArrowColWidth);
|
||||
ColumnDefinition newColumn;
|
||||
newColumn.MinWidth(KeyboardManagerConstants::RemapTableDropDownWidth);
|
||||
newColumn.MaxWidth(KeyboardManagerConstants::RemapTableDropDownWidth);
|
||||
newColumn.MinWidth(3 * KeyboardManagerConstants::ShortcutTableDropDownWidth + 2 * KeyboardManagerConstants::ShortcutTableDropDownSpacing);
|
||||
newColumn.MaxWidth(3 * KeyboardManagerConstants::ShortcutTableDropDownWidth + 2 * KeyboardManagerConstants::ShortcutTableDropDownSpacing);
|
||||
ColumnDefinition removeColumn;
|
||||
removeColumn.MinWidth(KeyboardManagerConstants::TableRemoveColWidth);
|
||||
keyRemapTable.Margin({ 10, 10, 10, 20 });
|
||||
@@ -300,7 +304,7 @@ void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMan
|
||||
|
||||
// Load existing remaps into UI
|
||||
std::unique_lock<std::mutex> lock(keyboardManagerState.singleKeyReMap_mutex);
|
||||
std::unordered_map<DWORD, DWORD> singleKeyRemapCopy = keyboardManagerState.singleKeyReMap;
|
||||
std::unordered_map<DWORD, std::variant<DWORD, Shortcut>> singleKeyRemapCopy = keyboardManagerState.singleKeyReMap;
|
||||
lock.unlock();
|
||||
PreProcessRemapTable(singleKeyRemapCopy);
|
||||
|
||||
@@ -322,13 +326,14 @@ void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMan
|
||||
KeyboardManagerHelper::ErrorType isSuccess = KeyboardManagerHelper::ErrorType::NoError;
|
||||
// Clear existing Key Remaps
|
||||
keyboardManagerState.ClearSingleKeyRemaps();
|
||||
DWORD successfulRemapCount = 0;
|
||||
DWORD successfulKeyToKeyRemapCount = 0;
|
||||
DWORD successfulKeyToShortcutRemapCount = 0;
|
||||
for (int i = 0; i < SingleKeyRemapControl::singleKeyRemapBuffer.size(); i++)
|
||||
{
|
||||
DWORD originalKey = SingleKeyRemapControl::singleKeyRemapBuffer[i][0];
|
||||
DWORD newKey = SingleKeyRemapControl::singleKeyRemapBuffer[i][1];
|
||||
DWORD originalKey = std::get<DWORD>(SingleKeyRemapControl::singleKeyRemapBuffer[i].first[0]);
|
||||
std::variant<DWORD, Shortcut> newKey = SingleKeyRemapControl::singleKeyRemapBuffer[i].first[1];
|
||||
|
||||
if (originalKey != NULL && newKey != NULL)
|
||||
if (originalKey != NULL && !(newKey.index() == 0 && std::get<DWORD>(newKey) == NULL) && !(newKey.index() == 1 && !std::get<Shortcut>(newKey).IsValidShortcut()))
|
||||
{
|
||||
// If Ctrl/Alt/Shift are added, add their L and R versions instead to the same key
|
||||
bool result = false;
|
||||
@@ -366,7 +371,14 @@ void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMan
|
||||
}
|
||||
else
|
||||
{
|
||||
successfulRemapCount += 1;
|
||||
if (newKey.index() == 0)
|
||||
{
|
||||
successfulKeyToKeyRemapCount += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
successfulKeyToShortcutRemapCount += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -375,7 +387,7 @@ void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMan
|
||||
}
|
||||
}
|
||||
|
||||
Trace::KeyRemapCount(successfulRemapCount);
|
||||
Trace::KeyRemapCount(successfulKeyToKeyRemapCount, successfulKeyToShortcutRemapCount);
|
||||
// Save the updated shortcuts remaps to file.
|
||||
bool saveResult = keyboardManagerState.SaveConfigToFile();
|
||||
if (!saveResult)
|
||||
|
||||
@@ -31,36 +31,7 @@ static IAsyncAction OnClickAccept(
|
||||
XamlRoot root,
|
||||
std::function<void()> ApplyRemappings)
|
||||
{
|
||||
KeyboardManagerHelper::ErrorType isSuccess = KeyboardManagerHelper::ErrorType::NoError;
|
||||
std::map<std::wstring, std::vector<std::vector<Shortcut>>> appSpecificBuffer;
|
||||
|
||||
// Create per app shortcut buffer
|
||||
for (int i = 0; i < ShortcutControl::shortcutRemapBuffer.size(); i++)
|
||||
{
|
||||
std::wstring currAppName = ShortcutControl::shortcutRemapBuffer[i].second;
|
||||
std::transform(currAppName.begin(), currAppName.end(), currAppName.begin(), towlower);
|
||||
|
||||
if (appSpecificBuffer.find(currAppName) == appSpecificBuffer.end())
|
||||
{
|
||||
appSpecificBuffer[currAppName] = std::vector<std::vector<Shortcut>>();
|
||||
}
|
||||
|
||||
appSpecificBuffer[currAppName].push_back(ShortcutControl::shortcutRemapBuffer[i].first);
|
||||
}
|
||||
|
||||
for (auto it : appSpecificBuffer)
|
||||
{
|
||||
KeyboardManagerHelper::ErrorType currentSuccess = Dialog::CheckIfRemappingsAreValid<Shortcut>(
|
||||
it.second,
|
||||
[](Shortcut shortcut) {
|
||||
return shortcut.IsValidShortcut();
|
||||
});
|
||||
if (currentSuccess != KeyboardManagerHelper::ErrorType::NoError)
|
||||
{
|
||||
isSuccess = currentSuccess;
|
||||
break;
|
||||
}
|
||||
}
|
||||
KeyboardManagerHelper::ErrorType isSuccess = Dialog::CheckIfRemappingsAreValid(ShortcutControl::shortcutRemapBuffer);
|
||||
|
||||
if (isSuccess != KeyboardManagerHelper::ErrorType::NoError)
|
||||
{
|
||||
@@ -171,13 +142,13 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa
|
||||
|
||||
// Text block for information about remap key section.
|
||||
TextBlock shortcutRemapInfoHeader;
|
||||
shortcutRemapInfoHeader.Text(L"Select shortcut you want to change (Shortcut) and the shortcut you want it to invoke (Mapped To).");
|
||||
shortcutRemapInfoHeader.Text(L"Select the shortcut you want to change (Shortcut) and then the key or shortcut you want it to invoke (Mapped To).");
|
||||
shortcutRemapInfoHeader.Margin({ 10, 0, 0, 10 });
|
||||
shortcutRemapInfoHeader.FontWeight(Text::FontWeights::SemiBold());
|
||||
shortcutRemapInfoHeader.TextWrapping(TextWrapping::Wrap);
|
||||
|
||||
TextBlock shortcutRemapInfoExample;
|
||||
shortcutRemapInfoExample.Text(L"For example, if you want Ctrl+C to paste, Ctrl+C is the \"Shortcut\" and Ctrl+V would be your \"Mapped To\".");
|
||||
shortcutRemapInfoExample.Text(L"For example, if you want to press \"Ctrl+C\" and get \"Alt\" only on Microsoft Edge, \"Ctrl+C\" would be your \"Shortcut\" column, the key \"Alt\" would be your \"Mapped To\" column, and \"MSEdge\" would be your \"Target App\" column. If no target app is entered, it will apply globally. The name must be the process name and not the app name.");
|
||||
shortcutRemapInfoExample.Margin({ 10, 0, 0, 20 });
|
||||
shortcutRemapInfoExample.FontStyle(Text::FontStyle::Italic);
|
||||
shortcutRemapInfoExample.TextWrapping(TextWrapping::Wrap);
|
||||
@@ -285,15 +256,17 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa
|
||||
// Clear existing shortcuts
|
||||
keyboardManagerState.ClearOSLevelShortcuts();
|
||||
keyboardManagerState.ClearAppSpecificShortcuts();
|
||||
DWORD successfulOSLevelRemapCount = 0;
|
||||
DWORD successfulAppSpecificRemapCount = 0;
|
||||
DWORD successfulOSLevelShortcutToShortcutRemapCount = 0;
|
||||
DWORD successfulOSLevelShortcutToKeyRemapCount = 0;
|
||||
DWORD successfulAppSpecificShortcutToShortcutRemapCount = 0;
|
||||
DWORD successfulAppSpecificShortcutToKeyRemapCount = 0;
|
||||
// Save the shortcuts that are valid and report if any of them were invalid
|
||||
for (int i = 0; i < ShortcutControl::shortcutRemapBuffer.size(); i++)
|
||||
{
|
||||
Shortcut originalShortcut = ShortcutControl::shortcutRemapBuffer[i].first[0];
|
||||
Shortcut newShortcut = ShortcutControl::shortcutRemapBuffer[i].first[1];
|
||||
Shortcut originalShortcut = std::get<Shortcut>(ShortcutControl::shortcutRemapBuffer[i].first[0]);
|
||||
std::variant<DWORD, Shortcut> newShortcut = ShortcutControl::shortcutRemapBuffer[i].first[1];
|
||||
|
||||
if (originalShortcut.IsValidShortcut() && newShortcut.IsValidShortcut())
|
||||
if (originalShortcut.IsValidShortcut() && ((newShortcut.index() == 0 && std::get<DWORD>(newShortcut) != NULL) || (newShortcut.index() == 1 && std::get<Shortcut>(newShortcut).IsValidShortcut())))
|
||||
{
|
||||
if (ShortcutControl::shortcutRemapBuffer[i].second == L"")
|
||||
{
|
||||
@@ -304,7 +277,14 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa
|
||||
}
|
||||
else
|
||||
{
|
||||
successfulOSLevelRemapCount += 1;
|
||||
if (newShortcut.index() == 0)
|
||||
{
|
||||
successfulOSLevelShortcutToKeyRemapCount += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
successfulOSLevelShortcutToShortcutRemapCount += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -316,7 +296,14 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa
|
||||
}
|
||||
else
|
||||
{
|
||||
successfulAppSpecificRemapCount += 1;
|
||||
if (newShortcut.index() == 0)
|
||||
{
|
||||
successfulAppSpecificShortcutToKeyRemapCount += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
successfulAppSpecificShortcutToShortcutRemapCount += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -327,8 +314,8 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa
|
||||
}
|
||||
|
||||
// Telemetry events
|
||||
Trace::OSLevelShortcutRemapCount(successfulOSLevelRemapCount);
|
||||
Trace::AppSpecificShortcutRemapCount(successfulAppSpecificRemapCount);
|
||||
Trace::OSLevelShortcutRemapCount(successfulOSLevelShortcutToShortcutRemapCount, successfulOSLevelShortcutToKeyRemapCount);
|
||||
Trace::AppSpecificShortcutRemapCount(successfulAppSpecificShortcutToShortcutRemapCount, successfulAppSpecificShortcutToKeyRemapCount);
|
||||
|
||||
// Save the updated key remaps to file.
|
||||
bool saveResult = keyboardManagerState.SaveConfigToFile();
|
||||
|
||||
@@ -53,7 +53,7 @@ void KeyDropDownControl::CheckAndUpdateKeyboardLayout(ComboBox currentDropDown,
|
||||
}
|
||||
|
||||
// Function to set selection handler for single key remap drop down. Needs to be called after the constructor since the singleKeyControl StackPanel is null if called in the constructor
|
||||
void KeyDropDownControl::SetSelectionHandler(Grid& table, StackPanel singleKeyControl, int colIndex, std::vector<std::vector<DWORD>>& singleKeyRemapBuffer)
|
||||
void KeyDropDownControl::SetSelectionHandler(Grid& table, StackPanel singleKeyControl, int colIndex, std::vector<std::pair<std::vector<std::variant<DWORD, Shortcut>>, std::wstring>>& singleKeyRemapBuffer)
|
||||
{
|
||||
// drop down selection handler
|
||||
auto onSelectionChange = [&, table, singleKeyControl, colIndex](winrt::Windows::Foundation::IInspectable const& sender) {
|
||||
@@ -70,11 +70,16 @@ void KeyDropDownControl::SetSelectionHandler(Grid& table, StackPanel singleKeyCo
|
||||
if (selectedKeyIndex != -1 && keyCodeList.size() > selectedKeyIndex)
|
||||
{
|
||||
// Check if the value being set is the same as the other column
|
||||
if (singleKeyRemapBuffer[rowIndex][std::abs(int(colIndex) - 1)] == keyCodeList[selectedKeyIndex])
|
||||
if (singleKeyRemapBuffer[rowIndex].first[std::abs(int(colIndex) - 1)].index() == 0)
|
||||
{
|
||||
errorType = KeyboardManagerHelper::ErrorType::MapToSameKey;
|
||||
if (std::get<DWORD>(singleKeyRemapBuffer[rowIndex].first[std::abs(int(colIndex) - 1)]) == keyCodeList[selectedKeyIndex])
|
||||
{
|
||||
errorType = KeyboardManagerHelper::ErrorType::MapToSameKey;
|
||||
}
|
||||
}
|
||||
|
||||
// If one column is shortcut and other is key no warning required
|
||||
|
||||
if (errorType == KeyboardManagerHelper::ErrorType::NoError && colIndex == 0)
|
||||
{
|
||||
// Check if the key is already remapped to something else
|
||||
@@ -82,11 +87,18 @@ void KeyDropDownControl::SetSelectionHandler(Grid& table, StackPanel singleKeyCo
|
||||
{
|
||||
if (i != rowIndex)
|
||||
{
|
||||
KeyboardManagerHelper::ErrorType result = KeyboardManagerHelper::DoKeysOverlap(singleKeyRemapBuffer[i][colIndex], keyCodeList[selectedKeyIndex]);
|
||||
if (result != KeyboardManagerHelper::ErrorType::NoError)
|
||||
if (singleKeyRemapBuffer[i].first[colIndex].index() == 0)
|
||||
{
|
||||
errorType = result;
|
||||
break;
|
||||
KeyboardManagerHelper::ErrorType result = KeyboardManagerHelper::DoKeysOverlap(std::get<DWORD>(singleKeyRemapBuffer[i].first[colIndex]), keyCodeList[selectedKeyIndex]);
|
||||
if (result != KeyboardManagerHelper::ErrorType::NoError)
|
||||
{
|
||||
errorType = result;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// check key to shortcut error
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -95,17 +107,17 @@ void KeyDropDownControl::SetSelectionHandler(Grid& table, StackPanel singleKeyCo
|
||||
// If there is no error, set the buffer
|
||||
if (errorType == KeyboardManagerHelper::ErrorType::NoError)
|
||||
{
|
||||
singleKeyRemapBuffer[rowIndex][colIndex] = keyCodeList[selectedKeyIndex];
|
||||
singleKeyRemapBuffer[rowIndex].first[colIndex] = keyCodeList[selectedKeyIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
singleKeyRemapBuffer[rowIndex][colIndex] = NULL;
|
||||
singleKeyRemapBuffer[rowIndex].first[colIndex] = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reset to null if the key is not found
|
||||
singleKeyRemapBuffer[rowIndex][colIndex] = NULL;
|
||||
singleKeyRemapBuffer[rowIndex].first[colIndex] = NULL;
|
||||
}
|
||||
|
||||
if (errorType != KeyboardManagerHelper::ErrorType::NoError)
|
||||
@@ -130,7 +142,7 @@ void KeyDropDownControl::SetSelectionHandler(Grid& table, StackPanel singleKeyCo
|
||||
});
|
||||
}
|
||||
|
||||
std::pair<KeyboardManagerHelper::ErrorType, int> KeyDropDownControl::ValidateShortcutSelection(Grid table, StackPanel shortcutControl, StackPanel parent, int colIndex, std::vector<std::pair<std::vector<Shortcut>, std::wstring>>& shortcutRemapBuffer, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects, TextBox targetApp)
|
||||
std::pair<KeyboardManagerHelper::ErrorType, int> KeyDropDownControl::ValidateShortcutSelection(Grid table, StackPanel shortcutControl, StackPanel parent, int colIndex, std::vector<std::pair<std::vector<std::variant<DWORD, Shortcut>>, std::wstring>>& shortcutRemapBuffer, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects, TextBox targetApp, bool isHybridControl, bool isSingleKeyWindow)
|
||||
{
|
||||
ComboBox currentDropDown = dropDown.as<ComboBox>();
|
||||
int selectedKeyIndex = currentDropDown.SelectedIndex();
|
||||
@@ -145,11 +157,18 @@ std::pair<KeyboardManagerHelper::ErrorType, int> KeyDropDownControl::ValidateSho
|
||||
|
||||
if (controlIindexFound)
|
||||
{
|
||||
rowIndex = (controlIndex - KeyboardManagerConstants::ShortcutTableHeaderCount) / KeyboardManagerConstants::ShortcutTableColCount;
|
||||
if (isSingleKeyWindow)
|
||||
{
|
||||
rowIndex = (controlIndex - KeyboardManagerConstants::RemapTableHeaderCount) / KeyboardManagerConstants::RemapTableColCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
rowIndex = (controlIndex - KeyboardManagerConstants::ShortcutTableHeaderCount) / KeyboardManagerConstants::ShortcutTableColCount;
|
||||
}
|
||||
if (selectedKeyIndex != -1 && keyCodeList.size() > selectedKeyIndex && dropDownFound)
|
||||
{
|
||||
// If only 1 drop down and action key is chosen: Warn that a modifier must be chosen
|
||||
if (parent.Children().Size() == 1 && !KeyboardManagerHelper::IsModifierKey(keyCodeList[selectedKeyIndex]))
|
||||
// If only 1 drop down and action key is chosen: Warn that a modifier must be chosen (if the drop down is not for a hybrid scenario)
|
||||
if (parent.Children().Size() == 1 && !KeyboardManagerHelper::IsModifierKey(keyCodeList[selectedKeyIndex]) && !isHybridControl)
|
||||
{
|
||||
// warn and reset the drop down
|
||||
errorType = KeyboardManagerHelper::ErrorType::ShortcutStartWithModifier;
|
||||
@@ -169,7 +188,7 @@ std::pair<KeyboardManagerHelper::ErrorType, int> KeyDropDownControl::ValidateSho
|
||||
// If not, add a new drop down
|
||||
else
|
||||
{
|
||||
AddDropDown(table, shortcutControl, parent, colIndex, shortcutRemapBuffer, keyDropDownControlObjects, targetApp);
|
||||
AddDropDown(table, shortcutControl, parent, colIndex, shortcutRemapBuffer, keyDropDownControlObjects, targetApp, isHybridControl, isSingleKeyWindow);
|
||||
}
|
||||
}
|
||||
// If last drop down and a modifier is selected but there are already max drop downs: warn the user
|
||||
@@ -181,8 +200,18 @@ std::pair<KeyboardManagerHelper::ErrorType, int> KeyDropDownControl::ValidateSho
|
||||
// If None is selected but it's the last index: warn
|
||||
else if (keyCodeList[selectedKeyIndex] == 0)
|
||||
{
|
||||
// warn and reset the drop down
|
||||
errorType = KeyboardManagerHelper::ErrorType::ShortcutOneActionKey;
|
||||
// If it is a hybrid control and there are 2 drop downs then deletion is allowed
|
||||
if (isHybridControl && parent.Children().Size() == KeyboardManagerConstants::MinShortcutSize)
|
||||
{
|
||||
// set delete drop down flag
|
||||
IsDeleteDropDownRequired = true;
|
||||
// do not delete the drop down now since there may be some other error which would cause the drop down to be invalid after removal
|
||||
}
|
||||
else
|
||||
{
|
||||
// warn and reset the drop down
|
||||
errorType = KeyboardManagerHelper::ErrorType::ShortcutOneActionKey;
|
||||
}
|
||||
}
|
||||
// If none of the above, then the action key will be set
|
||||
}
|
||||
@@ -208,11 +237,21 @@ std::pair<KeyboardManagerHelper::ErrorType, int> KeyDropDownControl::ValidateSho
|
||||
}
|
||||
else if (keyCodeList[selectedKeyIndex] == 0 && parent.Children().Size() <= KeyboardManagerConstants::MinShortcutSize)
|
||||
{
|
||||
// warn and reset the drop down
|
||||
errorType = KeyboardManagerHelper::ErrorType::ShortcutAtleast2Keys;
|
||||
// If it is a hybrid control and there are 2 drop downs then deletion is allowed
|
||||
if (isHybridControl && parent.Children().Size() == KeyboardManagerConstants::MinShortcutSize)
|
||||
{
|
||||
// set delete drop down flag
|
||||
IsDeleteDropDownRequired = true;
|
||||
// do not delete the drop down now since there may be some other error which would cause the drop down to be invalid after removal
|
||||
}
|
||||
else
|
||||
{
|
||||
// warn and reset the drop down
|
||||
errorType = KeyboardManagerHelper::ErrorType::ShortcutAtleast2Keys;
|
||||
}
|
||||
}
|
||||
// If the user tries to set an action key check if all drop down menus after this are empty if it is not the first key
|
||||
else if (dropDownIndex != 0)
|
||||
// If the user tries to set an action key check if all drop down menus after this are empty if it is not the first key. If it is a hybrid control, this can be done even on the first key
|
||||
else if (dropDownIndex != 0 || isHybridControl)
|
||||
{
|
||||
bool isClear = true;
|
||||
for (int i = dropDownIndex + 1; i < (int)parent.Children().Size(); i++)
|
||||
@@ -254,9 +293,22 @@ std::pair<KeyboardManagerHelper::ErrorType, int> KeyDropDownControl::ValidateSho
|
||||
// After validating the shortcut, now for errors like remap to same shortcut, remap shortcut more than once, Win L and Ctrl Alt Del
|
||||
if (errorType == KeyboardManagerHelper::ErrorType::NoError)
|
||||
{
|
||||
Shortcut tempShortcut;
|
||||
tempShortcut.SetKeyCodes(GetKeysFromStackPanel(parent));
|
||||
std::wstring appName = targetApp.Text().c_str();
|
||||
std::variant<DWORD, Shortcut> tempShortcut;
|
||||
std::vector<DWORD> selectedKeyCodes = GetKeysFromStackPanel(parent);
|
||||
if (isHybridControl && selectedKeyCodes.size() == 1)
|
||||
{
|
||||
tempShortcut = selectedKeyCodes[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
tempShortcut = Shortcut();
|
||||
std::get<Shortcut>(tempShortcut).SetKeyCodes(GetKeysFromStackPanel(parent));
|
||||
}
|
||||
std::wstring appName;
|
||||
if (targetApp != nullptr)
|
||||
{
|
||||
appName = targetApp.Text().c_str();
|
||||
}
|
||||
// Convert app name to lower case
|
||||
std::transform(appName.begin(), appName.end(), appName.begin(), towlower);
|
||||
std::wstring lowercaseDefAppName = KeyboardManagerConstants::DefaultAppName;
|
||||
@@ -266,10 +318,32 @@ std::pair<KeyboardManagerHelper::ErrorType, int> KeyDropDownControl::ValidateSho
|
||||
appName = L"";
|
||||
}
|
||||
|
||||
// Check if the value being set is the same as the other column
|
||||
if (shortcutRemapBuffer[rowIndex].first[std::abs(int(colIndex) - 1)] == tempShortcut && shortcutRemapBuffer[rowIndex].first[std::abs(int(colIndex) - 1)].IsValidShortcut() && tempShortcut.IsValidShortcut())
|
||||
// Check if the value being set is the same as the other column - index of other column does not have to be checked since only one column is hybrid
|
||||
if (tempShortcut.index() == 1)
|
||||
{
|
||||
errorType = KeyboardManagerHelper::ErrorType::MapToSameShortcut;
|
||||
// If shortcut to shortcut
|
||||
if (shortcutRemapBuffer[rowIndex].first[std::abs(int(colIndex) - 1)].index() == 1)
|
||||
{
|
||||
if (std::get<Shortcut>(shortcutRemapBuffer[rowIndex].first[std::abs(int(colIndex) - 1)]) == std::get<Shortcut>(tempShortcut) && std::get<Shortcut>(shortcutRemapBuffer[rowIndex].first[std::abs(int(colIndex) - 1)]).IsValidShortcut() && std::get<Shortcut>(tempShortcut).IsValidShortcut())
|
||||
{
|
||||
errorType = KeyboardManagerHelper::ErrorType::MapToSameShortcut;
|
||||
}
|
||||
}
|
||||
|
||||
// If one column is shortcut and other is key no warning required
|
||||
}
|
||||
else
|
||||
{
|
||||
// If key to key
|
||||
if (shortcutRemapBuffer[rowIndex].first[std::abs(int(colIndex) - 1)].index() == 0)
|
||||
{
|
||||
if (std::get<DWORD>(shortcutRemapBuffer[rowIndex].first[std::abs(int(colIndex) - 1)]) == std::get<DWORD>(tempShortcut) && std::get<DWORD>(shortcutRemapBuffer[rowIndex].first[std::abs(int(colIndex) - 1)]) != NULL && std::get<DWORD>(tempShortcut) != NULL)
|
||||
{
|
||||
errorType = KeyboardManagerHelper::ErrorType::MapToSameKey;
|
||||
}
|
||||
}
|
||||
|
||||
// If one column is shortcut and other is key no warning required
|
||||
}
|
||||
|
||||
if (errorType == KeyboardManagerHelper::ErrorType::NoError && colIndex == 0)
|
||||
@@ -282,7 +356,29 @@ std::pair<KeyboardManagerHelper::ErrorType, int> KeyDropDownControl::ValidateSho
|
||||
|
||||
if (i != rowIndex && currAppName == appName)
|
||||
{
|
||||
KeyboardManagerHelper::ErrorType result = Shortcut::DoKeysOverlap(shortcutRemapBuffer[i].first[colIndex], tempShortcut);
|
||||
KeyboardManagerHelper::ErrorType result = KeyboardManagerHelper::ErrorType::NoError;
|
||||
if (!isHybridControl)
|
||||
{
|
||||
result = Shortcut::DoKeysOverlap(std::get<Shortcut>(shortcutRemapBuffer[i].first[colIndex]), std::get<Shortcut>(tempShortcut));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tempShortcut.index() == 0 && shortcutRemapBuffer[i].first[colIndex].index() == 0)
|
||||
{
|
||||
if (std::get<DWORD>(tempShortcut) != NULL && std::get<DWORD>(shortcutRemapBuffer[i].first[colIndex]) != NULL)
|
||||
{
|
||||
result = KeyboardManagerHelper::DoKeysOverlap(std::get<DWORD>(shortcutRemapBuffer[i].first[colIndex]), std::get<DWORD>(tempShortcut));
|
||||
}
|
||||
}
|
||||
else if (tempShortcut.index() == 1 && shortcutRemapBuffer[i].first[colIndex].index() == 1)
|
||||
{
|
||||
if (std::get<Shortcut>(tempShortcut).IsValidShortcut() && std::get<Shortcut>(shortcutRemapBuffer[i].first[colIndex]).IsValidShortcut())
|
||||
{
|
||||
result = Shortcut::DoKeysOverlap(std::get<Shortcut>(shortcutRemapBuffer[i].first[colIndex]), std::get<Shortcut>(tempShortcut));
|
||||
}
|
||||
}
|
||||
// Other scenarios not possible since key to shortcut is with key to key, and shortcut to key is with shortcut to shortcut
|
||||
}
|
||||
if (result != KeyboardManagerHelper::ErrorType::NoError)
|
||||
{
|
||||
errorType = result;
|
||||
@@ -292,9 +388,9 @@ std::pair<KeyboardManagerHelper::ErrorType, int> KeyDropDownControl::ValidateSho
|
||||
}
|
||||
}
|
||||
|
||||
if (errorType == KeyboardManagerHelper::ErrorType::NoError)
|
||||
if (errorType == KeyboardManagerHelper::ErrorType::NoError && tempShortcut.index() == 1)
|
||||
{
|
||||
errorType = tempShortcut.IsShortcutIllegal();
|
||||
errorType = std::get<Shortcut>(tempShortcut).IsShortcutIllegal();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,10 +413,10 @@ std::pair<KeyboardManagerHelper::ErrorType, int> KeyDropDownControl::ValidateSho
|
||||
}
|
||||
|
||||
// Function to set selection handler for shortcut drop down. Needs to be called after the constructor since the shortcutControl StackPanel is null if called in the constructor
|
||||
void KeyDropDownControl::SetSelectionHandler(Grid& table, StackPanel shortcutControl, StackPanel parent, int colIndex, std::vector<std::pair<std::vector<Shortcut>, std::wstring>>& shortcutRemapBuffer, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects, TextBox& targetApp)
|
||||
void KeyDropDownControl::SetSelectionHandler(Grid& table, StackPanel shortcutControl, StackPanel parent, int colIndex, std::vector<std::pair<std::vector<std::variant<DWORD, Shortcut>>, std::wstring>>& shortcutRemapBuffer, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects, TextBox& targetApp, bool isHybridControl, bool isSingleKeyWindow)
|
||||
{
|
||||
auto onSelectionChange = [&, table, shortcutControl, colIndex, parent, targetApp](winrt::Windows::Foundation::IInspectable const& sender) {
|
||||
std::pair<KeyboardManagerHelper::ErrorType, int> validationResult = ValidateShortcutSelection(table, shortcutControl, parent, colIndex, shortcutRemapBuffer, keyDropDownControlObjects, targetApp);
|
||||
auto onSelectionChange = [&, table, shortcutControl, colIndex, parent, targetApp, isHybridControl, isSingleKeyWindow](winrt::Windows::Foundation::IInspectable const& sender) {
|
||||
std::pair<KeyboardManagerHelper::ErrorType, int> validationResult = ValidateShortcutSelection(table, shortcutControl, parent, colIndex, shortcutRemapBuffer, keyDropDownControlObjects, targetApp, isHybridControl, isSingleKeyWindow);
|
||||
|
||||
// Check if the drop down row index was identified from the return value of validateSelection
|
||||
if (validationResult.second != -1)
|
||||
@@ -329,22 +425,44 @@ void KeyDropDownControl::SetSelectionHandler(Grid& table, StackPanel shortcutCon
|
||||
if (validationResult.first != KeyboardManagerHelper::ErrorType::NoError)
|
||||
{
|
||||
// Validate all the drop downs
|
||||
ValidateShortcutFromDropDownList(table, shortcutControl, parent, colIndex, shortcutRemapBuffer, keyDropDownControlObjects, targetApp);
|
||||
ValidateShortcutFromDropDownList(table, shortcutControl, parent, colIndex, shortcutRemapBuffer, keyDropDownControlObjects, targetApp, isHybridControl, isSingleKeyWindow);
|
||||
}
|
||||
|
||||
// Reset the buffer based on the new selected drop down items
|
||||
shortcutRemapBuffer[validationResult.second].first[colIndex].SetKeyCodes(GetKeysFromStackPanel(parent));
|
||||
std::wstring newText = targetApp.Text().c_str();
|
||||
std::wstring lowercaseDefAppName = KeyboardManagerConstants::DefaultAppName;
|
||||
std::transform(newText.begin(), newText.end(), newText.begin(), towlower);
|
||||
std::transform(lowercaseDefAppName.begin(), lowercaseDefAppName.end(), lowercaseDefAppName.begin(), towlower);
|
||||
if (newText == lowercaseDefAppName)
|
||||
std::vector selectedKeyCodes = GetKeysFromStackPanel(parent);
|
||||
if (!isHybridControl)
|
||||
{
|
||||
shortcutRemapBuffer[validationResult.second].second = L"";
|
||||
std::get<Shortcut>(shortcutRemapBuffer[validationResult.second].first[colIndex]).SetKeyCodes(selectedKeyCodes);
|
||||
}
|
||||
else
|
||||
{
|
||||
shortcutRemapBuffer[validationResult.second].second = targetApp.Text().c_str();
|
||||
// If exactly one key is selected consider it to be a key remap
|
||||
if (selectedKeyCodes.size() == 1)
|
||||
{
|
||||
shortcutRemapBuffer[validationResult.second].first[colIndex] = selectedKeyCodes[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
Shortcut tempShortcut;
|
||||
tempShortcut.SetKeyCodes(selectedKeyCodes);
|
||||
// Assign instead of setting the value in the buffer since the previous value may not be a Shortcut
|
||||
shortcutRemapBuffer[validationResult.second].first[colIndex] = tempShortcut;
|
||||
}
|
||||
}
|
||||
if (targetApp != nullptr)
|
||||
{
|
||||
std::wstring newText = targetApp.Text().c_str();
|
||||
std::wstring lowercaseDefAppName = KeyboardManagerConstants::DefaultAppName;
|
||||
std::transform(newText.begin(), newText.end(), newText.begin(), towlower);
|
||||
std::transform(lowercaseDefAppName.begin(), lowercaseDefAppName.end(), lowercaseDefAppName.begin(), towlower);
|
||||
if (newText == lowercaseDefAppName)
|
||||
{
|
||||
shortcutRemapBuffer[validationResult.second].second = L"";
|
||||
}
|
||||
else
|
||||
{
|
||||
shortcutRemapBuffer[validationResult.second].second = targetApp.Text().c_str();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -389,11 +507,11 @@ ComboBox KeyDropDownControl::GetComboBox()
|
||||
}
|
||||
|
||||
// Function to add a drop down to the shortcut stack panel
|
||||
void KeyDropDownControl::AddDropDown(Grid table, StackPanel shortcutControl, StackPanel parent, const int colIndex, std::vector<std::pair<std::vector<Shortcut>, std::wstring>>& shortcutRemapBuffer, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects, TextBox& targetApp)
|
||||
void KeyDropDownControl::AddDropDown(Grid table, StackPanel shortcutControl, StackPanel parent, const int colIndex, std::vector<std::pair<std::vector<std::variant<DWORD, Shortcut>>, std::wstring>>& shortcutRemapBuffer, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects, TextBox targetApp, bool isHybridControl, bool isSingleKeyWindow)
|
||||
{
|
||||
keyDropDownControlObjects.push_back(std::move(std::unique_ptr<KeyDropDownControl>(new KeyDropDownControl(true))));
|
||||
parent.Children().Append(keyDropDownControlObjects[keyDropDownControlObjects.size() - 1]->GetComboBox());
|
||||
keyDropDownControlObjects[keyDropDownControlObjects.size() - 1]->SetSelectionHandler(table, shortcutControl, parent, colIndex, shortcutRemapBuffer, keyDropDownControlObjects, targetApp);
|
||||
keyDropDownControlObjects[keyDropDownControlObjects.size() - 1]->SetSelectionHandler(table, shortcutControl, parent, colIndex, shortcutRemapBuffer, keyDropDownControlObjects, targetApp, isHybridControl, isSingleKeyWindow);
|
||||
parent.UpdateLayout();
|
||||
}
|
||||
|
||||
@@ -455,19 +573,29 @@ bool KeyDropDownControl::CheckRepeatedModifier(StackPanel parent, int selectedKe
|
||||
}
|
||||
|
||||
// Function for validating the selection of shortcuts for all the associated drop downs
|
||||
void KeyDropDownControl::ValidateShortcutFromDropDownList(Grid table, StackPanel shortcutControl, StackPanel parent, int colIndex, std::vector<std::pair<std::vector<Shortcut>, std::wstring>>& shortcutRemapBuffer, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects, TextBox targetApp)
|
||||
void KeyDropDownControl::ValidateShortcutFromDropDownList(Grid table, StackPanel shortcutControl, StackPanel parent, int colIndex, std::vector<std::pair<std::vector<std::variant<DWORD, Shortcut>>, std::wstring>>& shortcutRemapBuffer, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects, TextBox targetApp, bool isHybridControl, bool isSingleKeyWindow)
|
||||
{
|
||||
// Iterate over all drop downs from left to right in that row/col and validate if there is an error in any of the drop downs. After this the state should be error-free (if it is a valid shortcut)
|
||||
for (int i = 0; i < keyDropDownControlObjects.size(); i++)
|
||||
{
|
||||
// Check for errors only if the current selection is a valid shortcut
|
||||
Shortcut tempComputedShortcut;
|
||||
tempComputedShortcut.SetKeyCodes(keyDropDownControlObjects[i]->GetKeysFromStackPanel(parent));
|
||||
|
||||
// If the shortcut is valid and that drop down is not empty
|
||||
if (tempComputedShortcut.IsValidShortcut() && keyDropDownControlObjects[i]->GetComboBox().SelectedIndex() != -1)
|
||||
std::vector<DWORD> selectedKeyCodes = keyDropDownControlObjects[i]->GetKeysFromStackPanel(parent);
|
||||
std::variant<DWORD, Shortcut> currentShortcut;
|
||||
if (selectedKeyCodes.size() == 1 && isHybridControl)
|
||||
{
|
||||
keyDropDownControlObjects[i]->ValidateShortcutSelection(table, shortcutControl, parent, colIndex, shortcutRemapBuffer, keyDropDownControlObjects, targetApp);
|
||||
currentShortcut = selectedKeyCodes[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
Shortcut temp;
|
||||
temp.SetKeyCodes(selectedKeyCodes);
|
||||
currentShortcut = temp;
|
||||
}
|
||||
|
||||
// If the key/shortcut is valid and that drop down is not empty
|
||||
if (((currentShortcut.index() == 0 && std::get<DWORD>(currentShortcut) != NULL) || (currentShortcut.index() == 1 && std::get<Shortcut>(currentShortcut).IsValidShortcut())) && keyDropDownControlObjects[i]->GetComboBox().SelectedIndex() != -1)
|
||||
{
|
||||
keyDropDownControlObjects[i]->ValidateShortcutSelection(table, shortcutControl, parent, colIndex, shortcutRemapBuffer, keyDropDownControlObjects, targetApp, isHybridControl, isSingleKeyWindow);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -479,3 +607,33 @@ void KeyDropDownControl::SetDropDownError(ComboBox currentDropDown, hstring mess
|
||||
warningMessage.as<TextBlock>().Text(message);
|
||||
currentDropDown.ContextFlyout().ShowAttachedFlyout((FrameworkElement)dropDown.as<ComboBox>());
|
||||
}
|
||||
|
||||
// Function to add a shortcut to the UI control as combo boxes
|
||||
void KeyDropDownControl::AddShortcutToControl(Shortcut shortcut, Grid table, StackPanel parent, KeyboardManagerState& keyboardManagerState, const int colIndex, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects, std::vector<std::pair<std::vector<std::variant<DWORD, Shortcut>>, std::wstring>>& remapBuffer, StackPanel controlLayout, TextBox targetApp, bool isHybridControl, bool isSingleKeyWindow)
|
||||
{
|
||||
// Delete the existing drop down menus
|
||||
parent.Children().Clear();
|
||||
// Remove references to the old drop down objects to destroy them
|
||||
keyDropDownControlObjects.clear();
|
||||
|
||||
std::vector<DWORD> shortcutKeyCodes = shortcut.GetKeyCodes();
|
||||
std::vector<DWORD> keyCodeList = keyboardManagerState.keyboardMap.GetKeyCodeList(true);
|
||||
if (shortcutKeyCodes.size() != 0)
|
||||
{
|
||||
KeyDropDownControl::AddDropDown(table, controlLayout, parent, colIndex, remapBuffer, keyDropDownControlObjects, targetApp, isHybridControl, isSingleKeyWindow);
|
||||
for (int i = 0; i < shortcutKeyCodes.size(); i++)
|
||||
{
|
||||
// New drop down gets added automatically when the SelectedIndex is set
|
||||
if (i < (int)parent.Children().Size())
|
||||
{
|
||||
ComboBox currentDropDown = parent.Children().GetAt(i).as<ComboBox>();
|
||||
auto it = std::find(keyCodeList.begin(), keyCodeList.end(), shortcutKeyCodes[i]);
|
||||
if (it != keyCodeList.end())
|
||||
{
|
||||
currentDropDown.SelectedIndex((int32_t)std::distance(keyCodeList.begin(), it));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
parent.UpdateLayout();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include <keyboardmanager/common/Shortcut.h>
|
||||
#include <variant>
|
||||
class KeyboardManagerState;
|
||||
class Shortcut;
|
||||
|
||||
namespace winrt::Windows
|
||||
{
|
||||
@@ -56,13 +57,13 @@ public:
|
||||
}
|
||||
|
||||
// Function to set selection handler for single key remap drop down. Needs to be called after the constructor since the singleKeyControl StackPanel is null if called in the constructor
|
||||
void SetSelectionHandler(winrt::Windows::UI::Xaml::Controls::Grid& table, winrt::Windows::UI::Xaml::Controls::StackPanel singleKeyControl, int colIndex, std::vector<std::vector<DWORD>>& singleKeyRemapBuffer);
|
||||
void SetSelectionHandler(winrt::Windows::UI::Xaml::Controls::Grid& table, winrt::Windows::UI::Xaml::Controls::StackPanel singleKeyControl, int colIndex, std::vector<std::pair<std::vector<std::variant<DWORD, Shortcut>>, std::wstring>>& singleKeyRemapBuffer);
|
||||
|
||||
// Function for validating the selection of shortcuts for the drop down
|
||||
std::pair<KeyboardManagerHelper::ErrorType, int> ValidateShortcutSelection(winrt::Windows::UI::Xaml::Controls::Grid table, winrt::Windows::UI::Xaml::Controls::StackPanel shortcutControl, winrt::Windows::UI::Xaml::Controls::StackPanel parent, int colIndex, std::vector<std::pair<std::vector<Shortcut>, std::wstring>>& shortcutRemapBuffer, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects, winrt::Windows::UI::Xaml::Controls::TextBox targetApp);
|
||||
std::pair<KeyboardManagerHelper::ErrorType, int> ValidateShortcutSelection(winrt::Windows::UI::Xaml::Controls::Grid table, winrt::Windows::UI::Xaml::Controls::StackPanel shortcutControl, winrt::Windows::UI::Xaml::Controls::StackPanel parent, int colIndex, std::vector<std::pair<std::vector<std::variant<DWORD, Shortcut>>, std::wstring>>& shortcutRemapBuffer, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects, winrt::Windows::UI::Xaml::Controls::TextBox targetApp, bool isHybridControl, bool isSingleKeyWindow);
|
||||
|
||||
// Function to set selection handler for shortcut drop down. Needs to be called after the constructor since the shortcutControl StackPanel is null if called in the constructor
|
||||
void SetSelectionHandler(winrt::Windows::UI::Xaml::Controls::Grid& table, winrt::Windows::UI::Xaml::Controls::StackPanel shortcutControl, winrt::Windows::UI::Xaml::Controls::StackPanel parent, int colIndex, std::vector<std::pair<std::vector<Shortcut>, std::wstring>>& shortcutRemapBuffer, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects, winrt::Windows::UI::Xaml::Controls::TextBox& targetApp);
|
||||
void SetSelectionHandler(winrt::Windows::UI::Xaml::Controls::Grid& table, winrt::Windows::UI::Xaml::Controls::StackPanel shortcutControl, winrt::Windows::UI::Xaml::Controls::StackPanel parent, int colIndex, std::vector<std::pair<std::vector<std::variant<DWORD, Shortcut>>, std::wstring>>& shortcutRemapBuffer, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects, winrt::Windows::UI::Xaml::Controls::TextBox& targetApp, bool isHybridControl, bool isSingleKeyWindow);
|
||||
|
||||
// Function to set the selected index of the drop down
|
||||
void SetSelectedIndex(int32_t index);
|
||||
@@ -71,7 +72,7 @@ public:
|
||||
ComboBox GetComboBox();
|
||||
|
||||
// Function to add a drop down to the shortcut stack panel
|
||||
static void AddDropDown(winrt::Windows::UI::Xaml::Controls::Grid table, winrt::Windows::UI::Xaml::Controls::StackPanel shortcutControl, winrt::Windows::UI::Xaml::Controls::StackPanel parent, const int colIndex, std::vector<std::pair<std::vector<Shortcut>, std::wstring>>& shortcutRemapBuffer, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects, winrt::Windows::UI::Xaml::Controls::TextBox& targetApp);
|
||||
static void AddDropDown(winrt::Windows::UI::Xaml::Controls::Grid table, winrt::Windows::UI::Xaml::Controls::StackPanel shortcutControl, winrt::Windows::UI::Xaml::Controls::StackPanel parent, const int colIndex, std::vector<std::pair<std::vector<std::variant<DWORD, Shortcut>>, std::wstring>>& shortcutRemapBuffer, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects, winrt::Windows::UI::Xaml::Controls::TextBox targetApp, bool isHybridControl, bool isSingleKeyWindow);
|
||||
|
||||
// Function to get the list of key codes from the shortcut combo box stack panel
|
||||
static std::vector<DWORD> GetKeysFromStackPanel(StackPanel parent);
|
||||
@@ -80,8 +81,11 @@ public:
|
||||
static bool CheckRepeatedModifier(winrt::Windows::UI::Xaml::Controls::StackPanel parent, int selectedKeyIndex, const std::vector<DWORD>& keyCodeList);
|
||||
|
||||
// Function for validating the selection of shortcuts for all the associated drop downs
|
||||
static void ValidateShortcutFromDropDownList(Grid table, StackPanel shortcutControl, StackPanel parent, int colIndex, std::vector<std::pair<std::vector<Shortcut>, std::wstring>>& shortcutRemapBuffer, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects, TextBox targetApp);
|
||||
static void ValidateShortcutFromDropDownList(Grid table, StackPanel shortcutControl, StackPanel parent, int colIndex, std::vector<std::pair<std::vector<std::variant<DWORD, Shortcut>>, std::wstring>>& shortcutRemapBuffer, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects, TextBox targetApp, bool isHybridControl, bool isSingleKeyWindow);
|
||||
|
||||
// Function to set the warning message
|
||||
void SetDropDownError(winrt::Windows::UI::Xaml::Controls::ComboBox currentDropDown, winrt::hstring message);
|
||||
|
||||
// Function to add a shortcut to the UI control as combo boxes
|
||||
static void AddShortcutToControl(Shortcut shortcut, Grid table, StackPanel parent, KeyboardManagerState& keyboardManagerState, const int colIndex, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects, std::vector<std::pair<std::vector<std::variant<DWORD, Shortcut>>, std::wstring>>& remapBuffer, StackPanel controlLayout, TextBox targetApp, bool isHybridControl, bool isSingleKeyWindow);
|
||||
};
|
||||
|
||||
@@ -2,28 +2,30 @@
|
||||
#include "ShortcutControl.h"
|
||||
#include "KeyDropDownControl.h"
|
||||
#include "keyboardmanager/common/KeyboardManagerState.h"
|
||||
#include "keyboardmanager/common/Helpers.h"
|
||||
|
||||
//Both static members are initialized to null
|
||||
HWND ShortcutControl::EditShortcutsWindowHandle = nullptr;
|
||||
KeyboardManagerState* ShortcutControl::keyboardManagerState = nullptr;
|
||||
// Initialized as new vector
|
||||
std::vector<std::pair<std::vector<Shortcut>, std::wstring>> ShortcutControl::shortcutRemapBuffer;
|
||||
std::vector<std::pair<std::vector<std::variant<DWORD, Shortcut>>, std::wstring>> ShortcutControl::shortcutRemapBuffer;
|
||||
|
||||
ShortcutControl::ShortcutControl(Grid table, const int colIndex, TextBox targetApp)
|
||||
{
|
||||
shortcutDropDownStackPanel = StackPanel();
|
||||
typeShortcut = Button();
|
||||
shortcutControlLayout = StackPanel();
|
||||
bool isHybridControl = colIndex == 1 ? true : false;
|
||||
|
||||
shortcutDropDownStackPanel.as<StackPanel>().Spacing(KeyboardManagerConstants::ShortcutTableDropDownSpacing);
|
||||
shortcutDropDownStackPanel.as<StackPanel>().Orientation(Windows::UI::Xaml::Controls::Orientation::Horizontal);
|
||||
|
||||
typeShortcut.as<Button>().Content(winrt::box_value(L"Type Shortcut"));
|
||||
typeShortcut.as<Button>().Content(winrt::box_value(L"Type"));
|
||||
typeShortcut.as<Button>().Width(KeyboardManagerConstants::ShortcutTableDropDownWidth);
|
||||
typeShortcut.as<Button>().Click([&, table, colIndex, targetApp](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
typeShortcut.as<Button>().Click([&, table, colIndex, isHybridControl, targetApp](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
keyboardManagerState->SetUIState(KeyboardManagerUIState::DetectShortcutWindowActivated, EditShortcutsWindowHandle);
|
||||
// Using the XamlRoot of the typeShortcut to get the root of the XAML host
|
||||
createDetectShortcutWindow(sender, sender.as<Button>().XamlRoot(), shortcutRemapBuffer, *keyboardManagerState, colIndex, table, targetApp);
|
||||
createDetectShortcutWindow(sender, sender.as<Button>().XamlRoot(), *keyboardManagerState, colIndex, table, keyDropDownControlObjects, shortcutControlLayout.as<StackPanel>(), targetApp, isHybridControl, false, EditShortcutsWindowHandle, shortcutRemapBuffer);
|
||||
});
|
||||
|
||||
shortcutControlLayout.as<StackPanel>().Margin({ 0, 0, 0, 10 });
|
||||
@@ -31,12 +33,12 @@ ShortcutControl::ShortcutControl(Grid table, const int colIndex, TextBox targetA
|
||||
|
||||
shortcutControlLayout.as<StackPanel>().Children().Append(typeShortcut.as<Button>());
|
||||
shortcutControlLayout.as<StackPanel>().Children().Append(shortcutDropDownStackPanel.as<StackPanel>());
|
||||
KeyDropDownControl::AddDropDown(table, shortcutControlLayout.as<StackPanel>(), shortcutDropDownStackPanel.as<StackPanel>(), colIndex, shortcutRemapBuffer, keyDropDownControlObjects, targetApp);
|
||||
KeyDropDownControl::AddDropDown(table, shortcutControlLayout.as<StackPanel>(), shortcutDropDownStackPanel.as<StackPanel>(), colIndex, shortcutRemapBuffer, keyDropDownControlObjects, targetApp, isHybridControl, false);
|
||||
shortcutControlLayout.as<StackPanel>().UpdateLayout();
|
||||
}
|
||||
|
||||
// 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(Grid& parent, std::vector<std::vector<std::unique_ptr<ShortcutControl>>>& keyboardRemapControlObjects, Shortcut originalKeys, Shortcut newKeys, std::wstring targetAppName)
|
||||
void ShortcutControl::AddNewShortcutControlRow(Grid& parent, std::vector<std::vector<std::unique_ptr<ShortcutControl>>>& keyboardRemapControlObjects, const Shortcut& originalKeys, const std::variant<DWORD, Shortcut>& newKeys, const std::wstring& targetAppName)
|
||||
{
|
||||
// Textbox for target application
|
||||
TextBox targetAppTextBox;
|
||||
@@ -87,12 +89,26 @@ void ShortcutControl::AddNewShortcutControlRow(Grid& parent, std::vector<std::ve
|
||||
int rowIndex = (lastIndexInRow - KeyboardManagerConstants::ShortcutTableHeaderCount) / KeyboardManagerConstants::ShortcutTableColCount;
|
||||
|
||||
// Validate both set of drop downs
|
||||
KeyDropDownControl::ValidateShortcutFromDropDownList(parent, keyboardRemapControlObjects[rowIndex][0]->getShortcutControl(), keyboardRemapControlObjects[rowIndex][0]->shortcutDropDownStackPanel.as<StackPanel>(), 0, ShortcutControl::shortcutRemapBuffer, keyboardRemapControlObjects[rowIndex][0]->keyDropDownControlObjects, targetAppTextBox);
|
||||
KeyDropDownControl::ValidateShortcutFromDropDownList(parent, keyboardRemapControlObjects[rowIndex][1]->getShortcutControl(), keyboardRemapControlObjects[rowIndex][1]->shortcutDropDownStackPanel.as<StackPanel>(), 1, ShortcutControl::shortcutRemapBuffer, keyboardRemapControlObjects[rowIndex][1]->keyDropDownControlObjects, targetAppTextBox);
|
||||
KeyDropDownControl::ValidateShortcutFromDropDownList(parent, keyboardRemapControlObjects[rowIndex][0]->getShortcutControl(), keyboardRemapControlObjects[rowIndex][0]->shortcutDropDownStackPanel.as<StackPanel>(), 0, ShortcutControl::shortcutRemapBuffer, keyboardRemapControlObjects[rowIndex][0]->keyDropDownControlObjects, targetAppTextBox, false, false);
|
||||
KeyDropDownControl::ValidateShortcutFromDropDownList(parent, keyboardRemapControlObjects[rowIndex][1]->getShortcutControl(), keyboardRemapControlObjects[rowIndex][1]->shortcutDropDownStackPanel.as<StackPanel>(), 1, ShortcutControl::shortcutRemapBuffer, keyboardRemapControlObjects[rowIndex][1]->keyDropDownControlObjects, targetAppTextBox, true, false);
|
||||
|
||||
// Reset the buffer based on the selected drop down items
|
||||
shortcutRemapBuffer[rowIndex].first[0].SetKeyCodes(KeyDropDownControl::GetKeysFromStackPanel(keyboardRemapControlObjects[rowIndex][0]->shortcutDropDownStackPanel.as<StackPanel>()));
|
||||
shortcutRemapBuffer[rowIndex].first[1].SetKeyCodes(KeyDropDownControl::GetKeysFromStackPanel(keyboardRemapControlObjects[rowIndex][1]->shortcutDropDownStackPanel.as<StackPanel>()));
|
||||
std::get<Shortcut>(shortcutRemapBuffer[rowIndex].first[0]).SetKeyCodes(KeyDropDownControl::GetKeysFromStackPanel(keyboardRemapControlObjects[rowIndex][0]->shortcutDropDownStackPanel.as<StackPanel>()));
|
||||
// second column is a hybrid column
|
||||
std::vector<DWORD> selectedKeyCodes = KeyDropDownControl::GetKeysFromStackPanel(keyboardRemapControlObjects[rowIndex][1]->shortcutDropDownStackPanel.as<StackPanel>());
|
||||
|
||||
// If exactly one key is selected consider it to be a key remap
|
||||
if (selectedKeyCodes.size() == 1)
|
||||
{
|
||||
shortcutRemapBuffer[rowIndex].first[1] = selectedKeyCodes[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
Shortcut tempShortcut;
|
||||
tempShortcut.SetKeyCodes(selectedKeyCodes);
|
||||
// Assign instead of setting the value in the buffer since the previous value may not be a Shortcut
|
||||
shortcutRemapBuffer[rowIndex].first[1] = tempShortcut;
|
||||
}
|
||||
std::wstring newText = targetAppTextBox.Text().c_str();
|
||||
std::wstring lowercaseDefAppName = KeyboardManagerConstants::DefaultAppName;
|
||||
std::transform(newText.begin(), newText.end(), newText.begin(), towlower);
|
||||
@@ -153,50 +169,33 @@ void ShortcutControl::AddNewShortcutControlRow(Grid& parent, std::vector<std::ve
|
||||
parent.UpdateLayout();
|
||||
|
||||
// Set the shortcut text if the two vectors are not empty (i.e. default args)
|
||||
if (originalKeys.IsValidShortcut() && newKeys.IsValidShortcut())
|
||||
if (originalKeys.IsValidShortcut() && !(newKeys.index() == 0 && std::get<DWORD>(newKeys) == NULL) && !(newKeys.index() == 1 && !std::get<Shortcut>(newKeys).IsValidShortcut()))
|
||||
{
|
||||
// change to load app name
|
||||
shortcutRemapBuffer.push_back(std::make_pair<std::vector<Shortcut>, std::wstring>(std::vector<Shortcut>{ Shortcut(), Shortcut() }, std::wstring(targetAppName)));
|
||||
keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][0]->AddShortcutToControl(originalKeys, parent, keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][0]->shortcutDropDownStackPanel.as<StackPanel>(), *keyboardManagerState, 0, targetAppTextBox);
|
||||
keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->AddShortcutToControl(newKeys, parent, keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->shortcutDropDownStackPanel.as<StackPanel>(), *keyboardManagerState, 1, targetAppTextBox);
|
||||
shortcutRemapBuffer.push_back(std::make_pair<std::vector<std::variant<DWORD, Shortcut>>, std::wstring>(std::vector<std::variant<DWORD, Shortcut>>{ Shortcut(), Shortcut() }, std::wstring(targetAppName)));
|
||||
KeyDropDownControl::AddShortcutToControl(originalKeys, parent, keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][0]->shortcutDropDownStackPanel.as<StackPanel>(), *keyboardManagerState, 0, keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][0]->keyDropDownControlObjects, shortcutRemapBuffer, keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][0]->shortcutControlLayout.as<StackPanel>(), targetAppTextBox, false, false);
|
||||
|
||||
if (newKeys.index() == 0)
|
||||
{
|
||||
std::vector<DWORD> shortcutListKeyCodes = keyboardManagerState->keyboardMap.GetKeyCodeList(true);
|
||||
auto it = std::find(shortcutListKeyCodes.begin(), shortcutListKeyCodes.end(), std::get<DWORD>(newKeys));
|
||||
if (it != shortcutListKeyCodes.end())
|
||||
{
|
||||
keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->keyDropDownControlObjects[0]->SetSelectedIndex((int32_t)std::distance(shortcutListKeyCodes.begin(), it));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
KeyDropDownControl::AddShortcutToControl(std::get<Shortcut>(newKeys), parent, keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->shortcutDropDownStackPanel.as<StackPanel>(), *keyboardManagerState, 1, keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->keyDropDownControlObjects, shortcutRemapBuffer, keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->shortcutControlLayout.as<StackPanel>(), targetAppTextBox, true, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Initialize both shortcuts as empty shortcuts
|
||||
shortcutRemapBuffer.push_back(std::make_pair<std::vector<Shortcut>, std::wstring>(std::vector<Shortcut>{ Shortcut(), Shortcut() }, std::wstring(targetAppName)));
|
||||
shortcutRemapBuffer.push_back(std::make_pair<std::vector<std::variant<DWORD, Shortcut>>, std::wstring>(std::vector<std::variant<DWORD, Shortcut>>{ Shortcut(), Shortcut() }, std::wstring(targetAppName)));
|
||||
}
|
||||
}
|
||||
|
||||
// Function to add a shortcut to the shortcut control as combo boxes
|
||||
void ShortcutControl::AddShortcutToControl(Shortcut& shortcut, Grid table, StackPanel parent, KeyboardManagerState& keyboardManagerState, const int colIndex, TextBox targetApp)
|
||||
{
|
||||
// Delete the existing drop down menus
|
||||
parent.Children().Clear();
|
||||
// Remove references to the old drop down objects to destroy them
|
||||
keyDropDownControlObjects.clear();
|
||||
|
||||
std::vector<DWORD> shortcutKeyCodes = shortcut.GetKeyCodes();
|
||||
std::vector<DWORD> keyCodeList = keyboardManagerState.keyboardMap.GetKeyCodeList(true);
|
||||
if (shortcutKeyCodes.size() != 0)
|
||||
{
|
||||
KeyDropDownControl::AddDropDown(table, shortcutControlLayout.as<StackPanel>(), parent, colIndex, shortcutRemapBuffer, keyDropDownControlObjects, targetApp);
|
||||
for (int i = 0; i < shortcutKeyCodes.size(); i++)
|
||||
{
|
||||
// New drop down gets added automatically when the SelectedIndex is set
|
||||
if (i < (int)parent.Children().Size())
|
||||
{
|
||||
ComboBox currentDropDown = parent.Children().GetAt(i).as<ComboBox>();
|
||||
auto it = std::find(keyCodeList.begin(), keyCodeList.end(), shortcutKeyCodes[i]);
|
||||
if (it != keyCodeList.end())
|
||||
{
|
||||
currentDropDown.SelectedIndex((int32_t)std::distance(keyCodeList.begin(), it));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
parent.UpdateLayout();
|
||||
}
|
||||
|
||||
// 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 ShortcutControl::getShortcutControl()
|
||||
{
|
||||
@@ -204,7 +203,7 @@ StackPanel ShortcutControl::getShortcutControl()
|
||||
}
|
||||
|
||||
// Function to create the detect shortcut UI window
|
||||
void ShortcutControl::createDetectShortcutWindow(winrt::Windows::Foundation::IInspectable const& sender, XamlRoot xamlRoot, std::vector<std::pair<std::vector<Shortcut>, std::wstring>>& shortcutRemapBuffer, KeyboardManagerState& keyboardManagerState, const int colIndex, Grid table, TextBox targetApp)
|
||||
void ShortcutControl::createDetectShortcutWindow(winrt::Windows::Foundation::IInspectable const& sender, XamlRoot xamlRoot, KeyboardManagerState& keyboardManagerState, const int colIndex, Grid table, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects, StackPanel controlLayout, TextBox targetApp, bool isHybridControl, bool isSingleKeyWindow, HWND parentWindow, std::vector<std::pair<std::vector<std::variant<DWORD, Shortcut>>, std::wstring>>& remapBuffer)
|
||||
{
|
||||
// ContentDialog for detecting shortcuts. This is the parent UI element.
|
||||
ContentDialog detectShortcutBox;
|
||||
@@ -215,7 +214,7 @@ void ShortcutControl::createDetectShortcutWindow(winrt::Windows::Foundation::IIn
|
||||
detectShortcutBox.IsPrimaryButtonEnabled(false);
|
||||
detectShortcutBox.IsSecondaryButtonEnabled(false);
|
||||
|
||||
// Get the linked text block for the "Type shortcut" button that was clicked
|
||||
// Get the linked stack panel for the "Type shortcut" button that was clicked
|
||||
StackPanel linkedShortcutStackPanel = KeyboardManagerHelper::getSiblingElement(sender).as<StackPanel>();
|
||||
|
||||
auto unregisterKeys = [&keyboardManagerState]() {
|
||||
@@ -230,33 +229,47 @@ void ShortcutControl::createDetectShortcutWindow(winrt::Windows::Foundation::IIn
|
||||
keyboardManagerState.ResetDetectedShortcutKey(key);
|
||||
};
|
||||
|
||||
auto onPressEnter = [this,
|
||||
linkedShortcutStackPanel,
|
||||
auto onPressEnter = [linkedShortcutStackPanel,
|
||||
detectShortcutBox,
|
||||
&keyboardManagerState,
|
||||
&shortcutRemapBuffer,
|
||||
unregisterKeys,
|
||||
colIndex,
|
||||
table,
|
||||
targetApp] {
|
||||
targetApp,
|
||||
&keyDropDownControlObjects,
|
||||
controlLayout,
|
||||
isHybridControl,
|
||||
isSingleKeyWindow,
|
||||
&remapBuffer] {
|
||||
// Save the detected shortcut in the linked text block
|
||||
Shortcut detectedShortcutKeys = keyboardManagerState.GetDetectedShortcut();
|
||||
|
||||
if (!detectedShortcutKeys.IsEmpty())
|
||||
{
|
||||
// The shortcut buffer gets set in this function
|
||||
AddShortcutToControl(detectedShortcutKeys, table, linkedShortcutStackPanel, keyboardManagerState, colIndex, targetApp);
|
||||
KeyDropDownControl::AddShortcutToControl(detectedShortcutKeys, table, linkedShortcutStackPanel, keyboardManagerState, colIndex, keyDropDownControlObjects, remapBuffer, controlLayout, targetApp, isHybridControl, isSingleKeyWindow);
|
||||
}
|
||||
// Hide the type shortcut UI
|
||||
detectShortcutBox.Hide();
|
||||
};
|
||||
|
||||
auto onReleaseEnter = [&keyboardManagerState,
|
||||
unregisterKeys] {
|
||||
unregisterKeys,
|
||||
isSingleKeyWindow,
|
||||
parentWindow] {
|
||||
// Reset the keyboard manager UI state
|
||||
keyboardManagerState.ResetUIState();
|
||||
// Revert UI state back to Edit Shortcut window
|
||||
keyboardManagerState.SetUIState(KeyboardManagerUIState::EditShortcutsWindowActivated, EditShortcutsWindowHandle);
|
||||
if (isSingleKeyWindow)
|
||||
{
|
||||
// Revert UI state back to Edit Keyboard window
|
||||
keyboardManagerState.SetUIState(KeyboardManagerUIState::EditKeyboardWindowActivated, parentWindow);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Revert UI state back to Edit Shortcut window
|
||||
keyboardManagerState.SetUIState(KeyboardManagerUIState::EditShortcutsWindowActivated, parentWindow);
|
||||
}
|
||||
|
||||
unregisterKeys();
|
||||
};
|
||||
|
||||
@@ -303,11 +316,19 @@ void ShortcutControl::createDetectShortcutWindow(winrt::Windows::Foundation::IIn
|
||||
cancelButton.Margin({ 2, 2, 2, 2 });
|
||||
cancelButton.Content(cancelButtonText);
|
||||
// Cancel button
|
||||
cancelButton.Click([detectShortcutBox, unregisterKeys, &keyboardManagerState](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
cancelButton.Click([detectShortcutBox, unregisterKeys, &keyboardManagerState, isSingleKeyWindow, parentWindow](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
// Reset the keyboard manager UI state
|
||||
keyboardManagerState.ResetUIState();
|
||||
// Revert UI state back to Edit Shortcut window
|
||||
keyboardManagerState.SetUIState(KeyboardManagerUIState::EditShortcutsWindowActivated, EditShortcutsWindowHandle);
|
||||
if (isSingleKeyWindow)
|
||||
{
|
||||
// Revert UI state back to Edit Keyboard window
|
||||
keyboardManagerState.SetUIState(KeyboardManagerUIState::EditKeyboardWindowActivated, parentWindow);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Revert UI state back to Edit Shortcut window
|
||||
keyboardManagerState.SetUIState(KeyboardManagerUIState::EditShortcutsWindowActivated, parentWindow);
|
||||
}
|
||||
unregisterKeys();
|
||||
detectShortcutBox.Hide();
|
||||
});
|
||||
@@ -315,7 +336,7 @@ void ShortcutControl::createDetectShortcutWindow(winrt::Windows::Foundation::IIn
|
||||
keyboardManagerState.RegisterKeyDelay(
|
||||
VK_ESCAPE,
|
||||
selectDetectedShortcutAndResetKeys,
|
||||
[&keyboardManagerState, detectShortcutBox, unregisterKeys](DWORD) {
|
||||
[&keyboardManagerState, detectShortcutBox, unregisterKeys, isSingleKeyWindow, parentWindow](DWORD) {
|
||||
detectShortcutBox.Dispatcher().RunAsync(
|
||||
Windows::UI::Core::CoreDispatcherPriority::Normal,
|
||||
[detectShortcutBox] {
|
||||
@@ -323,8 +344,16 @@ void ShortcutControl::createDetectShortcutWindow(winrt::Windows::Foundation::IIn
|
||||
});
|
||||
|
||||
keyboardManagerState.ResetUIState();
|
||||
// Revert UI state back to Edit Shortcut window
|
||||
keyboardManagerState.SetUIState(KeyboardManagerUIState::EditShortcutsWindowActivated, EditShortcutsWindowHandle);
|
||||
if (isSingleKeyWindow)
|
||||
{
|
||||
// Revert UI state back to Edit Keyboard window
|
||||
keyboardManagerState.SetUIState(KeyboardManagerUIState::EditKeyboardWindowActivated, parentWindow);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Revert UI state back to Edit Shortcut window
|
||||
keyboardManagerState.SetUIState(KeyboardManagerUIState::EditShortcutsWindowActivated, parentWindow);
|
||||
}
|
||||
unregisterKeys();
|
||||
},
|
||||
nullptr);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "keyboardmanager/common/Shortcut.h"
|
||||
#include <variant>
|
||||
|
||||
class KeyboardManagerState;
|
||||
class KeyDropDownControl;
|
||||
@@ -32,7 +33,7 @@ public:
|
||||
// Pointer to the keyboard manager state
|
||||
static KeyboardManagerState* keyboardManagerState;
|
||||
// Stores the current list of remappings
|
||||
static std::vector<std::pair<std::vector<Shortcut>, std::wstring>> shortcutRemapBuffer;
|
||||
static std::vector<std::pair<std::vector<std::variant<DWORD, Shortcut>>, std::wstring>> shortcutRemapBuffer;
|
||||
// Vector to store dynamically allocated KeyDropDownControl objects to avoid early destruction
|
||||
std::vector<std::unique_ptr<KeyDropDownControl>> keyDropDownControlObjects;
|
||||
|
||||
@@ -40,14 +41,11 @@ public:
|
||||
ShortcutControl(Grid table, const int colIndex, TextBox targetApp);
|
||||
|
||||
// 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(Grid& parent, std::vector<std::vector<std::unique_ptr<ShortcutControl>>>& keyboardRemapControlObjects, Shortcut originalKeys = Shortcut(), Shortcut newKeys = Shortcut(), std::wstring targetAppName = L"");
|
||||
|
||||
// Function to add a shortcut to the shortcut control as combo boxes
|
||||
void AddShortcutToControl(Shortcut& shortcut, Grid table, StackPanel parent, KeyboardManagerState& keyboardManagerState, const int colIndex, TextBox targetApp);
|
||||
static void AddNewShortcutControlRow(Grid& parent, std::vector<std::vector<std::unique_ptr<ShortcutControl>>>& keyboardRemapControlObjects, const Shortcut& originalKeys = Shortcut(), const std::variant<DWORD, Shortcut>& newKeys = Shortcut(), const std::wstring& targetAppName = L"");
|
||||
|
||||
// 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();
|
||||
|
||||
// Function to create the detect shortcut UI window
|
||||
void createDetectShortcutWindow(winrt::Windows::Foundation::IInspectable const& sender, XamlRoot xamlRoot, std::vector<std::pair<std::vector<Shortcut>, std::wstring>>& shortcutRemapBuffer, KeyboardManagerState& keyboardManagerState, const int colIndex, Grid table, TextBox targetApp);
|
||||
static void createDetectShortcutWindow(winrt::Windows::Foundation::IInspectable const& sender, XamlRoot xamlRoot, KeyboardManagerState& keyboardManagerState, const int colIndex, Grid table, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects, StackPanel controlLayout, TextBox targetApp, bool isHybridControl, bool isSingleKeyWindow, HWND parentWindow, std::vector<std::pair<std::vector<std::variant<DWORD, Shortcut>>, std::wstring>>& remapBuffer);
|
||||
};
|
||||
|
||||
@@ -3,39 +3,64 @@
|
||||
#include "keyboardmanager/common/Helpers.h"
|
||||
#include "keyboardmanager/common/KeyboardManagerConstants.h"
|
||||
#include "keyboardmanager/common/KeyboardManagerState.h"
|
||||
|
||||
#include "ShortcutControl.h"
|
||||
|
||||
//Both static members are initialized to null
|
||||
HWND SingleKeyRemapControl::EditKeyboardWindowHandle = nullptr;
|
||||
KeyboardManagerState* SingleKeyRemapControl::keyboardManagerState = nullptr;
|
||||
// Initialized as new vector
|
||||
std::vector<std::vector<DWORD>> SingleKeyRemapControl::singleKeyRemapBuffer;
|
||||
std::vector<std::pair<std::vector<std::variant<DWORD, Shortcut>>, std::wstring>> SingleKeyRemapControl::singleKeyRemapBuffer;
|
||||
|
||||
SingleKeyRemapControl::SingleKeyRemapControl(Grid table, const int colIndex) :
|
||||
singleKeyRemapDropDown(false)
|
||||
SingleKeyRemapControl::SingleKeyRemapControl(Grid table, const int colIndex)
|
||||
{
|
||||
typeKey = Button();
|
||||
typeKey.as<Button>().Content(winrt::box_value(L"Type Key"));
|
||||
typeKey.as<Button>().Width(KeyboardManagerConstants::RemapTableDropDownWidth);
|
||||
typeKey.as<Button>().Click([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
keyboardManagerState->SetUIState(KeyboardManagerUIState::DetectSingleKeyRemapWindowActivated, EditKeyboardWindowHandle);
|
||||
// Using the XamlRoot of the typeKey to get the root of the XAML host
|
||||
createDetectKeyWindow(sender, sender.as<Button>().XamlRoot(), singleKeyRemapBuffer, *keyboardManagerState);
|
||||
});
|
||||
typeKey.as<Button>().Content(winrt::box_value(L"Type"));
|
||||
|
||||
singleKeyRemapControlLayout = StackPanel();
|
||||
singleKeyRemapControlLayout.as<StackPanel>().Margin({ 0, 0, 0, 10 });
|
||||
singleKeyRemapControlLayout.as<StackPanel>().Spacing(10);
|
||||
|
||||
singleKeyRemapControlLayout.as<StackPanel>().Children().Append(typeKey.as<Button>());
|
||||
singleKeyRemapControlLayout.as<StackPanel>().Children().Append(singleKeyRemapDropDown.GetComboBox());
|
||||
// Set selection handler for the drop down
|
||||
singleKeyRemapDropDown.SetSelectionHandler(table, singleKeyRemapControlLayout.as<StackPanel>(), colIndex, singleKeyRemapBuffer);
|
||||
|
||||
// Key column
|
||||
if (colIndex == 0)
|
||||
{
|
||||
keyDropDownControlObjects.push_back(std::move(std::unique_ptr<KeyDropDownControl>(new KeyDropDownControl(false))));
|
||||
singleKeyRemapControlLayout.as<StackPanel>().Children().Append(keyDropDownControlObjects[0]->GetComboBox());
|
||||
// Set selection handler for the drop down
|
||||
keyDropDownControlObjects[0]->SetSelectionHandler(table, singleKeyRemapControlLayout.as<StackPanel>(), colIndex, singleKeyRemapBuffer);
|
||||
}
|
||||
|
||||
// Hybrid column
|
||||
else
|
||||
{
|
||||
hybridDropDownStackPanel = StackPanel();
|
||||
hybridDropDownStackPanel.as<StackPanel>().Spacing(KeyboardManagerConstants::ShortcutTableDropDownSpacing);
|
||||
hybridDropDownStackPanel.as<StackPanel>().Orientation(Windows::UI::Xaml::Controls::Orientation::Horizontal);
|
||||
KeyDropDownControl::AddDropDown(table, singleKeyRemapControlLayout.as<StackPanel>(), hybridDropDownStackPanel.as<StackPanel>(), colIndex, singleKeyRemapBuffer, keyDropDownControlObjects, nullptr, true, true);
|
||||
singleKeyRemapControlLayout.as<StackPanel>().Children().Append(hybridDropDownStackPanel.as<StackPanel>());
|
||||
}
|
||||
|
||||
StackPanel controlStackPanel = singleKeyRemapControlLayout.as<StackPanel>();
|
||||
typeKey.as<Button>().Click([&, table, colIndex, controlStackPanel](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
// Using the XamlRoot of the typeKey to get the root of the XAML host
|
||||
if (colIndex == 0)
|
||||
{
|
||||
keyboardManagerState->SetUIState(KeyboardManagerUIState::DetectSingleKeyRemapWindowActivated, EditKeyboardWindowHandle);
|
||||
createDetectKeyWindow(sender, sender.as<Button>().XamlRoot(), *keyboardManagerState);
|
||||
}
|
||||
else
|
||||
{
|
||||
keyboardManagerState->SetUIState(KeyboardManagerUIState::DetectShortcutWindowInEditKeyboardWindowActivated, EditKeyboardWindowHandle);
|
||||
ShortcutControl::createDetectShortcutWindow(sender, sender.as<Button>().XamlRoot(), *keyboardManagerState, colIndex, table, keyDropDownControlObjects, controlStackPanel, nullptr, true, true, EditKeyboardWindowHandle, singleKeyRemapBuffer);
|
||||
}
|
||||
});
|
||||
|
||||
singleKeyRemapControlLayout.as<StackPanel>().UpdateLayout();
|
||||
}
|
||||
|
||||
// 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(Grid& parent, std::vector<std::vector<std::unique_ptr<SingleKeyRemapControl>>>& keyboardRemapControlObjects, const DWORD originalKey, const DWORD newKey)
|
||||
void SingleKeyRemapControl::AddNewControlKeyRemapRow(Grid& parent, std::vector<std::vector<std::unique_ptr<SingleKeyRemapControl>>>& keyboardRemapControlObjects, const DWORD originalKey, const std::variant<DWORD, Shortcut> newKey)
|
||||
{
|
||||
// Create new SingleKeyRemapControl objects dynamically so that we does not get destructed
|
||||
std::vector<std::unique_ptr<SingleKeyRemapControl>> newrow;
|
||||
@@ -66,25 +91,33 @@ void SingleKeyRemapControl::AddNewControlKeyRemapRow(Grid& parent, std::vector<s
|
||||
parent.Children().Append(keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->getSingleKeyRemapControl());
|
||||
|
||||
// Set the key text if the two keys are not null (i.e. default args)
|
||||
if (originalKey != NULL && newKey != NULL)
|
||||
if (originalKey != NULL && !(newKey.index() == 0 && std::get<DWORD>(newKey) == NULL) && !(newKey.index() == 1 && !std::get<Shortcut>(newKey).IsValidShortcut()))
|
||||
{
|
||||
singleKeyRemapBuffer.push_back(std::vector<DWORD>{ originalKey, newKey });
|
||||
singleKeyRemapBuffer.push_back(std::make_pair<std::vector<std::variant<DWORD, Shortcut>>, std::wstring>(std::vector<std::variant<DWORD, Shortcut>>{ originalKey, newKey }, L""));
|
||||
std::vector<DWORD> keyCodes = keyboardManagerState->keyboardMap.GetKeyCodeList();
|
||||
std::vector<DWORD> shortcutListKeyCodes = keyboardManagerState->keyboardMap.GetKeyCodeList(true);
|
||||
auto it = std::find(keyCodes.begin(), keyCodes.end(), originalKey);
|
||||
if (it != keyCodes.end())
|
||||
{
|
||||
keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][0]->singleKeyRemapDropDown.SetSelectedIndex((int32_t)std::distance(keyCodes.begin(), it));
|
||||
keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][0]->keyDropDownControlObjects[0]->SetSelectedIndex((int32_t)std::distance(keyCodes.begin(), it));
|
||||
}
|
||||
it = std::find(keyCodes.begin(), keyCodes.end(), newKey);
|
||||
if (it != keyCodes.end())
|
||||
if (newKey.index() == 0)
|
||||
{
|
||||
keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->singleKeyRemapDropDown.SetSelectedIndex((int32_t)std::distance(keyCodes.begin(), it));
|
||||
it = std::find(shortcutListKeyCodes.begin(), shortcutListKeyCodes.end(), std::get<DWORD>(newKey));
|
||||
if (it != shortcutListKeyCodes.end())
|
||||
{
|
||||
keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->keyDropDownControlObjects[0]->SetSelectedIndex((int32_t)std::distance(shortcutListKeyCodes.begin(), it));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
KeyDropDownControl::AddShortcutToControl(std::get<Shortcut>(newKey), parent, keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->hybridDropDownStackPanel.as<StackPanel>(), *keyboardManagerState, 1, keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->keyDropDownControlObjects, singleKeyRemapBuffer, keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->singleKeyRemapControlLayout.as<StackPanel>(), nullptr, true, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Initialize both keys to NULL
|
||||
singleKeyRemapBuffer.push_back(std::vector<DWORD>{ NULL, NULL });
|
||||
singleKeyRemapBuffer.push_back(std::make_pair<std::vector<std::variant<DWORD, Shortcut>>, std::wstring>(std::vector<std::variant<DWORD, Shortcut>>{ NULL, NULL }, L""));
|
||||
}
|
||||
|
||||
// Delete row button
|
||||
@@ -136,7 +169,7 @@ StackPanel SingleKeyRemapControl::getSingleKeyRemapControl()
|
||||
}
|
||||
|
||||
// Function to create the detect remap key UI window
|
||||
void SingleKeyRemapControl::createDetectKeyWindow(winrt::Windows::Foundation::IInspectable const& sender, XamlRoot xamlRoot, std::vector<std::vector<DWORD>>& singleKeyRemapBuffer, KeyboardManagerState& keyboardManagerState)
|
||||
void SingleKeyRemapControl::createDetectKeyWindow(winrt::Windows::Foundation::IInspectable const& sender, XamlRoot xamlRoot, KeyboardManagerState& keyboardManagerState)
|
||||
{
|
||||
// ContentDialog for detecting remap key. This is the parent UI element.
|
||||
ContentDialog detectRemapKeyBox;
|
||||
@@ -160,7 +193,6 @@ void SingleKeyRemapControl::createDetectKeyWindow(winrt::Windows::Foundation::II
|
||||
auto onPressEnter = [linkedRemapDropDown,
|
||||
detectRemapKeyBox,
|
||||
&keyboardManagerState,
|
||||
&singleKeyRemapBuffer,
|
||||
unregisterKeys] {
|
||||
// Save the detected key in the linked text block
|
||||
DWORD detectedKey = keyboardManagerState.GetDetectedSingleRemapKey();
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
#include "KeyDropDownControl.h"
|
||||
#include <keyboardmanager/common/Shortcut.h>
|
||||
#include <variant>
|
||||
|
||||
class KeyboardManagerState;
|
||||
namespace winrt::Windows::UI::Xaml
|
||||
@@ -15,32 +17,34 @@ namespace winrt::Windows::UI::Xaml
|
||||
class SingleKeyRemapControl
|
||||
{
|
||||
private:
|
||||
// Drop down to display the selected remap key
|
||||
KeyDropDownControl singleKeyRemapDropDown;
|
||||
|
||||
// Button to type the remap key
|
||||
winrt::Windows::Foundation::IInspectable typeKey;
|
||||
|
||||
// StackPanel to parent the above controls
|
||||
winrt::Windows::Foundation::IInspectable singleKeyRemapControlLayout;
|
||||
|
||||
// Stack panel for the drop downs to display the selected shortcut for the hybrid case
|
||||
winrt::Windows::Foundation::IInspectable hybridDropDownStackPanel;
|
||||
|
||||
public:
|
||||
// Vector to store dynamically allocated KeyDropDownControl objects to avoid early destruction
|
||||
std::vector<std::unique_ptr<KeyDropDownControl>> keyDropDownControlObjects;
|
||||
// Handle to the current Edit Keyboard Window
|
||||
static HWND EditKeyboardWindowHandle;
|
||||
// Pointer to the keyboard manager state
|
||||
static KeyboardManagerState* keyboardManagerState;
|
||||
// Stores the current list of remappings
|
||||
static std::vector<std::vector<DWORD>> singleKeyRemapBuffer;
|
||||
static std::vector<std::pair<std::vector<std::variant<DWORD, Shortcut>>, std::wstring>> singleKeyRemapBuffer;
|
||||
|
||||
// constructor
|
||||
SingleKeyRemapControl(Grid table, const int colIndex);
|
||||
|
||||
// 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(winrt::Windows::UI::Xaml::Controls::Grid& parent, std::vector<std::vector<std::unique_ptr<SingleKeyRemapControl>>>& keyboardRemapControlObjects, const DWORD originalKey = NULL, const DWORD newKey = NULL);
|
||||
static void AddNewControlKeyRemapRow(winrt::Windows::UI::Xaml::Controls::Grid& parent, std::vector<std::vector<std::unique_ptr<SingleKeyRemapControl>>>& keyboardRemapControlObjects, const DWORD originalKey = NULL, const std::variant<DWORD, Shortcut> 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
|
||||
winrt::Windows::UI::Xaml::Controls::StackPanel getSingleKeyRemapControl();
|
||||
|
||||
// Function to create the detect remap keys UI window
|
||||
void createDetectKeyWindow(winrt::Windows::Foundation::IInspectable const& sender, XamlRoot xamlRoot, std::vector<std::vector<DWORD>>& singleKeyRemapBuffer, KeyboardManagerState& keyboardManagerState);
|
||||
void createDetectKeyWindow(winrt::Windows::Foundation::IInspectable const& sender, XamlRoot xamlRoot, KeyboardManagerState& keyboardManagerState);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user