diff --git a/build_scripts/qt/sources.pri b/build_scripts/qt/sources.pri index 7866f56..6c4e49e 100644 --- a/build_scripts/qt/sources.pri +++ b/build_scripts/qt/sources.pri @@ -47,11 +47,13 @@ HEADERS += src/overlaycontroller.h \ src/utils/setup.h \ src/utils/paths.h \ src/openvr/overlay_utils.h \ - src/keyboard_input/input_parser.h + src/keyboard_input/input_parser.h \ + src/keyboard_input/input_sender.h win32 { SOURCES += src/tabcontrollers/audiomanager/AudioManagerWindows.cpp \ - src/tabcontrollers/keyboardinput/KeyboardInputWindows.cpp + src/tabcontrollers/keyboardinput/KeyboardInputWindows.cpp \ + src/keyboard_input/input_sender_win.cpp HEADERS += src/tabcontrollers/audiomanager/AudioManagerWindows.h } diff --git a/src/keyboard_input/input_parser.cpp b/src/keyboard_input/input_parser.cpp index c984d2c..83789fa 100644 --- a/src/keyboard_input/input_parser.cpp +++ b/src/keyboard_input/input_parser.cpp @@ -289,10 +289,101 @@ std::vector = removeTokenInSameSequence( ctrlRemoved, Token::MODIFIER_ALT ); const auto shiftRemoved = removeTokenInSameSequence( altRemoved, Token::MODIFIER_SHIFT ); - const auto altgrRemoved - = removeTokenInSameSequence( shiftRemoved, Token::MODIFIER_ALTGR ); const auto superRemoved - = removeTokenInSameSequence( altgrRemoved, Token::MODIFIER_SUPER ); + = removeTokenInSameSequence( shiftRemoved, Token::MODIFIER_SUPER ); return superRemoved; } + +bool isModifier( const Token token ) noexcept +{ + switch ( token ) + { + case Token::MODIFIER_CTRL: + [[fallthrough]]; + case Token::MODIFIER_ALT: + [[fallthrough]]; + case Token::MODIFIER_SHIFT: + [[fallthrough]]; + case Token::MODIFIER_SUPER: + return true; + default: + return false; + } +} + +bool isLiteral( const Token token ) noexcept +{ + if ( isalnum( static_cast( token ) ) ) + { + return true; + } + + switch ( token ) + { + case Token::KEY_F1: + return true; + case Token::KEY_F2: + return true; + case Token::KEY_F3: + return true; + case Token::KEY_F4: + return true; + case Token::KEY_F5: + return true; + case Token::KEY_F6: + return true; + case Token::KEY_F7: + return true; + case Token::KEY_F8: + return true; + case Token::KEY_F9: + return true; + + case Token::KEY_BACKSPACE: + return true; + case Token::KEY_SPACE: + return true; + case Token::KEY_TAB: + return true; + case Token::KEY_ESC: + return true; + case Token::KEY_INS: + return true; + case Token::KEY_DEL: + return true; + case Token::KEY_END: + return true; + case Token::KEY_PGDN: + return true; + case Token::KEY_PGUP: + return true; + case Token::KEY_CAPS: + return true; + case Token::KEY_PRNSCRN: + return true; + case Token::KEY_PAUSE: + return true; + case Token::KEY_SCRLOCK: + return true; + case Token::KEY_LEFTARROW: + return true; + case Token::KEY_RIGHTARROW: + return true; + case Token::KEY_UPARROW: + return true; + case Token::KEY_DOWNARROW: + return true; + case Token::KEY_KPSLASH: + return true; + case Token::KEY_KPSTAR: + return true; + case Token::KEY_KPMINUS: + return true; + case Token::KEY_KPPLUS: + return true; + + default: + return false; + } +} diff --git a/src/keyboard_input/input_parser.h b/src/keyboard_input/input_parser.h index 5c62f20..672c880 100644 --- a/src/keyboard_input/input_parser.h +++ b/src/keyboard_input/input_parser.h @@ -91,3 +91,6 @@ std::vector ParseKeyboardInputsToTokens( const std::string inputs ) noexcept; std::vector removeIncorrectTokens( const std::vector& tokens ) noexcept; + +bool isModifier( const Token token ) noexcept; +bool isLiteral( const Token token ) noexcept; diff --git a/src/keyboard_input/input_sender.h b/src/keyboard_input/input_sender.h new file mode 100644 index 0000000..de851ca --- /dev/null +++ b/src/keyboard_input/input_sender.h @@ -0,0 +1,11 @@ +#pragma once +#include "input_parser.h" +#include + +enum class KeyStatus +{ + Up, + Down, +}; + +void sendTokensAsInput( const std::vector tokens ); diff --git a/src/keyboard_input/input_sender_win.cpp b/src/keyboard_input/input_sender_win.cpp new file mode 100644 index 0000000..4d58eff --- /dev/null +++ b/src/keyboard_input/input_sender_win.cpp @@ -0,0 +1,181 @@ +#include "input_sender.h" +#include +#include +#include + +WORD convertToVirtualKeycode( const Token token ) +{ + if ( isalnum( static_cast( token ) ) ) + { + return static_cast( VkKeyScan( static_cast( token ) ) ); + } + + switch ( token ) + { + case Token::KEY_F1: + return VK_F1; + case Token::KEY_F2: + return VK_F2; + case Token::KEY_F3: + return VK_F3; + case Token::KEY_F4: + return VK_F4; + case Token::KEY_F5: + return VK_F5; + case Token::KEY_F6: + return VK_F6; + case Token::KEY_F7: + return VK_F7; + case Token::KEY_F8: + return VK_F8; + case Token::KEY_F9: + return VK_F9; + + case Token::KEY_BACKSPACE: + return VK_BACK; + case Token::KEY_SPACE: + return VK_SPACE; + case Token::KEY_TAB: + return VK_TAB; + case Token::KEY_ESC: + return VK_ESCAPE; + case Token::KEY_INS: + return VK_INSERT; + case Token::KEY_DEL: + return VK_DELETE; + case Token::KEY_END: + return VK_END; + case Token::KEY_PGDN: + return VK_NEXT; + case Token::KEY_PGUP: + return VK_PRIOR; + case Token::KEY_CAPS: + return VK_CAPITAL; + case Token::KEY_PRNSCRN: + return VK_SNAPSHOT; + case Token::KEY_PAUSE: + return VK_PAUSE; + case Token::KEY_SCRLOCK: + return VK_SCROLL; + case Token::KEY_LEFTARROW: + return VK_LEFT; + case Token::KEY_RIGHTARROW: + return VK_RIGHT; + case Token::KEY_UPARROW: + return VK_UP; + case Token::KEY_DOWNARROW: + return VK_DOWN; + case Token::KEY_KPSLASH: + return VK_DIVIDE; + case Token::KEY_KPSTAR: + return VK_MULTIPLY; + case Token::KEY_KPMINUS: + return VK_SUBTRACT; + case Token::KEY_KPPLUS: + return VK_ADD; + + case Token::MODIFIER_CTRL: + return VK_CONTROL; + case Token::MODIFIER_ALT: + return VK_MENU; + case Token::MODIFIER_SHIFT: + return VK_SHIFT; + case Token::MODIFIER_SUPER: + return VK_LWIN; + + default: + // LOG incorrect symbol + return 0; + } +} + +INPUT createInputStruct( const WORD virtualKeyCode, + const KeyStatus keyStatus ) noexcept +{ + INPUT input = {}; + + input.type = INPUT_KEYBOARD; + + input.ki.wVk = virtualKeyCode; + + if ( keyStatus == KeyStatus::Up ) + { + input.ki.dwFlags = KEYEVENTF_KEYUP; + } + else if ( keyStatus == KeyStatus::Down ) + { + input.ki.dwFlags = 0; + } + + return input; +} + +void sendKeyboardInputRaw( std::vector inputs ) +{ + const auto success = SendInput( static_cast( inputs.size() ), + inputs.data(), + sizeof( INPUT ) ); + + if ( ( inputs.size() > 0 ) && !success ) + { + char* err; + auto errCode = GetLastError(); + if ( !FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER + | FORMAT_MESSAGE_FROM_SYSTEM, + nullptr, + errCode, + MAKELANGID( LANG_NEUTRAL, + SUBLANG_DEFAULT ), // default language + reinterpret_cast( &err ), + 0, + nullptr ) ) + { + LOG( ERROR ) + << "Error calling SendInput(): Could not get error message (" + << errCode << ")"; + } + else + { + LOG( ERROR ) << "Error calling SendInput(): " << err; + } + } +} + +void sendTokenAsInput( const std::vector tokens ) +{ + std::vector inputs = {}; + std::vector heldInputs = {}; + for ( const auto& token : tokens ) + { + if ( isModifier( token ) ) + { + inputs.push_back( createInputStruct( + convertToVirtualKeycode( token ), KeyStatus::Down ) ); + heldInputs.push_back( token ); + continue; + } + + if ( token == Token::TOKEN_NEW_SEQUENCE ) + { + for ( const auto& h : heldInputs ) + { + inputs.push_back( createInputStruct( + convertToVirtualKeycode( h ), KeyStatus::Up ) ); + } + heldInputs.clear(); + continue; + } + + if ( isLiteral( token ) ) + { + inputs.push_back( createInputStruct( + convertToVirtualKeycode( token ), KeyStatus::Down ) ); + inputs.push_back( createInputStruct( + convertToVirtualKeycode( token ), KeyStatus::Up ) ); + continue; + } + } + + sendKeyboardInputRaw( inputs ); + // send inputs +}