* add poweraccent (draft) for PR

* removing french text for Spell checking job

* add 'poweraccent' to spell checker

* add 'damienleroy' to spell checker file

* adding RuntimeIdentifiers for PowerAccent project

* duplicate image for settings

* update commandline arguments for launch settings

* Removing WndProc for testing with inter-process connection

* add PowerAccent sources for PowerToys

* fix spellcheck

* fixing stylecop conventions

* Remove StyleCop.Analyzers because of duplicate

* fixing command line reference

* Fixing CS8012 for PowerAccent.

* ARM64 processor

* - Modify PowerAccent fluenticon for dark mode
- Try fix arm64 release

* Remove taskbar

* init Oobe view

* - added POwerAccent to App.xaml.cs
- change style to markdown in Oobe display

* - fixing poweraccent crash
- change Oobe LearnMore link

* Installer and signing

* Cleanup
Add settings

* Issue template

* Add some more characters

* Disabled by default

* Proper ToUnicodeEx calling and remove hacks

* Fix spellcheck

* Remove CommandLine dependency and debug prints. Add logs

* fix signing

* Fix binary metadata with version

* Fix the added space bug

* Only type space if it was the trigger method

* Take account of InputTime for displaying UI

* Fix code styling

* Remove the Trace WriteLine hack and add a delay instead

* Reinstate logs

* Better explanations

* Add telemetry for showing the menu

* Update src/settings-ui/Settings.UI/Strings/en-us/Resources.resw

* Update src/settings-ui/Settings.UI/Strings/en-us/Resources.resw

* Update src/modules/poweraccent/PowerAccent.Core/Tools/KeyboardListener.cs

* Update src/modules/poweraccent/PowerAccent.Core/Services/SettingsService.cs

* Add accented characters for S

* Default to both activation methods

* Update src/modules/poweraccent/PowerAccent.Core/Services/SettingsService.cs

* Update src/modules/poweraccent/PowerAccent.Core/Services/SettingsService.cs

* Update src/modules/poweraccent/PowerAccent.Core/Services/SettingsService.cs

* Update src/modules/poweraccent/PowerAccent.Core/Services/SettingsService.cs

* Update src/modules/poweraccent/PowerAccent.Core/Services/SettingsService.cs

* Update src/modules/poweraccent/PowerAccent.Core/Services/SettingsService.cs

Co-authored-by: Damien LEROY <dleroy@veepee.com>
This commit is contained in:
damienleroy 2022-08-26 18:01:50 +02:00 коммит произвёл GitHub
Родитель 785160653c
Коммит d9c0af232b
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
66 изменённых файлов: 2836 добавлений и 7 удалений

1
.github/ISSUE_TEMPLATE/bug_report.yml поставляемый
Просмотреть файл

@ -46,6 +46,7 @@ body:
- PDF Thumbnail
- G-code Preview
- G-code Thumbnail
- PowerAccent
- PowerRename
- PowerToys Run
- Shortcut Guide

Просмотреть файл

@ -37,6 +37,7 @@ body:
- PDF Thumbnail
- G-code Preview
- G-code Thumbnail
- PowerAccent
- PowerRename
- PowerToys Run
- Shortcut Guide

21
.github/actions/spell-check/expect.txt поставляемый
Просмотреть файл

@ -201,10 +201,13 @@ BYPOSITION
bytearray
Caiguna
CALG
Calibri
callbackptr
Cangjie
CANRENAME
coord
CAPTURECHANGED
carret
cassert
CAtl
cch
@ -379,6 +382,7 @@ CYVIRTUALSCREEN
cziplib
Dac
dacl
damienleroy
Danmarkshavn
DARKPURPLE
DARKTEAL
@ -472,6 +476,7 @@ DPolicy
DPSAPI
DQTAT
DQTYPE
dragdrop
DRAWFRAME
drawingcolor
dreamsofameaningfullife
@ -488,6 +493,7 @@ DVSD
DVSL
DVTARGETDEVICE
DWINRT
dwhkl
dwl
dwm
dwmapi
@ -678,6 +684,7 @@ HACCEL
hangeul
hanselman
hardcoded
hardcodet
Hardlines
HARDWAREINPUT
hashcode
@ -718,12 +725,13 @@ HIMAGELIST
himl
hinst
hinstance
hitted
HIWORD
HKCC
HKCR
HKCU
hkey
HKL
hkl
HKLM
HKPD
HKU
@ -879,6 +887,7 @@ inheritdoc
initguid
Inkscape
Inlines
Inlining
inorder
INotification
INotify
@ -1008,6 +1017,7 @@ jxr
jyuwono
KBDLLHOOKSTRUCT
kbm
KCode
KEYBDINPUT
keybindings
keyboardeventhandlers
@ -1102,6 +1112,7 @@ LOCATIONCHANGE
logconsole
logfile
LOGFONT
Logique
LOGMSG
logon
LOGPIXELSX
@ -1153,6 +1164,8 @@ lzw
Maarten
Macquarie
Magadan
mah
mahapps
Mainwindow
majortype
MAJORVERSION
@ -1209,6 +1222,7 @@ mfplat
Mfsensorgroup
mftransform
mic
michkap
microsoft
Midl
mii
@ -1531,6 +1545,7 @@ popup
POPUPWINDOW
posix
powercfg
poweraccent
powerlauncher
POWEROCR
powerpreview
@ -2163,6 +2178,7 @@ uwp
uxtheme
UYVY
validmodulename
Vanara
vcamp
vcdl
VCINSTALLDIR
@ -2188,11 +2204,14 @@ VIDEOINFOHEADER
viewbox
viewmodel
vih
Virt
virtualization
Virtualizing
visiblecolorformats
Visibletrue
visualbrush
visualstudio
viter
VKey
VKTAB
VOS

Просмотреть файл

@ -106,6 +106,13 @@
"modules\\MouseUtils\\PowerToys.MouseHighlighter.dll",
"modules\\MouseUtils\\PowerToys.MousePointerCrosshairs.dll",
"modules\\PowerAccent\\PowerAccent.Core.dll",
"modules\\PowerAccent\\PowerAccent.dll",
"modules\\PowerAccent\\PowerAccent.exe",
"modules\\PowerAccent\\PowerToys.PowerAccent.dll",
"modules\\PowerAccent\\PowerToys.PowerAccent.exe",
"modules\\PowerAccent\\PowerToys.PowerAccentModuleInterface.dll",
"modules\\PowerRename\\PowerToys.PowerRenameExt.dll",
"modules\\PowerRename\\PowerToys.PowerRename.exe",
"modules\\PowerRename\\PowerToys.PowerRenameContextMenu.dll",
@ -187,7 +194,12 @@
"vccorlib140_app.dll",
"vcomp140_app.dll",
"vcruntime140_1_app.dll",
"vcruntime140_app.dll",
"vcruntime140_app.dll",
"modules\\PowerAccent\\Vanara.Core.dll",
"modules\\PowerAccent\\Vanara.PInvoke.Gdi32.dll",
"modules\\PowerAccent\\Vanara.PInvoke.Kernel32.dll",
"modules\\PowerAccent\\Vanara.PInvoke.Shared.dll",
"modules\\PowerAccent\\Vanara.PInvoke.User32.dll",
"modules\\FileExplorerPreview\\Microsoft.Web.WebView2.Core.dll",
"modules\\FileExplorerPreview\\Microsoft.Web.WebView2.WinForms.dll",
"modules\\FileExplorerPreview\\Microsoft.Web.WebView2.Wpf.dll",

Просмотреть файл

