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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

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