Merge branch 'dev/build-features' into users/niels9001/settingsV2UXtweaks

This commit is contained in:
Clint Rutkas 2020-05-05 21:28:44 -07:00 committed by GitHub
commit 98ede836d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 473 additions and 130 deletions

View File

@ -59,7 +59,15 @@ namespace Microsoft.PowerToys.Settings.UI.Lib
this.AutoDownloadUpdates = false; this.AutoDownloadUpdates = false;
this.Theme = "system"; this.Theme = "system";
this.SystemTheme = "light"; this.SystemTheme = "light";
this.PowertoysVersion = interop.CommonManaged.GetProductVersion(); try
{
this.PowertoysVersion = DefaultPowertoysVersion();
}
catch
{
this.PowertoysVersion = "v0.0.0";
}
this.Enabled = new EnabledModules(); this.Enabled = new EnabledModules();
this.CustomActionName = string.Empty; this.CustomActionName = string.Empty;
} }
@ -69,5 +77,10 @@ namespace Microsoft.PowerToys.Settings.UI.Lib
{ {
return JsonSerializer.Serialize(this); return JsonSerializer.Serialize(this);
} }
private string DefaultPowertoysVersion()
{
return interop.CommonManaged.GetProductVersion();
}
} }
} }

View File

@ -15,8 +15,11 @@ namespace Microsoft.PowerToys.Settings.UI.Lib
MaxMRUSize = new IntProperty(); MaxMRUSize = new IntProperty();
ShowIcon = new BoolProperty(); ShowIcon = new BoolProperty();
ExtendedContextMenuOnly = new BoolProperty(); ExtendedContextMenuOnly = new BoolProperty();
Enabled = new BoolProperty();
} }
public BoolProperty Enabled { get; set; }
[JsonPropertyName("bool_persist_input")] [JsonPropertyName("bool_persist_input")]
public BoolProperty PersistState { get; set; } public BoolProperty PersistState { get; set; }

View File

@ -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);
}
}
}

View File

@ -81,4 +81,4 @@ namespace Microsoft.PowerToys.Settings.UI.Lib
return Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); return Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
} }
} }
} }

View File

@ -12,6 +12,10 @@ namespace Microsoft.PowerToys.Settings.UI.Lib
[JsonPropertyName("PowerRename")] [JsonPropertyName("PowerRename")]
public PowerRenameSettings PowerRename { get; set; } public PowerRenameSettings PowerRename { get; set; }
public SndPowerRenameSettings()
{
}
public SndPowerRenameSettings(PowerRenameSettings settings) public SndPowerRenameSettings(PowerRenameSettings settings)
{ {
PowerRename = settings; PowerRename = settings;

View File

@ -369,16 +369,16 @@
<value>Choose Settings color</value> <value>Choose Settings color</value>
</data> </data>
<data name="PowerRename_Toggle_EnableOnContextMenu.Header" xml:space="preserve"> <data name="PowerRename_Toggle_EnableOnContextMenu.Header" xml:space="preserve">
<value>Show on default context menu</value> <value>Show icon on context menu</value>
</data> </data>
<data name="PowerRename_Toggle_EnableOnExtendedContextMenu.Header" xml:space="preserve"> <data name="PowerRename_Toggle_EnableOnExtendedContextMenu.Header" xml:space="preserve">
<value>Only show on extended context menu (Shift + Right-click)</value> <value>Only show the PowerRename menu item on the extended context menu (Shift + Right-click).</value>
</data> </data>
<data name="PowerRename_Toggle_MaxDispListNum.Text" xml:space="preserve"> <data name="PowerRename_Toggle_MaxDispListNum.Text" xml:space="preserve">
<value>Maximum numbers of items to show in recently used list</value> <value>Maximum numbers of items to show in recently used list for autocomplete dropdown.</value>
</data> </data>
<data name="PowerRename_Toggle_RestoreFlagsOnLaunch.Header" xml:space="preserve"> <data name="PowerRename_Toggle_RestoreFlagsOnLaunch.Header" xml:space="preserve">
<value>Restore search, replace and flags values on launch from previous run</value> <value>Restore search, replace and flags values on launch from previous run.</value>
</data> </data>
<data name="FileEplorerPreview_ToggleSwitch_Preview_MD.Header" xml:space="preserve"> <data name="FileEplorerPreview_ToggleSwitch_Preview_MD.Header" xml:space="preserve">
<value>Markdown Preview Handler</value> <value>Markdown Preview Handler</value>
@ -396,7 +396,7 @@
<value>Open-source notice</value> <value>Open-source notice</value>
</data> </data>
<data name="PowerRename_Toggle_AutoComplete.Header" xml:space="preserve"> <data name="PowerRename_Toggle_AutoComplete.Header" xml:space="preserve">
<value>Enable Auto Complete</value> <value>Enable autocomplete and autosuggest of recently used list for autocomplete dropdown.</value>
</data> </data>
<data name="FancyZones_BorderColor.Text" xml:space="preserve"> <data name="FancyZones_BorderColor.Text" xml:space="preserve">
<value>Zone border color (Default #FFFFFF)</value> <value>Zone border color (Default #FFFFFF)</value>

View File

@ -75,7 +75,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
ShellPage.DefaultSndMSGCallback(snd.ToString()); ShellPage.DefaultSndMSGCallback(snd.ToString());
_powerRenameEnabled = value; _powerRenameEnabled = value;
RaisePropertyChanged(); OnPropertyChanged("IsEnabled");
} }
} }
} }

