From 6d49bd766f32c357d959b7827706ff053829f9eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=81o=C5=9B?= Date: Thu, 3 Oct 2024 10:40:28 +0200 Subject: [PATCH] Introduce QVxMousePlugin Since VxWorks evdev implementation should be treated as a separate entity, extract current code for handling evdev mouse and create a separate plugin which will use VxWorks version of evdev. This will allow to separate evolution of actual evdev from VxWorks. This is a preparatory change, no mouse detection will be added with this patch yet. Task-number: QTBUG-115777 Change-Id: Icb62aeca8f091f58efd3c731eb35d6a0695a591d Reviewed-by: Karim Pinter Reviewed-by: Laszlo Agocs --- src/platformsupport/CMakeLists.txt | 2 +- src/platformsupport/input/CMakeLists.txt | 14 +- .../qvxmousehandler.cpp} | 24 +-- .../input/vxmouse/qvxmousehandler_p.h | 76 +++++++++ .../input/vxmouse/qvxmousemanager.cpp | 146 ++++++++++++++++++ .../input/vxmouse/qvxmousemanager_p.h | 58 +++++++ src/plugins/generic/CMakeLists.txt | 3 + src/plugins/generic/vxmouse/CMakeLists.txt | 20 +++ src/plugins/generic/vxmouse/main.cpp | 36 +++++ src/plugins/generic/vxmouse/vxmouse.json | 3 + .../platforms/eglfs/api/qeglfsintegration.cpp | 6 + 11 files changed, 366 insertions(+), 22 deletions(-) rename src/platformsupport/input/{evdevmouse/qevdevmousehandler_vxworks.cpp => vxmouse/qvxmousehandler.cpp} (81%) create mode 100644 src/platformsupport/input/vxmouse/qvxmousehandler_p.h create mode 100644 src/platformsupport/input/vxmouse/qvxmousemanager.cpp create mode 100644 src/platformsupport/input/vxmouse/qvxmousemanager_p.h create mode 100644 src/plugins/generic/vxmouse/CMakeLists.txt create mode 100644 src/plugins/generic/vxmouse/main.cpp create mode 100644 src/plugins/generic/vxmouse/vxmouse.json diff --git a/src/platformsupport/CMakeLists.txt b/src/platformsupport/CMakeLists.txt index 686c6213d2d..eb8128c0c8d 100644 --- a/src/platformsupport/CMakeLists.txt +++ b/src/platformsupport/CMakeLists.txt @@ -3,7 +3,7 @@ add_subdirectory(devicediscovery) add_subdirectory(fbconvenience) -if(QT_FEATURE_evdev OR QT_FEATURE_integrityhid OR QT_FEATURE_libinput OR QT_FEATURE_tslib OR QT_FEATURE_xkbcommon) +if(QT_FEATURE_evdev OR QT_FEATURE_integrityhid OR QT_FEATURE_libinput OR QT_FEATURE_tslib OR QT_FEATURE_xkbcommon OR QT_FEATURE_vxworksevdev) add_subdirectory(input) endif() if(QT_FEATURE_kms) diff --git a/src/platformsupport/input/CMakeLists.txt b/src/platformsupport/input/CMakeLists.txt index d193ad1dbd3..8e13b8317f1 100644 --- a/src/platformsupport/input/CMakeLists.txt +++ b/src/platformsupport/input/CMakeLists.txt @@ -33,7 +33,7 @@ qt_internal_extend_target(InputSupportPrivate CONDITION QT_FEATURE_evdev evdevkeyboard/qevdevkeyboard_defaultmap_p.h evdevkeyboard/qevdevkeyboardhandler.cpp evdevkeyboard/qevdevkeyboardhandler_p.h evdevkeyboard/qevdevkeyboardmanager.cpp evdevkeyboard/qevdevkeyboardmanager_p.h - evdevmouse/qevdevmousehandler_p.h + evdevmouse/qevdevmousehandler.cpp evdevmouse/qevdevmousehandler_p.h evdevmouse/qevdevmousemanager.cpp evdevmouse/qevdevmousemanager_p.h evdevtouch/qevdevtouchhandler.cpp evdevtouch/qevdevtouchhandler_p.h evdevtouch/qevdevtouchfilter_p.h @@ -63,14 +63,10 @@ qt_internal_extend_target(InputSupportPrivate CONDITION QT_FEATURE_evdev AND QT_ PkgConfig::Mtdev ) -qt_internal_extend_target(InputSupportPrivate CONDITION QT_FEATURE_evdev AND NOT VXWORKS +qt_internal_extend_target(InputSupportPrivate CONDITION QT_FEATURE_vxworksevdev SOURCES - evdevmouse/qevdevmousehandler.cpp -) - -qt_internal_extend_target(InputSupportPrivate CONDITION QT_FEATURE_evdev AND VXWORKS - SOURCES - evdevmouse/qevdevmousehandler_vxworks.cpp + vxmouse/qvxmousehandler.cpp vxmouse/qvxmousehandler_p.h + vxmouse/qvxmousemanager.cpp vxmouse/qvxmousemanager_p.h ) qt_internal_extend_target(InputSupportPrivate CONDITION QT_FEATURE_tslib @@ -98,7 +94,7 @@ qt_internal_extend_target(InputSupportPrivate CONDITION QT_FEATURE_libinput AND XKB::XKB ) -qt_internal_extend_target(InputSupportPrivate CONDITION QT_FEATURE_evdev OR QT_FEATURE_libinput +qt_internal_extend_target(InputSupportPrivate CONDITION QT_FEATURE_evdev OR QT_FEATURE_libinput OR QT_FEATURE_vxworksevdev SOURCES shared/devicehandlerlist_p.h shared/qevdevutil.cpp shared/qevdevutil_p.h diff --git a/src/platformsupport/input/evdevmouse/qevdevmousehandler_vxworks.cpp b/src/platformsupport/input/vxmouse/qvxmousehandler.cpp similarity index 81% rename from src/platformsupport/input/evdevmouse/qevdevmousehandler_vxworks.cpp rename to src/platformsupport/input/vxmouse/qvxmousehandler.cpp index 9cf0602ce3a..ba34bfeb52e 100644 --- a/src/platformsupport/input/evdevmouse/qevdevmousehandler_vxworks.cpp +++ b/src/platformsupport/input/vxmouse/qvxmousehandler.cpp @@ -1,7 +1,7 @@ // Copyright (C) 2024 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 "qevdevmousehandler_p.h" +#include "qvxmousehandler_p.h" #include #include @@ -18,11 +18,11 @@ QT_BEGIN_NAMESPACE -Q_LOGGING_CATEGORY(qLcEvdevMouse, "qt.qpa.input") +Q_LOGGING_CATEGORY(qLcVxMouse, "qt.qpa.input") -std::unique_ptr QEvdevMouseHandler::create(const QString &device, const QString &specification) +std::unique_ptr QVxMouseHandler::create(const QString &device, const QString &specification) { - qCDebug(qLcEvdevMouse) << "create mouse handler for" << device << specification; + qCDebug(qLcVxMouse) << "create mouse handler for" << device << specification; bool compression = false; int jitterLimit = 0; @@ -36,33 +36,33 @@ std::unique_ptr QEvdevMouseHandler::create(const QString &de int fd = qt_safe_open(device.toLocal8Bit().constData(), O_RDONLY | O_NONBLOCK, 0); if (fd >= 0) { - return std::unique_ptr(new QEvdevMouseHandler(device, fd, abs, compression, jitterLimit)); + return std::unique_ptr(new QVxMouseHandler(device, fd, abs, compression, jitterLimit)); } else { - qCWarning(qLcEvdevMouse) << "Cannot open mouse input device" << qPrintable(device) << ":" << strerror(errno); + qCWarning(qLcVxMouse) << "Cannot open mouse input device" << qPrintable(device) << ":" << strerror(errno); return nullptr; } } -QEvdevMouseHandler::QEvdevMouseHandler(const QString &device, int fd, bool abs, bool, int jitterLimit) +QVxMouseHandler::QVxMouseHandler(const QString &device, int fd, bool abs, bool, int jitterLimit) : m_device(device), m_fd(fd), m_notify(0), m_x(0), m_y(0), m_prevx(0), m_prevy(0), m_abs(abs), m_buttons(0), m_button(Qt::NoButton), m_eventType(QEvent::None), m_prevInvalid(true) { Q_UNUSED(jitterLimit) - setObjectName(QLatin1String("Evdev Mouse Handler")); + setObjectName(QLatin1String("VxWorksEvdev Mouse Handler")); QSocketNotifier *notifier; notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this); connect(notifier, &QSocketNotifier::activated, - this, &QEvdevMouseHandler::readMouseData); + this, &QVxMouseHandler::readMouseData); } -QEvdevMouseHandler::~QEvdevMouseHandler() +QVxMouseHandler::~QVxMouseHandler() { if (m_fd >= 0) qt_safe_close(m_fd); } -void QEvdevMouseHandler::sendMouseEvent() +void QVxMouseHandler::sendMouseEvent() { int x = m_x - m_prevx; int y = m_y - m_prevy; @@ -79,7 +79,7 @@ void QEvdevMouseHandler::sendMouseEvent() m_prevy = m_y; } -void QEvdevMouseHandler::readMouseData() +void QVxMouseHandler::readMouseData() { bool posChanged = false; bool btnChanged = false; diff --git a/src/platformsupport/input/vxmouse/qvxmousehandler_p.h b/src/platformsupport/input/vxmouse/qvxmousehandler_p.h new file mode 100644 index 00000000000..cfb4efb2ef8 --- /dev/null +++ b/src/platformsupport/input/vxmouse/qvxmousehandler_p.h @@ -0,0 +1,76 @@ +// Copyright (C) 2024 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 + +#ifndef QVXMOUSEHANDLER_P_H +#define QVXMOUSEHANDLER_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 +#include +#include +#include + +#include + +#include + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(qLcVxMouse) + +class QSocketNotifier; + +class QVxMouseHandler : public QObject +{ + Q_OBJECT +public: + static std::unique_ptr create(const QString &device, const QString &specification); + ~QVxMouseHandler(); + + void readMouseData(); + +signals: + void handleMouseEvent(int x, int y, bool abs, Qt::MouseButtons buttons, + Qt::MouseButton button, QEvent::Type type); + void handleWheelEvent(QPoint delta); + +private: + QVxMouseHandler(const QString &device, int fd, bool abs, bool compression, int jitterLimit); + + void sendMouseEvent(); + void detectHiResWheelSupport(); + + QString m_device; + int m_fd; + QSocketNotifier *m_notify = nullptr; + int m_x = 0, m_y = 0; + int m_prevx = 0, m_prevy = 0; + bool m_abs; + bool m_compression; + bool m_hiResWheel = false; + bool m_hiResHWheel = false; + Qt::MouseButtons m_buttons; + Qt::MouseButton m_button; + QEvent::Type m_eventType; + int m_jitterLimitSquared; + bool m_prevInvalid = true; + int m_hardwareWidth; + int m_hardwareHeight; + qreal m_hardwareScalerY; + qreal m_hardwareScalerX; +}; + +QT_END_NAMESPACE + +#endif // QVXMOUSEHANDLER_P_H diff --git a/src/platformsupport/input/vxmouse/qvxmousemanager.cpp b/src/platformsupport/input/vxmouse/qvxmousemanager.cpp new file mode 100644 index 00000000000..03bc3c2267a --- /dev/null +++ b/src/platformsupport/input/vxmouse/qvxmousemanager.cpp @@ -0,0 +1,146 @@ +// Copyright (C) 2024 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 "qvxmousemanager_p.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace Qt::StringLiterals; + +QVxMouseManager::QVxMouseManager(const QString &key, const QString &specification, QObject *parent) + : QObject(parent), m_x(0), m_y(0), m_xoffset(0), m_yoffset(0) +{ + Q_UNUSED(key); + + QString spec = QString::fromLocal8Bit(qgetenv("QT_QPA_VXEVDEV_MOUSE_PARAMETERS")); + + if (spec.isEmpty()) + spec = specification; + + auto parsed = QEvdevUtil::parseSpecification(spec); + m_spec = std::move(parsed.spec); + + for (const auto &arg : std::as_const(parsed.args)) { + if (arg.startsWith("xoffset="_L1)) { + m_xoffset = arg.mid(8).toInt(); + } else if (arg.startsWith("yoffset="_L1)) { + m_yoffset = arg.mid(8).toInt(); + } + } + + // add all mice for devices specified in the argument list + for (const QString &device : std::as_const(parsed.devices)) + addMouse(device); + + if (parsed.devices.isEmpty()) { + qCDebug(qLcVxMouse, "vxmouse: Using device discovery"); + if (auto deviceDiscovery = QDeviceDiscovery::create(QDeviceDiscovery::Device_Mouse | QDeviceDiscovery::Device_Touchpad, this)) { + // scan and add already connected keyboards + const QStringList devices = deviceDiscovery->scanConnectedDevices(); + for (const QString &device : devices) + addMouse(device); + + connect(deviceDiscovery, &QDeviceDiscovery::deviceDetected, + this, &QVxMouseManager::addMouse); + connect(deviceDiscovery, &QDeviceDiscovery::deviceRemoved, + this, &QVxMouseManager::removeMouse); + } + } + + QInputDeviceManager *manager = QGuiApplicationPrivate::inputDeviceManager(); + connect(manager, &QInputDeviceManager::cursorPositionChangeRequested, this, [this](const QPoint &pos) { + m_x = pos.x(); + m_y = pos.y(); + clampPosition(); + }); +} + +QVxMouseManager::~QVxMouseManager() +{ +} + +void QVxMouseManager::clampPosition() +{ + // clamp to screen geometry + QScreen *primaryScreen = QGuiApplication::primaryScreen(); + QRect g = QHighDpi::toNativePixels(primaryScreen->virtualGeometry(), primaryScreen); + if (m_x + m_xoffset < g.left()) + m_x = g.left() - m_xoffset; + else if (m_x + m_xoffset > g.right()) + m_x = g.right() - m_xoffset; + + if (m_y + m_yoffset < g.top()) + m_y = g.top() - m_yoffset; + else if (m_y + m_yoffset > g.bottom()) + m_y = g.bottom() - m_yoffset; +} + +void QVxMouseManager::handleMouseEvent(int x, int y, bool abs, Qt::MouseButtons buttons, + Qt::MouseButton button, QEvent::Type type) +{ + // update current absolute coordinates + if (!abs) { + m_x += x; + m_y += y; + } else { + m_x = x; + m_y = y; + } + + clampPosition(); + + QPoint pos(m_x + m_xoffset, m_y + m_yoffset); + // Cannot track the keyboard modifiers ourselves here. Instead, report the + // modifiers from the last key event that has been seen by QGuiApplication. + QWindowSystemInterface::handleMouseEvent(0, pos, pos, buttons, button, type, QGuiApplicationPrivate::inputDeviceManager()->keyboardModifiers()); +} + +void QVxMouseManager::handleWheelEvent(QPoint delta) +{ + QPoint pos(m_x + m_xoffset, m_y + m_yoffset); + QWindowSystemInterface::handleWheelEvent(0, pos, pos, QPoint(), delta, QGuiApplicationPrivate::inputDeviceManager()->keyboardModifiers()); +} + +void QVxMouseManager::addMouse(const QString &deviceNode) +{ + qCDebug(qLcVxMouse, "Adding mouse at %ls", qUtf16Printable(deviceNode)); + auto handler = QVxMouseHandler::create(deviceNode, m_spec); + if (handler) { + connect(handler.get(), &QVxMouseHandler::handleMouseEvent, + this, &QVxMouseManager::handleMouseEvent); + connect(handler.get(), &QVxMouseHandler::handleWheelEvent, + this, &QVxMouseManager::handleWheelEvent); + m_mice.add(deviceNode, std::move(handler)); + updateDeviceCount(); + } else { + qWarning("vxmouse: Failed to open mouse device %ls", qUtf16Printable(deviceNode)); + } +} + +void QVxMouseManager::removeMouse(const QString &deviceNode) +{ + if (m_mice.remove(deviceNode)) { + qCDebug(qLcVxMouse, "Removing mouse at %ls", qUtf16Printable(deviceNode)); + updateDeviceCount(); + } +} + +void QVxMouseManager::updateDeviceCount() +{ + QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount( + QInputDeviceManager::DeviceTypePointer, m_mice.count()); +} + +QT_END_NAMESPACE diff --git a/src/platformsupport/input/vxmouse/qvxmousemanager_p.h b/src/platformsupport/input/vxmouse/qvxmousemanager_p.h new file mode 100644 index 00000000000..211fe25fbdf --- /dev/null +++ b/src/platformsupport/input/vxmouse/qvxmousemanager_p.h @@ -0,0 +1,58 @@ +// Copyright (C) 2024 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 + +#ifndef QVXMOUSEMANAGER_P_H +#define QVXMOUSEMANAGER_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 "qvxmousehandler_p.h" + +#include + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QDeviceDiscovery; + +class QVxMouseManager : public QObject +{ +public: + QVxMouseManager(const QString &key, const QString &specification, QObject *parent = nullptr); + ~QVxMouseManager(); + + void handleMouseEvent(int x, int y, bool abs, Qt::MouseButtons buttons, + Qt::MouseButton button, QEvent::Type type); + void handleWheelEvent(QPoint delta); + + void addMouse(const QString &deviceNode = QString()); + void removeMouse(const QString &deviceNode); + +private: + void clampPosition(); + void updateDeviceCount(); + + QString m_spec; + QtInputSupport::DeviceHandlerList m_mice; + int m_x; + int m_y; + int m_xoffset; + int m_yoffset; +}; + +QT_END_NAMESPACE + +#endif // QVXMOUSEMANAGER_P_H diff --git a/src/plugins/generic/CMakeLists.txt b/src/plugins/generic/CMakeLists.txt index 6d3cf2a925e..fd67f5d3fea 100644 --- a/src/plugins/generic/CMakeLists.txt +++ b/src/plugins/generic/CMakeLists.txt @@ -9,6 +9,9 @@ endif() if(QT_FEATURE_evdev AND QT_FEATURE_tabletevent) add_subdirectory(evdevtablet) endif() +if(QT_FEATURE_vxworksevdev) + add_subdirectory(vxmouse) +endif() if(QT_FEATURE_tslib) add_subdirectory(tslib) endif() diff --git a/src/plugins/generic/vxmouse/CMakeLists.txt b/src/plugins/generic/vxmouse/CMakeLists.txt new file mode 100644 index 00000000000..2be07b6378f --- /dev/null +++ b/src/plugins/generic/vxmouse/CMakeLists.txt @@ -0,0 +1,20 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## QEvdevMousePlugin Plugin: +##################################################################### + +qt_internal_add_plugin(QVxMousePlugin + OUTPUT_NAME qvxmouseplugin + PLUGIN_TYPE generic + DEFAULT_IF FALSE + SOURCES + main.cpp + LIBRARIES + Qt::Core + Qt::CorePrivate + Qt::Gui + Qt::GuiPrivate + Qt::InputSupportPrivate +) diff --git a/src/plugins/generic/vxmouse/main.cpp b/src/plugins/generic/vxmouse/main.cpp new file mode 100644 index 00000000000..2ed9b8f0d5c --- /dev/null +++ b/src/plugins/generic/vxmouse/main.cpp @@ -0,0 +1,36 @@ +// 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 +#include + +QT_BEGIN_NAMESPACE + +class QVxMousePlugin : public QGenericPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QGenericPluginFactoryInterface_iid FILE "vxmouse.json") + +public: + QVxMousePlugin(); + + QObject* create(const QString &key, const QString &specification) override; +}; + +QVxMousePlugin::QVxMousePlugin() + : QGenericPlugin() +{ +} + +QObject* QVxMousePlugin::create(const QString &key, + const QString &specification) +{ + if (!key.compare(QLatin1String("VxMouse"), Qt::CaseInsensitive)) + return new QVxMouseManager(key, specification); + + return nullptr; +} + +QT_END_NAMESPACE + +#include "main.moc" diff --git a/src/plugins/generic/vxmouse/vxmouse.json b/src/plugins/generic/vxmouse/vxmouse.json new file mode 100644 index 00000000000..1f7bfb6545a --- /dev/null +++ b/src/plugins/generic/vxmouse/vxmouse.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "VxMouse" ] +} diff --git a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp index f0b64c475c5..f60fe28b84d 100644 --- a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp @@ -50,6 +50,10 @@ #include #endif +#if QT_CONFIG(vxworksevdev) +#include +#endif + #if QT_CONFIG(tslib) #include #endif @@ -435,6 +439,8 @@ void QEglFSIntegration::createInputHandlers() if (!useTslib) #endif new QEvdevTouchManager("EvdevTouch"_L1, QString() /* spec */, this); +#elif QT_CONFIG(vxworksevdev) + new QVxMouseManager("VxMouse"_L1, QString() /* spec */, this); #endif #if QT_CONFIG(integrityhid)