From e9309d91ac3ec0ddd7076b5cf66655380aa82cac Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Fri, 8 Sep 2017 13:21:38 +0200 Subject: Fix position of keyboard-invoked context menu in QQuickWebEngineView In QQuickWebEngineView the context menu is a QtQuickControls.Menu item. This menu is shown by calling popup() which always displays the menu below the mouse cursor. Work around the problem by moving the mouse cursor temporarily to the right position. Use a QObject property "pos" to store the requested menu position between addMenu() and showMenu() calls, because the Menu item doesn't have a "pos" QML property. Change-Id: Id772a0bb1a7548cad932e9f499ade68be32d86d3 Reviewed-by: Peter Varga --- src/webengine/ui_delegates_manager.cpp | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/webengine/ui_delegates_manager.cpp b/src/webengine/ui_delegates_manager.cpp index 6cc496d5b..c9c013d52 100644 --- a/src/webengine/ui_delegates_manager.cpp +++ b/src/webengine/ui_delegates_manager.cpp @@ -257,7 +257,7 @@ QObject *UIDelegatesManager::addMenu(QObject *parentMenu, const QString &title, if (!title.isEmpty()) QQmlProperty(menu, QStringLiteral("title")).write(title); if (!pos.isNull()) - QQmlProperty(menu, QStringLiteral("pos")).write(pos); + menu->setProperty("pos", pos); menu->setParent(parentMenu); @@ -496,9 +496,38 @@ void UIDelegatesManager::showFilePicker(QSharedPointer con QMetaObject::invokeMethod(filePicker, "open"); } +class TemporaryCursorMove +{ +public: + TemporaryCursorMove(const QQuickItem *item, const QPoint &pos) + { + if (pos.isNull() || !item->contains(pos)) + return; + const QPoint oldPos = QCursor::pos(); + const QPoint globalPos = item->mapToGlobal(QPointF(pos)).toPoint(); + if (oldPos == globalPos) + return; + m_oldCursorPos = oldPos; + QCursor::setPos(globalPos); + } + + ~TemporaryCursorMove() + { + if (!m_oldCursorPos.isNull()) + QCursor::setPos(m_oldCursorPos); + } + +private: + QPoint m_oldCursorPos; +}; + void UIDelegatesManager::showMenu(QObject *menu) { - QMetaObject::invokeMethod(menu, "popup"); + // QtQuick.Controls.Menu.popup() always shows the menu under the mouse cursor, i.e. the menu's + // position we set above is ignored. Work around the problem by moving the mouse cursor + // temporarily to the right position. + TemporaryCursorMove tcm(m_view, menu->property("pos").toPoint()); + QMetaObject::invokeMethod(menu, "popup"); } void UIDelegatesManager::showMessageBubble(const QRect &anchor, const QString &mainText, const QString &subText) -- cgit v1.2.3