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