Fix incorrect abs mouse coordinates on Linux when scaling to different aspect ratio

This commit is contained in:
loki 2021-06-23 14:05:09 +02:00
parent 7e3abefc2c
commit 029194cb60
5 changed files with 49 additions and 21 deletions

View File

@ -219,13 +219,21 @@ void passthrough(std::shared_ptr<input_t> &input, PNV_ABS_MOUSE_MOVE_PACKET pack
return;
}
float width = util::endian::big(packet->width);
float height = util::endian::big(packet->height);
int width = util::endian::big(packet->width);
int height = util::endian::big(packet->height);
auto scale_x = (float)touch_port.width / width;
auto scale_y = (float)touch_port.height / height;
auto offsetX = (width - (float)touch_port.width) * 0.5f;
auto offsetY = (height - (float)touch_port.height) * 0.5f;
platf::abs_mouse(platf_input, touch_port, x * scale_x, y * scale_y);
std::clamp(x, offsetX, width - offsetX);
std::clamp(y, offsetX, height - offsetY);
platf::touch_port_t abs_port {
touch_port.offset_x, touch_port.offset_y,
touch_port.env_width, touch_port.env_height
};
platf::abs_mouse(platf_input, abs_port, x - offsetX, y - offsetY); //touch_port, x * scale_x + offsetX, y * scale_y + offsetY);
}
void passthrough(std::shared_ptr<input_t> &input, PNV_MOUSE_BUTTON_PACKET packet) {

View File

@ -105,13 +105,10 @@ inline std::string_view from_pix_fmt(pix_fmt_e pix_fmt) {
// Dimensions for touchscreen input
struct touch_port_t {
std::uint32_t offset_x, offset_y;
std::uint32_t width, height;
int offset_x, offset_y;
int env_width, env_height;
constexpr touch_port_t(
std::uint32_t offset_x, std::uint32_t offset_y,
std::uint32_t width, std::uint32_t height) noexcept : offset_x { offset_x }, offset_y { offset_y },
width { width }, height { height } {};
int width, height;
};
struct gamepad_state_t {
@ -202,6 +199,7 @@ public:
// Offsets for when streaming a specific monitor. By default, they are 0.
int offset_x, offset_y;
int env_width, env_height;
int width, height;
};

View File

@ -147,7 +147,7 @@ struct x11_attr_t : public display_t {
* Last X (NOT the streamed monitor!) size.
* This way we can trigger reinitialization if the dimensions changed while streaming
*/
int lastWidth, lastHeight;
// int env_width, env_height;
x11_attr_t(mem_type_e mem_type) : xdisplay { XOpenDisplay(nullptr) }, xwindow {}, xattr {}, mem_type { mem_type } {
XInitThreads();
@ -204,8 +204,8 @@ struct x11_attr_t : public display_t {
height = xattr.height;
}
lastWidth = xattr.width;
lastHeight = xattr.height;
env_width = xattr.width;
env_height = xattr.height;
return 0;
}
@ -221,7 +221,7 @@ struct x11_attr_t : public display_t {
refresh();
//The whole X server changed, so we gotta reinit everything
if(xattr.width != lastWidth || xattr.height != lastHeight) {
if(xattr.width != env_width || xattr.height != env_height) {
BOOST_LOG(warning) << "X dimensions changed in non-SHM mode, request reinit"sv;
return capture_e::reinit;
}
@ -289,7 +289,7 @@ struct shm_attr_t : public x11_attr_t {
capture_e snapshot(img_t *img, std::chrono::milliseconds timeout, bool cursor) override {
//The whole X server changed, so we gotta reinit everything
if(xattr.width != lastWidth || xattr.height != lastHeight) {
if(xattr.width != env_width || xattr.height != env_height) {
BOOST_LOG(warning) << "X dimensions changed in SHM mode, request reinit"sv;
return capture_e::reinit;
}

View File

@ -145,8 +145,8 @@ 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 + 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));
auto scaled_x = (int)std::lround((x + touch_port.offset_x) * ((float)target_touch_port.env_width / (float)touch_port.env_width));
auto scaled_y = (int)std::lround((y + touch_port.offset_y) * ((float)target_touch_port.env_height / (float)touch_port.env_height));
libevdev_uinput_write_event(touchscreen, EV_ABS, ABS_X, scaled_x);
libevdev_uinput_write_event(touchscreen, EV_ABS, ABS_Y, scaled_y);
@ -470,7 +470,7 @@ evdev_t touchscreen() {
input_absinfo absx {
0,
0,
target_touch_port.width,
target_touch_port.env_width,
1,
0,
28
@ -479,7 +479,7 @@ evdev_t touchscreen() {
input_absinfo absy {
0,
0,
target_touch_port.height,
target_touch_port.env_height,
1,
0,
28

View File

@ -1261,6 +1261,28 @@ void captureThreadSync() {
while(encode_run_sync(synced_session_ctxs, ctx) == encode_e::reinit) {}
}
platf::touch_port_t make_port(platf::display_t *display, const config_t &config) {
float wd = display->width;
float hd = display->height;
float wt = config.width;
float ht = config.height;
auto scalar = std::fminf(wt / wd, ht / hd);
auto w2 = scalar * wd;
auto h2 = scalar * hd;
return platf::touch_port_t {
display->offset_x,
display->offset_y,
display->env_width,
display->env_height,
(int)w2,
(int)h2,
};
}
void capture_async(
safe::mail_t mail,
config_t &config,
@ -1323,7 +1345,7 @@ void capture_async(
images->raise(std::move(dummy_img));
// absolute mouse coordinates require that the dimensions of the screen are known
touch_port_event->raise(display->offset_x, display->offset_y, display->width, display->height);
touch_port_event->raise(make_port(display.get(), config));
encode_run(
frame_nr, key_frame_nr,