MCPcopy Create free account
hub / github.com/AutoHotkey/AutoHotkey / GetModifierLRState

Function GetModifierLRState

source/keyboard_mouse.cpp:3501–3592  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

3499
3500
3501modLR_type GetModifierLRState(bool aExplicitlyGet)
3502// Try to report a more reliable state of the modifier keys than GetKeyboardState alone could.
3503// Fix for v1.0.42.01: On Windows 2000/XP or later, GetAsyncKeyState() should be called rather than
3504// GetKeyState(). This is because our callers always want the current state of the modifier keys
3505// rather than their state at the time of the currently-in-process message was posted. For example,
3506// if the control key wasn't down at the time our thread's current message was posted, but it's logically
3507// down according to the system, we would want to release that control key before sending non-control
3508// keystrokes, even if one of our thread's own windows has keyboard focus (because if it does, the
3509// control-up keystroke should wind up getting processed after our thread realizes control is down).
3510// This applies even when the keyboard/mouse hook call use because keystrokes routed to the hook via
3511// the hook's message pump aren't messages per se, and thus GetKeyState and GetAsyncKeyState probably
3512// return the exact same thing whenever there are no messages in the hook's thread-queue (which is almost
3513// always the case).
3514{
3515 // If the hook is active, rely only on its tracked value rather than calling Get():
3516 if (g_KeybdHook && !aExplicitlyGet)
3517 return g_modifiersLR_logical;
3518
3519 // Very old comment:
3520 // Use GetKeyState() rather than GetKeyboardState() because it's the only way to get
3521 // accurate key state when a console window is active, it seems. I've also seen other
3522 // cases where GetKeyboardState() is incorrect (at least under WinXP) when GetKeyState(),
3523 // in its place, yields the correct info. Very strange.
3524
3525 modLR_type modifiersLR = 0; // Allows all to default to up/off to simplify the below.
3526 if (IsKeyDownAsync(VK_LSHIFT)) modifiersLR |= MOD_LSHIFT;
3527 if (IsKeyDownAsync(VK_RSHIFT)) modifiersLR |= MOD_RSHIFT;
3528 if (IsKeyDownAsync(VK_LCONTROL)) modifiersLR |= MOD_LCONTROL;
3529 if (IsKeyDownAsync(VK_RCONTROL)) modifiersLR |= MOD_RCONTROL;
3530 if (IsKeyDownAsync(VK_LMENU)) modifiersLR |= MOD_LALT;
3531 if (IsKeyDownAsync(VK_RMENU)) modifiersLR |= MOD_RALT;
3532 if (IsKeyDownAsync(VK_LWIN)) modifiersLR |= MOD_LWIN;
3533 if (IsKeyDownAsync(VK_RWIN)) modifiersLR |= MOD_RWIN;
3534
3535 // Thread-safe: The following section isn't thread-safe because either the hook thread
3536 // or the main thread can be calling it. However, given that anything dealing with
3537 // keystrokes isn't thread-safe in the sense that keystrokes can be coming in simultaneously
3538 // from multiple sources, it seems acceptable to keep it this way (especially since
3539 // the consequences of a thread collision seem very mild in this case).
3540 if (g_KeybdHook)
3541 {
3542 // Since hook is installed, fix any modifiers that it incorrectly thinks are down.
3543 // Though rare, this situation does arise during periods when the hook cannot track
3544 // the user's keystrokes, such as when the OS is doing something with the hardware,
3545 // e.g. switching to TV-out or changing video resolutions. There are probably other
3546 // situations where this happens -- never fully explored and identified -- so it
3547 // seems best to do this, at least when the caller specified aExplicitlyGet = true.
3548 // To limit the scope of this workaround, only change the state of the hook modifiers
3549 // to be "up" for those keys the hook thinks are logically down but which the OS thinks
3550 // are logically up. Note that it IS possible for a key to be physically down without
3551 // being logically down (i.e. during a Send command where the user is physically holding
3552 // down a modifier, but the Send command needs to put it up temporarily), so do not
3553 // change the hook's physical state for such keys in that case.
3554 // UPDATE: The following adjustment is now also relied upon by the SendInput method
3555 // to correct physical modifier state during periods when the hook was temporarily removed
3556 // to allow a SendInput to be uninterruptible.
3557 // UPDATE: The modifier state might also become incorrect due to keyboard events which
3558 // are missed due to User Interface Privelege Isolation; i.e. because a window belonging

Callers 9

ListKeyHistoryMethod · 0.85
SendUnicodeCharFunction · 0.85
SendKeysFunction · 0.85
SendKeyFunction · 0.85
SendASCFunction · 0.85
SendEventArrayFunction · 0.85
ScriptGetKeyStateFunction · 0.85
LowLevelCommonFunction · 0.85
ResetHookFunction · 0.85

Calls 1

AdjustKeyStateFunction · 0.85

Tested by

no test coverage detected