diff --git a/src/common/interop/interop.h b/src/common/interop/interop.h index 793d418712..e0ee2bdd9d 100644 --- a/src/common/interop/interop.h +++ b/src/common/interop/interop.h @@ -6,6 +6,7 @@ #include "..\keyboard_layout.h" #include "..\two_way_pipe_message_ipc.h" #include "..\common.h" +#include "..\shared_constants.h" using namespace System; using namespace System::Runtime::InteropServices; @@ -114,4 +115,11 @@ public return gcnew String(get_product_version().c_str()); } }; + + public + ref class Constants + { + public: + literal int VK_WIN_BOTH = CommonSharedConstants::VK_WIN_BOTH; + }; } diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/Utilities/Helper.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/Utilities/Helper.cs index 8533a41fd4..95b9eae2e1 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/Utilities/Helper.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/Utilities/Helper.cs @@ -117,5 +117,7 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.Utilities throw new FormatException("Bad product version format"); } } + + public const uint VirtualKeyWindows = interop.Constants.VK_WIN_BOTH; } } diff --git a/src/core/Microsoft.PowerToys.Settings.UI/ViewModels/KeyboardManagerViewModel.cs b/src/core/Microsoft.PowerToys.Settings.UI/ViewModels/KeyboardManagerViewModel.cs index 7604231ab2..a4e4c304b6 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI/ViewModels/KeyboardManagerViewModel.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI/ViewModels/KeyboardManagerViewModel.cs @@ -14,6 +14,7 @@ using Microsoft.PowerToys.Settings.UI.Lib; using Microsoft.PowerToys.Settings.UI.Lib.Utilities; using Microsoft.PowerToys.Settings.UI.Views; using Microsoft.Toolkit.Uwp.Helpers; +using Windows.System; using Windows.UI.Core; using Windows.UI.Xaml; @@ -183,6 +184,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels try { profile = SettingsUtils.GetSettings(PowerToyName, settings.Properties.ActiveConfiguration.Value + JsonFileType); + FilterRemapKeysList(profile.RemapKeys.InProcessRemapKeys); } finally { @@ -204,5 +206,33 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels return success; } + + private void FilterRemapKeysList(List remapKeysList) + { + CombineRemappings(remapKeysList, (uint)VirtualKey.LeftControl, (uint)VirtualKey.RightControl, (uint)VirtualKey.Control); + CombineRemappings(remapKeysList, (uint)VirtualKey.LeftMenu, (uint)VirtualKey.RightMenu, (uint)VirtualKey.Menu); + CombineRemappings(remapKeysList, (uint)VirtualKey.LeftShift, (uint)VirtualKey.RightShift, (uint)VirtualKey.Shift); + CombineRemappings(remapKeysList, (uint)VirtualKey.LeftWindows, (uint)VirtualKey.RightWindows, Helper.VirtualKeyWindows); + } + + private void CombineRemappings(List remapKeysList, uint leftKey, uint rightKey, uint combinedKey) + { + KeysDataModel firstRemap = remapKeysList.Find(x => uint.Parse(x.OriginalKeys) == leftKey); + KeysDataModel secondRemap = remapKeysList.Find(x => uint.Parse(x.OriginalKeys) == rightKey); + if (firstRemap != null && secondRemap != null) + { + if (firstRemap.NewRemapKeys == secondRemap.NewRemapKeys) + { + KeysDataModel combinedRemap = new KeysDataModel + { + OriginalKeys = combinedKey.ToString(), + NewRemapKeys = firstRemap.NewRemapKeys, + }; + remapKeysList.Insert(remapKeysList.IndexOf(firstRemap), combinedRemap); + remapKeysList.Remove(firstRemap); + remapKeysList.Remove(secondRemap); + } + } + } } } diff --git a/src/modules/keyboardmanager/ui/EditKeyboardWindow.cpp b/src/modules/keyboardmanager/ui/EditKeyboardWindow.cpp index 8f6b5d7148..c53ef0cb73 100644 --- a/src/modules/keyboardmanager/ui/EditKeyboardWindow.cpp +++ b/src/modules/keyboardmanager/ui/EditKeyboardWindow.cpp @@ -106,6 +106,32 @@ static IAsyncAction OnClickAccept(KeyboardManagerState& keyboardManagerState, Xa } ApplyRemappings(); } + +// Function to combine remappings if the L and R version of the modifier is mapped to the same key +void CombineRemappings(std::unordered_map& table, DWORD leftKey, DWORD rightKey, DWORD combinedKey) +{ + if (table.find(leftKey) != table.end() && table.find(rightKey) != table.end()) + { + // If they are mapped to the same key, delete those entries and set the common version + if (table[leftKey] == table[rightKey]) + { + table[combinedKey] = table[leftKey]; + table.erase(leftKey); + table.erase(rightKey); + } + } +} + +// Function to pre process the remap table before loading it into the UI +void PreProcessRemapTable(std::unordered_map& 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); + CombineRemappings(table, VK_LMENU, VK_RMENU, VK_MENU); + CombineRemappings(table, VK_LSHIFT, VK_RSHIFT, VK_SHIFT); + CombineRemappings(table, VK_LWIN, VK_RWIN, CommonSharedConstants::VK_WIN_BOTH); +} + // Function to create the Edit Keyboard Window void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardManagerState) { @@ -265,48 +291,7 @@ void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMan std::unique_lock lock(keyboardManagerState.singleKeyReMap_mutex); std::unordered_map singleKeyRemapCopy = keyboardManagerState.singleKeyReMap; lock.unlock(); - - // Pre process the table to combine L and R versions of Ctrl/Alt/Shift/Win that are mapped to the same key - if (singleKeyRemapCopy.find(VK_LCONTROL) != singleKeyRemapCopy.end() && singleKeyRemapCopy.find(VK_RCONTROL) != singleKeyRemapCopy.end()) - { - // If they are mapped to the same key, delete those entries and set the common version - if (singleKeyRemapCopy[VK_LCONTROL] == singleKeyRemapCopy[VK_RCONTROL]) - { - singleKeyRemapCopy[VK_CONTROL] = singleKeyRemapCopy[VK_LCONTROL]; - singleKeyRemapCopy.erase(VK_LCONTROL); - singleKeyRemapCopy.erase(VK_RCONTROL); - } - } - if (singleKeyRemapCopy.find(VK_LMENU) != singleKeyRemapCopy.end() && singleKeyRemapCopy.find(VK_RMENU) != singleKeyRemapCopy.end()) - { - // If they are mapped to the same key, delete those entries and set the common version - if (singleKeyRemapCopy[VK_LMENU] == singleKeyRemapCopy[VK_RMENU]) - { - singleKeyRemapCopy[VK_MENU] = singleKeyRemapCopy[VK_LMENU]; - singleKeyRemapCopy.erase(VK_LMENU); - singleKeyRemapCopy.erase(VK_RMENU); - } - } - if (singleKeyRemapCopy.find(VK_LSHIFT) != singleKeyRemapCopy.end() && singleKeyRemapCopy.find(VK_RSHIFT) != singleKeyRemapCopy.end()) - { - // If they are mapped to the same key, delete those entries and set the common version - if (singleKeyRemapCopy[VK_LSHIFT] == singleKeyRemapCopy[VK_RSHIFT]) - { - singleKeyRemapCopy[VK_SHIFT] = singleKeyRemapCopy[VK_LSHIFT]; - singleKeyRemapCopy.erase(VK_LSHIFT); - singleKeyRemapCopy.erase(VK_RSHIFT); - } - } - if (singleKeyRemapCopy.find(VK_LWIN) != singleKeyRemapCopy.end() && singleKeyRemapCopy.find(VK_RWIN) != singleKeyRemapCopy.end()) - { - // If they are mapped to the same key, delete those entries and set the common version - if (singleKeyRemapCopy[VK_LWIN] == singleKeyRemapCopy[VK_RWIN]) - { - singleKeyRemapCopy[CommonSharedConstants::VK_WIN_BOTH] = singleKeyRemapCopy[VK_LWIN]; - singleKeyRemapCopy.erase(VK_LWIN); - singleKeyRemapCopy.erase(VK_RWIN); - } - } + PreProcessRemapTable(singleKeyRemapCopy); for (const auto& it : singleKeyRemapCopy) {