| 3499 | |
| 3500 | |
| 3501 | modLR_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 |
no test coverage detected