-
Notifications
You must be signed in to change notification settings - Fork 7.8k
[KBM] Fixed Ctrl key state handling during and after shortcuts invoked by AltGr #31923
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
stefansjfw
merged 13 commits into
microsoft:main
from
gokcekantarci:KBM]-Alt-Right-Shortcut-Reset
Aug 21, 2024
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
fdf2aed
[KBM] Fixed Ctrl key state handling during and after shortcuts invoke…
gokcekantarci e5cc947
[KBM] Release ctrl in Alt gr condition is added to remap shortcut.
gokcekantarci 65aa359
Merge branch 'main' into KBM]-Alt-Right-Shortcut-Reset
gokcekantarci 2219b21
Merge branch 'main' into pr31923
jaimecbernardo 391f8ec
Merge remote-tracking branch 'upstream/main' into KBM]-Alt-Right-Shor…
gokcekantarci 2774e1c
[KBM] Ctrl(Left) stuck fix.
gokcekantarci 59b0b06
Revert "[KBM] Ctrl(Left) stuck fix."
gokcekantarci 57d755d
[KBM] Fixed Ctrl key state handling during and after shortcuts invoke…
gokcekantarci 76765e6
Merge remote-tracking branch 'upstream/main' into KBM]-Alt-Right-Shor…
gokcekantarci d3278dd
[KBM] Left ctrl stuck bug is solved.
gokcekantarci d0459e8
Merge branch 'KBM]-Alt-Right-Shortcut-Reset' of https://github.com/go…
gokcekantarci 051ddca
[KBM] Remove unnecessary changes.
gokcekantarci 0589998
[KBM] New Ctrl stuck case fix.
gokcekantarci File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -247,6 +247,14 @@ namespace KeyboardEventHandlers | |
| bool isMatchOnChordEnd = false; | ||
| bool isMatchOnChordStart = false; | ||
|
|
||
| static bool isAltRightKeyInvoked = false; | ||
|
|
||
| // Check if the right Alt key (AltGr) is pressed. | ||
| if (data->lParam->vkCode == VK_RMENU && ii.GetVirtualKeyState(VK_LCONTROL)) | ||
| { | ||
| isAltRightKeyInvoked = true; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this can be both KEYUP or KEYDOWN. Should |
||
| } | ||
|
|
||
| // If the shortcut has been pressed down | ||
| if (!it->second.isShortcutInvoked && it->first.CheckModifiersKeyboardState(ii)) | ||
| { | ||
|
|
@@ -522,6 +530,13 @@ namespace KeyboardEventHandlers | |
| // 5. The user presses any key apart from the action key or a modifier key in the original shortcut - revert the keyboard state to just the original modifiers being held down along with the current key press | ||
| // 6. The user releases any key apart from original modifier or original action key - This can't happen since the key down would have to happen first, which is handled above | ||
|
|
||
| // Prevents the unintended release of the Ctrl part when AltGr is pressed. AltGr acts as both Ctrl and Alt being pressed. | ||
| // After triggering a shortcut involving AltGr, the system might attempt to release the Ctrl part. This code ensures Ctrl remains pressed, maintaining the AltGr state correctly. | ||
| if (isAltRightKeyInvoked && data->lParam->vkCode == VK_LCONTROL && (data->wParam == WM_KEYUP || data->wParam == WM_SYSKEYUP)) | ||
| { | ||
| break; | ||
| } | ||
|
|
||
| // Get the common keys between the two shortcuts | ||
| int commonKeys = (remapToShortcut && !isRunProgram) ? it->first.GetCommonModifiersCount(std::get<Shortcut>(it->second.targetShortcut)) : 0; | ||
|
|
||
|
|
@@ -543,8 +558,15 @@ namespace KeyboardEventHandlers | |
|
|
||
| Helpers::SetModifierKeyEvents(std::get<Shortcut>(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first, data->lParam->vkCode); | ||
|
|
||
| // Set original shortcut key down state except the action key and the released modifier since the original action key may or may not be held down. If it is held down it will generate it's own key message | ||
| Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get<Shortcut>(it->second.targetShortcut), data->lParam->vkCode); | ||
| if (!isAltRightKeyInvoked) | ||
| { | ||
| // Set original shortcut key down state except the action key and the released modifier since the original action key may or may not be held down. If it is held down it will generate it's own key message | ||
| Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get<Shortcut>(it->second.targetShortcut), data->lParam->vkCode); | ||
| } | ||
| else | ||
| { | ||
| isAltRightKeyInvoked = false; | ||
| } | ||
|
|
||
| // Send a dummy key event to prevent modifier press+release from being triggered. Example: Win+Ctrl+A->Ctrl+V, press Win+Ctrl+A and release A then Ctrl, since Win will be pressed here we need to send a dummy event after it | ||
| Helpers::SetDummyKeyEvent(keyEventList, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); | ||
|
|
@@ -559,8 +581,16 @@ namespace KeyboardEventHandlers | |
| Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast<WORD>(Helpers::FilterArtificialKeys(std::get<DWORD>(it->second.targetShortcut))), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); | ||
| } | ||
|
|
||
| // Set original shortcut key down state except the action key and the released modifier since the original action key may or may not be held down. If it is held down it will generate it's own key message | ||
| Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, Shortcut(), data->lParam->vkCode); | ||
| // Ensures that after releasing both the action key and AltGr, Ctrl does not remain falsely pressed. | ||
| if (!isAltRightKeyInvoked) | ||
| { | ||
| // Set original shortcut key down state except the action key and the released modifier since the original action key may or may not be held down. If it is held down it will generate it's own key message | ||
| Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, Shortcut(), data->lParam->vkCode); | ||
| } | ||
| else | ||
| { | ||
| isAltRightKeyInvoked = false; | ||
| } | ||
|
|
||
| // Send a dummy key event to prevent modifier press+release from being triggered. Example: Win+Ctrl+A->V, press Win+Ctrl+A and release A then Ctrl, since Win will be pressed here we need to send a dummy event after it | ||
| Helpers::SetDummyKeyEvent(keyEventList, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); | ||
|
|
@@ -672,16 +702,22 @@ namespace KeyboardEventHandlers | |
| // Release new key state | ||
| Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast<WORD>(Helpers::FilterArtificialKeys(std::get<DWORD>(it->second.targetShortcut))), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); | ||
|
|
||
| // Set original shortcut key down state except the action key | ||
| Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); | ||
| if (!isAltRightKeyInvoked) | ||
| { | ||
| // Set original shortcut key down state except the action key | ||
| Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); | ||
| } | ||
|
|
||
| // Send a dummy key event to prevent modifier press+release from being triggered. Example: Win+A->V, press Shift+Win+A and release A, since Win will be pressed here we need to send a dummy event after it | ||
| Helpers::SetDummyKeyEvent(keyEventList, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); | ||
|
|
||
| // Reset the remap state | ||
| it->second.isShortcutInvoked = false; | ||
| it->second.winKeyInvoked = ModifierKey::Disabled; | ||
| it->second.isOriginalActionKeyPressed = false; | ||
| if (!isAltRightKeyInvoked) | ||
| { | ||
| // Reset the remap state | ||
| it->second.isShortcutInvoked = false; | ||
| it->second.winKeyInvoked = ModifierKey::Disabled; | ||
| it->second.isOriginalActionKeyPressed = false; | ||
| } | ||
|
|
||
| // If app specific shortcut has finished invoking, reset the target application | ||
| if (activatedApp != KeyboardManagerConstants::NoActivatedApp) | ||
|
|
@@ -741,7 +777,10 @@ namespace KeyboardEventHandlers | |
| if (newRemapping.RemapToKey()) | ||
| { | ||
| DWORD to = std::get<0>(newRemapping.targetShortcut); | ||
| Helpers::SetModifierKeyEvents(from, it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); | ||
| if (!isAltRightKeyInvoked) | ||
| { | ||
| Helpers::SetModifierKeyEvents(from, it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); | ||
| } | ||
| if (ii.GetVirtualKeyState(static_cast<WORD>(from.actionKey))) | ||
| { | ||
| // If the action key from the last shortcut is still being pressed, release it. | ||
|
|
@@ -752,13 +791,19 @@ namespace KeyboardEventHandlers | |
| else | ||
| { | ||
| Shortcut to = std::get<Shortcut>(newRemapping.targetShortcut); | ||
| Helpers::SetModifierKeyEvents(from, it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, to); | ||
| if (!isAltRightKeyInvoked) | ||
| { | ||
| Helpers::SetModifierKeyEvents(from, it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, to); | ||
| } | ||
| if (ii.GetVirtualKeyState(static_cast<WORD>(from.actionKey))) | ||
| { | ||
| // If the action key from the last shortcut is still being pressed, release it. | ||
| Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast<WORD>(from.actionKey), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); | ||
| } | ||
| Helpers::SetModifierKeyEvents(to, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, from); | ||
| if (!isAltRightKeyInvoked) | ||
| { | ||
| Helpers::SetModifierKeyEvents(to, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, from); | ||
| } | ||
| Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast<WORD>(to.actionKey), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); | ||
| newRemapping.isShortcutInvoked = true; | ||
| } | ||
|
|
@@ -783,10 +828,13 @@ namespace KeyboardEventHandlers | |
| { | ||
| Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast<WORD>(std::get<Shortcut>(it->second.targetShortcut).GetActionKey()), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); | ||
| } | ||
| Helpers::SetModifierKeyEvents(std::get<Shortcut>(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first); | ||
| if (!isAltRightKeyInvoked) | ||
| { | ||
| Helpers::SetModifierKeyEvents(std::get<Shortcut>(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first); | ||
|
|
||
| // Set old shortcut key down state | ||
| Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get<Shortcut>(it->second.targetShortcut)); | ||
| // Set old shortcut key down state | ||
| Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get<Shortcut>(it->second.targetShortcut)); | ||
| } | ||
|
|
||
| // key down for original shortcut action key with shortcut flag so that we don't invoke the same shortcut remap again | ||
| if (isActionKeyPressed) | ||
|
|
@@ -800,10 +848,13 @@ namespace KeyboardEventHandlers | |
| // Do not send a dummy key as we want the current key press to behave as normal i.e. it can do press+release functionality if required. Required to allow a shortcut to Win key remap invoked directly after shortcut to shortcut is released to open start menu | ||
| } | ||
|
|
||
| // Reset the remap state | ||
| it->second.isShortcutInvoked = false; | ||
| it->second.winKeyInvoked = ModifierKey::Disabled; | ||
| it->second.isOriginalActionKeyPressed = false; | ||
| if (!isAltRightKeyInvoked) | ||
| { | ||
| // Reset the remap state | ||
| it->second.isShortcutInvoked = false; | ||
| it->second.winKeyInvoked = ModifierKey::Disabled; | ||
| it->second.isOriginalActionKeyPressed = false; | ||
| } | ||
|
|
||
| // If app specific shortcut has finished invoking, reset the target application | ||
| if (activatedApp) | ||
|
|
@@ -848,8 +899,11 @@ namespace KeyboardEventHandlers | |
| { | ||
| std::vector<INPUT> keyEventList; | ||
|
|
||
| // Set original shortcut key down state | ||
| Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); | ||
| if (!isAltRightKeyInvoked) | ||
| { | ||
| // Set original shortcut key down state | ||
| Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); | ||
| } | ||
|
|
||
| // Send the original action key only if it is physically pressed. For remappings to keys other than disabled we already check earlier that it is not pressed in this scenario. For remap to disable | ||
| if (isRemapToDisable && isOriginalActionKeyPressed) | ||
|
|
@@ -863,10 +917,13 @@ namespace KeyboardEventHandlers | |
|
|
||
| // Do not send a dummy key as we want the current key press to behave as normal i.e. it can do press+release functionality if required. Required to allow a shortcut to Win key remap invoked directly after another shortcut to key remap is released to open start menu | ||
|
|
||
| // Reset the remap state | ||
| it->second.isShortcutInvoked = false; | ||
| it->second.winKeyInvoked = ModifierKey::Disabled; | ||
| it->second.isOriginalActionKeyPressed = false; | ||
| if (!isAltRightKeyInvoked) | ||
| { | ||
| // Reset the remap state | ||
| it->second.isShortcutInvoked = false; | ||
| it->second.winKeyInvoked = ModifierKey::Disabled; | ||
| it->second.isOriginalActionKeyPressed = false; | ||
| } | ||
|
|
||
| // If app specific shortcut has finished invoking, reset the target application | ||
| if (activatedApp != KeyboardManagerConstants::NoActivatedApp) | ||
|
|
||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why static?