KBM - Set up tests for keyboard hook remapping logic (#4004)

* Add test proj, refactor proj with filters, and move single remap function to a separate header

* Moved all methods to header files

* remove more unused commented code

* Reverted sln file

* Fixed sln file

* Added interface wrapping SendInput calls

* fixed formatting

* Created test mock class

* Added keyboard input logic

* Fixed compilation errors and added nuget reference to CppWinRT

* Added tests for single key remapping

* Refactored code for adding shortcut remap tests

* Separated test classes

* Fixed tests in release mode

* Added more tests

* Resolved comments
This commit is contained in:
Arjun Balgovind
2020-06-11 13:07:46 -07:00
committed by GitHub
parent 670033c4da
commit 071ea1dc97
30 changed files with 1866 additions and 66 deletions

View File

@@ -0,0 +1,13 @@
#pragma once
#include "windows.h"
// Interface used to wrap keyboard input library methods
class InputInterface
{
public:
// Function to simulate input
virtual UINT SendVirtualInput(UINT cInputs, LPINPUT pInputs, int cbSize) = 0;
// Function to get the state of a particular key
virtual bool GetVirtualKeyState(int key) = 0;
};

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200602.3\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200602.3\build\native\Microsoft.Windows.CppWinRT.props')" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
@@ -110,6 +111,7 @@
<ClCompile Include="trace.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="InputInterface.h" />
<ClInclude Include="Helpers.h" />
<ClInclude Include="KeyboardManagerConstants.h" />
<ClInclude Include="KeyboardManagerState.h" />
@@ -124,7 +126,18 @@
<Project>{74485049-c722-400f-abe5-86ac52d929b3}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200602.3\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200602.3\build\native\Microsoft.Windows.CppWinRT.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200602.3\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200602.3\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200602.3\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200602.3\build\native\Microsoft.Windows.CppWinRT.targets'))" />
</Target>
</Project>

View File

@@ -62,5 +62,11 @@
<ClInclude Include="Trace.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="InputInterface.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
</Project>

View File

@@ -1,5 +1,6 @@
#pragma once
#include <string>
#include <winrt/base.h>
namespace KeyboardManagerConstants
{

View File

@@ -184,4 +184,4 @@ public:
// Gets the Current Active Configuration Name.
std::wstring GetCurrentConfigName();
};
};

View File

