2020-03-24 01:44:02 +08:00
|
|
|
#include "pch.h"
|
|
|
|
#include "Helpers.h"
|
|
|
|
#include <sstream>
|
2020-04-23 23:37:52 +08:00
|
|
|
#include "../common/shared_constants.h"
|
2020-03-24 01:44:02 +08:00
|
|
|
|
2020-04-21 12:01:21 +08:00
|
|
|
using namespace winrt::Windows::Foundation;
|
|
|
|
|
2020-04-20 23:22:36 +08:00
|
|
|
namespace KeyboardManagerHelper
|
2020-03-24 01:44:02 +08:00
|
|
|
{
|
2020-04-20 23:22:36 +08:00
|
|
|
// Function to split a wstring based on a delimiter and return a vector of split strings
|
|
|
|
std::vector<std::wstring> splitwstring(const std::wstring& input, wchar_t delimiter)
|
2020-03-24 01:44:02 +08:00
|
|
|
{
|
2020-04-20 23:22:36 +08:00
|
|
|
std::wstringstream ss(input);
|
|
|
|
std::wstring item;
|
|
|
|
std::vector<std::wstring> splittedStrings;
|
|
|
|
while (std::getline(ss, item, delimiter))
|
|
|
|
{
|
|
|
|
splittedStrings.push_back(item);
|
|
|
|
}
|
2020-04-21 12:01:21 +08:00
|
|
|
|
2020-04-20 23:22:36 +08:00
|
|
|
return splittedStrings;
|
2020-03-24 01:44:02 +08:00
|
|
|
}
|
2020-04-21 12:01:21 +08:00
|
|
|
|
2020-04-20 23:22:36 +08:00
|
|
|
// Function to return the next sibling element for an element under a stack panel
|
2020-04-21 12:01:21 +08:00
|
|
|
IInspectable getSiblingElement(IInspectable const& element)
|
2020-04-20 23:22:36 +08:00
|
|
|
{
|
|
|
|
FrameworkElement frameworkElement = element.as<FrameworkElement>();
|
|
|
|
StackPanel parentElement = frameworkElement.Parent().as<StackPanel>();
|
|
|
|
uint32_t index;
|
2020-03-24 01:44:02 +08:00
|
|
|
|
2020-04-20 23:22:36 +08:00
|
|
|
parentElement.Children().IndexOf(frameworkElement, index);
|
|
|
|
return parentElement.Children().GetAt(index + 1);
|
|
|
|
}
|
2020-04-21 12:01:21 +08:00
|
|
|
|
2020-04-20 23:22:36 +08:00
|
|
|
// Function to check if the key is a modifier key
|
|
|
|
bool IsModifierKey(DWORD key)
|
|
|
|
{
|
|
|
|
return (GetKeyType(key) != KeyType::Action);
|
|
|
|
}
|
2020-04-19 07:12:26 +08:00
|
|
|
|
2020-04-20 23:22:36 +08:00
|
|
|
// Function to get the type of the key
|
|
|
|
KeyType GetKeyType(DWORD key)
|
2020-04-19 07:12:26 +08:00
|
|
|
{
|
2020-04-20 23:22:36 +08:00
|
|
|
switch (key)
|
|
|
|
{
|
2020-04-23 23:37:52 +08:00
|
|
|
case CommonSharedConstants::VK_WIN_BOTH:
|
2020-04-20 23:22:36 +08:00
|
|
|
case VK_LWIN:
|
|
|
|
case VK_RWIN:
|
|
|
|
return KeyType::Win;
|
|
|
|
case VK_CONTROL:
|
|
|
|
case VK_LCONTROL:
|
|
|
|
case VK_RCONTROL:
|
|
|
|
return KeyType::Ctrl;
|
|
|
|
case VK_MENU:
|
|
|
|
case VK_LMENU:
|
|
|
|
case VK_RMENU:
|
|
|
|
return KeyType::Alt;
|
|
|
|
case VK_SHIFT:
|
|
|
|
case VK_LSHIFT:
|
|
|
|
case VK_RSHIFT:
|
|
|
|
return KeyType::Shift;
|
|
|
|
default:
|
|
|
|
return KeyType::Action;
|
|
|
|
}
|
2020-04-19 07:12:26 +08:00
|
|
|
}
|
|
|
|
|
2020-04-20 23:22:36 +08:00
|
|
|
// Function to return if the key is an extended key which requires the use of the extended key flag
|
2020-04-27 06:09:40 +08:00
|
|
|
bool IsExtendedKey(DWORD key)
|
2020-04-17 06:17:57 +08:00
|
|
|
{
|
2020-04-20 23:22:36 +08:00
|
|
|
switch (key)
|
|
|
|
{
|
|
|
|
case VK_RCONTROL:
|
|
|
|
case VK_RMENU:
|
|
|
|
case VK_NUMLOCK:
|
|
|
|
case VK_SNAPSHOT:
|
|
|
|
case VK_CANCEL:
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
2020-04-17 06:17:57 +08:00
|
|
|
}
|
2020-04-27 06:09:40 +08:00
|
|
|
|
2020-04-21 12:01:21 +08:00
|
|
|
Collections::IVector<IInspectable> ToBoxValue(const std::vector<std::wstring>& list)
|
|
|
|
{
|
|
|
|
Collections::IVector<IInspectable> boxList = single_threaded_vector<IInspectable>();
|
|
|
|
for (auto& val : list)
|
|
|
|
{
|
|
|
|
boxList.Append(winrt::box_value(val));
|
|
|
|
}
|
|
|
|
|
|
|
|
return boxList;
|
|
|
|
}
|
2020-04-27 06:09:40 +08:00
|
|
|
|
|
|
|
// Function to check if two keys are equal or cover the same set of keys. Return value depends on type of overlap
|
|
|
|
ErrorType DoKeysOverlap(DWORD first, DWORD second)
|
|
|
|
{
|
|
|
|
// If the keys are same
|
|
|
|
if (first == second)
|
|
|
|
{
|
|
|
|
return ErrorType::SameKeyPreviouslyMapped;
|
|
|
|
}
|
|
|
|
else if ((GetKeyType(first) == GetKeyType(second)) && GetKeyType(first) != KeyType::Action)
|
|
|
|
{
|
|
|
|
// If the keys are of the same modifier type and overlapping, i.e. one is L/R and other is common
|
2020-05-09 08:34:24 +08:00
|
|
|
if (((first == VK_LWIN && second == VK_RWIN) || (first == VK_RWIN && second == VK_LWIN)) || ((first == VK_LCONTROL && second == VK_RCONTROL) || (first == VK_RCONTROL && second == VK_LCONTROL)) || ((first == VK_LMENU && second == VK_RMENU) || (first == VK_RMENU && second == VK_LMENU)) || ((first == VK_LSHIFT && second == VK_RSHIFT) || (first == VK_RSHIFT && second == VK_LSHIFT)))
|
2020-04-27 06:09:40 +08:00
|
|
|
{
|
|
|
|
return ErrorType::NoError;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return ErrorType::ConflictingModifierKey;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// If no overlap
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return ErrorType::NoError;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function to return the error message
|
|
|
|
winrt::hstring GetErrorMessage(ErrorType errorType)
|
|
|
|
{
|
|
|
|
switch (errorType)
|
|
|
|
{
|
|
|
|
case ErrorType::NoError:
|
|
|
|
return L"Remapping successful";
|
|
|
|
case ErrorType::SameKeyPreviouslyMapped:
|
|
|
|
return L"Cannot remap a key more than once";
|
|
|
|
case ErrorType::MapToSameKey:
|
|
|
|
return L"Cannot remap a key to itself";
|
|
|
|
case ErrorType::ConflictingModifierKey:
|
|
|
|
return L"Cannot remap this key as it conflicts with another remapped key";
|
|
|
|
case ErrorType::SameShortcutPreviouslyMapped:
|
|
|
|
return L"Cannot remap a shortcut more than once";
|
|
|
|
case ErrorType::MapToSameShortcut:
|
|
|
|
return L"Cannot remap a shortcut to itself";
|
|
|
|
case ErrorType::ConflictingModifierShortcut:
|
|
|
|
return L"Cannot remap this shortcut as it conflicts with another remapped shortcut";
|
|
|
|
case ErrorType::WinL:
|
|
|
|
return L"Cannot remap from/to Win L";
|
|
|
|
case ErrorType::CtrlAltDel:
|
|
|
|
return L"Cannot remap from/to Ctrl Alt Del";
|
|
|
|
case ErrorType::RemapUnsuccessful:
|
|
|
|
return L"Some remappings were not applied";
|
|
|
|
case ErrorType::SaveFailed:
|
|
|
|
return L"Failed to save the remappings";
|
|
|
|
case ErrorType::MissingKey:
|
|
|
|
return L"Incomplete remapping";
|
|
|
|
case ErrorType::ShortcutStartWithModifier:
|
|
|
|
return L"Shortcut must start with a modifier key";
|
|
|
|
case ErrorType::ShortcutCannotHaveRepeatedModifier:
|
|
|
|
return L"Shortcut cannot contain a repeated modifier";
|
|
|
|
case ErrorType::ShortcutAtleast2Keys:
|
|
|
|
return L"Shortcut must have atleast 2 keys";
|
|
|
|
case ErrorType::ShortcutOneActionKey:
|
|
|
|
return L"Shortcut must contain an action key";
|
|
|
|
case ErrorType::ShortcutNotMoreThanOneActionKey:
|
|
|
|
return L"Shortcut cannot have more than one action key";
|
2020-05-12 01:10:36 +08:00
|
|
|
case ErrorType::ShortcutMaxShortcutSizeOneActionKey:
|
|
|
|
return L"Shortcuts can only have up to 2 modifier keys";
|
2020-05-13 02:32:17 +08:00
|
|
|
default:
|
|
|
|
return L"Unexpected error";
|
2020-04-27 06:09:40 +08:00
|
|
|
}
|
|
|
|
}
|
2020-04-17 06:17:57 +08:00
|
|
|
}
|