summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config.tests/unix/libinput/libinput.cpp40
-rw-r--r--config.tests/unix/libinput/libinput.pro4
-rw-r--r--config.tests/unix/xkbcommon/xkbcommon.cpp42
-rw-r--r--config.tests/unix/xkbcommon/xkbcommon.pro2
-rwxr-xr-xconfigure173
-rw-r--r--src/platformsupport/input/input.pri4
-rw-r--r--src/platformsupport/input/libinput/libinput.pri21
-rw-r--r--src/platformsupport/input/libinput/qlibinputhandler.cpp188
-rw-r--r--src/platformsupport/input/libinput/qlibinputhandler_p.h90
-rw-r--r--src/platformsupport/input/libinput/qlibinputkeyboard.cpp279
-rw-r--r--src/platformsupport/input/libinput/qlibinputkeyboard_p.h98
-rw-r--r--src/platformsupport/input/libinput/qlibinputpointer.cpp101
-rw-r--r--src/platformsupport/input/libinput/qlibinputpointer_p.h70
-rw-r--r--src/platformsupport/input/libinput/qlibinputtouch.cpp165
-rw-r--r--src/platformsupport/input/libinput/qlibinputtouch_p.h83
-rw-r--r--src/plugins/generic/generic.pro4
-rw-r--r--src/plugins/generic/libinput/README18
-rw-r--r--src/plugins/generic/libinput/libinput.json3
-rw-r--r--src/plugins/generic/libinput/libinput.pro12
-rw-r--r--src/plugins/generic/libinput/main.cpp58
20 files changed, 1401 insertions, 54 deletions
diff --git a/config.tests/unix/libinput/libinput.cpp b/config.tests/unix/libinput/libinput.cpp
new file mode 100644
index 0000000000..0eb6a0f2d4
--- /dev/null
+++ b/config.tests/unix/libinput/libinput.cpp
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the config.tests 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 <libinput.h>
+
+int main()
+{
+ libinput_udev_create_context(NULL, NULL, NULL);
+ return 0;
+}
diff --git a/config.tests/unix/libinput/libinput.pro b/config.tests/unix/libinput/libinput.pro
new file mode 100644
index 0000000000..150119c504
--- /dev/null
+++ b/config.tests/unix/libinput/libinput.pro
@@ -0,0 +1,4 @@
+SOURCES = libinput.cpp
+CONFIG -= qt
+LIBS += $$QMAKE_LIBS_LIBINPUT
+INCLUDEPATH += $$QMAKE_INCDIR_LIBINPUT
diff --git a/config.tests/unix/xkbcommon/xkbcommon.cpp b/config.tests/unix/xkbcommon/xkbcommon.cpp
new file mode 100644
index 0000000000..4d50ebc363
--- /dev/null
+++ b/config.tests/unix/xkbcommon/xkbcommon.cpp
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the config.tests 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 <xkbcommon/xkbcommon.h>
+#include <xkbcommon/xkbcommon-keysyms.h>
+#include <xkbcommon/xkbcommon-names.h>
+
+int main()
+{
+ xkb_context_new(XKB_CONTEXT_NO_FLAGS);
+ return 0;
+}
diff --git a/config.tests/unix/xkbcommon/xkbcommon.pro b/config.tests/unix/xkbcommon/xkbcommon.pro
new file mode 100644
index 0000000000..4bc6e493b2
--- /dev/null
+++ b/config.tests/unix/xkbcommon/xkbcommon.pro
@@ -0,0 +1,2 @@
+SOURCES = xkbcommon.cpp
+CONFIG -= qt
diff --git a/configure b/configure
index 5024dc2e4e..d39478c3f5 100755
--- a/configure
+++ b/configure
@@ -643,6 +643,7 @@ CFG_XINPUT2=auto
CFG_XINPUT=runtime
CFG_XKB=auto
CFG_XKBCOMMON=yes
+CFG_XKBCOMMON_EVDEV=auto
CFG_XKB_CONFIG_ROOT=auto
CFG_XCB=auto
CFG_XCB_XLIB=auto
@@ -652,6 +653,7 @@ CFG_DIRECTFB=auto
CFG_LINUXFB=auto
CFG_KMS=auto
CFG_LIBUDEV=auto
+CFG_LIBINPUT=auto
CFG_OBSOLETE_WAYLAND=no
CFG_EVDEV=auto
CFG_TSLIB=auto
@@ -1722,7 +1724,14 @@ while [ "$#" -gt 0 ]; do
UNKNOWN_OPT=yes
fi
;;
- xkbcommon)
+ xkbcommon-evdev)
+ if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then
+ CFG_XKBCOMMON_EVDEV="$VAL"
+ else
+ UNKNOWN_OPT=yes
+ fi
+ ;;
+ xkbcommon|xkbcommon-x11)
if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ] || [ "$VAL" = "qt" ] || [ "$VAL" = "system" ]; then
CFG_XKBCOMMON="$VAL"
else
@@ -1784,6 +1793,13 @@ while [ "$#" -gt 0 ]; do
UNKNOWN_OPT=yes
fi
;;
+ libinput)
+ if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then
+ CFG_LIBINPUT="$VAL"
+ else
+ UNKNOWN_OPT=yes
+ fi
+ ;;
evdev)
if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then
CFG_EVDEV="$VAL"
@@ -2360,74 +2376,77 @@ Configure options:
Third Party Libraries:
- -qt-zlib ........... Use the zlib bundled with Qt.
- + -system-zlib ....... Use zlib from the operating system.
- See http://www.gzip.org/zlib
+ -qt-zlib ............ Use the zlib bundled with Qt.
+ + -system-zlib ........ Use zlib from the operating system.
+ See http://www.gzip.org/zlib
- -no-mtdev ......... Do not compile mtdev support.
- + -mtdev ............. Enable mtdev support.
+ -no-mtdev ........... Do not compile mtdev support.
+ + -mtdev .............. Enable mtdev support.
- + -no-journald ....... Do not send logging output to journald.
- -journald .......... Send logging output to journald.
+ + -no-journald ........ Do not send logging output to journald.
+ -journald ........... Send logging output to journald.
- -no-gif ............ Do not compile GIF reading support.
+ -no-gif ............. Do not compile GIF reading support.
- -no-libpng ......... Do not compile PNG support.
- -qt-libpng ......... Use the libpng bundled with Qt.
- + -system-libpng ..... Use libpng from the operating system.
- See http://www.libpng.org/pub/png
+ -no-libpng .......... Do not compile PNG support.
+ -qt-libpng .......... Use the libpng bundled with Qt.
+ + -system-libpng ...... Use libpng from the operating system.
+ See http://www.libpng.org/pub/png
- -no-libjpeg ........ Do not compile JPEG support.
- -qt-libjpeg ........ Use the libjpeg bundled with Qt.
- + -system-libjpeg .... Use libjpeg from the operating system.
- See http://www.ijg.org
+ -no-libjpeg ......... Do not compile JPEG support.
+ -qt-libjpeg ......... Use the libjpeg bundled with Qt.
+ + -system-libjpeg ..... Use libjpeg from the operating system.
+ See http://www.ijg.org
- -no-freetype ....... Do not compile in Freetype2 support.
- -qt-freetype ....... Use the libfreetype bundled with Qt.
- + -system-freetype.... Use the libfreetype provided by the system (enabled if -fontconfig is active).
- See http://www.freetype.org
+ -no-freetype ........ Do not compile in Freetype2 support.
+ -qt-freetype ........ Use the libfreetype bundled with Qt.
+ + -system-freetype..... Use the libfreetype provided by the system (enabled if -fontconfig is active).
+ See http://www.freetype.org
- -no-harfbuzz ....... Do not compile HarfBuzz-NG support.
- * -qt-harfbuzz ....... Use HarfBuzz-NG bundled with Qt to do text shaping.
- It can still be disabled by setting
- the QT_HARFBUZZ environment variable to "old".
- -system-harfbuzz ... Use HarfBuzz-NG from the operating system
- to do text shaping. It can still be disabled
- by setting the QT_HARFBUZZ environment variable to "old".
- See http://www.harfbuzz.org
+ -no-harfbuzz ........ Do not compile HarfBuzz-NG support.
+ * -qt-harfbuzz ........ Use HarfBuzz-NG bundled with Qt to do text shaping.
+ It can still be disabled by setting
+ the QT_HARFBUZZ environment variable to "old".
+ -system-harfbuzz .... Use HarfBuzz-NG from the operating system
+ to do text shaping. It can still be disabled
+ by setting the QT_HARFBUZZ environment variable to "old".
+ See http://www.harfbuzz.org
- -no-openssl ........ Do not compile support for OpenSSL.
- + -openssl ........... Enable run-time OpenSSL support.
- -openssl-linked .... Enabled linked OpenSSL support.
+ -no-openssl ......... Do not compile support for OpenSSL.
+ + -openssl ............ Enable run-time OpenSSL support.
+ -openssl-linked ..... Enabled linked OpenSSL support.
- -qt-pcre ........... Use the PCRE library bundled with Qt.
- + -system-pcre ....... Use the PCRE library from the operating system.
+ -qt-pcre ............ Use the PCRE library bundled with Qt.
+ + -system-pcre ........ Use the PCRE library from the operating system.
- -qt-xcb ............ Use xcb- libraries bundled with Qt.
- (libxcb.so will still be used from operating system).
- + -system-xcb ........ Use xcb- libraries from the operating system.
+ -qt-xcb ............. Use xcb- libraries bundled with Qt.
+ (libxcb.so will still be used from operating system).
+ + -system-xcb ......... Use xcb- libraries from the operating system.
- -xkb-config-root ... Set default XKB config root. This option is used only together with -qt-xkbcommon.
- -qt-xkbcommon ...... Use the xkbcommon library bundled with Qt.
- + -system-xkbcommon .. Use the xkbcommon library from the operating system.
+ -xkb-config-root .... Set default XKB config root. This option is used only together with -qt-xkbcommon-x11.
+ -qt-xkbcommon-x11 ... Use the xkbcommon library bundled with Qt in combination with xcb.
+ + -system-xkbcommon-x11 Use the xkbcommon library from the operating system in combination with xcb.
- -no-xinput2 ........ Do not compile XInput2 support.
- * -xinput2 ........... Compile XInput2 support.
+ -no-xkbcommon-evdev . Do not use X-less xkbcommon when compiling libinput support.
+ * -xkbcommon-evdev .... Use X-less xkbcommon when compiling libinput support.
- -no-xcb-xlib........ Do not compile Xcb-Xlib support.
- * -xcb-xlib........... Compile Xcb-Xlib support.
+ -no-xinput2 ......... Do not compile XInput2 support.
+ * -xinput2 ............ Compile XInput2 support.
- -no-glib ........... Do not compile Glib support.
- + -glib .............. Compile Glib support.
+ -no-xcb-xlib......... Do not compile Xcb-Xlib support.
+ * -xcb-xlib............ Compile Xcb-Xlib support.
- -no-pulseaudio ..... Do not compile PulseAudio support.
- + -pulseaudio ........ Compile PulseAudio support.
+ -no-glib ............ Do not compile Glib support.
+ + -glib ............... Compile Glib support.
- -no-alsa ........... Do not compile ALSA support.
- + -alsa .............. Compile ALSA support.
+ -no-pulseaudio ...... Do not compile PulseAudio support.
+ + -pulseaudio ......... Compile PulseAudio support.
- -no-gtkstyle ....... Do not compile GTK theme support.
- + -gtkstyle .......... Compile GTK theme support.
+ -no-alsa ............ Do not compile ALSA support.
+ + -alsa ............... Compile ALSA support.
+
+ -no-gtkstyle ........ Do not compile GTK theme support.
+ + -gtkstyle ........... Compile GTK theme support.
Additional options:
@@ -2554,6 +2573,9 @@ Additional options:
OpenGL ES 2.0 and higher, or regular desktop OpenGL.
Use es2 for <api> to override auto-detection.
+ -no-libinput ........ Do not support libinput.
+ * -libinput ........... Enable libinput support.
+
* -no-system-proxies .. Do not use system network proxies by default.
-system-proxies ..... Use system network proxies by default.
@@ -2991,7 +3013,7 @@ if [ "$XPLATFORM_MAC" = "no" -a "$CFG_DEBUG_RELEASE" = "yes" ]; then
fi
if ( [ "$CFG_XCB" = "system" ] || [ "$CFG_XCB" = "qt" ] ) && [ "$CFG_XKBCOMMON" = "no" ]; then
- echo "Error: -no-xkbcommon is not supported on XCB platform plugin."
+ echo "Error: -no-xkbcommon-x11 is not supported on XCB platform plugin."
exit 101
fi
@@ -5086,6 +5108,47 @@ if [ "$CFG_TSLIB" = "no" ]; then
QMakeVar add DEFINES QT_NO_TSLIB
fi
+if [ "$CFG_XKBCOMMON_EVDEV" != "no" ]; then
+ if [ -n "$PKG_CONFIG" ] && $PKG_CONFIG --exists xkbcommon 2>/dev/null; then
+ QMAKE_INCDIR_XKBCOMMON_EVDEV=`$PKG_CONFIG --cflags-only-I xkbcommon 2>/dev/null | sed -e 's,^-I,,g' -e 's, -I, ,g'`
+ QMAKE_LIBS_XKBCOMMON_EVDEV=`$PKG_CONFIG --libs xkbcommon 2>/dev/null`
+ QMAKE_CFLAGS_XKBCOMMON_EVDEV=`$PKG_CONFIG --cflags xkbcommon 2>/dev/null`
+ QMakeVar set QMAKE_INCDIR_XKBCOMMON_EVDEV "$QMAKE_INCDIR_XKBCOMMON_EVDEV"
+ QMakeVar set QMAKE_LIBS_XKBCOMMON_EVDEV "$QMAKE_LIBS_XKBCOMMON_EVDEV"
+ fi
+ if compileTest unix/xkbcommon "xkbcommon" $QMAKE_CFLAGS_XKBCOMMON_EVDEV $QMAKE_LIBS_XKBCOMMON_EVDEV; then
+ CFG_XKBCOMMON_EVDEV=yes
+ QT_CONFIG="$QT_CONFIG xkbcommon-evdev"
+ elif [ "$CFG_XKBCOMMON_EVDEV" = "yes" ]; then
+ echo "The xkbcommon-evdev functionality test failed!"
+ exit 1
+ else
+ CFG_XKBCOMMON_EVDEV=no
+ fi
+fi
+
+if [ "$CFG_LIBINPUT" != "no" ] && [ "$CFG_LIBUDEV" != "no" ]; then
+ if [ -n "$PKG_CONFIG" ] && $PKG_CONFIG --exists libinput 2>/dev/null; then
+ QMAKE_INCDIR_LIBINPUT=`$PKG_CONFIG --cflags-only-I libinput 2>/dev/null | sed -e 's,^-I,,g' -e 's, -I, ,g'`
+ QMAKE_LIBS_LIBINPUT=`$PKG_CONFIG --libs libinput 2>/dev/null`
+ QMAKE_CFLAGS_LIBINPUT=`$PKG_CONFIG --cflags libinput 2>/dev/null`
+ QMakeVar set QMAKE_INCDIR_LIBINPUT "$QMAKE_INCDIR_LIBINPUT"
+ QMakeVar set QMAKE_LIBS_LIBINPUT "$QMAKE_LIBS_LIBINPUT"
+ fi
+ if compileTest unix/libinput "libinput" $QMAKE_CFLAGS_LIBINPUT $QMAKE_LIBS_LIBINPUT; then
+ CFG_LIBINPUT=yes
+ QT_CONFIG="$QT_CONFIG libinput"
+ elif [ "$CFG_LIBINPUT" = "yes" ]; then
+ echo "The libinput functionality test failed!"
+ exit 1
+ else
+ CFG_LIBINPUT=no
+ fi
+fi
+if [ "$CFG_LIBINPUT" = "no" ]; then
+ QMakeVar add DEFINES QT_NO_LIBINPUT
+fi
+
# Check we actually have X11 :-)
if compileTest x11/xlib "XLib"; then
QT_CONFIG="$QT_CONFIG xlib"
@@ -6716,6 +6779,7 @@ report_support_plugin " GIF .................." "$CFG_GIF" qt QtGui
report_support_plugin " JPEG ................." "$CFG_JPEG" "$CFG_LIBJPEG" QtGui
report_support_plugin " PNG .................." "$CFG_PNG" "$CFG_LIBPNG" QtGui
report_support " journald ..............." "$CFG_JOURNALD"
+report_support " libinput................" "$CFG_LIBINPUT"
report_support " mtdev .................." "$CFG_MTDEV" yes "system library"
report_support " Networking:"
[ "$XPLATFORM_MAC" = "yes" ] && \
@@ -6778,7 +6842,8 @@ report_support_plugin " SQLite ..............." "$CFG_SQL_sqlite" "$CFG_SQLIT
report_support " TDS .................." "$CFG_SQL_tds" plugin "plugin" yes "built into QtSql"
report_support " tslib .................." "$CFG_TSLIB"
report_support " udev ..................." "$CFG_LIBUDEV"
-report_support " xkbcommon .............." "$CFG_XKBCOMMON" system "system library" qt "bundled copy, XKB config root: $CFG_XKB_CONFIG_ROOT"
+report_support " xkbcommon-x11..........." "$CFG_XKBCOMMON" system "system library" qt "bundled copy, XKB config root: $CFG_XKB_CONFIG_ROOT"
+report_support " xkbcommon-evdev........." "$CFG_XKBCOMMON_EVDEV"
report_support " zlib ..................." "$CFG_ZLIB" system "system library" yes "bundled copy"
echo
diff --git a/src/platformsupport/input/input.pri b/src/platformsupport/input/input.pri
index c1fd95703b..3b9593eb31 100644
--- a/src/platformsupport/input/input.pri
+++ b/src/platformsupport/input/input.pri
@@ -8,3 +8,7 @@ contains(QT_CONFIG, evdev) {
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/plugins/generic/generic.pro b/src/plugins/generic/generic.pro
index 4cdc7e7a76..82a4ad4ce8 100644
--- a/src/plugins/generic/generic.pro
+++ b/src/plugins/generic/generic.pro
@@ -9,3 +9,7 @@ contains(QT_CONFIG, tslib) {
}
SUBDIRS += tuiotouch
+
+contains(QT_CONFIG, libinput) {
+ SUBDIRS += libinput
+}
diff --git a/src/plugins/generic/libinput/README b/src/plugins/generic/libinput/README
new file mode 100644
index 0000000000..4312ccbf3a
--- /dev/null
+++ b/src/plugins/generic/libinput/README
@@ -0,0 +1,18 @@
+This is a generic plug-in for libinput 0.6.0
+(http://www.freedesktop.org/wiki/Software/libinput)
+
+Supports relative pointer, axis, keyboard and touch events. udev is
+required. xkbcommon is used to perform keyboard mapping. The dependency on
+xkbcommon is optional. However, no key events will be generated without it.
+
+The plugin is integrated with configure and is built automatically when the
+necessary dependencies are present.
+
+To use this plugin with eglfs, set QT_QPA_EGLFS_DISABLE_INPUT=1 before launching
+the application and pass -plugin libinput.
+
+To get info and debug messages from libinput, enable the logging category
+qt.qpa.input.
+
+For the time being xkbcommon's default keymap is used always. Support for
+changing it will be added in the future.
diff --git a/src/plugins/generic/libinput/libinput.json b/src/plugins/generic/libinput/libinput.json
new file mode 100644
index 0000000000..4a93f271f3
--- /dev/null
+++ b/src/plugins/generic/libinput/libinput.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "libinput" ]
+}
diff --git a/src/plugins/generic/libinput/libinput.pro b/src/plugins/generic/libinput/libinput.pro
new file mode 100644
index 0000000000..17dbb23ef0
--- /dev/null
+++ b/src/plugins/generic/libinput/libinput.pro
@@ -0,0 +1,12 @@
+TARGET = qlibinputplugin
+
+PLUGIN_TYPE = generic
+PLUGIN_EXTENDS = -
+PLUGIN_CLASS_NAME = QLibInputPlugin
+load(qt_plugin)
+
+QT += core-private platformsupport-private gui-private
+
+SOURCES = main.cpp
+
+OTHER_FILES = libinput.json
diff --git a/src/plugins/generic/libinput/main.cpp b/src/plugins/generic/libinput/main.cpp
new file mode 100644
index 0000000000..16c391cc22
--- /dev/null
+++ b/src/plugins/generic/libinput/main.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and 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 <QtGui/qgenericplugin.h>
+#include <QtPlatformSupport/private/qlibinputhandler_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QLibInputPlugin : public QGenericPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QGenericPluginFactoryInterface" FILE "libinput.json")
+
+public:
+ QObject *create(const QString &key, const QString &specification);
+};
+
+QObject *QLibInputPlugin::create(const QString &key, const QString &specification)
+{
+ if (!key.compare(QLatin1String("libinput"), Qt::CaseInsensitive))
+ return new QLibInputHandler(key, specification);
+
+ return 0;
+}
+
+QT_END_NAMESPACE
+
+#include "main.moc"