Skip to content

Commit

Permalink
Delay masking the last character in Password echo mode.
Browse files Browse the repository at this point in the history
If QT_GUI_PASSWORD_ECHO_DELAY is defined in qplatformdefs.h with an
integer value in milliseconds, QLineEdit and TextInput will display
the last character entered unmasked for that delay period and then
mask the character as normal.  If QT_GUI_PASSWORD_ECHO_DELAY is
not defined then the behaviour is unchanged.

Task-number: QTBUG-17003
Reviewed-by: Martin Jones

(cherry picked from commit f9e7aee2019d321edd655bfde7de43f20a106971)

Change-Id: Iddfa0daa1b39f0589cab27e5003fdd86ad81ff89
Reviewed-on: http://codereview.qt.nokia.com/4170
Reviewed-by: Andrew den Exter <andrew.den-exter@nokia.com>
  • Loading branch information
Andrew den Exter authored and Qt by Nokia committed Sep 6, 2011
1 parent c0fe60c commit 249754b
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/declarative/items/qsgtextinput.cpp
Expand Up @@ -1817,7 +1817,7 @@ void QSGTextInput::itemChange(ItemChange change, const ItemChangeData &value)
bool hasFocus = value.boolValue;
d->focused = hasFocus;
setCursorVisible(hasFocus && d->canvas && d->canvas->hasFocus());
if(echoMode() == QSGTextInput::PasswordEchoOnEdit && !hasFocus)
if(!hasFocus && d->control->passwordEchoEditing())
d->control->updatePasswordEchoEditing(false);//QLineControl sets it on key events, but doesn't deal with focus events
if (!hasFocus)
d->control->deselect();
Expand Down
2 changes: 1 addition & 1 deletion src/qtquick1/graphicsitems/qdeclarativetextinput.cpp
Expand Up @@ -1058,7 +1058,7 @@ void QDeclarative1TextInputPrivate::focusChanged(bool hasFocus)
Q_Q(QDeclarative1TextInput);
focused = hasFocus;
q->setCursorVisible(hasFocus && scene && scene->hasFocus());
if(q->echoMode() == QDeclarative1TextInput::PasswordEchoOnEdit && !hasFocus)
if(!hasFocus && control->passwordEchoEditing())
control->updatePasswordEchoEditing(false);//QLineControl sets it on key events, but doesn't deal with focus events
if (!hasFocus)
control->deselect();
Expand Down
58 changes: 58 additions & 0 deletions tests/auto/declarative/qsgtextinput/tst_qsgtextinput.cpp
Expand Up @@ -55,6 +55,8 @@
#include <QtOpenGL/QGLShaderProgram>
#include <math.h>

#include "qplatformdefs.h"

#ifdef Q_OS_SYMBIAN
// In Symbian OS test data is located in applications private dir
#define SRCDIR "."
Expand Down Expand Up @@ -132,6 +134,9 @@ private slots:
void focusOutClearSelection();

void echoMode();
#ifdef QT_GUI_PASSWORD_ECHO_DELAY
void passwordEchoDelay();
#endif
void geometrySignals();
void testQtQuick11Attributes();
void testQtQuick11Attributes_data();
Expand Down Expand Up @@ -1944,6 +1949,59 @@ void tst_qsgtextinput::echoMode()
QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), initial);
}

#ifdef QT_GUI_PASSWORD_ECHO_DELAY
void tst_qdeclarativetextinput::passwordEchoDelay()
{
QSGView canvas(QUrl::fromLocalFile(SRCDIR "/data/echoMode.qml"));
canvas.show();
canvas.setFocus();
QApplication::setActiveWindow(&canvas);
QTest::qWaitForWindowShown(&canvas);
QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&canvas));

QVERIFY(canvas.rootObject() != 0);

QSGTextInput *input = qobject_cast<QSGTextInput *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));

QChar fillChar = QLatin1Char('*');

input->setEchoMode(QDeclarativeTextInput::Password);
QCOMPARE(input->displayText(), QString(8, fillChar));
input->setText(QString());
QCOMPARE(input->displayText(), QString());