View File

@ -53,6 +53,12 @@
<TextBlock x:Uid="PowerRename_ShellIntergration" <TextBlock x:Uid="PowerRename_ShellIntergration"
Style="{StaticResource SettingsGroupTitleStyle}"/> Style="{StaticResource SettingsGroupTitleStyle}"/>
<ToggleSwitch x:Uid="PowerRename_Toggle_AutoComplete"
Margin="{StaticResource SmallTopMargin}"
IsOn="{Binding Mode=TwoWay, Path=MRUEnabled}"
IsEnabled="{ Binding Mode=TwoWay, Path=IsEnabled}"
/>
<ToggleSwitch x:Uid="PowerRename_Toggle_EnableOnContextMenu" <ToggleSwitch x:Uid="PowerRename_Toggle_EnableOnContextMenu"
Margin="{StaticResource SmallTopMargin}" Margin="{StaticResource SmallTopMargin}"
IsOn="{Binding Mode=TwoWay, Path=EnabledOnContextMenu}" IsOn="{Binding Mode=TwoWay, Path=EnabledOnContextMenu}"

View File

@ -129,6 +129,7 @@
<Compile Include="UnitTestApp.xaml.cs"> <Compile Include="UnitTestApp.xaml.cs">
<DependentUpon>UnitTestApp.xaml</DependentUpon> <DependentUpon>UnitTestApp.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="ViewModelTests\PowerRename.cs" />
<Compile Include="ViewModelTests\PowerPreview.cs" /> <Compile Include="ViewModelTests\PowerPreview.cs" />
<Compile Include="ViewModelTests\ShortcutGuide.cs" /> <Compile Include="ViewModelTests\ShortcutGuide.cs" />
<Compile Include="ViewModelTests\PowerLauncherViewModelTest.cs" /> <Compile Include="ViewModelTests\PowerLauncherViewModelTest.cs" />

View File

@ -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<OutGoingGeneralSettings>(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<PowerRenameSettingsIPCMessage>(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<PowerRenameSettingsIPCMessage>(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<PowerRenameSettingsIPCMessage>(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<PowerRenameSettingsIPCMessage>(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<PowerRenameSettingsIPCMessage>(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);
}
}
}

View File

@ -100,6 +100,7 @@
</ClCompile> </ClCompile>
<ClCompile Include="RemapShortcut.cpp" /> <ClCompile Include="RemapShortcut.cpp" />
<ClCompile Include="Shortcut.cpp" /> <ClCompile Include="Shortcut.cpp" />
<ClCompile Include="trace.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Helpers.h" /> <ClInclude Include="Helpers.h" />
@ -109,6 +110,7 @@
<ClInclude Include="pch.h" /> <ClInclude Include="pch.h" />
<ClInclude Include="RemapShortcut.h" /> <ClInclude Include="RemapShortcut.h" />
<ClInclude Include="Shortcut.h" /> <ClInclude Include="Shortcut.h" />
<ClInclude Include="trace.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\..\common\common.vcxproj"> <ProjectReference Include="..\..\..\common\common.vcxproj">

View File

@ -33,6 +33,9 @@
<ClCompile Include="KeyDelay.cpp"> <ClCompile Include="KeyDelay.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Trace.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="KeyboardManagerState.h"> <ClInclude Include="KeyboardManagerState.h">
@ -56,5 +59,8 @@
<ClInclude Include="KeyboardManagerConstants.h"> <ClInclude Include="KeyboardManagerConstants.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Trace.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -13,6 +13,7 @@
#include "winrt/Windows.UI.Text.h" #include "winrt/Windows.UI.Text.h"
#include "winrt/Windows.UI.Core.h" #include "winrt/Windows.UI.Core.h"
#include <stdlib.h> #include <stdlib.h>
#include <ProjectTelemetry.h>
using namespace winrt; using namespace winrt;
using namespace Windows::UI; using namespace Windows::UI;

View File

@ -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"));
}

View File

@ -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;
};

