fix(linux): fix touch misalignment for wlgrab on scaled outputs (#4665)

This commit is contained in:
herbie
2026-02-17 23:40:16 -05:00
committed by GitHub
parent 24c5dfd622
commit c9bcee4480
2 changed files with 53 additions and 22 deletions
+37 -22
View File
@@ -902,6 +902,31 @@ namespace input {
input->gamepads[packet->controllerNumber].id = id;
}
/**
* @brief Normalizes coordinates to monitor-local logical touch dimensions.
* @param touch_port The current touch port metadata.
* @param coords The in/out coordinate pair to normalize.
* @return The monitor-local touch port, or std::nullopt if dimensions are invalid.
*/
std::optional<platf::touch_port_t> monitor_touch_port(const input::touch_port_t &touch_port, std::pair<float, float> &coords) {
const float monitor_logical_w = (touch_port.width * touch_port.scalar_inv) / touch_port.scalar_tpcoords;
const float monitor_logical_h = (touch_port.height * touch_port.scalar_inv) / touch_port.scalar_tpcoords;
if (monitor_logical_w <= 0.0f || monitor_logical_h <= 0.0f) {
BOOST_LOG(warning) << "Ignoring touch/pen input due to invalid logical touch dimensions"sv;
return std::nullopt;
}
coords.first = (coords.first - touch_port.offset_x) / monitor_logical_w;
coords.second = (coords.second - touch_port.offset_y) / monitor_logical_h;
return platf::touch_port_t {
touch_port.offset_x,
touch_port.offset_y,
static_cast<int>(monitor_logical_w),
static_cast<int>(monitor_logical_h)
};
}
/**
* @brief Called to pass a touch message to the platform backend.
* @param input The input context pointer.
@@ -919,16 +944,11 @@ namespace input {
}
auto &touch_port = input->touch_port;
platf::touch_port_t abs_port {
touch_port.offset_x,
touch_port.offset_y,
touch_port.env_width,
touch_port.env_height
};
// Renormalize the coordinates
coords->first /= abs_port.width;
coords->second /= abs_port.height;
auto abs_port = monitor_touch_port(touch_port, *coords);
if (!abs_port) {
return;
}
// Normalize rotation value to 0-359 degree range
auto rotation = util::endian::little(packet->rotation);
@@ -941,7 +961,7 @@ namespace input {
{from_clamped_netfloat(packet->contactAreaMajor, 0.0f, 1.0f) * 65535.f,
from_clamped_netfloat(packet->contactAreaMinor, 0.0f, 1.0f) * 65535.f},
rotation,
{abs_port.width / 65535.f, abs_port.height / 65535.f}
{abs_port->width / 65535.f, abs_port->height / 65535.f}
);
platf::touch_input_t touch {
@@ -955,7 +975,7 @@ namespace input {
contact_area.second,
};
platf::touch_update(input->client_context.get(), abs_port, touch);
platf::touch_update(input->client_context.get(), *abs_port, touch);
}
/**
@@ -975,16 +995,11 @@ namespace input {
}
auto &touch_port = input->touch_port;
platf::touch_port_t abs_port {
touch_port.offset_x,
touch_port.offset_y,
touch_port.env_width,
touch_port.env_height
};
// Renormalize the coordinates
coords->first /= abs_port.width;
coords->second /= abs_port.height;
auto abs_port = monitor_touch_port(touch_port, *coords);
if (!abs_port) {
return;
}
// Normalize rotation value to 0-359 degree range
auto rotation = util::endian::little(packet->rotation);
@@ -997,7 +1012,7 @@ namespace input {
{from_clamped_netfloat(packet->contactAreaMajor, 0.0f, 1.0f) * 65535.f,
from_clamped_netfloat(packet->contactAreaMinor, 0.0f, 1.0f) * 65535.f},
rotation,
{abs_port.width / 65535.f, abs_port.height / 65535.f}
{abs_port->width / 65535.f, abs_port->height / 65535.f}
);
platf::pen_input_t pen {
@@ -1013,7 +1028,7 @@ namespace input {
contact_area.second,
};
platf::pen_update(input->client_context.get(), abs_port, pen);
platf::pen_update(input->client_context.get(), *abs_port, pen);
}
/**
+16
View File
@@ -74,10 +74,26 @@ namespace wl {
this->env_width = ::wl::env_width;
this->env_height = ::wl::env_height;
this->logical_width = monitor->viewport.logical_width;
this->logical_height = monitor->viewport.logical_height;
int desktop_logical_width = 0;
int desktop_logical_height = 0;
for (auto &monitor_entry : interface.monitors) {
auto output_monitor = monitor_entry.get();
desktop_logical_width = std::max(desktop_logical_width, output_monitor->viewport.offset_x + output_monitor->viewport.logical_width);
desktop_logical_height = std::max(desktop_logical_height, output_monitor->viewport.offset_y + output_monitor->viewport.logical_height);
}
this->env_logical_width = desktop_logical_width;
this->env_logical_height = desktop_logical_height;
BOOST_LOG(info) << "Selected monitor ["sv << monitor->description << "] for streaming"sv;
BOOST_LOG(debug) << "Offset: "sv << offset_x << 'x' << offset_y;
BOOST_LOG(debug) << "Resolution: "sv << width << 'x' << height;
BOOST_LOG(debug) << "Logical Resolution: "sv << logical_width << 'x' << logical_height;
BOOST_LOG(debug) << "Desktop Resolution: "sv << env_width << 'x' << env_height;
BOOST_LOG(debug) << "Logical Desktop Resolution: "sv << env_logical_width << 'x' << env_logical_height;
return 0;
}