Add libinput support

Supports relative pointer, axis, keyboard and touch events.

libinput support is only available in combination with libudev.
libxkbcommon is required to perform key mapping. For now the
default keymap is used always (selected when building xkbcommon).

[ChangeLog][QtGui] Added a plugin to get mouse, keyboard and touch events
via libinput.

Change-Id: I469d8992c0cd3e79225cefaeb931697baf86a92b
Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com>
This commit is contained in:
Laszlo Agocs 2014-12-09 11:45:29 +01:00
parent 4016b2500d
commit e78ec1c48a
20 changed files with 1401 additions and 54 deletions

View File

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

View File

@ -0,0 +1,4 @@
SOURCES = libinput.cpp
CONFIG -= qt
LIBS += $$QMAKE_LIBS_LIBINPUT
INCLUDEPATH += $$QMAKE_INCDIR_LIBINPUT

View File

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

View File

@ -0,0 +1,2 @@
SOURCES = xkbcommon.cpp
CONFIG -= qt

153
configure vendored
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -9,3 +9,7 @@ contains(QT_CONFIG, tslib) {
}
SUBDIRS += tuiotouch
contains(QT_CONFIG, libinput) {
SUBDIRS += libinput
}

View File

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

View File

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

View File

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

View File

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