View File

@ -5,7 +5,7 @@
STRINGTABLE STRINGTABLE
BEGIN 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" IDS_KEYBOARDMANAGER L"Keyboard Manager"
END END

View File

@ -108,7 +108,6 @@
<ItemGroup> <ItemGroup>
<ClInclude Include="pch.h" /> <ClInclude Include="pch.h" />
<ClInclude Include="resource.h" /> <ClInclude Include="resource.h" />
<ClInclude Include="trace.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="dllmain.cpp" /> <ClCompile Include="dllmain.cpp" />
@ -118,7 +117,6 @@
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">pch.h</PrecompiledHeaderFile> <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">pch.h</PrecompiledHeaderFile>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">pch.h</PrecompiledHeaderFile> <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">pch.h</PrecompiledHeaderFile>
</ClCompile> </ClCompile>
<ClCompile Include="trace.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="$(SolutionDir)src\common\common.vcxproj"> <ProjectReference Include="$(SolutionDir)src\common\common.vcxproj">

View File

@ -4,7 +4,6 @@
#include <interface/win_hook_event_data.h> #include <interface/win_hook_event_data.h>
#include <common/settings_objects.h> #include <common/settings_objects.h>
#include <common/shared_constants.h> #include <common/shared_constants.h>
#include "trace.h"
#include "resource.h" #include "resource.h"
#include <keyboardmanager/ui/EditKeyboardWindow.h> #include <keyboardmanager/ui/EditKeyboardWindow.h>
#include <keyboardmanager/ui/EditShortcutsWindow.h> #include <keyboardmanager/ui/EditShortcutsWindow.h>
@ -12,7 +11,8 @@
#include <keyboardmanager/common/Shortcut.h> #include <keyboardmanager/common/Shortcut.h>
#include <keyboardmanager/common/RemapShortcut.h> #include <keyboardmanager/common/RemapShortcut.h>
#include <keyboardmanager/common/KeyboardManagerConstants.h> #include <keyboardmanager/common/KeyboardManagerConstants.h>
#include <common\settings_helpers.h> #include <common/settings_helpers.h>
#include <keyboardmanager/common/trace.h>
extern "C" IMAGE_DOS_HEADER __ImageBase; extern "C" IMAGE_DOS_HEADER __ImageBase;
@ -267,6 +267,9 @@ public:
virtual void enable() virtual void enable()
{ {
m_enabled = true; m_enabled = true;
// Log telemetry
Trace::EnableKeyboardManager(true);
// Start keyboard hook
start_lowlevel_keyboard_hook(); start_lowlevel_keyboard_hook();
} }
@ -274,6 +277,9 @@ public:
virtual void disable() virtual void disable()
{ {
m_enabled = false; m_enabled = false;
// Log telemetry
Trace::EnableKeyboardManager(false);
// Stop keyboard hook
stop_lowlevel_keyboard_hook(); stop_lowlevel_keyboard_hook();
} }

View File

@ -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));
}

View File

@ -1,9 +0,0 @@
#pragma once
class Trace
{
public:
static void RegisterProvider();
static void UnregisterProvider();
static void MyEvent();
};

View File

