[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
This commit is contained in:
Roman Gilg 2019-12-12 15:41:12 +01:00 committed by Bhushan Shah
parent 7c70b344f5
commit 5b6e081af2
2 changed files with 60 additions and 15 deletions

View file

@ -86,6 +86,17 @@ public:
QRect geometry() const override; QRect geometry() const override;
QSize physicalSize() 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. * Current refresh rate in 1/ms.
*/ */
@ -159,17 +170,6 @@ protected:
QSize orientateSize(const QSize &size) const; 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: private:
void createWaylandOutput(); void createWaylandOutput();
void createXdgOutput(); void createXdgOutput();

View file

@ -21,9 +21,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "context.h" #include "context.h"
#include "device.h" #include "device.h"
#include "events.h" #include "events.h"
// TODO: Make it compile also in testing environment
#ifndef KWIN_BUILD_TESTING #ifndef KWIN_BUILD_TESTING
#include "../abstract_wayland_output.h"
#include "../main.h"
#include "../platform.h"
#include "../screens.h" #include "../screens.h"
#endif #endif
#include "../logind.h" #include "../logind.h"
#include "../udev.h" #include "../udev.h"
#include "libinput_logging.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() void Connection::processEvents()
{ {
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
@ -385,8 +422,12 @@ void Connection::processEvents()
case LIBINPUT_EVENT_TOUCH_DOWN: { case LIBINPUT_EVENT_TOUCH_DOWN: {
#ifndef KWIN_BUILD_TESTING #ifndef KWIN_BUILD_TESTING
TouchEvent *te = static_cast<TouchEvent*>(event.data()); TouchEvent *te = static_cast<TouchEvent*>(event.data());
const auto &geo = screens()->geometry(te->device()->screenId()); const auto *output = static_cast<AbstractWaylandOutput*>(
emit touchDown(te->id(), geo.topLeft() + te->absolutePos(geo.size()), te->time(), te->device()); 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; break;
#endif #endif
} }
@ -398,8 +439,12 @@ void Connection::processEvents()
case LIBINPUT_EVENT_TOUCH_MOTION: { case LIBINPUT_EVENT_TOUCH_MOTION: {
#ifndef KWIN_BUILD_TESTING #ifndef KWIN_BUILD_TESTING
TouchEvent *te = static_cast<TouchEvent*>(event.data()); TouchEvent *te = static_cast<TouchEvent*>(event.data());
const auto &geo = screens()->geometry(te->device()->screenId()); const auto *output = static_cast<AbstractWaylandOutput*>(
emit touchMotion(te->id(), geo.topLeft() + te->absolutePos(geo.size()), te->time(), te->device()); 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; break;
#endif #endif
} }