123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321 | // Copyright (C) 2011 - 2012 Research In Motion// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only#include"qqnxvirtualkeyboardpps.h"#include"qqnxscreen.h"#include <QtCore/QDebug>#include <QtCore/QSocketNotifier>#include <QtCore/private/qcore_unix_p.h>#include <errno.h>#include <fcntl.h>#include <stdlib.h>#include <string.h>#include <sys/iomsg.h>#include <sys/pps.h>#include <sys/stat.h>#include <sys/types.h>#include <unistd.h> QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcQpaQnxVirtualKeyboard,"qt.qpa.qnx.virtualkeyboard");const char*QQnxVirtualKeyboardPps::ms_PPSPath ="/pps/services/input/control";const size_tQQnxVirtualKeyboardPps::ms_bufferSize =2048;QQnxVirtualKeyboardPps::QQnxVirtualKeyboardPps():m_encoder(0),m_decoder(0),m_buffer(0),m_fd(-1),m_readNotifier(0){}QQnxVirtualKeyboardPps::~QQnxVirtualKeyboardPps(){close();}voidQQnxVirtualKeyboardPps::start(){qCDebug(lcQpaQnxVirtualKeyboard) <<"Starting keyboard event processing";if(!connect())return;}voidQQnxVirtualKeyboardPps::close(){delete m_readNotifier; m_readNotifier =0;if(m_fd != -1) {::close(m_fd); m_fd = -1;}if(m_decoder) {pps_decoder_cleanup(m_decoder);delete m_decoder; m_decoder =0;}if(m_encoder) {pps_encoder_cleanup(m_encoder);delete m_encoder; m_encoder =0;}delete[] m_buffer; m_buffer =0;}boolQQnxVirtualKeyboardPps::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){qCDebug(lcQpaQnxVirtualKeyboard) <<"Unable to open"<< ms_PPSPath <<':'<<strerror(errno);close();return false;} m_buffer =newchar[ms_bufferSize];if(Q_UNLIKELY(!m_buffer)) {qCritical("QQnxVirtualKeyboard: Unable to allocate buffer of %zu bytes. ""Size is unavailable.", ms_bufferSize);return false;}if(!queryPPSInfo())return false; m_readNotifier =newQSocketNotifier(m_fd,QSocketNotifier::Read);QObject::connect(m_readNotifier,SIGNAL(activated(QSocketDescriptor)),this,SLOT(ppsDataReady()));return true;}boolQQnxVirtualKeyboardPps::queryPPSInfo(){if(!prepareToSend())return false;// Request info, requires id to regenerate res message.pps_encoder_add_string(m_encoder,"msg","info");pps_encoder_add_string(m_encoder,"id","1");returnwriteCurrentPPSEncoder();}voidQQnxVirtualKeyboardPps::ppsDataReady(){ qint64 nread =qt_safe_read(m_fd, m_buffer, ms_bufferSize -1);qCDebug(lcQpaQnxVirtualKeyboard,"keyboardMessage size: %lld", nread);if(nread <0){connect();// reconnectreturn;}// We sometimes get spurious read notifications when no data is available.// Bail out early in this caseif(nread ==0)return;// nread is the real space necessary, not the amount read.if(Q_UNLIKELY(static_cast<size_t>(nread) > ms_bufferSize -1)) {qCritical("QQnxVirtualKeyboard: Keyboard buffer size too short; need %lld.", nread +1);connect();// reconnectreturn;} 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);#endifconst char*value;if(Q_UNLIKELY(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)qCDebug(lcQpaQnxVirtualKeyboard,"Unhandled command 'connect'");elseqCritical("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();elseqCritical("QQnxVirtualKeyboard: Unexpected keyboard PPS res value: %s", value ? value :"[null]");}else{qCritical("QQnxVirtualKeyboard: Unexpected keyboard PPS message type");}}voidQQnxVirtualKeyboardPps::handleKeyboardInfoMessage(){int newHeight =0;if(Q_UNLIKELY(pps_decoder_push(m_decoder,"dat") != PPS_DECODER_OK)) {qCritical("QQnxVirtualKeyboard: Keyboard PPS dat object not found");return;}if(Q_UNLIKELY(pps_decoder_get_int(m_decoder,"size", &newHeight) != PPS_DECODER_OK)) {qCritical("QQnxVirtualKeyboard: Keyboard PPS size field not found");return;}setHeight(newHeight);qCDebug(lcQpaQnxVirtualKeyboard,"size=%d", newHeight);}boolQQnxVirtualKeyboardPps::showKeyboard(){qCDebug(lcQpaQnxVirtualKeyboard) << Q_FUNC_INFO;if(!prepareToSend())return false;// NOTE: This must be done every time 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");returnwriteCurrentPPSEncoder();}boolQQnxVirtualKeyboardPps::hideKeyboard(){qCDebug(lcQpaQnxVirtualKeyboard) << Q_FUNC_INFO;if(!prepareToSend())return false;pps_encoder_add_string(m_encoder,"msg","hide");returnwriteCurrentPPSEncoder();}boolQQnxVirtualKeyboardPps::prepareToSend(){if(m_fd == -1&& !connect())return false;pps_encoder_reset(m_encoder);return true;}boolQQnxVirtualKeyboardPps::writeCurrentPPSEncoder(){if(::write(m_fd,pps_encoder_buffer(m_encoder),pps_encoder_length(m_encoder)) == -1) {close();return false;}return true;}voidQQnxVirtualKeyboardPps::applyKeyboardOptions(){if(!prepareToSend())return;// Send the options message.pps_encoder_add_string(m_encoder,"msg","options");pps_encoder_start_object(m_encoder,"dat");pps_encoder_add_string(m_encoder,"enter",enterKeyTypeStr());pps_encoder_add_string(m_encoder,"type",keyboardModeStr());pps_encoder_end_object(m_encoder);writeCurrentPPSEncoder();}const char*QQnxVirtualKeyboardPps::keyboardModeStr()const{switch(keyboardMode()) {case Url:return"url";case Email:return"email";case Web:return"web";case NumPunc:return"num_punc";case Number:return"number";case Symbol:return"symbol";case Phone:return"phone";case Pin:return"pin";case Password:return"password";case Alphanumeric:return"alphanumeric";case Default:return"default";}return"";}const char*QQnxVirtualKeyboardPps::enterKeyTypeStr()const{switch(enterKeyType()) {case DefaultReturn:return"enter.default";case Connect:return"enter.connect";case Done:return"enter.done";case Go:return"enter.go";case Join:return"enter.join";case Next:return"enter.next";case Search:return"enter.search";case Send:return"enter.send";case Submit:return"enter.submit";}return"";} QT_END_NAMESPACE
|