@ -3,6 +3,7 @@
#include "SingleKeyRemapControl.h" #include "SingleKeyRemapControl.h"
#include "KeyDropDownControl.h" #include "KeyDropDownControl.h"
#include "XamlBridge.h" #include "XamlBridge.h"
#include <keyboardmanager/common/trace.h>
LRESULT CALLBACK EditKeyboardWindowProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK EditKeyboardWindowProc(HWND, UINT, WPARAM, LPARAM);
@ -215,7 +216,7 @@ void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMan
KeyboardManagerHelper::ErrorType isSuccess = KeyboardManagerHelper::ErrorType::NoError; KeyboardManagerHelper::ErrorType isSuccess = KeyboardManagerHelper::ErrorType::NoError;
// Clear existing Key Remaps // Clear existing Key Remaps
keyboardManagerState.ClearSingleKeyRemaps(); keyboardManagerState.ClearSingleKeyRemaps();
DWORD successfulRemapCount = 0;
for (int i = 0; i < SingleKeyRemapControl::singleKeyRemapBuffer.size(); i++) for (int i = 0; i < SingleKeyRemapControl::singleKeyRemapBuffer.size(); i++)
{ {
DWORD originalKey = SingleKeyRemapControl::singleKeyRemapBuffer[i][0]; DWORD originalKey = SingleKeyRemapControl::singleKeyRemapBuffer[i][0];
@ -257,6 +258,10 @@ void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMan
isSuccess = KeyboardManagerHelper::ErrorType::RemapUnsuccessful; isSuccess = KeyboardManagerHelper::ErrorType::RemapUnsuccessful;
// Tooltip is already shown for this row // Tooltip is already shown for this row
} }
else
{
successfulRemapCount += 1;
}
} }
else else
{ {
@ -278,6 +283,7 @@ void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMan
{ {
isSuccess = KeyboardManagerHelper::ErrorType::SaveFailed; isSuccess = KeyboardManagerHelper::ErrorType::SaveFailed;
} }
Trace::KeyRemapCount(successfulRemapCount);
settingsMessage.Text(KeyboardManagerHelper::GetErrorMessage(isSuccess)); settingsMessage.Text(KeyboardManagerHelper::GetErrorMessage(isSuccess));
}); });

View File

@ -3,6 +3,7 @@
#include "ShortcutControl.h" #include "ShortcutControl.h"
#include "KeyDropDownControl.h" #include "KeyDropDownControl.h"
#include "XamlBridge.h" #include "XamlBridge.h"
#include <keyboardmanager/common/trace.h>
LRESULT CALLBACK EditShortcutsWindowProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK EditShortcutsWindowProc(HWND, UINT, WPARAM, LPARAM);
@ -167,7 +168,7 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa
KeyboardManagerHelper::ErrorType isSuccess = KeyboardManagerHelper::ErrorType::NoError; KeyboardManagerHelper::ErrorType isSuccess = KeyboardManagerHelper::ErrorType::NoError;
// Clear existing shortcuts // Clear existing shortcuts
keyboardManagerState.ClearOSLevelShortcuts(); keyboardManagerState.ClearOSLevelShortcuts();
DWORD successfulRemapCount = 0;
// Save the shortcuts that are valid and report if any of them were invalid // Save the shortcuts that are valid and report if any of them were invalid
for (int i = 0; i < ShortcutControl::shortcutRemapBuffer.size(); i++) for (int i = 0; i < ShortcutControl::shortcutRemapBuffer.size(); i++)
{ {
@ -182,6 +183,10 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa
isSuccess = KeyboardManagerHelper::ErrorType::RemapUnsuccessful; isSuccess = KeyboardManagerHelper::ErrorType::RemapUnsuccessful;
// Tooltip is already shown for this row // Tooltip is already shown for this row
} }
else
{
successfulRemapCount += 1;
}
} }
else else
{ {
@ -203,6 +208,7 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa
{ {
isSuccess = KeyboardManagerHelper::ErrorType::SaveFailed; isSuccess = KeyboardManagerHelper::ErrorType::SaveFailed;
} }
Trace::OSLevelShortcutRemapCount(successfulRemapCount);
settingsMessage.Text(KeyboardManagerHelper::GetErrorMessage(isSuccess)); settingsMessage.Text(KeyboardManagerHelper::GetErrorMessage(isSuccess));
}); });

View File

@ -1,15 +1,14 @@
#include "resource.h" #include "resource.h"
#include "../../../common/version.h"
<EFBFBD> <EFBFBD>
匀吀刀䤀一䜀吀䄀䈀䰀䔀ഀ<EFBFBD> 匀吀刀䤀一䜀吀䄀䈀䰀䔀ഀ<EFBFBD>
䈀䔀䜀䤀一ഀ<EFBFBD> 䈀䔀䜀䤀一ഀ<EFBFBD>
IDS_LAUNCHER_NAME L"Run" IDS_LAUNCHER_NAME L"Launcher"
IDS_LAUNCHER_SETTINGS_DESC L"<No description>" IDS_LAUNCHER_SETTINGS_DESC L"This feature requires Windows 10, May 2019 Update"
䔀一䐀ഀ<EFBFBD> 䔀一䐀ഀ<EFBFBD>
<EFBFBD> <EFBFBD>
 嘀䔀刀匀䤀伀一䤀一䘀伀ഀ<EFBFBD>  嘀䔀刀匀䤀伀一䤀一䘀伀ഀ<EFBFBD>
