diff options
Diffstat (limited to 'src/platformsupport/input/libinput/qlibinputtouch.cpp')
-rw-r--r-- | src/platformsupport/input/libinput/qlibinputtouch.cpp | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/src/platformsupport/input/libinput/qlibinputtouch.cpp b/src/platformsupport/input/libinput/qlibinputtouch.cpp new file mode 100644 index 0000000000..72cafb0ff7 --- /dev/null +++ b/src/platformsupport/input/libinput/qlibinputtouch.cpp @@ -0,0 +1,165 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the plugins module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qlibinputtouch_p.h" +#include <libinput.h> +#include <QtGui/QGuiApplication> +#include <QtGui/QScreen> + +QT_BEGIN_NAMESPACE + +QWindowSystemInterface::TouchPoint *QLibInputTouch::DeviceState::point(int32_t slot) +{ + const int id = qMax(0, slot); + + for (int i = 0; i < m_points.count(); ++i) + if (m_points.at(i).id == id) + return &m_points[i]; + + return Q_NULLPTR; +} + +QLibInputTouch::DeviceState *QLibInputTouch::deviceState(libinput_event_touch *e) +{ + libinput_device *dev = libinput_event_get_device(libinput_event_touch_get_base_event(e)); + return &m_devState[dev]; +} + +static inline QPointF getPos(libinput_event_touch *e) +{ + const QSize screenSize = QGuiApplication::primaryScreen()->geometry().size(); + const double x = libinput_event_touch_get_x_transformed(e, screenSize.width()); + const double y = libinput_event_touch_get_y_transformed(e, screenSize.height()); + return QPointF(x, y); +} + +void QLibInputTouch::registerDevice(libinput_device *dev) +{ + QTouchDevice *&td = m_devState[dev].m_touchDevice; + td = new QTouchDevice; + td->setName(QString::fromUtf8(libinput_device_get_name(dev))); + td->setType(QTouchDevice::TouchScreen); + td->setCapabilities(QTouchDevice::Position | QTouchDevice::Area); + QWindowSystemInterface::registerTouchDevice(td); +} + +void QLibInputTouch::unregisterDevice(libinput_device *dev) +{ + Q_UNUSED(dev); + // There is no way to remove a QTouchDevice. +} + +void QLibInputTouch::processTouchDown(libinput_event_touch *e) +{ + int slot = libinput_event_touch_get_slot(e); + DeviceState *state = deviceState(e); + QWindowSystemInterface::TouchPoint *tp = state->point(slot); + if (tp) { + qWarning("Incorrect touch state"); + } else { + QWindowSystemInterface::TouchPoint newTp; + newTp.id = qMax(0, slot); + newTp.state = Qt::TouchPointPressed; + newTp.area = QRect(0, 0, 8, 8); + newTp.area.moveCenter(getPos(e)); + state->m_points.append(newTp); + } +} + +void QLibInputTouch::processTouchMotion(libinput_event_touch *e) +{ + int slot = libinput_event_touch_get_slot(e); + DeviceState *state = deviceState(e); + QWindowSystemInterface::TouchPoint *tp = state->point(slot); + if (tp) { + const QPointF p = getPos(e); + if (tp->area.center() != p) { + tp->area.moveCenter(p); + // 'down' may be followed by 'motion' within the same "frame". + // Handle this by compressing and keeping the Pressed state until the 'frame'. + if (tp->state != Qt::TouchPointPressed) + tp->state = Qt::TouchPointMoved; + } else { + tp->state = Qt::TouchPointStationary; + } + } else { + qWarning("Inconsistent touch state (got 'motion' without 'down')"); + } +} + +void QLibInputTouch::processTouchUp(libinput_event_touch *e) +{ + int slot = libinput_event_touch_get_slot(e); + DeviceState *state = deviceState(e); + QWindowSystemInterface::TouchPoint *tp = state->point(slot); + if (tp) { + tp->state = Qt::TouchPointReleased; + // There may not be a Frame event after the last Up. Work this around. + Qt::TouchPointStates s = 0; + for (int i = 0; i < state->m_points.count(); ++i) + s |= state->m_points.at(i).state; + if (s == Qt::TouchPointReleased) + processTouchFrame(e); + } else { + qWarning("Inconsistent touch state (got 'up' without 'down')"); + } +} + +void QLibInputTouch::processTouchCancel(libinput_event_touch *e) +{ + DeviceState *state = deviceState(e); + if (state->m_touchDevice) + QWindowSystemInterface::handleTouchCancelEvent(Q_NULLPTR, state->m_touchDevice, QGuiApplication::keyboardModifiers()); + else + qWarning("TouchCancel without registered device"); +} + +void QLibInputTouch::processTouchFrame(libinput_event_touch *e) +{ + DeviceState *state = deviceState(e); + if (state->m_touchDevice && !state->m_points.isEmpty()) { + QWindowSystemInterface::handleTouchEvent(Q_NULLPTR, state->m_touchDevice, state->m_points, + QGuiApplication::keyboardModifiers()); + for (int i = 0; i < state->m_points.count(); ++i) { + QWindowSystemInterface::TouchPoint &tp(state->m_points[i]); + if (tp.state == Qt::TouchPointReleased) + state->m_points.removeAt(i--); + else if (tp.state == Qt::TouchPointPressed) + tp.state = Qt::TouchPointStationary; + } + } else { + qWarning("TouchFrame without registered device"); + } +} + +QT_END_NAMESPACE |