summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSean Harmer <sean.harmer.qnx@kdab.com>2012-09-17 14:02:35 +0100
committerQt by Nokia <qt-info@nokia.com>2012-09-17 17:00:39 +0200
commit9d74928189d990b24cfdd2350fe5a092951d670d (patch)
treed610aba7ce4fc77f5ceef27dcda2b64e2189ae4c /src
parent086f85a87c52c6026da294b7d00efffc50b669e1 (diff)
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')
-rw-r--r--src/plugins/platforms/blackberry/blackberry.pro6
-rw-r--r--src/plugins/platforms/blackberry/qbbbuttoneventnotifier.cpp219
-rw-r--r--src/plugins/platforms/blackberry/qbbbuttoneventnotifier.h87
-rw-r--r--src/plugins/platforms/blackberry/qbbintegration.cpp11
-rw-r--r--src/plugins/platforms/blackberry/qbbintegration.h2
5 files changed, 321 insertions, 4 deletions
diff --git a/src/plugins/platforms/blackberry/blackberry.pro b/src/plugins/platforms/blackberry/blackberry.pro
index ede46b7c5a..6c345839f8 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 0000000000..d6b2edba8d
--- /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 0000000000..8113de4283
--- /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 1ad8ff6de4..75ed659529 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 be820870a8..9b0ab46ef9 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;