@@ -260,7 +260,7 @@ bool Shortcut::CheckShiftKey(const DWORD& input) const
// Function to set a key in the shortcut based on the passed key code argument. Returns false if it is already set to the same value. This can be used to avoid UI refreshing
bool Shortcut::SetKey(const DWORD& input)
{
// Since there isn't a key for a common Win key this is handled with a separate argument
// Since there isn't a key for a common Win key we use the key code defined by us
if (input == CommonSharedConstants::VK_WIN_BOTH)
{
if (winKey == ModifierKey::Both)
@@ -493,27 +493,27 @@ void Shortcut::SetKeyCodes(const std::vector<DWORD>& keys)
}
// Function to check if all the modifiers in the shortcut have been pressed down
bool Shortcut::CheckModifiersKeyboardState() const
bool Shortcut::CheckModifiersKeyboardState(InputInterface& ii) const
{
// Check the win key state
if (winKey == ModifierKey::Both)
{
// Since VK_WIN does not exist, we check both VK_LWIN and VK_RWIN
if ((!(GetAsyncKeyState(VK_LWIN) & 0x8000)) && (!(GetAsyncKeyState(VK_RWIN) & 0x8000)))
if ((!(ii.GetVirtualKeyState(VK_LWIN))) && (!(ii.GetVirtualKeyState(VK_RWIN))))
{
return false;
}
}
else if (winKey == ModifierKey::Left)
{
if (!(GetAsyncKeyState(VK_LWIN) & 0x8000))
if (!(ii.GetVirtualKeyState(VK_LWIN)))
{
return false;
}
}
else if (winKey == ModifierKey::Right)
{
if (!(GetAsyncKeyState(VK_RWIN) & 0x8000))
if (!(ii.GetVirtualKeyState(VK_RWIN)))
{
return false;
}
@@ -522,21 +522,21 @@ bool Shortcut::CheckModifiersKeyboardState() const
// Check the ctrl key state
if (ctrlKey == ModifierKey::Left)
{
if (!(GetAsyncKeyState(VK_LCONTROL) & 0x8000))
if (!(ii.GetVirtualKeyState(VK_LCONTROL)))
{
return false;
}
}
else if (ctrlKey == ModifierKey::Right)
{
if (!(GetAsyncKeyState(VK_RCONTROL) & 0x8000))
if (!(ii.GetVirtualKeyState(VK_RCONTROL)))
{
return false;
}
}
else if (ctrlKey == ModifierKey::Both)
{
if (!(GetAsyncKeyState(VK_CONTROL) & 0x8000))
if (!(ii.GetVirtualKeyState(VK_CONTROL)))
{
return false;
}
@@ -545,21 +545,21 @@ bool Shortcut::CheckModifiersKeyboardState() const
// Check the alt key state
if (altKey == ModifierKey::Left)
{
if (!(GetAsyncKeyState(VK_LMENU) & 0x8000))
if (!(ii.GetVirtualKeyState(VK_LMENU)))
{
return false;
}
}
else if (altKey == ModifierKey::Right)
{
if (!(GetAsyncKeyState(VK_RMENU) & 0x8000))
if (!(ii.GetVirtualKeyState(VK_RMENU)))
{
return false;
}
}
else if (altKey == ModifierKey::Both)
{
if (!(GetAsyncKeyState(VK_MENU) & 0x8000))
if (!(ii.GetVirtualKeyState(VK_MENU)))
{
return false;
}
@@ -568,21 +568,21 @@ bool Shortcut::CheckModifiersKeyboardState() const
// Check the shift key state
if (shiftKey == ModifierKey::Left)
{
if (!(GetAsyncKeyState(VK_LSHIFT) & 0x8000))
if (!(ii.GetVirtualKeyState(VK_LSHIFT)))
{
return false;
}
}
else if (shiftKey == ModifierKey::Right)
{
if (!(GetAsyncKeyState(VK_RSHIFT) & 0x8000))
if (!(ii.GetVirtualKeyState(VK_RSHIFT)))
{
return false;
}
}
else if (shiftKey == ModifierKey::Both)
{
if (!(GetAsyncKeyState(VK_SHIFT) & 0x8000))
if (!(ii.GetVirtualKeyState(VK_SHIFT)))
{
return false;
}
@@ -592,7 +592,7 @@ bool Shortcut::CheckModifiersKeyboardState() const
}
// Function to check if any keys are pressed down except those in the shortcut
bool Shortcut::IsKeyboardStateClearExceptShortcut() const
bool Shortcut::IsKeyboardStateClearExceptShortcut(InputInterface& ii) const
{
// Iterate through all the virtual key codes - 0xFF is set to key down because of the Num Lock
for (int keyVal = 1; keyVal < 0xFF; keyVal++)
@@ -603,7 +603,7 @@ bool Shortcut::IsKeyboardStateClearExceptShortcut() const
continue;
}
// Check state of the key. If the key is pressed down but it is not part of the shortcut then the keyboard state is not clear
if (GetAsyncKeyState(keyVal) & 0x8000)
if (ii.GetVirtualKeyState(keyVal))
{
// If one of the win keys is pressed check if it is part of the shortcut
if (keyVal == VK_LWIN)
@@ -779,15 +779,15 @@ KeyboardManagerHelper::ErrorType Shortcut::DoKeysOverlap(const Shortcut& first,
else if (first.actionKey == second.actionKey)
{
// corresponding modifiers are either both disabled or both not disabled - this ensures that both match in types of modifiers i.e. Ctrl(l/r/c) Shift (l/r/c) A matches Ctrl(l/r/c) Shift (l/r/c) A
if (((first.winKey != ModifierKey::Disabled && second.winKey != ModifierKey::Disabled) || (first.winKey == ModifierKey::Disabled && second.winKey == ModifierKey::Disabled)) &&
((first.ctrlKey != ModifierKey::Disabled && second.ctrlKey != ModifierKey::Disabled) || (first.ctrlKey == ModifierKey::Disabled && second.ctrlKey == ModifierKey::Disabled)) &&
((first.altKey != ModifierKey::Disabled && second.altKey != ModifierKey::Disabled) || (first.altKey == ModifierKey::Disabled && second.altKey == ModifierKey::Disabled)) &&
if (((first.winKey != ModifierKey::Disabled && second.winKey != ModifierKey::Disabled) || (first.winKey == ModifierKey::Disabled && second.winKey == ModifierKey::Disabled)) &&
((first.ctrlKey != ModifierKey::Disabled && second.ctrlKey != ModifierKey::Disabled) || (first.ctrlKey == ModifierKey::Disabled && second.ctrlKey == ModifierKey::Disabled)) &&
((first.altKey != ModifierKey::Disabled && second.altKey != ModifierKey::Disabled) || (first.altKey == ModifierKey::Disabled && second.altKey == ModifierKey::Disabled)) &&
((first.shiftKey != ModifierKey::Disabled && second.shiftKey != ModifierKey::Disabled) || (first.shiftKey == ModifierKey::Disabled && second.shiftKey == ModifierKey::Disabled)))
{
// If one of the modifier is common
if ((first.winKey == ModifierKey::Both || second.winKey == ModifierKey::Both) ||
(first.ctrlKey == ModifierKey::Both || second.ctrlKey == ModifierKey::Both) ||
(first.altKey == ModifierKey::Both || second.altKey == ModifierKey::Both) ||
if ((first.winKey == ModifierKey::Both || second.winKey == ModifierKey::Both) ||
(first.ctrlKey == ModifierKey::Both || second.ctrlKey == ModifierKey::Both) ||
(first.altKey == ModifierKey::Both || second.altKey == ModifierKey::Both) ||
(first.shiftKey == ModifierKey::Both || second.shiftKey == ModifierKey::Both))
{
return KeyboardManagerHelper::ErrorType::ConflictingModifierShortcut;

View File

@@ -3,6 +3,7 @@
#include "../common/keyboard_layout.h"
#include "../common/shared_constants.h"
#include <interface/lowlevel_keyboard_event_data.h>
#include "InputInterface.h"
// Enum type to store different states of the win key
enum class ModifierKey
@@ -167,10 +168,10 @@ public:
void SetKeyCodes(const std::vector<DWORD>& keys);
// Function to check if all the modifiers in the shortcut have been pressed down
bool CheckModifiersKeyboardState() const;
bool CheckModifiersKeyboardState(InputInterface& ii) const;
// Function to check if any keys are pressed down except those in the shortcut
bool IsKeyboardStateClearExceptShortcut() const;
bool IsKeyboardStateClearExceptShortcut(InputInterface& ii) const;
// Function to get the number of modifiers that are common between the current shortcut and the shortcut in the argument
int GetCommonModifiersCount(const Shortcut& input) const;

View File

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