Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qqnxvirtualkeyboardpps.cpp
Go to the documentation of this file.
1// Copyright (C) 2011 - 2012 Research In Motion
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5#include "qqnxscreen.h"
6
7#include <QtCore/QDebug>
8#include <QtCore/QSocketNotifier>
9#include <QtCore/private/qcore_unix_p.h>
10
11#include <errno.h>
12#include <fcntl.h>
13#include <stdlib.h>
14#include <string.h>
15#include <sys/iomsg.h>
16#include <sys/pps.h>
17#include <sys/stat.h>
18#include <sys/types.h>
19#include <unistd.h>
20
22
23Q_LOGGING_CATEGORY(lcQpaQnxVirtualKeyboard, "qt.qpa.qnx.virtualkeyboard");
24
25const char *QQnxVirtualKeyboardPps::ms_PPSPath = "/pps/services/input/control";
26const size_t QQnxVirtualKeyboardPps::ms_bufferSize = 2048;
27
29 : m_encoder(0),
30 m_decoder(0),
31 m_buffer(0),
32 m_fd(-1),
33 m_readNotifier(0)
34{
35}
36
41
43{
44 qCDebug(lcQpaQnxVirtualKeyboard) << "Starting keyboard event processing";
45 if (!connect())
46 return;
47}
48
49void QQnxVirtualKeyboardPps::close()
50{
51 delete m_readNotifier;
52 m_readNotifier = 0;
53
54 if (m_fd != -1) {
55 ::close(m_fd);
56 m_fd = -1;
57 }
58
59 if (m_decoder) {
60 pps_decoder_cleanup(m_decoder);
61 delete m_decoder;
62 m_decoder = 0;
63 }
64
65 if (m_encoder) {
66 pps_encoder_cleanup(m_encoder);
67 delete m_encoder;
68 m_encoder = 0;
69 }
70
71 delete [] m_buffer;
72 m_buffer = 0;
73}
74
75bool QQnxVirtualKeyboardPps::connect()
76{
77 close();
78
79 m_encoder = new pps_encoder_t;
80 m_decoder = new pps_decoder_t;
81
82 pps_encoder_initialize(m_encoder, false);
83 pps_decoder_initialize(m_decoder, 0);
84
85 errno = 0;
86 m_fd = ::open(ms_PPSPath, O_RDWR);
87 if (m_fd == -1)
88 {
89 qCDebug(lcQpaQnxVirtualKeyboard) << "Unable to open" << ms_PPSPath
90 << ':' << strerror(errno);
91 close();
92 return false;
93 }
94
95 m_buffer = new char[ms_bufferSize];
96 if (Q_UNLIKELY(!m_buffer)) {
97 qCritical("QQnxVirtualKeyboard: Unable to allocate buffer of %zu bytes. "
98 "Size is unavailable.", ms_bufferSize);
99 return false;
100 }
101
102 if (!queryPPSInfo())
103 return false;
104
105 m_readNotifier = new QSocketNotifier(m_fd, QSocketNotifier::Read);
106 QObject::connect(m_readNotifier, SIGNAL(activated(QSocketDescriptor)), this, SLOT(ppsDataReady()));
107
108 return true;
109}
110
111bool QQnxVirtualKeyboardPps::queryPPSInfo()
112{
113 if (!prepareToSend())
114 return false;
115
116 // Request info, requires id to regenerate res message.
117 pps_encoder_add_string(m_encoder, "msg", "info");
118 pps_encoder_add_string(m_encoder, "id", "1");
119
120 return writeCurrentPPSEncoder();
121}
122
123void QQnxVirtualKeyboardPps::ppsDataReady()
124{
125 qint64 nread = qt_safe_read(m_fd, m_buffer, ms_bufferSize - 1);
126
127 qCDebug(lcQpaQnxVirtualKeyboard, "keyboardMessage size: %lld", nread);
128 if (nread < 0){
129 connect(); // reconnect
130 return;
131 }
132
133 // We sometimes get spurious read notifications when no data is available.
134 // Bail out early in this case
135 if (nread == 0)
136 return;
137
138 // nread is the real space necessary, not the amount read.
139 if (Q_UNLIKELY(static_cast<size_t>(nread) > ms_bufferSize - 1)) {
140 qCritical("QQnxVirtualKeyboard: Keyboard buffer size too short; need %lld.", nread + 1);
141 connect(); // reconnect
142 return;
143 }
144
145 m_buffer[nread] = 0;
146 pps_decoder_parse_pps_str(m_decoder, m_buffer);
147 pps_decoder_push(m_decoder, 0);
148#if defined(QQNXVIRTUALKEYBOARD_DEBUG)
149 pps_decoder_dump_tree(m_decoder, stderr);
150#endif
151
152 const char *value;
153 if (Q_UNLIKELY(pps_decoder_get_string(m_decoder, "error", &value) == PPS_DECODER_OK)) {
154 qCritical("QQnxVirtualKeyboard: Keyboard PPS decoder error: %s", value ? value : "[null]");
155 return;
156 }
157
158 if (pps_decoder_get_string(m_decoder, "msg", &value) == PPS_DECODER_OK) {
159 if (strcmp(value, "show") == 0)
160 setVisible(true);
161 else if (strcmp(value, "hide") == 0)
162 setVisible(false);
163 else if (strcmp(value, "info") == 0)
164 handleKeyboardInfoMessage();
165 else if (strcmp(value, "connect") == 0)
166 qCDebug(lcQpaQnxVirtualKeyboard, "Unhandled command 'connect'");
167 else
168 qCritical("QQnxVirtualKeyboard: Unexpected keyboard PPS msg value: %s", value ? value : "[null]");
169 } else if (pps_decoder_get_string(m_decoder, "res", &value) == PPS_DECODER_OK) {
170 if (strcmp(value, "info") == 0)
171 handleKeyboardInfoMessage();
172 else
173 qCritical("QQnxVirtualKeyboard: Unexpected keyboard PPS res value: %s", value ? value : "[null]");
174 } else {
175 qCritical("QQnxVirtualKeyboard: Unexpected keyboard PPS message type");
176 }
177}
178
179void QQnxVirtualKeyboardPps::handleKeyboardInfoMessage()
180{
181 int newHeight = 0;
182
183 if (Q_UNLIKELY(pps_decoder_push(m_decoder, "dat") != PPS_DECODER_OK)) {
184 qCritical("QQnxVirtualKeyboard: Keyboard PPS dat object not found");
185 return;
186 }
187 if (Q_UNLIKELY(pps_decoder_get_int(m_decoder, "size", &newHeight) != PPS_DECODER_OK)) {
188 qCritical("QQnxVirtualKeyboard: Keyboard PPS size field not found");
189 return;
190 }
191 setHeight(newHeight);
192
193 qCDebug(lcQpaQnxVirtualKeyboard, "size=%d", newHeight);
194}
195
197{
198 qCDebug(lcQpaQnxVirtualKeyboard) << Q_FUNC_INFO;
199
200 if (!prepareToSend())
201 return false;
202
203 // NOTE: This must be done every time the keyboard is shown even if there is no change because
204 // hiding the keyboard wipes the setting.
206
207 if (isVisible())
208 return true;
209
210 pps_encoder_reset(m_encoder);
211
212 // Send the show message.
213 pps_encoder_add_string(m_encoder, "msg", "show");
214
215 return writeCurrentPPSEncoder();
216}
217
219{
220 qCDebug(lcQpaQnxVirtualKeyboard) << Q_FUNC_INFO;
221
222 if (!prepareToSend())
223 return false;
224
225 pps_encoder_add_string(m_encoder, "msg", "hide");
226
227 return writeCurrentPPSEncoder();
228}
229
230bool QQnxVirtualKeyboardPps::prepareToSend()
231{
232 if (m_fd == -1 && !connect())
233 return false;
234
235 pps_encoder_reset(m_encoder);
236 return true;
237}
238
239bool QQnxVirtualKeyboardPps::writeCurrentPPSEncoder()
240{
241 if (::write(m_fd, pps_encoder_buffer(m_encoder), pps_encoder_length(m_encoder)) == -1) {
242 close();
243 return false;
244 }
245 return true;
246}
247
249{
250 if (!prepareToSend())
251 return;
252
253 // Send the options message.
254 pps_encoder_add_string(m_encoder, "msg", "options");
255 pps_encoder_start_object(m_encoder, "dat");
256
257 pps_encoder_add_string(m_encoder, "enter", enterKeyTypeStr());
258 pps_encoder_add_string(m_encoder, "type", keyboardModeStr());
259
260 pps_encoder_end_object(m_encoder);
261
262 writeCurrentPPSEncoder();
263}
264
265const char* QQnxVirtualKeyboardPps::keyboardModeStr() const
266{
267 switch (keyboardMode()) {
268 case Url:
269 return "url";
270 case Email:
271 return "email";
272 case Web:
273 return "web";
274 case NumPunc:
275 return "num_punc";
276 case Number:
277 return "number";
278 case Symbol:
279 return "symbol";
280 case Phone:
281 return "phone";
282 case Pin:
283 return "pin";
284 case Password:
285 return "password";
286 case Alphanumeric:
287 return "alphanumeric";
288 case Default:
289 return "default";
290 }
291
292 return "";
293}
294
295const char* QQnxVirtualKeyboardPps::enterKeyTypeStr() const
296{
297 switch (enterKeyType()) {
298 case DefaultReturn:
299 return "enter.default";
300 case Connect:
301 return "enter.connect";
302 case Done:
303 return "enter.done";
304 case Go:
305 return "enter.go";
306 case Join:
307 return "enter.join";
308 case Next:
309 return "enter.next";
310 case Search:
311 return "enter.search";
312 case Send:
313 return "enter.send";
314 case Submit:
315 return "enter.submit";
316 }
317
318 return "";
319}
320
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
\inmodule QtCore
\inmodule QtCore
Combined button and popup list for selecting options.
#define Q_UNLIKELY(x)
#define Q_FUNC_INFO
static qint64 qt_safe_read(int fd, void *data, qint64 maxlen)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qCritical
Definition qlogging.h:167
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
#define SLOT(a)
Definition qobjectdefs.h:52
#define SIGNAL(a)
Definition qobjectdefs.h:53
long long qint64
Definition qtypes.h:60
file open(QIODevice::ReadOnly)
gzip write("uncompressed data")