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/qvirtualkeyboardinputcontext.h>
31#include <QtVirtualKeyboard/private/qvirtualkeyboardinputcontext_p.h>
32#include <QtVirtualKeyboard/private/shifthandler_p.h>
33#include <QtVirtualKeyboard/private/platforminputcontext_p.h>
34#include <QtVirtualKeyboard/private/virtualkeyboarddebug_p.h>
35
36#include <QTextFormat>
37#include <QGuiApplication>
38
39QT_BEGIN_NAMESPACE
40using namespace QtVirtualKeyboard;
41
42/*!
43 \qmltype InputContext
44 \instantiates QVirtualKeyboardInputContext
45 \inqmlmodule QtQuick.VirtualKeyboard
46 \ingroup qtvirtualkeyboard-qml
47 \brief Provides access to an input context.
48
49 The InputContext can be accessed as singleton instance.
50*/
51
52/*!
53 \class QVirtualKeyboardInputContext
54 \inmodule QtVirtualKeyboard
55 \brief Provides access to an input context.
56*/
57
58/*!
59 \internal
60 Constructs an input context with \a parent as the platform input
61 context.
62*/
63QVirtualKeyboardInputContext::QVirtualKeyboardInputContext(QObject *parent) :
64 QObject(parent),
65 d_ptr(new QVirtualKeyboardInputContextPrivate(this))
66{
67 Q_D(QVirtualKeyboardInputContext);
68 d->init();
69 QObject::connect(sender: d->_shiftHandler, signal: &ShiftHandler::shiftActiveChanged, receiver: this, slot: &QVirtualKeyboardInputContext::shiftActiveChanged);
70 QObject::connect(sender: d->_shiftHandler, signal: &ShiftHandler::capsLockActiveChanged, receiver: this, slot: &QVirtualKeyboardInputContext::capsLockActiveChanged);
71 QObject::connect(sender: d->_shiftHandler, signal: &ShiftHandler::uppercaseChanged, receiver: this, slot: &QVirtualKeyboardInputContext::uppercaseChanged);
72 QObject::connect(sender: d, signal: &QVirtualKeyboardInputContextPrivate::localeChanged, receiver: this, slot: &QVirtualKeyboardInputContext::localeChanged);
73 QObject::connect(sender: d, signal: &QVirtualKeyboardInputContextPrivate::inputItemChanged, receiver: this, slot: &QVirtualKeyboardInputContext::inputItemChanged);
74}
75
76/*!
77 \internal
78 Destroys the input context and frees all allocated resources.
79*/
80QVirtualKeyboardInputContext::~QVirtualKeyboardInputContext()
81{
82}
83
84bool QVirtualKeyboardInputContext::isShiftActive() const
85{
86 Q_D(const QVirtualKeyboardInputContext);
87 return d->_shiftHandler->isShiftActive();
88}
89
90bool QVirtualKeyboardInputContext::isCapsLockActive() const
91{
92 Q_D(const QVirtualKeyboardInputContext);
93 return d->_shiftHandler->isCapsLockActive();
94}
95
96bool QVirtualKeyboardInputContext::isUppercase() const
97{
98 Q_D(const QVirtualKeyboardInputContext);
99 return d->_shiftHandler->isUppercase();
100}
101
102int QVirtualKeyboardInputContext::anchorPosition() const
103{
104 Q_D(const QVirtualKeyboardInputContext);
105 return d->anchorPosition;
106}
107
108int QVirtualKeyboardInputContext::cursorPosition() const
109{
110 Q_D(const QVirtualKeyboardInputContext);
111 return d->cursorPosition;
112}
113
114Qt::InputMethodHints QVirtualKeyboardInputContext::inputMethodHints() const
115{
116 Q_D(const QVirtualKeyboardInputContext);
117 return d->inputMethodHints;
118}
119
120QString QVirtualKeyboardInputContext::preeditText() const
121{
122 Q_D(const QVirtualKeyboardInputContext);
123 return d->preeditText;
124}
125
126void QVirtualKeyboardInputContext::setPreeditText(const QString &text, QList<QInputMethodEvent::Attribute> attributes, int replaceFrom, int replaceLength)
127{
128 Q_D(QVirtualKeyboardInputContext);
129 // Add default attributes
130 if (!text.isEmpty()) {
131 if (!d->testAttribute(attributes, attributeType: QInputMethodEvent::TextFormat)) {
132 QTextCharFormat textFormat;
133 textFormat.setUnderlineStyle(QTextCharFormat::SingleUnderline);
134 attributes.append(t: QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, 0, text.length(), textFormat));
135 }
136 } else if (d->_forceCursorPosition != -1) {
137 d->addSelectionAttribute(attributes);
138 }
139
140 d->sendPreedit(text, attributes, replaceFrom, replaceLength);
141}
142
143QList<QInputMethodEvent::Attribute> QVirtualKeyboardInputContext::preeditTextAttributes() const
144{
145 Q_D(const QVirtualKeyboardInputContext);
146 return d->preeditTextAttributes;
147}
148
149QString QVirtualKeyboardInputContext::surroundingText() const
150{
151 Q_D(const QVirtualKeyboardInputContext);
152 return d->surroundingText;
153}
154
155QString QVirtualKeyboardInputContext::selectedText() const
156{
157 Q_D(const QVirtualKeyboardInputContext);
158 return d->selectedText;
159}
160
161QRectF QVirtualKeyboardInputContext::anchorRectangle() const
162{
163 Q_D(const QVirtualKeyboardInputContext);
164 return d->anchorRectangle;
165}
166
167QRectF QVirtualKeyboardInputContext::cursorRectangle() const
168{
169 Q_D(const QVirtualKeyboardInputContext);
170 return d->cursorRectangle;
171}
172
173bool QVirtualKeyboardInputContext::isAnimating() const
174{
175 Q_D(const QVirtualKeyboardInputContext);
176 return d->animating;
177}
178
179void QVirtualKeyboardInputContext::setAnimating(bool animating)
180{
181 Q_D(QVirtualKeyboardInputContext);
182 if (d->animating != animating) {
183 VIRTUALKEYBOARD_DEBUG() << "QVirtualKeyboardInputContext::setAnimating():" << animating;
184 d->animating = animating;
185 emit animatingChanged();
186 d->platformInputContext->emitAnimatingChanged();
187 }
188}
189
190QString QVirtualKeyboardInputContext::locale() const
191{
192 Q_D(const QVirtualKeyboardInputContext);
193 return d->locale();
194}
195
196QObject *QVirtualKeyboardInputContext::inputItem() const
197{
198 Q_D(const QVirtualKeyboardInputContext);
199 return d->inputItem();
200}
201
202QVirtualKeyboardInputEngine *QVirtualKeyboardInputContext::inputEngine() const
203{
204 Q_D(const QVirtualKeyboardInputContext);
205 return d->inputEngine;
206}
207
208/*!
209 \qmlmethod void InputContext::sendKeyClick(int key, string text, int modifiers = 0)
210
211 Sends a key click event with the given \a key, \a text and \e modifiers to
212 the input item that currently has focus.
213*/
214/*!
215 Sends a key click event with the given \a key, \a text and \a modifiers to
216 the input item that currently has focus.
217*/
218void QVirtualKeyboardInputContext::sendKeyClick(int key, const QString &text, int modifiers)
219{
220 Q_D(QVirtualKeyboardInputContext);
221 if ((d->_focus && d->platformInputContext) || QT_VIRTUALKEYBOARD_FORCE_EVENTS_WITHOUT_FOCUS) {
222 QKeyEvent pressEvent(QEvent::KeyPress, key, Qt::KeyboardModifiers(modifiers), text);
223 QKeyEvent releaseEvent(QEvent::KeyRelease, key, Qt::KeyboardModifiers(modifiers), text);
224 VIRTUALKEYBOARD_DEBUG().nospace() << "InputContext::sendKeyClick()"
225#ifdef SENSITIVE_DEBUG
226 << ": " << key
227#endif
228 ;
229
230
231 d->setState(QVirtualKeyboardInputContextPrivate::State::KeyEvent);
232 d->platformInputContext->sendKeyEvent(event: &pressEvent);
233 d->platformInputContext->sendKeyEvent(event: &releaseEvent);
234 if (d->activeKeys.isEmpty())
235 d->clearState(state: QVirtualKeyboardInputContextPrivate::State::KeyEvent);
236 } else {
237 VIRTUALKEYBOARD_WARN() << "InputContext::sendKeyClick(): no focus to send key click"
238#ifdef SENSITIVE_DEBUG
239 << key << text
240#endif
241 << "- QGuiApplication::focusWindow() is:" << QGuiApplication::focusWindow();
242 }
243}
244
245/*!
246 \qmlmethod void InputContext::commit()
247
248 Commits the current pre-edit text.
249*/
250/*!
251 \fn void QVirtualKeyboardInputContext::commit()
252
253 Commits the current pre-edit text.
254*/
255void QVirtualKeyboardInputContext::commit()
256{
257 Q_D(QVirtualKeyboardInputContext);
258 QString text = d->preeditText;
259 commit(text);
260}
261
262/*!
263 \qmlmethod void InputContext::commit(string text, int replaceFrom = 0, int replaceLength = 0)
264
265 Commits the final \a text to the input item and optionally
266 modifies the text relative to the start of the pre-edit text.
267 If \e replaceFrom is non-zero, the \a text replaces the
268 contents relative to \e replaceFrom with a length of
269 \e replaceLength.
270*/
271/*!
272 Commits the final \a text to the input item and optionally
273 modifies the text relative to the start of the pre-edit text.
274 If \a replaceFrom is non-zero, the \a text replaces the
275 contents relative to \a replaceFrom with a length of
276 \a replaceLength.
277*/
278void QVirtualKeyboardInputContext::commit(const QString &text, int replaceFrom, int replaceLength)
279{
280 Q_D(QVirtualKeyboardInputContext);
281
282 VIRTUALKEYBOARD_DEBUG() << "QVirtualKeyboardInputContext::commit()"
283#ifdef SENSITIVE_DEBUG
284 << text << replaceFrom << replaceLength
285#endif
286 ;
287 bool preeditChanged = !d->preeditText.isEmpty();
288
289 if (d->platformInputContext) {
290 QList<QInputMethodEvent::Attribute> attributes;
291 d->addSelectionAttribute(attributes);
292 d->preeditText.clear();
293 d->preeditTextAttributes.clear();
294 QInputMethodEvent inputEvent(QString(), attributes);
295 inputEvent.setCommitString(commitString: text, replaceFrom, replaceLength);
296 d->sendInputMethodEvent(event: &inputEvent);
297 } else {
298 d->preeditText.clear();
299 d->preeditTextAttributes.clear();
300 }
301
302 if (preeditChanged)
303 emit preeditTextChanged();
304}
305
306/*!
307 \qmlmethod void InputContext::clear()
308
309 Clears the pre-edit text.
310*/
311/*!
312 \fn void QVirtualKeyboardInputContext::clear()
313
314 Clears the pre-edit text.
315*/
316void QVirtualKeyboardInputContext::clear()
317{
318 Q_D(QVirtualKeyboardInputContext);
319 bool preeditChanged = !d->preeditText.isEmpty();
320 d->preeditText.clear();
321 d->preeditTextAttributes.clear();
322
323 if (d->platformInputContext) {
324 QList<QInputMethodEvent::Attribute> attributes;
325 d->addSelectionAttribute(attributes);
326 QInputMethodEvent event(QString(), attributes);
327 d->sendInputMethodEvent(event: &event);
328 }
329
330 if (preeditChanged)
331 emit preeditTextChanged();
332}
333
334/*!
335 \internal
336*/
337void QVirtualKeyboardInputContext::setSelectionOnFocusObject(const QPointF &anchorPos, const QPointF &cursorPos)
338{
339 QPlatformInputContext::setSelectionOnFocusObject(anchorPos, cursorPos);
340}
341
342/*!
343 \property QVirtualKeyboardInputContext::anchorRectIntersectsClipRect
344 \brief Holds \c true if the bounding rectangle of the selection anchor
345 intersects the exposed input item rectangle.
346
347 \sa Qt::ImAnchorRectangle, Qt::ImInputItemClipRectangle
348*/
349/*!
350 \qmlproperty bool InputContext::anchorRectIntersectsClipRect
351 \readonly
352 \brief Holds \c true if the bounding rectangle of the selection anchor
353 intersects the exposed input item rectangle.
354
355 \sa Qt::ImAnchorRectangle, Qt::ImInputItemClipRectangle
356*/
357bool QVirtualKeyboardInputContext::anchorRectIntersectsClipRect() const
358{
359 Q_D(const QVirtualKeyboardInputContext);
360 return d->anchorRectIntersectsClipRect;
361}
362
363/*!
364 \property QVirtualKeyboardInputContext::cursorRectIntersectsClipRect
365 \brief Holds \c true if the bounding rectangle of the input cursor
366 intersects the exposed input item rectangle.
367
368 \sa Qt::ImCursorRectangle, Qt::ImInputItemClipRectangle
369*/
370/*!
371 \qmlproperty bool InputContext::cursorRectIntersectsClipRect
372 \readonly
373 \brief Holds \c true if the bounding rectangle of the input cursor
374 intersects the exposed input item rectangle.
375
376 \sa Qt::ImCursorRectangle, Qt::ImInputItemClipRectangle
377*/
378bool QVirtualKeyboardInputContext::cursorRectIntersectsClipRect() const
379{
380 Q_D(const QVirtualKeyboardInputContext);
381 return d->cursorRectIntersectsClipRect;
382}
383
384/*!
385 \property QVirtualKeyboardInputContext::selectionControlVisible
386 \brief Holds \c true if the selection control is currently visible.
387*/
388/*!
389 \qmlproperty bool InputContext::selectionControlVisible
390 \readonly
391 \brief Holds \c true if the selection control is currently visible.
392*/
393bool QVirtualKeyboardInputContext::isSelectionControlVisible() const
394{
395 Q_D(const QVirtualKeyboardInputContext);
396 return d->selectionControlVisible;
397}
398
399/*!
400 \internal
401*/
402QVirtualKeyboardInputContextPrivate *QVirtualKeyboardInputContext::priv() const
403{
404 Q_D(const QVirtualKeyboardInputContext);
405 return const_cast<QVirtualKeyboardInputContextPrivate *>(d);
406}
407
408/*!
409 \qmlproperty bool InputContext::shift
410 \deprecated
411
412 Use \l shiftActive instead.
413
414 This property is changed when the shift status changes.
415*/
416
417/*!
418 \property QVirtualKeyboardInputContext::shift
419 \brief the shift status.
420 \deprecated
421
422 Use \l shiftActive instead.
423
424 This property is changed when the shift status changes.
425*/
426
427/*!
428 \qmlproperty bool InputContext::shiftActive
429 \since QtQuick.VirtualKeyboard 2.4
430
431 This property is changed when the shift status changes.
432*/
433
434/*!
435 \property QVirtualKeyboardInputContext::shiftActive
436 \brief the shift status.
437
438 This property is changed when the shift status changes.
439*/
440
441/*!
442 \qmlproperty bool InputContext::capsLock
443 \deprecated
444
445 Use \l capsLockActive instead.
446
447 This property is changed when the caps lock status changes.
448*/
449
450/*!
451 \property QVirtualKeyboardInputContext::capsLock
452 \brief the caps lock status.
453 \deprecated
454
455 Use \l capsLockActive instead.
456
457 This property is changed when the caps lock status changes.
458*/
459
460/*!
461 \qmlproperty bool InputContext::capsLockActive
462 \since QtQuick.VirtualKeyboard 2.4
463
464 This property is changed when the caps lock status changes.
465*/
466
467/*!
468 \property QVirtualKeyboardInputContext::capsLockActive
469 \brief the caps lock status.
470
471 This property is changed when the caps lock status changes.
472*/
473
474/*!
475 \qmlproperty bool InputContext::uppercase
476 \since QtQuick.VirtualKeyboard 2.2
477
478 This property is \c true when either \l shiftActive or \l capsLockActive is \c true.
479*/
480
481/*!
482 \property QVirtualKeyboardInputContext::uppercase
483 \brief the uppercase status.
484
485 This property is \c true when either \l shiftActive or \l capsLockActive is \c true.
486*/
487
488/*!
489 \qmlproperty int InputContext::anchorPosition
490 \since QtQuick.VirtualKeyboard 2.2
491
492 This property is changed when the anchor position changes.
493*/
494
495/*!
496 \property QVirtualKeyboardInputContext::anchorPosition
497 \brief the anchor position.
498
499 This property is changed when the anchor position changes.
500*/
501
502/*!
503 \qmlproperty int InputContext::cursorPosition
504
505 This property is changed when the cursor position changes.
506*/
507
508/*!
509 \property QVirtualKeyboardInputContext::cursorPosition
510 \brief the cursor position.
511
512 This property is changed when the cursor position changes.
513*/
514
515/*!
516 \qmlproperty int InputContext::inputMethodHints
517
518 This property is changed when the input method hints changes.
519*/
520
521/*!
522 \property QVirtualKeyboardInputContext::inputMethodHints
523 \brief the input method hints.
524
525 This property is changed when the input method hints changes.
526*/
527
528/*!
529 \qmlproperty string InputContext::preeditText
530
531 This property sets the pre-edit text.
532*/
533
534/*!
535 \property QVirtualKeyboardInputContext::preeditText
536 \brief the pre-edit text.
537
538 This property sets the pre-edit text.
539*/
540
541/*!
542 \qmlproperty string InputContext::surroundingText
543
544 This property is changed when the surrounding text around the cursor changes.
545*/
546
547/*!
548 \property QVirtualKeyboardInputContext::surroundingText
549 \brief the surrounding text around cursor.
550
551 This property is changed when the surrounding text around the cursor changes.
552*/
553
554/*!
555 \qmlproperty string InputContext::selectedText
556
557 This property is changed when the selected text changes.
558*/
559
560/*!
561 \property QVirtualKeyboardInputContext::selectedText
562 \brief the selected text.
563
564 This property is changed when the selected text changes.
565*/
566
567/*!
568 \qmlproperty rect InputContext::anchorRectangle
569 \since QtQuick.VirtualKeyboard 2.1
570
571 This property is changed when the anchor rectangle changes.
572*/
573
574/*!
575 \property QVirtualKeyboardInputContext::anchorRectangle
576 \brief the anchor rectangle.
577
578 This property is changed when the anchor rectangle changes.
579*/
580
581/*!
582 \qmlproperty rect InputContext::cursorRectangle
583
584 This property is changed when the cursor rectangle changes.
585*/
586
587/*!
588 \property QVirtualKeyboardInputContext::cursorRectangle
589 \brief the cursor rectangle.
590
591 This property is changed when the cursor rectangle changes.
592*/
593
594/*!
595 \qmlproperty bool InputContext::animating
596
597 Use this property to set the animating status, for example
598 during UI transitioning states.
599*/
600
601/*!
602 \property QVirtualKeyboardInputContext::animating
603 \brief the animating status.
604
605 Use this property to set the animating status, for example
606 during UI transitioning states.
607*/
608
609/*!
610 \qmlproperty string InputContext::locale
611
612 This property is changed when the input locale changes.
613*/
614
615/*!
616 \property QVirtualKeyboardInputContext::locale
617 \brief the locale.
618
619 This property is changed when the input locale changes.
620*/
621
622/*!
623 \qmlproperty QtObject InputContext::inputItem
624 \deprecated
625
626 This property is changed when the focused input item changes.
627*/
628
629/*!
630 \property QVirtualKeyboardInputContext::inputItem
631 \brief the focused input item.
632 \deprecated
633
634 This property is changed when the focused input item changes.
635*/
636
637/*!
638 \qmlproperty InputEngine InputContext::inputEngine
639
640 This property stores the input engine.
641*/
642
643/*!
644 \property QVirtualKeyboardInputContext::inputEngine
645 \brief the input engine.
646
647 This property stores the input engine.
648*/
649
650/*!
651 \property QVirtualKeyboardInputContext::priv
652 \internal
653*/
654QT_END_NAMESPACE
655

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