@ -407,7 +407,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameUI", "src\module
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameContextMenu", "src\modules\powerrename\PowerRenameContextMenu\PowerRenameContextMenu.vcxproj", "{1DBBB112-4BB1-444B-8EBB-E66555C76BA6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.PowerToys.Run.Plugin.TimeZone.UnitTests", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.TimeZone.UnitTests\Microsoft.PowerToys.Run.Plugin.TimeZone.UnitTests.csproj", "{C5D46169-5334-48C3-8C28-644C72832E54}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.TimeZone.UnitTests", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.TimeZone.UnitTests\Microsoft.PowerToys.Run.Plugin.TimeZone.UnitTests.csproj", "{C5D46169-5334-48C3-8C28-644C72832E54}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.OneNote", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.OneNote\Microsoft.PowerToys.Run.Plugin.OneNote.csproj", "{5A1DB2F0-0715-4B3B-98E6-79BC41540045}"
EndProject
@ -415,6 +415,16 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ImageResizerContextMenu", "
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ImageResizerLib", "src\modules\imageresizer\ImageResizerLib\ImageResizerLib.vcxproj", "{18B3DB45-4FFE-4D01-97D6-5223FEEE1853}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PowerAccent", "PowerAccent", "{0F14491C-6369-4C45-AAA8-135814E66E6B}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerAccentModuleInterface", "src\modules\poweraccent\PowerAccentModuleInterface\PowerAccentModuleInterface.vcxproj", "{34A354C5-23C7-4343-916C-C52DAF4FC39D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PowerAccent", "src\modules\poweraccent\PowerAccent\PowerAccent.csproj", "{7B4CDB0D-28C9-4F95-88AA-73FCC06E354C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PowerAccent.Core", "src\modules\poweraccent\PowerAccent.Core\PowerAccent.Core.csproj", "{3264DF53-C805-4B0C-867C-FCEAF7AEF762}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PowerAccent.UI", "src\modules\poweraccent\PowerAccent.UI\PowerAccent.UI.csproj", "{31CAD28E-778A-441C-85BC-40AB3EAA2A10}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PowerOCR", "PowerOCR", "{A50C70A6-2DA0-4027-B90E-B1A40755A8A5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PowerOCR", "src\modules\PowerOCR\PowerOCR\PowerOCR.csproj", "{25C91A4E-BA4E-467A-85CD-8B62545BF674}"
@ -1640,6 +1650,54 @@ Global
{18B3DB45-4FFE-4D01-97D6-5223FEEE1853}.Release|x64.Build.0 = Release|x64
{18B3DB45-4FFE-4D01-97D6-5223FEEE1853}.Release|x86.ActiveCfg = Release|x64
{18B3DB45-4FFE-4D01-97D6-5223FEEE1853}.Release|x86.Build.0 = Release|x64
{34A354C5-23C7-4343-916C-C52DAF4FC39D}.Debug|ARM64.ActiveCfg = Debug|ARM64
{34A354C5-23C7-4343-916C-C52DAF4FC39D}.Debug|ARM64.Build.0 = Debug|ARM64
{34A354C5-23C7-4343-916C-C52DAF4FC39D}.Debug|x64.ActiveCfg = Debug|x64
{34A354C5-23C7-4343-916C-C52DAF4FC39D}.Debug|x64.Build.0 = Debug|x64
{34A354C5-23C7-4343-916C-C52DAF4FC39D}.Debug|x86.ActiveCfg = Debug|x64
{34A354C5-23C7-4343-916C-C52DAF4FC39D}.Debug|x86.Build.0 = Debug|x64
{34A354C5-23C7-4343-916C-C52DAF4FC39D}.Release|ARM64.ActiveCfg = Release|ARM64
{34A354C5-23C7-4343-916C-C52DAF4FC39D}.Release|ARM64.Build.0 = Release|ARM64
{34A354C5-23C7-4343-916C-C52DAF4FC39D}.Release|x64.ActiveCfg = Release|x64
{34A354C5-23C7-4343-916C-C52DAF4FC39D}.Release|x64.Build.0 = Release|x64
{34A354C5-23C7-4343-916C-C52DAF4FC39D}.Release|x86.ActiveCfg = Release|x64
{34A354C5-23C7-4343-916C-C52DAF4FC39D}.Release|x86.Build.0 = Release|x64
{7B4CDB0D-28C9-4F95-88AA-73FCC06E354C}.Debug|ARM64.ActiveCfg = Debug|ARM64
{7B4CDB0D-28C9-4F95-88AA-73FCC06E354C}.Debug|ARM64.Build.0 = Debug|ARM64
{7B4CDB0D-28C9-4F95-88AA-73FCC06E354C}.Debug|x64.ActiveCfg = Debug|x64
{7B4CDB0D-28C9-4F95-88AA-73FCC06E354C}.Debug|x64.Build.0 = Debug|x64
{7B4CDB0D-28C9-4F95-88AA-73FCC06E354C}.Debug|x86.ActiveCfg = Debug|x64
{7B4CDB0D-28C9-4F95-88AA-73FCC06E354C}.Debug|x86.Build.0 = Debug|x64
{7B4CDB0D-28C9-4F95-88AA-73FCC06E354C}.Release|ARM64.ActiveCfg = Release|ARM64
{7B4CDB0D-28C9-4F95-88AA-73FCC06E354C}.Release|ARM64.Build.0 = Release|ARM64
{7B4CDB0D-28C9-4F95-88AA-73FCC06E354C}.Release|x64.ActiveCfg = Release|x64
{7B4CDB0D-28C9-4F95-88AA-73FCC06E354C}.Release|x64.Build.0 = Release|x64
{7B4CDB0D-28C9-4F95-88AA-73FCC06E354C}.Release|x86.ActiveCfg = Release|x64
{7B4CDB0D-28C9-4F95-88AA-73FCC06E354C}.Release|x86.Build.0 = Release|x64
{3264DF53-C805-4B0C-867C-FCEAF7AEF762}.Debug|ARM64.ActiveCfg = Debug|ARM64
{3264DF53-C805-4B0C-867C-FCEAF7AEF762}.Debug|ARM64.Build.0 = Debug|ARM64
{3264DF53-C805-4B0C-867C-FCEAF7AEF762}.Debug|x64.ActiveCfg = Debug|x64
{3264DF53-C805-4B0C-867C-FCEAF7AEF762}.Debug|x64.Build.0 = Debug|x64
{3264DF53-C805-4B0C-867C-FCEAF7AEF762}.Debug|x86.ActiveCfg = Debug|x64
{3264DF53-C805-4B0C-867C-FCEAF7AEF762}.Debug|x86.Build.0 = Debug|x64
{3264DF53-C805-4B0C-867C-FCEAF7AEF762}.Release|ARM64.ActiveCfg = Release|ARM64
{3264DF53-C805-4B0C-867C-FCEAF7AEF762}.Release|ARM64.Build.0 = Release|ARM64
{3264DF53-C805-4B0C-867C-FCEAF7AEF762}.Release|x64.ActiveCfg = Release|x64
{3264DF53-C805-4B0C-867C-FCEAF7AEF762}.Release|x64.Build.0 = Release|x64
{3264DF53-C805-4B0C-867C-FCEAF7AEF762}.Release|x86.ActiveCfg = Release|x64
{3264DF53-C805-4B0C-867C-FCEAF7AEF762}.Release|x86.Build.0 = Release|x64
{31CAD28E-778A-441C-85BC-40AB3EAA2A10}.Debug|ARM64.ActiveCfg = Debug|ARM64
{31CAD28E-778A-441C-85BC-40AB3EAA2A10}.Debug|ARM64.Build.0 = Debug|ARM64
{31CAD28E-778A-441C-85BC-40AB3EAA2A10}.Debug|x64.ActiveCfg = Debug|x64
{31CAD28E-778A-441C-85BC-40AB3EAA2A10}.Debug|x64.Build.0 = Debug|x64
{31CAD28E-778A-441C-85BC-40AB3EAA2A10}.Debug|x86.ActiveCfg = Debug|x64
{31CAD28E-778A-441C-85BC-40AB3EAA2A10}.Debug|x86.Build.0 = Debug|x64
{31CAD28E-778A-441C-85BC-40AB3EAA2A10}.Release|ARM64.ActiveCfg = Release|ARM64
{31CAD28E-778A-441C-85BC-40AB3EAA2A10}.Release|ARM64.Build.0 = Release|ARM64
{31CAD28E-778A-441C-85BC-40AB3EAA2A10}.Release|x64.ActiveCfg = Release|x64
{31CAD28E-778A-441C-85BC-40AB3EAA2A10}.Release|x64.Build.0 = Release|x64
{31CAD28E-778A-441C-85BC-40AB3EAA2A10}.Release|x86.ActiveCfg = Release|x64
{31CAD28E-778A-441C-85BC-40AB3EAA2A10}.Release|x86.Build.0 = Release|x64
{25C91A4E-BA4E-467A-85CD-8B62545BF674}.Debug|ARM64.ActiveCfg = Debug|ARM64
{25C91A4E-BA4E-467A-85CD-8B62545BF674}.Debug|ARM64.Build.0 = Debug|ARM64
{25C91A4E-BA4E-467A-85CD-8B62545BF674}.Debug|x64.ActiveCfg = Debug|x64
@ -1814,6 +1872,11 @@ Global
{5A1DB2F0-0715-4B3B-98E6-79BC41540045} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{93B72A06-C8BD-484F-A6F7-C9F280B150BF} = {6C7F47CC-2151-44A3-A546-41C70025132C}
{18B3DB45-4FFE-4D01-97D6-5223FEEE1853} = {6C7F47CC-2151-44A3-A546-41C70025132C}
{0F14491C-6369-4C45-AAA8-135814E66E6B} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{34A354C5-23C7-4343-916C-C52DAF4FC39D} = {0F14491C-6369-4C45-AAA8-135814E66E6B}
{7B4CDB0D-28C9-4F95-88AA-73FCC06E354C} = {0F14491C-6369-4C45-AAA8-135814E66E6B}
{3264DF53-C805-4B0C-867C-FCEAF7AEF762} = {0F14491C-6369-4C45-AAA8-135814E66E6B}
{31CAD28E-778A-441C-85BC-40AB3EAA2A10} = {0F14491C-6369-4C45-AAA8-135814E66E6B}
{A50C70A6-2DA0-4027-B90E-B1A40755A8A5} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{25C91A4E-BA4E-467A-85CD-8B62545BF674} = {A50C70A6-2DA0-4027-B90E-B1A40755A8A5}
{6AB6A2D6-F859-4A82-9184-0BD29C9F07D1} = {A50C70A6-2DA0-4027-B90E-B1A40755A8A5}

Просмотреть файл

@ -6,6 +6,7 @@
<?define FancyZonesProjectName="FancyZones"?>
<?define ImageResizerProjectName="ImageResizer"?>
<?define KeyboardManagerProjectName="KeyboardManager"?>
<?define PowerAccentProjectName="PowerAccent"?>
<?define PowerRenameProjectName="PowerRename"?>
<?define ColorPickerProjectName="ColorPicker"?>
<?define PowerOCRProjectName="PowerOCR"?>
@ -49,11 +50,11 @@
<?define SettingsV2Files=Ijwhost.dll;ColorCode.Core.dll;ColorCode.WinUI.dll;CommunityToolkit.Common.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.Interop.dll;PowerToys.ManagedCommon.dll;System.Management.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.IO.Abstractions.dll;System.Text.Json.dll;WinRT.Runtime.dll;Microsoft.Graphics.Canvas.dll;Microsoft.WindowsAppRuntime.Bootstrap.dll;CoreMessagingXP.dll;dcompi.dll;dwmcorei.dll;DwmSceneI.dll;DWriteCore.dll;marshal.dll;Microsoft.DirectManipulation.dll;Microsoft.InputStateManager.dll;Microsoft.Internal.FrameworkUdk.dll;Microsoft.UI.Composition.OSSupport.dll;Microsoft.UI.Input.dll;Microsoft.UI.Windowing.Core.dll;Microsoft.UI.Xaml.Controls.dll;Microsoft.UI.Xaml.Controls.pri;Microsoft.ui.xaml.dll;Microsoft.UI.Xaml.Internal.dll;Microsoft.UI.Xaml.Phone.dll;Microsoft.ui.xaml.resources.19h1.dll;Microsoft.ui.xaml.resources.common.dll;Microsoft.Web.WebView2.Core.dll;Microsoft.Windows.ApplicationModel.Resources.dll;Microsoft.Windows.AppNotifications.Projection.dll;Microsoft.Windows.PushNotifications.Projection.dll;Microsoft.Windows.System.Projection.dll;Microsoft.WindowsAppRuntime.dll;Microsoft.WindowsAppRuntime.Insights.Resource.dll;Microsoft.WindowsAppRuntime.Release.Net.dll;MRM.dll;PushNotificationsLongRunningTask.ProxyStub.dll;WindowsAppRuntime.png;WindowsAppSdk.AppxDeploymentExtensions.Desktop.dll;WinUIEdit.dll;wuceffectsi.dll?>
<?define SettingsV2AssetsModulesFiles=ColorPicker.png;FancyZones.png;AlwaysOnTop.png;Awake.png;ImageResizer.png;KBM.png;MouseUtils.png;PowerLauncher.png;PowerPreview.png;PowerRename.png;PT.png;ShortcutGuide.png;VideoConference.png;PowerOCR.png?>
<?define SettingsV2AssetsModulesFiles=ColorPicker.png;FancyZones.png;AlwaysOnTop.png;Awake.png;ImageResizer.png;KBM.png;MouseUtils.png;PowerAccent.png;PowerOCR.png;PowerLauncher.png;PowerPreview.png;PowerRename.png;PT.png;ShortcutGuide.png;VideoConference.png?>
<?define SettingsV2OOBEAssetsModulesFiles=ColorPicker.gif;AlwaysOnTop.png;Awake.png;FancyZones.gif;FileExplorer.png;ImageResizer.gif;KBM.gif;MouseUtils.gif;PowerRename.gif;Run.gif;OOBEShortcutGuide.png;VideoConferenceMute.png;OOBEPTHero.png;PowerOCR.gif?>
<?define SettingsV2OOBEAssetsModulesFiles=ColorPicker.gif;AlwaysOnTop.png;Awake.png;FancyZones.gif;FileExplorer.png;ImageResizer.gif;KBM.gif;MouseUtils.gif;PowerAccent.gif;PowerOCR.gif;PowerRename.gif;Run.gif;OOBEShortcutGuide.png;VideoConferenceMute.png;OOBEPTHero.png?>
<?define SettingsV2OOBEAssetsFluentIconsFiles=ColorPicker.png;FancyZones.png;AlwaysOnTop.png;Awake.png;FileExplorerPreview.png;FindMyMouse.png;ImageResizer.png;KeyboardManager.png;MouseHighlighter.png;MouseCrosshairs.png;MouseUtils.png;PowerRename.png;PowerToys.png;PowerToysRun.png;Settings.png;ShortcutGuide.png;VideoConferenceMute.png;PowerOcr.png?>
<?define SettingsV2OOBEAssetsFluentIconsFiles=ColorPicker.png;FancyZones.png;AlwaysOnTop.png;Awake.png;FileExplorerPreview.png;FindMyMouse.png;ImageResizer.png;KeyboardManager.png;MouseHighlighter.png;MouseCrosshairs.png;MouseUtils.png;PowerAccent.png;PowerOcr.png;PowerRename.png;PowerToys.png;PowerToysRun.png;Settings.png;ShortcutGuide.png;VideoConferenceMute.png?>
<?define SettingsV2MicrosoftUIXamlAssetsInstallFiles=NoiseAsset_256x256_PNG.png?>
@ -119,6 +120,8 @@
<?define PowerRenameMicrosoftUIXamlAssetsInstallFiles=NoiseAsset_256x256_PNG.png?>
<?define PowerAccentFiles=ControlzEx.dll;GongSolutions.WPF.DragDrop.dll;Ijwhost.dll;MahApps.Metro.dll;Microsoft.Xaml.Behaviors.dll;PowerAccent.Core.dll;PowerAccent.deps.json;PowerAccent.dll;PowerAccent.exe;PowerAccent.runtimeconfig.json;PowerToys.PowerAccentModuleInterface.dll;PowerToys.Interop.dll;PowerToys.ManagedCommon.dll;PowerToys.ManagedTelemetry.dll;PowerToys.PowerAccent.deps.json;PowerToys.PowerAccent.dll;PowerToys.PowerAccent.exe;PowerToys.PowerAccent.runtimeconfig.json;PowerToys.Settings.UI.Lib.dll;System.IO.Abstractions.dll;System.Management.dll;System.Text.Json.dll;Vanara.Core.dll;Vanara.PInvoke.Gdi32.dll;Vanara.PInvoke.Kernel32.dll;Vanara.PInvoke.Shared.dll;Vanara.PInvoke.User32.dll?>
<Product Id="*"
Name="PowerToys (Preview)"
Language="1033"
@ -412,6 +415,8 @@
<Directory Id="ImageResizerInstallFolder" Name="$(var.ImageResizerProjectName)">
<Directory Id="ImageResizerAssetsFolder" Name="Assets" />
</Directory>
<Directory Id="PowerAccentInstallFolder" Name="$(var.PowerAccentProjectName)">
</Directory>
<Directory Id="PowerRenameInstallFolder" Name="$(var.PowerRenameProjectName)">
<Directory Id="PowerRenameAssetsFolder" Name="Assets" />
<Directory Id="PowerRenameMicrosoftUIXamlInstallFolder" Name="Microsoft.UI.Xaml">
@ -754,6 +759,15 @@
</Component>
</DirectoryRef>
<!-- PowerAccent -->
<DirectoryRef Id="PowerAccentInstallFolder" FileSource="$(var.BinDir)modules\$(var.PowerAccentProjectName)">
<?foreach File in $(var.PowerAccentFiles)?>
<Component Id="PowerAccent_$(var.File)" Win64="yes">
<File Id="PowerAccentFile_$(var.File)" Source="$(var.BinDir)modules\$(var.PowerAccentProjectName)\$(var.File)" />
</Component>
<?endforeach?>
</DirectoryRef>
<!-- PowerRename -->
<DirectoryRef Id="PowerRenameInstallFolder" FileSource="$(var.BinDir)modules\$(var.PowerRenameProjectName)">
<?foreach File in $(var.PowerRenameFiles)?>
@ -1054,6 +1068,9 @@
<?endforeach?>
<ComponentRef Id="DesktopShortcut" />
<ComponentRef Id="Module_PowerRename" />
<?foreach File in $(var.PowerAccentFiles)?>
<ComponentRef Id="PowerAccent_$(var.File)" />
<?endforeach?>
<?foreach File in $(var.PowerRenameFiles)?>
<ComponentRef Id="PowerRename_$(var.File)" />
<?endforeach?>

Просмотреть файл

@ -203,5 +203,9 @@ public
return gcnew String(CommonSharedConstants::AWAKE_EXIT_EVENT);
}
static String ^ PowerAccentExitEvent() {
return gcnew String(CommonSharedConstants::POWERACCENT_EXIT_EVENT);
}
};
}

Просмотреть файл

@ -38,6 +38,9 @@ namespace CommonSharedConstants
// Path to the event used by AlwaysOnTop
const wchar_t ALWAYS_ON_TOP_PIN_EVENT[] = L"Local\\AlwaysOnTopPinEvent-892e0aa2-cfa8-4cc4-b196-ddeb32314ce8";
// Path to the event used by PowerAccent
const wchar_t POWERACCENT_EXIT_EVENT[] = L"Local\\PowerToysPowerAccentExitEvent-53e93389-d19a-4fbb-9b36-1981c8965e17";
// Path to the event used by PowerOCR
const wchar_t SHOW_POWEROCR_SHARED_EVENT[] = L"Local\\PowerOCREvent-dc864e06-e1af-4ecc-9078-f98bee745e3a";

Просмотреть файл

@ -18,6 +18,7 @@ struct LogSettings
inline const static std::string launcherLoggerName = "launcher";
inline const static std::wstring launcherLogPath = L"LogsModuleInterface\\launcher-log.txt";
inline const static std::wstring awakeLogPath = L"Logs\\awake-log.txt";
inline const static std::wstring powerAccentLogPath = L"poweraccent.log";
inline const static std::string fancyZonesLoggerName = "fancyzones";
inline const static std::wstring fancyZonesLogPath = L"fancyzones-log.txt";
inline const static std::wstring fancyZonesOldLogPath = L"FancyZonesLogs\\"; // needed to clean up old logs

Просмотреть файл

@ -0,0 +1,27 @@
// 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 Vanara.PInvoke;
namespace PowerAccent.Core;
public enum LetterKey
{
A = User32.VK.VK_A,
C = User32.VK.VK_C,
E = User32.VK.VK_E,
I = User32.VK.VK_I,
N = User32.VK.VK_N,
O = User32.VK.VK_O,
S = User32.VK.VK_S,
U = User32.VK.VK_U,
Y = User32.VK.VK_Y,
}
public enum TriggerKey
{
Left = User32.VK.VK_LEFT,
Right = User32.VK.VK_RIGHT,
Space = User32.VK.VK_SPACE,
}

Просмотреть файл

@ -0,0 +1,58 @@
// 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.
namespace PowerAccent.Core;
public struct Point
{
public Point()
{
X = 0;
Y = 0;
}
public Point(double x, double y)
{
X = x;
Y = y;
}
public Point(int x, int y)
{
X = x;
Y = y;
}
public Point(System.Drawing.Point point)
{
X = point.X;
Y = point.Y;
}
public double X { get; init; }
public double Y { get; init; }
public static implicit operator Point(System.Drawing.Point point) => new Point(point.X, point.Y);
public static Point operator /(Point point, double divider)
{
if (divider == 0)
{
throw new DivideByZeroException();
}
return new Point(point.X / divider, point.Y / divider);
}
public static Point operator /(Point point, Point divider)
{
if (divider.X == 0 || divider.Y == 0)
{
throw new DivideByZeroException();
}
return new Point(point.X / divider.X, point.Y / divider.Y);
}
}

Просмотреть файл

@ -0,0 +1,68 @@
// 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.
namespace PowerAccent.Core;
public struct Rect
{
public Rect()
{
X = 0;
Y = 0;
Width = 0;
Height = 0;
}
public Rect(int x, int y, int width, int height)
{
X = x;
Y = y;
Width = width;
Height = height;
}
public Rect(double x, double y, double width, double height)
{
X = x;
Y = y;
Width = width;
Height = height;
}
public Rect(Point coord, Size size)
{
X = coord.X;
Y = coord.Y;
Width = size.Width;
Height = size.Height;
}
public double X { get; init; }
public double Y { get; init; }
public double Width { get; init; }
public double Height { get; init; }
public static Rect operator /(Rect rect, double divider)
{
if (divider == 0)
{
throw new DivideByZeroException();
}
return new Rect(rect.X / divider, rect.Y / divider, rect.Width / divider, rect.Height / divider);
}
public static Rect operator /(Rect rect, Rect divider)
{
if (divider.X == 0 || divider.Y == 0)
{
throw new DivideByZeroException();
}
return new Rect(rect.X / divider.X, rect.Y / divider.Y, rect.Width / divider.Width, rect.Height / divider.Height);
}
}

Просмотреть файл

@ -0,0 +1,52 @@
// 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.
namespace PowerAccent.Core;
public struct Size
{
public Size()
{
Width = 0;
Height = 0;
}
public Size(double width, double height)
{
Width = width;
Height = height;
}
public Size(int width, int height)
{
Width = width;
Height = height;
}
public double Width { get; init; }
public double Height { get; init; }
public static implicit operator Size(System.Drawing.Size size) => new Size(size.Width, size.Height);
public static Size operator /(Size size, double divider)
{
if (divider == 0)
{
throw new DivideByZeroException();
}
return new Size(size.Width / divider, size.Height / divider);
}
public static Size operator /(Size size, Size divider)
{
if (divider.Width == 0 || divider.Height == 0 || divider.Width == 0 || divider.Height == 0)
{
throw new DivideByZeroException();
}
return new Size(size.Width / divider.Width, size.Height / divider.Height);
}
}

Просмотреть файл

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\Version.props" />
<PropertyGroup>
<TargetFramework>net6.0-windows</TargetFramework>
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>disable</Nullable>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.0" />
<PackageReference Include="Vanara.PInvoke.User32" Version="3.3.15" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\settings-ui\Settings.UI.Library\Settings.UI.Library.csproj" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,206 @@
// 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;
using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
using PowerAccent.Core.Services;
using PowerAccent.Core.Tools;
namespace PowerAccent.Core;
public class PowerAccent : IDisposable
{
private readonly SettingsService _settingService = new SettingsService();
private readonly KeyboardListener _keyboardListener = new KeyboardListener();
private LetterKey? letterPressed;
private bool _visible;
private char[] _characters = Array.Empty<char>();
private int _selectedIndex = -1;
private Stopwatch _stopWatch;
private bool _triggeredWithSpace;
public event Action<bool, char[]> OnChangeDisplay;
public event Action<int, char> OnSelectCharacter;
public PowerAccent()
{
_keyboardListener.KeyDown += PowerAccent_KeyDown;
_keyboardListener.KeyUp += PowerAccent_KeyUp;
}
private bool PowerAccent_KeyDown(object sender, KeyboardListener.RawKeyEventArgs args)
{
if (Enum.IsDefined(typeof(LetterKey), (int)args.Key))
{
_stopWatch = Stopwatch.StartNew();
letterPressed = (LetterKey)args.Key;
}
TriggerKey? triggerPressed = null;
if (letterPressed.HasValue)
{
if (Enum.IsDefined(typeof(TriggerKey), (int)args.Key))
{
triggerPressed = (TriggerKey)args.Key;
if ((triggerPressed == TriggerKey.Space && _settingService.ActivationKey == PowerAccentActivationKey.LeftRightArrow) ||
((triggerPressed == TriggerKey.Left || triggerPressed == TriggerKey.Right) && _settingService.ActivationKey == PowerAccentActivationKey.Space))
{
triggerPressed = null;
}
}
}
if (!_visible && letterPressed.HasValue && triggerPressed.HasValue)
{
// Keep track if it was triggered with space so that it can be typed on false starts.
_triggeredWithSpace = triggerPressed.Value == TriggerKey.Space;
_visible = true;
_characters = WindowsFunctions.IsCapitalState() ? ToUpper(_settingService.GetLetterKey(letterPressed.Value)) : _settingService.GetLetterKey(letterPressed.Value);
Task.Delay(_settingService.InputTime).ContinueWith(
t =>
{
if (_visible)
{
OnChangeDisplay?.Invoke(true, _characters);
}
}, TaskScheduler.FromCurrentSynchronizationContext());
}
if (_visible && triggerPressed.HasValue)
{
if (_selectedIndex == -1)
{
if (triggerPressed.Value == TriggerKey.Left)
{
_selectedIndex = (_characters.Length / 2) - 1;
}
if (triggerPressed.Value == TriggerKey.Right)
{
_selectedIndex = _characters.Length / 2;
}
if (triggerPressed.Value == TriggerKey.Space)
{
_selectedIndex = 0;
}
if (_selectedIndex < 0)
{
_selectedIndex = 0;
}
if (_selectedIndex > _characters.Length - 1)
{
_selectedIndex = _characters.Length - 1;
}
OnSelectCharacter?.Invoke(_selectedIndex, _characters[_selectedIndex]);
return false;
}
if (triggerPressed.Value == TriggerKey.Space)
{
if (_selectedIndex < _characters.Length - 1)
{
++_selectedIndex;
}
else
{
_selectedIndex = 0;
}
}
if (triggerPressed.Value == TriggerKey.Left && _selectedIndex > 0)
{
--_selectedIndex;
}
if (triggerPressed.Value == TriggerKey.Right && _selectedIndex < _characters.Length - 1)
{
++_selectedIndex;
}
OnSelectCharacter?.Invoke(_selectedIndex, _characters[_selectedIndex]);
return false;
}
return true;
}
private bool PowerAccent_KeyUp(object sender, KeyboardListener.RawKeyEventArgs args)
{
if (Enum.IsDefined(typeof(LetterKey), (int)args.Key))
{
letterPressed = null;
_stopWatch.Stop();
if (_visible)
{
if (_stopWatch.ElapsedMilliseconds < _settingService.InputTime)
{
/* Debug.WriteLine("Insert before inputTime - " + _stopWatch.ElapsedMilliseconds); */
// False start, we should output the space if it was the trigger.
if (_triggeredWithSpace)
{
WindowsFunctions.Insert(' ');
}
OnChangeDisplay?.Invoke(false, null);
_selectedIndex = -1;
_visible = false;
return false;
}
/* Debug.WriteLine("Insert after inputTime - " + _stopWatch.ElapsedMilliseconds); */
OnChangeDisplay?.Invoke(false, null);
if (_selectedIndex != -1)
{
WindowsFunctions.Insert(_characters[_selectedIndex], true);
}
_selectedIndex = -1;
_visible = false;
}
}
return true;
}
public Point GetDisplayCoordinates(Size window)
{
var activeDisplay = WindowsFunctions.GetActiveDisplay();
Rect screen = new Rect(activeDisplay.Location, activeDisplay.Size) / activeDisplay.Dpi;
Position position = _settingService.Position;
/* Debug.WriteLine("Dpi: " + activeDisplay.Dpi); */
return Calculation.GetRawCoordinatesFromPosition(position, screen, window);
}
public char[] GetLettersFromKey(LetterKey letter)
{
return _settingService.GetLetterKey(letter);
}
public void Dispose()
{
_keyboardListener.Dispose();
GC.SuppressFinalize(this);
}
public static char[] ToUpper(char[] array)
{
char[] result = new char[array.Length];
for (int i = 0; i < array.Length; i++)
{
result[i] = char.ToUpper(array[i], System.Globalization.CultureInfo.InvariantCulture);
}
return result;
}
}

Просмотреть файл

@ -0,0 +1,180 @@
// 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.
namespace PowerAccent.Core.Services;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using System.IO.Abstractions;
using System.Text.Json;
public class SettingsService
{
private const string PowerAccentModuleName = "PowerAccent";
private readonly ISettingsUtils _settingsUtils;
private readonly IFileSystemWatcher _watcher;
private readonly object _loadingSettingsLock = new object();
public SettingsService()
{
_settingsUtils = new SettingsUtils();
ReadSettings();
_watcher = Helper.GetFileWatcher(PowerAccentModuleName, "settings.json", () => { ReadSettings(); });
}
private void ReadSettings()
{
// TODO this IO call should by Async, update GetFileWatcher helper to support async
lock (_loadingSettingsLock)
{
{
try
{
if (!_settingsUtils.SettingsExists(PowerAccentModuleName))
{
Logger.LogInfo("PowerAccent settings.json was missing, creating a new one");
var defaultSettings = new PowerAccentSettings();
var options = new JsonSerializerOptions
{
WriteIndented = true,
};
_settingsUtils.SaveSettings(JsonSerializer.Serialize(this, options), PowerAccentModuleName);
}
var settings = _settingsUtils.GetSettingsOrDefault<PowerAccentSettings>(PowerAccentModuleName);
if (settings != null)
{
ActivationKey = settings.Properties.ActivationKey;
switch (settings.Properties.ToolbarPosition.Value)
{
case "Top center":
Position = Position.Top;
break;
case "Bottom center":
Position = Position.Bottom;
break;
case "Left":
Position = Position.Left;
break;
case "Right":
Position = Position.Right;
break;
case "Top right corner":
Position = Position.TopRight;
break;
case "Top left corner":
Position = Position.TopLeft;
break;
case "Bottom right corner":
Position = Position.BottomRight;
break;
case "Bottom left corner":
Position = Position.BottomLeft;
break;
case "Center":
Position = Position.Center;
break;
}
}
}
catch (Exception ex)
{
Logger.LogError("Failed to read changed settings", ex);
}
}
}
}
private PowerAccentActivationKey _activationKey = PowerAccentActivationKey.Both;
public PowerAccentActivationKey ActivationKey
{
get
{
return _activationKey;
}
set
{
_activationKey = value;
}
}
private Position _position = Position.Top;
public Position Position
{
get
{
return _position;
}
set
{
_position = value;
}
}
private int _inputTime = 200;
public int InputTime
{
get
{
return _inputTime;
}
set
{
_inputTime = value;
}
}
public char[] GetLetterKey(LetterKey letter)
{
return GetDefaultLetterKey(letter);
}
public static char[] GetDefaultLetterKey(LetterKey letter)
{
switch (letter)
{
case LetterKey.A:
return new char[] { 'à', 'â', 'á', 'ä', 'ã', 'å', 'æ' };
case LetterKey.C:
return new char[] { 'ć', 'ĉ', 'č', 'ċ', 'ç', 'ḉ' };
case LetterKey.E:
return new char[] { 'é', 'è', 'ê', 'ë', 'ē', 'ė', '€' };
case LetterKey.I:
return new char[] { 'î', 'ï', 'í', 'ì', 'ī' };
case LetterKey.N:
return new char[] { 'ñ', 'ń' };
case LetterKey.O:
return new char[] { 'ô', 'ö', 'ó', 'ò', 'õ', 'ø', 'œ' };
case LetterKey.S:
return new char[] { 'š', 'ß', 'ś' };
case LetterKey.U:
return new char[] { 'û', 'ù', 'ü', 'ú', 'ū' };
case LetterKey.Y:
return new char[] { 'ÿ', 'ý' };
}
throw new ArgumentException("Letter {0} is missing", letter.ToString());
}
}
public enum Position
{
Top,
Bottom,
Left,
Right,
TopLeft,
TopRight,
BottomLeft,
BottomRight,
Center,
}

Просмотреть файл

@ -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 PowerAccent.Core.Telemetry
{
[EventData]
public class PowerAccentShowAccentMenuEvent : EventBase, IEvent
{
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
}
}

Просмотреть файл

@ -0,0 +1,50 @@
// 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 PowerAccent.Core.Services;
namespace PowerAccent.Core.Tools
{
internal static class Calculation
{
public static Point GetRawCoordinatesFromCaret(Point caret, Rect screen, Size window)
{
var left = caret.X - (window.Width / 2);
var top = caret.Y - window.Height - 20;
return new Point(
left < screen.X ? screen.X : (left + window.Width > (screen.X + screen.Width) ? (screen.X + screen.Width) - window.Width : left),
top < screen.Y ? caret.Y + 20 : top);
}
public static Point GetRawCoordinatesFromPosition(Position position, Rect screen, Size window)
{
int offset = 10;
double pointX = position switch
{
Position.Top or Position.Bottom or Position.Center
=> screen.X + (screen.Width / 2) - (window.Width / 2),
Position.TopLeft or Position.Left or Position.BottomLeft
=> screen.X + offset,
Position.TopRight or Position.Right or Position.BottomRight
=> screen.X + screen.Width - (window.Width + offset),
_ => throw new NotImplementedException(),
};
double pointY = position switch
{
Position.TopLeft or Position.Top or Position.TopRight
=> screen.Y + offset,
Position.Left or Position.Center or Position.Right
=> screen.Y + (screen.Height / 2) - (window.Height / 2),
Position.BottomLeft or Position.Bottom or Position.BottomRight
=> screen.Y + screen.Height - (window.Height + offset),
_ => throw new NotImplementedException(),
};
return new Point(pointX, pointY);
}
}
}

Просмотреть файл

@ -0,0 +1,359 @@
// 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.
#pragma warning disable SA1310 // FieldNamesMustNotContainUnderscore
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace PowerAccent.Core.Tools;
internal class KeyboardListener : IDisposable
{
/// <summary>
/// Initializes a new instance of the <see cref="KeyboardListener"/> class.
/// Creates global keyboard listener.
/// </summary>
public KeyboardListener()
{
// We have to store the LowLevelKeyboardProc, so that it is not garbage collected by runtime
_hookedLowLevelKeyboardProc = LowLevelKeyboardProc;
// Set the hook
_hookId = InterceptKeys.SetHook(_hookedLowLevelKeyboardProc);
// Assign the asynchronous callback event
hookedKeyboardCallbackAsync = new KeyboardCallbackAsync(KeyboardListener_KeyboardCallbackAsync);
}
/// <summary>
/// Fired when any of the keys is pressed down.
/// </summary>
public event RawKeyEventHandler KeyDown;
/// <summary>
/// Fired when any of the keys is released.
/// </summary>
public event RawKeyEventHandler KeyUp;
/// <summary>
/// Hook ID
/// </summary>
private readonly IntPtr _hookId = IntPtr.Zero;
/// <summary>
/// Contains the hooked callback in runtime.
/// </summary>
private readonly InterceptKeys.LowLevelKeyboardProc _hookedLowLevelKeyboardProc;
/// <summary>
/// Event to be invoked asynchronously (BeginInvoke) each time key is pressed.
/// </summary>
private KeyboardCallbackAsync hookedKeyboardCallbackAsync;
/// <summary>
/// Raw keyevent handler.
/// </summary>
/// <param name="sender">sender</param>
/// <param name="args">raw keyevent arguments</param>
public delegate bool RawKeyEventHandler(object sender, RawKeyEventArgs args);
/// <summary>
/// Asynchronous callback hook.
/// </summary>
/// <param name="keyEvent">Keyboard event</param>
/// <param name="vkCode">VKCode</param>
/// <param name="character">Character</param>
private delegate bool KeyboardCallbackAsync(InterceptKeys.KeyEvent keyEvent, int vkCode, string character);
/// <summary>
/// Actual callback hook.
/// <remarks>Calls asynchronously the asyncCallback.</remarks>
/// </summary>
/// <param name="nCode">VKCode</param>
/// <param name="wParam">wParam</param>
/// <param name="lParam">lParam</param>
[MethodImpl(MethodImplOptions.NoInlining)]
private IntPtr LowLevelKeyboardProc(int nCode, UIntPtr wParam, IntPtr lParam)
{
if (nCode >= 0)
{
if (wParam.ToUInt32() == (int)InterceptKeys.KeyEvent.WM_KEYDOWN ||
wParam.ToUInt32() == (int)InterceptKeys.KeyEvent.WM_KEYUP)
{
// Captures the character(s) pressed only on WM_KEYDOWN
var chars = InterceptKeys.VKCodeToString(
(uint)Marshal.ReadInt32(lParam),
wParam.ToUInt32() == (int)InterceptKeys.KeyEvent.WM_KEYDOWN);
if (!hookedKeyboardCallbackAsync.Invoke((InterceptKeys.KeyEvent)wParam.ToUInt32(), Marshal.ReadInt32(lParam), chars))
{
return (IntPtr)1;
}
}
}
return InterceptKeys.CallNextHookEx(_hookId, nCode, wParam, lParam);
}
/// <summary>
/// HookCallbackAsync procedure that calls accordingly the KeyDown or KeyUp events.
/// </summary>
/// <param name="keyEvent">Keyboard event</param>
/// <param name="vkCode">VKCode</param>
/// <param name="character">Character as string.</param>
private bool KeyboardListener_KeyboardCallbackAsync(InterceptKeys.KeyEvent keyEvent, int vkCode, string character)
{
switch (keyEvent)
{
// KeyDown events
case InterceptKeys.KeyEvent.WM_KEYDOWN:
if (KeyDown != null)
{
return KeyDown.Invoke(this, new RawKeyEventArgs(vkCode, character));
}
break;
// KeyUp events
case InterceptKeys.KeyEvent.WM_KEYUP:
if (KeyUp != null)
{
return KeyUp.Invoke(this, new RawKeyEventArgs(vkCode, character));
}
break;
default:
break;
}
return true;
}
public void Dispose()
{
InterceptKeys.UnhookWindowsHookEx(_hookId);
}
/// <summary>
/// Raw KeyEvent arguments.
/// </summary>
public class RawKeyEventArgs : EventArgs
{
/// <summary>
/// WPF Key of the key.
/// </summary>
#pragma warning disable SA1401 // Fields should be private
public uint Key;
#pragma warning restore SA1401 // Fields should be private
/// <summary>
/// Convert to string.
/// </summary>
/// <returns>Returns string representation of this key, if not possible empty string is returned.</returns>
public override string ToString()
{
return character;
}
/// <summary>
/// Unicode character of key pressed.
/// </summary>
private string character;
/// <summary>
/// Initializes a new instance of the <see cref="RawKeyEventArgs"/> class.
/// Create raw keyevent arguments.
/// </summary>
/// <param name="vKCode">VKCode</param>
/// <param name="character">Character</param>
public RawKeyEventArgs(int vKCode, string character)
{
this.character = character;
Key = (uint)vKCode; // User32.MapVirtualKey((uint)VKCode, User32.MAPVK.MAPVK_VK_TO_VSC_EX);
}
}
}
/// <summary>
/// Winapi Key interception helper class.
/// </summary>
internal static class InterceptKeys
{
public delegate IntPtr LowLevelKeyboardProc(int nCode, UIntPtr wParam, IntPtr lParam);
private const int WH_KEYBOARD_LL = 13;
/// <summary>
/// Key event
/// </summary>
public enum KeyEvent : int
{
/// <summary>
/// Key down
/// </summary>
WM_KEYDOWN = 256,
/// <summary>
/// Key up
/// </summary>
WM_KEYUP = 257,
/// <summary>
/// System key up
/// </summary>
WM_SYSKEYUP = 261,
/// <summary>
/// System key down
/// </summary>
WM_SYSKEYDOWN = 260,
}
public static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc, (IntPtr)0, 0);
}
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, UIntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
// Note: Sometimes single VKCode represents multiple chars, thus string.
// E.g. typing "^1" (notice that when pressing 1 the both characters appear,
// because of this behavior, "^" is called dead key)
[DllImport("user32.dll")]
#pragma warning disable CA1838 // Éviter les paramètres 'StringBuilder' pour les P/Invoke
private static extern int ToUnicodeEx(uint wVirtKey, uint wScanCode, byte[] lpKeyState, [Out, MarshalAs(UnmanagedType.LPWStr)] System.Text.StringBuilder pwszBuff, int cchBuff, uint wFlags, IntPtr dwhkl);
#pragma warning restore CA1838 // Éviter les paramètres 'StringBuilder' pour les P/Invoke
[DllImport("user32.dll")]
private static extern bool GetKeyboardState(byte[] lpKeyState);
[DllImport("user32.dll")]
private static extern uint MapVirtualKeyEx(uint uCode, uint uMapType, IntPtr dwhkl);
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
private static extern IntPtr GetKeyboardLayout(uint dwLayout);
[DllImport("User32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("User32.dll")]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.dll")]
private static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);
[DllImport("kernel32.dll")]
private static extern uint GetCurrentThreadId();
private static uint lastVKCode;
private static uint lastScanCode;
private static byte[] lastKeyState = new byte[255];
/// <summary>
/// Convert VKCode to Unicode.
/// <remarks>isKeyDown is required for because of keyboard state inconsistencies!</remarks>
/// </summary>
/// <param name="vKCode">VKCode</param>
/// <param name="isKeyDown">Is the key down event?</param>
/// <returns>String representing single unicode character.</returns>
public static string VKCodeToString(uint vKCode, bool isKeyDown)
{
// ToUnicodeEx needs StringBuilder, it populates that during execution.
System.Text.StringBuilder sbString = new System.Text.StringBuilder(5);
byte[] bKeyState = new byte[255];
bool bKeyStateStatus;
// Gets the current windows window handle, threadID, processID
IntPtr currentHWnd = GetForegroundWindow();
uint currentProcessID;
uint currentWindowThreadID = GetWindowThreadProcessId(currentHWnd, out currentProcessID);
// This programs Thread ID
uint thisProgramThreadId = GetCurrentThreadId();
// Attach to active thread so we can get that keyboard state
if (AttachThreadInput(thisProgramThreadId, currentWindowThreadID, true))
{
// Current state of the modifiers in keyboard
bKeyStateStatus = GetKeyboardState(bKeyState);
// Detach
AttachThreadInput(thisProgramThreadId, currentWindowThreadID, false);
}
else
{
// Could not attach, perhaps it is this process?
bKeyStateStatus = GetKeyboardState(bKeyState);
}
// On failure we return empty string.
if (!bKeyStateStatus)
{
return string.Empty;
}
// Gets the layout of keyboard
IntPtr hkl = GetKeyboardLayout(currentWindowThreadID);
// Maps the virtual keycode
uint lScanCode = MapVirtualKeyEx(vKCode, 0, hkl);
// Keyboard state goes inconsistent if this is not in place. In other words, we need to call above commands in UP events also.
if (!isKeyDown)
{
return string.Empty;
}
// Converts the VKCode to unicode
const uint wFlags = 1 << 2; // If bit 2 is set, keyboard state is not changed (Windows 10, version 1607 and newer)
int relevantKeyCountInBuffer = ToUnicodeEx(vKCode, lScanCode, bKeyState, sbString, sbString.Capacity, wFlags, hkl);
string ret = string.Empty;
switch (relevantKeyCountInBuffer)
{
// dead key
case -1:
break;
case 0:
break;
// Single character in buffer
case 1:
ret = sbString.Length == 0 ? string.Empty : sbString[0].ToString();
break;
// Two or more (only two of them is relevant)
case 2:
default:
ret = sbString.ToString().Substring(0, 2);
break;
}
// Save these
lastScanCode = lScanCode;
lastVKCode = vKCode;
lastKeyState = (byte[])bKeyState.Clone();
return ret;
}
}