QTest::keyPress(&canvas, '0');
QTest::keyPress(&canvas, '1');
QTest::keyPress(&canvas, '2');
QCOMPARE(input->displayText(), QString(2, fillChar) + QLatin1Char('2'));
QTest::keyPress(&canvas, '3');
QTest::keyPress(&canvas, '4');
QCOMPARE(input->displayText(), QString(4, fillChar) + QLatin1Char('4'));
QTest::keyPress(&canvas, Qt::Key_Backspace);
QCOMPARE(input->displayText(), QString(4, fillChar));
QTest::keyPress(&canvas, '4');
QCOMPARE(input->displayText(), QString(4, fillChar) + QLatin1Char('4'));
QTest::qWait(QT_GUI_PASSWORD_ECHO_DELAY);
QTRY_COMPARE(input->displayText(), QString(5, fillChar));
QTest::keyPress(&canvas, '5');
QCOMPARE(input->displayText(), QString(5, fillChar) + QLatin1Char('5'));
input->setFocus(false);
QVERIFY(!input->hasFocus());
QCOMPARE(input->displayText(), QString(6, fillChar));
input->setFocus(true);
QTRY_VERIFY(input->hasFocus());
QCOMPARE(input->displayText(), QString(6, fillChar));
QTest::keyPress(&canvas, '6');
QCOMPARE(input->displayText(), QString(6, fillChar) + QLatin1Char('6'));

QInputMethodEvent ev;
ev.setCommitString(QLatin1String("7"));
QApplication::sendEvent(&canvas, &ev);
QCOMPARE(input->displayText(), QString(7, fillChar) + QLatin1Char('7'));
}
#endif


void tst_qsgtextinput::simulateKey(QSGView *view, int key)
{
QKeyEvent press(QKeyEvent::KeyPress, key, 0);
Expand Down
Expand Up @@ -52,6 +52,8 @@
#include <QInputContext>
#include <private/qapplication_p.h>

#include "qplatformdefs.h"

#ifdef Q_OS_SYMBIAN
// In Symbian OS test data is located in applications private dir
#define SRCDIR "."
Expand Down Expand Up @@ -133,6 +135,9 @@ private slots:
void focusOutClearSelection();

void echoMode();
#ifdef QT_GUI_PASSWORD_ECHO_DELAY
void passwordEchoDelay();
#endif
void geometrySignals();
void testQtQuick11Attributes();
void testQtQuick11Attributes_data();
Expand Down Expand Up @@ -2062,6 +2067,62 @@ void tst_qdeclarativetextinput::echoMode()
delete canvas;
}


#ifdef QT_GUI_PASSWORD_ECHO_DELAY
void tst_qdeclarativetextinput::passwordEchoDelay()
{
QDeclarativeView *canvas = createView(SRCDIR "/data/echoMode.qml");
canvas->show();
canvas->setFocus();
QApplication::setActiveWindow(canvas);
QTest::qWaitForWindowShown(canvas);
QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));

QVERIFY(canvas->rootObject() != 0);

QDeclarative1TextInput *input = qobject_cast<QDeclarative1TextInput *>(qvariant_cast<QObject *>(canvas->rootObject()->property("myInput")));

QChar fillChar = QLatin1Char('*');

input->setEchoMode(QDeclarativeTextInput::Password);
QCOMPARE(input->displayText(), QString(8, fillChar));
input->setText(QString());
QCOMPARE(input->displayText(), QString());

QTest::keyPress(canvas, '0');
QTest::keyPress(canvas, '1');
QTest::keyPress(canvas, '2');
QCOMPARE(input->displayText(), QString(2, fillChar) + QLatin1Char('2'));
QTest::keyPress(canvas, '3');
QTest::keyPress(canvas, '4');
QCOMPARE(input->displayText(), QString(4, fillChar) + QLatin1Char('4'));
QTest::keyPress(canvas, Qt::Key_Backspace);
QCOMPARE(input->displayText(), QString(4, fillChar));
QTest::keyPress(canvas, '4');
QCOMPARE(input->displayText(), QString(4, fillChar) + QLatin1Char('4'));
QTest::qWait(QT_GUI_PASSWORD_ECHO_DELAY);
QTRY_COMPARE(input->displayText(), QString(5, fillChar));
QTest::keyPress(canvas, '5');
QCOMPARE(input->displayText(), QString(5, fillChar) + QLatin1Char('5'));
input->setFocus(false);
QVERIFY(!input->hasFocus());
QCOMPARE(input->displayText(), QString(6, fillChar));
input->setFocus(true);
QTRY_VERIFY(input->hasFocus());
QCOMPARE(input->displayText(), QString(6, fillChar));
QTest::keyPress(canvas, '6');
QCOMPARE(input->displayText(), QString(6, fillChar) + QLatin1Char('6'));

QInputMethodEvent ev;
ev.setCommitString(QLatin1String("7"));
QApplication::sendEvent(canvas, &ev);
QCOMPARE(input->displayText(), QString(7, fillChar) + QLatin1Char('7'));

delete canvas;
}
#endif


void tst_qdeclarativetextinput::simulateKey(QDeclarativeView *view, int key)
{
QKeyEvent press(QKeyEvent::KeyPress, key, 0);
Expand Down

0 comments on commit 249754b

Please sign in to comment.