Add support for pasting clipboard text

This commit is contained in:
Cameron Gutman 2021-02-07 13:46:38 -06:00
parent 36dc0f3e3c
commit b83c6f0c28
5 changed files with 134 additions and 0 deletions

View file

@ -134,6 +134,7 @@ SOURCES += \
settings/mappingfetcher.cpp \
settings/streamingpreferences.cpp \
streaming/input/abstouch.cpp \
streaming/input/clipboard.cpp \
streaming/input/gamepad.cpp \
streaming/input/input.cpp \
streaming/input/keyboard.cpp \

View file

@ -0,0 +1,101 @@
#include "input.h"
#define MAP_KEY(c, sc) \
case c: \
event.key.keysym.scancode = sc; \
break
#define MAP_KEY_SHIFT(c, sc) \
case c: \
event.key.keysym.scancode = sc; \
event.key.keysym.mod = KMOD_SHIFT; \
break
void SdlInputHandler::sendText(const char* text)
{
for (const char* c = text; *c != 0; c++) {
SDL_Event event = {};
if (*c >= 'A' && *c <= 'Z') {
event.key.keysym.scancode = (SDL_Scancode)((*c - 'A') + SDL_SCANCODE_A);
event.key.keysym.mod = KMOD_SHIFT;
}
else if (*c >= 'a' && *c <= 'z') {
event.key.keysym.scancode = (SDL_Scancode)((*c - 'a') + SDL_SCANCODE_A);
}
else if (*c >= '1' && *c <= '9') {
event.key.keysym.scancode = (SDL_Scancode)((*c - '1') + SDL_SCANCODE_1);
}
else {
// TODO: Smartquotes
switch (*c) {
// Handle CRLF separately to avoid duplicate newlines
case '\r':
if (*(c + 1) == '\n') {
c++;
}
event.key.keysym.scancode = SDL_SCANCODE_RETURN;
break;
MAP_KEY('\b', SDL_SCANCODE_BACKSPACE);
MAP_KEY('\n', SDL_SCANCODE_RETURN);
MAP_KEY('\t', SDL_SCANCODE_TAB);
MAP_KEY(' ', SDL_SCANCODE_SPACE);
MAP_KEY_SHIFT('!', SDL_SCANCODE_1);
MAP_KEY_SHIFT('"', SDL_SCANCODE_APOSTROPHE);
MAP_KEY_SHIFT('#', SDL_SCANCODE_3);
MAP_KEY_SHIFT('$', SDL_SCANCODE_4);
MAP_KEY_SHIFT('%', SDL_SCANCODE_5);
MAP_KEY_SHIFT('&', SDL_SCANCODE_7);
MAP_KEY('\'', SDL_SCANCODE_APOSTROPHE);
MAP_KEY_SHIFT('(', SDL_SCANCODE_9);
MAP_KEY_SHIFT(')', SDL_SCANCODE_0);
MAP_KEY_SHIFT('*', SDL_SCANCODE_8);
MAP_KEY_SHIFT('+', SDL_SCANCODE_EQUALS);
MAP_KEY(',', SDL_SCANCODE_COMMA);
MAP_KEY('-', SDL_SCANCODE_MINUS);
MAP_KEY('.', SDL_SCANCODE_PERIOD);
MAP_KEY('/', SDL_SCANCODE_SLASH);
MAP_KEY('0', SDL_SCANCODE_0);
MAP_KEY_SHIFT(':', SDL_SCANCODE_SEMICOLON);
MAP_KEY(';', SDL_SCANCODE_SEMICOLON);
MAP_KEY_SHIFT('<', SDL_SCANCODE_COMMA);
MAP_KEY('=', SDL_SCANCODE_EQUALS);
MAP_KEY_SHIFT('>', SDL_SCANCODE_PERIOD);
MAP_KEY_SHIFT('?', SDL_SCANCODE_SLASH);
MAP_KEY_SHIFT('@', SDL_SCANCODE_2);
MAP_KEY('[', SDL_SCANCODE_LEFTBRACKET);
MAP_KEY('\\', SDL_SCANCODE_BACKSLASH);
MAP_KEY(']', SDL_SCANCODE_RIGHTBRACKET);
MAP_KEY_SHIFT('^', SDL_SCANCODE_6);
MAP_KEY_SHIFT('_', SDL_SCANCODE_MINUS);
MAP_KEY('`', SDL_SCANCODE_GRAVE);
MAP_KEY_SHIFT('{', SDL_SCANCODE_LEFTBRACKET);
MAP_KEY_SHIFT('|', SDL_SCANCODE_BACKSLASH);
MAP_KEY_SHIFT('}', SDL_SCANCODE_RIGHTBRACKET);
MAP_KEY_SHIFT('~', SDL_SCANCODE_GRAVE);
default:
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
"Pasting text - non-ASCII character '%c' ignored",
*c);
continue;
}
}
event.type = SDL_KEYDOWN;
event.key.state = SDL_PRESSED;
handleKeyEvent(&event.key);
SDL_Delay(10);
event.type = SDL_KEYUP;
event.key.state = SDL_RELEASED;
handleKeyEvent(&event.key);
}
}

View file

@ -109,6 +109,11 @@ SdlInputHandler::SdlInputHandler(StreamingPreferences& prefs, NvComputer*, int s
m_SpecialKeyCombos[KeyComboToggleMinimize].scanCode = SDL_SCANCODE_D;
m_SpecialKeyCombos[KeyComboToggleMinimize].enabled = QGuiApplication::platformName() != "eglfs";
m_SpecialKeyCombos[KeyComboPasteText].keyCombo = KeyComboPasteText;
m_SpecialKeyCombos[KeyComboPasteText].keyCode = SDLK_v;
m_SpecialKeyCombos[KeyComboPasteText].scanCode = SDL_SCANCODE_V;
m_SpecialKeyCombos[KeyComboPasteText].enabled = true;
m_OldIgnoreDevices = SDL_GetHint(SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES);
m_OldIgnoreDevicesExcept = SDL_GetHint(SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT);

View file

@ -65,6 +65,8 @@ public:
void handleJoystickArrivalEvent(SDL_JoyDeviceEvent* event);
void sendText(const char* text);
void rumble(unsigned short controllerNumber, unsigned short lowFreqMotor, unsigned short highFreqMotor);
void handleTouchFingerEvent(SDL_TouchFingerEvent* event);
@ -101,6 +103,7 @@ private:
KeyComboToggleMouseMode,
KeyComboToggleCursorHide,
KeyComboToggleMinimize,
KeyComboPasteText,
KeyComboMax
};

View file

@ -87,6 +87,30 @@ void SdlInputHandler::performPendingSpecialKeyCombo()
SDL_MinimizeWindow(m_Window);
break;
case KeyComboPasteText:
{
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Detected paste text combo");
const char* text = SDL_GetClipboardText();
if (text != nullptr) {
// Reset pending key combo before pasting,
// otherwise it will ignore our keypresses.
m_PendingKeyCombo = KeyComboMax;
// Send the text and free it as required by SDL
sendText(text);
SDL_free((void*)text);
}
else {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
"No text in clipboard to paste!");
}
break;
}
default:
Q_UNREACHABLE();
}
// Reset pending key combo