[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;
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();

View file

@ -21,9 +21,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#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<TouchEvent*>(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<AbstractWaylandOutput*>(
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<TouchEvent*>(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<AbstractWaylandOutput*>(
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
}