2020-08-13 16:32:15 -07:00
|
|
|
#include "pch.h"
|
|
|
|
|
#include "BufferValidationHelpers.h"
|
2021-04-26 22:01:38 +03:00
|
|
|
|
2020-12-15 15:16:09 +03:00
|
|
|
#include <common/interop/shared_constants.h>
|
2021-05-07 11:16:31 +03:00
|
|
|
#include <keyboardmanager/common/KeyboardManagerConstants.h>
|
2021-09-03 16:19:16 +01:00
|
|
|
#include <keyboardmanager/common/Helpers.h>
|
2021-04-26 22:01:38 +03:00
|
|
|
|
2021-05-07 11:16:31 +03:00
|
|
|
#include "KeyboardManagerEditorStrings.h"
|
|
|
|
|
#include "KeyDropDownControl.h"
|
|
|
|
|
#include "UIHelpers.h"
|
|
|
|
|
#include "EditorHelpers.h"
|
|
|
|
|
#include "EditorConstants.h"
|
2020-08-13 16:32:15 -07:00
|
|
|
|
|
|
|
|
namespace BufferValidationHelpers
|
|
|
|
|
{
|
2021-09-03 16:19:16 +01:00
|
|
|
// 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);
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-13 16:32:15 -07:00
|
|
|
// Function to validate and update an element of the key remap buffer when the selection has changed
|
2021-05-07 11:16:31 +03:00
|
|
|
ShortcutErrorType ValidateAndUpdateKeyBufferElement(int rowIndex, int colIndex, int selectedKeyCode, RemapBuffer& remapBuffer)
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
2021-05-07 11:16:31 +03:00
|
|
|
ShortcutErrorType errorType = ShortcutErrorType::NoError;
|
2020-08-13 16:32:15 -07:00
|
|
|
|
|
|
|
|
// Check if the element was not found or the index exceeds the known keys
|
2020-10-19 12:27:47 +03:00
|
|
|
if (selectedKeyCode != -1)
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
|
|
|
|
// Check if the value being set is the same as the other column
|
2024-08-15 17:05:16 +09:00
|
|
|
if (remapBuffer[rowIndex].mapping[std::abs(colIndex - 1)].index() == 0)
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
2024-08-15 17:05:16 +09:00
|
|
|
DWORD otherColumnKeyCode = std::get<DWORD>(remapBuffer[rowIndex].mapping[std::abs(colIndex - 1)]);
|
2021-09-03 16:19:16 +01:00
|
|
|
if (otherColumnKeyCode == selectedKeyCode || IsKeyRemappingToItsCombinedKey(selectedKeyCode, otherColumnKeyCode))
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
2021-05-07 11:16:31 +03:00
|
|
|
errorType = ShortcutErrorType::MapToSameKey;
|
2020-08-13 16:32:15 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If one column is shortcut and other is key no warning required
|
|
|
|
|
|
2021-05-07 11:16:31 +03:00
|
|
|
if (errorType == ShortcutErrorType::NoError && colIndex == 0)
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
|
|
|
|
// Check if the key is already remapped to something else
|
|
|
|
|
for (int i = 0; i < remapBuffer.size(); i++)
|
|
|
|
|
{
|
|
|
|
|
if (i != rowIndex)
|
|
|
|
|
{
|
2024-08-15 17:05:16 +09:00
|
|
|
if (remapBuffer[i].mapping[colIndex].index() == 0)
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
2024-08-15 17:05:16 +09:00
|
|
|
ShortcutErrorType result = EditorHelpers::DoKeysOverlap(std::get<DWORD>(remapBuffer[i].mapping[colIndex]), selectedKeyCode);
|
2021-05-07 11:16:31 +03:00
|
|
|
if (result != ShortcutErrorType::NoError)
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
|
|
|
|
errorType = result;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If one column is shortcut and other is key no warning required
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If there is no error, set the buffer
|
2021-05-07 11:16:31 +03:00
|
|
|
if (errorType == ShortcutErrorType::NoError)
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
2024-08-15 17:05:16 +09:00
|
|
|
remapBuffer[rowIndex].mapping[colIndex] = (DWORD)selectedKeyCode;
|
2020-08-13 16:32:15 -07:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2024-08-15 17:05:16 +09:00
|
|
|
remapBuffer[rowIndex].mapping[colIndex] = (DWORD)0;
|
2020-08-13 16:32:15 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Reset to null if the key is not found
|
2024-08-15 17:05:16 +09:00
|
|
|
remapBuffer[rowIndex].mapping[colIndex] = (DWORD)0;
|
2020-08-13 16:32:15 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return errorType;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Function to validate an element of the shortcut remap buffer when the selection has changed
|
2021-05-07 11:16:31 +03:00
|
|
|
std::pair<ShortcutErrorType, DropDownAction> ValidateShortcutBufferElement(int rowIndex, int colIndex, uint32_t dropDownIndex, const std::vector<int32_t>& selectedCodes, std::wstring appName, bool isHybridControl, const RemapBuffer& remapBuffer, bool dropDownFound)
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
|
|
|
|
BufferValidationHelpers::DropDownAction dropDownAction = BufferValidationHelpers::DropDownAction::NoAction;
|
2021-05-07 11:16:31 +03:00
|
|
|
ShortcutErrorType errorType = ShortcutErrorType::NoError;
|
2020-10-19 12:27:47 +03:00
|
|
|
size_t dropDownCount = selectedCodes.size();
|
|
|
|
|
DWORD selectedKeyCode = dropDownFound ? selectedCodes[dropDownIndex] : -1;
|
2020-08-13 16:32:15 -07:00
|
|
|
|
2020-10-19 12:27:47 +03:00
|
|
|
if (selectedKeyCode != -1 && dropDownFound)
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
|
|
|
|
// If only 1 drop down and action key is chosen: Warn that a modifier must be chosen (if the drop down is not for a hybrid scenario)
|
2021-05-07 11:16:31 +03:00
|
|
|
if (dropDownCount == 1 && !Helpers::IsModifierKey(selectedKeyCode) && !isHybridControl)
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
|
|
|
|
// warn and reset the drop down
|
2021-05-07 11:16:31 +03:00
|
|
|
errorType = ShortcutErrorType::ShortcutStartWithModifier;
|
2020-08-13 16:32:15 -07:00
|
|
|
}
|
|
|
|
|
else if (dropDownIndex == dropDownCount - 1)
|
|
|
|
|
{
|
2021-04-26 22:01:38 +03:00
|
|
|
// If it is the last drop down
|
2020-08-13 16:32:15 -07:00
|
|
|
// If last drop down and a modifier is selected: add a new drop down (max drop down count should be enforced)
|
2021-05-07 11:16:31 +03:00
|
|
|
if (Helpers::IsModifierKey(selectedKeyCode) && dropDownCount < EditorConstants::MaxShortcutSize)
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
|
|
|
|
// If it matched any of the previous modifiers then reset that drop down
|
2021-05-07 11:16:31 +03:00
|
|
|
if (EditorHelpers::CheckRepeatedModifier(selectedCodes, selectedKeyCode))
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
|
|
|
|
// warn and reset the drop down
|
2021-05-07 11:16:31 +03:00
|
|
|
errorType = ShortcutErrorType::ShortcutCannotHaveRepeatedModifier;
|
2020-08-13 16:32:15 -07:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-04-26 22:01:38 +03:00
|
|
|
// If not, add a new drop down
|
2020-08-13 16:32:15 -07:00
|
|
|
dropDownAction = BufferValidationHelpers::DropDownAction::AddDropDown;
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-05-07 11:16:31 +03:00
|
|
|
else if (Helpers::IsModifierKey(selectedKeyCode) && dropDownCount >= EditorConstants::MaxShortcutSize)
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
2021-04-26 22:01:38 +03:00
|
|
|
// If last drop down and a modifier is selected but there are already max drop downs: warn the user
|
2020-08-13 16:32:15 -07:00
|
|
|
// warn and reset the drop down
|
2021-05-07 11:16:31 +03:00
|
|
|
errorType = ShortcutErrorType::ShortcutMaxShortcutSizeOneActionKey;
|
2020-08-13 16:32:15 -07:00
|
|
|
}
|
2020-10-19 12:27:47 +03:00
|
|
|
else if (selectedKeyCode == 0)
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
2021-04-26 22:01:38 +03:00
|
|
|
// If None is selected but it's the last index: warn
|
2020-08-13 16:32:15 -07:00
|
|
|
// If it is a hybrid control and there are 2 drop downs then deletion is allowed
|
2021-05-07 11:16:31 +03:00
|
|
|
if (isHybridControl && dropDownCount == EditorConstants::MinShortcutSize)
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
|
|
|
|
// set delete drop down flag
|
|
|
|
|
dropDownAction = BufferValidationHelpers::DropDownAction::DeleteDropDown;
|
|
|
|
|
// do not delete the drop down now since there may be some other error which would cause the drop down to be invalid after removal
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// warn and reset the drop down
|
2021-05-07 11:16:31 +03:00
|
|
|
errorType = ShortcutErrorType::ShortcutOneActionKey;
|
2020-08-13 16:32:15 -07:00
|
|
|
}
|
|
|
|
|
}
|
2020-10-19 12:27:47 +03:00
|
|
|
else if (selectedKeyCode == CommonSharedConstants::VK_DISABLED && dropDownIndex)
|
2020-10-02 15:36:36 +03:00
|
|
|
{
|
2024-12-06 06:33:08 -10:00
|
|
|
// Disable cannot be selected if one modifier key has already been selected
|
2021-05-07 11:16:31 +03:00
|
|
|
errorType = ShortcutErrorType::ShortcutDisableAsActionKey;
|
2020-10-02 15:36:36 +03:00
|
|
|
}
|
2020-08-13 16:32:15 -07:00
|
|
|
// If none of the above, then the action key will be set
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-04-26 22:01:38 +03:00
|
|
|
// If it is not the last drop down
|
2021-05-07 11:16:31 +03:00
|
|
|
if (Helpers::IsModifierKey(selectedKeyCode))
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
|
|
|
|
// If it matched any of the previous modifiers then reset that drop down
|
2021-05-07 11:16:31 +03:00
|
|
|
if (EditorHelpers::CheckRepeatedModifier(selectedCodes, selectedKeyCode))
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
|
|
|
|
// warn and reset the drop down
|
2021-05-07 11:16:31 +03:00
|
|
|
errorType = ShortcutErrorType::ShortcutCannotHaveRepeatedModifier;
|
2020-08-13 16:32:15 -07:00
|
|
|
}
|
|
|
|
|
// If not, the modifier key will be set
|
|
|
|
|
}
|
2021-05-07 11:16:31 +03:00
|
|
|
else if (selectedKeyCode == 0 && dropDownCount > EditorConstants::MinShortcutSize)
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
2021-04-26 22:01:38 +03:00
|
|
|
// If None is selected and there are more than 2 drop downs
|
2020-08-13 16:32:15 -07:00
|
|
|
// set delete drop down flag
|
|
|
|
|
dropDownAction = BufferValidationHelpers::DropDownAction::DeleteDropDown;
|
|
|
|
|
// do not delete the drop down now since there may be some other error which would cause the drop down to be invalid after removal
|
|
|
|
|
}
|
2021-05-07 11:16:31 +03:00
|
|
|
else if (selectedKeyCode == 0 && dropDownCount <= EditorConstants::MinShortcutSize)
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
|
|
|
|
// If it is a hybrid control and there are 2 drop downs then deletion is allowed
|
2021-05-07 11:16:31 +03:00
|
|
|
if (isHybridControl && dropDownCount == EditorConstants::MinShortcutSize)
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
|
|
|
|
// set delete drop down flag
|
|
|
|
|
dropDownAction = BufferValidationHelpers::DropDownAction::DeleteDropDown;
|
|
|
|
|
// do not delete the drop down now since there may be some other error which would cause the drop down to be invalid after removal
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// warn and reset the drop down
|
2021-05-07 11:16:31 +03:00
|
|
|
errorType = ShortcutErrorType::ShortcutAtleast2Keys;
|
2020-08-13 16:32:15 -07:00
|
|
|
}
|
|
|
|
|
}
|
2020-10-19 12:27:47 +03:00
|
|
|
else if (selectedKeyCode == CommonSharedConstants::VK_DISABLED && dropDownIndex)
|
2020-10-02 15:36:36 +03:00
|
|
|
{
|
2021-04-26 22:01:38 +03:00
|
|
|
// Allow selection of VK_DISABLE only in first dropdown
|
2021-05-07 11:16:31 +03:00
|
|
|
errorType = ShortcutErrorType::ShortcutDisableAsActionKey;
|
2020-10-02 15:36:36 +03:00
|
|
|
}
|
2020-08-13 16:32:15 -07:00
|
|
|
else if (dropDownIndex != 0 || isHybridControl)
|
|
|
|
|
{
|
2021-04-26 22:01:38 +03:00
|
|
|
// If the user tries to set an action key check if all drop down menus after this are empty if it is not the first key.
|
|
|
|
|
// If it is a hybrid control, this can be done even on the first key
|
2020-08-13 16:32:15 -07:00
|
|
|
bool isClear = true;
|
2023-02-08 11:01:13 +00:00
|
|
|
for (int i = dropDownIndex + 1; i < static_cast<int>(dropDownCount); i++)
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
2020-10-19 12:27:47 +03:00
|
|
|
if (selectedCodes[i] != -1)
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
|
|
|
|
isClear = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isClear)
|
|
|
|
|
{
|
|
|
|
|
dropDownAction = BufferValidationHelpers::DropDownAction::ClearUnusedDropDowns;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
[KBM]Launch apps / URI with keyboard shortcuts, support chords (#30121)
* Working UI update with just runProgram Path and isRunProgram
* First working, basic. no args or path, or setting change detections.
* Revert and fixed.
* Some clean up, working with config file monitor
* Args and Start-in should be working.
* File monitor, quotes, xaml screens one
* Fixed enable/disable toogle from XAML
* Code cleanup.
* Betting logging.
* Cleanup, start of RunProgramDescriptor and usage of run_non_elevated/run_elevated
* Code moved to KeyboardEventHandlers, but not enabled since it won't build as is, needs elevation.h. Other testing..
* Key chords working, pretty much
* Added gui for elevation level, need to refresh on change...
* f: include shellapi.h and reference wil in KBMEL
* run_elevated/run_non_elevated sorted out. Working!
* Removed lots of old temp code.
* Fix some speling errors.
* Cleanup before trying to add a UI for the chord
* Added "DifferentUser" option
* Closer on UI for chords.
* Better UI, lots working.
* Clean up
* Text for “Allow chords” – needs to look better…
* Bugs and clean-up
* Cleanup
* Refactor and clean up.
* More clean up
* Some localization.
* Don’t show “Allow chords“ to the “to” shortcut
* Maybe better foreground after opening new app
* Better chord matching.
* Runprogram fix for stealing existing shortcut.
* Better runProgram stuff
* Temp commit
* Working well
* Toast test
* More toast
* Added File and Folder picker UI
* Pre-check on run program file exists.
* Refactor to SetupRunProgramControls
* Open URI UI is going.
* Open URI working well
* Open URI stuff working well
* Allowed AppSpecific shortcut and fixed backup/restore shortcut dups
* Fixed settings screen
* Start of code to find by name...
* UI fixed
* Small fixes
* Some single edit code working.
* UI getting better.
* Fixes
* Fixed and merge from main
* UI updates
* UI updates.
* UI stuff
* Fixed crash from move ui item locations.
* Fixed crash from move ui item locations.
* Added delete confirm
* Basic sound working.
* Localized some stuff
* Added sounds
* Better experiance when shortcut is in use.
* UI tweaks
* Fixed KBM ui for unicode shortcut not having ","
* Some clean up
* Cleanup
* Cleanup
* Fixed applyXamlStyling
* Added back stuff lost in merge
* applyXamlStyling, again
* Fixed crash on change from non shortcut to shortcut
* Update src/modules/keyboardmanager/KeyboardManagerEngineTest/KeyboardManagerEngineTest.vcxproj
* Fixed some spelling type issues.
* ImplementationLibrary 231216
* Comment bump to see if the Microsoft.Windows.ImplementationLibrary version thing gets picked up
* Correct, Microsoft.Windows.ImplementationLibrary, finally?
* Fixed two test that failed because we now allow key-chords.
* Removed shortcut sounds.
* use original behavior when "allow chords" is off in shortcut window
* fix crash when editing a shortcut that has apps specified for it
* split KBM chords with comma on dashboard page
* Fix some spelling items.
* More "spelling"
* Fix XAML styling
* align TextBlock and ToggleSwitch
* fix cutoff issue at the top
* increase ComboBox width
* Added *Unsupported* for backwards compat on config of KBM
* fix spellcheck
* Fix crash on Remap key screen
* Fixed Remap Keys ComboBox width too short.
* Removed KBM Single Edit mode, fixed crash.
* Fix Xaml with xaml cops
* Fix crash on setting "target app" for some types of shortcuts.
* Space to toggle chord, combobox back
* fix spellcheck
* fix some code nits
* Code review updates.
* Add exclusions to the bug report tool
* Code review and kill CloseAndEndTask
* Fix alignment / 3 comboboxes per row
* Fix daily telemetry events to exclude start app and open URI
* Add chords and remove app start and open uri from config telemetry
* comma instead of plus in human readable shortcut telemetry data
* Code review, restore default-old state when new row added in KBM
* Code review, restore default-old state when new row added in KBM, part 2
* Still show target app on Settings
* Only allow enabling chords for origin shortcuts
---------
Co-authored-by: Andrey Nekrasov <yuyoyuppe@users.noreply.github.com>
Co-authored-by: Jaime Bernardo <jaime@janeasystems.com>
2024-02-27 18:12:05 -05:00
|
|
|
// this used to "warn and reset the drop down" but for now, since we will allow Chords, we do allow this
|
|
|
|
|
// leaving the here and commented out for posterity, for now.
|
|
|
|
|
// errorType = ShortcutErrorType::ShortcutNotMoreThanOneActionKey;
|
2020-08-13 16:32:15 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-04-26 22:01:38 +03:00
|
|
|
// If there an action key is chosen on the first drop down and there are more than one drop down menus
|
2020-08-13 16:32:15 -07:00
|
|
|
// warn and reset the drop down
|
2021-05-07 11:16:31 +03:00
|
|
|
errorType = ShortcutErrorType::ShortcutStartWithModifier;
|
2020-08-13 16:32:15 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// After validating the shortcut, now for errors like remap to same shortcut, remap shortcut more than once, Win L and Ctrl Alt Del
|
2021-05-07 11:16:31 +03:00
|
|
|
if (errorType == ShortcutErrorType::NoError)
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
2023-11-23 11:46:07 +01:00
|
|
|
KeyShortcutTextUnion tempShortcut;
|
2020-10-19 12:27:47 +03:00
|
|
|
if (isHybridControl && KeyDropDownControl::GetNumberOfSelectedKeys(selectedCodes) == 1)
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
2021-06-01 19:15:16 +03:00
|
|
|
tempShortcut = (DWORD)*std::find_if(selectedCodes.begin(), selectedCodes.end(), [](int32_t a) { return a != -1 && a != 0; });
|
2020-08-13 16:32:15 -07:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
tempShortcut = Shortcut();
|
2020-10-19 12:27:47 +03:00
|
|
|
std::get<Shortcut>(tempShortcut).SetKeyCodes(selectedCodes);
|
2020-08-13 16:32:15 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Convert app name to lower case
|
|
|
|
|
std::transform(appName.begin(), appName.end(), appName.begin(), towlower);
|
2022-12-18 11:45:19 +00:00
|
|
|
std::wstring lowercaseDefAppName = KeyboardManagerEditorStrings::DefaultAppName();
|
2020-08-13 16:32:15 -07:00
|
|
|
std::transform(lowercaseDefAppName.begin(), lowercaseDefAppName.end(), lowercaseDefAppName.begin(), towlower);
|
|
|
|
|
if (appName == lowercaseDefAppName)
|
|
|
|
|
{
|
|
|
|
|
appName = L"";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check if the value being set is the same as the other column - index of other column does not have to be checked since only one column is hybrid
|
|
|
|
|
if (tempShortcut.index() == 1)
|
|
|
|
|
{
|
|
|
|
|
// If shortcut to shortcut
|
2024-08-15 17:05:16 +09:00
|
|
|
if (remapBuffer[rowIndex].mapping[std::abs(colIndex - 1)].index() == 1)
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
2024-08-15 17:05:16 +09:00
|
|
|
auto& shortcut = std::get<Shortcut>(remapBuffer[rowIndex].mapping[std::abs(colIndex - 1)]);
|
2021-05-07 11:16:31 +03:00
|
|
|
if (shortcut == std::get<Shortcut>(tempShortcut) && EditorHelpers::IsValidShortcut(shortcut) && EditorHelpers::IsValidShortcut(std::get<Shortcut>(tempShortcut)))
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
2021-05-07 11:16:31 +03:00
|
|
|
errorType = ShortcutErrorType::MapToSameShortcut;
|
2020-08-13 16:32:15 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If one column is shortcut and other is key no warning required
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// If key to key
|
2024-08-15 17:05:16 +09:00
|
|
|
if (remapBuffer[rowIndex].mapping[std::abs(colIndex - 1)].index() == 0)
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
2024-08-15 17:05:16 +09:00
|
|
|
DWORD otherColumnKeyCode = std::get<DWORD>(remapBuffer[rowIndex].mapping[std::abs(colIndex - 1)]);
|
2021-09-03 16:19:16 +01:00
|
|
|
DWORD shortcutKeyCode = std::get<DWORD>(tempShortcut);
|
|
|
|
|
if ((otherColumnKeyCode == shortcutKeyCode || IsKeyRemappingToItsCombinedKey(otherColumnKeyCode, shortcutKeyCode)) && otherColumnKeyCode != NULL && shortcutKeyCode != NULL)
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
2021-05-07 11:16:31 +03:00
|
|
|
errorType = ShortcutErrorType::MapToSameKey;
|
2020-08-13 16:32:15 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If one column is shortcut and other is key no warning required
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-07 11:16:31 +03:00
|
|
|
if (errorType == ShortcutErrorType::NoError && colIndex == 0)
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
|
|
|
|
// Check if the key is already remapped to something else for the same target app
|
|
|
|
|
for (int i = 0; i < remapBuffer.size(); i++)
|
|
|
|
|
{
|
2024-08-15 17:05:16 +09:00
|
|
|
std::wstring currAppName = remapBuffer[i].appName;
|
2020-08-13 16:32:15 -07:00
|
|
|
std::transform(currAppName.begin(), currAppName.end(), currAppName.begin(), towlower);
|
|
|
|
|
|
|
|
|
|
if (i != rowIndex && currAppName == appName)
|
|
|
|
|
{
|
2021-05-07 11:16:31 +03:00
|
|
|
ShortcutErrorType result = ShortcutErrorType::NoError;
|
2020-08-13 16:32:15 -07:00
|
|
|
if (!isHybridControl)
|
|
|
|
|
{
|
2024-08-15 17:05:16 +09:00
|
|
|
result = EditorHelpers::DoShortcutsOverlap(std::get<Shortcut>(remapBuffer[i].mapping[colIndex]), std::get<Shortcut>(tempShortcut));
|
2020-08-13 16:32:15 -07:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2024-08-15 17:05:16 +09:00
|
|
|
if (tempShortcut.index() == 0 && remapBuffer[i].mapping[colIndex].index() == 0)
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
2024-08-15 17:05:16 +09:00
|
|
|
if (std::get<DWORD>(tempShortcut) != NULL && std::get<DWORD>(remapBuffer[i].mapping[colIndex]) != NULL)
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
2024-08-15 17:05:16 +09:00
|
|
|
result = EditorHelpers::DoKeysOverlap(std::get<DWORD>(remapBuffer[i].mapping[colIndex]), std::get<DWORD>(tempShortcut));
|
2020-08-13 16:32:15 -07:00
|
|
|
}
|
|
|
|
|
}
|
2024-08-15 17:05:16 +09:00
|
|
|
else if (tempShortcut.index() == 1 && remapBuffer[i].mapping[colIndex].index() == 1)
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
2024-08-15 17:05:16 +09:00
|
|
|
auto& shortcut = std::get<Shortcut>(remapBuffer[i].mapping[colIndex]);
|
2021-05-07 11:16:31 +03:00
|
|
|
if (EditorHelpers::IsValidShortcut(std::get<Shortcut>(tempShortcut)) && EditorHelpers::IsValidShortcut(shortcut))
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
2024-08-15 17:05:16 +09:00
|
|
|
result = EditorHelpers::DoShortcutsOverlap(std::get<Shortcut>(remapBuffer[i].mapping[colIndex]), std::get<Shortcut>(tempShortcut));
|
2020-08-13 16:32:15 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Other scenarios not possible since key to shortcut is with key to key, and shortcut to key is with shortcut to shortcut
|
|
|
|
|
}
|
2021-05-07 11:16:31 +03:00
|
|
|
if (result != ShortcutErrorType::NoError)
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
|
|
|
|
errorType = result;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-07 11:16:31 +03:00
|
|
|
if (errorType == ShortcutErrorType::NoError && tempShortcut.index() == 1)
|
2020-08-13 16:32:15 -07:00
|
|
|
{
|
2021-05-07 11:16:31 +03:00
|
|
|
errorType = EditorHelpers::IsShortcutIllegal(std::get<Shortcut>(tempShortcut));
|
2020-08-13 16:32:15 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return std::make_pair(errorType, dropDownAction);
|
|
|
|
|
}
|
|
|
|
|
}
|