Integrate Blackberry Platform Services (BPS) with Qt event loop.
This ensures interoperability between the Blackbery C and C++ APIs and makes it easier to expose platform services in C++ that are exposed in BPS - since events from both APIs can be processed on the same thread. Change-Id: I7270adc64c26396f66d9126141500d5e58be51e7 Reviewed-by: Kevin Krammer <kevin.krammer@kdab.com> Reviewed-by: Giuseppe D'Angelo <dangelog@gmail.com> Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com>
This commit is contained in:
parent
77a816c00d
commit
0723e14699
@ -136,3 +136,10 @@ vxworks {
|
||||
kernel/qfunctions_vxworks.h
|
||||
}
|
||||
|
||||
blackberry {
|
||||
SOURCES += \
|
||||
kernel/qeventdispatcher_blackberry.cpp
|
||||
HEADERS += \
|
||||
kernel/qeventdispatcher_blackberry_p.h
|
||||
}
|
||||
|
||||
|
@ -67,10 +67,14 @@
|
||||
#include <private/qlocale_p.h>
|
||||
|
||||
#if defined(Q_OS_UNIX)
|
||||
# if !defined(QT_NO_GLIB)
|
||||
# include "qeventdispatcher_glib_p.h"
|
||||
# if defined(Q_OS_BLACKBERRY)
|
||||
# include "qeventdispatcher_blackberry_p.h"
|
||||
# else
|
||||
# if !defined(QT_NO_GLIB)
|
||||
# include "qeventdispatcher_glib_p.h"
|
||||
# endif
|
||||
# include "qeventdispatcher_unix_p.h"
|
||||
# endif
|
||||
# include "qeventdispatcher_unix_p.h"
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
@ -328,12 +332,16 @@ void QCoreApplicationPrivate::createEventDispatcher()
|
||||
{
|
||||
Q_Q(QCoreApplication);
|
||||
#if defined(Q_OS_UNIX)
|
||||
# if defined(Q_OS_BLACKBERRY)
|
||||
eventDispatcher = new QEventDispatcherBlackberry(q);
|
||||
# else
|
||||
# if !defined(QT_NO_GLIB)
|
||||
if (qgetenv("QT_NO_GLIB").isEmpty() && QEventDispatcherGlib::versionSupported())
|
||||
eventDispatcher = new QEventDispatcherGlib(q);
|
||||
else
|
||||
# endif
|
||||
eventDispatcher = new QEventDispatcherUNIX(q);
|
||||
# endif
|
||||
#elif defined(Q_OS_WIN)
|
||||
eventDispatcher = new QEventDispatcherWin32(q);
|
||||
#else
|
||||
|
262
src/corelib/kernel/qeventdispatcher_blackberry.cpp
Normal file
262
src/corelib/kernel/qeventdispatcher_blackberry.cpp
Normal file
@ -0,0 +1,262 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Research In Motion
|
||||
** 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.
|
||||
**
|
||||
** 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 "qeventdispatcher_blackberry_p.h"
|
||||
#include "qsocketnotifier.h"
|
||||
#include "qdebug.h"
|
||||
|
||||
#include <bps/bps.h>
|
||||
#include <bps/event.h>
|
||||
|
||||
struct bpsIOHandlerData {
|
||||
bpsIOHandlerData()
|
||||
: count(0), readfds(0), writefds(0), exceptfds(0)
|
||||
{
|
||||
}
|
||||
|
||||
int count;
|
||||
fd_set *readfds;
|
||||
fd_set *writefds;
|
||||
fd_set *exceptfds;
|
||||
};
|
||||
|
||||
static int bpsIOReadyDomain = -1;
|
||||
|
||||
static int bpsIOHandler(int fd, int io_events, void *data)
|
||||
{
|
||||
// decode callback payload
|
||||
bpsIOHandlerData *ioData = static_cast<bpsIOHandlerData*>(data);
|
||||
|
||||
// check if first file is ready
|
||||
bool firstReady = (ioData->count == 0);
|
||||
|
||||
// update ready state of file
|
||||
if (io_events & BPS_IO_INPUT) {
|
||||
FD_SET(fd, ioData->readfds);
|
||||
ioData->count++;
|
||||
}
|
||||
|
||||
if (io_events & BPS_IO_OUTPUT) {
|
||||
FD_SET(fd, ioData->writefds);
|
||||
ioData->count++;
|
||||
}
|
||||
|
||||
if (io_events & BPS_IO_EXCEPT) {
|
||||
FD_SET(fd, ioData->exceptfds);
|
||||
ioData->count++;
|
||||
}
|
||||
|
||||
// force bps_get_event() to return immediately by posting an event to ourselves;
|
||||
// but this only needs to happen once if multiple files become ready at the same time
|
||||
if (firstReady) {
|
||||
// create IO ready event
|
||||
bps_event_t *event;
|
||||
int result = bps_event_create(&event, bpsIOReadyDomain, 0, NULL, NULL);
|
||||
if (result != BPS_SUCCESS) {
|
||||
qWarning("QEventDispatcherBlackberryPrivate::QEventDispatcherBlackberry: bps_event_create() failed");
|
||||
return BPS_FAILURE;
|
||||
}
|
||||
|
||||
// post IO ready event to our thread
|
||||
result = bps_push_event(event);
|
||||
if (result != BPS_SUCCESS) {
|
||||
qWarning("QEventDispatcherBlackberryPrivate::QEventDispatcherBlackberry: bps_push_event() failed");
|
||||
bps_event_destroy(event);
|
||||
return BPS_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return BPS_SUCCESS;
|
||||
}
|
||||
|
||||
QEventDispatcherBlackberryPrivate::QEventDispatcherBlackberryPrivate()
|
||||
: ioData(new bpsIOHandlerData)
|
||||
{
|
||||
// prepare to use BPS
|
||||
int result = bps_initialize();
|
||||
if (result != BPS_SUCCESS)
|
||||
qFatal("QEventDispatcherBlackberryPrivate::QEventDispatcherBlackberry: bps_initialize() failed");
|
||||
|
||||
// get domain for IO ready events - ignoring race condition here for now
|
||||
if (bpsIOReadyDomain == -1) {
|
||||
bpsIOReadyDomain = bps_register_domain();
|
||||
if (bpsIOReadyDomain == -1)
|
||||
qWarning("QEventDispatcherBlackberryPrivate::QEventDispatcherBlackberry: bps_register_domain() failed");
|
||||
}
|
||||
|
||||
// \TODO Reinstate this when bps is fixed. See comment in select() below.
|
||||
// Register thread_pipe[0] with bps
|
||||
/*
|
||||
int io_events = BPS_IO_INPUT;
|
||||
result = bps_add_fd(thread_pipe[0], io_events, &bpsIOHandler, ioData.data());
|
||||
if (result != BPS_SUCCESS)
|
||||
qWarning() << Q_FUNC_INFO << "bps_add_fd() failed";
|
||||
*/
|
||||
}
|
||||
|
||||
QEventDispatcherBlackberryPrivate::~QEventDispatcherBlackberryPrivate()
|
||||
{
|
||||
// we're done using BPS
|
||||
bps_shutdown();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
QEventDispatcherBlackberry::QEventDispatcherBlackberry(QObject *parent)
|
||||
: QEventDispatcherUNIX(*new QEventDispatcherBlackberryPrivate, parent)
|
||||
{
|
||||
}
|
||||
|
||||
QEventDispatcherBlackberry::QEventDispatcherBlackberry(QEventDispatcherBlackberryPrivate &dd, QObject *parent)
|
||||
: QEventDispatcherUNIX(dd, parent)
|
||||
{
|
||||
}
|
||||
|
||||
QEventDispatcherBlackberry::~QEventDispatcherBlackberry()
|
||||
{
|
||||
}
|
||||
|
||||
void QEventDispatcherBlackberry::registerSocketNotifier(QSocketNotifier *notifier)
|
||||
{
|
||||
Q_ASSERT(notifier);
|
||||
|
||||
// Call the base Unix implementation. Needed to allow select() to be called correctly
|
||||
QEventDispatcherUNIX::registerSocketNotifier(notifier);
|
||||
|
||||
// Register the fd with bps
|
||||
int sockfd = notifier->socket();
|
||||
int type = notifier->type();
|
||||
|
||||
int io_events = 0;
|
||||
switch (type) {
|
||||
case QSocketNotifier::Read:
|
||||
io_events |= BPS_IO_INPUT;
|
||||
break;
|
||||
case QSocketNotifier::Write:
|
||||
io_events |= BPS_IO_OUTPUT;
|
||||
break;
|
||||
case QSocketNotifier::Exception:
|
||||
default:
|
||||
io_events |= BPS_IO_EXCEPT;
|
||||
break;
|
||||
}
|
||||
|
||||
Q_D(QEventDispatcherBlackberry);
|
||||
int result = bps_add_fd(sockfd, io_events, &bpsIOHandler, d->ioData.data());
|
||||
if (result != BPS_SUCCESS)
|
||||
qWarning() << Q_FUNC_INFO << "bps_add_fd() failed";
|
||||
}
|
||||
|
||||
void QEventDispatcherBlackberry::unregisterSocketNotifier(QSocketNotifier *notifier)
|
||||
{
|
||||
// Unregister the fd with bps
|
||||
int sockfd = notifier->socket();
|
||||
int result = bps_remove_fd(sockfd);
|
||||
if (result != BPS_SUCCESS)
|
||||
qWarning() << Q_FUNC_INFO << "bps_remove_fd() failed";
|
||||
|
||||
// Allow the base Unix implementation to unregister the fd too
|
||||
QEventDispatcherUNIX::unregisterSocketNotifier(notifier);
|
||||
}
|
||||
|
||||
int QEventDispatcherBlackberry::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
||||
timeval *timeout)
|
||||
{
|
||||
Q_UNUSED(nfds);
|
||||
|
||||
// prepare file sets for bps callback
|
||||
Q_D(QEventDispatcherBlackberry);
|
||||
d->ioData->count = 0;
|
||||
d->ioData->readfds = readfds;
|
||||
d->ioData->writefds = writefds;
|
||||
d->ioData->exceptfds = exceptfds;
|
||||
|
||||
// \TODO Remove this when bps is fixed
|
||||
//
|
||||
// Work around a bug in BPS with which if we register the thread_pipe[0] fd with bps in the
|
||||
// private class' ctor once only then we get spurious notifications that thread_pipe[0] is
|
||||
// ready for reading. The first time the notification is correct and the pipe is emptied in
|
||||
// the calling doSelect() function. The 2nd notification is an error and the resulting attempt
|
||||
// to read and call to wakeUps.testAndSetRelease(1, 0) fails as there has been no intervening
|
||||
// call to QEventDispatcherUNIX::wakeUp().
|
||||
//
|
||||
// Registering thread_pipe[0] here and unregistering it at the end of this call works around
|
||||
// this issue.
|
||||
int io_events = BPS_IO_INPUT;
|
||||
int result = bps_add_fd(d->thread_pipe[0], io_events, &bpsIOHandler, d->ioData.data());
|
||||
if (result != BPS_SUCCESS)
|
||||
qWarning() << Q_FUNC_INFO << "bps_add_fd() failed";
|
||||
|
||||
// reset all file sets
|
||||
if (readfds)
|
||||
FD_ZERO(readfds);
|
||||
|
||||
if (writefds)
|
||||
FD_ZERO(writefds);
|
||||
|
||||
if (exceptfds)
|
||||
FD_ZERO(exceptfds);
|
||||
|
||||
// convert timeout to milliseconds
|
||||
int timeout_ms = -1;
|
||||
if (timeout)
|
||||
timeout_ms = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000);
|
||||
|
||||
// wait for event or file to be ready
|
||||
bps_event_t *event = NULL;
|
||||
result = bps_get_event(&event, timeout_ms);
|
||||
if (result != BPS_SUCCESS)
|
||||
qWarning("QEventDispatcherBlackberry::select: bps_get_event() failed");
|
||||
|
||||
// pass all received events through filter - except IO ready events
|
||||
if (event && bps_event_get_domain(event) != bpsIOReadyDomain)
|
||||
filterEvent((void*)event);
|
||||
|
||||
// \TODO Remove this when bps is fixed (see comment above)
|
||||
result = bps_remove_fd(d->thread_pipe[0]);
|
||||
if (result != BPS_SUCCESS)
|
||||
qWarning() << Q_FUNC_INFO << "bps_remove_fd() failed";
|
||||
|
||||
// the number of bits set in the file sets
|
||||
return d->ioData->count;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
96
src/corelib/kernel/qeventdispatcher_blackberry_p.h
Normal file
96
src/corelib/kernel/qeventdispatcher_blackberry_p.h
Normal file
@ -0,0 +1,96 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Research In Motion
|
||||
** 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.
|
||||
**
|
||||
** 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 QEVENTDISPATCHER_BLACKBERRY_P_H
|
||||
#define QEVENTDISPATCHER_BLACKBERRY_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include "private/qeventdispatcher_unix_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QEventDispatcherBlackberryPrivate;
|
||||
|
||||
class Q_CORE_EXPORT QEventDispatcherBlackberry : public QEventDispatcherUNIX
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DECLARE_PRIVATE(QEventDispatcherBlackberry)
|
||||
|
||||
public:
|
||||
explicit QEventDispatcherBlackberry(QObject *parent = 0);
|
||||
~QEventDispatcherBlackberry();
|
||||
|
||||
void registerSocketNotifier(QSocketNotifier *notifier);
|
||||
void unregisterSocketNotifier(QSocketNotifier *notifier);
|
||||
|
||||
protected:
|
||||
QEventDispatcherBlackberry(QEventDispatcherBlackberryPrivate &dd, QObject *parent = 0);
|
||||
|
||||
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
||||
timeval *timeout);
|
||||
};
|
||||
|
||||
struct bpsIOHandlerData;
|
||||
|
||||
class Q_CORE_EXPORT QEventDispatcherBlackberryPrivate : public QEventDispatcherUNIXPrivate
|
||||
{
|
||||
Q_DECLARE_PUBLIC(QEventDispatcherBlackberry)
|
||||
|
||||
public:
|
||||
QEventDispatcherBlackberryPrivate();
|
||||
~QEventDispatcherBlackberryPrivate();
|
||||
|
||||
QScopedPointer<bpsIOHandlerData> ioData;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QEVENTDISPATCHER_BLACKBERRY_P_H
|
@ -44,11 +44,15 @@
|
||||
#include "qplatformdefs.h"
|
||||
|
||||
#include <private/qcoreapplication_p.h>
|
||||
#if !defined(QT_NO_GLIB)
|
||||
# include "../kernel/qeventdispatcher_glib_p.h"
|
||||
#endif
|
||||
|
||||
#include <private/qeventdispatcher_unix_p.h>
|
||||
#if defined(Q_OS_BLACKBERRY)
|
||||
# include <private/qeventdispatcher_blackberry_p.h>
|
||||
#else
|
||||
# if !defined(QT_NO_GLIB)
|
||||
# include "../kernel/qeventdispatcher_glib_p.h"
|
||||
# endif
|
||||
# include <private/qeventdispatcher_unix_p.h>
|
||||
#endif
|
||||
|
||||
#include "qthreadstorage.h"
|
||||
|
||||
@ -248,6 +252,9 @@ typedef void*(*QtThreadCallback)(void*);
|
||||
|
||||
void QThreadPrivate::createEventDispatcher(QThreadData *data)
|
||||
{
|
||||
#if defined(Q_OS_BLACKBERRY)
|
||||
data->eventDispatcher = new QEventDispatcherBlackberry;
|
||||
#else
|
||||
#if !defined(QT_NO_GLIB)
|
||||
if (qgetenv("QT_NO_GLIB").isEmpty()
|
||||
&& qgetenv("QT_NO_THREADED_GLIB").isEmpty()
|
||||
@ -256,6 +263,8 @@ void QThreadPrivate::createEventDispatcher(QThreadData *data)
|
||||
else
|
||||
#endif
|
||||
data->eventDispatcher = new QEventDispatcherUNIX;
|
||||
#endif
|
||||
|
||||
data->eventDispatcher->startingUp();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user