summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config.tests/unix/evdev/evdev.cpp59
-rw-r--r--config.tests/unix/evdev/evdev.pro2
-rw-r--r--config.tests/unix/libudev/libudev.cpp49
-rw-r--r--config.tests/unix/libudev/libudev.pro3
-rwxr-xr-xconfigure42
-rw-r--r--src/platformsupport/platformsupport.pro1
-rw-r--r--src/platformsupport/udev/qudevhelper.cpp73
-rw-r--r--src/platformsupport/udev/qudevhelper_p.h (renamed from src/plugins/generic/touchscreen/qtoucheventsenderqpa.h)40
-rw-r--r--src/platformsupport/udev/udev.pri5
-rw-r--r--src/plugins/generic/evdevmouse/README11
-rw-r--r--src/plugins/generic/evdevmouse/evdevmouse.pro13
-rw-r--r--src/plugins/generic/evdevmouse/main.cpp (renamed from src/plugins/generic/linuxinput/main.cpp)24
-rw-r--r--src/plugins/generic/evdevmouse/qevdevmouse.cpp214
-rw-r--r--src/plugins/generic/evdevmouse/qevdevmouse.h (renamed from src/plugins/generic/linuxinput/qlinuxinput.h)32
-rw-r--r--src/plugins/generic/evdevtouch/70-qtouchscreen.rules (renamed from src/plugins/generic/touchscreen/70-qtouchscreen.rules)0
-rw-r--r--src/plugins/generic/evdevtouch/README36
-rw-r--r--src/plugins/generic/evdevtouch/evdevtouch.pro14
-rw-r--r--src/plugins/generic/evdevtouch/main.cpp (renamed from src/plugins/generic/touchscreen/main.cpp)18
-rw-r--r--src/plugins/generic/evdevtouch/qevdevtouch.cpp (renamed from src/plugins/generic/touchscreen/qtouchscreen.cpp)123
-rw-r--r--src/plugins/generic/evdevtouch/qevdevtouch.h (renamed from src/plugins/generic/touchscreen/qtouchscreen.h)20
-rw-r--r--src/plugins/generic/generic.pro6
-rw-r--r--src/plugins/generic/linuxinput/linuxinput.pro14
-rw-r--r--src/plugins/generic/linuxinput/qlinuxinput.cpp365
-rw-r--r--src/plugins/generic/touchscreen/README45
-rw-r--r--src/plugins/generic/touchscreen/qtoucheventsenderqpa.cpp116
-rw-r--r--src/plugins/generic/touchscreen/touchscreen.pro18
26 files changed, 651 insertions, 692 deletions
diff --git a/config.tests/unix/evdev/evdev.cpp b/config.tests/unix/evdev/evdev.cpp
new file mode 100644
index 0000000000..3dddd60038
--- /dev/null
+++ b/config.tests/unix/evdev/evdev.cpp
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the config.tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <linux/input.h>
+
+enum {
+ e1 = ABS_MT_POSITION_X,
+ e2 = ABS_MT_TRACKING_ID,
+ e3 = ABS_PRESSURE,
+ e4 = ABS_X,
+ e5 = REL_X,
+ e6 = SYN_REPORT,
+ e7 = SYN_MT_REPORT
+};
+
+int main()
+{
+ ::input_event buf[32];
+ (void) buf;
+ return 0;
+}
diff --git a/config.tests/unix/evdev/evdev.pro b/config.tests/unix/evdev/evdev.pro
new file mode 100644
index 0000000000..42db391216
--- /dev/null
+++ b/config.tests/unix/evdev/evdev.pro
@@ -0,0 +1,2 @@
+SOURCES = evdev.cpp
+CONFIG -= qt
diff --git a/config.tests/unix/libudev/libudev.cpp b/config.tests/unix/libudev/libudev.cpp
new file mode 100644
index 0000000000..1a08a715d8
--- /dev/null
+++ b/config.tests/unix/libudev/libudev.cpp
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the config.tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <libudev.h>
+
+int main()
+{
+ udev *u = udev_new();
+ udev_unref(u);
+ return 0;
+}
diff --git a/config.tests/unix/libudev/libudev.pro b/config.tests/unix/libudev/libudev.pro
new file mode 100644
index 0000000000..7f571b5a6d
--- /dev/null
+++ b/config.tests/unix/libudev/libudev.pro
@@ -0,0 +1,3 @@
+SOURCES = libudev.cpp
+CONFIG -= qt
+LIBS += -ludev
diff --git a/configure b/configure
index 5e78360fa6..a3b94e1eee 100755
--- a/configure
+++ b/configure
@@ -727,6 +727,8 @@ CFG_XKB=auto
CFG_XCB=auto
CFG_XCB_LIMITED=yes
CFG_WAYLAND=auto
+CFG_LIBUDEV=auto
+CFG_EVDEV=auto
CFG_NIS=auto
CFG_CUPS=auto
CFG_ICONV=auto
@@ -1843,6 +1845,20 @@ while [ "$#" -gt 0 ]; do
UNKNOWN_OPT=yes
fi
;;
+ libudev)
+ if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then
+ CFG_LIBUDEV="$VAL"
+ else
+ UNKNOWN_OPT=yes
+ fi
+ ;;
+ evdev)
+ if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then
+ CFG_EVDEV="$VAL"
+ else
+ UNKNOWN_OPT=yes
+ fi
+ ;;
cups)
if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then
CFG_CUPS="$VAL"
@@ -5651,6 +5667,32 @@ if [ "$PLATFORM_QPA" = "yes" ]; then
fi
fi
+ if [ "$CFG_LIBUDEV" != "no" ]; then
+ if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/unix/libudev "libudev" $L_FLAGS $I_FLAGS $l_FLAGS; then
+ CFG_LIBUDEV=yes
+ QT_CONFIG="$QT_CONFIG libudev"
+ elif [ "$CFG_LIBUDEV" = "yes" ]; then
+ echo "The libudev functionality test failed!"
+ exit 1
+ else
+ CFG_LIBUDEV=no
+ QMakeVar add DEFINES QT_NO_LIBUDEV
+ fi
+ fi
+
+ if [ "$CFG_EVDEV" != "no" ]; then
+ if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/unix/evdev "evdev" $L_FLAGS $I_FLAGS $l_FLAGS; then
+ CFG_EVDEV=yes
+ QT_CONFIG="$QT_CONFIG evdev"
+ elif [ "$CFG_EVDEV" = "yes" ]; then
+ echo "The evdev functionality test failed!"
+ exit 1
+ else
+ CFG_EVDEV=no
+ QMakeVar add DEFINES QT_NO_EVDEV
+ fi
+ fi
+
# Check we actually have X11 :-)
if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/x11/xlib "XLib" $L_FLAGS $I_FLAGS $l_FLAGS $X11TESTS_FLAGS; then
QT_CONFIG="$QT_CONFIG xlib"
diff --git a/src/platformsupport/platformsupport.pro b/src/platformsupport/platformsupport.pro
index 36323d9766..64decd0392 100644
--- a/src/platformsupport/platformsupport.pro
+++ b/src/platformsupport/platformsupport.pro
@@ -33,3 +33,4 @@ include(fontdatabases/fontdatabases.pri)
include(glxconvenience/glxconvenience.pri)
#include(printersupport/printersupport.pri)
include(inputcontext/inputcontext.pri)
+include(udev/udev.pri)
diff --git a/src/platformsupport/udev/qudevhelper.cpp b/src/platformsupport/udev/qudevhelper.cpp
new file mode 100644
index 0000000000..b63ef64ed8
--- /dev/null
+++ b/src/platformsupport/udev/qudevhelper.cpp
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qudevhelper_p.h"
+#include <libudev.h>
+
+QT_BEGIN_NAMESPACE
+
+void q_udev_devicePath(int type, QString *path)
+{
+ *path = QString();
+ udev *u = udev_new();
+ udev_enumerate *ue = udev_enumerate_new(u);
+ udev_enumerate_add_match_subsystem(ue, "input");
+ if (type & UDev_Mouse)
+ udev_enumerate_add_match_property(ue, "ID_INPUT_MOUSE", "1");
+ if (type & UDev_Touchpad)
+ udev_enumerate_add_match_property(ue, "ID_INPUT_TOUCHPAD", "1");
+ if (type & UDev_Touchscreen)
+ udev_enumerate_add_match_property(ue, "ID_INPUT_TOUCHSCREEN", "1");
+ udev_enumerate_scan_devices(ue);
+ udev_list_entry *entry;
+ udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(ue)) {
+ const char *syspath = udev_list_entry_get_name(entry);
+ udev_device *udevice = udev_device_new_from_syspath(u, syspath);
+ QString candidate = QString::fromLocal8Bit(udev_device_get_devnode(udevice));
+ udev_device_unref(udevice);
+ if (path->isEmpty() && candidate.startsWith(QLatin1String("/dev/input/event")))
+ *path = candidate;
+ }
+ udev_enumerate_unref(ue);
+ udev_unref(u);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/generic/touchscreen/qtoucheventsenderqpa.h b/src/platformsupport/udev/qudevhelper_p.h
index 6b21dfe259..e6046ca085 100644
--- a/src/plugins/generic/touchscreen/qtoucheventsenderqpa.h
+++ b/src/platformsupport/udev/qudevhelper_p.h
@@ -3,7 +3,7 @@
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
-** This file is part of the plugins module of the Qt Toolkit.
+** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
@@ -39,39 +39,21 @@
**
****************************************************************************/
-#ifndef QTOUCHEVENTSENDERQPA_H
-#define QTOUCHEVENTSENDERQPA_H
+#ifndef QUDEVHELPER_P_H
+#define QUDEVHELPER_P_H
-#include "qtouchscreen.h"
-
-QT_BEGIN_HEADER
+#include <QString>
QT_BEGIN_NAMESPACE
-class QTouchDevice;
-
-class QTouchEventSenderQPA : public QTouchScreenObserver
-{
-public:
- QTouchEventSenderQPA(const QString &spec = QString());
- void touch_configure(int x_min, int x_max, int y_min, int y_max,
- int pressure_min, int pressure_max, const QString &dev_name);
- void touch_point(const QList<QWindowSystemInterface::TouchPoint> &points);
-
-private:
- bool m_forceToActiveWindow;
- int hw_range_x_min;
- int hw_range_x_max;
- int hw_range_y_min;
- int hw_range_y_max;
- int hw_pressure_min;
- int hw_pressure_max;
- QString hw_dev_name;
- QTouchDevice *m_device;
+enum QUDeviceType {
+ UDev_Mouse = 0x01,
+ UDev_Touchpad = 0x02,
+ UDev_Touchscreen = 0x04
};
-QT_END_NAMESPACE
+void q_udev_devicePath(int type, QString *path);
-QT_END_HEADER
+QT_END_NAMESPACE
-#endif // QTOUCHEVENTSENDERQPA_H
+#endif // QUDEVHELPER_P_H
diff --git a/src/platformsupport/udev/udev.pri b/src/platformsupport/udev/udev.pri
new file mode 100644
index 0000000000..ac3f7df40a
--- /dev/null
+++ b/src/platformsupport/udev/udev.pri
@@ -0,0 +1,5 @@
+contains(QT_CONFIG, libudev) {
+ HEADERS += $$PWD/qudevhelper_p.h
+ SOURCES += $$PWD/qudevhelper.cpp
+ LIBS += -ludev
+}
diff --git a/src/plugins/generic/evdevmouse/README b/src/plugins/generic/evdevmouse/README
new file mode 100644
index 0000000000..b89c0a7066
--- /dev/null
+++ b/src/plugins/generic/evdevmouse/README
@@ -0,0 +1,11 @@
+Generic plug-in for absolute & relative evdev pointer events.
+
+To use it, launch apps with -plugin EvdevMouse
+
+The plug-in will try to pick a mouse or touchpad device from udev.
+If automatic detection does not work, use -plugin
+EvdevMouse:/dev/input/eventN to explicitly set the device node.
+
+The initial cursor position is assumed to be (0, 0). Relative events
+will generate Qt mouse events with screen positions relative to this
+initial position.
diff --git a/src/plugins/generic/evdevmouse/evdevmouse.pro b/src/plugins/generic/evdevmouse/evdevmouse.pro
new file mode 100644
index 0000000000..f25199161b
--- /dev/null
+++ b/src/plugins/generic/evdevmouse/evdevmouse.pro
@@ -0,0 +1,13 @@
+TARGET = qevdevmouseplugin
+load(qt_plugin)
+
+DESTDIR = $$QT.gui.plugins/generic
+target.path = $$[QT_INSTALL_PLUGINS]/generic
+INSTALLS += target
+
+HEADERS = qevdevmouse.h
+
+QT += core-private platformsupport-private
+
+SOURCES = main.cpp \
+ qevdevmouse.cpp
diff --git a/src/plugins/generic/linuxinput/main.cpp b/src/plugins/generic/evdevmouse/main.cpp
index 04fc00f528..34ca62f960 100644
--- a/src/plugins/generic/linuxinput/main.cpp
+++ b/src/plugins/generic/evdevmouse/main.cpp
@@ -40,38 +40,38 @@
****************************************************************************/
#include <qgenericplugin_qpa.h>
-#include "qlinuxinput.h"
+#include "qevdevmouse.h"
QT_BEGIN_NAMESPACE
-class QLinuxInputPlugin : public QGenericPlugin
+class QEvdevMousePlugin : public QGenericPlugin
{
public:
- QLinuxInputPlugin();
+ QEvdevMousePlugin();
QStringList keys() const;
QObject* create(const QString &key, const QString &specification);
};
-QLinuxInputPlugin::QLinuxInputPlugin()
+QEvdevMousePlugin::QEvdevMousePlugin()
: QGenericPlugin()
{
}
-QStringList QLinuxInputPlugin::keys() const
+QStringList QEvdevMousePlugin::keys() const
{
return (QStringList()
- << QLatin1String("LinuxInputMouse"));
+ << QLatin1String("EvdevMouse"));
}
-QObject* QLinuxInputPlugin::create(const QString &key,
- const QString &specification)
+QObject* QEvdevMousePlugin::create(const QString &key,
+ const QString &specification)
{
- if (!key.compare(QLatin1String("LinuxInputMouse"), Qt::CaseInsensitive))
- return new QLinuxInputMouseHandler(key, specification);
+ if (!key.compare(QLatin1String("EvdevMouse"), Qt::CaseInsensitive))
+ return new QEvdevMouseHandler(key, specification);
return 0;
- }
+}
-Q_EXPORT_PLUGIN2(qlinuxinputplugin, QLinuxInputPlugin)
+Q_EXPORT_PLUGIN2(qevdevmouseplugin, QEvdevMousePlugin)
QT_END_NAMESPACE
diff --git a/src/plugins/generic/evdevmouse/qevdevmouse.cpp b/src/plugins/generic/evdevmouse/qevdevmouse.cpp
new file mode 100644
index 0000000000..0b72123c02
--- /dev/null
+++ b/src/plugins/generic/evdevmouse/qevdevmouse.cpp
@@ -0,0 +1,214 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qevdevmouse.h"
+
+#include <QSocketNotifier>
+#include <QStringList>
+#include <QPoint>
+#include <QWindowSystemInterface>
+
+#include <qplatformdefs.h>
+#include <private/qcore_unix_p.h> // overrides QT_OPEN
+#include <QtPlatformSupport/private/qudevhelper_p.h>
+
+#include <errno.h>
+
+#include <linux/kd.h>
+#include <linux/input.h>
+
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+QEvdevMouseHandler::QEvdevMouseHandler(const QString &key,
+ const QString &specification)
+ : m_notify(0), m_x(0), m_y(0), m_prevx(0), m_prevy(0),
+ m_xoffset(0), m_yoffset(0), m_buttons(0)
+{
+ Q_UNUSED(key);
+ setObjectName(QLatin1String("Evdev Mouse Handler"));
+
+ QString dev;
+ q_udev_devicePath(UDev_Mouse | UDev_Touchpad, &dev);
+ if (dev.isEmpty())
+ dev = QLatin1String("/dev/input/event0");
+
+ m_compression = true;
+ m_smooth = false;
+ int jitterLimit = 0;
+
+ QStringList args = specification.split(QLatin1Char(':'));
+ foreach (const QString &arg, args) {
+ if (arg == "nocompress")
+ m_compression = false;
+ else if (arg.startsWith("dejitter="))
+ jitterLimit = arg.mid(9).toInt();
+ else if (arg.startsWith("xoffset="))
+ m_xoffset = arg.mid(8).toInt();
+ else if (arg.startsWith("yoffset="))
+ m_yoffset = arg.mid(8).toInt();
+ else if (arg.startsWith(QLatin1String("/dev/")))
+ dev = arg;
+ }
+ m_jitterLimitSquared = jitterLimit*jitterLimit;
+
+ qDebug("evdevmouse: Using device %s", qPrintable(dev));
+ m_fd = QT_OPEN(dev.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);
+ if (m_fd >= 0) {
+ m_notify = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
+ connect(m_notify, SIGNAL(activated(int)), this, SLOT(readMouseData()));
+ } else {
+ qWarning("Cannot open mouse input device '%s': %s", qPrintable(dev), strerror(errno));
+ return;
+ }
+}
+
+QEvdevMouseHandler::~QEvdevMouseHandler()
+{
+ if (m_fd >= 0)
+ QT_CLOSE(m_fd);
+}
+
+void QEvdevMouseHandler::sendMouseEvent()
+{
+ QPoint pos(m_x + m_xoffset, m_y + m_yoffset);
+ //qDebug("mouse event %d %d %d", pos.x(), pos.y(), int(m_buttons));
+ QWindowSystemInterface::handleMouseEvent(0, pos, pos, m_buttons);
+ m_prevx = m_x;
+ m_prevy = m_y;
+}
+
+void QEvdevMouseHandler::readMouseData()
+{
+ struct ::input_event buffer[32];
+ int n = 0;
+ bool posChanged = false;
+ bool pendingMouseEvent = false;
+ int eventCompressCount = 0;
+ forever {
+ n = QT_READ(m_fd, reinterpret_cast<char *>(buffer) + n, sizeof(buffer) - n);
+
+ if (n == 0) {
+ qWarning("Got EOF from the input device.");
+ return;
+ } else if (n < 0 && (errno != EINTR && errno != EAGAIN)) {
+ qWarning("Could not read from input device: %s", strerror(errno));
+ return;
+ } else if (n % sizeof(buffer[0]) == 0) {
+ break;
+ }
+ }
+
+ n /= sizeof(buffer[0]);
+
+ 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) {
+ if (data->code == ABS_X && m_x != data->value) {
+ m_x = data->value;
+ posChanged = true;
+ } else if (data->code == ABS_Y && m_y != data->value) {
+ m_y = data->value;
+ posChanged = true;
+ }
+ } else if (data->type == EV_REL) {
+ if (data->code == REL_X) {
+ m_x += data->value;
+ posChanged = true;
+ } else if (data->code == REL_Y) {
+ m_y += data->value;
+ posChanged = true;
+ } else if (data->code == ABS_WHEEL) { // vertical scroll
+ // data->value: 1 == up, -1 == down
+ int delta = 120 * data->value;
+ QWindowSystemInterface::handleWheelEvent(0, QPoint(m_x, m_y),
+ QPoint(m_x, m_y),
+ delta, Qt::Vertical);
+ } else if (data->code == ABS_THROTTLE) { // horizontal scroll
+ // data->value: 1 == right, -1 == left
+ int delta = 120 * -data->value;
+ QWindowSystemInterface::handleWheelEvent(0, QPoint(m_x, m_y),
+ QPoint(m_x, m_y),
+ delta, Qt::Horizontal);
+ }
+ } else if (data->type == EV_KEY && data->code == BTN_TOUCH) {
+ m_buttons = data->value ? Qt::LeftButton : Qt::NoButton;
+
+ sendMouseEvent();
+ pendingMouseEvent = false;
+ } else if (data->type == EV_KEY && data->code >= BTN_LEFT && data->code <= BTN_MIDDLE) {
+ Qt::MouseButton button = Qt::NoButton;
+ switch (data->code) {
+ case BTN_LEFT: button = Qt::LeftButton; break;
+ case BTN_MIDDLE: button = Qt::MidButton; break;
+ case BTN_RIGHT: button = Qt::RightButton; break;
+ }
+ if (data->value)
+ m_buttons |= button;
+ else
+ m_buttons &= ~button;
+ sendMouseEvent();
+ pendingMouseEvent = false;
+ } else if (data->type == EV_SYN && data->code == SYN_REPORT) {
+ if (posChanged) {
+ posChanged = false;
+ if (m_compression) {
+ pendingMouseEvent = true;
+ eventCompressCount++;
+ } else {
+ sendMouseEvent();
+ }
+ }
+ } else if (data->type == EV_MSC && data->code == MSC_SCAN) {
+ // kernel encountered an unmapped key - just ignore it
+ continue;
+ }
+ }
+ if (m_compression && pendingMouseEvent) {
+ int distanceSquared = (m_x - m_prevx)*(m_x - m_prevx) + (m_y - m_prevy)*(m_y - m_prevy);
+ if (distanceSquared > m_jitterLimitSquared)
+ sendMouseEvent();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/generic/linuxinput/qlinuxinput.h b/src/plugins/generic/evdevmouse/qevdevmouse.h
index a512ad959a..9542d133f2 100644
--- a/src/plugins/generic/linuxinput/qlinuxinput.h
+++ b/src/plugins/generic/evdevmouse/qevdevmouse.h
@@ -39,12 +39,11 @@
**
****************************************************************************/
-#ifndef QLINUXINPUT_H
-#define QLINUXINPUT_H
+#ifndef QEVDEVMOUSE_H
+#define QEVDEVMOUSE_H
-#include <qobject.h>
-#include <Qt>
-#include <termios.h>
+#include <QObject>
+#include <QString>
QT_BEGIN_HEADER
@@ -52,35 +51,34 @@ QT_BEGIN_NAMESPACE
class QSocketNotifier;
-class QLinuxInputMouseHandlerData;
-
-class QLinuxInputMouseHandler : public QObject
+class QEvdevMouseHandler : public QObject
{
Q_OBJECT
public:
- QLinuxInputMouseHandler(const QString &key, const QString &specification);
- ~QLinuxInputMouseHandler();
+ QEvdevMouseHandler(const QString &key, const QString &specification);
+ ~QEvdevMouseHandler();
private slots:
void readMouseData();
private:
- void sendMouseEvent(int x, int y, Qt::MouseButtons buttons);
- QSocketNotifier * m_notify;
- int m_fd;
- int m_x, m_y;
+ void sendMouseEvent();
+ void pathFromUdev(QString *path);
+
+ QSocketNotifier *m_notify;
+ int m_fd;
+ int m_x, m_y;
int m_prevx, m_prevy;
int m_xoffset, m_yoffset;
int m_smoothx, m_smoothy;
- Qt::MouseButtons m_buttons;
+ Qt::MouseButtons m_buttons;
bool m_compression;
bool m_smooth;
int m_jitterLimitSquared;
- QLinuxInputMouseHandlerData *d;
};
QT_END_NAMESPACE
QT_END_HEADER
-#endif // QLINUXINPUT_H
+#endif // QEVDEVMOUSE_H
diff --git a/src/plugins/generic/touchscreen/70-qtouchscreen.rules b/src/plugins/generic/evdevtouch/70-qtouchscreen.rules
index 2afde8f8a3..2afde8f8a3 100644
--- a/src/plugins/generic/touchscreen/70-qtouchscreen.rules
+++ b/src/plugins/generic/evdevtouch/70-qtouchscreen.rules
diff --git a/src/plugins/generic/evdevtouch/README b/src/plugins/generic/evdevtouch/README
new file mode 100644
index 0000000000..4764ef8f70
--- /dev/null
+++ b/src/plugins/generic/evdevtouch/README
@@ -0,0 +1,36 @@
+Generic plug-in for evdev touch events. (protocol type A)
+
+Tested with the following drivers: bcm5974, hid_magicmouse.
+
+To use it, pass -plugin EvdevTouch on the command line.
+
+If automatic detection does not work, use -plugin
+EvdevTouch:/dev/input/eventN to explicitly set the device file
+name.
+
+By default the surface of the touch device is mapped to the entire
+screen. If this is not desired, pass force_window in the plugin
+specification as shown in the example above. This will cause mapping
+the touch surface to the active window instead. For example:
+./fingerpaint -plugin EvdevTouch:force_window
+
+Only touch events are generated, mouse events are not. Be aware however
+that ignored touch events will generate a mouse event from the first
+touch point by default. See AA_SynthesizeMouseForUnhandledTouchEvents.
+
+If no evdev events are read, disable the synaptics driver from X or
+temporarily disable the device by running
+xinput set-prop <device> <device enabled property> 0.
+Use xinput list and xinput list-props to figure out the values.
+
+When not running on a windowing system (eglfs, kms, etc.) and having a
+touchpad, the evdevmouse and touch plugins can be combined to get both
+mouse and touch events:
+./app -platform kms -plugin EvdevTouch -plugin EvdevMouse
+
+If the input device cannot be accessed, set up a udev rule.
+For example:
+ sudo cp 70-qtouchscreen.rules /etc/udev/rules.d
+ sudo udevadm trigger --subsystem-match=input
+The udev rule matches any touchpad or touchscreen device. If there are
+multiple ones, specify the device manually as described above.
diff --git a/src/plugins/generic/evdevtouch/evdevtouch.pro b/src/plugins/generic/evdevtouch/evdevtouch.pro
new file mode 100644
index 0000000000..78fe551aa2
--- /dev/null
+++ b/src/plugins/generic/evdevtouch/evdevtouch.pro
@@ -0,0 +1,14 @@
+TARGET = qevdevtouchplugin
+load(qt_plugin)
+
+DESTDIR = $$QT.gui.plugins/generic
+target.path = $$[QT_INSTALL_PLUGINS]/generic
+INSTALLS += target
+
+HEADERS = \
+ qevdevtouch.h
+
+SOURCES = main.cpp \
+ qevdevtouch.cpp
+
+QT += core-private platformsupport-private
diff --git a/src/plugins/generic/touchscreen/main.cpp b/src/plugins/generic/evdevtouch/main.cpp
index 1f438ef1e7..526e336fd8 100644
--- a/src/plugins/generic/touchscreen/main.cpp
+++ b/src/plugins/generic/evdevtouch/main.cpp
@@ -40,8 +40,7 @@
****************************************************************************/
#include <qgenericplugin_qpa.h>
-#include "qtouchscreen.h"
-#include "qtoucheventsenderqpa.h"
+#include "qevdevtouch.h"
QT_BEGIN_NAMESPACE
@@ -60,21 +59,18 @@ QTouchScreenPlugin::QTouchScreenPlugin()
QStringList QTouchScreenPlugin::keys() const
{
- return QStringList() << "LinuxTouchScreen";
+ return QStringList() << "EvdevTouch";
}
QObject* QTouchScreenPlugin::create(const QString &key,
- const QString &spec)
+ const QString &spec)
{
- if (!key.compare(QLatin1String("LinuxTouchScreen"), Qt::CaseInsensitive)) {
- QTouchScreenObserver *obs = new QTouchEventSenderQPA(spec);
- QTouchScreenHandlerThread *h = new QTouchScreenHandlerThread(spec, obs);
- return h;
- }
+ if (!key.compare(QLatin1String("EvdevTouch"), Qt::CaseInsensitive))
+ return new QTouchScreenHandlerThread(spec);
return 0;
- }
+}
-Q_EXPORT_PLUGIN2(qtouchscreenplugin, QTouchScreenPlugin)
+Q_EXPORT_PLUGIN2(qevdevtouchplugin, QTouchScreenPlugin)
QT_END_NAMESPACE
diff --git a/src/plugins/generic/touchscreen/qtouchscreen.cpp b/src/plugins/generic/evdevtouch/qevdevtouch.cpp
index 8e04c10b9f..d508c4a12a 100644
--- a/src/plugins/generic/touchscreen/qtouchscreen.cpp
+++ b/src/plugins/generic/evdevtouch/qevdevtouch.cpp
@@ -39,13 +39,15 @@
**
****************************************************************************/
-#include "qtouchscreen.h"
+#include "qevdevtouch.h"
#include <QStringList>
#include <QHash>
#include <QSocketNotifier>
+#include <QGuiApplication>
+#include <QDebug>
#include <QtCore/private/qcore_unix_p.h>
+#include <QtPlatformSupport/private/qudevhelper_p.h>
#include <linux/input.h>
-#include <libudev.h>
QT_BEGIN_NAMESPACE
@@ -77,6 +79,8 @@ public:
Contact m_currentData;
int findClosestContact(const QHash<int, Contact> &contacts, int x, int y, int *dist);
+ void reportPoints();
+ void registerDevice();
int hw_range_x_min;
int hw_range_x_max;
@@ -85,8 +89,8 @@ public:
int hw_pressure_min;
int hw_pressure_max;
QString hw_name;
-
- QList<QTouchScreenObserver *> m_observers;
+ bool m_forceToActiveWindow;
+ QTouchDevice *m_device;
};
QTouchScreenData::QTouchScreenData(QTouchScreenHandler *q_ptr, const QStringList &args)
@@ -96,23 +100,37 @@ QTouchScreenData::QTouchScreenData(QTouchScreenHandler *q_ptr, const QStringList
hw_range_y_min(0), hw_range_y_max(0),
hw_pressure_min(0), hw_pressure_max(0)
{
- Q_UNUSED(args);
+ m_forceToActiveWindow = args.contains(QLatin1String("force_window"));
+}
+
+void QTouchScreenData::registerDevice()
+{
+ m_device = new QTouchDevice;
+ m_device->setName(hw_name);
+ m_device->setType(QTouchDevice::TouchScreen);
+ m_device->setCapabilities(QTouchDevice::Position | QTouchDevice::Area);
+ if (hw_pressure_max > hw_pressure_min)
+ m_device->setCapabilities(m_device->capabilities() | QTouchDevice::Pressure);
+
+ QWindowSystemInterface::registerTouchDevice(m_device);
}
QTouchScreenHandler::QTouchScreenHandler(const QString &spec)
: m_notify(0), m_fd(-1), d(0)
{
- setObjectName(QLatin1String("Linux Touch Handler"));
+ setObjectName(QLatin1String("Evdev Touch Handler"));
- QString dev = QLatin1String("/dev/input/event5");
- try_udev(&dev);
+ QString dev;
+ q_udev_devicePath(UDev_Touchpad | UDev_Touchscreen, &dev);
+ if (dev.isEmpty())
+ dev = QLatin1String("/dev/input/event0");
QStringList args = spec.split(QLatin1Char(':'));
for (int i = 0; i < args.count(); ++i)
if (args.at(i).startsWith(QLatin1String("/dev/")))
dev = args.at(i);
- qDebug("Using device '%s'", qPrintable(dev));
+ qDebug("evdevtouch: Using device %s", qPrintable(dev));
m_fd = QT_OPEN(dev.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);
if (m_fd >= 0) {
@@ -149,6 +167,8 @@ QTouchScreenHandler::QTouchScreenHandler(const QString &spec)
d->hw_name = QString::fromLocal8Bit(name);
qDebug("device name: %s", name);
}
+
+ d->registerDevice();
}
QTouchScreenHandler::~QTouchScreenHandler()
@@ -159,38 +179,6 @@ QTouchScreenHandler::~QTouchScreenHandler()
delete d;
}
-void QTouchScreenHandler::addObserver(QTouchScreenObserver *observer)
-{
- if (!d || !observer)
- return;
- d->m_observers.append(observer);
- observer->touch_configure(d->hw_range_x_min, d->hw_range_x_max,
- d->hw_range_y_min, d->hw_range_y_max,
- d->hw_pressure_min, d->hw_pressure_max,
- d->hw_name);
-}
-
-void QTouchScreenHandler::try_udev(QString *path)
-{
- *path = QString();
- udev *u = udev_new();
- udev_enumerate *ue = udev_enumerate_new(u);
- udev_enumerate_add_match_subsystem(ue, "input");
- udev_enumerate_add_match_property(ue, "ID_INPUT_TOUCHPAD", "1");
- udev_enumerate_scan_devices(ue);
- udev_list_entry *entry;
- udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(ue)) {
- const char *syspath = udev_list_entry_get_name(entry);
- udev_device *udevice = udev_device_new_from_syspath(u, syspath);
- QString candidate = QString::fromLocal8Bit(udev_device_get_devnode(udevice));
- udev_device_unref(udevice);
- if (path->isEmpty() && candidate.startsWith("/dev/input/event"))
- *path = candidate;
- }
- udev_enumerate_unref(ue);
- udev_unref(u);
-}
-
void QTouchScreenHandler::readData()
{
::input_event buffer[32];
@@ -289,7 +277,7 @@ void QTouchScreenData::processInputEvent(input_event *data)
tp.state = contact.state;
combinedStates |= tp.state;
- // Store the HW coordinates. Observers can then map it to screen space or something else.
+ // Store the HW coordinates for now, will be updated later.
tp.area = QRectF(0, 0, contact.maj, contact.maj);
tp.area.moveCenter(QPoint(contact.x, contact.y));
tp.pressure = contact.pressure;
@@ -307,10 +295,8 @@ void QTouchScreenData::processInputEvent(input_event *data)
m_lastContacts = m_contacts;
m_contacts.clear();
- if (!m_touchPoints.isEmpty() && combinedStates != Qt::TouchPointStationary) {
- for (int i = 0; i < m_observers.count(); ++i)
- m_observers.at(i)->touch_point(m_touchPoints);
- }
+ if (!m_touchPoints.isEmpty() && combinedStates != Qt::TouchPointStationary)
+ reportPoints();
}
m_lastEventType = data->type;
@@ -369,10 +355,48 @@ void QTouchScreenData::assignIds()
m_contacts = newContacts;
}
+void QTouchScreenData::reportPoints()
+{
+ QRect winRect;
+ if (m_forceToActiveWindow) {
+ QWindow *win = QGuiApplication::activeWindow();
+ if (!win)
+ return;
+ winRect = win->geometry();
+ } else {
+ winRect = QGuiApplication::primaryScreen()->geometry();
+ }
+
+ const int hw_w = hw_range_x_max - hw_range_x_min;
+ const int hw_h = hw_range_y_max - hw_range_y_min;
+
+ // Map the coordinates based on the normalized position. QPA expects 'area'
+ // to be in screen coordinates.
+ const int pointCount = m_touchPoints.count();
+ for (int i = 0; i < pointCount; ++i) {
+ QWindowSystemInterface::TouchPoint &tp(m_touchPoints[i]);
+
+ // Generate a screen position that is always inside the active window
+ // or the primary screen.
+ const int wx = winRect.left() + int(tp.normalPosition.x() * winRect.width());
+ const int wy = winRect.top() + int(tp.normalPosition.y() * winRect.height());
+ const qreal sizeRatio = (winRect.width() + winRect.height()) / qreal(hw_w + hw_h);
+ tp.area = QRect(0, 0, tp.area.width() * sizeRatio, tp.area.height() * sizeRatio);
+ tp.area.moveCenter(QPoint(wx, wy));
+
+ // Calculate normalized pressure.
+ if (!hw_pressure_min && !hw_pressure_max)
+ tp.pressure = tp.state == Qt::TouchPointReleased ? 0 : 1;
+ else
+ tp.pressure = (tp.pressure - hw_pressure_min) / qreal(hw_pressure_max - hw_pressure_min);
+ }
+
+ QWindowSystemInterface::handleTouchEvent(0, m_device, m_touchPoints);
+}
+
-QTouchScreenHandlerThread::QTouchScreenHandlerThread(const QString &spec,
- QTouchScreenObserver *observer)
- : m_spec(spec), m_handler(0), m_observer(observer)
+QTouchScreenHandlerThread::QTouchScreenHandlerThread(const QString &spec)
+ : m_spec(spec), m_handler(0)
{
start();
}
@@ -386,7 +410,6 @@ QTouchScreenHandlerThread::~QTouchScreenHandlerThread()
void QTouchScreenHandlerThread::run()
{
m_handler = new QTouchScreenHandler(m_spec);
- m_handler->addObserver(m_observer);
exec();
delete m_handler;
m_handler = 0;
diff --git a/src/plugins/generic/touchscreen/qtouchscreen.h b/src/plugins/generic/evdevtouch/qevdevtouch.h
index 33a1b0ad2f..343f638526 100644
--- a/src/plugins/generic/touchscreen/qtouchscreen.h
+++ b/src/plugins/generic/evdevtouch/qevdevtouch.h
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef QTOUCHSCREEN_H
-#define QTOUCHSCREEN_H
+#ifndef QEVDEVTOUCH_H
+#define QEVDEVTOUCH_H
#include <QObject>
#include <QString>
@@ -55,14 +55,6 @@ QT_BEGIN_NAMESPACE
class QSocketNotifier;
class QTouchScreenData;
-class QTouchScreenObserver
-{
-public:
- virtual void touch_configure(int x_min, int x_max, int y_min, int y_max,
- int pressure_min, int pressure_max, const QString &dev_name) = 0;
- virtual void touch_point(const QList<QWindowSystemInterface::TouchPoint> &points) = 0;
-};
-
class QTouchScreenHandler : public QObject
{
Q_OBJECT
@@ -70,13 +62,12 @@ class QTouchScreenHandler : public QObject
public:
QTouchScreenHandler(const QString &spec = QString());
~QTouchScreenHandler();
- void addObserver(QTouchScreenObserver *observer);
private slots:
void readData();
private:
- void try_udev(QString *path);
+ void pathFromUdev(QString *path);
QSocketNotifier *m_notify;
int m_fd;
@@ -86,7 +77,7 @@ private:
class QTouchScreenHandlerThread : public QThread
{
public:
- QTouchScreenHandlerThread(const QString &spec, QTouchScreenObserver *observer);
+ QTouchScreenHandlerThread(const QString &spec);
~QTouchScreenHandlerThread();
void run();
QTouchScreenHandler *handler() { return m_handler; }
@@ -94,11 +85,10 @@ public:
private:
QString m_spec;
QTouchScreenHandler *m_handler;
- QTouchScreenObserver *m_observer;
};
QT_END_NAMESPACE
QT_END_HEADER
-#endif // QTOUCHSCREEN_H
+#endif // QEVDEVTOUCH_H
diff --git a/src/plugins/generic/generic.pro b/src/plugins/generic/generic.pro
index 68c7636940..c4c3f9229a 100644
--- a/src/plugins/generic/generic.pro
+++ b/src/plugins/generic/generic.pro
@@ -1,3 +1,9 @@
TEMPLATE = subdirs
linux-g++-maemo: SUBDIRS += meego
+
+contains(QT_CONFIG, evdev) {
+ contains(QT_CONFIG, libudev) {
+ SUBDIRS += evdevmouse evdevtouch
+ }
+}
diff --git a/src/plugins/generic/linuxinput/linuxinput.pro b/src/plugins/generic/linuxinput/linuxinput.pro
deleted file mode 100644
index 6ef5f0fb3a..0000000000
--- a/src/plugins/generic/linuxinput/linuxinput.pro
+++ /dev/null
@@ -1,14 +0,0 @@
-TARGET = qlinuxinputplugin
-load(qt_plugin)
-
-DESTDIR = $$QT.gui.plugins/generic
-target.path = $$[QT_INSTALL_PLUGINS]/generic
-INSTALLS += target
-
-HEADERS = qlinuxinput.h
-
-QT += core-private
-
-SOURCES = main.cpp \
- qlinuxinput.cpp
-
diff --git a/src/plugins/generic/linuxinput/qlinuxinput.cpp b/src/plugins/generic/linuxinput/qlinuxinput.cpp
deleted file mode 100644
index 04633845cb..0000000000
--- a/src/plugins/generic/linuxinput/qlinuxinput.cpp
+++ /dev/null
@@ -1,365 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-#include "qlinuxinput.h"
-
-
-#include <QSocketNotifier>
-#include <QStringList>
-#include <QPoint>
-#include <QWindowSystemInterface>
-
-#include <qplatformdefs.h>
-#include <private/qcore_unix_p.h> // overrides QT_OPEN
-
-#include <errno.h>
-#include <termios.h>
-
-#include <linux/kd.h>
-#include <linux/input.h>
-
-#include <qdebug.h>
-
-QT_BEGIN_NAMESPACE
-
-
-//#define QT_QPA_EXPERIMENTAL_TOUCHEVENT
-
-#ifdef QT_QPA_EXPERIMENTAL_TOUCHEVENT
-class QLinuxInputMouseHandlerData
-{
-public:
- QLinuxInputMouseHandlerData() :seenMT(false), state(QEvent::TouchBegin), currentIdx(0) {}
-
- void ensureCurrentPoint() {
- if (currentIdx >= touchPoints.size()) {
- Q_ASSERT(currentIdx == touchPoints.size());
- QWindowSystemInterface::TouchPoint tp;
- tp.id = currentIdx;
- tp.isPrimary = (currentIdx == 0);
- tp.pressure = 1;
- tp.area = QRectF(0,0,1,1);
- tp.state = Qt::TouchPointReleased; // init in neutral state
- touchPoints.append(tp);
- }
- }
- void setCurrentPoint(int i) {
- currentIdx = i;
- if (currentIdx < touchPoints.size()) {
- currentX = int(touchPoints[currentIdx].area.left());
- currentY = int(touchPoints[currentIdx].area.top());
- } else {
- currentY = currentX = -999;
- }
- }
- void advanceCurrentPoint() {
- setCurrentPoint(currentIdx + 1);
- }
- int currentPoint() { return currentIdx; }
- void setCurrentX(int value) {
- ensureCurrentPoint();
- touchPoints[currentIdx].area.moveLeft(value);
- }
- bool currentMoved() {
- return currentX != touchPoints[currentIdx].area.left() || currentY != touchPoints[currentIdx].area.top();
- }
- void updateCurrentPos() {
- ensureCurrentPoint();
- touchPoints[currentIdx].area.moveTopLeft(QPointF(currentX, currentY));
- }
- void setCurrentState(Qt::TouchPointState state) {
- ensureCurrentPoint();
- touchPoints[currentIdx].state = state;
- }
- Qt::TouchPointState currentState() const {
- if (currentIdx < touchPoints.size())
- return touchPoints[currentIdx].state;
- return Qt::TouchPointReleased;
- }
- QList<QWindowSystemInterface::TouchPoint> touchPoints;
- int currentX;
- int currentY;
- bool seenMT;
- QEvent::Type state;
-private:
- int currentIdx;
-};
-#endif
-
-
-QLinuxInputMouseHandler::QLinuxInputMouseHandler(const QString &key,
- const QString &specification)
- : m_notify(0), m_x(0), m_y(0), m_prevx(0), m_prevy(0), m_xoffset(0), m_yoffset(0), m_buttons(0), d(0)
-{
- qDebug() << "QLinuxInputMouseHandler" << key << specification;
-
-
- setObjectName(QLatin1String("LinuxInputSubsystem Mouse Handler"));
-
- QString dev = QLatin1String("/dev/input/event0");
- m_compression = true;
- m_smooth = false;
- int jitterLimit = 0;
-
- QStringList args = specification.split(QLatin1Char(':'));
- foreach (const QString &arg, args) {
- if (arg == "nocompress")
- m_compression = false;
- else if (arg.startsWith("dejitter="))
- jitterLimit = arg.mid(9).toInt();
- else if (arg.startsWith("xoffset="))
- m_xoffset = arg.mid(8).toInt();
- else if (arg.startsWith("yoffset="))
- m_yoffset = arg.mid(8).toInt();
- else if (arg.startsWith(QLatin1String("/dev/")))
- dev = arg;
- }
- m_jitterLimitSquared = jitterLimit*jitterLimit;
-
- m_fd = QT_OPEN(dev.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);
- if (m_fd >= 0) {
- m_notify = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
- connect(m_notify, SIGNAL(activated(int)), this, SLOT(readMouseData()));
- } else {
- qWarning("Cannot open mouse input device '%s': %s", qPrintable(dev), strerror(errno));
- return;
- }
-#ifdef QT_QPA_EXPERIMENTAL_TOUCHEVENT
- d = new QLinuxInputMouseHandlerData;
-#endif
-}
-
-
-QLinuxInputMouseHandler::~QLinuxInputMouseHandler()
-{
- if (m_fd >= 0)
- QT_CLOSE(m_fd);
-#ifdef QT_QPA_EXPERIMENTAL_TOUCHEVENT
- delete d;
-#endif
-}
-
-void QLinuxInputMouseHandler::sendMouseEvent(int x, int y, Qt::MouseButtons buttons)
-{
- QPoint pos(x+m_xoffset, y+m_yoffset);
- QWindowSystemInterface::handleMouseEvent(0, pos, pos, m_buttons);
- m_prevx = x;
- m_prevy = y;
-}
-
-void QLinuxInputMouseHandler::readMouseData()
-{
- struct ::input_event buffer[32];
- int n = 0;
- bool posChanged = false;
- bool pendingMouseEvent = false;
- int eventCompressCount = 0;
- forever {
- n = QT_READ(m_fd, reinterpret_cast<char *>(buffer) + n, sizeof(buffer) - n);
-
- if (n == 0) {
- qWarning("Got EOF from the input device.");
- return;
- } else if (n < 0 && (errno != EINTR && errno != EAGAIN)) {
- qWarning("Could not read from input device: %s", strerror(errno));
- return;
- } else if (n % sizeof(buffer[0]) == 0) {
- break;
- }
- }
-
- n /= sizeof(buffer[0]);
-
- for (int i = 0; i < n; ++i) {
- struct ::input_event *data = &buffer[i];
- //qDebug() << ">>" << hex << data->type << data->code << dec << data->value;
- bool unknown = false;
- if (data->type == EV_ABS) {
- if (data->code == ABS_X && m_x != data->value) {
- m_x = data->value;
- posChanged = true;
- } else if (data->code == ABS_Y && m_y != data->value) {
- m_y = data->value;
- posChanged = true;
- } else if (data->code == ABS_PRESSURE) {
- //ignore for now...
- } else if (data->code == ABS_TOOL_WIDTH) {
- //ignore for now...
- } else if (data->code == ABS_HAT0X) {
- //ignore for now...
- } else if (data->code == ABS_HAT0Y) {
- //ignore for now...
-#ifdef QT_QPA_EXPERIMENTAL_TOUCHEVENT
- } else if (data->code == ABS_MT_POSITION_X) {
- d->currentX = data->value;
- d->seenMT = true;
- } else if (data->code == ABS_MT_POSITION_Y) {
- d->currentY = data->value;
- d->seenMT = true;
- } else if (data->code == ABS_MT_TOUCH_MAJOR) {
- if (data->value == 0)
- d->setCurrentState(Qt::TouchPointReleased);
- //otherwise, ignore for now...
- } else if (data->code == ABS_MT_TOUCH_MINOR) {
- //ignore for now...
-#endif
- } else {
- unknown = true;
- }
- } else if (data->type == EV_REL) {
- if (data->code == REL_X) {
- m_x += data->value;
- posChanged = true;
- } else if (data->code == REL_Y) {
- m_y += data->value;
- posChanged = true;
- } else if (data->code == ABS_WHEEL) { // vertical scroll
- // data->value: 1 == up, -1 == down
- int delta = 120 * data->value;
- QWindowSystemInterface::handleWheelEvent(0, QPoint(m_x, m_y),
- QPoint(m_x, m_y),
- delta, Qt::Vertical);
- } else if (data->code == ABS_THROTTLE) { // horizontal scroll
- // data->value: 1 == right, -1 == left
- int delta = 120 * -data->value;
- QWindowSystemInterface::handleWheelEvent(0, QPoint(m_x, m_y),
- QPoint(m_x, m_y),
- delta, Qt::Horizontal);
- } else {
- unknown = true;
- }
- } else if (data->type == EV_KEY && data->code == BTN_TOUCH) {
- m_buttons = data->value ? Qt::LeftButton : Qt::NoButton;
-
- sendMouseEvent(m_x, m_y, m_buttons);
- pendingMouseEvent = false;
- } else if (data->type == EV_KEY && data->code >= BTN_LEFT && data->code <= BTN_MIDDLE) {
- Qt::MouseButton button = Qt::NoButton;
- switch (data->code) {
- case BTN_LEFT: button = Qt::LeftButton; break;
- case BTN_MIDDLE: button = Qt::MidButton; break;
- case BTN_RIGHT: button = Qt::RightButton; break;
- }
- if (data->value)
- m_buttons |= button;
- else
- m_buttons &= ~button;
- sendMouseEvent(m_x, m_y, m_buttons);
- pendingMouseEvent = false;
- } else if (data->type == EV_SYN && data->code == SYN_REPORT) {
- if (posChanged) {
- posChanged = false;
- if (m_compression) {
- pendingMouseEvent = true;
- eventCompressCount++;
- } else {
- sendMouseEvent(m_x, m_y, m_buttons);
- }
- }
-#ifdef QT_QPA_EXPERIMENTAL_TOUCHEVENT
- if (d->state == QEvent::TouchBegin && !d->seenMT) {
- //no multipoint-touch events to send
- } else {
- if (!d->seenMT)
- d->state = QEvent::TouchEnd;
-
- for (int i = d->currentPoint(); i < d->touchPoints.size(); ++i) {
- d->touchPoints[i].pressure = 0;
- d->touchPoints[i].state = Qt::TouchPointReleased;
- }
- //qDebug() << "handleTouchEvent" << d->state << d->touchPoints.size() << d->touchPoints[0].state;
- QWindowSystemInterface::handleTouchEvent(0, d->state, QTouchEvent::TouchScreen, d->touchPoints);
- if (d->seenMT) {
- d->state = QEvent::TouchUpdate;
- } else {
- d->state = QEvent::TouchBegin;
- d->touchPoints.clear();
- }
- d->setCurrentPoint(0);
- d->seenMT = false;
- }
- } else if (data->type == EV_SYN && data->code == SYN_MT_REPORT) {
- //store data for this touch point
-
- if (!d->seenMT) {
- d->setCurrentState(Qt::TouchPointReleased);
- } else if (d->currentState() == Qt::TouchPointReleased) {
- d->updateCurrentPos();
- d->setCurrentState(Qt::TouchPointPressed);
- } else if (d->currentMoved()) {
- d->updateCurrentPos();
- d->setCurrentState(Qt::TouchPointMoved);
- } else {
- d->setCurrentState(Qt::TouchPointStationary);
- }
- //qDebug() << "end of point" << d->currentPoint() << d->currentX << d->currentY << d->currentState();
-
- //advance to next tp:
- d->advanceCurrentPoint();
-#endif
- } else if (data->type == EV_MSC && data->code == MSC_SCAN) {
- // kernel encountered an unmapped key - just ignore it
- continue;
- } else {
- unknown = true;
- }
-#ifdef QLINUXINPUT_EXTRA_DEBUG
- if (unknown) {
- qWarning("unknown mouse event type=%x, code=%x, value=%x", data->type, data->code, data->value);
- }
-#endif
- }
- if (m_compression && pendingMouseEvent) {
- int distanceSquared = (m_x - m_prevx)*(m_x - m_prevx) + (m_y - m_prevy)*(m_y - m_prevy);
- if (distanceSquared > m_jitterLimitSquared)
- sendMouseEvent(m_x, m_y, m_buttons);
- }
-}
-
-
-
-
-
-
-
-QT_END_NAMESPACE
-
diff --git a/src/plugins/generic/touchscreen/README b/src/plugins/generic/touchscreen/README
deleted file mode 100644
index ac73f5f147..0000000000
--- a/src/plugins/generic/touchscreen/README
+++ /dev/null
@@ -1,45 +0,0 @@
-Generic plug-in for evdev touch events.
-
-Tested with the following drivers: bcm5974, hid_magicmouse.
-
-(1) Using as a QPA generic plug-in
-
-1. set up and connect the touch device
-2. install libudev-dev or similar
-3. build this plug-in (qmake && make)
-4. sudo cp 70-qtouchscreen.rules /etc/udev/rules.d
-5. sudo udevadm trigger --subsystem-match=input
-6. ./fingerpaint -plugin LinuxTouchScreen:force_window
-
-If automatic detection does not work, use -plugin
-LinuxTouchScreen:/dev/input/eventN to explicitly set the device file
-name.
-
-By default the surface of the touch device is mapped to the entire
-screen. If this is not desired, pass force_window in the plugin
-specification as shown in the example above. This will cause mapping
-the touch surface to the active window instead.
-
-Only touch events are generated, mouse events are not. Be aware however
-that ignored touch events will generate a mouse event from the first
-touch point by default. See AA_SynthesizeMouseForUnhandledTouchEvents.
-
-(2) Using in a compositor
-
-The classes (QTouchScreenHandler, QTouchScreenHandlerThread) are also
-suitable for direct inclusion into an application, e.g. a Wayland
-compositor. The compositor may then register its own
-QTouchScreenObserver because relying on the QTouchEvents generated by
-the QPA event sender may not always be satisfactory as some low-level
-details get lost, and due to performance reasons.
-
-(3) Possible issues and solutions
-
-The udev rule matches any touchpad device. If there are multiple ones,
-specify the device as described above.
-
-If no evdev events are read, remove 50-synaptics.conf (or similar)
-from /usr/share/X11/xorg.conf.d and restart X. Or at least temporarily
-disable the device by running xinput set-prop <device> <device enabled
-property> 0. Use xinput list and xinput list-props to figure out the
-values.
diff --git a/src/plugins/generic/touchscreen/qtoucheventsenderqpa.cpp b/src/plugins/generic/touchscreen/qtoucheventsenderqpa.cpp
deleted file mode 100644
index ac4a12c09a..0000000000
--- a/src/plugins/generic/touchscreen/qtoucheventsenderqpa.cpp
+++ /dev/null
@@ -1,116 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/
-**
-** This file is part of the plugins module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qtoucheventsenderqpa.h"
-#include <QGuiApplication>
-#include <QScreen>
-#include <QStringList>
-#include <QDebug>
-
-QT_BEGIN_NAMESPACE
-
-QTouchEventSenderQPA::QTouchEventSenderQPA(const QString &spec)
-{
- m_forceToActiveWindow = spec.split(QLatin1Char(':')).contains(QLatin1String("force_window"));
- m_device = new QTouchDevice;
- m_device->setType(QTouchDevice::TouchScreen);
- m_device->setCapabilities(QTouchDevice::Position | QTouchDevice::Area);
- QWindowSystemInterface::registerTouchDevice(m_device);
-}
-
-void QTouchEventSenderQPA::touch_configure(int x_min, int x_max, int y_min, int y_max,
- int pressure_min, int pressure_max,
- const QString &dev_name)
-{
- hw_range_x_min = x_min;
- hw_range_x_max = x_max;
- hw_range_y_min = y_min;
- hw_range_y_max = y_max;
-
- hw_pressure_min = pressure_min;
- hw_pressure_max = pressure_max;
-
- m_device->setName(dev_name);
-
- if (hw_pressure_max > hw_pressure_min)
- m_device->setCapabilities(m_device->capabilities() | QTouchDevice::Pressure);
-}
-
-void QTouchEventSenderQPA::touch_point(const QList<QWindowSystemInterface::TouchPoint> &points)
-{
- QRect winRect;
- if (m_forceToActiveWindow) {
- QWindow *win = QGuiApplication::activeWindow();
- if (!win)
- return;
- winRect = win->geometry();
- } else {
- winRect = QGuiApplication::primaryScreen()->geometry();
- }
-
- const int hw_w = hw_range_x_max - hw_range_x_min;
- const int hw_h = hw_range_y_max - hw_range_y_min;
-
- QList<QWindowSystemInterface::TouchPoint> touchPoints = points;
- // Map the coordinates based on the normalized position. QPA expects 'area'
- // to be in screen coordinates.
- for (int i = 0; i < touchPoints.size(); ++i) {
- QWindowSystemInterface::TouchPoint &tp(touchPoints[i]);
-
- // Generate a screen position that is always inside the active window
- // or the primary screen.
- const int wx = winRect.left() + int(tp.normalPosition.x() * winRect.width());
- const int wy = winRect.top() + int(tp.normalPosition.y() * winRect.height());
- const qreal sizeRatio = (winRect.width() + winRect.height()) / qreal(hw_w + hw_h);
- tp.area = QRect(0, 0, tp.area.width() * sizeRatio, tp.area.height() * sizeRatio);
- tp.area.moveCenter(QPoint(wx, wy));
-
- // Calculate normalized pressure.
- if (!hw_pressure_min && !hw_pressure_max)
- tp.pressure = tp.state == Qt::TouchPointReleased ? 0 : 1;
- else
- tp.pressure = (tp.pressure - hw_pressure_min) / qreal(hw_pressure_max - hw_pressure_min);
- }
-
- QWindowSystemInterface::handleTouchEvent(0, m_device, touchPoints);
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/generic/touchscreen/touchscreen.pro b/src/plugins/generic/touchscreen/touchscreen.pro
deleted file mode 100644
index 60aa29c5ec..0000000000
--- a/src/plugins/generic/touchscreen/touchscreen.pro
+++ /dev/null
@@ -1,18 +0,0 @@
-TARGET = qtouchscreenplugin
-load(qt_plugin)
-
-DESTDIR = $$QT.gui.plugins/generic
-target.path = $$[QT_INSTALL_PLUGINS]/generic
-INSTALLS += target
-
-HEADERS = \
- qtouchscreen.h \
- qtoucheventsenderqpa.h
-
-SOURCES = main.cpp \
- qtouchscreen.cpp \
- qtoucheventsenderqpa.cpp
-
-QT += core-private gui-private
-
-LIBS += -ludev