bool QQnxVirtualKeyboardBps::handleVirtualKeyboardEvent(bps_event_t *event)
{
    switch (bps_event_get_code(event)) {
    case VIRTUALKEYBOARD_EVENT_VISIBLE:
        qVirtualKeyboardDebug() << Q_FUNC_INFO << "EVENT VISIBLE: current visibility=" << isVisible();
        setVisible(true);
        break;

    case VIRTUALKEYBOARD_EVENT_HIDDEN:
        qVirtualKeyboardDebug() << Q_FUNC_INFO << "EVENT HIDDEN: current visibility=" << isVisible();
        setVisible(false);
        break;

    case VIRTUALKEYBOARD_EVENT_INFO: {
        const int newHeight = virtualkeyboard_event_get_height(event);
        qVirtualKeyboardDebug() << Q_FUNC_INFO << "EVENT INFO: current height=" << height() << "new height=" << newHeight;
        setHeight(newHeight);
        break;
    }

    default:
        qVirtualKeyboardDebug() << Q_FUNC_INFO << "Unhandled virtual keyboard event. code=" << bps_event_get_code(event);
        return false;
    }

    return true;
}
void QQnxVirtualKeyboardPps::ppsDataReady()
{
    ssize_t nread = qt_safe_read(m_fd, m_buffer, ms_bufferSize - 1);

    qVirtualKeyboardDebug() << Q_FUNC_INFO << "keyboardMessage size: " << nread;
    if (nread < 0){
        connect(); // reconnect
        return;
    }

    // We sometimes get spurious read notifications when no data is available.
    // Bail out early in this case
    if (nread == 0)
        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, 0);
#if defined(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]");
        return;
    }

    if (pps_decoder_get_string(m_decoder, "msg", &value) == PPS_DECODER_OK) {
        if (strcmp(value, "show") == 0)
            setVisible(true);
        else if (strcmp(value, "hide") == 0)
            setVisible(false);
        else if (strcmp(value, "info") == 0)
            handleKeyboardInfoMessage();
        else if (strcmp(value, "connect") == 0)
            qVirtualKeyboardDebug() << Q_FUNC_INFO << "Unhandled command 'connect'";
        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");
    }
}
bool QQnxVirtualKeyboardBps::handleLocaleEvent(bps_event_t *event)
{
    if (bps_event_get_code(event) == LOCALE_INFO) {
        const QString language = QString::fromLatin1(locale_event_get_language(event));
        const QString country  = QString::fromLatin1(locale_event_get_country(event));
        const QLocale newLocale(language + QLatin1Char('_') + country);

        qVirtualKeyboardDebug() << Q_FUNC_INFO << "current locale" << locale() << "new locale=" << newLocale;
        setLocale(newLocale);
        return true;
    }

    qVirtualKeyboardDebug() << Q_FUNC_INFO << "Unhandled locale event. code=" << bps_event_get_code(event);

    return false;
}
bool QQnxVirtualKeyboardPps::hideKeyboard()
{
    qVirtualKeyboardDebug() << Q_FUNC_INFO;

    if (m_fd == -1 && !connect())
        return false;

    pps_encoder_add_string(m_encoder, "msg", "hide");

    if (::write(m_fd, pps_encoder_buffer(m_encoder), pps_encoder_length(m_encoder)) == -1) {
        close();

        //Try again.
        if (connect()) {
            if (::write(m_fd, pps_encoder_buffer(m_encoder), pps_encoder_length(m_encoder)) == -1) {
                close();
                return false;
            }
        }
        else
            return false;
    }

    pps_encoder_reset(m_encoder);

    // Return true if no error occurs.  Sizing response will be triggered when confirmation of
    // the change arrives.
    return true;
}
bool QQnxVirtualKeyboardPps::showKeyboard()
{
    qVirtualKeyboardDebug() << Q_FUNC_INFO;

    // Try to connect.
    if (m_fd == -1 && !connect())
        return false;

    // NOTE:  This must be done everytime the keyboard is shown even if there is no change because
    // hiding the keyboard wipes the setting.
    applyKeyboardModeOptions(keyboardMode());

    if (isVisible())
        return true;

    pps_encoder_reset(m_encoder);

    // Send the show message.
    pps_encoder_add_string(m_encoder, "msg", "show");

    if (::write(m_fd, pps_encoder_buffer(m_encoder), pps_encoder_length(m_encoder)) == -1) {
        close();
        return false;
    }

    pps_encoder_reset(m_encoder);

    // Return true if no error occurs.  Sizing response will be triggered when confirmation of
    // the change arrives.
    return true;
}
void QQnxVirtualKeyboardPps::handleKeyboardInfoMessage()
{
    int newHeight = 0;
    const char *value;

    if (pps_decoder_push(m_decoder, "dat") != PPS_DECODER_OK) {
        qCritical("QQnxVirtualKeyboard: Keyboard PPS dat object not found");
        return;
    }
    if (pps_decoder_get_int(m_decoder, "size", &newHeight) != PPS_DECODER_OK) {
        qCritical("QQnxVirtualKeyboard: Keyboard PPS size field not found");
        return;
    }
    if (pps_decoder_push(m_decoder, "locale") != PPS_DECODER_OK) {
        qCritical("QQnxVirtualKeyboard: Keyboard PPS locale object not found");
        return;
    }
    if (pps_decoder_get_string(m_decoder, "languageId", &value) != PPS_DECODER_OK) {
        qCritical("QQnxVirtualKeyboard: Keyboard PPS languageId field not found");
        return;
    }
    const QString languageId = QString::fromLatin1(value);
    if (pps_decoder_get_string(m_decoder, "countryId", &value) != PPS_DECODER_OK) {
        qCritical("QQnxVirtualKeyboard: Keyboard PPS size countryId not found");
        return;
    }
    const QString countryId = QString::fromLatin1(value);

    setHeight(newHeight);

    const QLocale locale = QLocale(languageId + QLatin1Char('_') + countryId);
    setLocale(locale);

    qVirtualKeyboardDebug() << Q_FUNC_INFO << "size=" << newHeight << "locale=" << locale;
}
bool QQnxVirtualKeyboardPps::connect()
{
    close();

    m_encoder = new pps_encoder_t;
    m_decoder = new pps_decoder_t;

    pps_encoder_initialize(m_encoder, false);
    pps_decoder_initialize(m_decoder, 0);

    errno = 0;
    m_fd = ::open(ms_PPSPath, O_RDWR);
    if (m_fd == -1)
    {
        qVirtualKeyboardDebug() << Q_FUNC_INFO << ": Unable to open" << ms_PPSPath
                                               << ":" << strerror(errno);
        close();
        return false;
    }

    m_buffer = new char[ms_bufferSize];
    if (!m_buffer) {
        qCritical("QQnxVirtualKeyboard: Unable to allocate buffer of %d bytes. "
                  "Size is unavailable.",  ms_bufferSize);
        return false;
    }

    if (!queryPPSInfo())
        return false;

    m_readNotifier = new QSocketNotifier(m_fd, QSocketNotifier::Read);
    QObject::connect(m_readNotifier, SIGNAL(activated(int)), this, SLOT(ppsDataReady()));

    return true;
}
void QQnxVirtualKeyboardBps::applyKeyboardOptions()
{
    virtualkeyboard_layout_t layout = keyboardLayout();
    virtualkeyboard_enter_t enter = enterKey();

    qVirtualKeyboardDebug() << Q_FUNC_INFO << "mode=" << keyboardMode() << "enterKey=" << enterKeyType();

    virtualkeyboard_change_options(layout, enter);
}
bool QQnxVirtualKeyboardBps::showKeyboard()
{
    qVirtualKeyboardDebug() << Q_FUNC_INFO << "current visibility=" << isVisible();

    // They keyboard's mode is global between applications, we have to set it each time
    if ( !isVisible() )
        applyKeyboardOptions();

    virtualkeyboard_show();
    return true;
}
bool QQnxVirtualKeyboardPps::hideKeyboard()
{
    qVirtualKeyboardDebug() << Q_FUNC_INFO;

    if (!prepareToSend())
        return false;

    pps_encoder_add_string(m_encoder, "msg", "hide");

    return writeCurrentPPSEncoder();
}
void QQnxVirtualKeyboardPps::handleKeyboardInfoMessage()
{
    int newHeight = 0;

    if (pps_decoder_push(m_decoder, "dat") != PPS_DECODER_OK) {
        qCritical("QQnxVirtualKeyboard: Keyboard PPS dat object not found");
        return;
    }
    if (pps_decoder_get_int(m_decoder, "size", &newHeight) != PPS_DECODER_OK) {
        qCritical("QQnxVirtualKeyboard: Keyboard PPS size field not found");
        return;
    }
    setHeight(newHeight);

    qVirtualKeyboardDebug() << Q_FUNC_INFO << "size=" << newHeight;
}
bool QQnxVirtualKeyboardPps::showKeyboard()
{
    qVirtualKeyboardDebug() << Q_FUNC_INFO;

    if (!prepareToSend())
        return false;

    // NOTE:  This must be done everytime the keyboard is shown even if there is no change because
    // hiding the keyboard wipes the setting.
    applyKeyboardOptions();

    if (isVisible())
        return true;

    pps_encoder_reset(m_encoder);

    // Send the show message.
    pps_encoder_add_string(m_encoder, "msg", "show");

    return writeCurrentPPSEncoder();
}
void QQnxVirtualKeyboardPps::handleKeyboardInfoMessage()
{
    int newHeight = 0;
    const char *value;

    if (pps_decoder_push(m_decoder, "dat") != PPS_DECODER_OK) {
        qCritical("QQnxVirtualKeyboard: Keyboard PPS dat object not found");
        return;
    }
    if (pps_decoder_get_int(m_decoder, "size", &newHeight) != PPS_DECODER_OK) {
        qCritical("QQnxVirtualKeyboard: Keyboard PPS size field not found");
        return;
    }
    if (pps_decoder_push(m_decoder, "locale") != PPS_DECODER_OK) {
        qCritical("QQnxVirtualKeyboard: Keyboard PPS locale object not found");
        return;
    }
    if (pps_decoder_get_string(m_decoder, "languageId", &value) != PPS_DECODER_OK) {
        qCritical("QQnxVirtualKeyboard: Keyboard PPS languageId field not found");
        return;
    }
    const QString languageId = QString::fromLatin1(value);
    if (pps_decoder_get_string(m_decoder, "countryId", &value) != PPS_DECODER_OK) {
        qCritical("QQnxVirtualKeyboard: Keyboard PPS size countryId not found");
        return;
    }
    const QString countryId = QString::fromLatin1(value);

    // HUGE hack, should be removed ASAP.
    newHeight -= KEYBOARD_SHADOW_HEIGHT; // We want to ignore the 8 pixel shadow above the keyboard. (PR 88400)

    setHeight(newHeight);

    const QLocale locale = QLocale(languageId + QLatin1Char('_') + countryId);
    setLocale(locale);

    qVirtualKeyboardDebug() << Q_FUNC_INFO << "size=" << newHeight << "locale=" << locale;
}
bool QQnxVirtualKeyboardBps::hideKeyboard()
{
    qVirtualKeyboardDebug() << Q_FUNC_INFO << "current visibility=" << isVisible();
    virtualkeyboard_hide();
    return true;
}
void QQnxVirtualKeyboardPps::start()
{
    qVirtualKeyboardDebug() << Q_FUNC_INFO << "starting keyboard event processing";
    if (!connect())
        return;
}