From 29518b04a619fdd7784e88eebe687fb87ae8a8b5 Mon Sep 17 00:00:00 2001 From: Kevin Krammer Date: Thu, 22 Mar 2012 13:54:00 +0100 Subject: 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 9dc86ac0f2d019f93665c1ae0e3c2cd33fd88bce Change-Id: I994dceed07312a3846737c8bea34cffa4ab408f1 Reviewed-by: Sean Harmer Reviewed-by: Robin Burchell --- src/plugins/platforms/qnx/qqnxvirtualkeyboard.cpp | 165 +++++++++++----------- src/plugins/platforms/qnx/qqnxvirtualkeyboard.h | 17 ++- 2 files changed, 92 insertions(+), 90 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/qnx/qqnxvirtualkeyboard.cpp b/src/plugins/platforms/qnx/qqnxvirtualkeyboard.cpp index 9d7fe92660..20c89d3e32 100644 --- a/src/plugins/platforms/qnx/qqnxvirtualkeyboard.cpp +++ b/src/plugins/platforms/qnx/qqnxvirtualkeyboard.cpp @@ -46,6 +46,8 @@ #include #include +#include +#include #include #include @@ -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. - ::close(m_fd); - } - - // Wait for the thread to die (should be immediate), then continue the cleanup. - wait(); + delete m_readNotifier; + m_readNotifier = 0; - if (m_fd) { + if (m_fd != -1) { + ::close(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; + if (nread < 0){ + connect(); // reconnect + return; + } - // nread is the real space necessary, not the amount read. - if (static_cast(nread) > ms_bufferSize - 1) { - qCritical("QQnxVirtualKeyboard: Keyboard buffer size too short; need %u.", nread + 1); - break; - } + // nread is the real space necessary, not the amount read. + if (static_cast(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); + 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); + 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"); + 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; } -#ifdef QQNXVIRTUALKEYBOARD_DEBUG - qDebug() << "QQNX: exiting keyboard thread"; -#endif - - if (m_decoder) - pps_decoder_cleanup(m_decoder); + 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() diff --git a/src/plugins/platforms/qnx/qqnxvirtualkeyboard.h b/src/plugins/platforms/qnx/qqnxvirtualkeyboard.h index 21b2e8736c..73a296fb9f 100644 --- a/src/plugins/platforms/qnx/qqnxvirtualkeyboard.h +++ b/src/plugins/platforms/qnx/qqnxvirtualkeyboard.h @@ -42,7 +42,7 @@ #ifndef VIRTUALKEYBOARD_H_ #define VIRTUALKEYBOARD_H_ -#include +#include #include #include #include @@ -52,10 +52,12 @@ #include #include +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; -- cgit v1.2.3