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>
This commit is contained in:
Sean Harmer 2012-09-04 19:58:27 +01:00 committed by Qt by Nokia
parent e54f6ed87b
commit 834e9823fc
5 changed files with 328 additions and 2 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;