diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/GeneralSettings.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/GeneralSettings.cs
index 6e3ed59038..6b4712ff96 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/GeneralSettings.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/GeneralSettings.cs
@@ -59,7 +59,15 @@ namespace Microsoft.PowerToys.Settings.UI.Lib
this.AutoDownloadUpdates = false;
this.Theme = "system";
this.SystemTheme = "light";
- this.PowertoysVersion = interop.CommonManaged.GetProductVersion();
+ try
+ {
+ this.PowertoysVersion = DefaultPowertoysVersion();
+ }
+ catch
+ {
+ this.PowertoysVersion = "v0.0.0";
+ }
+
this.Enabled = new EnabledModules();
this.CustomActionName = string.Empty;
}
@@ -69,5 +77,10 @@ namespace Microsoft.PowerToys.Settings.UI.Lib
{
return JsonSerializer.Serialize(this);
}
+
+ private string DefaultPowertoysVersion()
+ {
+ return interop.CommonManaged.GetProductVersion();
+ }
}
}
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/PowerRenameProperties.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/PowerRenameProperties.cs
index 99bc3bd1f8..dffa50d639 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/PowerRenameProperties.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/PowerRenameProperties.cs
@@ -15,8 +15,11 @@ namespace Microsoft.PowerToys.Settings.UI.Lib
MaxMRUSize = new IntProperty();
ShowIcon = new BoolProperty();
ExtendedContextMenuOnly = new BoolProperty();
+ Enabled = new BoolProperty();
}
+ public BoolProperty Enabled { get; set; }
+
[JsonPropertyName("bool_persist_input")]
public BoolProperty PersistState { get; set; }
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/PowerRenameSettingsIPCMessage.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/PowerRenameSettingsIPCMessage.cs
new file mode 100644
index 0000000000..9a56de6bc9
--- /dev/null
+++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/PowerRenameSettingsIPCMessage.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace Microsoft.PowerToys.Settings.UI.Lib
+{
+ public class PowerRenameSettingsIPCMessage
+ {
+ [JsonPropertyName("powertoys")]
+ public SndPowerRenameSettings Powertoys { get; set; }
+
+ public PowerRenameSettingsIPCMessage()
+ {
+
+ }
+
+ public PowerRenameSettingsIPCMessage(SndPowerRenameSettings settings)
+ {
+ this.Powertoys = settings;
+ }
+
+ public string ToJsonString()
+ {
+ return JsonSerializer.Serialize(this);
+ }
+ }
+}
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/SettingsUtils.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/SettingsUtils.cs
index 210cf800f6..abc6c1cd9d 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/SettingsUtils.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/SettingsUtils.cs
@@ -81,4 +81,4 @@ namespace Microsoft.PowerToys.Settings.UI.Lib
return Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/SndPowerRenameSettings.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/SndPowerRenameSettings.cs
index 75ffd5b4a1..781680f964 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/SndPowerRenameSettings.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/SndPowerRenameSettings.cs
@@ -12,6 +12,10 @@ namespace Microsoft.PowerToys.Settings.UI.Lib
[JsonPropertyName("PowerRename")]
public PowerRenameSettings PowerRename { get; set; }
+ public SndPowerRenameSettings()
+ {
+ }
+
public SndPowerRenameSettings(PowerRenameSettings settings)
{
PowerRename = settings;
diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw b/src/core/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw
index 1ef12c9ae2..408431a5af 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw
+++ b/src/core/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw
@@ -369,16 +369,16 @@
Choose Settings color
- Show on default context menu
+ Show icon on context menu
- Only show on extended context menu (Shift + Right-click)
+ Only show the PowerRename menu item on the extended context menu (Shift + Right-click).
- Maximum numbers of items to show in recently used list
+ Maximum numbers of items to show in recently used list for autocomplete dropdown.
- Restore search, replace and flags values on launch from previous run
+ Restore search, replace and flags values on launch from previous run.
Markdown Preview Handler
@@ -396,7 +396,7 @@
Open-source notice
- Enable Auto Complete
+ Enable autocomplete and autosuggest of recently used list for autocomplete dropdown.
Zone border color (Default #FFFFFF)
diff --git a/src/core/Microsoft.PowerToys.Settings.UI/ViewModels/PowerRenameViewModel.cs b/src/core/Microsoft.PowerToys.Settings.UI/ViewModels/PowerRenameViewModel.cs
index a1b9078c4a..ad26928cca 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI/ViewModels/PowerRenameViewModel.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI/ViewModels/PowerRenameViewModel.cs
@@ -75,7 +75,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
ShellPage.DefaultSndMSGCallback(snd.ToString());
_powerRenameEnabled = value;
- RaisePropertyChanged();
+ OnPropertyChanged("IsEnabled");
}
}
}
diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Views/PowerRenamePage.xaml b/src/core/Microsoft.PowerToys.Settings.UI/Views/PowerRenamePage.xaml
index c370a5d516..2638835ffb 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI/Views/PowerRenamePage.xaml
+++ b/src/core/Microsoft.PowerToys.Settings.UI/Views/PowerRenamePage.xaml
@@ -53,6 +53,12 @@
+
+
UnitTestApp.xaml
+
diff --git a/src/core/Microsoft.PowerToys.Settings.UnitTest/ViewModelTests/PowerRename.cs b/src/core/Microsoft.PowerToys.Settings.UnitTest/ViewModelTests/PowerRename.cs
new file mode 100644
index 0000000000..8b2d97fcc0
--- /dev/null
+++ b/src/core/Microsoft.PowerToys.Settings.UnitTest/ViewModelTests/PowerRename.cs
@@ -0,0 +1,156 @@
+using Microsoft.PowerToys.Settings.UI.Lib;
+using Microsoft.PowerToys.Settings.UI.ViewModels;
+using Microsoft.PowerToys.Settings.UI.Views;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Text.Json;
+using System.Threading.Tasks;
+
+namespace ViewModelTests
+{
+ [TestClass]
+ public class PowerRename
+ {
+ public const string ModuleName = "PowerRename";
+ public string schemaText = null;
+
+ [TestInitialize]
+ public void Setup()
+ {
+ // initialize creation of test settings file.
+ GeneralSettings generalSettings = new GeneralSettings();
+ PowerRenameSettings powerRename = new PowerRenameSettings();
+
+ SettingsUtils.SaveSettings(generalSettings.ToJsonString());
+ SettingsUtils.SaveSettings(powerRename.ToJsonString(), powerRename.name, "power-rename-settings.json");
+ }
+
+ [TestCleanup]
+ public void CleanUp()
+ {
+ // delete folder created.
+ string generalSettings_file_name = string.Empty;
+ if (SettingsUtils.SettingsFolderExists(generalSettings_file_name))
+ {
+ DeleteFolder(generalSettings_file_name);
+ }
+
+ // delete folder created.
+ if (SettingsUtils.SettingsFolderExists(ModuleName))
+ {
+ DeleteFolder(ModuleName);
+ }
+ }
+
+ [TestMethod]
+ public void IsEnabled_ShouldEnableModule_WhenSuccessful()
+ {
+ // arrange
+ PowerRenameViewModel viewModel = new PowerRenameViewModel();
+
+ // Assert
+ ShellPage.DefaultSndMSGCallback = msg =>
+ {
+ OutGoingGeneralSettings snd = JsonSerializer.Deserialize(msg);
+ Assert.IsTrue(snd.GeneralSettings.Enabled.PowerRename);
+ };
+
+ // act
+ viewModel.IsEnabled = true;
+ }
+
+ [TestMethod]
+ public void MRUEnabled_ShouldSetValue2True_WhenSuccessful()
+ {
+ // arrange
+ PowerRenameViewModel viewModel = new PowerRenameViewModel();
+
+ // Assert
+ ShellPage.DefaultSndMSGCallback = msg =>
+ {
+ PowerRenameSettingsIPCMessage snd = JsonSerializer.Deserialize(msg);
+ Assert.IsTrue(snd.Powertoys.PowerRename.properties.MRUEnabled.Value);
+ };
+
+ // act
+ viewModel.MRUEnabled = true;
+ }
+
+ [TestMethod]
+ public void EnabledOnContextMenu_ShouldSetValue2True_WhenSuccessful()
+ {
+ // arrange
+ PowerRenameViewModel viewModel = new PowerRenameViewModel();
+
+ // Assert
+ ShellPage.DefaultSndMSGCallback = msg =>
+ {
+ PowerRenameSettingsIPCMessage snd = JsonSerializer.Deserialize(msg);
+ Assert.IsTrue(snd.Powertoys.PowerRename.properties.ShowIcon.Value);
+ };
+
+ // act
+ viewModel.EnabledOnContextMenu = true;
+ }
+
+ [TestMethod]
+ public void EnabledOnContextExtendedMenu_ShouldSetValue2True_WhenSuccessful()
+ {
+ // arrange
+ PowerRenameViewModel viewModel = new PowerRenameViewModel();
+
+ // Assert
+ ShellPage.DefaultSndMSGCallback = msg =>
+ {
+ PowerRenameSettingsIPCMessage snd = JsonSerializer.Deserialize(msg);
+ Assert.IsTrue(snd.Powertoys.PowerRename.properties.ShowIcon.Value);
+ };
+
+ // act
+ viewModel.EnabledOnContextMenu = true;
+ }
+
+ [TestMethod]
+ public void RestoreFlagsOnLaunch_ShouldSetValue2True_WhenSuccessful()
+ {
+ // arrange
+ PowerRenameViewModel viewModel = new PowerRenameViewModel();
+
+ // Assert
+ ShellPage.DefaultSndMSGCallback = msg =>
+ {
+ PowerRenameSettingsIPCMessage snd = JsonSerializer.Deserialize(msg);
+ Assert.IsTrue(snd.Powertoys.PowerRename.properties.PersistState.Value);
+ };
+
+ // act
+ viewModel.RestoreFlagsOnLaunch = true;
+ }
+
+ [TestMethod]
+ public void MaxDispListNum_ShouldSetMaxSuggListTo20_WhenSuccessful()
+ {
+ // arrange
+ PowerRenameViewModel viewModel = new PowerRenameViewModel();
+
+ // Assert
+ ShellPage.DefaultSndMSGCallback = msg =>
+ {
+ PowerRenameSettingsIPCMessage snd = JsonSerializer.Deserialize(msg);
+ Assert.AreEqual(20,snd.Powertoys.PowerRename.properties.MaxMRUSize.Value);
+ };
+
+ // act
+ viewModel.MaxDispListNum = 20;
+ }
+
+ public void DeleteFolder(string powertoy)
+ {
+ Directory.Delete(Path.Combine(SettingsUtils.LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}"), true);
+ }
+ }
+}
diff --git a/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj b/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj
index ba7e2ff857..7a9aab4897 100644
--- a/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj
+++ b/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj
@@ -100,6 +100,7 @@
+
@@ -109,6 +110,7 @@
+
diff --git a/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj.filters b/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj.filters
index 25b1c95513..2e5f17c3f6 100644
--- a/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj.filters
+++ b/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj.filters
@@ -33,6 +33,9 @@
Source Files
+
+ Source Files
+
@@ -56,5 +59,8 @@
Header Files
+
+ Header Files
+
\ No newline at end of file
diff --git a/src/modules/keyboardmanager/common/pch.h b/src/modules/keyboardmanager/common/pch.h
index bdd02fa85d..5ecf9fd3ad 100644
--- a/src/modules/keyboardmanager/common/pch.h
+++ b/src/modules/keyboardmanager/common/pch.h
@@ -13,6 +13,7 @@
#include "winrt/Windows.UI.Text.h"
#include "winrt/Windows.UI.Core.h"
#include
+#include
using namespace winrt;
using namespace Windows::UI;
diff --git a/src/modules/keyboardmanager/common/trace.cpp b/src/modules/keyboardmanager/common/trace.cpp
new file mode 100644
index 0000000000..d17a2a3f6e
--- /dev/null
+++ b/src/modules/keyboardmanager/common/trace.cpp
@@ -0,0 +1,52 @@
+#include "pch.h"
+#include "trace.h"
+
+TRACELOGGING_DEFINE_PROVIDER(
+ g_hProvider,
+ "Microsoft.PowerToys",
+ // {38e8889b-9731-53f5-e901-e8a7c1753074}
+ (0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
+ TraceLoggingOptionProjectTelemetry());
+
+void Trace::RegisterProvider() noexcept
+{
+ TraceLoggingRegister(g_hProvider);
+}
+
+void Trace::UnregisterProvider() noexcept
+{
+ TraceLoggingUnregister(g_hProvider);
+}
+
+// Log if the user has KBM enabled or disabled - Can also be used to see how often users have to restart the keyboard hook
+void Trace::EnableKeyboardManager(const bool enabled) noexcept
+{
+ TraceLoggingWrite(
+ g_hProvider,
+ "KeyboardManager_EnableKeyboardManager",
+ ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
+ TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
+ TraceLoggingBoolean(enabled, "Enabled"));
+}
+
+// Log number of key remaps when the user uses Edit Keyboard and saves settings
+void Trace::KeyRemapCount(const DWORD count) noexcept
+{
+ TraceLoggingWrite(
+ g_hProvider,
+ "KeyboardManager_KeyRemapCount",
+ ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
+ TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
+ TraceLoggingValue(count, "KeyRemapCount"));
+}
+
+// Log number of os level shortcut remaps when the user uses Edit Shortcuts and saves settings
+void Trace::OSLevelShortcutRemapCount(const DWORD count) noexcept
+{
+ TraceLoggingWrite(
+ g_hProvider,
+ "KeyboardManager_OSLevelShortcutRemapCount",
+ ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
+ TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
+ TraceLoggingValue(count, "OSLevelShortcutRemapCount"));
+}
diff --git a/src/modules/keyboardmanager/common/trace.h b/src/modules/keyboardmanager/common/trace.h
new file mode 100644
index 0000000000..e5c1f140a8
--- /dev/null
+++ b/src/modules/keyboardmanager/common/trace.h
@@ -0,0 +1,17 @@
+#pragma once
+
+class Trace
+{
+public:
+ static void RegisterProvider() noexcept;
+ static void UnregisterProvider() noexcept;
+
+ // Log if the user has KBM enabled or disabled - Can also be used to see how often users have to restart the keyboard hook
+ static void EnableKeyboardManager(const bool enabled) noexcept;
+
+ // Log number of key remaps when the user uses Edit Keyboard and saves settings
+ static void KeyRemapCount(const DWORD count) noexcept;
+
+ // Log number of os level shortcut remaps when the user uses Edit Shortcuts and saves settings
+ static void OSLevelShortcutRemapCount(const DWORD count) noexcept;
+};
diff --git a/src/modules/keyboardmanager/dll/KeyboardManager.rc b/src/modules/keyboardmanager/dll/KeyboardManager.rc
index bc266ccb07..468391622c 100644
--- a/src/modules/keyboardmanager/dll/KeyboardManager.rc
+++ b/src/modules/keyboardmanager/dll/KeyboardManager.rc
@@ -5,7 +5,7 @@
STRINGTABLE
BEGIN
- IDS_SETTINGS_DESCRIPTION L"Customize your experience by remapping keys or creating new shortcuts!"
+ IDS_SETTINGS_DESCRIPTION L"This feature requires Windows 10, May 2019 Update"
IDS_KEYBOARDMANAGER L"Keyboard Manager"
END
diff --git a/src/modules/keyboardmanager/dll/KeyboardManager.vcxproj b/src/modules/keyboardmanager/dll/KeyboardManager.vcxproj
index dcad4f41a2..b307667d50 100644
--- a/src/modules/keyboardmanager/dll/KeyboardManager.vcxproj
+++ b/src/modules/keyboardmanager/dll/KeyboardManager.vcxproj
@@ -108,7 +108,6 @@
-
@@ -118,7 +117,6 @@
pch.h
pch.h
-
diff --git a/src/modules/keyboardmanager/dll/dllmain.cpp b/src/modules/keyboardmanager/dll/dllmain.cpp
index 2adafaf598..06d0545969 100644
--- a/src/modules/keyboardmanager/dll/dllmain.cpp
+++ b/src/modules/keyboardmanager/dll/dllmain.cpp
@@ -4,7 +4,6 @@
#include
#include
#include
-#include "trace.h"
#include "resource.h"
#include
#include
@@ -12,7 +11,8 @@
#include
#include
#include
-#include
+#include
+#include
extern "C" IMAGE_DOS_HEADER __ImageBase;
@@ -267,6 +267,9 @@ public:
virtual void enable()
{
m_enabled = true;
+ // Log telemetry
+ Trace::EnableKeyboardManager(true);
+ // Start keyboard hook
start_lowlevel_keyboard_hook();
}
@@ -274,6 +277,9 @@ public:
virtual void disable()
{
m_enabled = false;
+ // Log telemetry
+ Trace::EnableKeyboardManager(false);
+ // Stop keyboard hook
stop_lowlevel_keyboard_hook();
}
diff --git a/src/modules/keyboardmanager/dll/trace.cpp b/src/modules/keyboardmanager/dll/trace.cpp
deleted file mode 100644
index 1ba411198c..0000000000
--- a/src/modules/keyboardmanager/dll/trace.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-#include "pch.h"
-#include "trace.h"
-
-TRACELOGGING_DEFINE_PROVIDER(
- g_hProvider,
- "Microsoft.PowerToys",
- // {38e8889b-9731-53f5-e901-e8a7c1753074}
- (0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
- TraceLoggingOptionProjectTelemetry());
-
-void Trace::RegisterProvider()
-{
- TraceLoggingRegister(g_hProvider);
-}
-
-void Trace::UnregisterProvider()
-{
- TraceLoggingUnregister(g_hProvider);
-}
-
-void Trace::MyEvent()
-{
- TraceLoggingWrite(
- g_hProvider,
- "PowerToyName_MyEvent",
- ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
- TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"),
- TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
-}
diff --git a/src/modules/keyboardmanager/dll/trace.h b/src/modules/keyboardmanager/dll/trace.h
deleted file mode 100644
index acd37a7a20..0000000000
--- a/src/modules/keyboardmanager/dll/trace.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#pragma once
-
-class Trace
-{
-public:
- static void RegisterProvider();
- static void UnregisterProvider();
- static void MyEvent();
-};
diff --git a/src/modules/keyboardmanager/ui/EditKeyboardWindow.cpp b/src/modules/keyboardmanager/ui/EditKeyboardWindow.cpp
index a24adddd8e..a0a7dd70d4 100644
--- a/src/modules/keyboardmanager/ui/EditKeyboardWindow.cpp
+++ b/src/modules/keyboardmanager/ui/EditKeyboardWindow.cpp
@@ -3,6 +3,7 @@
#include "SingleKeyRemapControl.h"
#include "KeyDropDownControl.h"
#include "XamlBridge.h"
+#include
LRESULT CALLBACK EditKeyboardWindowProc(HWND, UINT, WPARAM, LPARAM);
@@ -215,7 +216,7 @@ void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMan
KeyboardManagerHelper::ErrorType isSuccess = KeyboardManagerHelper::ErrorType::NoError;
// Clear existing Key Remaps
keyboardManagerState.ClearSingleKeyRemaps();
-
+ DWORD successfulRemapCount = 0;
for (int i = 0; i < SingleKeyRemapControl::singleKeyRemapBuffer.size(); i++)
{
DWORD originalKey = SingleKeyRemapControl::singleKeyRemapBuffer[i][0];
@@ -257,6 +258,10 @@ void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMan
isSuccess = KeyboardManagerHelper::ErrorType::RemapUnsuccessful;
// Tooltip is already shown for this row
}
+ else
+ {
+ successfulRemapCount += 1;
+ }
}
else
{
@@ -278,6 +283,7 @@ void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMan
{
isSuccess = KeyboardManagerHelper::ErrorType::SaveFailed;
}
+ Trace::KeyRemapCount(successfulRemapCount);
settingsMessage.Text(KeyboardManagerHelper::GetErrorMessage(isSuccess));
});
diff --git a/src/modules/keyboardmanager/ui/EditShortcutsWindow.cpp b/src/modules/keyboardmanager/ui/EditShortcutsWindow.cpp
index 742584330c..afc159389f 100644
--- a/src/modules/keyboardmanager/ui/EditShortcutsWindow.cpp
+++ b/src/modules/keyboardmanager/ui/EditShortcutsWindow.cpp
@@ -3,6 +3,7 @@
#include "ShortcutControl.h"
#include "KeyDropDownControl.h"
#include "XamlBridge.h"
+#include
LRESULT CALLBACK EditShortcutsWindowProc(HWND, UINT, WPARAM, LPARAM);
@@ -167,7 +168,7 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa
KeyboardManagerHelper::ErrorType isSuccess = KeyboardManagerHelper::ErrorType::NoError;
// Clear existing shortcuts
keyboardManagerState.ClearOSLevelShortcuts();
-
+ DWORD successfulRemapCount = 0;
// Save the shortcuts that are valid and report if any of them were invalid
for (int i = 0; i < ShortcutControl::shortcutRemapBuffer.size(); i++)
{
@@ -182,6 +183,10 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa
isSuccess = KeyboardManagerHelper::ErrorType::RemapUnsuccessful;
// Tooltip is already shown for this row
}
+ else
+ {
+ successfulRemapCount += 1;
+ }
}
else
{
@@ -203,6 +208,7 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa
{
isSuccess = KeyboardManagerHelper::ErrorType::SaveFailed;
}
+ Trace::OSLevelShortcutRemapCount(successfulRemapCount);
settingsMessage.Text(KeyboardManagerHelper::GetErrorMessage(isSuccess));
});
diff --git a/src/modules/launcher/Microsoft.Launcher/Microsoft.Launcher.rc b/src/modules/launcher/Microsoft.Launcher/Microsoft.Launcher.rc
index 7e9f4c4be2..c870c17192 100644
Binary files a/src/modules/launcher/Microsoft.Launcher/Microsoft.Launcher.rc and b/src/modules/launcher/Microsoft.Launcher/Microsoft.Launcher.rc differ
diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.Indexer/Main.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.Indexer/Main.cs
index f579cba84f..97196f95c8 100644
--- a/src/modules/launcher/Plugins/Microsoft.Plugin.Indexer/Main.cs
+++ b/src/modules/launcher/Plugins/Microsoft.Plugin.Indexer/Main.cs
@@ -12,6 +12,8 @@ using Microsoft.Plugin.Indexer.SearchHelper;
using Microsoft.Search.Interop;
using Microsoft.PowerToys.Settings.UI.Lib;
using System.Windows.Controls;
+using Wox.Infrastructure.Logger;
+using System.Text.RegularExpressions;
namespace Microsoft.Plugin.Indexer
{
@@ -30,6 +32,9 @@ namespace Microsoft.Plugin.Indexer
// To access Windows Search functionalities
private readonly WindowsSearchAPI _api = new WindowsSearchAPI();
+ // Reserved keywords in oleDB
+ private string ReservedStringPattern = @"^[\/\\\$\%]+$";
+
private IContextMenu _contextMenuLoader;
// To save the configurations of plugins
@@ -50,67 +55,68 @@ namespace Microsoft.Plugin.Indexer
_settings.MaxSearchCount = 50;
}
- try
- {
- var searchResultsList = _api.Search(searchQuery, maxCount: _settings.MaxSearchCount).ToList();
- foreach (var searchResult in searchResultsList)
- {
- var path = searchResult.Path;
+ var regexMatch = Regex.Match(searchQuery, ReservedStringPattern);
- string workingDir = null;
- if (_settings.UseLocationAsWorkingDir)
- workingDir = Path.GetDirectoryName(path);
-
- Result r = new Result();
- r.Title = searchResult.Title;
- r.SubTitle = "Search: " + path;
- r.IcoPath = path;
- r.Action = c =>
- {
- bool hide;
- try
- {
- Process.Start(new ProcessStartInfo
- {
- FileName = path,
- UseShellExecute = true,
- WorkingDirectory = workingDir
- });
- hide = true;
- }
- catch (Win32Exception)
- {
- var name = $"Plugin: {_context.CurrentPluginMetadata.Name}";
- var msg = "Can't Open this file";
- _context.API.ShowMsg(name, msg, string.Empty);
- hide = false;
- }
- return hide;
- };
- r.ContextData = searchResult;
-
- //If the result is a directory, then it's display should show a directory.
- if(Directory.Exists(path))
+ if (!regexMatch.Success)
+ {
+ try
+ {
+ var searchResultsList = _api.Search(searchQuery, maxCount: _settings.MaxSearchCount).ToList();
+ foreach (var searchResult in searchResultsList)
{
- r.QueryTextDisplay = path;
- }
-
- results.Add(r);
- }
- }
- catch(InvalidOperationException)
- {
- //The connection has closed, internal error of ExecuteReader()
- //Not showing this exception to the users
- }
- catch (Exception ex)
- {
- results.Add(new Result
- {
- Title = ex.ToString(),
- IcoPath = "Images\\WindowsIndexerImg.bmp"
- });
- }
+ var path = searchResult.Path;
+
+ string workingDir = null;
+ if (_settings.UseLocationAsWorkingDir)
+ workingDir = Path.GetDirectoryName(path);
+
+ Result r = new Result();
+ r.Title = searchResult.Title;
+ r.SubTitle = "Search: " + path;
+ r.IcoPath = path;
+ r.Action = c =>
+ {
+ bool hide;
+ try
+ {
+ Process.Start(new ProcessStartInfo
+ {
+ FileName = path,
+ UseShellExecute = true,
+ WorkingDirectory = workingDir
+ });
+ hide = true;
+ }
+ catch (Win32Exception)
+ {
+ var name = $"Plugin: {_context.CurrentPluginMetadata.Name}";
+ var msg = "Can't Open this file";
+ _context.API.ShowMsg(name, msg, string.Empty);
+ hide = false;
+ }
+ return hide;
+ };
+ r.ContextData = searchResult;
+
+ //If the result is a directory, then it's display should show a directory.
+ if (Directory.Exists(path))
+ {
+ r.QueryTextDisplay = path;
+ }
+
+ results.Add(r);
+ }
+ }
+ catch (InvalidOperationException)
+ {
+ //The connection has closed, internal error of ExecuteReader()
+ //Not showing this exception to the users
+ }
+ catch (Exception ex)
+ {
+ Log.Info(ex.ToString());
+ }
+ }
}
return results;
diff --git a/src/runner/pch.h b/src/runner/pch.h
index 07842b0166..fa35d00897 100644
--- a/src/runner/pch.h
+++ b/src/runner/pch.h
@@ -27,4 +27,5 @@
#include
#include
+#include
#include
\ No newline at end of file
diff --git a/src/runner/settings_window.cpp b/src/runner/settings_window.cpp
index 112cbf8021..7c2432c404 100644
--- a/src/runner/settings_window.cpp
+++ b/src/runner/settings_window.cpp
@@ -207,6 +207,41 @@ BOOL run_settings_non_elevated(LPCWSTR executable_path, LPWSTR executable_args,
return process_created;
}
+// The following three helper functions determine if the user has a build version higher than or equal to 19h1, as that is a requirement for xaml islands
+// Source : Microsoft-ui-xaml github
+// Link: https://github.com/microsoft/microsoft-ui-xaml/blob/c045cde57c5c754683d674634a0baccda34d58c4/dev/dll/SharedHelpers.cpp
+template bool IsAPIContractVxAvailable()
+{
+ static bool isAPIContractVxAvailableInitialized = false;
+ static bool isAPIContractVxAvailable = false;
+ if (!isAPIContractVxAvailableInitialized)
+ {
+ isAPIContractVxAvailableInitialized = true;
+ isAPIContractVxAvailable = winrt::Windows::Foundation::Metadata::ApiInformation::IsApiContractPresent(L"Windows.Foundation.UniversalApiContract", APIVersion);
+ }
+
+ return isAPIContractVxAvailable;
+}
+
+
+bool IsAPIContractV8Available()
+{
+ return IsAPIContractVxAvailable<8>();
+}
+
+bool Is19H1OrHigher()
+{
+ return IsAPIContractV8Available();
+}
+
+// This function returns true if the build is 19h1 or higher, so that we deploy the new settings.
+// It returns false otherwise.
+bool use_new_settings()
+{
+ return Is19H1OrHigher();
+}
+
+
DWORD g_settings_process_id = 0;
void run_settings_window()
@@ -223,7 +258,15 @@ void run_settings_window()
// Arg 1: executable path.
std::wstring executable_path = get_module_folderpath();
- executable_path.append(L"\\SettingsUIRunner\\Microsoft.PowerToys.Settings.UI.Runner.exe");
+
+ if (use_new_settings())
+ {
+ executable_path.append(L"\\SettingsUIRunner\\Microsoft.PowerToys.Settings.UI.Runner.exe");
+ }
+ else
+ {
+ executable_path.append(L"\\PowerToysSettings.exe");
+ }
// Arg 2: pipe server. Generate unique names for the pipes, if getting a UUID is possible.
std::wstring powertoys_pipe_name(L"\\\\.\\pipe\\powertoys_runner_");
@@ -245,7 +288,7 @@ void run_settings_window()
// Arg 4: settings theme.
const std::wstring settings_theme_setting{ get_general_settings().theme };
- std::wstring settings_theme;
+ std::wstring settings_theme = L"system";
if (settings_theme_setting == L"dark" || (settings_theme_setting == L"system" && WindowsColors::is_dark_mode()))
{
settings_theme = L"dark";
@@ -350,15 +393,27 @@ LExit:
g_settings_process_id = 0;
}
+#define MAX_TITLE_LENGTH 100
void bring_settings_to_front()
{
auto callback = [](HWND hwnd, LPARAM data) -> BOOL {
DWORD processId;
if (GetWindowThreadProcessId(hwnd, &processId) && processId == g_settings_process_id)
{
- ShowWindow(hwnd, SW_NORMAL);
- SetForegroundWindow(hwnd);
- return FALSE;
+ std::wstring windowTitle = L"PowerToys Settings";
+
+ WCHAR title[MAX_TITLE_LENGTH];
+ int len = GetWindowTextW(hwnd, title, MAX_TITLE_LENGTH);
+ if (len <= 0)
+ {
+ return TRUE;
+ }
+ if (wcsncmp(title, windowTitle.c_str(), len) == 0)
+ {
+ ShowWindow(hwnd, SW_RESTORE);
+ SetForegroundWindow(hwnd);
+ return FALSE;
+ }
}
return TRUE;
@@ -378,3 +433,15 @@ void open_settings_window()
std::thread(run_settings_window).detach();
}
}
+
+void close_settings_window()
+{
+ if (g_settings_process_id != 0)
+ {
+ HANDLE proc = OpenProcess(PROCESS_TERMINATE, false, g_settings_process_id);
+ if (proc != INVALID_HANDLE_VALUE)
+ {
+ TerminateProcess(proc, 0);
+ }
+ }
+}
diff --git a/src/runner/settings_window.h b/src/runner/settings_window.h
index 97bb613fa4..0f9048f16e 100644
--- a/src/runner/settings_window.h
+++ b/src/runner/settings_window.h
@@ -1,2 +1,3 @@
#pragma once
void open_settings_window();
+void close_settings_window();
\ No newline at end of file
diff --git a/src/runner/tray_icon.cpp b/src/runner/tray_icon.cpp
index 04bf03322d..21fe702566 100644
--- a/src/runner/tray_icon.cpp
+++ b/src/runner/tray_icon.cpp
@@ -67,6 +67,7 @@ LRESULT __stdcall tray_icon_window_proc(HWND window, UINT message, WPARAM wparam
Shell_NotifyIcon(NIM_DELETE, &tray_icon_data);
tray_icon_created = false;
}
+ close_settings_window();
PostQuitMessage(0);
break;
case WM_CLOSE: