diff --git a/sunshine/input.cpp b/sunshine/input.cpp index 2ad4b7cf..ce2a81e3 100644 --- a/sunshine/input.cpp +++ b/sunshine/input.cpp @@ -209,6 +209,14 @@ void passthrough(std::shared_ptr &input, PNV_ABS_MOUSE_MOVE_PACKET pack float x = util::endian::big(packet->x); float y = util::endian::big(packet->y); + // Prevent divide by zero + // Don't expect it to happen, but just in case + if(!packet->width || !packet->height) { + BOOST_LOG(warning) << "Moonlight passed invalid dimensions"sv; + + return; + } + float width = util::endian::big(packet->width); float height = util::endian::big(packet->height); @@ -220,7 +228,9 @@ void passthrough(std::shared_ptr &input, PNV_ABS_MOUSE_MOVE_PACKET pack void passthrough(std::shared_ptr &input, PNV_MOUSE_BUTTON_PACKET packet) { auto constexpr BUTTON_RELEASED = 0x09; - auto constexpr BUTTON_LEFT = 0x01; + + auto constexpr BUTTON_LEFT = 0x01; + auto constexpr BUTTON_RIGHT = 0x03; display_cursor = true; @@ -228,9 +238,14 @@ void passthrough(std::shared_ptr &input, PNV_MOUSE_BUTTON_PACKET packet auto button = util::endian::big(packet->button); if(button > 0 && button < mouse_press.size()) { + if(mouse_press[button] != release) { + // button state is already what we want + return; + } + mouse_press[button] = !release; } - +/////////////////////////////////// /*/ * When Moonlight sends mouse input through absolute coordinates, * it's possible that BUTTON_RIGHT is pressed down immediately after releasing BUTTON_LEFT. @@ -247,13 +262,30 @@ void passthrough(std::shared_ptr &input, PNV_MOUSE_BUTTON_PACKET packet /*/ if(button == BUTTON_LEFT && release && !input->mouse_left_button_timeout) { input->mouse_left_button_timeout = task_pool.pushDelayed([=]() { - platf::button_mouse(platf_input, button, release); + auto left_released = mouse_press[BUTTON_LEFT]; + if(left_released) { + // Already released left button + return; + } + platf::button_mouse(platf_input, BUTTON_LEFT, release); input->mouse_left_button_timeout = nullptr; }, 10ms).task_id; return; } + if( + button == BUTTON_RIGHT && !release && + input->mouse_left_button_timeout > DISABLE_LEFT_BUTTON_DELAY + ) { + platf::button_mouse(platf_input, BUTTON_RIGHT, false); + platf::button_mouse(platf_input, BUTTON_RIGHT, true); + + mouse_press[BUTTON_RIGHT] = false; + + return; + } +/////////////////////////////////// platf::button_mouse(platf_input, button, release); } diff --git a/sunshine/platform/windows/display_base.cpp b/sunshine/platform/windows/display_base.cpp index 8644ed88..46405397 100644 --- a/sunshine/platform/windows/display_base.cpp +++ b/sunshine/platform/windows/display_base.cpp @@ -129,8 +129,10 @@ int display_base_t::init() { if(desc.AttachedToDesktop) { output = std::move(output_tmp); - width = desc.DesktopCoordinates.right - desc.DesktopCoordinates.left; - height = desc.DesktopCoordinates.bottom - desc.DesktopCoordinates.top; + offset_x = desc.DesktopCoordinates.left; + offset_y = desc.DesktopCoordinates.top; + width = desc.DesktopCoordinates.right - offset_x; + height = desc.DesktopCoordinates.bottom - offset_y; } } diff --git a/sunshine/platform/windows/input.cpp b/sunshine/platform/windows/input.cpp index 4f40576c..b372afd2 100755 --- a/sunshine/platform/windows/input.cpp +++ b/sunshine/platform/windows/input.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -17,7 +18,12 @@ using namespace std::literals; using adapteraddrs_t = util::c_ptr; -volatile HDESK _lastKnownInputDesktop = NULL; +volatile HDESK _lastKnownInputDesktop = NULL; +constexpr touch_port_t target_touch_port { + 0, 0, + 65535, 65535 +}; + HDESK pairInputDesktop(); class vigem_t { @@ -165,7 +171,40 @@ input_t input() { return result; } -void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) {} +void send_input(INPUT &i) { +retry: + auto send = SendInput(1, &i, sizeof(INPUT)); + if(send != 1) { + auto hDesk = pairInputDesktop(); + if (_lastKnownInputDesktop != hDesk) { + _lastKnownInputDesktop = hDesk; + goto retry; + } + BOOST_LOG(warning) << "Couldn't send input"sv; + } +} +void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) { + INPUT i {}; + + i.type = INPUT_MOUSE; + auto &mi = i.mi; + + mi.dwFlags = + MOUSEEVENTF_MOVE | + MOUSEEVENTF_ABSOLUTE | + + // MOUSEEVENTF_VIRTUALDESK maps to the entirety of the desktop rather than the primary desktop + MOUSEEVENTF_VIRTUALDESK; + + auto scaled_x = std::lround((x + touch_port.offset_x) * ((float)target_touch_port.width / (float)touch_port.width)); + auto scaled_y = std::lround((y + touch_port.offset_y) * ((float)target_touch_port.height / (float)touch_port.height)); + + mi.dx = scaled_x; + mi.dy = scaled_y; + + send_input(i); +} + void move_mouse(input_t &input, int deltaX, int deltaY) { INPUT i {}; @@ -176,16 +215,7 @@ void move_mouse(input_t &input, int deltaX, int deltaY) { mi.dx = deltaX; mi.dy = deltaY; -retry: - auto send = SendInput(1, &i, sizeof(INPUT)); - if(send != 1) { - auto hDesk = pairInputDesktop(); - if (_lastKnownInputDesktop != hDesk) { - _lastKnownInputDesktop = hDesk; - goto retry; - } - BOOST_LOG(warning) << "Couldn't send mouse movement input"sv; - } + send_input(i); } void button_mouse(input_t &input, int button, bool release) { @@ -228,16 +258,7 @@ void button_mouse(input_t &input, int button, bool release) { return; } -retry: - auto send = SendInput(1, &i, sizeof(INPUT)); - if(send != 1) { - auto hDesk = pairInputDesktop(); - if (_lastKnownInputDesktop != hDesk) { - _lastKnownInputDesktop = hDesk; - goto retry; - } - BOOST_LOG(warning) << "Couldn't send mouse button input"sv; - } + send_input(i); } void scroll(input_t &input, int distance) { @@ -249,16 +270,7 @@ void scroll(input_t &input, int distance) { mi.dwFlags = MOUSEEVENTF_WHEEL; mi.mouseData = distance; -retry: - auto send = SendInput(1, &i, sizeof(INPUT)); - if(send != 1) { - auto hDesk = pairInputDesktop(); - if (_lastKnownInputDesktop != hDesk) { - _lastKnownInputDesktop = hDesk; - goto retry; - } - BOOST_LOG(warning) << "Couldn't send mouse scroll input"sv; - } + send_input(i); } void keyboard(input_t &input, uint16_t modcode, bool release) { @@ -304,16 +316,7 @@ void keyboard(input_t &input, uint16_t modcode, bool release) { ki.dwFlags |= KEYEVENTF_KEYUP; } -retry: - auto send = SendInput(1, &i, sizeof(INPUT)); - if(send != 1) { - auto hDesk = pairInputDesktop(); - if (_lastKnownInputDesktop != hDesk) { - _lastKnownInputDesktop = hDesk; - goto retry; - } - BOOST_LOG(warning) << "Couldn't send keyboard input"sv; - } + send_input(i); } int alloc_gamepad(input_t &input, int nr) {