mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-15 03:07:56 +01:00
[PastePlain] Introduce Paste as Plain Text module (#23645)
* [PastePlain] Introduce Paste as Plain Text module * fix build * add telemetry * update settings UI * spell * Add navigation items to Settings and OOBE * Add PastePlain to the Quick Access flyout * try to fix PastePlain not being enabled from runner/settings * load dll properly * installer files * Add PastePlain project name * Use win32 APIs in the module interface instead * Fix spellcheck * Fix build errors * Add success, error and invoke telemetry * Add Settings Telemetry * Add GPO definitions * Fix analyzer errors * Use static_cast instead of reinterpret_cast * Add images to Settings * Add note about replacing clipboard contents * Fix learn more text * Add link to readme * Remove unneeded C# app * Fix installer * Fix spellchecker --------- Co-authored-by: Jaime Bernardo <jaime@janeasystems.com>
This commit is contained in:
34
.github/actions/spell-check/expect.txt
vendored
34
.github/actions/spell-check/expect.txt
vendored
@@ -721,6 +721,7 @@ HTTRANSPARENT
|
||||
HValue
|
||||
Hvci
|
||||
hwb
|
||||
HWHEEL
|
||||
HWINEVENTHOOK
|
||||
hwnd
|
||||
HWNDFIRST
|
||||
@@ -893,6 +894,8 @@ LCONTROL
|
||||
LCtrl
|
||||
Ldone
|
||||
ldx
|
||||
LEFTDOWN
|
||||
LEFTUP
|
||||
LEFTSCROLLBAR
|
||||
lego
|
||||
len
|
||||
@@ -1041,6 +1044,8 @@ Mgmt
|
||||
mic
|
||||
microsoft
|
||||
Midl
|
||||
MIDDLEDOWN
|
||||
MIDDLEUP
|
||||
mii
|
||||
MIIM
|
||||
millis
|
||||
@@ -1174,6 +1179,7 @@ NOACTIVATE
|
||||
NOAGGREGATION
|
||||
NOASYNC
|
||||
NOCLOSEPROCESS
|
||||
NOCOALESCE
|
||||
NOCOPYBITS
|
||||
nodeca
|
||||
nodiscard
|
||||
@@ -1247,7 +1253,7 @@ oldpath
|
||||
oldtheme
|
||||
oleaut
|
||||
OLECHAR
|
||||
oledb
|
||||
OLEDB
|
||||
oledbcommand
|
||||
oledbconnection
|
||||
OLIVEGREEN
|
||||
@@ -1292,6 +1298,7 @@ PARENTRELATIVEPARSING
|
||||
PArgb
|
||||
parray
|
||||
PARTIALCONFIRMATIONDIALOGTITLE
|
||||
pasteplain
|
||||
pathcch
|
||||
Pathto
|
||||
PAUDIO
|
||||
@@ -1377,7 +1384,7 @@ Prefixer
|
||||
Preinstalled
|
||||
prevhost
|
||||
previewer
|
||||
previewhandlerframeinfo
|
||||
PREVIEWHANDLERFRAMEINFO
|
||||
previewpane
|
||||
previouscamera
|
||||
PREVIOUSINSTALLFOLDER
|
||||
@@ -1465,7 +1472,7 @@ rectp
|
||||
rects
|
||||
recyclebin
|
||||
redirectedfrom
|
||||
redist
|
||||
Redist
|
||||
redistributable
|
||||
reencode
|
||||
reencoded
|
||||
@@ -1522,6 +1529,8 @@ rgs
|
||||
rhs
|
||||
ricardosantos
|
||||
RIDEV
|
||||
RIGHTDOWN
|
||||
RIGHTUP
|
||||
RIGHTSCROLLBAR
|
||||
riid
|
||||
RKey
|
||||
@@ -1529,6 +1538,7 @@ RLO
|
||||
RMENU
|
||||
RNumber
|
||||
roadmap
|
||||
Roamable
|
||||
robmensching
|
||||
Roboto
|
||||
rooler
|
||||
@@ -1588,7 +1598,7 @@ secauthz
|
||||
secpol
|
||||
Secur
|
||||
securityoverview
|
||||
segoe
|
||||
Segoe
|
||||
Sekan
|
||||
SENDCHANGE
|
||||
sendinput
|
||||
@@ -1654,7 +1664,7 @@ SHOWMINNOACTIVE
|
||||
SHOWNA
|
||||
SHOWNOACTIVATE
|
||||
SHOWNORMAL
|
||||
showwindow
|
||||
SHOWWINDOW
|
||||
shtypes
|
||||
SICHINT
|
||||
sid
|
||||
@@ -1688,6 +1698,7 @@ Soref
|
||||
SOURCECLIENTAREAONLY
|
||||
SOURCEHEADER
|
||||
sourcesdirectory
|
||||
SPACEBAR
|
||||
spam
|
||||
spdisp
|
||||
spdlog
|
||||
@@ -1721,7 +1732,7 @@ STARTUPINFO
|
||||
STARTUPINFOEX
|
||||
STARTUPINFOW
|
||||
startupscreen
|
||||
statflag
|
||||
STATFLAG
|
||||
STATICEDGE
|
||||
STATSTG
|
||||
stdafx
|
||||
@@ -1733,7 +1744,7 @@ STDMETHODCALLTYPE
|
||||
STDMETHODIMP
|
||||
stefan
|
||||
Stereolithography
|
||||
stgm
|
||||
STGM
|
||||
STGMEDIUM
|
||||
sticpl
|
||||
stl
|
||||
@@ -1780,7 +1791,7 @@ SYSICONINDEX
|
||||
sysinfo
|
||||
SYSKEY
|
||||
syskeydown
|
||||
syskeyup
|
||||
SYSKEYUP
|
||||
SYSMENU
|
||||
SYSTEMAPPS
|
||||
systemroot
|
||||
@@ -1893,6 +1904,7 @@ UIs
|
||||
Ulaanbaatar
|
||||
ULARGE
|
||||
ULONGLONG
|
||||
UMsg
|
||||
unassign
|
||||
uncompilable
|
||||
UNCPRIORITY
|
||||
@@ -1972,6 +1984,7 @@ VIDEOINFOHEADER
|
||||
viewbox
|
||||
viewmodel
|
||||
vih
|
||||
VIRTUALDESK
|
||||
virtualkey
|
||||
visiblecolorformats
|
||||
Visibletrue
|
||||
@@ -2062,7 +2075,7 @@ WINL
|
||||
winmd
|
||||
winmm
|
||||
winmsg
|
||||
winnt
|
||||
WINNT
|
||||
winres
|
||||
winrt
|
||||
winsdk
|
||||
@@ -2130,6 +2143,7 @@ wtypes
|
||||
Wubi
|
||||
wuceffectsi
|
||||
WVC
|
||||
WVk
|
||||
Wwan
|
||||
Wwanpp
|
||||
XAttribute
|
||||
@@ -2142,6 +2156,8 @@ XBUTTONUP
|
||||
XControl
|
||||
xcopy
|
||||
XDocument
|
||||
XDOWN
|
||||
XUP
|
||||
XElement
|
||||
XFile
|
||||
XIncrement
|
||||
|
||||
2
.github/actions/spell-check/patterns.txt
vendored
2
.github/actions/spell-check/patterns.txt
vendored
@@ -56,7 +56,7 @@ https?://(?:(?:www\.|)youtube\.com|youtu.be)/[-a-zA-Z0-9?&=]*
|
||||
/gist\.github\.com/[^/]+/[0-9a-f]+
|
||||
|
||||
# msdn
|
||||
\b(?:download\.visualstudio|docs|msdn)\.microsoft\.com/[-_a-zA-Z0-9()=./]*
|
||||
\b(?:download\.visualstudio|docs|msdn|learn)\.microsoft\.com/[-_a-zA-Z0-9()=./]*
|
||||
|
||||
# medium
|
||||
link\.medium\.com/[a-zA-Z0-9]+
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
"modules\\PowerOCR\\PowerToys.PowerOCR.dll",
|
||||
"modules\\PowerOCR\\PowerToys.PowerOCR.exe",
|
||||
|
||||
"modules\\PastePlain\\PowerToys.PastePlainModuleInterface.dll",
|
||||
|
||||
"modules\\Awake\\PowerToys.AwakeModuleInterface.dll",
|
||||
"modules\\Awake\\PowerToys.Awake.exe",
|
||||
"modules\\Awake\\PowerToys.Awake.dll",
|
||||
|
||||
@@ -487,7 +487,11 @@ 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("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AllExperiments", "src\common\AllExperiments\AllExperiments.csproj", "{9CE59ED5-7087-4353-88EB-788038A73CEC}"
|
||||
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}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AllExperiments", "src\common\AllExperiments\AllExperiments.csproj", "{9CE59ED5-7087-4353-88EB-788038A73CEC}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@@ -2024,6 +2028,18 @@ 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
|
||||
{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
|
||||
{FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Debug|x64.Build.0 = Debug|x64
|
||||
{FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Debug|x86.Build.0 = Debug|x64
|
||||
{FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Release|x64.ActiveCfg = Release|x64
|
||||
{FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Release|x64.Build.0 = Release|x64
|
||||
{FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Release|x86.ActiveCfg = Release|x64
|
||||
{FC373B24-3293-453C-AAF5-CF2909DCEE6A}.Release|x86.Build.0 = Release|x64
|
||||
{9CE59ED5-7087-4353-88EB-788038A73CEC}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{9CE59ED5-7087-4353-88EB-788038A73CEC}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{9CE59ED5-7087-4353-88EB-788038A73CEC}.Debug|x64.ActiveCfg = Debug|x64
|
||||
@@ -2206,6 +2222,8 @@ 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}
|
||||
{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}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
|
||||
@@ -20,9 +20,9 @@ Microsoft PowerToys is a set of utilities for power users to tune and streamline
|
||||
| [Always on Top](https://aka.ms/PowerToysOverview_AoT) | [PowerToys Awake](https://aka.ms/PowerToysOverview_Awake) | [Color Picker](https://aka.ms/PowerToysOverview_ColorPicker) |
|
||||
| [FancyZones](https://aka.ms/PowerToysOverview_FancyZones) | [File Explorer Add-ons](https://aka.ms/PowerToysOverview_FileExplorerAddOns) | [File Locksmith](https://aka.ms/PowerToysOverview_FileLocksmith) |
|
||||
| [Hosts File Editor](https://aka.ms/PowerToysOverview_HostsFileEditor) | [Image Resizer](https://aka.ms/PowerToysOverview_ImageResizer) | [Keyboard Manager](https://aka.ms/PowerToysOverview_KeyboardManager) |
|
||||
| [Mouse utilities](https://aka.ms/PowerToysOverview_MouseUtilities) | [PowerRename](https://aka.ms/PowerToysOverview_PowerRename) | [PowerToys Run](https://aka.ms/PowerToysOverview_PowerToysRun) |
|
||||
| [Quick Accent](https://aka.ms/PowerToysOverview_QuickAccent) | [Screen Ruler](https://aka.ms/PowerToysOverview_ScreenRuler) | [Shortcut Guide](https://aka.ms/PowerToysOverview_ShortcutGuide) |
|
||||
| [Text Extractor](https://aka.ms/PowerToysOverview_TextExtractor) | [Video Conference Mute](https://aka.ms/PowerToysOverview_VideoConference) |
|
||||
| [Mouse utilities](https://aka.ms/PowerToysOverview_MouseUtilities) | [Paste as Plain Text](https://aka.ms/PowerToysOverview_PastePlain) | [PowerRename](https://aka.ms/PowerToysOverview_PowerRename) |
|
||||
| [PowerToys Run](https://aka.ms/PowerToysOverview_PowerToysRun) | [Quick Accent](https://aka.ms/PowerToysOverview_QuickAccent) | [Screen Ruler](https://aka.ms/PowerToysOverview_ScreenRuler) |
|
||||
| [Shortcut Guide](https://aka.ms/PowerToysOverview_ShortcutGuide) | [Text Extractor](https://aka.ms/PowerToysOverview_TextExtractor) | [Video Conference Mute](https://aka.ms/PowerToysOverview_VideoConference) |
|
||||
|
||||
## Installing and running Microsoft PowerToys
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
<?define AlwaysOnTopProjectName="AlwaysOnTop"?>
|
||||
<?define MeasureToolProjectName="MeasureTool"?>
|
||||
<?define HostsProjectName="Hosts"?>
|
||||
<?define PastePlainProjectName="PastePlain"?>
|
||||
|
||||
<?define RepoDir="$(var.ProjectDir)..\..\" ?>
|
||||
<?if $(var.Platform) = x64?>
|
||||
|
||||
20
installer/PowerToysSetup/PastePlain.wxs
Normal file
20
installer/PowerToysSetup/PastePlain.wxs
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
|
||||
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension" >
|
||||
|
||||
<?include $(sys.CURRENTDIR)\Common.wxi?>
|
||||
|
||||
<Fragment>
|
||||
<DirectoryRef Id="PastePlainInstallFolder" FileSource="$(var.BinDir)modules\$(var.PastePlainProjectName)">
|
||||
<!-- !Warning! Make sure to change Component Guid if you update the file list -->
|
||||
<Component Id="Module_PastePlain" Win64="yes">
|
||||
<File Source="$(var.BinDir)modules\$(var.PastePlainProjectName)\PowerToys.PastePlainModuleInterface.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
|
||||
<ComponentGroup Id="PastePlainComponentGroup" Directory="INSTALLFOLDER">
|
||||
<ComponentRef Id="Module_PastePlain" />
|
||||
</ComponentGroup>
|
||||
|
||||
</Fragment>
|
||||
</Wix>
|
||||
@@ -74,6 +74,7 @@ call "..\..\publish.cmd" arm64
|
||||
<Compile Include="KeyboardManager.wxs" />
|
||||
<Compile Include="MeasureTool.wxs" />
|
||||
<Compile Include="MouseUtils.wxs" />
|
||||
<Compile Include="PastePlain.wxs" />
|
||||
<Compile Include="PowerAccent.wxs" />
|
||||
<Compile Include="PowerRename.wxs" />
|
||||
<Compile Include="Run.wxs" />
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
<ComponentGroupRef Id="KeyboardManagerComponentGroup" />
|
||||
<ComponentGroupRef Id="MeasureToolComponentGroup" />
|
||||
<ComponentGroupRef Id="MouseUtilsComponentGroup" />
|
||||
<ComponentGroupRef Id="PastePlainComponentGroup" />
|
||||
<ComponentGroupRef Id="PowerAccentComponentGroup" />
|
||||
<ComponentGroupRef Id="PowerRenameComponentGroup" />
|
||||
<ComponentGroupRef Id="RunComponentGroup" />
|
||||
@@ -478,6 +479,10 @@
|
||||
<Directory Id="MouseUtilsInstallFolder" Name="$(var.MouseUtilsProjectName)">
|
||||
</Directory>
|
||||
|
||||
<!-- PastePlain -->
|
||||
<Directory Id="PastePlainInstallFolder" Name="$(var.PastePlainProjectName)">
|
||||
</Directory>
|
||||
|
||||
<!-- AlwaysOnTop -->
|
||||
<Directory Id="AlwaysOnTopInstallFolder" Name="$(var.AlwaysOnTopProjectName)">
|
||||
</Directory>
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
<?include $(sys.CURRENTDIR)\Common.wxi?>
|
||||
|
||||
<?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;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;PowerAccent.gif;PowerOCR.gif;PowerRename.gif;Run.gif;ScreenRuler.gif;OOBEShortcutGuide.png;VideoConferenceMute.png;OOBEPTHero.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;PowerAccent.png;PowerOcr.png;PowerRename.png;PowerToys.png;PowerToysRun.png;ScreenRuler.png;Settings.png;ShortcutGuide.png;VideoConferenceMute.png?>
|
||||
<?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?>
|
||||
<?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 SettingsV2MicrosoftUIXamlAssetsInstallFiles=NoiseAsset_256x256_PNG.png?>
|
||||
|
||||
<!-- These files are needed for release builds to contain the experimentation DLLs -->
|
||||
|
||||
@@ -108,6 +108,10 @@ namespace winrt::PowerToys::GPOWrapper::implementation
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredTextExtractorEnabledValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredPastePlainEnabledValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredPastePlainEnabledValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredVideoConferenceMuteEnabledValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredVideoConferenceMuteEnabledValue());
|
||||
|
||||
@@ -33,6 +33,7 @@ namespace winrt::PowerToys::GPOWrapper::implementation
|
||||
static GpoRuleConfigured GetConfiguredScreenRulerEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredShortcutGuideEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredTextExtractorEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredPastePlainEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredVideoConferenceMuteEnabledValue();
|
||||
static GpoRuleConfigured GetAllowExperimentationValue();
|
||||
};
|
||||
|
||||
@@ -37,6 +37,7 @@ namespace PowerToys
|
||||
static GpoRuleConfigured GetConfiguredScreenRulerEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredShortcutGuideEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredTextExtractorEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredPastePlainEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredVideoConferenceMuteEnabledValue();
|
||||
static GpoRuleConfigured GetAllowExperimentationValue();
|
||||
}
|
||||
|
||||
@@ -41,5 +41,10 @@ namespace PowerToys.GPOWrapperProjection
|
||||
{
|
||||
return (GpoRuleConfigured)PowerToys.GPOWrapper.GPOWrapper.GetConfiguredTextExtractorEnabledValue();
|
||||
}
|
||||
|
||||
public static GpoRuleConfigured GetConfiguredPastePlainEnabledValue()
|
||||
{
|
||||
return (GpoRuleConfigured)PowerToys.GPOWrapper.GPOWrapper.GetConfiguredPastePlainEnabledValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ namespace powertoys_gpo {
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_SCREEN_RULER = L"ConfigureEnabledUtilityScreenRuler";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_SHORTCUT_GUIDE = L"ConfigureEnabledUtilityShortcutGuide";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_TEXT_EXTRACTOR = L"ConfigureEnabledUtilityTextExtractor";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_PASTE_PLAIN = L"ConfigureEnabledUtilityPastePlain";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_VIDEO_CONFERENCE_MUTE = L"ConfigureEnabledUtilityVideoConferenceMute";
|
||||
const std::wstring POLICY_ALLOW_EXPERIMENTATION = L"AllowExperimentation";
|
||||
|
||||
@@ -231,6 +232,11 @@ namespace powertoys_gpo {
|
||||
return getConfiguredValue(POLICY_CONFIGURE_ENABLED_TEXT_EXTRACTOR);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getConfiguredPastePlainEnabledValue()
|
||||
{
|
||||
return getConfiguredValue(POLICY_CONFIGURE_ENABLED_PASTE_PLAIN);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getConfiguredVideoConferenceMuteEnabledValue()
|
||||
{
|
||||
return getConfiguredValue(POLICY_CONFIGURE_ENABLED_VIDEO_CONFERENCE_MUTE);
|
||||
|
||||
@@ -217,6 +217,16 @@
|
||||
<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" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="ConfigureEnabledUtilityPowerRename" class="Both" displayName="$(string.ConfigureEnabledUtilityPowerRename)" explainText="$(string.ConfigureEnabledUtilityDescription)" key="Software\Policies\PowerToys" valueName="ConfigureEnabledUtilityPowerRename">
|
||||
<parentCategory ref="PowerToys" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_64_0" />
|
||||
|
||||
@@ -55,6 +55,7 @@ If this setting is disabled, experimentation is not allowed.
|
||||
<string id="ConfigureEnabledUtilityFindMyMouse">Find My Mouse: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityMouseHighlighter">Mouse Highlighter: 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>
|
||||
<string id="ConfigureEnabledUtilityPowerLauncher">PowerToys Run: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityQuickAccent">Quick Accent: Configure enabled state</string>
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
namespace PastePlainConstants
|
||||
{
|
||||
// Name of the powertoy module.
|
||||
inline const std::wstring ModuleKey = L"PastePlain";
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" 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')" />
|
||||
<Target Name="GenerateResourceFiles" BeforeTargets="PrepareForBuild">
|
||||
<Exec Command="powershell -NonInteractive -executionpolicy Unrestricted $(SolutionDir)tools\build\convert-resx-to-rc.ps1 $(MSBuildThisFileDirectory) resource.base.h resource.h PastePlain.base.rc PastePlain.rc" />
|
||||
</Target>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{FC373B24-3293-453C-AAF5-CF2909DCEE6A}</ProjectGuid>
|
||||
<RootNamespace>PastePlain</RootNamespace>
|
||||
<ProjectName>PastePlainModuleInterface</ProjectName>
|
||||
<TargetName>PowerToys.PastePlainModuleInterface</TargetName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
</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\PastePlain\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>EXAMPLEPOWERTOY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\..\common\inc;..\..\..\common\Telemetry;..\..\;..\..\..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="PastePlainConstants.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<None Include="packages.config" />
|
||||
<None Include="resource.base.h" />
|
||||
<ClInclude Include="trace.h" />
|
||||
<ClInclude Include="Generated Files\resource.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>
|
||||
<None Include="PastePlain.base.rc" />
|
||||
<ResourceCompile Include="Generated Files\PastePlain.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources.resx">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
</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>
|
||||
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Generated Files">
|
||||
<UniqueIdentifier>{875a08c6-f610-4667-bd0f-80171ed96072}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Generated Files\resource.h">
|
||||
<Filter>Generated Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PastePlainConstants.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="trace.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="trace.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="resource.base.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</None>
|
||||
<None Include="Resources.resx">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="packages.config" />
|
||||
<None Include="PastePlain.base.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="Generated Files\PastePlain.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
126
src/modules/pasteplain/PastePlainModuleInterface/Resources.resx
Normal file
126
src/modules/pasteplain/PastePlainModuleInterface/Resources.resx
Normal file
@@ -0,0 +1,126 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<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>
|
||||
<data name="PastePlain_Name" xml:space="preserve">
|
||||
<value>Paste As Plain Text</value>
|
||||
</data>
|
||||
<data name="PastePlain_Settings_Desc" xml:space="preserve">
|
||||
<value>PowerToys integration to paste clipboard contents as plain text</value>
|
||||
</data>
|
||||
</root>
|
||||
495
src/modules/pasteplain/PastePlainModuleInterface/dllmain.cpp
Normal file
495
src/modules/pasteplain/PastePlainModuleInterface/dllmain.cpp
Normal file
@@ -0,0 +1,495 @@
|
||||
// dllmain.cpp : Defines the entry point for the DLL application.
|
||||
#include "pch.h"
|
||||
|
||||
#include <interface/powertoy_module_interface.h>
|
||||
#include "trace.h"
|
||||
#include "Generated Files/resource.h"
|
||||
#include <common/logger/logger.h>
|
||||
#include <common/SettingsAPI/settings_objects.h>
|
||||
#include <common/utils/resources.h>
|
||||
|
||||
#include "PastePlainConstants.h"
|
||||
#include <common/interop/shared_constants.h>
|
||||
#include <common/utils/logger_helper.h>
|
||||
#include <common/utils/winapi_error.h>
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE /*hModule*/,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID /*lpReserved*/)
|
||||
{
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
Trace::RegisterProvider();
|
||||
break;
|
||||
case DLL_THREAD_ATTACH:
|
||||
break;
|
||||
case DLL_THREAD_DETACH:
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
Trace::UnregisterProvider();
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
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"ActivationShortcut";
|
||||
}
|
||||
|
||||
struct ModuleSettings
|
||||
{
|
||||
} g_settings;
|
||||
|
||||
class PastePlain : public PowertoyModuleIface
|
||||
{
|
||||
private:
|
||||
bool m_enabled = false;
|
||||
|
||||
std::wstring app_name;
|
||||
|
||||
//contains the non localized key of the powertoy
|
||||
std::wstring app_key;
|
||||
|
||||
HANDLE m_hProcess;
|
||||
|
||||
// Time to wait for process to close after sending WM_CLOSE signal
|
||||
static const int MAX_WAIT_MILLISEC = 10000;
|
||||
|
||||
Hotkey m_hotkey;
|
||||
|
||||
// Handle to event used to invoke PastePlain
|
||||
HANDLE m_hInvokeEvent;
|
||||
|
||||
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 PastePlain start shortcut");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::info("PastePlain settings are empty");
|
||||
}
|
||||
|
||||
if (!m_hotkey.key)
|
||||
{
|
||||
Logger::info("PastePlain is going to use default shortcut");
|
||||
m_hotkey.win = true;
|
||||
m_hotkey.alt = false;
|
||||
m_hotkey.shift = false;
|
||||
m_hotkey.ctrl = true;
|
||||
m_hotkey.key = 'V';
|
||||
}
|
||||
}
|
||||
|
||||
bool is_process_running()
|
||||
{
|
||||
return WaitForSingleObject(m_hProcess, 0) == WAIT_TIMEOUT;
|
||||
}
|
||||
|
||||
void launch_process()
|
||||
{
|
||||
Logger::trace(L"Starting PastePlain 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\\PastePlain\\PowerToys.PastePlain.exe";
|
||||
sei.nShow = SW_SHOWNORMAL;
|
||||
sei.lpParameters = executable_args.data();
|
||||
if (ShellExecuteExW(&sei))
|
||||
{
|
||||
Logger::trace("Successfully started the PastePlain process");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::error(L"PastePlain failed to start. {}", get_last_error_or_default(GetLastError()));
|
||||
}
|
||||
|
||||
m_hProcess = sei.hProcess;
|
||||
}
|
||||
|
||||
// Load the settings file.
|
||||
void init_settings()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Load and parse the settings file for this PowerToy.
|
||||
PowerToysSettings::PowerToyValues settings =
|
||||
PowerToysSettings::PowerToyValues::load_from_settings_file(get_key());
|
||||
|
||||
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.
|
||||
}
|
||||
}
|
||||
|
||||
void try_inject_modifier_key_up(std::vector<INPUT> &inputs, short modifier)
|
||||
{
|
||||
// Most significant bit is set if key is down
|
||||
if ((GetAsyncKeyState(static_cast<int>(modifier)) & 0x8000) != 0)
|
||||
{
|
||||
INPUT input_event = {};
|
||||
input_event.type = INPUT_KEYBOARD;
|
||||
input_event.ki.wVk = modifier;
|
||||
input_event.ki.dwFlags = KEYEVENTF_KEYUP;
|
||||
inputs.push_back(input_event);
|
||||
}
|
||||
}
|
||||
|
||||
void try_to_paste_as_plain_text()
|
||||
{
|
||||
std::wstring clipboard_text;
|
||||
|
||||
{
|
||||
// Read clipboard data begin
|
||||
|
||||
if (!OpenClipboard(NULL))
|
||||
{
|
||||
DWORD errorCode = GetLastError();
|
||||
auto errorMessage = get_last_error_message(errorCode);
|
||||
Logger::error(L"Couldn't open the clipboard to get the text. {}", errorMessage.has_value() ? errorMessage.value() : L"");
|
||||
Trace::PastePlainError(errorCode, errorMessage.has_value() ? errorMessage.value() : L"", L"read.OpenClipboard");
|
||||
return;
|
||||
}
|
||||
HANDLE h_clipboard_data = GetClipboardData(CF_UNICODETEXT);
|
||||
|
||||
if (h_clipboard_data == NULL)
|
||||
{
|
||||
DWORD errorCode = GetLastError();
|
||||
auto errorMessage = get_last_error_message(errorCode);
|
||||
Logger::error(L"Failed to get clipboard data. {}", errorMessage.has_value() ? errorMessage.value() : L"");
|
||||
Trace::PastePlainError(errorCode, errorMessage.has_value() ? errorMessage.value() : L"", L"read.GetClipboardData");
|
||||
CloseClipboard();
|
||||
return;
|
||||
}
|
||||
|
||||
wchar_t* pch_data= static_cast<wchar_t*>(GlobalLock(h_clipboard_data));
|
||||
|
||||
if (NULL == pch_data )
|
||||
{
|
||||
DWORD errorCode = GetLastError();
|
||||
auto errorMessage = get_last_error_message(errorCode);
|
||||
Logger::error(L"Couldn't lock the buffer to get the unformatted text from the clipboard. {}", errorMessage.has_value() ? errorMessage.value() : L"");
|
||||
Trace::PastePlainError(errorCode, errorMessage.has_value() ? errorMessage.value() : L"", L"read.GlobalLock");
|
||||
CloseClipboard();
|
||||
return;
|
||||
}
|
||||
|
||||
clipboard_text = pch_data;
|
||||
GlobalUnlock(h_clipboard_data);
|
||||
|
||||
CloseClipboard();
|
||||
// Read clipboard data end
|
||||
}
|
||||
|
||||
{
|
||||
// Copy text to clipboard begin
|
||||
UINT no_clipboard_history_or_roaming_format = 0;
|
||||
|
||||
// Get the format identifier for not adding the data to the clipboard history or roaming.
|
||||
// https://learn.microsoft.com/en-us/windows/win32/dataxchg/clipboard-formats#cloud-clipboard-and-clipboard-history-formats
|
||||
if (0 == (no_clipboard_history_or_roaming_format = RegisterClipboardFormat(L"ExcludeClipboardContentFromMonitorProcessing")))
|
||||
{
|
||||
DWORD errorCode = GetLastError();
|
||||
auto errorMessage = get_last_error_message(errorCode);
|
||||
Logger::error(L"Couldn't get the clipboard data format type that would allow excluding the data from the clipboard history / roaming. {}", errorMessage.has_value() ? errorMessage.value() : L"");
|
||||
Trace::PastePlainError(errorCode, errorMessage.has_value() ? errorMessage.value() : L"", L"write.RegisterClipboardFormat");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!OpenClipboard(NULL))
|
||||
{
|
||||
DWORD errorCode = GetLastError();
|
||||
auto errorMessage = get_last_error_message(errorCode);
|
||||
Logger::error(L"Couldn't open the clipboard to copy the unformatted text. {}", errorMessage.has_value() ? errorMessage.value() : L"");
|
||||
Trace::PastePlainError(errorCode, errorMessage.has_value() ? errorMessage.value() : L"", L"write.OpenClipboard");
|
||||
return;
|
||||
}
|
||||
|
||||
HGLOBAL h_clipboard_data;
|
||||
|
||||
if (NULL == (h_clipboard_data = GlobalAlloc(GMEM_MOVEABLE, (clipboard_text.length() + 1) * sizeof(wchar_t))))
|
||||
{
|
||||
DWORD errorCode = GetLastError();
|
||||
auto errorMessage = get_last_error_message(errorCode);
|
||||
Logger::error(L"Couldn't allocate a buffer for the unformatted text. {}", errorMessage.has_value() ? errorMessage.value() : L"");
|
||||
Trace::PastePlainError(errorCode, errorMessage.has_value() ? errorMessage.value() : L"", L"write.GlobalAlloc");
|
||||
CloseClipboard();
|
||||
return;
|
||||
}
|
||||
wchar_t* pch_data = static_cast<wchar_t*>(GlobalLock(h_clipboard_data));
|
||||
|
||||
if (NULL == pch_data)
|
||||
{
|
||||
DWORD errorCode = GetLastError();
|
||||
auto errorMessage = get_last_error_message(errorCode);
|
||||
Logger::error(L"Couldn't lock the buffer to send the unformatted text to the clipboard. {}", errorMessage.has_value() ? errorMessage.value() : L"");
|
||||
GlobalFree(h_clipboard_data);
|
||||
CloseClipboard();
|
||||
Trace::PastePlainError(errorCode, errorMessage.has_value() ? errorMessage.value() : L"", L"write.GlobalLock");
|
||||
return;
|
||||
}
|
||||
|
||||
wcscpy_s(pch_data, clipboard_text.length() + 1, clipboard_text.c_str());
|
||||
|
||||
EmptyClipboard();
|
||||
|
||||
if (NULL == SetClipboardData(CF_UNICODETEXT, h_clipboard_data))
|
||||
{
|
||||
DWORD errorCode = GetLastError();
|
||||
auto errorMessage = get_last_error_message(errorCode);
|
||||
Logger::error(L"Couldn't set the clipboard data to the unformatted text. {}", errorMessage.has_value() ? errorMessage.value() : L"");
|
||||
GlobalUnlock(h_clipboard_data);
|
||||
GlobalFree(h_clipboard_data);
|
||||
CloseClipboard();
|
||||
Trace::PastePlainError(errorCode, errorMessage.has_value() ? errorMessage.value() : L"", L"write.SetClipboardData");
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't show in history or allow data roaming.
|
||||
SetClipboardData(no_clipboard_history_or_roaming_format, 0);
|
||||
|
||||
CloseClipboard();
|
||||
// Copy text to clipboard end
|
||||
}
|
||||
{
|
||||
// Clear kb state and send Ctrl+V begin
|
||||
|
||||
// we can assume that the last pressed key is...
|
||||
// (1) not a modifier key and
|
||||
// (2) marked as handled (so it never gets a key down input event).
|
||||
// So, let's check which modifiers were pressed,
|
||||
// and, if they were, inject a key up event for each of them
|
||||
std::vector<INPUT> inputs;
|
||||
try_inject_modifier_key_up(inputs, VK_LCONTROL);
|
||||
try_inject_modifier_key_up(inputs, VK_RCONTROL);
|
||||
try_inject_modifier_key_up(inputs, VK_LWIN);
|
||||
try_inject_modifier_key_up(inputs, VK_RWIN);
|
||||
try_inject_modifier_key_up(inputs, VK_LSHIFT);
|
||||
try_inject_modifier_key_up(inputs, VK_RSHIFT);
|
||||
try_inject_modifier_key_up(inputs, VK_LMENU);
|
||||
try_inject_modifier_key_up(inputs, VK_RMENU);
|
||||
|
||||
// send Ctrl+V (key downs and key ups)
|
||||
{
|
||||
INPUT input_event = {};
|
||||
input_event.type = INPUT_KEYBOARD;
|
||||
input_event.ki.wVk = VK_CONTROL;
|
||||
inputs.push_back(input_event);
|
||||
}
|
||||
|
||||
{
|
||||
INPUT input_event = {};
|
||||
input_event.type = INPUT_KEYBOARD;
|
||||
input_event.ki.wVk = 0x56; // V
|
||||
inputs.push_back(input_event);
|
||||
}
|
||||
|
||||
{
|
||||
INPUT input_event = {};
|
||||
input_event.type = INPUT_KEYBOARD;
|
||||
input_event.ki.wVk = 0x56; // V
|
||||
input_event.ki.dwFlags = KEYEVENTF_KEYUP;
|
||||
inputs.push_back(input_event);
|
||||
}
|
||||
|
||||
{
|
||||
INPUT input_event = {};
|
||||
input_event.type = INPUT_KEYBOARD;
|
||||
input_event.ki.wVk = VK_CONTROL;
|
||||
input_event.ki.dwFlags = KEYEVENTF_KEYUP;
|
||||
inputs.push_back(input_event);
|
||||
}
|
||||
|
||||
auto uSent = SendInput(static_cast<UINT>(inputs.size()), inputs.data(), sizeof(INPUT));
|
||||
if (uSent != inputs.size())
|
||||
{
|
||||
DWORD errorCode = GetLastError();
|
||||
auto errorMessage = get_last_error_message(errorCode);
|
||||
Logger::error(L"SendInput failed. Expected to send {} inputs and sent only {}. {}", inputs.size(), uSent, errorMessage.has_value() ? errorMessage.value() : L"");
|
||||
Trace::PastePlainError(errorCode, errorMessage.has_value() ? errorMessage.value() : L"", L"input.SendInput");
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear kb state and send Ctrl+V end
|
||||
}
|
||||
Trace::PastePlainSuccess();
|
||||
}
|
||||
|
||||
public:
|
||||
PastePlain()
|
||||
{
|
||||
app_name = GET_RESOURCE_STRING(IDS_PASTEPLAIN_NAME);
|
||||
app_key = PastePlainConstants::ModuleKey;
|
||||
LoggerHelpers::init_logger(app_key, L"ModuleInterface", "PastePlain");
|
||||
init_settings();
|
||||
}
|
||||
|
||||
~PastePlain()
|
||||
{
|
||||
if (m_enabled)
|
||||
{
|
||||
}
|
||||
m_enabled = false;
|
||||
}
|
||||
|
||||
// Destroy the powertoy and free memory
|
||||
virtual void destroy() override
|
||||
{
|
||||
Logger::trace("PastePlain::destroy()");
|
||||
delete this;
|
||||
}
|
||||
|
||||
// Return the localized display name of the powertoy
|
||||
virtual const wchar_t* get_name() override
|
||||
{
|
||||
return app_name.c_str();
|
||||
}
|
||||
|
||||
// Return the non localized key of the powertoy, this will be cached by the runner
|
||||
virtual const wchar_t* get_key() override
|
||||
{
|
||||
return app_key.c_str();
|
||||
}
|
||||
|
||||
// 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::getConfiguredPastePlainEnabledValue();
|
||||
}
|
||||
|
||||
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(GET_RESOURCE_STRING(IDS_PASTEPLAIN_SETTINGS_DESC));
|
||||
|
||||
settings.set_overview_link(L"https://aka.ms/PowerToysOverview_PastePlain");
|
||||
|
||||
return settings.serialize_to_buffer(buffer, buffer_size);
|
||||
}
|
||||
|
||||
virtual void call_custom_action(const wchar_t* /*action*/) override
|
||||
{
|
||||
}
|
||||
|
||||
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);
|
||||
// If you don't need to do any custom processing of the settings, proceed
|
||||
// to persists the values calling:
|
||||
values.save_to_settings_file();
|
||||
// Otherwise call a custom function to process the settings before saving them to disk:
|
||||
// save_settings();
|
||||
}
|
||||
catch (std::exception&)
|
||||
{
|
||||
// Improper JSON.
|
||||
}
|
||||
}
|
||||
|
||||
virtual void enable()
|
||||
{
|
||||
Logger::trace("PastePlain::enable()");
|
||||
m_enabled = true;
|
||||
Trace::EnablePastePlain(true);
|
||||
};
|
||||
|
||||
virtual void disable()
|
||||
{
|
||||
Logger::trace("PastePlain::disable()");
|
||||
m_enabled = false;
|
||||
Trace::EnablePastePlain(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
virtual bool on_hotkey(size_t /*hotkeyId*/) override
|
||||
{
|
||||
if (m_enabled)
|
||||
{
|
||||
Logger::trace(L"PastePlain hotkey pressed");
|
||||
|
||||
std::thread([=]() {
|
||||
// hotkey work should be kept to a minimum, or Windows might deregister our low level keyboard hook.
|
||||
// Move work to another thread.
|
||||
try_to_paste_as_plain_text();
|
||||
}).detach();
|
||||
|
||||
Trace::PastePlainInvoked();
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool is_enabled() override
|
||||
{
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
virtual void send_settings_telemetry() override
|
||||
{
|
||||
Logger::info("Send settings telemetry");
|
||||
Trace::SettingsTelemetry(m_hotkey);
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create()
|
||||
{
|
||||
return new PastePlain();
|
||||
}
|
||||
@@ -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>
|
||||
2
src/modules/pasteplain/PastePlainModuleInterface/pch.cpp
Normal file
2
src/modules/pasteplain/PastePlainModuleInterface/pch.cpp
Normal file
@@ -0,0 +1,2 @@
|
||||
#include "pch.h"
|
||||
|
||||
7
src/modules/pasteplain/PastePlainModuleInterface/pch.h
Normal file
7
src/modules/pasteplain/PastePlainModuleInterface/pch.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.Foundation.Collections.h>
|
||||
#include <ProjectTelemetry.h>
|
||||
#include <shellapi.h>
|
||||
#include <Shlwapi.h>
|
||||
@@ -0,0 +1,13 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by PowerOCR.rc
|
||||
|
||||
//////////////////////////////
|
||||
// Non-localizable
|
||||
|
||||
#define FILE_DESCRIPTION "PowerToys PastePlain"
|
||||
#define INTERNAL_NAME "PowerToys.PastePlainModuleInterface"
|
||||
#define ORIGINAL_FILENAME "PowerToys.PastePlainModuleInterface.dll"
|
||||
|
||||
// Non-localizable
|
||||
//////////////////////////////
|
||||
82
src/modules/pasteplain/PastePlainModuleInterface/trace.cpp
Normal file
82
src/modules/pasteplain/PastePlainModuleInterface/trace.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
#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);
|
||||
}
|
||||
|
||||
// Log if the user has PastePlain enabled or disabled
|
||||
void Trace::EnablePastePlain(const bool enabled) noexcept
|
||||
{
|
||||
TraceLoggingWrite(
|
||||
g_hProvider,
|
||||
"PastePlain_EnablePastePlain",
|
||||
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
|
||||
TraceLoggingBoolean(enabled, "Enabled"));
|
||||
}
|
||||
|
||||
// Log if the user has invoked PastePlain
|
||||
void Trace::PastePlainInvoked() noexcept
|
||||
{
|
||||
TraceLoggingWrite(
|
||||
g_hProvider,
|
||||
"PastePlain_InvokePastePlain",
|
||||
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
|
||||
}
|
||||
|
||||
// Log if a PastePlain invocation has succeeded
|
||||
void Trace::PastePlainSuccess() noexcept
|
||||
{
|
||||
TraceLoggingWrite(
|
||||
g_hProvider,
|
||||
"PastePlain_Success",
|
||||
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
|
||||
}
|
||||
|
||||
// Log if an error occurs in PastePlain
|
||||
void Trace::PastePlainError(const DWORD errorCode, std::wstring errorMessage, std::wstring methodName) noexcept
|
||||
{
|
||||
TraceLoggingWrite(
|
||||
g_hProvider,
|
||||
"PastePlain_Error",
|
||||
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
|
||||
TraceLoggingValue(methodName.c_str(), "MethodName"),
|
||||
TraceLoggingValue(errorCode, "ErrorCode"),
|
||||
TraceLoggingValue(errorMessage.c_str(), "ErrorMessage"));
|
||||
}
|
||||
|
||||
// Event to send settings telemetry.
|
||||
void Trace::SettingsTelemetry(PowertoyModuleIface::Hotkey& hotkey) noexcept
|
||||
{
|
||||
std::wstring hotKeyStr =
|
||||
std::wstring(hotkey.win ? L"Win + " : L"") +
|
||||
std::wstring(hotkey.ctrl ? L"Ctrl + " : L"") +
|
||||
std::wstring(hotkey.shift ? L"Shift + " : L"") +
|
||||
std::wstring(hotkey.alt ? L"Alt + " : L"") +
|
||||
std::wstring(L"VK ") + std::to_wstring(hotkey.key);
|
||||
|
||||
TraceLoggingWrite(
|
||||
g_hProvider,
|
||||
"PastePlain_Settings",
|
||||
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
|
||||
TraceLoggingWideString(hotKeyStr.c_str(), "HotKey")
|
||||
);
|
||||
}
|
||||
24
src/modules/pasteplain/PastePlainModuleInterface/trace.h
Normal file
24
src/modules/pasteplain/PastePlainModuleInterface/trace.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
#include <interface/powertoy_module_interface.h>
|
||||
|
||||
class Trace
|
||||
{
|
||||
public:
|
||||
static void RegisterProvider();
|
||||
static void UnregisterProvider();
|
||||
|
||||
// Log if the user has PastePlain enabled or disabled
|
||||
static void EnablePastePlain(const bool enabled) noexcept;
|
||||
|
||||
// Log if the user has invoked PastePlain
|
||||
static void PastePlainInvoked() noexcept;
|
||||
|
||||
// Log if a PastePlain invocation has succeeded
|
||||
static void Trace::PastePlainSuccess() noexcept;
|
||||
|
||||
// Log if an error occurs in PastePlain
|
||||
static void Trace::PastePlainError(const DWORD errorCode, std::wstring errorMessage, std::wstring methodName) noexcept;
|
||||
|
||||
// Event to send settings telemetry.
|
||||
static void Trace::SettingsTelemetry(PowertoyModuleIface::Hotkey& hotkey) noexcept;
|
||||
};
|
||||
@@ -162,6 +162,7 @@ int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow
|
||||
L"modules/MouseUtils/PowerToys.MousePointerCrosshairs.dll",
|
||||
L"modules/PowerAccent/PowerToys.PowerAccentModuleInterface.dll",
|
||||
L"modules/PowerOCR/PowerToys.PowerOCRModuleInterface.dll",
|
||||
L"modules/PastePlain/PowerToys.PastePlainModuleInterface.dll",
|
||||
L"modules/FileLocksmith/PowerToys.FileLocksmithExt.dll",
|
||||
L"modules/MeasureTool/PowerToys.MeasureToolModuleInterface.dll",
|
||||
L"modules/Hosts/PowerToys.HostsModuleInterface.dll",
|
||||
|
||||
@@ -279,6 +279,23 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
}
|
||||
}
|
||||
|
||||
private bool pastePlain = true;
|
||||
|
||||
[JsonPropertyName("PastePlain")]
|
||||
public bool PastePlain
|
||||
{
|
||||
get => pastePlain;
|
||||
set
|
||||
{
|
||||
if (pastePlain != value)
|
||||
{
|
||||
LogTelemetryEvent(value);
|
||||
pastePlain = value;
|
||||
NotifyChange();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool measureTool = true;
|
||||
|
||||
[JsonPropertyName("Measure Tool")]
|
||||
|
||||
21
src/settings-ui/Settings.UI.Library/PastePlainProperties.cs
Normal file
21
src/settings-ui/Settings.UI.Library/PastePlainProperties.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
{
|
||||
public class PastePlainProperties
|
||||
{
|
||||
public PastePlainProperties()
|
||||
{
|
||||
ActivationShortcut = new HotkeySettings(true, true, false, false, 0x56); // Ctrl+Win+V
|
||||
}
|
||||
|
||||
public HotkeySettings ActivationShortcut { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
=> JsonSerializer.Serialize(this);
|
||||
}
|
||||
}
|
||||
49
src/settings-ui/Settings.UI.Library/PastePlainSettings.cs
Normal file
49
src/settings-ui/Settings.UI.Library/PastePlainSettings.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
// 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.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
{
|
||||
public class PastePlainSettings : BasePTModuleSettings, ISettingsConfig
|
||||
{
|
||||
public const string ModuleName = "PastePlain";
|
||||
|
||||
[JsonPropertyName("properties")]
|
||||
public PastePlainProperties Properties { get; set; }
|
||||
|
||||
public PastePlainSettings()
|
||||
{
|
||||
Properties = new PastePlainProperties();
|
||||
Version = "1";
|
||||
Name = ModuleName;
|
||||
}
|
||||
|
||||
public virtual void Save(ISettingsUtils settingsUtils)
|
||||
{
|
||||
// Save settings to file
|
||||
var options = new JsonSerializerOptions
|
||||
{
|
||||
WriteIndented = true,
|
||||
};
|
||||
|
||||
if (settingsUtils == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(settingsUtils));
|
||||
}
|
||||
|
||||
settingsUtils.SaveSettings(JsonSerializer.Serialize(this, options), ModuleName);
|
||||
}
|
||||
|
||||
public string GetModuleName()
|
||||
=> Name;
|
||||
|
||||
// This can be utilized in the future if the settings.json file is to be modified/deleted.
|
||||
public bool UpgradeSettingsConfiguration()
|
||||
=> false;
|
||||
}
|
||||
}
|
||||
@@ -151,6 +151,7 @@ namespace Microsoft.PowerToys.Settings.UI
|
||||
case "VideoConference": StartupPage = typeof(Views.VideoConferencePage); break;
|
||||
case "MeasureTool": StartupPage = typeof(Views.MeasureToolPage); break;
|
||||
case "Hosts": StartupPage = typeof(Views.HostsPage); break;
|
||||
case "PastePlain": StartupPage = typeof(Views.PastePlainPage); break;
|
||||
default: Debug.Assert(false, "Unexpected SettingsWindow argument value"); break;
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 526 KiB |
BIN
src/settings-ui/Settings.UI/Assets/Modules/OOBE/PastePlain.gif
Normal file
BIN
src/settings-ui/Settings.UI/Assets/Modules/OOBE/PastePlain.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
BIN
src/settings-ui/Settings.UI/Assets/Modules/PastePlain.png
Normal file
BIN
src/settings-ui/Settings.UI/Assets/Modules/PastePlain.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.7 KiB |
@@ -123,6 +123,9 @@ namespace Microsoft.PowerToys.Settings.UI
|
||||
case "MousePointerCrosshairs":
|
||||
needToUpdate = generalSettingsConfig.Enabled.MousePointerCrosshairs != isEnabled;
|
||||
generalSettingsConfig.Enabled.MousePointerCrosshairs = isEnabled; break;
|
||||
case "PastePlain":
|
||||
needToUpdate = generalSettingsConfig.Enabled.PastePlain != isEnabled;
|
||||
generalSettingsConfig.Enabled.PastePlain = isEnabled; break;
|
||||
case "PowerRename":
|
||||
needToUpdate = generalSettingsConfig.Enabled.PowerRename != isEnabled;
|
||||
generalSettingsConfig.Enabled.PowerRename = isEnabled; break;
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Enums
|
||||
VideoConference,
|
||||
MeasureTool,
|
||||
Hosts,
|
||||
PastePlain,
|
||||
WhatsNew,
|
||||
}
|
||||
}
|
||||
|
||||
44
src/settings-ui/Settings.UI/OOBE/Views/OobePastePlain.xaml
Normal file
44
src/settings-ui/Settings.UI/OOBE/Views/OobePastePlain.xaml
Normal file
@@ -0,0 +1,44 @@
|
||||
<Page
|
||||
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobePastePlain"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:Microsoft.PowerToys.Settings.UI.OOBE.Views"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<controls:OOBEPageControl
|
||||
x:Uid="Oobe_PastePlain"
|
||||
HeroImage="ms-appx:///Assets/Modules/OOBE/PastePlain.gif">
|
||||
|
||||
<controls:OOBEPageControl.PageContent>
|
||||
<StackPanel Orientation="Vertical">
|
||||
<TextBlock
|
||||
x:Uid="Oobe_HowToUse"
|
||||
Style="{ThemeResource OobeSubtitleStyle}" />
|
||||
|
||||
<controls:ShortcutWithTextLabelControl
|
||||
x:Name="HotkeyControl"
|
||||
x:Uid="Oobe_PastePlain_HowToUse" />
|
||||
|
||||
<StackPanel
|
||||
Margin="0,24,0,0"
|
||||
Orientation="Horizontal"
|
||||
Spacing="12">
|
||||
<Button
|
||||
x:Uid="OOBE_Settings"
|
||||
Click="SettingsLaunchButton_Click" />
|
||||
<HyperlinkButton
|
||||
NavigateUri="https://aka.ms/PowerToysOverview_PastePlain"
|
||||
Style="{StaticResource TextButtonStyle}">
|
||||
<TextBlock
|
||||
x:Uid="LearnMore_PastePlain"
|
||||
TextWrapping="Wrap" />
|
||||
</HyperlinkButton>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</controls:OOBEPageControl.PageContent>
|
||||
</controls:OOBEPageControl>
|
||||
</Page>
|
||||
@@ -0,0 +1,46 @@
|
||||
// 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 Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
|
||||
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
|
||||
using Microsoft.PowerToys.Settings.UI.Views;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
|
||||
{
|
||||
public sealed partial class OobePastePlain : Page
|
||||
{
|
||||
public OobePowerToysModule ViewModel { get; set; }
|
||||
|
||||
public OobePastePlain()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.PastePlain]);
|
||||
DataContext = ViewModel;
|
||||
}
|
||||
|
||||
private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
if (OobeShellPage.OpenMainWindowCallback != null)
|
||||
{
|
||||
OobeShellPage.OpenMainWindowCallback(typeof(PastePlainPage));
|
||||
}
|
||||
|
||||
ViewModel.LogOpeningSettingsEvent();
|
||||
}
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
{
|
||||
ViewModel.LogOpeningModuleEvent();
|
||||
HotkeyControl.Keys = SettingsRepository<PastePlainSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut.GetKeysList();
|
||||
}
|
||||
|
||||
protected override void OnNavigatedFrom(NavigationEventArgs e)
|
||||
{
|
||||
ViewModel.LogClosingModuleEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,6 +68,10 @@
|
||||
x:Uid="Shell_MouseUtilities"
|
||||
Icon="{ui:BitmapIcon Source=/Assets/FluentIcons/FluentIconsMouseUtils.png}"
|
||||
Tag="MouseUtils" />
|
||||
<NavigationViewItem
|
||||
x:Uid="Shell_PastePlain"
|
||||
Icon="{ui:BitmapIcon Source=/Assets/FluentIcons/FluentIconsPastePlain.png}"
|
||||
Tag="PastePlain" />
|
||||
<NavigationViewItem
|
||||
x:Uid="Shell_PowerRename"
|
||||
Icon="{ui:BitmapIcon Source=/Assets/FluentIcons/FluentIconsPowerRename.png}"
|
||||
|
||||
@@ -159,6 +159,12 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
|
||||
IsNew = true,
|
||||
});
|
||||
|
||||
Modules.Insert((int)PowerToysModules.PastePlain, new OobePowerToysModule()
|
||||
{
|
||||
ModuleName = "PastePlain",
|
||||
IsNew = true,
|
||||
});
|
||||
|
||||
Modules.Insert((int)PowerToysModules.WhatsNew, new OobePowerToysModule()
|
||||
{
|
||||
ModuleName = "WhatsNew",
|
||||
@@ -234,6 +240,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
|
||||
case "MouseUtils": NavigationFrame.Navigate(typeof(OobeMouseUtils)); break;
|
||||
case "MeasureTool": NavigationFrame.Navigate(typeof(OobeMeasureTool)); break;
|
||||
case "Hosts": NavigationFrame.Navigate(typeof(OobeHosts)); break;
|
||||
case "PastePlain": NavigationFrame.Navigate(typeof(OobePastePlain)); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1970,6 +1970,10 @@ From there, simply click on one of the supported files in the File Explorer and
|
||||
<value>Learn more about Mouse utilities</value>
|
||||
<comment>Mouse utilities is a product name, do not loc</comment>
|
||||
</data>
|
||||
<data name="LearnMore_PastePlain.Text" xml:space="preserve">
|
||||
<value>Learn more about Paste as Plain Text</value>
|
||||
<comment> Paste as Plain Text is the name of the module. </comment>
|
||||
</data>
|
||||
<data name="LearnMore_PowerPreview.Text" xml:space="preserve">
|
||||
<value>Learn more about File Explorer add-ons</value>
|
||||
<comment>File Explorer is a product name, localize as Windows does</comment>
|
||||
@@ -2934,6 +2938,31 @@ Activate by holding the key for the character you want to add an accent to, then
|
||||
<data name="GPO_ExperimentationIsDisallowed.Title" xml:space="preserve">
|
||||
<value>The system administrator has disabled experimentation.</value>
|
||||
</data>
|
||||
<data name="Shell_PastePlain.Content" xml:space="preserve">
|
||||
<value>Paste As Plain Text</value>
|
||||
<comment>Product name: Navigation view item name for Paste as Plain Text</comment>
|
||||
</data>
|
||||
<data name="PastePlain.ModuleDescription" xml:space="preserve">
|
||||
<value>Paste As Plain Text is a quick shortcut for pasting the text contents of your clipboard without formatting. Note: the formatted text in the clipboard is replaced with the unformatted text.</value>
|
||||
</data>
|
||||
<data name="PastePlain.ModuleTitle" xml:space="preserve">
|
||||
<value>Paste As Plain Text</value>
|
||||
</data>
|
||||
<data name="PastePlain_Cancel" xml:space="preserve">
|
||||
<value>cancel</value>
|
||||
</data>
|
||||
<data name="PastePlain_EnableToggleControl_HeaderText.Header" xml:space="preserve">
|
||||
<value>Enable Paste As Plain Text</value>
|
||||
</data>
|
||||
<data name="Oobe_PastePlain.Description" xml:space="preserve">
|
||||
<value>Paste As Plain Text strips rich formatting from your clipboard data and pastes it as non-formatted text.</value>
|
||||
</data>
|
||||
<data name="Oobe_PastePlain.Title" xml:space="preserve">
|
||||
<value>Paste As Plain Text</value>
|
||||
</data>
|
||||
<data name="Oobe_PastePlain_HowToUse.Text" xml:space="preserve">
|
||||
<value>to paste your clipboard data as plain text. Note: this will replace the formatted text in your clipboard with the plain text.</value>
|
||||
</data>
|
||||
<data name="AllAppsTxt.Text" xml:space="preserve">
|
||||
<value>All apps</value>
|
||||
</data>
|
||||
|
||||
@@ -88,6 +88,11 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
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 });
|
||||
}
|
||||
|
||||
if ((gpo = GPOWrapper.GetConfiguredPastePlainEnabledValue()) != GpoRuleConfigured.Disabled && gpo != GpoRuleConfigured.Enabled)
|
||||
{
|
||||
FlyoutMenuItems.Add(new FlyoutMenuItem() { Label = resourceLoader.GetString("PastePlain/ModuleTitle"), IsEnabled = generalSettingsConfig.Enabled.PastePlain, Tag = "PastePlain", Icon = "ms-appx:///Assets/FluentIcons/FluentIconsPastePlain.png", EnabledChangedCallback = EnabledChangedOnUI });
|
||||
}
|
||||
|
||||
if ((gpo = GPOWrapper.GetConfiguredPowerRenameEnabledValue()) != GpoRuleConfigured.Disabled && gpo != GpoRuleConfigured.Enabled)
|
||||
{
|
||||
FlyoutMenuItems.Add(new FlyoutMenuItem() { Label = resourceLoader.GetString("PowerRename/ModuleTitle"), IsEnabled = generalSettingsConfig.Enabled.PowerRename, Tag = "PowerRename", Icon = "ms-appx:///Assets/FluentIcons/FluentIconsPowerRename.png", EnabledChangedCallback = EnabledChangedOnUI });
|
||||
@@ -149,6 +154,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
case "KeyboardManager": item.IsEnabled = generalSettingsConfig.Enabled.KeyboardManager; break;
|
||||
case "MouseHighlighter": item.IsEnabled = generalSettingsConfig.Enabled.MouseHighlighter; 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;
|
||||
case "PowerLauncher": item.IsEnabled = generalSettingsConfig.Enabled.PowerLauncher; break;
|
||||
case "PowerAccent": item.IsEnabled = generalSettingsConfig.Enabled.PowerAccent; break;
|
||||
|
||||
196
src/settings-ui/Settings.UI/ViewModels/PastePlainViewModel.cs
Normal file
196
src/settings-ui/Settings.UI/ViewModels/PastePlainViewModel.cs
Normal file
@@ -0,0 +1,196 @@
|
||||
// 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.Globalization;
|
||||
using System.Text.Json;
|
||||
using System.Timers;
|
||||
using global::PowerToys.GPOWrapper;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
{
|
||||
public class PastePlainViewModel : Observable, IDisposable
|
||||
{
|
||||
private bool disposedValue;
|
||||
|
||||
// Delay saving of settings in order to avoid calling save multiple times and hitting file in use exception. If there is no other request to save settings in given interval, we proceed to save it, otherwise we schedule saving it after this interval
|
||||
private const int SaveSettingsDelayInMs = 500;
|
||||
|
||||
private GeneralSettings GeneralSettingsConfig { get; set; }
|
||||
|
||||
private readonly ISettingsUtils _settingsUtils;
|
||||
private readonly object _delayedActionLock = new object();
|
||||
|
||||
private readonly PastePlainSettings _pastePlainSettings;
|
||||
private Timer _delayedTimer;
|
||||
|
||||
private GpoRuleConfigured _enabledGpoRuleConfiguration;
|
||||
private bool _enabledStateIsGPOConfigured;
|
||||
private bool _isEnabled;
|
||||
|
||||
private Func<string, int> SendConfigMSG { get; }
|
||||
|
||||
public PastePlainViewModel(
|
||||
ISettingsUtils settingsUtils,
|
||||
ISettingsRepository<GeneralSettings> settingsRepository,
|
||||
ISettingsRepository<PastePlainSettings> pastePlainSettingsRepository,
|
||||
Func<string, int> ipcMSGCallBackFunc)
|
||||
{
|
||||
// To obtain the general settings configurations of PowerToys Settings.
|
||||
if (settingsRepository == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(settingsRepository));
|
||||
}
|
||||
|
||||
GeneralSettingsConfig = settingsRepository.SettingsConfig;
|
||||
|
||||
// To obtain the settings configurations of Fancy zones.
|
||||
if (settingsRepository == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(settingsRepository));
|
||||
}
|
||||
|
||||
_settingsUtils = settingsUtils ?? throw new ArgumentNullException(nameof(settingsUtils));
|
||||
|
||||
if (pastePlainSettingsRepository == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(pastePlainSettingsRepository));
|
||||
}
|
||||
|
||||
_pastePlainSettings = pastePlainSettingsRepository.SettingsConfig;
|
||||
|
||||
InitializeEnabledValue();
|
||||
|
||||
// set the callback functions value to hangle outgoing IPC message.
|
||||
SendConfigMSG = ipcMSGCallBackFunc;
|
||||
|
||||
_delayedTimer = new Timer();
|
||||
_delayedTimer.Interval = SaveSettingsDelayInMs;
|
||||
_delayedTimer.Elapsed += DelayedTimer_Tick;
|
||||
_delayedTimer.AutoReset = false;
|
||||
}
|
||||
|
||||
private void InitializeEnabledValue()
|
||||
{
|
||||
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredPastePlainEnabledValue();
|
||||
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
|
||||
{
|
||||
// Get the enabled state from GPO.
|
||||
_enabledStateIsGPOConfigured = true;
|
||||
_isEnabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
|
||||
}
|
||||
else
|
||||
{
|
||||
_isEnabled = GeneralSettingsConfig.Enabled.PastePlain;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsEnabled
|
||||
{
|
||||
get => _isEnabled;
|
||||
set
|
||||
{
|
||||
if (_enabledStateIsGPOConfigured)
|
||||
{
|
||||
// If it's GPO configured, shouldn't be able to change this state.
|
||||
return;
|
||||
}
|
||||
|
||||
if (_isEnabled != value)
|
||||
{
|
||||
_isEnabled = value;
|
||||
OnPropertyChanged(nameof(IsEnabled));
|
||||
|
||||
// Set the status of PastePlain in the general settings
|
||||
GeneralSettingsConfig.Enabled.PastePlain = value;
|
||||
var outgoing = new OutGoingGeneralSettings(GeneralSettingsConfig);
|
||||
|
||||
SendConfigMSG(outgoing.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsEnabledGpoConfigured
|
||||
{
|
||||
get => _enabledStateIsGPOConfigured;
|
||||
}
|
||||
|
||||
public HotkeySettings ActivationShortcut
|
||||
{
|
||||
get => _pastePlainSettings.Properties.ActivationShortcut;
|
||||
set
|
||||
{
|
||||
if (_pastePlainSettings.Properties.ActivationShortcut != value)
|
||||
{
|
||||
_pastePlainSettings.Properties.ActivationShortcut = value;
|
||||
OnPropertyChanged(nameof(ActivationShortcut));
|
||||
|
||||
_settingsUtils.SaveSettings(_pastePlainSettings.ToJsonString(), PastePlainSettings.ModuleName);
|
||||
NotifySettingsChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ScheduleSavingOfSettings()
|
||||
{
|
||||
lock (_delayedActionLock)
|
||||
{
|
||||
if (_delayedTimer.Enabled)
|
||||
{
|
||||
_delayedTimer.Stop();
|
||||
}
|
||||
|
||||
_delayedTimer.Start();
|
||||
}
|
||||
}
|
||||
|
||||
private void DelayedTimer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
lock (_delayedActionLock)
|
||||
{
|
||||
_delayedTimer.Stop();
|
||||
NotifySettingsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void NotifySettingsChanged()
|
||||
{
|
||||
// Using InvariantCulture as this is an IPC message
|
||||
SendConfigMSG(
|
||||
string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"{{ \"powertoys\": {{ \"{0}\": {1} }} }}",
|
||||
PastePlainSettings.ModuleName,
|
||||
JsonSerializer.Serialize(_pastePlainSettings)));
|
||||
}
|
||||
|
||||
public void RefreshEnabledState()
|
||||
{
|
||||
InitializeEnabledValue();
|
||||
OnPropertyChanged(nameof(IsEnabled));
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposedValue)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_delayedTimer.Dispose();
|
||||
}
|
||||
|
||||
disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
55
src/settings-ui/Settings.UI/Views/PastePlainPage.xaml
Normal file
55
src/settings-ui/Settings.UI/Views/PastePlainPage.xaml
Normal file
@@ -0,0 +1,55 @@
|
||||
<Page
|
||||
x:Class="Microsoft.PowerToys.Settings.UI.Views.PastePlainPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:labs="using:CommunityToolkit.Labs.WinUI"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="using:CommunityToolkit.WinUI.UI"
|
||||
AutomationProperties.LandmarkType="Main"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<controls:SettingsPageControl
|
||||
x:Uid="PastePlain"
|
||||
ModuleImageSource="ms-appx:///Assets/Modules/PastePlain.png">
|
||||
<controls:SettingsPageControl.ModuleContent>
|
||||
<StackPanel ChildrenTransitions="{StaticResource SettingsCardsAnimations}"
|
||||
Orientation="Vertical" Spacing="2">
|
||||
<labs:SettingsCard
|
||||
x:Uid="PastePlain_EnableToggleControl_HeaderText"
|
||||
HeaderIcon="{ui:BitmapIcon Source=/Assets/FluentIcons/FluentIconsPastePlain.png}"
|
||||
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabledGpoConfigured, Converter={StaticResource BoolNegationConverter}}">
|
||||
<ToggleSwitch
|
||||
x:Uid="ToggleSwitch"
|
||||
IsOn="{x:Bind ViewModel.IsEnabled, Mode=TwoWay}" />
|
||||
</labs:SettingsCard>
|
||||
<InfoBar
|
||||
x:Uid="GPO_IsSettingForced"
|
||||
IsClosable="False"
|
||||
IsOpen="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabledGpoConfigured}"
|
||||
IsTabStop="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabledGpoConfigured}"
|
||||
Severity="Informational" />
|
||||
|
||||
<controls:SettingsGroup
|
||||
x:Uid="Shortcut"
|
||||
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
|
||||
<labs:SettingsCard
|
||||
x:Uid="Activation_Shortcut"
|
||||
HeaderIcon="{ui:FontIcon FontFamily={StaticResource SymbolThemeFontFamily},
|
||||
Glyph=}">
|
||||
<controls:ShortcutControl
|
||||
MinWidth="{StaticResource SettingActionControlMinWidth}"
|
||||
HotkeySettings="{x:Bind Path=ViewModel.ActivationShortcut, Mode=TwoWay}" />
|
||||
</labs:SettingsCard>
|
||||
</controls:SettingsGroup>
|
||||
</StackPanel>
|
||||
</controls:SettingsPageControl.ModuleContent>
|
||||
|
||||
<controls:SettingsPageControl.PrimaryLinks>
|
||||
<controls:PageLink
|
||||
x:Uid="LearnMore_PastePlain"
|
||||
Link="https://aka.ms/PowerToysOverview_PastePlain" />
|
||||
</controls:SettingsPageControl.PrimaryLinks>
|
||||
</controls:SettingsPageControl>
|
||||
</Page>
|
||||
33
src/settings-ui/Settings.UI/Views/PastePlainPage.xaml.cs
Normal file
33
src/settings-ui/Settings.UI/Views/PastePlainPage.xaml.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
// 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 Microsoft.PowerToys.Settings.UI.Helpers;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Settings.UI.ViewModels;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Views
|
||||
{
|
||||
public sealed partial class PastePlainPage : Page, IRefreshablePage
|
||||
{
|
||||
private PastePlainViewModel ViewModel { get; set; }
|
||||
|
||||
public PastePlainPage()
|
||||
{
|
||||
var settingsUtils = new SettingsUtils();
|
||||
ViewModel = new PastePlainViewModel(
|
||||
settingsUtils,
|
||||
SettingsRepository<GeneralSettings>.GetInstance(settingsUtils),
|
||||
SettingsRepository<PastePlainSettings>.GetInstance(settingsUtils),
|
||||
ShellPage.SendDefaultIPCMessage);
|
||||
DataContext = ViewModel;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void RefreshEnabledState()
|
||||
{
|
||||
ViewModel.RefreshEnabledState();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -100,6 +100,11 @@
|
||||
helpers:NavHelper.NavigateTo="views:MouseUtilsPage"
|
||||
Icon="{ui:BitmapIcon Source=/Assets/FluentIcons/FluentIconsMouseUtils.png}" />
|
||||
|
||||
<NavigationViewItem
|
||||
x:Uid="Shell_PastePlain"
|
||||
helpers:NavHelper.NavigateTo="views:PastePlainPage"
|
||||
Icon="{ui:BitmapIcon Source=/Assets/FluentIcons/FluentIconsPastePlain.png}" />
|
||||
|
||||
<NavigationViewItem
|
||||
x:Uid="Shell_PowerRename"
|
||||
helpers:NavHelper.NavigateTo="views:PowerRenamePage"
|
||||
|
||||
Reference in New Issue
Block a user