| 387 | } |
| 388 | |
| 389 | void reshade::input::next_frame() |
| 390 | { |
| 391 | static const auto GetKeyState_trampoline = reshade::hooks::is_hooked(GetKeyState) ? reshade::hooks::call(HookGetKeyState, GetKeyState) : GetKeyState; |
| 392 | static const auto GetAsyncKeyState_trampoline = reshade::hooks::is_hooked(GetAsyncKeyState) ? reshade::hooks::call(HookGetAsyncKeyState, GetAsyncKeyState) : GetAsyncKeyState; |
| 393 | |
| 394 | _frame_count++; |
| 395 | |
| 396 | // Backup key states from the last processed frame so that state transitions can be identified |
| 397 | std::copy_n(_keys, 256, _last_keys); |
| 398 | |
| 399 | for (uint8_t &state : _keys) |
| 400 | state &= ~0x08; |
| 401 | |
| 402 | // Reset any pressed down key states (apart from mouse buttons) that have not been updated for more than 5 seconds |
| 403 | // Do not check mouse buttons here, since 'GetAsyncKeyState' always returns the state of the physical mouse buttons, not the logical ones in case they were remapped |
| 404 | // See https://docs.microsoft.com/windows/win32/api/winuser/nf-winuser-getasynckeystate |
| 405 | // And time is not tracked for mouse buttons anyway |
| 406 | const DWORD time = GetTickCount(); |
| 407 | for (unsigned int i = 8; i < 256; ++i) |
| 408 | if ((_keys[i] & 0x80) != 0 && |
| 409 | (time - _keys_time[i]) > 5000 && |
| 410 | (GetAsyncKeyState_trampoline(i) & 0x8000) == 0) |
| 411 | (_keys[i] = 0x08); |
| 412 | |
| 413 | _text_input.clear(); |
| 414 | _mouse_wheel_delta = 0; |
| 415 | _last_mouse_position[0] = _mouse_position[0]; |
| 416 | _last_mouse_position[1] = _mouse_position[1]; |
| 417 | |
| 418 | // Update caps lock state |
| 419 | _keys[VK_CAPITAL] |= GetKeyState_trampoline(VK_CAPITAL) & 0x1; |
| 420 | |
| 421 | // Update modifier key state |
| 422 | if ((_keys[VK_MENU] & 0x88) != 0 && |
| 423 | (GetKeyState_trampoline(VK_MENU) & 0x8000) == 0) |
| 424 | (_keys[VK_MENU] = 0x08); |
| 425 | |
| 426 | // Update print screen state (there is no key down message, but the key up one is received via the message queue) |
| 427 | if ((_keys[VK_SNAPSHOT] & 0x80) == 0 && |
| 428 | (GetAsyncKeyState_trampoline(VK_SNAPSHOT) & 0x8000) != 0) |
| 429 | (_keys[VK_SNAPSHOT] = 0x88), |
| 430 | (_keys_time[VK_SNAPSHOT] = time); |
| 431 | |
| 432 | // Run through all forms of input blocking for all windows and establish whether any of them are blocking input |
| 433 | const std::shared_lock<std::shared_mutex> lock(s_windows_mutex); |
| 434 | |
| 435 | s_block_mouse.store(std::any_of(s_windows.cbegin(), s_windows.cend(), |
| 436 | [](const std::pair<HWND, std::weak_ptr<reshade::input>> &input_window) { |
| 437 | return !input_window.second.expired() && input_window.second.lock()->is_blocking_mouse_input(); |
| 438 | })); |
| 439 | s_block_keyboard.store(std::any_of(s_windows.cbegin(), s_windows.cend(), |
| 440 | [](const std::pair<HWND, std::weak_ptr<reshade::input>> &input_window) { |
| 441 | return !input_window.second.expired() && input_window.second.lock()->is_blocking_keyboard_input(); |
| 442 | })); |
| 443 | s_block_cursor_warping.store(std::any_of(s_windows.cbegin(), s_windows.cend(), |
| 444 | [](const std::pair<HWND, std::weak_ptr<reshade::input>> &input_window) { |
| 445 | return !input_window.second.expired() && input_window.second.lock()->is_blocking_mouse_cursor_warping(); |
| 446 | })); |
no test coverage detected