diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt
index a7551312327..cc620ed98f6 100644
--- a/.github/actions/spell-check/expect.txt
+++ b/.github/actions/spell-check/expect.txt
@@ -216,6 +216,7 @@ cim
CImage
cla
clangformat
+clayton
CLASSDC
CLASSNOTAVAILABLE
clickable
@@ -536,6 +537,7 @@ EXTENDEDKEY
EXTENDEDVERBS
eyetracker
fabricbot
+fancymouse
fancyzones
FANCYZONESDRAWLAYOUTTEST
FANCYZONESEDITOR
diff --git a/.pipelines/ESRPSigning_core.json b/.pipelines/ESRPSigning_core.json
index 96efd6cd4a1..d7173d5fb78 100644
--- a/.pipelines/ESRPSigning_core.json
+++ b/.pipelines/ESRPSigning_core.json
@@ -132,7 +132,10 @@
"modules\\MouseUtils\\PowerToys.FindMyMouse.dll",
"modules\\MouseUtils\\PowerToys.MouseHighlighter.dll",
+ "modules\\MouseUtils\\PowerToys.MouseJump.dll",
"modules\\MouseUtils\\PowerToys.MousePointerCrosshairs.dll",
+ "modules\\MouseUtils\\MouseJumpUI\\PowerToys.MouseJumpUI.dll",
+ "modules\\MouseUtils\\MouseJumpUI\\PowerToys.MouseJumpUI.exe",
"modules\\PowerAccent\\PowerAccent.Core.dll",
"modules\\PowerAccent\\PowerToys.PowerAccent.dll",
diff --git a/.pipelines/ci/templates/build-powertoys-steps.yml b/.pipelines/ci/templates/build-powertoys-steps.yml
index 703d520f108..94675840fea 100644
--- a/.pipelines/ci/templates/build-powertoys-steps.yml
+++ b/.pipelines/ci/templates/build-powertoys-steps.yml
@@ -208,6 +208,7 @@ steps:
**\UnitTests-SvgThumbnailProvider.dll
**\UnitTests-SvgPreviewHandler.dll
**\PowerToys.Hosts.Tests.dll
+ **\MouseJumpUI.UnitTests.dll
!**\obj\**
!**\ref\**
diff --git a/PowerToys.sln b/PowerToys.sln
index 725839892c6..783b8ad6056 100644
--- a/PowerToys.sln
+++ b/PowerToys.sln
@@ -487,6 +487,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StlThumbnailProviderCpp", "
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SvgThumbnailProviderCpp", "src\modules\previewpane\SvgThumbnailProviderCpp\SvgThumbnailProviderCpp.vcxproj", "{2BBC9E33-21EC-401C-84DA-BB6590A9B2AA}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MouseJump", "src\modules\MouseUtils\MouseJump\MouseJump.vcxproj", "{8A08D663-4995-40E3-B42C-3F910625F284}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MouseJumpUI", "src\modules\MouseUtils\MouseJumpUI\MouseJumpUI.csproj", "{D962A009-834F-4EEC-AABB-430DF8F98E39}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MouseJumpUI.UnitTests", "src\modules\MouseUtils\MouseJumpUI.UnitTests\MouseJumpUI.UnitTests.csproj", "{D9C5DE64-6849-4278-91AD-9660AECF2876}"
+EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "pasteplain", "pasteplain", "{9873BA05-4C41-4819-9283-CF45D795431B}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PastePlainModuleInterface", "src\modules\pasteplain\PastePlainModuleInterface\PastePlainModuleInterface.vcxproj", "{FC373B24-3293-453C-AAF5-CF2909DCEE6A}"
@@ -2028,6 +2034,42 @@ Global
{2BBC9E33-21EC-401C-84DA-BB6590A9B2AA}.Release|x64.Build.0 = Release|x64
{2BBC9E33-21EC-401C-84DA-BB6590A9B2AA}.Release|x86.ActiveCfg = Release|x64
{2BBC9E33-21EC-401C-84DA-BB6590A9B2AA}.Release|x86.Build.0 = Release|x64
+ {8A08D663-4995-40E3-B42C-3F910625F284}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {8A08D663-4995-40E3-B42C-3F910625F284}.Debug|ARM64.Build.0 = Debug|ARM64
+ {8A08D663-4995-40E3-B42C-3F910625F284}.Debug|x64.ActiveCfg = Debug|x64
+ {8A08D663-4995-40E3-B42C-3F910625F284}.Debug|x64.Build.0 = Debug|x64
+ {8A08D663-4995-40E3-B42C-3F910625F284}.Debug|x86.ActiveCfg = Debug|x64
+ {8A08D663-4995-40E3-B42C-3F910625F284}.Debug|x86.Build.0 = Debug|x64
+ {8A08D663-4995-40E3-B42C-3F910625F284}.Release|ARM64.ActiveCfg = Release|ARM64
+ {8A08D663-4995-40E3-B42C-3F910625F284}.Release|ARM64.Build.0 = Release|ARM64
+ {8A08D663-4995-40E3-B42C-3F910625F284}.Release|x64.ActiveCfg = Release|x64
+ {8A08D663-4995-40E3-B42C-3F910625F284}.Release|x64.Build.0 = Release|x64
+ {8A08D663-4995-40E3-B42C-3F910625F284}.Release|x86.ActiveCfg = Release|x64
+ {8A08D663-4995-40E3-B42C-3F910625F284}.Release|x86.Build.0 = Release|x64
+ {D962A009-834F-4EEC-AABB-430DF8F98E39}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {D962A009-834F-4EEC-AABB-430DF8F98E39}.Debug|ARM64.Build.0 = Debug|ARM64
+ {D962A009-834F-4EEC-AABB-430DF8F98E39}.Debug|x64.ActiveCfg = Debug|x64
+ {D962A009-834F-4EEC-AABB-430DF8F98E39}.Debug|x64.Build.0 = Debug|x64
+ {D962A009-834F-4EEC-AABB-430DF8F98E39}.Debug|x86.ActiveCfg = Debug|x64
+ {D962A009-834F-4EEC-AABB-430DF8F98E39}.Debug|x86.Build.0 = Debug|x64
+ {D962A009-834F-4EEC-AABB-430DF8F98E39}.Release|ARM64.ActiveCfg = Release|ARM64
+ {D962A009-834F-4EEC-AABB-430DF8F98E39}.Release|ARM64.Build.0 = Release|ARM64
+ {D962A009-834F-4EEC-AABB-430DF8F98E39}.Release|x64.ActiveCfg = Release|x64
+ {D962A009-834F-4EEC-AABB-430DF8F98E39}.Release|x64.Build.0 = Release|x64
+ {D962A009-834F-4EEC-AABB-430DF8F98E39}.Release|x86.ActiveCfg = Release|x64
+ {D962A009-834F-4EEC-AABB-430DF8F98E39}.Release|x86.Build.0 = Release|x64
+ {D9C5DE64-6849-4278-91AD-9660AECF2876}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {D9C5DE64-6849-4278-91AD-9660AECF2876}.Debug|ARM64.Build.0 = Debug|ARM64
+ {D9C5DE64-6849-4278-91AD-9660AECF2876}.Debug|x64.ActiveCfg = Debug|x64
+ {D9C5DE64-6849-4278-91AD-9660AECF2876}.Debug|x64.Build.0 = Debug|x64
+ {D9C5DE64-6849-4278-91AD-9660AECF2876}.Debug|x86.ActiveCfg = Debug|x64
+ {D9C5DE64-6849-4278-91AD-9660AECF2876}.Debug|x86.Build.0 = Debug|x64
+ {D9C5DE64-6849-4278-91AD-9660AECF2876}.Release|ARM64.ActiveCfg = Release|ARM64
+ {D9C5DE64-6849-4278-91AD-9660AECF2876}.Release|ARM64.Build.0 = Release|ARM64
+ {D9C5DE64-6849-4278-91AD-9660AECF2876}.Release|x64.ActiveCfg = Release|x64
+ {D9C5DE64-6849-4278-91AD-9660AECF2876}.Release|x64.Build.0 = Release|x64
+ {D9C5DE64-6849-4278-91AD-9660AECF2876}.Release|x86.ActiveCfg = Release|x64
+ {D9C5DE64-6849-4278-91AD-9660AECF2876}.Release|x86.Build.0 = Release|x64
{FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Debug|ARM64.ActiveCfg = Debug|ARM64
{FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Debug|ARM64.Build.0 = Debug|ARM64
{FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Debug|x64.ActiveCfg = Debug|x64
@@ -2222,6 +2264,9 @@ Global
{CA5518ED-0458-4B09-8F53-4122B9888655} = {2F305555-C296-497E-AC20-5FA1B237996A}
{D6DCC3AE-18C0-488A-B978-BAA9E3CFF09D} = {2F305555-C296-497E-AC20-5FA1B237996A}
{2BBC9E33-21EC-401C-84DA-BB6590A9B2AA} = {2F305555-C296-497E-AC20-5FA1B237996A}
+ {8A08D663-4995-40E3-B42C-3F910625F284} = {322566EF-20DC-43A6-B9F8-616AF942579A}
+ {D962A009-834F-4EEC-AABB-430DF8F98E39} = {322566EF-20DC-43A6-B9F8-616AF942579A}
+ {D9C5DE64-6849-4278-91AD-9660AECF2876} = {322566EF-20DC-43A6-B9F8-616AF942579A}
{9873BA05-4C41-4819-9283-CF45D795431B} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{FC373B24-3293-453C-AAF5-CF2909DCEE6A} = {9873BA05-4C41-4819-9283-CF45D795431B}
{9CE59ED5-7087-4353-88EB-788038A73CEC} = {1AFB6476-670D-4E80-A464-657E01DFF482}
diff --git a/installer/PowerToysSetup/MouseUtils.wxs b/installer/PowerToysSetup/MouseUtils.wxs
index 0d8ed66f1af..913ac7b5046 100644
--- a/installer/PowerToysSetup/MouseUtils.wxs
+++ b/installer/PowerToysSetup/MouseUtils.wxs
@@ -4,6 +4,8 @@
+
+
@@ -16,12 +18,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/installer/PowerToysSetup/Product.wxs b/installer/PowerToysSetup/Product.wxs
index 8ef113c1b38..903178678ff 100644
--- a/installer/PowerToysSetup/Product.wxs
+++ b/installer/PowerToysSetup/Product.wxs
@@ -477,6 +477,7 @@
+
diff --git a/installer/PowerToysSetup/Settings.wxs b/installer/PowerToysSetup/Settings.wxs
index e36bd5e642e..013ffe95890 100644
--- a/installer/PowerToysSetup/Settings.wxs
+++ b/installer/PowerToysSetup/Settings.wxs
@@ -7,7 +7,7 @@
-
+
diff --git a/installer/PowerToysSetupCustomActions/CustomAction.cpp b/installer/PowerToysSetupCustomActions/CustomAction.cpp
index c1f9e5a99af..ed17d9a34c8 100644
--- a/installer/PowerToysSetupCustomActions/CustomAction.cpp
+++ b/installer/PowerToysSetupCustomActions/CustomAction.cpp
@@ -1036,6 +1036,7 @@ const std::wstring PTInteropConsumers[] =
L"modules\\FileLocksmith",
L"modules\\Hosts",
L"modules\\FileExplorerPreview",
+ L"modules\\MouseUtils\\MouseJumpUI",
};
UINT __stdcall CreatePTInteropHardlinksCA(MSIHANDLE hInstall)
@@ -1079,7 +1080,8 @@ UINT __stdcall CreateDotnetRuntimeHardlinksCA(MSIHANDLE hInstall)
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
std::wstring installationFolder, dotnetRuntimeFilesSrcDir, colorPickerDir, powerOCRDir, launcherDir, fancyZonesDir,
- imageResizerDir, settingsDir, awakeDir, measureToolDir, powerAccentDir, fileExplorerAddOnsDir, hostsDir, fileLocksmithDir;
+ imageResizerDir, settingsDir, awakeDir, measureToolDir, powerAccentDir, fileExplorerAddOnsDir, hostsDir, fileLocksmithDir,
+ mouseJumpDir;
hr = WcaInitialize(hInstall, "CreateDotnetRuntimeHardlinksCA");
ExitOnFailure(hr, "Failed to initialize");
@@ -1100,6 +1102,7 @@ UINT __stdcall CreateDotnetRuntimeHardlinksCA(MSIHANDLE hInstall)
fileExplorerAddOnsDir = installationFolder + L"modules\\FileExplorerPreview\\";
hostsDir = installationFolder + L"modules\\Hosts\\";
fileLocksmithDir = installationFolder + L"modules\\FileLocksmith\\";
+ mouseJumpDir = installationFolder + L"modules\\MouseUtils\\MouseJumpUI\\";
for (auto file : dotnetRuntimeFiles)
{
@@ -1116,6 +1119,7 @@ UINT __stdcall CreateDotnetRuntimeHardlinksCA(MSIHANDLE hInstall)
std::filesystem::create_hard_link((dotnetRuntimeFilesSrcDir + file).c_str(), (fileExplorerAddOnsDir + file).c_str(), ec);
std::filesystem::create_hard_link((dotnetRuntimeFilesSrcDir + file).c_str(), (hostsDir + file).c_str(), ec);
std::filesystem::create_hard_link((dotnetRuntimeFilesSrcDir + file).c_str(), (fileLocksmithDir + file).c_str(), ec);
+ std::filesystem::create_hard_link((dotnetRuntimeFilesSrcDir + file).c_str(), (mouseJumpDir + file).c_str(), ec);
if (ec.value() != S_OK)
{
@@ -1139,6 +1143,7 @@ UINT __stdcall CreateDotnetRuntimeHardlinksCA(MSIHANDLE hInstall)
std::filesystem::create_hard_link((dotnetRuntimeFilesSrcDir + file).c_str(), (powerAccentDir + file).c_str(), ec);
std::filesystem::create_hard_link((dotnetRuntimeFilesSrcDir + file).c_str(), (fileExplorerAddOnsDir + file).c_str(), ec);
std::filesystem::create_hard_link((dotnetRuntimeFilesSrcDir + file).c_str(), (hostsDir + file).c_str(), ec);
+ std::filesystem::create_hard_link((dotnetRuntimeFilesSrcDir + file).c_str(), (mouseJumpDir + file).c_str(), ec);
if (ec.value() != S_OK)
{
@@ -1233,7 +1238,7 @@ UINT __stdcall DeleteDotnetRuntimeHardlinksCA(MSIHANDLE hInstall)
UINT er = ERROR_SUCCESS;
std::wstring installationFolder, colorPickerDir, powerOCRDir, launcherDir, fancyZonesDir,
imageResizerDir, settingsDir, awakeDir, measureToolDir, powerAccentDir, fileExplorerAddOnsDir,
- hostsDir, fileLocksmithDir;
+ hostsDir, fileLocksmithDir, mouseJumpDir;
hr = WcaInitialize(hInstall, "DeleteDotnetRuntimeHardlinksCA");
ExitOnFailure(hr, "Failed to initialize");
@@ -1253,6 +1258,7 @@ UINT __stdcall DeleteDotnetRuntimeHardlinksCA(MSIHANDLE hInstall)
fileExplorerAddOnsDir = installationFolder + L"modules\\FileExplorerPreview\\";
hostsDir = installationFolder + L"modules\\Hosts\\";
fileLocksmithDir = installationFolder + L"modules\\FileLocksmith\\";
+ mouseJumpDir = installationFolder + L"modules\\MouseUtils\\MouseJumpUI\\";
try
{
@@ -1270,6 +1276,7 @@ UINT __stdcall DeleteDotnetRuntimeHardlinksCA(MSIHANDLE hInstall)
DeleteFile((fileExplorerAddOnsDir + file).c_str());
DeleteFile((hostsDir + file).c_str());
DeleteFile((fileLocksmithDir + file).c_str());
+ DeleteFile((mouseJumpDir + file).c_str());
}
for (auto file : dotnetRuntimeWPFFiles)
@@ -1283,6 +1290,7 @@ UINT __stdcall DeleteDotnetRuntimeHardlinksCA(MSIHANDLE hInstall)
DeleteFile((powerAccentDir + file).c_str());
DeleteFile((fileExplorerAddOnsDir + file).c_str());
DeleteFile((hostsDir + file).c_str());
+ DeleteFile((mouseJumpDir + file).c_str());
}
}
catch (std::exception e)
@@ -1316,13 +1324,14 @@ UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall)
}
processes.resize(bytes / sizeof(processes[0]));
- std::array processesToTerminate = {
+ std::array processesToTerminate = {
L"PowerToys.PowerLauncher.exe",
L"PowerToys.Settings.exe",
L"PowerToys.Awake.exe",
L"PowerToys.FancyZones.exe",
L"PowerToys.FancyZonesEditor.exe",
L"PowerToys.FileLocksmithUI.exe",
+ L"PowerToys.MouseJumpUI.exe",
L"PowerToys.ColorPickerUI.exe",
L"PowerToys.AlwaysOnTop.exe",
L"PowerToys.exe"
diff --git a/src/common/GPOWrapper/GPOWrapper.cpp b/src/common/GPOWrapper/GPOWrapper.cpp
index dba7b29a5d4..09327b9c311 100644
--- a/src/common/GPOWrapper/GPOWrapper.cpp
+++ b/src/common/GPOWrapper/GPOWrapper.cpp
@@ -80,6 +80,10 @@ namespace winrt::PowerToys::GPOWrapper::implementation
{
return static_cast(powertoys_gpo::getConfiguredMouseHighlighterEnabledValue());
}
+ GpoRuleConfigured GPOWrapper::GetConfiguredMouseJumpEnabledValue()
+ {
+ return static_cast(powertoys_gpo::getConfiguredMouseJumpEnabledValue());
+ }
GpoRuleConfigured GPOWrapper::GetConfiguredMousePointerCrosshairsEnabledValue()
{
return static_cast(powertoys_gpo::getConfiguredMousePointerCrosshairsEnabledValue());
diff --git a/src/common/GPOWrapper/GPOWrapper.h b/src/common/GPOWrapper/GPOWrapper.h
index fcb559d0347..0ca33d1224d 100644
--- a/src/common/GPOWrapper/GPOWrapper.h
+++ b/src/common/GPOWrapper/GPOWrapper.h
@@ -26,6 +26,7 @@ namespace winrt::PowerToys::GPOWrapper::implementation
static GpoRuleConfigured GetConfiguredKeyboardManagerEnabledValue();
static GpoRuleConfigured GetConfiguredFindMyMouseEnabledValue();
static GpoRuleConfigured GetConfiguredMouseHighlighterEnabledValue();
+ static GpoRuleConfigured GetConfiguredMouseJumpEnabledValue();
static GpoRuleConfigured GetConfiguredMousePointerCrosshairsEnabledValue();
static GpoRuleConfigured GetConfiguredPowerRenameEnabledValue();
static GpoRuleConfigured GetConfiguredPowerLauncherEnabledValue();
diff --git a/src/common/GPOWrapper/GPOWrapper.idl b/src/common/GPOWrapper/GPOWrapper.idl
index 51189e48dae..2b9f631cc7e 100644
--- a/src/common/GPOWrapper/GPOWrapper.idl
+++ b/src/common/GPOWrapper/GPOWrapper.idl
@@ -30,6 +30,7 @@ namespace PowerToys
static GpoRuleConfigured GetConfiguredKeyboardManagerEnabledValue();
static GpoRuleConfigured GetConfiguredFindMyMouseEnabledValue();
static GpoRuleConfigured GetConfiguredMouseHighlighterEnabledValue();
+ static GpoRuleConfigured GetConfiguredMouseJumpEnabledValue();
static GpoRuleConfigured GetConfiguredMousePointerCrosshairsEnabledValue();
static GpoRuleConfigured GetConfiguredPowerRenameEnabledValue();
static GpoRuleConfigured GetConfiguredPowerLauncherEnabledValue();
diff --git a/src/common/logger/logger_settings.h b/src/common/logger/logger_settings.h
index b4242123145..bfe35315d83 100644
--- a/src/common/logger/logger_settings.h
+++ b/src/common/logger/logger_settings.h
@@ -47,6 +47,7 @@ struct LogSettings
inline const static std::wstring keyboardManagerLogPath = L"Logs\\keyboard-manager-log.txt";
inline const static std::string findMyMouseLoggerName = "find-my-mouse";
inline const static std::string mouseHighlighterLoggerName = "mouse-highlighter";
+ inline const static std::string mouseJumpLoggerName = "mouse-jump";
inline const static std::string mousePointerCrosshairsLoggerName = "mouse-pointer-crosshairs";
inline const static std::string imageResizerLoggerName = "imageresizer";
inline const static std::string powerRenameLoggerName = "powerrename";
diff --git a/src/common/utils/gpo.h b/src/common/utils/gpo.h
index 1e1bcc2140f..3414129b814 100644
--- a/src/common/utils/gpo.h
+++ b/src/common/utils/gpo.h
@@ -38,6 +38,7 @@ namespace powertoys_gpo {
const std::wstring POLICY_CONFIGURE_ENABLED_KEYBOARD_MANAGER = L"ConfigureEnabledUtilityKeyboardManager";
const std::wstring POLICY_CONFIGURE_ENABLED_FIND_MY_MOUSE = L"ConfigureEnabledUtilityFindMyMouse";
const std::wstring POLICY_CONFIGURE_ENABLED_MOUSE_HIGHLIGHTER = L"ConfigureEnabledUtilityMouseHighlighter";
+ const std::wstring POLICY_CONFIGURE_ENABLED_MOUSE_JUMP = L"ConfigureEnabledUtilityMouseJump";
const std::wstring POLICY_CONFIGURE_ENABLED_MOUSE_POINTER_CROSSHAIRS = L"ConfigureEnabledUtilityMousePointerCrosshairs";
const std::wstring POLICY_CONFIGURE_ENABLED_POWER_RENAME = L"ConfigureEnabledUtilityPowerRename";
const std::wstring POLICY_CONFIGURE_ENABLED_POWER_LAUNCHER = L"ConfigureEnabledUtilityPowerLauncher";
@@ -197,6 +198,11 @@ namespace powertoys_gpo {
return getConfiguredValue(POLICY_CONFIGURE_ENABLED_MOUSE_HIGHLIGHTER);
}
+ inline gpo_rule_configured_t getConfiguredMouseJumpEnabledValue()
+ {
+ return getConfiguredValue(POLICY_CONFIGURE_ENABLED_MOUSE_JUMP);
+ }
+
inline gpo_rule_configured_t getConfiguredMousePointerCrosshairsEnabledValue()
{
return getConfiguredValue(POLICY_CONFIGURE_ENABLED_MOUSE_POINTER_CROSSHAIRS);
diff --git a/src/gpo/assets/PowerToys.admx b/src/gpo/assets/PowerToys.admx
index 4a7fbadafd0..9ccf25b0a25 100644
--- a/src/gpo/assets/PowerToys.admx
+++ b/src/gpo/assets/PowerToys.admx
@@ -217,6 +217,16 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/gpo/assets/en-US/PowerToys.adml b/src/gpo/assets/en-US/PowerToys.adml
index 9dadbafef22..25ea233de65 100644
--- a/src/gpo/assets/en-US/PowerToys.adml
+++ b/src/gpo/assets/en-US/PowerToys.adml
@@ -54,6 +54,7 @@ If this setting is disabled, experimentation is not allowed.
Keyboard Manager: Configure enabled state
Find My Mouse: Configure enabled state
Mouse Highlighter: Configure enabled state
+ Mouse Jump: Configure enabled state
Mouse Pointer Crosshairs: Configure enabled state
Paste as Plain Text: Configure enabled state
Power Rename: Configure enabled state
diff --git a/src/modules/MouseUtils/MouseJump/MouseJump.rc b/src/modules/MouseUtils/MouseJump/MouseJump.rc
new file mode 100644
index 00000000000..f8d0a54cdab
--- /dev/null
+++ b/src/modules/MouseUtils/MouseJump/MouseJump.rc
@@ -0,0 +1,40 @@
+#include
+#include "resource.h"
+#include "../../../common/version/version.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+#include "winres.h"
+#undef APSTUDIO_READONLY_SYMBOLS
+
+1 VERSIONINFO
+FILEVERSION FILE_VERSION
+PRODUCTVERSION PRODUCT_VERSION
+FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+#ifdef _DEBUG
+FILEFLAGS VS_FF_DEBUG
+#else
+FILEFLAGS 0x0L
+#endif
+FILEOS VOS_NT_WINDOWS32
+FILETYPE VFT_DLL
+FILESUBTYPE VFT2_UNKNOWN
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0" // US English (0x0409), Unicode (0x04B0) charset
+ BEGIN
+ VALUE "CompanyName", COMPANY_NAME
+ VALUE "FileDescription", FILE_DESCRIPTION
+ VALUE "FileVersion", FILE_VERSION_STRING
+ VALUE "InternalName", INTERNAL_NAME
+ VALUE "LegalCopyright", COPYRIGHT_NOTE
+ VALUE "OriginalFilename", ORIGINAL_FILENAME
+ VALUE "ProductName", PRODUCT_NAME
+ VALUE "ProductVersion", PRODUCT_VERSION_STRING
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200 // US English (0x0409), Unicode (1200) charset
+ END
+END
\ No newline at end of file
diff --git a/src/modules/MouseUtils/MouseJump/MouseJump.vcxproj b/src/modules/MouseUtils/MouseJump/MouseJump.vcxproj
new file mode 100644
index 00000000000..16b9692ffdf
--- /dev/null
+++ b/src/modules/MouseUtils/MouseJump/MouseJump.vcxproj
@@ -0,0 +1,129 @@
+
+
+
+
+ 15.0
+ {8a08d663-4995-40e3-b42c-3f910625f284}
+ Win32Proj
+ MouseJumpModuleInterface
+ MouseJump
+
+
+
+ DynamicLibrary
+ true
+ v143
+ Unicode
+
+
+ DynamicLibrary
+ false
+ v143
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+ $(SolutionDir)$(Platform)\$(Configuration)\modules\MouseUtils\
+ PowerToys.MouseJump
+
+
+ true
+
+
+ false
+
+
+
+ Level3
+ Disabled
+ true
+ _DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+ MultiThreadedDebug
+ stdcpplatest
+
+
+ Windows
+ true
+ $(OutDir)$(TargetName)$(TargetExt)
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+ MultiThreaded
+ stdcpplatest
+
+
+ Windows
+ true
+ true
+ true
+ $(OutDir)$(TargetName)$(TargetExt)
+
+
+
+
+ $(SolutionDir)src\;$(SolutionDir)src\modules;$(SolutionDir)src\common\Telemetry;%(AdditionalIncludeDirectories)
+
+
+
+
+ Use
+ pch.h
+
+
+
+
+
+
+
+
+
+
+ Create
+
+
+
+
+
+ {d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}
+
+
+ {6955446d-23f7-4023-9bb3-8657f904af99}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
\ No newline at end of file
diff --git a/src/modules/MouseUtils/MouseJump/dllmain.cpp b/src/modules/MouseUtils/MouseJump/dllmain.cpp
new file mode 100644
index 00000000000..4be0abdc481
--- /dev/null
+++ b/src/modules/MouseUtils/MouseJump/dllmain.cpp
@@ -0,0 +1,302 @@
+#include "pch.h"
+
+#include
+//#include
+//#include
+#include
+#include "trace.h"
+#include
+#include
+
+extern "C" IMAGE_DOS_HEADER __ImageBase;
+
+HMODULE m_hModule;
+
+BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID /*lpReserved*/)
+{
+ m_hModule = hModule;
+ switch (ul_reason_for_call)
+ {
+ case DLL_PROCESS_ATTACH:
+ Trace::RegisterProvider();
+ break;
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ break;
+ case DLL_PROCESS_DETACH:
+ Trace::UnregisterProvider();
+ break;
+ }
+ return TRUE;
+}
+
+// The PowerToy name that will be shown in the settings.
+const static wchar_t* MODULE_NAME = L"MouseJump";
+// Add a description that will we shown in the module settings page.
+const static wchar_t* MODULE_DESC = L"Quickly move the mouse long distances";
+
+namespace
+{
+ const wchar_t JSON_KEY_PROPERTIES[] = L"properties";
+ const wchar_t JSON_KEY_WIN[] = L"win";
+ const wchar_t JSON_KEY_ALT[] = L"alt";
+ const wchar_t JSON_KEY_CTRL[] = L"ctrl";
+ const wchar_t JSON_KEY_SHIFT[] = L"shift";
+ const wchar_t JSON_KEY_CODE[] = L"code";
+ const wchar_t JSON_KEY_ACTIVATION_SHORTCUT[] = L"activation_shortcut";
+}
+
+// Implement the PowerToy Module Interface and all the required methods.
+class MouseJump : public PowertoyModuleIface
+{
+private:
+ // The PowerToy state.
+ bool m_enabled = false;
+
+ // Hotkey to invoke the module
+ Hotkey m_hotkey;
+ HANDLE m_hProcess;
+
+ void parse_hotkey(PowerToysSettings::PowerToyValues& settings)
+ {
+ auto settingsObject = settings.get_raw_json();
+ if (settingsObject.GetView().Size())
+ {
+ try
+ {
+ auto jsonHotkeyObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_ACTIVATION_SHORTCUT);
+ m_hotkey.win = jsonHotkeyObject.GetNamedBoolean(JSON_KEY_WIN);
+ m_hotkey.alt = jsonHotkeyObject.GetNamedBoolean(JSON_KEY_ALT);
+ m_hotkey.shift = jsonHotkeyObject.GetNamedBoolean(JSON_KEY_SHIFT);
+ m_hotkey.ctrl = jsonHotkeyObject.GetNamedBoolean(JSON_KEY_CTRL);
+ m_hotkey.key = static_cast(jsonHotkeyObject.GetNamedNumber(JSON_KEY_CODE));
+ }
+ catch (...)
+ {
+ Logger::error("Failed to initialize Mouse Jump start shortcut");
+ }
+ }
+ else
+ {
+ Logger::info("MouseJump settings are empty");
+ }
+
+ if (!m_hotkey.key)
+ {
+ Logger::info("MouseJump is going to use default shortcut");
+ m_hotkey.win = true;
+ m_hotkey.alt = false;
+ m_hotkey.shift = true;
+ m_hotkey.ctrl = false;
+ m_hotkey.key = 'D';
+ }
+ }
+
+ bool is_process_running()
+ {
+ return WaitForSingleObject(m_hProcess, 0) == WAIT_TIMEOUT;
+ }
+
+ void launch_process()
+ {
+ Logger::trace(L"Starting MouseJump process");
+ unsigned long powertoys_pid = GetCurrentProcessId();
+
+ std::wstring executable_args = L"";
+ executable_args.append(std::to_wstring(powertoys_pid));
+
+ SHELLEXECUTEINFOW sei{ sizeof(sei) };
+ sei.fMask = { SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI };
+ sei.lpFile = L"modules\\MouseUtils\\MouseJumpUI\\PowerToys.MouseJumpUI.exe";
+ sei.nShow = SW_SHOWNORMAL;
+ sei.lpParameters = executable_args.data();
+ if (ShellExecuteExW(&sei))
+ {
+ Logger::trace("Successfully started the Mouse Jump process");
+ }
+ else
+ {
+ Logger::error(L"Mouse Jump failed to start. {}", get_last_error_or_default(GetLastError()));
+ }
+
+ m_hProcess = sei.hProcess;
+ }
+
+ // Load initial settings from the persisted values.
+ void init_settings();
+
+ void terminate_process()
+ {
+ TerminateProcess(m_hProcess, 1);
+ }
+
+public:
+ // Constructor
+ MouseJump()
+ {
+ LoggerHelpers::init_logger(MODULE_NAME, L"ModuleInterface", LogSettings::mouseJumpLoggerName);
+ init_settings();
+ };
+
+ ~MouseJump()
+ {
+ if (m_enabled)
+ {
+ terminate_process();
+ }
+ m_enabled = false;
+ }
+
+ // Destroy the powertoy and free memory
+ virtual void destroy() override
+ {
+ delete this;
+ }
+
+ // Return the display name of the powertoy, this will be cached by the runner
+ virtual const wchar_t* get_name() override
+ {
+ return MODULE_NAME;
+ }
+
+ // Return the non localized key of the powertoy, this will be cached by the runner
+ virtual const wchar_t* get_key() override
+ {
+ return MODULE_NAME;
+ }
+
+ // Return the configured status for the gpo policy for the module
+ virtual powertoys_gpo::gpo_rule_configured_t gpo_policy_enabled_configuration() override
+ {
+ return powertoys_gpo::getConfiguredMouseJumpEnabledValue();
+ }
+
+ // Return JSON with the configuration options.
+ virtual bool get_config(wchar_t* buffer, int* buffer_size) override
+ {
+ HINSTANCE hinstance = reinterpret_cast(&__ImageBase);
+
+ // Create a Settings object.
+ PowerToysSettings::Settings settings(hinstance, get_name());
+ settings.set_description(MODULE_DESC);
+
+ return settings.serialize_to_buffer(buffer, buffer_size);
+ }
+
+ // Signal from the Settings editor to call a custom action.
+ // This can be used to spawn more complex editors.
+ virtual void call_custom_action(const wchar_t* action) override
+ {
+ }
+
+ // Called by the runner to pass the updated settings values as a serialized JSON.
+ virtual void set_config(const wchar_t* config) override
+ {
+ try
+ {
+ // Parse the input JSON string.
+ PowerToysSettings::PowerToyValues values =
+ PowerToysSettings::PowerToyValues::from_json_string(config, get_key());
+
+ parse_hotkey(values);
+
+ values.save_to_settings_file();
+ }
+ catch (std::exception&)
+ {
+ // Improper JSON.
+ }
+ }
+
+ // Enable the powertoy
+ virtual void enable()
+ {
+ m_enabled = true;
+ Trace::EnableJumpTool(true);
+ }
+
+ // Disable the powertoy
+ virtual void disable()
+ {
+ if (m_enabled)
+ {
+ terminate_process();
+ }
+
+ m_enabled = false;
+ Trace::EnableJumpTool(false);
+ }
+
+ // Returns if the powertoys is enabled
+ virtual bool is_enabled() override
+ {
+ return m_enabled;
+ }
+
+ virtual bool on_hotkey(size_t /*hotkeyId*/) override
+ {
+ if (m_enabled)
+ {
+ Logger::trace(L"MouseJump hotkey pressed");
+ Trace::InvokeJumpTool();
+ if (is_process_running())
+ {
+ terminate_process();
+ }
+ launch_process();
+
+ return true;
+ }
+
+ return false;
+ }
+
+ virtual size_t get_hotkeys(Hotkey* hotkeys, size_t buffer_size) override
+ {
+ if (m_hotkey.key)
+ {
+ if (hotkeys && buffer_size >= 1)
+ {
+ hotkeys[0] = m_hotkey;
+ }
+
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ // Returns whether the PowerToys should be enabled by default
+ virtual bool is_enabled_by_default() const override
+ {
+ return false;
+ }
+
+};
+
+// Load the settings file.
+void MouseJump::init_settings()
+{
+ try
+ {
+ // Load and parse the settings file for this PowerToy.
+ PowerToysSettings::PowerToyValues settings =
+ PowerToysSettings::PowerToyValues::load_from_settings_file(MouseJump::get_name());
+
+ parse_hotkey(settings);
+
+ }
+ catch (std::exception&)
+ {
+ Logger::warn(L"An exception occurred while loading the settings file");
+ // Error while loading from the settings file. Let default values stay as they are.
+ }
+}
+
+
+extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create()
+{
+ return new MouseJump();
+}
\ No newline at end of file
diff --git a/src/modules/MouseUtils/MouseJump/packages.config b/src/modules/MouseUtils/MouseJump/packages.config
new file mode 100644
index 00000000000..48319b8c957
--- /dev/null
+++ b/src/modules/MouseUtils/MouseJump/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/modules/MouseUtils/MouseJump/pch.cpp b/src/modules/MouseUtils/MouseJump/pch.cpp
new file mode 100644
index 00000000000..1d9f38c57d6
--- /dev/null
+++ b/src/modules/MouseUtils/MouseJump/pch.cpp
@@ -0,0 +1 @@
+#include "pch.h"
diff --git a/src/modules/MouseUtils/MouseJump/pch.h b/src/modules/MouseUtils/MouseJump/pch.h
new file mode 100644
index 00000000000..74abb62da1e
--- /dev/null
+++ b/src/modules/MouseUtils/MouseJump/pch.h
@@ -0,0 +1,10 @@
+#pragma once
+
+#define WIN32_LEAN_AND_MEAN
+#include
+#include
+
+//#include
+#include
+#include
+#include
diff --git a/src/modules/MouseUtils/MouseJump/resource.h b/src/modules/MouseUtils/MouseJump/resource.h
new file mode 100644
index 00000000000..67b823fd7f7
--- /dev/null
+++ b/src/modules/MouseUtils/MouseJump/resource.h
@@ -0,0 +1,13 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by MeasureTool.rc
+
+//////////////////////////////
+// Non-localizable
+
+#define FILE_DESCRIPTION "PowerToys MouseJump"
+#define INTERNAL_NAME "PowerToys.MouseJump"
+#define ORIGINAL_FILENAME "PowerToys.MouseJump.dll"
+
+// Non-localizable
+//////////////////////////////
diff --git a/src/modules/MouseUtils/MouseJump/trace.cpp b/src/modules/MouseUtils/MouseJump/trace.cpp
new file mode 100644
index 00000000000..9f5380284d6
--- /dev/null
+++ b/src/modules/MouseUtils/MouseJump/trace.cpp
@@ -0,0 +1,38 @@
+#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::EnableJumpTool(const bool enabled) noexcept
+{
+ TraceLoggingWrite(
+ g_hProvider,
+ "MouseJump_EnableJumpTool",
+ ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
+ TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
+ TraceLoggingBoolean(enabled, "Enabled"));
+}
+
+void Trace::InvokeJumpTool() noexcept
+{
+ TraceLoggingWrite(
+ g_hProvider,
+ "MouseJump_InvokeJumpTool",
+ ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
+ TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
+}
diff --git a/src/modules/MouseUtils/MouseJump/trace.h b/src/modules/MouseUtils/MouseJump/trace.h
new file mode 100644
index 00000000000..aaaa3362913
--- /dev/null
+++ b/src/modules/MouseUtils/MouseJump/trace.h
@@ -0,0 +1,12 @@
+#pragma once
+
+class Trace
+{
+public:
+ static void RegisterProvider();
+ static void UnregisterProvider();
+
+ static void EnableJumpTool(const bool enabled) noexcept;
+
+ static void InvokeJumpTool() noexcept;
+};
diff --git a/src/modules/MouseUtils/MouseJumpUI.UnitTests/Helpers/LayoutHelperTests.cs b/src/modules/MouseUtils/MouseJumpUI.UnitTests/Helpers/LayoutHelperTests.cs
new file mode 100644
index 00000000000..64db5b4491f
--- /dev/null
+++ b/src/modules/MouseUtils/MouseJumpUI.UnitTests/Helpers/LayoutHelperTests.cs
@@ -0,0 +1,514 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.Drawing;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace MouseJumpUI.Helpers.Tests;
+
+[TestClass]
+public static class LayoutHelperTests
+{
+ [TestClass]
+ public class CenterObjectTests
+ {
+ public class TestCase
+ {
+ public TestCase(Size obj, Point midpoint, Point expectedResult)
+ {
+ this.Obj = obj;
+ this.Midpoint = midpoint;
+ this.ExpectedResult = expectedResult;
+ }
+
+ public Size Obj { get; set; }
+
+ public Point Midpoint { get; set; }
+
+ public Point ExpectedResult { get; set; }
+ }
+
+ public static IEnumerable