Make QNX virtual keyboard handling main event loop driven
Refactor from polling in an endless loop running in a separate thread
to using a QSocketNotifier working on the main thread.
Similar to "de-threading" of the navigator event handling in
9dc86ac0f2
Change-Id: I994dceed07312a3846737c8bea34cffa4ab408f1
Reviewed-by: Sean Harmer <sh@theharmers.co.uk>
Reviewed-by: Robin Burchell <robin+qt@viroteck.net>
bb10
parent
1a414cbc26
commit
29518b04a6
|
|
@ -46,6 +46,8 @@
|
|||
#include <QtGui/QPlatformWindow>
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QSocketNotifier>
|
||||
#include <QtCore/private/qcore_unix_p.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
|
@ -65,17 +67,17 @@ static QQnxVirtualKeyboard *s_instance = 0;
|
|||
// Huge hack for keyboard shadow (see QNX PR 88400). Should be removed ASAP.
|
||||
#define KEYBOARD_SHADOW_HEIGHT 8
|
||||
|
||||
QQnxVirtualKeyboard::QQnxVirtualKeyboard() :
|
||||
m_encoder(NULL),
|
||||
m_decoder(NULL),
|
||||
m_buffer(NULL),
|
||||
m_height(0),
|
||||
m_fd(-1),
|
||||
m_keyboardMode(Default),
|
||||
m_visible(false),
|
||||
m_locale(QLatin1String("en_US"))
|
||||
QQnxVirtualKeyboard::QQnxVirtualKeyboard()
|
||||
: m_encoder(0),
|
||||
m_decoder(0),
|
||||
m_buffer(0),
|
||||
m_height(0),
|
||||
m_fd(-1),
|
||||
m_keyboardMode(Default),
|
||||
m_visible(false),
|
||||
m_locale(QLatin1String("en_US")),
|
||||
m_readNotifier(0)
|
||||
{
|
||||
connect();
|
||||
}
|
||||
|
||||
QQnxVirtualKeyboard::~QQnxVirtualKeyboard()
|
||||
|
|
@ -88,12 +90,24 @@ QQnxVirtualKeyboard& QQnxVirtualKeyboard::instance()
|
|||
{
|
||||
if (!s_instance) {
|
||||
s_instance = new QQnxVirtualKeyboard();
|
||||
s_instance->start();
|
||||
|
||||
// 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(s_instance, "start", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
return *s_instance;
|
||||
}
|
||||
|
||||
void QQnxVirtualKeyboard::start()
|
||||
{
|
||||
#ifdef QQNXVIRTUALKEYBOARD_DEBUG
|
||||
qDebug() << "QQNX: starting keyboard event processing";
|
||||
#endif
|
||||
if (!connect())
|
||||
return;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void QQnxVirtualKeyboard::destroy()
|
||||
{
|
||||
|
|
@ -105,35 +119,28 @@ void QQnxVirtualKeyboard::destroy()
|
|||
|
||||
void QQnxVirtualKeyboard::close()
|
||||
{
|
||||
if (m_fd) {
|
||||
// any reads will fail after we close the fd, which is basically what we want.
|
||||
delete m_readNotifier;
|
||||
m_readNotifier = 0;
|
||||
|
||||
if (m_fd != -1) {
|
||||
::close(m_fd);
|
||||
}
|
||||
|
||||
// Wait for the thread to die (should be immediate), then continue the cleanup.
|
||||
wait();
|
||||
|
||||
if (m_fd) {
|
||||
m_fd = -1;
|
||||
}
|
||||
|
||||
|
||||
if (m_decoder)
|
||||
{
|
||||
if (m_decoder) {
|
||||
pps_decoder_cleanup(m_decoder);
|
||||
delete m_decoder;
|
||||
m_decoder = NULL;
|
||||
m_decoder = 0;
|
||||
}
|
||||
|
||||
if (m_encoder)
|
||||
{
|
||||
if (m_encoder) {
|
||||
pps_encoder_cleanup(m_encoder);
|
||||
delete m_encoder;
|
||||
m_encoder = NULL;
|
||||
m_encoder = 0;
|
||||
}
|
||||
|
||||
delete [] m_buffer;
|
||||
m_buffer = NULL;
|
||||
m_buffer = 0;
|
||||
}
|
||||
|
||||
bool QQnxVirtualKeyboard::connect()
|
||||
|
|
@ -165,7 +172,8 @@ bool QQnxVirtualKeyboard::connect()
|
|||
if (!queryPPSInfo())
|
||||
return false;
|
||||
|
||||
start();
|
||||
m_readNotifier = new QSocketNotifier(m_fd, QSocketNotifier::Read);
|
||||
QObject::connect(m_readNotifier, SIGNAL(activated(int)), this, SLOT(ppsDataReady()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -192,74 +200,63 @@ void QQnxVirtualKeyboard::notifyClientActiveStateChange(bool active)
|
|||
hideKeyboard();
|
||||
}
|
||||
|
||||
void QQnxVirtualKeyboard::run()
|
||||
{
|
||||
ppsDataReady();
|
||||
}
|
||||
|
||||
void QQnxVirtualKeyboard::ppsDataReady()
|
||||
{
|
||||
while (1) {
|
||||
ssize_t nread = read(m_fd, m_buffer, ms_bufferSize - 1);
|
||||
ssize_t nread = qt_safe_read(m_fd, m_buffer, ms_bufferSize - 1);
|
||||
|
||||
#ifdef QQNXVIRTUALKEYBOARD_DEBUG
|
||||
qDebug() << "QQNX: keyboardMessage size: " << nread;
|
||||
qDebug() << "QQNX: keyboardMessage size: " << nread;
|
||||
#endif
|
||||
if (nread < 0)
|
||||
break;
|
||||
|
||||
// nread is the real space necessary, not the amount read.
|
||||
if (static_cast<size_t>(nread) > ms_bufferSize - 1) {
|
||||
qCritical("QQnxVirtualKeyboard: Keyboard buffer size too short; need %u.", nread + 1);
|
||||
break;
|
||||
}
|
||||
|
||||
m_buffer[nread] = 0;
|
||||
pps_decoder_parse_pps_str(m_decoder, m_buffer);
|
||||
pps_decoder_push(m_decoder, NULL);
|
||||
#ifdef QQNXVIRTUALKEYBOARD_DEBUG
|
||||
pps_decoder_dump_tree(m_decoder, stderr);
|
||||
#endif
|
||||
|
||||
const char *value;
|
||||
if (pps_decoder_get_string(m_decoder, "error", &value) == PPS_DECODER_OK) {
|
||||
qCritical("QQnxVirtualKeyboard: Keyboard PPS decoder error: %s", value ? value : "[null]");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pps_decoder_get_string(m_decoder, "msg", &value) == PPS_DECODER_OK) {
|
||||
if (strcmp(value, "show") == 0) {
|
||||
const bool oldVisible = m_visible;
|
||||
m_visible = true;
|
||||
handleKeyboardStateChangeMessage(true);
|
||||
if (oldVisible != m_visible)
|
||||
emit visibilityChanged(m_visible);
|
||||
} else if (strcmp(value, "hide") == 0) {
|
||||
const bool oldVisible = m_visible;
|
||||
m_visible = false;
|
||||
handleKeyboardStateChangeMessage(false);
|
||||
if (oldVisible != m_visible)
|
||||
emit visibilityChanged(m_visible);
|
||||
} else if (strcmp(value, "info") == 0)
|
||||
handleKeyboardInfoMessage();
|
||||
else if (strcmp(value, "connect") == 0) { }
|
||||
else
|
||||
qCritical("QQnxVirtualKeyboard: Unexpected keyboard PPS msg value: %s", value ? value : "[null]");
|
||||
} else if (pps_decoder_get_string(m_decoder, "res", &value) == PPS_DECODER_OK) {
|
||||
if (strcmp(value, "info") == 0)
|
||||
handleKeyboardInfoMessage();
|
||||
else
|
||||
qCritical("QQnxVirtualKeyboard: Unexpected keyboard PPS res value: %s", value ? value : "[null]");
|
||||
} else
|
||||
qCritical("QQnxVirtualKeyboard: Unexpected keyboard PPS message type");
|
||||
if (nread < 0){
|
||||
connect(); // reconnect
|
||||
return;
|
||||
}
|
||||
|
||||
// nread is the real space necessary, not the amount read.
|
||||
if (static_cast<size_t>(nread) > ms_bufferSize - 1) {
|
||||
qCritical("QQnxVirtualKeyboard: Keyboard buffer size too short; need %u.", nread + 1);
|
||||
connect(); // reconnect
|
||||
return;
|
||||
}
|
||||
|
||||
m_buffer[nread] = 0;
|
||||
pps_decoder_parse_pps_str(m_decoder, m_buffer);
|
||||
pps_decoder_push(m_decoder, NULL);
|
||||
#ifdef QQNXVIRTUALKEYBOARD_DEBUG
|
||||
qDebug() << "QQNX: exiting keyboard thread";
|
||||
pps_decoder_dump_tree(m_decoder, stderr);
|
||||
#endif
|
||||
|
||||
if (m_decoder)
|
||||
pps_decoder_cleanup(m_decoder);
|
||||
const char *value;
|
||||
if (pps_decoder_get_string(m_decoder, "error", &value) == PPS_DECODER_OK) {
|
||||
qCritical("QQnxVirtualKeyboard: Keyboard PPS decoder error: %s", value ? value : "[null]");
|
||||
return;
|
||||
}
|
||||
|
||||
if (pps_decoder_get_string(m_decoder, "msg", &value) == PPS_DECODER_OK) {
|
||||
if (strcmp(value, "show") == 0) {
|
||||
const bool oldVisible = m_visible;
|
||||
m_visible = true;
|
||||
handleKeyboardStateChangeMessage(true);
|
||||
if (oldVisible != m_visible)
|
||||
emit visibilityChanged(m_visible);
|
||||
} else if (strcmp(value, "hide") == 0) {
|
||||
const bool oldVisible = m_visible;
|
||||
m_visible = false;
|
||||
handleKeyboardStateChangeMessage(false);
|
||||
if (oldVisible != m_visible)
|
||||
emit visibilityChanged(m_visible);
|
||||
} else if (strcmp(value, "info") == 0)
|
||||
handleKeyboardInfoMessage();
|
||||
else if (strcmp(value, "connect") == 0) { }
|
||||
else
|
||||
qCritical("QQnxVirtualKeyboard: Unexpected keyboard PPS msg value: %s", value ? value : "[null]");
|
||||
} else if (pps_decoder_get_string(m_decoder, "res", &value) == PPS_DECODER_OK) {
|
||||
if (strcmp(value, "info") == 0)
|
||||
handleKeyboardInfoMessage();
|
||||
else
|
||||
qCritical("QQnxVirtualKeyboard: Unexpected keyboard PPS res value: %s", value ? value : "[null]");
|
||||
} else
|
||||
qCritical("QQnxVirtualKeyboard: Unexpected keyboard PPS message type");
|
||||
}
|
||||
|
||||
void QQnxVirtualKeyboard::handleKeyboardInfoMessage()
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@
|
|||
#ifndef VIRTUALKEYBOARD_H_
|
||||
#define VIRTUALKEYBOARD_H_
|
||||
|
||||
#include <QtCore/QThread>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QLocale>
|
||||
#include <QtGui/QPlatformScreen>
|
||||
#include <QtGui/QWindowSystemInterface>
|
||||
|
|
@ -52,10 +52,12 @@
|
|||
#include <string>
|
||||
#include <sys/pps.h>
|
||||
|
||||
class QSocketNotifier;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
/* Shamelessly copied from the browser - this should be rewritten once we have a proper PPS wrapper class */
|
||||
class QQnxVirtualKeyboard : public QThread
|
||||
class QQnxVirtualKeyboard : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
|
@ -83,10 +85,16 @@ public:
|
|||
bool isVisible() const { return m_visible; }
|
||||
QLocale locale() const { return m_locale; }
|
||||
|
||||
public Q_SLOTS:
|
||||
void start();
|
||||
|
||||
Q_SIGNALS:
|
||||
void localeChanged(const QLocale &locale);
|
||||
void visibilityChanged(bool visible);
|
||||
|
||||
private Q_SLOTS:
|
||||
void ppsDataReady();
|
||||
|
||||
private:
|
||||
QQnxVirtualKeyboard();
|
||||
virtual ~QQnxVirtualKeyboard();
|
||||
|
|
@ -94,7 +102,6 @@ private:
|
|||
// Will be called internally if needed.
|
||||
bool connect();
|
||||
void close();
|
||||
void ppsDataReady();
|
||||
bool queryPPSInfo();
|
||||
void handleKeyboardInfoMessage();
|
||||
void handleKeyboardStateChangeMessage(bool visible);
|
||||
|
|
@ -110,9 +117,6 @@ private:
|
|||
void addPhoneModeOptions();
|
||||
void addPinModeOptions();
|
||||
|
||||
// QThread overrides
|
||||
virtual void run();
|
||||
|
||||
pps_encoder_t *m_encoder;
|
||||
pps_decoder_t *m_decoder;
|
||||
char *m_buffer;
|
||||
|
|
@ -121,6 +125,7 @@ private:
|
|||
KeyboardMode m_keyboardMode;
|
||||
bool m_visible;
|
||||
QLocale m_locale;
|
||||
QSocketNotifier *m_readNotifier;
|
||||
|
||||
// Path to keyboardManager in PPS.
|
||||
static const char *ms_PPSPath;
|
||||
|
|
|
|||
Loading…
Reference in New Issue