Split out touch related functionality from InputRedirection

Similar to c044ad98be this change splits
all touch handling related functionality into a dedicated class called
TouchInputRedirection.
This commit is contained in:
Martin Gräßlin 2016-02-15 09:36:59 +01:00
parent fed7a48112
commit b8f8b2d8a0
5 changed files with 278 additions and 119 deletions

View file

@ -333,6 +333,7 @@ set(kwin_KDEINIT_SRCS
globalshortcuts.cpp
input.cpp
pointer_input.cpp
touch_input.cpp
netinfo.cpp
placement.cpp
atoms.cpp

130
input.cpp
View file

@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "input.h"
#include "pointer_input.h"
#include "touch_input.h"
#include "client.h"
#include "effects.h"
#include "globalshortcuts.h"
@ -412,10 +413,10 @@ public:
auto seat = waylandServer()->seat();
seat->setTimestamp(time);
if (!seat->isTouchSequence()) {
input()->updateTouchWindow(pos);
input()->touch()->update(pos);
}
if (touchSurfaceAllowed()) {
input()->insertTouchId(id, seat->touchDown(pos));
input()->touch()->insertId(id, seat->touchDown(pos));
}
return true;
}
@ -426,7 +427,7 @@ public:
auto seat = waylandServer()->seat();
seat->setTimestamp(time);
if (touchSurfaceAllowed()) {
const qint32 kwaylandId = input()->touchId(id);
const qint32 kwaylandId = input()->touch()->mappedId(id);
if (kwaylandId != -1) {
seat->touchMove(kwaylandId, pos);
}
@ -440,10 +441,10 @@ public:
auto seat = waylandServer()->seat();
seat->setTimestamp(time);
if (touchSurfaceAllowed()) {
const qint32 kwaylandId = input()->touchId(id);
const qint32 kwaylandId = input()->touch()->mappedId(id);
if (kwaylandId != -1) {
seat->touchUp(kwaylandId);
input()->removeTouchId(id);
input()->touch()->removeId(id);
}
}
return true;
@ -774,8 +775,8 @@ public:
auto seat = waylandServer()->seat();
seat->setTimestamp(time);
if (!seat->isTouchSequence()) {
input()->updateTouchWindow(pos);
if (AbstractClient *c = dynamic_cast<AbstractClient*>(input()->m_touchWindow.data())) {
input()->touch()->update(pos);
if (AbstractClient *c = dynamic_cast<AbstractClient*>(input()->touch()->window().data())) {
// perform same handling as if it were a left click
bool wasAction = false;
const Options::MouseCommand command = c->getMouseCommand(Qt::LeftButton, &wasAction);
@ -787,7 +788,7 @@ public:
}
}
}
input()->insertTouchId(id, seat->touchDown(pos));
input()->touch()->insertId(id, seat->touchDown(pos));
return true;
}
bool touchMotion(quint32 id, const QPointF &pos, quint32 time) override {
@ -796,7 +797,7 @@ public:
}
auto seat = waylandServer()->seat();
seat->setTimestamp(time);
const qint32 kwaylandId = input()->touchId(id);
const qint32 kwaylandId = input()->touch()->mappedId(id);
if (kwaylandId != -1) {
seat->touchMove(kwaylandId, pos);
}
@ -808,10 +809,10 @@ public:
}
auto seat = waylandServer()->seat();
seat->setTimestamp(time);
const qint32 kwaylandId = input()->touchId(id);
const qint32 kwaylandId = input()->touch()->mappedId(id);
if (kwaylandId != -1) {
seat->touchUp(kwaylandId);
input()->removeTouchId(id);
input()->touch()->removeId(id);
}
return true;
}
@ -822,6 +823,7 @@ KWIN_SINGLETON_FACTORY(InputRedirection)
InputRedirection::InputRedirection(QObject *parent)
: QObject(parent)
, m_pointer(new PointerInputRedirection(this))
, m_touch(new TouchInputRedirection(this))
, m_xkb(new Xkb(this))
, m_shortcuts(new GlobalShortcutsManager(this))
{
@ -930,15 +932,9 @@ void InputRedirection::setupWorkspace()
connect(workspace(), &Workspace::configChanged, this, &InputRedirection::reconfigure);
m_pointer->init();
m_touch->init();
connect(ScreenLocker::KSldApp::self(), &ScreenLocker::KSldApp::lockStateChanged, this, &InputRedirection::updateKeyboardWindow);
connect(ScreenLocker::KSldApp::self(), &ScreenLocker::KSldApp::lockStateChanged, this,
[this] {
cancelTouch();
// position doesn't matter
updateTouchWindow(QPointF());
}
);
}
setupInputFilters();
}
@ -1022,11 +1018,11 @@ void InputRedirection::setupLibInput()
m_pointer->processMotion(screen, time);
}
);
connect(conn, &LibInput::Connection::touchDown, this, &InputRedirection::processTouchDown);
connect(conn, &LibInput::Connection::touchUp, this, &InputRedirection::processTouchUp);
connect(conn, &LibInput::Connection::touchMotion, this, &InputRedirection::processTouchMotion);
connect(conn, &LibInput::Connection::touchCanceled, this, &InputRedirection::cancelTouch);
connect(conn, &LibInput::Connection::touchFrame, this, &InputRedirection::touchFrame);
connect(conn, &LibInput::Connection::touchDown, m_touch, &TouchInputRedirection::processDown);
connect(conn, &LibInput::Connection::touchUp, m_touch, &TouchInputRedirection::processUp);
connect(conn, &LibInput::Connection::touchMotion, m_touch, &TouchInputRedirection::processMotion);
connect(conn, &LibInput::Connection::touchCanceled, m_touch, &TouchInputRedirection::cancel);
connect(conn, &LibInput::Connection::touchFrame, m_touch, &TouchInputRedirection::frame);
if (screens()) {
setupLibInputWithScreens();
} else {
@ -1087,19 +1083,6 @@ void InputRedirection::setupLibInputWithScreens()
#endif
}
void InputRedirection::updateFocusedTouchPosition()
{
if (m_touchWindow.isNull()) {
return;
}
if (auto seat = findSeat()) {
if (m_touchWindow.data()->surface() != seat->focusedTouchSurface()) {
return;
}
seat->setFocusedTouchSurfacePosition(m_touchWindow.data()->pos());
}
}
void InputRedirection::processPointerMotion(const QPointF &pos, uint32_t time)
{
m_pointer->processMotion(pos, time);
@ -1200,92 +1183,27 @@ void InputRedirection::processKeymapChange(int fd, uint32_t size)
void InputRedirection::processTouchDown(qint32 id, const QPointF &pos, quint32 time)
{
for (auto it = m_filters.constBegin(), end = m_filters.constEnd(); it != end; it++) {
if ((*it)->touchDown(id, pos, time)) {
return;
}
}
m_touch->processDown(id, pos, time);
}
void InputRedirection::updateTouchWindow(const QPointF &pos)
{
// TODO: handle pointer grab aka popups
Toplevel *t = findToplevel(pos.toPoint());
auto oldWindow = m_touchWindow;
if (!oldWindow.isNull() && t == oldWindow.data()) {
return;
}
if (auto seat = findSeat()) {
// disconnect old surface
if (oldWindow) {
disconnect(oldWindow.data(), &Toplevel::geometryChanged, this, &InputRedirection::updateFocusedTouchPosition);
}
if (t && t->surface()) {
seat->setFocusedTouchSurface(t->surface(), t->pos());
connect(t, &Toplevel::geometryChanged, this, &InputRedirection::updateFocusedTouchPosition);
} else {
seat->setFocusedTouchSurface(nullptr);
t = nullptr;
}
}
if (!t) {
m_touchWindow.clear();
return;
}
m_touchWindow = QWeakPointer<Toplevel>(t);
}
void InputRedirection::processTouchUp(qint32 id, quint32 time)
{
for (auto it = m_filters.constBegin(), end = m_filters.constEnd(); it != end; it++) {
if ((*it)->touchUp(id, time)) {
return;
}
}
m_touch->processUp(id, time);
}
void InputRedirection::processTouchMotion(qint32 id, const QPointF &pos, quint32 time)
{
for (auto it = m_filters.constBegin(), end = m_filters.constEnd(); it != end; it++) {
if ((*it)->touchMotion(id, pos, time)) {
return;
}
}
m_touch->processMotion(id, pos, time);
}
void InputRedirection::cancelTouch()
{
if (auto seat = findSeat()) {
seat->cancelTouchSequence();
}
m_touchIdMapper.clear();
m_touch->cancel();
}
void InputRedirection::touchFrame()
{
if (auto seat = findSeat()) {
seat->touchFrame();
}
}
void InputRedirection::insertTouchId(quint32 internalId, qint32 kwaylandId)
{
m_touchIdMapper.insert(internalId, kwaylandId);
}
qint32 InputRedirection::touchId(quint32 internalId)
{
auto it = input()->m_touchIdMapper.constFind(internalId);
if (it != input()->m_touchIdMapper.constEnd()) {
return it.value();
}
return -1;
}
void InputRedirection::removeTouchId(quint32 internalId)
{
m_touchIdMapper.remove(internalId);
m_touch->frame();
}
Qt::MouseButtons InputRedirection::qtButtonStates() const

18
input.h
View file

@ -45,6 +45,7 @@ class Toplevel;
class Xkb;
class InputEventFilter;
class PointerInputRedirection;
class TouchInputRedirection;
namespace Decoration
{
@ -144,12 +145,8 @@ public:
GlobalShortcutsManager *shortcuts() const {
return m_shortcuts;
}
void insertTouchId(quint32 internalId, qint32 kwaylandId);
qint32 touchId(quint32 internalId);
void removeTouchId(quint32 internalId);
void updateKeyboardWindow();
void updateTouchWindow(const QPointF &pos);
QVector<InputEventFilter*> filters() const {
return m_filters;
@ -157,6 +154,9 @@ public:
PointerInputRedirection *pointer() const {
return m_pointer;
}
TouchInputRedirection *touch() const {
return m_touch;
}
Q_SIGNALS:
/**
@ -201,21 +201,13 @@ private:
void setupLibInput();
void setupLibInputWithScreens();
void registerShortcutForGlobalAccelTimestamp(QAction *action);
void updateFocusedTouchPosition();
void setupWorkspace();
void reconfigure();
void setupInputFilters();
void installInputEventFilter(InputEventFilter *filter);
PointerInputRedirection *m_pointer;
TouchInputRedirection *m_touch;
QScopedPointer<Xkb> m_xkb;
/**
* @brief The Toplevel which currently receives touch events
*/
QWeakPointer<Toplevel> m_touchWindow;
/**
* external/kwayland
**/
QHash<qint32, qint32> m_touchIdMapper;
GlobalShortcutsManager *m_shortcuts;

171
touch_input.cpp Normal file
View file

@ -0,0 +1,171 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2013, 2016 Martin Gräßlin <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "touch_input.h"
#include "input.h"
#include "toplevel.h"
#include "wayland_server.h"
// KWayland
#include <KWayland/Server/seat_interface.h>
// screenlocker
#include <KScreenLocker/KsldApp>
namespace KWin
{
TouchInputRedirection::TouchInputRedirection(InputRedirection *parent)
: QObject(parent)
, m_input(parent)
{
}
TouchInputRedirection::~TouchInputRedirection() = default;
void TouchInputRedirection::init()
{
Q_ASSERT(!m_inited);
m_inited = true;
connect(ScreenLocker::KSldApp::self(), &ScreenLocker::KSldApp::lockStateChanged, this,
[this] {
cancel();
// position doesn't matter
update();
}
);
}
void TouchInputRedirection::update(const QPointF &pos)
{
if (!m_inited) {
return;
}
// TODO: handle pointer grab aka popups
Toplevel *t = m_input->findToplevel(pos.toPoint());
auto oldWindow = m_window;
if (!oldWindow.isNull() && t == oldWindow.data()) {
return;
}
auto seat = waylandServer()->seat();
// disconnect old surface
if (oldWindow) {
disconnect(m_windowGeometryConnection);
m_windowGeometryConnection = QMetaObject::Connection();
}
if (t && t->surface()) {
seat->setFocusedTouchSurface(t->surface(), t->pos());
m_windowGeometryConnection = connect(t, &Toplevel::geometryChanged, this,
[this] {
if (m_window.isNull()) {
return;
}
auto seat = waylandServer()->seat();
if (m_window.data()->surface() != seat->focusedTouchSurface()) {
return;
}
seat->setFocusedTouchSurfacePosition(m_window.data()->pos());
}
);
} else {
seat->setFocusedTouchSurface(nullptr);
t = nullptr;
}
if (!t) {
m_window.clear();
return;
}
m_window = QPointer<Toplevel>(t);
}
void TouchInputRedirection::insertId(quint32 internalId, qint32 kwaylandId)
{
m_idMapper.insert(internalId, kwaylandId);
}
qint32 TouchInputRedirection::mappedId(quint32 internalId)
{
auto it = m_idMapper.constFind(internalId);
if (it != m_idMapper.constEnd()) {
return it.value();
}
return -1;
}
void TouchInputRedirection::removeId(quint32 internalId)
{
m_idMapper.remove(internalId);
}
void TouchInputRedirection::processDown(qint32 id, const QPointF &pos, quint32 time)
{
if (!m_inited) {
return;
}
const auto &filters = m_input->filters();
for (auto it = filters.begin(), end = filters.end(); it != end; it++) {
if ((*it)->touchDown(id, pos, time)) {
return;
}
}
}
void TouchInputRedirection::processUp(qint32 id, quint32 time)
{
if (!m_inited) {
return;
}
const auto &filters = m_input->filters();
for (auto it = filters.begin(), end = filters.end(); it != end; it++) {
if ((*it)->touchUp(id, time)) {
return;
}
}
}
void TouchInputRedirection::processMotion(qint32 id, const QPointF &pos, quint32 time)
{
if (!m_inited) {
return;
}
const auto &filters = m_input->filters();
for (auto it = filters.begin(), end = filters.end(); it != end; it++) {
if ((*it)->touchMotion(id, pos, time)) {
return;
}
}
}
void TouchInputRedirection::cancel()
{
if (!m_inited) {
return;
}
waylandServer()->seat()->cancelTouchSequence();
m_idMapper.clear();
}
void TouchInputRedirection::frame()
{
if (!m_inited) {
return;
}
waylandServer()->seat()->touchFrame();
}
}

77
touch_input.h Normal file
View file

@ -0,0 +1,77 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2013, 2016 Martin Gräßlin <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#ifndef KWIN_TOUCH_INPUT_H
#define KWIN_TOUCH_INPUT_H
#include <QHash>
#include <QObject>
#include <QPointer>
#include <QPointF>
namespace KWin
{
class InputRedirection;
class Toplevel;
class TouchInputRedirection : public QObject
{
Q_OBJECT
public:
explicit TouchInputRedirection(InputRedirection *parent);
virtual ~TouchInputRedirection();
void update(const QPointF &pos = QPointF());
void init();
void processDown(qint32 id, const QPointF &pos, quint32 time);
void processUp(qint32 id, quint32 time);
void processMotion(qint32 id, const QPointF &pos, quint32 time);
void cancel();
void frame();
void insertId(quint32 internalId, qint32 kwaylandId);
void removeId(quint32 internalId);
qint32 mappedId(quint32 internalId);
/**
* @brief The Toplevel which currently receives touch events
*/
QPointer<Toplevel> window() const {
return m_window;
}
private:
InputRedirection *m_input;
bool m_inited = false;
/**
* @brief The Toplevel which currently receives touch events
*/
QPointer<Toplevel> m_window;
/**
* external/kwayland
**/
QHash<qint32, qint32> m_idMapper;
QMetaObject::Connection m_windowGeometryConnection;
};
}
#endif