Просмотреть файл

@ -0,0 +1,79 @@
// 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;
using System.IO.Abstractions;
using interop;
namespace PowerAccent.Core.Tools
{
public static class Logger
{
private static readonly IFileSystem _fileSystem = new FileSystem();
private static readonly string ApplicationLogPath = Path.Combine(Constants.AppDataPath(), "PowerAccent\\Logs");
static Logger()
{
if (!_fileSystem.Directory.Exists(ApplicationLogPath))
{
_fileSystem.Directory.CreateDirectory(ApplicationLogPath);
}
// Using InvariantCulture since this is used for a log file name
var logFilePath = _fileSystem.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;
}
}
}

Просмотреть файл

@ -0,0 +1,78 @@
// 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.InteropServices;
using Vanara.PInvoke;
namespace PowerAccent.Core.Tools;
internal static class WindowsFunctions
{
public static void Insert(char c, bool back = false)
{
unsafe
{
if (back)
{
// Split in 2 different SendInput (Powershell doesn't take back issue)
var inputsBack = new User32.INPUT[]
{
new User32.INPUT { type = User32.INPUTTYPE.INPUT_KEYBOARD, ki = new User32.KEYBDINPUT { wVk = (ushort)User32.VK.VK_BACK } },
new User32.INPUT { type = User32.INPUTTYPE.INPUT_KEYBOARD, ki = new User32.KEYBDINPUT { wVk = (ushort)User32.VK.VK_BACK, dwFlags = User32.KEYEVENTF.KEYEVENTF_KEYUP } },
};
var temp1 = User32.SendInput((uint)inputsBack.Length, inputsBack, sizeof(User32.INPUT));
System.Threading.Thread.Sleep(1); // Some apps, like Terminal, need a little wait to process the sent backspace or they'll ignore it.
}
// Letter
var inputsInsert = new User32.INPUT[1]
{
new User32.INPUT { type = User32.INPUTTYPE.INPUT_KEYBOARD, ki = new User32.KEYBDINPUT { wVk = 0, dwFlags = User32.KEYEVENTF.KEYEVENTF_UNICODE, wScan = c } },
};
var temp2 = User32.SendInput((uint)inputsInsert.Length, inputsInsert, sizeof(User32.INPUT));
}
}
public static Point GetCaretPosition()
{
User32.GUITHREADINFO guiInfo = new ();
guiInfo.cbSize = (uint)Marshal.SizeOf(guiInfo);
User32.GetGUIThreadInfo(0, ref guiInfo);
System.Drawing.Point caretPosition = new System.Drawing.Point(guiInfo.rcCaret.left, guiInfo.rcCaret.top);
User32.ClientToScreen(guiInfo.hwndCaret, ref caretPosition);
if (caretPosition.X == 0)
{
System.Drawing.Point testPoint;
User32.GetCaretPos(out testPoint);
return testPoint;
}
return caretPosition;
}
public static (Point Location, Size Size, double Dpi) GetActiveDisplay()
{
User32.GUITHREADINFO guiInfo = new ();
guiInfo.cbSize = (uint)Marshal.SizeOf(guiInfo);
User32.GetGUIThreadInfo(0, ref guiInfo);
var res = User32.MonitorFromWindow(guiInfo.hwndActive, User32.MonitorFlags.MONITOR_DEFAULTTONEAREST);
User32.MONITORINFO monitorInfo = new ();
monitorInfo.cbSize = (uint)Marshal.SizeOf(monitorInfo);
User32.GetMonitorInfo(res, ref monitorInfo);
double dpi = User32.GetDpiForWindow(guiInfo.hwndActive) / 96d;
return (monitorInfo.rcWork.Location, monitorInfo.rcWork.Size, dpi);
}
public static bool IsCapitalState()
{
var capital = User32.GetKeyState((int)User32.VK.VK_CAPITAL);
var shift = User32.GetKeyState((int)User32.VK.VK_SHIFT);
return capital != 0 || shift < 0;
}
}

