summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Varga <pvarga@inf.u-szeged.hu>2017-05-09 18:17:54 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-05-17 09:04:15 +0000
commit59df7bd0a92acf6cb9ef2eac551b7a0913e2cd1f (patch)
tree44f79e6f2b780441367720e8f9c9a3c06f134f8e
parentb56a0dfbcda6a71a06236a29e514b8d4ec5a02ed (diff)
Fix selectionChanged signal out of input field
Task-number: QTBUG-60688 Change-Id: I6d0b78e6b8df54c40ae30d5f0909c631c440a9cd Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
-rw-r--r--src/core/render_widget_host_view_qt.cpp33
-rw-r--r--src/core/render_widget_host_view_qt.h4
-rw-r--r--tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp95
3 files changed, 122 insertions, 10 deletions
diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp
index 72abe04af..cf22273e4 100644
--- a/src/core/render_widget_host_view_qt.cpp
+++ b/src/core/render_widget_host_view_qt.cpp
@@ -97,6 +97,7 @@ enum ImStateFlags {
TextInputStateUpdated = 1 << 0,
TextSelectionUpdated = 1 << 1,
TextSelectionBoundsUpdated = 1 << 2,
+ TextSelectionFlags = TextSelectionUpdated | TextSelectionBoundsUpdated,
AllFlags = TextInputStateUpdated | TextSelectionUpdated | TextSelectionBoundsUpdated
};
@@ -266,8 +267,8 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost* widget
, m_needsBeginFrames(false)
, m_addedFrameObserver(false)
, m_imState(0)
- , m_anchorPositionWithinSelection(0)
- , m_cursorPositionWithinSelection(0)
+ , m_anchorPositionWithinSelection(-1)
+ , m_cursorPositionWithinSelection(-1)
, m_cursorPosition(0)
, m_emptyPreviousSelection(true)
{
@@ -776,8 +777,10 @@ void RenderWidgetHostViewQt::OnSelectionBoundsChanged(content::TextInputManager
Q_UNUSED(updated_view);
m_imState |= ImStateFlags::TextSelectionBoundsUpdated;
- if (m_imState == ImStateFlags::AllFlags)
+ if (m_imState == ImStateFlags::AllFlags
+ || (m_imState == ImStateFlags::TextSelectionFlags && getTextInputType() == ui::TEXT_INPUT_TYPE_NONE)) {
selectionChanged();
+ }
}
void RenderWidgetHostViewQt::OnTextSelectionChanged(content::TextInputManager *text_input_manager, RenderWidgetHostViewBase *updated_view)
@@ -794,8 +797,10 @@ void RenderWidgetHostViewQt::OnTextSelectionChanged(content::TextInputManager *t
#endif // defined(USE_X11)
m_imState |= ImStateFlags::TextSelectionUpdated;
- if (m_imState == ImStateFlags::AllFlags)
+ if (m_imState == ImStateFlags::AllFlags
+ || (m_imState == ImStateFlags::TextSelectionFlags && getTextInputType() == ui::TEXT_INPUT_TYPE_NONE)) {
selectionChanged();
+ }
}
void RenderWidgetHostViewQt::selectionChanged()
@@ -803,6 +808,22 @@ void RenderWidgetHostViewQt::selectionChanged()
// Reset input manager state
m_imState = 0;
+ // Handle text selection out of an input field
+ if (getTextInputType() == ui::TEXT_INPUT_TYPE_NONE) {
+ if (GetSelectedText().empty() && m_emptyPreviousSelection)
+ return;
+
+ // Reset position values to emit selectionChanged signal when clearing text selection
+ // by clicking into an input field. These values are intended to be used by inputMethodQuery
+ // so they are not expected to be valid when selection is out of an input field.
+ m_anchorPositionWithinSelection = -1;
+ m_cursorPositionWithinSelection = -1;
+
+ m_emptyPreviousSelection = GetSelectedText().empty();
+ m_adapterClient->selectionChanged();
+ return;
+ }
+
const content::TextInputManager::TextSelection *selection = text_input_manager_->GetTextSelection();
if (!selection)
return;
@@ -817,8 +838,8 @@ void RenderWidgetHostViewQt::selectionChanged()
return;
}
- uint newAnchorPositionWithinSelection = 0;
- uint newCursorPositionWithinSelection = 0;
+ int newAnchorPositionWithinSelection = 0;
+ int newCursorPositionWithinSelection = 0;
if (text_input_manager_->GetSelectionRegion()->anchor.type() == gfx::SelectionBound::RIGHT) {
newAnchorPositionWithinSelection = selection->range.GetMax() - selection->offset;
diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h
index 799930830..3b679923e 100644
--- a/src/core/render_widget_host_view_qt.h
+++ b/src/core/render_widget_host_view_qt.h
@@ -263,8 +263,8 @@ private:
gfx::SizeF m_lastContentsSize;
uint m_imState;
- uint m_anchorPositionWithinSelection;
- uint m_cursorPositionWithinSelection;
+ int m_anchorPositionWithinSelection;
+ int m_cursorPositionWithinSelection;
uint m_cursorPosition;
bool m_emptyPreviousSelection;
QString m_surroundingText;
diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
index 32a518ad8..37c7ae881 100644
--- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
+++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
@@ -100,7 +100,8 @@ private Q_SLOTS:
void softwareInputPanel();
void inputMethods();
- void textSelection();
+ void textSelectionInInputField();
+ void textSelectionOutOfInputField();
void hiddenText();
void emptyInputMethodEvent();
void imeComposition();
@@ -1584,7 +1585,7 @@ void tst_QWebEngineView::inputMethods()
QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("QtWebEngine"));
}
-void tst_QWebEngineView::textSelection()
+void tst_QWebEngineView::textSelectionInInputField()
{
QWebEngineView view;
view.show();
@@ -1662,6 +1663,96 @@ void tst_QWebEngineView::textSelection()
QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCurrentSelection).toString(), QString("QtWebEngi"));
}
+void tst_QWebEngineView::textSelectionOutOfInputField()
+{
+ QWebEngineView view;
+ view.show();
+
+ QSignalSpy selectionChangedSpy(&view, SIGNAL(selectionChanged()));
+ QSignalSpy loadFinishedSpy(&view, SIGNAL(loadFinished(bool)));
+ view.setHtml("<html><body>"
+ " This is a text"
+ "</body></html>");
+ QVERIFY(loadFinishedSpy.wait());
+
+ QCOMPARE(selectionChangedSpy.count(), 0);
+ QVERIFY(!view.hasSelection());
+ QVERIFY(view.page()->selectedText().isEmpty());
+
+ // Simple click should not update text selection, however it updates selection bounds in Chromium
+ QTest::mouseClick(view.focusProxy(), Qt::LeftButton, 0, view.geometry().center());
+ QCOMPARE(selectionChangedSpy.count(), 0);
+ QVERIFY(!view.hasSelection());
+ QVERIFY(view.page()->selectedText().isEmpty());
+
+ // Workaround for macOS: press ctrl+a without key text
+ QKeyEvent keyPressCtrlA(QEvent::KeyPress, Qt::Key_A, Qt::ControlModifier);
+ QKeyEvent keyReleaseCtrlA(QEvent::KeyRelease, Qt::Key_A, Qt::ControlModifier);
+
+ // Select text by ctrl+a
+ QApplication::sendEvent(view.focusProxy(), &keyPressCtrlA);
+ QApplication::sendEvent(view.focusProxy(), &keyReleaseCtrlA);
+ QVERIFY(selectionChangedSpy.wait());
+ QCOMPARE(selectionChangedSpy.count(), 1);
+ QVERIFY(view.hasSelection());
+ QCOMPARE(view.page()->selectedText(), QString("This is a text"));
+
+ // Deselect text by mouse click
+ QTest::mouseClick(view.focusProxy(), Qt::LeftButton, 0, view.geometry().center());
+ QVERIFY(selectionChangedSpy.wait());
+ QCOMPARE(selectionChangedSpy.count(), 2);
+ QVERIFY(!view.hasSelection());
+ QVERIFY(view.page()->selectedText().isEmpty());
+
+ selectionChangedSpy.clear();
+ view.setHtml("<html><body>"
+ " This is a text"
+ " <br>"
+ " <input type='text' id='input1' value='QtWebEngine' size='50'/>"
+ "</body></html>");
+ QVERIFY(loadFinishedSpy.wait());
+
+ QCOMPARE(selectionChangedSpy.count(), 0);
+ QVERIFY(!view.hasSelection());
+ QVERIFY(view.page()->selectedText().isEmpty());
+
+ // Make sure the input field does not have the focus
+ evaluateJavaScriptSync(view.page(), "document.getElementById('input1').blur()");
+ QTRY_VERIFY(evaluateJavaScriptSync(view.page(), "document.activeElement.id").toString().isEmpty());
+
+ // Select the whole page by ctrl+a
+ QApplication::sendEvent(view.focusProxy(), &keyPressCtrlA);
+ QApplication::sendEvent(view.focusProxy(), &keyReleaseCtrlA);
+ QVERIFY(selectionChangedSpy.wait());
+ QCOMPARE(selectionChangedSpy.count(), 1);
+ QVERIFY(view.hasSelection());
+ QVERIFY(view.page()->selectedText().startsWith(QString("This is a text")));
+
+ // Remove selection by clicking into an input field
+ QPoint textInputCenter = elementCenter(view.page(), "input1");
+ QTest::mouseClick(view.focusProxy(), Qt::LeftButton, 0, textInputCenter);
+ QVERIFY(selectionChangedSpy.wait());
+ QCOMPARE(evaluateJavaScriptSync(view.page(), "document.activeElement.id").toString(), QStringLiteral("input1"));
+ QCOMPARE(selectionChangedSpy.count(), 2);
+ QVERIFY(!view.hasSelection());
+ QVERIFY(view.page()->selectedText().isEmpty());
+
+ // Select the content of the input field by ctrl+a
+ QApplication::sendEvent(view.focusProxy(), &keyPressCtrlA);
+ QApplication::sendEvent(view.focusProxy(), &keyReleaseCtrlA);
+ QVERIFY(selectionChangedSpy.wait());
+ QCOMPARE(selectionChangedSpy.count(), 3);
+ QVERIFY(view.hasSelection());
+ QCOMPARE(view.page()->selectedText(), QString("QtWebEngine"));
+
+ // Deselect input field's text by mouse click
+ QTest::mouseClick(view.focusProxy(), Qt::LeftButton, 0, view.geometry().center());
+ QVERIFY(selectionChangedSpy.wait());
+ QCOMPARE(selectionChangedSpy.count(), 4);
+ QVERIFY(!view.hasSelection());
+ QVERIFY(view.page()->selectedText().isEmpty());
+}
+
void tst_QWebEngineView::hiddenText()
{
QWebEngineView view;