Merge pull request #511 from cgutman/utf8_events
Add support for UTF-8 input messages on Windows
This commit is contained in:
@@ -34,13 +34,6 @@ endif()
|
|||||||
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||||
set(SUNSHINE_SOURCE_ASSETS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src_assets")
|
set(SUNSHINE_SOURCE_ASSETS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src_assets")
|
||||||
|
|
||||||
if(WIN32)
|
|
||||||
# Ugly hack to compile with #include <qos2.h>
|
|
||||||
add_compile_definitions(
|
|
||||||
QOS_FLOWID=UINT32
|
|
||||||
PQOS_FLOWID=UINT32*
|
|
||||||
QOS_NON_ADAPTIVE_FLOW=2)
|
|
||||||
endif()
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
macro(ADD_FRAMEWORK fwname appname)
|
macro(ADD_FRAMEWORK fwname appname)
|
||||||
find_library(FRAMEWORK_${fwname}
|
find_library(FRAMEWORK_${fwname}
|
||||||
|
|||||||
108
src/input.cpp
108
src/input.cpp
@@ -4,6 +4,7 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <moonlight-common-c/src/Input.h>
|
#include <moonlight-common-c/src/Input.h>
|
||||||
|
#include <moonlight-common-c/src/Limelight.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
@@ -175,7 +176,7 @@ void print(PNV_ABS_MOUSE_MOVE_PACKET packet) {
|
|||||||
void print(PNV_MOUSE_BUTTON_PACKET packet) {
|
void print(PNV_MOUSE_BUTTON_PACKET packet) {
|
||||||
BOOST_LOG(debug)
|
BOOST_LOG(debug)
|
||||||
<< "--begin mouse button packet--"sv << std::endl
|
<< "--begin mouse button packet--"sv << std::endl
|
||||||
<< "action ["sv << util::hex(packet->action).to_string_view() << ']' << std::endl
|
<< "action ["sv << util::hex(packet->header.magic).to_string_view() << ']' << std::endl
|
||||||
<< "button ["sv << util::hex(packet->button).to_string_view() << ']' << std::endl
|
<< "button ["sv << util::hex(packet->button).to_string_view() << ']' << std::endl
|
||||||
<< "--end mouse button packet--"sv;
|
<< "--end mouse button packet--"sv;
|
||||||
}
|
}
|
||||||
@@ -190,12 +191,20 @@ void print(PNV_SCROLL_PACKET packet) {
|
|||||||
void print(PNV_KEYBOARD_PACKET packet) {
|
void print(PNV_KEYBOARD_PACKET packet) {
|
||||||
BOOST_LOG(debug)
|
BOOST_LOG(debug)
|
||||||
<< "--begin keyboard packet--"sv << std::endl
|
<< "--begin keyboard packet--"sv << std::endl
|
||||||
<< "keyAction ["sv << util::hex(packet->keyAction).to_string_view() << ']' << std::endl
|
<< "keyAction ["sv << util::hex(packet->header.magic).to_string_view() << ']' << std::endl
|
||||||
<< "keyCode ["sv << util::hex(packet->keyCode).to_string_view() << ']' << std::endl
|
<< "keyCode ["sv << util::hex(packet->keyCode).to_string_view() << ']' << std::endl
|
||||||
<< "modifiers ["sv << util::hex(packet->modifiers).to_string_view() << ']' << std::endl
|
<< "modifiers ["sv << util::hex(packet->modifiers).to_string_view() << ']' << std::endl
|
||||||
<< "--end keyboard packet--"sv;
|
<< "--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) {
|
void print(PNV_MULTI_CONTROLLER_PACKET packet) {
|
||||||
// Moonlight spams controller packet even when not necessary
|
// Moonlight spams controller packet even when not necessary
|
||||||
BOOST_LOG(verbose)
|
BOOST_LOG(verbose)
|
||||||
@@ -212,33 +221,32 @@ void print(PNV_MULTI_CONTROLLER_PACKET packet) {
|
|||||||
<< "--end controller packet--"sv;
|
<< "--end controller packet--"sv;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr int PACKET_TYPE_SCROLL_OR_KEYBOARD = PACKET_TYPE_SCROLL;
|
void print(void *payload) {
|
||||||
void print(void *input) {
|
auto header = (PNV_INPUT_HEADER)payload;
|
||||||
int input_type = util::endian::big(*(int *)input);
|
|
||||||
|
|
||||||
switch(input_type) {
|
switch(util::endian::little(header->magic)) {
|
||||||
case PACKET_TYPE_REL_MOUSE_MOVE:
|
case MOUSE_MOVE_REL_MAGIC_GEN5:
|
||||||
print((PNV_REL_MOUSE_MOVE_PACKET)input);
|
print((PNV_REL_MOUSE_MOVE_PACKET)payload);
|
||||||
break;
|
break;
|
||||||
case PACKET_TYPE_ABS_MOUSE_MOVE:
|
case MOUSE_MOVE_ABS_MAGIC:
|
||||||
print((PNV_ABS_MOUSE_MOVE_PACKET)input);
|
print((PNV_ABS_MOUSE_MOVE_PACKET)payload);
|
||||||
break;
|
break;
|
||||||
case PACKET_TYPE_MOUSE_BUTTON:
|
case MOUSE_BUTTON_DOWN_EVENT_MAGIC_GEN5:
|
||||||
print((PNV_MOUSE_BUTTON_PACKET)input);
|
case MOUSE_BUTTON_UP_EVENT_MAGIC_GEN5:
|
||||||
|
print((PNV_MOUSE_BUTTON_PACKET)payload);
|
||||||
break;
|
break;
|
||||||
case PACKET_TYPE_SCROLL_OR_KEYBOARD: {
|
case SCROLL_MAGIC_GEN5:
|
||||||
char *tmp_input = (char *)input + 4;
|
print((PNV_SCROLL_PACKET)payload);
|
||||||
if(tmp_input[0] == 0x0A) {
|
|
||||||
print((PNV_SCROLL_PACKET)input);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
print((PNV_KEYBOARD_PACKET)input);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
case KEY_DOWN_EVENT_MAGIC:
|
||||||
case PACKET_TYPE_MULTI_CONTROLLER:
|
case KEY_UP_EVENT_MAGIC:
|
||||||
print((PNV_MULTI_CONTROLLER_PACKET)input);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -294,14 +302,8 @@ void passthrough(std::shared_ptr<input_t> &input, PNV_ABS_MOUSE_MOVE_PACKET pack
|
|||||||
}
|
}
|
||||||
|
|
||||||
void passthrough(std::shared_ptr<input_t> &input, PNV_MOUSE_BUTTON_PACKET packet) {
|
void passthrough(std::shared_ptr<input_t> &input, PNV_MOUSE_BUTTON_PACKET packet) {
|
||||||
auto constexpr BUTTON_RELEASED = 0x09;
|
auto release = util::endian::little(packet->header.magic) == MOUSE_BUTTON_UP_EVENT_MAGIC_GEN5;
|
||||||
|
auto button = util::endian::big(packet->button);
|
||||||
auto constexpr BUTTON_LEFT = 0x01;
|
|
||||||
auto constexpr BUTTON_RIGHT = 0x03;
|
|
||||||
|
|
||||||
auto release = packet->action == BUTTON_RELEASED;
|
|
||||||
|
|
||||||
auto button = util::endian::big(packet->button);
|
|
||||||
if(button > 0 && button < mouse_press.size()) {
|
if(button > 0 && button < mouse_press.size()) {
|
||||||
if(mouse_press[button] != release) {
|
if(mouse_press[button] != release) {
|
||||||
// button state is already what we want
|
// button state is already what we want
|
||||||
@@ -417,9 +419,7 @@ void repeat_key(short key_code) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void passthrough(std::shared_ptr<input_t> &input, PNV_KEYBOARD_PACKET packet) {
|
void passthrough(std::shared_ptr<input_t> &input, PNV_KEYBOARD_PACKET packet) {
|
||||||
auto constexpr BUTTON_RELEASED = 0x04;
|
auto release = util::endian::little(packet->header.magic) == KEY_UP_EVENT_MAGIC;
|
||||||
|
|
||||||
auto release = packet->keyAction == BUTTON_RELEASED;
|
|
||||||
auto keyCode = packet->keyCode & 0x00FF;
|
auto keyCode = packet->keyCode & 0x00FF;
|
||||||
|
|
||||||
auto &pressed = key_press[keyCode];
|
auto &pressed = key_press[keyCode];
|
||||||
@@ -459,6 +459,11 @@ void passthrough(PNV_SCROLL_PACKET packet) {
|
|||||||
platf::scroll(platf_input, util::endian::big(packet->scrollAmt1));
|
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<gamepad_t> &gamepads, std::int16_t old_state, std::int16_t new_state, const platf::rumble_queue_t &rumble_queue) {
|
int updateGamepads(std::vector<gamepad_t> &gamepads, std::int16_t old_state, std::int16_t new_state, const platf::rumble_queue_t &rumble_queue) {
|
||||||
auto xorGamepadMask = old_state ^ new_state;
|
auto xorGamepadMask = old_state ^ new_state;
|
||||||
if(!xorGamepadMask) {
|
if(!xorGamepadMask) {
|
||||||
@@ -600,31 +605,30 @@ void passthrough(std::shared_ptr<input_t> &input, PNV_MULTI_CONTROLLER_PACKET pa
|
|||||||
|
|
||||||
void passthrough_helper(std::shared_ptr<input_t> input, std::vector<std::uint8_t> &&input_data) {
|
void passthrough_helper(std::shared_ptr<input_t> input, std::vector<std::uint8_t> &&input_data) {
|
||||||
void *payload = input_data.data();
|
void *payload = input_data.data();
|
||||||
|
auto header = (PNV_INPUT_HEADER)payload;
|
||||||
|
|
||||||
int input_type = util::endian::big(*(int *)payload);
|
switch(util::endian::little(header->magic)) {
|
||||||
|
case MOUSE_MOVE_REL_MAGIC_GEN5:
|
||||||
switch(input_type) {
|
|
||||||
case PACKET_TYPE_REL_MOUSE_MOVE:
|
|
||||||
passthrough(input, (PNV_REL_MOUSE_MOVE_PACKET)payload);
|
passthrough(input, (PNV_REL_MOUSE_MOVE_PACKET)payload);
|
||||||
break;
|
break;
|
||||||
case PACKET_TYPE_ABS_MOUSE_MOVE:
|
case MOUSE_MOVE_ABS_MAGIC:
|
||||||
passthrough(input, (PNV_ABS_MOUSE_MOVE_PACKET)payload);
|
passthrough(input, (PNV_ABS_MOUSE_MOVE_PACKET)payload);
|
||||||
break;
|
break;
|
||||||
case PACKET_TYPE_MOUSE_BUTTON:
|
case MOUSE_BUTTON_DOWN_EVENT_MAGIC_GEN5:
|
||||||
|
case MOUSE_BUTTON_UP_EVENT_MAGIC_GEN5:
|
||||||
passthrough(input, (PNV_MOUSE_BUTTON_PACKET)payload);
|
passthrough(input, (PNV_MOUSE_BUTTON_PACKET)payload);
|
||||||
break;
|
break;
|
||||||
case PACKET_TYPE_SCROLL_OR_KEYBOARD: {
|
case SCROLL_MAGIC_GEN5:
|
||||||
char *tmp_input = (char *)payload + 4;
|
passthrough((PNV_SCROLL_PACKET)payload);
|
||||||
if(tmp_input[0] == 0x0A) {
|
|
||||||
passthrough((PNV_SCROLL_PACKET)payload);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
passthrough(input, (PNV_KEYBOARD_PACKET)payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
case KEY_DOWN_EVENT_MAGIC:
|
||||||
case PACKET_TYPE_MULTI_CONTROLLER:
|
case KEY_UP_EVENT_MAGIC:
|
||||||
|
passthrough(input, (PNV_KEYBOARD_PACKET)payload);
|
||||||
|
break;
|
||||||
|
case UTF8_TEXT_EVENT_MAGIC:
|
||||||
|
passthrough((PNV_UNICODE_PACKET)payload);
|
||||||
|
break;
|
||||||
|
case MULTI_CONTROLLER_MAGIC_GEN5:
|
||||||
passthrough(input, (PNV_MULTI_CONTROLLER_PACKET)payload);
|
passthrough(input, (PNV_MULTI_CONTROLLER_PACKET)payload);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -296,6 +296,7 @@ void button_mouse(input_t &input, int button, bool release);
|
|||||||
void scroll(input_t &input, int distance);
|
void scroll(input_t &input, int distance);
|
||||||
void keyboard(input_t &input, uint16_t modcode, bool release);
|
void keyboard(input_t &input, uint16_t modcode, bool release);
|
||||||
void gamepad(input_t &input, int nr, const gamepad_state_t &gamepad_state);
|
void gamepad(input_t &input, int nr, const gamepad_state_t &gamepad_state);
|
||||||
|
void unicode(input_t &input, char *utf8, int size);
|
||||||
|
|
||||||
int alloc_gamepad(input_t &input, int nr, rumble_queue_t rumble_queue);
|
int alloc_gamepad(input_t &input, int nr, rumble_queue_t rumble_queue);
|
||||||
void free_gamepad(input_t &input, int nr);
|
void free_gamepad(input_t &input, int nr);
|
||||||
|
|||||||
@@ -994,6 +994,10 @@ void keyboard(input_t &input, uint16_t modcode, bool release) {
|
|||||||
keycode.pressed = 1;
|
keycode.pressed = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void unicode(input_t &input, char *utf8, int size) {
|
||||||
|
BOOST_LOG(info) << "unicode: Unicode input not yet implemented for Linux."sv;
|
||||||
|
}
|
||||||
|
|
||||||
int alloc_gamepad(input_t &input, int nr, rumble_queue_t rumble_queue) {
|
int alloc_gamepad(input_t &input, int nr, rumble_queue_t rumble_queue) {
|
||||||
return ((input_raw_t *)input.get())->alloc_gamepad(nr, std::move(rumble_queue));
|
return ((input_raw_t *)input.get())->alloc_gamepad(nr, std::move(rumble_queue));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -277,6 +277,10 @@ void keyboard(input_t &input, uint16_t modcode, bool release) {
|
|||||||
CGEventPost(kCGHIDEventTap, event);
|
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) {
|
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;
|
BOOST_LOG(info) << "alloc_gamepad: Gamepad not yet implemented for MacOS."sv;
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -326,6 +326,34 @@ void keyboard(input_t &input, uint16_t modcode, bool release) {
|
|||||||
send_input(i);
|
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) {
|
int alloc_gamepad(input_t &input, int nr, rumble_queue_t rumble_queue) {
|
||||||
if(!input) {
|
if(!input) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
2
third-party/moonlight-common-c
vendored
2
third-party/moonlight-common-c
vendored
Submodule third-party/moonlight-common-c updated: 3b9d8a3176...8169a31ecc
Reference in New Issue
Block a user