mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-02-24 04:00:02 +01:00
[Keyboard Manager] Toggle module hotkey/shortcut (#42472)
## Summary of the Pull Request Adds a keyboard shortcut to be able to toggle the Keyboard Manager module on and off. ## PR Checklist - [x] Closes: #4879 - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments Modeled the changes and addition of a global shortcut using the Color Picker module. Notes: - This uses `KeyboardManagerSettings` and the associated .json settings file. I don't think there's anything else in this module that uses this. - The default key binding for this is `winkey + shift + k` - I've had to update the `KeyboardManagerViewModel` to extend `PageViewModelBase` as opposed to `Observable` to get it to work. But I will say that there were some things in here that I didn't fully dig into, so let me know if there's any potential things I'm missing. - I'm not too sure how to update the Settings UI after a hotkey is pressed (pressing the hotkey currently will not show the module being toggled off) - can't find a good way to refresh the settings ui after enabling/disabling the module. Any pointers here would be appreciated! ## Validation Steps Performed - Manually validated the following items: - Using the default shortcut (`winkey + shift + k`) - Changing the shortcut - Ensuring the change is persistent ## Media https://github.com/user-attachments/assets/e471b8df-787a-441e-b9e0-330361865c76 --------- Co-authored-by: Weike Qu <weikequ@get-stride.com> Co-authored-by: Leilei Zhang <leilzh@microsoft.com> Co-authored-by: vanzue <vanzue@outlook.com> Co-authored-by: Kai Tao <69313318+vanzue@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -52,15 +52,15 @@
|
||||
<PrecompiledHeader Condition="'$(UsePrecompiledHeaders)' != 'false'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="$(RepoRoot)src\common\logger\logger.vcxproj">
|
||||
<Project>{d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(RepoRoot)src\common\SettingsAPI\SettingsAPI.vcxproj">
|
||||
<Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\common\KeyboardManagerCommon.vcxproj">
|
||||
<Project>{8affa899-0b73-49ec-8c50-0fadda57b2fc}</Project>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="$(RepoRoot)src\common\logger\logger.vcxproj">
|
||||
<Project>{d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(RepoRoot)src\common\SettingsAPI\SettingsAPI.vcxproj">
|
||||
<Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\common\KeyboardManagerCommon.vcxproj">
|
||||
<Project>{8affa899-0b73-49ec-8c50-0fadda57b2fc}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -85,4 +85,4 @@
|
||||
<Target Name="GenerateResourceFiles" BeforeTargets="PrepareForBuild">
|
||||
<Exec Command="powershell -NonInteractive -executionpolicy Unrestricted $(RepoRoot)tools\build\convert-resx-to-rc.ps1 $(MSBuildThisFileDirectory) resource.base.h resource.h KeyboardManager.base.rc KeyboardManager.rc" />
|
||||
</Target>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -28,12 +28,24 @@ BOOL APIENTRY DllMain(HMODULE /*hModule*/, DWORD ul_reason_for_call, LPVOID /*lp
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
const wchar_t JSON_KEY_PROPERTIES[] = L"properties";
|
||||
const wchar_t JSON_KEY_WIN[] = L"win";
|
||||
const wchar_t JSON_KEY_ALT[] = L"alt";
|
||||
const wchar_t JSON_KEY_CTRL[] = L"ctrl";
|
||||
const wchar_t JSON_KEY_SHIFT[] = L"shift";
|
||||
const wchar_t JSON_KEY_CODE[] = L"code";
|
||||
const wchar_t JSON_KEY_ACTIVATION_SHORTCUT[] = L"ToggleShortcut";
|
||||
}
|
||||
|
||||
// Implement the PowerToy Module Interface and all the required methods.
|
||||
class KeyboardManager : public PowertoyModuleIface
|
||||
{
|
||||
private:
|
||||
// The PowerToy state.
|
||||
bool m_enabled = false;
|
||||
bool m_active = false;
|
||||
|
||||
// The PowerToy name that will be shown in the settings.
|
||||
const std::wstring app_name = GET_RESOURCE_STRING(IDS_KEYBOARDMANAGER);
|
||||
@@ -41,10 +53,146 @@ private:
|
||||
//contains the non localized key of the powertoy
|
||||
std::wstring app_key = KeyboardManagerConstants::ModuleName;
|
||||
|
||||
// Hotkey for toggling the module
|
||||
Hotkey m_hotkey = { .key = 0 };
|
||||
|
||||
ULONGLONG m_lastHotkeyToggleTime = 0;
|
||||
|
||||
HANDLE m_hProcess = nullptr;
|
||||
|
||||
HANDLE m_hTerminateEngineEvent = nullptr;
|
||||
|
||||
void refresh_process_state()
|
||||
{
|
||||
if (m_hProcess && WaitForSingleObject(m_hProcess, 0) != WAIT_TIMEOUT)
|
||||
{
|
||||
CloseHandle(m_hProcess);
|
||||
m_hProcess = nullptr;
|
||||
m_active = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool start_engine()
|
||||
{
|
||||
refresh_process_state();
|
||||
if (m_hProcess)
|
||||
{
|
||||
m_active = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_hTerminateEngineEvent)
|
||||
{
|
||||
Logger::error(L"Cannot start keyboard manager engine because terminate event is not available");
|
||||
m_active = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned long powertoys_pid = GetCurrentProcessId();
|
||||
std::wstring executable_args = std::to_wstring(powertoys_pid);
|
||||
|
||||
SHELLEXECUTEINFOW sei{ sizeof(sei) };
|
||||
sei.fMask = { SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI };
|
||||
sei.lpFile = L"KeyboardManagerEngine\\PowerToys.KeyboardManagerEngine.exe";
|
||||
sei.nShow = SW_SHOWNORMAL;
|
||||
sei.lpParameters = executable_args.data();
|
||||
if (ShellExecuteExW(&sei) == false)
|
||||
{
|
||||
Logger::error(L"Failed to start keyboard manager engine");
|
||||
auto message = get_last_error_message(GetLastError());
|
||||
if (message.has_value())
|
||||
{
|
||||
Logger::error(message.value());
|
||||
}
|
||||
|
||||
m_active = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_hProcess = sei.hProcess;
|
||||
if (m_hProcess)
|
||||
{
|
||||
SetPriorityClass(m_hProcess, REALTIME_PRIORITY_CLASS);
|
||||
m_active = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
m_active = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
void stop_engine()
|
||||
{
|
||||
refresh_process_state();
|
||||
if (!m_hProcess)
|
||||
{
|
||||
m_active = false;
|
||||
return;
|
||||
}
|
||||
|
||||
SetEvent(m_hTerminateEngineEvent);
|
||||
auto waitResult = WaitForSingleObject(m_hProcess, 1500);
|
||||
if (waitResult == WAIT_TIMEOUT)
|
||||
{
|
||||
TerminateProcess(m_hProcess, 0);
|
||||
WaitForSingleObject(m_hProcess, 500);
|
||||
}
|
||||
|
||||
CloseHandle(m_hProcess);
|
||||
m_hProcess = nullptr;
|
||||
ResetEvent(m_hTerminateEngineEvent);
|
||||
m_active = false;
|
||||
}
|
||||
|
||||
void parse_hotkey(PowerToysSettings::PowerToyValues& settings)
|
||||
{
|
||||
auto settingsObject = settings.get_raw_json();
|
||||
if (settingsObject.GetView().Size())
|
||||
{
|
||||
try
|
||||
{
|
||||
auto jsonHotkeyObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES)
|
||||
.GetNamedObject(JSON_KEY_ACTIVATION_SHORTCUT);
|
||||
m_hotkey.win = jsonHotkeyObject.GetNamedBoolean(JSON_KEY_WIN);
|
||||
m_hotkey.alt = jsonHotkeyObject.GetNamedBoolean(JSON_KEY_ALT);
|
||||
m_hotkey.shift = jsonHotkeyObject.GetNamedBoolean(JSON_KEY_SHIFT);
|
||||
m_hotkey.ctrl = jsonHotkeyObject.GetNamedBoolean(JSON_KEY_CTRL);
|
||||
m_hotkey.key = static_cast<unsigned char>(jsonHotkeyObject.GetNamedNumber(JSON_KEY_CODE));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Logger::error("Failed to initialize Keyboard Manager toggle shortcut");
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_hotkey.key)
|
||||
{
|
||||
// Set default: Win+Shift+K
|
||||
m_hotkey.win = true;
|
||||
m_hotkey.shift = true;
|
||||
m_hotkey.ctrl = false;
|
||||
m_hotkey.alt = false;
|
||||
m_hotkey.key = 'K';
|
||||
}
|
||||
}
|
||||
|
||||
// Load the settings file.
|
||||
void init_settings()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Load and parse the settings file for this PowerToy.
|
||||
PowerToysSettings::PowerToyValues settings =
|
||||
PowerToysSettings::PowerToyValues::load_from_settings_file(get_key());
|
||||
parse_hotkey(settings);
|
||||
}
|
||||
catch (std::exception&)
|
||||
{
|
||||
Logger::warn(L"An exception occurred while loading the settings file");
|
||||
// Error while loading from the settings file. Let default values stay as they are.
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
KeyboardManager()
|
||||
@@ -65,8 +213,20 @@ public:
|
||||
Logger::error(message.value());
|
||||
}
|
||||
}
|
||||
|
||||
init_settings();
|
||||
};
|
||||
|
||||
~KeyboardManager()
|
||||
{
|
||||
stop_engine();
|
||||
if (m_hTerminateEngineEvent)
|
||||
{
|
||||
CloseHandle(m_hTerminateEngineEvent);
|
||||
m_hTerminateEngineEvent = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy the powertoy and free memory
|
||||
virtual void destroy() override
|
||||
{
|
||||
@@ -117,6 +277,7 @@ public:
|
||||
// Parse the input JSON string.
|
||||
PowerToysSettings::PowerToyValues values =
|
||||
PowerToysSettings::PowerToyValues::from_json_string(config, get_key());
|
||||
parse_hotkey(values);
|
||||
|
||||
// If you don't need to do any custom processing of the settings, proceed
|
||||
// to persists the values calling:
|
||||
@@ -134,33 +295,7 @@ public:
|
||||
m_enabled = true;
|
||||
// Log telemetry
|
||||
Trace::EnableKeyboardManager(true);
|
||||
|
||||
unsigned long powertoys_pid = GetCurrentProcessId();
|
||||
std::wstring executable_args = L"";
|
||||
executable_args.append(std::to_wstring(powertoys_pid));
|
||||
|
||||
SHELLEXECUTEINFOW sei{ sizeof(sei) };
|
||||
sei.fMask = { SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI };
|
||||
sei.lpFile = L"KeyboardManagerEngine\\PowerToys.KeyboardManagerEngine.exe";
|
||||
sei.nShow = SW_SHOWNORMAL;
|
||||
sei.lpParameters = executable_args.data();
|
||||
if (ShellExecuteExW(&sei) == false)
|
||||
{
|
||||
Logger::error(L"Failed to start keyboard manager engine");
|
||||
auto message = get_last_error_message(GetLastError());
|
||||
if (message.has_value())
|
||||
{
|
||||
Logger::error(message.value());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_hProcess = sei.hProcess;
|
||||
if (m_hProcess)
|
||||
{
|
||||
SetPriorityClass(m_hProcess, REALTIME_PRIORITY_CLASS);
|
||||
}
|
||||
}
|
||||
start_engine();
|
||||
}
|
||||
|
||||
// Disable the powertoy
|
||||
@@ -169,15 +304,7 @@ public:
|
||||
m_enabled = false;
|
||||
// Log telemetry
|
||||
Trace::EnableKeyboardManager(false);
|
||||
|
||||
if (m_hProcess)
|
||||
{
|
||||
SetEvent(m_hTerminateEngineEvent);
|
||||
WaitForSingleObject(m_hProcess, 1500);
|
||||
|
||||
TerminateProcess(m_hProcess, 0);
|
||||
m_hProcess = nullptr;
|
||||
}
|
||||
stop_engine();
|
||||
}
|
||||
|
||||
// Returns if the powertoys is enabled
|
||||
@@ -192,9 +319,54 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return the invocation hotkey for toggling
|
||||
virtual size_t get_hotkeys(Hotkey* hotkeys, size_t buffer_size) override
|
||||
{
|
||||
if (m_hotkey.key)
|
||||
{
|
||||
if (hotkeys && buffer_size >= 1)
|
||||
{
|
||||
hotkeys[0] = m_hotkey;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Process the hotkey event
|
||||
virtual bool on_hotkey(size_t /*hotkeyId*/) override
|
||||
{
|
||||
if (!m_enabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr ULONGLONG hotkeyToggleDebounceMs = 500;
|
||||
const auto now = GetTickCount64();
|
||||
if (now - m_lastHotkeyToggleTime < hotkeyToggleDebounceMs)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
m_lastHotkeyToggleTime = now;
|
||||
|
||||
refresh_process_state();
|
||||
if (m_active)
|
||||
{
|
||||
stop_engine();
|
||||
}
|
||||
else
|
||||
{
|
||||
start_engine();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create()
|
||||
{
|
||||
return new KeyboardManager();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,12 +21,17 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
[CmdConfigureIgnoreAttribute]
|
||||
public GenericProperty<List<string>> KeyboardConfigurations { get; set; }
|
||||
|
||||
public HotkeySettings DefaultToggleShortcut => new HotkeySettings(true, false, false, true, 0x4B);
|
||||
|
||||
public KeyboardManagerProperties()
|
||||
{
|
||||
ToggleShortcut = DefaultToggleShortcut;
|
||||
KeyboardConfigurations = new GenericProperty<List<string>>(new List<string> { "default", });
|
||||
ActiveConfiguration = new GenericProperty<string>("default");
|
||||
}
|
||||
|
||||
public HotkeySettings ToggleShortcut { get; set; }
|
||||
|
||||
public string ToJsonString()
|
||||
{
|
||||
return JsonSerializer.Serialize(this);
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
// 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;
|
||||
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
@@ -32,5 +33,18 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public HotkeyAccessor[] GetAllHotkeyAccessors()
|
||||
{
|
||||
var hotkeyAccessors = new List<HotkeyAccessor>
|
||||
{
|
||||
new HotkeyAccessor(
|
||||
() => Properties.ToggleShortcut,
|
||||
value => Properties.ToggleShortcut = value ?? Properties.DefaultToggleShortcut,
|
||||
"Toggle_Shortcut"),
|
||||
};
|
||||
|
||||
return hotkeyAccessors.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.PowerToys.Settings.UI.Helpers;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using SettingsUILibrary = Settings.UI.Library;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.SerializationContext;
|
||||
|
||||
@@ -24,6 +23,7 @@ namespace Microsoft.PowerToys.Settings.UI.SerializationContext;
|
||||
[JsonSerializable(typeof(FileLocksmithSettings))]
|
||||
[JsonSerializable(typeof(FindMyMouseSettings))]
|
||||
[JsonSerializable(typeof(IList<PowerToysReleaseInfo>))]
|
||||
[JsonSerializable(typeof(KeyboardManagerSettings))]
|
||||
[JsonSerializable(typeof(LightSwitchSettings))]
|
||||
[JsonSerializable(typeof(MeasureToolSettings))]
|
||||
[JsonSerializable(typeof(MouseHighlighterSettings))]
|
||||
|
||||
@@ -70,6 +70,13 @@
|
||||
</tkcontrols:SettingsCard>
|
||||
</controls:GPOInfoControl>
|
||||
|
||||
<tkcontrols:SettingsCard
|
||||
Name="ToggleShortcut"
|
||||
x:Uid="KeyboardManager_Toggle_Shortcut"
|
||||
HeaderIcon="{ui:FontIcon Glyph=}">
|
||||
<controls:ShortcutControl MinWidth="{StaticResource SettingActionControlMinWidth}" HotkeySettings="{x:Bind Path=ViewModel.ToggleShortcut, Mode=TwoWay}" />
|
||||
</tkcontrols:SettingsCard>
|
||||
|
||||
<controls:SettingsGroup x:Uid="KeyboardManager_Keys" IsEnabled="{x:Bind ViewModel.Enabled, Mode=OneWay}">
|
||||
<tkcontrols:SettingsCard
|
||||
Name="KeyboardManagerRemapKeyboardButton"
|
||||
|
||||
@@ -1876,6 +1876,12 @@ Made with 💗 by Microsoft and the PowerToys community.</value>
|
||||
<data name="Activation_Shortcut.Description" xml:space="preserve">
|
||||
<value>Customize the shortcut to activate this module</value>
|
||||
</data>
|
||||
<data name="KeyboardManager_Toggle_Shortcut.Header" xml:space="preserve">
|
||||
<value>Toggle shortcut</value>
|
||||
</data>
|
||||
<data name="KeyboardManager_Toggle_Shortcut.Description" xml:space="preserve">
|
||||
<value>Use a shortcut to toggle this module on or off (note that the Settings UI will not update)</value>
|
||||
</data>
|
||||
<data name="PasteAsPlainText_Shortcut.Header" xml:space="preserve">
|
||||
<value>Paste as plain text directly</value>
|
||||
</data>
|
||||
|
||||
@@ -8,6 +8,7 @@ using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
@@ -18,18 +19,20 @@ using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.ViewModels.Commands;
|
||||
using Microsoft.PowerToys.Settings.UI.SerializationContext;
|
||||
using Microsoft.PowerToys.Settings.Utilities;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
{
|
||||
public partial class KeyboardManagerViewModel : Observable
|
||||
public partial class KeyboardManagerViewModel : PageViewModelBase
|
||||
{
|
||||
private GeneralSettings GeneralSettingsConfig { get; set; }
|
||||
|
||||
private readonly SettingsUtils _settingsUtils;
|
||||
|
||||
private const string PowerToyName = KeyboardManagerSettings.ModuleName;
|
||||
protected override string ModuleName => KeyboardManagerSettings.ModuleName;
|
||||
|
||||
private const string JsonFileType = ".json";
|
||||
|
||||
// Default editor path. Can be removed once the new WinUI3 editor is released.
|
||||
@@ -74,15 +77,15 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
|
||||
_settingsUtils = settingsUtils ?? throw new ArgumentNullException(nameof(settingsUtils));
|
||||
|
||||
if (_settingsUtils.SettingsExists(PowerToyName))
|
||||
if (_settingsUtils.SettingsExists(ModuleName))
|
||||
{
|
||||
try
|
||||
{
|
||||
Settings = _settingsUtils.GetSettingsOrDefault<KeyboardManagerSettings>(PowerToyName);
|
||||
Settings = _settingsUtils.GetSettingsOrDefault<KeyboardManagerSettings>(ModuleName);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError($"Exception encountered while reading {PowerToyName} settings.", e);
|
||||
Logger.LogError($"Exception encountered while reading {ModuleName} settings.", e);
|
||||
#if DEBUG
|
||||
if (e is ArgumentException || e is ArgumentNullException || e is PathTooLongException)
|
||||
{
|
||||
@@ -100,7 +103,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
else
|
||||
{
|
||||
Settings = new KeyboardManagerSettings();
|
||||
_settingsUtils.SaveSettings(Settings.ToJsonString(), PowerToyName);
|
||||
_settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,6 +177,41 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public override Dictionary<string, HotkeySettings[]> GetAllHotkeySettings()
|
||||
{
|
||||
var hotkeysDict = new Dictionary<string, HotkeySettings[]>
|
||||
{
|
||||
[ModuleName] = [ToggleShortcut],
|
||||
};
|
||||
|
||||
return hotkeysDict;
|
||||
}
|
||||
|
||||
public HotkeySettings ToggleShortcut
|
||||
{
|
||||
get => Settings.Properties.ToggleShortcut;
|
||||
set
|
||||
{
|
||||
if (Settings.Properties.ToggleShortcut != value)
|
||||
{
|
||||
Settings.Properties.ToggleShortcut = value ?? Settings.Properties.DefaultToggleShortcut;
|
||||
OnPropertyChanged(nameof(ToggleShortcut));
|
||||
NotifySettingsChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void NotifySettingsChanged()
|
||||
{
|
||||
// Using InvariantCulture as this is an IPC message
|
||||
SendConfigMSG(
|
||||
string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"{{ \"powertoys\": {{ \"{0}\": {1} }} }}",
|
||||
ModuleName,
|
||||
JsonSerializer.Serialize(Settings, SourceGenerationContextContext.Default.KeyboardManagerSettings)));
|
||||
}
|
||||
|
||||
public static List<AppSpecificKeysDataModel> CombineShortcutLists(List<KeysDataModel> globalShortcutList, List<AppSpecificKeysDataModel> appSpecificShortcutList)
|
||||
{
|
||||
string allAppsDescription = "All Apps";
|
||||
@@ -256,13 +294,13 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
{
|
||||
if (editor != null && editor.HasExited)
|
||||
{
|
||||
Logger.LogInfo($"Previous instance of {PowerToyName} editor exited");
|
||||
Logger.LogInfo($"Previous instance of {ModuleName} editor exited");
|
||||
editor = null;
|
||||
}
|
||||
|
||||
if (editor != null)
|
||||
{
|
||||
Logger.LogInfo($"The {PowerToyName} editor instance {editor.Id} exists. Bringing the process to the front");
|
||||
Logger.LogInfo($"The {ModuleName} editor instance {editor.Id} exists. Bringing the process to the front");
|
||||
BringProcessToFront(editor);
|
||||
return;
|
||||
}
|
||||
@@ -298,14 +336,14 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
}
|
||||
|
||||
string path = Path.Combine(Environment.CurrentDirectory, editorPath);
|
||||
Logger.LogInfo($"Starting {PowerToyName} editor from {path}");
|
||||
Logger.LogInfo($"Starting {ModuleName} editor from {path}");
|
||||
|
||||
// InvariantCulture: type represents the KeyboardManagerEditorType enum value
|
||||
editor = Process.Start(path, $"{type.ToString(CultureInfo.InvariantCulture)} {Environment.ProcessId}");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError($"Exception encountered when opening an {PowerToyName} editor", e);
|
||||
Logger.LogError($"Exception encountered when opening an {ModuleName} editor", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,7 +376,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
{
|
||||
while (!readSuccessfully && !ts.IsCancellationRequested)
|
||||
{
|
||||
profileExists = _settingsUtils.SettingsExists(PowerToyName, fileName);
|
||||
profileExists = _settingsUtils.SettingsExists(ModuleName, fileName);
|
||||
if (!profileExists)
|
||||
{
|
||||
break;
|
||||
@@ -347,12 +385,12 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
{
|
||||
try
|
||||
{
|
||||
_profile = _settingsUtils.GetSettingsOrDefault<KeyboardManagerProfile>(PowerToyName, fileName);
|
||||
_profile = _settingsUtils.GetSettingsOrDefault<KeyboardManagerProfile>(ModuleName, fileName);
|
||||
readSuccessfully = true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError($"Exception encountered when reading {PowerToyName} settings", e);
|
||||
Logger.LogError($"Exception encountered when reading {ModuleName} settings", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -379,23 +417,23 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
|
||||
if (!completedInTime)
|
||||
{
|
||||
Logger.LogError($"Timeout encountered when loading {PowerToyName} profile");
|
||||
Logger.LogError($"Timeout encountered when loading {ModuleName} profile");
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// Failed to load the configuration.
|
||||
Logger.LogError($"Exception encountered when loading {PowerToyName} profile", e);
|
||||
Logger.LogError($"Exception encountered when loading {ModuleName} profile", e);
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (!profileExists)
|
||||
{
|
||||
Logger.LogInfo($"Couldn't load {PowerToyName} profile because it doesn't exist");
|
||||
Logger.LogInfo($"Couldn't load {ModuleName} profile because it doesn't exist");
|
||||
}
|
||||
else if (!success)
|
||||
{
|
||||
Logger.LogError($"Couldn't load {PowerToyName} profile");
|
||||
Logger.LogError($"Couldn't load {ModuleName} profile");
|
||||
}
|
||||
|
||||
return success;
|
||||
|
||||
Reference in New Issue
Block a user