| 2531 | /////////////////////// |
| 2532 | |
| 2533 | void PutKeybdEventIntoArray(modLR_type aKeyAsModifiersLR, vk_type aVK, sc_type aSC, DWORD aEventFlags, DWORD aExtraInfo) |
| 2534 | // This function is designed to be called from only one thread (the main thread) since it's not thread-safe. |
| 2535 | // Playback hook only supports sending neutral modifiers. Caller must ensure that any left/right modifiers |
| 2536 | // such as VK_RCONTROL are translated into neutral (e.g. VK_CONTROL). |
| 2537 | { |
| 2538 | bool key_up = aEventFlags & KEYEVENTF_KEYUP; |
| 2539 | // To make the SendPlay method identical in output to the other keystroke methods, have it generate |
| 2540 | // a leading down/up LControl event immediately prior to each RAlt event (with no key-delay). |
| 2541 | // This avoids having to add special handling to places like SetModifierLRState() to do AltGr things |
| 2542 | // differently when sending via playback vs. other methods. The event order recorded by the journal |
| 2543 | // record hook is a little different than what the low-level keyboard hook sees, but I don't think |
| 2544 | // the order should matter in this case: |
| 2545 | // sc vk key msg |
| 2546 | // 138 12 Alt syskeydown (right vs. left scan code) |
| 2547 | // 01d 11 Ctrl keydown (left scan code) <-- In keyboard hook, normally this precedes Alt, not follows it. Seems inconsequential (testing confirms). |
| 2548 | // 01d 11 Ctrl keyup (left scan code) |
| 2549 | // 138 12 Alt syskeyup (right vs. left scan code) |
| 2550 | // Check for VK_MENU not VK_RMENU because caller should have translated it to neutral: |
| 2551 | if (aVK == VK_MENU && aSC == SC_RALT && sTargetLayoutHasAltGr == CONDITION_TRUE && sSendMode == SM_PLAY) |
| 2552 | // Must pass VK_CONTROL rather than VK_LCONTROL because playback hook requires neutral modifiers. |
| 2553 | PutKeybdEventIntoArray(MOD_LCONTROL, VK_CONTROL, SC_LCONTROL, aEventFlags, aExtraInfo); // Recursive call to self. |
| 2554 | |
| 2555 | // Above must be done prior to the capacity check below because above might add a new array item. |
| 2556 | if (sEventCount == sMaxEvents) // Array's capacity needs expanding. |
| 2557 | if (!ExpandEventArray()) |
| 2558 | return; |
| 2559 | |
| 2560 | // Keep track of the predicted modifier state for use in other places: |
| 2561 | if (key_up) |
| 2562 | sEventModifiersLR &= ~aKeyAsModifiersLR; |
| 2563 | else |
| 2564 | sEventModifiersLR |= aKeyAsModifiersLR; |
| 2565 | |
| 2566 | if (sSendMode == SM_INPUT) |
| 2567 | { |
| 2568 | INPUT &this_event = sEventSI[sEventCount]; // For performance and convenience. |
| 2569 | this_event.type = INPUT_KEYBOARD; |
| 2570 | this_event.ki.wVk = aVK; |
| 2571 | this_event.ki.wScan = (aEventFlags & KEYEVENTF_UNICODE) ? aSC : LOBYTE(aSC); |
| 2572 | this_event.ki.dwFlags = aEventFlags; |
| 2573 | this_event.ki.dwExtraInfo = aExtraInfo; // Although our hook won't be installed (or won't detect, in the case of playback), that of other scripts might be, so set this for them. |
| 2574 | this_event.ki.time = 0; // Let the system provide its own timestamp, which might be more accurate for individual events if this will be a very long SendInput. |
| 2575 | sHooksToRemoveDuringSendInput |= HOOK_KEYBD; // Presence of keyboard hook defeats uninterruptibility of keystrokes. |
| 2576 | } |
| 2577 | else // Playback hook. |
| 2578 | { |
| 2579 | PlaybackEvent &this_event = sEventPB[sEventCount]; // For performance and convenience. |
| 2580 | if (!(aVK || aSC)) // Caller is signaling that aExtraInfo contains a delay/sleep event. |
| 2581 | { |
| 2582 | // Although delays at the tail end of the playback array can't be implemented by the playback |
| 2583 | // itself, caller wants them put in too. |
| 2584 | this_event.message = 0; // Message number zero flags it as a delay rather than an actual event. |
| 2585 | this_event.time_to_wait = aExtraInfo; |
| 2586 | } |
| 2587 | else // A normal (non-delay) event for playback. |
| 2588 | { |
| 2589 | // By monitoring incoming events in a message/event loop, the following key combinations were |
| 2590 | // confirmed to be WM_SYSKEYDOWN vs. WM_KEYDOWN (up events weren't tested, so are assumed to |
no test coverage detected