From a9ad59b32a67aced8cf2baf6182ad3ded94a5af7 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Sat, 25 Mar 2023 21:59:05 +0200 Subject: [PATCH] Improve Workspace::outputAt() Workspace::outputAt() casts vectors to four rectangle corners and uses the shortest one to decide which output is the closest to the given point. This works poorly on dual monitor setups where on the left side you have a monitor with landscape orientation and one with portrait orientation on the right hand side. In that case, outputAt() will prefer the left monitor even though the right monitor is the closest one if you cast a perpendicular from the given point to the right monitor. In order to improve the handling of that case, this change makes Workspace::outputAt() compute the closest point to the output geometry rectangle and use the squared distance as the score. --- autotests/integration/pointer_input.cpp | 2 +- src/workspace.cpp | 15 +++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/autotests/integration/pointer_input.cpp b/autotests/integration/pointer_input.cpp index 8be420e43c..f773dc4e54 100644 --- a/autotests/integration/pointer_input.cpp +++ b/autotests/integration/pointer_input.cpp @@ -1520,7 +1520,7 @@ void PointerInputTest::testConfineToScreenGeometry_data() QTest::newRow("move right - top screen") << QPoint(1920, 512) << QPoint(2660, 512) << QPoint(2660, 512); QTest::newRow("move bottom-right - top screen") << QPoint(1920, 512) << QPoint(2660, 1124) << QPoint(2660, 1023); QTest::newRow("move bottom - top screen") << QPoint(1920, 512) << QPoint(1920, 1124) << QPoint(1920, 1124); - QTest::newRow("move bottom-left - top screen") << QPoint(1920, 512) << QPoint(1180, 1124) << QPoint(1180, 1023); + QTest::newRow("move bottom-left - top screen") << QPoint(1920, 512) << QPoint(1180, 1124) << QPoint(1280, 1124); QTest::newRow("move left - top screen") << QPoint(1920, 512) << QPoint(1180, 512) << QPoint(1180, 512); QTest::newRow("move top-left - right screen") << QPoint(3200, 512) << QPoint(2460, -100) << QPoint(2460, 0); diff --git a/src/workspace.cpp b/src/workspace.cpp index 0966d4e1e8..734fef1d29 100644 --- a/src/workspace.cpp +++ b/src/workspace.cpp @@ -1231,14 +1231,13 @@ Output *Workspace::outputAt(const QPointF &pos) const qreal minDistance; for (Output *output : std::as_const(m_outputs)) { - const QRect &geo = output->geometry(); - if (geo.contains(pos.toPoint())) { - return output; - } - qreal distance = QPointF(geo.topLeft() - pos).manhattanLength(); - distance = std::min(distance, QPointF(geo.topRight() - pos).manhattanLength()); - distance = std::min(distance, QPointF(geo.bottomRight() - pos).manhattanLength()); - distance = std::min(distance, QPointF(geo.bottomLeft() - pos).manhattanLength()); + const QRectF geo = output->geometry(); + + const QPointF closestPoint(std::clamp(pos.x(), geo.x(), geo.x() + geo.width() - 1), + std::clamp(pos.y(), geo.y(), geo.y() + geo.height() - 1)); + + const QPointF ray = closestPoint - pos; + const qreal distance = ray.x() * ray.x() + ray.y() * ray.y(); if (!bestOutput || distance < minDistance) { minDistance = distance; bestOutput = output;