mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-06-07 01:08:18 +08:00
[New Utility]Mouse Jump(#23566)
* #23216 - initial MouseJump commit * #23216 - Mouse Jump - fix spelling, removing Interop folder * #23216 - Mouse Jump - removed orphaned project guids from PowerToys.sln * #23216 - Mouse Jump - removed orphaned project guids from PowerToys.sln * #23216 - Mouse Jump - switch MS Logger to NLog for nuget package allow-listing * #23216 added MouseJumpUI.UnitTests.dll to "MS Tests" step in build-powertoys-steps.yml * [MouseJump] fixed screenshot coords (x & y were transposed) (#23216) * [MouseJump] close form rather than hide on deactivate (#23216) * [MouseJump] added UI dll for signing (#23216) * [MouseJump] close form rather than hide on deactivate (#23216) * [MouseJump] removed redundant line * [MouseJump] configure dpi awareness, add NLog.config (microsoft#23216) * [MouseJump] fix spellchecker errors (microsoft#23216) * [MouseJump] fixing comment style warning (microsoft#23216) * [MouseJump] simplified dpi config (microsoft#23216) * [MouseJump] fixed edge case issue with moving cursor (microsoft#23216) * [MouseJump] fixed typo (microsoft#23216) * [MouseJump] added attribution (microsoft#23216) * [Mouse Jump] fix attribution link and spelling (microsoft#23216) * Add MouseJump to installer * Fix centralized version control * Add Quick Access enable/disable entry * Fix analyzer error in GPO * Fix botched merge * Disabled by default and remove boilerplate code * Add GPO definitions * Add GPO implications when starting standalone * Update hotkey when it's changed in Settings * Use standard Logger * Add OOBE strings for Mouse Jump * Add telemetry * Update installer * Add signing * Add to bug report tool * Address PR feedback
This commit is contained in:
parent
a2e29c8c3a
commit
0524a4bddd
2
.github/actions/spell-check/expect.txt
vendored
2
.github/actions/spell-check/expect.txt
vendored
@ -216,6 +216,7 @@ cim
|
||||
CImage
|
||||
cla
|
||||
clangformat
|
||||
clayton
|
||||
CLASSDC
|
||||
CLASSNOTAVAILABLE
|
||||
clickable
|
||||
@ -536,6 +537,7 @@ EXTENDEDKEY
|
||||
EXTENDEDVERBS
|
||||
eyetracker
|
||||
fabricbot
|
||||
fancymouse
|
||||
fancyzones
|
||||
FANCYZONESDRAWLAYOUTTEST
|
||||
FANCYZONESEDITOR
|
||||
|
@ -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",
|
||||
|
@ -208,6 +208,7 @@ steps:
|
||||
**\UnitTests-SvgThumbnailProvider.dll
|
||||
**\UnitTests-SvgPreviewHandler.dll
|
||||
**\PowerToys.Hosts.Tests.dll
|
||||
**\MouseJumpUI.UnitTests.dll
|
||||
!**\obj\**
|
||||
!**\ref\**
|
||||
|
||||
|
@ -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}
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
<?include $(sys.CURRENTDIR)\Common.wxi?>
|
||||
|
||||
<?define MouseJumpUIComponentFiles=PowerToys.MouseJumpUI.deps.json;PowerToys.MouseJumpUI.dll;PowerToys.MouseJumpUI.exe;PowerToys.MouseJumpUI.runtimeconfig.json;WinRT.Runtime.dll;PowerToys.ManagedCommon.dll;PowerToys.GPOWrapper.dll;PowerToys.ManagedTelemetry.dll;Ijwhost.dll;System.Management.dll?>
|
||||
|
||||
<Fragment>
|
||||
<!-- MouseUtils -->
|
||||
<DirectoryRef Id="MouseUtilsInstallFolder" FileSource="$(var.BinDir)modules\$(var.MouseUtilsProjectName)">
|
||||
@ -16,12 +18,26 @@
|
||||
<Component Id="Module_MousePointerCrosshairs" Win64="yes">
|
||||
<File Source="$(var.BinDir)modules\$(var.MouseUtilsProjectName)\PowerToys.MousePointerCrosshairs.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="Module_MouseJump" Win64="yes">
|
||||
<File Source="$(var.BinDir)modules\$(var.MouseUtilsProjectName)\PowerToys.MouseJump.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
|
||||
<!-- MouseJump UI -->
|
||||
<?foreach File in $(var.MouseJumpUIComponentFiles)?>
|
||||
<Component Id="MouseJumpUIComp_$(var.File)" Win64="yes" Directory="MouseJumpUIFolder">
|
||||
<File Id="MouseJumpUIFile_$(var.File)" Source="$(var.BinDir)modules\$(var.MouseUtilsProjectName)\MouseJumpUI\$(var.File)" />
|
||||
</Component>
|
||||
<?endforeach?>
|
||||
|
||||
<ComponentGroup Id="MouseUtilsComponentGroup" Directory="INSTALLFOLDER">
|
||||
<ComponentRef Id="Module_FindMyMouse"/>
|
||||
<ComponentRef Id="Module_MouseHighlighter"/>
|
||||
<ComponentRef Id="Module_MousePointerCrosshairs" />
|
||||
<ComponentRef Id="Module_MouseJump" />
|
||||
<?foreach File in $(var.MouseJumpUIComponentFiles)?>
|
||||
<ComponentRef Id="MouseJumpUIComp_$(var.File)" />
|
||||
<?endforeach?>
|
||||
</ComponentGroup>
|
||||
|
||||
</Fragment>
|
||||
|
@ -477,6 +477,7 @@
|
||||
|
||||
<!-- Mouse Utils -->
|
||||
<Directory Id="MouseUtilsInstallFolder" Name="$(var.MouseUtilsProjectName)">
|
||||
<Directory Id="MouseJumpUIFolder" Name="MouseJumpUI" />
|
||||
</Directory>
|
||||
|
||||
<!-- PastePlain -->
|
||||
|
@ -7,7 +7,7 @@
|
||||
<?define SettingsV2Files=WinUIEx.dll;backup_restore_settings.json;Ijwhost.dll;ColorCode.Core.dll;ColorCode.WinUI.dll;CommunityToolkit.Common.dll;CommunityToolkit.Labs.WinUI.SettingsControls.dll;CommunityToolkit.WinUI.dll;CommunityToolkit.WinUI.UI.Controls.Core.dll;CommunityToolkit.WinUI.UI.Controls.DataGrid.dll;CommunityToolkit.WinUI.UI.Controls.Input.dll;CommunityToolkit.WinUI.UI.Controls.Layout.dll;CommunityToolkit.WinUI.UI.Controls.Markdown.dll;CommunityToolkit.WinUI.UI.Controls.Media.dll;CommunityToolkit.WinUI.UI.Controls.Primitives.dll;CommunityToolkit.WinUI.UI.dll;icon.ico;Microsoft.Graphics.Canvas.Interop.dll;Microsoft.InteractiveExperiences.Projection.dll;Microsoft.Windows.ApplicationModel.DynamicDependency.Projection.dll;Microsoft.Windows.ApplicationModel.Resources.Projection.dll;Microsoft.Windows.ApplicationModel.WindowsAppRuntime.Projection.dll;Microsoft.Windows.AppLifecycle.Projection.dll;Microsoft.Windows.SDK.NET.dll;Microsoft.Windows.System.Power.Projection.dll;Microsoft.WindowsAppRuntime.Bootstrap.Net.dll;Microsoft.WinUI.dll;Microsoft.Xaml.Interactions.dll;Microsoft.Xaml.Interactivity.dll;PowerToys.ManagedCommon.dll;PowerToys.ManagedTelemetry.dll;PowerToys.Settings.deps.json;PowerToys.Settings.dll;PowerToys.Settings.exe;PowerToys.Settings.runtimeconfig.json;PowerToys.Settings.UI.Lib.dll;resources.pri;System.CodeDom.dll;System.IO.Abstractions.dll;WinRT.Runtime.dll;Microsoft.Graphics.Canvas.dll;System.Management.dll;PowerToys.GPOWrapper.dll;System.Text.Json.dll;WindowsBase.dll;PowerToys.AllExperiments.dll?>
|
||||
<?define SettingsV2AssetsModulesFiles=ColorPicker.png;FancyZones.png;FileLocksmith.png;AlwaysOnTop.png;HostsFileEditor.png;Awake.png;ImageResizer.png;KBM.png;MouseUtils.png;PastePlain.png;PowerAccent.png;PowerOCR.png;PowerLauncher.png;PowerPreview.png;PowerRename.png;PT.png;ScreenRuler.png;ShortcutGuide.png;VideoConference.png?>
|
||||
<?define SettingsV2OOBEAssetsModulesFiles=ColorPicker.gif;AlwaysOnTop.png;HostsFileEditor.png;Awake.png;FancyZones.gif;FileExplorer.png;FileLocksmith.gif;ImageResizer.gif;KBM.gif;MouseUtils.gif;PastePlain.gif;PowerAccent.gif;PowerOCR.gif;PowerRename.gif;Run.gif;ScreenRuler.gif;OOBEShortcutGuide.png;VideoConferenceMute.png;OOBEPTHero.png;OOBEPTHeroShort.png?>
|
||||
<?define SettingsV2OOBEAssetsFluentIconsFiles=ColorPicker.png;Experimentation.png;FancyZones.png;FileLocksmith.png;AlwaysOnTop.png;Awake.png;FileExplorerPreview.png;FindMyMouse.png;Hosts.png;ImageResizer.png;KeyboardManager.png;MouseHighlighter.png;MouseCrosshairs.png;MouseUtils.png;PastePlain.png;PowerAccent.png;PowerOcr.png;PowerRename.png;PowerToys.png;PowerToysRun.png;ScreenRuler.png;Settings.png;ShortcutGuide.png;VideoConferenceMute.png?>
|
||||
<?define SettingsV2OOBEAssetsFluentIconsFiles=ColorPicker.png;Experimentation.png;FancyZones.png;FileLocksmith.png;AlwaysOnTop.png;Awake.png;FileExplorerPreview.png;FindMyMouse.png;Hosts.png;ImageResizer.png;KeyboardManager.png;MouseHighlighter.png;MouseJump.png;MouseCrosshairs.png;MouseUtils.png;PastePlain.png;PowerAccent.png;PowerOcr.png;PowerRename.png;PowerToys.png;PowerToysRun.png;ScreenRuler.png;Settings.png;ShortcutGuide.png;VideoConferenceMute.png?>
|
||||
<?define SettingsV2MicrosoftUIXamlAssetsInstallFiles=NoiseAsset_256x256_PNG.png?>
|
||||
|
||||
<!-- These files are needed for release builds to contain the experimentation DLLs -->
|
||||
|
@ -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<std::wstring_view, 9> processesToTerminate = {
|
||||
std::array<std::wstring_view, 10> 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"
|
||||
|
@ -80,6 +80,10 @@ namespace winrt::PowerToys::GPOWrapper::implementation
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredMouseHighlighterEnabledValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredMouseJumpEnabledValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredMouseJumpEnabledValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredMousePointerCrosshairsEnabledValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredMousePointerCrosshairsEnabledValue());
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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";
|
||||
|
@ -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);
|
||||
|
@ -217,6 +217,16 @@
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="ConfigureEnabledUtilityMouseJump" class="Both" displayName="$(string.ConfigureEnabledUtilityMouseJump)" explainText="$(string.ConfigureEnabledUtilityDescription)" key="Software\Policies\PowerToys" valueName="ConfigureEnabledUtilityMouseJump">
|
||||
<parentCategory ref="PowerToys" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_68_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="ConfigureEnabledUtilityPastePlain" class="Both" displayName="$(string.ConfigureEnabledUtilityPastePlain)" explainText="$(string.ConfigureEnabledUtilityDescription)" key="Software\Policies\PowerToys" valueName="ConfigureEnabledUtilityPastePlain">
|
||||
<parentCategory ref="PowerToys" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_68_0" />
|
||||
|
@ -54,6 +54,7 @@ If this setting is disabled, experimentation is not allowed.
|
||||
<string id="ConfigureEnabledUtilityKeyboardManager">Keyboard Manager: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityFindMyMouse">Find My Mouse: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityMouseHighlighter">Mouse Highlighter: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityMouseJump">Mouse Jump: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityMousePointerCrosshairs">Mouse Pointer Crosshairs: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityPastePlain">Paste as Plain Text: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityPowerRename">Power Rename: Configure enabled state</string>
|
||||
|
40
src/modules/MouseUtils/MouseJump/MouseJump.rc
Normal file
40
src/modules/MouseUtils/MouseJump/MouseJump.rc
Normal file
@ -0,0 +1,40 @@
|
||||
#include <windows.h>
|
||||
#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
|
129
src/modules/MouseUtils/MouseJump/MouseJump.vcxproj
Normal file
129
src/modules/MouseUtils/MouseJump/MouseJump.vcxproj
Normal file
@ -0,0 +1,129 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220929.3\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220929.3\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{8a08d663-4995-40e3-b42c-3f910625f284}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>MouseJumpModuleInterface</RootNamespace>
|
||||
<ProjectName>MouseJump</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\MouseUtils\</OutDir>
|
||||
<TargetName>PowerToys.MouseJump</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)src\;$(SolutionDir)src\modules;$(SolutionDir)src\common\Telemetry;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(CIBuild)'!='true'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="trace.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader Condition="'$(CIBuild)'!='true'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="trace.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\common\logger\logger.vcxproj">
|
||||
<Project>{d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\common\SettingsAPI\SettingsAPI.vcxproj">
|
||||
<Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="MouseJump.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<Import Project="..\..\..\..\deps\spdlog.props" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220929.3\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220929.3\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>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}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220929.3\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220929.3\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220929.3\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220929.3\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
302
src/modules/MouseUtils/MouseJump/dllmain.cpp
Normal file
302
src/modules/MouseUtils/MouseJump/dllmain.cpp
Normal file
@ -0,0 +1,302 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include <interface/powertoy_module_interface.h>
|
||||
//#include <interface/lowlevel_keyboard_event_data.h>
|
||||
//#include <interface/win_hook_event_data.h>
|
||||
#include <common/SettingsAPI/settings_objects.h>
|
||||
#include "trace.h"
|
||||
#include <common/utils/winapi_error.h>
|
||||
#include <common/utils/logger_helper.h>
|
||||
|
||||
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<unsigned char>(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<HINSTANCE>(&__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();
|
||||
}
|
4
src/modules/MouseUtils/MouseJump/packages.config
Normal file
4
src/modules/MouseUtils/MouseJump/packages.config
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.220929.3" targetFramework="native" />
|
||||
</packages>
|
1
src/modules/MouseUtils/MouseJump/pch.cpp
Normal file
1
src/modules/MouseUtils/MouseJump/pch.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include "pch.h"
|
10
src/modules/MouseUtils/MouseJump/pch.h
Normal file
10
src/modules/MouseUtils/MouseJump/pch.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
//#include <common/common.h>
|
||||
#include <ProjectTelemetry.h>
|
||||
#include <common/SettingsAPI/settings_helpers.h>
|
||||
#include <common/logger/logger.h>
|
13
src/modules/MouseUtils/MouseJump/resource.h
Normal file
13
src/modules/MouseUtils/MouseJump/resource.h
Normal file
@ -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
|
||||
//////////////////////////////
|
38
src/modules/MouseUtils/MouseJump/trace.cpp
Normal file
38
src/modules/MouseUtils/MouseJump/trace.cpp
Normal file
@ -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));
|
||||
}
|
12
src/modules/MouseUtils/MouseJump/trace.h
Normal file
12
src/modules/MouseUtils/MouseJump/trace.h
Normal file
@ -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;
|
||||
};
|
@ -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<object[]> GetTestCases()
|
||||
{
|
||||
// zero-sized object should center exactly on the midpoint
|
||||
yield return new[] { new TestCase(new(0, 0), new(0, 0), new(0, 0)), };
|
||||
|
||||
// odd-sized objects should center above/left of the midpoint
|
||||
yield return new[] { new TestCase(new(1, 1), new(1, 1), new(0, 0)), };
|
||||
yield return new[] { new TestCase(new(1, 1), new(5, 5), new(4, 4)), };
|
||||
|
||||
// even-sized objects should center exactly on the midpoint
|
||||
yield return new[] { new TestCase(new(2, 2), new(1, 1), new(0, 0)), };
|
||||
yield return new[] { new TestCase(new(2, 2), new(5, 5), new(4, 4)), };
|
||||
yield return new[] { new TestCase(new(800, 600), new(1000, 1000), new(600, 700)), };
|
||||
|
||||
// negative result position
|
||||
yield return new[] { new TestCase(new(1000, 1200), new(300, 300), new(-200, -300)), };
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[DynamicData(nameof(GetTestCases), DynamicDataSourceType.Method)]
|
||||
public void RunTestCases(TestCase data)
|
||||
{
|
||||
var actual = LayoutHelper.CenterObject(data.Obj, data.Midpoint);
|
||||
var expected = data.ExpectedResult;
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
public class CombineRegionsTests
|
||||
{
|
||||
public class TestCase
|
||||
{
|
||||
public TestCase(List<Rectangle> bounds, Rectangle expectedResult)
|
||||
{
|
||||
this.Bounds = bounds;
|
||||
this.ExpectedResult = expectedResult;
|
||||
}
|
||||
|
||||
public List<Rectangle> Bounds { get; set; }
|
||||
|
||||
public Rectangle ExpectedResult { get; set; }
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> GetTestCases()
|
||||
{
|
||||
// empty list
|
||||
yield return new[]
|
||||
{
|
||||
new TestCase(
|
||||
new(),
|
||||
Rectangle.Empty),
|
||||
};
|
||||
|
||||
// empty bounds
|
||||
yield return new[]
|
||||
{
|
||||
new TestCase(
|
||||
new()
|
||||
{
|
||||
Rectangle.Empty,
|
||||
},
|
||||
Rectangle.Empty),
|
||||
};
|
||||
|
||||
// single region
|
||||
//
|
||||
// +---+
|
||||
// | 0 |
|
||||
// +---+
|
||||
yield return new[]
|
||||
{
|
||||
new TestCase(
|
||||
new()
|
||||
{
|
||||
new(100, 100, 100, 100),
|
||||
},
|
||||
new(100, 100, 100, 100)),
|
||||
};
|
||||
|
||||
// multi-monitor desktop
|
||||
//
|
||||
// +----------------+
|
||||
// | |
|
||||
// | 1 +-------+
|
||||
// | | 0 |
|
||||
// +----------------+-------+
|
||||
yield return new[]
|
||||
{
|
||||
new TestCase(
|
||||
new()
|
||||
{
|
||||
new(5120, 0, 1920, 1080),
|
||||
new(0, 0, 5120, 1440),
|
||||
},
|
||||
new(0, 0, 7040, 1440)),
|
||||
};
|
||||
|
||||
// multi-monitor desktop
|
||||
//
|
||||
// note - windows puts the *primary* monitor at the origin (0,0),
|
||||
// so screens positioned *above* or *left* will have negative coordinates
|
||||
//
|
||||
// +-------+
|
||||
// | 0 |
|
||||
// +-------+--------+
|
||||
// | |
|
||||
// | 1 |
|
||||
// | |
|
||||
// +----------------+
|
||||
yield return new[]
|
||||
{
|
||||
new TestCase(
|
||||
new()
|
||||
{
|
||||
new(0, -1000, 1920, 1080),
|
||||
new(0, 0, 5120, 1440),
|
||||
},
|
||||
new(0, -1000, 5120, 2440)),
|
||||
};
|
||||
|
||||
// multi-monitor desktop
|
||||
//
|
||||
// note - windows puts the *primary* monitor at the origin (0,0),
|
||||
// so screens positioned *above* or *left* will have negative coordinates
|
||||
//
|
||||
// +-------+----------------+
|
||||
// | 0 | |
|
||||
// +-------+ 1 |
|
||||
// | |
|
||||
// +----------------+
|
||||
yield return new[]
|
||||
{
|
||||
new TestCase(
|
||||
new()
|
||||
{
|
||||
new(-1920, 0, 1920, 1080),
|
||||
new(0, 0, 5120, 1440),
|
||||
},
|
||||
new(-1920, 0, 7040, 1440)),
|
||||
};
|
||||
|
||||
// non-contiguous regions
|
||||
//
|
||||
// +---+
|
||||
// | 0 | +-------+
|
||||
// +---+ | |
|
||||
// | 1 |
|
||||
// | |
|
||||
// +-------+
|
||||
yield return new[]
|
||||
{
|
||||
new TestCase(
|
||||
new()
|
||||
{
|
||||
new(0, 0, 100, 100),
|
||||
new(200, 150, 200, 200),
|
||||
},
|
||||
new(0, 0, 400, 350)),
|
||||
};
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[DynamicData(nameof(GetTestCases), DynamicDataSourceType.Method)]
|
||||
public void RunTestCases(TestCase data)
|
||||
{
|
||||
var actual = LayoutHelper.CombineRegions(data.Bounds);
|
||||
var expected = data.ExpectedResult;
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
public class GetMidpointTests
|
||||
{
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
public class MoveInsideTests
|
||||
{
|
||||
public class TestCase
|
||||
{
|
||||
public TestCase(Rectangle obj, Rectangle bounds, Rectangle expectedResult)
|
||||
{
|
||||
this.Obj = obj;
|
||||
this.Bounds = bounds;
|
||||
this.ExpectedResult = expectedResult;
|
||||
}
|
||||
|
||||
public Rectangle Obj { get; set; }
|
||||
|
||||
public Rectangle Bounds { get; set; }
|
||||
|
||||
public Rectangle ExpectedResult { get; set; }
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> GetTestCases()
|
||||
{
|
||||
// already inside - obj fills bounds exactly
|
||||
yield return new[]
|
||||
{
|
||||
new TestCase(new(0, 0, 100, 100), new(0, 0, 100, 100), new(0, 0, 100, 100)),
|
||||
};
|
||||
|
||||
// already inside - obj exactly in each corner
|
||||
yield return new[]
|
||||
{
|
||||
new TestCase(new(0, 0, 100, 100), new(0, 0, 200, 200), new(0, 0, 100, 100)),
|
||||
};
|
||||
yield return new[]
|
||||
{
|
||||
new TestCase(new(100, 0, 100, 100), new(0, 0, 200, 200), new(100, 0, 100, 100)),
|
||||
};
|
||||
yield return new[]
|
||||
{
|
||||
new TestCase(new(0, 100, 100, 100), new(0, 0, 200, 200), new(0, 100, 100, 100)),
|
||||
};
|
||||
yield return new[]
|
||||
{
|
||||
new TestCase(new(100, 100, 100, 100), new(0, 0, 200, 200), new(100, 100, 100, 100)),
|
||||
};
|
||||
|
||||
// move inside - obj outside each corner
|
||||
yield return new[]
|
||||
{
|
||||
new TestCase(new(-50, -50, 100, 100), new(0, 0, 200, 200), new(0, 0, 100, 100)),
|
||||
};
|
||||
yield return new[]
|
||||
{
|
||||
new TestCase(new(250, -50, 100, 100), new(0, 0, 200, 200), new(100, 0, 100, 100)),
|
||||
};
|
||||
yield return new[]
|
||||
{
|
||||
new TestCase(new(-50, 250, 100, 100), new(0, 0, 200, 200), new(0, 100, 100, 100)),
|
||||
};
|
||||
yield return new[]
|
||||
{
|
||||
new TestCase(new(150, 150, 100, 100), new(0, 0, 200, 200), new(100, 100, 100, 100)),
|
||||
};
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[DynamicData(nameof(GetTestCases), DynamicDataSourceType.Method)]
|
||||
public void RunTestCases(TestCase data)
|
||||
{
|
||||
var actual = LayoutHelper.MoveInside(data.Obj, data.Bounds);
|
||||
var expected = data.ExpectedResult;
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
public class ScaleLocationTests
|
||||
{
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
public class ScaleToFitTests
|
||||
{
|
||||
public class TestCase
|
||||
{
|
||||
public TestCase(Size obj, Size bounds, Size expectedResult)
|
||||
{
|
||||
this.Obj = obj;
|
||||
this.Bounds = bounds;
|
||||
this.ExpectedResult = expectedResult;
|
||||
}
|
||||
|
||||
public Size Obj { get; set; }
|
||||
|
||||
public Size Bounds { get; set; }
|
||||
|
||||
public Size ExpectedResult { get; set; }
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> GetTestCases()
|
||||
{
|
||||
// identity tests
|
||||
yield return new[]
|
||||
{
|
||||
new TestCase(new(0, 0), new(0, 0), new(0, 0)),
|
||||
};
|
||||
yield return new[]
|
||||
{
|
||||
new TestCase(new(512, 384), new(512, 384), new(512, 384)),
|
||||
};
|
||||
yield return new[]
|
||||
{
|
||||
new TestCase(new(1024, 768), new(1024, 768), new(1024, 768)),
|
||||
};
|
||||
|
||||
// integer scaling factor tests
|
||||
yield return new[]
|
||||
{
|
||||
new TestCase(new(512, 384), new(2048, 1536), new(2048, 1536)),
|
||||
};
|
||||
yield return new[]
|
||||
{
|
||||
new TestCase(new(2048, 1536), new(1024, 768), new(1024, 768)),
|
||||
};
|
||||
|
||||
// scale to fit width
|
||||
yield return new[]
|
||||
{
|
||||
new TestCase(new(512, 384), new(2048, 3072), new(2048, 1536)),
|
||||
};
|
||||
|
||||
// scale to fit height
|
||||
yield return new[]
|
||||
{
|
||||
new TestCase(new(512, 384), new(4096, 1536), new(2048, 1536)),
|
||||
};
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[DynamicData(nameof(GetTestCases), DynamicDataSourceType.Method)]
|
||||
public void RunTestCases(TestCase data)
|
||||
{
|
||||
var actual = LayoutHelper.ScaleToFit(data.Obj, data.Bounds);
|
||||
var expected = data.ExpectedResult;
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
}
|
||||
|
||||
[TestClass]
|
||||
public class GetPreviewFormBoundsTests
|
||||
{
|
||||
public class TestCase
|
||||
{
|
||||
public TestCase(
|
||||
Rectangle desktopBounds,
|
||||
Point cursorPosition,
|
||||
Rectangle currentMonitorBounds,
|
||||
Size maximumPreviewImageSize,
|
||||
Size previewImagePadding,
|
||||
Rectangle expectedResult)
|
||||
{
|
||||
this.DesktopBounds = desktopBounds;
|
||||
this.CursorPosition = cursorPosition;
|
||||
this.CurrentMonitorBounds = currentMonitorBounds;
|
||||
this.MaximumPreviewImageSize = maximumPreviewImageSize;
|
||||
this.PreviewImagePadding = previewImagePadding;
|
||||
this.ExpectedResult = expectedResult;
|
||||
}
|
||||
|
||||
public Rectangle DesktopBounds { get; set; }
|
||||
|
||||
public Point CursorPosition { get; set; }
|
||||
|
||||
public Rectangle CurrentMonitorBounds { get; set; }
|
||||
|
||||
public Size MaximumPreviewImageSize { get; set; }
|
||||
|
||||
public Size PreviewImagePadding { get; set; }
|
||||
|
||||
public Rectangle ExpectedResult { get; set; }
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> GetTestCases()
|
||||
{
|
||||
// multi-monitor desktop
|
||||
//
|
||||
// +----------------+
|
||||
// | |
|
||||
// | 1 +-------+
|
||||
// | | 0 |
|
||||
// +----------------+-------+
|
||||
//
|
||||
// clicked near top left corner so that the
|
||||
// preview box overhangs the top and left
|
||||
//
|
||||
// +----------------+
|
||||
// | * |
|
||||
// | 1 +-------+
|
||||
// | | 0 |
|
||||
// +----------------+-------+
|
||||
//
|
||||
// form is centered on mouse cursor and then
|
||||
// nudged back into the top left corner
|
||||
//
|
||||
// +-----+----------+
|
||||
// | * | |
|
||||
// +-----+ 1 +-------+
|
||||
// | | 0 |
|
||||
// +----------------+-------+
|
||||
yield return new[]
|
||||
{
|
||||
new TestCase(
|
||||
desktopBounds: new(-5120, -359, 7040, 1440),
|
||||
cursorPosition: new(-5020, -259),
|
||||
currentMonitorBounds: new(-5120, -359, 5120, 1440),
|
||||
maximumPreviewImageSize: new(1600, 1200),
|
||||
previewImagePadding: new(10, 10),
|
||||
expectedResult: new(-5120, -359, 1610, 337)),
|
||||
};
|
||||
|
||||
// multi-monitor desktop
|
||||
//
|
||||
// +----------------+
|
||||
// | |
|
||||
// | 1 +-------+
|
||||
// | | 0 |
|
||||
// +----------------+-------+
|
||||
//
|
||||
// clicked in the center of the second monitor
|
||||
//
|
||||
// +----------------+
|
||||
// | |
|
||||
// | * +-------+
|
||||
// | | 0 |
|
||||
// +----------------+-------+
|
||||
//
|
||||
// form is centered on the mouse cursor
|
||||
//
|
||||
// +----------------+
|
||||
// | +-----+ |
|
||||
// | | * | +-------+
|
||||
// | +-----+ | 0 |
|
||||
// +----------------+-------+
|
||||
yield return new[]
|
||||
{
|
||||
new TestCase(
|
||||
desktopBounds: new(-5120, -359, 7040, 1440),
|
||||
cursorPosition: new(-2560, 361),
|
||||
currentMonitorBounds: new(-5120, -359, 5120, 1440),
|
||||
maximumPreviewImageSize: new(1600, 1200),
|
||||
previewImagePadding: new(10, 10),
|
||||
expectedResult: new(-3365, 192, 1610, 337)),
|
||||
};
|
||||
|
||||
// multi-monitor desktop
|
||||
//
|
||||
// +----------------+
|
||||
// | |
|
||||
// | 1 +-------+
|
||||
// | | 0 |
|
||||
// +----------------+-------+
|
||||
//
|
||||
// clicked in the center of the monitor
|
||||
//
|
||||
// +----------------+
|
||||
// | |
|
||||
// | * +-------+
|
||||
// | | 0 |
|
||||
// +----------------+-------+
|
||||
//
|
||||
// max preview is larger than monitor,
|
||||
// form is scaled to monitor size, with
|
||||
// consideration for image padding
|
||||
//
|
||||
// *----------------*
|
||||
// |+--------------+|
|
||||
// || * |+-------+
|
||||
// |+--------------+| 0 |
|
||||
// +----------------+-------+
|
||||
yield return new[]
|
||||
{
|
||||
new TestCase(
|
||||
desktopBounds: new(-5120, -359, 7040, 1440),
|
||||
cursorPosition: new(-2560, 361),
|
||||
currentMonitorBounds: new(-5120, -359, 5120, 1440),
|
||||
maximumPreviewImageSize: new(160000, 120000),
|
||||
previewImagePadding: new(10, 10),
|
||||
expectedResult: new(-5120, -166, 5120, 1055)),
|
||||
};
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[DynamicData(nameof(GetTestCases), DynamicDataSourceType.Method)]
|
||||
public void RunTestCases(TestCase data)
|
||||
{
|
||||
var actual = LayoutHelper.GetPreviewFormBounds(
|
||||
desktopBounds: data.DesktopBounds,
|
||||
activatedPosition: data.CursorPosition,
|
||||
activatedMonitorBounds: data.CurrentMonitorBounds,
|
||||
maximumThumbnailImageSize: data.MaximumPreviewImageSize,
|
||||
thumbnailImagePadding: data.PreviewImagePadding);
|
||||
var expected = data.ExpectedResult;
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\..\Version.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0-windows10.0.19041.0</TargetFramework>
|
||||
<ProjectGuid>{D9C5DE64-6849-4278-91AD-9660AECF2876}</ProjectGuid>
|
||||
<RootNamespace>Microsoft.MouseJumpUI.UnitTests</RootNamespace>
|
||||
<IsPackable>false</IsPackable>
|
||||
<Nullable>enable</Nullable>
|
||||
<OutputType>Library</OutputType>
|
||||
<Version>$(Version).0</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputPath>..\..\..\..\$(Platform)\$(Configuration)\modules\MouseUtils\MouseJumpUI.UnitTests\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Windows.CsWinRT" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||
<PackageReference Include="MSTest.TestAdapter" />
|
||||
<PackageReference Include="MSTest.TestFramework" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MouseJumpUI\MouseJumpUI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
191
src/modules/MouseUtils/MouseJumpUI/Helpers/LayoutHelper.cs
Normal file
191
src/modules/MouseUtils/MouseJumpUI/Helpers/LayoutHelper.cs
Normal file
@ -0,0 +1,191 @@
|
||||
// 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;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
|
||||
namespace MouseJumpUI.Helpers;
|
||||
|
||||
internal static class LayoutHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Center an object on the given origin.
|
||||
/// </summary>
|
||||
public static Point CenterObject(Size obj, Point origin)
|
||||
{
|
||||
return new Point(
|
||||
x: (int)(origin.X - ((float)obj.Width / 2)),
|
||||
y: (int)(origin.Y - ((float)obj.Height / 2)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Combines the specified regions and returns the smallest rectangle that contains them.
|
||||
/// </summary>
|
||||
/// <param name="regions">The regions to combine.</param>
|
||||
/// <returns>
|
||||
/// Returns the smallest rectangle that contains all the specified regions.
|
||||
/// </returns>
|
||||
public static Rectangle CombineRegions(List<Rectangle> regions)
|
||||
{
|
||||
if (regions == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(regions));
|
||||
}
|
||||
|
||||
if (regions.Count == 0)
|
||||
{
|
||||
return Rectangle.Empty;
|
||||
}
|
||||
|
||||
var combined = regions.Aggregate(
|
||||
seed: regions[0],
|
||||
func: Rectangle.Union);
|
||||
return combined;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the midpoint of the given region.
|
||||
/// </summary>
|
||||
public static Point GetMidpoint(Rectangle region)
|
||||
{
|
||||
return new Point(
|
||||
(region.Left + region.Right) / 2,
|
||||
(region.Top + region.Bottom) / 2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the largest Size object that can fit inside
|
||||
/// all of the given sizes. (Equivalent to a Size
|
||||
/// object with the smallest Width and smallest Height from
|
||||
/// all of the specified sizes).
|
||||
/// </summary>
|
||||
public static Size IntersectSizes(params Size[] sizes)
|
||||
{
|
||||
return new Size(
|
||||
sizes.Min(s => s.Width),
|
||||
sizes.Min(s => s.Height));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the location to move the inner rectangle so that it sits entirely inside
|
||||
/// the outer rectangle. Returns the inner rectangle's current position if it is
|
||||
/// already inside the outer rectangle.
|
||||
/// </summary>
|
||||
public static Rectangle MoveInside(Rectangle inner, Rectangle outer)
|
||||
{
|
||||
if ((inner.Width > outer.Width) || (inner.Height > outer.Height))
|
||||
{
|
||||
throw new ArgumentException($"{nameof(inner)} cannot be larger than {nameof(outer)}.");
|
||||
}
|
||||
|
||||
return inner with
|
||||
{
|
||||
X = Math.Clamp(inner.X, outer.X, outer.Right - inner.Width),
|
||||
Y = Math.Clamp(inner.Y, outer.Y, outer.Bottom - inner.Height),
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scales a location within a reference region onto a new region
|
||||
/// so that it's proportionally in the same position in the new region.
|
||||
/// </summary>
|
||||
public static Point ScaleLocation(Rectangle originalBounds, Point originalLocation, Rectangle scaledBounds)
|
||||
{
|
||||
return new Point(
|
||||
(int)(originalLocation.X / (double)originalBounds.Width * scaledBounds.Width) + scaledBounds.Left,
|
||||
(int)(originalLocation.Y / (double)originalBounds.Height * scaledBounds.Height) + scaledBounds.Top);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scale an object to fit inside the specified bounds while maintaining aspect ratio.
|
||||
/// </summary>
|
||||
public static Size ScaleToFit(Size obj, Size bounds)
|
||||
{
|
||||
if (bounds.Width == 0 || bounds.Height == 0)
|
||||
{
|
||||
return Size.Empty;
|
||||
}
|
||||
|
||||
var widthRatio = (double)obj.Width / bounds.Width;
|
||||
var heightRatio = (double)obj.Height / bounds.Height;
|
||||
var scaledSize = (widthRatio > heightRatio)
|
||||
? bounds with
|
||||
{
|
||||
Height = (int)(obj.Height / widthRatio),
|
||||
}
|
||||
: bounds with
|
||||
{
|
||||
Width = (int)(obj.Width / heightRatio),
|
||||
};
|
||||
return scaledSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the position to show the preview form based on a number of factors.
|
||||
/// </summary>
|
||||
/// <param name="desktopBounds">
|
||||
/// The bounds of the entire desktop / virtual screen. Might start at a negative
|
||||
/// x, y if a non-primary screen is located left of or above the primary screen.
|
||||
/// </param>
|
||||
/// <param name="activatedPosition">
|
||||
/// The current position of the cursor on the virtual desktop.
|
||||
/// </param>
|
||||
/// <param name="activatedMonitorBounds">
|
||||
/// The bounds of the screen the cursor is currently on. Might start at a negative
|
||||
/// x, y if a non-primary screen is located left of or above the primary screen.
|
||||
/// </param>
|
||||
/// <param name="maximumThumbnailImageSize">
|
||||
/// The largest allowable size of the preview image. This is literally the just
|
||||
/// image itself, not including padding around the image.
|
||||
/// </param>
|
||||
/// <param name="thumbnailImagePadding">
|
||||
/// The total width and height of padding around the preview image.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The size and location to use when showing the preview image form.
|
||||
/// </returns>
|
||||
public static Rectangle GetPreviewFormBounds(
|
||||
Rectangle desktopBounds,
|
||||
Point activatedPosition,
|
||||
Rectangle activatedMonitorBounds,
|
||||
Size maximumThumbnailImageSize,
|
||||
Size thumbnailImagePadding)
|
||||
{
|
||||
// see https://learn.microsoft.com/en-gb/windows/win32/gdi/the-virtual-screen
|
||||
// calculate the maximum size the form is allowed to be
|
||||
var maxFormSize = LayoutHelper.IntersectSizes(
|
||||
new[]
|
||||
{
|
||||
// can't be bigger than the current screen
|
||||
activatedMonitorBounds.Size,
|
||||
|
||||
// can't be bigger than the max preview image
|
||||
// *plus* the padding around the preview image
|
||||
// (max thumbnail image size doesn't include the padding)
|
||||
maximumThumbnailImageSize + thumbnailImagePadding,
|
||||
});
|
||||
|
||||
// calculate the actual form size by scaling the entire
|
||||
// desktop bounds into the max thumbnail size while accounting
|
||||
// for the size of the padding around the preview
|
||||
var thumbnailImageSize = LayoutHelper.ScaleToFit(
|
||||
obj: desktopBounds.Size,
|
||||
bounds: maxFormSize - thumbnailImagePadding);
|
||||
var formSize = thumbnailImageSize + thumbnailImagePadding;
|
||||
|
||||
// center the form to the activated position, but nudge it back
|
||||
// inside the visible area of the screen if it falls outside
|
||||
var formBounds = LayoutHelper.MoveInside(
|
||||
inner: new Rectangle(
|
||||
LayoutHelper.CenterObject(
|
||||
obj: formSize,
|
||||
origin: activatedPosition),
|
||||
formSize),
|
||||
outer: activatedMonitorBounds);
|
||||
|
||||
return formBounds;
|
||||
}
|
||||
}
|
77
src/modules/MouseUtils/MouseJumpUI/Helpers/Logger.cs
Normal file
77
src/modules/MouseUtils/MouseJumpUI/Helpers/Logger.cs
Normal file
@ -0,0 +1,77 @@
|
||||
// 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;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
|
||||
namespace MouseJumpUI.Helpers
|
||||
{
|
||||
// TODO: use centralized logger https://github.com/microsoft/PowerToys/issues/19650
|
||||
public static class Logger
|
||||
{
|
||||
private static readonly string ApplicationLogPath = Path.Combine(interop.Constants.AppDataPath(), "MouseJump\\Logs");
|
||||
|
||||
static Logger()
|
||||
{
|
||||
if (!Directory.Exists(ApplicationLogPath))
|
||||
{
|
||||
Directory.CreateDirectory(ApplicationLogPath);
|
||||
}
|
||||
|
||||
// Using InvariantCulture since this is used for a log file name
|
||||
var logFilePath = Path.Combine(ApplicationLogPath, "Log_" + DateTime.Now.ToString(@"yyyy-MM-dd", CultureInfo.InvariantCulture) + ".txt");
|
||||
|
||||
Trace.Listeners.Add(new TextWriterTraceListener(logFilePath));
|
||||
|
||||
Trace.AutoFlush = true;
|
||||
}
|
||||
|
||||
public static void LogError(string message)
|
||||
{
|
||||
Log(message, "ERROR");
|
||||
}
|
||||
|
||||
public static void LogError(string message, Exception ex)
|
||||
{
|
||||
Log(
|
||||
message + Environment.NewLine +
|
||||
ex?.Message + Environment.NewLine +
|
||||
"Inner exception: " + Environment.NewLine +
|
||||
ex?.InnerException?.Message + Environment.NewLine +
|
||||
"Stack trace: " + Environment.NewLine +
|
||||
ex?.StackTrace,
|
||||
"ERROR");
|
||||
}
|
||||
|
||||
public static void LogWarning(string message)
|
||||
{
|
||||
Log(message, "WARNING");
|
||||
}
|
||||
|
||||
public static void LogInfo(string message)
|
||||
{
|
||||
Log(message, "INFO");
|
||||
}
|
||||
|
||||
private static void Log(string message, string type)
|
||||
{
|
||||
Trace.WriteLine(type + ": " + DateTime.Now.TimeOfDay);
|
||||
Trace.Indent();
|
||||
Trace.WriteLine(GetCallerInfo());
|
||||
Trace.WriteLine(message);
|
||||
Trace.Unindent();
|
||||
}
|
||||
|
||||
private static string GetCallerInfo()
|
||||
{
|
||||
StackTrace stackTrace = new StackTrace();
|
||||
|
||||
var methodName = stackTrace.GetFrame(3)?.GetMethod();
|
||||
var className = methodName?.DeclaringType.Name;
|
||||
return "[Method]: " + methodName?.Name + " [Class]: " + className;
|
||||
}
|
||||
}
|
||||
}
|
95
src/modules/MouseUtils/MouseJumpUI/MainForm.Designer.cs
generated
Normal file
95
src/modules/MouseUtils/MouseJumpUI/MainForm.Designer.cs
generated
Normal file
@ -0,0 +1,95 @@
|
||||
// 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.Windows.Forms;
|
||||
|
||||
namespace MouseJumpUI;
|
||||
|
||||
partial class MainForm
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
|
||||
panel1 = new Panel();
|
||||
Thumbnail = new PictureBox();
|
||||
panel1.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)Thumbnail).BeginInit();
|
||||
SuspendLayout();
|
||||
//
|
||||
// panel1
|
||||
//
|
||||
panel1.BackColor = System.Drawing.SystemColors.Highlight;
|
||||
panel1.Controls.Add(Thumbnail);
|
||||
panel1.Dock = DockStyle.Fill;
|
||||
panel1.Location = new System.Drawing.Point(0, 0);
|
||||
panel1.Name = "panel1";
|
||||
panel1.Padding = new Padding(5);
|
||||
panel1.Size = new System.Drawing.Size(800, 450);
|
||||
panel1.TabIndex = 1;
|
||||
//
|
||||
// Thumbnail
|
||||
//
|
||||
Thumbnail.BackColor = System.Drawing.SystemColors.Control;
|
||||
Thumbnail.Dock = DockStyle.Fill;
|
||||
Thumbnail.Location = new System.Drawing.Point(5, 5);
|
||||
Thumbnail.Name = "Thumbnail";
|
||||
Thumbnail.Size = new System.Drawing.Size(790, 440);
|
||||
Thumbnail.SizeMode = PictureBoxSizeMode.StretchImage;
|
||||
Thumbnail.TabIndex = 1;
|
||||
Thumbnail.TabStop = false;
|
||||
Thumbnail.Click += Thumbnail_Click;
|
||||
//
|
||||
// MainForm
|
||||
//
|
||||
AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
|
||||
AutoScaleMode = AutoScaleMode.Font;
|
||||
ClientSize = new System.Drawing.Size(800, 450);
|
||||
Controls.Add(panel1);
|
||||
FormBorderStyle = FormBorderStyle.None;
|
||||
Icon = (System.Drawing.Icon)resources.GetObject("$this.Icon");
|
||||
KeyPreview = true;
|
||||
Name = "MainForm";
|
||||
ShowInTaskbar = false;
|
||||
StartPosition = FormStartPosition.Manual;
|
||||
Text = "MouseJump";
|
||||
TopMost = true;
|
||||
Deactivate += MainForm_Deactivate;
|
||||
Load += MainForm_Load;
|
||||
KeyDown += MainForm_KeyDown;
|
||||
panel1.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)Thumbnail).EndInit();
|
||||
ResumeLayout(false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private Panel panel1;
|
||||
private PictureBox Thumbnail;
|
||||
|
||||
}
|
177
src/modules/MouseUtils/MouseJumpUI/MainForm.cs
Normal file
177
src/modules/MouseUtils/MouseJumpUI/MainForm.cs
Normal file
@ -0,0 +1,177 @@
|
||||
// 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;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using MouseJumpUI.Helpers;
|
||||
|
||||
namespace MouseJumpUI;
|
||||
|
||||
internal partial class MainForm : Form
|
||||
{
|
||||
public MainForm()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
this.ShowThumbnail();
|
||||
}
|
||||
|
||||
private void MainForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
}
|
||||
|
||||
private void MainForm_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.KeyCode == Keys.Escape)
|
||||
{
|
||||
this.OnDeactivate(EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
private void MainForm_Deactivate(object sender, EventArgs e)
|
||||
{
|
||||
// dispose the existing image if there is one
|
||||
if (Thumbnail.Image != null)
|
||||
{
|
||||
Thumbnail.Image.Dispose();
|
||||
Thumbnail.Image = null;
|
||||
}
|
||||
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private void Thumbnail_Click(object sender, EventArgs e)
|
||||
{
|
||||
var mouseEventArgs = (MouseEventArgs)e;
|
||||
Logger.LogInfo($"Reporting mouse event args \n\tbutton = {mouseEventArgs.Button}\n\tlocation = {mouseEventArgs.Location} ");
|
||||
|
||||
if (mouseEventArgs.Button == MouseButtons.Left)
|
||||
{
|
||||
// plain click - move mouse pointer
|
||||
var desktopBounds = LayoutHelper.CombineRegions(
|
||||
Screen.AllScreens.Select(
|
||||
screen => screen.Bounds).ToList());
|
||||
Logger.LogInfo($"desktop bounds = {desktopBounds}");
|
||||
|
||||
var mouseEvent = (MouseEventArgs)e;
|
||||
|
||||
var scaledLocation = LayoutHelper.ScaleLocation(
|
||||
originalBounds: Thumbnail.Bounds,
|
||||
originalLocation: new Point(mouseEvent.X, mouseEvent.Y),
|
||||
scaledBounds: desktopBounds);
|
||||
Logger.LogInfo($"scaled location = {scaledLocation}");
|
||||
|
||||
// set the new cursor position *twice* - the cursor sometimes end up in
|
||||
// the wrong place if we try to cross the dead space between non-aligned
|
||||
// monitors - e.g. when trying to move the cursor from (a) to (b) we can
|
||||
// *sometimes* - for no clear reason - end up at (c) instead.
|
||||
//
|
||||
// +----------------+
|
||||
// |(c) (b) |
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// +---------+ |
|
||||
// | (a) | |
|
||||
// +---------+----------------+
|
||||
//
|
||||
// setting the position a second time seems to fix this and moves the
|
||||
// cursor to the expected location (b) - for more details see
|
||||
// https://github.com/mikeclayton/FancyMouse/pull/3
|
||||
Cursor.Position = scaledLocation;
|
||||
Cursor.Position = scaledLocation;
|
||||
Microsoft.PowerToys.Telemetry.PowerToysTelemetry.Log.WriteEvent(new Telemetry.MouseJumpTeleportCursorEvent());
|
||||
}
|
||||
|
||||
this.Close();
|
||||
}
|
||||
|
||||
public void ShowThumbnail()
|
||||
{
|
||||
if (this.Thumbnail.Image != null)
|
||||
{
|
||||
var tmp = this.Thumbnail.Image;
|
||||
this.Thumbnail.Image = null;
|
||||
tmp.Dispose();
|
||||
}
|
||||
|
||||
var screens = Screen.AllScreens;
|
||||
foreach (var i in Enumerable.Range(0, screens.Length))
|
||||
{
|
||||
var screen = screens[i];
|
||||
Logger.LogInfo($"screen[{i}] = \"{screen.DeviceName}\"\n\tprimary = {screen.Primary}\n\tbounds = {screen.Bounds}\n\tworking area = {screen.WorkingArea}");
|
||||
}
|
||||
|
||||
var desktopBounds = LayoutHelper.CombineRegions(
|
||||
screens.Select(screen => screen.Bounds).ToList());
|
||||
Logger.LogInfo(
|
||||
$"desktop bounds = {desktopBounds}");
|
||||
|
||||
var activatedPosition = Cursor.Position;
|
||||
Logger.LogInfo(
|
||||
$"activated position = {activatedPosition}");
|
||||
|
||||
var previewImagePadding = new Size(
|
||||
panel1.Padding.Left + panel1.Padding.Right,
|
||||
panel1.Padding.Top + panel1.Padding.Bottom);
|
||||
Logger.LogInfo(
|
||||
$"image padding = {previewImagePadding}");
|
||||
|
||||
var maxThumbnailSize = new Size(1600, 1200);
|
||||
var formBounds = LayoutHelper.GetPreviewFormBounds(
|
||||
desktopBounds: desktopBounds,
|
||||
activatedPosition: activatedPosition,
|
||||
activatedMonitorBounds: Screen.FromPoint(activatedPosition).Bounds,
|
||||
maximumThumbnailImageSize: maxThumbnailSize,
|
||||
thumbnailImagePadding: previewImagePadding);
|
||||
Logger.LogInfo(
|
||||
$"form bounds = {formBounds}");
|
||||
|
||||
// take a screenshot of the entire desktop
|
||||
// see https://learn.microsoft.com/en-gb/windows/win32/gdi/the-virtual-screen
|
||||
var screenshot = new Bitmap(desktopBounds.Width, desktopBounds.Height, PixelFormat.Format32bppArgb);
|
||||
using (var graphics = Graphics.FromImage(screenshot))
|
||||
{
|
||||
// note - it *might* be faster to capture each monitor individually and assemble them into
|
||||
// a single image ourselves as we *may* not have to transfer all of the blank pixels
|
||||
// that are outside the desktop bounds - e.g. the *** in the ascii art below
|
||||
//
|
||||
// +----------------+********
|
||||
// | |********
|
||||
// | 1 +-------+
|
||||
// | | |
|
||||
// +----------------+ 0 |
|
||||
// *****************| |
|
||||
// *****************+-------+
|
||||
//
|
||||
// for very irregular monitor layouts this *might* be a big percentage of the rectangle
|
||||
// containing the desktop bounds.
|
||||
//
|
||||
// then again, it might not make much difference at all - we'd need to do some perf tests
|
||||
graphics.CopyFromScreen(desktopBounds.Left, desktopBounds.Top, 0, 0, desktopBounds.Size);
|
||||
}
|
||||
|
||||
// resize and position the form
|
||||
// note - do this in two steps rather than "this.Bounds = formBounds" as there
|
||||
// appears to be an issue in WinForms with dpi scaling even when using PerMonitorV2,
|
||||
// where the form scaling uses either the *primary* screen scaling or the *previous*
|
||||
// screen's scaling when the form is moved to a different screen. i've got no idea
|
||||
// *why*, but the exact sequence of calls below seems to be a workaround...
|
||||
// see https://github.com/mikeclayton/FancyMouse/issues/2
|
||||
this.Location = formBounds.Location;
|
||||
_ = this.PointToScreen(Point.Empty);
|
||||
this.Size = formBounds.Size;
|
||||
|
||||
// update the preview image
|
||||
this.Thumbnail.Image = screenshot;
|
||||
|
||||
this.Show();
|
||||
Microsoft.PowerToys.Telemetry.PowerToysTelemetry.Log.WriteEvent(new Telemetry.MouseJumpTeleportCursorEvent());
|
||||
|
||||
// we have to activate the form to make sure the deactivate event fires
|
||||
this.Activate();
|
||||
}
|
||||
}
|
317
src/modules/MouseUtils/MouseJumpUI/MainForm.resx
Normal file
317
src/modules/MouseUtils/MouseJumpUI/MainForm.resx
Normal file
@ -0,0 +1,317 @@
|
||||
<root>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
AAABAAMAMDAAAAEAIACoJQAANgAAACAgAAABACAAqBAAAN4lAAAQEAAAAQAgAGgEAACGNgAAKAAAADAA
|
||||
AABgAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAD/AAAA/wAAAP8AAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAP9kdJz/ZHSc/2R0nP9kdJz/AAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAA/2R0nP9kdJz/ZHSc/2R0nP9kdJz/ZHSc/wAAAP8AAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAA/2R0nP9kdJz/ZHSc/2R0nP9kdJz/ZHSc/wAA
|
||||
AP8AAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/G4uP/xuLj/wAAAP9kdJz/ZHSc/2R0
|
||||
nP9kdJz/AAAA/8bi4//G4uP/AAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/8bi4//G4uP/xuLj/8bi
|
||||
4/8AAAD/AAAA/wAAAP8AAAD/xuLj/8bi4//G4uP/xuLj/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/xuLj/8bi
|
||||
4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi4/8AAAD/AAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AP/G4uP/xuLj/8bi4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi
|
||||
4//G4uP/AAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAA/8bi4//G4uP/xuLj/5Okpf8kISD/k6Sl/8bi4//G4uP/xuLj/8bi4//G4uP/xuLj/5Ok
|
||||
pf8kISD/k6Sl/8bi4//G4uP/xuLj/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAA/8bi4//G4uP/xuLj/yQhIP8kISD/JCEg/8bi4//G4uP/xuLj/8bi
|
||||
4//G4uP/xuLj/yQhIP8kISD/JCEg/8bi4//G4uP/xuLj/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/xuLj/8bi4//G4uP/xuLj/5Okpf8kISD/k6Sl/8bi
|
||||
4//G4uP/xuLj/8bi4//G4uP/xuLj/5Okpf8kISD/k6Sl/8bi4//G4uP/xuLj/8bi4/8AAAD/AAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/xuLj/8bi4//G4uP/xuLj/8bi
|
||||
4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi
|
||||
4/8AAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/G4uP/xuLj/wAA
|
||||
AP8AAAD/AAAA/8bi4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi4//G4uP/xuLj/wAA
|
||||
AP8AAAD/AAAA/8bi4//G4uP/AAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/8bi
|
||||
4//G4uP/AAAA/4CYtf+AmLX/gJi1/wAAAP/G4uP/xuLj/8bi4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi
|
||||
4//G4uP/AAAA/4CYtf+AmLX/gJi1/wAAAP/G4uP/xuLj/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAD/xuLj/8bi4/8AAAD/gJi1/4CYtf+AmLX/gJi1/4CYtf8AAAD/xuLj/8bi4//G4uP/xuLj/8bi
|
||||
4//G4uP/xuLj/8bi4/8AAAD/gJi1/4CYtf+AmLX/gJi1/4CYtf8AAAD/xuLj/8bi4/8AAAD/AAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAD/xuLj/wAAAP+AmLX/gJi1/4CYtf+AmLX/gJi1/4CYtf8AAAD/xuLj/8bi
|
||||
4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi4/8AAAD/gJi1/4CYtf+AmLX/gJi1/4CYtf+AmLX/AAAA/8bi
|
||||
4/8AAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/G4uP/xuLj/wAAAP+AmLX/gJi1/4CYtf+AmLX/gJi1/4CY
|
||||
tf8AAAD/xuLj/8bi4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi4/8AAAD/gJi1/4CYtf+AmLX/gJi1/4CY
|
||||
tf+AmLX/AAAA/8bi4//G4uP/AAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/8bi4//G4uP/AAAA/4CYtf+AmLX/gJi1/4CY
|
||||
tf+AmLX/gJi1/wAAAP/G4uP/xuLj/8bi4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi4//G4uP/AAAA/4CY
|
||||
tf+AmLX/gJi1/4CYtf+AmLX/gJi1/wAAAP/G4uP/xuLj/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/8bi4/8AAAD/gJi1/4CY
|
||||
tf+AmLX/gJi1/4CYtf+AmLX/gJi1/wAAAP/G4uP/AAAA/wAAAP/G4uP/xuLj/8bi4//G4uP/AAAA/wAA
|
||||
AP/G4uP/AAAA/4CYtf+AmLX/gJi1/4CYtf+AmLX/gJi1/4CYtf8AAAD/xuLj/wAAAP8AAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/8bi
|
||||
4/8AAAD/gJi1/4CYtf+AmLX/gJi1/4CYtf+AmLX/AAAA/8bi4//G4uP/AAAA/wAAAAAAAAD/AAAA/wAA
|
||||
AP8AAAD/AAAAAAAAAP/G4uP/xuLj/wAAAP+AmLX/gJi1/4CYtf+AmLX/gJi1/4CYtf8AAAD/xuLj/wAA
|
||||
AP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAA/8bi4/8AAAD/gJi1/4CYtf+AmLX/gJi1/4CYtf8AAAD/xuLj/8bi4/8AAAD/AAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/xuLj/8bi4/8AAAD/gJi1/4CYtf+AmLX/gJi1/4CY
|
||||
tf8AAAD/xuLj/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAA/8bi4/8AAAD/gJi1/4CYtf+AmLX/gJi1/wAAAP/G4uP/xuLj/wAA
|
||||
AP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/8bi4//G4uP/AAAA/4CY
|
||||
tf+AmLX/gJi1/4CYtf8AAAD/xuLj/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/8bi4//G4uP/AAAA/4CYtf+AmLX/gJi1/wAA
|
||||
AP/G4uP/AAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AP/G4uP/AAAA/4CYtf+AmLX/gJi1/wAAAP/G4uP/xuLj/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/G4uP/xuLj/wAA
|
||||
AP+AmLX/AAAA/8bi4//G4uP/AAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAP/G4uP/xuLj/wAAAP+AmLX/AAAA/8bi4//G4uP/AAAA/wAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAD/xuLj/wAAAP+AmLX/AAAA/8bi4/8AAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/xuLj/wAAAP+AmLX/AAAA/8bi4/8AAAD/AAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAD/xuLj/8bi4/8AAAD/xuLj/8bi4/8AAAD/AAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/xuLj/8bi4/8AAAD/xuLj/8bi
|
||||
4/8AAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/8bi4//G4uP/xuLj/wAAAP8AAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/8bi
|
||||
4//G4uP/xuLj/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAD/AAAA/wAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAP8AAAD/AAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAP///////wAA////////AAD///////8AAP///////wAA////////AAD///////8AAP//
|
||||
/////wAA////////AAD///////8AAP///////wAA///8P///AAD///gf//8AAP//8A///wAA///gB///
|
||||
AAD//8AD//8AAP//gAH//wAA//8AAP//AAD//gAAf/8AAP/8AAA//wAA//wAAD//AAD/+AAAH/8AAP/4
|
||||
AAAf/wAA//AAAA//AAD/4AAAB/8AAP/AAAAD/wAA/8AAAAP/AAD/gAAAAf8AAP8AAAAA/wAA/wAAAAD/
|
||||
AAD/AAQgAP8AAP8AD/AA/wAA/wAf+AD/AAD/AD/8AP8AAP+AP/wB/wAA/8B//gP/AAD/wH/+A/8AAP/g
|
||||
//8H/wAA//H//4//AAD///////8AAP///////wAA////////AAD///////8AAP///////wAA////////
|
||||
AAD///////8AAP///////wAA////////AAD///////8AACgAAAAgAAAAQAAAAAEAIAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAA/wAAAP8AAAD/AAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/2R0nP9kdJz/ZHSc/2R0nP8AAAD/AAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP9kdJz/ZHSc/2R0nP9kdJz/ZHSc/2R0
|
||||
nP8AAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAA/2R0nP9kdJz/ZHSc/2R0
|
||||
nP9kdJz/ZHSc/wAAAP8AAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/8bi4//G4uP/AAAA/2R0
|
||||
nP9kdJz/ZHSc/2R0nP8AAAD/xuLj/8bi4/8AAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/G4uP/xuLj/8bi
|
||||
4//G4uP/AAAA/wAAAP8AAAD/AAAA/8bi4//G4uP/xuLj/8bi4/8AAAD/AAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/xuLj/8bi
|
||||
4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi4/8AAAD/AAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/8bi
|
||||
4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi
|
||||
4/8AAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AP/G4uP/xuLj/8bi4/+TpKX/JCEg/5Okpf/G4uP/xuLj/8bi4//G4uP/xuLj/8bi4/+TpKX/JCEg/5Ok
|
||||
pf/G4uP/xuLj/8bi4/8AAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAA/8bi4//G4uP/xuLj/yQhIP8kISD/JCEg/8bi4//G4uP/xuLj/8bi4//G4uP/xuLj/yQh
|
||||
IP8kISD/JCEg/8bi4//G4uP/xuLj/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAP/G4uP/xuLj/8bi4//G4uP/k6Sl/yQhIP+TpKX/xuLj/8bi4//G4uP/xuLj/8bi
|
||||
4//G4uP/k6Sl/yQhIP+TpKX/xuLj/8bi4//G4uP/xuLj/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAA/8bi4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi
|
||||
4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi4//G4uP/AAAA/wAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/G4uP/xuLj/wAAAP8AAAD/AAAA/8bi4//G4uP/xuLj/8bi
|
||||
4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi4//G4uP/xuLj/wAAAP8AAAD/AAAA/8bi4//G4uP/AAAA/wAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/xuLj/8bi4/8AAAD/gJi1/4CYtf+AmLX/AAAA/8bi
|
||||
4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi4/8AAAD/gJi1/4CYtf+AmLX/AAAA/8bi
|
||||
4//G4uP/AAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/8bi4//G4uP/AAAA/4CYtf+AmLX/gJi1/4CY
|
||||
tf+AmLX/AAAA/8bi4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi4//G4uP/AAAA/4CYtf+AmLX/gJi1/4CY
|
||||
tf+AmLX/AAAA/8bi4//G4uP/AAAA/wAAAAAAAAAAAAAAAAAAAAAAAAD/xuLj/wAAAP+AmLX/gJi1/4CY
|
||||
tf+AmLX/gJi1/4CYtf8AAAD/xuLj/8bi4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi4/8AAAD/gJi1/4CY
|
||||
tf+AmLX/gJi1/4CYtf+AmLX/AAAA/8bi4/8AAAD/AAAAAAAAAAAAAAAAAAAA/8bi4//G4uP/AAAA/4CY
|
||||
tf+AmLX/gJi1/4CYtf+AmLX/gJi1/wAAAP/G4uP/xuLj/8bi4//G4uP/xuLj/8bi4//G4uP/xuLj/wAA
|
||||
AP+AmLX/gJi1/4CYtf+AmLX/gJi1/4CYtf8AAAD/xuLj/8bi4/8AAAD/AAAAAAAAAP/G4uP/xuLj/wAA
|
||||
AP+AmLX/gJi1/4CYtf+AmLX/gJi1/4CYtf8AAAD/xuLj/8bi4//G4uP/xuLj/8bi4//G4uP/xuLj/8bi
|
||||
4//G4uP/xuLj/wAAAP+AmLX/gJi1/4CYtf+AmLX/gJi1/4CYtf8AAAD/xuLj/8bi4/8AAAD/AAAA/8bi
|
||||
4/8AAAD/gJi1/4CYtf+AmLX/gJi1/4CYtf+AmLX/gJi1/wAAAP/G4uP/AAAA/wAAAP/G4uP/xuLj/8bi
|
||||
4//G4uP/AAAA/wAAAP/G4uP/AAAA/4CYtf+AmLX/gJi1/4CYtf+AmLX/gJi1/4CYtf8AAAD/xuLj/wAA
|
||||
AP8AAAD/xuLj/wAAAP+AmLX/gJi1/4CYtf+AmLX/gJi1/4CYtf8AAAD/xuLj/8bi4/8AAAD/AAAAAAAA
|
||||
AP8AAAD/AAAA/wAAAP8AAAAAAAAA/8bi4//G4uP/AAAA/4CYtf+AmLX/gJi1/4CYtf+AmLX/gJi1/wAA
|
||||
AP/G4uP/AAAA/wAAAP/G4uP/AAAA/4CYtf+AmLX/gJi1/4CYtf+AmLX/AAAA/8bi4//G4uP/AAAA/wAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/8bi4//G4uP/AAAA/4CYtf+AmLX/gJi1/4CY
|
||||
tf+AmLX/AAAA/8bi4/8AAAD/AAAA/8bi4/8AAAD/gJi1/4CYtf+AmLX/gJi1/wAAAP/G4uP/xuLj/wAA
|
||||
AP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/8bi4//G4uP/AAAA/4CY
|
||||
tf+AmLX/gJi1/4CYtf8AAAD/xuLj/wAAAP8AAAD/xuLj/8bi4/8AAAD/gJi1/4CYtf+AmLX/AAAA/8bi
|
||||
4/8AAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/8bi
|
||||
4/8AAAD/gJi1/4CYtf+AmLX/AAAA/8bi4//G4uP/AAAA/wAAAAAAAAD/xuLj/8bi4/8AAAD/gJi1/wAA
|
||||
AP/G4uP/xuLj/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAD/xuLj/8bi4/8AAAD/gJi1/wAAAP/G4uP/xuLj/wAAAP8AAAAAAAAAAAAAAAAAAAD/xuLj/wAA
|
||||
AP+AmLX/AAAA/8bi4/8AAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAD/xuLj/wAAAP+AmLX/AAAA/8bi4/8AAAD/AAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AP/G4uP/xuLj/wAAAP/G4uP/xuLj/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/G4uP/xuLj/wAAAP/G4uP/xuLj/wAAAP8AAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAP/G4uP/xuLj/8bi4/8AAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/G4uP/xuLj/8bi4/8AAAD/AAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAD/AAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAD/AAAA/wAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////D////gf///wD///4Af//8AD//+A
|
||||
Af//AAD//gAAf/wAAD/8AAA/+AAAH/gAAB/wAAAP4AAAB8AAAAPAAAADgAAAAQAAAAAAAAAAAAQgAAAP
|
||||
8AAAH/gAAD/8AIA//AHAf/4DwH/+A+D//wfx//+P//////////8oAAAAEAAAACAAAAABACAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAyOk7/MjpO/wAA
|
||||
AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAyOk7/ZHSc/2R0
|
||||
nP8yOk7/AAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECVqqr/laqq/zI6
|
||||
Tv8yOk7/laqq/5Wqqv8AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECVqqr/xuLj/8bi
|
||||
4//G4uP/xuLj/8bi4//G4uP/laqq/wAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABjcXL/xuLj/0BC
|
||||
Qf+RoqP/xuLj/8bi4/+RoqP/QEJB/8bi4/9jcXL/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAxuLj/8bi
|
||||
4/+RoqP/udPU/8bi4//G4uP/udPU/5Gio//G4uP/xuLj/wAAAIAAAAAAAAAAAAAAAAAAAABAlaqq/1Jf
|
||||
Zv9ATFv/laqq/8bi4//G4uP/xuLj/8bi4/+Vqqr/QExb/1JfZv+Vqqr/AAAAQAAAAAAAAAAAY3Fy/1Jf
|
||||
Zv+AmLX/gJi1/0BMW//G4uP/xuLj/8bi4//G4uP/QExb/4CYtf+AmLX/Ul9m/2Nxcv8AAAAAQktMv5Wq
|
||||
qv9gcoj/gJi1/4CYtf9SX2b/xuLj/8bi4//G4uP/xuLj/1JfZv+AmLX/gJi1/2ByiP+Vqqr/QktMv2Nx
|
||||
cv9ATFv/gJi1/4CYtf9gcoj/laqq/wAAAL9jcXL/Y3Fy/wAAAL+Vqqr/YHKI/4CYtf+AmLX/QExb/2Nx
|
||||
cv9jcXL/QExb/4CYtf9gcoj/laqq/0JLTL8AAAAAAAAAAAAAAAAAAAAAQktMv5Wqqv9gcoj/gJi1/0BM
|
||||
W/9jcXL/QktMv5Wqqv9gcoj/Ul9m/2Nxcv8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABjcXL/Ul9m/2By
|
||||
iP+Vqqr/QktMvwAAAABjcXL/Ul9m/5Wqqv8AAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgJWq
|
||||
qv9SX2b/Y3Fy/wAAAAAAAAAAAAAAQGNxcv9CS0y/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AABCS0y/Y3Fy/wAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//rEH8P6xB+B+sQfAPrEHgB6xB4AesQcADrEGAAaxBgAGsQQAA
|
||||
rEEAAKxBA8CsQQfgrEGH4axBj/GsQf//rEE=
|
||||
</value>
|
||||
</data>
|
||||
</root>
|
66
src/modules/MouseUtils/MouseJumpUI/MouseJumpUI.csproj
Normal file
66
src/modules/MouseUtils/MouseJumpUI/MouseJumpUI.csproj
Normal file
@ -0,0 +1,66 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\..\Version.props" />
|
||||
<PropertyGroup>
|
||||
<AssemblyTitle>PowerToys.MouseJumpUI</AssemblyTitle>
|
||||
<AssemblyDescription>PowerToys MouseJumpUI</AssemblyDescription>
|
||||
<Version>$(Version).0</Version>
|
||||
<OutputPath>..\..\..\..\$(Platform)\$(Configuration)\modules\MouseUtils\MouseJumpUI</OutputPath>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<GenerateSatelliteAssembliesForCore>true</GenerateSatelliteAssembliesForCore>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<StartupObject>MouseJumpUI.Program</StartupObject>
|
||||
<SelfContained>true</SelfContained>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- SelfContained=true requires RuntimeIdentifier to be set -->
|
||||
<PropertyGroup Condition="'$(Platform)'=='x64'">
|
||||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Platform)'=='ARM64'">
|
||||
<RuntimeIdentifier>win10-arm64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<ApplicationHighDpiMode>PerMonitorV2</ApplicationHighDpiMode>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{D962A009-834F-4EEC-AABB-430DF8F98E39}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>MouseJumpUI</RootNamespace>
|
||||
<AssemblyName>PowerToys.MouseJumpUI</AssemblyName>
|
||||
<TargetFramework>net7.0-windows10.0.19041.0</TargetFramework>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- See https://learn.microsoft.com/windows/apps/develop/platform/csharp-winrt/net-projection-from-cppwinrt-component for more info -->
|
||||
<PropertyGroup>
|
||||
<CsWinRTIncludes>PowerToys.GPOWrapper</CsWinRTIncludes>
|
||||
<CsWinRTGeneratedFilesDir>$(OutDir)</CsWinRTGeneratedFilesDir>
|
||||
<ErrorOnDuplicatePublishOutputFiles>false</ErrorOnDuplicatePublishOutputFiles>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Optimize>true</Optimize>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Windows.CsWinRT" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\common\GPOWrapper\GPOWrapper.vcxproj" />
|
||||
<ProjectReference Include="..\..\..\common\interop\PowerToys.Interop.vcxproj" />
|
||||
<ProjectReference Include="..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
38
src/modules/MouseUtils/MouseJumpUI/Program.cs
Normal file
38
src/modules/MouseUtils/MouseJumpUI/Program.cs
Normal file
@ -0,0 +1,38 @@
|
||||
// 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;
|
||||
using System.Windows.Forms;
|
||||
using MouseJumpUI.Helpers;
|
||||
|
||||
namespace MouseJumpUI;
|
||||
|
||||
internal static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
private static void Main()
|
||||
{
|
||||
// To customize application configuration such as set high DPI settings or default font,
|
||||
// see https://aka.ms/applicationconfiguration.
|
||||
ApplicationConfiguration.Initialize();
|
||||
|
||||
if (PowerToys.GPOWrapper.GPOWrapper.GetConfiguredMouseJumpEnabledValue() == PowerToys.GPOWrapper.GpoRuleConfigured.Disabled)
|
||||
{
|
||||
// TODO : Log message
|
||||
Logger.LogWarning("Tried to start with a GPO policy setting the utility to always be disabled. Please contact your systems administrator.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Application.HighDpiMode != HighDpiMode.PerMonitorV2)
|
||||
{
|
||||
Logger.LogError("High dpi mode is not set to PerMonitorV2.");
|
||||
return;
|
||||
}
|
||||
|
||||
Application.Run(new MainForm());
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
// 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.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("MouseJumpUI.UnitTests")]
|
@ -0,0 +1,16 @@
|
||||
// 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.Diagnostics.Tracing;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry.Events;
|
||||
|
||||
namespace MouseJumpUI.Telemetry
|
||||
{
|
||||
[EventData]
|
||||
public class MouseJumpShowEvent : EventBase, IEvent
|
||||
{
|
||||
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
// 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.Diagnostics.Tracing;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry.Events;
|
||||
|
||||
namespace MouseJumpUI.Telemetry
|
||||
{
|
||||
[EventData]
|
||||
public class MouseJumpTeleportCursorEvent : EventBase, IEvent
|
||||
{
|
||||
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
}
|
||||
}
|
@ -158,6 +158,7 @@ int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow
|
||||
L"modules/Awake/PowerToys.AwakeModuleInterface.dll",
|
||||
L"modules/MouseUtils/PowerToys.FindMyMouse.dll",
|
||||
L"modules/MouseUtils/PowerToys.MouseHighlighter.dll",
|
||||
L"modules/MouseUtils/PowerToys.MouseJump.dll",
|
||||
L"modules/AlwaysOnTop/PowerToys.AlwaysOnTopModuleInterface.dll",
|
||||
L"modules/MouseUtils/PowerToys.MousePointerCrosshairs.dll",
|
||||
L"modules/PowerAccent/PowerToys.PowerAccentModuleInterface.dll",
|
||||
|
@ -214,6 +214,22 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
}
|
||||
}
|
||||
|
||||
private bool mouseJump = true;
|
||||
|
||||
[JsonPropertyName("MouseJump")]
|
||||
public bool MouseJump
|
||||
{
|
||||
get => mouseJump;
|
||||
set
|
||||
{
|
||||
if (mouseJump != value)
|
||||
{
|
||||
LogTelemetryEvent(value);
|
||||
mouseJump = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool alwaysOnTop = true;
|
||||
|
||||
[JsonPropertyName("AlwaysOnTop")]
|
||||
|
19
src/settings-ui/Settings.UI.Library/MouseJumpProperties.cs
Normal file
19
src/settings-ui/Settings.UI.Library/MouseJumpProperties.cs
Normal file
@ -0,0 +1,19 @@
|
||||
// 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.Text.Json.Serialization;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
{
|
||||
public class MouseJumpProperties
|
||||
{
|
||||
[JsonPropertyName("activation_shortcut")]
|
||||
public HotkeySettings ActivationShortcut { get; set; }
|
||||
|
||||
public MouseJumpProperties()
|
||||
{
|
||||
ActivationShortcut = new HotkeySettings(true, false, false, true, 0x44);
|
||||
}
|
||||
}
|
||||
}
|
35
src/settings-ui/Settings.UI.Library/MouseJumpSettings.cs
Normal file
35
src/settings-ui/Settings.UI.Library/MouseJumpSettings.cs
Normal file
@ -0,0 +1,35 @@
|
||||
// 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.Text.Json.Serialization;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
{
|
||||
public class MouseJumpSettings : BasePTModuleSettings, ISettingsConfig
|
||||
{
|
||||
public const string ModuleName = "MouseJump";
|
||||
|
||||
[JsonPropertyName("properties")]
|
||||
public MouseJumpProperties Properties { get; set; }
|
||||
|
||||
public MouseJumpSettings()
|
||||
{
|
||||
Name = ModuleName;
|
||||
Properties = new MouseJumpProperties();
|
||||
Version = "1.0";
|
||||
}
|
||||
|
||||
public string GetModuleName()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
|
||||
// This can be utilized in the future if the settings.json file is to be modified/deleted.
|
||||
public bool UpgradeSettingsConfiguration()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
29
src/settings-ui/Settings.UI.Library/SndMouseJumpSettings.cs
Normal file
29
src/settings-ui/Settings.UI.Library/SndMouseJumpSettings.cs
Normal file
@ -0,0 +1,29 @@
|
||||
// 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.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
{
|
||||
public class SndMouseJumpSettings
|
||||
{
|
||||
[JsonPropertyName("MouseJump")]
|
||||
public MouseJumpSettings MouseJump { get; set; }
|
||||
|
||||
public SndMouseJumpSettings()
|
||||
{
|
||||
}
|
||||
|
||||
public SndMouseJumpSettings(MouseJumpSettings settings)
|
||||
{
|
||||
MouseJump = settings;
|
||||
}
|
||||
|
||||
public string ToJsonString()
|
||||
{
|
||||
return JsonSerializer.Serialize(this);
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
@ -120,6 +120,9 @@ namespace Microsoft.PowerToys.Settings.UI
|
||||
case "MouseHighlighter":
|
||||
needToUpdate = generalSettingsConfig.Enabled.MouseHighlighter != isEnabled;
|
||||
generalSettingsConfig.Enabled.MouseHighlighter = isEnabled; break;
|
||||
case "MouseJump":
|
||||
needToUpdate = generalSettingsConfig.Enabled.MouseJump != isEnabled;
|
||||
generalSettingsConfig.Enabled.MouseJump = isEnabled; break;
|
||||
case "MousePointerCrosshairs":
|
||||
needToUpdate = generalSettingsConfig.Enabled.MousePointerCrosshairs != isEnabled;
|
||||
generalSettingsConfig.Enabled.MousePointerCrosshairs = isEnabled; break;
|
||||
|
@ -35,6 +35,13 @@
|
||||
x:Uid="Oobe_MouseUtils_MousePointerCrosshairs_Description"
|
||||
Background="Transparent" />
|
||||
|
||||
<TextBlock
|
||||
x:Uid="Oobe_MouseUtils_MouseJump"
|
||||
Style="{ThemeResource OobeSubtitleStyle}" />
|
||||
<toolkitcontrols:MarkdownTextBlock
|
||||
x:Uid="Oobe_MouseUtils_MouseJump_Description"
|
||||
Background="Transparent" />
|
||||
|
||||
<StackPanel
|
||||
Margin="0,24,0,0"
|
||||
Orientation="Horizontal"
|
||||
|
@ -2030,6 +2030,14 @@ From there, simply click on one of the supported files in the File Explorer and
|
||||
<value>Draw crosshairs centered around the mouse pointer.</value>
|
||||
<comment>Mouse as in the hardware peripheral.</comment>
|
||||
</data>
|
||||
<data name="Oobe_MouseUtils_MouseJump.Text" xml:space="preserve">
|
||||
<value>Mouse Jump</value>
|
||||
<comment>Mouse as in the hardware peripheral.</comment>
|
||||
</data>
|
||||
<data name="Oobe_MouseUtils_MouseJump_Description.Text" xml:space="preserve">
|
||||
<value>Jump the mouse pointer quickly to anywhere on your desktop.</value>
|
||||
<comment>Mouse as in the hardware peripheral.</comment>
|
||||
</data>
|
||||
<data name="Launch_Run.Content" xml:space="preserve">
|
||||
<value>Launch PowerToys Run</value>
|
||||
</data>
|
||||
@ -3014,4 +3022,22 @@ Activate by holding the key for the character you want to add an accent to, then
|
||||
<value>The maximum size, in kilobytes, for files to be displayed. This is a safety mechanism to prevent loading large files into RAM.</value>
|
||||
<comment>"RAM" refers to random access memory; "size" refers to disk space; "bytes" refer to the measurement unit</comment>
|
||||
</data>
|
||||
<data name="MouseUtils_MouseJump.Description" xml:space="preserve">
|
||||
<value>Quickly move the mouse pointer long distances.</value>
|
||||
<comment>"Mouse Jump" is the name of the utility. Mouse is the hardware mouse.</comment>
|
||||
</data>
|
||||
<data name="MouseUtils_MouseJump.Header" xml:space="preserve">
|
||||
<value>Mouse Jump</value>
|
||||
<comment>Refers to the utility name</comment>
|
||||
</data>
|
||||
<data name="MouseUtils_MouseJump_ActivationShortcut.Description" xml:space="preserve">
|
||||
<value>Customize the shortcut to turn on or off this mode</value>
|
||||
</data>
|
||||
<data name="MouseUtils_MouseJump_ActivationShortcut.Header" xml:space="preserve">
|
||||
<value>Activation shortcut</value>
|
||||
</data>
|
||||
<data name="MouseUtils_Enable_MouseJump.Header" xml:space="preserve">
|
||||
<value>Enable Mouse Jump</value>
|
||||
<comment>"Mouse Jump" is the name of the utility.</comment>
|
||||
</data>
|
||||
</root>
|
@ -83,6 +83,11 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
FlyoutMenuItems.Add(new FlyoutMenuItem() { Label = resourceLoader.GetString("MouseUtils_MouseHighlighter/Header"), IsEnabled = generalSettingsConfig.Enabled.MouseHighlighter, Tag = "MouseHighlighter", Icon = "ms-appx:///Assets/FluentIcons/FluentIconsMouseHighlighter.png", EnabledChangedCallback = EnabledChangedOnUI });
|
||||
}
|
||||
|
||||
if ((gpo = GPOWrapper.GetConfiguredMouseJumpEnabledValue()) != GpoRuleConfigured.Disabled && gpo != GpoRuleConfigured.Enabled)
|
||||
{
|
||||
FlyoutMenuItems.Add(new FlyoutMenuItem() { Label = resourceLoader.GetString("MouseUtils_MouseJump/Header"), IsEnabled = generalSettingsConfig.Enabled.MouseJump, Tag = "MouseJump", Icon = "ms-appx:///Assets/FluentIcons/FluentIconsMouseJump.png", EnabledChangedCallback = EnabledChangedOnUI });
|
||||
}
|
||||
|
||||
if ((gpo = GPOWrapper.GetConfiguredMousePointerCrosshairsEnabledValue()) != GpoRuleConfigured.Disabled && gpo != GpoRuleConfigured.Enabled)
|
||||
{
|
||||
FlyoutMenuItems.Add(new FlyoutMenuItem() { Label = resourceLoader.GetString("MouseUtils_MousePointerCrosshairs/Header"), IsEnabled = generalSettingsConfig.Enabled.MousePointerCrosshairs, Tag = "MousePointerCrosshairs", Icon = "ms-appx:///Assets/FluentIcons/FluentIconsMouseCrosshairs.png", EnabledChangedCallback = EnabledChangedOnUI });
|
||||
@ -153,6 +158,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
case "ImageResizer": item.IsEnabled = generalSettingsConfig.Enabled.ImageResizer; break;
|
||||
case "KeyboardManager": item.IsEnabled = generalSettingsConfig.Enabled.KeyboardManager; break;
|
||||
case "MouseHighlighter": item.IsEnabled = generalSettingsConfig.Enabled.MouseHighlighter; break;
|
||||
case "MouseJump": item.IsEnabled = generalSettingsConfig.Enabled.MouseJump; break;
|
||||
case "MousePointerCrosshairs": item.IsEnabled = generalSettingsConfig.Enabled.MousePointerCrosshairs; break;
|
||||
case "PastePlain": item.IsEnabled = generalSettingsConfig.Enabled.PastePlain; break;
|
||||
case "PowerRename": item.IsEnabled = generalSettingsConfig.Enabled.PowerRename; break;
|
||||
|
@ -21,9 +21,11 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
|
||||
private MouseHighlighterSettings MouseHighlighterSettingsConfig { get; set; }
|
||||
|
||||
private MouseJumpSettings MouseJumpSettingsConfig { get; set; }
|
||||
|
||||
private MousePointerCrosshairsSettings MousePointerCrosshairsSettingsConfig { get; set; }
|
||||
|
||||
public MouseUtilsViewModel(ISettingsUtils settingsUtils, ISettingsRepository<GeneralSettings> settingsRepository, ISettingsRepository<FindMyMouseSettings> findMyMouseSettingsRepository, ISettingsRepository<MouseHighlighterSettings> mouseHighlighterSettingsRepository, ISettingsRepository<MousePointerCrosshairsSettings> mousePointerCrosshairsSettingsRepository, Func<string, int> ipcMSGCallBackFunc)
|
||||
public MouseUtilsViewModel(ISettingsUtils settingsUtils, ISettingsRepository<GeneralSettings> settingsRepository, ISettingsRepository<FindMyMouseSettings> findMyMouseSettingsRepository, ISettingsRepository<MouseHighlighterSettings> mouseHighlighterSettingsRepository, ISettingsRepository<MouseJumpSettings> mouseJumpSettingsRepository, ISettingsRepository<MousePointerCrosshairsSettings> mousePointerCrosshairsSettingsRepository, Func<string, int> ipcMSGCallBackFunc)
|
||||
{
|
||||
SettingsUtils = settingsUtils;
|
||||
|
||||
@ -78,6 +80,13 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
_highlightFadeDelayMs = MouseHighlighterSettingsConfig.Properties.HighlightFadeDelayMs.Value;
|
||||
_highlightFadeDurationMs = MouseHighlighterSettingsConfig.Properties.HighlightFadeDurationMs.Value;
|
||||
|
||||
if (mouseJumpSettingsRepository == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(mouseJumpSettingsRepository));
|
||||
}
|
||||
|
||||
MouseJumpSettingsConfig = mouseJumpSettingsRepository.SettingsConfig;
|
||||
|
||||
if (mousePointerCrosshairsSettingsRepository == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(mousePointerCrosshairsSettingsRepository));
|
||||
@ -126,6 +135,18 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
_isMouseHighlighterEnabled = GeneralSettingsConfig.Enabled.MouseHighlighter;
|
||||
}
|
||||
|
||||
_jumpEnabledGpoRuleConfiguration = GPOWrapper.GetConfiguredMouseJumpEnabledValue();
|
||||
if (_jumpEnabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _jumpEnabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
|
||||
{
|
||||
// Get the enabled state from GPO.
|
||||
_jumpEnabledStateIsGPOConfigured = true;
|
||||
_isMouseJumpEnabled = _jumpEnabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
|
||||
}
|
||||
else
|
||||
{
|
||||
_isMouseJumpEnabled = GeneralSettingsConfig.Enabled.MouseJump;
|
||||
}
|
||||
|
||||
_mousePointerCrosshairsEnabledGpoRuleConfiguration = GPOWrapper.GetConfiguredMousePointerCrosshairsEnabledValue();
|
||||
if (_mousePointerCrosshairsEnabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _mousePointerCrosshairsEnabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
|
||||
{
|
||||
@ -530,6 +551,64 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
SettingsUtils.SaveSettings(MouseHighlighterSettingsConfig.ToJsonString(), MouseHighlighterSettings.ModuleName);
|
||||
}
|
||||
|
||||
public bool IsMouseJumpEnabled
|
||||
{
|
||||
get => _isMouseJumpEnabled;
|
||||
set
|
||||
{
|
||||
if (_jumpEnabledStateIsGPOConfigured)
|
||||
{
|
||||
// If it's GPO configured, shouldn't be able to change this state.
|
||||
return;
|
||||
}
|
||||
|
||||
if (_isMouseJumpEnabled != value)
|
||||
{
|
||||
_isMouseJumpEnabled = value;
|
||||
|
||||
GeneralSettingsConfig.Enabled.MouseJump = value;
|
||||
OnPropertyChanged(nameof(_isMouseJumpEnabled));
|
||||
|
||||
OutGoingGeneralSettings outgoing = new OutGoingGeneralSettings(GeneralSettingsConfig);
|
||||
SendConfigMSG(outgoing.ToString());
|
||||
|
||||
NotifyMouseJumpPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsJumpEnabledGpoConfigured
|
||||
{
|
||||
get => _jumpEnabledStateIsGPOConfigured;
|
||||
}
|
||||
|
||||
public HotkeySettings MouseJumpActivationShortcut
|
||||
{
|
||||
get
|
||||
{
|
||||
return MouseJumpSettingsConfig.Properties.ActivationShortcut;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (MouseJumpSettingsConfig.Properties.ActivationShortcut != value)
|
||||
{
|
||||
MouseJumpSettingsConfig.Properties.ActivationShortcut = value;
|
||||
NotifyMouseJumpPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void NotifyMouseJumpPropertyChanged([CallerMemberName] string propertyName = null)
|
||||
{
|
||||
OnPropertyChanged(propertyName);
|
||||
|
||||
SndMouseJumpSettings outsettings = new SndMouseJumpSettings(MouseJumpSettingsConfig);
|
||||
SndModuleSettings<SndMouseJumpSettings> ipcMessage = new SndModuleSettings<SndMouseJumpSettings>(outsettings);
|
||||
SendConfigMSG(ipcMessage.ToJsonString());
|
||||
SettingsUtils.SaveSettings(MouseJumpSettingsConfig.ToJsonString(), MouseJumpSettings.ModuleName);
|
||||
}
|
||||
|
||||
public bool IsMousePointerCrosshairsEnabled
|
||||
{
|
||||
get => _isMousePointerCrosshairsEnabled;
|
||||
@ -703,6 +782,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
InitializeEnabledValues();
|
||||
OnPropertyChanged(nameof(IsFindMyMouseEnabled));
|
||||
OnPropertyChanged(nameof(IsMouseHighlighterEnabled));
|
||||
OnPropertyChanged(nameof(IsMouseJumpEnabled));
|
||||
OnPropertyChanged(nameof(IsMousePointerCrosshairsEnabled));
|
||||
}
|
||||
|
||||
@ -732,6 +812,10 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
private int _highlightFadeDelayMs;
|
||||
private int _highlightFadeDurationMs;
|
||||
|
||||
private GpoRuleConfigured _jumpEnabledGpoRuleConfiguration;
|
||||
private bool _jumpEnabledStateIsGPOConfigured;
|
||||
private bool _isMouseJumpEnabled;
|
||||
|
||||
private GpoRuleConfigured _mousePointerCrosshairsEnabledGpoRuleConfiguration;
|
||||
private bool _mousePointerCrosshairsEnabledStateIsGPOConfigured;
|
||||
private bool _isMousePointerCrosshairsEnabled;
|
||||
|
@ -206,6 +206,31 @@
|
||||
</labs:SettingsExpander>
|
||||
</controls:SettingsGroup>
|
||||
|
||||
<controls:SettingsGroup x:Uid="MouseUtils_MouseJump">
|
||||
<labs:SettingsCard
|
||||
x:Uid="MouseUtils_Enable_MouseJump"
|
||||
HeaderIcon="{ui:BitmapIcon Source=/Assets/FluentIcons/FluentIconsMouseJump.png}"
|
||||
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsJumpEnabledGpoConfigured, Converter={StaticResource BoolNegationConverter}}">
|
||||
<ToggleSwitch
|
||||
x:Uid="ToggleSwitch"
|
||||
IsOn="{x:Bind ViewModel.IsMouseJumpEnabled, Mode=TwoWay}" />
|
||||
</labs:SettingsCard>
|
||||
<InfoBar
|
||||
x:Uid="GPO_IsSettingForced"
|
||||
IsClosable="False"
|
||||
IsOpen="{x:Bind Mode=OneWay, Path=ViewModel.IsJumpEnabledGpoConfigured}"
|
||||
IsTabStop="{x:Bind Mode=OneWay, Path=ViewModel.IsJumpEnabledGpoConfigured}"
|
||||
Severity="Informational" />
|
||||
<labs:SettingsCard
|
||||
x:Uid="MouseUtils_MouseJump_ActivationShortcut"
|
||||
HeaderIcon="{ui:FontIcon FontFamily={StaticResource SymbolThemeFontFamily}, Glyph=}"
|
||||
IsEnabled="{x:Bind ViewModel.IsMouseJumpEnabled, Mode=OneWay}">
|
||||
<controls:ShortcutControl
|
||||
MinWidth="{StaticResource SettingActionControlMinWidth}"
|
||||
HotkeySettings="{x:Bind Path=ViewModel.MouseJumpActivationShortcut, Mode=TwoWay}" />
|
||||
</labs:SettingsCard>
|
||||
</controls:SettingsGroup>
|
||||
|
||||
<controls:SettingsGroup x:Uid="MouseUtils_MousePointerCrosshairs">
|
||||
<labs:SettingsCard
|
||||
x:Uid="MouseUtils_Enable_MousePointerCrosshairs"
|
||||
@ -296,6 +321,9 @@
|
||||
<controls:PageLink
|
||||
Link="https://devblogs.microsoft.com/oldnewthing/author/oldnewthing"
|
||||
Text="Raymond Chen's Find My Mouse" />
|
||||
<controls:PageLink
|
||||
Link="https://michael-clayton.com/projects/fancymouse"
|
||||
Text="Michael Clayton's Mouse Jump (FancyMouse)" />
|
||||
</controls:SettingsPageControl.SecondaryLinks>
|
||||
</controls:SettingsPageControl>
|
||||
</Page>
|
||||
|
@ -37,6 +37,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
||||
SettingsRepository<GeneralSettings>.GetInstance(settingsUtils),
|
||||
SettingsRepository<FindMyMouseSettings>.GetInstance(settingsUtils),
|
||||
SettingsRepository<MouseHighlighterSettings>.GetInstance(settingsUtils),
|
||||
SettingsRepository<MouseJumpSettings>.GetInstance(settingsUtils),
|
||||
SettingsRepository<MousePointerCrosshairsSettings>.GetInstance(settingsUtils),
|
||||
ShellPage.SendDefaultIPCMessage);
|
||||
|
||||
|
@ -15,6 +15,7 @@ std::vector<std::wstring> processes =
|
||||
L"PowerToys.PowerAccent.exe",
|
||||
L"PowerToys.PowerLauncher.exe",
|
||||
L"PowerToys.PowerOCR.exe",
|
||||
L"PowerToys.MouseJumpUI.exe",
|
||||
L"PowerToys.MeasureToolUI.exe",
|
||||
L"PowerToys.ShortcutGuide.exe",
|
||||
L"PowerToys.PowerRename.exe",
|
||||
|
@ -47,6 +47,7 @@ void ReportGPOValues(const std::filesystem::path& tmpDir)
|
||||
report << "getConfiguredKeyboardManagerEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredKeyboardManagerEnabledValue()) << std::endl;
|
||||
report << "getConfiguredFindMyMouseEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredFindMyMouseEnabledValue()) << std::endl;
|
||||
report << "getConfiguredMouseHighlighterEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredMouseHighlighterEnabledValue()) << std::endl;
|
||||
report << "getConfiguredMouseJumpEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredMouseJumpEnabledValue()) << std::endl;
|
||||
report << "getConfiguredMousePointerCrosshairsEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredMousePointerCrosshairsEnabledValue()) << std::endl;
|
||||
report << "getConfiguredPowerRenameEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredPowerRenameEnabledValue()) << std::endl;
|
||||
report << "getConfiguredPowerLauncherEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredPowerLauncherEnabledValue()) << std::endl;
|
||||
|
Loading…
Reference in New Issue
Block a user