mirror of
https://github.com/microsoft/PowerToys.git
synced 2024-11-24 04:12:32 +08:00
[PowerAccent] Move low-level keyboard hook to c++ (#20190)
* Move llkeyboardhook to c++ * expect.txt * Address PR comment - Resolve namespaces * Address PR comments - CallNextHook and correct char selection * Also unpress the letter key Co-authored-by: Jaime Bernardo <jaime@janeasystems.com>
This commit is contained in:
parent
7f8c5c9f0c
commit
7b0f97597d
2
.github/actions/spell-check/expect.txt
vendored
2
.github/actions/spell-check/expect.txt
vendored
@ -742,7 +742,7 @@ HKCC
|
|||||||
HKCR
|
HKCR
|
||||||
HKCU
|
HKCU
|
||||||
hkey
|
hkey
|
||||||
hkl
|
HKL
|
||||||
HKLM
|
HKLM
|
||||||
HKPD
|
HKPD
|
||||||
HKU
|
HKU
|
||||||
|
@ -117,6 +117,7 @@
|
|||||||
"modules\\PowerAccent\\PowerToys.PowerAccent.dll",
|
"modules\\PowerAccent\\PowerToys.PowerAccent.dll",
|
||||||
"modules\\PowerAccent\\PowerToys.PowerAccent.exe",
|
"modules\\PowerAccent\\PowerToys.PowerAccent.exe",
|
||||||
"modules\\PowerAccent\\PowerToys.PowerAccentModuleInterface.dll",
|
"modules\\PowerAccent\\PowerToys.PowerAccentModuleInterface.dll",
|
||||||
|
"modules\\PowerAccent\\PowerToys.PowerAccentKeyboardService.dll",
|
||||||
|
|
||||||
"modules\\PowerRename\\PowerToys.PowerRenameExt.dll",
|
"modules\\PowerRename\\PowerToys.PowerRenameExt.dll",
|
||||||
"modules\\PowerRename\\PowerToys.PowerRename.exe",
|
"modules\\PowerRename\\PowerToys.PowerRename.exe",
|
||||||
|
@ -447,6 +447,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MeasureToolModuleInterface"
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MeasureToolUI", "src\modules\MeasureTool\MeasureToolUI\MeasureToolUI.csproj", "{515554D1-D004-4F7F-A107-2211FC0F6B2C}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MeasureToolUI", "src\modules\MeasureTool\MeasureToolUI\MeasureToolUI.csproj", "{515554D1-D004-4F7F-A107-2211FC0F6B2C}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerAccentKeyboardService", "src\modules\poweraccent\PowerAccentKeyboardService\PowerAccentKeyboardService.vcxproj", "{C97D9A5D-206C-454E-997E-009E227D7F02}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|ARM64 = Debug|ARM64
|
Debug|ARM64 = Debug|ARM64
|
||||||
@ -1790,6 +1792,18 @@ Global
|
|||||||
{515554D1-D004-4F7F-A107-2211FC0F6B2C}.Release|x86.ActiveCfg = Release|x86
|
{515554D1-D004-4F7F-A107-2211FC0F6B2C}.Release|x86.ActiveCfg = Release|x86
|
||||||
{515554D1-D004-4F7F-A107-2211FC0F6B2C}.Release|x86.Build.0 = Release|x86
|
{515554D1-D004-4F7F-A107-2211FC0F6B2C}.Release|x86.Build.0 = Release|x86
|
||||||
{515554D1-D004-4F7F-A107-2211FC0F6B2C}.Release|x86.Deploy.0 = Release|x86
|
{515554D1-D004-4F7F-A107-2211FC0F6B2C}.Release|x86.Deploy.0 = Release|x86
|
||||||
|
{C97D9A5D-206C-454E-997E-009E227D7F02}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||||
|
{C97D9A5D-206C-454E-997E-009E227D7F02}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||||
|
{C97D9A5D-206C-454E-997E-009E227D7F02}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{C97D9A5D-206C-454E-997E-009E227D7F02}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{C97D9A5D-206C-454E-997E-009E227D7F02}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
|
{C97D9A5D-206C-454E-997E-009E227D7F02}.Debug|x86.Build.0 = Debug|x64
|
||||||
|
{C97D9A5D-206C-454E-997E-009E227D7F02}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||||
|
{C97D9A5D-206C-454E-997E-009E227D7F02}.Release|ARM64.Build.0 = Release|ARM64
|
||||||
|
{C97D9A5D-206C-454E-997E-009E227D7F02}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{C97D9A5D-206C-454E-997E-009E227D7F02}.Release|x64.Build.0 = Release|x64
|
||||||
|
{C97D9A5D-206C-454E-997E-009E227D7F02}.Release|x86.ActiveCfg = Release|x64
|
||||||
|
{C97D9A5D-206C-454E-997E-009E227D7F02}.Release|x86.Build.0 = Release|x64
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@ -1941,6 +1955,7 @@ Global
|
|||||||
{54A93AF7-60C7-4F6C-99D2-FBB1F75F853A} = {7AC943C9-52E8-44CF-9083-744D8049667B}
|
{54A93AF7-60C7-4F6C-99D2-FBB1F75F853A} = {7AC943C9-52E8-44CF-9083-744D8049667B}
|
||||||
{92C39820-9F84-4529-BC7D-22AAE514D63B} = {7AC943C9-52E8-44CF-9083-744D8049667B}
|
{92C39820-9F84-4529-BC7D-22AAE514D63B} = {7AC943C9-52E8-44CF-9083-744D8049667B}
|
||||||
{515554D1-D004-4F7F-A107-2211FC0F6B2C} = {7AC943C9-52E8-44CF-9083-744D8049667B}
|
{515554D1-D004-4F7F-A107-2211FC0F6B2C} = {7AC943C9-52E8-44CF-9083-744D8049667B}
|
||||||
|
{C97D9A5D-206C-454E-997E-009E227D7F02} = {0F14491C-6369-4C45-AAA8-135814E66E6B}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0}
|
SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0}
|
||||||
|
@ -125,7 +125,7 @@
|
|||||||
|
|
||||||
<?define MeasureToolMicrosoftUIXamlAssetsInstallFiles=NoiseAsset_256x256_PNG.png?>
|
<?define MeasureToolMicrosoftUIXamlAssetsInstallFiles=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?>
|
<?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;PowerToys.PowerAccentKeyboardService.dll;Microsoft.Windows.SDK.NET.dll;WinRT.Runtime.dll?>
|
||||||
|
|
||||||
<Product Id="*"
|
<Product Id="*"
|
||||||
Name="PowerToys (Preview)"
|
Name="PowerToys (Preview)"
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
// 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,
|
|
||||||
}
|
|
@ -1,20 +1,28 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<Import Project="..\..\..\Version.props" />
|
<Import Project="..\..\..\Version.props" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0-windows</TargetFramework>
|
<TargetFramework>net6.0-windows10.0.19041.0</TargetFramework>
|
||||||
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>disable</Nullable>
|
<Nullable>disable</Nullable>
|
||||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||||
|
<UseWPF>true</UseWPF>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<CsWinRTIncludes>PowerToys.PowerAccentKeyboardService</CsWinRTIncludes>
|
||||||
|
<CsWinRTGeneratedFilesDir>$(OutDir)</CsWinRTGeneratedFilesDir>
|
||||||
|
<ErrorOnDuplicatePublishOutputFiles>false</ErrorOnDuplicatePublishOutputFiles>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Windows.CsWinRT" Version="2.0.0" />
|
||||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.0" />
|
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.0" />
|
||||||
<PackageReference Include="Vanara.PInvoke.User32" Version="3.3.15" />
|
<PackageReference Include="Vanara.PInvoke.User32" Version="3.3.15" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\..\settings-ui\Settings.UI.Library\Settings.UI.Library.csproj" />
|
<ProjectReference Include="..\..\..\settings-ui\Settings.UI.Library\Settings.UI.Library.csproj" />
|
||||||
|
<ProjectReference Include="..\PowerAccentKeyboardService\PowerAccentKeyboardService.vcxproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -2,64 +2,67 @@
|
|||||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
using System.Diagnostics;
|
using System.Windows;
|
||||||
using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
|
|
||||||
using PowerAccent.Core.Services;
|
using PowerAccent.Core.Services;
|
||||||
using PowerAccent.Core.Tools;
|
using PowerAccent.Core.Tools;
|
||||||
|
using PowerToys.PowerAccentKeyboardService;
|
||||||
|
|
||||||
namespace PowerAccent.Core;
|
namespace PowerAccent.Core;
|
||||||
|
|
||||||
public class PowerAccent : IDisposable
|
public class PowerAccent : IDisposable
|
||||||
{
|
{
|
||||||
private readonly SettingsService _settingService = new SettingsService();
|
private readonly SettingsService _settingService;
|
||||||
private readonly KeyboardListener _keyboardListener = new KeyboardListener();
|
|
||||||
|
|
||||||
private LetterKey? letterPressed;
|
|
||||||
private bool _visible;
|
private bool _visible;
|
||||||
private char[] _characters = Array.Empty<char>();
|
private char[] _characters = Array.Empty<char>();
|
||||||
private int _selectedIndex = -1;
|
private int _selectedIndex = -1;
|
||||||
private Stopwatch _stopWatch;
|
|
||||||
private bool _triggeredWithSpace;
|
|
||||||
|
|
||||||
public event Action<bool, char[]> OnChangeDisplay;
|
public event Action<bool, char[]> OnChangeDisplay;
|
||||||
|
|
||||||
public event Action<int, char> OnSelectCharacter;
|
public event Action<int, char> OnSelectCharacter;
|
||||||
|
|
||||||
|
private KeyboardListener _keyboardListener;
|
||||||
|
|
||||||
public PowerAccent()
|
public PowerAccent()
|
||||||
{
|
{
|
||||||
_keyboardListener.KeyDown += PowerAccent_KeyDown;
|
_keyboardListener = new KeyboardListener();
|
||||||
_keyboardListener.KeyUp += PowerAccent_KeyUp;
|
_keyboardListener.InitHook();
|
||||||
|
_settingService = new SettingsService(_keyboardListener);
|
||||||
|
|
||||||
|
SetEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool PowerAccent_KeyDown(object sender, KeyboardListener.RawKeyEventArgs args)
|
private void SetEvents()
|
||||||
{
|
{
|
||||||
if (Enum.IsDefined(typeof(LetterKey), (int)args.Key))
|
_keyboardListener.SetShowToolbarEvent(new PowerToys.PowerAccentKeyboardService.ShowToolbar((LetterKey letterKey) =>
|
||||||
{
|
{
|
||||||
_stopWatch = Stopwatch.StartNew();
|
Application.Current.Dispatcher.Invoke(() =>
|
||||||
letterPressed = (LetterKey)args.Key;
|
{
|
||||||
|
ShowToolbar(letterKey);
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
_keyboardListener.SetHideToolbarEvent(new PowerToys.PowerAccentKeyboardService.HideToolbar((InputType inputType) =>
|
||||||
|
{
|
||||||
|
Application.Current.Dispatcher.Invoke(() =>
|
||||||
|
{
|
||||||
|
SendInputAndHideToolbar(inputType);
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
_keyboardListener.SetNextCharEvent(new PowerToys.PowerAccentKeyboardService.NextChar((TriggerKey triggerKey) =>
|
||||||
|
{
|
||||||
|
Application.Current.Dispatcher.Invoke(() =>
|
||||||
|
{
|
||||||
|
ProcessNextChar(triggerKey);
|
||||||
|
});
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
TriggerKey? triggerPressed = null;
|
private void ShowToolbar(LetterKey letterKey)
|
||||||
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;
|
_visible = true;
|
||||||
_characters = WindowsFunctions.IsCapitalState() ? ToUpper(_settingService.GetLetterKey(letterPressed.Value)) : _settingService.GetLetterKey(letterPressed.Value);
|
_characters = WindowsFunctions.IsCapitalState() ? ToUpper(SettingsService.GetDefaultLetterKey(letterKey)) : SettingsService.GetDefaultLetterKey(letterKey);
|
||||||
Task.Delay(_settingService.InputTime).ContinueWith(
|
Task.Delay(_settingService.InputTime).ContinueWith(
|
||||||
t =>
|
t =>
|
||||||
{
|
{
|
||||||
@ -70,21 +73,47 @@ public class PowerAccent : IDisposable
|
|||||||
}, TaskScheduler.FromCurrentSynchronizationContext());
|
}, TaskScheduler.FromCurrentSynchronizationContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_visible && triggerPressed.HasValue)
|
private void SendInputAndHideToolbar(InputType inputType)
|
||||||
{
|
{
|
||||||
if (_selectedIndex == -1)
|
switch (inputType)
|
||||||
{
|
{
|
||||||
if (triggerPressed.Value == TriggerKey.Left)
|
case InputType.Space:
|
||||||
|
{
|
||||||
|
WindowsFunctions.Insert(' ');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case InputType.Char:
|
||||||
|
{
|
||||||
|
if (_selectedIndex != -1)
|
||||||
|
{
|
||||||
|
WindowsFunctions.Insert(_characters[_selectedIndex], true);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OnChangeDisplay?.Invoke(false, null);
|
||||||
|
_selectedIndex = -1;
|
||||||
|
_visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessNextChar(TriggerKey triggerKey)
|
||||||
|
{
|
||||||
|
if (_visible && _selectedIndex == -1)
|
||||||
|
{
|
||||||
|
if (triggerKey == TriggerKey.Left)
|
||||||
{
|
{
|
||||||
_selectedIndex = (_characters.Length / 2) - 1;
|
_selectedIndex = (_characters.Length / 2) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (triggerPressed.Value == TriggerKey.Right)
|
if (triggerKey == TriggerKey.Right)
|
||||||
{
|
{
|
||||||
_selectedIndex = _characters.Length / 2;
|
_selectedIndex = _characters.Length / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (triggerPressed.Value == TriggerKey.Space)
|
if (triggerKey == TriggerKey.Space)
|
||||||
{
|
{
|
||||||
_selectedIndex = 0;
|
_selectedIndex = 0;
|
||||||
}
|
}
|
||||||
@ -100,10 +129,10 @@ public class PowerAccent : IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
OnSelectCharacter?.Invoke(_selectedIndex, _characters[_selectedIndex]);
|
OnSelectCharacter?.Invoke(_selectedIndex, _characters[_selectedIndex]);
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (triggerPressed.Value == TriggerKey.Space)
|
if (triggerKey == TriggerKey.Space)
|
||||||
{
|
{
|
||||||
if (_selectedIndex < _characters.Length - 1)
|
if (_selectedIndex < _characters.Length - 1)
|
||||||
{
|
{
|
||||||
@ -115,60 +144,17 @@ public class PowerAccent : IDisposable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (triggerPressed.Value == TriggerKey.Left && _selectedIndex > 0)
|
if (triggerKey == TriggerKey.Left && _selectedIndex > 0)
|
||||||
{
|
{
|
||||||
--_selectedIndex;
|
--_selectedIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (triggerPressed.Value == TriggerKey.Right && _selectedIndex < _characters.Length - 1)
|
if (triggerKey == TriggerKey.Right && _selectedIndex < _characters.Length - 1)
|
||||||
{
|
{
|
||||||
++_selectedIndex;
|
++_selectedIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
OnSelectCharacter?.Invoke(_selectedIndex, _characters[_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)
|
public Point GetDisplayCoordinates(Size window)
|
||||||
@ -182,14 +168,9 @@ public class PowerAccent : IDisposable
|
|||||||
return Calculation.GetRawCoordinatesFromPosition(position, screen, window);
|
return Calculation.GetRawCoordinatesFromPosition(position, screen, window);
|
||||||
}
|
}
|
||||||
|
|
||||||
public char[] GetLettersFromKey(LetterKey letter)
|
|
||||||
{
|
|
||||||
return _settingService.GetLetterKey(letter);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_keyboardListener.Dispose();
|
_keyboardListener.UnInitHook();
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ namespace PowerAccent.Core.Services;
|
|||||||
using Microsoft.PowerToys.Settings.UI.Library;
|
using Microsoft.PowerToys.Settings.UI.Library;
|
||||||
using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
|
using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
|
||||||
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
|
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
|
||||||
|
using PowerToys.PowerAccentKeyboardService;
|
||||||
using System.IO.Abstractions;
|
using System.IO.Abstractions;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|
||||||
@ -16,10 +17,12 @@ public class SettingsService
|
|||||||
private readonly ISettingsUtils _settingsUtils;
|
private readonly ISettingsUtils _settingsUtils;
|
||||||
private readonly IFileSystemWatcher _watcher;
|
private readonly IFileSystemWatcher _watcher;
|
||||||
private readonly object _loadingSettingsLock = new object();
|
private readonly object _loadingSettingsLock = new object();
|
||||||
|
private KeyboardListener _keyboardListener;
|
||||||
|
|
||||||
public SettingsService()
|
public SettingsService(KeyboardListener keyboardListener)
|
||||||
{
|
{
|
||||||
_settingsUtils = new SettingsUtils();
|
_settingsUtils = new SettingsUtils();
|
||||||
|
_keyboardListener = keyboardListener;
|
||||||
ReadSettings();
|
ReadSettings();
|
||||||
_watcher = Helper.GetFileWatcher(PowerAccentModuleName, "settings.json", () => { ReadSettings(); });
|
_watcher = Helper.GetFileWatcher(PowerAccentModuleName, "settings.json", () => { ReadSettings(); });
|
||||||
}
|
}
|
||||||
@ -48,7 +51,10 @@ public class SettingsService
|
|||||||
if (settings != null)
|
if (settings != null)
|
||||||
{
|
{
|
||||||
ActivationKey = settings.Properties.ActivationKey;
|
ActivationKey = settings.Properties.ActivationKey;
|
||||||
|
_keyboardListener.UpdateActivationKey((int)ActivationKey);
|
||||||
|
|
||||||
InputTime = settings.Properties.InputTime.Value;
|
InputTime = settings.Properties.InputTime.Value;
|
||||||
|
_keyboardListener.UpdateInputTime(InputTime);
|
||||||
switch (settings.Properties.ToolbarPosition.Value)
|
switch (settings.Properties.ToolbarPosition.Value)
|
||||||
{
|
{
|
||||||
case "Top center":
|
case "Top center":
|
||||||
@ -79,6 +85,8 @@ public class SettingsService
|
|||||||
Position = Position.Center;
|
Position = Position.Center;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_keyboardListener.UpdateInputTime(InputTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -134,32 +142,27 @@ public class SettingsService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public char[] GetLetterKey(LetterKey letter)
|
|
||||||
{
|
|
||||||
return GetDefaultLetterKey(letter);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static char[] GetDefaultLetterKey(LetterKey letter)
|
public static char[] GetDefaultLetterKey(LetterKey letter)
|
||||||
{
|
{
|
||||||
switch (letter)
|
switch (letter)
|
||||||
{
|
{
|
||||||
case LetterKey.A:
|
case LetterKey.VK_A:
|
||||||
return new char[] { 'à', 'â', 'á', 'ä', 'ã', 'å', 'æ' };
|
return new char[] { 'à', 'â', 'á', 'ä', 'ã', 'å', 'æ' };
|
||||||
case LetterKey.C:
|
case LetterKey.VK_C:
|
||||||
return new char[] { 'ć', 'ĉ', 'č', 'ċ', 'ç', 'ḉ' };
|
return new char[] { 'ć', 'ĉ', 'č', 'ċ', 'ç', 'ḉ' };
|
||||||
case LetterKey.E:
|
case LetterKey.VK_E:
|
||||||
return new char[] { 'é', 'è', 'ê', 'ë', 'ē', 'ė', '€' };
|
return new char[] { 'é', 'è', 'ê', 'ë', 'ē', 'ė', '€' };
|
||||||
case LetterKey.I:
|
case LetterKey.VK_I:
|
||||||
return new char[] { 'î', 'ï', 'í', 'ì', 'ī' };
|
return new char[] { 'î', 'ï', 'í', 'ì', 'ī' };
|
||||||
case LetterKey.N:
|
case LetterKey.VK_N:
|
||||||
return new char[] { 'ñ', 'ń' };
|
return new char[] { 'ñ', 'ń' };
|
||||||
case LetterKey.O:
|
case LetterKey.VK_O:
|
||||||
return new char[] { 'ô', 'ö', 'ó', 'ò', 'õ', 'ø', 'œ' };
|
return new char[] { 'ô', 'ö', 'ó', 'ò', 'õ', 'ø', 'œ' };
|
||||||
case LetterKey.S:
|
case LetterKey.VK_S:
|
||||||
return new char[] { 'š', 'ß', 'ś' };
|
return new char[] { 'š', 'ß', 'ś' };
|
||||||
case LetterKey.U:
|
case LetterKey.VK_U:
|
||||||
return new char[] { 'û', 'ù', 'ü', 'ú', 'ū' };
|
return new char[] { 'û', 'ù', 'ü', 'ú', 'ū' };
|
||||||
case LetterKey.Y:
|
case LetterKey.VK_Y:
|
||||||
return new char[] { 'ÿ', 'ý' };
|
return new char[] { 'ÿ', 'ý' };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,359 +0,0 @@
|
|||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -27,9 +27,10 @@ internal static class WindowsFunctions
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Letter
|
// Letter
|
||||||
var inputsInsert = new User32.INPUT[1]
|
var inputsInsert = new User32.INPUT[]
|
||||||
{
|
{
|
||||||
new User32.INPUT { type = User32.INPUTTYPE.INPUT_KEYBOARD, ki = new User32.KEYBDINPUT { wVk = 0, dwFlags = User32.KEYEVENTF.KEYEVENTF_UNICODE, wScan = c } },
|
new User32.INPUT { type = User32.INPUTTYPE.INPUT_KEYBOARD, ki = new User32.KEYBDINPUT { wVk = 0, dwFlags = User32.KEYEVENTF.KEYEVENTF_UNICODE, wScan = c } },
|
||||||
|
new User32.INPUT { type = User32.INPUTTYPE.INPUT_KEYBOARD, ki = new User32.KEYBDINPUT { wVk = 0, dwFlags = User32.KEYEVENTF.KEYEVENTF_UNICODE | User32.KEYEVENTF.KEYEVENTF_KEYUP, wScan = c } },
|
||||||
};
|
};
|
||||||
var temp2 = User32.SendInput((uint)inputsInsert.Length, inputsInsert, sizeof(User32.INPUT));
|
var temp2 = User32.SendInput((uint)inputsInsert.Length, inputsInsert, sizeof(User32.INPUT));
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<Import Project="..\..\..\Version.props" />
|
<Import Project="..\..\..\Version.props" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>net6.0-windows</TargetFramework>
|
<TargetFramework>net6.0-windows10.0.19041.0</TargetFramework>
|
||||||
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
|
||||||
<Nullable>disable</Nullable>
|
<Nullable>disable</Nullable>
|
||||||
<UseWPF>true</UseWPF>
|
<UseWPF>true</UseWPF>
|
||||||
@ -26,6 +26,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="gong-wpf-dragdrop" Version="3.1.1" />
|
<PackageReference Include="gong-wpf-dragdrop" Version="3.1.1" />
|
||||||
<PackageReference Include="MahApps.Metro" Version="2.4.9" />
|
<PackageReference Include="MahApps.Metro" Version="2.4.9" />
|
||||||
|
<PackageReference Include="Microsoft.Windows.CsWinRT" Version="2.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<Import Project="..\..\..\Version.props" />
|
<Import Project="..\..\..\Version.props" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>net6.0-windows</TargetFramework>
|
<TargetFramework>net6.0-windows10.0.19041.0</TargetFramework>
|
||||||
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
|
||||||
<UseWPF>true</UseWPF>
|
<UseWPF>true</UseWPF>
|
||||||
<Nullable>disable</Nullable>
|
<Nullable>disable</Nullable>
|
||||||
@ -12,6 +12,9 @@
|
|||||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||||
<AssemblyName>PowerToys.PowerAccent</AssemblyName>
|
<AssemblyName>PowerToys.PowerAccent</AssemblyName>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Windows.CsWinRT" Version="2.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
|
<ProjectReference Include="..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
|
||||||
|
@ -0,0 +1,207 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "KeyboardListener.h"
|
||||||
|
#include "KeyboardListener.g.cpp"
|
||||||
|
|
||||||
|
#include <common/logger/logger.h>
|
||||||
|
#include <common/utils/logger_helper.h>
|
||||||
|
#include <common/utils/winapi_error.h>
|
||||||
|
|
||||||
|
namespace winrt::PowerToys::PowerAccentKeyboardService::implementation
|
||||||
|
{
|
||||||
|
KeyboardListener::KeyboardListener() :
|
||||||
|
m_toolbarVisible(false), m_triggeredWithSpace(false)
|
||||||
|
{
|
||||||
|
s_instance = this;
|
||||||
|
LoggerHelpers::init_logger(L"PowerAccent", L"PowerAccentKeyboardService", "PowerAccent");
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardListener::InitHook()
|
||||||
|
{
|
||||||
|
#if defined(DISABLE_LOWLEVEL_HOOKS_WHEN_DEBUGGED)
|
||||||
|
const bool hook_disabled = IsDebuggerPresent();
|
||||||
|
#else
|
||||||
|
const bool hook_disabled = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!hook_disabled)
|
||||||
|
{
|
||||||
|
s_llKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(NULL), NULL);
|
||||||
|
if (!s_llKeyboardHook)
|
||||||
|
{
|
||||||
|
DWORD errorCode = GetLastError();
|
||||||
|
show_last_error_message(L"SetWindowsHookEx", errorCode, L"PowerToys - PowerAccent");
|
||||||
|
auto errorMessage = get_last_error_message(errorCode);
|
||||||
|
Logger::error(errorMessage.has_value() ? errorMessage.value() : L"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardListener::UnInitHook()
|
||||||
|
{
|
||||||
|
if (s_llKeyboardHook)
|
||||||
|
{
|
||||||
|
if (UnhookWindowsHookEx(s_llKeyboardHook))
|
||||||
|
{
|
||||||
|
s_llKeyboardHook = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardListener::SetShowToolbarEvent(ShowToolbar showToolbarEvent)
|
||||||
|
{
|
||||||
|
m_showToolbarCb = [trigger = std::move(showToolbarEvent)](LetterKey key) {
|
||||||
|
trigger(key);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardListener::SetHideToolbarEvent(HideToolbar hideToolbarEvent)
|
||||||
|
{
|
||||||
|
m_hideToolbarCb = [trigger = std::move(hideToolbarEvent)](InputType inputType) {
|
||||||
|
trigger(inputType);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardListener::SetNextCharEvent(NextChar nextCharEvent)
|
||||||
|
{
|
||||||
|
m_nextCharCb = [trigger = std::move(nextCharEvent)](TriggerKey triggerKey) {
|
||||||
|
trigger(triggerKey);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardListener::UpdateActivationKey(int32_t activationKey)
|
||||||
|
{
|
||||||
|
m_settings.activationKey = static_cast<PowerAccentActivationKey>(activationKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardListener::UpdateInputTime(int32_t inputTime)
|
||||||
|
{
|
||||||
|
m_settings.inputTime = std::chrono::milliseconds(inputTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KeyboardListener::OnKeyDown(KBDLLHOOKSTRUCT info) noexcept
|
||||||
|
{
|
||||||
|
if (std::find(std::begin(letters), end(letters), static_cast<LetterKey>(info.vkCode)) != end(letters))
|
||||||
|
{
|
||||||
|
m_stopwatch.reset();
|
||||||
|
letterPressed = static_cast<LetterKey>(info.vkCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT triggerPressed = 0;
|
||||||
|
if (letterPressed != LetterKey::None)
|
||||||
|
{
|
||||||
|
if (std::find(std::begin(triggers), end(triggers), static_cast<TriggerKey>(info.vkCode)) != end(triggers))
|
||||||
|
{
|
||||||
|
triggerPressed = info.vkCode;
|
||||||
|
|
||||||
|
if ((triggerPressed == VK_SPACE && m_settings.activationKey == PowerAccentActivationKey::LeftRightArrow) ||
|
||||||
|
((triggerPressed == VK_LEFT || triggerPressed == VK_RIGHT) && m_settings.activationKey == PowerAccentActivationKey::Space))
|
||||||
|
{
|
||||||
|
triggerPressed = 0;
|
||||||
|
Logger::info(L"Reset trigger key");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_toolbarVisible && letterPressed != LetterKey::None && triggerPressed)
|
||||||
|
{
|
||||||
|
Logger::info(L"Show toolbar. Letter: %d, Trigger: %d", letterPressed, triggerPressed);
|
||||||
|
|
||||||
|
// Keep track if it was triggered with space so that it can be typed on false starts.
|
||||||
|
m_triggeredWithSpace = triggerPressed == VK_SPACE;
|
||||||
|
m_toolbarVisible = true;
|
||||||
|
|
||||||
|
m_showToolbarCb(letterPressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_toolbarVisible && triggerPressed)
|
||||||
|
{
|
||||||
|
if (triggerPressed == VK_LEFT)
|
||||||
|
{
|
||||||
|
Logger::info(L"Next toolbar position - left");
|
||||||
|
m_nextCharCb(TriggerKey::Left);
|
||||||
|
}
|
||||||
|
else if (triggerPressed == VK_RIGHT)
|
||||||
|
{
|
||||||
|
Logger::info(L"Next toolbar position - right");
|
||||||
|
m_nextCharCb(TriggerKey::Right);
|
||||||
|
}
|
||||||
|
else if (triggerPressed == VK_SPACE)
|
||||||
|
{
|
||||||
|
Logger::info(L"Next toolbar position - space");
|
||||||
|
m_nextCharCb(TriggerKey::Space);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KeyboardListener::OnKeyUp(KBDLLHOOKSTRUCT info) noexcept
|
||||||
|
{
|
||||||
|
if (std::find(std::begin(letters), end(letters), static_cast<LetterKey>(info.vkCode)) != end(letters))
|
||||||
|
{
|
||||||
|
letterPressed = LetterKey::None;
|
||||||
|
|
||||||
|
if (m_toolbarVisible)
|
||||||
|
{
|
||||||
|
if (m_stopwatch.elapsed() < m_settings.inputTime)
|
||||||
|
{
|
||||||
|
Logger::info(L"Activation too fast. Do nothing.");
|
||||||
|
|
||||||
|
// False start, we should output the space if it was the trigger.
|
||||||
|
if (m_triggeredWithSpace)
|
||||||
|
{
|
||||||
|
m_hideToolbarCb(InputType::Space);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_hideToolbarCb(InputType::None);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_toolbarVisible = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger::info(L"Hide toolbar event and input char");
|
||||||
|
|
||||||
|
m_hideToolbarCb(InputType::Char);
|
||||||
|
|
||||||
|
m_toolbarVisible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT KeyboardListener::LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
if (nCode == HC_ACTION && s_instance != nullptr)
|
||||||
|
{
|
||||||
|
KBDLLHOOKSTRUCT* key = reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam);
|
||||||
|
switch (wParam)
|
||||||
|
{
|
||||||
|
case WM_KEYDOWN:
|
||||||
|
{
|
||||||
|
if (s_instance->OnKeyDown(*key))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WM_KEYUP:
|
||||||
|
{
|
||||||
|
if (s_instance->OnKeyUp(*key))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return CallNextHookEx(NULL, nCode, wParam, lParam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "KeyboardListener.g.h"
|
||||||
|
|
||||||
|
#include <spdlog/stopwatch.h>
|
||||||
|
|
||||||
|
namespace winrt::PowerToys::PowerAccentKeyboardService::implementation
|
||||||
|
{
|
||||||
|
enum PowerAccentActivationKey
|
||||||
|
{
|
||||||
|
LeftRightArrow,
|
||||||
|
Space,
|
||||||
|
Both,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PowerAccentSettings
|
||||||
|
{
|
||||||
|
PowerAccentActivationKey activationKey{ PowerAccentActivationKey::Both };
|
||||||
|
std::chrono::milliseconds inputTime{ 200 };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct KeyboardListener : KeyboardListenerT<KeyboardListener>
|
||||||
|
{
|
||||||
|
using LetterKey = winrt::PowerToys::PowerAccentKeyboardService::LetterKey;
|
||||||
|
using TriggerKey = winrt::PowerToys::PowerAccentKeyboardService::TriggerKey;
|
||||||
|
using InputType = winrt::PowerToys::PowerAccentKeyboardService::InputType;
|
||||||
|
|
||||||
|
KeyboardListener();
|
||||||
|
|
||||||
|
void KeyboardListener::InitHook();
|
||||||
|
void KeyboardListener::UnInitHook();
|
||||||
|
void SetShowToolbarEvent(ShowToolbar showToolbarEvent);
|
||||||
|
void SetHideToolbarEvent(HideToolbar hideToolbarEvent);
|
||||||
|
void SetNextCharEvent(NextChar NextCharEvent);
|
||||||
|
|
||||||
|
void UpdateActivationKey(int32_t activationKey);
|
||||||
|
void UpdateInputTime(int32_t inputTime);
|
||||||
|
|
||||||
|
static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool OnKeyDown(KBDLLHOOKSTRUCT info) noexcept;
|
||||||
|
bool OnKeyUp(KBDLLHOOKSTRUCT info) noexcept;
|
||||||
|
|
||||||
|
static inline KeyboardListener* s_instance;
|
||||||
|
HHOOK s_llKeyboardHook = nullptr;
|
||||||
|
bool m_toolbarVisible;
|
||||||
|
PowerAccentSettings m_settings;
|
||||||
|
std::function<void(LetterKey)> m_showToolbarCb;
|
||||||
|
std::function<void(InputType)> m_hideToolbarCb;
|
||||||
|
std::function<void(TriggerKey)> m_nextCharCb;
|
||||||
|
bool m_triggeredWithSpace;
|
||||||
|
spdlog::stopwatch m_stopwatch;
|
||||||
|
|
||||||
|
static inline const std::vector<LetterKey> letters = { LetterKey::VK_A,
|
||||||
|
LetterKey::VK_C,
|
||||||
|
LetterKey::VK_E,
|
||||||
|
LetterKey::VK_I,
|
||||||
|
LetterKey::VK_N,
|
||||||
|
LetterKey::VK_O,
|
||||||
|
LetterKey::VK_S,
|
||||||
|
LetterKey::VK_U,
|
||||||
|
LetterKey::VK_Y };
|
||||||
|
LetterKey letterPressed{};
|
||||||
|
|
||||||
|
static inline const std::vector<TriggerKey> triggers = { TriggerKey::Right, TriggerKey::Left, TriggerKey::Space };
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace winrt::PowerToys::PowerAccentKeyboardService::factory_implementation
|
||||||
|
{
|
||||||
|
struct KeyboardListener : KeyboardListenerT<KeyboardListener, implementation::KeyboardListener>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
namespace PowerToys
|
||||||
|
{
|
||||||
|
namespace PowerAccentKeyboardService
|
||||||
|
{
|
||||||
|
enum LetterKey
|
||||||
|
{
|
||||||
|
None = 0x00,
|
||||||
|
VK_A = 0x41,
|
||||||
|
VK_C = 0x43,
|
||||||
|
VK_E = 0x45,
|
||||||
|
VK_I = 0x49,
|
||||||
|
VK_N = 0x4E,
|
||||||
|
VK_O = 0x4F,
|
||||||
|
VK_S = 0x53,
|
||||||
|
VK_U = 0x55,
|
||||||
|
VK_Y = 0x59
|
||||||
|
};
|
||||||
|
|
||||||
|
enum TriggerKey
|
||||||
|
{
|
||||||
|
Right = 0x27, // VK_RIGHT
|
||||||
|
Left = 0x25, // VK_LEFT
|
||||||
|
Space = 0x20 // VK_SPACE
|
||||||
|
};
|
||||||
|
|
||||||
|
enum InputType
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Space,
|
||||||
|
Char
|
||||||
|
};
|
||||||
|
|
||||||
|
[version(1.0), uuid(37197089-5438-4479-af57-30ab3f3c8be4)] delegate void ShowToolbar(LetterKey key);
|
||||||
|
[version(1.0), uuid(8eb79d6b-1826-424f-9fbc-af21ae19725e)] delegate void HideToolbar(InputType inputType);
|
||||||
|
[version(1.0), uuid(db72d45c-a5a2-446f-bdc1-506e9121764a)] delegate void NextChar(TriggerKey inputSpace);
|
||||||
|
|
||||||
|
[default_interface] runtimeclass KeyboardListener {
|
||||||
|
KeyboardListener();
|
||||||
|
void InitHook();
|
||||||
|
void UnInitHook();
|
||||||
|
void SetShowToolbarEvent(event ShowToolbar showToolbarEvent);
|
||||||
|
void SetHideToolbarEvent(event HideToolbar hideToolbarEvent);
|
||||||
|
void SetNextCharEvent(event NextChar nextCharEvent);
|
||||||
|
void UpdateActivationKey(Int32 activationKey);
|
||||||
|
void UpdateInputTime(Int32 inputTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
EXPORTS
|
||||||
|
DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
|
||||||
|
DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE
|
@ -0,0 +1,40 @@
|
|||||||
|
#include <windows.h>
|
||||||
|
#include "resource.h"
|
||||||
|
#include "../../../common/version/version.h"
|
||||||
|
|
||||||
|
#define APSTUDIO_READONLY_SYMBOLS
|
||||||
|
#include "winres.h"
|
||||||
|
#undef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
|
||||||
|
1 VERSIONINFO
|
||||||
|
FILEVERSION FILE_VERSION
|
||||||
|
PRODUCTVERSION PRODUCT_VERSION
|
||||||
|
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||||
|
#ifdef _DEBUG
|
||||||
|
FILEFLAGS VS_FF_DEBUG
|
||||||
|
#else
|
||||||
|
FILEFLAGS 0x0L
|
||||||
|
#endif
|
||||||
|
FILEOS VOS_NT_WINDOWS32
|
||||||
|
FILETYPE VFT_DLL
|
||||||
|
FILESUBTYPE VFT2_UNKNOWN
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "040904b0" // US English (0x0409), Unicode (0x04B0) charset
|
||||||
|
BEGIN
|
||||||
|
VALUE "CompanyName", COMPANY_NAME
|
||||||
|
VALUE "FileDescription", FILE_DESCRIPTION
|
||||||
|
VALUE "FileVersion", FILE_VERSION_STRING
|
||||||
|
VALUE "InternalName", INTERNAL_NAME
|
||||||
|
VALUE "LegalCopyright", COPYRIGHT_NOTE
|
||||||
|
VALUE "OriginalFilename", ORIGINAL_FILENAME
|
||||||
|
VALUE "ProductName", PRODUCT_NAME
|
||||||
|
VALUE "ProductVersion", PRODUCT_VERSION_STRING
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x409, 1200 // US English (0x0409), Unicode (1200) charset
|
||||||
|
END
|
||||||
|
END
|
@ -0,0 +1,139 @@
|
|||||||
|
<?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">
|
||||||
|
<CppWinRTOptimized>true</CppWinRTOptimized>
|
||||||
|
<CppWinRTRootNamespaceAutoMerge>true</CppWinRTRootNamespaceAutoMerge>
|
||||||
|
<CppWinRTGenerateWindowsMetadata>true</CppWinRTGenerateWindowsMetadata>
|
||||||
|
<MinimalCoreWin>true</MinimalCoreWin>
|
||||||
|
<ProjectGuid>{c97d9a5d-206c-454e-997e-009e227d7f02}</ProjectGuid>
|
||||||
|
<ProjectName>PowerAccentKeyboardService</ProjectName>
|
||||||
|
<RootNamespace>PowerToys.PowerAccentKeyboardService</RootNamespace>
|
||||||
|
<DefaultLanguage>en-US</DefaultLanguage>
|
||||||
|
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
|
||||||
|
<AppContainerApplication>false</AppContainerApplication>
|
||||||
|
<AppxPackage>false</AppxPackage>
|
||||||
|
<ApplicationType>Windows Store</ApplicationType>
|
||||||
|
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
|
||||||
|
<WindowsTargetPlatformVersion Condition=" '$(WindowsTargetPlatformVersion)' == '' ">10.0.19041.0</WindowsTargetPlatformVersion>
|
||||||
|
<WindowsTargetPlatformMinVersion>10.0.17134.0</WindowsTargetPlatformMinVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
<GenerateManifest>false</GenerateManifest>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</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>
|
||||||
|
<ImportGroup Label="PropertySheets">
|
||||||
|
<Import Project="PropertySheet.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetName>PowerToys.PowerAccentKeyboardService</TargetName>
|
||||||
|
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\PowerAccent\</OutDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup>
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
|
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<AdditionalOptions>%(AdditionalOptions) /bigobj</AdditionalOptions>
|
||||||
|
<!--Temporarily disable cppwinrt heap enforcement to work around xaml compiler generated std::shared_ptr use -->
|
||||||
|
<AdditionalOptions Condition="'$(CppWinRTHeapEnforcement)'==''">/DWINRT_NO_MAKE_DETECTION %(AdditionalOptions)</AdditionalOptions>
|
||||||
|
<PreprocessorDefinitions>_WINRT_DLL;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>../../..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||||
|
<ModuleDefinitionFile>PowerAccentKeyboardService.def</ModuleDefinitionFile>
|
||||||
|
<AdditionalDependencies>Shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
|
||||||
|
<ClCompile>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
|
||||||
|
<ClCompile>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="pch.h" />
|
||||||
|
<ClInclude Include="KeyboardListener.h">
|
||||||
|
<DependentUpon>KeyboardListener.idl</DependentUpon>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="resource.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="pch.cpp">
|
||||||
|
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="KeyboardListener.cpp">
|
||||||
|
<DependentUpon>KeyboardListener.idl</DependentUpon>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Midl Include="KeyboardListener.idl" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="packages.config" />
|
||||||
|
<None Include="PowerAccentKeyboardService.def" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="PropertySheet.props" />
|
||||||
|
</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>
|
||||||
|
<ProjectReference Include="..\..\..\common\version\version.vcxproj">
|
||||||
|
<Project>{cc6e41ac-8174-4e8a-8d22-85dd7f4851df}</Project>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="PowerAccentKeyboardService.rc" />
|
||||||
|
</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')" />
|
||||||
|
</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'))" />
|
||||||
|
</Target>
|
||||||
|
</Project>
|
@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Resources">
|
||||||
|
<UniqueIdentifier>accd3aa8-1ba0-4223-9bbe-0c431709210b</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Generated Files">
|
||||||
|
<UniqueIdentifier>{926ab91d-31b4-48c3-b9a4-e681349f27f0}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="pch.cpp" />
|
||||||
|
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="pch.h" />
|
||||||
|
<ClInclude Include="resource.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Midl Include="KeyboardListener.idl" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="PowerAccentKeyboardService.def" />
|
||||||
|
<None Include="packages.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="PropertySheet.props" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="PowerAccentKeyboardService.rc">
|
||||||
|
<Filter>Resources</Filter>
|
||||||
|
</ResourceCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ImportGroup Label="PropertySheets" />
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<!--
|
||||||
|
To customize common C++/WinRT project properties:
|
||||||
|
* right-click the project node
|
||||||
|
* expand the Common Properties item
|
||||||
|
* select the C++/WinRT property page
|
||||||
|
|
||||||
|
For more advanced scenarios, and complete documentation, please see:
|
||||||
|
https://github.com/Microsoft/cppwinrt/tree/master/nuget
|
||||||
|
-->
|
||||||
|
<PropertyGroup />
|
||||||
|
<ItemDefinitionGroup />
|
||||||
|
</Project>
|
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="Microsoft.Windows.CppWinRT" version="2.0.220418.1" targetFramework="native" />
|
||||||
|
</packages>
|
@ -0,0 +1 @@
|
|||||||
|
#include "pch.h"
|
4
src/modules/poweraccent/PowerAccentKeyboardService/pch.h
Normal file
4
src/modules/poweraccent/PowerAccentKeyboardService/pch.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <unknwn.h>
|
||||||
|
#include <winrt/Windows.Foundation.h>
|
||||||
|
#include <winrt/Windows.Foundation.Collections.h>
|
@ -0,0 +1,13 @@
|
|||||||
|
//{{NO_DEPENDENCIES}}
|
||||||
|
// Microsoft Visual C++ generated include file.
|
||||||
|
// Used by PowerToys.MeasureToolCore.rc
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
// Non-localizable
|
||||||
|
|
||||||
|
#define FILE_DESCRIPTION "PowerToys PowerAccentKeyboardService"
|
||||||
|
#define INTERNAL_NAME "PowerToys.PowerAccentKeyboardService"
|
||||||
|
#define ORIGINAL_FILENAME "PowerToys.PowerAccentKeyboardService.dll"
|
||||||
|
|
||||||
|
// Non-localizable
|
||||||
|
//////////////////////////////
|
@ -25,7 +25,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\PowerAccent\</OutDir>
|
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\PowerAccent\</OutDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup >
|
<PropertyGroup>
|
||||||
<TargetName>PowerToys.$(ProjectName)</TargetName>
|
<TargetName>PowerToys.$(ProjectName)</TargetName>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup>
|
<ItemDefinitionGroup>
|
||||||
|
Loading…
Reference in New Issue
Block a user