diff options
Diffstat (limited to 'src/platformsupport/input')
21 files changed, 1384 insertions, 139 deletions
diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp index 27d15dfafa..9ce97cf373 100644 --- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp +++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp @@ -37,20 +37,18 @@ #include <QSocketNotifier> #include <QStringList> -#include <qpa/qwindowsysteminterface.h> #include <QCoreApplication> +#include <QLoggingCategory> +#include <qpa/qwindowsysteminterface.h> #include <private/qcore_unix_p.h> #include <linux/input.h> -//#define QT_QPA_KEYMAP_DEBUG - -#ifdef QT_QPA_KEYMAP_DEBUG -#include <qdebug.h> -#endif - QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(qLcEvdevKey, "qt.qpa.input") +Q_LOGGING_CATEGORY(qLcEvdevKeyMap, "qt.qpa.input.keymap") + // simple builtin US keymap #include "qevdevkeyboard_defaultmap_p.h" @@ -60,9 +58,7 @@ QEvdevKeyboardHandler::QEvdevKeyboardHandler(const QString &device, int fd, bool m_no_zap(disableZap), m_do_compose(enableCompose), m_keymap(0), m_keymap_size(0), m_keycompose(0), m_keycompose_size(0) { -#ifdef QT_QPA_KEYMAP_DEBUG - qWarning() << "Create keyboard handler with for device" << device; -#endif + qCDebug(qLcEvdevKey) << "Create keyboard handler with for device" << device; setObjectName(QLatin1String("LinuxInput Keyboard Handler")); @@ -89,9 +85,7 @@ QEvdevKeyboardHandler *QEvdevKeyboardHandler::create(const QString &device, const QString &specification, const QString &defaultKeymapFile) { -#ifdef QT_QPA_KEYMAP_DEBUG - qWarning() << "Try to create keyboard handler for" << device << specification; -#endif + qCDebug(qLcEvdevKey) << "Try to create keyboard handler for" << device << specification; QString keymapFile = defaultKeymapFile; int repeatDelay = 400; @@ -116,9 +110,7 @@ QEvdevKeyboardHandler *QEvdevKeyboardHandler::create(const QString &device, grab = arg.mid(5).toInt(); } -#ifdef QT_QPA_KEYMAP_DEBUG - qWarning() << "Opening keyboard at" << device; -#endif + qCDebug(qLcEvdevKey) << "Opening keyboard at" << device; int fd; fd = qt_safe_open(device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0); @@ -138,9 +130,7 @@ QEvdevKeyboardHandler *QEvdevKeyboardHandler::create(const QString &device, void QEvdevKeyboardHandler::switchLed(int led, bool state) { -#ifdef QT_QPA_KEYMAP_DEBUG - qWarning() << "switchLed" << led << state; -#endif + qCDebug(qLcEvdevKey) << "switchLed" << led << state; struct ::input_event led_ie; ::gettimeofday(&led_ie.time, 0); @@ -153,10 +143,6 @@ void QEvdevKeyboardHandler::switchLed(int led, bool state) void QEvdevKeyboardHandler::readKeycode() { -#ifdef QT_QPA_KEYMAP_DEBUG - qWarning() << "Read new keycode on" << m_device; -#endif - struct ::input_event buffer[32]; int n = 0; @@ -164,11 +150,11 @@ void QEvdevKeyboardHandler::readKeycode() int result = qt_safe_read(m_fd, reinterpret_cast<char *>(buffer) + n, sizeof(buffer) - n); if (result == 0) { - qWarning("Got EOF from the input device."); + qWarning("evdevkeyboard: Got EOF from the input device"); return; } else if (result < 0) { if (errno != EINTR && errno != EAGAIN) { - qWarning("Could not read from input device: %s", strerror(errno)); + qErrnoWarning(errno, "evdevkeyboard: Could not read from input device"); return; } } else { @@ -249,21 +235,17 @@ QEvdevKeyboardHandler::KeycodeAction QEvdevKeyboardHandler::processKeycode(quint if (m_locks[0] /*CapsLock*/ && map_withmod && (map_withmod->flags & QEvdevKeyboardMap::IsLetter)) modifiers ^= QEvdevKeyboardMap::ModShift; -#ifdef QT_QPA_KEYMAP_DEBUG - qWarning("Processing key event: keycode=%3d, modifiers=%02x pressed=%d, autorepeat=%d | plain=%d, withmod=%d, size=%d", \ - keycode, modifiers, pressed ? 1 : 0, autorepeat ? 1 : 0, \ - map_plain ? map_plain - m_keymap : -1, \ - map_withmod ? map_withmod - m_keymap : -1, \ - m_keymap_size); -#endif + qCDebug(qLcEvdevKeyMap, "Processing key event: keycode=%3d, modifiers=%02x pressed=%d, autorepeat=%d | plain=%d, withmod=%d, size=%d", + keycode, modifiers, pressed ? 1 : 0, autorepeat ? 1 : 0, + int(map_plain ? map_plain - m_keymap : -1), + int(map_withmod ? map_withmod - m_keymap : -1), + m_keymap_size); const QEvdevKeyboardMap::Mapping *it = map_withmod ? map_withmod : map_plain; if (!it) { -#ifdef QT_QPA_KEYMAP_DEBUG // we couldn't even find a plain mapping - qWarning("Could not find a suitable mapping for keycode: %3d, modifiers: %02x", keycode, modifiers); -#endif + qCDebug(qLcEvdevKeyMap, "Could not find a suitable mapping for keycode: %3d, modifiers: %02x", keycode, modifiers); return result; } @@ -397,9 +379,7 @@ QEvdevKeyboardHandler::KeycodeAction QEvdevKeyboardHandler::processKeycode(quint } if (!skip) { -#ifdef QT_QPA_KEYMAP_DEBUG - qWarning("Processing: uni=%04x, qt=%08x, qtmod=%08x", unicode, qtcode & ~modmask, (qtcode & modmask)); -#endif + qCDebug(qLcEvdevKeyMap, "Processing: uni=%04x, qt=%08x, qtmod=%08x", unicode, qtcode & ~modmask, (qtcode & modmask)); //If NumLockOff and keypad key pressed remap event sent if (!m_locks[1] && (qtcode & Qt::KeypadModifier) && @@ -457,9 +437,7 @@ QEvdevKeyboardHandler::KeycodeAction QEvdevKeyboardHandler::processKeycode(quint void QEvdevKeyboardHandler::unloadKeymap() { -#ifdef QT_QPA_KEYMAP_DEBUG - qWarning() << "Unload current keymap and restore built-in"; -#endif + qCDebug(qLcEvdevKey) << "Unload current keymap and restore built-in"; if (m_keymap && m_keymap != s_keymap_default) delete [] m_keymap; @@ -481,7 +459,7 @@ void QEvdevKeyboardHandler::unloadKeymap() quint16 ledbits[1]; memset(ledbits, 0, sizeof(ledbits)); if (::ioctl(m_fd, EVIOCGLED(sizeof(ledbits)), ledbits) < 0) { - qWarning("Failed to query led states. Settings numlock & capslock off"); + qWarning("evdevkeyboard: Failed to query led states"); switchLed(LED_NUML,false); switchLed(LED_CAPSL, false); switchLed(LED_SCROLLL,false); @@ -495,17 +473,13 @@ void QEvdevKeyboardHandler::unloadKeymap() //Scrollock if ((ledbits[0]&0x04) > 0) m_locks[2] = 1; -#ifdef QT_QPA_KEYMAP_DEBUG - qWarning("numlock=%d , capslock=%d, scrolllock=%d",m_locks[1],m_locks[0],m_locks[2]); -#endif + qCDebug(qLcEvdevKey, "numlock=%d , capslock=%d, scrolllock=%d", m_locks[1], m_locks[0], m_locks[2]); } } bool QEvdevKeyboardHandler::loadKeymap(const QString &file) { -#ifdef QT_QPA_KEYMAP_DEBUG - qWarning() << "Load keymap" << file; -#endif + qCDebug(qLcEvdevKey) << "Loading keymap" << file; QFile f(file); @@ -529,7 +503,7 @@ bool QEvdevKeyboardHandler::loadKeymap(const QString &file) ds >> qmap_magic >> qmap_version >> qmap_keymap_size >> qmap_keycompose_size; if (ds.status() != QDataStream::Ok || qmap_magic != QEvdevKeyboardMap::FileMagic || qmap_version != 1 || qmap_keymap_size == 0) { - qWarning("'%s' is ot a valid.qmap keymap file.", qPrintable(file)); + qWarning("'%s' is not a valid .qmap keymap file", qPrintable(file)); return false; } diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager.cpp b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager.cpp index 3f8eb1bcd5..4614fbd499 100644 --- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager.cpp +++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager.cpp @@ -35,15 +35,12 @@ #include <QStringList> #include <QCoreApplication> - -//#define QT_QPA_KEYMAP_DEBUG - -#ifdef QT_QPA_KEYMAP_DEBUG -#include <QDebug> -#endif +#include <QLoggingCategory> QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(qLcEvdevKey) + QEvdevKeyboardManager::QEvdevKeyboardManager(const QString &key, const QString &specification, QObject *parent) : QObject(parent) { @@ -74,10 +71,7 @@ QEvdevKeyboardManager::QEvdevKeyboardManager(const QString &key, const QString & addKeyboard(device); if (devices.isEmpty()) { -#ifdef QT_QPA_KEYMAP_DEBUG - qWarning() << "Use device discovery"; -#endif - + qCDebug(qLcEvdevKey) << "evdevkeyboard: Using device discovery"; m_deviceDiscovery = QDeviceDiscovery::create(QDeviceDiscovery::Device_Keyboard, this); if (m_deviceDiscovery) { // scan and add already connected keyboards @@ -100,24 +94,19 @@ QEvdevKeyboardManager::~QEvdevKeyboardManager() void QEvdevKeyboardManager::addKeyboard(const QString &deviceNode) { -#ifdef QT_QPA_KEYMAP_DEBUG - qWarning() << "Adding keyboard at" << deviceNode; -#endif - + qCDebug(qLcEvdevKey) << "Adding keyboard at" << deviceNode; QEvdevKeyboardHandler *keyboard; keyboard = QEvdevKeyboardHandler::create(deviceNode, m_spec, m_defaultKeymapFile); if (keyboard) m_keyboards.insert(deviceNode, keyboard); else - qWarning("Failed to open keyboard"); + qWarning("Failed to open keyboard device %s", qPrintable(deviceNode)); } void QEvdevKeyboardManager::removeKeyboard(const QString &deviceNode) { if (m_keyboards.contains(deviceNode)) { -#ifdef QT_QPA_KEYMAP_DEBUG - qWarning() << "Removing keyboard at" << deviceNode; -#endif + qCDebug(qLcEvdevKey) << "Removing keyboard at" << deviceNode; QEvdevKeyboardHandler *keyboard = m_keyboards.value(deviceNode); m_keyboards.remove(deviceNode); delete keyboard; diff --git a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp index 11db06680a..eddf180e4a 100644 --- a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp +++ b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp @@ -38,6 +38,7 @@ #include <QPoint> #include <QGuiApplication> #include <QScreen> +#include <QLoggingCategory> #include <qpa/qwindowsysteminterface.h> #include <qplatformdefs.h> @@ -48,19 +49,15 @@ #include <linux/kd.h> #include <linux/input.h> -#include <qdebug.h> - -//#define QT_QPA_MOUSE_HANDLER_DEBUG - #define TEST_BIT(array, bit) (array[bit/8] & (1<<(bit%8))) QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(qLcEvdevMouse, "qt.qpa.input") + QEvdevMouseHandler *QEvdevMouseHandler::create(const QString &device, const QString &specification) { -#ifdef QT_QPA_MOUSE_HANDLER_DEBUG - qWarning() << "Try to create mouse handler for" << device << specification; -#endif + qCDebug(qLcEvdevMouse) << "create mouse handler for" << device << specification; bool compression = true; int jitterLimit = 0; @@ -85,7 +82,7 @@ QEvdevMouseHandler *QEvdevMouseHandler::create(const QString &device, const QStr ::ioctl(fd, EVIOCGRAB, grab); return new QEvdevMouseHandler(device, fd, abs, compression, jitterLimit); } else { - qWarning("Cannot open mouse input device '%s': %s", qPrintable(device), strerror(errno)); + qErrnoWarning(errno, "Cannot open mouse input device %s", qPrintable(device)); return 0; } } @@ -148,12 +145,10 @@ bool QEvdevMouseHandler::getHardwareMaximum() m_hardwareScalerX = static_cast<qreal>(m_hardwareWidth) / (g.right() - g.left()); m_hardwareScalerY = static_cast<qreal>(m_hardwareHeight) / (g.bottom() - g.top()); -#ifdef QT_QPA_MOUSE_HANDLER_DEBUG - qDebug() << "Absolute pointing device"; - qDebug() << "hardware max x" << m_hardwareWidth; - qDebug() << "hardware max y" << m_hardwareHeight; - qDebug() << "hardware scalers x" << m_hardwareScalerX << "y" << m_hardwareScalerY; -#endif + qCDebug(qLcEvdevMouse) << "Absolute pointing device" + << "hardware max x" << m_hardwareWidth + << "hardware max y" << m_hardwareHeight + << "hardware scalers x" << m_hardwareScalerX << "y" << m_hardwareScalerY; return true; } @@ -194,11 +189,11 @@ void QEvdevMouseHandler::readMouseData() int result = QT_READ(m_fd, reinterpret_cast<char *>(buffer) + n, sizeof(buffer) - n); if (result == 0) { - qWarning("Got EOF from the input device."); + qWarning("evdevmouse: Got EOF from the input device"); return; } else if (result < 0) { if (errno != EINTR && errno != EAGAIN) { - qWarning("Could not read from input device: %s", strerror(errno)); + qErrnoWarning(errno, "evdevmouse: Could not read from input device"); return; } } else { @@ -212,7 +207,6 @@ void QEvdevMouseHandler::readMouseData() for (int i = 0; i < n; ++i) { struct ::input_event *data = &buffer[i]; - //qDebug() << ">>" << hex << data->type << data->code << dec << data->value; if (data->type == EV_ABS) { // Touchpads: store the absolute position for now, will calculate a relative one later. if (data->code == ABS_X && m_x != data->value) { diff --git a/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp b/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp index 2b52c4e995..a0c9c9f34d 100644 --- a/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp +++ b/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp @@ -36,16 +36,13 @@ #include <QStringList> #include <QGuiApplication> #include <QScreen> +#include <QLoggingCategory> #include <qpa/qwindowsysteminterface.h> -//#define QT_QPA_MOUSEMANAGER_DEBUG - -#ifdef QT_QPA_MOUSEMANAGER_DEBUG -#include <QDebug> -#endif - QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(qLcEvdevMouse) + QEvdevMouseManager::QEvdevMouseManager(const QString &key, const QString &specification, QObject *parent) : QObject(parent), m_x(0), m_y(0), m_xoffset(0), m_yoffset(0) { @@ -79,10 +76,7 @@ QEvdevMouseManager::QEvdevMouseManager(const QString &key, const QString &specif addMouse(device); if (devices.isEmpty()) { -#ifdef QT_QPA_MOUSEMANAGER_DEBUG - qWarning() << "Use device discovery"; -#endif - + qCDebug(qLcEvdevMouse) << "evdevmouse: Using device discovery"; m_deviceDiscovery = QDeviceDiscovery::create(QDeviceDiscovery::Device_Mouse | QDeviceDiscovery::Device_Touchpad, this); if (m_deviceDiscovery) { // scan and add already connected keyboards @@ -130,28 +124,17 @@ void QEvdevMouseManager::handleMouseEvent(int x, int y, bool abs, Qt::MouseButto // 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, QGuiApplication::keyboardModifiers()); - -#ifdef QT_QPA_MOUSEMANAGER_DEBUG - qDebug("mouse event %d %d %d", pos.x(), pos.y(), int(buttons)); -#endif } void QEvdevMouseManager::handleWheelEvent(int delta, Qt::Orientation orientation) { QPoint pos(m_x + m_xoffset, m_y + m_yoffset); QWindowSystemInterface::handleWheelEvent(0, pos, pos, delta, orientation, QGuiApplication::keyboardModifiers()); - -#ifdef QT_QPA_MOUSEMANAGER_DEBUG - qDebug("mouse wheel event %dx%d %d %d", pos.x(), pos.y(), delta, int(orientation)); -#endif } void QEvdevMouseManager::addMouse(const QString &deviceNode) { -#ifdef QT_QPA_MOUSEMANAGER_DEBUG - qWarning() << "Adding mouse at" << deviceNode; -#endif - + qCDebug(qLcEvdevMouse) << "Adding mouse at" << deviceNode; QEvdevMouseHandler *handler; handler = QEvdevMouseHandler::create(deviceNode, m_spec); if (handler) { @@ -159,16 +142,14 @@ void QEvdevMouseManager::addMouse(const QString &deviceNode) connect(handler, SIGNAL(handleWheelEvent(int,Qt::Orientation)), this, SLOT(handleWheelEvent(int,Qt::Orientation))); m_mice.insert(deviceNode, handler); } else { - qWarning("Failed to open mouse"); + qWarning("evdevmouse: Failed to open mouse device %s", qPrintable(deviceNode)); } } void QEvdevMouseManager::removeMouse(const QString &deviceNode) { if (m_mice.contains(deviceNode)) { -#ifdef QT_QPA_MOUSEMANAGER_DEBUG - qWarning() << "Removing mouse at" << deviceNode; -#endif + qCDebug(qLcEvdevMouse) << "Removing mouse at" << deviceNode; QEvdevMouseHandler *handler = m_mice.value(deviceNode); m_mice.remove(deviceNode); delete handler; diff --git a/src/platformsupport/input/evdevtablet/qevdevtablet.cpp b/src/platformsupport/input/evdevtablet/qevdevtablet.cpp index 8d91c49488..8dbf5832d9 100644 --- a/src/platformsupport/input/evdevtablet/qevdevtablet.cpp +++ b/src/platformsupport/input/evdevtablet/qevdevtablet.cpp @@ -36,13 +36,15 @@ #include <QStringList> #include <QSocketNotifier> #include <QGuiApplication> -#include <QDebug> +#include <QLoggingCategory> #include <QtCore/private/qcore_unix_p.h> #include <QtPlatformSupport/private/qdevicediscovery_p.h> #include <linux/input.h> QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(qLcEvdevTablet, "qt.qpa.input") + class QEvdevTabletData { public: @@ -87,28 +89,28 @@ bool QEvdevTabletData::queryLimits() if (ok) { minValues.x = absInfo.minimum; maxValues.x = absInfo.maximum; - qDebug("evdevtablet: min X: %d max X: %d", minValues.x, maxValues.x); + 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; - qDebug("evdevtablet: min Y: %d max Y: %d", minValues.y, maxValues.y); + 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; - qDebug("evdevtablet: min pressure: %d max pressure: %d", minValues.p, maxValues.p); + 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; - qDebug("evdevtablet: min distance: %d max distance: %d", minValues.d, maxValues.d); + 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); - qDebug("evdevtablet: device name: %s", name); + qCDebug(qLcEvdevTablet, "evdevtablet: device name: %s", name); } return ok; } @@ -232,7 +234,7 @@ QEvdevTabletHandler::QEvdevTabletHandler(const QString &spec, QObject *parent) } } if (!dev.isEmpty()) { - qDebug("evdevtablet: using %s", qPrintable(dev)); + 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(); diff --git a/src/platformsupport/input/evdevtablet/qevdevtablet_p.h b/src/platformsupport/input/evdevtablet/qevdevtablet_p.h index c20ddec787..4778c85d21 100644 --- a/src/platformsupport/input/evdevtablet/qevdevtablet_p.h +++ b/src/platformsupport/input/evdevtablet/qevdevtablet_p.h @@ -73,7 +73,7 @@ class QEvdevTabletHandlerThread : public QThread public: explicit QEvdevTabletHandlerThread(const QString &spec, QObject *parent = 0); ~QEvdevTabletHandlerThread(); - void run(); + void run() Q_DECL_OVERRIDE; QEvdevTabletHandler *handler() { return m_handler; } private: diff --git a/src/platformsupport/input/evdevtouch/qevdevtouch.cpp b/src/platformsupport/input/evdevtouch/qevdevtouch.cpp index d0d8b783a4..dd831c9e82 100644 --- a/src/platformsupport/input/evdevtouch/qevdevtouch.cpp +++ b/src/platformsupport/input/evdevtouch/qevdevtouch.cpp @@ -36,7 +36,7 @@ #include <QHash> #include <QSocketNotifier> #include <QGuiApplication> -#include <QDebug> +#include <QLoggingCategory> #include <QtCore/private/qcore_unix_p.h> #include <QtPlatformSupport/private/qdevicediscovery_p.h> #include <linux/input.h> @@ -49,6 +49,8 @@ extern "C" { QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(qLcEvdevTouch, "qt.qpa.input") + /* android (and perhaps some other linux-derived stuff) don't define everything * in linux/input.h, so we'll need to do that ourselves. */ @@ -164,7 +166,8 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &specification, { setObjectName(QLatin1String("Evdev Touch Handler")); - bool printDeviceInfo = qgetenv("QT_QPA_EVDEV_DEBUG").toInt(); + if (qEnvironmentVariableIsSet("QT_QPA_EVDEV_DEBUG")) + ((QLoggingCategory &) qLcEvdevTouch()).setEnabled(QtDebugMsg, true); // only the first device argument is used for now QString spec = QString::fromLocal8Bit(qgetenv("QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS")); @@ -215,13 +218,11 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &specification, } if (dev.isEmpty()) { - if (printDeviceInfo) - qDebug("evdevtouch: No touch devices found"); + qCDebug(qLcEvdevTouch, "evdevtouch: No touch devices found"); return; } - if (printDeviceInfo) - qDebug("evdevtouch: Using device %s", qPrintable(dev)); + qCDebug(qLcEvdevTouch, "evdevtouch: Using device %s", qPrintable(dev)); m_fd = QT_OPEN(dev.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0); @@ -257,25 +258,22 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &specification, } #endif - if (printDeviceInfo) - qDebug("evdevtouch: Protocol type %c %s (%s)", d->m_typeB ? 'B' : 'A', - mtdevStr, d->m_singleTouch ? "single" : "multi"); + qCDebug(qLcEvdevTouch, "evdevtouch: Protocol type %c %s (%s)", d->m_typeB ? 'B' : 'A', + mtdevStr, d->m_singleTouch ? "single" : "multi"); input_absinfo absInfo; memset(&absInfo, 0, sizeof(input_absinfo)); bool has_x_range = false, has_y_range = false; if (ioctl(m_fd, EVIOCGABS((d->m_singleTouch ? ABS_X : ABS_MT_POSITION_X)), &absInfo) >= 0) { - if (printDeviceInfo) - qDebug("evdevtouch: min X: %d max X: %d", absInfo.minimum, absInfo.maximum); + qCDebug(qLcEvdevTouch, "evdevtouch: min X: %d max X: %d", absInfo.minimum, absInfo.maximum); d->hw_range_x_min = absInfo.minimum; d->hw_range_x_max = absInfo.maximum; has_x_range = true; } if (ioctl(m_fd, EVIOCGABS((d->m_singleTouch ? ABS_Y : ABS_MT_POSITION_Y)), &absInfo) >= 0) { - if (printDeviceInfo) - qDebug("evdevtouch: min Y: %d max Y: %d", absInfo.minimum, absInfo.maximum); + qCDebug(qLcEvdevTouch, "evdevtouch: min Y: %d max Y: %d", absInfo.minimum, absInfo.maximum); d->hw_range_y_min = absInfo.minimum; d->hw_range_y_max = absInfo.maximum; has_y_range = true; @@ -285,8 +283,7 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &specification, qWarning("evdevtouch: Invalid ABS limits, behavior unspecified"); if (ioctl(m_fd, EVIOCGABS(ABS_PRESSURE), &absInfo) >= 0) { - if (printDeviceInfo) - qDebug("evdevtouch: min pressure: %d max pressure: %d", absInfo.minimum, absInfo.maximum); + qCDebug(qLcEvdevTouch, "evdevtouch: min pressure: %d max pressure: %d", absInfo.minimum, absInfo.maximum); if (absInfo.maximum > absInfo.minimum) { d->hw_pressure_min = absInfo.minimum; d->hw_pressure_max = absInfo.maximum; @@ -296,8 +293,7 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &specification, char name[1024]; if (ioctl(m_fd, EVIOCGNAME(sizeof(name) - 1), name) >= 0) { d->hw_name = QString::fromLocal8Bit(name); - if (printDeviceInfo) - qDebug("evdevtouch: device name: %s", name); + qCDebug(qLcEvdevTouch, "evdevtouch: device name: %s", name); } // Fix up the coordinate ranges for am335x in case the kernel driver does not have them fixed. @@ -310,9 +306,8 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &specification, d->hw_range_y_min = 220; d->hw_range_y_max = 3907; } - if (printDeviceInfo) - qDebug("evdevtouch: found ti-tsc, overriding: min X: %d max X: %d min Y: %d max Y: %d", - d->hw_range_x_min, d->hw_range_x_max, d->hw_range_y_min, d->hw_range_y_max); + qCDebug(qLcEvdevTouch, "evdevtouch: found ti-tsc, overriding: min X: %d max X: %d min Y: %d max Y: %d", + d->hw_range_x_min, d->hw_range_x_max, d->hw_range_y_min, d->hw_range_y_max); } bool grabSuccess = !ioctl(m_fd, EVIOCGRAB, (void *) 1); diff --git a/src/platformsupport/input/evdevtouch/qevdevtouch_p.h b/src/platformsupport/input/evdevtouch/qevdevtouch_p.h index 31b2d86834..e7861f0360 100644 --- a/src/platformsupport/input/evdevtouch/qevdevtouch_p.h +++ b/src/platformsupport/input/evdevtouch/qevdevtouch_p.h @@ -85,7 +85,7 @@ class QEvdevTouchScreenHandlerThread : public QThread public: explicit QEvdevTouchScreenHandlerThread(const QString &spec, QObject *parent = 0); ~QEvdevTouchScreenHandlerThread(); - void run(); + void run() Q_DECL_OVERRIDE; QEvdevTouchScreenHandler *handler() { return m_handler; } private: diff --git a/src/platformsupport/input/input.pri b/src/platformsupport/input/input.pri index 1524eb454e..3b9593eb31 100644 --- a/src/platformsupport/input/input.pri +++ b/src/platformsupport/input/input.pri @@ -4,3 +4,11 @@ contains(QT_CONFIG, evdev) { include($$PWD/evdevtouch/evdevtouch.pri) include($$PWD/evdevtablet/evdevtablet.pri) } + +contains(QT_CONFIG, tslib) { + include($$PWD/tslib/tslib.pri) +} + +contains(QT_CONFIG, libinput) { + include($$PWD/libinput/libinput.pri) +} diff --git a/src/platformsupport/input/libinput/libinput.pri b/src/platformsupport/input/libinput/libinput.pri new file mode 100644 index 0000000000..bed9e79738 --- /dev/null +++ b/src/platformsupport/input/libinput/libinput.pri @@ -0,0 +1,21 @@ +HEADERS += \ + $$PWD/qlibinputhandler_p.h \ + $$PWD/qlibinputpointer_p.h \ + $$PWD/qlibinputkeyboard_p.h \ + $$PWD/qlibinputtouch_p.h + +SOURCES += \ + $$PWD/qlibinputhandler.cpp \ + $$PWD/qlibinputpointer.cpp \ + $$PWD/qlibinputkeyboard.cpp \ + $$PWD/qlibinputtouch.cpp + +INCLUDEPATH += $$QMAKE_INCDIR_LIBUDEV $$QMAKE_INCDIR_LIBINPUT +LIBS_PRIVATE += $$QMAKE_LIBS_LIBUDEV $$QMAKE_LIBS_LIBINPUT + +contains(QT_CONFIG, xkbcommon-evdev) { + INCLUDEPATH += $$QMAKE_INCDIR_XKBCOMMON_EVDEV + LIBS_PRIVATE += $$QMAKE_LIBS_XKBCOMMON_EVDEV +} else { + DEFINES += QT_NO_XKBCOMMON_EVDEV +} diff --git a/src/platformsupport/input/libinput/qlibinputhandler.cpp b/src/platformsupport/input/libinput/qlibinputhandler.cpp new file mode 100644 index 0000000000..557c6eb435 --- /dev/null +++ b/src/platformsupport/input/libinput/qlibinputhandler.cpp @@ -0,0 +1,188 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qlibinputhandler_p.h" +#include <libudev.h> +#include <libinput.h> +#include <QtCore/QLoggingCategory> +#include <QtCore/QSocketNotifier> +#include <QtCore/private/qcore_unix_p.h> + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(qLcInput, "qt.qpa.input") + +static int liOpen(const char *path, int flags, void *user_data) +{ + Q_UNUSED(user_data); + return qt_safe_open(path, flags); +} + +static void liClose(int fd, void *user_data) +{ + Q_UNUSED(user_data); + qt_safe_close(fd); +} + +static const struct libinput_interface liInterface = { + liOpen, + liClose +}; + +static void liLogHandler(libinput *libinput, libinput_log_priority priority, const char *format, va_list args) +{ + Q_UNUSED(libinput); + Q_UNUSED(priority); + + char buf[512]; + int n = vsnprintf(buf, sizeof(buf), format, args); + if (n > 0) { + if (buf[n - 1] == '\n') + buf[n - 1] = '\0'; + qCDebug(qLcInput, "libinput: %s", buf); + } +} + +QLibInputHandler::QLibInputHandler(const QString &key, const QString &spec) +{ + Q_UNUSED(key); + Q_UNUSED(spec); + + m_udev = udev_new(); + if (!m_udev) + qFatal("Failed to get udev context for libinput"); + + m_li = libinput_udev_create_context(&liInterface, Q_NULLPTR, m_udev); + if (!m_li) + qFatal("Failed to get libinput context"); + + libinput_log_set_handler(m_li, liLogHandler); + if (qLcInput().isDebugEnabled()) + libinput_log_set_priority(m_li, LIBINPUT_LOG_PRIORITY_DEBUG); + + if (libinput_udev_assign_seat(m_li, "seat0")) + qFatal("Failed to assign seat"); + + m_liFd = libinput_get_fd(m_li); + m_notifier = new QSocketNotifier(m_liFd, QSocketNotifier::Read); + connect(m_notifier, SIGNAL(activated(int)), SLOT(onReadyRead())); + + // Process the initial burst of DEVICE_ADDED events. + onReadyRead(); +} + +QLibInputHandler::~QLibInputHandler() +{ + delete m_notifier; + + if (m_li) + libinput_unref(m_li); + + if (m_udev) + udev_unref(m_udev); +} + +void QLibInputHandler::onReadyRead() +{ + if (libinput_dispatch(m_li)) { + qWarning("libinput_dispatch failed"); + return; + } + + libinput_event *ev; + while ((ev = libinput_get_event(m_li)) != Q_NULLPTR) { + processEvent(ev); + libinput_event_destroy(ev); + } +} + +void QLibInputHandler::processEvent(libinput_event *ev) +{ + libinput_event_type type = libinput_event_get_type(ev); + libinput_device *dev = libinput_event_get_device(ev); + + switch (type) { + case LIBINPUT_EVENT_DEVICE_ADDED: + { + // This is not just for hotplugging, it is also called for each input + // device libinput reads from on startup. Hence it is suitable for doing + // touch device registration. + const char *sysname = libinput_device_get_sysname(dev); // node name without path + const char *name = libinput_device_get_name(dev); + emit deviceAdded(QString::fromUtf8(sysname), QString::fromUtf8(name)); + if (libinput_device_has_capability(dev, LIBINPUT_DEVICE_CAP_TOUCH)) + m_touch.registerDevice(dev); + break; + } + case LIBINPUT_EVENT_DEVICE_REMOVED: + { + const char *sysname = libinput_device_get_sysname(dev); + const char *name = libinput_device_get_name(dev); + emit deviceRemoved(QString::fromUtf8(sysname), QString::fromUtf8(name)); + if (libinput_device_has_capability(dev, LIBINPUT_DEVICE_CAP_TOUCH)) + m_touch.unregisterDevice(dev); + break; + } + case LIBINPUT_EVENT_POINTER_BUTTON: + m_pointer.processButton(libinput_event_get_pointer_event(ev)); + break; + case LIBINPUT_EVENT_POINTER_MOTION: + m_pointer.processMotion(libinput_event_get_pointer_event(ev)); + break; + case LIBINPUT_EVENT_POINTER_AXIS: + m_pointer.processAxis(libinput_event_get_pointer_event(ev)); + break; + case LIBINPUT_EVENT_KEYBOARD_KEY: + m_keyboard.processKey(libinput_event_get_keyboard_event(ev)); + break; + case LIBINPUT_EVENT_TOUCH_DOWN: + m_touch.processTouchDown(libinput_event_get_touch_event(ev)); + break; + case LIBINPUT_EVENT_TOUCH_MOTION: + m_touch.processTouchMotion(libinput_event_get_touch_event(ev)); + break; + case LIBINPUT_EVENT_TOUCH_UP: + m_touch.processTouchUp(libinput_event_get_touch_event(ev)); + break; + case LIBINPUT_EVENT_TOUCH_CANCEL: + m_touch.processTouchCancel(libinput_event_get_touch_event(ev)); + break; + case LIBINPUT_EVENT_TOUCH_FRAME: + m_touch.processTouchFrame(libinput_event_get_touch_event(ev)); + break; + default: + break; + } +} + +QT_END_NAMESPACE diff --git a/src/platformsupport/input/libinput/qlibinputhandler_p.h b/src/platformsupport/input/libinput/qlibinputhandler_p.h new file mode 100644 index 0000000000..b6c88111af --- /dev/null +++ b/src/platformsupport/input/libinput/qlibinputhandler_p.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLIBINPUTHANDLER_P_H +#define QLIBINPUTHANDLER_P_H + +#include <QtCore/QObject> +#include "qlibinputpointer_p.h" +#include "qlibinputkeyboard_p.h" +#include "qlibinputtouch_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. +// + +struct udev; +struct libinput; +struct libinput_event; + +QT_BEGIN_NAMESPACE + +class QSocketNotifier; + +class QLibInputHandler : public QObject +{ + Q_OBJECT + +public: + QLibInputHandler(const QString &key, const QString &spec); + ~QLibInputHandler(); + +signals: + void deviceAdded(const QString &sysname, const QString &name); + void deviceRemoved(const QString &sysname, const QString &name); + +private slots: + void onReadyRead(); + +private: + void processEvent(libinput_event *ev); + + udev *m_udev; + libinput *m_li; + int m_liFd; + QSocketNotifier *m_notifier; + QLibInputPointer m_pointer; + QLibInputKeyboard m_keyboard; + QLibInputTouch m_touch; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/platformsupport/input/libinput/qlibinputkeyboard.cpp b/src/platformsupport/input/libinput/qlibinputkeyboard.cpp new file mode 100644 index 0000000000..41c849e8a5 --- /dev/null +++ b/src/platformsupport/input/libinput/qlibinputkeyboard.cpp @@ -0,0 +1,279 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qlibinputkeyboard_p.h" +#include <QtCore/QTextCodec> +#include <qpa/qwindowsysteminterface.h> +#include <libinput.h> +#ifndef QT_NO_XKBCOMMON_EVDEV +#include <xkbcommon/xkbcommon-keysyms.h> +#include <xkbcommon/xkbcommon-names.h> +#endif + +QT_BEGIN_NAMESPACE + +const int REPEAT_DELAY = 500; +const int REPEAT_RATE = 100; + +#ifndef QT_NO_XKBCOMMON_EVDEV +struct KeyTabEntry { + int xkbkey; + int qtkey; +}; + +static inline bool operator==(const KeyTabEntry &a, const KeyTabEntry &b) +{ + return a.xkbkey == b.xkbkey; +} + +static const KeyTabEntry keyTab[] = { + { XKB_KEY_Escape, Qt::Key_Escape }, + { XKB_KEY_Tab, Qt::Key_Tab }, + { XKB_KEY_ISO_Left_Tab, Qt::Key_Backtab }, + { XKB_KEY_BackSpace, Qt::Key_Backspace }, + { XKB_KEY_Return, Qt::Key_Return }, + { XKB_KEY_Insert, Qt::Key_Insert }, + { XKB_KEY_Delete, Qt::Key_Delete }, + { XKB_KEY_Clear, Qt::Key_Delete }, + { XKB_KEY_Pause, Qt::Key_Pause }, + { XKB_KEY_Print, Qt::Key_Print }, + + { XKB_KEY_Home, Qt::Key_Home }, + { XKB_KEY_End, Qt::Key_End }, + { XKB_KEY_Left, Qt::Key_Left }, + { XKB_KEY_Up, Qt::Key_Up }, + { XKB_KEY_Right, Qt::Key_Right }, + { XKB_KEY_Down, Qt::Key_Down }, + { XKB_KEY_Prior, Qt::Key_PageUp }, + { XKB_KEY_Next, Qt::Key_PageDown }, + + { XKB_KEY_Shift_L, Qt::Key_Shift }, + { XKB_KEY_Shift_R, Qt::Key_Shift }, + { XKB_KEY_Shift_Lock, Qt::Key_Shift }, + { XKB_KEY_Control_L, Qt::Key_Control }, + { XKB_KEY_Control_R, Qt::Key_Control }, + { XKB_KEY_Meta_L, Qt::Key_Meta }, + { XKB_KEY_Meta_R, Qt::Key_Meta }, + { XKB_KEY_Alt_L, Qt::Key_Alt }, + { XKB_KEY_Alt_R, Qt::Key_Alt }, + { XKB_KEY_Caps_Lock, Qt::Key_CapsLock }, + { XKB_KEY_Num_Lock, Qt::Key_NumLock }, + { XKB_KEY_Scroll_Lock, Qt::Key_ScrollLock }, + { XKB_KEY_Super_L, Qt::Key_Super_L }, + { XKB_KEY_Super_R, Qt::Key_Super_R }, + { XKB_KEY_Menu, Qt::Key_Menu }, + { XKB_KEY_Hyper_L, Qt::Key_Hyper_L }, + { XKB_KEY_Hyper_R, Qt::Key_Hyper_R }, + { XKB_KEY_Help, Qt::Key_Help }, + + { XKB_KEY_KP_Space, Qt::Key_Space }, + { XKB_KEY_KP_Tab, Qt::Key_Tab }, + { XKB_KEY_KP_Enter, Qt::Key_Enter }, + { XKB_KEY_KP_Home, Qt::Key_Home }, + { XKB_KEY_KP_Left, Qt::Key_Left }, + { XKB_KEY_KP_Up, Qt::Key_Up }, + { XKB_KEY_KP_Right, Qt::Key_Right }, + { XKB_KEY_KP_Down, Qt::Key_Down }, + { XKB_KEY_KP_Prior, Qt::Key_PageUp }, + { XKB_KEY_KP_Next, Qt::Key_PageDown }, + { XKB_KEY_KP_End, Qt::Key_End }, + { XKB_KEY_KP_Begin, Qt::Key_Clear }, + { XKB_KEY_KP_Insert, Qt::Key_Insert }, + { XKB_KEY_KP_Delete, Qt::Key_Delete }, + { XKB_KEY_KP_Equal, Qt::Key_Equal }, + { XKB_KEY_KP_Multiply, Qt::Key_Asterisk }, + { XKB_KEY_KP_Add, Qt::Key_Plus }, + { XKB_KEY_KP_Separator, Qt::Key_Comma }, + { XKB_KEY_KP_Subtract, Qt::Key_Minus }, + { XKB_KEY_KP_Decimal, Qt::Key_Period }, + { XKB_KEY_KP_Divide, Qt::Key_Slash }, +}; +#endif + +QLibInputKeyboard::QLibInputKeyboard() +#ifndef QT_NO_XKBCOMMON_EVDEV + : m_ctx(0), + m_keymap(0), + m_state(0) +#endif +{ +#ifndef QT_NO_XKBCOMMON_EVDEV + m_ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + if (!m_ctx) { + qWarning("Failed to create xkb context"); + return; + } + m_keymap = xkb_keymap_new_from_names(m_ctx, Q_NULLPTR, XKB_KEYMAP_COMPILE_NO_FLAGS); + if (!m_keymap) { + qWarning("Failed to compile keymap"); + return; + } + m_state = xkb_state_new(m_keymap); + if (!m_state) { + qWarning("Failed to create xkb state"); + return; + } + m_modindex[0] = xkb_keymap_mod_get_index(m_keymap, XKB_MOD_NAME_CTRL); + m_modindex[1] = xkb_keymap_mod_get_index(m_keymap, XKB_MOD_NAME_ALT); + m_modindex[2] = xkb_keymap_mod_get_index(m_keymap, XKB_MOD_NAME_SHIFT); + m_modindex[3] = xkb_keymap_mod_get_index(m_keymap, XKB_MOD_NAME_LOGO); + + m_repeatTimer.setSingleShot(true); + connect(&m_repeatTimer, &QTimer::timeout, this, &QLibInputKeyboard::handleRepeat); +#endif +} + +QLibInputKeyboard::~QLibInputKeyboard() +{ +#ifndef QT_NO_XKBCOMMON_EVDEV + if (m_state) + xkb_state_unref(m_state); + if (m_keymap) + xkb_keymap_unref(m_keymap); + if (m_ctx) + xkb_context_unref(m_ctx); +#endif +} + +void QLibInputKeyboard::processKey(libinput_event_keyboard *e) +{ +#ifndef QT_NO_XKBCOMMON_EVDEV + if (!m_ctx || !m_keymap || !m_state) + return; + + const uint32_t k = libinput_event_keyboard_get_key(e) + 8; + const bool pressed = libinput_event_keyboard_get_key_state(e) == LIBINPUT_KEY_STATE_PRESSED; + + QByteArray chars; + chars.resize(1 + xkb_state_key_get_utf8(m_state, k, Q_NULLPTR, 0)); + xkb_state_key_get_utf8(m_state, k, chars.data(), chars.size()); + const QString text = QString::fromUtf8(chars); + + const xkb_keysym_t sym = xkb_state_key_get_one_sym(m_state, k); + + Qt::KeyboardModifiers mods = Qt::NoModifier; + const int qtkey = keysymToQtKey(sym, &mods, text); + + xkb_state_component modtype = xkb_state_component(XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED); + if (xkb_state_mod_index_is_active(m_state, m_modindex[0], modtype) && (qtkey != Qt::Key_Control || !pressed)) + mods |= Qt::ControlModifier; + if (xkb_state_mod_index_is_active(m_state, m_modindex[1], modtype) && (qtkey != Qt::Key_Alt || !pressed)) + mods |= Qt::AltModifier; + if (xkb_state_mod_index_is_active(m_state, m_modindex[2], modtype) && (qtkey != Qt::Key_Shift || !pressed)) + mods |= Qt::ShiftModifier; + if (xkb_state_mod_index_is_active(m_state, m_modindex[3], modtype) && (qtkey != Qt::Key_Meta || !pressed)) + mods |= Qt::MetaModifier; + + xkb_state_update_key(m_state, k, pressed ? XKB_KEY_DOWN : XKB_KEY_UP); + + QWindowSystemInterface::handleExtendedKeyEvent(Q_NULLPTR, + pressed ? QEvent::KeyPress : QEvent::KeyRelease, + qtkey, mods, k, sym, mods, text); + + if (pressed && xkb_keymap_key_repeats(m_keymap, k)) { + m_repeatData.qtkey = qtkey; + m_repeatData.mods = mods; + m_repeatData.nativeScanCode = k; + m_repeatData.virtualKey = sym; + m_repeatData.nativeMods = mods; + m_repeatData.unicodeText = text; + m_repeatData.repeatCount = 1; + m_repeatTimer.setInterval(REPEAT_DELAY); + m_repeatTimer.start(); + } else if (m_repeatTimer.isActive()) { + m_repeatTimer.stop(); + } + +#else + Q_UNUSED(e); +#endif +} + +#ifndef QT_NO_XKBCOMMON_EVDEV +void QLibInputKeyboard::handleRepeat() +{ + QWindowSystemInterface::handleExtendedKeyEvent(Q_NULLPTR, QEvent::KeyPress, + m_repeatData.qtkey, m_repeatData.mods, + m_repeatData.nativeScanCode, m_repeatData.virtualKey, m_repeatData.nativeMods, + m_repeatData.unicodeText, true, m_repeatData.repeatCount); + m_repeatData.repeatCount += 1; + m_repeatTimer.setInterval(REPEAT_RATE); + m_repeatTimer.start(); +} + +int QLibInputKeyboard::keysymToQtKey(xkb_keysym_t key) const +{ + const size_t elemCount = sizeof(keyTab) / sizeof(KeyTabEntry); + KeyTabEntry e; + e.xkbkey = key; + const KeyTabEntry *result = std::find(keyTab, keyTab + elemCount, e); + return result != keyTab + elemCount ? result->qtkey : 0; +} + +int QLibInputKeyboard::keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers *modifiers, const QString &text) const +{ + int code = 0; +#ifndef QT_NO_TEXTCODEC + QTextCodec *systemCodec = QTextCodec::codecForLocale(); +#endif + if (keysym < 128 || (keysym < 256 +#ifndef QT_NO_TEXTCODEC + && systemCodec->mibEnum() == 4 +#endif + )) { + // upper-case key, if known + code = isprint((int)keysym) ? toupper((int)keysym) : 0; + } else if (keysym >= XKB_KEY_F1 && keysym <= XKB_KEY_F35) { + // function keys + code = Qt::Key_F1 + ((int)keysym - XKB_KEY_F1); + } else if (keysym >= XKB_KEY_KP_Space && keysym <= XKB_KEY_KP_9) { + if (keysym >= XKB_KEY_KP_0) { + // numeric keypad keys + code = Qt::Key_0 + ((int)keysym - XKB_KEY_KP_0); + } else { + code = keysymToQtKey(keysym); + } + *modifiers |= Qt::KeypadModifier; + } else if (text.length() == 1 && text.unicode()->unicode() > 0x1f + && text.unicode()->unicode() != 0x7f + && !(keysym >= XKB_KEY_dead_grave && keysym <= XKB_KEY_dead_currency)) { + code = text.unicode()->toUpper().unicode(); + } else { + // any other keys + code = keysymToQtKey(keysym); + } + return code; +} +#endif + +QT_END_NAMESPACE diff --git a/src/platformsupport/input/libinput/qlibinputkeyboard_p.h b/src/platformsupport/input/libinput/qlibinputkeyboard_p.h new file mode 100644 index 0000000000..bcd4d23d98 --- /dev/null +++ b/src/platformsupport/input/libinput/qlibinputkeyboard_p.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLIBINPUTKEYBOARD_P_H +#define QLIBINPUTKEYBOARD_P_H + +#include <QtCore/QPoint> +#include <QtCore/QTimer> + +#ifndef QT_NO_XKBCOMMON_EVDEV +#include <xkbcommon/xkbcommon.h> +#endif + +// +// 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. +// + +struct libinput_event_keyboard; + +QT_BEGIN_NAMESPACE + +class QLibInputKeyboard : public QObject +{ + Q_OBJECT + +public: + QLibInputKeyboard(); + ~QLibInputKeyboard(); + + void processKey(libinput_event_keyboard *e); + +#ifndef QT_NO_XKBCOMMON_EVDEV +private slots: + void handleRepeat(); + +private: + int keysymToQtKey(xkb_keysym_t key) const; + int keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers *modifiers, const QString &text) const; + + xkb_context *m_ctx; + xkb_keymap *m_keymap; + xkb_state *m_state; + xkb_mod_index_t m_modindex[4]; + + QTimer m_repeatTimer; + + struct { + int qtkey; + Qt::KeyboardModifiers mods; + int nativeScanCode; + int virtualKey; + int nativeMods; + QString unicodeText; + int repeatCount; + } m_repeatData; +#endif +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/platformsupport/input/libinput/qlibinputpointer.cpp b/src/platformsupport/input/libinput/qlibinputpointer.cpp new file mode 100644 index 0000000000..28e5529b3c --- /dev/null +++ b/src/platformsupport/input/libinput/qlibinputpointer.cpp @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qlibinputpointer_p.h" +#include <libinput.h> +#include <QtGui/QGuiApplication> +#include <QtGui/QScreen> +#include <qpa/qwindowsysteminterface.h> + +QT_BEGIN_NAMESPACE + +QLibInputPointer::QLibInputPointer() + : m_buttons(Qt::NoButton) +{ +} + +void QLibInputPointer::processButton(libinput_event_pointer *e) +{ + const uint32_t b = libinput_event_pointer_get_button(e); + const bool pressed = libinput_event_pointer_get_button_state(e) == LIBINPUT_BUTTON_STATE_PRESSED; + + Qt::MouseButton button = Qt::NoButton; + switch (b) { + case 0x110: button = Qt::LeftButton; break; // BTN_LEFT + case 0x111: button = Qt::RightButton; break; + case 0x112: button = Qt::MiddleButton; break; + case 0x113: button = Qt::ExtraButton1; break; // AKA Qt::BackButton + case 0x114: button = Qt::ExtraButton2; break; // AKA Qt::ForwardButton + case 0x115: button = Qt::ExtraButton3; break; // AKA Qt::TaskButton + case 0x116: button = Qt::ExtraButton4; break; + case 0x117: button = Qt::ExtraButton5; break; + case 0x118: button = Qt::ExtraButton6; break; + case 0x119: button = Qt::ExtraButton7; break; + case 0x11a: button = Qt::ExtraButton8; break; + case 0x11b: button = Qt::ExtraButton9; break; + case 0x11c: button = Qt::ExtraButton10; break; + case 0x11d: button = Qt::ExtraButton11; break; + case 0x11e: button = Qt::ExtraButton12; break; + case 0x11f: button = Qt::ExtraButton13; break; + } + + if (pressed) + m_buttons |= button; + else + m_buttons &= ~button; + + QWindowSystemInterface::handleMouseEvent(Q_NULLPTR, m_pos, m_pos, m_buttons, QGuiApplication::keyboardModifiers()); +} + +void QLibInputPointer::processMotion(libinput_event_pointer *e) +{ + const double dx = libinput_event_pointer_get_dx(e); + const double dy = libinput_event_pointer_get_dy(e); + const QRect g = QGuiApplication::primaryScreen()->virtualGeometry(); + + m_pos.setX(qBound(g.left(), qRound(m_pos.x() + dx), g.right())); + m_pos.setY(qBound(g.top(), qRound(m_pos.y() + dy), g.bottom())); + + QWindowSystemInterface::handleMouseEvent(Q_NULLPTR, m_pos, m_pos, m_buttons, QGuiApplication::keyboardModifiers()); +} + +void QLibInputPointer::processAxis(libinput_event_pointer *e) +{ + const double v = libinput_event_pointer_get_axis_value(e) * 120; + const Qt::Orientation ori = libinput_event_pointer_get_axis(e) == LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL + ? Qt::Vertical : Qt::Horizontal; + + QWindowSystemInterface::handleWheelEvent(Q_NULLPTR, m_pos, m_pos, qRound(-v), ori, QGuiApplication::keyboardModifiers()); +} + +QT_END_NAMESPACE diff --git a/src/platformsupport/input/libinput/qlibinputpointer_p.h b/src/platformsupport/input/libinput/qlibinputpointer_p.h new file mode 100644 index 0000000000..efc19ab4fd --- /dev/null +++ b/src/platformsupport/input/libinput/qlibinputpointer_p.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLIBINPUTPOINTER_P_H +#define QLIBINPUTPOINTER_P_H + +#include <QtCore/QPoint> + +// +// 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. +// + +struct libinput_event_pointer; + +QT_BEGIN_NAMESPACE + +class QLibInputPointer +{ +public: + QLibInputPointer(); + + void processButton(libinput_event_pointer *e); + void processMotion(libinput_event_pointer *e); + void processAxis(libinput_event_pointer *e); + +private: + QPoint m_pos; + Qt::MouseButtons m_buttons; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/platformsupport/input/libinput/qlibinputtouch.cpp b/src/platformsupport/input/libinput/qlibinputtouch.cpp new file mode 100644 index 0000000000..ed453a6a9a --- /dev/null +++ b/src/platformsupport/input/libinput/qlibinputtouch.cpp @@ -0,0 +1,165 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qlibinputtouch_p.h" +#include <libinput.h> +#include <QtGui/QGuiApplication> +#include <QtGui/QScreen> + +QT_BEGIN_NAMESPACE + +QWindowSystemInterface::TouchPoint *QLibInputTouch::DeviceState::point(int32_t slot) +{ + const int id = qMax(0, slot); + + for (int i = 0; i < m_points.count(); ++i) + if (m_points.at(i).id == id) + return &m_points[i]; + + return Q_NULLPTR; +} + +QLibInputTouch::DeviceState *QLibInputTouch::deviceState(libinput_event_touch *e) +{ + libinput_device *dev = libinput_event_get_device(libinput_event_touch_get_base_event(e)); + return &m_devState[dev]; +} + +static inline QPointF getPos(libinput_event_touch *e) +{ + const QSize screenSize = QGuiApplication::primaryScreen()->geometry().size(); + 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); +} + +void QLibInputTouch::registerDevice(libinput_device *dev) +{ + QTouchDevice *&td = m_devState[dev].m_touchDevice; + td = new QTouchDevice; + td->setName(QString::fromUtf8(libinput_device_get_name(dev))); + td->setType(QTouchDevice::TouchScreen); + td->setCapabilities(QTouchDevice::Position | QTouchDevice::Area); + QWindowSystemInterface::registerTouchDevice(td); +} + +void QLibInputTouch::unregisterDevice(libinput_device *dev) +{ + Q_UNUSED(dev); + // There is no way to remove a QTouchDevice. +} + +void QLibInputTouch::processTouchDown(libinput_event_touch *e) +{ + int slot = libinput_event_touch_get_slot(e); + DeviceState *state = deviceState(e); + QWindowSystemInterface::TouchPoint *tp = state->point(slot); + if (tp) { + qWarning("Incorrect touch state"); + } else { + QWindowSystemInterface::TouchPoint newTp; + newTp.id = qMax(0, slot); + newTp.state = Qt::TouchPointPressed; + newTp.area = QRect(0, 0, 8, 8); + newTp.area.moveCenter(getPos(e)); + state->m_points.append(newTp); + } +} + +void QLibInputTouch::processTouchMotion(libinput_event_touch *e) +{ + int slot = libinput_event_touch_get_slot(e); + DeviceState *state = deviceState(e); + QWindowSystemInterface::TouchPoint *tp = state->point(slot); + if (tp) { + const QPointF p = getPos(e); + if (tp->area.center() != p) { + tp->area.moveCenter(p); + // 'down' may be followed by 'motion' within the same "frame". + // Handle this by compressing and keeping the Pressed state until the 'frame'. + if (tp->state != Qt::TouchPointPressed) + tp->state = Qt::TouchPointMoved; + } else { + tp->state = Qt::TouchPointStationary; + } + } else { + qWarning("Inconsistent touch state (got 'motion' without 'down')"); + } +} + +void QLibInputTouch::processTouchUp(libinput_event_touch *e) +{ + int slot = libinput_event_touch_get_slot(e); + DeviceState *state = deviceState(e); + QWindowSystemInterface::TouchPoint *tp = state->point(slot); + if (tp) { + tp->state = Qt::TouchPointReleased; + // There may not be a Frame event after the last Up. Work this around. + Qt::TouchPointStates s = 0; + for (int i = 0; i < state->m_points.count(); ++i) + s |= state->m_points.at(i).state; + if (s == Qt::TouchPointReleased) + processTouchFrame(e); + } else { + qWarning("Inconsistent touch state (got 'up' without 'down')"); + } +} + +void QLibInputTouch::processTouchCancel(libinput_event_touch *e) +{ + DeviceState *state = deviceState(e); + if (state->m_touchDevice) + QWindowSystemInterface::handleTouchCancelEvent(Q_NULLPTR, state->m_touchDevice, QGuiApplication::keyboardModifiers()); + else + qWarning("TouchCancel without registered device"); +} + +void QLibInputTouch::processTouchFrame(libinput_event_touch *e) +{ + DeviceState *state = deviceState(e); + if (state->m_touchDevice && !state->m_points.isEmpty()) { + QWindowSystemInterface::handleTouchEvent(Q_NULLPTR, state->m_touchDevice, state->m_points, + QGuiApplication::keyboardModifiers()); + for (int i = 0; i < state->m_points.count(); ++i) { + QWindowSystemInterface::TouchPoint &tp(state->m_points[i]); + if (tp.state == Qt::TouchPointReleased) + state->m_points.removeAt(i--); + else if (tp.state == Qt::TouchPointPressed) + tp.state = Qt::TouchPointStationary; + } + } else { + qWarning("TouchFrame without registered device"); + } +} + +QT_END_NAMESPACE diff --git a/src/platformsupport/input/libinput/qlibinputtouch_p.h b/src/platformsupport/input/libinput/qlibinputtouch_p.h new file mode 100644 index 0000000000..dceea5600c --- /dev/null +++ b/src/platformsupport/input/libinput/qlibinputtouch_p.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLIBINPUTTOUCH_P_H +#define QLIBINPUTTOUCH_P_H + +#include <QtCore/QHash> +#include <QtCore/QList> +#include <qpa/qwindowsysteminterface.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. +// + +struct libinput_event_touch; +struct libinput_device; + +QT_BEGIN_NAMESPACE + +class QLibInputTouch +{ +public: + void registerDevice(libinput_device *dev); + void unregisterDevice(libinput_device *dev); + void processTouchDown(libinput_event_touch *e); + void processTouchMotion(libinput_event_touch *e); + void processTouchUp(libinput_event_touch *e); + void processTouchCancel(libinput_event_touch *e); + void processTouchFrame(libinput_event_touch *e); + +private: + struct DeviceState { + DeviceState() : m_touchDevice(0) { } + QWindowSystemInterface::TouchPoint *point(int32_t slot); + QList<QWindowSystemInterface::TouchPoint> m_points; + QTouchDevice *m_touchDevice; + }; + + DeviceState *deviceState(libinput_event_touch *e); + + QHash<libinput_device *, DeviceState> m_devState; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/platformsupport/input/tslib/qtslib.cpp b/src/platformsupport/input/tslib/qtslib.cpp new file mode 100644 index 0000000000..e75fd9e691 --- /dev/null +++ b/src/platformsupport/input/tslib/qtslib.cpp @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtslib_p.h" + +#include <QSocketNotifier> +#include <QStringList> +#include <QPoint> +#include <QLoggingCategory> + +#include <qpa/qwindowsysteminterface.h> + +#include <errno.h> +#include <tslib.h> + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(qLcTsLib, "qt.qpa.input") + +QTsLibMouseHandler::QTsLibMouseHandler(const QString &key, + const QString &specification, + QObject *parent) + : QObject(parent), + m_notify(0), m_x(0), m_y(0), m_pressed(0), m_rawMode(false) +{ + qCDebug(qLcTsLib) << "Initializing tslib plugin" << key << specification; + setObjectName(QLatin1String("TSLib Mouse Handler")); + + QByteArray device = qgetenv("TSLIB_TSDEVICE"); + + if (specification.startsWith(QStringLiteral("/dev/"))) + device = specification.toLocal8Bit(); + + if (device.isEmpty()) + device = QByteArrayLiteral("/dev/input/event1"); + + m_dev = ts_open(device.constData(), 1); + if (!m_dev) { + qErrnoWarning(errno, "ts_open() failed"); + return; + } + + if (ts_config(m_dev)) + qErrnoWarning(errno, "ts_config() failed"); + + m_rawMode = !key.compare(QLatin1String("TslibRaw"), Qt::CaseInsensitive); + + int fd = ts_fd(m_dev); + if (fd >= 0) { + qCDebug(qLcTsLib) << "tslib device is" << device; + m_notify = new QSocketNotifier(fd, QSocketNotifier::Read, this); + connect(m_notify, SIGNAL(activated(int)), this, SLOT(readMouseData())); + } else { + qErrnoWarning(errno, "tslib: Cannot open input device %s", device.constData()); + } +} + +QTsLibMouseHandler::~QTsLibMouseHandler() +{ + if (m_dev) + ts_close(m_dev); +} + +static bool get_sample(struct tsdev *dev, struct ts_sample *sample, bool rawMode) +{ + if (rawMode) + return (ts_read_raw(dev, sample, 1) == 1); + else + return (ts_read(dev, sample, 1) == 1); +} + +void QTsLibMouseHandler::readMouseData() +{ + ts_sample sample; + + while (get_sample(m_dev, &sample, m_rawMode)) { + bool pressed = sample.pressure; + int x = sample.x; + int y = sample.y; + + // work around missing coordinates on mouse release + if (sample.pressure == 0 && sample.x == 0 && sample.y == 0) { + x = m_x; + y = m_y; + } + + if (!m_rawMode) { + //filtering: ignore movements of 2 pixels or less + int dx = x - m_x; + int dy = y - m_y; + if (dx*dx <= 4 && dy*dy <= 4 && pressed == m_pressed) + continue; + } + QPoint pos(x, y); + + QWindowSystemInterface::handleMouseEvent(0, pos, pos, pressed ? Qt::LeftButton : Qt::NoButton); + + m_x = x; + m_y = y; + m_pressed = pressed; + } +} + +QT_END_NAMESPACE diff --git a/src/platformsupport/input/tslib/qtslib_p.h b/src/platformsupport/input/tslib/qtslib_p.h new file mode 100644 index 0000000000..4bcefb6cb9 --- /dev/null +++ b/src/platformsupport/input/tslib/qtslib_p.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTSLIB_H +#define QTSLIB_H + +#include <QObject> + +struct tsdev; + +QT_BEGIN_NAMESPACE + +class QSocketNotifier; + +class QTsLibMouseHandler : public QObject +{ + Q_OBJECT + +public: + QTsLibMouseHandler(const QString &key, const QString &specification, QObject *parent = 0); + ~QTsLibMouseHandler(); + +private slots: + void readMouseData(); + +private: + QSocketNotifier * m_notify; + tsdev *m_dev; + int m_x, m_y; + bool m_pressed; + bool m_rawMode; +}; + +QT_END_NAMESPACE + +#endif // QTSLIB_H diff --git a/src/platformsupport/input/tslib/tslib.pri b/src/platformsupport/input/tslib/tslib.pri new file mode 100644 index 0000000000..c9fef1ca8f --- /dev/null +++ b/src/platformsupport/input/tslib/tslib.pri @@ -0,0 +1,7 @@ +HEADERS += \ + $$PWD/qtslib_p.h + +SOURCES += \ + $$PWD/qtslib.cpp + +LIBS += -lts |