FILEVERSION FILE_VERSION FILEVERSION 0,1,0,0
PRODUCTVERSION PRODUCT_VERSION PRODUCTVERSION 0,1,0,0
 䘀䤀䰀䔀䘀䰀䄀䜀匀䴀䄀匀䬀  砀㌀昀䰀ഀ<EFBFBD>  䘀䤀䰀䔀䘀䰀䄀䜀匀䴀䄀匀䬀  砀㌀昀䰀ഀ<EFBFBD>
⌀椀昀搀攀昀 开䐀䔀䈀唀䜀ഀ<EFBFBD> ⌀椀昀搀攀昀 开䐀䔀䈀唀䜀ഀ<EFBFBD>
 䘀䤀䰀䔀䘀䰀䄀䜀匀  砀㄀䰀ഀ<EFBFBD>  䘀䤀䰀䔀䘀䰀䄀䜀匀  砀㄀䰀ഀ<EFBFBD>
@ -24,14 +23,14 @@
    䈀䔀䜀䤀一ഀ<EFBFBD>     䈀䔀䜀䤀一ഀ<EFBFBD>
        䈀䰀伀䌀䬀    㐀戀 ∀ഀ<EFBFBD>         䈀䰀伀䌀䬀    㐀戀 ∀ഀ<EFBFBD>
        䈀䔀䜀䤀一ഀ<EFBFBD>         䈀䔀䜀䤀一ഀ<EFBFBD>
VALUE "CompanyName", COMPANY_NAME VALUE "CompanyName", "Company Name"
VALUE "FileDescription", "Microsoft.Launcher Module" VALUE "FileDescription", "Wox.Launcher Module"
VALUE "FileVersion", FILE_VERSION_STRING VALUE "FileVersion", "0.1.0.0"
VALUE "InternalName", "Microsoft.Launcher" VALUE "InternalName", "Wox.Launcher"
VALUE "LegalCopyright", COPYRIGHT_NOTE VALUE "LegalCopyright", "Copyright (C) 2019 Company Name"
VALUE "OriginalFilename", "Microsoft.Launcher.dll" VALUE "OriginalFilename", "Wox.Launcher.dll"
VALUE "ProductName", "Microsoft.Launcher" VALUE "ProductName", "Wox.Launcher"
VALUE "ProductVersion", PRODUCT_VERSION_STRING VALUE "ProductVersion", "0.1.0.0"
        䔀一䐀ഀ<EFBFBD>         䔀一䐀ഀ<EFBFBD>
    䔀一䐀ഀ<EFBFBD>     䔀一䐀ഀ<EFBFBD>
    䈀䰀伀䌀䬀 ∀嘀愀爀䘀椀氀攀䤀渀昀漀∀ഀ<EFBFBD>     䈀䰀伀䌀䬀 ∀嘀愀爀䘀椀氀攀䤀渀昀漀∀ഀ<EFBFBD>

View File

