From 4b899a29fa5a8acc381673e6b527345f8eaad7b5 Mon Sep 17 00:00:00 2001 From: Elvis Lee Date: Thu, 24 Sep 2020 16:54:50 +0900 Subject: webOS: Support mapping evdev keyboard and touchscreen to specific window MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit First we refactor QTouchOutputMapping into a QOutputMapping base class and a QDefaultOutputMapping subclass, because it will be used to map more kinds of devices, not only touchscreens. On WebOS, the plan is to have a custom subclass that overrides an additional windowForDeviceNode() virtual function, so that events from specific devices can be sent to specific windows. But in the future, Qt may have a more generic mechanism for mapping devices to screens, and of course windows are displayed on screens; so this direct device->window mapping is likely to be temporary. In the QT_QPA_EGLFS_KMS_CONFIG JSON configuration, symlinked device nodes are now supported. Task-number: QTBUG-85268 Change-Id: Id1f0bb59f4a439abaec6bd35016c95de1cbdb26a Reviewed-by: Elvis Lee Reviewed-by: Shawn Rutledge Reviewed-by: Tor Arne Vestbø --- src/platformsupport/input/CMakeLists.txt | 2 +- .../input/evdevkeyboard/qevdevkeyboardhandler.cpp | 7 +- .../input/evdevtouch/qevdevtouchhandler.cpp | 10 +- .../input/libinput/qlibinputtouch.cpp | 34 ++++-- .../input/libinput/qlibinputtouch_p.h | 1 + .../input/shared/qoutputmapping.cpp | 129 +++++++++++++++++++++ .../input/shared/qoutputmapping_p.h | 88 ++++++++++++++ .../input/shared/qtouchoutputmapping.cpp | 91 --------------- .../input/shared/qtouchoutputmapping_p.h | 71 ------------ src/platformsupport/input/shared/shared.pri | 4 +- 10 files changed, 255 insertions(+), 182 deletions(-) create mode 100644 src/platformsupport/input/shared/qoutputmapping.cpp create mode 100644 src/platformsupport/input/shared/qoutputmapping_p.h delete mode 100644 src/platformsupport/input/shared/qtouchoutputmapping.cpp delete mode 100644 src/platformsupport/input/shared/qtouchoutputmapping_p.h (limited to 'src/platformsupport') diff --git a/src/platformsupport/input/CMakeLists.txt b/src/platformsupport/input/CMakeLists.txt index 0d6c3a34ae..12a1b22e9a 100644 --- a/src/platformsupport/input/CMakeLists.txt +++ b/src/platformsupport/input/CMakeLists.txt @@ -91,7 +91,7 @@ qt_internal_extend_target(InputSupport CONDITION QT_FEATURE_evdev OR QT_FEATURE_ SOURCES shared/devicehandlerlist_p.h shared/qevdevutil.cpp shared/qevdevutil_p.h - shared/qtouchoutputmapping.cpp shared/qtouchoutputmapping_p.h + shared/qoutputmapping.cpp shared/qoutputmapping_p.h ) qt_internal_extend_target(InputSupport CONDITION QT_FEATURE_integrityhid diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp index 788a135f9e..ec9d588aff 100644 --- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp +++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qevdevkeyboardhandler_p.h" +#include "qoutputmapping_p.h" #include @@ -240,7 +241,11 @@ void QEvdevKeyboardHandler::processKeyEvent(int nativecode, int unicode, int qtc if (!autoRepeat) QGuiApplicationPrivate::inputDeviceManager()->setKeyboardModifiers(QEvdevKeyboardHandler::toQtModifiers(m_modifiers)); - QWindowSystemInterface::handleExtendedKeyEvent(0, (isPress ? QEvent::KeyPress : QEvent::KeyRelease), + QWindow *window = nullptr; +#ifdef Q_OS_WEBOS + window = QOutputMapping::get()->windowForDeviceNode(m_device); +#endif + QWindowSystemInterface::handleExtendedKeyEvent(window, (isPress ? QEvent::KeyPress : QEvent::KeyRelease), qtcode, modifiers, nativecode + 8, 0, int(modifiers), (unicode != 0xffff ) ? QString(QChar(unicode)) : QString(), autoRepeat); } diff --git a/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp b/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp index 37b3ec7fec..0497d210e5 100644 --- a/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp +++ b/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp @@ -39,7 +39,7 @@ ****************************************************************************/ #include "qevdevtouchhandler_p.h" -#include "qtouchoutputmapping_p.h" +#include "qoutputmapping_p.h" #include #include #include @@ -350,9 +350,9 @@ 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_screenName = mapping.screenNameForDeviceNode(d->deviceNode); + QOutputMapping *mapping = QOutputMapping::get(); + d->m_screenName = mapping->screenNameForDeviceNode(d->deviceNode); + if (mapping->load()) { if (!d->m_screenName.isEmpty()) qCDebug(qLcEvdevTouch, "evdevtouch: Mapping device %ls to screen %ls", qUtf16Printable(d->deviceNode), qUtf16Printable(d->m_screenName)); @@ -728,7 +728,7 @@ QRect QEvdevTouchScreenData::screenGeometry() const // suddenly it was all broken. // // For now we only support the display configuration of the KMS/DRM - // backends of eglfs. See QTouchOutputMapping. + // backends of eglfs. See QOutputMapping. // // The good news it that once winRect refers to the correct screen // geometry in the full virtual desktop space, there is nothing else diff --git a/src/platformsupport/input/libinput/qlibinputtouch.cpp b/src/platformsupport/input/libinput/qlibinputtouch.cpp index 32d1df5b89..ed531f5773 100644 --- a/src/platformsupport/input/libinput/qlibinputtouch.cpp +++ b/src/platformsupport/input/libinput/qlibinputtouch.cpp @@ -38,7 +38,7 @@ ****************************************************************************/ #include "qlibinputtouch_p.h" -#include "qtouchoutputmapping_p.h" +#include "qoutputmapping_p.h" #include #include #include @@ -68,9 +68,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,7 +84,13 @@ QPointF QLibInputTouch::getPos(libinput_event_touch *e) if (m_screen) screen = m_screen; } - const QRect geom = QHighDpi::toNativePixels(screen->geometry(), screen); + return QHighDpi::toNativePixels(screen->geometry(), screen); +} + +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); @@ -101,19 +106,26 @@ 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); } diff --git a/src/platformsupport/input/libinput/qlibinputtouch_p.h b/src/platformsupport/input/libinput/qlibinputtouch_p.h index 175e96f583..67c20b9af6 100644 --- a/src/platformsupport/input/libinput/qlibinputtouch_p.h +++ b/src/platformsupport/input/libinput/qlibinputtouch_p.h @@ -83,6 +83,7 @@ private: }; DeviceState *deviceState(libinput_event_touch *e); + QRect screenGeometry(DeviceState *state); QPointF getPos(libinput_event_touch *e); QHash m_devState; diff --git a/src/platformsupport/input/shared/qoutputmapping.cpp b/src/platformsupport/input/shared/qoutputmapping.cpp new file mode 100644 index 0000000000..b1c428dee2 --- /dev/null +++ b/src/platformsupport/input/shared/qoutputmapping.cpp @@ -0,0 +1,129 @@ +/**************************************************************************** +** +** 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 "qoutputmapping_p.h" +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +static QOutputMapping *s_outputMapping = nullptr; + +QOutputMapping *QOutputMapping::get() +{ + if (!s_outputMapping) + s_outputMapping = new QDefaultOutputMapping; + + return s_outputMapping; +} + +bool QOutputMapping::load() +{ + return false; +} + +QString QOutputMapping::screenNameForDeviceNode(const QString &deviceNode) +{ + Q_UNUSED(deviceNode); + return QString(); +} + +#ifdef Q_OS_WEBOS +QWindow *QOutputMapping::windowForDeviceNode(const QString &deviceNode) +{ + Q_UNUSED(deviceNode); + return nullptr; +} + +void QOutputMapping::set(QOutputMapping *mapping) +{ + if (s_outputMapping) + delete s_outputMapping; + + s_outputMapping = mapping; +} +#endif // Q_OS_WEBOS + +bool QDefaultOutputMapping::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("name"))) { + qWarning("evdevtouch: Output %d specifies touchDevice but not name, this is wrong", i); + continue; + } + QFileInfo deviceNode(output.value(QStringLiteral("touchDevice")).toString()); + const QString &screenName = output.value(QStringLiteral("name")).toString(); + m_screenTable.insert(deviceNode.canonicalFilePath(), screenName); + } + + return true; +} + +QString QDefaultOutputMapping::screenNameForDeviceNode(const QString &deviceNode) +{ + return m_screenTable.value(deviceNode); +} + +QT_END_NAMESPACE diff --git a/src/platformsupport/input/shared/qoutputmapping_p.h b/src/platformsupport/input/shared/qoutputmapping_p.h new file mode 100644 index 0000000000..5376672eff --- /dev/null +++ b/src/platformsupport/input/shared/qoutputmapping_p.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** 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 QOUTPUTMAPPING_P_H +#define QOUTPUTMAPPING_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 +#include + +QT_BEGIN_NAMESPACE + +class QWindow; + +class QOutputMapping +{ +public: + virtual ~QOutputMapping() {} + + static QOutputMapping *get(); + virtual bool load(); + virtual QString screenNameForDeviceNode(const QString &deviceNode); + +#ifdef Q_OS_WEBOS + virtual QWindow *windowForDeviceNode(const QString &deviceNode); + static void set(QOutputMapping *mapping); +#endif +}; + +class QDefaultOutputMapping : public QOutputMapping +{ +public: + bool load() override; + QString screenNameForDeviceNode(const QString &deviceNode) override; + +private: + QHash m_screenTable; +}; + +QT_END_NAMESPACE + +#endif // QOUTPUTMAPPING_P_H diff --git a/src/platformsupport/input/shared/qtouchoutputmapping.cpp b/src/platformsupport/input/shared/qtouchoutputmapping.cpp deleted file mode 100644 index 0a1afd4739..0000000000 --- a/src/platformsupport/input/shared/qtouchoutputmapping.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/**************************************************************************** -** -** 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 -#include -#include -#include -#include - -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("name"))) { - qWarning("evdevtouch: Output %d specifies touchDevice but not name, this is wrong", i); - continue; - } - const QString &deviceNode = output.value(QStringLiteral("touchDevice")).toString(); - const QString &screenName = output.value(QStringLiteral("name")).toString(); - m_screenTable.insert(deviceNode, screenName); - } - - return true; -} - -QString QTouchOutputMapping::screenNameForDeviceNode(const QString &deviceNode) -{ - return m_screenTable.value(deviceNode); -} - -QT_END_NAMESPACE diff --git a/src/platformsupport/input/shared/qtouchoutputmapping_p.h b/src/platformsupport/input/shared/qtouchoutputmapping_p.h deleted file mode 100644 index 94d4dbc3b1..0000000000 --- a/src/platformsupport/input/shared/qtouchoutputmapping_p.h +++ /dev/null @@ -1,71 +0,0 @@ -/**************************************************************************** -** -** 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 -#include - -QT_BEGIN_NAMESPACE - -class QTouchOutputMapping -{ -public: - bool load(); - QString screenNameForDeviceNode(const QString &deviceNode); - -private: - QHash m_screenTable; -}; - -QT_END_NAMESPACE - -#endif // QTOUCHOUTPUTMAPPING_P_H diff --git a/src/platformsupport/input/shared/shared.pri b/src/platformsupport/input/shared/shared.pri index c29d11e7d6..73eb38c9da 100644 --- a/src/platformsupport/input/shared/shared.pri +++ b/src/platformsupport/input/shared/shared.pri @@ -1,8 +1,8 @@ HEADERS += \ $$PWD/devicehandlerlist_p.h \ $$PWD/qevdevutil_p.h \ - $$PWD/qtouchoutputmapping_p.h + $$PWD/qoutputmapping_p.h SOURCES += \ $$PWD/qevdevutil.cpp \ - $$PWD/qtouchoutputmapping.cpp + $$PWD/qoutputmapping.cpp -- cgit v1.2.3