From b8f8b2d8a0d0f4b2b61f16d47ed098ce34a0bd38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Mon, 15 Feb 2016 09:36:59 +0100 Subject: [PATCH] Split out touch related functionality from InputRedirection Similar to c044ad98bed1ee9bab8aa388cd2de5652103a9d8 this change splits all touch handling related functionality into a dedicated class called TouchInputRedirection. --- CMakeLists.txt | 1 + input.cpp | 130 +++++++----------------------------- input.h | 18 ++--- touch_input.cpp | 171 ++++++++++++++++++++++++++++++++++++++++++++++++ touch_input.h | 77 ++++++++++++++++++++++ 5 files changed, 278 insertions(+), 119 deletions(-) create mode 100644 touch_input.cpp create mode 100644 touch_input.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 08c647c292..e0a8d67cd1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -333,6 +333,7 @@ set(kwin_KDEINIT_SRCS globalshortcuts.cpp input.cpp pointer_input.cpp + touch_input.cpp netinfo.cpp placement.cpp atoms.cpp diff --git a/input.cpp b/input.cpp index 2c01b5f78e..df4b2f7124 100644 --- a/input.cpp +++ b/input.cpp @@ -19,6 +19,7 @@ along with this program. If not, see . *********************************************************************/ #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(input()->m_touchWindow.data())) { + input()->touch()->update(pos); + if (AbstractClient *c = dynamic_cast(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(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 diff --git a/input.h b/input.h index 2579e5a494..2800aa1bb7 100644 --- a/input.h +++ b/input.h @@ -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 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 m_xkb; - /** - * @brief The Toplevel which currently receives touch events - */ - QWeakPointer m_touchWindow; - /** - * external/kwayland - **/ - QHash m_touchIdMapper; GlobalShortcutsManager *m_shortcuts; diff --git a/touch_input.cpp b/touch_input.cpp new file mode 100644 index 0000000000..f2f44b8802 --- /dev/null +++ b/touch_input.cpp @@ -0,0 +1,171 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2013, 2016 Martin Gräßlin + +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 . +*********************************************************************/ +#include "touch_input.h" +#include "input.h" +#include "toplevel.h" +#include "wayland_server.h" +// KWayland +#include +// screenlocker +#include + +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(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(); +} + +} diff --git a/touch_input.h b/touch_input.h new file mode 100644 index 0000000000..d4e5e2f328 --- /dev/null +++ b/touch_input.h @@ -0,0 +1,77 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2013, 2016 Martin Gräßlin + +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 . +*********************************************************************/ +#ifndef KWIN_TOUCH_INPUT_H +#define KWIN_TOUCH_INPUT_H + +#include +#include +#include +#include + +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 window() const { + return m_window; + } + +private: + InputRedirection *m_input; + bool m_inited = false; + /** + * @brief The Toplevel which currently receives touch events + */ + QPointer m_window; + /** + * external/kwayland + **/ + QHash m_idMapper; + QMetaObject::Connection m_windowGeometryConnection; +}; + +} + +#endif