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