From 98215659a4c56cd6ba460834b6ee07bf9de95635 Mon Sep 17 00:00:00 2001 From: Andreas Pokorny Date: Tue, 22 Mar 2016 16:04:19 +0100 Subject: [PATCH] Add mir backend for input info Signed-off-by: Andreas Pokorny --- config.tests/mir/main.cpp | 42 ++++ config.tests/mir/mir.pro | 8 + qtsystems.pro | 1 + src/systeminfo/linux/qinputinfomanager.cpp | 47 ++++ src/systeminfo/linux/qinputinfomanager_p.h | 78 +++++++ src/systeminfo/linux/qinputinfomanagermir.cpp | 136 +++++++++++ src/systeminfo/linux/qinputinfomanagermir_p.h | 64 ++++++ src/systeminfo/linux/qinputinfomanagerudev.cpp | 286 +++++++++++++++++++++++ src/systeminfo/linux/qinputinfomanagerudev_p.h | 73 ++++++ src/systeminfo/qinputinfo.cpp | 32 ++- src/systeminfo/qinputinfo.h | 3 +- src/systeminfo/systeminfo.pro | 25 ++- 14 files changed, 783 insertions(+), 396 deletions(-) create mode 100644 config.tests/mir/main.cpp create mode 100644 config.tests/mir/mir.pro delete mode 100644 src/systeminfo/linux/qinputdeviceinfo_linux.cpp delete mode 100644 src/systeminfo/linux/qinputdeviceinfo_linux_p.h create mode 100644 src/systeminfo/linux/qinputinfomanager.cpp create mode 100644 src/systeminfo/linux/qinputinfomanager_p.h create mode 100644 src/systeminfo/linux/qinputinfomanagermir.cpp create mode 100644 src/systeminfo/linux/qinputinfomanagermir_p.h create mode 100644 src/systeminfo/linux/qinputinfomanagerudev.cpp create mode 100644 src/systeminfo/linux/qinputinfomanagerudev_p.h diff --git a/config.tests/mir/main.cpp b/config.tests/mir/main.cpp new file mode 100644 index 0000000..5b128ab --- /dev/null +++ b/config.tests/mir/main.cpp @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSystems 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +int main() +{ + MirInputConfig* (*function_is_available)(MirConnection *connection); + function_is_available = &mir_connection_create_input_config; + return 0; +} diff --git a/config.tests/mir/mir.pro b/config.tests/mir/mir.pro new file mode 100644 index 0000000..694373a --- /dev/null +++ b/config.tests/mir/mir.pro @@ -0,0 +1,8 @@ +TEMPLATE = app + +CONFIG += link_pkgconfig +PKGCONFIG += mirclient + +TARGET = mir + +SOURCES += main.cpp diff --git a/qtsystems.pro b/qtsystems.pro index 3a455fa..f54e2ea 100644 --- a/qtsystems.pro +++ b/qtsystems.pro @@ -5,6 +5,7 @@ qtCompileTest(gconf) qtCompileTest(bluez) qtCompileTest(udev) qtCompileTest(x11) + qtCompileTest(mir) # FIXME: This causes tests to be installed (if examples are installed as well), # which is needed to run some tests because they are broken. diff --git a/src/systeminfo/linux/qinputinfomanager.cpp b/src/systeminfo/linux/qinputinfomanager.cpp new file mode 100644 index 0000000..2d5054d --- /dev/null +++ b/src/systeminfo/linux/qinputinfomanager.cpp @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Canonical, Ltd. and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSystems module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qinputinfomanager_p.h" + +QInputInfoManagerPrivate::QInputInfoManagerPrivate(QObject *parent) : + QObject(parent) +{ +} diff --git a/src/systeminfo/linux/qinputinfomanager_p.h b/src/systeminfo/linux/qinputinfomanager_p.h new file mode 100644 index 0000000..4f827b7 --- /dev/null +++ b/src/systeminfo/linux/qinputinfomanager_p.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Canonical, Ltd. and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSystems module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QINPUTDEVICEINFO_LINUX_P_H +#define QINPUTDEVICEINFO_LINUX_P_H + +#include +#include "qinputinfo.h" + +class QInputDevicePrivate : public QObject +{ + Q_OBJECT +public: + explicit QInputDevicePrivate(QObject *parent = 0); + + QString name; + QString identifier; + QList buttons; //keys + QList switches; + QList relativeAxes; + QList absoluteAxes; + QInputDevice::InputTypeFlags type; +}; + +class QInputInfoManagerPrivate : public QObject +{ + Q_OBJECT +public: + explicit QInputInfoManagerPrivate(QObject *parent = 0); + QVector deviceList; + QMap deviceMap; + static QInputInfoManagerPrivate * instance(); + +signals: + void deviceAdded( QInputDevice *inputDevice); + void deviceRemoved(const QString &deviceId); + void ready(); +}; + +#endif // QINPUTDEVICEINFO_LINUX_P_H diff --git a/src/systeminfo/linux/qinputinfomanagermir.cpp b/src/systeminfo/linux/qinputinfomanagermir.cpp new file mode 100644 index 0000000..fce48b0 --- /dev/null +++ b/src/systeminfo/linux/qinputinfomanagermir.cpp @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Canonical, Ltd. and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSystems module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qinputinfomanagermir_p.h" +#include "linux/input-event-codes.h" + +QInputInfoManagerMir::QInputInfoManagerMir(MirConnection *con, QObject *parent) + : QInputInfoManagerPrivate(parent), connection{con}, config{mir_connection_create_input_config(con), mir_input_config_destroy} +{ + mir_connection_set_input_config_change_callback( + connection, + [](MirConnection* con, void* context) + { + QInputInfoManagerMir *this_ = static_cast(context); + this_->config = MirInputConfigPtr{mir_connection_create_input_config(con), mir_input_config_destroy}; + this_->update_devices(); + }, this); + + update_devices(); +} + +void QInputInfoManagerMir::update_devices() +{ + QList deletedDevices = deviceMap.keys(); + + for (int index = 0, e = mir_input_config_device_count(config.get()); index!=e; ++index) { + + MirInputDevice const *input_device = mir_input_config_get_device( + config.get(), + index); + + QString id = QString::number(mir_input_device_get_id(input_device)); + if (!deviceMap.contains(id)) { + QInputDevice *nDevice = new QInputDevice(this); + nDevice->setName(QString::fromUtf8(mir_input_device_get_name(input_device))); + nDevice->setIdentifier(id); + QInputDevice::InputTypeFlags flags = QInputDevice::UnknownType; + + MirInputDeviceCapabilities caps = mir_input_device_get_capabilities(input_device); + + if (caps & mir_input_device_capability_pointer) { + nDevice->addRelativeAxis(REL_X); + nDevice->addRelativeAxis(REL_Y); + nDevice->addRelativeAxis(REL_WHEEL); + nDevice->addButton(BTN_MOUSE); + nDevice->addButton(BTN_RIGHT); + nDevice->addButton(BTN_MIDDLE); + if (caps & mir_input_device_capability_touchpad) + { + flags |= QInputDevice::TouchPad; + } + else + { + flags |= QInputDevice::Mouse; + nDevice->addButton(BTN_SIDE); + nDevice->addButton(BTN_EXTRA); + nDevice->addButton(BTN_FORWARD); + nDevice->addButton(BTN_BACK); + nDevice->addButton(BTN_TASK); + } + } + + if (caps & mir_input_device_capability_keyboard) + { + flags |= QInputDevice::Button; + + // keyboard with enough keys for text entry + if (caps & mir_input_device_capability_alpha_numeric) + { + flags |= QInputDevice::Keyboard; + for (int i = KEY_1; i != KEY_SLASH; ++i) + nDevice->addButton(i); + } + } + + nDevice->setTypes(flags); + + deviceMap.insert(id, nDevice); + deviceList.push_back(nDevice); + + Q_EMIT deviceAdded(nDevice); + } + else + { + deletedDevices.removeOne(id); + } + } + + for (QList::const_iterator it = deletedDevices.begin(), e = deletedDevices.end(); + it != e ; ++it) + { + QInputDevice * device = deviceMap.take(*it); + deviceList.removeOne(device); + Q_EMIT deviceRemoved(*it); + delete device; + } + Q_EMIT ready(); +} diff --git a/src/systeminfo/linux/qinputinfomanagermir_p.h b/src/systeminfo/linux/qinputinfomanagermir_p.h new file mode 100644 index 0000000..a14e997 --- /dev/null +++ b/src/systeminfo/linux/qinputinfomanagermir_p.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Canonical, Ltd. and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSystems module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QINPUTINFOMANAGER_MIR_P_H +#define QINPUTINFOMANAGER_MIR_P_H + +#include "qinputinfomanager_p.h" +#include +#include +#include + +#include + +class QInputInfoManagerMir : public QInputInfoManagerPrivate +{ +public: + QInputInfoManagerMir(MirConnection *con, QObject *parent = NULL); + +private: + void update_devices(); + MirConnection *connection; + using MirInputConfigPtr = std::unique_ptr; + MirInputConfigPtr config; +}; + +#endif // QINPUTINFOMANAGER_MIR_P_H diff --git a/src/systeminfo/linux/qinputinfomanagerudev.cpp b/src/systeminfo/linux/qinputinfomanagerudev.cpp new file mode 100644 index 0000000..dd5aff7 --- /dev/null +++ b/src/systeminfo/linux/qinputinfomanagerudev.cpp @@ -0,0 +1,286 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Canonical, Ltd. and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSystems module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qinputinfomanagerudev_p.h" + +#include +#include +#include +#include +#include +#include +#include + +QInputInfoManagerUdev::QInputInfoManagerUdev(QObject *parent) : + QInputInfoManagerPrivate(parent), + udevice(0) +{ + QTimer::singleShot(250,this,SLOT(init())); +} + +QInputInfoManagerUdev::~QInputInfoManagerUdev() +{ + udev_unref(udevice); + udev_monitor_unref(udevMonitor); +} + +void QInputInfoManagerUdev::init() +{ + if (!udevice) + udevice = udev_new(); + + udev_list_entry *devices; + udev_list_entry *dev_list_entry; + udev_device *dev; + + QString subsystem = QStringLiteral("input"); + struct udev_enumerate *enumerate = 0; + + if (udevice) { + + udevMonitor = udev_monitor_new_from_netlink(udevice, "udev"); + udev_monitor_filter_add_match_subsystem_devtype(udevMonitor, subsystem.toLatin1(), NULL); + enumerate = udev_enumerate_new(udevice); + udev_enumerate_add_match_subsystem(enumerate, subsystem.toLatin1()); + + udev_monitor_enable_receiving(udevMonitor); + notifierFd = udev_monitor_get_fd(udevMonitor); + + notifier = new QSocketNotifier(notifierFd, QSocketNotifier::Read, this); + connect(notifier, SIGNAL(activated(int)), this, SLOT(onUDevChanges())); + + udev_enumerate_scan_devices(enumerate); + devices = udev_enumerate_get_list_entry(enumerate); + + udev_list_entry_foreach(dev_list_entry, devices) { + const char *path; + path = udev_list_entry_get_name(dev_list_entry); + + dev = udev_device_new_from_syspath(udevice, path); + if (qstrcmp(udev_device_get_subsystem(dev), "input") == 0 ) { + QInputDevice *iDevice = addDevice(dev); + if (iDevice && !iDevice->identifier().isEmpty()) { + deviceMap.insert(iDevice->identifier(),iDevice); + } + } + udev_device_unref(dev); + } + udev_enumerate_unref(enumerate); + } + // udev_unref(udevice); + Q_FOREACH (const QString &devicePath, deviceMap.keys()) { + Q_EMIT deviceAdded(deviceMap.value(devicePath)); + } + Q_EMIT ready(); +} + +QInputDevice::InputTypeFlags QInputInfoManagerUdev::getInputTypeFlags(struct udev_device *dev) +{ + QInputDevice::InputTypeFlags flags = QInputDevice::UnknownType; + if (qstrcmp(udev_device_get_property_value(dev, "ID_INPUT_KEY"), "1") == 0 ) { + flags |= QInputDevice::Button; + } + if (qstrcmp(udev_device_get_property_value(dev, "ID_INPUT_MOUSE"), "1") == 0) { + flags |= QInputDevice::Mouse; + } + if (qstrcmp(udev_device_get_property_value(dev, "ID_INPUT_TOUCHPAD"), "1") == 0) { + flags |= QInputDevice::TouchPad; + } + if (qstrcmp(udev_device_get_property_value(dev, "ID_INPUT_TOUCHSCREEN"), "1") == 0 + || qstrcmp(udev_device_get_property_value(dev, "ID_INPUT_TABLET"), "1") == 0) { + flags |= QInputDevice::TouchScreen; + } + if (qstrcmp(udev_device_get_property_value(dev, "ID_INPUT_KEYBOARD"), "1") == 0 ) { + flags |= QInputDevice::Keyboard; + } + if (!QString::fromLatin1(udev_device_get_property_value(dev, "SW")).isEmpty()) { + flags |= QInputDevice::Switch; + } + + return flags; +} + +QInputDevice *QInputInfoManagerUdev::addDevice(struct udev_device *udev) +{ + QString eventPath = QString::fromLatin1(udev_device_get_sysname(udev)); + + if (eventPath.contains(QStringLiteral("event"))) + eventPath.prepend(QStringLiteral("/dev/input/")); + + if (deviceMap.contains(eventPath)) { + return Q_NULLPTR; + } + struct libevdev *dev = NULL; + int fd; + int rc = 1; + QInputDevice *inputDevice; + inputDevice = addUdevDevice(udev); + if (!inputDevice) { + return Q_NULLPTR; + } + eventPath = inputDevice->identifier(); + + fd = open(eventPath.toLatin1(), O_RDONLY|O_NONBLOCK); + if (fd == -1) { + return inputDevice; + } + rc = libevdev_new_from_fd(fd, &dev); + if (rc < 0) { + qWarning() << "Failed to init libevdev ("<< strerror(-rc) << ")"; + return Q_NULLPTR; + } + + for (int i = 0; i < EV_MAX; i++) { + if (i == EV_KEY || i == EV_SW || i == EV_REL + || i == EV_REL || i == EV_ABS) { + for (int j = 0; j < libevdev_event_type_get_max(i); j++) { + if (libevdev_has_event_code(dev, i, j)) { + switch (i) { + case EV_KEY: + inputDevice->addButton(j); + break; + case EV_SW: + inputDevice->addSwitch(j); + break; + case EV_REL: + inputDevice->addRelativeAxis(j); + break; + case EV_ABS: + inputDevice->addAbsoluteAxis(j); + break; + }; + } + } + } + } + + return inputDevice; +} + +void QInputInfoManagerUdev::addDetails(struct udev_device *) +{ +} + +void QInputInfoManagerUdev::removeDevice(const QString &path) +{ + // this path is not a full evdev path + Q_FOREACH (const QString devicePath, deviceMap.keys()) { + if (devicePath.contains(path)) { + QInputDevice *removedDevice = deviceMap.take(devicePath); + removedDevice->deleteLater(); + Q_EMIT deviceRemoved(devicePath); + } + } +} + +QInputDevice *QInputInfoManagerUdev::addUdevDevice(struct udev_device *udev) +{ + QInputDevice *iDevice; + + struct udev_list_entry *list; + struct udev_list_entry *node; + + list = udev_device_get_properties_list_entry (udev); + QString syspath = QString::fromLatin1(udev_device_get_syspath(udev)); + QDir sysdir(syspath); + + QStringList infoList = sysdir.entryList(QStringList() << QStringLiteral("event*"),QDir::Dirs); + + if (infoList.count() > 0) { + QString token = infoList.at(0); + + token.prepend(QStringLiteral("/dev/input/")); + iDevice = new QInputDevice(this); + iDevice->setIdentifier(token); + } else { + return Q_NULLPTR; + } + udev_list_entry_foreach (node, list) { + + QString key = QString::fromLatin1(udev_list_entry_get_name(node)); + QString value = QString::fromLatin1(udev_list_entry_get_value(node)); + + if (key == QStringLiteral("NAME")) { + iDevice->setName(value.remove(QStringLiteral("\""))); + } + } + iDevice->setTypes(getInputTypeFlags(udev)); + return iDevice; +} + +void QInputInfoManagerUdev::onUDevChanges() +{ + if (!udevMonitor) + return; + + udev_device *dev = udev_monitor_receive_device(udevMonitor); + + if (dev) { + if (qstrcmp(udev_device_get_subsystem(dev), "input") == 0 ) { + QString eventPath = QString::fromLatin1(udev_device_get_sysname(dev)); + + QString action = QString::fromStdString(udev_device_get_action(dev)); + + if (!eventPath.contains(QStringLiteral("/dev/input/"))) + eventPath.prepend(QStringLiteral("/dev/input/")); + + if (action == QStringLiteral("add")) { + if (deviceMap.contains(eventPath)){ + udev_device_unref(dev); + return; + } + + QInputDevice *iDevice = addDevice(dev); + if (!iDevice) { + delete iDevice; + return; + } + iDevice->setTypes(getInputTypeFlags(dev)); + udev_device_unref(dev); + deviceMap.insert(eventPath,iDevice); + Q_EMIT deviceAdded(deviceMap.value(eventPath)); + + } else if (action == QStringLiteral("remove")) { + removeDevice(eventPath); + } + } + } +} diff --git a/src/systeminfo/linux/qinputinfomanagerudev_p.h b/src/systeminfo/linux/qinputinfomanagerudev_p.h new file mode 100644 index 0000000..671cfc4 --- /dev/null +++ b/src/systeminfo/linux/qinputinfomanagerudev_p.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Canonical, Ltd. and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtSystems module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QINPUTDEVICEMANAGER_UDEV_P_H +#define QINPUTDEVICEMANAGER_UDEV_P_H + +#include "qinputinfomanager_p.h" +#include + +class QInputInfoManagerUdev : public QInputInfoManagerPrivate +{ + Q_OBJECT +public: + explicit QInputInfoManagerUdev(QObject *parent = 0); + ~QInputInfoManagerUdev(); + +private: + QInputDevice *addDevice(struct udev_device *udev); + QInputDevice *addUdevDevice(struct udev_device *); + + QInputDevice *addDevice(const QString &path); + void removeDevice(const QString &path); + QSocketNotifier *notifier; + int notifierFd; + struct udev_monitor *udevMonitor; + QInputDevice::InputTypeFlags getInputTypeFlags(struct udev_device *); + struct udev *udevice; + void addDetails(struct udev_device *); + +private Q_SLOTS: + void onUDevChanges(); + void init(); +}; + +#endif // QINPUTDEVICEMANAGER_UDEV_P_H diff --git a/src/systeminfo/qinputinfo.cpp b/src/systeminfo/qinputinfo.cpp index 0464ddf..b7ec2e5 100644 --- a/src/systeminfo/qinputinfo.cpp +++ b/src/systeminfo/qinputinfo.cpp @@ -41,11 +41,26 @@ #include "qinputinfo.h" -#if defined(Q_OS_LINUX) -#include "linux/qinputdeviceinfo_linux_p.h" +#include "linux/qinputinfomanager_p.h" + +#if !defined(QT_NO_UDEV) +#include "linux/qinputinfomanagerudev_p.h" #endif -Q_GLOBAL_STATIC(QInputDeviceManagerPrivate, inputDeviceManagerPrivate) +#if !defined(QT_NO_MIR) +#include +#include +#include "linux/qinputinfomanagermir_p.h" +#endif + +#if !defined(QT_NO_UDEV) +Q_GLOBAL_STATIC(QInputInfoManagerUdev, inputDeviceManagerUdev) +#endif +#if !defined(QT_NO_MIR) +Q_GLOBAL_STATIC_WITH_ARGS(QInputInfoManagerMir, + inputDeviceManagerMir, + (static_cast(QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("mirconnection")))) +#endif QT_BEGIN_NAMESPACE @@ -54,8 +69,13 @@ QT_BEGIN_NAMESPACE QInputDeviceManagerPrivate * QInputDeviceManagerPrivate::instance() { - QInputDeviceManagerPrivate *priv = inputDeviceManagerPrivate(); - return priv; +#ifndef QT_NO_MIR + if (QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("mirconnection")) + return inputDeviceManagerMir(); +#endif +#ifndef QT_NO_UDEV + return inputDeviceManagerUdev(); +#endif } QInputDevicePrivate::QInputDevicePrivate(QObject *parent) : @@ -242,7 +262,7 @@ void QInputDevice::setTypes(QInputDevice::InputTypeFlags type) QInputDeviceManager::QInputDeviceManager(QObject *parent) : QObject(parent), - d_ptr(inputDeviceManagerPrivate) + d_ptr(QInputInfoManagerPrivate::instance()) { connect(d_ptr, &QInputDeviceManagerPrivate::deviceAdded,this,&QInputDeviceManager::addedDevice); connect(d_ptr, &QInputDeviceManagerPrivate::deviceRemoved,this,&QInputDeviceManager::deviceRemoved); diff --git a/src/systeminfo/qinputinfo.h b/src/systeminfo/qinputinfo.h index 1864f62..be74d8d 100644 --- a/src/systeminfo/qinputinfo.h +++ b/src/systeminfo/qinputinfo.h @@ -65,7 +65,8 @@ public: Q_OBJECT Q_ENUMS(InputType) Q_FLAGS(InputType InputTypeFlags) - friend class QInputDeviceManagerPrivate; + friend class QInputInfoManagerUdev; + friend class QInputInfoManagerMir; public: diff --git a/src/systeminfo/systeminfo.pro b/src/systeminfo/systeminfo.pro index 26f160c..a505e0e 100644 --- a/src/systeminfo/systeminfo.pro +++ b/src/systeminfo/systeminfo.pro @@ -13,7 +13,7 @@ SOURCES += qdeviceinfo.cpp \ qbatteryinfo.cpp \ qnetworkinfo.cpp \ qinputinfo.cpp \ - linux/qinputdeviceinfo_linux.cpp + linux/qinputinfomanager.cpp win32: !simulator: { # Wbemidl.h violates C/C++ strict strings @@ -122,12 +122,24 @@ LIBS += -ludev -levdev SOURCES += linux/qbatteryinfo_linux.cpp } + config_mir { + QT += gui gui-private + CONFIG += link_pkgconfig + PKGCONFIG += mirclient + LIBS += -lmirclient + SOURCES += linux/qinputinfomanagermir.cpp + } else { + DEFINES += QT_NO_MIR + } + config_udev { CONFIG += link_pkgconfig PKGCONFIG += udev LIBS += -ludev - PRIVATE_HEADERS += linux/qudevwrapper_p.h - SOURCES += linux/qudevwrapper.cpp + PRIVATE_HEADERS += linux/qudevwrapper_p.h \ + linux/qinputinfomanagerudev_p.h + SOURCES += linux/qudevwrapper.cpp \ + linux/qinputinfomanagerudev.cpp } else { DEFINES += QT_NO_UDEV } @@ -216,12 +228,15 @@ simulator { DEFINES += QT_NO_OFONO QT_NO_UDISKS } + DEFINES += QT_NO_MIR + config_udev { CONFIG += link_pkgconfig PKGCONFIG += udev LIBS += -ludev PRIVATE_HEADERS += linux/qudevwrapper_p.h - SOURCES += linux/qudevwrapper.cpp + SOURCES += linux/qudevwrapper.cpp \ + linux/qinputdeviceinfo_udev.cpp } else { DEFINES += QT_NO_UDEV } @@ -233,7 +248,7 @@ QMAKE_DOCS = $$PWD/../../doc/config/systeminfo/qtsysteminfo.qdocconf HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS \ qinputinfo.h \ - linux/qinputdeviceinfo_linux_p.h + linux/qinputinfomanager_p.h load(qt_module) # This must be done after loading qt_module.prf -- 2.7.3