Просмотреть файл

@ -0,0 +1,17 @@
<Application x:Class="PowerAccent.UI.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:PowerAccent"
StartupUri="Selector.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<!-- Theme setting -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Blue.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>

Просмотреть файл

@ -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 System.Threading;
using System.Windows;
namespace PowerAccent.UI
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
private static Mutex _mutex;
protected override void OnStartup(StartupEventArgs e)
{
const string appName = "PowerAccent";
bool createdNew;
_mutex = new Mutex(true, appName, out createdNew);
if (!createdNew)
{
// app is already running! Exiting the application
Application.Current.Shutdown();
}
base.OnStartup(e);
}
}
}

Просмотреть файл

@ -0,0 +1,10 @@
// 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;
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, // where theme specific resource dictionaries are located (used if a resource is not found in the page, or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly) // where the generic resource dictionary is locate (used if a resource is not found in the page, app, or any theme specific resource dictionaries)
]

Просмотреть файл

@ -0,0 +1,35 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\Version.props" />
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
<Nullable>disable</Nullable>
<UseWPF>true</UseWPF>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<ApplicationIcon>a-icon.ico</ApplicationIcon>
<AssemblyName>PowerAccent</AssemblyName>
<XamlDebuggingInformation>True</XamlDebuggingInformation>
</PropertyGroup>
<ItemGroup>
<None Remove="win11desktop.jpg" />
</ItemGroup>
<ItemGroup>
<Resource Include="a-icon.ico">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Resource>
<Resource Include="win11desktop.jpg" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="gong-wpf-dragdrop" Version="3.1.1" />
<PackageReference Include="MahApps.Metro" Version="2.4.9" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PowerAccent.Core\PowerAccent.Core.csproj" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,55 @@
<Window x:Class="PowerAccent.UI.Selector"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:PowerAccent"
mc:Ignorable="d" SizeToContent="WidthAndHeight" ShowInTaskbar="False" ResizeMode="NoResize"
Title="MainWindow" Height="50" Width="50" Visibility="Collapsed" WindowStyle="None">
<Grid>
<ListBox x:Name="characters" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" IsHitTestVisible="False"
BorderThickness="1" BorderBrush="SlateGray">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel IsItemsHost="False" Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock TextAlignment="Center" VerticalAlignment="Center" Text="{Binding}" FontSize="18" />
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemContainerStyle>
<Style x:Name="ItemStyle" TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border x:Name="myBorder"
Padding="0" Margin="0"
SnapsToDevicePixels="true"
Style="{DynamicResource borderContent}">
<ContentPresenter />
</Border>
<ControlTemplate.Resources>
<Style x:Key="borderContent" TargetType="Border">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Background" Value="#ECECEC"/>
<Setter Property="Width" Value="50"/>
<Setter Property="Height" Value="50"/>
</Style>
</ControlTemplate.Resources>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="myBorder" Property="Background" Value="White"/>
<Setter Property="FontWeight" Value="Bold"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
</Grid>
</Window>

