Skip to content

Commit

Permalink
Don't overwrite text selections made in focus handlers.
Browse files Browse the repository at this point in the history
Defer giving focus to TextInput or TextEdit until after other mouse
press handling has been performed, otherwise setting the cursor position
will overwrite any selection or cursor position set in the
on(Active)FocusChanged handler.

Change-Id: I6332642484de65138a444987b5a81be69c6f835f
Reviewed-by: Yann Bodson <yann.bodson@nokia.com>
  • Loading branch information
Andrew den Exter authored and Qt by Nokia committed Mar 21, 2012
1 parent 0e1baa2 commit b6380ad
Show file tree
Hide file tree
Showing 4 changed files with 228 additions and 47 deletions.
2 changes: 1 addition & 1 deletion src/quick/items/qquicktextedit.cpp
Expand Up @@ -1477,14 +1477,14 @@ Handles the given mouse \a event.
void QQuickTextEdit::mousePressEvent(QMouseEvent *event)
{
Q_D(QQuickTextEdit);
d->control->processEvent(event, QPointF(0, -d->yoff));
if (d->focusOnPress){
bool hadActiveFocus = hasActiveFocus();
forceActiveFocus();
// re-open input panel on press if already focused
if (hasActiveFocus() && hadActiveFocus && !isReadOnly())
openSoftwareInputPanel();
}
d->control->processEvent(event, QPointF(0, -d->yoff));
if (!event->isAccepted())
QQuickImplicitSizeItem::mousePressEvent(event);
}
Expand Down
22 changes: 12 additions & 10 deletions src/quick/items/qquicktextinput.cpp
Expand Up @@ -1444,13 +1444,9 @@ void QQuickTextInput::mousePressEvent(QMouseEvent *event)

d->pressPos = event->localPos();

if (d->focusOnPress) {
bool hadActiveFocus = hasActiveFocus();
forceActiveFocus();
// re-open input panel on press if already focused
if (hasActiveFocus() && hadActiveFocus && !d->m_readOnly)
openSoftwareInputPanel();
}
if (d->sendMouseEventToInputContext(event))
return;

if (d->selectByMouse) {
setKeepMouseGrab(false);
d->selectPressed = true;
Expand All @@ -1463,12 +1459,18 @@ void QQuickTextInput::mousePressEvent(QMouseEvent *event)
}
}

if (d->sendMouseEventToInputContext(event))
return;

bool mark = (event->modifiers() & Qt::ShiftModifier) && d->selectByMouse;
int cursor = d->positionAt(event->localPos());
d->moveCursor(cursor, mark);

if (d->focusOnPress) {
bool hadActiveFocus = hasActiveFocus();
forceActiveFocus();
// re-open input panel on press if already focused
if (hasActiveFocus() && hadActiveFocus && !d->m_readOnly)
openSoftwareInputPanel();
}

event->setAccepted(true);
}

Expand Down
145 changes: 112 additions & 33 deletions tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
Expand Up @@ -1013,23 +1013,88 @@ void tst_qquicktextedit::persistentSelection()

void tst_qquicktextedit::focusOnPress()
{
{
QString componentStr = "import QtQuick 2.0\nTextEdit { activeFocusOnPress: true; text: \"Hello World\" }";
QString componentStr =
"import QtQuick 2.0\n"
"TextEdit {\n"
"property bool selectOnFocus: false\n"
"width: 100; height: 50\n"
"activeFocusOnPress: true\n"
"text: \"Hello World\"\n"
"onFocusChanged: { if (focus && selectOnFocus) selectAll() }"
" }";
QQmlComponent texteditComponent(&engine);
texteditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
QVERIFY(textEditObject != 0);
QCOMPARE(textEditObject->focusOnPress(), true);
}
QCOMPARE(textEditObject->hasFocus(), false);

{
QString componentStr = "import QtQuick 2.0\nTextEdit { activeFocusOnPress: false; text: \"Hello World\" }";
QQmlComponent texteditComponent(&engine);
texteditComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
QVERIFY(textEditObject != 0);
QSignalSpy focusSpy(textEditObject, SIGNAL(focusChanged(bool)));
QSignalSpy activeFocusSpy(textEditObject, SIGNAL(focusChanged(bool)));
QSignalSpy activeFocusOnPressSpy(textEditObject, SIGNAL(activeFocusOnPressChanged(bool)));

textEditObject->setFocusOnPress(true);
QCOMPARE(textEditObject->focusOnPress(), true);
QCOMPARE(activeFocusOnPressSpy.count(), 0);

QQuickCanvas canvas;
canvas.resize(100, 50);
textEditObject->setParentItem(canvas.rootItem());
canvas.show();
canvas.requestActivateWindow();
QTest::qWaitForWindowShown(&canvas);
QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);

QCOMPARE(textEditObject->hasFocus(), false);
QCOMPARE(textEditObject->hasActiveFocus(), false);

QPoint centerPoint(canvas.width()/2, canvas.height()/2);
Qt::KeyboardModifiers noModifiers = 0;
QTest::mousePress(&canvas, Qt::LeftButton, noModifiers, centerPoint);
QGuiApplication::processEvents();
QCOMPARE(textEditObject->hasFocus(), true);
QCOMPARE(textEditObject->hasActiveFocus(), true);
QCOMPARE(focusSpy.count(), 1);
QCOMPARE(activeFocusSpy.count(), 1);
QCOMPARE(textEditObject->selectedText(), QString());
QTest::mouseRelease(&canvas, Qt::LeftButton, noModifiers, centerPoint);

textEditObject->setFocusOnPress(false);
QCOMPARE(textEditObject->focusOnPress(), false);
}
QCOMPARE(activeFocusOnPressSpy.count(), 1);

