summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean Harmer <sean.harmer@kdab.com>2012-09-04 19:58:27 +0100
committerQt by Nokia <qt-info@nokia.com>2012-09-07 18:41:22 +0200
commit834e9823fc727d89c6b8e959dee29efa617a5aec (patch)
tree9ef70491bbffe36df64600a39e40d49bd9ec4b73
parente54f6ed87b020df0a724ec90763775daf63ffab3 (diff)
QNX: Enable support for hardware buttons in QPA plugin
Change-Id: I3de18c3fdcfdacddc375b70800b34b6a8d16ac41 Reviewed-by: Qt Doc Bot <qt_docbot@qt-project.org> Reviewed-by: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> Reviewed-by: Thomas McGuire <thomas.mcguire@kdab.com> Reviewed-by: Kevin Krammer <kevin.krammer@kdab.com>
-rw-r--r--src/plugins/platforms/qnx/qnx.pro7
-rw-r--r--src/plugins/platforms/qnx/qqnxbuttoneventnotifier.cpp221
-rw-r--r--src/plugins/platforms/qnx/qqnxbuttoneventnotifier.h90
-rw-r--r--src/plugins/platforms/qnx/qqnxintegration.cpp10
-rw-r--r--src/plugins/platforms/qnx/qqnxintegration.h2
5 files changed, 328 insertions, 2 deletions
diff --git a/src/plugins/platforms/qnx/qnx.pro b/src/plugins/platforms/qnx/qnx.pro
index 5298824600..dc16016af3 100644
--- a/src/plugins/platforms/qnx/qnx.pro
+++ b/src/plugins/platforms/qnx/qnx.pro
@@ -23,6 +23,7 @@ CONFIG(blackberry) {
# Uncomment these to enable debugging output for various aspects of the plugin
#DEFINES += QQNXBPSEVENTFILTER_DEBUG
#DEFINES += QQNXBUFFER_DEBUG
+#DEFINES += QQNXBUTTON_DEBUG
#DEFINES += QQNXCLIPBOARD_DEBUG
#DEFINES += QQNXFILEDIALOGHELPER_DEBUG
#DEFINES += QQNXGLBACKINGSTORE_DEBUG
@@ -109,12 +110,14 @@ CONFIG(qqnx_pps) {
SOURCES += qqnxnavigatorpps.cpp \
qqnxnavigatoreventnotifier.cpp \
qqnxvirtualkeyboardpps.cpp \
- qqnxclipboard.cpp
+ qqnxclipboard.cpp \
+ qqnxbuttoneventnotifier.cpp
HEADERS += qqnxnavigatorpps.h \
qqnxnavigatoreventnotifier.h \
qqnxvirtualkeyboardpps.h \
- qqnxclipboard.h
+ qqnxclipboard.h \
+ qqnxbuttoneventnotifier.h
LIBS += -lpps -lclipboard
diff --git a/src/plugins/platforms/qnx/qqnxbuttoneventnotifier.cpp b/src/plugins/platforms/qnx/qqnxbuttoneventnotifier.cpp
new file mode 100644
index 0000000000..f4e72371ed
--- /dev/null
+++ b/src/plugins/platforms/qnx/qqnxbuttoneventnotifier.cpp
@@ -0,0 +1,221 @@
+/***************************************************************************
+**
+** Copyright (C) 2012 Research In Motion
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqnxbuttoneventnotifier.h"
+
+#include <QtGui/QGuiApplication>
+#include <qpa/qwindowsysteminterface.h>
+
+#include <QtCore/QDebug>
+#include <QtCore/QMetaEnum>
+#include <QtCore/QSocketNotifier>
+#include <QtCore/private/qcore_unix_p.h>
+
+#ifdef QQNXBUTTON_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;
+
+QQnxButtonEventNotifier::QQnxButtonEventNotifier(QObject *parent)
+ : QObject(parent),
+ m_fd(-1),
+ m_readNotifier(0)
+{
+ // Set initial state of buttons to ButtonUp and
+ // fetch the new button ids
+ int enumeratorIndex = QQnxButtonEventNotifier::staticMetaObject.indexOfEnumerator(QByteArrayLiteral("ButtonId"));
+ QMetaEnum enumerator = QQnxButtonEventNotifier::staticMetaObject.enumerator(enumeratorIndex);
+ for (int buttonId = bid_minus; buttonId < ButtonCount; ++buttonId) {
+ m_buttonKeys.append(enumerator.valueToKey(buttonId));
+ m_state[buttonId] = ButtonUp;
+ }
+}
+
+QQnxButtonEventNotifier::~QQnxButtonEventNotifier()
+{
+ close();
+}
+
+void QQnxButtonEventNotifier::start()
+{
+ qButtonDebug() << Q_FUNC_INFO << "starting hardware button event processing";
+ if (m_fd != -1)
+ return;
+
+ // Open the pps interface
+ errno = 0;
+ m_fd = qt_safe_open(ppsPath, O_RDONLY);
+ if (m_fd == -1) {
+ qWarning("QQNX: failed to open buttons pps, errno=%d", errno);
+ return;
+ }
+
+ m_readNotifier = new QSocketNotifier(m_fd, QSocketNotifier::Read);
+ QObject::connect(m_readNotifier, SIGNAL(activated(int)), this, SLOT(updateButtonStates()));
+
+ qButtonDebug() << Q_FUNC_INFO << "successfully connected to Navigator. fd =" << m_fd;
+}
+
+void QQnxButtonEventNotifier::updateButtonStates()
+{
+ // Allocate buffer for pps data
+ char buffer[ppsBufferSize];
+
+ // Attempt to read pps data
+ errno = 0;
+ int bytes = qt_safe_read(m_fd, 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 = m_buttonKeys.at(buttonId);
+ ButtonState newState = (fields.value(key) == QByteArrayLiteral("b_up") ? ButtonUp : ButtonDown);
+
+ // If state has changed, update our state and inject a keypress event
+ if (m_state[buttonId] != newState) {
+ qButtonDebug() << "Hardware button event: button =" << key << "state =" << fields.value(key);
+ m_state[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(QGuiApplication::focusWindow(), type, key, modifier);
+ }
+ }
+}
+
+void QQnxButtonEventNotifier::close()
+{
+ delete m_readNotifier;
+ m_readNotifier = 0;
+
+ if (m_fd != -1) {
+ qt_safe_close(m_fd);
+ m_fd = -1;
+ }
+}
+
+bool QQnxButtonEventNotifier::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) != QByteArrayLiteral("@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(QByteArrayLiteral("::"));
+ 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/qnx/qqnxbuttoneventnotifier.h b/src/plugins/platforms/qnx/qqnxbuttoneventnotifier.h
new file mode 100644
index 0000000000..01b9a7248f
--- /dev/null
+++ b/src/plugins/platforms/qnx/qqnxbuttoneventnotifier.h
@@ -0,0 +1,90 @@
+/***************************************************************************
+**
+** Copyright (C) 2012 Research In Motion
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQNXBUTTONSEVENTNOTIFIER_H
+#define QQNXBUTTONSEVENTNOTIFIER_H
+
+#include <QObject>
+
+QT_BEGIN_NAMESPACE
+
+class QSocketNotifier;
+
+class QQnxButtonEventNotifier : 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 QQnxButtonEventNotifier(QObject *parent = 0);
+ ~QQnxButtonEventNotifier();
+
+public Q_SLOTS:
+ void start();
+
+private Q_SLOTS:
+ void updateButtonStates();
+
+private:
+ void close();
+ bool parsePPS(const QByteArray &ppsData, QHash<QByteArray, QByteArray> *messageFields) const;
+
+ int m_fd;
+ QSocketNotifier *m_readNotifier;
+ ButtonState m_state[ButtonCount];
+ QList<QByteArray> m_buttonKeys;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQNXBUTTONSEVENTNOTIFIER_H
diff --git a/src/plugins/platforms/qnx/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp
index b988020293..b3bd4e30fb 100644
--- a/src/plugins/platforms/qnx/qqnxintegration.cpp
+++ b/src/plugins/platforms/qnx/qqnxintegration.cpp
@@ -62,6 +62,7 @@
#endif
#if defined(QQNX_PPS)
+# include "qqnxbuttoneventnotifier.h"
# include "qqnxnavigatoreventnotifier.h"
# include "qqnxclipboard.h"
@@ -112,6 +113,7 @@ QQnxIntegration::QQnxIntegration()
#if defined(QQNX_PPS)
, m_navigatorEventNotifier(0)
, m_inputContext(0)
+ , m_buttonsNotifier(new QQnxButtonEventNotifier())
#endif
, m_services(0)
, m_fontDatabase(new QGenericUnixFontDatabase())
@@ -210,6 +212,11 @@ QQnxIntegration::QQnxIntegration()
#endif
}
+#if defined(QQNX_PPS)
+ // 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(m_buttonsNotifier, "start", Qt::QueuedConnection);
+#endif
}
QQnxIntegration::~QQnxIntegration()
@@ -218,6 +225,9 @@ QQnxIntegration::~QQnxIntegration()
delete m_nativeInterface;
#if defined(QQNX_PPS)
+ // Destroy the hardware button notifier
+ delete m_buttonsNotifier;
+
// Destroy input context
delete m_inputContext;
#endif
diff --git a/src/plugins/platforms/qnx/qqnxintegration.h b/src/plugins/platforms/qnx/qqnxintegration.h
index fe2447c0ac..361d4fd9d0 100644
--- a/src/plugins/platforms/qnx/qqnxintegration.h
+++ b/src/plugins/platforms/qnx/qqnxintegration.h
@@ -65,6 +65,7 @@ class QQnxServices;
#if defined(QQNX_PPS)
class QQnxInputContext;
class QQnxNavigatorEventNotifier;
+class QQnxButtonEventNotifier;
#endif
#if !defined(QT_NO_CLIPBOARD)
@@ -132,6 +133,7 @@ private:
#if defined(QQNX_PPS)
QQnxNavigatorEventNotifier *m_navigatorEventNotifier;
QQnxInputContext *m_inputContext;
+ QQnxButtonEventNotifier *m_buttonsNotifier;
#endif
QQnxServices *m_services;
QPlatformFontDatabase *m_fontDatabase;