summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Weghorn <[email protected]>2025-06-14 22:57:59 +0200
committerMichael Weghorn <[email protected]>2025-06-16 16:41:00 +0200
commit9756f62a63f58098513343714b4c0367c0a62dde (patch)
tree4629c951f46b959e73a6fe4e7a1e33fe535ec630
parent4556caaa594e0e51984cc051df9fa0e2bdd9c0c6 (diff)
QLineEdit a11y: Report displayText on a11y layer
Instead of reporting no/empty text on the a11y layer when using a QLineEdit::EchoMode that doesn't display the actual text as is (e.g. in case of a password field), use QLineEdit::displayText, which already prevents exposing the actual text unless it's also displayed on screen. Previously, the character count and caret/cursor position was still reported for the actual text, but an empty string was reported for the text itself, which was inconsistent. (A cursor position of 3 within an allegedly empty text doesn't make sense, and empty text cannot have a character count of 5.) With this commit in place, entering "hello" in the QLineEdit from the sample app from QTBUG-109599 now results in replacement/mask characters as shown on screen being reported for the text on the a11y layer as well as long as QLineEdit::Password is used. Demo using Accerciser's IPython console on Linux, with the QLineEdit's accessible object selected in Accerciser's treeview of the sample app's a11y hierarchy. Without this commit in place: In [11]: text = acc.queryText() In [12]: text.characterCount Out[12]: 5 In [13]: text.getText(0, -1) Out[13]: '' With this commit in place: In [16]: text = acc.queryText() In [17]: text.characterCount Out[17]: 5 In [18]: text.getText(0, -1) Out[18]: '●●●●●' The Orca screen reader now announces "circle" as expected when moving the cursor between the individual characters. This also fixes the assert/crash seen with Narrator as mentioned in QTBUG-109599, due to the above-mentioned mismatch between reported character count and actual text length. (QWindowsUiaTextRangeProvider::ExpandToEnclosingUnit relies on the reported character count, then accesses the character by index, but the actual string was empty.) The QAccessibleLineEdit::text(QAccessible::Value) case previously had manual handling to report mask characters. Use the displayText there, too. Adjust tst_QAccessibility::lineEditTest accordingly and extend it to test the QAccessibleTextInterface in addition. Since mask characters for passwords in QLineEdit::displayText are platform-dependent, don't compare the text reported via a11y interfaces to a hard-coded string, but instead check it matches the displayText, but differs from the (plain) text. Fixes: QTBUG-109599 Pick-to: 6.10 6.9 Change-Id: Ifebb4502b71e11d431b708eea613cb2a10e3f237 Reviewed-by: Volker Hilsheimer <[email protected]>
-rw-r--r--src/widgets/accessible/simplewidgets.cpp24
-rw-r--r--tests/auto/other/qaccessibility/tst_qaccessibility.cpp16
2 files changed, 17 insertions, 23 deletions
diff --git a/src/widgets/accessible/simplewidgets.cpp b/src/widgets/accessible/simplewidgets.cpp
index a15c51bc09f..f256f2cb37c 100644
--- a/src/widgets/accessible/simplewidgets.cpp
+++ b/src/widgets/accessible/simplewidgets.cpp
@@ -669,10 +669,7 @@ QString QAccessibleLineEdit::text(QAccessible::Text t) const
QString str;
switch (t) {
case QAccessible::Value:
- if (lineEdit()->echoMode() == QLineEdit::Normal)
- str = lineEdit()->text();
- else if (lineEdit()->echoMode() != QLineEdit::NoEcho)
- str = QString(lineEdit()->text().size(), QChar::fromLatin1('*'));
+ str = lineEdit()->displayText();
break;
default:
break;
@@ -786,19 +783,12 @@ QString QAccessibleLineEdit::text(int startOffset, int endOffset) const
if (startOffset > endOffset)
return QString();
- if (lineEdit()->echoMode() != QLineEdit::Normal)
- return QString();
-
- return lineEdit()->text().mid(startOffset, endOffset - startOffset);
+ return lineEdit()->displayText().mid(startOffset, endOffset - startOffset);
}
QString QAccessibleLineEdit::textBeforeOffset(int offset, QAccessible::TextBoundaryType boundaryType,
int *startOffset, int *endOffset) const
{
- if (lineEdit()->echoMode() != QLineEdit::Normal) {
- *startOffset = *endOffset = -1;
- return QString();
- }
if (offset == -2)
offset = cursorPosition();
return QAccessibleTextInterface::textBeforeOffset(offset, boundaryType, startOffset, endOffset);
@@ -807,10 +797,6 @@ QString QAccessibleLineEdit::textBeforeOffset(int offset, QAccessible::TextBound
QString QAccessibleLineEdit::textAfterOffset(int offset, QAccessible::TextBoundaryType boundaryType,
int *startOffset, int *endOffset) const
{
- if (lineEdit()->echoMode() != QLineEdit::Normal) {
- *startOffset = *endOffset = -1;
- return QString();
- }
if (offset == -2)
offset = cursorPosition();
return QAccessibleTextInterface::textAfterOffset(offset, boundaryType, startOffset, endOffset);
@@ -819,10 +805,6 @@ QString QAccessibleLineEdit::textAfterOffset(int offset, QAccessible::TextBounda
QString QAccessibleLineEdit::textAtOffset(int offset, QAccessible::TextBoundaryType boundaryType,
int *startOffset, int *endOffset) const
{
- if (lineEdit()->echoMode() != QLineEdit::Normal) {
- *startOffset = *endOffset = -1;
- return QString();
- }
if (offset == -2)
offset = cursorPosition();
return QAccessibleTextInterface::textAtOffset(offset, boundaryType, startOffset, endOffset);
@@ -851,7 +833,7 @@ void QAccessibleLineEdit::setSelection(int selectionIndex, int startOffset, int
int QAccessibleLineEdit::characterCount() const
{
- return lineEdit()->text().size();
+ return lineEdit()->displayText().size();
}
void QAccessibleLineEdit::scrollToSubstring(int startIndex, int endIndex)
diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
index a316e81aa57..011852c28e4 100644
--- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
+++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
@@ -2138,6 +2138,8 @@ void tst_QAccessibility::lineEditTest()
auto le = std::make_unique<QLineEdit>();
QAccessibleInterface *iface(QAccessible::queryAccessibleInterface(le.get()));
QVERIFY(iface);
+ QAccessibleTextInterface *textIface = iface->textInterface();
+ QVERIFY(textIface);
le->show();
QApplication::processEvents();
@@ -2169,13 +2171,23 @@ void tst_QAccessibility::lineEditTest()
QCOMPARE(iface->text(QAccessible::Value), QString());
le->setEchoMode(QLineEdit::Password);
QVERIFY(iface->state().passwordEdit);
- QCOMPARE(iface->text(QAccessible::Value), QString(secret.size(), QLatin1Char('*')));
+ QVERIFY(iface->text(QAccessible::Value) != le->text());
+ QCOMPARE(iface->text(QAccessible::Value), le->displayText());
+ QCOMPARE(textIface->characterCount(), secret.size());
+ QVERIFY(textIface->text(0, textIface->characterCount()) != le->text());
+ QCOMPARE(textIface->text(0, textIface->characterCount()), le->displayText());
le->setEchoMode(QLineEdit::PasswordEchoOnEdit);
QVERIFY(iface->state().passwordEdit);
- QCOMPARE(iface->text(QAccessible::Value), QString(secret.size(), QLatin1Char('*')));
+ QVERIFY(iface->text(QAccessible::Value) != le->text());
+ QCOMPARE(iface->text(QAccessible::Value), le->displayText());
+ QCOMPARE(textIface->characterCount(), secret.size());
+ QVERIFY(textIface->text(0, textIface->characterCount()) != le->text());
+ QCOMPARE(textIface->text(0, textIface->characterCount()), le->displayText());
le->setEchoMode(QLineEdit::Normal);
QVERIFY(!(iface->state().passwordEdit));
QCOMPARE(iface->text(QAccessible::Value), secret);
+ QCOMPARE(textIface->characterCount(), secret.size());
+ QCOMPARE(textIface->text(0, textIface->characterCount()), secret);
le->setParent(toplevel);
toplevel->show();