Revision control

++ // Copyright (C) 2016 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
++ // Qt-Security score:significant reason:default
++
++ #include <QtVirtualKeyboard/qvirtualkeyboardinputcontext.h>
++ #include <QtVirtualKeyboard/private/qvirtualkeyboardinputcontext_p.h>
++ #include <QtVirtualKeyboard/private/shifthandler_p.h>
++ #include <QtVirtualKeyboard/private/platforminputcontext_p.h>
++ #include <QtVirtualKeyboard/private/virtualkeyboarddebug_p.h>
++ #include <QtVirtualKeyboard/qvirtualkeyboardobserver.h>
++
++ #include <QTextFormat>
++ #include <QGuiApplication>
++ #include <QtGui/private/qhighdpiscaling_p.h>
++
++ QT_BEGIN_NAMESPACE
++ using namespace QtVirtualKeyboard;
++
++ /*!
++ \qmltype InputContext
++ \nativetype QVirtualKeyboardInputContext
++ \inqmlmodule QtQuick.VirtualKeyboard
++ \ingroup qtvirtualkeyboard-internal-qml
++ \brief Provides access to an input context.
++
++ The InputContext can be accessed as singleton instance.
++ */
++
++ /*!
++ \class QVirtualKeyboardInputContext
++ \inmodule QtVirtualKeyboard
++ \ingroup qtvirtualkeyboard-cpp-for-devs
++ \brief Provides access to an input context.
++ */
++
++ /*!
++ \internal
++ Constructs an input context with \a parent as the platform input
++ context.
++ */
++ QVirtualKeyboardInputContext::QVirtualKeyboardInputContext(QObject *parent) :
++ QObject(parent),
++ d_ptr(new QVirtualKeyboardInputContextPrivate(this))
++ {
++ Q_D(QVirtualKeyboardInputContext);
++ d->init();
++ QObject::connect(d->_shiftHandler, &ShiftHandler::shiftActiveChanged, this, &QVirtualKeyboardInputContext::shiftActiveChanged);
++ QObject::connect(d->_shiftHandler, &ShiftHandler::capsLockActiveChanged, this, &QVirtualKeyboardInputContext::capsLockActiveChanged);
++ QObject::connect(d->_shiftHandler, &ShiftHandler::uppercaseChanged, this, &QVirtualKeyboardInputContext::uppercaseChanged);
++ QObject::connect(d, &QVirtualKeyboardInputContextPrivate::localeChanged, this, &QVirtualKeyboardInputContext::localeChanged);
++ QObject::connect(d, &QVirtualKeyboardInputContextPrivate::inputItemChanged, this, &QVirtualKeyboardInputContext::inputItemChanged);
++ }
++
++ /*!
++ \internal
++ Destroys the input context and frees all allocated resources.
++ */
++ QVirtualKeyboardInputContext::~QVirtualKeyboardInputContext()
++ {
++ }
++
++ bool QVirtualKeyboardInputContext::isShiftActive() const
++ {
++ Q_D(const QVirtualKeyboardInputContext);
++ return d->_shiftHandler->isShiftActive();
++ }
++
++ bool QVirtualKeyboardInputContext::isCapsLockActive() const
++ {
++ Q_D(const QVirtualKeyboardInputContext);
++ return d->_shiftHandler->isCapsLockActive();
++ }
++
++ bool QVirtualKeyboardInputContext::isUppercase() const
++ {
++ Q_D(const QVirtualKeyboardInputContext);
++ return d->_shiftHandler->isUppercase();
++ }
++
++ int QVirtualKeyboardInputContext::anchorPosition() const
++ {
++ Q_D(const QVirtualKeyboardInputContext);
++ return d->anchorPosition;
++ }
++
++ int QVirtualKeyboardInputContext::cursorPosition() const
++ {
++ Q_D(const QVirtualKeyboardInputContext);
++ return d->cursorPosition;
++ }
++
++ Qt::InputMethodHints QVirtualKeyboardInputContext::inputMethodHints() const
++ {
++ Q_D(const QVirtualKeyboardInputContext);
++ return d->inputMethodHints;
++ }
++
++ QString QVirtualKeyboardInputContext::preeditText() const
++ {
++ Q_D(const QVirtualKeyboardInputContext);
++ return d->preeditText;
++ }
++
++ void QVirtualKeyboardInputContext::setPreeditText(const QString &text, QList<QInputMethodEvent::Attribute> attributes, int replaceFrom, int replaceLength)
++ {
++ Q_D(QVirtualKeyboardInputContext);
++ // Add default attributes
++ if (!text.isEmpty()) {
++ if (!d->testAttribute(attributes, QInputMethodEvent::TextFormat)) {
++ QTextCharFormat textFormat;
++ textFormat.setUnderlineStyle(QTextCharFormat::SingleUnderline);
++ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, 0, text.size(), textFormat));
++ }
++ } else if (d->_forceCursorPosition != -1) {
++ d->addSelectionAttribute(attributes);
++ }
++
++ d->sendPreedit(text, attributes, replaceFrom, replaceLength);
++ }
++
++ QList<QInputMethodEvent::Attribute> QVirtualKeyboardInputContext::preeditTextAttributes() const
++ {
++ Q_D(const QVirtualKeyboardInputContext);
++ return d->preeditTextAttributes;
++ }
++
++ QString QVirtualKeyboardInputContext::surroundingText() const
++ {
++ Q_D(const QVirtualKeyboardInputContext);
++ return d->surroundingText;
++ }
++
++ QString QVirtualKeyboardInputContext::selectedText() const
++ {
++ Q_D(const QVirtualKeyboardInputContext);
++ return d->selectedText;
++ }
++
++ QRectF QVirtualKeyboardInputContext::anchorRectangle() const
++ {
++ Q_D(const QVirtualKeyboardInputContext);
++ return d->anchorRectangle;
++ }
++
++ QRectF QVirtualKeyboardInputContext::cursorRectangle() const
++ {
++ Q_D(const QVirtualKeyboardInputContext);
++ return d->cursorRectangle;
++ }
++
++ bool QVirtualKeyboardInputContext::isAnimating() const
++ {
++ Q_D(const QVirtualKeyboardInputContext);
++ return d->animating;
++ }
++
++ void QVirtualKeyboardInputContext::setAnimating(bool animating)
++ {
++ Q_D(QVirtualKeyboardInputContext);
++ if (d->animating != animating) {
++ VIRTUALKEYBOARD_DEBUG() << "QVirtualKeyboardInputContext::setAnimating():" << animating;
++ d->animating = animating;
++ emit animatingChanged();
++ d->platformInputContext->emitAnimatingChanged();
++ }
++ }
++
++ QString QVirtualKeyboardInputContext::locale() const
++ {
++ Q_D(const QVirtualKeyboardInputContext);
++ return d->locale();
++ }
++
++ QObject *QVirtualKeyboardInputContext::inputItem() const
++ {
++ Q_D(const QVirtualKeyboardInputContext);
++ return d->inputItem();
++ }
++
++ QVirtualKeyboardInputEngine *QVirtualKeyboardInputContext::inputEngine() const
++ {
++ Q_D(const QVirtualKeyboardInputContext);
++ return d->inputEngine;
++ }
++
++ /*!
++ \qmlmethod void InputContext::sendKeyClick(int key, string text, int modifiers = 0)
++
++ Sends a key click event with the given \a key, \a text and \a modifiers to
++ the input item that currently has focus.
++ */
++ /*!
++ Sends a key click event with the given \a key, \a text and \a modifiers to
++ the input item that currently has focus.
++ */
++ void QVirtualKeyboardInputContext::sendKeyClick(int key, const QString &text, int modifiers)
++ {
++ Q_D(QVirtualKeyboardInputContext);
++ if ((d->_focus && d->platformInputContext) || QtVirtualKeyboard::forceEventsWithoutFocus()) {
++ QKeyEvent pressEvent(QEvent::KeyPress, key, Qt::KeyboardModifiers(modifiers), text);
++ QKeyEvent releaseEvent(QEvent::KeyRelease, key, Qt::KeyboardModifiers(modifiers), text);
++ VIRTUALKEYBOARD_DEBUG().nospace() << "InputContext::sendKeyClick()"
++ #ifdef SENSITIVE_DEBUG
++ << ": " << key
++ #endif
++ ;
++
++
++ d->setState(QVirtualKeyboardInputContextPrivate::State::KeyEvent);
++ d->platformInputContext->sendKeyEvent(&pressEvent);
++ d->platformInputContext->sendKeyEvent(&releaseEvent);
++
++ if (key == Qt::Key_Return || key == Qt::Key_Enter)
++ d->maybeCloseOnReturn();
++
++ if (d->activeKeys.isEmpty())
++ d->clearState(QVirtualKeyboardInputContextPrivate::State::KeyEvent);
++ } else {
++ VIRTUALKEYBOARD_WARN() << "InputContext::sendKeyClick(): no focus to send key click"
++ #ifdef SENSITIVE_DEBUG
++ << key << text
++ #endif
++ << "- QGuiApplication::focusWindow() is:" << QGuiApplication::focusWindow();
++ }
++ }
++
++ /*!
++ \qmlmethod void InputContext::commit()
++
++ Commits the current pre-edit text.
++ */
++ /*!
++ \fn void QVirtualKeyboardInputContext::commit()
++
++ Commits the current pre-edit text.
++ */
++ void QVirtualKeyboardInputContext::commit()
++ {
++ Q_D(QVirtualKeyboardInputContext);
++ QString text = d->preeditText;
++ commit(text);
++ }
++
++ /*!
++ \qmlmethod void InputContext::commit(string text, int replaceFrom = 0, int replaceLength = 0)
++
++ Commits the final \a text to the input item and optionally
++ modifies the text relative to the start of the pre-edit text.
++ If \e replaceFrom is non-zero, the \a text replaces the
++ contents relative to \e replaceFrom with a length of
++ \e replaceLength.
++ */
++ /*!
++ Commits the final \a text to the input item and optionally
++ modifies the text relative to the start of the pre-edit text.
++ If \a replaceFrom is non-zero, the \a text replaces the
++ contents relative to \a replaceFrom with a length of
++ \a replaceLength.
++ */
++ void QVirtualKeyboardInputContext::commit(const QString &text, int replaceFrom, int replaceLength)
++ {
++ Q_D(QVirtualKeyboardInputContext);
++
++ VIRTUALKEYBOARD_DEBUG() << "QVirtualKeyboardInputContext::commit()"
++ #ifdef SENSITIVE_DEBUG
++ << text << replaceFrom << replaceLength
++ #endif
++ ;
++ bool preeditChanged = !d->preeditText.isEmpty();
++
++ if (d->platformInputContext) {
++ QList<QInputMethodEvent::Attribute> attributes;
++ d->addSelectionAttribute(attributes);
++ d->preeditText.clear();
++ d->preeditTextAttributes.clear();
++ QInputMethodEvent inputEvent(QString(), attributes);
++ inputEvent.setCommitString(text, replaceFrom, replaceLength);
++ d->sendInputMethodEvent(&inputEvent);
++ } else {
++ d->preeditText.clear();
++ d->preeditTextAttributes.clear();
++ }
++
++ if (preeditChanged)
++ emit preeditTextChanged();
++ }
++
++ /*!
++ \qmlmethod void InputContext::clear()
++
++ Clears the pre-edit text.
++ */
++ /*!
++ \fn void QVirtualKeyboardInputContext::clear()
++
++ Clears the pre-edit text.
++ */
++ void QVirtualKeyboardInputContext::clear()
++ {
++ Q_D(QVirtualKeyboardInputContext);
++ bool preeditChanged = !d->preeditText.isEmpty();
++ d->preeditText.clear();
++ d->preeditTextAttributes.clear();
++
++ if (d->platformInputContext) {
++ QList<QInputMethodEvent::Attribute> attributes;
++ d->addSelectionAttribute(attributes);
++ QInputMethodEvent event(QString(), attributes);
++ d->sendInputMethodEvent(&event);
++ }
++
++ if (preeditChanged)
++ emit preeditTextChanged();
++ }
++
++ /*!
++ \internal
++ */
++ void QVirtualKeyboardInputContext::setSelectionOnFocusObject(const QPointF &anchorPos, const QPointF &cursorPos)
++ {
++ QWindow *window = qApp->focusWindow();
++ const QPointF &nativeAnchorPos = QHighDpi::toNativePixels(anchorPos, window);
++ const QPointF &nativeCursorPos = QHighDpi::toNativePixels(cursorPos, window);
++
++ QPlatformInputContext::setSelectionOnFocusObject(nativeAnchorPos, nativeCursorPos);
++ }
++
++ /*!
++ \property QVirtualKeyboardInputContext::anchorRectIntersectsClipRect
++ \brief Holds \c true if the bounding rectangle of the selection anchor
++ intersects the exposed input item rectangle.
++
++ \sa Qt::ImAnchorRectangle, Qt::ImInputItemClipRectangle
++ */
++ /*!
++ \qmlproperty bool InputContext::anchorRectIntersectsClipRect
++ \readonly
++ \brief Holds \c true if the bounding rectangle of the selection anchor
++ intersects the exposed input item rectangle.
++
++ \sa Qt::ImAnchorRectangle, Qt::ImInputItemClipRectangle
++ */
++ bool QVirtualKeyboardInputContext::anchorRectIntersectsClipRect() const
++ {
++ Q_D(const QVirtualKeyboardInputContext);
++ return d->anchorRectIntersectsClipRect;
++ }
++
++ /*!
++ \property QVirtualKeyboardInputContext::cursorRectIntersectsClipRect
++ \brief Holds \c true if the bounding rectangle of the input cursor
++ intersects the exposed input item rectangle.
++
++ \sa Qt::ImCursorRectangle, Qt::ImInputItemClipRectangle
++ */
++ /*!
++ \qmlproperty bool InputContext::cursorRectIntersectsClipRect
++ \readonly
++ \brief Holds \c true if the bounding rectangle of the input cursor
++ intersects the exposed input item rectangle.
++
++ \sa Qt::ImCursorRectangle, Qt::ImInputItemClipRectangle
++ */
++ bool QVirtualKeyboardInputContext::cursorRectIntersectsClipRect() const
++ {
++ Q_D(const QVirtualKeyboardInputContext);
++ return d->cursorRectIntersectsClipRect;
++ }
++
++ /*!
++ \property QVirtualKeyboardInputContext::selectionControlVisible
++ \brief Holds \c true if the selection control is currently visible.
++ */
++ /*!
++ \qmlproperty bool InputContext::selectionControlVisible
++ \readonly
++ \brief Holds \c true if the selection control is currently visible.
++ */
++ bool QVirtualKeyboardInputContext::isSelectionControlVisible() const
++ {
++ Q_D(const QVirtualKeyboardInputContext);
++ return d->selectionControlVisible;
++ }
++
++ /*!
++ \internal
++ */
++ QVirtualKeyboardInputContextPrivate *QVirtualKeyboardInputContext::priv() const
++ {
++ Q_D(const QVirtualKeyboardInputContext);
++ return const_cast<QVirtualKeyboardInputContextPrivate *>(d);
++ }
++
++ /*!
++ \property QVirtualKeyboardInputContext::keyboardObserver
++ \since 6.1
++ \brief Holds the keyboard observer object, which can be used to receive
++ notifications of keyboard change events.
++ */
++ /*!
++ \qmlproperty KeyboardObserver InputContext::keyboardObserver
++ \readonly
++ \since 6.1
++ \brief Holds the keyboard observer object, which can be used to receive
++ notifications of keyboard change events.
++ */
++ QVirtualKeyboardObserver *QVirtualKeyboardInputContext::keyboardObserver() const
++ {
++ Q_D(const QVirtualKeyboardInputContext);
++ return d->keyboardObserver;
++ }
++
++ /*!
++ \qmlproperty bool InputContext::shift
++ \deprecated
++
++ Use \l shiftActive instead.
++
++ This property is changed when the shift status changes.
++ */
++
++ /*!
++ \property QVirtualKeyboardInputContext::shift
++ \brief the shift status.
++ \deprecated
++
++ Use \l shiftActive instead.
++
++ This property is changed when the shift status changes.
++ */
++
++ /*!
++ \qmlproperty bool InputContext::shiftActive
++ \since QtQuick.VirtualKeyboard 2.4
++
++ This property is changed when the shift status changes.
++ */
++
++ /*!
++ \property QVirtualKeyboardInputContext::shiftActive
++ \brief the shift status.
++
++ This property is changed when the shift status changes.
++ */
++
++ /*!
++ \qmlproperty bool InputContext::capsLock
++ \deprecated
++
++ Use \l capsLockActive instead.
++
++ This property is changed when the caps lock status changes.
++ */
++
++ /*!
++ \property QVirtualKeyboardInputContext::capsLock
++ \brief the caps lock status.
++ \deprecated
++
++ Use \l capsLockActive instead.
++
++ This property is changed when the caps lock status changes.
++ */
++
++ /*!
++ \qmlproperty bool InputContext::capsLockActive
++ \since QtQuick.VirtualKeyboard 2.4
++
++ This property is changed when the caps lock status changes.
++ */
++
++ /*!
++ \property QVirtualKeyboardInputContext::capsLockActive
++ \brief the caps lock status.
++
++ This property is changed when the caps lock status changes.
++ */
++
++ /*!
++ \qmlproperty bool InputContext::uppercase
++ \since QtQuick.VirtualKeyboard 2.2
++
++ This property is \c true when either \l shiftActive or \l capsLockActive is \c true.
++ */
++
++ /*!
++ \property QVirtualKeyboardInputContext::uppercase
++ \brief the uppercase status.
++
++ This property is \c true when either \l shiftActive or \l capsLockActive is \c true.
++ */
++
++ /*!
++ \qmlproperty int InputContext::anchorPosition
++ \since QtQuick.VirtualKeyboard 2.2
++
++ This property is changed when the anchor position changes.
++ */
++
++ /*!
++ \property QVirtualKeyboardInputContext::anchorPosition
++ \brief the anchor position.
++
++ This property is changed when the anchor position changes.
++ */
++
++ /*!
++ \qmlproperty int InputContext::cursorPosition
++
++ This property is changed when the cursor position changes.
++ */
++
++ /*!
++ \property QVirtualKeyboardInputContext::cursorPosition
++ \brief the cursor position.
++
++ This property is changed when the cursor position changes.
++ */
++
++ /*!
++ \qmlproperty int InputContext::inputMethodHints
++
++ This property is changed when the input method hints changes.
++ */
++
++ /*!
++ \property QVirtualKeyboardInputContext::inputMethodHints
++ \brief the input method hints.
++
++ This property is changed when the input method hints changes.
++ */
++
++ /*!
++ \qmlproperty string InputContext::preeditText
++
++ This property sets the pre-edit text.
++ */
++
++ /*!
++ \property QVirtualKeyboardInputContext::preeditText
++ \brief the pre-edit text.
++
++ This property sets the pre-edit text.
++ */
++
++ /*!
++ \qmlproperty string InputContext::surroundingText
++
++ This property is changed when the surrounding text around the cursor changes.
++ */
++
++ /*!
++ \property QVirtualKeyboardInputContext::surroundingText
++ \brief the surrounding text around cursor.
++
++ This property is changed when the surrounding text around the cursor changes.
++ */
++
++ /*!
++ \qmlproperty string InputContext::selectedText
++
++ This property is changed when the selected text changes.
++ */
++
++ /*!
++ \property QVirtualKeyboardInputContext::selectedText
++ \brief the selected text.
++
++ This property is changed when the selected text changes.
++ */
++
++ /*!
++ \qmlproperty rect InputContext::anchorRectangle
++ \since QtQuick.VirtualKeyboard 2.1
++
++ This property is changed when the anchor rectangle changes.
++ */
++
++ /*!
++ \property QVirtualKeyboardInputContext::anchorRectangle
++ \brief the anchor rectangle.
++
++ This property is changed when the anchor rectangle changes.
++ */
++
++ /*!
++ \qmlproperty rect InputContext::cursorRectangle
++
++ This property is changed when the cursor rectangle changes.
++ */
++
++ /*!
++ \property QVirtualKeyboardInputContext::cursorRectangle
++ \brief the cursor rectangle.
++
++ This property is changed when the cursor rectangle changes.
++ */
++
++ /*!
++ \qmlproperty bool InputContext::animating
++
++ Use this property to set the animating status, for example
++ during UI transitioning states.
++ */
++
++ /*!
++ \property QVirtualKeyboardInputContext::animating
++ \brief the animating status.
++
++ Use this property to set the animating status, for example
++ during UI transitioning states.
++ */
++
++ /*!
++ \qmlproperty string InputContext::locale
++
++ This property is changed when the input locale changes.
++ */
++
++ /*!
++ \property QVirtualKeyboardInputContext::locale
++ \brief the locale.
++
++ This property is changed when the input locale changes.
++ */
++
++ /*!
++ \qmlproperty QtObject InputContext::inputItem
++ \deprecated
++
++ Use \l {QtQuick::Window::activeFocusItem}{Window.activeFocusItem}
++ instead. This property was never intended as public API; it was exposed
++ only for the internal use of the virtual keyboard.
++
++ This property is changed when the focused input item changes.
++
++ \note If you are tracking the input item in order to react to the
++ keyboard geometry or to the cursor position, prefer the input method
++ properties in \l {Qt::inputMethod}{Qt.inputMethod}, such as
++ \l {QInputMethod::keyboardRectangle}{keyboardRectangle} and
++ \l {QInputMethod::cursorRectangle}{cursorRectangle}. Those work
++ independently of the virtual keyboard and do not require access to the
++ focused item itself.
++ */
++
++ /*!
++ \property QVirtualKeyboardInputContext::inputItem
++ \brief the focused input item.
++ \deprecated
++
++ Use \l QGuiApplication::focusObject() instead. This property was never
++ intended as public API; it was exposed only for the internal use of the
++ virtual keyboard.
++
++ This property is changed when the focused input item changes.
++
++ \note If you are tracking the input item in order to react to the
++ keyboard geometry or to the cursor position, prefer \l QInputMethod,
++ which provides \l {QInputMethod::keyboardRectangle}{keyboardRectangle}
++ and \l {QInputMethod::cursorRectangle}{cursorRectangle} without
++ requiring access to the focused item itself.
++ */
++
++ /*!
++ \qmlproperty InputEngine InputContext::inputEngine
++
++ This property stores the input engine.
++ */
++
++ /*!
++ \property QVirtualKeyboardInputContext::inputEngine
++ \brief the input engine.
++
++ This property stores the input engine.
++ */
++
++ /*!
++ \property QVirtualKeyboardInputContext::priv
++ \internal
++ */
++ QT_END_NAMESPACE