Fix keyboard input implementation error and replace old system
This commit is contained in:
@@ -12,12 +12,12 @@ SOURCES += src/main.cpp\
|
|||||||
src/tabcontrollers/PttController.cpp \
|
src/tabcontrollers/PttController.cpp \
|
||||||
src/tabcontrollers/VideoTabController.cpp \
|
src/tabcontrollers/VideoTabController.cpp \
|
||||||
src/utils/ChaperoneUtils.cpp \
|
src/utils/ChaperoneUtils.cpp \
|
||||||
src/tabcontrollers/audiomanager/AudioManagerDummy.cpp \
|
|
||||||
src/openvr/openvr_init.cpp \
|
src/openvr/openvr_init.cpp \
|
||||||
src/openvr/ivrinput.cpp \
|
src/openvr/ivrinput.cpp \
|
||||||
src/utils/setup.cpp \
|
src/utils/setup.cpp \
|
||||||
src/utils/paths.cpp \
|
src/utils/paths.cpp \
|
||||||
src/openvr/overlay_utils.cpp \
|
src/openvr/overlay_utils.cpp \
|
||||||
|
src/tabcontrollers/keyboardinput/KeyboardInput.cpp \
|
||||||
src/keyboard_input/input_parser.cpp
|
src/keyboard_input/input_parser.cpp
|
||||||
|
|
||||||
HEADERS += src/overlaycontroller.h \
|
HEADERS += src/overlaycontroller.h \
|
||||||
@@ -52,15 +52,13 @@ HEADERS += src/overlaycontroller.h \
|
|||||||
|
|
||||||
win32 {
|
win32 {
|
||||||
SOURCES += src/tabcontrollers/audiomanager/AudioManagerWindows.cpp \
|
SOURCES += src/tabcontrollers/audiomanager/AudioManagerWindows.cpp \
|
||||||
src/tabcontrollers/keyboardinput/KeyboardInputWindows.cpp \
|
|
||||||
src/keyboard_input/input_sender_win.cpp
|
src/keyboard_input/input_sender_win.cpp
|
||||||
HEADERS += src/tabcontrollers/audiomanager/AudioManagerWindows.h
|
HEADERS += src/tabcontrollers/audiomanager/AudioManagerWindows.h
|
||||||
}
|
}
|
||||||
|
|
||||||
unix:!macx {
|
unix:!macx {
|
||||||
!noX11 {
|
!noX11 {
|
||||||
SOURCES += src/tabcontrollers/keyboardinput/KeyboardInputX11.cpp \
|
SOURCES += src/keyboard_input/input_sender_X11.cpp
|
||||||
src/keyboard_input/input_sender_X11.cpp
|
|
||||||
CONFIG += x11
|
CONFIG += x11
|
||||||
LIBS += -lXtst
|
LIBS += -lXtst
|
||||||
}
|
}
|
||||||
@@ -70,7 +68,6 @@ unix:!macx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
macx {
|
macx {
|
||||||
SOURCES += src/tabcontrollers/keyboardinput/KeyboardInputDummy.cpp
|
|
||||||
}
|
}
|
||||||
|
|
||||||
win32-msvc {
|
win32-msvc {
|
||||||
|
|||||||
@@ -316,13 +316,74 @@ bool isModifier( const Token token ) noexcept
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isLiteralKey( const Token token ) noexcept
|
||||||
|
{
|
||||||
|
switch ( token )
|
||||||
|
{
|
||||||
|
case Token::KEY_a:
|
||||||
|
return true;
|
||||||
|
case Token::KEY_b:
|
||||||
|
return true;
|
||||||
|
case Token::KEY_c:
|
||||||
|
return true;
|
||||||
|
case Token::KEY_d:
|
||||||
|
return true;
|
||||||
|
case Token::KEY_e:
|
||||||
|
return true;
|
||||||
|
case Token::KEY_f:
|
||||||
|
return true;
|
||||||
|
case Token::KEY_g:
|
||||||
|
return true;
|
||||||
|
case Token::KEY_h:
|
||||||
|
return true;
|
||||||
|
case Token::KEY_i:
|
||||||
|
return true;
|
||||||
|
case Token::KEY_j:
|
||||||
|
return true;
|
||||||
|
case Token::KEY_k:
|
||||||
|
return true;
|
||||||
|
case Token::KEY_l:
|
||||||
|
return true;
|
||||||
|
case Token::KEY_m:
|
||||||
|
return true;
|
||||||
|
case Token::KEY_n:
|
||||||
|
return true;
|
||||||
|
case Token::KEY_o:
|
||||||
|
return true;
|
||||||
|
case Token::KEY_p:
|
||||||
|
return true;
|
||||||
|
case Token::KEY_q:
|
||||||
|
return true;
|
||||||
|
case Token::KEY_r:
|
||||||
|
return true;
|
||||||
|
case Token::KEY_s:
|
||||||
|
return true;
|
||||||
|
case Token::KEY_t:
|
||||||
|
return true;
|
||||||
|
case Token::KEY_u:
|
||||||
|
return true;
|
||||||
|
case Token::KEY_v:
|
||||||
|
return true;
|
||||||
|
case Token::KEY_w:
|
||||||
|
return true;
|
||||||
|
case Token::KEY_x:
|
||||||
|
return true;
|
||||||
|
case Token::KEY_y:
|
||||||
|
return true;
|
||||||
|
case Token::KEY_z:
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool isLiteral( const Token token ) noexcept
|
bool isLiteral( const Token token ) noexcept
|
||||||
{
|
{
|
||||||
if ( isalnum( static_cast<int>( token ) ) )
|
if ( isLiteralKey( token ) )
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ( token )
|
switch ( token )
|
||||||
{
|
{
|
||||||
case Token::KEY_F1:
|
case Token::KEY_F1:
|
||||||
|
|||||||
@@ -95,3 +95,4 @@ std::vector<Token>
|
|||||||
|
|
||||||
bool isModifier( const Token token ) noexcept;
|
bool isModifier( const Token token ) noexcept;
|
||||||
bool isLiteral( const Token token ) noexcept;
|
bool isLiteral( const Token token ) noexcept;
|
||||||
|
bool isLiteralKey( const Token token ) noexcept;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
unsigned int tokenToKeyCode( const Token token, Display* const display )
|
unsigned int tokenToKeyCode( const Token token, Display* const display )
|
||||||
{
|
{
|
||||||
if ( isalnum( static_cast<int>( token ) ) )
|
if ( isLiteralKey( token ) )
|
||||||
{
|
{
|
||||||
return XKeysymToKeycode( display, static_cast<KeySym>( token ) );
|
return XKeysymToKeycode( display, static_cast<KeySym>( token ) );
|
||||||
}
|
}
|
||||||
@@ -137,6 +137,14 @@ void sendTokensAsInput( const std::vector<Token> tokens )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( !heldInputs.empty() )
|
||||||
|
{
|
||||||
|
for ( const auto& h : heldInputs )
|
||||||
|
{
|
||||||
|
sendKeyPress( h, KeyStatus::Up, display );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
XSync( display, False );
|
XSync( display, False );
|
||||||
XTestGrabControl( display, False );
|
XTestGrabControl( display, False );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
WORD convertToVirtualKeycode( const Token token )
|
WORD convertToVirtualKeycode( const Token token )
|
||||||
{
|
{
|
||||||
if ( isalnum( static_cast<int>( token ) ) )
|
if ( isLiteralKey( token ) )
|
||||||
{
|
{
|
||||||
return static_cast<WORD>( VkKeyScan( static_cast<int>( token ) ) );
|
return static_cast<WORD>( VkKeyScan( static_cast<int>( token ) ) );
|
||||||
}
|
}
|
||||||
@@ -178,6 +178,15 @@ void sendTokensAsInput( const std::vector<Token> tokens )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( !heldInputs.empty() )
|
||||||
|
{
|
||||||
|
for ( const auto& h : heldInputs )
|
||||||
|
{
|
||||||
|
inputs.push_back( createInputStruct( convertToVirtualKeycode( h ),
|
||||||
|
KeyStatus::Up ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sendKeyboardInputRaw( inputs );
|
sendKeyboardInputRaw( inputs );
|
||||||
// send inputs
|
// send inputs
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
#include "KeyboardInput.h"
|
||||||
|
#include "src/keyboard_input/input_sender.h"
|
||||||
|
|
||||||
|
namespace keyboardinput
|
||||||
|
{
|
||||||
|
void sendKeyboardInput( QString input )
|
||||||
|
{
|
||||||
|
sendStringAsInput( input.toStdString() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendKeyboardEnter()
|
||||||
|
{
|
||||||
|
const auto tokens = std::vector<Token>{ Token::KEY_ENTER };
|
||||||
|
|
||||||
|
sendTokensAsInput( tokens );
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendKeyboardBackspace( const int count )
|
||||||
|
{
|
||||||
|
const auto tokens = std::vector<Token>{ Token::KEY_BACKSPACE };
|
||||||
|
for ( int i = 0; i < count; ++i )
|
||||||
|
{
|
||||||
|
sendTokensAsInput( tokens );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendKeyboardAltTab()
|
||||||
|
{
|
||||||
|
const auto tokens
|
||||||
|
= std::vector<Token>{ Token::MODIFIER_ALT, Token::KEY_TAB };
|
||||||
|
|
||||||
|
sendTokensAsInput( tokens );
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendKeyboardAltEnter()
|
||||||
|
{
|
||||||
|
const auto tokens
|
||||||
|
= std::vector<Token>{ Token::MODIFIER_ALT, Token::KEY_ENTER };
|
||||||
|
|
||||||
|
sendTokensAsInput( tokens );
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendKeyboardCtrlC()
|
||||||
|
{
|
||||||
|
const auto tokens
|
||||||
|
= std::vector<Token>{ Token::MODIFIER_CTRL, Token::KEY_c };
|
||||||
|
|
||||||
|
sendTokensAsInput( tokens );
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendKeyboardCtrlV()
|
||||||
|
{
|
||||||
|
const auto tokens
|
||||||
|
= std::vector<Token>{ Token::MODIFIER_CTRL, Token::KEY_v };
|
||||||
|
|
||||||
|
sendTokensAsInput( tokens );
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendMediaNextSong()
|
||||||
|
{
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendMediaPreviousSong()
|
||||||
|
{
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendMediaPausePlay()
|
||||||
|
{
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendMediaStopSong()
|
||||||
|
{
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace keyboardinput
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
#include "KeyboardInput.h"
|
|
||||||
|
|
||||||
// Used to get the compiler to shut up about C4100: unreferenced formal
|
|
||||||
// parameter. The cast is to get GCC to shut up about it.
|
|
||||||
#define UNREFERENCED_PARAMETER( P ) static_cast<void>( ( P ) )
|
|
||||||
|
|
||||||
namespace keyboardinput
|
|
||||||
{
|
|
||||||
void sendKeyboardInput( QString input )
|
|
||||||
{
|
|
||||||
// noop
|
|
||||||
UNREFERENCED_PARAMETER( input );
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendKeyboardEnter()
|
|
||||||
{
|
|
||||||
// noop
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendKeyboardBackspace( const int count )
|
|
||||||
{
|
|
||||||
// noop
|
|
||||||
UNREFERENCED_PARAMETER( count );
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendKeyboardAltTab()
|
|
||||||
{
|
|
||||||
// noop
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendKeyboardAltEnter()
|
|
||||||
{
|
|
||||||
// noop
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendKeyboardCtrlC()
|
|
||||||
{
|
|
||||||
// noop
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendKeyboardCtrlV()
|
|
||||||
{
|
|
||||||
// noop
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendMediaNextSong()
|
|
||||||
{
|
|
||||||
// noop
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendMediaPreviousSong()
|
|
||||||
{
|
|
||||||
// noop
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendMediaPausePlay()
|
|
||||||
{
|
|
||||||
// noop
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendMediaStopSong()
|
|
||||||
{
|
|
||||||
// noop
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace keyboardinput
|
|
||||||
@@ -1,344 +0,0 @@
|
|||||||
#include "KeyboardInput.h"
|
|
||||||
#include <Windows.h>
|
|
||||||
#include "easylogging++.h"
|
|
||||||
|
|
||||||
namespace keyboardinput
|
|
||||||
{
|
|
||||||
/*!
|
|
||||||
Fills out an INPUT struct ip with scanCode and keyup status.
|
|
||||||
*/
|
|
||||||
void fillKiStruct( INPUT& ip, WORD scanCode, bool keyup )
|
|
||||||
{
|
|
||||||
ip.type = INPUT_KEYBOARD;
|
|
||||||
ip.ki.wVk = scanCode;
|
|
||||||
if ( keyup )
|
|
||||||
{
|
|
||||||
ip.ki.dwFlags = KEYEVENTF_KEYUP;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ip.ki.dwFlags = 0;
|
|
||||||
}
|
|
||||||
ip.ki.wScan = 0;
|
|
||||||
ip.ki.dwExtraInfo = 0;
|
|
||||||
ip.ki.time = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Calls SendInput on an INPUT struct and has associated error handling.
|
|
||||||
|
|
||||||
inputCount can't be deduced from input because of implicit conversions from
|
|
||||||
arrays to pointers when passed as arguments.
|
|
||||||
*/
|
|
||||||
void sendKeyboardInputRaw( const int inputCount, const LPINPUT input )
|
|
||||||
{
|
|
||||||
const auto success
|
|
||||||
= SendInput( static_cast<UINT>( inputCount ), input, sizeof( INPUT ) );
|
|
||||||
|
|
||||||
if ( ( inputCount > 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<LPTSTR>( &err ),
|
|
||||||
0,
|
|
||||||
nullptr ) )
|
|
||||||
{
|
|
||||||
LOG( ERROR )
|
|
||||||
<< "Error calling SendInput(): Could not get error message ("
|
|
||||||
<< errCode << ")";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG( ERROR ) << "Error calling SendInput(): " << err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Returns an INPUT struct with the corresponding virtualKeyCode and keyStatus set.
|
|
||||||
|
|
||||||
All fields except ki.wVk and ki.dwFlags are zero.
|
|
||||||
The INPUT struct is used with the SendInput Windows function.
|
|
||||||
Official Docs:
|
|
||||||
https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-taginput
|
|
||||||
*/
|
|
||||||
INPUT createInputStruct( const WORD virtualKeyCode, const KeyStatus keyStatus )
|
|
||||||
{
|
|
||||||
// Zero init to ensure random data doesn't muck something up.
|
|
||||||
INPUT input = {};
|
|
||||||
|
|
||||||
input.type = INPUT_KEYBOARD;
|
|
||||||
|
|
||||||
input.ki.wVk = virtualKeyCode;
|
|
||||||
|
|
||||||
if ( keyStatus == KeyStatus::Up )
|
|
||||||
{
|
|
||||||
input.ki.dwFlags = KEYEVENTF_KEYUP;
|
|
||||||
}
|
|
||||||
else if ( keyStatus == KeyStatus::Down )
|
|
||||||
{
|
|
||||||
// Struct is already zero initialized, but this is here for clarity.
|
|
||||||
// Compiler will likely sort this out, otherwise the performance hit is
|
|
||||||
// negligible.
|
|
||||||
// There is no corresponding KEYDOWN event, you just don't
|
|
||||||
// set KEYEVENTF_KEYUP.
|
|
||||||
input.ki.dwFlags = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The sizeof(INPUT) on MSVC is 28. Returning by value is a non-issue
|
|
||||||
// compared to the simplicity of not having to pass a ref to an already
|
|
||||||
// existing INPUT struct, and possibly forgetting to zero it out.
|
|
||||||
return input;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Sends a key press to Windows. The virtualKeyCode is a Windows specific define
|
|
||||||
found in <windows.h>.
|
|
||||||
|
|
||||||
Virtual Key Codes offical docs:
|
|
||||||
https://docs.microsoft.com/en-us/windows/desktop/inputdev/virtual-key-codes
|
|
||||||
*/
|
|
||||||
void sendKeyPressAndRelease( const WORD virtualKeyCode )
|
|
||||||
{
|
|
||||||
const auto press = createInputStruct( virtualKeyCode, KeyStatus::Down );
|
|
||||||
const auto release = createInputStruct( virtualKeyCode, KeyStatus::Up );
|
|
||||||
|
|
||||||
constexpr auto numberOfActions = 2;
|
|
||||||
|
|
||||||
INPUT actions[numberOfActions] = { press, release };
|
|
||||||
|
|
||||||
sendKeyboardInputRaw( numberOfActions, actions );
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendKeyboardInput( QString input )
|
|
||||||
{
|
|
||||||
int len = input.length();
|
|
||||||
if ( len > 0 )
|
|
||||||
{
|
|
||||||
LPINPUT ips = new INPUT[static_cast<unsigned int>( len ) * 5 + 3];
|
|
||||||
int ii = 0;
|
|
||||||
bool shiftPressed = false;
|
|
||||||
bool ctrlPressed = false;
|
|
||||||
bool altPressed = false;
|
|
||||||
for ( int i = 0; i < len; i++ )
|
|
||||||
{
|
|
||||||
short tmp = VkKeyScan( input.at( i ).toLatin1() );
|
|
||||||
WORD c = tmp & 0xFF;
|
|
||||||
short shiftState = tmp >> 8;
|
|
||||||
bool isShift = shiftState & 1;
|
|
||||||
bool isCtrl = shiftState & 2;
|
|
||||||
bool isAlt = shiftState & 4;
|
|
||||||
if ( isShift && !shiftPressed )
|
|
||||||
{
|
|
||||||
fillKiStruct( ips[ii++], VK_SHIFT, false );
|
|
||||||
shiftPressed = true;
|
|
||||||
}
|
|
||||||
else if ( !isShift && shiftPressed )
|
|
||||||
{
|
|
||||||
fillKiStruct( ips[ii++], VK_SHIFT, true );
|
|
||||||
shiftPressed = false;
|
|
||||||
}
|
|
||||||
if ( isCtrl && !ctrlPressed )
|
|
||||||
{
|
|
||||||
fillKiStruct( ips[ii++], VK_CONTROL, false );
|
|
||||||
ctrlPressed = true;
|
|
||||||
}
|
|
||||||
else if ( !isCtrl && ctrlPressed )
|
|
||||||
{
|
|
||||||
fillKiStruct( ips[ii++], VK_CONTROL, true );
|
|
||||||
ctrlPressed = false;
|
|
||||||
}
|
|
||||||
if ( isAlt && !altPressed )
|
|
||||||
{
|
|
||||||
fillKiStruct( ips[ii++], VK_MENU, false );
|
|
||||||
altPressed = true;
|
|
||||||
}
|
|
||||||
else if ( !isAlt && altPressed )
|
|
||||||
{
|
|
||||||
fillKiStruct( ips[ii++], VK_MENU, true );
|
|
||||||
altPressed = false;
|
|
||||||
}
|
|
||||||
fillKiStruct( ips[ii++], c, false );
|
|
||||||
fillKiStruct( ips[ii++], c, true );
|
|
||||||
}
|
|
||||||
if ( shiftPressed )
|
|
||||||
{
|
|
||||||
fillKiStruct( ips[ii++], VK_SHIFT, true );
|
|
||||||
shiftPressed = false;
|
|
||||||
}
|
|
||||||
if ( ctrlPressed )
|
|
||||||
{
|
|
||||||
fillKiStruct( ips[ii++], VK_CONTROL, true );
|
|
||||||
ctrlPressed = false;
|
|
||||||
}
|
|
||||||
if ( altPressed )
|
|
||||||
{
|
|
||||||
fillKiStruct( ips[ii++], VK_MENU, true );
|
|
||||||
altPressed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
sendKeyboardInputRaw( ii, ips );
|
|
||||||
delete[] ips;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Sends a single Enter keypress to Windows.
|
|
||||||
*/
|
|
||||||
void sendKeyboardEnter()
|
|
||||||
{
|
|
||||||
sendKeyPressAndRelease( VK_RETURN );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Sends count amount of backspaces to Windows. count of 0 or below will do
|
|
||||||
nothing.
|
|
||||||
*/
|
|
||||||
void sendKeyboardBackspace( const int count )
|
|
||||||
{
|
|
||||||
// We can only send a positive amount of key presses.
|
|
||||||
if ( count <= 0 )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( int presses = 0; presses < count; ++presses )
|
|
||||||
{
|
|
||||||
sendKeyPressAndRelease( VK_BACK );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Sends an Alt + Tab combination to Windows.
|
|
||||||
|
|
||||||
Used for tabbing out of game windows blocking other programs on desktop while in
|
|
||||||
VR. At least one use case was tabbing out of a fullscreen game to be able to use
|
|
||||||
a music player.
|
|
||||||
*/
|
|
||||||
void sendKeyboardAltTab()
|
|
||||||
{
|
|
||||||
constexpr auto altKey = VK_MENU;
|
|
||||||
constexpr auto tabKey = VK_TAB;
|
|
||||||
|
|
||||||
const auto pressAlt = createInputStruct( altKey, KeyStatus::Down );
|
|
||||||
const auto pressTab = createInputStruct( tabKey, KeyStatus::Down );
|
|
||||||
const auto releaseAlt = createInputStruct( altKey, KeyStatus::Up );
|
|
||||||
const auto releaseTab = createInputStruct( tabKey, KeyStatus::Up );
|
|
||||||
|
|
||||||
constexpr auto numberOfActions = 4;
|
|
||||||
|
|
||||||
INPUT actions[numberOfActions]
|
|
||||||
= { pressAlt, pressTab, releaseAlt, releaseTab };
|
|
||||||
|
|
||||||
sendKeyboardInputRaw( numberOfActions, actions );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Sends an Alt + Tab combination to Windows.
|
|
||||||
|
|
||||||
Used for toggling full screen on games and various applications that appear on
|
|
||||||
the desktop.
|
|
||||||
*/
|
|
||||||
void sendKeyboardAltEnter()
|
|
||||||
{
|
|
||||||
constexpr auto altKey = VK_MENU;
|
|
||||||
constexpr auto enterKey = VK_RETURN;
|
|
||||||
|
|
||||||
const auto pressAlt = createInputStruct( altKey, KeyStatus::Down );
|
|
||||||
const auto pressEnter = createInputStruct( enterKey, KeyStatus::Down );
|
|
||||||
const auto releaseAlt = createInputStruct( altKey, KeyStatus::Up );
|
|
||||||
const auto releaseEnter = createInputStruct( enterKey, KeyStatus::Up );
|
|
||||||
|
|
||||||
constexpr auto numberOfActions = 4;
|
|
||||||
|
|
||||||
INPUT actions[numberOfActions]
|
|
||||||
= { pressAlt, pressEnter, releaseAlt, releaseEnter };
|
|
||||||
|
|
||||||
sendKeyboardInputRaw( numberOfActions, actions );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Sends a Ctrl + C combination to Windows.
|
|
||||||
|
|
||||||
Used for copy in copy-paste operations.
|
|
||||||
*/
|
|
||||||
void sendKeyboardCtrlC()
|
|
||||||
{
|
|
||||||
constexpr auto ctrlKey = VK_CONTROL;
|
|
||||||
constexpr auto cKey = 0x43;
|
|
||||||
|
|
||||||
const auto pressCtrl = createInputStruct( ctrlKey, KeyStatus::Down );
|
|
||||||
const auto pressC = createInputStruct( cKey, KeyStatus::Down );
|
|
||||||
const auto releaseC = createInputStruct( cKey, KeyStatus::Up );
|
|
||||||
const auto releaseCtrl = createInputStruct( ctrlKey, KeyStatus::Up );
|
|
||||||
|
|
||||||
constexpr auto numberOfActions = 4;
|
|
||||||
|
|
||||||
INPUT actions[numberOfActions]
|
|
||||||
= { pressCtrl, pressC, releaseC, releaseCtrl };
|
|
||||||
|
|
||||||
sendKeyboardInputRaw( numberOfActions, actions );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Sends a Ctrl + V combination to Windows.
|
|
||||||
|
|
||||||
Used for paste in copy-paste operations.
|
|
||||||
*/
|
|
||||||
void sendKeyboardCtrlV()
|
|
||||||
{
|
|
||||||
constexpr auto ctrlKey = VK_CONTROL;
|
|
||||||
constexpr auto vKey = 0x56;
|
|
||||||
|
|
||||||
const auto pressCtrl = createInputStruct( ctrlKey, KeyStatus::Down );
|
|
||||||
const auto pressV = createInputStruct( vKey, KeyStatus::Down );
|
|
||||||
const auto releaseV = createInputStruct( vKey, KeyStatus::Up );
|
|
||||||
const auto releaseCtrl = createInputStruct( ctrlKey, KeyStatus::Up );
|
|
||||||
|
|
||||||
constexpr auto numberOfActions = 4;
|
|
||||||
|
|
||||||
INPUT actions[numberOfActions]
|
|
||||||
= { pressCtrl, pressV, releaseV, releaseCtrl };
|
|
||||||
|
|
||||||
sendKeyboardInputRaw( numberOfActions, actions );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Sends a media key Next Song button to Windows.
|
|
||||||
*/
|
|
||||||
void sendMediaNextSong()
|
|
||||||
{
|
|
||||||
sendKeyPressAndRelease( VK_MEDIA_NEXT_TRACK );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Sends a media key Previous Song button to Windows.
|
|
||||||
*/
|
|
||||||
void sendMediaPreviousSong()
|
|
||||||
{
|
|
||||||
sendKeyPressAndRelease( VK_MEDIA_PREV_TRACK );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Sends a media key Play/Pause button to Windows.
|
|
||||||
*/
|
|
||||||
void sendMediaPausePlay()
|
|
||||||
{
|
|
||||||
sendKeyPressAndRelease( VK_MEDIA_PLAY_PAUSE );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Sends a media key Stop button to Windows.
|
|
||||||
*/
|
|
||||||
void sendMediaStopSong()
|
|
||||||
{
|
|
||||||
sendKeyPressAndRelease( VK_MEDIA_STOP );
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace keyboardinput
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
#include "KeyboardInput.h"
|
|
||||||
#include <X11/Xlib.h>
|
|
||||||
#include <X11/Intrinsic.h>
|
|
||||||
#include <X11/extensions/XTest.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <array>
|
|
||||||
|
|
||||||
namespace keyboardinput
|
|
||||||
{
|
|
||||||
constexpr auto noModifier = 0;
|
|
||||||
void sendKeyPress( const KeySym keySymbol, const KeySym modifierSymbol )
|
|
||||||
{
|
|
||||||
Display* const display = XOpenDisplay( nullptr );
|
|
||||||
|
|
||||||
const KeyCode keycode = XKeysymToKeycode( display, keySymbol );
|
|
||||||
if ( keycode == 0 )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
XTestGrabControl( display, True );
|
|
||||||
|
|
||||||
KeyCode modcode = 0;
|
|
||||||
if ( modifierSymbol != 0 )
|
|
||||||
{
|
|
||||||
modcode = XKeysymToKeycode( display, modifierSymbol );
|
|
||||||
XTestFakeKeyEvent( display, modcode, True, 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
XTestFakeKeyEvent( display, keycode, True, 0 );
|
|
||||||
XTestFakeKeyEvent( display, keycode, False, 0 );
|
|
||||||
|
|
||||||
if ( modifierSymbol != 0 )
|
|
||||||
{
|
|
||||||
XTestFakeKeyEvent( display, modcode, False, 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
XSync( display, False );
|
|
||||||
XTestGrabControl( display, False );
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendKeyboardInput( QString input )
|
|
||||||
{
|
|
||||||
std::vector<char> characters = { 0 };
|
|
||||||
for ( const auto& character : input )
|
|
||||||
{
|
|
||||||
characters.push_back( character.toLatin1() );
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( const auto character : characters )
|
|
||||||
{
|
|
||||||
sendKeyPress( XStringToKeysym( &character ), noModifier );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendKeyboardEnter()
|
|
||||||
{
|
|
||||||
sendKeyPress( XK_Return, noModifier );
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendKeyboardBackspace( const int count )
|
|
||||||
{
|
|
||||||
for ( int i = 0; i < count; ++i )
|
|
||||||
{
|
|
||||||
sendKeyPress( XK_BackSpace, noModifier );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendKeyboardAltTab()
|
|
||||||
{
|
|
||||||
sendKeyPress( XK_Tab, XK_Alt_L );
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendKeyboardAltEnter()
|
|
||||||
{
|
|
||||||
sendKeyPress( XK_Return, XK_Alt_L );
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendKeyboardCtrlC()
|
|
||||||
{
|
|
||||||
sendKeyPress( XK_c, XK_Control_L );
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendKeyboardCtrlV()
|
|
||||||
{
|
|
||||||
sendKeyPress( XK_v, XK_Control_L );
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendMediaNextSong()
|
|
||||||
{
|
|
||||||
// noop
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendMediaPreviousSong()
|
|
||||||
{
|
|
||||||
// noop
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendMediaPausePlay()
|
|
||||||
{
|
|
||||||
// noop
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendMediaStopSong()
|
|
||||||
{
|
|
||||||
// noop
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace keyboardinput
|
|
||||||
Reference in New Issue
Block a user