diff options
author | Sean Harmer <sean.harmer.qnx@kdab.com> | 2012-09-17 13:02:35 (GMT) |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-09-17 15:00:39 (GMT) |
commit | 9d74928189d990b24cfdd2350fe5a092951d670d (patch) | |
tree | d610aba7ce4fc77f5ceef27dcda2b64e2189ae4c /src/plugins | |
parent | 086f85a87c52c6026da294b7d00efffc50b669e1 (diff) | |
download | Qt-9d74928189d990b24cfdd2350fe5a092951d670d.zip Qt-9d74928189d990b24cfdd2350fe5a092951d670d.tar.gz Qt-9d74928189d990b24cfdd2350fe5a092951d670d.tar.bz2 |
QNX: Enable support for hardware buttons in QPA plugin
Backport of 3f407cddf8b1d5fc09b414dbecd9a47d30e3abe7
Change-Id: Id7fd3ca76793d8d3e3698dd402fe31e04567e938
Reviewed-by: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
Diffstat (limited to 'src/plugins')
5 files changed, 321 insertions, 4 deletions
diff --git a/src/plugins/platforms/blackberry/blackberry.pro b/src/plugins/platforms/blackberry/blackberry.pro index ede46b7..6c34583 100644 --- a/src/plugins/platforms/blackberry/blackberry.pro +++ b/src/plugins/platforms/blackberry/blackberry.pro @@ -30,7 +30,8 @@ SOURCES = main.cpp \ qbbrootwindow.cpp \ qbbscreeneventhandler.cpp \ qbbabstractvirtualkeyboard.cpp \ - qbbnativeinterface.cpp + qbbnativeinterface.cpp \ + qbbbuttoneventnotifier.cpp HEADERS = qbbbuffer.h \ qbbscreeneventthread.h \ @@ -49,7 +50,8 @@ HEADERS = qbbbuffer.h \ qbbrootwindow.h \ qbbscreeneventhandler.h \ qbbabstractvirtualkeyboard.h \ - qbbnativeinterface.h + qbbnativeinterface.h \ + qbbbuttoneventnotifier.h blackberry { SOURCES += qbbbpseventfilter.cpp \ diff --git a/src/plugins/platforms/blackberry/qbbbuttoneventnotifier.cpp b/src/plugins/platforms/blackberry/qbbbuttoneventnotifier.cpp new file mode 100644 index 0000000..d6b2edb --- /dev/null +++ b/src/plugins/platforms/blackberry/qbbbuttoneventnotifier.cpp @@ -0,0 +1,219 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Research In Motion <blackberry-qt@qnx.com> +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia 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 "qbbbuttoneventnotifier.h" + +#include <QtGui/QApplication> +#include <qwindowsysteminterface_qpa.h> + +#include <QtCore/QDebug> +#include <QtCore/QMetaEnum> +#include <QtCore/QSocketNotifier> +#include <QtCore/private/qcore_unix_p.h> + +//#define QBBBUTTON_DEBUG + +#ifdef QBBBUTTON_DEBUG +#define qButtonDebug qDebug +#else +#define qButtonDebug QT_NO_QDEBUG_MACRO +#endif + +QT_BEGIN_NAMESPACE + +static const char *ppsPath = "/pps/system/buttons/status"; +static const int ppsBufferSize = 256; + +QBBButtonEventNotifier::QBBButtonEventNotifier(QObject *parent) + : QObject(parent), + mFd(-1), + mReadNotifier(0) +{ + // Set initial state of buttons to ButtonUp and + // fetch the new button ids + int enumeratorIndex = QBBButtonEventNotifier::staticMetaObject.indexOfEnumerator("ButtonId"); + QMetaEnum enumerator = QBBButtonEventNotifier::staticMetaObject.enumerator(enumeratorIndex); + for (int buttonId = bid_minus; buttonId < ButtonCount; ++buttonId) { + mButtonKeys.append(enumerator.valueToKey(buttonId)); + mState[buttonId] = ButtonUp; + } +} + +QBBButtonEventNotifier::~QBBButtonEventNotifier() +{ + close(); +} + +void QBBButtonEventNotifier::start() +{ + qButtonDebug() << Q_FUNC_INFO << "starting hardware button event processing"; + if (mFd != -1) + return; + + // Open the pps interface + errno = 0; + mFd = qt_safe_open(ppsPath, O_RDONLY); + if (mFd == -1) { + qWarning("QQNX: failed to open buttons pps, errno=%d", errno); + return; + } + + mReadNotifier = new QSocketNotifier(mFd, QSocketNotifier::Read); + QObject::connect(mReadNotifier, SIGNAL(activated(int)), this, SLOT(updateButtonStates())); + + qButtonDebug() << Q_FUNC_INFO << "successfully connected to Navigator. fd =" << mFd; +} + +void QBBButtonEventNotifier::updateButtonStates() +{ + // Allocate buffer for pps data + char buffer[ppsBufferSize]; + + // Attempt to read pps data + errno = 0; + int bytes = qt_safe_read(mFd, buffer, ppsBufferSize - 1); + qButtonDebug() << "Read" << bytes << "bytes of data"; + if (bytes == -1) { + qWarning("QQNX: failed to read hardware buttons pps object, errno=%d", errno); + return; + } + + // We seem to get a spurious read notification after the real one. Ignore it + if (bytes == 0) + return; + + // Ensure data is null terminated + buffer[bytes] = '\0'; + + qButtonDebug() << Q_FUNC_INFO << "received PPS message:\n" << buffer; + + // Process received message + QByteArray ppsData = QByteArray::fromRawData(buffer, bytes); + QHash<QByteArray, QByteArray> fields; + if (!parsePPS(ppsData, &fields)) + return; + + // Update our state and inject key events as needed + for (int buttonId = bid_minus; buttonId < ButtonCount; ++buttonId) { + // Extract the new button state + QByteArray key = mButtonKeys.at(buttonId); + ButtonState newState = (fields.value(key) == QByteArray("b_up") ? ButtonUp : ButtonDown); + + // If state has changed, update our state and inject a keypress event + if (mState[buttonId] != newState) { + qButtonDebug() << "Hardware button event: button =" << key << "state =" << fields.value(key); + mState[buttonId] = newState; + + // Is it a key press or key release event? + QEvent::Type type = (newState == ButtonDown) ? QEvent::KeyPress : QEvent::KeyRelease; + + Qt::Key key; + switch (buttonId) { + case bid_minus: + key = Qt::Key_VolumeDown; + break; + + case bid_playpause: + key = Qt::Key_Play; + break; + + case bid_plus: + key = Qt::Key_VolumeUp; + break; + + case bid_power: + key = Qt::Key_PowerDown; + break; + + default: + qButtonDebug() << "Unknown hardware button"; + continue; + } + + // No modifiers + Qt::KeyboardModifiers modifier = Qt::NoModifier; + + // Post the event + QWindowSystemInterface::handleKeyEvent(QApplication::activeWindow(), type, key, modifier); + } + } +} + +void QBBButtonEventNotifier::close() +{ + delete mReadNotifier; + mReadNotifier = 0; + + if (mFd != -1) { + qt_safe_close(mFd); + mFd = -1; + } +} + +bool QBBButtonEventNotifier::parsePPS(const QByteArray &ppsData, QHash<QByteArray, QByteArray> *messageFields) const +{ + // tokenize pps data into lines + QList<QByteArray> lines = ppsData.split('\n'); + + // validate pps object + if (lines.size() == 0 || lines.at(0) != QByteArray("@status")) { + qWarning("QQNX: unrecognized pps object, data=%s", ppsData.constData()); + return false; + } + + // parse pps object attributes and extract values + for (int i = 1; i < lines.size(); i++) { + + // tokenize current attribute + const QByteArray &attr = lines.at(i); + + qButtonDebug() << Q_FUNC_INFO << "attr=" << attr; + + int doubleColon = attr.indexOf(QByteArray("::")); + if (doubleColon == -1) { + // abort - malformed attribute + continue; + } + + QByteArray key = attr.left(doubleColon); + QByteArray value = attr.mid(doubleColon + 2); + messageFields->insert(key, value); + } + return true; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/blackberry/qbbbuttoneventnotifier.h b/src/plugins/platforms/blackberry/qbbbuttoneventnotifier.h new file mode 100644 index 0000000..8113de4 --- /dev/null +++ b/src/plugins/platforms/blackberry/qbbbuttoneventnotifier.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Research In Motion <blackberry-qt@qnx.com> +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia 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 QBBBUTTONSEVENTNOTIFIER_H +#define QBBBUTTONSEVENTNOTIFIER_H + +#include <QObject> +#include <QHash> + +QT_BEGIN_NAMESPACE + +class QSocketNotifier; + +class QBBButtonEventNotifier : public QObject +{ + Q_OBJECT + Q_ENUMS(ButtonId) +public: + enum ButtonId { + bid_minus = 0, + bid_playpause, + bid_plus, + bid_power, + ButtonCount + }; + + enum ButtonState { + ButtonUp, + ButtonDown + }; + + explicit QBBButtonEventNotifier(QObject *parent = 0); + ~QBBButtonEventNotifier(); + +public Q_SLOTS: + void start(); + +private Q_SLOTS: + void updateButtonStates(); + +private: + void close(); + bool parsePPS(const QByteArray &ppsData, QHash<QByteArray, QByteArray> *messageFields) const; + + int mFd; + QSocketNotifier *mReadNotifier; + ButtonState mState[ButtonCount]; + QList<QByteArray> mButtonKeys; +}; + +QT_END_NAMESPACE + +#endif // QBBBUTTONSEVENTNOTIFIER_H diff --git a/src/plugins/platforms/blackberry/qbbintegration.cpp b/src/plugins/platforms/blackberry/qbbintegration.cpp index 1ad8ff6..75ed659 100644 --- a/src/plugins/platforms/blackberry/qbbintegration.cpp +++ b/src/plugins/platforms/blackberry/qbbintegration.cpp @@ -54,6 +54,7 @@ #include "qbbglcontext.h" #include "qbblocalethread.h" #include "qbbnativeinterface.h" +#include "qbbbuttoneventnotifier.h" #if defined(Q_OS_BLACKBERRY) #include "qbbbpseventfilter.h" #include "qbbvirtualkeyboardbps.h" @@ -80,6 +81,7 @@ Q_DECLARE_METATYPE(screen_window_t); QBBIntegration::QBBIntegration() : mScreenEventThread(0), mNavigatorEventHandler(new QBBNavigatorEventHandler()), + mButtonsNotifier(new QBBButtonEventNotifier()), mFontDb(new QGenericUnixFontDatabase()), mScreenEventHandler(new QBBScreenEventHandler()), mPaintUsingOpenGL(getenv("QBB_USE_OPENGL") != NULL), @@ -164,6 +166,10 @@ QBBIntegration::QBBIntegration() : // Set up the input context qApp->setInputContext(new QBBInputContext(*mVirtualKeyboard, qApp)); + + // delay invocation of start() to the time the event loop is up and running + // needed to have the QThread internals of the main thread properly initialized + QMetaObject::invokeMethod(mButtonsNotifier, "start", Qt::QueuedConnection); } QBBIntegration::~QBBIntegration() @@ -171,10 +177,11 @@ QBBIntegration::~QBBIntegration() #if defined(QBBINTEGRATION_DEBUG) qDebug() << "QBB: platform plugin shutdown begin"; #endif - - delete mNativeInterface; + // Destroy the hardware button notifier + delete mButtonsNotifier; + #ifdef QBBLOCALETHREAD_ENABLED // stop/destroy the locale thread. delete mLocaleThread; diff --git a/src/plugins/platforms/blackberry/qbbintegration.h b/src/plugins/platforms/blackberry/qbbintegration.h index be82087..9b0ab46 100644 --- a/src/plugins/platforms/blackberry/qbbintegration.h +++ b/src/plugins/platforms/blackberry/qbbintegration.h @@ -53,6 +53,7 @@ class QBBScreen; class QBBScreenEventHandler; class QBBNativeInterface; class QBBBpsEventFilter; +class QBBButtonEventNotifier; class QBBIntegration : public QPlatformIntegration { @@ -90,6 +91,7 @@ private: QBBScreenEventThread *mScreenEventThread; QBBNavigatorEventHandler *mNavigatorEventHandler; QBBNavigatorEventNotifier *mNavigatorEventNotifier; + QBBButtonEventNotifier *mButtonsNotifier; QBBLocaleThread *mLocaleThread; QPlatformFontDatabase *mFontDb; QList<QPlatformScreen*> mScreens; |