diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 013993b3f88..3030e11f253 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -108,6 +108,7 @@ QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcPopup, "qt.gui.popup"); +Q_LOGGING_CATEGORY(lcVirtualKeyboard, "qt.gui.virtualkeyboard"); using namespace Qt::StringLiterals; using namespace QtMiscUtils; @@ -2109,6 +2110,59 @@ bool QGuiApplicationPrivate::processNativeEvent(QWindow *window, const QByteArra return window->nativeEvent(eventType, message, result); } +bool QGuiApplicationPrivate::isUsingVirtualKeyboard() +{ + static const bool usingVirtualKeyboard = getenv("QT_IM_MODULE") == QByteArray("qtvirtualkeyboard"); + return usingVirtualKeyboard; +} + +// If a virtual keyboard exists, forward mouse event +bool QGuiApplicationPrivate::maybeForwardEventToVirtualKeyboard(QEvent *e) +{ + if (!isUsingVirtualKeyboard()) { + qCDebug(lcVirtualKeyboard) << "Virtual keyboard not supported."; + return false; + } + + static QPointer virtualKeyboard; + const QEvent::Type type = e->type(); + Q_ASSERT(type == QEvent::MouseButtonPress || type == QEvent::MouseButtonRelease); + const auto me = static_cast(e); + const QPointF posF = me->globalPosition(); + const QPoint pos = posF.toPoint(); + + // Is there a visible virtual keyboard at event position? + if (!virtualKeyboard) { + if (QWindow *win = QGuiApplication::topLevelAt(pos); + win->inherits("QtVirtualKeyboard::InputView")) { + virtualKeyboard = win; + } else { + qCDebug(lcVirtualKeyboard) << "Virtual keyboard supported, but inactive."; + return false; + } + } + + Q_ASSERT(virtualKeyboard); + const bool virtualKeyboardUnderMouse = virtualKeyboard->isVisible() + && virtualKeyboard->geometry().contains(pos); + + if (!virtualKeyboardUnderMouse) { + qCDebug(lcVirtualKeyboard) << type << "at" << pos << "is outside geometry" + << virtualKeyboard->geometry() << "of" << virtualKeyboard.data(); + return false; + } + + QMouseEvent vkbEvent(type, virtualKeyboard->mapFromGlobal(pos), pos, + me->button(), me->buttons(), me->modifiers(), + me->pointingDevice()); + + QGuiApplication::sendEvent(virtualKeyboard, &vkbEvent); + qCDebug(lcVirtualKeyboard) << "Forwarded" << type << "to" << virtualKeyboard.data() + << "at" << pos; + + return true; +} + void Q_TRACE_INSTRUMENT(qtgui) QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e) { Q_TRACE_PARAM_REPLACE(QWindowSystemInterfacePrivate::WindowSystemEvent *, int); diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h index 81f616e773c..45eac1c2654 100644 --- a/src/gui/kernel/qguiapplication_p.h +++ b/src/gui/kernel/qguiapplication_p.h @@ -40,6 +40,9 @@ QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(lcPopup) +Q_DECLARE_LOGGING_CATEGORY(lcVirtualKeyboard) + class QColorTrcLut; class QPlatformIntegration; class QPlatformTheme; @@ -165,6 +168,9 @@ public: static bool sendQWindowEventToQPlatformWindow(QWindow *window, QEvent *event); + static bool maybeForwardEventToVirtualKeyboard(QEvent *e); + static bool isUsingVirtualKeyboard(); + static inline Qt::Alignment visualAlignment(Qt::LayoutDirection direction, Qt::Alignment alignment) { if (!(alignment & Qt::AlignHorizontal_Mask)) diff --git a/src/widgets/util/qcompleter.cpp b/src/widgets/util/qcompleter.cpp index 21612ad6d16..bc965806dec 100644 --- a/src/widgets/util/qcompleter.cpp +++ b/src/widgets/util/qcompleter.cpp @@ -1463,12 +1463,16 @@ bool QCompleter::eventFilter(QObject *o, QEvent *e) } #endif if (!d->popup->underMouse()) { - d->popup->hide(); + if (!QGuiApplicationPrivate::maybeForwardEventToVirtualKeyboard(e)) + d->popup->hide(); return true; } } return false; + case QEvent::MouseButtonRelease: + QGuiApplicationPrivate::maybeForwardEventToVirtualKeyboard(e); + return true; case QEvent::InputMethod: case QEvent::ShortcutOverride: QCoreApplication::sendEvent(d->widget, e);