diff options
Diffstat (limited to 'src/platformsupport/input/libinput/qlibinputhandler.cpp')
-rw-r--r-- | src/platformsupport/input/libinput/qlibinputhandler.cpp | 188 |
1 files changed, 188 insertions, 0 deletions
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 |