Skip to content

Commit

Permalink
[KBM Editor] fix crash when mapping left and right modifier to the co…
Browse files Browse the repository at this point in the history
…mbined key. (#12999)

* [KBM Editor] Don't combine keys to same key

* Avoid crashes when flyouts can't be shown yet

* Disallow mapping of left or right key to combined

* Refactor remap to combined key check

* Add log message when flyout fails to load
  • Loading branch information
jaimecbernardo committed Sep 3, 2021
1 parent 4a1e21a commit b8236d5
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <common/interop/shared_constants.h>
#include <keyboardmanager/common/KeyboardManagerConstants.h>
#include <keyboardmanager/common/Helpers.h>

#include "KeyboardManagerEditorStrings.h"
#include "KeyDropDownControl.h"
Expand All @@ -12,6 +13,13 @@

namespace BufferValidationHelpers
{
// Helper function to verify if a key is being remapped to/from its combined key
bool IsKeyRemappingToItsCombinedKey(DWORD keyCode1, DWORD keyCode2)
{
return (keyCode1 == Helpers::GetCombinedKey(keyCode1) || keyCode2 == Helpers::GetCombinedKey(keyCode2)) &&
Helpers::GetCombinedKey(keyCode1) == Helpers::GetCombinedKey(keyCode2);
}

// Function to validate and update an element of the key remap buffer when the selection has changed
ShortcutErrorType ValidateAndUpdateKeyBufferElement(int rowIndex, int colIndex, int selectedKeyCode, RemapBuffer& remapBuffer)
{
Expand All @@ -23,7 +31,8 @@ namespace BufferValidationHelpers
// Check if the value being set is the same as the other column
if (remapBuffer[rowIndex].first[std::abs(int(colIndex) - 1)].index() == 0)
{
if (std::get<DWORD>(remapBuffer[rowIndex].first[std::abs(int(colIndex) - 1)]) == selectedKeyCode)
DWORD otherColumnKeyCode = std::get<DWORD>(remapBuffer[rowIndex].first[std::abs(int(colIndex) - 1)]);
if (otherColumnKeyCode == selectedKeyCode || IsKeyRemappingToItsCombinedKey(selectedKeyCode, otherColumnKeyCode))
{
errorType = ShortcutErrorType::MapToSameKey;
}
Expand Down Expand Up @@ -251,7 +260,9 @@ namespace BufferValidationHelpers
// If key to key
if (remapBuffer[rowIndex].first[std::abs(int(colIndex) - 1)].index() == 0)
{
if (std::get<DWORD>(remapBuffer[rowIndex].first[std::abs(int(colIndex) - 1)]) == std::get<DWORD>(tempShortcut) && std::get<DWORD>(remapBuffer[rowIndex].first[std::abs(int(colIndex) - 1)]) != NULL && std::get<DWORD>(tempShortcut) != NULL)
DWORD otherColumnKeyCode = std::get<DWORD>(remapBuffer[rowIndex].first[std::abs(int(colIndex) - 1)]);
DWORD shortcutKeyCode = std::get<DWORD>(tempShortcut);
if ((otherColumnKeyCode == shortcutKeyCode || IsKeyRemappingToItsCombinedKey(otherColumnKeyCode, shortcutKeyCode)) && otherColumnKeyCode != NULL && shortcutKeyCode != NULL)
{
errorType = ShortcutErrorType::MapToSameKey;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ namespace BufferValidationHelpers
ClearUnusedDropDowns
};

// Helper function to verify if a key is being remapped to/from its combined key
bool IsKeyRemappingToItsCombinedKey(DWORD keyCode1, DWORD keyCode2);

// Function to validate and update an element of the key remap buffer when the selection has changed
ShortcutErrorType ValidateAndUpdateKeyBufferElement(int rowIndex, int colIndex, int selectedKeyCode, RemapBuffer& remapBuffer);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,15 @@ void KeyDropDownControl::SetDropDownError(ComboBox currentDropDown, hstring mess
{
currentDropDown.SelectedIndex(-1);
warningMessage.as<TextBlock>().Text(message);
currentDropDown.ContextFlyout().ShowAttachedFlyout((FrameworkElement)dropDown.as<ComboBox>());
try
{
currentDropDown.ContextFlyout().ShowAttachedFlyout((FrameworkElement)dropDown.as<ComboBox>());
}
catch (winrt::hresult_error const&)
{
// If it's loading and some remaps are invalid from previous configs, avoid crashing when flyouts can't be showed yet.
Logger::error(L"Failed to show dropdown error flyout: {}", message);
}
}

// Function to add a shortcut to the UI control as combo boxes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "LoadingAndSavingRemappingHelper.h"

#include <set>
#include <variant>
#include <common/interop/shared_constants.h>
#include <keyboardmanager/common/MappingConfiguration.h>

Expand Down Expand Up @@ -88,6 +89,11 @@ namespace LoadingAndSavingRemappingHelper
// If they are mapped to the same key, delete those entries and set the common version
if (table[leftKey] == table[rightKey])
{
if (std::holds_alternative<DWORD>(table[leftKey]) && std::get<DWORD>(table[leftKey]) == combinedKey)
{
// Avoid mapping a key to itself when the combined key is equal to the resulting mapping.
return;
}
table[combinedKey] = table[leftKey];
table.erase(leftKey);
table.erase(rightKey);
Expand Down
21 changes: 21 additions & 0 deletions src/modules/keyboardmanager/common/Helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,27 @@ namespace Helpers
return (GetKeyType(key) != KeyType::Action);
}

// Function to get the combined key for modifier keys
DWORD GetCombinedKey(DWORD key)
{
switch (key) {
case VK_LWIN:
case VK_RWIN:
return CommonSharedConstants::VK_WIN_BOTH;
case VK_LCONTROL:
case VK_RCONTROL:
return VK_CONTROL;
case VK_LMENU:
case VK_RMENU:
return VK_MENU;
case VK_LSHIFT:
case VK_RSHIFT:
return VK_SHIFT;
default:
return key;
}
}

// Function to get the type of the key
KeyType GetKeyType(DWORD key)
{
Expand Down
3 changes: 3 additions & 0 deletions src/modules/keyboardmanager/common/Helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ namespace Helpers
// Function to check if the key is a modifier key
bool IsModifierKey(DWORD key);

// Function to get the combined key for modifier keys
DWORD GetCombinedKey(DWORD key);

// Function to get the type of the key
KeyType GetKeyType(DWORD key);

Expand Down

0 comments on commit b8236d5

Please sign in to comment.