From 10472dce9202e4460b2d908bdbe0cd65291f77e5 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 9 Jan 2015 14:48:01 +0100 Subject: Unify input device hotplugging support for embedded On embedded the mouse cursor will now appear and reappear regardless of how the input handling code is loaded (via a generic plugin or compiled-in to the platform plugin). Instead of passing around QDeviceDiscovery instances that only works when compiling-in the code into the platform plugin, introduce a new internal central QInputDeviceManager. The single instance of this provides a place to store any future input device related signals and properties. Also introduce mouse hotplugging support to linuxfb. [ChangeLog][QtGui] The mouse cursor on Embedded Linux is now handling hotplugging correctly with eglfs and linuxfb regardless of how the input handling code is loaded (via a generic plugin or built in to the platform plugin). Change-Id: I147c1b04a193baf216598015264f2c06e1b20f84 Reviewed-by: Andy Nichols --- .../eglconvenience/qeglplatformcursor.cpp | 37 +++++------------ .../eglconvenience/qeglplatformcursor_p.h | 11 ++---- .../eglconvenience/qeglplatformintegration.cpp | 7 +--- src/platformsupport/fbconvenience/qfbcursor.cpp | 46 ++++++++++++++++++++-- src/platformsupport/fbconvenience/qfbcursor_p.h | 23 ++++++++++- .../input/evdevkeyboard/qevdevkeyboardmanager.cpp | 12 +++++- .../input/evdevmouse/qevdevmousemanager.cpp | 7 ++++ .../input/evdevmouse/qevdevmousemanager_p.h | 6 +-- .../input/libinput/qlibinputhandler.cpp | 40 ++++++++++++++++++- .../input/libinput/qlibinputhandler_p.h | 2 + 10 files changed, 138 insertions(+), 53 deletions(-) (limited to 'src/platformsupport') diff --git a/src/platformsupport/eglconvenience/qeglplatformcursor.cpp b/src/platformsupport/eglconvenience/qeglplatformcursor.cpp index cf41bd2f1b..b07f8cd470 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcursor.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformcursor.cpp @@ -39,7 +39,7 @@ #include #include -#include +#include #include "qeglplatformcursor_p.h" #include "qeglplatformintegration_p.h" @@ -79,6 +79,11 @@ QEGLPlatformCursor::QEGLPlatformCursor(QPlatformScreen *screen) QCursor cursor(Qt::ArrowCursor); setCurrentCursor(&cursor); #endif + + m_deviceListener = new QEGLPlatformCursorDeviceListener(this); + connect(QGuiApplicationPrivate::inputDeviceManager(), &QInputDeviceManager::deviceListChanged, + m_deviceListener, &QEGLPlatformCursorDeviceListener::onDeviceListChanged); + updateMouseStatus(); } QEGLPlatformCursor::~QEGLPlatformCursor() @@ -87,42 +92,20 @@ QEGLPlatformCursor::~QEGLPlatformCursor() delete m_deviceListener; } -void QEGLPlatformCursor::setMouseDeviceDiscovery(QDeviceDiscovery *dd) -{ - if (m_visible && dd) { - m_deviceListener = new QEGLPlatformCursorDeviceListener(dd, this); - updateMouseStatus(); - } -} - void QEGLPlatformCursor::updateMouseStatus() { m_visible = m_deviceListener->hasMouse(); } -QEGLPlatformCursorDeviceListener::QEGLPlatformCursorDeviceListener(QDeviceDiscovery *dd, QEGLPlatformCursor *cursor) - : m_cursor(cursor) -{ - m_mouseCount = dd->scanConnectedDevices().count(); - connect(dd, SIGNAL(deviceDetected(QString)), SLOT(onDeviceAdded())); - connect(dd, SIGNAL(deviceRemoved(QString)), SLOT(onDeviceRemoved())); -} - bool QEGLPlatformCursorDeviceListener::hasMouse() const { - return m_mouseCount > 0; -} - -void QEGLPlatformCursorDeviceListener::onDeviceAdded() -{ - ++m_mouseCount; - m_cursor->updateMouseStatus(); + return QGuiApplicationPrivate::inputDeviceManager()->deviceCount(QInputDeviceManager::DeviceTypePointer) > 0; } -void QEGLPlatformCursorDeviceListener::onDeviceRemoved() +void QEGLPlatformCursorDeviceListener::onDeviceListChanged(QInputDeviceManager::DeviceType type) { - --m_mouseCount; - m_cursor->updateMouseStatus(); + if (type == QInputDeviceManager::DeviceTypePointer) + m_cursor->updateMouseStatus(); } void QEGLPlatformCursor::resetResources() diff --git a/src/platformsupport/eglconvenience/qeglplatformcursor_p.h b/src/platformsupport/eglconvenience/qeglplatformcursor_p.h index bf2aeef378..8d111e26ed 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcursor_p.h +++ b/src/platformsupport/eglconvenience/qeglplatformcursor_p.h @@ -48,11 +48,11 @@ #include #include #include +#include QT_BEGIN_NAMESPACE class QOpenGLShaderProgram; -class QDeviceDiscovery; class QEGLPlatformCursor; class QEGLPlatformCursorDeviceListener : public QObject @@ -60,16 +60,14 @@ class QEGLPlatformCursorDeviceListener : public QObject Q_OBJECT public: - QEGLPlatformCursorDeviceListener(QDeviceDiscovery *dd, QEGLPlatformCursor *cursor); + QEGLPlatformCursorDeviceListener(QEGLPlatformCursor *cursor) : m_cursor(cursor) { } bool hasMouse() const; -private slots: - void onDeviceAdded(); - void onDeviceRemoved(); +public slots: + void onDeviceListChanged(QInputDeviceManager::DeviceType type); private: QEGLPlatformCursor *m_cursor; - int m_mouseCount; }; class QEGLPlatformCursorUpdater : public QObject @@ -108,7 +106,6 @@ public: void paintOnScreen(); void resetResources(); - void setMouseDeviceDiscovery(QDeviceDiscovery *dd); void updateMouseStatus(); private: diff --git a/src/platformsupport/eglconvenience/qeglplatformintegration.cpp b/src/platformsupport/eglconvenience/qeglplatformintegration.cpp index e2a215d35f..ef794f0e1b 100644 --- a/src/platformsupport/eglconvenience/qeglplatformintegration.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformintegration.cpp @@ -352,12 +352,7 @@ void QEGLPlatformIntegration::createInputHandlers() { #if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK)) m_kbdMgr = new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString() /* spec */, this); - QEvdevMouseManager *mouseMgr = new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString() /* spec */, this); - Q_FOREACH (QScreen *screen, QGuiApplication::screens()) { - QEGLPlatformCursor *cursor = qobject_cast(screen->handle()->cursor()); - if (cursor) - cursor->setMouseDeviceDiscovery(mouseMgr->deviceDiscovery()); - } + new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString() /* spec */, this); #ifndef QT_NO_TSLIB const bool useTslib = qEnvironmentVariableIntValue("QT_QPA_EGLFS_TSLIB"); if (useTslib) diff --git a/src/platformsupport/fbconvenience/qfbcursor.cpp b/src/platformsupport/fbconvenience/qfbcursor.cpp index 806556b1e4..8d6a695d68 100644 --- a/src/platformsupport/fbconvenience/qfbcursor.cpp +++ b/src/platformsupport/fbconvenience/qfbcursor.cpp @@ -34,14 +34,47 @@ #include "qfbcursor_p.h" #include "qfbscreen_p.h" #include +#include QT_BEGIN_NAMESPACE +bool QFbCursorDeviceListener::hasMouse() const +{ + return QGuiApplicationPrivate::inputDeviceManager()->deviceCount(QInputDeviceManager::DeviceTypePointer) > 0; +} + +void QFbCursorDeviceListener::onDeviceListChanged(QInputDeviceManager::DeviceType type) +{ + if (type == QInputDeviceManager::DeviceTypePointer) + m_cursor->updateMouseStatus(); +} + QFbCursor::QFbCursor(QFbScreen *screen) - : mScreen(screen), mDirty(false), mOnScreen(false) + : mVisible(true), + mScreen(screen), + mDirty(false), + mOnScreen(false), + mGraphic(0), + mDeviceListener(0) { + QByteArray hideCursorVal = qgetenv("QT_QPA_FB_HIDECURSOR"); + if (!hideCursorVal.isEmpty()) + mVisible = hideCursorVal.toInt() == 0; + if (!mVisible) + return; + mGraphic = new QPlatformCursorImage(0, 0, 0, 0, 0, 0); setCursor(Qt::ArrowCursor); + + mDeviceListener = new QFbCursorDeviceListener(this); + connect(QGuiApplicationPrivate::inputDeviceManager(), &QInputDeviceManager::deviceListChanged, + mDeviceListener, &QFbCursorDeviceListener::onDeviceListChanged); + updateMouseStatus(); +} + +QFbCursor::~QFbCursor() +{ + delete mDeviceListener; } QRect QFbCursor::getCurrentRect() @@ -68,6 +101,9 @@ void QFbCursor::pointerEvent(const QMouseEvent & e) QRect QFbCursor::drawCursor(QPainter & painter) { + if (!mVisible) + return QRect(); + mDirty = false; if (mCurrentRect.isNull()) return QRect(); @@ -131,15 +167,19 @@ void QFbCursor::changeCursor(QCursor * widgetCursor, QWindow *window) void QFbCursor::setDirty() { + if (!mVisible) + return; + if (!mDirty) { mDirty = true; mScreen->scheduleUpdate(); } } -void QFbCursor::setMouseDeviceDiscovery(QDeviceDiscovery *dd) +void QFbCursor::updateMouseStatus() { - Q_UNUSED(dd); + mVisible = mDeviceListener->hasMouse(); + mScreen->setDirty(mVisible ? getCurrentRect() : lastPainted()); } QT_END_NAMESPACE diff --git a/src/platformsupport/fbconvenience/qfbcursor_p.h b/src/platformsupport/fbconvenience/qfbcursor_p.h index 75501a0ff0..bec781fb21 100644 --- a/src/platformsupport/fbconvenience/qfbcursor_p.h +++ b/src/platformsupport/fbconvenience/qfbcursor_p.h @@ -46,11 +46,27 @@ // #include +#include QT_BEGIN_NAMESPACE class QFbScreen; -class QDeviceDiscovery; +class QFbCursor; + +class QFbCursorDeviceListener : public QObject +{ + Q_OBJECT + +public: + QFbCursorDeviceListener(QFbCursor *cursor) : m_cursor(cursor) { } + bool hasMouse() const; + +public slots: + void onDeviceListChanged(QInputDeviceManager::DeviceType type); + +private: + QFbCursor *m_cursor; +}; class QFbCursor : public QPlatformCursor { @@ -58,6 +74,7 @@ class QFbCursor : public QPlatformCursor public: QFbCursor(QFbScreen *screen); + ~QFbCursor(); // output methods QRect dirtyRect(); @@ -74,7 +91,7 @@ public: virtual bool isOnScreen() const { return mOnScreen; } virtual QRect lastPainted() const { return mPrevRect; } - void setMouseDeviceDiscovery(QDeviceDiscovery *dd); + void updateMouseStatus(); private: void setCursor(const uchar *data, const uchar *mask, int width, int height, int hotX, int hotY); @@ -82,12 +99,14 @@ private: void setCursor(const QImage &image, int hotx, int hoty); QRect getCurrentRect(); + bool mVisible; QFbScreen *mScreen; QRect mCurrentRect; // next place to draw the cursor QRect mPrevRect; // last place the cursor was drawn bool mDirty; bool mOnScreen; QPlatformCursorImage *mGraphic; + QFbCursorDeviceListener *mDeviceListener; }; QT_END_NAMESPACE diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager.cpp b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager.cpp index 4614fbd499..8853da8371 100644 --- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager.cpp +++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager.cpp @@ -37,6 +37,9 @@ #include #include +#include +#include + QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(qLcEvdevKey) @@ -97,10 +100,13 @@ void QEvdevKeyboardManager::addKeyboard(const QString &deviceNode) qCDebug(qLcEvdevKey) << "Adding keyboard at" << deviceNode; QEvdevKeyboardHandler *keyboard; keyboard = QEvdevKeyboardHandler::create(deviceNode, m_spec, m_defaultKeymapFile); - if (keyboard) + if (keyboard) { m_keyboards.insert(deviceNode, keyboard); - else + QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount( + QInputDeviceManager::DeviceTypeKeyboard, m_keyboards.count()); + } else { qWarning("Failed to open keyboard device %s", qPrintable(deviceNode)); + } } void QEvdevKeyboardManager::removeKeyboard(const QString &deviceNode) @@ -109,6 +115,8 @@ void QEvdevKeyboardManager::removeKeyboard(const QString &deviceNode) qCDebug(qLcEvdevKey) << "Removing keyboard at" << deviceNode; QEvdevKeyboardHandler *keyboard = m_keyboards.value(deviceNode); m_keyboards.remove(deviceNode); + QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount( + QInputDeviceManager::DeviceTypeKeyboard, m_keyboards.count()); delete keyboard; } } diff --git a/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp b/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp index a0c9c9f34d..17e6b0cafa 100644 --- a/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp +++ b/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp @@ -38,6 +38,9 @@ #include #include #include +#include +#include +#include QT_BEGIN_NAMESPACE @@ -141,6 +144,8 @@ void QEvdevMouseManager::addMouse(const QString &deviceNode) connect(handler, SIGNAL(handleMouseEvent(int,int,bool,Qt::MouseButtons)), this, SLOT(handleMouseEvent(int,int,bool,Qt::MouseButtons))); connect(handler, SIGNAL(handleWheelEvent(int,Qt::Orientation)), this, SLOT(handleWheelEvent(int,Qt::Orientation))); m_mice.insert(deviceNode, handler); + QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount( + QInputDeviceManager::DeviceTypePointer, m_mice.count()); } else { qWarning("evdevmouse: Failed to open mouse device %s", qPrintable(deviceNode)); } @@ -152,6 +157,8 @@ void QEvdevMouseManager::removeMouse(const QString &deviceNode) qCDebug(qLcEvdevMouse) << "Removing mouse at" << deviceNode; QEvdevMouseHandler *handler = m_mice.value(deviceNode); m_mice.remove(deviceNode); + QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount( + QInputDeviceManager::DeviceTypePointer, m_mice.count()); delete handler; } } diff --git a/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h b/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h index 14aa6a8fd2..d30a2b337f 100644 --- a/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h +++ b/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h @@ -47,14 +47,14 @@ #include "qevdevmousehandler_p.h" -#include - #include #include #include QT_BEGIN_NAMESPACE +class QDeviceDiscovery; + class QEvdevMouseManager : public QObject { Q_OBJECT @@ -62,8 +62,6 @@ public: QEvdevMouseManager(const QString &key, const QString &specification, QObject *parent = 0); ~QEvdevMouseManager(); - QDeviceDiscovery *deviceDiscovery() { return m_deviceDiscovery; } - public slots: void handleMouseEvent(int x, int y, bool abs, Qt::MouseButtons buttons); void handleWheelEvent(int delta, Qt::Orientation orientation); diff --git a/src/platformsupport/input/libinput/qlibinputhandler.cpp b/src/platformsupport/input/libinput/qlibinputhandler.cpp index cab4527d0a..0ed605019c 100644 --- a/src/platformsupport/input/libinput/qlibinputhandler.cpp +++ b/src/platformsupport/input/libinput/qlibinputhandler.cpp @@ -41,6 +41,8 @@ #include #include #include +#include +#include QT_BEGIN_NAMESPACE @@ -146,8 +148,25 @@ void QLibInputHandler::processEvent(libinput_event *ev) 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)) + + QInputDeviceManagerPrivate *inputManagerPriv = QInputDeviceManagerPrivate::get( + QGuiApplicationPrivate::inputDeviceManager()); + if (libinput_device_has_capability(dev, LIBINPUT_DEVICE_CAP_TOUCH)) { m_touch->registerDevice(dev); + int &count(m_devCount[QInputDeviceManager::DeviceTypeTouch]); + ++count; + inputManagerPriv->setDeviceCount(QInputDeviceManager::DeviceTypeTouch, count); + } + if (libinput_device_has_capability(dev, LIBINPUT_DEVICE_CAP_POINTER)) { + int &count(m_devCount[QInputDeviceManager::DeviceTypePointer]); + ++count; + inputManagerPriv->setDeviceCount(QInputDeviceManager::DeviceTypePointer, count); + } + if (libinput_device_has_capability(dev, LIBINPUT_DEVICE_CAP_KEYBOARD)) { + int &count(m_devCount[QInputDeviceManager::DeviceTypeKeyboard]); + ++count; + inputManagerPriv->setDeviceCount(QInputDeviceManager::DeviceTypeKeyboard, count); + } break; } case LIBINPUT_EVENT_DEVICE_REMOVED: @@ -155,8 +174,25 @@ void QLibInputHandler::processEvent(libinput_event *ev) 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)) + + QInputDeviceManagerPrivate *inputManagerPriv = QInputDeviceManagerPrivate::get( + QGuiApplicationPrivate::inputDeviceManager()); + if (libinput_device_has_capability(dev, LIBINPUT_DEVICE_CAP_TOUCH)) { m_touch->unregisterDevice(dev); + int &count(m_devCount[QInputDeviceManager::DeviceTypeTouch]); + --count; + inputManagerPriv->setDeviceCount(QInputDeviceManager::DeviceTypeTouch, count); + } + if (libinput_device_has_capability(dev, LIBINPUT_DEVICE_CAP_POINTER)) { + int &count(m_devCount[QInputDeviceManager::DeviceTypePointer]); + --count; + inputManagerPriv->setDeviceCount(QInputDeviceManager::DeviceTypePointer, count); + } + if (libinput_device_has_capability(dev, LIBINPUT_DEVICE_CAP_KEYBOARD)) { + int &count(m_devCount[QInputDeviceManager::DeviceTypeKeyboard]); + --count; + inputManagerPriv->setDeviceCount(QInputDeviceManager::DeviceTypeKeyboard, count); + } break; } case LIBINPUT_EVENT_POINTER_BUTTON: diff --git a/src/platformsupport/input/libinput/qlibinputhandler_p.h b/src/platformsupport/input/libinput/qlibinputhandler_p.h index a1cfaca3ce..6d376c4ca3 100644 --- a/src/platformsupport/input/libinput/qlibinputhandler_p.h +++ b/src/platformsupport/input/libinput/qlibinputhandler_p.h @@ -36,6 +36,7 @@ #include #include +#include // // W A R N I N G @@ -84,6 +85,7 @@ private: QScopedPointer m_pointer; QScopedPointer m_keyboard; QScopedPointer m_touch; + QMap m_devCount; }; QT_END_NAMESPACE -- cgit v1.2.3