mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-06-07 09:28:03 +08:00
[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
This commit is contained in:
parent
cae77ae291
commit
325db535c0
@ -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<T>
|
||||||
|
{
|
||||||
|
[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()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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; }
|
||||||
|
}
|
||||||
|
}
|
@ -2,22 +2,25 @@
|
|||||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Microsoft.PowerToys.Settings.UI.Lib
|
namespace Microsoft.PowerToys.Settings.UI.Lib
|
||||||
{
|
{
|
||||||
public class KeyboardManagerProperties
|
public class KeyboardManagerProperties
|
||||||
{
|
{
|
||||||
// Bool property to notify Keyboard Manager module if the Edit Shortcut button is pressed.
|
[JsonPropertyName("activeConfiguration")]
|
||||||
public BoolProperty EditShortcut { get; set; }
|
public GenericProperty<string> ActiveConfiguration { get; set; }
|
||||||
|
|
||||||
// Bool property to notify Keyboard Manager module if the Remap Keyboard button is pressed.
|
// List of all Keyboard Configurations.
|
||||||
public BoolProperty RemapKeyboard { get; set; }
|
[JsonPropertyName("keyboardConfigurations")]
|
||||||
|
public GenericProperty<List<string>> KeyboardConfigurations { get; set; }
|
||||||
|
|
||||||
public KeyboardManagerProperties()
|
public KeyboardManagerProperties()
|
||||||
{
|
{
|
||||||
EditShortcut = new BoolProperty();
|
KeyboardConfigurations = new GenericProperty<List<string>>(new List<string> { "default", });
|
||||||
RemapKeyboard = new BoolProperty();
|
ActiveConfiguration = new GenericProperty<string>("default");
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ToJsonString()
|
public string ToJsonString()
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Microsoft.PowerToys.Settings.UI.Lib
|
namespace Microsoft.PowerToys.Settings.UI.Lib
|
||||||
@ -27,5 +28,11 @@ namespace Microsoft.PowerToys.Settings.UI.Lib
|
|||||||
version = "1";
|
version = "1";
|
||||||
name = ptName;
|
name = ptName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// converts the current to a json string.
|
||||||
|
public override string ToJsonString()
|
||||||
|
{
|
||||||
|
return JsonSerializer.Serialize(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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; }
|
||||||
|
}
|
||||||
|
}
|
@ -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<KeysDataModel> InProcessRemapKeys { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -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<KeysDataModel> GlobalRemapShortcuts { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -2,8 +2,12 @@
|
|||||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
using Microsoft.PowerToys.Settings.UI.Lib.CustomAction;
|
using Microsoft.PowerToys.Settings.UI.Lib.CustomAction;
|
||||||
|
|
||||||
namespace Microsoft.PowerToys.Settings.UI.Lib.Utilities
|
namespace Microsoft.PowerToys.Settings.UI.Lib.Utilities
|
||||||
@ -41,6 +45,23 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.Utilities
|
|||||||
return sendCustomAction.ToJsonString();
|
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")]
|
[DllImport("user32.dll")]
|
||||||
private static extern bool AllowSetForegroundWindow(int dwProcessId);
|
private static extern bool AllowSetForegroundWindow(int dwProcessId);
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,13 @@
|
|||||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// 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.Threading.Tasks;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using Microsoft.PowerToys.Settings.UI.Helpers;
|
using Microsoft.PowerToys.Settings.UI.Helpers;
|
||||||
|
using Microsoft.PowerToys.Settings.UI.Lib;
|
||||||
using Microsoft.PowerToys.Settings.UI.Lib.Utilities;
|
using Microsoft.PowerToys.Settings.UI.Lib.Utilities;
|
||||||
using Microsoft.PowerToys.Settings.UI.Views;
|
using Microsoft.PowerToys.Settings.UI.Views;
|
||||||
|
|
||||||
@ -12,8 +16,19 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
|||||||
{
|
{
|
||||||
public class KeyboardManagerViewModel : Observable
|
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 remapKeyboardCommand;
|
||||||
private ICommand editShortcutCommand;
|
private ICommand editShortcutCommand;
|
||||||
|
private FileSystemWatcher watcher;
|
||||||
|
private KeyboardManagerSettings settings;
|
||||||
|
|
||||||
public ICommand RemapKeyboardCommand => remapKeyboardCommand ?? (remapKeyboardCommand = new RelayCommand(OnRemapKeyboard));
|
public ICommand RemapKeyboardCommand => remapKeyboardCommand ?? (remapKeyboardCommand = new RelayCommand(OnRemapKeyboard));
|
||||||
|
|
||||||
@ -21,6 +36,18 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
|||||||
|
|
||||||
public KeyboardManagerViewModel()
|
public KeyboardManagerViewModel()
|
||||||
{
|
{
|
||||||
|
if (SettingsUtils.SettingsExists(PowerToyName))
|
||||||
|
{
|
||||||
|
// Todo: Be more resillent while reading and saving settings.
|
||||||
|
settings = SettingsUtils.GetSettings<KeyboardManagerSettings>(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()
|
private async void OnRemapKeyboard()
|
||||||
@ -36,15 +63,49 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
|||||||
private async Task OnRemapKeyboardBackground()
|
private async Task OnRemapKeyboardBackground()
|
||||||
{
|
{
|
||||||
Helper.AllowRunnerToForeground();
|
Helper.AllowRunnerToForeground();
|
||||||
ShellPage.DefaultSndMSGCallback(Helper.GetSerializedCustomAction("Keyboard Manager", "RemapKeyboard", "Create Remap Keyboard Window"));
|
ShellPage.DefaultSndMSGCallback(Helper.GetSerializedCustomAction(PowerToyName, RemapKeyboardActionName, RemapKeyboardActionValue));
|
||||||
await Task.CompletedTask;
|
await Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task OnEditShortcutBackground()
|
private async Task OnEditShortcutBackground()
|
||||||
{
|
{
|
||||||
Helper.AllowRunnerToForeground();
|
Helper.AllowRunnerToForeground();
|
||||||
ShellPage.DefaultSndMSGCallback(Helper.GetSerializedCustomAction("Keyboard Manager", "EditShortcut", "Create Edit Shortcut Window"));
|
ShellPage.DefaultSndMSGCallback(Helper.GetSerializedCustomAction(PowerToyName, EditShortcutActionName, EditShortcutActionValue));
|
||||||
await Task.CompletedTask;
|
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<KeyboadManagerConfigModel>(PowerToyName, settings.Properties.ActiveConfiguration.Value + JsonFileType);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// Make sure to release the mutex.
|
||||||
|
configFileMutex.ReleaseMutex();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
// Failed to load the configuration.
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,74 +2,77 @@
|
|||||||
#include "Helpers.h"
|
#include "Helpers.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
// Function to split a wstring based on a delimiter and return a vector of split strings
|
namespace KeyboardManagerHelper
|
||||||
std::vector<std::wstring> splitwstring(const std::wstring& input, wchar_t delimiter)
|
|
||||||
{
|
{
|
||||||
std::wstringstream ss(input);
|
// Function to split a wstring based on a delimiter and return a vector of split strings
|
||||||
std::wstring item;
|
std::vector<std::wstring> splitwstring(const std::wstring& input, wchar_t delimiter)
|
||||||
std::vector<std::wstring> splittedStrings;
|
|
||||||
while (std::getline(ss, item, L' '))
|
|
||||||
{
|
{
|
||||||
splittedStrings.push_back(item);
|
std::wstringstream ss(input);
|
||||||
|
std::wstring item;
|
||||||
|
std::vector<std::wstring> 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<FrameworkElement>();
|
||||||
|
StackPanel parentElement = frameworkElement.Parent().as<StackPanel>();
|
||||||
|
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 get the type of the key
|
||||||
}
|
KeyType GetKeyType(DWORD key)
|
||||||
|
|
||||||
// Function to return the next sibling element for an element under a stack panel
|
|
||||||
IInspectable getSiblingElement(IInspectable const& element)
|
|
||||||
{
|
|
||||||
FrameworkElement frameworkElement = element.as<FrameworkElement>();
|
|
||||||
StackPanel parentElement = frameworkElement.Parent().as<StackPanel>();
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
case VK_LWIN:
|
switch (key)
|
||||||
case VK_RWIN:
|
{
|
||||||
return KeyType::Win;
|
case VK_LWIN:
|
||||||
case VK_CONTROL:
|
case VK_RWIN:
|
||||||
case VK_LCONTROL:
|
return KeyType::Win;
|
||||||
case VK_RCONTROL:
|
case VK_CONTROL:
|
||||||
return KeyType::Ctrl;
|
case VK_LCONTROL:
|
||||||
case VK_MENU:
|
case VK_RCONTROL:
|
||||||
case VK_LMENU:
|
return KeyType::Ctrl;
|
||||||
case VK_RMENU:
|
case VK_MENU:
|
||||||
return KeyType::Alt;
|
case VK_LMENU:
|
||||||
case VK_SHIFT:
|
case VK_RMENU:
|
||||||
case VK_LSHIFT:
|
return KeyType::Alt;
|
||||||
case VK_RSHIFT:
|
case VK_SHIFT:
|
||||||
return KeyType::Shift;
|
case VK_LSHIFT:
|
||||||
default:
|
case VK_RSHIFT:
|
||||||
return KeyType::Action;
|
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)
|
|
||||||
{
|
// Function to return if the key is an extended key which requires the use of the extended key flag
|
||||||
switch (key)
|
bool isExtendedKey(DWORD key)
|
||||||
{
|
{
|
||||||
case VK_RCONTROL:
|
switch (key)
|
||||||
case VK_RMENU:
|
{
|
||||||
case VK_NUMLOCK:
|
case VK_RCONTROL:
|
||||||
case VK_SNAPSHOT:
|
case VK_RMENU:
|
||||||
case VK_CANCEL:
|
case VK_NUMLOCK:
|
||||||
return true;
|
case VK_SNAPSHOT:
|
||||||
default:
|
case VK_CANCEL:
|
||||||
return false;
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,52 +2,58 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <winrt/Windows.System.h>
|
#include <winrt/Windows.System.h>
|
||||||
|
|
||||||
// Type to distinguish between keys
|
namespace KeyboardManagerHelper
|
||||||
enum class KeyType
|
|
||||||
{
|
{
|
||||||
Win,
|
// Type to distinguish between keys
|
||||||
Ctrl,
|
enum class KeyType
|
||||||
Alt,
|
|
||||||
Shift,
|
|
||||||
Action
|
|
||||||
};
|
|
||||||
|
|
||||||
// Function to split a wstring based on a delimiter and return a vector of split strings
|
|
||||||
std::vector<std::wstring> 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<typename T>
|
|
||||||
winrt::hstring convertVectorToHstring(const std::vector<T>& input)
|
|
||||||
{
|
|
||||||
winrt::hstring output;
|
|
||||||
for (int i = 0; i < input.size(); i++)
|
|
||||||
{
|
{
|
||||||
output = output + winrt::to_hstring((unsigned int)input[i]) + winrt::to_hstring(L" ");
|
Win,
|
||||||
}
|
Ctrl,
|
||||||
return output;
|
Alt,
|
||||||
}
|
Shift,
|
||||||
|
Action
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to split a wstring based on a delimiter and return a vector of split strings
|
||||||
|
std::vector<std::wstring> 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
|
// Function to convert an unsigned int vector to hstring by concatenating them
|
||||||
template<typename T>
|
template<typename T>
|
||||||
std::vector<T> convertWStringVectorToIntegerVector(const std::vector<std::wstring>& input)
|
winrt::hstring convertVectorToHstring(const std::vector<T>& input)
|
||||||
{
|
|
||||||
std::vector<T> typeVector;
|
|
||||||
for (int i = 0; i < input.size(); i++)
|
|
||||||
{
|
{
|
||||||
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<typename T>
|
||||||
|
std::vector<T> convertWStringVectorToIntegerVector(const std::vector<std::wstring>& input)
|
||||||
|
{
|
||||||
|
std::vector<T> 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);
|
|
||||||
|
@ -55,8 +55,8 @@
|
|||||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||||
|
<AdditionalIncludeDirectories>..\;..\..\..\common;..\..\..\common\telemetry;..\..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)src\;$(SolutionDir)src\modules;$(SolutionDir)src\common\Telemetry;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -74,7 +74,7 @@
|
|||||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)src\;$(SolutionDir)src\modules;$(SolutionDir)src\common\Telemetry;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\;..\..\..\common;..\..\..\common\telemetry;..\..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
@ -100,6 +100,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Helpers.h" />
|
<ClInclude Include="Helpers.h" />
|
||||||
|
<ClInclude Include="KeyboardManagerConstants.h" />
|
||||||
<ClInclude Include="KeyboardManagerState.h" />
|
<ClInclude Include="KeyboardManagerState.h" />
|
||||||
<ClInclude Include="KeyDelay.h" />
|
<ClInclude Include="KeyDelay.h" />
|
||||||
<ClInclude Include="LayoutMap.h" />
|
<ClInclude Include="LayoutMap.h" />
|
||||||
|
@ -59,5 +59,8 @@
|
|||||||
<ClInclude Include="KeyDelay.h">
|
<ClInclude Include="KeyDelay.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="KeyboardManagerConstants.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -0,0 +1,41 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
@ -5,6 +5,19 @@
|
|||||||
KeyboardManagerState::KeyboardManagerState() :
|
KeyboardManagerState::KeyboardManagerState() :
|
||||||
uiState(KeyboardManagerUIState::Deactivated), currentUIWindow(nullptr), currentShortcutUI(nullptr), currentSingleKeyUI(nullptr), detectedRemapKey(NULL)
|
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.
|
// 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);
|
keyDelays[ev->lParam->vkCode]->KeyEvent(ev);
|
||||||
return true;
|
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<std::mutex> 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<std::mutex> 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<std::mutex> lock(currentConfig_mutex);
|
||||||
|
currentConfig = configName;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring KeyboardManagerState::GetCurrentConfigName()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(currentConfig_mutex);
|
||||||
|
return currentConfig;
|
||||||
}
|
}
|
@ -4,9 +4,11 @@
|
|||||||
#include "Shortcut.h"
|
#include "Shortcut.h"
|
||||||
#include "RemapShortcut.h"
|
#include "RemapShortcut.h"
|
||||||
#include "KeyDelay.h"
|
#include "KeyDelay.h"
|
||||||
|
#include "KeyboardManagerConstants.h"
|
||||||
#include <interface/lowlevel_keyboard_event_data.h>
|
#include <interface/lowlevel_keyboard_event_data.h>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <winrt/Windows.UI.Xaml.Controls.h>
|
#include <winrt/Windows.UI.Xaml.Controls.h>
|
||||||
|
#include <../common/settings_helpers.h>
|
||||||
using namespace winrt::Windows::UI::Xaml::Controls;
|
using namespace winrt::Windows::UI::Xaml::Controls;
|
||||||
|
|
||||||
// Enum type to store different states of the UI
|
// 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
|
// Stores the UI element which is to be updated based on the shortcut entered
|
||||||
StackPanel currentShortcutUI;
|
StackPanel currentShortcutUI;
|
||||||
std::mutex currentShortcutUI_mutex;
|
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.
|
// Registered KeyDelay objects, used to notify delayed key events.
|
||||||
std::map<DWORD, std::unique_ptr<KeyDelay>> keyDelays;
|
std::map<DWORD, std::unique_ptr<KeyDelay>> keyDelays;
|
||||||
@ -84,6 +93,9 @@ public:
|
|||||||
// Constructor
|
// Constructor
|
||||||
KeyboardManagerState();
|
KeyboardManagerState();
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
~KeyboardManagerState();
|
||||||
|
|
||||||
// Function to reset the UI state members
|
// Function to reset the UI state members
|
||||||
void ResetUIState();
|
void ResetUIState();
|
||||||
|
|
||||||
@ -157,4 +169,13 @@ public:
|
|||||||
|
|
||||||
// Reset the shortcut (backend) state after releasing a key.
|
// Reset the shortcut (backend) state after releasing a key.
|
||||||
void ResetDetectedShortcutKey(DWORD 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();
|
||||||
};
|
};
|
@ -418,6 +418,43 @@ std::vector<winrt::hstring> Shortcut::GetKeyVector(LayoutMap& keyboardMap) const
|
|||||||
return keys;
|
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
|
// Function to return a vector of key codes in the display order
|
||||||
std::vector<DWORD> Shortcut::GetKeyCodes()
|
std::vector<DWORD> Shortcut::GetKeyCodes()
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Helpers.h"
|
#include "Helpers.h"
|
||||||
#include "LayoutMap.h"
|
#include "LayoutMap.h"
|
||||||
|
#include "KeyboardManagerConstants.h"
|
||||||
#include <interface/lowlevel_keyboard_event_data.h>
|
#include <interface/lowlevel_keyboard_event_data.h>
|
||||||
|
|
||||||
// Enum type to store different states of the win key
|
// 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.
|
// Less than operator must be defined to use with std::map.
|
||||||
inline bool operator<(const Shortcut& sc) const
|
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.
|
// 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);
|
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
|
// Function to return a vector of hstring for each key in the display order
|
||||||
std::vector<winrt::hstring> GetKeyVector(LayoutMap& keyboardMap) const;
|
std::vector<winrt::hstring> GetKeyVector(LayoutMap& keyboardMap) const;
|
||||||
|
|
||||||
|
@ -19,6 +19,5 @@ using namespace Windows::UI;
|
|||||||
using namespace Windows::UI::Composition;
|
using namespace Windows::UI::Composition;
|
||||||
using namespace Windows::UI::Xaml::Hosting;
|
using namespace Windows::UI::Xaml::Hosting;
|
||||||
using namespace Windows::Foundation::Numerics;
|
using namespace Windows::Foundation::Numerics;
|
||||||
using namespace Windows::Foundation;
|
|
||||||
using namespace Windows::UI::Xaml;
|
using namespace Windows::UI::Xaml;
|
||||||
using namespace Windows::UI::Xaml::Controls;
|
using namespace Windows::UI::Xaml::Controls;
|
@ -10,6 +10,8 @@
|
|||||||
#include <keyboardmanager/common/KeyboardManagerState.h>
|
#include <keyboardmanager/common/KeyboardManagerState.h>
|
||||||
#include <keyboardmanager/common/Shortcut.h>
|
#include <keyboardmanager/common/Shortcut.h>
|
||||||
#include <keyboardmanager/common/RemapShortcut.h>
|
#include <keyboardmanager/common/RemapShortcut.h>
|
||||||
|
#include <keyboardmanager/common/KeyboardManagerConstants.h>
|
||||||
|
#include <common\settings_helpers.h>
|
||||||
|
|
||||||
extern "C" IMAGE_DOS_HEADER __ImageBase;
|
extern "C" IMAGE_DOS_HEADER __ImageBase;
|
||||||
|
|
||||||
@ -64,12 +66,81 @@ public:
|
|||||||
// Constructor
|
// Constructor
|
||||||
KeyboardManager()
|
KeyboardManager()
|
||||||
{
|
{
|
||||||
init_map();
|
// Load the initial configuration.
|
||||||
|
load_config();
|
||||||
|
|
||||||
// Set the static pointer to the newest object of the class
|
// Set the static pointer to the newest object of the class
|
||||||
keyboardmanager_object_ptr = this;
|
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
|
// This function is used to add the hardcoded mappings
|
||||||
void init_map()
|
void init_map()
|
||||||
{
|
{
|
||||||
@ -325,7 +396,7 @@ public:
|
|||||||
keyEventArray[index].type = inputType;
|
keyEventArray[index].type = inputType;
|
||||||
keyEventArray[index].ki.wVk = keyCode;
|
keyEventArray[index].ki.wVk = keyCode;
|
||||||
keyEventArray[index].ki.dwFlags = flags;
|
keyEventArray[index].ki.dwFlags = flags;
|
||||||
if (isExtendedKey(keyCode))
|
if (KeyboardManagerHelper::isExtendedKey(keyCode))
|
||||||
{
|
{
|
||||||
keyEventArray[index].ki.dwFlags |= KEYEVENTF_EXTENDEDKEY;
|
keyEventArray[index].ki.dwFlags |= KEYEVENTF_EXTENDEDKEY;
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMan
|
|||||||
cancelButton.Background(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::LightGray() });
|
cancelButton.Background(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::LightGray() });
|
||||||
cancelButton.Foreground(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::Black() });
|
cancelButton.Foreground(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::Black() });
|
||||||
cancelButton.Content(winrt::box_value(winrt::to_hstring("Cancel")));
|
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
|
// Close the window since settings do not need to be saved
|
||||||
PostMessage(_hWndEditKeyboardWindow, WM_CLOSE, 0, 0);
|
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.Background(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::LightGray() });
|
||||||
applyButton.Foreground(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::Black() });
|
applyButton.Foreground(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::Black() });
|
||||||
applyButton.Content(winrt::box_value(winrt::to_hstring("Apply")));
|
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;
|
bool isSuccess = true;
|
||||||
// Clear existing Key Remaps
|
// Clear existing Key Remaps
|
||||||
keyboardManagerState.ClearSingleKeyRemaps();
|
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.Foreground(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::Green() });
|
||||||
settingsMessage.Text(winrt::to_hstring("Remapping successful!"));
|
settingsMessage.Text(winrt::to_hstring("Remapping successful!"));
|
||||||
}
|
}
|
||||||
else
|
else if (!isSuccess && saveResult)
|
||||||
{
|
{
|
||||||
settingsMessage.Foreground(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::Red() });
|
settingsMessage.Foreground(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::Red() });
|
||||||
settingsMessage.Text(winrt::to_hstring("All remappings were not successfully applied."));
|
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);
|
header.Children().Append(headerText);
|
||||||
@ -212,7 +220,7 @@ void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMan
|
|||||||
plusSymbol.Glyph(L"\xE109");
|
plusSymbol.Glyph(L"\xE109");
|
||||||
addRemapKey.Content(plusSymbol);
|
addRemapKey.Content(plusSymbol);
|
||||||
addRemapKey.Margin({ 10 });
|
addRemapKey.Margin({ 10 });
|
||||||
addRemapKey.Click([&](IInspectable const& sender, RoutedEventArgs const&) {
|
addRemapKey.Click([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||||
SingleKeyRemapControl::AddNewControlKeyRemapRow(keyRemapTable, keyboardRemapControlObjects);
|
SingleKeyRemapControl::AddNewControlKeyRemapRow(keyRemapTable, keyboardRemapControlObjects);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa
|
|||||||
// Cancel button
|
// Cancel button
|
||||||
Button cancelButton;
|
Button cancelButton;
|
||||||
cancelButton.Content(winrt::box_value(winrt::to_hstring("Cancel")));
|
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
|
// Close the window since settings do not need to be saved
|
||||||
PostMessage(_hWndEditShortcutsWindow, WM_CLOSE, 0, 0);
|
PostMessage(_hWndEditShortcutsWindow, WM_CLOSE, 0, 0);
|
||||||
});
|
});
|
||||||
@ -151,7 +151,7 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa
|
|||||||
// Apply button
|
// Apply button
|
||||||
Button applyButton;
|
Button applyButton;
|
||||||
applyButton.Content(winrt::box_value(winrt::to_hstring("Apply")));
|
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;
|
bool isSuccess = true;
|
||||||
// Clear existing shortcuts
|
// Clear existing shortcuts
|
||||||
keyboardManagerState.ClearOSLevelShortcuts();
|
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.Foreground(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::Green() });
|
||||||
settingsMessage.Text(winrt::to_hstring("Remapping successful!"));
|
settingsMessage.Text(winrt::to_hstring("Remapping successful!"));
|
||||||
}
|
}
|
||||||
else
|
else if (!isSuccess && saveResult)
|
||||||
{
|
{
|
||||||
settingsMessage.Foreground(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::Red() });
|
settingsMessage.Foreground(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::Red() });
|
||||||
settingsMessage.Text(winrt::to_hstring("All remappings were not successfully applied."));
|
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);
|
header.Children().Append(headerText);
|
||||||
@ -200,7 +208,7 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa
|
|||||||
plusSymbol.Glyph(L"\xE109");
|
plusSymbol.Glyph(L"\xE109");
|
||||||
addShortcut.Content(plusSymbol);
|
addShortcut.Content(plusSymbol);
|
||||||
addShortcut.Margin({ 10 });
|
addShortcut.Margin({ 10 });
|
||||||
addShortcut.Click([&](IInspectable const& sender, RoutedEventArgs const&) {
|
addShortcut.Click([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||||
ShortcutControl::AddNewShortcutControlRow(shortcutTable, keyboardRemapControlObjects);
|
ShortcutControl::AddNewShortcutControlRow(shortcutTable, keyboardRemapControlObjects);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ void KeyDropDownControl::SetDefaultProperties(bool isShortcut)
|
|||||||
keyCodeList = keyboardManagerState->keyboardMap.GetKeyCodeList(isShortcut);
|
keyCodeList = keyboardManagerState->keyboardMap.GetKeyCodeList(isShortcut);
|
||||||
dropDown.ItemsSource(keyboardManagerState->keyboardMap.GetKeyNameList(isShortcut));
|
dropDown.ItemsSource(keyboardManagerState->keyboardMap.GetKeyNameList(isShortcut));
|
||||||
// drop down open handler - to reload the items with the latest layout
|
// 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<ComboBox>();
|
ComboBox currentDropDown = sender.as<ComboBox>();
|
||||||
CheckAndUpdateKeyboardLayout(currentDropDown, isShortcut);
|
CheckAndUpdateKeyboardLayout(currentDropDown, isShortcut);
|
||||||
});
|
});
|
||||||
@ -93,7 +93,7 @@ bool KeyDropDownControl::CheckRepeatedModifier(StackPanel parent, uint32_t dropD
|
|||||||
if (i != dropDownIndex)
|
if (i != dropDownIndex)
|
||||||
{
|
{
|
||||||
// If the key type for the newly added key matches any of the existing keys in the shortcut
|
// 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;
|
matchPreviousModifier = true;
|
||||||
break;
|
break;
|
||||||
|
@ -26,7 +26,7 @@ public:
|
|||||||
KeyDropDownControl(size_t rowIndex, size_t colIndex, std::vector<std::vector<DWORD>>& singleKeyRemapBuffer)
|
KeyDropDownControl(size_t rowIndex, size_t colIndex, std::vector<std::vector<DWORD>>& singleKeyRemapBuffer)
|
||||||
{
|
{
|
||||||
SetDefaultProperties(false);
|
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<ComboBox>();
|
ComboBox currentDropDown = sender.as<ComboBox>();
|
||||||
int selectedKeyIndex = currentDropDown.SelectedIndex();
|
int selectedKeyIndex = currentDropDown.SelectedIndex();
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ public:
|
|||||||
dropDown.ContextFlyout().SetAttachedFlyout((FrameworkElement)dropDown, warningFlyout);
|
dropDown.ContextFlyout().SetAttachedFlyout((FrameworkElement)dropDown, warningFlyout);
|
||||||
|
|
||||||
// drop down selection handler
|
// 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<ComboBox>();
|
ComboBox currentDropDown = sender.as<ComboBox>();
|
||||||
int selectedKeyIndex = currentDropDown.SelectedIndex();
|
int selectedKeyIndex = currentDropDown.SelectedIndex();
|
||||||
uint32_t dropDownIndex = -1;
|
uint32_t dropDownIndex = -1;
|
||||||
@ -62,7 +62,7 @@ public:
|
|||||||
if (selectedKeyIndex != -1 && keyCodeList.size() > selectedKeyIndex && dropDownFound)
|
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 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
|
// warn and reset the drop down
|
||||||
SetDropDownError(currentDropDown, warningMessage, L"Shortcut must start with a modifier key");
|
SetDropDownError(currentDropDown, warningMessage, L"Shortcut must start with a modifier key");
|
||||||
@ -71,7 +71,7 @@ public:
|
|||||||
else if (dropDownIndex == parent.Children().Size() - 1)
|
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 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 it matched any of the previous modifiers then reset that drop down
|
||||||
if (CheckRepeatedModifier(parent, dropDownIndex, selectedKeyIndex, keyCodeList))
|
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
|
// 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
|
// warn and reset the drop down
|
||||||
SetDropDownError(currentDropDown, warningMessage, L"Shortcut must contain an action key");
|
SetDropDownError(currentDropDown, warningMessage, L"Shortcut must contain an action key");
|
||||||
@ -102,7 +102,7 @@ public:
|
|||||||
// If it is the not the last drop down
|
// If it is the not the last drop down
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (IsModifierKey(keyCodeList[selectedKeyIndex]))
|
if (KeyboardManagerHelper::IsModifierKey(keyCodeList[selectedKeyIndex]))
|
||||||
{
|
{
|
||||||
// If it matched any of the previous modifiers then reset that drop down
|
// If it matched any of the previous modifiers then reset that drop down
|
||||||
if (CheckRepeatedModifier(parent, dropDownIndex, selectedKeyIndex, keyCodeList))
|
if (CheckRepeatedModifier(parent, dropDownIndex, selectedKeyIndex, keyCodeList))
|
||||||
|
@ -34,7 +34,7 @@ void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, std::vector<s
|
|||||||
deleteSymbol.FontFamily(Xaml::Media::FontFamily(L"Segoe MDL2 Assets"));
|
deleteSymbol.FontFamily(Xaml::Media::FontFamily(L"Segoe MDL2 Assets"));
|
||||||
deleteSymbol.Glyph(L"\xE74D");
|
deleteSymbol.Glyph(L"\xE74D");
|
||||||
deleteShortcut.Content(deleteSymbol);
|
deleteShortcut.Content(deleteSymbol);
|
||||||
deleteShortcut.Click([&](IInspectable const& sender, RoutedEventArgs const&) {
|
deleteShortcut.Click([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||||
StackPanel currentRow = sender.as<Button>().Parent().as<StackPanel>();
|
StackPanel currentRow = sender.as<Button>().Parent().as<StackPanel>();
|
||||||
uint32_t index;
|
uint32_t index;
|
||||||
parent.Children().IndexOf(currentRow, index);
|
parent.Children().IndexOf(currentRow, index);
|
||||||
@ -101,7 +101,7 @@ StackPanel ShortcutControl::getShortcutControl()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Function to create the detect shortcut UI window
|
// Function to create the detect shortcut UI window
|
||||||
void ShortcutControl::createDetectShortcutWindow(IInspectable const& sender, XamlRoot xamlRoot, std::vector<std::vector<Shortcut>>& shortcutRemapBuffer, KeyboardManagerState& keyboardManagerState, const size_t rowIndex, const size_t colIndex)
|
void ShortcutControl::createDetectShortcutWindow(winrt::Windows::Foundation::IInspectable const& sender, XamlRoot xamlRoot, std::vector<std::vector<Shortcut>>& shortcutRemapBuffer, KeyboardManagerState& keyboardManagerState, const size_t rowIndex, const size_t colIndex)
|
||||||
{
|
{
|
||||||
// ContentDialog for detecting shortcuts. This is the parent UI element.
|
// ContentDialog for detecting shortcuts. This is the parent UI element.
|
||||||
ContentDialog detectShortcutBox;
|
ContentDialog detectShortcutBox;
|
||||||
@ -115,7 +115,7 @@ void ShortcutControl::createDetectShortcutWindow(IInspectable const& sender, Xam
|
|||||||
detectShortcutBox.IsSecondaryButtonEnabled(false);
|
detectShortcutBox.IsSecondaryButtonEnabled(false);
|
||||||
|
|
||||||
// Get the linked text block for the "Type shortcut" button that was clicked
|
// Get the linked text block for the "Type shortcut" button that was clicked
|
||||||
StackPanel linkedShortcutStackPanel = getSiblingElement(sender).as<StackPanel>();
|
StackPanel linkedShortcutStackPanel = KeyboardManagerHelper::getSiblingElement(sender).as<StackPanel>();
|
||||||
|
|
||||||
auto unregisterKeys = [&keyboardManagerState]() {
|
auto unregisterKeys = [&keyboardManagerState]() {
|
||||||
std::thread t1(&KeyboardManagerState::UnregisterKeyDelay, &keyboardManagerState, VK_ESCAPE);
|
std::thread t1(&KeyboardManagerState::UnregisterKeyDelay, &keyboardManagerState, VK_ESCAPE);
|
||||||
@ -161,7 +161,7 @@ void ShortcutControl::createDetectShortcutWindow(IInspectable const& sender, Xam
|
|||||||
primaryButton.Content(primaryButtonText);
|
primaryButton.Content(primaryButtonText);
|
||||||
|
|
||||||
// OK button
|
// OK button
|
||||||
primaryButton.Click([onAccept](IInspectable const& sender, RoutedEventArgs const&) {
|
primaryButton.Click([onAccept](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||||
onAccept();
|
onAccept();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -191,7 +191,7 @@ void ShortcutControl::createDetectShortcutWindow(IInspectable const& sender, Xam
|
|||||||
cancelButton.Margin({ 2, 2, 2, 2 });
|
cancelButton.Margin({ 2, 2, 2, 2 });
|
||||||
cancelButton.Content(cancelButtonText);
|
cancelButton.Content(cancelButtonText);
|
||||||
// Cancel button
|
// 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
|
// Reset the keyboard manager UI state
|
||||||
keyboardManagerState.ResetUIState();
|
keyboardManagerState.ResetUIState();
|
||||||
unregisterKeys();
|
unregisterKeys();
|
||||||
|
@ -37,7 +37,7 @@ public:
|
|||||||
KeyDropDownControl::AddDropDown(shortcutDropDownStackPanel, rowIndex, colIndex, shortcutRemapBuffer, keyDropDownControlObjects);
|
KeyDropDownControl::AddDropDown(shortcutDropDownStackPanel, rowIndex, colIndex, shortcutRemapBuffer, keyDropDownControlObjects);
|
||||||
|
|
||||||
typeShortcut.Content(winrt::box_value(winrt::to_hstring("Type Shortcut")));
|
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);
|
keyboardManagerState->SetUIState(KeyboardManagerUIState::DetectShortcutWindowActivated, EditShortcutsWindowHandle);
|
||||||
// Using the XamlRoot of the typeShortcut to get the root of the XAML host
|
// Using the XamlRoot of the typeShortcut to get the root of the XAML host
|
||||||
createDetectShortcutWindow(sender, sender.as<Button>().XamlRoot(), shortcutRemapBuffer, *keyboardManagerState, rowIndex, colIndex);
|
createDetectShortcutWindow(sender, sender.as<Button>().XamlRoot(), shortcutRemapBuffer, *keyboardManagerState, rowIndex, colIndex);
|
||||||
@ -62,5 +62,5 @@ public:
|
|||||||
StackPanel getShortcutControl();
|
StackPanel getShortcutControl();
|
||||||
|
|
||||||
// Function to create the detect shortcut UI window
|
// Function to create the detect shortcut UI window
|
||||||
void createDetectShortcutWindow(IInspectable const& sender, XamlRoot xamlRoot, std::vector<std::vector<Shortcut>>& shortcutRemapBuffer, KeyboardManagerState& keyboardManagerState, const size_t rowIndex, const size_t colIndex);
|
void createDetectShortcutWindow(winrt::Windows::Foundation::IInspectable const& sender, XamlRoot xamlRoot, std::vector<std::vector<Shortcut>>& shortcutRemapBuffer, KeyboardManagerState& keyboardManagerState, const size_t rowIndex, const size_t colIndex);
|
||||||
};
|
};
|
||||||
|
@ -56,7 +56,7 @@ void SingleKeyRemapControl::AddNewControlKeyRemapRow(StackPanel& parent, std::ve
|
|||||||
deleteSymbol.FontFamily(Xaml::Media::FontFamily(L"Segoe MDL2 Assets"));
|
deleteSymbol.FontFamily(Xaml::Media::FontFamily(L"Segoe MDL2 Assets"));
|
||||||
deleteSymbol.Glyph(L"\xE74D");
|
deleteSymbol.Glyph(L"\xE74D");
|
||||||
deleteRemapKeys.Content(deleteSymbol);
|
deleteRemapKeys.Content(deleteSymbol);
|
||||||
deleteRemapKeys.Click([&](IInspectable const& sender, RoutedEventArgs const&) {
|
deleteRemapKeys.Click([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||||
StackPanel currentRow = sender.as<Button>().Parent().as<StackPanel>();
|
StackPanel currentRow = sender.as<Button>().Parent().as<StackPanel>();
|
||||||
uint32_t index;
|
uint32_t index;
|
||||||
parent.Children().IndexOf(currentRow, index);
|
parent.Children().IndexOf(currentRow, index);
|
||||||
@ -77,7 +77,7 @@ StackPanel SingleKeyRemapControl::getSingleKeyRemapControl()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Function to create the detect remap key UI window
|
// Function to create the detect remap key UI window
|
||||||
void SingleKeyRemapControl::createDetectKeyWindow(IInspectable const& sender, XamlRoot xamlRoot, std::vector<std::vector<DWORD>>& singleKeyRemapBuffer, KeyboardManagerState& keyboardManagerState, const size_t rowIndex, const size_t colIndex)
|
void SingleKeyRemapControl::createDetectKeyWindow(winrt::Windows::Foundation::IInspectable const& sender, XamlRoot xamlRoot, std::vector<std::vector<DWORD>>& singleKeyRemapBuffer, KeyboardManagerState& keyboardManagerState, const size_t rowIndex, const size_t colIndex)
|
||||||
{
|
{
|
||||||
// ContentDialog for detecting remap key. This is the parent UI element.
|
// ContentDialog for detecting remap key. This is the parent UI element.
|
||||||
ContentDialog detectRemapKeyBox;
|
ContentDialog detectRemapKeyBox;
|
||||||
@ -91,7 +91,7 @@ void SingleKeyRemapControl::createDetectKeyWindow(IInspectable const& sender, Xa
|
|||||||
detectRemapKeyBox.IsSecondaryButtonEnabled(false);
|
detectRemapKeyBox.IsSecondaryButtonEnabled(false);
|
||||||
|
|
||||||
// Get the linked text block for the "Type Key" button that was clicked
|
// Get the linked text block for the "Type Key" button that was clicked
|
||||||
ComboBox linkedRemapDropDown = getSiblingElement(sender).as<ComboBox>();
|
ComboBox linkedRemapDropDown = KeyboardManagerHelper::getSiblingElement(sender).as<ComboBox>();
|
||||||
|
|
||||||
auto unregisterKeys = [&keyboardManagerState]() {
|
auto unregisterKeys = [&keyboardManagerState]() {
|
||||||
std::thread t1(&KeyboardManagerState::UnregisterKeyDelay, &keyboardManagerState, VK_ESCAPE);
|
std::thread t1(&KeyboardManagerState::UnregisterKeyDelay, &keyboardManagerState, VK_ESCAPE);
|
||||||
@ -135,7 +135,7 @@ void SingleKeyRemapControl::createDetectKeyWindow(IInspectable const& sender, Xa
|
|||||||
primaryButton.HorizontalAlignment(HorizontalAlignment::Stretch);
|
primaryButton.HorizontalAlignment(HorizontalAlignment::Stretch);
|
||||||
primaryButton.Margin({ 2, 2, 2, 2 });
|
primaryButton.Margin({ 2, 2, 2, 2 });
|
||||||
primaryButton.Content(primaryButtonText);
|
primaryButton.Content(primaryButtonText);
|
||||||
primaryButton.Click([onAccept](IInspectable const& sender, RoutedEventArgs const&) {
|
primaryButton.Click([onAccept](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||||
onAccept();
|
onAccept();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -165,7 +165,7 @@ void SingleKeyRemapControl::createDetectKeyWindow(IInspectable const& sender, Xa
|
|||||||
cancelButton.Margin({ 2, 2, 2, 2 });
|
cancelButton.Margin({ 2, 2, 2, 2 });
|
||||||
cancelButton.Content(cancelButtonText);
|
cancelButton.Content(cancelButtonText);
|
||||||
// Cancel button
|
// Cancel button
|
||||||
cancelButton.Click([detectRemapKeyBox, unregisterKeys, &keyboardManagerState](IInspectable const& sender, RoutedEventArgs const&) {
|
cancelButton.Click([detectRemapKeyBox, unregisterKeys, &keyboardManagerState](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||||
// Reset the keyboard manager UI state
|
// Reset the keyboard manager UI state
|
||||||
keyboardManagerState.ResetUIState();
|
keyboardManagerState.ResetUIState();
|
||||||
unregisterKeys();
|
unregisterKeys();
|
||||||
|
@ -28,7 +28,7 @@ public:
|
|||||||
typeKey.Content(winrt::box_value(winrt::to_hstring("Type Key")));
|
typeKey.Content(winrt::box_value(winrt::to_hstring("Type Key")));
|
||||||
typeKey.Background(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::LightGray() });
|
typeKey.Background(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::LightGray() });
|
||||||
typeKey.Foreground(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::Black() });
|
typeKey.Foreground(Windows::UI::Xaml::Media::SolidColorBrush{ Windows::UI::Colors::Black() });
|
||||||
typeKey.Click([&, rowIndex, colIndex](IInspectable const& sender, RoutedEventArgs const&) {
|
typeKey.Click([&, rowIndex, colIndex](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||||
keyboardManagerState->SetUIState(KeyboardManagerUIState::DetectSingleKeyRemapWindowActivated, EditKeyboardWindowHandle);
|
keyboardManagerState->SetUIState(KeyboardManagerUIState::DetectSingleKeyRemapWindowActivated, EditKeyboardWindowHandle);
|
||||||
// Using the XamlRoot of the typeKey to get the root of the XAML host
|
// Using the XamlRoot of the typeKey to get the root of the XAML host
|
||||||
createDetectKeyWindow(sender, sender.as<Button>().XamlRoot(), singleKeyRemapBuffer, *keyboardManagerState, rowIndex, colIndex);
|
createDetectKeyWindow(sender, sender.as<Button>().XamlRoot(), singleKeyRemapBuffer, *keyboardManagerState, rowIndex, colIndex);
|
||||||
@ -50,5 +50,5 @@ public:
|
|||||||
StackPanel getSingleKeyRemapControl();
|
StackPanel getSingleKeyRemapControl();
|
||||||
|
|
||||||
// Function to create the detect remap keys UI window
|
// Function to create the detect remap keys UI window
|
||||||
void createDetectKeyWindow(IInspectable const& sender, XamlRoot xamlRoot, std::vector<std::vector<DWORD>>& singleKeyRemapBuffer, KeyboardManagerState& keyboardManagerState, const size_t rowIndex, const size_t colIndex);
|
void createDetectKeyWindow(winrt::Windows::Foundation::IInspectable const& sender, XamlRoot xamlRoot, std::vector<std::vector<DWORD>>& singleKeyRemapBuffer, KeyboardManagerState& keyboardManagerState, const size_t rowIndex, const size_t colIndex);
|
||||||
};
|
};
|
||||||
|
@ -21,6 +21,5 @@ using namespace Windows::UI;
|
|||||||
using namespace Windows::UI::Composition;
|
using namespace Windows::UI::Composition;
|
||||||
using namespace Windows::UI::Xaml::Hosting;
|
using namespace Windows::UI::Xaml::Hosting;
|
||||||
using namespace Windows::Foundation::Numerics;
|
using namespace Windows::Foundation::Numerics;
|
||||||
using namespace Windows::Foundation;
|
|
||||||
using namespace Windows::UI::Xaml;
|
using namespace Windows::UI::Xaml;
|
||||||
using namespace Windows::UI::Xaml::Controls;
|
using namespace Windows::UI::Xaml::Controls;
|
Loading…
Reference in New Issue
Block a user