summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Varga <pvarga@inf.u-szeged.hu>2017-09-05 16:10:41 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-09-17 00:39:59 +0000
commita12a811026baa86d7d8e4728d893114c76feec20 (patch)
tree102b3893f438dad2a48ebe3454ede5a2b2c218f0
parenta6d3799cf34569f5618e4b95f56a42f0e350e403 (diff)
Commit the done-so-far IME composition on touch event
Fix is based on afc9e2d9674f7ab5800df4803cc68c71d1ae691a Moreover, new quick auto test has been added to check that the commit happens in case mouse and touch input events. Task-number: QTBUG-62942 Change-Id: Ie9d55e0bb5b3bbc34c099502e735b94f37c5d5f8 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
-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 9968d3e4..98055062 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 2f9063ea..4bc13653 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 dce0afb8..8e7169be 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 */