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