@@ -271,10 +271,18 @@ namespace KeyboardEventHandlers
271
271
continue ;
272
272
}
273
273
274
- if (data-> lParam -> vkCode == itShortcut. GetSecondKey () && itShortcut.IsChordStarted () && itShortcut.HasChord ())
274
+ if (itShortcut.IsChordStarted () && itShortcut.HasChord ())
275
275
{
276
- Logger::trace (L" ChordKeyboardHandler:found chord match {}, {}" , itShortcut.GetActionKey (), itShortcut.GetSecondKey ());
277
- isMatchOnChordEnd = true ;
276
+ if (data->lParam ->vkCode == itShortcut.GetSecondKey ())
277
+ {
278
+ Logger::trace (L" ChordKeyboardHandler:found chord match {}, {}" , itShortcut.GetActionKey (), itShortcut.GetSecondKey ());
279
+ isMatchOnChordEnd = true ;
280
+ }
281
+ // Resets chord status for the shortcut. A key was pressed and we registered if it was the end of the chord. We can reset it.
282
+ if (data->lParam ->vkCode != itShortcut.GetActionKey ())
283
+ {
284
+ itShortcut.SetChordStarted (false );
285
+ }
278
286
}
279
287
280
288
if (resetChordsResults.AnyChordStarted && !isMatchOnChordEnd)
@@ -670,7 +678,7 @@ namespace KeyboardEventHandlers
670
678
if (!remapToShortcut || (remapToShortcut && std::get<Shortcut>(it->second .targetShortcut ).CheckModifiersKeyboardState (ii)))
671
679
{
672
680
// Case 2: If the original shortcut is still held down the keyboard will get a key down message of the action key in the original shortcut and the new shortcut's modifiers will be held down (keys held down send repeated keydown messages)
673
- if (data->lParam ->vkCode == it->first .GetActionKey () && (data->wParam == WM_KEYDOWN || data->wParam == WM_SYSKEYDOWN))
681
+ if ((( data->lParam ->vkCode == it->first .GetActionKey () && !it-> first . HasChord ())||(data-> lParam -> vkCode == it-> first . GetSecondKey () && it-> first . HasChord ()) ) && (data->wParam == WM_KEYDOWN || data->wParam == WM_SYSKEYDOWN))
674
682
{
675
683
// In case of mapping to disable do not send anything
676
684
if (remapToKey && std::get<DWORD>(it->second .targetShortcut ) == CommonSharedConstants::VK_DISABLED)
@@ -716,15 +724,46 @@ namespace KeyboardEventHandlers
716
724
}
717
725
718
726
// Case 3: If the action key is released from the original shortcut, keep modifiers of the new shortcut until some other key event which doesn't apply to the original shortcut
719
- if (!remapToText && data->lParam ->vkCode == it->first .GetActionKey () && (data->wParam == WM_KEYUP || data->wParam == WM_SYSKEYUP))
727
+ if (!remapToText && ((!it-> first . HasChord () && data->lParam ->vkCode == it->first .GetActionKey ()) || (it-> first . HasChord () && data-> lParam -> vkCode ==it-> first . GetSecondKey ()) ) && (data->wParam == WM_KEYUP || data->wParam == WM_SYSKEYUP))
720
728
{
721
729
size_t key_count = 1 ;
722
730
LPINPUT keyEventList = nullptr ;
723
- if (remapToShortcut)
731
+ if (remapToShortcut && !it-> first . HasChord () )
724
732
{
733
+ // Just lift the action key for no chords.
725
734
keyEventList = new INPUT[key_count]{};
726
735
Helpers::SetKeyEvent (keyEventList, 0 , INPUT_KEYBOARD, static_cast <WORD>(std::get<Shortcut>(it->second .targetShortcut ).GetActionKey ()), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
727
736
}
737
+ else if (remapToShortcut && it->first .HasChord ())
738
+ {
739
+ // If it has a chord, we'll want a full clean contemplated in the else, since you can't really repeat chords by pressing the end key again.
740
+
741
+ // Key up for all new shortcut keys, key down for original shortcut modifiers and current key press but common keys aren't repeated
742
+ key_count = (dest_size) + (src_size +1 ) - (2 * static_cast <size_t >(commonKeys));
743
+ int i = 0 ;
744
+
745
+ keyEventList = new INPUT[key_count]{};
746
+ Helpers::SetKeyEvent (keyEventList, i, INPUT_KEYBOARD, static_cast <WORD>(std::get<Shortcut>(it->second .targetShortcut ).GetActionKey ()), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG);
747
+ i++;
748
+
749
+ // Release new shortcut state (release in reverse order of shortcut to be accurate)
750
+ Helpers::SetModifierKeyEvents (std::get<Shortcut>(it->second .targetShortcut ), it->second .winKeyInvoked , keyEventList, i, false , KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first );
751
+
752
+ // Set old shortcut key down state
753
+ Helpers::SetModifierKeyEvents (it->first , it->second .winKeyInvoked , keyEventList, i, true , KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get<Shortcut>(it->second .targetShortcut ));
754
+
755
+ // Reset the remap state
756
+ it->second .isShortcutInvoked = false ;
757
+ it->second .winKeyInvoked = ModifierKey::Disabled;
758
+ it->second .isOriginalActionKeyPressed = false ;
759
+
760
+ // If app specific shortcut has finished invoking, reset the target application
761
+ if (activatedApp)
762
+ {
763
+ state.SetActivatedApp (KeyboardManagerConstants::NoActivatedApp);
764
+ }
765
+
766
+ }
728
767
else if (std::get<DWORD>(it->second .targetShortcut ) == CommonSharedConstants::VK_DISABLED)
729
768
{
730
769
// If remapped to disable, do nothing and suppress the key event
@@ -822,7 +861,7 @@ namespace KeyboardEventHandlers
822
861
Shortcut currentlyPressed = it->first ;
823
862
currentlyPressed.actionKey = data->lParam ->vkCode ;
824
863
auto newRemappingIter = reMap.find (currentlyPressed);
825
- if (newRemappingIter != reMap.end ())
864
+ if (newRemappingIter != reMap.end () && !newRemappingIter-> first . HasChord () )
826
865
{
827
866
auto & newRemapping = newRemappingIter->second ;
828
867
Shortcut from = std::get<Shortcut>(it->second .targetShortcut );
0 commit comments