From 325db535c0deb4311f75afecd799ab9b0c52a0c7 Mon Sep 17 00:00:00 2001 From: udit3333 Date: Mon, 20 Apr 2020 08:22:36 -0700 Subject: [PATCH] [Kbm] Save the remaps to file[part-1] (#2184) * Added Inital FileWatcher Implementation * Added logic to read remap from file * Added remap logic save to file * Refactor code * Moved the strings to constant file * Added logic to handle Win key * Updated filewatcher logic to avoid duplicate events * Added comments * Fix spacing * Fix spacing * Update logic to accomodate upstream merge * Added global property name for os level shortcuts * Added subkey for inprocess keys * Remove non required file * Added Changes required after merge * Fix spacing in Helper.cpp --- .../GenericProperty.cs | 27 ++++ .../KeyboadManagerConfigModel.cs | 18 +++ .../KeyboardManagerProperties.cs | 15 +- .../KeyboardManagerSettings.cs | 7 + .../KeysDataModel.cs | 17 +++ .../RemapKeysDataModel.cs | 15 ++ .../ShortcutsKeyDataModel.cs | 15 ++ .../Utilities/Helper.cs | 21 +++ .../ViewModels/KeyboardManagerViewModel.cs | 65 ++++++++- .../keyboardmanager/common/Helpers.cpp | 131 +++++++++--------- src/modules/keyboardmanager/common/Helpers.h | 90 ++++++------ .../common/KeyboardManagerCommon.vcxproj | 5 +- .../KeyboardManagerCommon.vcxproj.filters | 3 + .../common/KeyboardManagerConstants.h | 41 ++++++ .../common/KeyboardManagerState.cpp | 88 ++++++++++++ .../common/KeyboardManagerState.h | 21 +++ .../keyboardmanager/common/Shortcut.cpp | 37 +++++ src/modules/keyboardmanager/common/Shortcut.h | 26 ++++ src/modules/keyboardmanager/common/pch.h | 1 - src/modules/keyboardmanager/dll/dllmain.cpp | 75 +++++++++- .../keyboardmanager/ui/EditKeyboardWindow.cpp | 18 ++- .../ui/EditShortcutsWindow.cpp | 18 ++- .../keyboardmanager/ui/KeyDropDownControl.cpp | 4 +- .../keyboardmanager/ui/KeyDropDownControl.h | 12 +- .../keyboardmanager/ui/ShortcutControl.cpp | 10 +- .../keyboardmanager/ui/ShortcutControl.h | 4 +- .../ui/SingleKeyRemapControl.cpp | 10 +- .../ui/SingleKeyRemapControl.h | 4 +- src/modules/keyboardmanager/ui/pch.h | 1 - 29 files changed, 647 insertions(+), 152 deletions(-) create mode 100644 src/core/Microsoft.PowerToys.Settings.UI.Lib/GenericProperty.cs create mode 100644 src/core/Microsoft.PowerToys.Settings.UI.Lib/KeyboadManagerConfigModel.cs create mode 100644 src/core/Microsoft.PowerToys.Settings.UI.Lib/KeysDataModel.cs create mode 100644 src/core/Microsoft.PowerToys.Settings.UI.Lib/RemapKeysDataModel.cs create mode 100644 src/core/Microsoft.PowerToys.Settings.UI.Lib/ShortcutsKeyDataModel.cs create mode 100644 src/modules/keyboardmanager/common/KeyboardManagerConstants.h diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/GenericProperty.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/GenericProperty.cs new file mode 100644 index 0000000000..fe2bdbc838 --- /dev/null +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/GenericProperty.cs @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Microsoft.PowerToys.Settings.UI.Lib +{ +#pragma warning disable SA1649 // File name should match first type name + + public class GenericProperty + { + [JsonPropertyName("value")] + public T Value { get; set; } + + public GenericProperty(T value) + { + Value = value; + } + + // Added a parameterless constructor because of an exception during deserialization. More details here: https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-how-to#deserialization-behavior + public GenericProperty() + { + } + } +} diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/KeyboadManagerConfigModel.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/KeyboadManagerConfigModel.cs new file mode 100644 index 0000000000..0b3d6c2377 --- /dev/null +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/KeyboadManagerConfigModel.cs @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Microsoft.PowerToys.Settings.UI.Lib +{ + public class KeyboadManagerConfigModel + { + [JsonPropertyName("remapKeys")] + public RemapKeysDataModel RemapKeys { get; set; } + + [JsonPropertyName("remapShortcuts")] + public ShortcutsKeyDataModel RemapShortcuts { get; set; } + } +} diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/KeyboardManagerProperties.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/KeyboardManagerProperties.cs index adfae0d561..e4b9289852 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/KeyboardManagerProperties.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/KeyboardManagerProperties.cs @@ -2,22 +2,25 @@ // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Collections.Generic; using System.Text.Json; +using System.Text.Json.Serialization; namespace Microsoft.PowerToys.Settings.UI.Lib { public class KeyboardManagerProperties { - // Bool property to notify Keyboard Manager module if the Edit Shortcut button is pressed. - public BoolProperty EditShortcut { get; set; } + [JsonPropertyName("activeConfiguration")] + public GenericProperty ActiveConfiguration { get; set; } - // Bool property to notify Keyboard Manager module if the Remap Keyboard button is pressed. - public BoolProperty RemapKeyboard { get; set; } + // List of all Keyboard Configurations. + [JsonPropertyName("keyboardConfigurations")] + public GenericProperty> KeyboardConfigurations { get; set; } public KeyboardManagerProperties() { - EditShortcut = new BoolProperty(); - RemapKeyboard = new BoolProperty(); + KeyboardConfigurations = new GenericProperty>(new List { "default", }); + ActiveConfiguration = new GenericProperty("default"); } public string ToJsonString() diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/KeyboardManagerSettings.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/KeyboardManagerSettings.cs index 75f44eb5ab..d5aae938b8 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/KeyboardManagerSettings.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/KeyboardManagerSettings.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Text; +using System.Text.Json; using System.Text.Json.Serialization; namespace Microsoft.PowerToys.Settings.UI.Lib @@ -27,5 +28,11 @@ namespace Microsoft.PowerToys.Settings.UI.Lib version = "1"; name = ptName; } + + // converts the current to a json string. + public override string ToJsonString() + { + return JsonSerializer.Serialize(this); + } } } diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/KeysDataModel.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/KeysDataModel.cs new file mode 100644 index 0000000000..2b66cbc8ab --- /dev/null +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/KeysDataModel.cs @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Text.Json.Serialization; + +namespace Microsoft.PowerToys.Settings.UI.Lib +{ + public class KeysDataModel + { + [JsonPropertyName("originalKeys")] + public string OriginalKeys { get; set; } + + [JsonPropertyName("newRemapKeys")] + public string NewRemapKeys { get; set; } + } +} diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/RemapKeysDataModel.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/RemapKeysDataModel.cs new file mode 100644 index 0000000000..af376a648c --- /dev/null +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/RemapKeysDataModel.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Microsoft.PowerToys.Settings.UI.Lib +{ + public class RemapKeysDataModel + { + [JsonPropertyName("inProcess")] + public List InProcessRemapKeys { get; set; } + } +} \ No newline at end of file diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ShortcutsKeyDataModel.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ShortcutsKeyDataModel.cs new file mode 100644 index 0000000000..7b75a86b11 --- /dev/null +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ShortcutsKeyDataModel.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Microsoft.PowerToys.Settings.UI.Lib +{ + public class ShortcutsKeyDataModel + { + [JsonPropertyName("global")] + public List GlobalRemapShortcuts { get; set; } + } +} 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 8211463d6e..e9079dc4b8 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/Utilities/Helper.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/Utilities/Helper.cs @@ -2,8 +2,12 @@ // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using System.Diagnostics; +using System.IO; using System.Runtime.InteropServices; +using System.Text; +using System.Text.Json; using Microsoft.PowerToys.Settings.UI.Lib.CustomAction; namespace Microsoft.PowerToys.Settings.UI.Lib.Utilities @@ -41,6 +45,23 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.Utilities return sendCustomAction.ToJsonString(); } + public static FileSystemWatcher GetFileWatcher(string moduleName, string fileName, Action onChangedCallback) + { + var watcher = new FileSystemWatcher(); + watcher.Path = Path.Combine(LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{moduleName}"); + watcher.Filter = fileName; + watcher.NotifyFilter = NotifyFilters.LastWrite; + watcher.Changed += (o, e) => onChangedCallback(); + watcher.EnableRaisingEvents = true; + + return watcher; + } + + private static string LocalApplicationDataFolder() + { + return Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); + } + [DllImport("user32.dll")] private static extern bool AllowSetForegroundWindow(int dwProcessId); } diff --git a/src/core/Microsoft.PowerToys.Settings.UI/ViewModels/KeyboardManagerViewModel.cs b/src/core/Microsoft.PowerToys.Settings.UI/ViewModels/KeyboardManagerViewModel.cs index dc3435ba89..b27689b62c 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI/ViewModels/KeyboardManagerViewModel.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI/ViewModels/KeyboardManagerViewModel.cs @@ -2,9 +2,13 @@ // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; +using System.IO; +using System.Threading; using System.Threading.Tasks; using System.Windows.Input; using Microsoft.PowerToys.Settings.UI.Helpers; +using Microsoft.PowerToys.Settings.UI.Lib; using Microsoft.PowerToys.Settings.UI.Lib.Utilities; using Microsoft.PowerToys.Settings.UI.Views; @@ -12,8 +16,19 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels { public class KeyboardManagerViewModel : Observable { + private const string PowerToyName = "Keyboard Manager"; + private const string RemapKeyboardActionName = "RemapKeyboard"; + private const string RemapKeyboardActionValue = "Open Remap Keyboard Window"; + private const string EditShortcutActionName = "EditShortcut"; + private const string EditShortcutActionValue = "Open Edit Shortcut Window"; + private const string JsonFileType = ".json"; + private const string ConfigFileMutexName = "PowerToys.KeyboardManager.ConfigMutex"; + private const int ConfigFileMutexWaitTimeoutMiliSeconds = 1000; + private ICommand remapKeyboardCommand; private ICommand editShortcutCommand; + private FileSystemWatcher watcher; + private KeyboardManagerSettings settings; public ICommand RemapKeyboardCommand => remapKeyboardCommand ?? (remapKeyboardCommand = new RelayCommand(OnRemapKeyboard)); @@ -21,6 +36,18 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels public KeyboardManagerViewModel() { + if (SettingsUtils.SettingsExists(PowerToyName)) + { + // Todo: Be more resillent while reading and saving settings. + settings = SettingsUtils.GetSettings(PowerToyName); + } + else + { + settings = new KeyboardManagerSettings(PowerToyName); + SettingsUtils.SaveSettings(settings.ToJsonString(), PowerToyName); + } + + watcher = Helper.GetFileWatcher(PowerToyName, settings.Properties.ActiveConfiguration.Value + JsonFileType, OnConfigFileUpdate); } private async void OnRemapKeyboard() @@ -36,15 +63,49 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels private async Task OnRemapKeyboardBackground() { Helper.AllowRunnerToForeground(); - ShellPage.DefaultSndMSGCallback(Helper.GetSerializedCustomAction("Keyboard Manager", "RemapKeyboard", "Create Remap Keyboard Window")); + ShellPage.DefaultSndMSGCallback(Helper.GetSerializedCustomAction(PowerToyName, RemapKeyboardActionName, RemapKeyboardActionValue)); await Task.CompletedTask; } private async Task OnEditShortcutBackground() { Helper.AllowRunnerToForeground(); - ShellPage.DefaultSndMSGCallback(Helper.GetSerializedCustomAction("Keyboard Manager", "EditShortcut", "Create Edit Shortcut Window")); + ShellPage.DefaultSndMSGCallback(Helper.GetSerializedCustomAction(PowerToyName, EditShortcutActionName, EditShortcutActionValue)); await Task.CompletedTask; } + + private void OnConfigFileUpdate() + { + // Note: FileSystemWatcher raise notification mutiple times for single update operation. + // Todo: Handle duplicate events either by somehow supress them or re-read the configuration everytime since we will be updating the UI only if something is changed. + GetKeyboardManagerConfigFile(); + } + + private void GetKeyboardManagerConfigFile() + { + try + { + using (var configFileMutex = Mutex.OpenExisting(ConfigFileMutexName)) + { + if (configFileMutex.WaitOne(ConfigFileMutexWaitTimeoutMiliSeconds)) + { + // update the UI element here. + try + { + var config = SettingsUtils.GetSettings(PowerToyName, settings.Properties.ActiveConfiguration.Value + JsonFileType); + } + finally + { + // Make sure to release the mutex. + configFileMutex.ReleaseMutex(); + } + } + } + } + catch (Exception) + { + // Failed to load the configuration. + } + } } } diff --git a/src/modules/keyboardmanager/common/Helpers.cpp b/src/modules/keyboardmanager/common/Helpers.cpp index b440dfea1f..613f888a4d 100644 --- a/src/modules/keyboardmanager/common/Helpers.cpp +++ b/src/modules/keyboardmanager/common/Helpers.cpp @@ -2,74 +2,77 @@ #include "Helpers.h" #include -// Function to split a wstring based on a delimiter and return a vector of split strings -std::vector splitwstring(const std::wstring& input, wchar_t delimiter) +namespace KeyboardManagerHelper { - std::wstringstream ss(input); - std::wstring item; - std::vector splittedStrings; - while (std::getline(ss, item, L' ')) + // Function to split a wstring based on a delimiter and return a vector of split strings + std::vector splitwstring(const std::wstring& input, wchar_t delimiter) { - splittedStrings.push_back(item); + std::wstringstream ss(input); + std::wstring item; + std::vector splittedStrings; + while (std::getline(ss, item, delimiter)) + { + splittedStrings.push_back(item); + } + + return splittedStrings; + } + + // Function to return the next sibling element for an element under a stack panel + winrt::Windows::Foundation::IInspectable getSiblingElement(winrt::Windows::Foundation::IInspectable const& element) + { + FrameworkElement frameworkElement = element.as(); + StackPanel parentElement = frameworkElement.Parent().as(); + uint32_t index; + + parentElement.Children().IndexOf(frameworkElement, index); + return parentElement.Children().GetAt(index + 1); + } + + // Function to check if the key is a modifier key + bool IsModifierKey(DWORD key) + { + return (GetKeyType(key) != KeyType::Action); } - return splittedStrings; -} - -// Function to return the next sibling element for an element under a stack panel -IInspectable getSiblingElement(IInspectable const& element) -{ - FrameworkElement frameworkElement = element.as(); - StackPanel parentElement = frameworkElement.Parent().as(); - uint32_t index; - - parentElement.Children().IndexOf(frameworkElement, index); - return parentElement.Children().GetAt(index + 1); -} - -// Function to check if the key is a modifier key -bool IsModifierKey(DWORD key) -{ - return (GetKeyType(key) != KeyType::Action); -} - -// Function to get the type of the key -KeyType GetKeyType(DWORD key) -{ - switch (key) + // Function to get the type of the key + KeyType GetKeyType(DWORD key) { - case VK_LWIN: - case VK_RWIN: - return KeyType::Win; - case VK_CONTROL: - case VK_LCONTROL: - case VK_RCONTROL: - return KeyType::Ctrl; - case VK_MENU: - case VK_LMENU: - case VK_RMENU: - return KeyType::Alt; - case VK_SHIFT: - case VK_LSHIFT: - case VK_RSHIFT: - return KeyType::Shift; - default: - return KeyType::Action; - } -} - -// Function to return if the key is an extended key which requires the use of the extended key flag -bool isExtendedKey(DWORD key) -{ - switch (key) - { - case VK_RCONTROL: - case VK_RMENU: - case VK_NUMLOCK: - case VK_SNAPSHOT: - case VK_CANCEL: - return true; - default: - return false; + switch (key) + { + case VK_LWIN: + case VK_RWIN: + return KeyType::Win; + case VK_CONTROL: + case VK_LCONTROL: + case VK_RCONTROL: + return KeyType::Ctrl; + case VK_MENU: + case VK_LMENU: + case VK_RMENU: + return KeyType::Alt; + case VK_SHIFT: + case VK_LSHIFT: + case VK_RSHIFT: + return KeyType::Shift; + default: + return KeyType::Action; + } + } + + // Function to return if the key is an extended key which requires the use of the extended key flag + bool isExtendedKey(DWORD key) + { + switch (key) + { + case VK_RCONTROL: + case VK_RMENU: + case VK_NUMLOCK: + case VK_SNAPSHOT: + case VK_CANCEL: + return true; + default: + return false; + } } } diff --git a/src/modules/keyboardmanager/common/Helpers.h b/src/modules/keyboardmanager/common/Helpers.h index cc2aedefb5..046a0d83c5 100644 --- a/src/modules/keyboardmanager/common/Helpers.h +++ b/src/modules/keyboardmanager/common/Helpers.h @@ -2,52 +2,58 @@ #include #include -// Type to distinguish between keys -enum class KeyType +namespace KeyboardManagerHelper { - Win, - Ctrl, - Alt, - Shift, - Action -}; - -// Function to split a wstring based on a delimiter and return a vector of split strings -std::vector splitwstring(const std::wstring& input, wchar_t delimiter); - -// Function to return the next sibling element for an element under a stack panel -winrt::Windows::Foundation::IInspectable getSiblingElement(winrt::Windows::Foundation::IInspectable const& element); - -// Function to convert an unsigned int vector to hstring by concatenating them -template -winrt::hstring convertVectorToHstring(const std::vector& input) -{ - winrt::hstring output; - for (int i = 0; i < input.size(); i++) + // Type to distinguish between keys + enum class KeyType { - output = output + winrt::to_hstring((unsigned int)input[i]) + winrt::to_hstring(L" "); - } - return output; -} + Win, + Ctrl, + Alt, + Shift, + Action + }; + + // Function to split a wstring based on a delimiter and return a vector of split strings + std::vector splitwstring(const std::wstring& input, wchar_t delimiter); + + // Function to return the next sibling element for an element under a stack panel + winrt::Windows::Foundation::IInspectable getSiblingElement(winrt::Windows::Foundation::IInspectable const& element); -// Function to convert a wstring vector to a integer vector -template -std::vector convertWStringVectorToIntegerVector(const std::vector& input) -{ - std::vector typeVector; - for (int i = 0; i < input.size(); i++) + // Function to convert an unsigned int vector to hstring by concatenating them + template + winrt::hstring convertVectorToHstring(const std::vector& input) { - typeVector.push_back((T)std::stoi(input[i])); + winrt::hstring output; + for (int i = 0; i < input.size(); i++) + { + output = output + winrt::to_hstring((unsigned int)input[i]) + winrt::to_hstring(L" "); + } + return output; } - return typeVector; + // Function to convert a wstring vector to a integer vector + template + std::vector convertWStringVectorToIntegerVector(const std::vector& input) + { + std::vector typeVector; + for (int i = 0; i < input.size(); i++) + { + typeVector.push_back((T)std::stoi(input[i])); + } + + return typeVector; + } + + // Function to return if the key is an extended key which requires the use of the extended key flag + bool isExtendedKey(DWORD key); + + // Function to check if the key is a modifier key + bool IsModifierKey(DWORD key); + + // Function to get the type of the key + KeyType GetKeyType(DWORD key); + + // Function to return if the key is an extended key which requires the use of the extended key flag + bool isExtendedKey(DWORD key); } - -// Function to check if the key is a modifier key -bool IsModifierKey(DWORD key); - -// Function to get the type of the key -KeyType GetKeyType(DWORD key); - -// Function to return if the key is an extended key which requires the use of the extended key flag -bool isExtendedKey(DWORD key); diff --git a/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj b/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj index aa0affb8cf..9575c769c9 100644 --- a/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj +++ b/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj @@ -55,8 +55,8 @@ _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpplatest + ..\;..\..\..\common;..\..\..\common\telemetry;..\..\;%(AdditionalIncludeDirectories) MultiThreadedDebug - $(SolutionDir)src\;$(SolutionDir)src\modules;$(SolutionDir)src\common\Telemetry;%(AdditionalIncludeDirectories) Use pch.h @@ -74,7 +74,7 @@ NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpplatest - $(SolutionDir)src\;$(SolutionDir)src\modules;$(SolutionDir)src\common\Telemetry;%(AdditionalIncludeDirectories) + ..\;..\..\..\common;..\..\..\common\telemetry;..\..\;%(AdditionalIncludeDirectories) MultiThreaded Use pch.h @@ -100,6 +100,7 @@ + diff --git a/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj.filters b/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj.filters index 9cf7199d16..b7b3256953 100644 --- a/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj.filters +++ b/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj.filters @@ -59,5 +59,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/src/modules/keyboardmanager/common/KeyboardManagerConstants.h b/src/modules/keyboardmanager/common/KeyboardManagerConstants.h new file mode 100644 index 0000000000..f954c8b9fa --- /dev/null +++ b/src/modules/keyboardmanager/common/KeyboardManagerConstants.h @@ -0,0 +1,41 @@ +#pragma once +#include + +namespace KeyboardManagerConstants +{ + // Name of the powertoy module. + inline const std::wstring ModuleName = L"Keyboard Manager"; + + // Name of the property use to store current active configuration. + inline const std::wstring ActiveConfigurationSettingName = L"activeConfiguration"; + + // Name of the property use to store single keyremaps. + inline const std::wstring RemapKeysSettingName = L"remapKeys"; + + // Name of the property use to store single keyremaps array in case of in process approach. + inline const std::wstring InProcessRemapKeysSettingName = L"inProcess"; + + // Name of the property use to store shortcut remaps. + inline const std::wstring RemapShortcutsSettingName = L"remapShortcuts"; + + // Name of the property use to store global shortcut remaps array. + inline const std::wstring GlobalRemapShortcutsSettingName = L"global"; + + // Name of the property use to store original keys. + inline const std::wstring OriginalKeysSettingName = L"originalKeys"; + + // Name of the property use to store new remap keys. + inline const std::wstring NewRemapKeysSettingName = L"newRemapKeys"; + + // Name of the default configuration. + inline const std::wstring DefaultConfiguration = L"default"; + + // Name of the named mutex used for configuration file. + inline const std::wstring ConfigFileMutexName = L"PowerToys.KeyboardManager.ConfigMutex"; + + // Name of the dummy update file. + inline const std::wstring DummyUpdateFileName = L"settings-updated.json"; + + // Fake key code to represent VK_WIN. + inline const DWORD VK_WIN_BOTH = 0x104; +} \ No newline at end of file diff --git a/src/modules/keyboardmanager/common/KeyboardManagerState.cpp b/src/modules/keyboardmanager/common/KeyboardManagerState.cpp index 4aff6ccda7..5c8dca1f6c 100644 --- a/src/modules/keyboardmanager/common/KeyboardManagerState.cpp +++ b/src/modules/keyboardmanager/common/KeyboardManagerState.cpp @@ -5,6 +5,19 @@ KeyboardManagerState::KeyboardManagerState() : uiState(KeyboardManagerUIState::Deactivated), currentUIWindow(nullptr), currentShortcutUI(nullptr), currentSingleKeyUI(nullptr), detectedRemapKey(NULL) { + configFile_mutex = CreateMutex( + NULL, // default security descriptor + FALSE, // mutex not owned + KeyboardManagerConstants::ConfigFileMutexName.c_str()); +} + +// Destructor +KeyboardManagerState::~KeyboardManagerState() +{ + if (configFile_mutex) + { + CloseHandle(configFile_mutex); + } } // Function to check the if the UI state matches the argument state. For states with activated windows it also checks if the window is in focus. @@ -344,4 +357,79 @@ bool KeyboardManagerState::HandleKeyDelayEvent(LowlevelKeyboardEvent* ev) keyDelays[ev->lParam->vkCode]->KeyEvent(ev); return true; +} + +// Save the updated configuration. +bool KeyboardManagerState::SaveConfigToFile() +{ + bool result = true; + json::JsonObject configJson; + json::JsonObject remapShortcuts; + json::JsonObject remapKeys; + json::JsonArray inProcessRemapKeysArray; + json::JsonArray globalRemapShortcutsArray; + std::unique_lock lockSingleKeyReMap(singleKeyReMap_mutex); + for (const auto &it : singleKeyReMap) + { + json::JsonObject keys; + keys.SetNamedValue(KeyboardManagerConstants::OriginalKeysSettingName, json::value(winrt::to_hstring((unsigned int)it.first))); + keys.SetNamedValue(KeyboardManagerConstants::NewRemapKeysSettingName, json::value(winrt::to_hstring((unsigned int)it.second))); + + inProcessRemapKeysArray.Append(keys); + } + lockSingleKeyReMap.unlock(); + + std::unique_lock lockOsLevelShortcutReMap(osLevelShortcutReMap_mutex); + for (const auto &it : osLevelShortcutReMap) + { + json::JsonObject keys; + keys.SetNamedValue(KeyboardManagerConstants::OriginalKeysSettingName, json::value(it.first.ToHstringVK())); + keys.SetNamedValue(KeyboardManagerConstants::NewRemapKeysSettingName, json::value(it.second.targetShortcut.ToHstringVK())); + + globalRemapShortcutsArray.Append(keys); + } + lockOsLevelShortcutReMap.unlock(); + + remapShortcuts.SetNamedValue(KeyboardManagerConstants::GlobalRemapShortcutsSettingName, globalRemapShortcutsArray); + remapKeys.SetNamedValue(KeyboardManagerConstants::InProcessRemapKeysSettingName, inProcessRemapKeysArray); + configJson.SetNamedValue(KeyboardManagerConstants::RemapKeysSettingName, remapKeys); + configJson.SetNamedValue(KeyboardManagerConstants::RemapShortcutsSettingName, remapShortcuts); + + // Set timeout of 1sec to wait for file to get free. + DWORD timeout = 1000; + auto dwWaitResult = WaitForSingleObject( + configFile_mutex, + timeout); + if (dwWaitResult == WAIT_OBJECT_0) + { + try + { + json::to_file((PTSettingsHelper::get_module_save_folder_location(KeyboardManagerConstants::ModuleName) + L"\\" + GetCurrentConfigName() + L".json"), configJson); + } + catch (...) + { + result = false; + } + + // Make sure to release the Mutex. + ReleaseMutex(configFile_mutex); + } + else + { + result = false; + } + + return result; +} + +void KeyboardManagerState::SetCurrentConfigName(const std::wstring& configName) +{ + std::lock_guard lock(currentConfig_mutex); + currentConfig = configName; +} + +std::wstring KeyboardManagerState::GetCurrentConfigName() +{ + std::lock_guard lock(currentConfig_mutex); + return currentConfig; } \ No newline at end of file diff --git a/src/modules/keyboardmanager/common/KeyboardManagerState.h b/src/modules/keyboardmanager/common/KeyboardManagerState.h index 8280652cf0..53b0130927 100644 --- a/src/modules/keyboardmanager/common/KeyboardManagerState.h +++ b/src/modules/keyboardmanager/common/KeyboardManagerState.h @@ -4,9 +4,11 @@ #include "Shortcut.h" #include "RemapShortcut.h" #include "KeyDelay.h" +#include "KeyboardManagerConstants.h" #include #include #include +#include <../common/settings_helpers.h> using namespace winrt::Windows::UI::Xaml::Controls; // Enum type to store different states of the UI @@ -51,6 +53,13 @@ private: // Stores the UI element which is to be updated based on the shortcut entered StackPanel currentShortcutUI; std::mutex currentShortcutUI_mutex; + + // Stores the current configuration name. + std::wstring currentConfig = KeyboardManagerConstants::DefaultConfiguration; + std::mutex currentConfig_mutex; + + // Handle of named mutex used for configuration file. + HANDLE configFile_mutex; // Registered KeyDelay objects, used to notify delayed key events. std::map> keyDelays; @@ -84,6 +93,9 @@ public: // Constructor KeyboardManagerState(); + // Destructor + ~KeyboardManagerState(); + // Function to reset the UI state members void ResetUIState(); @@ -157,4 +169,13 @@ public: // Reset the shortcut (backend) state after releasing a key. void ResetDetectedShortcutKey(DWORD key); + + // Save the updated configuration. + bool SaveConfigToFile(); + + // Sets the Current Active Configuartion Name. + void SetCurrentConfigName(const std::wstring& configName); + + // Gets the Current Active Configuartion Name. + std::wstring GetCurrentConfigName(); }; \ No newline at end of file diff --git a/src/modules/keyboardmanager/common/Shortcut.cpp b/src/modules/keyboardmanager/common/Shortcut.cpp index e98cabc95b..5c7be0d76f 100644 --- a/src/modules/keyboardmanager/common/Shortcut.cpp +++ b/src/modules/keyboardmanager/common/Shortcut.cpp @@ -418,6 +418,43 @@ std::vector Shortcut::GetKeyVector(LayoutMap& keyboardMap) const return keys; } +// Function to return the string representation of the shortcut in virtual key codes appended in a string by ";" separator. +winrt::hstring Shortcut::ToHstringVK() const +{ + winrt::hstring output; + if (winKey != ModifierKey::Disabled && winKey != ModifierKey::Both) + { + output = output + winrt::to_hstring((unsigned int)GetWinKey(ModifierKey::Left)) + winrt::to_hstring(L";"); + } + if (winKey == ModifierKey::Both) + { + output = output + winrt::to_hstring((unsigned int)KeyboardManagerConstants::VK_WIN_BOTH) + winrt::to_hstring(L";"); + } + if (ctrlKey != ModifierKey::Disabled) + { + output = output + winrt::to_hstring((unsigned int)GetCtrlKey()) + winrt::to_hstring(L";"); + } + if (altKey != ModifierKey::Disabled) + { + output = output + winrt::to_hstring((unsigned int)GetAltKey()) + winrt::to_hstring(L";"); + } + if (shiftKey != ModifierKey::Disabled) + { + output = output + winrt::to_hstring((unsigned int)GetShiftKey()) + winrt::to_hstring(L";"); + } + if (actionKey != NULL) + { + output = output + winrt::to_hstring((unsigned int)GetActionKey()) + winrt::to_hstring(L";"); + } + + if (!output.empty()) + { + output = winrt::hstring(output.c_str(), output.size() - 1); + } + + return output; +} + // Function to return a vector of key codes in the display order std::vector Shortcut::GetKeyCodes() { diff --git a/src/modules/keyboardmanager/common/Shortcut.h b/src/modules/keyboardmanager/common/Shortcut.h index 6ccf9851c5..0a72b8bb06 100644 --- a/src/modules/keyboardmanager/common/Shortcut.h +++ b/src/modules/keyboardmanager/common/Shortcut.h @@ -1,6 +1,7 @@ #pragma once #include "Helpers.h" #include "LayoutMap.h" +#include "KeyboardManagerConstants.h" #include // Enum type to store different states of the win key @@ -28,6 +29,25 @@ public: { } + // Constructor to intialize Shortcut from it's virtual key code string representation. + Shortcut(const std::wstring& shortcutVK) : + winKey(ModifierKey::Disabled), ctrlKey(ModifierKey::Disabled), altKey(ModifierKey::Disabled), shiftKey(ModifierKey::Disabled), actionKey(NULL) + { + auto keys = KeyboardManagerHelper::splitwstring(shortcutVK, ';'); + for (auto it : keys) + { + auto vkKeyCode = std::stoul(it); + if (vkKeyCode == KeyboardManagerConstants::VK_WIN_BOTH) + { + SetKey(vkKeyCode, true); + } + else + { + SetKey(vkKeyCode); + } + } + } + // Less than operator must be defined to use with std::map. inline bool operator<(const Shortcut& sc) const { @@ -135,6 +155,12 @@ public: // Function to reset the state of a shortcut key based on the passed key code argument. Since there is no VK_WIN code, use the second argument for setting common win key. void ResetKey(const DWORD& input, const bool& isWinBoth = false); + // Function to return the string representation of the shortcut + winrt::hstring ToHstring(LayoutMap& keyboardMap); + + // Function to return the string representation of the shortcut in virtual key codes appended in a string by ";" separator. + winrt::hstring ToHstringVK() const; + // Function to return a vector of hstring for each key in the display order std::vector GetKeyVector(LayoutMap& keyboardMap) const; diff --git a/src/modules/keyboardmanager/common/pch.h b/src/modules/keyboardmanager/common/pch.h index 29c7a4effb..bdd02fa85d 100644 --- a/src/modules/keyboardmanager/common/pch.h +++ b/src/modules/keyboardmanager/common/pch.h @@ -19,6 +19,5 @@ using namespace Windows::UI; using namespace Windows::UI::Composition; using namespace Windows::UI::Xaml::Hosting; using namespace Windows::Foundation::Numerics; -using namespace Windows::Foundation; using namespace Windows::UI::Xaml; using namespace Windows::UI::Xaml::Controls; \ No newline at end of file diff --git a/src/modules/keyboardmanager/dll/dllmain.cpp b/src/modules/keyboardmanager/dll/dllmain.cpp index eb436d09ed..ce5edd48bd 100644 --- a/src/modules/keyboardmanager/dll/dllmain.cpp +++ b/src/modules/keyboardmanager/dll/dllmain.cpp @@ -10,6 +10,8 @@ #include #include #include +#include +#include extern "C" IMAGE_DOS_HEADER __ImageBase; @@ -64,12 +66,81 @@ public: // Constructor KeyboardManager() { - init_map(); + // Load the initial configuration. + load_config(); // Set the static pointer to the newest object of the class keyboardmanager_object_ptr = this; }; + // Load config from the saved settings. + void load_config() + { + try + { + PowerToysSettings::PowerToyValues settings = + PowerToysSettings::PowerToyValues::load_from_settings_file(get_name()); + auto current_config = settings.get_string_value(KeyboardManagerConstants::ActiveConfigurationSettingName); + + if (current_config) + { + keyboardManagerState.SetCurrentConfigName(*current_config); + // Read the config file and load the remaps. + auto configFile = json::from_file(PTSettingsHelper::get_module_save_folder_location(KeyboardManagerConstants::ModuleName) + L"\\" + *current_config + L".json"); + if (configFile) + { + auto jsonData = *configFile; + auto remapKeysData = jsonData.GetNamedObject(KeyboardManagerConstants::RemapKeysSettingName); + auto remapShortcutsData = jsonData.GetNamedObject(KeyboardManagerConstants::RemapShortcutsSettingName); + keyboardManagerState.ClearSingleKeyRemaps(); + + if (remapKeysData) + { + auto inProcessRemapKeys = remapKeysData.GetNamedArray(KeyboardManagerConstants::InProcessRemapKeysSettingName); + for (const auto& it : inProcessRemapKeys) + { + try + { + auto originalKey = it.GetObjectW().GetNamedString(KeyboardManagerConstants::OriginalKeysSettingName); + auto newRemapKey = it.GetObjectW().GetNamedString(KeyboardManagerConstants::NewRemapKeysSettingName); + keyboardManagerState.AddSingleKeyRemap(std::stoul(originalKey.c_str()), std::stoul(newRemapKey.c_str())); + } + catch (...) + { + // Improper Key Data JSON. Try the next remap. + } + } + } + + keyboardManagerState.ClearOSLevelShortcuts(); + if (remapShortcutsData) + { + auto globalRemapShortcuts = remapShortcutsData.GetNamedArray(KeyboardManagerConstants::GlobalRemapShortcutsSettingName); + for (const auto& it : globalRemapShortcuts) + { + try + { + auto originalKeys = it.GetObjectW().GetNamedString(KeyboardManagerConstants::OriginalKeysSettingName); + auto newRemapKeys = it.GetObjectW().GetNamedString(KeyboardManagerConstants::NewRemapKeysSettingName); + Shortcut originalSC(originalKeys.c_str()); + Shortcut newRemapSC(newRemapKeys.c_str()); + keyboardManagerState.AddOSLevelShortcut(originalSC, newRemapSC); + } + catch (...) + { + // Improper Key Data JSON. Try the next shortcut. + } + } + } + } + } + } + catch (...) + { + // Unable to load inital config. + } + } + // This function is used to add the hardcoded mappings void init_map() { @@ -325,7 +396,7 @@ public: keyEventArray[index].type = inputType; keyEventArray[index].ki.wVk = keyCode; keyEventArray[index].ki.dwFlags = flags; - if (isExtendedKey(keyCode)) + if (KeyboardManagerHelper::isExtendedKey(keyCode)) { keyEventArray[index].ki.dwFlags |= KEYEVENTF_EXTENDEDKEY; } diff --git a/src/modules/keyboardmanager/ui/EditKeyboardWindow.cpp b/src/modules/keyboardmanager/ui/EditKeyboardWindow.cpp index 957c504d4a..3cabea6674 100644 --- a/src/modules/keyboardmanager/ui/EditKeyboardWindow.cpp +++ b/src/modules/keyboardmanager/ui/EditKeyboardWindow.cpp @@ -95,7 +95,7 @@ void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMan cancelButton.Background(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::LightGray() }); cancelButton.Foreground(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::Black() }); cancelButton.Content(winrt::box_value(winrt::to_hstring("Cancel"))); - cancelButton.Click([&](IInspectable const& sender, RoutedEventArgs const&) { + cancelButton.Click([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) { // Close the window since settings do not need to be saved PostMessage(_hWndEditKeyboardWindow, WM_CLOSE, 0, 0); }); @@ -162,7 +162,7 @@ void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMan applyButton.Background(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::LightGray() }); applyButton.Foreground(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::Black() }); applyButton.Content(winrt::box_value(winrt::to_hstring("Apply"))); - applyButton.Click([&](IInspectable const& sender, RoutedEventArgs const&) { + applyButton.Click([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) { bool isSuccess = true; // Clear existing Key Remaps keyboardManagerState.ClearSingleKeyRemaps(); @@ -186,16 +186,24 @@ void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMan } } - if (isSuccess) + // Save the updated shortcuts remaps to file. + auto saveResult = keyboardManagerState.SaveConfigToFile(); + + if (isSuccess && saveResult) { settingsMessage.Foreground(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::Green() }); settingsMessage.Text(winrt::to_hstring("Remapping successful!")); } - else + else if (!isSuccess && saveResult) { settingsMessage.Foreground(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::Red() }); settingsMessage.Text(winrt::to_hstring("All remappings were not successfully applied.")); } + else + { + settingsMessage.Foreground(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::Red() }); + settingsMessage.Text(winrt::to_hstring("Failed to save the remappings.")); + } }); header.Children().Append(headerText); @@ -212,7 +220,7 @@ void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMan plusSymbol.Glyph(L"\xE109"); addRemapKey.Content(plusSymbol); addRemapKey.Margin({ 10 }); - addRemapKey.Click([&](IInspectable const& sender, RoutedEventArgs const&) { + addRemapKey.Click([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) { SingleKeyRemapControl::AddNewControlKeyRemapRow(keyRemapTable, keyboardRemapControlObjects); }); diff --git a/src/modules/keyboardmanager/ui/EditShortcutsWindow.cpp b/src/modules/keyboardmanager/ui/EditShortcutsWindow.cpp index 72fda019b3..5b4cc3ef3c 100644 --- a/src/modules/keyboardmanager/ui/EditShortcutsWindow.cpp +++ b/src/modules/keyboardmanager/ui/EditShortcutsWindow.cpp @@ -94,7 +94,7 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa // Cancel button Button cancelButton; cancelButton.Content(winrt::box_value(winrt::to_hstring("Cancel"))); - cancelButton.Click([&](IInspectable const& sender, RoutedEventArgs const&) { + cancelButton.Click([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) { // Close the window since settings do not need to be saved PostMessage(_hWndEditShortcutsWindow, WM_CLOSE, 0, 0); }); @@ -151,7 +151,7 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa // Apply button Button applyButton; applyButton.Content(winrt::box_value(winrt::to_hstring("Apply"))); - applyButton.Click([&](IInspectable const& sender, RoutedEventArgs const&) { + applyButton.Click([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) { bool isSuccess = true; // Clear existing shortcuts keyboardManagerState.ClearOSLevelShortcuts(); @@ -176,16 +176,24 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa } } - if (isSuccess) + // Save the updated key remaps to file. + auto saveResult = keyboardManagerState.SaveConfigToFile(); + + if (isSuccess && saveResult) { settingsMessage.Foreground(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::Green() }); settingsMessage.Text(winrt::to_hstring("Remapping successful!")); } - else + else if (!isSuccess && saveResult) { settingsMessage.Foreground(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::Red() }); settingsMessage.Text(winrt::to_hstring("All remappings were not successfully applied.")); } + else + { + settingsMessage.Foreground(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::Red() }); + settingsMessage.Text(winrt::to_hstring("Failed to save the remappings.")); + } }); header.Children().Append(headerText); @@ -200,7 +208,7 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa plusSymbol.Glyph(L"\xE109"); addShortcut.Content(plusSymbol); addShortcut.Margin({ 10 }); - addShortcut.Click([&](IInspectable const& sender, RoutedEventArgs const&) { + addShortcut.Click([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) { ShortcutControl::AddNewShortcutControlRow(shortcutTable, keyboardRemapControlObjects); }); diff --git a/src/modules/keyboardmanager/ui/KeyDropDownControl.cpp b/src/modules/keyboardmanager/ui/KeyDropDownControl.cpp index e15257e4b8..fca34d3db3 100644 --- a/src/modules/keyboardmanager/ui/KeyDropDownControl.cpp +++ b/src/modules/keyboardmanager/ui/KeyDropDownControl.cpp @@ -14,7 +14,7 @@ void KeyDropDownControl::SetDefaultProperties(bool isShortcut) keyCodeList = keyboardManagerState->keyboardMap.GetKeyCodeList(isShortcut); dropDown.ItemsSource(keyboardManagerState->keyboardMap.GetKeyNameList(isShortcut)); // drop down open handler - to reload the items with the latest layout - dropDown.DropDownOpened([&, isShortcut](IInspectable const& sender, auto args) { + dropDown.DropDownOpened([&, isShortcut](winrt::Windows::Foundation::IInspectable const& sender, auto args) { ComboBox currentDropDown = sender.as(); CheckAndUpdateKeyboardLayout(currentDropDown, isShortcut); }); @@ -93,7 +93,7 @@ bool KeyDropDownControl::CheckRepeatedModifier(StackPanel parent, uint32_t dropD if (i != dropDownIndex) { // If the key type for the newly added key matches any of the existing keys in the shortcut - if (GetKeyType(keyCodeList[selectedKeyIndex]) == GetKeyType(currentKeys[i])) + if (KeyboardManagerHelper::GetKeyType(keyCodeList[selectedKeyIndex]) == KeyboardManagerHelper::GetKeyType(currentKeys[i])) { matchPreviousModifier = true; break; diff --git a/src/modules/keyboardmanager/ui/KeyDropDownControl.h b/src/modules/keyboardmanager/ui/KeyDropDownControl.h index f43b34463f..3c98dd602d 100644 --- a/src/modules/keyboardmanager/ui/KeyDropDownControl.h +++ b/src/modules/keyboardmanager/ui/KeyDropDownControl.h @@ -26,7 +26,7 @@ public: KeyDropDownControl(size_t rowIndex, size_t colIndex, std::vector>& singleKeyRemapBuffer) { SetDefaultProperties(false); - dropDown.SelectionChanged([&, rowIndex, colIndex](IInspectable const& sender, SelectionChangedEventArgs const& args) { + dropDown.SelectionChanged([&, rowIndex, colIndex](winrt::Windows::Foundation::IInspectable const& sender, SelectionChangedEventArgs const& args) { ComboBox currentDropDown = sender.as(); int selectedKeyIndex = currentDropDown.SelectedIndex(); @@ -53,7 +53,7 @@ public: dropDown.ContextFlyout().SetAttachedFlyout((FrameworkElement)dropDown, warningFlyout); // drop down selection handler - dropDown.SelectionChanged([&, rowIndex, colIndex, parent, warningMessage](IInspectable const& sender, SelectionChangedEventArgs const&) { + dropDown.SelectionChanged([&, rowIndex, colIndex, parent, warningMessage](winrt::Windows::Foundation::IInspectable const& sender, SelectionChangedEventArgs const&) { ComboBox currentDropDown = sender.as(); int selectedKeyIndex = currentDropDown.SelectedIndex(); uint32_t dropDownIndex = -1; @@ -62,7 +62,7 @@ public: 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 && !IsModifierKey(keyCodeList[selectedKeyIndex])) + if (parent.Children().Size() == 1 && !KeyboardManagerHelper::IsModifierKey(keyCodeList[selectedKeyIndex])) { // warn and reset the drop down SetDropDownError(currentDropDown, warningMessage, L"Shortcut must start with a modifier key"); @@ -71,7 +71,7 @@ public: else if (dropDownIndex == parent.Children().Size() - 1) { // If last drop down and a modifier is selected: add a new drop down (max of 5 drop downs should be enforced) - if (IsModifierKey(keyCodeList[selectedKeyIndex]) && parent.Children().Size() < 5) + if (KeyboardManagerHelper::IsModifierKey(keyCodeList[selectedKeyIndex]) && parent.Children().Size() < 5) { // If it matched any of the previous modifiers then reset that drop down if (CheckRepeatedModifier(parent, dropDownIndex, selectedKeyIndex, keyCodeList)) @@ -86,7 +86,7 @@ public: } } // If last drop down and a modifier is selected but there are already 5 drop downs: warn the user - else if (IsModifierKey(keyCodeList[selectedKeyIndex]) && parent.Children().Size() >= 5) + else if (KeyboardManagerHelper::IsModifierKey(keyCodeList[selectedKeyIndex]) && parent.Children().Size() >= 5) { // warn and reset the drop down SetDropDownError(currentDropDown, warningMessage, L"Shortcut must contain an action key"); @@ -102,7 +102,7 @@ public: // If it is the not the last drop down else { - if (IsModifierKey(keyCodeList[selectedKeyIndex])) + if (KeyboardManagerHelper::IsModifierKey(keyCodeList[selectedKeyIndex])) { // If it matched any of the previous modifiers then reset that drop down if (CheckRepeatedModifier(parent, dropDownIndex, selectedKeyIndex, keyCodeList)) diff --git a/src/modules/keyboardmanager/ui/ShortcutControl.cpp b/src/modules/keyboardmanager/ui/ShortcutControl.cpp index ed76027dc7..2bb2d7eeca 100644 --- a/src/modules/keyboardmanager/ui/ShortcutControl.cpp +++ b/src/modules/keyboardmanager/ui/ShortcutControl.cpp @@ -34,7 +34,7 @@ void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, std::vector().Parent().as(); uint32_t index; parent.Children().IndexOf(currentRow, index); @@ -101,7 +101,7 @@ StackPanel ShortcutControl::getShortcutControl() } // Function to create the detect shortcut UI window -void ShortcutControl::createDetectShortcutWindow(IInspectable const& sender, XamlRoot xamlRoot, std::vector>& shortcutRemapBuffer, KeyboardManagerState& keyboardManagerState, const size_t rowIndex, const size_t colIndex) +void ShortcutControl::createDetectShortcutWindow(winrt::Windows::Foundation::IInspectable const& sender, XamlRoot xamlRoot, std::vector>& shortcutRemapBuffer, KeyboardManagerState& keyboardManagerState, const size_t rowIndex, const size_t colIndex) { // ContentDialog for detecting shortcuts. This is the parent UI element. ContentDialog detectShortcutBox; @@ -115,7 +115,7 @@ void ShortcutControl::createDetectShortcutWindow(IInspectable const& sender, Xam detectShortcutBox.IsSecondaryButtonEnabled(false); // Get the linked text block for the "Type shortcut" button that was clicked - StackPanel linkedShortcutStackPanel = getSiblingElement(sender).as(); + StackPanel linkedShortcutStackPanel = KeyboardManagerHelper::getSiblingElement(sender).as(); auto unregisterKeys = [&keyboardManagerState]() { std::thread t1(&KeyboardManagerState::UnregisterKeyDelay, &keyboardManagerState, VK_ESCAPE); @@ -161,7 +161,7 @@ void ShortcutControl::createDetectShortcutWindow(IInspectable const& sender, Xam primaryButton.Content(primaryButtonText); // OK button - primaryButton.Click([onAccept](IInspectable const& sender, RoutedEventArgs const&) { + primaryButton.Click([onAccept](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) { onAccept(); }); @@ -191,7 +191,7 @@ void ShortcutControl::createDetectShortcutWindow(IInspectable const& sender, Xam cancelButton.Margin({ 2, 2, 2, 2 }); cancelButton.Content(cancelButtonText); // Cancel button - cancelButton.Click([detectShortcutBox, unregisterKeys, &keyboardManagerState](IInspectable const& sender, RoutedEventArgs const&) { + cancelButton.Click([detectShortcutBox, unregisterKeys, &keyboardManagerState](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) { // Reset the keyboard manager UI state keyboardManagerState.ResetUIState(); unregisterKeys(); diff --git a/src/modules/keyboardmanager/ui/ShortcutControl.h b/src/modules/keyboardmanager/ui/ShortcutControl.h index 7dbe1f5ae6..246bac1901 100644 --- a/src/modules/keyboardmanager/ui/ShortcutControl.h +++ b/src/modules/keyboardmanager/ui/ShortcutControl.h @@ -37,7 +37,7 @@ public: KeyDropDownControl::AddDropDown(shortcutDropDownStackPanel, rowIndex, colIndex, shortcutRemapBuffer, keyDropDownControlObjects); typeShortcut.Content(winrt::box_value(winrt::to_hstring("Type Shortcut"))); - typeShortcut.Click([&, rowIndex, colIndex](IInspectable const& sender, RoutedEventArgs const&) { + typeShortcut.Click([&, rowIndex, colIndex](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