mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-06 03:07:04 +02: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:
@@ -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.
|
||||
// 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<string> 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<List<string>> KeyboardConfigurations { get; set; }
|
||||
|
||||
public KeyboardManagerProperties()
|
||||
{
|
||||
EditShortcut = new BoolProperty();
|
||||
RemapKeyboard = new BoolProperty();
|
||||
KeyboardConfigurations = new GenericProperty<List<string>>(new List<string> { "default", });
|
||||
ActiveConfiguration = new GenericProperty<string>("default");
|
||||
}
|
||||
|
||||
public string ToJsonString()
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
// 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);
|
||||
}
|
||||
|
||||
@@ -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<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()
|
||||
@@ -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<KeyboadManagerConfigModel>(PowerToyName, settings.Properties.ActiveConfiguration.Value + JsonFileType);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Make sure to release the mutex.
|
||||
configFileMutex.ReleaseMutex();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Failed to load the configuration.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user