From 36559d02642d77766a08416032a80f0b13ef56d7 Mon Sep 17 00:00:00 2001 From: Arjun Balgovind <32061677+arjunbalgovind@users.noreply.github.com> Date: Tue, 5 May 2020 12:30:50 -0700 Subject: [PATCH 1/8] Added telemetry to KBM (#2670) * Added telemetry to KBM * Reverted set_config change * resolving comments --- .../common/KeyboardManagerCommon.vcxproj | 2 + .../KeyboardManagerCommon.vcxproj.filters | 6 +++ src/modules/keyboardmanager/common/pch.h | 1 + src/modules/keyboardmanager/common/trace.cpp | 52 +++++++++++++++++++ src/modules/keyboardmanager/common/trace.h | 17 ++++++ .../dll/KeyboardManager.vcxproj | 2 - src/modules/keyboardmanager/dll/dllmain.cpp | 10 +++- src/modules/keyboardmanager/dll/trace.cpp | 29 ----------- src/modules/keyboardmanager/dll/trace.h | 9 ---- .../keyboardmanager/ui/EditKeyboardWindow.cpp | 8 ++- .../ui/EditShortcutsWindow.cpp | 8 ++- 11 files changed, 100 insertions(+), 44 deletions(-) create mode 100644 src/modules/keyboardmanager/common/trace.cpp create mode 100644 src/modules/keyboardmanager/common/trace.h delete mode 100644 src/modules/keyboardmanager/dll/trace.cpp delete mode 100644 src/modules/keyboardmanager/dll/trace.h 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.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)); }); From d65e2ab2d401032726dc842f19ab2613a46ee094 Mon Sep 17 00:00:00 2001 From: Lavius Motileng <58791731+laviusmotileng-ms@users.noreply.github.com> Date: Tue, 5 May 2020 14:02:55 -0700 Subject: [PATCH 2/8] FIX : [Settings] - Can start multiple settings dialogs (#2421) * Launch new wpf process with same/old ipc names * updated bring window to front * reverted change * removed unused string --- src/runner/settings_window.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/runner/settings_window.cpp b/src/runner/settings_window.cpp index 112cbf8021..06e6f0c1a2 100644 --- a/src/runner/settings_window.cpp +++ b/src/runner/settings_window.cpp @@ -350,15 +350,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; From 462c17a0c3200e1ea04396a7d46b77423cdd65e1 Mon Sep 17 00:00:00 2001 From: Tomas Agustin Raies Date: Tue, 5 May 2020 14:13:52 -0700 Subject: [PATCH 3/8] Close Settings Window on runner exit (#2695) --- src/runner/settings_window.cpp | 12 ++++++++++++ src/runner/settings_window.h | 1 + src/runner/tray_icon.cpp | 1 + 3 files changed, 14 insertions(+) diff --git a/src/runner/settings_window.cpp b/src/runner/settings_window.cpp index 06e6f0c1a2..e31e047eb9 100644 --- a/src/runner/settings_window.cpp +++ b/src/runner/settings_window.cpp @@ -390,3 +390,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: From c2adf56b2fb2abdc57496538880675ea1167d459 Mon Sep 17 00:00:00 2001 From: Lavius Motileng <58791731+laviusmotileng-ms@users.noreply.github.com> Date: Tue, 5 May 2020 14:28:44 -0700 Subject: [PATCH 4/8] updated header text and tests for PowerRename (#2607) --- .../PowerRenameProperties.cs | 3 + .../PowerRenameSettingsIPCMessage.cs | 29 ++++ .../SettingsUtils.cs | 2 +- .../SndPowerRenameSettings.cs | 4 + .../Strings/en-us/Resources.resw | 10 +- .../ViewModels/PowerRenameViewModel.cs | 2 +- .../Views/PowerRenamePage.xaml | 8 +- ...crosoft.PowerToys.Settings.UnitTest.csproj | 1 + .../ViewModelTests/PowerRename.cs | 156 ++++++++++++++++++ 9 files changed, 204 insertions(+), 11 deletions(-) create mode 100644 src/core/Microsoft.PowerToys.Settings.UI.Lib/PowerRenameSettingsIPCMessage.cs create mode 100644 src/core/Microsoft.PowerToys.Settings.UnitTest/ViewModelTests/PowerRename.cs 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 792170b70b..dcb845c56d 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 9d9922b3b2..edf7a04543 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI/Views/PowerRenamePage.xaml +++ b/src/core/Microsoft.PowerToys.Settings.UI/Views/PowerRenamePage.xaml @@ -50,15 +50,15 @@ IsOn="{Binding Mode=TwoWay, Path=IsEnabled}" /> + + - - - + 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); + } + } +} From 1a29870958aa682e2964c6ac27cb03828ca1663c Mon Sep 17 00:00:00 2001 From: Alekhya Date: Tue, 5 May 2020 15:53:30 -0700 Subject: [PATCH 5/8] OS Detection and setting the old or new settings UI page accordingly (#2674) * Added code to detect os build number * To set the settings.exe according to the powerToys version that is running * Modified the description of old UI for launcher and keyboard remapper * Using API contracts instead of registry * Removing file that was included by mistake --- .../keyboardmanager/dll/KeyboardManager.rc | 2 +- .../Microsoft.Launcher/Microsoft.Launcher.rc | Bin 2084 -> 2004 bytes src/runner/pch.h | 1 + src/runner/settings_window.cpp | 45 +++++++++++++++++- 4 files changed, 46 insertions(+), 2 deletions(-) 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/launcher/Microsoft.Launcher/Microsoft.Launcher.rc b/src/modules/launcher/Microsoft.Launcher/Microsoft.Launcher.rc index 7e9f4c4be2a4c7c1264da3bda8c848e2322a3167..c870c17192615e4299b13d3341781a8cbf306e5b 100644 GIT binary patch delta 413 zcmZ1?aD{(@!Ni&vejkQJhEj$+hGd2ehE#^4iFdsdLx9XohGGTo8<6V9)`I`vUb<0%;>4-;lu)$O>gB0ICC-mO9y; z(U%vb&Jc(}w87-njH;+2o8K~WGf65jI0KE&1!_$MS_3lB56H>|8ZnVseDViYw#ge< zBqlqt$gze4)m2O`WKo_xg;@kDqrRz+BRsi))z2Pc zR{_wLBA}`BAVjR-R+Lg}6wM^0Rdgj%s|dBxKHT*mEO+Tj@DJSk z6@G&&SKqlh(D`B!fu#tkbbwv2n? zy6BO~dE{J~5y_p=PO-gs9N&lrYVkkDA;W8?tIFP5U%V%wvX(af!YJMoHOx z_nbfMsZyt9#4s8jk*<6hc81c>+LjZuxR_)J>7Fn=?4@xvca1cMEAQq?27A_OWo(Dm Rx%=o*p%TuJ}{ 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 e31e047eb9..e30166268a 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_"); From 3beea79b383bbb396d06a431ba8e465abbed39bf Mon Sep 17 00:00:00 2001 From: Tomas Agustin Raies Date: Tue, 5 May 2020 16:01:55 -0700 Subject: [PATCH 6/8] Workaround for Settings ViewModel tests (#2693) --- .../GeneralSettings.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) 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(); + } } } From e01ed8ad3c92b8ff9b38d75309cb1638ad95b821 Mon Sep 17 00:00:00 2001 From: Divyansh Srivastava Date: Tue, 5 May 2020 16:07:32 -0700 Subject: [PATCH 7/8] Fix for indexer symbol error (#2702) * Removed error sent as result in indexer plugin * Added code to filter query based on reserved keyword regex --- .../Plugins/Microsoft.Plugin.Indexer/Main.cs | 124 +++++++++--------- 1 file changed, 65 insertions(+), 59 deletions(-) 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; From e75916fd929ac09c0cec8fdce10c22fbc093900e Mon Sep 17 00:00:00 2001 From: Arjun Balgovind <32061677+arjunbalgovind@users.noreply.github.com> Date: Tue, 5 May 2020 21:17:43 -0700 Subject: [PATCH 8/8] Fixed SettingsV2 crash (#2704) * Fixed crash * Initialize theme string --- src/runner/settings_window.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runner/settings_window.cpp b/src/runner/settings_window.cpp index e30166268a..7c2432c404 100644 --- a/src/runner/settings_window.cpp +++ b/src/runner/settings_window.cpp @@ -288,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";