[New PowerToy] PowerAccent (#19212)
* 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:
Родитель
785160653c
Коммит
d9c0af232b
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 9.4 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 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();
|
||||
});
|
||||
}
|
||||
}
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 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;
|
||||
|
|
Двоичные данные
src/settings-ui/Settings.UI/Assets/FluentIcons/FluentIconsPowerAccent.png
Normal file
Двоичные данные
src/settings-ui/Settings.UI/Assets/FluentIcons/FluentIconsPowerAccent.png
Normal file
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 2.4 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 186 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 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="">
|
||||
<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="">
|
||||
<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",
|
||||
|
|
Загрузка…
Ссылка в новой задаче