mirror of
https://github.com/moonlight-stream/moonlight-qt
synced 2024-11-14 15:37:09 +00:00
Add support for pasting clipboard text
This commit is contained in:
parent
36dc0f3e3c
commit
b83c6f0c28
5 changed files with 134 additions and 0 deletions
|
@ -134,6 +134,7 @@ SOURCES += \
|
||||||
settings/mappingfetcher.cpp \
|
settings/mappingfetcher.cpp \
|
||||||
settings/streamingpreferences.cpp \
|
settings/streamingpreferences.cpp \
|
||||||
streaming/input/abstouch.cpp \
|
streaming/input/abstouch.cpp \
|
||||||
|
streaming/input/clipboard.cpp \
|
||||||
streaming/input/gamepad.cpp \
|
streaming/input/gamepad.cpp \
|
||||||
streaming/input/input.cpp \
|
streaming/input/input.cpp \
|
||||||
streaming/input/keyboard.cpp \
|
streaming/input/keyboard.cpp \
|
||||||
|
|
101
app/streaming/input/clipboard.cpp
Normal file
101
app/streaming/input/clipboard.cpp
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -109,6 +109,11 @@ SdlInputHandler::SdlInputHandler(StreamingPreferences& prefs, NvComputer*, int s
|
||||||
m_SpecialKeyCombos[KeyComboToggleMinimize].scanCode = SDL_SCANCODE_D;
|
m_SpecialKeyCombos[KeyComboToggleMinimize].scanCode = SDL_SCANCODE_D;
|
||||||
m_SpecialKeyCombos[KeyComboToggleMinimize].enabled = QGuiApplication::platformName() != "eglfs";
|
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_OldIgnoreDevices = SDL_GetHint(SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES);
|
||||||
m_OldIgnoreDevicesExcept = SDL_GetHint(SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT);
|
m_OldIgnoreDevicesExcept = SDL_GetHint(SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT);
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,8 @@ public:
|
||||||
|
|
||||||
void handleJoystickArrivalEvent(SDL_JoyDeviceEvent* event);
|
void handleJoystickArrivalEvent(SDL_JoyDeviceEvent* event);
|
||||||
|
|
||||||
|
void sendText(const char* text);
|
||||||
|
|
||||||
void rumble(unsigned short controllerNumber, unsigned short lowFreqMotor, unsigned short highFreqMotor);
|
void rumble(unsigned short controllerNumber, unsigned short lowFreqMotor, unsigned short highFreqMotor);
|
||||||
|
|
||||||
void handleTouchFingerEvent(SDL_TouchFingerEvent* event);
|
void handleTouchFingerEvent(SDL_TouchFingerEvent* event);
|
||||||
|
@ -101,6 +103,7 @@ private:
|
||||||
KeyComboToggleMouseMode,
|
KeyComboToggleMouseMode,
|
||||||
KeyComboToggleCursorHide,
|
KeyComboToggleCursorHide,
|
||||||
KeyComboToggleMinimize,
|
KeyComboToggleMinimize,
|
||||||
|
KeyComboPasteText,
|
||||||
KeyComboMax
|
KeyComboMax
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,30 @@ void SdlInputHandler::performPendingSpecialKeyCombo()
|
||||||
|
|
||||||
SDL_MinimizeWindow(m_Window);
|
SDL_MinimizeWindow(m_Window);
|
||||||
break;
|
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
|
// Reset pending key combo
|
||||||
|
|
Loading…
Reference in a new issue