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
41QT_BEGIN_NAMESPACE
42using namespace QtVirtualKeyboard;
43
44class QVirtualKeyboardInputEnginePrivate : public QObjectPrivate
45{
46 Q_DECLARE_PUBLIC(QVirtualKeyboardInputEngine)
47
48public:
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
105class RecursiveMethodGuard
106{
107public:
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 }
120private:
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*/
157QVirtualKeyboardInputEngine::QVirtualKeyboardInputEngine(QVirtualKeyboardInputContext *parent) :
158 QObject(*new QVirtualKeyboardInputEnginePrivate(this), parent)
159{
160 Q_D(QVirtualKeyboardInputEngine);
161 d->inputContext = parent;
162}
163
164void 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*/
183QVirtualKeyboardInputEngine::~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*/
217bool 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*/
256void 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*/
289bool 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*/
334bool 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*/
349QVirtualKeyboardInputContext *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*/
358Qt::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*/
368Qt::Key QVirtualKeyboardInputEngine::previousKey() const
369{
370 Q_D(const QVirtualKeyboardInputEngine);
371 return d->previousKey;
372}
373
374/*!
375 Returns the active input method.
376*/
377QVirtualKeyboardAbstractInputMethod *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*/
386void 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*/
413QList<int> QVirtualKeyboardInputEngine::inputModes() const
414{
415 Q_D(const QVirtualKeyboardInputEngine);
416 return d->inputModes;
417}
418
419QVirtualKeyboardInputEngine::InputMode QVirtualKeyboardInputEngine::inputMode() const
420{
421 Q_D(const QVirtualKeyboardInputEngine);
422 return d->inputMode;
423}
424
425void 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
450QVirtualKeyboardSelectionListModel *QVirtualKeyboardInputEngine::wordCandidateListModel() const
451{
452 Q_D(const QVirtualKeyboardInputEngine);
453 return d->selectionListModels[QVirtualKeyboardSelectionListModel::Type::WordCandidateList];
454}
455
456bool 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*/
468QList<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*/
524QVirtualKeyboardTrace *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*/
564bool 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*/
583bool 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*/
596bool 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*/
608void 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*/
627void 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*/
642void 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*/
657void 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*/
692void 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*/
715void 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
1094QT_END_NAMESPACE
1095

source code of qtvirtualkeyboard/src/virtualkeyboard/qvirtualkeyboardinputengine.cpp