textEditObject->setFocus(false);
QCOMPARE(textEditObject->hasFocus(), false);
QCOMPARE(textEditObject->hasActiveFocus(), false);
QCOMPARE(focusSpy.count(), 2);
QCOMPARE(activeFocusSpy.count(), 2);

// Wait for double click timeout to expire before clicking again.
QTest::qWait(400);
QTest::mousePress(&canvas, Qt::LeftButton, noModifiers, centerPoint);
QGuiApplication::processEvents();
QCOMPARE(textEditObject->hasFocus(), false);
QCOMPARE(textEditObject->hasActiveFocus(), false);
QCOMPARE(focusSpy.count(), 2);
QCOMPARE(activeFocusSpy.count(), 2);
QTest::mouseRelease(&canvas, Qt::LeftButton, noModifiers, centerPoint);

textEditObject->setFocusOnPress(true);
QCOMPARE(textEditObject->focusOnPress(), true);
QCOMPARE(activeFocusOnPressSpy.count(), 2);

// Test a selection made in the on(Active)FocusChanged handler isn't overwritten.
textEditObject->setProperty("selectOnFocus", true);

QTest::qWait(400);
QTest::mousePress(&canvas, Qt::LeftButton, noModifiers, centerPoint);
QGuiApplication::processEvents();
QCOMPARE(textEditObject->hasFocus(), true);
QCOMPARE(textEditObject->hasActiveFocus(), true);
QCOMPARE(focusSpy.count(), 3);
QCOMPARE(activeFocusSpy.count(), 3);
QCOMPARE(textEditObject->selectedText(), textEditObject->text());
QTest::mouseRelease(&canvas, Qt::LeftButton, noModifiers, centerPoint);
}

void tst_qquicktextedit::selection()
Expand Down Expand Up @@ -1563,32 +1628,41 @@ void tst_qquicktextedit::mouseSelection_data()
QTest::addColumn<int>("from");
QTest::addColumn<int>("to");
QTest::addColumn<QString>("selectedText");
QTest::addColumn<bool>("focus");
QTest::addColumn<bool>("focusOnPress");
QTest::addColumn<bool>("doubleClick");

