diff options
| author | Michael Weghorn <m.weghorn@posteo.de> | 2025-09-22 12:34:53 +0200 |
|---|---|---|
| committer | Michael Weghorn <m.weghorn@posteo.de> | 2025-10-30 23:35:22 +0100 |
| commit | 064790206cae95425d38fbc72d0893f10fd82860 (patch) | |
| tree | dd64835056714b59fb971831ffa9eca4a7f680f7 /src | |
| parent | 1227db3adf91a92cf7e5f048dbeca2b9a3663c84 (diff) | |
a11y: Make QQuickTextInput accessible
So far, accessibility logic was implemented
in QQuickTextField, while its base class
QQuickTextInput didn't have any implementation.
Most of the existing logic only requires
QQuickTextInput(Private), however.
Move that logic to the QQuickTextInput(Private)
base class and only leave the QQuickTextField-specific
logic in the subclass.
Task-number: QTBUG-139943
Fixes: QTBUG-140441
Change-Id: I757222a7b6c21b575bfe404333cc7ed91af86ed7
Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
Diffstat (limited to 'src')
| -rw-r--r-- | src/quick/items/qquicktextinput.cpp | 60 | ||||
| -rw-r--r-- | src/quick/items/qquicktextinput_p_p.h | 22 | ||||
| -rw-r--r-- | src/quicktemplates/qquicktextfield.cpp | 39 | ||||
| -rw-r--r-- | src/quicktemplates/qquicktextfield_p_p.h | 11 |
4 files changed, 86 insertions, 46 deletions
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index 95e1b83c20..5adc5ce802 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -91,6 +91,10 @@ void QQuickTextInput::componentComplete() updateCursorRectangle(); if (d->cursorComponent && isCursorVisible()) QQuickTextUtil::createCursor(d); +#if QT_CONFIG(accessibility) + if (QAccessible::isActive()) + d->accessibilityActiveChanged(true); +#endif } /*! @@ -2841,6 +2845,57 @@ void QQuickTextInput::focusOutEvent(QFocusEvent *event) QQuickImplicitSizeItem::focusOutEvent(event); } +void QQuickTextInputPrivate::readOnlyChanged(bool isReadOnly) +{ + Q_UNUSED(isReadOnly); +#if QT_CONFIG(accessibility) + if (QQuickAccessibleAttached *accessibleAttached = + QQuickAccessibleAttached::attachedProperties(q_func())) + accessibleAttached->set_readOnly(isReadOnly); +#endif +} + +void QQuickTextInputPrivate::echoModeChanged(QQuickTextInput::EchoMode echoMode) +{ +#if QT_CONFIG(accessibility) + if (!QAccessible::isActive()) + return; + + if (QQuickAccessibleAttached *accessibleAttached = + QQuickAccessibleAttached::attachedProperties(q_func())) + accessibleAttached->set_passwordEdit((echoMode == QQuickTextInput::Password + || echoMode == QQuickTextInput::PasswordEchoOnEdit) + ? true + : false); +#else + Q_UNUSED(echoMode); +#endif +} + +#if QT_CONFIG(accessibility) +void QQuickTextInputPrivate::accessibilityActiveChanged(bool active) +{ + if (!active) + return; + + Q_Q(QQuickTextInput); + QQuickAccessibleAttached *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>( + qmlAttachedPropertiesObject<QQuickAccessibleAttached>(q, true)); + Q_ASSERT(accessibleAttached); + accessibleAttached->setRole(effectiveAccessibleRole()); + accessibleAttached->set_readOnly(m_readOnly); + accessibleAttached->set_passwordEdit((m_echoMode == QQuickTextInput::Password + || m_echoMode == QQuickTextInput::PasswordEchoOnEdit) + ? true + : false); +} + +QAccessible::Role QQuickTextInputPrivate::accessibleRole() const +{ + return QAccessible::EditableText; +} +#endif + /*! \qmlproperty bool QtQuick::TextInput::inputMethodComposing \readonly @@ -2908,6 +2963,11 @@ void QQuickTextInputPrivate::init() m_inputControl = new QInputControl(QInputControl::LineEdit, q); setSizePolicy(QLayoutPolicy::Expanding, QLayoutPolicy::Fixed); + + QObjectPrivate::connect(q, &QQuickTextInput::readOnlyChanged, this, + &QQuickTextInputPrivate::readOnlyChanged); + QObjectPrivate::connect(q, &QQuickTextInput::echoModeChanged, this, + &QQuickTextInputPrivate::echoModeChanged); } void QQuickTextInputPrivate::cancelInput() diff --git a/src/quick/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h index 918a6da0fd..b0c88e5f30 100644 --- a/src/quick/items/qquicktextinput_p_p.h +++ b/src/quick/items/qquicktextinput_p_p.h @@ -14,6 +14,9 @@ #include <QtCore/qelapsedtimer.h> #include <QtCore/qpointer.h> #include <QtCore/qbasictimer.h> +#if QT_CONFIG(accessibility) +#include <QtGui/qaccessible.h> +#endif #include <QtGui/qclipboard.h> #include <QtGui/qguiapplication.h> #include <QtGui/qpalette.h> @@ -41,6 +44,9 @@ class QSGInternalTextNode; class QInputControl; class Q_QUICK_EXPORT QQuickTextInputPrivate : public QQuickImplicitSizeItemPrivate +#if QT_CONFIG(accessibility) + , public QAccessible::ActivationObserver +#endif { public: Q_DECLARE_PUBLIC(QQuickTextInput) @@ -131,6 +137,10 @@ public: , selectByTouchDrag(false) #endif { +#if QT_CONFIG(accessibility) + QAccessible::installActivationObserver(this); + setAccessible(); +#endif } ~QQuickTextInputPrivate() @@ -140,6 +150,10 @@ public: // to zero it out if (m_echoMode != QQuickTextInput::Normal) m_text.fill(u'\0'); + +#if QT_CONFIG(accessibility) + QAccessible::removeActivationObserver(this); +#endif } void init(); @@ -160,6 +174,14 @@ public: #endif void handleFocusEvent(QFocusEvent *event); + virtual void readOnlyChanged(bool isReadOnly); + void echoModeChanged(QQuickTextInput::EchoMode echoMode); + +#if QT_CONFIG(accessibility) + void accessibilityActiveChanged(bool active) override; + QAccessible::Role accessibleRole() const override; +#endif + struct MaskInputData { enum Casemode { NoCaseMode, Upper, Lower }; QChar maskChar; // either the separator char or the inputmask diff --git a/src/quicktemplates/qquicktextfield.cpp b/src/quicktemplates/qquicktextfield.cpp index ec2088b012..86584ea49e 100644 --- a/src/quicktemplates/qquicktextfield.cpp +++ b/src/quicktemplates/qquicktextfield.cpp @@ -86,17 +86,10 @@ using namespace Qt::StringLiterals; QQuickTextFieldPrivate::QQuickTextFieldPrivate() { -#if QT_CONFIG(accessibility) - QAccessible::installActivationObserver(this); - setAccessible(); -#endif } QQuickTextFieldPrivate::~QQuickTextFieldPrivate() { -#if QT_CONFIG(accessibility) - QAccessible::removeActivationObserver(this); -#endif } void QQuickTextFieldPrivate::setTopInset(qreal value, bool reset) @@ -261,45 +254,25 @@ void QQuickTextFieldPrivate::implicitHeightChanged() void QQuickTextFieldPrivate::readOnlyChanged(bool isReadOnly) { - Q_UNUSED(isReadOnly); -#if QT_CONFIG(accessibility) - if (QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(q_func())) - accessibleAttached->set_readOnly(isReadOnly); -#endif + QQuickTextInputPrivate::readOnlyChanged(isReadOnly); #if QT_CONFIG(cursor) q_func()->setCursor(isReadOnly && !selectByMouse ? Qt::ArrowCursor : Qt::IBeamCursor); #endif } -void QQuickTextFieldPrivate::echoModeChanged(QQuickTextField::EchoMode echoMode) -{ -#if QT_CONFIG(accessibility) - if (QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(q_func())) - accessibleAttached->set_passwordEdit((echoMode == QQuickTextField::Password || echoMode == QQuickTextField::PasswordEchoOnEdit) ? true : false); -#else - Q_UNUSED(echoMode); -#endif -} - #if QT_CONFIG(accessibility) void QQuickTextFieldPrivate::accessibilityActiveChanged(bool active) { + QQuickTextInputPrivate::accessibilityActiveChanged(active); + if (!active) return; - Q_Q(QQuickTextField); QQuickAccessibleAttached *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(q, true)); Q_ASSERT(accessibleAttached); - accessibleAttached->setRole(effectiveAccessibleRole()); - accessibleAttached->set_readOnly(m_readOnly); - accessibleAttached->set_passwordEdit((m_echoMode == QQuickTextField::Password || m_echoMode == QQuickTextField::PasswordEchoOnEdit) ? true : false); accessibleAttached->setDescriptionImplicitly(placeholder); } -QAccessible::Role QQuickTextFieldPrivate::accessibleRole() const -{ - return QAccessible::EditableText; -} #endif void QQuickTextFieldPrivate::cancelBackground() @@ -387,8 +360,6 @@ QQuickTextField::QQuickTextField(QQuickItem *parent) #if QT_CONFIG(cursor) setCursor(Qt::IBeamCursor); #endif - QObjectPrivate::connect(this, &QQuickTextInput::readOnlyChanged, d, &QQuickTextFieldPrivate::readOnlyChanged); - QObjectPrivate::connect(this, &QQuickTextInput::echoModeChanged, d, &QQuickTextFieldPrivate::echoModeChanged); #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) if (qEnvironmentVariable("QT_QUICK_CONTROLS_TEXT_SELECTION_BEHAVIOR") == u"old"_s) QQuickTextInput::setOldSelectionDefault(); @@ -798,10 +769,6 @@ void QQuickTextField::componentComplete() if (!d->explicitHoverEnabled) setAcceptHoverEvents(QQuickControlPrivate::calcHoverEnabled(d->parentItem)); #endif -#if QT_CONFIG(accessibility) - if (QAccessible::isActive()) - d->accessibilityActiveChanged(true); -#endif } void QQuickTextField::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value) diff --git a/src/quicktemplates/qquicktextfield_p_p.h b/src/quicktemplates/qquicktextfield_p_p.h index 04e0788ed7..50bf4852c8 100644 --- a/src/quicktemplates/qquicktextfield_p_p.h +++ b/src/quicktemplates/qquicktextfield_p_p.h @@ -25,16 +25,9 @@ #include <QtQuickTemplates2/private/qquicktextfield_p.h> -#if QT_CONFIG(accessibility) -#include <QtGui/qaccessible.h> -#endif - QT_BEGIN_NAMESPACE class QQuickTextFieldPrivate : public QQuickTextInputPrivate, public QQuickItemChangeListener -#if QT_CONFIG(accessibility) - , public QAccessible::ActivationObserver -#endif { public: Q_DECLARE_PUBLIC(QQuickTextField) @@ -77,12 +70,10 @@ public: void implicitWidthChanged() override; void implicitHeightChanged() override; - void readOnlyChanged(bool isReadOnly); - void echoModeChanged(QQuickTextField::EchoMode echoMode); + virtual void readOnlyChanged(bool isReadOnly) override; #if QT_CONFIG(accessibility) void accessibilityActiveChanged(bool active) override; - QAccessible::Role accessibleRole() const override; #endif void cancelBackground(); |
