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 <karim.pinter@qt.io>
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
This commit is contained in:
Michał Łoś 2024-10-03 10:40:28 +02:00
parent 3bd189ab7b
commit 6d49bd766f
11 changed files with 366 additions and 22 deletions

View File

@ -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)

View File

@ -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

View File

@ -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 <QGuiApplication>
#include <QLoggingCategory>
@ -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> QEvdevMouseHandler::create(const QString &device, const QString &specification)
std::unique_ptr<QVxMouseHandler> 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> 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<QEvdevMouseHandler>(new QEvdevMouseHandler(device, fd, abs, compression, jitterLimit));
return std::unique_ptr<QVxMouseHandler>(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;

View File

@ -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 <QObject>
#include <QString>
#include <QPoint>
#include <QEvent>
#include <QLoggingCategory>
#include <private/qglobal_p.h>
#include <memory>
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(qLcVxMouse)
class QSocketNotifier;
class QVxMouseHandler : public QObject
{
Q_OBJECT
public:
static std::unique_ptr<QVxMouseHandler> 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

View File

@ -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 <QtInputSupport/private/qevdevutil_p.h>
#include <QStringList>
#include <QGuiApplication>
#include <QScreen>
#include <QLoggingCategory>
#include <qpa/qwindowsysteminterface.h>
#include <QtDeviceDiscoverySupport/private/qdevicediscovery_p.h>
#include <private/qguiapplication_p.h>
#include <private/qinputdevicemanager_p_p.h>
#include <private/qhighdpiscaling_p.h>
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

View File

@ -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 <QtInputSupport/private/devicehandlerlist_p.h>
#include <QObject>
#include <QHash>
#include <QSocketNotifier>
#include <QPoint>
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<QVxMouseHandler> m_mice;
int m_x;
int m_y;
int m_xoffset;
int m_yoffset;
};
QT_END_NAMESPACE
#endif // QVXMOUSEMANAGER_P_H

View File

@ -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()

View File

@ -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
)

View File

@ -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 <QtGui/qgenericplugin.h>
#include <QtInputSupport/private/qvxmousemanager_p.h>
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"

View File

@ -0,0 +1,3 @@
{
"Keys": [ "VxMouse" ]
}

View File

@ -50,6 +50,10 @@
#include <QtInputSupport/private/qevdevtouchmanager_p.h>
#endif
#if QT_CONFIG(vxworksevdev)
#include <QtInputSupport/private/qvxmousemanager_p.h>
#endif
#if QT_CONFIG(tslib)
#include <QtInputSupport/private/qtslib_p.h>
#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)