| 649 | |
| 650 | |
| 651 | void UpdateKeyState(KBDLLHOOKSTRUCT &event, vk_type vk, sc_type sc, bool key_up, bool aIsSuppressed) |
| 652 | // Always use the parameter vk rather than event.vkCode because the caller or caller's caller |
| 653 | // might have adjusted vk, namely to make it a left/right specific modifier key rather than a |
| 654 | // neutral one. |
| 655 | { |
| 656 | // See above notes near the first mention of SHIFT_KEY_WORKAROUND_TIMEOUT for details. |
| 657 | // This part of the workaround can be tested via "NumpadEnd::KeyHistory". Turn on numlock, |
| 658 | // hold down shift, and press numpad1. The hotkey will fire and the status should display |
| 659 | // that the shift key is physically, but not logically down at that exact moment: |
| 660 | if (prior_event_was_physical && (prior_vk == VK_LSHIFT || prior_vk == VK_SHIFT) // But not RSHIFT. |
| 661 | && (DWORD)(GetTickCount() - prior_event_tickcount) < (DWORD)SHIFT_KEY_WORKAROUND_TIMEOUT) |
| 662 | { |
| 663 | bool current_is_dual_state = IsDualStateNumpadKey(vk, sc); |
| 664 | // Verified: Both down and up events for the *current* (not prior) key qualify for this: |
| 665 | bool fix_it = (!prior_event_was_key_up && DualStateNumpadKeyIsDown()) // Case #4 of the workaround. |
| 666 | || (prior_event_was_key_up && key_up && current_is_dual_state); // Case #5 |
| 667 | if (fix_it) |
| 668 | next_phys_shift_down_is_not_phys = true; |
| 669 | // In the first case, both the numpad key-up and down events are eligible: |
| 670 | if ( fix_it || (prior_event_was_key_up && current_is_dual_state) ) |
| 671 | { |
| 672 | // Since the prior event (the shift key) already happened (took effect) and since only |
| 673 | // now is it known that it shouldn't have been physical, undo the effects of it having |
| 674 | // been physical: |
| 675 | g_modifiersLR_physical = prior_modifiersLR_physical; |
| 676 | g_PhysicalKeyState[VK_SHIFT] = prior_shift_state; |
| 677 | g_PhysicalKeyState[VK_LSHIFT] = prior_lshift_state; |
| 678 | } |
| 679 | } |
| 680 | |
| 681 | |
| 682 | // Must do this part prior to UpdateModifierState() because we want to store the values |
| 683 | // as they are prior to the potentially-erroneously-physical shift key event takes effect. |
| 684 | // The state of these is also saved because we can't assume that a shift-down, for |
| 685 | // example, CHANGED the state to down, because it may have been already down before that: |
| 686 | prior_modifiersLR_physical = g_modifiersLR_physical; |
| 687 | prior_shift_state = g_PhysicalKeyState[VK_SHIFT]; |
| 688 | prior_lshift_state = g_PhysicalKeyState[VK_LSHIFT]; |
| 689 | |
| 690 | // If this function was called from SuppressThisKey(), these comments apply: |
| 691 | // Currently SuppressThisKey is only called with a modifier in the rare case |
| 692 | // when disguise_next_lwin/rwin_up is in effect. But there may be other cases in the |
| 693 | // future, so we need to make sure the physical state of the modifiers is updated |
| 694 | // in our tracking system even though the key is being suppressed: |
| 695 | if (kvk[vk].as_modifiersLR) |
| 696 | UpdateModifierState(event, vk, sc, key_up, aIsSuppressed); // Update our tracking of LWIN/RWIN/RSHIFT etc. |
| 697 | |
| 698 | // Now that we're done using the old values (the above used them and also UpdateModifierState()'s |
| 699 | // calls to EventIsPhysical()), update these to their new values: |
| 700 | prior_vk = vk; |
| 701 | prior_sc = sc; |
| 702 | prior_event_was_key_up = key_up; |
| 703 | prior_event_was_physical = EventIsPhysical(event, vk, sc, key_up); |
| 704 | prior_event_tickcount = GetTickCount(); |
| 705 | } |
| 706 | #endif // Keyboard hook |
| 707 | |
| 708 |
no test coverage detected