mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-05 10:46:33 +02:00
[KBM]Allow remapping keys and shortcuts to arbitrary unicode sequences (#29399)
* [KBM] Allow remapping keys and shortcuts to arbitrary unicode sequences * f: spelling * f: tests * f: split shortcut configuration * f: address ui layout comments * [BugReport]Don't report personal info * f: fix crash in KBME * f: add missed type button * f: fix shortcut line UI elements alignment * f: align elements size * f: add warning about non-mapped keys
This commit is contained in:
@@ -220,7 +220,7 @@ namespace BufferValidationHelpers
|
||||
// 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 == ShortcutErrorType::NoError)
|
||||
{
|
||||
KeyShortcutUnion tempShortcut;
|
||||
KeyShortcutTextUnion tempShortcut;
|
||||
if (isHybridControl && KeyDropDownControl::GetNumberOfSelectedKeys(selectedCodes) == 1)
|
||||
{
|
||||
tempShortcut = (DWORD)*std::find_if(selectedCodes.begin(), selectedCodes.end(), [](int32_t a) { return a != -1 && a != 0; });
|
||||
|
||||
@@ -285,14 +285,21 @@ inline void CreateEditKeyboardWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMan
|
||||
|
||||
// Load existing remaps into UI
|
||||
SingleKeyRemapTable singleKeyRemapCopy = mappingConfiguration.singleKeyReMap;
|
||||
SingleKeyToTextRemapTable singleKeyToTextRemapCopy = mappingConfiguration.singleKeyToTextReMap;
|
||||
|
||||
LoadingAndSavingRemappingHelper::PreProcessRemapTable(singleKeyRemapCopy);
|
||||
LoadingAndSavingRemappingHelper::PreProcessRemapTable(singleKeyToTextRemapCopy);
|
||||
|
||||
for (const auto& it : singleKeyRemapCopy)
|
||||
{
|
||||
SingleKeyRemapControl::AddNewControlKeyRemapRow(keyRemapTable, keyboardRemapControlObjects, it.first, it.second);
|
||||
}
|
||||
|
||||
for (const auto& it : singleKeyToTextRemapCopy)
|
||||
{
|
||||
SingleKeyRemapControl::AddNewControlKeyRemapRow(keyRemapTable, keyboardRemapControlObjects, it.first, it.second);
|
||||
}
|
||||
|
||||
// Main Header Apply button
|
||||
Button applyButton;
|
||||
applyButton.Content(winrt::box_value(GET_RESOURCE_STRING(IDS_OK_BUTTON)));
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace EditorConstants
|
||||
inline const long ShortcutTableRemoveColIndex = 4;
|
||||
inline const long ShortcutArrowColumnWidth = 90;
|
||||
inline const DWORD64 ShortcutTableDropDownWidth = 160;
|
||||
inline const DWORD64 ShortcutTableDropDownSpacing = 10;
|
||||
inline const long ShortcutTableDropDownSpacing = 10;
|
||||
inline const long ShortcutOriginColumnWidth = 3 * ShortcutTableDropDownWidth + 3 * ShortcutTableDropDownSpacing;
|
||||
inline const long ShortcutTargetColumnWidth = 3 * ShortcutTableDropDownWidth + 3 * ShortcutTableDropDownSpacing + 15;
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ void KeyDropDownControl::SetDefaultProperties(bool isShortcut, bool renderDisabl
|
||||
}
|
||||
|
||||
dropDown.as<ComboBox>().MaxDropDownHeight(EditorConstants::TableDropDownHeight);
|
||||
|
||||
|
||||
// Initialise layout attribute
|
||||
previousLayout = GetKeyboardLayout(0);
|
||||
dropDown.as<ComboBox>().SelectedValuePath(L"DataContext");
|
||||
@@ -83,7 +83,20 @@ void KeyDropDownControl::SetDefaultProperties(bool isShortcut, bool renderDisabl
|
||||
// Attach the tip to the drop down
|
||||
warningTip.Target(dropDown.as<ComboBox>());
|
||||
dropDown.as<ComboBox>().Loaded([&](winrt::Windows::Foundation::IInspectable const& sender, auto args) {
|
||||
Media::VisualTreeHelper::GetChild(dropDown.as<ComboBox>(), 0).as<Grid>().Children().Append(warningTip);
|
||||
auto combo = dropDown.as<ComboBox>();
|
||||
auto child0 = Media::VisualTreeHelper::GetChild(combo, 0);
|
||||
if (!child0)
|
||||
return;
|
||||
|
||||
auto grid = child0.as<Grid>();
|
||||
if (!grid)
|
||||
return;
|
||||
|
||||
auto& gridChildren = grid.Children();
|
||||
if (!gridChildren)
|
||||
return;
|
||||
|
||||
gridChildren.Append(warningTip);
|
||||
});
|
||||
|
||||
// Tip properties
|
||||
@@ -102,7 +115,7 @@ void KeyDropDownControl::SetDefaultProperties(bool isShortcut, bool renderDisabl
|
||||
warningFlyout.as<Flyout>().FlyoutPresenterStyle(style);
|
||||
dropDown.as<ComboBox>().ContextFlyout().SetAttachedFlyout((FrameworkElement)dropDown.as<ComboBox>(), warningFlyout.as<Flyout>());
|
||||
#endif
|
||||
|
||||
|
||||
// To set the accessible name of the combo-box (by default index 1)
|
||||
SetAccessibleNameForComboBox(dropDown.as<ComboBox>(), 1);
|
||||
}
|
||||
@@ -141,7 +154,7 @@ void KeyDropDownControl::SetSelectionHandler(StackPanel& table, StackPanel row,
|
||||
|
||||
ComboBox currentDropDown = sender.as<ComboBox>();
|
||||
int selectedKeyCode = GetSelectedValue(currentDropDown);
|
||||
|
||||
|
||||
// Validate current remap selection
|
||||
ShortcutErrorType errorType = BufferValidationHelpers::ValidateAndUpdateKeyBufferElement(rowIndex, colIndex, selectedKeyCode, singleKeyRemapBuffer);
|
||||
|
||||
@@ -228,7 +241,7 @@ std::pair<ShortcutErrorType, int> KeyDropDownControl::ValidateShortcutSelection(
|
||||
}
|
||||
|
||||
parent.Children().RemoveAt(dropDownIndex);
|
||||
|
||||
|
||||
// delete drop down control object from the vector so that it can be destructed
|
||||
keyDropDownControlObjects.erase(keyDropDownControlObjects.begin() + dropDownIndex);
|
||||
}
|
||||
@@ -368,7 +381,7 @@ void KeyDropDownControl::ValidateShortcutFromDropDownList(StackPanel table, Stac
|
||||
{
|
||||
// Check for errors only if the current selection is a valid shortcut
|
||||
std::vector<int32_t> selectedKeyCodes = GetSelectedCodesFromStackPanel(parent);
|
||||
KeyShortcutUnion currentShortcut;
|
||||
KeyShortcutTextUnion currentShortcut;
|
||||
if (GetNumberOfSelectedKeys(selectedKeyCodes) == 1 && isHybridControl)
|
||||
{
|
||||
currentShortcut = (DWORD)selectedKeyCodes[0];
|
||||
@@ -415,7 +428,7 @@ void KeyDropDownControl::AddShortcutToControl(Shortcut shortcut, StackPanel tabl
|
||||
{
|
||||
// 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();
|
||||
|
||||
@@ -11,7 +11,22 @@ namespace KeyboardManagerEditorStrings
|
||||
{
|
||||
return GET_RESOURCE_STRING(IDS_EDITSHORTCUTS_ALLAPPS);
|
||||
}
|
||||
|
||||
|
||||
inline std::wstring MappingTypeText()
|
||||
{
|
||||
return GET_RESOURCE_STRING(IDS_MAPPING_TYPE_DROPDOWN_TEXT);
|
||||
}
|
||||
|
||||
inline std::wstring MappingTypeShortcut()
|
||||
{
|
||||
return GET_RESOURCE_STRING(IDS_MAPPING_TYPE_DROPDOWN_SHORTCUT);
|
||||
}
|
||||
|
||||
inline std::wstring MappingTypeKey()
|
||||
{
|
||||
return GET_RESOURCE_STRING(IDS_MAPPING_TYPE_DROPDOWN_KEY);
|
||||
}
|
||||
|
||||
// Function to return the error message
|
||||
winrt::hstring GetErrorMessage(ShortcutErrorType errorType);
|
||||
}
|
||||
|
||||
@@ -17,20 +17,20 @@ namespace LoadingAndSavingRemappingHelper
|
||||
ShortcutErrorType CheckIfRemappingsAreValid(const RemapBuffer& remappings)
|
||||
{
|
||||
ShortcutErrorType isSuccess = ShortcutErrorType::NoError;
|
||||
std::map<std::wstring, std::set<KeyShortcutUnion>> ogKeys;
|
||||
std::map<std::wstring, std::set<KeyShortcutTextUnion>> ogKeys;
|
||||
for (int i = 0; i < remappings.size(); i++)
|
||||
{
|
||||
KeyShortcutUnion ogKey = remappings[i].first[0];
|
||||
KeyShortcutUnion newKey = remappings[i].first[1];
|
||||
KeyShortcutTextUnion ogKey = remappings[i].first[0];
|
||||
KeyShortcutTextUnion newKey = remappings[i].first[1];
|
||||
std::wstring appName = remappings[i].second;
|
||||
|
||||
bool ogKeyValidity = (ogKey.index() == 0 && std::get<DWORD>(ogKey) != NULL) || (ogKey.index() == 1 && EditorHelpers::IsValidShortcut(std::get<Shortcut>(ogKey)));
|
||||
bool newKeyValidity = (newKey.index() == 0 && std::get<DWORD>(newKey) != NULL) || (newKey.index() == 1 && EditorHelpers::IsValidShortcut(std::get<Shortcut>(newKey)));
|
||||
const bool ogKeyValidity = (ogKey.index() == 0 && std::get<DWORD>(ogKey) != NULL) || (ogKey.index() == 1 && EditorHelpers::IsValidShortcut(std::get<Shortcut>(ogKey)));
|
||||
const bool newKeyValidity = (newKey.index() == 0 && std::get<DWORD>(newKey) != NULL) || (newKey.index() == 1 && EditorHelpers::IsValidShortcut(std::get<Shortcut>(newKey))) || (newKey.index() == 2 && !std::get<std::wstring>(newKey).empty());
|
||||
|
||||
// Add new set for a new target app name
|
||||
if (ogKeys.find(appName) == ogKeys.end())
|
||||
{
|
||||
ogKeys[appName] = std::set<KeyShortcutUnion>();
|
||||
ogKeys[appName] = std::set<KeyShortcutTextUnion>();
|
||||
}
|
||||
|
||||
if (ogKeyValidity && newKeyValidity && ogKeys[appName].find(ogKey) == ogKeys[appName].end())
|
||||
@@ -59,9 +59,12 @@ namespace LoadingAndSavingRemappingHelper
|
||||
for (int i = 0; i < remappings.size(); i++)
|
||||
{
|
||||
DWORD ogKey = std::get<DWORD>(remappings[i].first[0]);
|
||||
KeyShortcutUnion newKey = remappings[i].first[1];
|
||||
KeyShortcutTextUnion newKey = remappings[i].first[1];
|
||||
|
||||
if (ogKey != NULL && ((newKey.index() == 0 && std::get<DWORD>(newKey) != 0) || (newKey.index() == 1 && EditorHelpers::IsValidShortcut(std::get<Shortcut>(newKey)))))
|
||||
const bool hasValidKeyRemapping = newKey.index() == 0 && std::get<DWORD>(newKey) != 0;
|
||||
const bool hasValidShortcutRemapping = newKey.index() == 1 && EditorHelpers::IsValidShortcut(std::get<Shortcut>(newKey));
|
||||
const bool hasValidTextRemapping = newKey.index() == 2 && !std::get<std::wstring>(newKey).empty();
|
||||
if (ogKey != NULL && (hasValidKeyRemapping || hasValidShortcutRemapping || hasValidTextRemapping))
|
||||
{
|
||||
ogKeys.insert(ogKey);
|
||||
|
||||
@@ -116,53 +119,64 @@ namespace LoadingAndSavingRemappingHelper
|
||||
{
|
||||
// Clear existing Key Remaps
|
||||
mappingConfiguration.ClearSingleKeyRemaps();
|
||||
mappingConfiguration.ClearSingleKeyToTextRemaps();
|
||||
DWORD successfulKeyToKeyRemapCount = 0;
|
||||
DWORD successfulKeyToShortcutRemapCount = 0;
|
||||
DWORD successfulKeyToTextRemapCount = 0;
|
||||
for (int i = 0; i < remappings.size(); i++)
|
||||
{
|
||||
DWORD originalKey = std::get<DWORD>(remappings[i].first[0]);
|
||||
KeyShortcutUnion newKey = remappings[i].first[1];
|
||||
const DWORD originalKey = std::get<DWORD>(remappings[i].first[0]);
|
||||
KeyShortcutTextUnion newKey = remappings[i].first[1];
|
||||
|
||||
if (originalKey != NULL && !(newKey.index() == 0 && std::get<DWORD>(newKey) == NULL) && !(newKey.index() == 1 && !EditorHelpers::IsValidShortcut(std::get<Shortcut>(newKey))))
|
||||
if (originalKey != NULL && !(newKey.index() == 0 && std::get<DWORD>(newKey) == NULL) && !(newKey.index() == 1 && !EditorHelpers::IsValidShortcut(std::get<Shortcut>(newKey))) && !(newKey.index() == 2 && std::get<std::wstring>(newKey).empty()))
|
||||
{
|
||||
// If Ctrl/Alt/Shift are added, add their L and R versions instead to the same key
|
||||
bool result = false;
|
||||
bool res1, res2;
|
||||
switch (originalKey)
|
||||
std::vector<DWORD> originalKeysWithModifiers;
|
||||
if (originalKey == VK_CONTROL)
|
||||
{
|
||||
case VK_CONTROL:
|
||||
res1 = mappingConfiguration.AddSingleKeyRemap(VK_LCONTROL, newKey);
|
||||
res2 = mappingConfiguration.AddSingleKeyRemap(VK_RCONTROL, newKey);
|
||||
result = res1 && res2;
|
||||
break;
|
||||
case VK_MENU:
|
||||
res1 = mappingConfiguration.AddSingleKeyRemap(VK_LMENU, newKey);
|
||||
res2 = mappingConfiguration.AddSingleKeyRemap(VK_RMENU, newKey);
|
||||
result = res1 && res2;
|
||||
break;
|
||||
case VK_SHIFT:
|
||||
res1 = mappingConfiguration.AddSingleKeyRemap(VK_LSHIFT, newKey);
|
||||
res2 = mappingConfiguration.AddSingleKeyRemap(VK_RSHIFT, newKey);
|
||||
result = res1 && res2;
|
||||
break;
|
||||
case CommonSharedConstants::VK_WIN_BOTH:
|
||||
res1 = mappingConfiguration.AddSingleKeyRemap(VK_LWIN, newKey);
|
||||
res2 = mappingConfiguration.AddSingleKeyRemap(VK_RWIN, newKey);
|
||||
result = res1 && res2;
|
||||
break;
|
||||
default:
|
||||
result = mappingConfiguration.AddSingleKeyRemap(originalKey, newKey);
|
||||
originalKeysWithModifiers.push_back(VK_LCONTROL);
|
||||
originalKeysWithModifiers.push_back(VK_RCONTROL);
|
||||
}
|
||||
else if (originalKey == VK_MENU)
|
||||
{
|
||||
originalKeysWithModifiers.push_back(VK_LMENU);
|
||||
originalKeysWithModifiers.push_back(VK_RMENU);
|
||||
}
|
||||
else if (originalKey == VK_SHIFT)
|
||||
{
|
||||
originalKeysWithModifiers.push_back(VK_LSHIFT);
|
||||
originalKeysWithModifiers.push_back(VK_RSHIFT);
|
||||
}
|
||||
else if (originalKey == CommonSharedConstants::VK_WIN_BOTH)
|
||||
{
|
||||
originalKeysWithModifiers.push_back(VK_LWIN);
|
||||
originalKeysWithModifiers.push_back(VK_RWIN);
|
||||
}
|
||||
else
|
||||
{
|
||||
originalKeysWithModifiers.push_back(originalKey);
|
||||
}
|
||||
|
||||
for (const DWORD key : originalKeysWithModifiers)
|
||||
{
|
||||
const bool mappedToText = newKey.index() == 2;
|
||||
result = mappedToText ? mappingConfiguration.AddSingleKeyToTextRemap(key, std::get<std::wstring>(newKey)) : mappingConfiguration.AddSingleKeyRemap(key, newKey) && result;
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
if (newKey.index() == 0)
|
||||
{
|
||||
successfulKeyToKeyRemapCount += 1;
|
||||
++successfulKeyToKeyRemapCount;
|
||||
}
|
||||
else
|
||||
else if (newKey.index() == 1)
|
||||
{
|
||||
successfulKeyToShortcutRemapCount += 1;
|
||||
++successfulKeyToShortcutRemapCount;
|
||||
}
|
||||
else if (newKey.index() == 2)
|
||||
{
|
||||
++successfulKeyToTextRemapCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -171,7 +185,7 @@ namespace LoadingAndSavingRemappingHelper
|
||||
// If telemetry is to be logged, log the key remap counts
|
||||
if (isTelemetryRequired)
|
||||
{
|
||||
Trace::KeyRemapCount(successfulKeyToKeyRemapCount, successfulKeyToShortcutRemapCount);
|
||||
Trace::KeyRemapCount(successfulKeyToKeyRemapCount, successfulKeyToShortcutRemapCount, successfulKeyToTextRemapCount);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,14 +199,14 @@ namespace LoadingAndSavingRemappingHelper
|
||||
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 < remappings.size(); i++)
|
||||
{
|
||||
Shortcut originalShortcut = std::get<Shortcut>(remappings[i].first[0]);
|
||||
KeyShortcutUnion newShortcut = remappings[i].first[1];
|
||||
KeyShortcutTextUnion newShortcut = remappings[i].first[1];
|
||||
|
||||
if (EditorHelpers::IsValidShortcut(originalShortcut) && ((newShortcut.index() == 0 && std::get<DWORD>(newShortcut) != NULL) || (newShortcut.index() == 1 && EditorHelpers::IsValidShortcut(std::get<Shortcut>(newShortcut)))))
|
||||
if (EditorHelpers::IsValidShortcut(originalShortcut) && ((newShortcut.index() == 0 && std::get<DWORD>(newShortcut) != NULL) || (newShortcut.index() == 1 && EditorHelpers::IsValidShortcut(std::get<Shortcut>(newShortcut))) || (newShortcut.index() == 2 && !std::get<std::wstring>(newShortcut).empty())))
|
||||
{
|
||||
if (remappings[i].second == L"")
|
||||
{
|
||||
|
||||
@@ -15,10 +15,10 @@ namespace LoadingAndSavingRemappingHelper
|
||||
std::vector<DWORD> GetOrphanedKeys(const RemapBuffer& remappings);
|
||||
|
||||
// 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, KeyShortcutUnion>& table, DWORD leftKey, DWORD rightKey, DWORD combinedKey);
|
||||
void CombineRemappings(std::unordered_map<DWORD, KeyShortcutTextUnion>& table, DWORD leftKey, DWORD rightKey, DWORD combinedKey);
|
||||
|
||||
// Function to pre process the remap table before loading it into the UI
|
||||
void PreProcessRemapTable(std::unordered_map<DWORD, KeyShortcutUnion>& table);
|
||||
void PreProcessRemapTable(std::unordered_map<DWORD, KeyShortcutTextUnion>& table);
|
||||
|
||||
// Function to apply the single key remappings from the buffer to the KeyboardManagerState variable
|
||||
void ApplySingleKeyRemappings(MappingConfiguration& mappingConfiguration, const RemapBuffer& remappings, bool isTelemetryRequired);
|
||||
|
||||
@@ -21,7 +21,7 @@ ShortcutControl::ShortcutControl(StackPanel table, StackPanel row, const int col
|
||||
shortcutDropDownVariableSizedWrapGrid = VariableSizedWrapGrid();
|
||||
typeShortcut = Button();
|
||||
shortcutControlLayout = StackPanel();
|
||||
bool isHybridControl = colIndex == 1 ? true : false;
|
||||
const bool isHybridControl = colIndex == 1;
|
||||
|
||||
// TODO: Check if there is a VariableSizedWrapGrid equivalent.
|
||||
// shortcutDropDownVariableSizedWrapGrid.as<VariableSizedWrapGrid>().Spacing(EditorConstants::ShortcutTableDropDownSpacing);
|
||||
@@ -41,7 +41,13 @@ ShortcutControl::ShortcutControl(StackPanel table, StackPanel row, const int col
|
||||
|
||||
shortcutControlLayout.as<StackPanel>().Spacing(EditorConstants::ShortcutTableDropDownSpacing);
|
||||
|
||||
shortcutControlLayout.as<StackPanel>().Children().Append(typeShortcut.as<Button>());
|
||||
keyComboAndSelectStackPanel = StackPanel();
|
||||
keyComboAndSelectStackPanel.as<StackPanel>().Orientation(Windows::UI::Xaml::Controls::Orientation::Horizontal);
|
||||
keyComboAndSelectStackPanel.as<StackPanel>().Spacing(EditorConstants::ShortcutTableDropDownSpacing);
|
||||
|
||||
keyComboAndSelectStackPanel.as<StackPanel>().Children().Append(typeShortcut.as<Button>());
|
||||
shortcutControlLayout.as<StackPanel>().Children().InsertAt(0, keyComboAndSelectStackPanel.as<StackPanel>());
|
||||
|
||||
shortcutControlLayout.as<StackPanel>().Children().Append(shortcutDropDownVariableSizedWrapGrid.as<VariableSizedWrapGrid>());
|
||||
KeyDropDownControl::AddDropDown(table, row, shortcutDropDownVariableSizedWrapGrid.as<VariableSizedWrapGrid>(), colIndex, shortcutRemapBuffer, keyDropDownControlObjects, targetApp, isHybridControl, false);
|
||||
try
|
||||
@@ -63,7 +69,7 @@ void ShortcutControl::SetAccessibleNameForTextBox(TextBox targetAppTextBox, int
|
||||
{
|
||||
targetAppTextBoxAccessibleName += GET_RESOURCE_STRING(IDS_EDITSHORTCUTS_ALLAPPS);
|
||||
}
|
||||
|
||||
|
||||
targetAppTextBox.SetValue(Automation::AutomationProperties::NameProperty(), box_value(targetAppTextBoxAccessibleName));
|
||||
}
|
||||
|
||||
@@ -77,7 +83,7 @@ void ShortcutControl::UpdateAccessibleNames(StackPanel sourceColumn, StackPanel
|
||||
}
|
||||
|
||||
// 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, std::vector<std::vector<std::unique_ptr<ShortcutControl>>>& keyboardRemapControlObjects, const Shortcut& originalKeys, const KeyShortcutUnion& newKeys, const std::wstring& targetAppName)
|
||||
void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, std::vector<std::vector<std::unique_ptr<ShortcutControl>>>& keyboardRemapControlObjects, const Shortcut& originalKeys, const KeyShortcutTextUnion& newKeys, const std::wstring& targetAppName)
|
||||
{
|
||||
// Textbox for target application
|
||||
TextBox targetAppTextBox;
|
||||
@@ -115,6 +121,60 @@ void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, std::vector<s
|
||||
// ShortcutControl for the new shortcut
|
||||
auto target = keyboardRemapControlObjects.back()[1]->GetShortcutControl();
|
||||
target.Width(EditorConstants::ShortcutTargetColumnWidth);
|
||||
|
||||
auto typeCombo = ComboBox();
|
||||
typeCombo.Width(EditorConstants::RemapTableDropDownWidth);
|
||||
typeCombo.Items().Append(winrt::box_value(KeyboardManagerEditorStrings::MappingTypeShortcut()));
|
||||
typeCombo.Items().Append(winrt::box_value(KeyboardManagerEditorStrings::MappingTypeText()));
|
||||
auto controlStackPanel = keyboardRemapControlObjects.back()[1]->shortcutControlLayout.as<StackPanel>();
|
||||
auto firstLineStackPanel = keyboardRemapControlObjects.back()[1]->keyComboAndSelectStackPanel.as<StackPanel>();
|
||||
firstLineStackPanel.Children().InsertAt(0, typeCombo);
|
||||
|
||||
auto textInput = TextBox();
|
||||
auto textInputMargin = Windows::UI::Xaml::Thickness();
|
||||
textInputMargin.Top = -EditorConstants::ShortcutTableDropDownSpacing;
|
||||
textInputMargin.Bottom = EditorConstants::ShortcutTableDropDownSpacing; // compensate for a collapsed UIElement
|
||||
textInput.Margin(textInputMargin);
|
||||
|
||||
textInput.AcceptsReturn(false);
|
||||
textInput.Visibility(Visibility::Collapsed);
|
||||
textInput.Width(EditorConstants::TableDropDownHeight);
|
||||
controlStackPanel.Children().Append(textInput);
|
||||
textInput.HorizontalAlignment(HorizontalAlignment::Left);
|
||||
textInput.TextChanged([parent, row](winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::Controls::TextChangedEventArgs const& e) mutable {
|
||||
auto textbox = sender.as<TextBox>();
|
||||
auto text = textbox.Text();
|
||||
uint32_t rowIndex = -1;
|
||||
|
||||
if (!parent.Children().IndexOf(row, rowIndex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
shortcutRemapBuffer[rowIndex].first[1] = text.c_str();
|
||||
});
|
||||
|
||||
auto grid = keyboardRemapControlObjects.back()[1]->shortcutDropDownVariableSizedWrapGrid.as<VariableSizedWrapGrid>();
|
||||
auto gridMargin = Windows::UI::Xaml::Thickness();
|
||||
gridMargin.Bottom = -EditorConstants::ShortcutTableDropDownSpacing; // compensate for a collapsed textInput
|
||||
grid.Margin(gridMargin);
|
||||
auto button = keyboardRemapControlObjects.back()[1]->typeShortcut.as<Button>();
|
||||
|
||||
typeCombo.SelectionChanged([typeCombo, grid, button, textInput](winrt::Windows::Foundation::IInspectable const&, SelectionChangedEventArgs const&) {
|
||||
const bool textSelected = typeCombo.SelectedIndex() == 1;
|
||||
|
||||
const auto shortcutInputVisibility = textSelected ? Visibility::Collapsed : Visibility::Visible;
|
||||
|
||||
grid.Visibility(shortcutInputVisibility);
|
||||
button.Visibility(shortcutInputVisibility);
|
||||
|
||||
const auto textInputVisibility = textSelected ? Visibility::Visible : Visibility::Collapsed;
|
||||
textInput.Visibility(textInputVisibility);
|
||||
});
|
||||
|
||||
const bool textSelected = newKeys.index() == 2;
|
||||
typeCombo.SelectedIndex(textSelected);
|
||||
|
||||
row.Children().Append(target);
|
||||
|
||||
targetAppTextBox.Width(EditorConstants::ShortcutTableDropDownWidth);
|
||||
@@ -129,7 +189,7 @@ void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, std::vector<s
|
||||
});
|
||||
|
||||
// LostFocus handler will be called whenever text is updated by a user and then they click something else or tab to another control. Does not get called if Text is updated while the TextBox isn't in focus (i.e. from code)
|
||||
targetAppTextBox.LostFocus([&keyboardRemapControlObjects, parent, row, targetAppTextBox](auto const& sender, auto const& e) {
|
||||
targetAppTextBox.LostFocus([&keyboardRemapControlObjects, parent, row, targetAppTextBox, typeCombo, textInput](auto const& sender, auto const& e) {
|
||||
// Get index of targetAppTextBox button
|
||||
uint32_t rowIndex;
|
||||
if (!parent.Children().IndexOf(row, rowIndex))
|
||||
@@ -151,19 +211,27 @@ void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, std::vector<s
|
||||
std::get<Shortcut>(shortcutRemapBuffer[rowIndex].first[0]).SetKeyCodes(KeyDropDownControl::GetSelectedCodesFromStackPanel(keyboardRemapControlObjects[rowIndex][0]->shortcutDropDownVariableSizedWrapGrid.as<VariableSizedWrapGrid>()));
|
||||
// second column is a hybrid column
|
||||
|
||||
std::vector<int32_t> selectedKeyCodes = KeyDropDownControl::GetSelectedCodesFromStackPanel(keyboardRemapControlObjects[rowIndex][1]->shortcutDropDownVariableSizedWrapGrid.as<VariableSizedWrapGrid>());
|
||||
|
||||
// If exactly one key is selected consider it to be a key remap
|
||||
if (selectedKeyCodes.size() == 1)
|
||||
const bool textSelected = typeCombo.SelectedIndex() == 1;
|
||||
if (textSelected)
|
||||
{
|
||||
shortcutRemapBuffer[rowIndex].first[1] = (DWORD)selectedKeyCodes[0];
|
||||
shortcutRemapBuffer[rowIndex].first[1] = textInput.Text().c_str();
|
||||
}
|
||||
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::vector<int32_t> selectedKeyCodes = KeyDropDownControl::GetSelectedCodesFromStackPanel(keyboardRemapControlObjects[rowIndex][1]->shortcutDropDownVariableSizedWrapGrid.as<VariableSizedWrapGrid>());
|
||||
|
||||
// If exactly one key is selected consider it to be a key remap
|
||||
if (selectedKeyCodes.size() == 1)
|
||||
{
|
||||
shortcutRemapBuffer[rowIndex].first[1] = (DWORD)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 = KeyboardManagerEditorStrings::DefaultAppName();
|
||||
@@ -263,10 +331,19 @@ void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, std::vector<s
|
||||
{
|
||||
keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->keyDropDownControlObjects[0]->SetSelectedValue(std::to_wstring(std::get<DWORD>(newKeys)));
|
||||
}
|
||||
else
|
||||
else if (newKeys.index() == 1)
|
||||
{
|
||||
KeyDropDownControl::AddShortcutToControl(std::get<Shortcut>(newKeys), parent, keyboardRemapControlObjects.back()[1]->shortcutDropDownVariableSizedWrapGrid.as<VariableSizedWrapGrid>(), *keyboardManagerState, 1, keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->keyDropDownControlObjects, shortcutRemapBuffer, row, targetAppTextBox, true, false);
|
||||
}
|
||||
else if (newKeys.index() == 2)
|
||||
{
|
||||
shortcutRemapBuffer.back().first[1] = std::get<std::wstring>(newKeys);
|
||||
const auto& remapControl = keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1];
|
||||
const auto& controlChildren = remapControl->GetShortcutControl().Children();
|
||||
const auto& topLineChildren = controlChildren.GetAt(0).as<StackPanel>();
|
||||
topLineChildren.Children().GetAt(0).as<ComboBox>().SelectedIndex(1);
|
||||
controlChildren.GetAt(2).as<TextBox>().Text(std::get<std::wstring>(newKeys));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -291,8 +368,8 @@ void ShortcutControl::CreateDetectShortcutWindow(winrt::Windows::Foundation::IIn
|
||||
detectShortcutBox.XamlRoot(xamlRoot);
|
||||
detectShortcutBox.Title(box_value(GET_RESOURCE_STRING(IDS_TYPESHORTCUT_TITLE)));
|
||||
|
||||
// Get the linked stack panel for the "Type shortcut" button that was clicked
|
||||
VariableSizedWrapGrid linkedShortcutVariableSizedWrapGrid = UIHelpers::GetSiblingElement(sender).as<VariableSizedWrapGrid>();
|
||||
// Get the parent linked stack panel for the "Type shortcut" button that was clicked
|
||||
VariableSizedWrapGrid linkedShortcutVariableSizedWrapGrid = UIHelpers::GetSiblingElement(sender.as<FrameworkElement>().Parent()).as<VariableSizedWrapGrid>();
|
||||
|
||||
auto unregisterKeys = [&keyboardManagerState]() {
|
||||
keyboardManagerState.ClearRegisteredKeyDelays();
|
||||
|
||||
@@ -31,6 +31,9 @@ private:
|
||||
// StackPanel to parent the above controls
|
||||
winrt::Windows::Foundation::IInspectable shortcutControlLayout;
|
||||
|
||||
// StackPanel to parent the first line of "To" Column
|
||||
winrt::Windows::Foundation::IInspectable keyComboAndSelectStackPanel;
|
||||
|
||||
// Function to set the accessible name of the target app text box
|
||||
static void SetAccessibleNameForTextBox(TextBox targetAppTextBox, int rowIndex);
|
||||
|
||||
@@ -54,7 +57,7 @@ public:
|
||||
ShortcutControl(StackPanel table, StackPanel row, 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(StackPanel& parent, std::vector<std::vector<std::unique_ptr<ShortcutControl>>>& keyboardRemapControlObjects, const Shortcut& originalKeys = Shortcut(), const KeyShortcutUnion& newKeys = Shortcut(), const std::wstring& targetAppName = L"");
|
||||
static void AddNewShortcutControlRow(StackPanel& parent, std::vector<std::vector<std::unique_ptr<ShortcutControl>>>& keyboardRemapControlObjects, const Shortcut& originalKeys = Shortcut(), const KeyShortcutTextUnion& 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();
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "SingleKeyRemapControl.h"
|
||||
|
||||
#include "KeyboardManagerState.h"
|
||||
#include "KeyboardManagerEditorStrings.h"
|
||||
#include "ShortcutControl.h"
|
||||
#include "UIHelpers.h"
|
||||
#include "EditorHelpers.h"
|
||||
@@ -20,25 +21,80 @@ SingleKeyRemapControl::SingleKeyRemapControl(StackPanel table, StackPanel row, c
|
||||
typeKey.as<Button>().Content(winrt::box_value(GET_RESOURCE_STRING(IDS_TYPE_BUTTON)));
|
||||
|
||||
singleKeyRemapControlLayout = StackPanel();
|
||||
singleKeyRemapControlLayout.as<StackPanel>().Spacing(10);
|
||||
singleKeyRemapControlLayout.as<StackPanel>().Children().Append(typeKey.as<Button>());
|
||||
singleKeyRemapControlLayout.as<StackPanel>().Spacing(EditorConstants::ShortcutTableDropDownSpacing);
|
||||
|
||||
// Key column
|
||||
// Key column (From key)
|
||||
if (colIndex == 0)
|
||||
{
|
||||
singleKeyRemapControlLayout.as<StackPanel>().Children().Append(typeKey.as<Button>());
|
||||
|
||||
keyDropDownControlObjects.emplace_back(std::make_unique<KeyDropDownControl>(false));
|
||||
singleKeyRemapControlLayout.as<StackPanel>().Children().Append(keyDropDownControlObjects[0]->GetComboBox());
|
||||
// Set selection handler for the drop down
|
||||
keyDropDownControlObjects[0]->SetSelectionHandler(table, row, colIndex, singleKeyRemapBuffer);
|
||||
}
|
||||
|
||||
// Hybrid column
|
||||
// Hybrid column (To Key/Shortcut/Text)
|
||||
else
|
||||
{
|
||||
StackPanel keyComboAndSelectStackPanel;
|
||||
keyComboAndSelectStackPanel.Orientation(Windows::UI::Xaml::Controls::Orientation::Horizontal);
|
||||
keyComboAndSelectStackPanel.Spacing(EditorConstants::ShortcutTableDropDownSpacing);
|
||||
|
||||
hybridDropDownVariableSizedWrapGrid = VariableSizedWrapGrid();
|
||||
hybridDropDownVariableSizedWrapGrid.as<VariableSizedWrapGrid>().Orientation(Windows::UI::Xaml::Controls::Orientation::Horizontal);
|
||||
KeyDropDownControl::AddDropDown(table, row, hybridDropDownVariableSizedWrapGrid.as<VariableSizedWrapGrid>(), colIndex, singleKeyRemapBuffer, keyDropDownControlObjects, nullptr, true, true);
|
||||
singleKeyRemapControlLayout.as<StackPanel>().Children().Append(hybridDropDownVariableSizedWrapGrid.as<VariableSizedWrapGrid>());
|
||||
auto grid = hybridDropDownVariableSizedWrapGrid.as<VariableSizedWrapGrid>();
|
||||
grid.Orientation(Windows::UI::Xaml::Controls::Orientation::Horizontal);
|
||||
auto gridMargin = Windows::UI::Xaml::Thickness();
|
||||
gridMargin.Bottom = -EditorConstants::ShortcutTableDropDownSpacing; // compensate for a collapsed textInput
|
||||
grid.Margin(gridMargin);
|
||||
|
||||
KeyDropDownControl::AddDropDown(table, row, grid, colIndex, singleKeyRemapBuffer, keyDropDownControlObjects, nullptr, true, true);
|
||||
|
||||
singleKeyRemapControlLayout.as<StackPanel>().Children().Append(grid);
|
||||
|
||||
auto textInput = TextBox();
|
||||
|
||||
auto textBoxMargin = Windows::UI::Xaml::Thickness();
|
||||
textBoxMargin.Top = -EditorConstants::ShortcutTableDropDownSpacing; // compensate for a collapsed grid
|
||||
textBoxMargin.Bottom = EditorConstants::ShortcutTableDropDownSpacing;
|
||||
textInput.Margin(textBoxMargin);
|
||||
textInput.AcceptsReturn(false);
|
||||
textInput.Visibility(Visibility::Collapsed);
|
||||
textInput.Width(EditorConstants::TableDropDownHeight);
|
||||
singleKeyRemapControlLayout.as<StackPanel>().Children().Append(textInput);
|
||||
textInput.HorizontalAlignment(HorizontalAlignment::Left);
|
||||
textInput.TextChanged([this, row, table](winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::Controls::TextChangedEventArgs const& e) mutable {
|
||||
auto textbox = sender.as<TextBox>();
|
||||
auto text = textbox.Text();
|
||||
uint32_t rowIndex = -1;
|
||||
if (!table.Children().IndexOf(row, rowIndex))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
singleKeyRemapBuffer[rowIndex].first[1] = text.c_str();
|
||||
});
|
||||
|
||||
auto typeCombo = ComboBox();
|
||||
typeCombo.Width(EditorConstants::RemapTableDropDownWidth);
|
||||
typeCombo.Items().Append(winrt::box_value(KeyboardManagerEditorStrings::MappingTypeKey()));
|
||||
typeCombo.Items().Append(winrt::box_value(KeyboardManagerEditorStrings::MappingTypeText()));
|
||||
keyComboAndSelectStackPanel.Children().Append(typeCombo);
|
||||
keyComboAndSelectStackPanel.Children().Append(typeKey.as<Button>());
|
||||
singleKeyRemapControlLayout.as<StackPanel>().Children().InsertAt(0, keyComboAndSelectStackPanel);
|
||||
|
||||
typeCombo.SelectedIndex(0);
|
||||
typeCombo.SelectionChanged([this, typeCombo, grid, textInput](winrt::Windows::Foundation::IInspectable const&, SelectionChangedEventArgs const&) {
|
||||
const bool textSelected = typeCombo.SelectedIndex() == 1;
|
||||
|
||||
const auto keyInputVisibility = textSelected ? Visibility::Collapsed : Visibility::Visible;
|
||||
|
||||
grid.Visibility(keyInputVisibility);
|
||||
typeKey.as<Button>().Visibility(keyInputVisibility);
|
||||
|
||||
const auto textInputVisibility = textSelected ? Visibility::Visible : Visibility::Collapsed;
|
||||
textInput.Visibility(textInputVisibility);
|
||||
});
|
||||
}
|
||||
|
||||
typeKey.as<Button>().Click([&, table, colIndex, row](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
@@ -73,8 +129,15 @@ void SingleKeyRemapControl::UpdateAccessibleNames(StackPanel sourceColumn, Stack
|
||||
deleteButton.SetValue(Automation::AutomationProperties::NameProperty(), box_value(GET_RESOURCE_STRING(IDS_AUTOMATIONPROPERTIES_ROW) + std::to_wstring(rowIndex) + L", " + GET_RESOURCE_STRING(IDS_DELETE_REMAPPING_BUTTON)));
|
||||
}
|
||||
|
||||
void SingleKeyRemapControl::TextToMapChangedHandler(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::Controls::TextChangedEventArgs const& e) // TODO: remove
|
||||
{
|
||||
auto textbox = sender.as<TextBox>();
|
||||
auto text = textbox.Text();
|
||||
(void)text;
|
||||
}
|
||||
|
||||
// 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, std::vector<std::vector<std::unique_ptr<SingleKeyRemapControl>>>& keyboardRemapControlObjects, const DWORD originalKey, const KeyShortcutUnion newKey)
|
||||
void SingleKeyRemapControl::AddNewControlKeyRemapRow(StackPanel& parent, std::vector<std::vector<std::unique_ptr<SingleKeyRemapControl>>>& keyboardRemapControlObjects, const DWORD originalKey, const KeyShortcutTextUnion newKey)
|
||||
{
|
||||
// Create new SingleKeyRemapControl objects dynamically so that we does not get destructed
|
||||
std::vector<std::unique_ptr<SingleKeyRemapControl>> newrow;
|
||||
@@ -112,7 +175,7 @@ void SingleKeyRemapControl::AddNewControlKeyRemapRow(StackPanel& parent, std::ve
|
||||
row.Children().Append(targetElement);
|
||||
|
||||
// Set the key text if the two keys are not null (i.e. default args)
|
||||
if (originalKey != NULL && !(newKey.index() == 0 && std::get<DWORD>(newKey) == NULL) && !(newKey.index() == 1 && !EditorHelpers::IsValidShortcut(std::get<Shortcut>(newKey))))
|
||||
if (originalKey != NULL && !(newKey.index() == 0 && std::get<DWORD>(newKey) == NULL) && !(newKey.index() == 1 && !EditorHelpers::IsValidShortcut(std::get<Shortcut>(newKey))) && !(newKey.index() == 2 && std::get<std::wstring>(newKey).empty()))
|
||||
{
|
||||
singleKeyRemapBuffer.push_back(std::make_pair<RemapBufferItem, std::wstring>(RemapBufferItem{ originalKey, newKey }, L""));
|
||||
keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][0]->keyDropDownControlObjects[0]->SetSelectedValue(std::to_wstring(originalKey));
|
||||
@@ -120,10 +183,20 @@ void SingleKeyRemapControl::AddNewControlKeyRemapRow(StackPanel& parent, std::ve
|
||||
{
|
||||
keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->keyDropDownControlObjects[0]->SetSelectedValue(std::to_wstring(std::get<DWORD>(newKey)));
|
||||
}
|
||||
else
|
||||
else if (newKey.index() == 1)
|
||||
{
|
||||
KeyDropDownControl::AddShortcutToControl(std::get<Shortcut>(newKey), parent, keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->hybridDropDownVariableSizedWrapGrid.as<VariableSizedWrapGrid>(), *keyboardManagerState, 1, keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->keyDropDownControlObjects, singleKeyRemapBuffer, row, nullptr, true, true);
|
||||
}
|
||||
else if (newKey.index() == 2)
|
||||
{
|
||||
auto& singleKeyRemapControl = keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1];
|
||||
|
||||
const auto& firstLineStackPanel = singleKeyRemapControl->singleKeyRemapControlLayout.as<StackPanel>().Children().GetAt(0).as<StackPanel>();
|
||||
|
||||
firstLineStackPanel.Children().GetAt(0).as<ComboBox>().SelectedIndex(1);
|
||||
|
||||
singleKeyRemapControl->singleKeyRemapControlLayout.as<StackPanel>().Children().GetAt(2).as<TextBox>().Text(std::get<std::wstring>(newKey));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -178,7 +251,7 @@ void SingleKeyRemapControl::AddNewControlKeyRemapRow(StackPanel& parent, std::ve
|
||||
{
|
||||
}
|
||||
singleKeyRemapBuffer.erase(singleKeyRemapBuffer.begin() + rowIndex);
|
||||
|
||||
|
||||
// delete the SingleKeyRemapControl objects so that they get destructed
|
||||
keyboardRemapControlObjects.erase(keyboardRemapControlObjects.begin() + rowIndex);
|
||||
});
|
||||
|
||||
@@ -35,6 +35,8 @@ private:
|
||||
// Function to set the accessible names for all the controls in a row
|
||||
static void UpdateAccessibleNames(StackPanel sourceColumn, StackPanel mappedToColumn, Button deleteButton, int rowIndex);
|
||||
|
||||
void TextToMapChangedHandler(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::Controls::TextChangedEventArgs const& e);
|
||||
|
||||
public:
|
||||
// Vector to store dynamically allocated KeyDropDownControl objects to avoid early destruction
|
||||
std::vector<std::unique_ptr<KeyDropDownControl>> keyDropDownControlObjects;
|
||||
@@ -52,7 +54,7 @@ public:
|
||||
SingleKeyRemapControl(StackPanel table, StackPanel row, 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(StackPanel& parent, std::vector<std::vector<std::unique_ptr<SingleKeyRemapControl>>>& keyboardRemapControlObjects, const DWORD originalKey = 0, const KeyShortcutUnion newKey = (DWORD)0);
|
||||
static void AddNewControlKeyRemapRow(StackPanel& parent, std::vector<std::vector<std::unique_ptr<SingleKeyRemapControl>>>& keyboardRemapControlObjects, const DWORD originalKey = 0, const KeyShortcutTextUnion newKey = (DWORD)0);
|
||||
|
||||
// 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();
|
||||
|
||||
@@ -9,13 +9,19 @@ namespace UIHelpers
|
||||
void SetFocusOnTypeButtonInLastRow(StackPanel& parent, long colCount)
|
||||
{
|
||||
// First element in the last row (StackPanel)
|
||||
StackPanel firstElementInLastRow = parent.Children().GetAt(parent.Children().Size() - 1).as<StackPanel>().Children().GetAt(0).as<StackPanel>();
|
||||
auto lastHotKeyLine = parent.Children().GetAt(parent.Children().Size() - 1).as<StackPanel>();
|
||||
|
||||
// Type button is the first child in the StackPanel
|
||||
Button firstTypeButtonInLastRow = firstElementInLastRow.Children().GetAt(0).as<Button>();
|
||||
// Get "To" Column
|
||||
auto toColumn = lastHotKeyLine.Children().GetAt(2).as<StackPanel>();
|
||||
|
||||
// Get first line in "To" Column
|
||||
auto firstLineIntoColumn = toColumn.Children().GetAt(0).as<StackPanel>();
|
||||
|
||||
// Get Type Button from the first line
|
||||
Button typeButton = firstLineIntoColumn.Children().GetAt(1).as<Button>();
|
||||
|
||||
// Set programmatic focus on the button
|
||||
firstTypeButtonInLastRow.Focus(FocusState::Programmatic);
|
||||
typeButton.Focus(FocusState::Programmatic);
|
||||
}
|
||||
|
||||
RECT GetForegroundWindowDesktopRect()
|
||||
@@ -68,4 +74,22 @@ namespace UIHelpers
|
||||
|
||||
return boxList;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
std::vector<std::wstring> GetChildrenNames(StackPanel& s)
|
||||
{
|
||||
std::vector<std::wstring> result;
|
||||
for (auto child : s.Children())
|
||||
{
|
||||
std::wstring nameAndClass =
|
||||
child.as<IFrameworkElement>().Name().c_str();
|
||||
|
||||
nameAndClass += L" ";
|
||||
nameAndClass += winrt::get_class_name(child.try_as<winrt::Windows::Foundation::IInspectable>()).c_str();
|
||||
result.push_back(nameAndClass);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -29,4 +29,9 @@ namespace UIHelpers
|
||||
|
||||
// Function to return the list of key name in the order for the drop down based on the key codes
|
||||
winrt::Windows::Foundation::Collections::IVector<winrt::Windows::Foundation::IInspectable> ToBoxValue(const std::vector<std::pair<DWORD, std::wstring>>& list);
|
||||
|
||||
#ifndef NDEBUG
|
||||
// Useful For debugging issues
|
||||
std::vector<std::wstring> GetChildrenNames(StackPanel& s);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ void Trace::UnregisterProvider() noexcept
|
||||
}
|
||||
|
||||
// Log number of key remaps when the user uses Edit Keyboard and saves settings
|
||||
void Trace::KeyRemapCount(const DWORD keyToKeyCount, const DWORD keyToShortcutCount) noexcept
|
||||
void Trace::KeyRemapCount(const DWORD keyToKeyCount, const DWORD keyToShortcutCount, const DWORD keyToTextCount) noexcept
|
||||
{
|
||||
TraceLoggingWrite(
|
||||
g_hProvider,
|
||||
@@ -28,7 +28,8 @@ void Trace::KeyRemapCount(const DWORD keyToKeyCount, const DWORD keyToShortcutCo
|
||||
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
|
||||
TraceLoggingValue(keyToKeyCount + keyToShortcutCount, "KeyRemapCount"),
|
||||
TraceLoggingValue(keyToKeyCount, "KeyToKeyRemapCount"),
|
||||
TraceLoggingValue(keyToShortcutCount, "KeyToShortcutRemapCount"));
|
||||
TraceLoggingValue(keyToShortcutCount, "KeyToShortcutRemapCount"),
|
||||
TraceLoggingValue(keyToTextCount, "KeyToTextRemapCount"));
|
||||
}
|
||||
|
||||
// Log number of os level shortcut remaps when the user uses Edit Shortcuts and saves settings
|
||||
|
||||
@@ -7,14 +7,14 @@ public:
|
||||
static void UnregisterProvider() noexcept;
|
||||
|
||||
// Log number of key remaps when the user uses Edit Keyboard and saves settings
|
||||
static void KeyRemapCount(const DWORD keyToKeyCount, const DWORD keyToShortcutCount) noexcept;
|
||||
static void KeyRemapCount(const DWORD keyToKeyCount, const DWORD keyToShortcutCount, const DWORD keyToTextCount) noexcept;
|
||||
|
||||
// Log number of os level shortcut remaps when the user uses Edit Shortcuts and saves settings
|
||||
static void OSLevelShortcutRemapCount(const DWORD shortcutToShortcutCount, const DWORD shortcutToKeyCount) noexcept;
|
||||
|
||||
// Log number of app specific shortcut remaps when the user uses Edit Shortcuts and saves settings
|
||||
static void AppSpecificShortcutRemapCount(const DWORD shortcutToShortcutCount, const DWORD shortcutToKeyCount) noexcept;
|
||||
|
||||
|
||||
// Log if an error occurs in KBM
|
||||
static void Error(const DWORD errorCode, std::wstring errorMessage, std::wstring methodName) noexcept;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user