summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/core/render_widget_host_view_qt.cpp13
-rw-r--r--tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp93
-rw-r--r--tests/auto/quick/shared/util.h77
3 files changed, 183 insertions, 0 deletions
diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp
index 9968d3e49..980550620 100644
--- a/src/core/render_widget_host_view_qt.cpp
+++ b/src/core/render_widget_host_view_qt.cpp
@@ -1414,6 +1414,19 @@ void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev)
break;
}
+ if (m_imeInProgress && ev->type() == QEvent::TouchBegin) {
+ m_imeInProgress = false;
+ // Tell input method to commit the pre-edit string entered so far, and finish the
+ // composition operation.
+#ifdef Q_OS_WIN
+ // Yes the function name is counter-intuitive, but commit isn't actually implemented
+ // by the Windows QPA, and reset does exactly what is necessary in this case.
+ qApp->inputMethod()->reset();
+#else
+ qApp->inputMethod()->commit();
+#endif
+ }
+
// Make sure that ACTION_POINTER_DOWN is delivered before ACTION_MOVE,
// and ACTION_MOVE before ACTION_POINTER_UP.
std::sort(touchPoints.begin(), touchPoints.end(), compareTouchPoints);
diff --git a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp
index 2f9063ea5..4bc136539 100644
--- a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp
+++ b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp
@@ -35,7 +35,9 @@
#include <QtQml/QQmlEngine>
#include <QtTest/QtTest>
#include <QtWebEngine/QQuickWebEngineProfile>
+#include <private/qinputmethod_p.h>
#include <private/qquickwebengineview_p.h>
+#include <qpa/qplatforminputcontext.h>
#include <functional>
@@ -70,6 +72,8 @@ private Q_SLOTS:
void inputMethod();
void inputMethodHints();
+ void interruptImeTextComposition_data();
+ void interruptImeTextComposition();
void basicRenderingSanity();
void setZoomFactor();
void printToPdf();
@@ -450,6 +454,95 @@ void tst_QQuickWebEngineView::inputMethod()
#endif
}
+class TestInputContext : public QPlatformInputContext
+{
+public:
+ TestInputContext()
+ : commitCallCount(0)
+ , resetCallCount(0)
+ {
+ QInputMethodPrivate* inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
+ inputMethodPrivate->testContext = this;
+ }
+
+ ~TestInputContext()
+ {
+ QInputMethodPrivate* inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
+ inputMethodPrivate->testContext = 0;
+ }
+
+ virtual void commit() {
+ commitCallCount++;
+ }
+
+ virtual void reset() {
+ resetCallCount++;
+ }
+
+ int commitCallCount;
+ int resetCallCount;
+};
+
+void tst_QQuickWebEngineView::interruptImeTextComposition_data()
+{
+ QTest::addColumn<QString>("eventType");
+
+ QTest::newRow("MouseButton") << QString("MouseButton");
+#ifndef Q_OS_MACOS
+ QTest::newRow("Touch") << QString("Touch");
+#endif
+}
+
+void tst_QQuickWebEngineView::interruptImeTextComposition()
+{
+ m_window->show();
+ QTRY_VERIFY(qApp->focusObject());
+ QQuickItem *input;
+
+ QQuickWebEngineView *view = webEngineView();
+ view->loadHtml("<html><body>"
+ " <input type='text' id='input1' /><br>"
+ " <input type='text' id='input2' />"
+ "</body></html>");
+ QVERIFY(waitForLoadSucceeded(view));
+
+ runJavaScript("document.getElementById('input1').focus();");
+ QTRY_COMPARE(activeElementId(view), QStringLiteral("input1"));
+
+ TestInputContext testContext;
+
+ // Send temporary text, which makes the editor has composition 'x'
+ QList<QInputMethodEvent::Attribute> attributes;
+ QInputMethodEvent event("x", attributes);
+ input = qobject_cast<QQuickItem *>(qApp->focusObject());
+ QGuiApplication::sendEvent(input, &event);
+ QTRY_COMPARE(elementValue(view, "input1"), QStringLiteral("x"));
+
+ // Focus 'input2' input field by an input event
+ QFETCH(QString, eventType);
+ if (eventType == "MouseButton") {
+ QPoint textInputCenter = elementCenter(view, QStringLiteral("input2"));
+ QTest::mouseClick(view->window(), Qt::LeftButton, 0, textInputCenter);
+ } else if (eventType == "Touch") {
+ QPoint textInputCenter = elementCenter(view, QStringLiteral("input2"));
+ QTouchDevice *touchDevice = QTest::createTouchDevice();
+ QTest::touchEvent(view->window(), touchDevice).press(0, textInputCenter, view->window());
+ QTest::touchEvent(view->window(), touchDevice).release(0, textInputCenter, view->window());
+ }
+ QTRY_COMPARE(activeElementId(view), QStringLiteral("input2"));
+#ifndef Q_OS_WIN
+ QTRY_COMPARE(testContext.commitCallCount, 1);
+#else
+ QTRY_COMPARE(testContext.resetCallCount, 2);
+#endif
+
+ // Check the composition text has been committed
+ runJavaScript("document.getElementById('input1').focus();");
+ QTRY_COMPARE(activeElementId(view), QStringLiteral("input1"));
+ input = qobject_cast<QQuickItem *>(qApp->focusObject());
+ QTRY_COMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QStringLiteral("x"));
+}
+
void tst_QQuickWebEngineView::inputMethodHints()
{
#if !defined(QQUICKWEBENGINEVIEW_ITEMACCEPTSINPUTMETHOD)
diff --git a/tests/auto/quick/shared/util.h b/tests/auto/quick/shared/util.h
index dce0afb8e..8e7169be7 100644
--- a/tests/auto/quick/shared/util.h
+++ b/tests/auto/quick/shared/util.h
@@ -142,4 +142,81 @@ inline QString bodyInnerText(QQuickWebEngineView *webEngineView)
return arguments.at(1).toString();
}
+inline QString activeElementId(QQuickWebEngineView *webEngineView)
+{
+ qRegisterMetaType<QQuickWebEngineView::JavaScriptConsoleMessageLevel>("JavaScriptConsoleMessageLevel");
+ QSignalSpy consoleMessageSpy(webEngineView, &QQuickWebEngineView::javaScriptConsoleMessage);
+
+ webEngineView->runJavaScript(
+ "if (document.activeElement == null)"
+ " console.log('');"
+ "else"
+ " console.log(document.activeElement.id);"
+ );
+
+ if (!consoleMessageSpy.wait())
+ return QString();
+
+ QList<QVariant> arguments = consoleMessageSpy.takeFirst();
+ if (static_cast<QQuickWebEngineView::JavaScriptConsoleMessageLevel>(arguments.at(0).toInt()) != QQuickWebEngineView::InfoMessageLevel)
+ return QString();
+
+ return arguments.at(1).toString();
+}
+
+inline QString elementValue(QQuickWebEngineView *webEngineView, const QString &id)
+{
+ qRegisterMetaType<QQuickWebEngineView::JavaScriptConsoleMessageLevel>("JavaScriptConsoleMessageLevel");
+ QSignalSpy consoleMessageSpy(webEngineView, &QQuickWebEngineView::javaScriptConsoleMessage);
+
+ webEngineView->runJavaScript(QString(
+ "var element = document.getElementById('" + id + "');"
+ "if (element == null)"
+ " console.log('');"
+ "else"
+ " console.log(element.value);")
+ );
+
+ if (!consoleMessageSpy.wait())
+ return QString();
+
+ QList<QVariant> arguments = consoleMessageSpy.takeFirst();
+ if (static_cast<QQuickWebEngineView::JavaScriptConsoleMessageLevel>(arguments.at(0).toInt()) != QQuickWebEngineView::InfoMessageLevel)
+ return QString();
+
+ return arguments.at(1).toString();
+}
+
+inline QPoint elementCenter(QQuickWebEngineView *webEngineView, const QString &id)
+{
+ qRegisterMetaType<QQuickWebEngineView::JavaScriptConsoleMessageLevel>("JavaScriptConsoleMessageLevel");
+ QSignalSpy consoleMessageSpy(webEngineView, &QQuickWebEngineView::javaScriptConsoleMessage);
+
+ webEngineView->runJavaScript(QString(
+ "var element = document.getElementById('" + id + "');"
+ "var rect = element.getBoundingClientRect();"
+ "console.log((rect.left + rect.right) / 2);"
+ "console.log((rect.top + rect.bottom) / 2);")
+ );
+
+ QTRY_LOOP_IMPL(consoleMessageSpy.count() == 2, 5000, 50);
+ if (consoleMessageSpy.count() != 2)
+ return QPoint();
+
+ QList<QVariant> arguments;
+ double x, y;
+
+ arguments = consoleMessageSpy.takeFirst();
+ if (static_cast<QQuickWebEngineView::JavaScriptConsoleMessageLevel>(arguments.at(0).toInt()) != QQuickWebEngineView::InfoMessageLevel)
+ return QPoint();
+ x = arguments.at(1).toDouble();
+
+ arguments = consoleMessageSpy.takeLast();
+ if (static_cast<QQuickWebEngineView::JavaScriptConsoleMessageLevel>(arguments.at(0).toInt()) != QQuickWebEngineView::InfoMessageLevel)
+ return QPoint();
+ y = arguments.at(1).toDouble();
+
+ return QPoint(x, y);
+}
+
#endif /* UTIL_H */