diff --git a/src/input.cpp b/src/input.cpp index b1745df0..2238c316 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -197,6 +197,14 @@ void print(PNV_KEYBOARD_PACKET packet) { << "--end keyboard packet--"sv; } +void print(PNV_UNICODE_PACKET packet) { + std::string text(packet->text, util::endian::big(packet->header.size) - sizeof(packet->header.magic)); + BOOST_LOG(debug) + << "--begin unicode packet--"sv << std::endl + << "text ["sv << text << ']' << std::endl + << "--end unicode packet--"sv; +} + void print(PNV_MULTI_CONTROLLER_PACKET packet) { // Moonlight spams controller packet even when not necessary BOOST_LOG(verbose) @@ -234,6 +242,9 @@ void print(void *payload) { case KEY_UP_EVENT_MAGIC: print((PNV_KEYBOARD_PACKET)payload); break; + case UTF8_TEXT_EVENT_MAGIC: + print((PNV_UNICODE_PACKET)payload); + break; case MULTI_CONTROLLER_MAGIC_GEN5: print((PNV_MULTI_CONTROLLER_PACKET)payload); break; @@ -448,6 +459,11 @@ void passthrough(PNV_SCROLL_PACKET packet) { platf::scroll(platf_input, util::endian::big(packet->scrollAmt1)); } +void passthrough(PNV_UNICODE_PACKET packet) { + auto size = util::endian::big(packet->header.size) - sizeof(packet->header.magic); + platf::unicode(platf_input, packet->text, size); +} + int updateGamepads(std::vector &gamepads, std::int16_t old_state, std::int16_t new_state, const platf::rumble_queue_t &rumble_queue) { auto xorGamepadMask = old_state ^ new_state; if(!xorGamepadMask) { @@ -609,6 +625,9 @@ void passthrough_helper(std::shared_ptr input, std::vectoralloc_gamepad(nr, std::move(rumble_queue)); } diff --git a/src/platform/macos/input.cpp b/src/platform/macos/input.cpp index 3d9c21a3..f1970944 100644 --- a/src/platform/macos/input.cpp +++ b/src/platform/macos/input.cpp @@ -277,6 +277,10 @@ void keyboard(input_t &input, uint16_t modcode, bool release) { CGEventPost(kCGHIDEventTap, event); } +void unicode(input_t &input, char *utf8, int size) { + BOOST_LOG(info) << "unicode: Unicode input not yet implemented for MacOS."sv; +} + int alloc_gamepad(input_t &input, int nr, rumble_queue_t rumble_queue) { BOOST_LOG(info) << "alloc_gamepad: Gamepad not yet implemented for MacOS."sv; return -1; diff --git a/src/platform/windows/input.cpp b/src/platform/windows/input.cpp index 9ac01a26..dddaf376 100644 --- a/src/platform/windows/input.cpp +++ b/src/platform/windows/input.cpp @@ -326,6 +326,34 @@ void keyboard(input_t &input, uint16_t modcode, bool release) { send_input(i); } +void unicode(input_t &input, char *utf8, int size) { + // We can do no worse than one UTF-16 character per byte of UTF-8 + WCHAR wide[size]; + + int chars = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8, size, wide, size); + if(chars <= 0) { + return; + } + + // Send all key down events + for(int i = 0; i < chars; i++) { + INPUT input {}; + input.type = INPUT_KEYBOARD; + input.ki.wScan = wide[i]; + input.ki.dwFlags = KEYEVENTF_UNICODE; + send_input(input); + } + + // Send all key up events + for(int i = 0; i < chars; i++) { + INPUT input {}; + input.type = INPUT_KEYBOARD; + input.ki.wScan = wide[i]; + input.ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP; + send_input(input); + } +} + int alloc_gamepad(input_t &input, int nr, rumble_queue_t rumble_queue) { if(!input) { return 0;