summaryrefslogtreecommitdiffstats
path: root/tests/auto
diff options
context:
space:
mode:
authorPeter Varga <pvarga@inf.u-szeged.hu>2018-11-21 14:09:38 +0100
committerPeter Varga <pvarga@inf.u-szeged.hu>2018-11-29 13:26:18 +0000
commit35ee29eb348b4629f47a6b700f9e2c356265aeba (patch)
treeb33d72bf152b494f7c5b7017fdc218da1d975a07 /tests/auto
parentce7d46d6122c0af2c5820d51bbb804bc81cdefa7 (diff)
Fix input method update
Do the update after the input properties are changed in RenderWidgetHostViewQt. Moreover, always update on input state changes, like cursor position, surrounding text and text selection (see QInputMethod::update() docs). Task-number: QTBUG-70158 Task-number: QTBUG-71995 Change-Id: I9d5c6e299826fbe66f5285b648013ef79aabed9b Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'tests/auto')
-rw-r--r--tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp184
-rw-r--r--tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp189
2 files changed, 373 insertions, 0 deletions
diff --git a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp
index 5cb904fb6..cf08ccd1d 100644
--- a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp
+++ b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp
@@ -75,6 +75,7 @@ private Q_SLOTS:
void inputMethod();
void inputMethodHints();
+ void inputContextQueryInput();
void interruptImeTextComposition_data();
void interruptImeTextComposition();
void basicRenderingSanity();
@@ -471,6 +472,24 @@ void tst_QQuickWebEngineView::inputMethod()
QVERIFY(!view->flags().testFlag(QQuickItem::ItemAcceptsInputMethod));
}
+struct InputMethodInfo
+{
+ InputMethodInfo(const int cursorPosition,
+ const int anchorPosition,
+ QString surroundingText,
+ QString selectedText)
+ : cursorPosition(cursorPosition)
+ , anchorPosition(anchorPosition)
+ , surroundingText(surroundingText)
+ , selectedText(selectedText)
+ {}
+
+ const int cursorPosition;
+ const int anchorPosition;
+ QString surroundingText;
+ QString selectedText;
+};
+
class TestInputContext : public QPlatformInputContext
{
public:
@@ -496,8 +515,28 @@ public:
resetCallCount++;
}
+ virtual void update(Qt::InputMethodQueries queries)
+ {
+ if (!qApp->focusObject())
+ return;
+
+ if (!(queries & Qt::ImQueryInput))
+ return;
+
+ QInputMethodQueryEvent imQueryEvent(Qt::ImQueryInput);
+ QGuiApplication::sendEvent(qApp->focusObject(), &imQueryEvent);
+
+ const int cursorPosition = imQueryEvent.value(Qt::ImCursorPosition).toInt();
+ const int anchorPosition = imQueryEvent.value(Qt::ImAnchorPosition).toInt();
+ QString surroundingText = imQueryEvent.value(Qt::ImSurroundingText).toString();
+ QString selectedText = imQueryEvent.value(Qt::ImCurrentSelection).toString();
+
+ infos.append(InputMethodInfo(cursorPosition, anchorPosition, surroundingText, selectedText));
+ }
+
int commitCallCount;
int resetCallCount;
+ QList<InputMethodInfo> infos;
};
void tst_QQuickWebEngineView::interruptImeTextComposition_data()
@@ -561,6 +600,151 @@ void tst_QQuickWebEngineView::interruptImeTextComposition()
QTRY_COMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QStringLiteral("x"));
}
+void tst_QQuickWebEngineView::inputContextQueryInput()
+{
+ m_window->show();
+ QTRY_VERIFY(qApp->focusObject());
+ TestInputContext testContext;
+
+ QQuickWebEngineView *view = webEngineView();
+ view->settings()->setFocusOnNavigationEnabled(true);
+ view->loadHtml("<html><body>"
+ " <input type='text' id='input1' />"
+ "</body></html>");
+ QVERIFY(waitForLoadSucceeded(view));
+ QCOMPARE(testContext.infos.count(), 0);
+
+ // Set focus on an input field.
+ QPoint textInputCenter = elementCenter(view, "input1");
+ QTest::mouseClick(view->window(), Qt::LeftButton, 0, textInputCenter);
+ QTRY_COMPARE(testContext.infos.count(), 2);
+ QCOMPARE(evaluateJavaScriptSync(view, "document.activeElement.id").toString(), QStringLiteral("input1"));
+ foreach (const InputMethodInfo &info, testContext.infos) {
+ QCOMPARE(info.cursorPosition, 0);
+ QCOMPARE(info.anchorPosition, 0);
+ QCOMPARE(info.surroundingText, QStringLiteral(""));
+ QCOMPARE(info.selectedText, QStringLiteral(""));
+ }
+ testContext.infos.clear();
+
+ // Change content of an input field from JavaScript.
+ evaluateJavaScriptSync(view, "document.getElementById('input1').value='QtWebEngine';");
+ QTRY_COMPARE(testContext.infos.count(), 1);
+ QCOMPARE(testContext.infos[0].cursorPosition, 11);
+ QCOMPARE(testContext.infos[0].anchorPosition, 11);
+ QCOMPARE(testContext.infos[0].surroundingText, QStringLiteral("QtWebEngine"));
+ QCOMPARE(testContext.infos[0].selectedText, QStringLiteral(""));
+ testContext.infos.clear();
+
+ // Change content of an input field by key press.
+ QTest::keyClick(view->window(), Qt::Key_Exclam);
+ QTRY_COMPARE(testContext.infos.count(), 1);
+ QCOMPARE(testContext.infos[0].cursorPosition, 12);
+ QCOMPARE(testContext.infos[0].anchorPosition, 12);
+ QCOMPARE(testContext.infos[0].surroundingText, QStringLiteral("QtWebEngine!"));
+ QCOMPARE(testContext.infos[0].selectedText, QStringLiteral(""));
+ testContext.infos.clear();
+
+ // Change cursor position.
+ QTest::keyClick(view->window(), Qt::Key_Left);
+ QTRY_COMPARE(testContext.infos.count(), 1);
+ QCOMPARE(testContext.infos[0].cursorPosition, 11);
+ QCOMPARE(testContext.infos[0].anchorPosition, 11);
+ QCOMPARE(testContext.infos[0].surroundingText, QStringLiteral("QtWebEngine!"));
+ QCOMPARE(testContext.infos[0].selectedText, QStringLiteral(""));
+ testContext.infos.clear();
+
+ // Selection by IME.
+ {
+ QList<QInputMethodEvent::Attribute> attributes;
+ QInputMethodEvent::Attribute newSelection(QInputMethodEvent::Selection, 2, 12, QVariant());
+ attributes.append(newSelection);
+ QInputMethodEvent event("", attributes);
+ QGuiApplication::sendEvent(qApp->focusObject(), &event);
+ }
+ QTRY_COMPARE(testContext.infos.count(), 2);
+
+ // As a first step, Chromium moves the cursor to the start of the selection.
+ // We don't filter this in QtWebEngine because we don't know yet if this is part of a selection.
+ QCOMPARE(testContext.infos[0].cursorPosition, 2);
+ QCOMPARE(testContext.infos[0].anchorPosition, 2);
+ QCOMPARE(testContext.infos[0].surroundingText, QStringLiteral("QtWebEngine!"));
+ QCOMPARE(testContext.infos[0].selectedText, QStringLiteral(""));
+
+ // The update of the selection.
+ QCOMPARE(testContext.infos[1].cursorPosition, 12);
+ QCOMPARE(testContext.infos[1].anchorPosition, 2);
+ QCOMPARE(testContext.infos[1].surroundingText, QStringLiteral("QtWebEngine!"));
+ QCOMPARE(testContext.infos[1].selectedText, QStringLiteral("WebEngine!"));
+ testContext.infos.clear();
+
+ // Clear selection by IME.
+ {
+ QList<QInputMethodEvent::Attribute> attributes;
+ QInputMethodEvent::Attribute newSelection(QInputMethodEvent::Selection, 0, 0, QVariant());
+ attributes.append(newSelection);
+ QInputMethodEvent event("", attributes);
+ QGuiApplication::sendEvent(qApp->focusObject(), &event);
+ }
+ QTRY_COMPARE(testContext.infos.count(), 1);
+ QCOMPARE(testContext.infos[0].cursorPosition, 0);
+ QCOMPARE(testContext.infos[0].anchorPosition, 0);
+ QCOMPARE(testContext.infos[0].surroundingText, QStringLiteral("QtWebEngine!"));
+ QCOMPARE(testContext.infos[0].selectedText, QStringLiteral(""));
+ testContext.infos.clear();
+
+ // Compose text.
+ {
+ QList<QInputMethodEvent::Attribute> attributes;
+ QInputMethodEvent event("123", attributes);
+ QGuiApplication::sendEvent(qApp->focusObject(), &event);
+ }
+ QTRY_COMPARE(testContext.infos.count(), 1);
+ QCOMPARE(testContext.infos[0].cursorPosition, 3);
+ QCOMPARE(testContext.infos[0].anchorPosition, 3);
+ QCOMPARE(testContext.infos[0].surroundingText, QStringLiteral("QtWebEngine!"));
+ QCOMPARE(testContext.infos[0].selectedText, QStringLiteral(""));
+ QCOMPARE(evaluateJavaScriptSync(view, "document.getElementById('input1').value").toString(), QStringLiteral("123QtWebEngine!"));
+ testContext.infos.clear();
+
+ // Cancel composition.
+ {
+ QList<QInputMethodEvent::Attribute> attributes;
+ QInputMethodEvent event("", attributes);
+ QGuiApplication::sendEvent(qApp->focusObject(), &event);
+ }
+ QTRY_COMPARE(testContext.infos.count(), 2);
+ foreach (const InputMethodInfo &info, testContext.infos) {
+ QCOMPARE(info.cursorPosition, 0);
+ QCOMPARE(info.anchorPosition, 0);
+ QCOMPARE(info.surroundingText, QStringLiteral("QtWebEngine!"));
+ QCOMPARE(info.selectedText, QStringLiteral(""));
+ }
+ QCOMPARE(evaluateJavaScriptSync(view, "document.getElementById('input1').value").toString(), QStringLiteral("QtWebEngine!"));
+ testContext.infos.clear();
+
+ // Commit text.
+ {
+ QList<QInputMethodEvent::Attribute> attributes;
+ QInputMethodEvent event("", attributes);
+ event.setCommitString(QStringLiteral("123"), 0, 0);
+ QGuiApplication::sendEvent(qApp->focusObject(), &event);
+ }
+ QTRY_COMPARE(testContext.infos.count(), 1);
+ QCOMPARE(testContext.infos[0].cursorPosition, 3);
+ QCOMPARE(testContext.infos[0].anchorPosition, 3);
+ QCOMPARE(testContext.infos[0].surroundingText, QStringLiteral("123QtWebEngine!"));
+ QCOMPARE(testContext.infos[0].selectedText, QStringLiteral(""));
+ QCOMPARE(evaluateJavaScriptSync(view, "document.getElementById('input1').value").toString(), QStringLiteral("123QtWebEngine!"));
+ testContext.infos.clear();
+
+ // Focus out.
+ QTest::keyPress(view->window(), Qt::Key_Tab);
+ QTRY_COMPARE(testContext.infos.count(), 1);
+ QTRY_COMPARE(evaluateJavaScriptSync(view, "document.activeElement.id").toString(), QStringLiteral(""));
+ testContext.infos.clear();
+}
+
void tst_QQuickWebEngineView::inputMethodHints()
{
m_window->show();
diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
index a6487d19a..eb340b6f5 100644
--- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
+++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
@@ -167,6 +167,7 @@ private Q_SLOTS:
void inputFieldOverridesShortcuts();
void softwareInputPanel();
+ void inputContextQueryInput();
void inputMethods();
void textSelectionInInputField();
void textSelectionOutOfInputField();
@@ -1689,6 +1690,24 @@ void tst_QWebEngineView::inputFieldOverridesShortcuts()
QTRY_VERIFY(actionTriggered);
}
+struct InputMethodInfo
+{
+ InputMethodInfo(const int cursorPosition,
+ const int anchorPosition,
+ QString surroundingText,
+ QString selectedText)
+ : cursorPosition(cursorPosition)
+ , anchorPosition(anchorPosition)
+ , surroundingText(surroundingText)
+ , selectedText(selectedText)
+ {}
+
+ const int cursorPosition;
+ const int anchorPosition;
+ QString surroundingText;
+ QString selectedText;
+};
+
class TestInputContext : public QPlatformInputContext
{
public:
@@ -1718,7 +1737,27 @@ public:
return m_visible;
}
+ virtual void update(Qt::InputMethodQueries queries)
+ {
+ if (!qApp->focusObject())
+ return;
+
+ if (!(queries & Qt::ImQueryInput))
+ return;
+
+ QInputMethodQueryEvent imQueryEvent(Qt::ImQueryInput);
+ QApplication::sendEvent(qApp->focusObject(), &imQueryEvent);
+
+ const int cursorPosition = imQueryEvent.value(Qt::ImCursorPosition).toInt();
+ const int anchorPosition = imQueryEvent.value(Qt::ImAnchorPosition).toInt();
+ QString surroundingText = imQueryEvent.value(Qt::ImSurroundingText).toString();
+ QString selectedText = imQueryEvent.value(Qt::ImCurrentSelection).toString();
+
+ infos.append(InputMethodInfo(cursorPosition, anchorPosition, surroundingText, selectedText));
+ }
+
bool m_visible;
+ QList<InputMethodInfo> infos;
};
void tst_QWebEngineView::softwareInputPanel()
@@ -1779,6 +1818,156 @@ void tst_QWebEngineView::softwareInputPanel()
QVERIFY(!testContext.isInputPanelVisible());
}
+void tst_QWebEngineView::inputContextQueryInput()
+{
+ TestInputContext testContext;
+ QWebEngineView view;
+ view.resize(640, 480);
+ view.show();
+
+ QSignalSpy selectionChangedSpy(&view, SIGNAL(selectionChanged()));
+ QSignalSpy loadFinishedSpy(&view, SIGNAL(loadFinished(bool)));
+ view.setHtml("<html><body>"
+ " <input type='text' id='input1' value='' size='50'/>"
+ "</body></html>");
+ QTRY_COMPARE(loadFinishedSpy.count(), 1);
+ QCOMPARE(testContext.infos.count(), 0);
+
+ // Set focus on an input field.
+ QPoint textInputCenter = elementCenter(view.page(), "input1");
+ QTest::mouseClick(view.focusProxy(), Qt::LeftButton, 0, textInputCenter);
+ QTRY_COMPARE(testContext.infos.count(), 2);
+ QCOMPARE(evaluateJavaScriptSync(view.page(), "document.activeElement.id").toString(), QStringLiteral("input1"));
+ foreach (const InputMethodInfo &info, testContext.infos) {
+ QCOMPARE(info.cursorPosition, 0);
+ QCOMPARE(info.anchorPosition, 0);
+ QCOMPARE(info.surroundingText, QStringLiteral(""));
+ QCOMPARE(info.selectedText, QStringLiteral(""));
+ }
+ testContext.infos.clear();
+
+ // Change content of an input field from JavaScript.
+ evaluateJavaScriptSync(view.page(), "document.getElementById('input1').value='QtWebEngine';");
+ QTRY_COMPARE(testContext.infos.count(), 1);
+ QCOMPARE(testContext.infos[0].cursorPosition, 11);
+ QCOMPARE(testContext.infos[0].anchorPosition, 11);
+ QCOMPARE(testContext.infos[0].surroundingText, QStringLiteral("QtWebEngine"));
+ QCOMPARE(testContext.infos[0].selectedText, QStringLiteral(""));
+ testContext.infos.clear();
+
+ // Change content of an input field by key press.
+ QTest::keyClick(view.focusProxy(), Qt::Key_Exclam);
+ QTRY_COMPARE(testContext.infos.count(), 1);
+ QCOMPARE(testContext.infos[0].cursorPosition, 12);
+ QCOMPARE(testContext.infos[0].anchorPosition, 12);
+ QCOMPARE(testContext.infos[0].surroundingText, QStringLiteral("QtWebEngine!"));
+ QCOMPARE(testContext.infos[0].selectedText, QStringLiteral(""));
+ testContext.infos.clear();
+
+ // Change cursor position.
+ QTest::keyClick(view.focusProxy(), Qt::Key_Left);
+ QTRY_COMPARE(testContext.infos.count(), 1);
+ QCOMPARE(testContext.infos[0].cursorPosition, 11);
+ QCOMPARE(testContext.infos[0].anchorPosition, 11);
+ QCOMPARE(testContext.infos[0].surroundingText, QStringLiteral("QtWebEngine!"));
+ QCOMPARE(testContext.infos[0].selectedText, QStringLiteral(""));
+ testContext.infos.clear();
+
+ // Selection by IME.
+ {
+ QList<QInputMethodEvent::Attribute> attributes;
+ QInputMethodEvent::Attribute newSelection(QInputMethodEvent::Selection, 2, 12, QVariant());
+ attributes.append(newSelection);
+ QInputMethodEvent event("", attributes);
+ QApplication::sendEvent(view.focusProxy(), &event);
+ }
+ QTRY_COMPARE(testContext.infos.count(), 2);
+ QCOMPARE(selectionChangedSpy.count(), 1);
+
+ // As a first step, Chromium moves the cursor to the start of the selection.
+ // We don't filter this in QtWebEngine because we don't know yet if this is part of a selection.
+ QCOMPARE(testContext.infos[0].cursorPosition, 2);
+ QCOMPARE(testContext.infos[0].anchorPosition, 2);
+ QCOMPARE(testContext.infos[0].surroundingText, QStringLiteral("QtWebEngine!"));
+ QCOMPARE(testContext.infos[0].selectedText, QStringLiteral(""));
+
+ // The update of the selection.
+ QCOMPARE(testContext.infos[1].cursorPosition, 12);
+ QCOMPARE(testContext.infos[1].anchorPosition, 2);
+ QCOMPARE(testContext.infos[1].surroundingText, QStringLiteral("QtWebEngine!"));
+ QCOMPARE(testContext.infos[1].selectedText, QStringLiteral("WebEngine!"));
+ testContext.infos.clear();
+ selectionChangedSpy.clear();
+
+ // Clear selection by IME.
+ {
+ QList<QInputMethodEvent::Attribute> attributes;
+ QInputMethodEvent::Attribute newSelection(QInputMethodEvent::Selection, 0, 0, QVariant());
+ attributes.append(newSelection);
+ QInputMethodEvent event("", attributes);
+ QApplication::sendEvent(view.focusProxy(), &event);
+ }
+ QTRY_COMPARE(testContext.infos.count(), 1);
+ QCOMPARE(selectionChangedSpy.count(), 1);
+ QCOMPARE(testContext.infos[0].cursorPosition, 0);
+ QCOMPARE(testContext.infos[0].anchorPosition, 0);
+ QCOMPARE(testContext.infos[0].surroundingText, QStringLiteral("QtWebEngine!"));
+ QCOMPARE(testContext.infos[0].selectedText, QStringLiteral(""));
+ testContext.infos.clear();
+ selectionChangedSpy.clear();
+
+ // Compose text.
+ {
+ QList<QInputMethodEvent::Attribute> attributes;
+ QInputMethodEvent event("123", attributes);
+ QApplication::sendEvent(view.focusProxy(), &event);
+ }
+ QTRY_COMPARE(testContext.infos.count(), 1);
+ QCOMPARE(testContext.infos[0].cursorPosition, 3);
+ QCOMPARE(testContext.infos[0].anchorPosition, 3);
+ QCOMPARE(testContext.infos[0].surroundingText, QStringLiteral("QtWebEngine!"));
+ QCOMPARE(testContext.infos[0].selectedText, QStringLiteral(""));
+ QCOMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('input1').value").toString(), QStringLiteral("123QtWebEngine!"));
+ testContext.infos.clear();
+
+ // Cancel composition.
+ {
+ QList<QInputMethodEvent::Attribute> attributes;
+ QInputMethodEvent event("", attributes);
+ QApplication::sendEvent(view.focusProxy(), &event);
+ }
+ QTRY_COMPARE(testContext.infos.count(), 2);
+ foreach (const InputMethodInfo &info, testContext.infos) {
+ QCOMPARE(info.cursorPosition, 0);
+ QCOMPARE(info.anchorPosition, 0);
+ QCOMPARE(info.surroundingText, QStringLiteral("QtWebEngine!"));
+ QCOMPARE(info.selectedText, QStringLiteral(""));
+ }
+ QCOMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('input1').value").toString(), QStringLiteral("QtWebEngine!"));
+ testContext.infos.clear();
+
+ // Commit text.
+ {
+ QList<QInputMethodEvent::Attribute> attributes;
+ QInputMethodEvent event("", attributes);
+ event.setCommitString(QStringLiteral("123"), 0, 0);
+ QApplication::sendEvent(view.focusProxy(), &event);
+ }
+ QTRY_COMPARE(testContext.infos.count(), 1);
+ QCOMPARE(testContext.infos[0].cursorPosition, 3);
+ QCOMPARE(testContext.infos[0].anchorPosition, 3);
+ QCOMPARE(testContext.infos[0].surroundingText, QStringLiteral("123QtWebEngine!"));
+ QCOMPARE(testContext.infos[0].selectedText, QStringLiteral(""));
+ QCOMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('input1').value").toString(), QStringLiteral("123QtWebEngine!"));
+ testContext.infos.clear();
+
+ // Focus out.
+ QTest::keyPress(view.focusProxy(), Qt::Key_Tab);
+ QTRY_COMPARE(testContext.infos.count(), 1);
+ QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.activeElement.id").toString(), QStringLiteral(""));
+ testContext.infos.clear();
+}
+
void tst_QWebEngineView::inputMethods()
{
QWebEngineView view;