@ -12,6 +12,8 @@ using Microsoft.Plugin.Indexer.SearchHelper;
using Microsoft.Search.Interop; using Microsoft.Search.Interop;
using Microsoft.PowerToys.Settings.UI.Lib; using Microsoft.PowerToys.Settings.UI.Lib;
using System.Windows.Controls; using System.Windows.Controls;
using Wox.Infrastructure.Logger;
using System.Text.RegularExpressions;
namespace Microsoft.Plugin.Indexer namespace Microsoft.Plugin.Indexer
{ {
@ -30,6 +32,9 @@ namespace Microsoft.Plugin.Indexer
// To access Windows Search functionalities // To access Windows Search functionalities
private readonly WindowsSearchAPI _api = new WindowsSearchAPI(); private readonly WindowsSearchAPI _api = new WindowsSearchAPI();
// Reserved keywords in oleDB
private string ReservedStringPattern = @"^[\/\\\$\%]+$";
private IContextMenu _contextMenuLoader; private IContextMenu _contextMenuLoader;
// To save the configurations of plugins // To save the configurations of plugins
@ -50,67 +55,68 @@ namespace Microsoft.Plugin.Indexer
_settings.MaxSearchCount = 50; _settings.MaxSearchCount = 50;
} }
try var regexMatch = Regex.Match(searchQuery, ReservedStringPattern);
{
var searchResultsList = _api.Search(searchQuery, maxCount: _settings.MaxSearchCount).ToList();
foreach (var searchResult in searchResultsList)
{
var path = searchResult.Path;
string workingDir = null; if (!regexMatch.Success)
if (_settings.UseLocationAsWorkingDir) {
workingDir = Path.GetDirectoryName(path); try
{
Result r = new Result(); var searchResultsList = _api.Search(searchQuery, maxCount: _settings.MaxSearchCount).ToList();
r.Title = searchResult.Title; foreach (var searchResult in searchResultsList)
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; var path = searchResult.Path;
}
string workingDir = null;
results.Add(r); if (_settings.UseLocationAsWorkingDir)
} workingDir = Path.GetDirectoryName(path);
}
catch(InvalidOperationException) Result r = new Result();
{ r.Title = searchResult.Title;
//The connection has closed, internal error of ExecuteReader() r.SubTitle = "Search: " + path;
//Not showing this exception to the users r.IcoPath = path;
} r.Action = c =>
catch (Exception ex) {
{ bool hide;
results.Add(new Result try
{ {
Title = ex.ToString(), Process.Start(new ProcessStartInfo
IcoPath = "Images\\WindowsIndexerImg.bmp" {
}); 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; return results;

View File

@ -27,4 +27,5 @@
#include <winrt/Windows.ApplicationModel.h> #include <winrt/Windows.ApplicationModel.h>
#include <winrt/Windows.Storage.h> #include <winrt/Windows.Storage.h>
#include <winrt/Windows.Foundation.Metadata.h>
#include <wil/resource.h> #include <wil/resource.h>

View File

@ -207,6 +207,41 @@ BOOL run_settings_non_elevated(LPCWSTR executable_path, LPWSTR executable_args,
return process_created; 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<uint16_t APIVersion> 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; DWORD g_settings_process_id = 0;
void run_settings_window() void run_settings_window()
@ -223,7 +258,15 @@ void run_settings_window()
// Arg 1: executable path. // Arg 1: executable path.
std::wstring executable_path = get_module_folderpath(); 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. // 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_"); std::wstring powertoys_pipe_name(L"\\\\.\\pipe\\powertoys_runner_");
@ -245,7 +288,7 @@ void run_settings_window()
// Arg 4: settings theme. // Arg 4: settings theme.
const std::wstring settings_theme_setting{ get_general_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())) if (settings_theme_setting == L"dark" || (settings_theme_setting == L"system" && WindowsColors::is_dark_mode()))
{ {
settings_theme = L"dark"; settings_theme = L"dark";
@ -350,15 +393,27 @@ LExit:
g_settings_process_id = 0; g_settings_process_id = 0;
} }
#define MAX_TITLE_LENGTH 100
void bring_settings_to_front() void bring_settings_to_front()
{ {
auto callback = [](HWND hwnd, LPARAM data) -> BOOL { auto callback = [](HWND hwnd, LPARAM data) -> BOOL {
DWORD processId; DWORD processId;
if (GetWindowThreadProcessId(hwnd, &processId) && processId == g_settings_process_id) if (GetWindowThreadProcessId(hwnd, &processId) && processId == g_settings_process_id)
{ {
ShowWindow(hwnd, SW_NORMAL); std::wstring windowTitle = L"PowerToys Settings";
SetForegroundWindow(hwnd);
return FALSE; 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; return TRUE;
@ -378,3 +433,15 @@ void open_settings_window()
std::thread(run_settings_window).detach(); 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);
}
}
}

View File

@ -1,2 +1,3 @@
#pragma once #pragma once
void open_settings_window(); void open_settings_window();
void close_settings_window();

View File

@ -67,6 +67,7 @@ LRESULT __stdcall tray_icon_window_proc(HWND window, UINT message, WPARAM wparam
Shell_NotifyIcon(NIM_DELETE, &tray_icon_data); Shell_NotifyIcon(NIM_DELETE, &tray_icon_data);
tray_icon_created = false; tray_icon_created = false;
} }
close_settings_window();
PostQuitMessage(0); PostQuitMessage(0);
break; break;
case WM_CLOSE: case WM_CLOSE: