diff options
Diffstat (limited to 'src/platformsupport/input/evdevtablet')
-rw-r--r-- | src/platformsupport/input/evdevtablet/evdevtablet.pri | 6 | ||||
-rw-r--r-- | src/platformsupport/input/evdevtablet/qevdevtablethandler.cpp (renamed from src/platformsupport/input/evdevtablet/qevdevtablet.cpp) | 203 | ||||
-rw-r--r-- | src/platformsupport/input/evdevtablet/qevdevtablethandler_p.h (renamed from src/platformsupport/input/evdevtablet/qevdevtablet_p.h) | 19 | ||||
-rw-r--r-- | src/platformsupport/input/evdevtablet/qevdevtabletmanager.cpp | 122 | ||||
-rw-r--r-- | src/platformsupport/input/evdevtablet/qevdevtabletmanager_p.h | 76 |
5 files changed, 306 insertions, 120 deletions
diff --git a/src/platformsupport/input/evdevtablet/evdevtablet.pri b/src/platformsupport/input/evdevtablet/evdevtablet.pri index 5ace0df61d..fb9489353c 100644 --- a/src/platformsupport/input/evdevtablet/evdevtablet.pri +++ b/src/platformsupport/input/evdevtablet/evdevtablet.pri @@ -1,8 +1,10 @@ HEADERS += \ - $$PWD/qevdevtablet_p.h + $$PWD/qevdevtablethandler_p.h \ + $$PWD/qevdevtabletmanager_p.h SOURCES += \ - $$PWD/qevdevtablet.cpp + $$PWD/qevdevtablethandler.cpp \ + $$PWD/qevdevtabletmanager.cpp contains(QT_CONFIG, libudev) { LIBS_PRIVATE += $$QMAKE_LIBS_LIBUDEV diff --git a/src/platformsupport/input/evdevtablet/qevdevtablet.cpp b/src/platformsupport/input/evdevtablet/qevdevtablethandler.cpp index c6f952c64d..aa87340112 100644 --- a/src/platformsupport/input/evdevtablet/qevdevtablet.cpp +++ b/src/platformsupport/input/evdevtablet/qevdevtablethandler.cpp @@ -31,14 +31,14 @@ ** ****************************************************************************/ -#include "qevdevtablet_p.h" -#include <qpa/qwindowsysteminterface.h> +#include "qevdevtablethandler_p.h" + #include <QStringList> #include <QSocketNotifier> #include <QGuiApplication> #include <QLoggingCategory> #include <QtCore/private/qcore_unix_p.h> -#include <QtPlatformSupport/private/qdevicediscovery_p.h> +#include <qpa/qwindowsysteminterface.h> #include <linux/input.h> QT_BEGIN_NAMESPACE @@ -49,16 +49,11 @@ class QEvdevTabletData { public: QEvdevTabletData(QEvdevTabletHandler *q_ptr); - bool queryLimits(); - void testGrab(); + void processInputEvent(input_event *ev); - void reportProximityEnter(); - void reportProximityLeave(); void report(); QEvdevTabletHandler *q; - QSocketNotifier *notifier; - int fd; int lastEventType; QString devName; struct { @@ -73,57 +68,13 @@ public: }; QEvdevTabletData::QEvdevTabletData(QEvdevTabletHandler *q_ptr) - : q(q_ptr), notifier(0), fd(-1), lastEventType(0) + : q(q_ptr), lastEventType(0) { memset(&minValues, 0, sizeof(minValues)); memset(&maxValues, 0, sizeof(maxValues)); memset(&state, 0, sizeof(state)); } -bool QEvdevTabletData::queryLimits() -{ - bool ok = true; - input_absinfo absInfo; - memset(&absInfo, 0, sizeof(input_absinfo)); - ok &= ioctl(fd, EVIOCGABS(ABS_X), &absInfo) >= 0; - if (ok) { - minValues.x = absInfo.minimum; - maxValues.x = absInfo.maximum; - qCDebug(qLcEvdevTablet, "evdevtablet: min X: %d max X: %d", minValues.x, maxValues.x); - } - ok &= ioctl(fd, EVIOCGABS(ABS_Y), &absInfo) >= 0; - if (ok) { - minValues.y = absInfo.minimum; - maxValues.y = absInfo.maximum; - qCDebug(qLcEvdevTablet, "evdevtablet: min Y: %d max Y: %d", minValues.y, maxValues.y); - } - if (ioctl(fd, EVIOCGABS(ABS_PRESSURE), &absInfo) >= 0) { - minValues.p = absInfo.minimum; - maxValues.p = absInfo.maximum; - qCDebug(qLcEvdevTablet, "evdevtablet: min pressure: %d max pressure: %d", minValues.p, maxValues.p); - } - if (ioctl(fd, EVIOCGABS(ABS_DISTANCE), &absInfo) >= 0) { - minValues.d = absInfo.minimum; - maxValues.d = absInfo.maximum; - qCDebug(qLcEvdevTablet, "evdevtablet: min distance: %d max distance: %d", minValues.d, maxValues.d); - } - char name[128]; - if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), name) >= 0) { - devName = QString::fromLocal8Bit(name); - qCDebug(qLcEvdevTablet, "evdevtablet: device name: %s", name); - } - return ok; -} - -void QEvdevTabletData::testGrab() -{ - bool grabSuccess = !ioctl(fd, EVIOCGRAB, (void *) 1); - if (grabSuccess) - ioctl(fd, EVIOCGRAB, (void *) 0); - else - qWarning("evdevtablet: ERROR: The device is grabbed by another process. No events will be read."); -} - void QEvdevTabletData::processInputEvent(input_event *ev) { if (ev->type == EV_ABS) { @@ -167,20 +118,10 @@ void QEvdevTabletData::processInputEvent(input_event *ev) lastEventType = ev->type; } -void QEvdevTabletData::reportProximityEnter() -{ - QWindowSystemInterface::handleTabletEnterProximityEvent(QTabletEvent::Stylus, state.tool, 1); -} - -void QEvdevTabletData::reportProximityLeave() -{ - QWindowSystemInterface::handleTabletLeaveProximityEvent(QTabletEvent::Stylus, state.tool, 1); -} - void QEvdevTabletData::report() { if (!state.lastReportTool && state.tool) - reportProximityEnter(); + QWindowSystemInterface::handleTabletEnterProximityEvent(QTabletEvent::Stylus, state.tool, q->deviceId()); qreal nx = (state.x - minValues.x) / qreal(maxValues.x - minValues.x); qreal ny = (state.y - minValues.y) / qreal(maxValues.y - minValues.y); @@ -194,16 +135,17 @@ void QEvdevTabletData::report() pointer = state.lastReportTool; } - qreal pressure = (state.p - minValues.p) / qreal(maxValues.p - minValues.p); + int pressureRange = maxValues.p - minValues.p; + qreal pressure = pressureRange ? (state.p - minValues.p) / qreal(pressureRange) : qreal(1); if (state.down || state.lastReportDown) { QWindowSystemInterface::handleTabletEvent(0, state.down, QPointF(), globalPos, QTabletEvent::Stylus, pointer, - pressure, 0, 0, 0, 0, 0, 1, qGuiApp->keyboardModifiers()); + pressure, 0, 0, 0, 0, 0, q->deviceId(), qGuiApp->keyboardModifiers()); } if (state.lastReportTool && !state.tool) - reportProximityLeave(); + QWindowSystemInterface::handleTabletLeaveProximityEvent(QTabletEvent::Stylus, state.tool, q->deviceId()); state.lastReportDown = state.down; state.lastReportTool = state.tool; @@ -211,69 +153,104 @@ void QEvdevTabletData::report() } -QEvdevTabletHandler::QEvdevTabletHandler(const QString &spec, QObject *parent) - : QObject(parent), d(0) +QEvdevTabletHandler::QEvdevTabletHandler(const QString &device, const QString &spec, QObject *parent) + : QObject(parent), m_fd(-1), m_device(device), m_notifier(0), d(0) { + Q_UNUSED(spec) + setObjectName(QLatin1String("Evdev Tablet Handler")); - d = new QEvdevTabletData(this); - QString dev; - QStringList args = spec.split(QLatin1Char(':')); - for (int i = 0; i < args.count(); ++i) { - if (args.at(i).startsWith(QLatin1String("/dev/"))) { - dev = args.at(i); - break; - } - } - if (dev.isEmpty()) { - QScopedPointer<QDeviceDiscovery> deviceDiscovery( - QDeviceDiscovery::create(QDeviceDiscovery::Device_Tablet, this)); - if (deviceDiscovery) { - QStringList devices = deviceDiscovery->scanConnectedDevices(); - if (!devices.isEmpty()) - dev = devices.at(0); - } - } - if (!dev.isEmpty()) { - qCDebug(qLcEvdevTablet, "evdevtablet: using %s", qPrintable(dev)); - d->fd = QT_OPEN(dev.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0); - if (d->fd >= 0) { - d->testGrab(); - if (d->queryLimits()) { - d->notifier = new QSocketNotifier(d->fd, QSocketNotifier::Read, this); - connect(d->notifier, SIGNAL(activated(int)), this, SLOT(readData())); - } - } else { - qErrnoWarning(errno, "evdevtablet: Cannot open input device"); - } + + qCDebug(qLcEvdevTablet, "evdevtablet: using %s", qPrintable(device)); + + m_fd = QT_OPEN(device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0); + if (m_fd < 0) { + qErrnoWarning(errno, "evdevtablet: Cannot open input device %s", qPrintable(device)); + return; } + + bool grabSuccess = !ioctl(m_fd, EVIOCGRAB, (void *) 1); + if (grabSuccess) + ioctl(m_fd, EVIOCGRAB, (void *) 0); + else + qWarning("evdevtablet: %s: The device is grabbed by another process. No events will be read.", qPrintable(device)); + + d = new QEvdevTabletData(this); + if (!queryLimits()) + qWarning("evdevtablet: %s: Unset or invalid ABS limits. Behavior will be unspecified.", qPrintable(device)); + + m_notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this); + connect(m_notifier, &QSocketNotifier::activated, this, &QEvdevTabletHandler::readData); } QEvdevTabletHandler::~QEvdevTabletHandler() { - delete d->notifier; - if (d->fd >= 0) - QT_CLOSE(d->fd); + if (m_fd >= 0) + QT_CLOSE(m_fd); delete d; } +qint64 QEvdevTabletHandler::deviceId() const +{ + return m_fd; +} + +bool QEvdevTabletHandler::queryLimits() +{ + bool ok = true; + input_absinfo absInfo; + memset(&absInfo, 0, sizeof(input_absinfo)); + ok &= ioctl(m_fd, EVIOCGABS(ABS_X), &absInfo) >= 0; + if (ok) { + d->minValues.x = absInfo.minimum; + d->maxValues.x = absInfo.maximum; + qCDebug(qLcEvdevTablet, "evdevtablet: %s: min X: %d max X: %d", qPrintable(m_device), + d->minValues.x, d->maxValues.x); + } + ok &= ioctl(m_fd, EVIOCGABS(ABS_Y), &absInfo) >= 0; + if (ok) { + d->minValues.y = absInfo.minimum; + d->maxValues.y = absInfo.maximum; + qCDebug(qLcEvdevTablet, "evdevtablet: %s: min Y: %d max Y: %d", qPrintable(m_device), + d->minValues.y, d->maxValues.y); + } + if (ioctl(m_fd, EVIOCGABS(ABS_PRESSURE), &absInfo) >= 0) { + d->minValues.p = absInfo.minimum; + d->maxValues.p = absInfo.maximum; + qCDebug(qLcEvdevTablet, "evdevtablet: %s: min pressure: %d max pressure: %d", qPrintable(m_device), + d->minValues.p, d->maxValues.p); + } + if (ioctl(m_fd, EVIOCGABS(ABS_DISTANCE), &absInfo) >= 0) { + d->minValues.d = absInfo.minimum; + d->maxValues.d = absInfo.maximum; + qCDebug(qLcEvdevTablet, "evdevtablet: %s: min distance: %d max distance: %d", qPrintable(m_device), + d->minValues.d, d->maxValues.d); + } + char name[128]; + if (ioctl(m_fd, EVIOCGNAME(sizeof(name) - 1), name) >= 0) { + d->devName = QString::fromLocal8Bit(name); + qCDebug(qLcEvdevTablet, "evdevtablet: %s: device name: %s", qPrintable(m_device), name); + } + return ok; +} + void QEvdevTabletHandler::readData() { static input_event buffer[32]; int n = 0; for (; ;) { - int result = QT_READ(d->fd, reinterpret_cast<char*>(buffer) + n, sizeof(buffer) - n); + int result = QT_READ(m_fd, reinterpret_cast<char*>(buffer) + n, sizeof(buffer) - n); if (!result) { - qWarning("evdevtablet: Got EOF from input device"); + qWarning("evdevtablet: %s: Got EOF from input device", qPrintable(m_device)); return; } else if (result < 0) { if (errno != EINTR && errno != EAGAIN) { - qErrnoWarning(errno, "evdevtablet: Could not read from input device"); + qErrnoWarning(errno, "evdevtablet: %s: Could not read from input device", qPrintable(m_device)); if (errno == ENODEV) { // device got disconnected -> stop reading - delete d->notifier; - d->notifier = 0; - QT_CLOSE(d->fd); - d->fd = -1; + delete m_notifier; + m_notifier = 0; + QT_CLOSE(m_fd); + m_fd = -1; } return; } @@ -291,8 +268,8 @@ void QEvdevTabletHandler::readData() } -QEvdevTabletHandlerThread::QEvdevTabletHandlerThread(const QString &spec, QObject *parent) - : QDaemonThread(parent), m_spec(spec), m_handler(0) +QEvdevTabletHandlerThread::QEvdevTabletHandlerThread(const QString &device, const QString &spec, QObject *parent) + : QDaemonThread(parent), m_device(device), m_spec(spec), m_handler(0) { start(); } @@ -305,7 +282,7 @@ QEvdevTabletHandlerThread::~QEvdevTabletHandlerThread() void QEvdevTabletHandlerThread::run() { - m_handler = new QEvdevTabletHandler(m_spec); + m_handler = new QEvdevTabletHandler(m_device, m_spec); exec(); delete m_handler; m_handler = 0; diff --git a/src/platformsupport/input/evdevtablet/qevdevtablet_p.h b/src/platformsupport/input/evdevtablet/qevdevtablethandler_p.h index f546f9a88a..4a9b2bab34 100644 --- a/src/platformsupport/input/evdevtablet/qevdevtablet_p.h +++ b/src/platformsupport/input/evdevtablet/qevdevtablethandler_p.h @@ -31,8 +31,8 @@ ** ****************************************************************************/ -#ifndef QEVDEVTABLET_P_H -#define QEVDEVTABLET_P_H +#ifndef QEVDEVTABLETHANDLER_P_H +#define QEVDEVTABLETHANDLER_P_H // // W A R N I N G @@ -52,6 +52,7 @@ QT_BEGIN_NAMESPACE +class QSocketNotifier; class QEvdevTabletData; class QEvdevTabletHandler : public QObject @@ -59,29 +60,37 @@ class QEvdevTabletHandler : public QObject Q_OBJECT public: - explicit QEvdevTabletHandler(const QString &spec = QString(), QObject *parent = 0); + explicit QEvdevTabletHandler(const QString &device, const QString &spec = QString(), QObject *parent = 0); ~QEvdevTabletHandler(); + qint64 deviceId() const; + private slots: void readData(); private: + bool queryLimits(); + + int m_fd; + QString m_device; + QSocketNotifier *m_notifier; QEvdevTabletData *d; }; class QEvdevTabletHandlerThread : public QDaemonThread { public: - explicit QEvdevTabletHandlerThread(const QString &spec, QObject *parent = 0); + explicit QEvdevTabletHandlerThread(const QString &device, const QString &spec, QObject *parent = 0); ~QEvdevTabletHandlerThread(); void run() Q_DECL_OVERRIDE; QEvdevTabletHandler *handler() { return m_handler; } private: + QString m_device; QString m_spec; QEvdevTabletHandler *m_handler; }; QT_END_NAMESPACE -#endif // QEVDEVTABLET_P_H +#endif // QEVDEVTABLETHANDLER_P_H diff --git a/src/platformsupport/input/evdevtablet/qevdevtabletmanager.cpp b/src/platformsupport/input/evdevtablet/qevdevtabletmanager.cpp new file mode 100644 index 0000000000..05fd6e655c --- /dev/null +++ b/src/platformsupport/input/evdevtablet/qevdevtabletmanager.cpp @@ -0,0 +1,122 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the plugins module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qevdevtabletmanager_p.h" +#include "qevdevtablethandler_p.h" + +#include <QStringList> +#include <QGuiApplication> +#include <QLoggingCategory> +#include <QtPlatformSupport/private/qdevicediscovery_p.h> +#include <private/qguiapplication_p.h> +#include <private/qinputdevicemanager_p_p.h> + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(qLcEvdevTablet) + +QEvdevTabletManager::QEvdevTabletManager(const QString &key, const QString &specification, QObject *parent) + : QObject(parent) +{ + Q_UNUSED(key); + + if (qEnvironmentVariableIsSet("QT_QPA_EVDEV_DEBUG")) + const_cast<QLoggingCategory &>(qLcEvdevTablet()).setEnabled(QtDebugMsg, true); + + QString spec = QString::fromLocal8Bit(qgetenv("QT_QPA_EVDEV_TABLET_PARAMETERS")); + + if (spec.isEmpty()) + spec = specification; + + QStringList args = spec.split(QLatin1Char(':')); + QStringList devices; + + foreach (const QString &arg, args) { + if (arg.startsWith(QLatin1String("/dev/"))) { + devices.append(arg); + args.removeAll(arg); + } + } + + // build new specification without /dev/ elements + m_spec = args.join(QLatin1Char(':')); + + foreach (const QString &device, devices) + addDevice(device); + + // when no devices specified, use device discovery to scan and monitor + if (devices.isEmpty()) { + qCDebug(qLcEvdevTablet) << "evdevtablet: Using device discovery"; + m_deviceDiscovery = QDeviceDiscovery::create(QDeviceDiscovery::Device_Tablet, this); + if (m_deviceDiscovery) { + QStringList devices = m_deviceDiscovery->scanConnectedDevices(); + foreach (const QString &device, devices) + addDevice(device); + connect(m_deviceDiscovery, SIGNAL(deviceDetected(QString)), this, SLOT(addDevice(QString))); + connect(m_deviceDiscovery, SIGNAL(deviceRemoved(QString)), this, SLOT(removeDevice(QString))); + } + } +} + +QEvdevTabletManager::~QEvdevTabletManager() +{ + qDeleteAll(m_activeDevices); +} + +void QEvdevTabletManager::addDevice(const QString &deviceNode) +{ + qCDebug(qLcEvdevTablet) << "Adding device at" << deviceNode; + QEvdevTabletHandlerThread *handler; + handler = new QEvdevTabletHandlerThread(deviceNode, m_spec); + if (handler) { + m_activeDevices.insert(deviceNode, handler); + QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount( + QInputDeviceManager::DeviceTypeTablet, m_activeDevices.count()); + } else { + qWarning("evdevtablet: Failed to open tablet device %s", qPrintable(deviceNode)); + } +} + +void QEvdevTabletManager::removeDevice(const QString &deviceNode) +{ + if (m_activeDevices.contains(deviceNode)) { + qCDebug(qLcEvdevTablet) << "Removing device at" << deviceNode; + QEvdevTabletHandlerThread *handler = m_activeDevices.value(deviceNode); + m_activeDevices.remove(deviceNode); + QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount( + QInputDeviceManager::DeviceTypeTablet, m_activeDevices.count()); + delete handler; + } +} + +QT_END_NAMESPACE diff --git a/src/platformsupport/input/evdevtablet/qevdevtabletmanager_p.h b/src/platformsupport/input/evdevtablet/qevdevtabletmanager_p.h new file mode 100644 index 0000000000..893ff03fa7 --- /dev/null +++ b/src/platformsupport/input/evdevtablet/qevdevtabletmanager_p.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QEVDEVTABLETMANAGER_P_H +#define QEVDEVTABLETMANAGER_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 <QHash> +#include <QSocketNotifier> + +QT_BEGIN_NAMESPACE + +class QDeviceDiscovery; +class QEvdevTabletHandlerThread; + +class QEvdevTabletManager : public QObject +{ + Q_OBJECT +public: + QEvdevTabletManager(const QString &key, const QString &spec, QObject *parent = 0); + ~QEvdevTabletManager(); + +private slots: + void addDevice(const QString &deviceNode); + void removeDevice(const QString &deviceNode); + +private: + QString m_spec; + QDeviceDiscovery *m_deviceDiscovery; + QHash<QString, QEvdevTabletHandlerThread *> m_activeDevices; +}; + +QT_END_NAMESPACE + +#endif // QEVDEVTABLETMANAGER_P_H |