diff options
Diffstat (limited to 'src')
9 files changed, 221 insertions, 9 deletions
diff --git a/src/platformsupport/input/evdevtouch/evdevtouch.pri b/src/platformsupport/input/evdevtouch/evdevtouch.pri index c2edc13143..44eb9da113 100644 --- a/src/platformsupport/input/evdevtouch/evdevtouch.pri +++ b/src/platformsupport/input/evdevtouch/evdevtouch.pri @@ -6,6 +6,8 @@ SOURCES += \ $$PWD/qevdevtouchhandler.cpp \ $$PWD/qevdevtouchmanager.cpp +INCLUDEPATH += $$PWD/../shared + contains(QT_CONFIG, libudev) { LIBS_PRIVATE += $$QMAKE_LIBS_LIBUDEV } @@ -14,4 +16,3 @@ contains(QT_CONFIG, mtdev) { CONFIG += link_pkgconfig PKGCONFIG_PRIVATE += mtdev } - diff --git a/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp b/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp index 6b98ed30a9..5f9455559d 100644 --- a/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp +++ b/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qevdevtouchhandler_p.h" +#include "qtouchoutputmapping_p.h" #include <QStringList> #include <QHash> #include <QSocketNotifier> @@ -116,6 +117,7 @@ public: int findClosestContact(const QHash<int, Contact> &contacts, int x, int y, int *dist); void addTouchPoint(const Contact &contact, Qt::TouchPointStates *combinedStates); void reportPoints(); + void loadMultiScreenMappings(); int hw_range_x_min; int hw_range_x_max; @@ -124,10 +126,12 @@ public: int hw_pressure_min; int hw_pressure_max; QString hw_name; + QString deviceNode; bool m_forceToActiveWindow; bool m_typeB; QTransform m_rotate; bool m_singleTouch; + int m_screenIndex; }; QEvdevTouchScreenData::QEvdevTouchScreenData(QEvdevTouchScreenHandler *q_ptr, const QStringList &args) @@ -137,7 +141,8 @@ QEvdevTouchScreenData::QEvdevTouchScreenData(QEvdevTouchScreenHandler *q_ptr, co hw_range_x_min(0), hw_range_x_max(0), hw_range_y_min(0), hw_range_y_max(0), hw_pressure_min(0), hw_pressure_max(0), - m_typeB(false), m_singleTouch(false) + m_typeB(false), m_singleTouch(false), + m_screenIndex(-1) { m_forceToActiveWindow = args.contains(QLatin1String("force_window")); } @@ -222,7 +227,9 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &device, const } #endif - qCDebug(qLcEvdevTouch, "evdevtouch: %s: Protocol type %c %s (%s)", qPrintable(device), + d->deviceNode = device; + + qCDebug(qLcEvdevTouch, "evdevtouch: %s: Protocol type %c %s (%s)", qPrintable(d->deviceNode), d->m_typeB ? 'B' : 'A', mtdevStr, d->m_singleTouch ? "single" : "multi"); input_absinfo absInfo; @@ -292,6 +299,14 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &device, const if (inverty) d->m_rotate *= QTransform::fromTranslate(0.5, 0.5).scale(1.0, -1.0).translate(-0.5, -0.5); + QTouchOutputMapping mapping; + if (mapping.load()) { + d->m_screenIndex = mapping.screenIndexForDeviceNode(d->deviceNode); + if (d->m_screenIndex >= 0) + qCDebug(qLcEvdevTouch, "evdevtouch: Mapping device %s to screen index %d", + qPrintable(d->deviceNode), d->m_screenIndex); + } + registerTouchDevice(); } @@ -643,8 +658,23 @@ void QEvdevTouchScreenData::reportPoints() return; winRect = QHighDpi::toNativePixels(win->geometry(), win); } else { - QScreen *primary = QGuiApplication::primaryScreen(); - winRect = QHighDpi::toNativePixels(primary->geometry(), primary); + // Now it becomes tricky. Traditionally we picked the primaryScreen() + // and were done with it. But then, enter multiple screens, and + // suddenly it was all broken. + // + // For now we only support the display configuration of the KMS/DRM + // backends of eglfs. See QTouchOutputMapping. + // + // The good news it that once winRect refers to the correct screen + // geometry in the full virtual desktop space, there is nothing else + // left to do since qguiapp will handle the rest. + QScreen *screen = QGuiApplication::primaryScreen(); + if (m_screenIndex >= 0) { + const QList<QScreen *> screens = QGuiApplication::screens(); + if (m_screenIndex < screens.count()) + screen = screens.at(m_screenIndex); + } + winRect = QHighDpi::toNativePixels(screen->geometry(), screen); } const int hw_w = hw_range_x_max - hw_range_x_min; @@ -675,10 +705,12 @@ void QEvdevTouchScreenData::reportPoints() tp.pressure = (tp.pressure - hw_pressure_min) / qreal(hw_pressure_max - hw_pressure_min); } + // Let qguiapp pick the target window. QWindowSystemInterface::handleTouchEvent(Q_NULLPTR, q->touchDevice(), m_touchPoints); } + QEvdevTouchScreenHandlerThread::QEvdevTouchScreenHandlerThread(const QString &device, const QString &spec, QObject *parent) : QDaemonThread(parent), m_device(device), m_spec(spec), m_handler(Q_NULLPTR), m_touchDeviceRegistered(false) { diff --git a/src/platformsupport/input/input.pri b/src/platformsupport/input/input.pri index 3b9593eb31..5ce9e6844f 100644 --- a/src/platformsupport/input/input.pri +++ b/src/platformsupport/input/input.pri @@ -12,3 +12,7 @@ contains(QT_CONFIG, tslib) { contains(QT_CONFIG, libinput) { include($$PWD/libinput/libinput.pri) } + +contains(QT_CONFIG, evdev)|contains(QT_CONFIG, libinput) { + include($$PWD/shared/shared.pri) +} diff --git a/src/platformsupport/input/libinput/libinput.pri b/src/platformsupport/input/libinput/libinput.pri index 35d962ff3c..aeba6c725a 100644 --- a/src/platformsupport/input/libinput/libinput.pri +++ b/src/platformsupport/input/libinput/libinput.pri @@ -13,6 +13,8 @@ SOURCES += \ INCLUDEPATH += $$QMAKE_INCDIR_LIBUDEV $$QMAKE_INCDIR_LIBINPUT LIBS_PRIVATE += $$QMAKE_LIBS_LIBUDEV $$QMAKE_LIBS_LIBINPUT +INCLUDEPATH += $$PWD/../shared + contains(QT_CONFIG, xkbcommon-evdev) { INCLUDEPATH += $$QMAKE_INCDIR_XKBCOMMON_EVDEV LIBS_PRIVATE += $$QMAKE_LIBS_XKBCOMMON_EVDEV diff --git a/src/platformsupport/input/libinput/qlibinputtouch.cpp b/src/platformsupport/input/libinput/qlibinputtouch.cpp index 1e82ce5c91..42925a18e1 100644 --- a/src/platformsupport/input/libinput/qlibinputtouch.cpp +++ b/src/platformsupport/input/libinput/qlibinputtouch.cpp @@ -64,11 +64,14 @@ QLibInputTouch::DeviceState *QLibInputTouch::deviceState(libinput_event_touch *e static inline QPointF getPos(libinput_event_touch *e) { + // TODO Map to correct screen using QTouchOutputMapping. + // Perhaps investigate libinput_device_get_output_name as well. + // For now just use the primary screen. QScreen *screen = QGuiApplication::primaryScreen(); - const QSize screenSize = QHighDpi::toNativePixels(screen->geometry().size(), screen); - 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); + const QRect geom = QHighDpi::toNativePixels(screen->geometry(), screen); + 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); } void QLibInputTouch::registerDevice(libinput_device *dev) diff --git a/src/platformsupport/input/shared/qtouchoutputmapping.cpp b/src/platformsupport/input/shared/qtouchoutputmapping.cpp new file mode 100644 index 0000000000..55c1dc34f4 --- /dev/null +++ b/src/platformsupport/input/shared/qtouchoutputmapping.cpp @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qtouchoutputmapping_p.h" +#include <QFile> +#include <QVariantMap> +#include <QJsonDocument> +#include <QJsonObject> +#include <QJsonArray> + +QT_BEGIN_NAMESPACE + +bool QTouchOutputMapping::load() +{ + static QByteArray configFile = qgetenv("QT_QPA_EGLFS_KMS_CONFIG"); + if (configFile.isEmpty()) + return false; + + QFile file(QString::fromUtf8(configFile)); + if (!file.open(QFile::ReadOnly)) { + qWarning("touch input support: Failed to open %s", configFile.constData()); + return false; + } + + const QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); + if (!doc.isObject()) { + qWarning("touch input support: Failed to parse %s", configFile.constData()); + return false; + } + + // What we are interested is the virtualIndex and touchDevice properties for + // each element in the outputs array. + const QJsonArray outputs = doc.object().value(QLatin1String("outputs")).toArray(); + for (int i = 0; i < outputs.size(); ++i) { + const QVariantMap output = outputs.at(i).toObject().toVariantMap(); + if (!output.contains(QStringLiteral("touchDevice"))) + continue; + if (!output.contains(QStringLiteral("virtualIndex"))) { + qWarning("evdevtouch: Output %d specifies touchDevice but not virtualIndex, this is wrong", i); + continue; + } + const QString &deviceNode = output.value(QStringLiteral("touchDevice")).toString(); + const int screenIndex = output.value(QStringLiteral("virtualIndex")).toInt(); + m_screenIndexTable.insert(deviceNode, screenIndex); + } + + return true; +} + +int QTouchOutputMapping::screenIndexForDeviceNode(const QString &deviceNode) +{ + return m_screenIndexTable.value(deviceNode, -1); +} + +QT_END_NAMESPACE diff --git a/src/platformsupport/input/shared/qtouchoutputmapping_p.h b/src/platformsupport/input/shared/qtouchoutputmapping_p.h new file mode 100644 index 0000000000..74999d93ce --- /dev/null +++ b/src/platformsupport/input/shared/qtouchoutputmapping_p.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QTOUCHOUTPUTMAPPING_P_H +#define QTOUCHOUTPUTMAPPING_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QString> +#include <QHash> + +QT_BEGIN_NAMESPACE + +class QTouchOutputMapping +{ +public: + bool load(); + int screenIndexForDeviceNode(const QString &deviceNode); + +private: + QHash<QString, int> m_screenIndexTable; +}; + +QT_END_NAMESPACE + +#endif // QTOUCHOUTPUTMAPPING_P_H diff --git a/src/platformsupport/input/shared/shared.pri b/src/platformsupport/input/shared/shared.pri new file mode 100644 index 0000000000..1443235244 --- /dev/null +++ b/src/platformsupport/input/shared/shared.pri @@ -0,0 +1,5 @@ +HEADERS += \ + $$PWD/qtouchoutputmapping_p.h + +SOURCES += \ + $$PWD/qtouchoutputmapping.cpp diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp index 842896bbad..5944e8d51f 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp @@ -417,6 +417,9 @@ void QEglFSKmsDevice::createScreens() else pos.rx() += s->geometry().width(); qCDebug(qLcEglfsKmsDebug) << "Adding screen" << s << "to QPA with geometry" << s->geometry(); + // The order in qguiapp's screens list will match the order set by + // virtualIndex. This is not only handy but also required since for instance + // evdevtouch relies on it when performing touch device - screen mapping. qpaIntegration->addScreen(s); siblings << s; } |