Просмотреть файл

@ -0,0 +1,71 @@
// 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;
using Point = PowerAccent.Core.Point;
using Size = PowerAccent.Core.Size;
namespace PowerAccent.UI;
public partial class Selector : Window, IDisposable
{
private Core.PowerAccent _powerAccent = new Core.PowerAccent();
public Selector()
{
InitializeComponent();
Application.Current.MainWindow.ShowActivated = false;
Application.Current.MainWindow.Topmost = true;
}
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
_powerAccent.OnChangeDisplay += PowerAccent_OnChangeDisplay;
_powerAccent.OnSelectCharacter += PowerAccent_OnSelectionCharacter;
this.Visibility = Visibility.Hidden;
}
private void PowerAccent_OnSelectionCharacter(int index, char character)
{
characters.SelectedIndex = index;
}
private void PowerAccent_OnChangeDisplay(bool isActive, char[] chars)
{
this.Visibility = isActive ? Visibility.Visible : Visibility.Collapsed;
if (isActive)
{
CenterWindow();
characters.ItemsSource = chars;
Microsoft.PowerToys.Telemetry.PowerToysTelemetry.Log.WriteEvent(new PowerAccent.Core.Telemetry.PowerAccentShowAccentMenuEvent());
}
}
private void MenuExit_Click(object sender, RoutedEventArgs e)
{
Application.Current.Shutdown();
}
private void CenterWindow()
{
UpdateLayout();
Size window = new Size(((System.Windows.Controls.Panel)Application.Current.MainWindow.Content).ActualWidth, ((System.Windows.Controls.Panel)Application.Current.MainWindow.Content).ActualHeight);
Point position = _powerAccent.GetDisplayCoordinates(window);
this.Left = position.X;
this.Top = position.Y;
}
protected override void OnClosed(EventArgs e)
{
_powerAccent.Dispose();
base.OnClosed(e);
}
public void Dispose()
{
GC.SuppressFinalize(this);
}
}

