1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:GPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU |
19 | ** General Public License version 3 or (at your option) any later version |
20 | ** approved by the KDE Free Qt Foundation. The licenses are as published by |
21 | ** the Free Software Foundation and appearing in the file LICENSE.GPL3 |
22 | ** included in the packaging of this file. Please review the following |
23 | ** information to ensure the GNU General Public License requirements will |
24 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
25 | ** |
26 | ** $QT_END_LICENSE$ |
27 | ** |
28 | ****************************************************************************/ |
29 | |
30 | #include <QtVirtualKeyboard/qvirtualkeyboardinputengine.h> |
31 | #include <QtVirtualKeyboard/qvirtualkeyboardinputcontext.h> |
32 | #include <QtVirtualKeyboard/private/qvirtualkeyboardinputcontext_p.h> |
33 | #include <QtVirtualKeyboard/private/shifthandler_p.h> |
34 | #include <QtVirtualKeyboard/private/fallbackinputmethod_p.h> |
35 | #include <QtVirtualKeyboard/qvirtualkeyboardtrace.h> |
36 | #include <QtVirtualKeyboard/private/virtualkeyboarddebug_p.h> |
37 | |
38 | #include <QTimerEvent> |
39 | #include <QtCore/private/qobject_p.h> |
40 | |
41 | QT_BEGIN_NAMESPACE |
42 | using namespace QtVirtualKeyboard; |
43 | |
44 | class QVirtualKeyboardInputEnginePrivate : public QObjectPrivate |
45 | { |
46 | Q_DECLARE_PUBLIC(QVirtualKeyboardInputEngine) |
47 | |
48 | public: |
49 | QVirtualKeyboardInputEnginePrivate(QVirtualKeyboardInputEngine *q_ptr) : |
50 | QObjectPrivate(), |
51 | q_ptr(q_ptr), |
52 | inputContext(nullptr), |
53 | fallbackInputMethod(nullptr), |
54 | textCase(QVirtualKeyboardInputEngine::TextCase::Lower), |
55 | inputMode(QVirtualKeyboardInputEngine::InputMode::Latin), |
56 | activeKey(Qt::Key_unknown), |
57 | activeKeyModifiers(Qt::NoModifier), |
58 | previousKey(Qt::Key_unknown), |
59 | repeatTimer(0), |
60 | repeatCount(0), |
61 | recursiveMethodLock(0) |
62 | { |
63 | } |
64 | |
65 | virtual ~QVirtualKeyboardInputEnginePrivate() |
66 | { |
67 | } |
68 | |
69 | bool virtualKeyClick(Qt::Key key, const QString &text, Qt::KeyboardModifiers modifiers, bool isAutoRepeat) |
70 | { |
71 | Q_Q(QVirtualKeyboardInputEngine); |
72 | bool accept = false; |
73 | if (inputMethod) { |
74 | accept = inputMethod->keyEvent(key, text, modifiers); |
75 | if (!accept) { |
76 | accept = fallbackInputMethod->keyEvent(key, text, modifiers); |
77 | } |
78 | emit q->virtualKeyClicked(key, text, modifiers, isAutoRepeat); |
79 | } else if (QT_VIRTUALKEYBOARD_FORCE_EVENTS_WITHOUT_FOCUS) { |
80 | accept = fallbackInputMethod->keyEvent(key, text, modifiers); |
81 | emit q->virtualKeyClicked(key, text, modifiers, isAutoRepeat); |
82 | } else { |
83 | qWarning() << "input method is not set" ; |
84 | } |
85 | return accept; |
86 | } |
87 | |
88 | QVirtualKeyboardInputEngine* q_ptr; |
89 | QVirtualKeyboardInputContext *inputContext; |
90 | QPointer<QVirtualKeyboardAbstractInputMethod> inputMethod; |
91 | QVirtualKeyboardAbstractInputMethod *fallbackInputMethod; |
92 | QVirtualKeyboardInputEngine::TextCase textCase; |
93 | QVirtualKeyboardInputEngine::InputMode inputMode; |
94 | QList<int> inputModes; |
95 | QMap<QVirtualKeyboardSelectionListModel::Type, QVirtualKeyboardSelectionListModel *> selectionListModels; |
96 | Qt::Key activeKey; |
97 | QString activeKeyText; |
98 | Qt::KeyboardModifiers activeKeyModifiers; |
99 | Qt::Key previousKey; |
100 | int repeatTimer; |
101 | int repeatCount; |
102 | int recursiveMethodLock; |
103 | }; |
104 | |
105 | class RecursiveMethodGuard |
106 | { |
107 | public: |
108 | explicit RecursiveMethodGuard(int &ref) : m_ref(ref) |
109 | { |
110 | m_ref++; |
111 | } |
112 | ~RecursiveMethodGuard() |
113 | { |
114 | m_ref--; |
115 | } |
116 | bool locked() const |
117 | { |
118 | return m_ref > 1; |
119 | } |
120 | private: |
121 | int &m_ref; |
122 | }; |
123 | |
124 | /*! |
125 | \qmltype InputEngine |
126 | \inqmlmodule QtQuick.VirtualKeyboard |
127 | \ingroup qtvirtualkeyboard-qml |
128 | \instantiates QVirtualKeyboardInputEngine |
129 | \brief Maps the user input to the input methods. |
130 | |
131 | The input engine is responsible for routing input events to input |
132 | methods. The actual input logic is implemented by the input methods. |
133 | |
134 | The input engine also includes the default input method, which takes |
135 | care of default processing if the active input method does not handle |
136 | the event. |
137 | */ |
138 | |
139 | /*! |
140 | \class QVirtualKeyboardInputEngine |
141 | \inmodule QtVirtualKeyboard |
142 | \brief The InputEngine class provides an input engine |
143 | that supports C++ and QML integration. |
144 | |
145 | The input engine is responsible for routing input events to input |
146 | methods. The actual input logic is implemented by the input methods. |
147 | |
148 | The input engine also includes the default input method, which takes |
149 | care of default processing if the active input method does not handle |
150 | the event. |
151 | */ |
152 | |
153 | /*! |
154 | \internal |
155 | Constructs an input engine with input context as \a parent. |
156 | */ |
157 | QVirtualKeyboardInputEngine::QVirtualKeyboardInputEngine(QVirtualKeyboardInputContext *parent) : |
158 | QObject(*new QVirtualKeyboardInputEnginePrivate(this), parent) |
159 | { |
160 | Q_D(QVirtualKeyboardInputEngine); |
161 | d->inputContext = parent; |
162 | } |
163 | |
164 | void QVirtualKeyboardInputEngine::init() |
165 | { |
166 | Q_D(QVirtualKeyboardInputEngine); |
167 | ShiftHandler *shiftHandler = d->inputContext->priv()->shiftHandler(); |
168 | QObject::connect(sender: shiftHandler, signal: &ShiftHandler::shiftActiveChanged, receiver: this, slot: &QVirtualKeyboardInputEngine::shiftChanged); |
169 | QObject::connect(sender: d->inputContext, signal: &QVirtualKeyboardInputContext::localeChanged, receiver: this, slot: &QVirtualKeyboardInputEngine::update); |
170 | QObject::connect(sender: d->inputContext, signal: &QVirtualKeyboardInputContext::inputMethodHintsChanged, receiver: this, slot: &QVirtualKeyboardInputEngine::updateSelectionListModels); |
171 | QObject::connect(sender: d->inputContext, signal: &QVirtualKeyboardInputContext::localeChanged, receiver: this, slot: &QVirtualKeyboardInputEngine::updateInputModes); |
172 | QObject::connect(sender: this, signal: &QVirtualKeyboardInputEngine::inputMethodChanged, receiver: this, slot: &QVirtualKeyboardInputEngine::updateInputModes); |
173 | d->fallbackInputMethod = new FallbackInputMethod(this); |
174 | if (d->fallbackInputMethod) |
175 | d->fallbackInputMethod->setInputEngine(this); |
176 | d->selectionListModels[QVirtualKeyboardSelectionListModel::Type::WordCandidateList] = new QVirtualKeyboardSelectionListModel(this); |
177 | } |
178 | |
179 | /*! |
180 | \internal |
181 | Destroys the input engine and frees all allocated resources. |
182 | */ |
183 | QVirtualKeyboardInputEngine::~QVirtualKeyboardInputEngine() |
184 | { |
185 | } |
186 | |
187 | /*! |
188 | \qmlmethod bool InputEngine::virtualKeyPress(int key, string text, int modifiers, bool repeat) |
189 | |
190 | Called by the keyboard layer to indicate that \a key was pressed, with |
191 | the given \a text and \a modifiers. |
192 | |
193 | The \a key is set as an active key (down key). The actual key event is |
194 | triggered when the key is released by the virtualKeyRelease() method. The |
195 | key press event can be discarded by calling virtualKeyCancel(). |
196 | |
197 | The key press also initiates the key repeat timer if \a repeat is \c true. |
198 | |
199 | Returns \c true if the key was accepted by this input engine. |
200 | |
201 | \sa virtualKeyCancel(), virtualKeyRelease() |
202 | */ |
203 | /*! |
204 | Called by the keyboard layer to indicate that \a key was pressed, with |
205 | the given \a text and \a modifiers. |
206 | |
207 | The \a key is set as an active key (down key). The actual key event is |
208 | triggered when the key is released by the virtualKeyRelease() method. The |
209 | key press event can be discarded by calling virtualKeyCancel(). |
210 | |
211 | The key press also initiates the key repeat timer if \a repeat is \c true. |
212 | |
213 | Returns \c true if the key was accepted by this input engine. |
214 | |
215 | \sa virtualKeyCancel(), virtualKeyRelease() |
216 | */ |
217 | bool QVirtualKeyboardInputEngine::virtualKeyPress(Qt::Key key, const QString &text, Qt::KeyboardModifiers modifiers, bool repeat) |
218 | { |
219 | Q_D(QVirtualKeyboardInputEngine); |
220 | VIRTUALKEYBOARD_DEBUG() << "QVirtualKeyboardInputEngine::virtualKeyPress()" |
221 | #ifdef SENSITIVE_DEBUG |
222 | << key << text << modifiers << repeat |
223 | #endif |
224 | ; |
225 | |
226 | bool accept = false; |
227 | if (d->activeKey == Qt::Key_unknown || d->activeKey == key) { |
228 | d->activeKey = key; |
229 | d->activeKeyText = text; |
230 | d->activeKeyModifiers = modifiers; |
231 | if (repeat) { |
232 | d->repeatTimer = startTimer(interval: 600); |
233 | } |
234 | accept = true; |
235 | emit activeKeyChanged(key: d->activeKey); |
236 | } else { |
237 | qWarning(msg: "key press ignored; key is already active" ); |
238 | } |
239 | return accept; |
240 | } |
241 | |
242 | /*! |
243 | \qmlmethod void InputEngine::virtualKeyCancel() |
244 | |
245 | Reverts the active key state without emitting the key event. |
246 | This method is useful when the user discards the current key and |
247 | the key state needs to be restored. |
248 | */ |
249 | /*! |
250 | \fn void QVirtualKeyboardInputEngine::virtualKeyCancel() |
251 | |
252 | Reverts the active key state without emitting the key event. |
253 | This method is useful when the user discards the current key and |
254 | the key state needs to be restored. |
255 | */ |
256 | void QVirtualKeyboardInputEngine::virtualKeyCancel() |
257 | { |
258 | Q_D(QVirtualKeyboardInputEngine); |
259 | VIRTUALKEYBOARD_DEBUG() << "QVirtualKeyboardInputEngine::virtualKeyCancel()" ; |
260 | if (d->activeKey != Qt::Key_unknown) { |
261 | d->activeKey = Qt::Key_unknown; |
262 | d->activeKeyText = QString(); |
263 | d->activeKeyModifiers = Qt::KeyboardModifiers(); |
264 | if (d->repeatTimer) { |
265 | killTimer(id: d->repeatTimer); |
266 | d->repeatTimer = 0; |
267 | d->repeatCount = 0; |
268 | } |
269 | emit activeKeyChanged(key: d->activeKey); |
270 | } |
271 | } |
272 | |
273 | /*! |
274 | \qmlmethod bool InputEngine::virtualKeyRelease(int key, string text, int modifiers) |
275 | |
276 | Releases the key at \a key. The method emits a key event for the input |
277 | method if the event has not been generated by a repeating timer. |
278 | The \a text and \a modifiers are passed to the input method. |
279 | |
280 | Returns \c true if the key was accepted by the input engine. |
281 | */ |
282 | /*! |
283 | Releases the key at \a key. The method emits a key event for the input |
284 | method if the event has not been generated by a repeating timer. |
285 | The \a text and \a modifiers are passed to the input method. |
286 | |
287 | Returns \c true if the key was accepted by the input engine. |
288 | */ |
289 | bool QVirtualKeyboardInputEngine::virtualKeyRelease(Qt::Key key, const QString &text, Qt::KeyboardModifiers modifiers) |
290 | { |
291 | Q_D(QVirtualKeyboardInputEngine); |
292 | VIRTUALKEYBOARD_DEBUG() << "QVirtualKeyboardInputEngine::virtualKeyRelease()" |
293 | #ifdef SENSITIVE_DEBUG |
294 | << key << text << modifiers |
295 | #endif |
296 | ; |
297 | |
298 | bool accept = false; |
299 | if (d->activeKey == key) { |
300 | if (!d->repeatCount) { |
301 | accept = d->virtualKeyClick(key, text, modifiers, isAutoRepeat: false); |
302 | } else { |
303 | accept = true; |
304 | } |
305 | } else { |
306 | qWarning(msg: "key release ignored; key is not pressed" ); |
307 | } |
308 | if (d->activeKey != Qt::Key_unknown) { |
309 | d->previousKey = d->activeKey; |
310 | emit previousKeyChanged(key: d->previousKey); |
311 | d->activeKey = Qt::Key_unknown; |
312 | d->activeKeyText = QString(); |
313 | d->activeKeyModifiers = Qt::KeyboardModifiers(); |
314 | if (d->repeatTimer) { |
315 | killTimer(id: d->repeatTimer); |
316 | d->repeatTimer = 0; |
317 | d->repeatCount = 0; |
318 | } |
319 | emit activeKeyChanged(key: d->activeKey); |
320 | } |
321 | return accept; |
322 | } |
323 | |
324 | /*! |
325 | \qmlmethod bool InputEngine::virtualKeyClick(int key, string text, int modifiers) |
326 | |
327 | Emits a key click event for the given \a key, \a text and \a modifiers. |
328 | Returns \c true if the key event was accepted by the input engine. |
329 | */ |
330 | /*! |
331 | Emits a key click event for the given \a key, \a text and \a modifiers. |
332 | Returns \c true if the key event was accepted by the input engine. |
333 | */ |
334 | bool QVirtualKeyboardInputEngine::virtualKeyClick(Qt::Key key, const QString &text, Qt::KeyboardModifiers modifiers) |
335 | { |
336 | Q_D(QVirtualKeyboardInputEngine); |
337 | VIRTUALKEYBOARD_DEBUG() << "QVirtualKeyboardInputEngine::virtualKeyClick()" |
338 | #ifdef SENSITIVE_DEBUG |
339 | << key << text << modifiers |
340 | #endif |
341 | ; |
342 | return d->virtualKeyClick(key, text, modifiers, isAutoRepeat: false); |
343 | } |
344 | |
345 | /*! |
346 | Returns the \c InputContext instance associated with the input |
347 | engine. |
348 | */ |
349 | QVirtualKeyboardInputContext *QVirtualKeyboardInputEngine::inputContext() const |
350 | { |
351 | Q_D(const QVirtualKeyboardInputEngine); |
352 | return d->inputContext; |
353 | } |
354 | |
355 | /*! |
356 | Returns the currently active key, or Qt::Key_unknown if no key is active. |
357 | */ |
358 | Qt::Key QVirtualKeyboardInputEngine::activeKey() const |
359 | { |
360 | Q_D(const QVirtualKeyboardInputEngine); |
361 | return d->activeKey; |
362 | } |
363 | |
364 | /*! |
365 | Returns the previously active key, or Qt::Key_unknown if no key has been |
366 | active. |
367 | */ |
368 | Qt::Key QVirtualKeyboardInputEngine::previousKey() const |
369 | { |
370 | Q_D(const QVirtualKeyboardInputEngine); |
371 | return d->previousKey; |
372 | } |
373 | |
374 | /*! |
375 | Returns the active input method. |
376 | */ |
377 | QVirtualKeyboardAbstractInputMethod *QVirtualKeyboardInputEngine::inputMethod() const |
378 | { |
379 | Q_D(const QVirtualKeyboardInputEngine); |
380 | return d->inputMethod; |
381 | } |
382 | |
383 | /*! |
384 | Sets \a inputMethod as the active input method. |
385 | */ |
386 | void QVirtualKeyboardInputEngine::setInputMethod(QVirtualKeyboardAbstractInputMethod *inputMethod) |
387 | { |
388 | Q_D(QVirtualKeyboardInputEngine); |
389 | VIRTUALKEYBOARD_DEBUG() << "QVirtualKeyboardInputEngine::setInputMethod():" << inputMethod; |
390 | if (d->inputMethod != inputMethod) { |
391 | update(); |
392 | if (d->inputMethod) { |
393 | QObject::disconnect(sender: d->inputMethod.data(), signal: &QVirtualKeyboardAbstractInputMethod::selectionListsChanged, receiver: this, slot: &QVirtualKeyboardInputEngine::updateSelectionListModels); |
394 | d->inputMethod->setInputEngine(nullptr); |
395 | } |
396 | d->inputMethod = inputMethod; |
397 | if (d->inputMethod) { |
398 | d->inputMethod->setInputEngine(this); |
399 | QObject::connect(sender: d->inputMethod.data(), signal: &QVirtualKeyboardAbstractInputMethod::selectionListsChanged, receiver: this, slot: &QVirtualKeyboardInputEngine::updateSelectionListModels); |
400 | |
401 | // Set current text case |
402 | d->inputMethod->setTextCase(d->textCase); |
403 | } |
404 | updateSelectionListModels(); |
405 | emit inputMethodChanged(); |
406 | emit patternRecognitionModesChanged(); |
407 | } |
408 | } |
409 | |
410 | /*! |
411 | Returns the list of available input modes. |
412 | */ |
413 | QList<int> QVirtualKeyboardInputEngine::inputModes() const |
414 | { |
415 | Q_D(const QVirtualKeyboardInputEngine); |
416 | return d->inputModes; |
417 | } |
418 | |
419 | QVirtualKeyboardInputEngine::InputMode QVirtualKeyboardInputEngine::inputMode() const |
420 | { |
421 | Q_D(const QVirtualKeyboardInputEngine); |
422 | return d->inputMode; |
423 | } |
424 | |
425 | void QVirtualKeyboardInputEngine::setInputMode(QVirtualKeyboardInputEngine::InputMode inputMode) |
426 | { |
427 | Q_D(QVirtualKeyboardInputEngine); |
428 | VIRTUALKEYBOARD_DEBUG() << "QVirtualKeyboardInputEngine::setInputMode():" << inputMode; |
429 | if (d->inputMethod) { |
430 | #ifdef QT_DEBUG |
431 | // Cached input modes should be in sync with the input method |
432 | // If the assert below fails, we have missed an update somewhere |
433 | QList<int> cachedInputModes(d->inputModes); |
434 | updateInputModes(); |
435 | Q_ASSERT(cachedInputModes == d->inputModes); |
436 | #endif |
437 | if (d->inputModes.contains(t: static_cast<int>(inputMode))) { |
438 | d->inputMethod->setInputMode(locale: d->inputContext->locale(), inputMode); |
439 | if (d->inputMode != inputMode) { |
440 | d->inputMode = inputMode; |
441 | emit inputModeChanged(); |
442 | } |
443 | } else { |
444 | qWarning() << "Input mode" << inputMode << |
445 | "is not in the list of available input modes" << d->inputModes; |
446 | } |
447 | } |
448 | } |
449 | |
450 | QVirtualKeyboardSelectionListModel *QVirtualKeyboardInputEngine::wordCandidateListModel() const |
451 | { |
452 | Q_D(const QVirtualKeyboardInputEngine); |
453 | return d->selectionListModels[QVirtualKeyboardSelectionListModel::Type::WordCandidateList]; |
454 | } |
455 | |
456 | bool QVirtualKeyboardInputEngine::wordCandidateListVisibleHint() const |
457 | { |
458 | Q_D(const QVirtualKeyboardInputEngine); |
459 | const auto it = d->selectionListModels.constFind(akey: QVirtualKeyboardSelectionListModel::Type::WordCandidateList); |
460 | if (it == d->selectionListModels.cend()) |
461 | return false; |
462 | return it.value()->dataSource() != nullptr; |
463 | } |
464 | |
465 | /*! |
466 | Returns list of supported pattern recognition modes. |
467 | */ |
468 | QList<int> QVirtualKeyboardInputEngine::patternRecognitionModes() const |
469 | { |
470 | Q_D(const QVirtualKeyboardInputEngine); |
471 | QList<PatternRecognitionMode> patterRecognitionModeList; |
472 | if (d->inputMethod) |
473 | patterRecognitionModeList = d->inputMethod->patternRecognitionModes(); |
474 | QList<int> resultList; |
475 | if (patterRecognitionModeList.isEmpty()) |
476 | return resultList; |
477 | resultList.reserve(alloc: patterRecognitionModeList.size()); |
478 | for (const PatternRecognitionMode &patternRecognitionMode : qAsConst(t&: patterRecognitionModeList)) |
479 | resultList.append(t: static_cast<int>(patternRecognitionMode)); |
480 | return resultList; |
481 | } |
482 | |
483 | /*! |
484 | \qmlmethod Trace InputEngine::traceBegin(int traceId, int patternRecognitionMode, var traceCaptureDeviceInfo, var traceScreenInfo) |
485 | \since QtQuick.VirtualKeyboard 2.0 |
486 | |
487 | Starts a trace interaction with the input engine. |
488 | |
489 | The trace is uniquely identified by the \a traceId. The input engine will assign |
490 | the id to the Trace object if the input method accepts the event. |
491 | |
492 | The \a patternRecognitionMode specifies the recognition mode used for the pattern. |
493 | |
494 | If the current input method accepts the event it returns a Trace object associated with this interaction. |
495 | If the input method discards the event, it returns a null value. |
496 | |
497 | The \a traceCaptureDeviceInfo provides information about the source device and the \a traceScreenInfo |
498 | provides information about the screen context. |
499 | |
500 | By definition, the Trace object remains valid until the traceEnd() method is called. |
501 | |
502 | The trace interaction is ended by calling the \l {InputEngine::traceEnd()} {InputEngine.traceEnd()} method. |
503 | */ |
504 | /*! |
505 | \since QtQuick.VirtualKeyboard 2.0 |
506 | |
507 | Starts a trace interaction with the input engine. |
508 | |
509 | The trace is uniquely identified by the \a traceId. The input engine will assign |
510 | the id to the QVirtualKeyboardTrace object if the input method accepts the event. |
511 | |
512 | The \a patternRecognitionMode specifies the recognition mode used for the pattern. |
513 | |
514 | If the current input method accepts the event it returns a QVirtualKeyboardTrace object associated with this interaction. |
515 | If the input method discards the event, it returns a NULL value. |
516 | |
517 | The \a traceCaptureDeviceInfo provides information about the source device and the \a traceScreenInfo |
518 | provides information about the screen context. |
519 | |
520 | By definition, the QVirtualKeyboardTrace object remains valid until the traceEnd() method is called. |
521 | |
522 | The trace interaction is ended by calling the traceEnd() method. |
523 | */ |
524 | QVirtualKeyboardTrace *QVirtualKeyboardInputEngine::traceBegin( |
525 | int traceId, PatternRecognitionMode patternRecognitionMode, |
526 | const QVariantMap &traceCaptureDeviceInfo, const QVariantMap &traceScreenInfo) |
527 | { |
528 | Q_D(QVirtualKeyboardInputEngine); |
529 | VIRTUALKEYBOARD_DEBUG() << "QVirtualKeyboardInputEngine::traceBegin():" |
530 | << "traceId:" << traceId |
531 | << "patternRecognitionMode:" << patternRecognitionMode |
532 | << "traceCaptureDeviceInfo:" << traceCaptureDeviceInfo |
533 | << "traceScreenInfo:" << traceScreenInfo; |
534 | if (!d->inputMethod) |
535 | return nullptr; |
536 | if (patternRecognitionMode == PatternRecognitionMode::None) |
537 | return nullptr; |
538 | if (!d->inputMethod->patternRecognitionModes().contains(t: patternRecognitionMode)) |
539 | return nullptr; |
540 | QVirtualKeyboardTrace *trace = d->inputMethod->traceBegin(traceId, patternRecognitionMode, traceCaptureDeviceInfo, traceScreenInfo); |
541 | if (trace) |
542 | trace->setTraceId(traceId); |
543 | return trace; |
544 | } |
545 | |
546 | /*! |
547 | \qmlmethod bool InputEngine::traceEnd(Trace trace) |
548 | |
549 | Ends the trace interaction with the input engine. |
550 | |
551 | The \a trace object may be discarded at any point after calling this function. |
552 | |
553 | The function returns true if the trace interaction was accepted (i.e. the touch |
554 | events should not be used for anything else). |
555 | */ |
556 | /*! |
557 | Ends the trace interaction with the input engine. |
558 | |
559 | The \a trace object may be discarded at any point after calling this function. |
560 | |
561 | The function returns true if the trace interaction was accepted (i.e. the touch |
562 | events should not be used for anything else). |
563 | */ |
564 | bool QVirtualKeyboardInputEngine::traceEnd(QVirtualKeyboardTrace *trace) |
565 | { |
566 | Q_D(QVirtualKeyboardInputEngine); |
567 | VIRTUALKEYBOARD_DEBUG() << "QVirtualKeyboardInputEngine::traceEnd():" << trace; |
568 | Q_ASSERT(trace); |
569 | if (!d->inputMethod) |
570 | return false; |
571 | return d->inputMethod->traceEnd(trace); |
572 | } |
573 | |
574 | /*! |
575 | \since QtQuick.VirtualKeyboard 2.0 |
576 | |
577 | This function attempts to reselect a word located at the \a cursorPosition. |
578 | The \a reselectFlags define the rules for how the word should be selected in |
579 | relation to the cursor position. |
580 | |
581 | The function returns \c true if the word was successfully reselected. |
582 | */ |
583 | bool QVirtualKeyboardInputEngine::reselect(int cursorPosition, const ReselectFlags &reselectFlags) |
584 | { |
585 | Q_D(QVirtualKeyboardInputEngine); |
586 | VIRTUALKEYBOARD_DEBUG() << "QVirtualKeyboardInputEngine::reselect():" << cursorPosition << reselectFlags; |
587 | if (!d->inputMethod || !wordCandidateListVisibleHint()) |
588 | return false; |
589 | return d->inputMethod->reselect(cursorPosition, reselectFlags); |
590 | } |
591 | |
592 | /*! |
593 | \internal |
594 | This method is called when the current preedit text is clicked. |
595 | */ |
596 | bool QVirtualKeyboardInputEngine::clickPreeditText(int cursorPosition) |
597 | { |
598 | Q_D(QVirtualKeyboardInputEngine); |
599 | if (!d->inputMethod) |
600 | return false; |
601 | return d->inputMethod->clickPreeditText(cursorPosition); |
602 | } |
603 | |
604 | /*! |
605 | \internal |
606 | Resets the input method. |
607 | */ |
608 | void QVirtualKeyboardInputEngine::reset() |
609 | { |
610 | Q_D(QVirtualKeyboardInputEngine); |
611 | if (d->inputMethod) { |
612 | RecursiveMethodGuard guard(d->recursiveMethodLock); |
613 | if (!guard.locked()) { |
614 | emit inputMethodReset(); |
615 | updateInputModes(); |
616 | } |
617 | } else { |
618 | updateInputModes(); |
619 | } |
620 | } |
621 | |
622 | /*! |
623 | \internal |
624 | Updates the input method's state. This method is called whenever the input |
625 | context is changed. |
626 | */ |
627 | void QVirtualKeyboardInputEngine::update() |
628 | { |
629 | Q_D(QVirtualKeyboardInputEngine); |
630 | if (d->inputMethod) { |
631 | RecursiveMethodGuard guard(d->recursiveMethodLock); |
632 | if (!guard.locked()) { |
633 | emit inputMethodUpdate(); |
634 | } |
635 | } |
636 | } |
637 | |
638 | /*! |
639 | \internal |
640 | Updates the text case for the input method. |
641 | */ |
642 | void QVirtualKeyboardInputEngine::shiftChanged() |
643 | { |
644 | Q_D(QVirtualKeyboardInputEngine); |
645 | TextCase newCase = d->inputContext->priv()->shiftHandler()->isShiftActive() ? TextCase::Upper : TextCase::Lower; |
646 | if (d->textCase != newCase) { |
647 | d->textCase = newCase; |
648 | if (d->inputMethod) { |
649 | d->inputMethod->setTextCase(d->textCase); |
650 | } |
651 | } |
652 | } |
653 | |
654 | /*! |
655 | \internal |
656 | */ |
657 | void QVirtualKeyboardInputEngine::updateSelectionListModels() |
658 | { |
659 | Q_D(QVirtualKeyboardInputEngine); |
660 | QList<QVirtualKeyboardSelectionListModel::Type> inactiveSelectionLists = d->selectionListModels.keys(); |
661 | if (d->inputMethod) { |
662 | // Allocate selection lists for the input method |
663 | const QList<QVirtualKeyboardSelectionListModel::Type> activeSelectionLists = d->inputMethod->selectionLists(); |
664 | for (const QVirtualKeyboardSelectionListModel::Type &selectionListType : activeSelectionLists) { |
665 | auto it = d->selectionListModels.find(akey: selectionListType); |
666 | if (it == d->selectionListModels.end()) { |
667 | it = d->selectionListModels.insert(akey: selectionListType, avalue: new QVirtualKeyboardSelectionListModel(this)); |
668 | if (selectionListType == QVirtualKeyboardSelectionListModel::Type::WordCandidateList) |
669 | emit wordCandidateListModelChanged(); |
670 | } |
671 | it.value()->setDataSource(dataSource: d->inputMethod, type: selectionListType); |
672 | if (selectionListType == QVirtualKeyboardSelectionListModel::Type::WordCandidateList) |
673 | emit wordCandidateListVisibleHintChanged(); |
674 | inactiveSelectionLists.removeAll(t: selectionListType); |
675 | } |
676 | } |
677 | |
678 | // Deallocate inactive selection lists |
679 | for (const QVirtualKeyboardSelectionListModel::Type &selectionListType : qAsConst(t&: inactiveSelectionLists)) { |
680 | const auto it = d->selectionListModels.constFind(akey: selectionListType); |
681 | if (it != d->selectionListModels.cend()) { |
682 | it.value()->setDataSource(dataSource: nullptr, type: selectionListType); |
683 | if (selectionListType == QVirtualKeyboardSelectionListModel::Type::WordCandidateList) |
684 | emit wordCandidateListVisibleHintChanged(); |
685 | } |
686 | } |
687 | } |
688 | |
689 | /*! |
690 | \internal |
691 | */ |
692 | void QVirtualKeyboardInputEngine::updateInputModes() |
693 | { |
694 | Q_D(QVirtualKeyboardInputEngine); |
695 | QList<int> newInputModes; |
696 | if (d->inputMethod) { |
697 | QList<InputMode> tmpList(d->inputMethod->inputModes(locale: d->inputContext->locale())); |
698 | if (!tmpList.isEmpty()) { |
699 | std::transform(first: tmpList.constBegin(), last: tmpList.constEnd(), |
700 | result: std::back_inserter(x&: newInputModes), |
701 | unary_op: [tmpList] (InputMode inputMode) { |
702 | return static_cast<int>(inputMode); |
703 | }); |
704 | } |
705 | } |
706 | if (d->inputModes != newInputModes) { |
707 | d->inputModes = newInputModes; |
708 | emit inputModesChanged(); |
709 | } |
710 | } |
711 | |
712 | /*! |
713 | \internal |
714 | */ |
715 | void QVirtualKeyboardInputEngine::timerEvent(QTimerEvent *timerEvent) |
716 | { |
717 | Q_D(QVirtualKeyboardInputEngine); |
718 | if (timerEvent->timerId() == d->repeatTimer) { |
719 | d->virtualKeyClick(key: d->activeKey, text: d->activeKeyText, modifiers: d->activeKeyModifiers, isAutoRepeat: true); |
720 | if (!d->repeatCount) { |
721 | killTimer(id: d->repeatTimer); |
722 | d->repeatTimer = startTimer(interval: 50); |
723 | } |
724 | d->repeatCount++; |
725 | } |
726 | } |
727 | |
728 | /*! |
729 | \qmlproperty int InputEngine::activeKey |
730 | |
731 | Currently pressed key. |
732 | */ |
733 | |
734 | /*! |
735 | \property QVirtualKeyboardInputEngine::activeKey |
736 | \brief the active key. |
737 | |
738 | Currently pressed key. |
739 | */ |
740 | |
741 | /*! |
742 | \qmlproperty int InputEngine::previousKey |
743 | |
744 | Previously pressed key. |
745 | */ |
746 | /*! |
747 | \property QVirtualKeyboardInputEngine::previousKey |
748 | \brief the previous active key. |
749 | |
750 | Previously pressed key. |
751 | */ |
752 | |
753 | /*! |
754 | \qmlproperty InputMethod InputEngine::inputMethod |
755 | |
756 | Use this property to set the active input method, or to monitor when the |
757 | active input method changes. |
758 | */ |
759 | |
760 | /*! |
761 | \property QVirtualKeyboardInputEngine::inputMethod |
762 | \brief the active input method. |
763 | |
764 | Use this property to set active the input method, or to monitor when the |
765 | active input method changes. |
766 | */ |
767 | |
768 | /*! |
769 | \qmlproperty list<int> InputEngine::inputModes |
770 | |
771 | The list of available input modes is dependent on the input method and |
772 | locale. This property is updated when either of the dependencies change. |
773 | */ |
774 | |
775 | /*! |
776 | \property QVirtualKeyboardInputEngine::inputModes |
777 | \brief the available input modes for active input method. |
778 | |
779 | The list of available input modes is dependent on the input method and |
780 | locale. This property is updated when either of the dependencies changes. |
781 | */ |
782 | |
783 | /*! |
784 | \qmlproperty int InputEngine::inputMode |
785 | |
786 | Use this property to get or set the current input mode. The |
787 | InputEngine::inputModes property provides the list of valid input modes |
788 | for the current input method and locale. |
789 | |
790 | The predefined input modes are: |
791 | |
792 | \list |
793 | \li \c InputEngine.InputMode.Latin The default input mode for latin text. |
794 | \li \c InputEngine.InputMode.Numeric Only numeric input is allowed. |
795 | \li \c InputEngine.InputMode.Dialable Only dialable input is allowed. |
796 | \li \c InputEngine.InputMode.Pinyin Pinyin input mode for Chinese. |
797 | \li \c InputEngine.InputMode.Cangjie Cangjie input mode for Chinese. |
798 | \li \c InputEngine.InputMode.Zhuyin Zhuyin input mode for Chinese. |
799 | \li \c InputEngine.InputMode.Hangul Hangul input mode for Korean. |
800 | \li \c InputEngine.InputMode.Hiragana Hiragana input mode for Japanese. |
801 | \li \c InputEngine.InputMode.Katakana Katakana input mode for Japanese. |
802 | \li \c InputEngine.InputMode.FullwidthLatin Fullwidth latin input mode for East Asian languages. |
803 | \li \c InputEngine.InputMode.Greek Greek input mode. |
804 | \li \c InputEngine.InputMode.Cyrillic Cyrillic input mode. |
805 | \li \c InputEngine.InputMode.Arabic Arabic input mode. |
806 | \li \c InputEngine.InputMode.Hebrew Hebrew input mode. |
807 | \li \c InputEngine.InputMode.ChineseHandwriting Chinese handwriting. |
808 | \li \c InputEngine.InputMode.JapaneseHandwriting Japanese handwriting. |
809 | \li \c InputEngine.InputMode.KoreanHandwriting Korean handwriting. |
810 | \li \c InputEngine.InputMode.Thai Thai input mode. |
811 | \endlist |
812 | */ |
813 | |
814 | /*! |
815 | \property QVirtualKeyboardInputEngine::inputMode |
816 | \brief the current input mode. |
817 | |
818 | Use this property to get or set the current input mode. The |
819 | InputEngine::inputModes provides list of valid input modes |
820 | for current input method and locale. |
821 | */ |
822 | |
823 | /*! |
824 | \qmlproperty SelectionListModel InputEngine::wordCandidateListModel |
825 | |
826 | Use this property to access the list model for the word candidate |
827 | list. |
828 | */ |
829 | |
830 | /*! |
831 | \property QVirtualKeyboardInputEngine::wordCandidateListModel |
832 | \brief list model for the word candidate list. |
833 | |
834 | Use this property to access the list model for the word candidate |
835 | list. |
836 | */ |
837 | |
838 | /*! |
839 | \qmlproperty bool InputEngine::wordCandidateListVisibleHint |
840 | |
841 | Use this property to check if the word candidate list should be visible |
842 | in the UI. |
843 | */ |
844 | |
845 | /*! |
846 | \property QVirtualKeyboardInputEngine::wordCandidateListVisibleHint |
847 | \brief visible hint for the word candidate list. |
848 | |
849 | Use this property to check if the word candidate list should be visible |
850 | in the UI. |
851 | */ |
852 | |
853 | /*! |
854 | \enum QVirtualKeyboardInputEngine::InputMode |
855 | |
856 | This enum specifies the input mode for the input method. |
857 | |
858 | \value Latin |
859 | The default input mode for latin text. |
860 | \value Numeric |
861 | Only numeric input is allowed. |
862 | \value Dialable |
863 | Only dialable input is allowed. |
864 | \value Pinyin |
865 | Pinyin input mode for Chinese. |
866 | \value Cangjie |
867 | Cangjie input mode for Chinese. |
868 | \value Zhuyin |
869 | Zhuyin input mode for Chinese. |
870 | \value Hangul |
871 | Hangul input mode for Korean. |
872 | \value Hiragana |
873 | Hiragana input mode for Japanese. |
874 | \value Katakana |
875 | Katakana input mode for Japanese. |
876 | \value FullwidthLatin |
877 | Fullwidth latin input mode for East Asian languages. |
878 | \value Greek |
879 | Greek input mode. |
880 | \value Cyrillic |
881 | Cyrillic input mode. |
882 | \value Arabic |
883 | Arabic input mode. |
884 | \value Hebrew |
885 | Hebrew input mode. |
886 | \value ChineseHandwriting |
887 | Chinese handwriting input mode. |
888 | \value JapaneseHandwriting |
889 | Japanese handwriting input mode. |
890 | \value KoreanHandwriting |
891 | Korean handwriting input mode. |
892 | \value Thai |
893 | Thai input mode. |
894 | */ |
895 | |
896 | /*! |
897 | \enum QVirtualKeyboardInputEngine::TextCase |
898 | |
899 | This enum specifies the text case for the input method. |
900 | |
901 | \value Lower |
902 | Lower case text. |
903 | \value Upper |
904 | Upper case text. |
905 | */ |
906 | |
907 | /*! |
908 | \enum QVirtualKeyboardInputEngine::PatternRecognitionMode |
909 | |
910 | This enum specifies the input mode for the input method. |
911 | |
912 | \value None |
913 | Pattern recognition is not available. |
914 | \value PatternRecognitionDisabled |
915 | \c obsolete Use PatternRecognitionMode::None |
916 | \value Handwriting |
917 | Pattern recognition mode for handwriting recognition. |
918 | \value HandwritingRecoginition |
919 | \c obsolete Use PatternRecognitionMode::Handwriting |
920 | */ |
921 | |
922 | /*! |
923 | \enum QVirtualKeyboardInputEngine::ReselectFlag |
924 | |
925 | This enum specifies the rules for word reselection. |
926 | |
927 | \value WordBeforeCursor |
928 | Activate the word before the cursor. When this flag is used exclusively, the word must end exactly at the cursor. |
929 | \value WordAfterCursor |
930 | Activate the word after the cursor. When this flag is used exclusively, the word must start exactly at the cursor. |
931 | \value WordAtCursor |
932 | Activate the word at the cursor. This flag is a combination of the above flags with the exception that the word cannot start or stop at the cursor. |
933 | */ |
934 | |
935 | /*! |
936 | \qmlsignal void InputEngine::virtualKeyClicked(int key, string text, int modifiers) |
937 | |
938 | Indicates that the virtual \a key was clicked with the given \a text and |
939 | \a modifiers. |
940 | This signal is emitted after the input method has processed the key event. |
941 | */ |
942 | |
943 | /*! |
944 | \fn void QVirtualKeyboardInputEngine::virtualKeyClicked(Qt::Key key, const QString &text, Qt::KeyboardModifiers modifiers, bool isAutoRepeat) |
945 | |
946 | Indicates that the virtual \a key was clicked with the given \a text and |
947 | \a modifiers. The \a isAutoRepeat indicates if the event is automatically |
948 | repeated while the key is being pressed. |
949 | This signal is emitted after the input method has processed the key event. |
950 | */ |
951 | |
952 | /*! |
953 | \qmlproperty list<int> InputEngine::patternRecognitionModes |
954 | \since QtQuick.VirtualKeyboard 2.0 |
955 | |
956 | The list of available pattern recognition modes. |
957 | |
958 | Possible values: |
959 | |
960 | \value InputEngine.PatternRecognitionMode.None |
961 | Pattern recognition is not available. |
962 | \value InputEngine.PatternRecognitionMode.PatternRecognitionDisabled |
963 | \c obsolete - Use \c None instead. |
964 | \value InputEngine.PatternRecognitionMode.Handwriting |
965 | Pattern recognition mode for handwriting recognition. |
966 | \value InputEngine.PatternRecognitionMode.HandwritingRecoginition |
967 | \c obsolete - Use \c Handwriting instead. |
968 | |
969 | */ |
970 | |
971 | /*! |
972 | \property QVirtualKeyboardInputEngine::patternRecognitionModes |
973 | \since QtQuick.VirtualKeyboard 2.0 |
974 | \brief the list of available pattern recognition modes. |
975 | |
976 | The list of available pattern recognition modes. |
977 | */ |
978 | |
979 | /*! |
980 | \qmlsignal void InputEngine::activeKeyChanged(int key) |
981 | |
982 | Indicates that the active \a key has changed. |
983 | */ |
984 | |
985 | /*! |
986 | \fn void QVirtualKeyboardInputEngine::activeKeyChanged(Qt::Key key) |
987 | |
988 | Indicates that the active \a key has changed. |
989 | */ |
990 | |
991 | /*! |
992 | \qmlsignal void InputEngine::previousKeyChanged(int key) |
993 | |
994 | Indicates that the previous \a key has changed. |
995 | */ |
996 | |
997 | /*! |
998 | \fn void QVirtualKeyboardInputEngine::previousKeyChanged(Qt::Key key) |
999 | |
1000 | Indicates that the previous \a key has changed. |
1001 | */ |
1002 | |
1003 | /*! |
1004 | \qmlsignal void InputEngine::inputMethodChanged() |
1005 | |
1006 | Indicates that the input method has changed. |
1007 | */ |
1008 | |
1009 | /*! |
1010 | \fn void QVirtualKeyboardInputEngine::inputMethodChanged() |
1011 | |
1012 | Indicates that the input method has changed. |
1013 | */ |
1014 | |
1015 | /*! |
1016 | \qmlsignal void InputEngine::inputMethodReset() |
1017 | |
1018 | Emitted when the input method needs to be reset. |
1019 | |
1020 | \note This signal is automatically connected to QVirtualKeyboardAbstractInputMethod::reset() |
1021 | and InputMethod::reset() when the input method is activated. |
1022 | */ |
1023 | |
1024 | /*! |
1025 | \fn void QVirtualKeyboardInputEngine::inputMethodReset() |
1026 | |
1027 | Emitted when the input method needs to be reset. |
1028 | |
1029 | \note This signal is automatically connected to QVirtualKeyboardAbstractInputMethod::reset() |
1030 | and InputMethod::reset() when the input method is activated. |
1031 | */ |
1032 | |
1033 | /*! |
1034 | \qmlsignal void InputEngine::inputMethodUpdate() |
1035 | |
1036 | \note This signal is automatically connected to QVirtualKeyboardAbstractInputMethod::update() |
1037 | and InputMethod::update() when the input method is activated. |
1038 | */ |
1039 | |
1040 | /*! |
1041 | \fn void QVirtualKeyboardInputEngine::inputMethodUpdate() |
1042 | |
1043 | \note This signal is automatically connected to QVirtualKeyboardAbstractInputMethod::update() |
1044 | and InputMethod::update() when the input method is activated. |
1045 | */ |
1046 | |
1047 | /*! |
1048 | \qmlsignal void InputEngine::inputModesChanged() |
1049 | |
1050 | Indicates that the available input modes have changed. |
1051 | */ |
1052 | |
1053 | /*! |
1054 | \fn void QVirtualKeyboardInputEngine::inputModesChanged() |
1055 | |
1056 | Indicates that the available input modes have changed. |
1057 | */ |
1058 | |
1059 | /*! |
1060 | \qmlsignal void InputEngine::inputModeChanged() |
1061 | |
1062 | Indicates that the input mode has changed. |
1063 | */ |
1064 | |
1065 | /*! |
1066 | \fn void QVirtualKeyboardInputEngine::inputModeChanged() |
1067 | |
1068 | Indicates that the input mode has changed. |
1069 | */ |
1070 | |
1071 | /*! |
1072 | \qmlsignal void InputEngine::patternRecognitionModesChanged() |
1073 | \since QtQuick.VirtualKeyboard 2.0 |
1074 | |
1075 | Indicates that the available pattern recognition modes have changed. |
1076 | |
1077 | The predefined pattern recognition modes are: |
1078 | |
1079 | \list |
1080 | \li \c InputEngine.PatternRecognitionMode.None Pattern recognition is not available. |
1081 | \li \c InputEngine.PatternRecognitionMode.PatternRecognitionDisabled \c obsolete Use InputEngine.PatternRecognitionMode.None |
1082 | \li \c InputEngine.PatternRecognitionMode.Handwriting Pattern recognition mode for handwriting recognition. |
1083 | \li \c InputEngine.PatternRecognitionMode.HandwritingRecoginition \c obsolete Use InputEngine.PatternRecognitionMode.Handwriting |
1084 | \endlist |
1085 | */ |
1086 | |
1087 | /*! |
1088 | \fn void QVirtualKeyboardInputEngine::patternRecognitionModesChanged() |
1089 | \since QtQuick.VirtualKeyboard 2.0 |
1090 | |
1091 | Indicates that the available pattern recognition modes have changed. |
1092 | */ |
1093 | |
1094 | QT_END_NAMESPACE |
1095 | |