From 2e9a1cfbbaacbe1ea63808214801aeb306fdfb11 Mon Sep 17 00:00:00 2001 From: loki <loki@fakeemail.com> Date: Tue, 11 May 2021 23:51:45 +0200 Subject: [PATCH] absolute mouse coordinates regardless of the number of monitors attached on Linux --- sunshine/platform/common.h | 4 ++++ sunshine/platform/linux/display.cpp | 28 +++++++++++----------------- sunshine/platform/linux/input.cpp | 8 ++++---- sunshine/platform/windows/input.cpp | 2 +- sunshine/video.cpp | 9 +++++++-- 5 files changed, 27 insertions(+), 24 deletions(-) diff --git a/sunshine/platform/common.h b/sunshine/platform/common.h index 69e41922..96c3d84e 100644 --- a/sunshine/platform/common.h +++ b/sunshine/platform/common.h @@ -122,6 +122,7 @@ enum class capture_e : int { class display_t { public: + display_t() noexcept : offset_x { 0 }, offset_y { 0 } {} virtual capture_e snapshot(img_t *img, std::chrono::milliseconds timeout, bool cursor) = 0; virtual std::shared_ptr<img_t> alloc_img() = 0; @@ -133,6 +134,9 @@ public: virtual ~display_t() = default; + // Offsets for when streaming a specific monitor. By default, they are 0. + int offset_x, offset_y; + int width, height; }; diff --git a/sunshine/platform/linux/display.cpp b/sunshine/platform/linux/display.cpp index 39fbd616..4ca09f59 100644 --- a/sunshine/platform/linux/display.cpp +++ b/sunshine/platform/linux/display.cpp @@ -153,12 +153,7 @@ struct x11_attr_t: public display_t */ int lastWidth, lastHeight; - /* - * Offsets for when streaming a specific monitor. By default, they are 0. - */ - int displayOffsetX, displayOffsetY; - - x11_attr_t() : xdisplay { XOpenDisplay(nullptr) }, xwindow { }, xattr { }, displayOffsetX { 0 }, displayOffsetY { 0 } { + x11_attr_t() : xdisplay { XOpenDisplay(nullptr) }, xwindow { }, xattr { } { XInitThreads(); } @@ -199,8 +194,8 @@ struct x11_attr_t: public display_t width = crt_info->width; height = crt_info->height; - displayOffsetX = crt_info->x; - displayOffsetY = crt_info->y; + offset_x = crt_info->x; + offset_y = crt_info->y; } else { width = xattr.width; @@ -228,7 +223,7 @@ struct x11_attr_t: public display_t BOOST_LOG(warning)<< "X dimensions changed in non-SHM mode, request reinit"sv; return capture_e::reinit; } - XImage *img { XGetImage(xdisplay.get(), xwindow, displayOffsetX, displayOffsetY, width, height, AllPlanes, ZPixmap) }; + XImage *img { XGetImage(xdisplay.get(), xwindow, offset_x, offset_y, width, height, AllPlanes, ZPixmap) }; auto img_out = (x11_img_t*) img_out_base; img_out->width = img->width; @@ -239,7 +234,7 @@ struct x11_attr_t: public display_t img_out->img.reset(img); if (cursor) { - blend_cursor(xdisplay.get(), *img_out_base, displayOffsetX, displayOffsetY); + blend_cursor(xdisplay.get(), *img_out_base, offset_x, offset_y); } return capture_e::ok; @@ -288,19 +283,18 @@ struct shm_attr_t: public x11_attr_t { return capture_e::reinit; } else { - auto img_cookie = xcb_shm_get_image_unchecked(xcb.get(), display->root, displayOffsetX, displayOffsetY, width, height, ~0, XCB_IMAGE_FORMAT_Z_PIXMAP, seg, 0); + auto img_cookie = xcb_shm_get_image_unchecked(xcb.get(), display->root, offset_x, offset_y, width, height, ~0, XCB_IMAGE_FORMAT_Z_PIXMAP, seg, 0); xcb_img_t img_reply { xcb_shm_get_image_reply(xcb.get(), img_cookie,nullptr) }; - if (!img_reply) { - BOOST_LOG(error) - << "Could not get image reply"sv; + if(!img_reply) { + BOOST_LOG(error) << "Could not get image reply"sv; return capture_e::reinit; } - std::copy_n((std::uint8_t*) data.data, frame_size(), img->data); + std::copy_n((std::uint8_t*)data.data, frame_size(), img->data); - if (cursor) { - blend_cursor(shm_xdisplay.get(), *img, displayOffsetX, displayOffsetY); + if(cursor) { + blend_cursor(shm_xdisplay.get(), *img, offset_x, offset_y); } return capture_e::ok; diff --git a/sunshine/platform/linux/input.cpp b/sunshine/platform/linux/input.cpp index 8b4578bc..b0a5cec1 100644 --- a/sunshine/platform/linux/input.cpp +++ b/sunshine/platform/linux/input.cpp @@ -145,11 +145,11 @@ public: void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) { auto touchscreen = ((input_raw_t*)input.get())->touch_input.get(); - auto scaled_x = (int)std::lround(x * ((float)target_touch_port.width / (float)touch_port.width)); - auto scaled_y = (int)std::lround(y * ((float)target_touch_port.height / (float)touch_port.height)); + auto scaled_x = (int)std::lround((x + touch_port.offset_x) * ((float)target_touch_port.width / (float)touch_port.width)); + auto scaled_y = (int)std::lround((y + touch_port.offset_y) * ((float)target_touch_port.height / (float)touch_port.height)); - libevdev_uinput_write_event(touchscreen, EV_ABS, ABS_X, scaled_x + touch_port.offset_x); - libevdev_uinput_write_event(touchscreen, EV_ABS, ABS_Y, scaled_y + touch_port.offset_y); + libevdev_uinput_write_event(touchscreen, EV_ABS, ABS_X, scaled_x); + libevdev_uinput_write_event(touchscreen, EV_ABS, ABS_Y, scaled_y); libevdev_uinput_write_event(touchscreen, EV_KEY, BTN_TOOL_FINGER, 1); libevdev_uinput_write_event(touchscreen, EV_KEY, BTN_TOOL_FINGER, 0); diff --git a/sunshine/platform/windows/input.cpp b/sunshine/platform/windows/input.cpp index d0af736e..4f40576c 100755 --- a/sunshine/platform/windows/input.cpp +++ b/sunshine/platform/windows/input.cpp @@ -165,7 +165,7 @@ input_t input() { return result; } -void abs_mouse(input_t &input, int x, int y) {} +void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) {} void move_mouse(input_t &input, int deltaX, int deltaY) { INPUT i {}; diff --git a/sunshine/video.cpp b/sunshine/video.cpp index 88dfd01b..54252375 100644 --- a/sunshine/video.cpp +++ b/sunshine/video.cpp @@ -856,7 +856,9 @@ encode_e encode_run_sync(std::vector<std::unique_ptr<sync_session_ctx_t>> &synce return encode_e::error; } - input::touch_port_event->raise(0, 0, img->width, img->height); + // absolute mouse coordinates require that the dimensions of the screen are known + input::touch_port_event->raise(disp->offset_x, disp->offset_y, disp->width, disp->height); + std::vector<sync_session_t> synced_sessions; for(auto &ctx : synced_session_ctxs) { auto synced_session = make_synced_session(disp.get(), encoder, *img, *ctx); @@ -1064,9 +1066,12 @@ void capture_async( if(display->dummy_img(dummy_img.get())) { return; } - input::touch_port_event->raise(0, 0, dummy_img->width, dummy_img->height); + images->raise(std::move(dummy_img)); + // absolute mouse coordinates require that the dimensions of the screen are known + input::touch_port_event->raise(display->offset_x, display->offset_y, display->width, display->height); + encode_run( frame_nr, key_frame_nr, shutdown_event,