Двоичные данные
src/modules/poweraccent/PowerAccent.UI/a-icon.ico Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 9.4 KiB

Двоичные данные
src/modules/poweraccent/PowerAccent.UI/win11desktop.jpg Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 39 KiB

Просмотреть файл

@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\Version.props" />
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
<UseWPF>true</UseWPF>
<Nullable>disable</Nullable>
<StartupObject>PowerAccent.Program</StartupObject>
<OutputPath>$(SolutionDir)$(Platform)\$(Configuration)\modules\PowerAccent</OutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<AssemblyName>PowerToys.PowerAccent</AssemblyName>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
<ProjectReference Include="..\..\..\settings-ui\Settings.UI.Library\Settings.UI.Library.csproj" />
<ProjectReference Include="..\PowerAccent.UI\PowerAccent.UI.csproj" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,96 @@
// 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.
#pragma warning disable SA1310 // FieldNamesMustNotContainUnderscore
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using interop;
using ManagedCommon;
using PowerAccent.Core.Tools;
using PowerAccent.UI;
namespace PowerAccent;
internal static class Program
{
private const string PROGRAM_NAME = "PowerAccent";
private const string PROGRAM_APP_NAME = "PowerToys.PowerAccent";
private static App _application;
private static int _powerToysRunnerPid;
private static CancellationTokenSource _tokenSource = new CancellationTokenSource();
[STAThread]
public static void Main(string[] args)
{
_ = new Mutex(true, PROGRAM_APP_NAME, out bool instantiated);
if (instantiated)
{
Arguments(args);
InitEvents();
_application = new App();
_application.InitializeComponent();
_application.Run();
}
else
{
Logger.LogWarning("Another running PowerAccent instance was detected. Exiting PowerAccent");
}
}
private static void InitEvents()
{
Task.Run(
() =>
{
EventWaitHandle eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.PowerAccentExitEvent());
if (eventHandle.WaitOne())
{
Terminate();
}
}, _tokenSource.Token);
}
private static void Arguments(string[] args)
{
if (args?.Length > 0)
{
try
{
_ = int.TryParse(args[0], out _powerToysRunnerPid);
Logger.LogInfo($"PowerAccent started from the PowerToys Runner. Runner pid={_powerToysRunnerPid}");
RunnerHelper.WaitForPowerToysRunner(_powerToysRunnerPid, () =>
{
Logger.LogInfo("PowerToys Runner exited. Exiting PowerAccent");
Terminate();
});
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
else
{
Logger.LogInfo($"PowerAccent started detached from PowerToys Runner.");
_powerToysRunnerPid = -1;
}
}
private static void Terminate()
{
Application.Current.Dispatcher.BeginInvoke(() =>
{
_tokenSource.Cancel();
Application.Current.Shutdown();
});
}
}

Двоичные данные
src/modules/poweraccent/PowerAccent/win11desktop.jpg Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 39 KiB

Просмотреть файл

@ -0,0 +1,7 @@
#include <string>
namespace PowerAccentConstants
{
// Name of the powertoy module.
inline const std::wstring ModuleKey = L"PowerAccent";
}

Просмотреть файл

@ -0,0 +1,108 @@
// Microsoft Visual C++ generated resource script.
//
#include <windows.h>
#include "resource.h"
#include "../../../common/version/version.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#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
/////////////////////////////////////////////////////////////////////////////
// English (United States) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE
BEGIN
IDS_POWERACCENT_NAME "PowerAccent"
END
#endif // English (United States) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

Просмотреть файл

@ -0,0 +1,82 @@
<?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.220418.1\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.props')" />
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{34A354C5-23C7-4343-916C-C52DAF4FC39D}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>PowerAccent</RootNamespace>
<ProjectName>PowerAccentModuleInterface</ProjectName>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
</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\PowerAccent\</OutDir>
</PropertyGroup>
<PropertyGroup >
<TargetName>PowerToys.$(ProjectName)</TargetName>
</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="PowerAccentConstants.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="trace.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</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="PowerAccentModuleInterface.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.220418.1\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.220201.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.220201.1\build\native\Microsoft.Windows.ImplementationLibrary.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.220418.1\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220418.1\build\native\Microsoft.Windows.CppWinRT.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.220201.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.220201.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
</Target>
</Project>

Просмотреть файл

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="trace.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="pch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="dllmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="PowerAccentConstants.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="trace.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Generated Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Header Files">
<UniqueIdentifier>{e8ef1c4e-cc50-4ce5-b00d-4e3ac5c1a7db}</UniqueIdentifier>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{fbd9cdd2-e7d5-4417-9b52-25e345ae9562}</UniqueIdentifier>
</Filter>
<Filter Include="Generated Files">
<UniqueIdentifier>{c2a23a2b-5846-440f-b29e-eea748dba12d}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{77f1702b-da7f-4ff6-90a3-19db515cf963}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="PowerAccentModuleInterface.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,186 @@
#include "pch.h"
#include <interface/powertoy_module_interface.h>
#include <common/SettingsAPI/settings_objects.h>
#include <common/interop/shared_constants.h>
#include "trace.h"
#include "resource.h"
#include "PowerAccentConstants.h"
#include <common/logger/logger.h>
#include <common/SettingsAPI/settings_helpers.h>
#include <common/utils/elevation.h>
#include <common/utils/process_path.h>
#include <common/utils/resources.h>
#include <common/utils/os-detect.h>
#include <common/utils/logger_helper.h>
#include <common/utils/winapi_error.h>
#include <filesystem>
#include <set>
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:
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
Trace::UnregisterProvider();
break;
}
return TRUE;
}
const static wchar_t* MODULE_NAME = L"PowerAccent";
const static wchar_t* MODULE_DESC = L"A module that keeps your computer PowerAccent on-demand.";
class PowerAccent : public PowertoyModuleIface
{
std::wstring app_name;
std::wstring app_key;
private:
bool m_enabled = false;
HANDLE m_hInvokeEvent;
PROCESS_INFORMATION p_info;
bool is_process_running()
{
return WaitForSingleObject(p_info.hProcess, 0) == WAIT_TIMEOUT;
}
void launch_process()
{
Logger::trace(L"Launching PowerToys PowerAccent process");
unsigned long powertoys_pid = GetCurrentProcessId();
std::wstring executable_args = L"" + std::to_wstring(powertoys_pid);
std::wstring application_path = L"modules\\PowerAccent\\PowerToys.PowerAccent.exe";
std::wstring full_command_path = application_path + L" " + executable_args.data();
Logger::trace(L"PowerToys PowerAccent launching: " + full_command_path);
STARTUPINFO info = { sizeof(info) };
if (!CreateProcess(application_path.c_str(), full_command_path.data(), NULL, NULL, true, NULL, NULL, NULL, &info, &p_info))
{
DWORD error = GetLastError();
std::wstring message = L"PowerToys PowerAccent failed to start with error: ";
message += std::to_wstring(error);
Logger::error(message);
}
}
public:
PowerAccent()
{
app_name = MODULE_NAME;
app_key = PowerAccentConstants::ModuleKey;
LoggerHelpers::init_logger(app_key, L"ModuleInterface", "PowerAccent");
Logger::info("Launcher object is constructing");
};
virtual void destroy() override
{
delete this;
}
virtual const wchar_t* get_name() override
{
return MODULE_NAME;
}
virtual bool get_config(wchar_t* buffer, int* buffer_size) override
{
HINSTANCE hinstance = reinterpret_cast<HINSTANCE>(&__ImageBase);
PowerToysSettings::Settings settings(hinstance, get_name());
settings.set_description(MODULE_DESC);
return settings.serialize_to_buffer(buffer, buffer_size);
}
virtual const wchar_t* get_key() override
{
return app_key.c_str();
}
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());
// If you don't need to do any custom processing of the settings, proceed
// to persists the values.
values.save_to_settings_file();
}
catch (std::exception&)
{
// Improper JSON.
}
}
virtual void enable()
{
ResetEvent(m_hInvokeEvent);
launch_process();
m_enabled = true;
Trace::EnablePowerAccent(true);
};
virtual void disable()
{
if (m_enabled)
{
Logger::trace(L"Disabling PowerAccent... {}", m_enabled);
ResetEvent(m_hInvokeEvent);
auto exitEvent = CreateEvent(nullptr, false, false, CommonSharedConstants::POWERACCENT_EXIT_EVENT);
if (!exitEvent)
{
Logger::warn(L"Failed to create exit event for PowerToys PowerAccent. {}", get_last_error_or_default(GetLastError()));
}
else
{
Logger::trace(L"Signaled exit event for PowerToys PowerAccent.");
if (!SetEvent(exitEvent))
{
Logger::warn(L"Failed to signal exit event for PowerToys PowerAccent. {}", get_last_error_or_default(GetLastError()));
// For some reason, we couldn't process the signal correctly, so we still
// need to terminate the PowerAccent process.
TerminateProcess(p_info.hProcess, 1);
}
ResetEvent(exitEvent);
CloseHandle(exitEvent);
CloseHandle(p_info.hProcess);
}
}
m_enabled = false;
Trace::EnablePowerAccent(false);
}
virtual bool is_enabled() override
{
return m_enabled;
}
// Returns whether the PowerToys should be enabled by default
virtual bool is_enabled_by_default() const override
{
return false;
}
};
extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create()
{
return new PowerAccent();
}

Просмотреть файл

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.200729.8" targetFramework="native" />
</packages>

Просмотреть файл

@ -0,0 +1 @@
#include "pch.h"

Просмотреть файл

