From 5b6e081af20e3469b1893a3d48f9e675015693d8 Mon Sep 17 00:00:00 2001 From: Roman Gilg Date: Thu, 12 Dec 2019 15:41:12 +0100 Subject: [PATCH] [libinput] Send touch events with respect to device rotation Summary: Touch events coming from libinput devices must be transformed according to the current device rotation. Test Plan: Manually. Reviewers: #kwin Subscribers: kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D25921 --- abstract_wayland_output.h | 22 ++++++++-------- libinput/connection.cpp | 53 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 60 insertions(+), 15 deletions(-) diff --git a/abstract_wayland_output.h b/abstract_wayland_output.h index c2d91508da..aa4023f937 100644 --- a/abstract_wayland_output.h +++ b/abstract_wayland_output.h @@ -86,6 +86,17 @@ public: QRect geometry() const override; QSize physicalSize() const override; + /** + * Returns the orientation of this output. + * + * - Flipped along the vertical axis is landscape + inv. portrait. + * - Rotated 90° and flipped along the horizontal axis is portrait + inv. landscape + * - Rotated 180° and flipped along the vertical axis is inv. landscape + inv. portrait + * - Rotated 270° and flipped along the horizontal axis is inv. portrait + inv. landscape + + * portrait + */ + Transform transform() const; + /** * Current refresh rate in 1/ms. */ @@ -159,17 +170,6 @@ protected: QSize orientateSize(const QSize &size) const; - /** - * Returns the orientation of this output. - * - * - Flipped along the vertical axis is landscape + inv. portrait. - * - Rotated 90° and flipped along the horizontal axis is portrait + inv. landscape - * - Rotated 180° and flipped along the vertical axis is inv. landscape + inv. portrait - * - Rotated 270° and flipped along the horizontal axis is inv. portrait + inv. landscape + - * portrait - */ - Transform transform() const; - private: void createWaylandOutput(); void createXdgOutput(); diff --git a/libinput/connection.cpp b/libinput/connection.cpp index ff1497b67d..cc5628ea17 100644 --- a/libinput/connection.cpp +++ b/libinput/connection.cpp @@ -21,9 +21,15 @@ along with this program. If not, see . #include "context.h" #include "device.h" #include "events.h" + +// TODO: Make it compile also in testing environment #ifndef KWIN_BUILD_TESTING +#include "../abstract_wayland_output.h" +#include "../main.h" +#include "../platform.h" #include "../screens.h" #endif + #include "../logind.h" #include "../udev.h" #include "libinput_logging.h" @@ -244,6 +250,37 @@ void Connection::handleEvent() } } +#ifndef KWIN_BUILD_TESTING +QPointF devicePointToGlobalPosition(const QPointF &devicePos, const AbstractWaylandOutput *output) +{ + using Transform = AbstractWaylandOutput::Transform; + + QPointF pos = devicePos; + // TODO: Do we need to handle the flipped cases differently? + switch (output->transform()) { + case Transform::Normal: + case Transform::Flipped: + break; + case Transform::Rotated90: + case Transform::Flipped90: + pos = QPointF(output->modeSize().height() - devicePos.y(), devicePos.x()); + break; + case Transform::Rotated180: + case Transform::Flipped180: + pos = QPointF(output->modeSize().width() - devicePos.x(), + output->modeSize().height() - devicePos.y()); + break; + case Transform::Rotated270: + case Transform::Flipped270: + pos = QPointF(devicePos.y(), output->modeSize().width() - devicePos.x()); + break; + default: + Q_UNREACHABLE(); + } + return output->geometry().topLeft() + pos / output->scale(); +} +#endif + void Connection::processEvents() { QMutexLocker locker(&m_mutex); @@ -385,8 +422,12 @@ void Connection::processEvents() case LIBINPUT_EVENT_TOUCH_DOWN: { #ifndef KWIN_BUILD_TESTING TouchEvent *te = static_cast(event.data()); - const auto &geo = screens()->geometry(te->device()->screenId()); - emit touchDown(te->id(), geo.topLeft() + te->absolutePos(geo.size()), te->time(), te->device()); + const auto *output = static_cast( + kwinApp()->platform()->enabledOutputs()[te->device()->screenId()]); + const QPointF globalPos = + devicePointToGlobalPosition(te->absolutePos(output->modeSize()), + output); + emit touchDown(te->id(), globalPos, te->time(), te->device()); break; #endif } @@ -398,8 +439,12 @@ void Connection::processEvents() case LIBINPUT_EVENT_TOUCH_MOTION: { #ifndef KWIN_BUILD_TESTING TouchEvent *te = static_cast(event.data()); - const auto &geo = screens()->geometry(te->device()->screenId()); - emit touchMotion(te->id(), geo.topLeft() + te->absolutePos(geo.size()), te->time(), te->device()); + const auto *output = static_cast( + kwinApp()->platform()->enabledOutputs()[te->device()->screenId()]); + const QPointF globalPos = + devicePointToGlobalPosition(te->absolutePos(output->modeSize()), + output); + emit touchMotion(te->id(), globalPos, te->time(), te->device()); break; #endif }