// import installed
QTest::newRow("on") << testFile("mouseselection_true.qml") << 4 << 9 << "45678" << false;
QTest::newRow("off") << testFile("mouseselection_false.qml") << 4 << 9 << QString() << false;
QTest::newRow("default") << testFile("mouseselection_default.qml") << 4 << 9 << QString() << false;
QTest::newRow("off word selection") << testFile("mouseselection_false_words.qml") << 4 << 9 << QString() << false;
QTest::newRow("on word selection (4,9)") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << false;
QTest::newRow("on word selection (2,13)") << testFile("mouseselection_true_words.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << false;
QTest::newRow("on word selection (2,30)") << testFile("mouseselection_true_words.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << false;
QTest::newRow("on word selection (9,13)") << testFile("mouseselection_true_words.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << false;
QTest::newRow("on word selection (9,30)") << testFile("mouseselection_true_words.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << false;
QTest::newRow("on word selection (13,2)") << testFile("mouseselection_true_words.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << false;
QTest::newRow("on word selection (20,2)") << testFile("mouseselection_true_words.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << false;
QTest::newRow("on word selection (12,9)") << testFile("mouseselection_true_words.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << false;
QTest::newRow("on word selection (30,9)") << testFile("mouseselection_true_words.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << false;

QTest::newRow("off double click (4,9)") << testFile("mouseselection_true.qml") << 4 << 9 << "0123456789" << true;
QTest::newRow("off double click (2,13)") << testFile("mouseselection_true.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true;
QTest::newRow("off double click (2,30)") << testFile("mouseselection_true.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true;
QTest::newRow("off double click (9,13)") << testFile("mouseselection_true.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true;
QTest::newRow("off double click (9,30)") << testFile("mouseselection_true.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true;
QTest::newRow("off double click (13,2)") << testFile("mouseselection_true.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true;
QTest::newRow("off double click (20,2)") << testFile("mouseselection_true.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true;
QTest::newRow("off double click (12,9)") << testFile("mouseselection_true.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true;
QTest::newRow("off double click (30,9)") << testFile("mouseselection_true.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true;
QTest::newRow("on") << testFile("mouseselection_true.qml") << 4 << 9 << "45678" << true << true << false;
QTest::newRow("off") << testFile("mouseselection_false.qml") << 4 << 9 << QString() << true << true << false;
QTest::newRow("default") << testFile("mouseselection_default.qml") << 4 << 9 << QString() << true << true << false;
QTest::newRow("off word selection") << testFile("mouseselection_false_words.qml") << 4 << 9 << QString() << true << true << false;
QTest::newRow("on word selection (4,9)") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << true << true << false;

QTest::newRow("on unfocused") << testFile("mouseselection_true.qml") << 4 << 9 << "45678" << false << false << false;
QTest::newRow("on word selection (4,9) unfocused") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << false << false << false;

QTest::newRow("on focus on press") << testFile("mouseselection_true.qml") << 4 << 9 << "45678" << false << true << false;
QTest::newRow("on word selection (4,9) focus on press") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << false << true << false;

QTest::newRow("on word selection (2,13)") << testFile("mouseselection_true_words.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
QTest::newRow("on word selection (2,30)") << testFile("mouseselection_true_words.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
QTest::newRow("on word selection (9,13)") << testFile("mouseselection_true_words.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
QTest::newRow("on word selection (9,30)") << testFile("mouseselection_true_words.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
QTest::newRow("on word selection (13,2)") << testFile("mouseselection_true_words.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
QTest::newRow("on word selection (20,2)") << testFile("mouseselection_true_words.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
QTest::newRow("on word selection (12,9)") << testFile("mouseselection_true_words.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
QTest::newRow("on word selection (30,9)") << testFile("mouseselection_true_words.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;

QTest::newRow("off double click (4,9)") << testFile("mouseselection_true.qml") << 4 << 9 << "0123456789" << true << true << true;
QTest::newRow("off double click (2,13)") << testFile("mouseselection_true.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
QTest::newRow("off double click (2,30)") << testFile("mouseselection_true.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
QTest::newRow("off double click (9,13)") << testFile("mouseselection_true.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
QTest::newRow("off double click (9,30)") << testFile("mouseselection_true.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
QTest::newRow("off double click (13,2)") << testFile("mouseselection_true.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
QTest::newRow("off double click (20,2)") << testFile("mouseselection_true.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
QTest::newRow("off double click (12,9)") << testFile("mouseselection_true.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
QTest::newRow("off double click (30,9)") << testFile("mouseselection_true.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
}

void tst_qquicktextedit::mouseSelection()
Expand All @@ -1597,6 +1671,8 @@ void tst_qquicktextedit::mouseSelection()
QFETCH(int, from);
QFETCH(int, to);
QFETCH(QString, selectedText);
QFETCH(bool, focus);
QFETCH(bool, focusOnPress);
QFETCH(bool, doubleClick);

QQuickView canvas(QUrl::fromLocalFile(qmlfile));
Expand All @@ -1610,6 +1686,9 @@ void tst_qquicktextedit::mouseSelection()
QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
QVERIFY(textEditObject != 0);

textEditObject->setFocus(focus);
textEditObject->setFocusOnPress(focusOnPress);

// press-and-drag-and-release from x1 to x2
QPoint p1 = textEditObject->positionToRectangle(from).center().toPoint();
QPoint p2 = textEditObject->positionToRectangle(to).center().toPoint();
Expand Down

0 comments on commit b6380ad

Please sign in to comment.