@ -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,26 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by PowerAccent.rc
//
#define IDS_POWERACCENT_NAME 101
//////////////////////////////
// Non-localizable
#define FILE_DESCRIPTION "PowerToys PowerAccent Module"
#define INTERNAL_NAME "PowerToys.PowerAccentModuleInterface"
#define ORIGINAL_FILENAME "PowerToys.PowerAccentModuleInterface.dll"
// Non-localizable
//////////////////////////////
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

Просмотреть файл

@ -0,0 +1,29 @@
#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::EnablePowerAccent(const bool enabled) noexcept
{
TraceLoggingWrite(
g_hProvider,
"PowerAccent_EnablePowerAccent",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
TraceLoggingBoolean(enabled, "Enabled"));
}

Просмотреть файл

@ -0,0 +1,11 @@
#pragma once
class Trace
{
public:
static void RegisterProvider();
static void UnregisterProvider();
// Log if the user has PowerAccent enabled or disabled
static void EnablePowerAccent(const bool enabled) noexcept;
};

Просмотреть файл

@ -153,8 +153,8 @@ int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow
L"modules/MouseUtils/PowerToys.MouseHighlighter.dll",
L"modules/AlwaysOnTop/PowerToys.AlwaysOnTopModuleInterface.dll",
L"modules/MouseUtils/PowerToys.MousePointerCrosshairs.dll",
L"modules/PowerAccent/PowerToys.PowerAccentModuleInterface.dll",
L"modules/PowerOCR/PowerToys.PowerOCRModuleInterface.dll",
};
const auto VCM_PATH = L"modules/VideoConference/PowerToys.VideoConferenceModule.dll";
if (const auto mf = LoadLibraryA("mf.dll"))

Просмотреть файл

@ -239,6 +239,22 @@ namespace Microsoft.PowerToys.Settings.UI.Library
}
}
private bool powerAccent;
[JsonPropertyName("PowerAccent")]
public bool PowerAccent
{
get => powerAccent;
set
{
if (powerAccent != value)
{
LogTelemetryEvent(value);
powerAccent = value;
}
}
}
private bool powerOCR = true;
[JsonPropertyName("PowerOCR")]

Просмотреть файл

@ -0,0 +1,13 @@
// 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.
namespace Microsoft.PowerToys.Settings.UI.Library.Enumerations
{
public enum PowerAccentActivationKey
{
LeftRightArrow,
Space,
Both,
}
}

Просмотреть файл

@ -0,0 +1,25 @@
// 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 ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class PowerAccentProperties
{
[JsonPropertyName("activation_key")]
public PowerAccentActivationKey ActivationKey { get; set; }
[JsonPropertyName("toolbar_position")]
public StringProperty ToolbarPosition { get; set; }
public PowerAccentProperties()
{
ActivationKey = PowerAccentActivationKey.Both;
ToolbarPosition = "Top center";
}
}
}

Просмотреть файл

@ -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 PowerAccentSettings : BasePTModuleSettings, ISettingsConfig
{
public const string ModuleName = "PowerAccent";
public const string ModuleVersion = "0.0.1";
[JsonPropertyName("properties")]
public PowerAccentProperties Properties { get; set; }
public PowerAccentSettings()
{
Name = ModuleName;
Version = ModuleVersion;
Properties = new PowerAccentProperties();
}
public string GetModuleName()
{
return Name;
}
public bool UpgradeSettingsConfiguration()
{
return false;
}
}
}

Просмотреть файл

@ -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 SndPowerAccentSettings
{
[JsonPropertyName("PowerAccent")]
public PowerAccentSettings PowerAccentSettings { get; set; }
public SndPowerAccentSettings()
{
}
public SndPowerAccentSettings(PowerAccentSettings settings)
{
PowerAccentSettings = settings;
}
public string ToJsonString()
{
return JsonSerializer.Serialize(this);
}
}
}

Просмотреть файл

@ -0,0 +1,187 @@
// 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.Runtime.CompilerServices;
using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
{
public class PowerAccentViewModel : Observable
{
private GeneralSettings GeneralSettingsConfig { get; set; }
private readonly PowerAccentSettings _powerAccentSettings;
private readonly ISettingsUtils _settingsUtils;
private Func<string, int> SendConfigMSG { get; }
public PowerAccentViewModel(ISettingsUtils settingsUtils, ISettingsRepository<GeneralSettings> settingsRepository, Func<string, int> ipcMSGCallBackFunc)
{
// To obtain the general settings configurations of PowerToys Settings.
if (settingsRepository == null)
{
throw new ArgumentNullException(nameof(settingsRepository));
}
_settingsUtils = settingsUtils ?? throw new ArgumentNullException(nameof(settingsUtils));
GeneralSettingsConfig = settingsRepository.SettingsConfig;
_isEnabled = GeneralSettingsConfig.Enabled.PowerAccent;
if (_settingsUtils.SettingsExists(PowerAccentSettings.ModuleName))
{
_powerAccentSettings = _settingsUtils.GetSettingsOrDefault<PowerAccentSettings>(PowerAccentSettings.ModuleName);
}
else
{
_powerAccentSettings = new PowerAccentSettings();
}
switch (_powerAccentSettings.Properties.ToolbarPosition.Value)
{
case "Top center":
_toolbarPositionIndex = 0;
break;
case "Bottom center":
_toolbarPositionIndex = 1;
break;
case "Left":
_toolbarPositionIndex = 2;
break;
case "Right":
_toolbarPositionIndex = 3;
break;
case "Top right corner":
_toolbarPositionIndex = 4;
break;
case "Top left corner":
_toolbarPositionIndex = 5;
break;
case "Bottom right corner":
_toolbarPositionIndex = 6;
break;
case "Bottom left corner":
_toolbarPositionIndex = 7;
break;
case "Center":
_toolbarPositionIndex = 8;
break;
}
// set the callback functions value to hangle outgoing IPC message.
SendConfigMSG = ipcMSGCallBackFunc;
}
public bool IsEnabled
{
get => _isEnabled;
set
{
if (_isEnabled != value)
{
_isEnabled = value;
GeneralSettingsConfig.Enabled.PowerAccent = value;
OnPropertyChanged(nameof(IsEnabled));
OutGoingGeneralSettings outgoing = new OutGoingGeneralSettings(GeneralSettingsConfig);
SendConfigMSG(outgoing.ToString());
}
}
}
public int ActivationKey
{
get
{
return (int)_powerAccentSettings.Properties.ActivationKey;
}
set
{
if (value != (int)_powerAccentSettings.Properties.ActivationKey)
{
_powerAccentSettings.Properties.ActivationKey = (PowerAccentActivationKey)value;
OnPropertyChanged(nameof(ActivationKey));
RaisePropertyChanged();
}
}
}
private int _toolbarPositionIndex;
public int ToolbarPositionIndex
{
get
{
return _toolbarPositionIndex;
}
set
{
if (_toolbarPositionIndex != value)
{
_toolbarPositionIndex = value;
switch (_toolbarPositionIndex)
{
case 0:
_powerAccentSettings.Properties.ToolbarPosition.Value = "Top center";
break;
case 1:
_powerAccentSettings.Properties.ToolbarPosition.Value = "Bottom center";
break;
case 2:
_powerAccentSettings.Properties.ToolbarPosition.Value = "Left";
break;
case 3:
_powerAccentSettings.Properties.ToolbarPosition.Value = "Right";
break;
case 4:
_powerAccentSettings.Properties.ToolbarPosition.Value = "Top right corner";
break;
case 5:
_powerAccentSettings.Properties.ToolbarPosition.Value = "Top left corner";
break;
case 6:
_powerAccentSettings.Properties.ToolbarPosition.Value = "Bottom right corner";
break;
case 7:
_powerAccentSettings.Properties.ToolbarPosition.Value = "Bottom left corner";
break;
case 8:
_powerAccentSettings.Properties.ToolbarPosition.Value = "Center";
break;
}
RaisePropertyChanged(nameof(ToolbarPositionIndex));
}
}
}
private void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
// Notify UI of property change
OnPropertyChanged(propertyName);
if (SendConfigMSG != null)
{
SndPowerAccentSettings snd = new SndPowerAccentSettings(_powerAccentSettings);
SndModuleSettings<SndPowerAccentSettings> ipcMessage = new SndModuleSettings<SndPowerAccentSettings>(snd);
SendConfigMSG(ipcMessage.ToJsonString());
}
}
private bool _isEnabled;
}
}

Просмотреть файл

@ -122,6 +122,7 @@ namespace Microsoft.PowerToys.Settings.UI
case "ImageResizer": StartupPage = typeof(Views.ImageResizerPage); break;
case "KBM": StartupPage = typeof(Views.KeyboardManagerPage); break;
case "MouseUtils": StartupPage = typeof(Views.MouseUtilsPage); break;
case "PowerAccent": StartupPage = typeof(Views.PowerAccentPage); break;
case "PowerOCR": StartupPage = typeof(Views.PowerOcrPage); break;
case "PowerRename": StartupPage = typeof(Views.PowerRenamePage); break;
case "FileExplorer": StartupPage = typeof(Views.PowerPreviewPage); break;

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 2.4 KiB

Двоичные данные
src/settings-ui/Settings.UI/Assets/Modules/OOBE/PowerAccent.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 186 KiB

Двоичные данные
src/settings-ui/Settings.UI/Assets/Modules/PowerAccent.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 202 KiB

Просмотреть файл

@ -0,0 +1,44 @@
<UserControl
x:Class="Microsoft.PowerToys.Settings.UI.Controls.PowerAccentShortcutControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ItemsControl AutomationProperties.AccessibilityView="Raw"
ItemsSource="{x:Bind Keys}"
VerticalAlignment="Center"
IsTabStop="False">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Spacing="4" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<controls:KeyVisual IsTabStop="False"
AutomationProperties.AccessibilityView="Raw"
VisualType="SmallOutline"
VerticalAlignment="Center"
Content="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<toolkitcontrols:MarkdownTextBlock Background="Transparent"
Text="{x:Bind Text}"
Margin="8,0,0,0"
Grid.Column="1"
VerticalAlignment="Center" />
</Grid>
</UserControl>

Просмотреть файл

@ -0,0 +1,36 @@
// 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 Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Controls
{
public sealed partial class PowerAccentShortcutControl : UserControl
{
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(PowerAccentShortcutControl), new PropertyMetadata(default(string)));
#pragma warning disable CA2227 // Collection properties should be read only
public List<object> Keys
#pragma warning restore CA2227 // Collection properties should be read only
{
get { return (List<object>)GetValue(KeysProperty); }
set { SetValue(KeysProperty, value); }
}
public static readonly DependencyProperty KeysProperty = DependencyProperty.Register("Keys", typeof(List<object>), typeof(PowerAccentShortcutControl), new PropertyMetadata(default(string)));
public PowerAccentShortcutControl()
{
this.InitializeComponent();
}
}
}

Просмотреть файл

@ -15,6 +15,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Enums
ImageResizer,
KBM,
MouseUtils,
PowerAccent,
PowerOCR,
PowerRename,
Run,

Просмотреть файл

@ -0,0 +1,33 @@
<Page x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobePowerAccent"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.OOBE.Views"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls">
<controls:OOBEPageControl x:Uid="Oobe_PowerAccent"
HeroImage="ms-appx:///Assets/Modules/OOBE/PowerAccent.gif">
<controls:OOBEPageControl.PageContent>
<StackPanel Orientation="Vertical">
<TextBlock x:Uid="Oobe_HowToUse"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock Background="Transparent" x:Uid="Oobe_PowerAccent_HowToUse" />
<StackPanel Orientation="Horizontal" Spacing="12" Margin="0,24,0,0">
<Button x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click"/>
<HyperlinkButton NavigateUri="https://github.com/damienleroy/PowerAccent/"
Style="{StaticResource TextButtonStyle}">
<TextBlock x:Uid="LearnMore_PowerAccent"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.PageContent>
</controls:OOBEPageControl>
</Page>

Просмотреть файл

@ -0,0 +1,44 @@
// 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.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 OobePowerAccent : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobePowerAccent()
{
InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.PowerAccent]);
DataContext = ViewModel;
}
private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.OpenMainWindowCallback != null)
{
OobeShellPage.OpenMainWindowCallback(typeof(PowerAccentPage));
}
ViewModel.LogOpeningSettingsEvent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
}
}

