6#if QT_CONFIG(accessibility)
8#include "qapplication.h"
18#if QT_CONFIG(whatsthis)
19#include "qwhatsthis.h"
24#if QT_CONFIG(rubberband)
31#include <QtGui/private/qaccessiblehelper_p.h>
32#include <QtWidgets/private/qwidget_p.h>
34#include <qpa/qplatformwindow.h>
38using namespace Qt::StringLiterals;
40QWidgetList _q_ac_childWidgets(
const QWidget *widget);
42static QString buddyString(
const QWidget *widget)
46 QWidget *parent = widget->parentWidget();
49#if QT_CONFIG(shortcut) && QT_CONFIG(label)
50 for (QObject *o : parent->children()) {
51 QLabel *label = qobject_cast<QLabel*>(o);
52 if (label && label->buddy() == widget)
57#if QT_CONFIG(groupbox)
58 QGroupBox *groupbox = qobject_cast<QGroupBox*>(parent);
60 return groupbox->title();
66QString qt_accHotKey(
const QString &text)
69 return QKeySequence::mnemonic(text).toString(QKeySequence::NativeText);
78class QAccessibleWidgetPrivate
81 QAccessibleWidgetPrivate()
82 :role(QAccessible::Client)
85 QAccessible::Role role;
87 QStringList primarySignals;
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
114
115
116
117QAccessibleWidget::QAccessibleWidget(QWidget *w, QAccessible::Role role)
118: QAccessibleObject(w)
121 d =
new QAccessibleWidgetPrivate();
126
127
128
129
130QAccessibleWidget::QAccessibleWidget(QWidget *w, QAccessible::Role role,
const QString &name)
131 : QAccessibleWidget(w, role)
137bool QAccessibleWidget::isValid()
const
139 if (!object() ||
static_cast<QWidget *>(object())->d_func()->data.in_destructor)
141 return QAccessibleObject::isValid();
145QWindow *QAccessibleWidget::window()
const
147 const QWidget *w = widget();
149 QWindow *result = w->windowHandle();
151 if (
const QWidget *nativeParent = w->nativeParentWidget())
152 result = nativeParent->windowHandle();
158
159
160QAccessibleWidget::~QAccessibleWidget()
166
167
168QWidget *QAccessibleWidget::widget()
const
170 return qobject_cast<QWidget*>(object());
174
175
176
177QObject *QAccessibleWidget::parentObject()
const
179 QWidget *w = widget();
180 if (!w || w->isWindow() || !w->parentWidget())
186QRect QAccessibleWidget::rect()
const
188 QWidget *w = widget();
191 QPoint wpos = w->mapToGlobal(QPoint(0, 0));
193 return QRect(wpos.x(), wpos.y(), w->width(), w->height());
197
198
199
200
201
202void QAccessibleWidget::addControllingSignal(
const QString &signal)
204 QByteArray s = QMetaObject::normalizedSignature(signal.toLatin1());
205 if (Q_UNLIKELY(object()->metaObject()->indexOfSignal(s) < 0))
206 qWarning(
"Signal %s unknown in %s", s.constData(), object()->metaObject()->className());
207 d->primarySignals << QLatin1StringView(s);
210static inline bool isAncestor(
const QObject *obj,
const QObject *child)
215 child = child->parent();
221QList<std::pair<QAccessibleInterface *, QAccessible::Relation>>
222QAccessibleWidget::relations(QAccessible::Relation match )
const
224 QList<std::pair<QAccessibleInterface *, QAccessible::Relation>> rels;
225 if (match & QAccessible::Label) {
226 const QAccessible::Relation rel = QAccessible::Label;
227#if QT_CONFIG(shortcut) && QT_CONFIG(label)
228 for (QLabel *label : std::as_const(widget()->d_func()->labels)) {
230 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(label);
231 rels.emplace_back(iface, rel);
234#if QT_CONFIG(groupbox)
235 QGroupBox *groupbox = qobject_cast<QGroupBox *>(widget()->parentWidget());
236 if (groupbox && !groupbox->title().isEmpty()) {
237 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(groupbox);
238 rels.emplace_back(iface, rel);
243 if (match & QAccessible::Controlled) {
244 QObjectList allReceivers;
245 QObject *connectionObject = object();
246 for (
int sig = 0; sig < d->primarySignals.size(); ++sig) {
247 const QObjectList receivers = connectionObject->d_func()->receiverList(d->primarySignals.at(sig).toLatin1());
248 allReceivers += receivers;
251 allReceivers.removeAll(object());
253 for (
int i = 0; i < allReceivers.size(); ++i) {
254 const QAccessible::Relation rel = QAccessible::Controlled;
255 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(allReceivers.at(i));
257 rels.emplace_back(iface, rel);
265QAccessibleInterface *QAccessibleWidget::parent()
const
267 return QAccessible::queryAccessibleInterface(parentObject());
271QAccessibleInterface *QAccessibleWidget::child(
int index)
const
274 QWidgetList childList = _q_ac_childWidgets(widget());
275 if (index >= 0 && index < childList.size())
276 return QAccessible::queryAccessibleInterface(childList.at(index));
281QAccessibleInterface *QAccessibleWidget::focusChild()
const
283 if (widget()->hasFocus())
284 return QAccessible::queryAccessibleInterface(object());
286 QWidget *fw = widget()->focusWidget();
290 if (isAncestor(widget(), fw)) {
291 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(fw);
292 if (!iface || iface ==
this || !iface->focusChild())
294 return iface->focusChild();
300int QAccessibleWidget::childCount()
const
302 QWidgetList cl = _q_ac_childWidgets(widget());
307int QAccessibleWidget::indexOfChild(
const QAccessibleInterface *child)
const
311 QWidgetList cl = _q_ac_childWidgets(widget());
312 return cl.indexOf(qobject_cast<QWidget *>(child->object()));
316QString QAccessibleWidget::text(QAccessible::Text t)
const
321 case QAccessible::Name:
322 if (!d->name.isEmpty()) {
324 }
else if (!widget()->accessibleName().isEmpty()) {
325 str = widget()->accessibleName();
326 }
else if (widget()->isWindow()) {
327 if (QWindow *window = widget()->windowHandle()) {
328 if (QPlatformWindow *platformWindow = window->handle())
329 str = platformWindow->windowTitle();
332 str = qt_accStripAmp(buddyString(widget()));
335 case QAccessible::Description:
336 str = widget()->accessibleDescription();
337#if QT_CONFIG(tooltip)
339 str = widget()->toolTip();
342 case QAccessible::Identifier:
343 str = widget()->accessibleIdentifier();
345 case QAccessible::Help:
346#if QT_CONFIG(whatsthis)
347 str = widget()->whatsThis();
350 case QAccessible::Accelerator:
351 str = qt_accHotKey(buddyString(widget()));
353 case QAccessible::Value:
362QStringList QAccessibleWidget::actionNames()
const
365 if (widget()->isEnabled()) {
366 if (widget()->focusPolicy() != Qt::NoFocus)
367 names << setFocusAction();
368 if (widget()->contextMenuPolicy() == Qt::ActionsContextMenu && widget()->actions().size() > 0)
369 names << showMenuAction();
375void QAccessibleWidget::doAction(
const QString &actionName)
377 if (!widget()->isEnabled())
380 if (actionName == setFocusAction()) {
381 if (widget()->isWindow())
382 widget()->activateWindow();
383 widget()->setFocus();
384 }
else if (actionName == showMenuAction()) {
385 QContextMenuEvent e(QContextMenuEvent::Other,
386 QPoint(), widget()->mapToGlobal(QPoint()),
387 QGuiApplication::keyboardModifiers());
388 QCoreApplication::sendEvent(widget(), &e);
393QStringList QAccessibleWidget::keyBindingsForAction(
const QString & )
const
395 return QStringList();
399QAccessible::Role QAccessibleWidget::role()
const
405QAccessible::State QAccessibleWidget::state()
const
407 QAccessible::State state;
409 QWidget *w = widget();
410 if (w->testAttribute(Qt::WA_WState_Visible) ==
false)
411 state.invisible =
true;
412 if (w->focusPolicy() != Qt::NoFocus)
413 state.focusable =
true;
415 state.focused =
true;
417 state.disabled =
true;
419 if (w->windowFlags() & Qt::WindowSystemMenuHint)
420 state.movable =
true;
421 if (w->minimumSize() != w->maximumSize())
422 state.sizeable =
true;
423 if (w->isActiveWindow())
431QColor QAccessibleWidget::foregroundColor()
const
433 return widget()->palette().color(widget()->foregroundRole());
437QColor QAccessibleWidget::backgroundColor()
const
439 return widget()->palette().color(widget()->backgroundRole());
443void *QAccessibleWidget::interface_cast(QAccessible::InterfaceType t)
445 if (t == QAccessible::ActionInterface)
446 return static_cast<QAccessibleActionInterface*>(
this);
452QAccessibleWidgetV2::QAccessibleWidgetV2(QWidget *object, QAccessible::Role role,
454 : QAccessibleWidget(object, role, name)
458QAccessibleWidgetV2::QAccessibleWidgetV2(QWidget *object, QAccessible::Role role)
459 : QAccessibleWidget(object, role)
463QAccessibleWidgetV2::~QAccessibleWidgetV2() =
default;
466void *QAccessibleWidgetV2::interface_cast(QAccessible::InterfaceType t)
468 if (t == QAccessible::AttributesInterface)
469 return static_cast<QAccessibleAttributesInterface *>(
this);
470 return QAccessibleWidget::interface_cast(t);
474QList<QAccessible::Attribute> QAccessibleWidgetV2::attributeKeys()
const
476 return { QAccessible::Attribute::Locale };
480QVariant QAccessibleWidgetV2::attributeValue(QAccessible::Attribute key)
const
482 if (key == QAccessible::Attribute::Locale)
483 return QVariant::fromValue(widget()->locale());