diff options
Diffstat (limited to 'src/platformsupport/input/libinput/qlibinputtouch.cpp')
-rw-r--r-- | src/platformsupport/input/libinput/qlibinputtouch.cpp | 116 |
1 files changed, 64 insertions, 52 deletions
diff --git a/src/platformsupport/input/libinput/qlibinputtouch.cpp b/src/platformsupport/input/libinput/qlibinputtouch.cpp index 32d1df5b89..e3a483dc84 100644 --- a/src/platformsupport/input/libinput/qlibinputtouch.cpp +++ b/src/platformsupport/input/libinput/qlibinputtouch.cpp @@ -1,44 +1,8 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 https://www.qt.io/terms-conditions. For further -** information use the contact form at https://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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qlibinputtouch_p.h" -#include "qtouchoutputmapping_p.h" +#include "qoutputmapping_p.h" #include <libinput.h> #include <QtGui/QGuiApplication> #include <QtGui/QPointingDevice> @@ -50,12 +14,13 @@ QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(qLcLibInput) +Q_LOGGING_CATEGORY(qLcLibInputEvents, "qt.qpa.input.events") QWindowSystemInterface::TouchPoint *QLibInputTouch::DeviceState::point(int32_t slot) { const int id = qMax(0, slot); - for (int i = 0; i < m_points.count(); ++i) + for (int i = 0; i < m_points.size(); ++i) if (m_points.at(i).id == id) return &m_points[i]; @@ -68,9 +33,8 @@ QLibInputTouch::DeviceState *QLibInputTouch::deviceState(libinput_event_touch *e return &m_devState[dev]; } -QPointF QLibInputTouch::getPos(libinput_event_touch *e) +QRect QLibInputTouch::screenGeometry(DeviceState *state) { - DeviceState *state = deviceState(e); QScreen *screen = QGuiApplication::primaryScreen(); if (!state->m_screenName.isEmpty()) { if (!m_screen) { @@ -85,12 +49,45 @@ QPointF QLibInputTouch::getPos(libinput_event_touch *e) if (m_screen) screen = m_screen; } - const QRect geom = QHighDpi::toNativePixels(screen->geometry(), screen); + return screen ? QHighDpi::toNativePixels(screen->geometry(), screen) : QRect(); +} + +QPointF QLibInputTouch::getPos(libinput_event_touch *e) +{ + DeviceState *state = deviceState(e); + QRect geom = screenGeometry(state); const double x = libinput_event_touch_get_x_transformed(e, geom.width()); const double y = libinput_event_touch_get_y_transformed(e, geom.height()); return geom.topLeft() + QPointF(x, y); } +static void setMatrix(libinput_device *dev) +{ + if (libinput_device_config_calibration_has_matrix(dev)) { + QByteArray env = qgetenv("QT_QPA_LIBINPUT_TOUCH_MATRIX"); + env = env.simplified(); + if (env.size()) { + float matrix[6]; + QList<QByteArray> list = env.split(' '); + if (list.length() != 6) { + qCWarning(qLcLibInput, "matrix length %lld wrong, should be 6", list.length()); + return; + } + for (int i = 0; i < 6; i++) { + bool ok = true; + matrix[i] = list[i].toFloat(&ok); + if (!ok) { + qCWarning(qLcLibInput, "Invalid matrix entry %d %s ", i, list[i].constData()); + return; + } + } + if (libinput_device_config_calibration_set_matrix(dev, matrix) != LIBINPUT_CONFIG_STATUS_SUCCESS) + qCWarning(qLcLibInput, "Failed to set libinput calibration matrix "); + } + } else { + qCWarning(qLcLibInput, "Touch device doesn't support matrix"); + } +} void QLibInputTouch::registerDevice(libinput_device *dev) { struct udev_device *udev_device; @@ -101,20 +98,28 @@ void QLibInputTouch::registerDevice(libinput_device *dev) qCDebug(qLcLibInput, "libinput: registerDevice %s - %s", qPrintable(devNode), qPrintable(devName)); - QTouchOutputMapping mapping; - if (mapping.load()) { - m_devState[dev].m_screenName = mapping.screenNameForDeviceNode(devNode); - if (!m_devState[dev].m_screenName.isEmpty()) - qCDebug(qLcLibInput, "libinput: Mapping device %s to screen %s", - qPrintable(devNode), qPrintable(m_devState[dev].m_screenName)); + QOutputMapping *mapping = QOutputMapping::get(); + QRect geom; + if (mapping->load()) { + m_devState[dev].m_screenName = mapping->screenNameForDeviceNode(devNode); + if (!m_devState[dev].m_screenName.isEmpty()) { + geom = screenGeometry(&m_devState[dev]); + qCDebug(qLcLibInput) << "libinput: Mapping device" << devNode + << "to screen" << m_devState[dev].m_screenName + << "with geometry" << geom; + } } QPointingDevice *&td = m_devState[dev].m_touchDevice; td = new QPointingDevice(devName, udev_device_get_devnum(udev_device), QInputDevice::DeviceType::TouchScreen, QPointingDevice::PointerType::Finger, QPointingDevice::Capability::Position | QPointingDevice::Capability::Area, 16, 0); - QPointingDevicePrivate::get(td)->busId = QString::fromLocal8Bit(udev_device_get_syspath(udev_device)); // TODO is that the best to choose? + auto devPriv = QPointingDevicePrivate::get(td); + devPriv->busId = QString::fromLocal8Bit(udev_device_get_syspath(udev_device)); // TODO is that the best to choose? + if (!geom.isNull()) + devPriv->setAvailableVirtualGeometry(geom); QWindowSystemInterface::registerInputDevice(td); + setMatrix(dev); } void QLibInputTouch::unregisterDevice(libinput_device *dev) @@ -137,6 +142,7 @@ void QLibInputTouch::processTouchDown(libinput_event_touch *e) newTp.area = QRect(0, 0, 8, 8); newTp.area.moveCenter(getPos(e)); state->m_points.append(newTp); + qCDebug(qLcLibInputEvents) << "touch down" << newTp; } } @@ -156,6 +162,7 @@ void QLibInputTouch::processTouchMotion(libinput_event_touch *e) // Handle this by compressing and keeping the Pressed state until the 'frame'. if (tp->state != QEventPoint::State::Pressed && tp->state != QEventPoint::State::Released) tp->state = tmpState; + qCDebug(qLcLibInputEvents) << "touch move" << tp; } else { qWarning("Inconsistent touch state (got 'motion' without 'down')"); } @@ -170,10 +177,13 @@ void QLibInputTouch::processTouchUp(libinput_event_touch *e) tp->state = QEventPoint::State::Released; // There may not be a Frame event after the last Up. Work this around. QEventPoint::States s; - for (int i = 0; i < state->m_points.count(); ++i) + for (int i = 0; i < state->m_points.size(); ++i) s |= state->m_points.at(i).state; + qCDebug(qLcLibInputEvents) << "touch up" << s << tp; if (s == QEventPoint::State::Released) processTouchFrame(e); + else + qCDebug(qLcLibInputEvents, "waiting for all points to be released"); } else { qWarning("Inconsistent touch state (got 'up' without 'down')"); } @@ -182,6 +192,7 @@ void QLibInputTouch::processTouchUp(libinput_event_touch *e) void QLibInputTouch::processTouchCancel(libinput_event_touch *e) { DeviceState *state = deviceState(e); + qCDebug(qLcLibInputEvents) << "touch cancel" << state->m_points; if (state->m_touchDevice) QWindowSystemInterface::handleTouchCancelEvent(nullptr, state->m_touchDevice, QGuiApplication::keyboardModifiers()); else @@ -195,13 +206,14 @@ void QLibInputTouch::processTouchFrame(libinput_event_touch *e) qWarning("TouchFrame without registered device"); return; } + qCDebug(qLcLibInputEvents) << "touch frame" << state->m_points; if (state->m_points.isEmpty()) return; QWindowSystemInterface::handleTouchEvent(nullptr, state->m_touchDevice, state->m_points, QGuiApplication::keyboardModifiers()); - for (int i = 0; i < state->m_points.count(); ++i) { + for (int i = 0; i < state->m_points.size(); ++i) { QWindowSystemInterface::TouchPoint &tp(state->m_points[i]); if (tp.state == QEventPoint::State::Released) state->m_points.removeAt(i--); |