Просмотреть файл

@ -116,6 +116,14 @@
</muxc:NavigationViewItem.Icon>
</muxc:NavigationViewItem>
<muxc:NavigationViewItem x:Uid="Shell_PowerAccent"
Tag="PowerAccent">
<muxc:NavigationViewItem.Icon>
<BitmapIcon UriSource="ms-appx:///Assets/FluentIcons/FluentIconsPowerAccent.png"
ShowAsMonochrome="False" />
</muxc:NavigationViewItem.Icon>
</muxc:NavigationViewItem>
<muxc:NavigationViewItem x:Uid="Shell_PowerOCR"
Tag="PowerOCR">
<muxc:NavigationViewItem.Icon>

Просмотреть файл

@ -102,11 +102,19 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
ModuleName = "MouseUtils",
IsNew = true,
});
Modules.Insert((int)PowerToysModules.PowerAccent, new OobePowerToysModule()
{
ModuleName = "PowerAccent",
IsNew = true,
});
Modules.Insert((int)PowerToysModules.PowerOCR, new OobePowerToysModule()
{
ModuleName = "PowerOCR",
IsNew = true,
});
Modules.Insert((int)PowerToysModules.PowerRename, new OobePowerToysModule()
{
ModuleName = "PowerRename",
@ -174,6 +182,7 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
case "Run": NavigationFrame.Navigate(typeof(OobeRun)); break;
case "ImageResizer": NavigationFrame.Navigate(typeof(OobeImageResizer)); break;
case "KBM": NavigationFrame.Navigate(typeof(OobeKBM)); break;
case "PowerAccent": NavigationFrame.Navigate(typeof(OobePowerAccent)); break;
case "PowerRename": NavigationFrame.Navigate(typeof(OobePowerRename)); break;
case "PowerOCR": NavigationFrame.Navigate(typeof(OobePowerOCR)); break;
case "FileExplorer": NavigationFrame.Navigate(typeof(OobeFileExplorer)); break;

Просмотреть файл

@ -2164,6 +2164,89 @@ From there, simply click on one of the supported files in the File Explorer and
<data name="AlwaysOnTop_RoundCorners.Content" xml:space="preserve">
<value>Enable round corners</value>
</data>
<data name="LearnMore_PowerAccent.Text" xml:space="preserve">
<value>Learn more about PowerAccent</value>
<comment>PowerAccent is a product name, do not loc</comment>
</data>
<data name="PowerAccent_EnablePowerAccent.Header" xml:space="preserve">
<value>Enable PowerAccent</value>
</data>
<data name="Shell_PowerAccent.Content" xml:space="preserve">
<value>PowerAccent</value>
</data>
<data name="PowerAccent.ModuleDescription" xml:space="preserve">
<value>PowerAccent is an alternative way to type accented characters, useful for when a keyboard doesn't support that specific accent. While holding the key for the character you want to add an accent to, press the Activation Key (space key or left and right arrow keys) and an overlay to select the accented character will appear.</value>
<comment>key refers to a physical key on a keyboard</comment>
</data>
<data name="PowerAccent.ModuleTitle" xml:space="preserve">
<value>PowerAccent</value>
</data>
<data name="PowerAccent.SecondaryLinksHeader" xml:space="preserve">
<value>Attribution</value>
</data>
<data name="Oobe_PowerAccent.Description" xml:space="preserve">
<value>PowerAccent is an easy way to write letters with accents, like on the phone or Mac.</value>
</data>
<data name="Oobe_PowerAccent.Title" xml:space="preserve">
<value>PowerAccent</value>
</data>
<data name="Oobe_PowerAccent_HowToUse.Text" xml:space="preserve">
<value>Open **PowerToys Settings** and enable PowerAccent. While holding the key for the character you want to add an accent to, press the Activation Key and an overlay to select the accented character will appear.</value>
<comment>key refers to a physical key on a keyboard</comment>
</data>
<data name="PowerAccent_Activation_GroupSettings.Header" xml:space="preserve">
<value>Activation</value>
</data>
<data name="PowerAccent_Activation_Shortcut.Header" xml:space="preserve">
<value>Activation key</value>
</data>
<data name="PowerAccent_Activation_Shortcut.Description" xml:space="preserve">
<value>Select the activation key to activate this module by holding down the letter and pressing the activation key</value>
</data>
<data name="PowerAccent_Activation_Key_Arrows.Content" xml:space="preserve">
<value>Left/Right Arrow</value>
<comment>Left/Right arrow keyboard keys.</comment>
</data>
<data name="PowerAccent_Activation_Key_Space.Content" xml:space="preserve">
<value>Space</value>
<comment>Space is the space keyboard key.</comment>
</data>
<data name="PowerAccent_Activation_Key_Both.Content" xml:space="preserve">
<value>Both</value>
</data>
<data name="PowerAccent_Toolbar.Header" xml:space="preserve">
<value>Toolbar</value>
</data>
<data name="PowerAccent_ToolbarPosition.Header" xml:space="preserve">
<value>Toolbar position</value>
</data>
<data name="PowerAccent_ToolbarPosition_TopCenter.Content" xml:space="preserve">
<value>Top center</value>
</data>
<data name="PowerAccent_ToolbarPosition_TopLeftCorner.Content" xml:space="preserve">
<value>Top left corner</value>
</data>
<data name="PowerAccent_ToolbarPosition_TopRightCorner.Content" xml:space="preserve">
<value>Top right corner</value>
</data>
<data name="PowerAccent_ToolbarPosition_BottomLeftCorner.Content" xml:space="preserve">
<value>Bottom left corner</value>
</data>
<data name="PowerAccent_ToolbarPosition_BottomCenter.Content" xml:space="preserve">
<value>Bottom center</value>
</data>
<data name="PowerAccent_ToolbarPosition_BottomRightCorner.Content" xml:space="preserve">
<value>Bottom right corner</value>
</data>
<data name="PowerAccent_ToolbarPosition_Center.Content" xml:space="preserve">
<value>Center</value>
</data>
<data name="PowerAccent_ToolbarPosition_Left.Content" xml:space="preserve">
<value>Left</value>
</data>
<data name="PowerAccent_ToolbarPosition_Right.Content" xml:space="preserve">
<value>Right</value>
</data>
<data name="LearnMore_PowerOcr.Text" xml:space="preserve">
<value>Learn more about PowerOCR</value>
</data>

Просмотреть файл

@ -0,0 +1,69 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.Views.PowerAccentPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:converters="using:Microsoft.PowerToys.Settings.UI.Converters"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
mc:Ignorable="d"
AutomationProperties.LandmarkType="Main">
<controls:SettingsPageControl x:Uid="PowerAccent" IsTabStop="False"
ModuleImageSource="ms-appx:///Assets/Modules/PowerAccent.png">
<controls:SettingsPageControl.ModuleContent>
<StackPanel Orientation="Vertical">
<controls:Setting x:Uid="PowerAccent_EnablePowerAccent">
<controls:Setting.Icon>
<BitmapIcon UriSource="ms-appx:///Assets/FluentIcons/FluentIconsPowerAccent.png" ShowAsMonochrome="False" />
</controls:Setting.Icon>
<controls:Setting.ActionContent>
<ToggleSwitch IsOn="{x:Bind ViewModel.IsEnabled, Mode=TwoWay}" x:Uid="ToggleSwitch" HorizontalAlignment="Right"/>
</controls:Setting.ActionContent>
</controls:Setting>
<controls:SettingsGroup x:Uid="PowerAccent_Activation_GroupSettings" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<controls:Setting x:Uid="PowerAccent_Activation_Shortcut" Icon="&#xEDA7;">
<controls:Setting.ActionContent>
<ComboBox MinWidth="{StaticResource SettingActionControlMinWidth}"
SelectedIndex="{x:Bind Path=ViewModel.ActivationKey, Mode=TwoWay}" >
<ComboBoxItem x:Uid="PowerAccent_Activation_Key_Arrows"/>
<ComboBoxItem x:Uid="PowerAccent_Activation_Key_Space"/>
<ComboBoxItem x:Uid="PowerAccent_Activation_Key_Both"/>
</ComboBox>
</controls:Setting.ActionContent>
</controls:Setting>
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="PowerAccent_Toolbar" IsEnabled="{Binding Mode=OneWay, Path=IsEnabled}">
<controls:Setting x:Uid="PowerAccent_ToolbarPosition" Icon="&#xEC12;">
<controls:Setting.ActionContent>
<ComboBox MinWidth="{StaticResource SettingActionControlMinWidth}"
SelectedIndex="{x:Bind Path=ViewModel.ToolbarPositionIndex, Mode=TwoWay}" >
<ComboBoxItem x:Uid="PowerAccent_ToolbarPosition_TopCenter"/>
<ComboBoxItem x:Uid="PowerAccent_ToolbarPosition_BottomCenter"/>
<ComboBoxItem x:Uid="PowerAccent_ToolbarPosition_Left"/>
<ComboBoxItem x:Uid="PowerAccent_ToolbarPosition_Right"/>
<ComboBoxItem x:Uid="PowerAccent_ToolbarPosition_TopRightCorner"/>
<ComboBoxItem x:Uid="PowerAccent_ToolbarPosition_TopLeftCorner"/>
<ComboBoxItem x:Uid="PowerAccent_ToolbarPosition_BottomRightCorner"/>
<ComboBoxItem x:Uid="PowerAccent_ToolbarPosition_BottomLeftCorner"/>
<ComboBoxItem x:Uid="PowerAccent_ToolbarPosition_Center"/>
</ComboBox>
</controls:Setting.ActionContent>
</controls:Setting>
</controls:SettingsGroup>
</StackPanel>
</controls:SettingsPageControl.ModuleContent>
<controls:SettingsPageControl.PrimaryLinks>
<controls:PageLink x:Uid="LearnMore_PowerAccent" Link="https://aka.ms/PowerToysOverview_PowerAccent"/>
</controls:SettingsPageControl.PrimaryLinks>
<controls:SettingsPageControl.SecondaryLinks>
<controls:PageLink Text="Damien Leroy's PowerAccent" Link="https://github.com/damienleroy"/>
</controls:SettingsPageControl.SecondaryLinks>
</controls:SettingsPageControl>
</Page>

Просмотреть файл

@ -0,0 +1,23 @@
// 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.Library.ViewModels;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Views
{
public sealed partial class PowerAccentPage : Page
{
private PowerAccentViewModel ViewModel { get; set; }
public PowerAccentPage()
{
var settingsUtils = new SettingsUtils();
ViewModel = new PowerAccentViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage);
DataContext = ViewModel;
this.InitializeComponent();
}
}
}

Просмотреть файл

@ -113,6 +113,14 @@
</muxc:NavigationViewItem.Icon>
</muxc:NavigationViewItem>
<muxc:NavigationViewItem x:Uid="Shell_PowerAccent"
helpers:NavHelper.NavigateTo="views:PowerAccentPage">
<muxc:NavigationViewItem.Icon>
<BitmapIcon UriSource="ms-appx:///Assets/FluentIcons/FluentIconsPowerAccent.png"
ShowAsMonochrome="False" />
</muxc:NavigationViewItem.Icon>
</muxc:NavigationViewItem>
<muxc:NavigationViewItem x:Uid="Shell_PowerRename"
helpers:NavHelper.NavigateTo="views:PowerRenamePage">
<muxc:NavigationViewItem.Icon>

Просмотреть файл

@ -11,6 +11,7 @@ std::vector<std::wstring> processes =
L"PowerToys.FancyZones.exe",
L"PowerToys.KeyboardManagerEngine.exe",
L"PowerToys.KeyboardManagerEditor.exe",
L"PowerToys.PowerAccent.exe",
L"PowerToys.PowerLauncher.exe",
L"PowerToys.PowerOCR.exe",
L"PowerToys.ShortcutGuide.exe",