Accessiblity State as bit field.

We would like to add more flags that will be over the 32 bit boundary.
On Windows enums don't seem to digest values >32 bit.
This patch changes the state flags to be a bit field instead.

The windows part of the patch was written by Jan-Arve Sæther.

Change-Id: I2d1d87807f920ce4d4a5c7bfea8b1122ed44eb08
Reviewed-by: Jan-Arve Sæther <jan-arve.saether@nokia.com>
This commit is contained in:
Frederik Gladhorn 2012-01-05 13:57:33 +01:00 committed by Qt by Nokia
parent 5313c28b30
commit 39a052c664
11 changed files with 245 additions and 158 deletions

View File

@ -1197,6 +1197,11 @@ const char *qAccessibleEventString(QAccessible::Event event)
return QAccessible::staticMetaObject.enumerator(eventEnum).valueToKey(event); return QAccessible::staticMetaObject.enumerator(eventEnum).valueToKey(event);
} }
bool operator==(const QAccessible::State &first, const QAccessible::State &second)
{
return memcmp(&first, &second, sizeof(QAccessible::State)) == 0;
}
#ifndef QT_NO_DEBUG_STREAM #ifndef QT_NO_DEBUG_STREAM
Q_GUI_EXPORT QDebug operator<<(QDebug d, const QAccessibleInterface *iface) Q_GUI_EXPORT QDebug operator<<(QDebug d, const QAccessibleInterface *iface)
{ {
@ -1214,8 +1219,7 @@ Q_GUI_EXPORT QDebug operator<<(QDebug d, const QAccessibleInterface *iface)
if (iface->object()) { if (iface->object()) {
d << "obj=" << iface->object(); d << "obj=" << iface->object();
} }
bool invisible = iface->state() & QAccessible::Invisible; if (iface->state().invisible) {
if (invisible) {
d << "invisible"; d << "invisible";
} else { } else {
d << "rect=" << iface->rect(); d << "rect=" << iface->rect();

View File

@ -148,46 +148,47 @@ public:
AcceleratorChanged = 0x80C0 AcceleratorChanged = 0x80C0
}; };
// 64 bit enums seem hard on some platforms (windows...)
// which makes using a bit field a sensible alternative
struct State {
quint64 unavailable : 1;
quint64 selected : 1;
quint64 focused : 1;
quint64 pressed : 1;
quint64 checked : 1;
quint64 mixed : 1;
quint64 readOnly : 1;
quint64 hotTracked : 1;
quint64 defaultButton : 1;
quint64 expanded : 1;
quint64 collapsed : 1;
quint64 busy : 1;
// quint64 Floating : 1;
quint64 expandable : 1;
quint64 marqueed : 1;
quint64 animated : 1;
quint64 invisible : 1;
quint64 offscreen : 1;
quint64 sizeable : 1;
quint64 movable : 1;
quint64 selfVoicing : 1;
quint64 focusable : 1;
quint64 selectable : 1;
quint64 linked : 1;
quint64 traversed : 1;
quint64 multiSelectable : 1;
quint64 extSelectable : 1;
// quint64 alertLow : 1;
// quint64 alertMedium : 1;
// quint64 alertHigh : 1;
quint64 passwordEdit : 1;
quint64 hasPopup : 1;
quint64 modal : 1;
enum StateFlag { State() {
Normal = 0x00000000, qMemSet(this, 0, sizeof(State));
Unavailable = 0x00000001, }
Selected = 0x00000002,
Focused = 0x00000004,
Pressed = 0x00000008,
Checked = 0x00000010,
Mixed = 0x00000020,
ReadOnly = 0x00000040,
HotTracked = 0x00000080,
DefaultButton = 0x00000100,
Expanded = 0x00000200,
Collapsed = 0x00000400,
Busy = 0x00000800,
// Floating = 0x00001000,
Expandable = 0x00001000,
Marqueed = 0x00002000,
Animated = 0x00004000,
Invisible = 0x00008000,
Offscreen = 0x00010000,
Sizeable = 0x00020000,
Movable = 0x00040000,
SelfVoicing = 0x00080000,
Focusable = 0x00100000,
Selectable = 0x00200000,
Linked = 0x00400000,
Traversed = 0x00800000,
MultiSelectable = 0x01000000,
ExtSelectable = 0x02000000,
//AlertLow = 0x04000000,
//AlertMedium = 0x08000000,
//AlertHigh = 0x10000000, /* reused for HasInvokeExtension */
Protected = 0x20000000,
HasPopup = 0x40000000,
Modal = 0x80000000
}; };
Q_DECLARE_FLAGS(State, StateFlag)
enum Role { enum Role {
NoRole = 0x00000000, NoRole = 0x00000000,
@ -334,7 +335,8 @@ private:
QAccessible() {} QAccessible() {}
}; };
Q_DECLARE_OPERATORS_FOR_FLAGS(QAccessible::State) Q_GUI_EXPORT bool operator==(const QAccessible::State &first, const QAccessible::State &second);
Q_DECLARE_OPERATORS_FOR_FLAGS(QAccessible::Relation) Q_DECLARE_OPERATORS_FOR_FLAGS(QAccessible::Relation)
QT_END_NAMESPACE QT_END_NAMESPACE
Q_DECLARE_METATYPE(QSet<QAccessible::Method>) Q_DECLARE_METATYPE(QSet<QAccessible::Method>)
@ -377,7 +379,6 @@ public:
virtual QRect rect() const = 0; virtual QRect rect() const = 0;
virtual QAccessible::Role role() const = 0; virtual QAccessible::Role role() const = 0;
virtual QAccessible::State state() const = 0; virtual QAccessible::State state() const = 0;
// FIXME virtual QSet<QAccessible::State> states() const = 0;
virtual QColor foregroundColor() const; virtual QColor foregroundColor() const;
virtual QColor backgroundColor() const; virtual QColor backgroundColor() const;

View File

@ -304,7 +304,7 @@ QAccessible::Role QAccessibleApplication::role() const
/*! \reimp */ /*! \reimp */
QAccessible::State QAccessibleApplication::state() const QAccessible::State QAccessibleApplication::state() const
{ {
return QGuiApplication::activeWindow() ? QAccessible::Focused : QAccessible::Normal; return QAccessible::State();
} }

View File

@ -363,7 +363,7 @@ QAccessible::Role QAccessibleTable::role() const
QAccessible::State QAccessibleTable::state() const QAccessible::State QAccessibleTable::state() const
{ {
return QAccessible::Normal; return QAccessible::State();
} }
QAccessibleInterface *QAccessibleTable::childAt(int x, int y) const QAccessibleInterface *QAccessibleTable::childAt(int x, int y) const
@ -701,34 +701,34 @@ QAccessible::Role QAccessibleTableCell::role() const
QAccessible::State QAccessibleTableCell::state() const QAccessible::State QAccessibleTableCell::state() const
{ {
QAccessible::State st = QAccessible::Normal; QAccessible::State st;
QRect globalRect = view->rect(); QRect globalRect = view->rect();
globalRect.translate(view->mapToGlobal(QPoint(0,0))); globalRect.translate(view->mapToGlobal(QPoint(0,0)));
if (!globalRect.intersects(rect())) if (!globalRect.intersects(rect()))
st |= QAccessible::Invisible; st.invisible = true;
if (view->selectionModel()->isSelected(m_index)) if (view->selectionModel()->isSelected(m_index))
st |= QAccessible::Selected; st.selected = true;
if (view->selectionModel()->currentIndex() == m_index) if (view->selectionModel()->currentIndex() == m_index)
st |= QAccessible::Focused; st.focused = true;
if (m_index.model()->data(m_index, Qt::CheckStateRole).toInt() == Qt::Checked) if (m_index.model()->data(m_index, Qt::CheckStateRole).toInt() == Qt::Checked)
st |= QAccessible::Checked; st.checked = true;
Qt::ItemFlags flags = m_index.flags(); Qt::ItemFlags flags = m_index.flags();
if (flags & Qt::ItemIsSelectable) { if (flags & Qt::ItemIsSelectable) {
st |= QAccessible::Selectable; st.selectable = true;
st |= QAccessible::Focusable; st.focusable = true;
if (view->selectionMode() == QAbstractItemView::MultiSelection) if (view->selectionMode() == QAbstractItemView::MultiSelection)
st |= QAccessible::MultiSelectable; st.multiSelectable = true;
if (view->selectionMode() == QAbstractItemView::ExtendedSelection) if (view->selectionMode() == QAbstractItemView::ExtendedSelection)
st |= QAccessible::ExtSelectable; st.extSelectable = true;
} }
if (m_role == QAccessible::TreeItem) { if (m_role == QAccessible::TreeItem) {
const QTreeView *treeView = qobject_cast<const QTreeView*>(view); const QTreeView *treeView = qobject_cast<const QTreeView*>(view);
if (treeView->model()->hasChildren(m_index)) if (treeView->model()->hasChildren(m_index))
st |= QAccessible::Expandable; st.expandable = true;
if (treeView->isExpanded(m_index)) if (treeView->isExpanded(m_index))
st |= QAccessible::Expanded; st.expanded = true;
} }
return st; return st;
} }
@ -840,7 +840,7 @@ QAccessible::Role QAccessibleTableHeaderCell::role() const
QAccessible::State QAccessibleTableHeaderCell::state() const QAccessible::State QAccessibleTableHeaderCell::state() const
{ {
return QAccessible::Normal; return QAccessible::State();
} }
QRect QAccessibleTableHeaderCell::rect() const QRect QAccessibleTableHeaderCell::rect() const

View File

@ -264,7 +264,7 @@ public:
QObject *object() const { return 0; } QObject *object() const { return 0; }
QAccessible::Role role() const { return QAccessible::Pane; } QAccessible::Role role() const { return QAccessible::Pane; }
QAccessible::State state() const { return QAccessible::Normal; } QAccessible::State state() const { return QAccessible::State(); }
QRect rect() const { return QRect(); } QRect rect() const { return QRect(); }
bool isValid() const { return true; } bool isValid() const { return true; }

View File

@ -282,28 +282,28 @@ void QAccessibleMenuItem::setText(QAccessible::Text /*t*/, const QString & /*tex
QAccessible::State QAccessibleMenuItem::state() const QAccessible::State QAccessibleMenuItem::state() const
{ {
QAccessible::State s = QAccessible::Normal; QAccessible::State s;
QWidget *own = owner(); QWidget *own = owner();
if (own->testAttribute(Qt::WA_WState_Visible) == false || m_action->isVisible() == false) { if (own->testAttribute(Qt::WA_WState_Visible) == false || m_action->isVisible() == false) {
s |= QAccessible::Invisible; s.invisible = true;
} }
if (QMenu *menu = qobject_cast<QMenu*>(own)) { if (QMenu *menu = qobject_cast<QMenu*>(own)) {
if (menu->activeAction() == m_action) if (menu->activeAction() == m_action)
s |= QAccessible::Focused; s.focused = true;
#ifndef QT_NO_MENUBAR #ifndef QT_NO_MENUBAR
} else if (QMenuBar *menuBar = qobject_cast<QMenuBar*>(own)) { } else if (QMenuBar *menuBar = qobject_cast<QMenuBar*>(own)) {
if (menuBar->activeAction() == m_action) if (menuBar->activeAction() == m_action)
s |= QAccessible::Focused; s.focused = true;
#endif #endif
} }
if (own->style()->styleHint(QStyle::SH_Menu_MouseTracking)) if (own->style()->styleHint(QStyle::SH_Menu_MouseTracking))
s |= QAccessible::HotTracked; s.hotTracked = true;
if (m_action->isSeparator() || !m_action->isEnabled()) if (m_action->isSeparator() || !m_action->isEnabled())
s |= QAccessible::Unavailable; s.unavailable = true;
if (m_action->isChecked()) if (m_action->isChecked())
s |= QAccessible::Checked; s.checked = true;
return s; return s;
} }

View File

@ -845,18 +845,21 @@ void QAccessibleMdiSubWindow::setText(QAccessible::Text textType, const QString
QAccessible::State QAccessibleMdiSubWindow::state() const QAccessible::State QAccessibleMdiSubWindow::state() const
{ {
QAccessible::State state = QAccessible::Normal | QAccessible::Focusable; QAccessible::State state;
if (!mdiSubWindow()->isMaximized()) state.focusable = true;
state |= (QAccessible::Movable | QAccessible::Sizeable); if (!mdiSubWindow()->isMaximized()) {
state.movable = true;
state.sizeable = true;
}
if (mdiSubWindow()->isAncestorOf(QApplication::focusWidget()) if (mdiSubWindow()->isAncestorOf(QApplication::focusWidget())
|| QApplication::focusWidget() == mdiSubWindow()) || QApplication::focusWidget() == mdiSubWindow())
state |= QAccessible::Focused; state.focused = true;
if (!mdiSubWindow()->isVisible()) if (!mdiSubWindow()->isVisible())
state |= QAccessible::Invisible; state.invisible = true;
if (!mdiSubWindow()->parentWidget()->contentsRect().contains(mdiSubWindow()->geometry())) if (!mdiSubWindow()->parentWidget()->contentsRect().contains(mdiSubWindow()->geometry()))
state |= QAccessible::Offscreen; state.offscreen = true;
if (!mdiSubWindow()->isEnabled()) if (!mdiSubWindow()->isEnabled())
state |= QAccessible::Unavailable; state.unavailable = true;
return state; return state;
} }
@ -1256,17 +1259,17 @@ QString QAccessibleTitleBar::text(QAccessible::Text t) const
QAccessible::State QAccessibleTitleBar::state() const QAccessible::State QAccessibleTitleBar::state() const
{ {
QAccessible::State state = QAccessible::Normal; QAccessible::State state;
QDockWidget *w = dockWidget(); QDockWidget *w = dockWidget();
if (w->testAttribute(Qt::WA_WState_Visible) == false) if (w->testAttribute(Qt::WA_WState_Visible) == false)
state |= QAccessible::Invisible; state.invisible = true;
if (w->focusPolicy() != Qt::NoFocus && w->isActiveWindow()) if (w->focusPolicy() != Qt::NoFocus && w->isActiveWindow())
state |= QAccessible::Focusable; state.focusable = true;
if (w->hasFocus()) if (w->hasFocus())
state |= QAccessible::Focused; state.focused = true;
if (!w->isEnabled()) if (!w->isEnabled())
state |= QAccessible::Unavailable; state.unavailable = true;
return state; return state;
} }

View File

@ -140,18 +140,18 @@ QAccessible::State QAccessibleButton::state() const
QAbstractButton *b = button(); QAbstractButton *b = button();
QCheckBox *cb = qobject_cast<QCheckBox *>(b); QCheckBox *cb = qobject_cast<QCheckBox *>(b);
if (b->isChecked()) if (b->isChecked())
state |= QAccessible::Checked; state.checked = true;
else if (cb && cb->checkState() == Qt::PartiallyChecked) else if (cb && cb->checkState() == Qt::PartiallyChecked)
state |= QAccessible::Mixed; state.mixed = true;
if (b->isDown()) if (b->isDown())
state |= QAccessible::Pressed; state.pressed = true;
QPushButton *pb = qobject_cast<QPushButton*>(b); QPushButton *pb = qobject_cast<QPushButton*>(b);
if (pb) { if (pb) {
if (pb->isDefault()) if (pb->isDefault())
state |= QAccessible::DefaultButton; state.defaultButton = true;
#ifndef QT_NO_MENU #ifndef QT_NO_MENU
if (pb->menu()) if (pb->menu())
state |= QAccessible::HasPopup; state.hasPopup = true;
#endif #endif
} }
@ -171,7 +171,7 @@ QStringList QAccessibleButton::actionNames() const
break; break;
default: default:
if (button()->isCheckable()) { if (button()->isCheckable()) {
if (state() & QAccessible::Checked) { if (state().checked) {
names << uncheckAction(); names << uncheckAction();
} else { } else {
// FIXME // FIXME
@ -263,10 +263,10 @@ QAccessible::State QAccessibleToolButton::state() const
{ {
QAccessible::State st = QAccessibleButton::state(); QAccessible::State st = QAccessibleButton::state();
if (toolButton()->autoRaise()) if (toolButton()->autoRaise())
st |= QAccessible::HotTracked; st.hotTracked = true;
#ifndef QT_NO_MENU #ifndef QT_NO_MENU
if (toolButton()->menu()) if (toolButton()->menu())
st |= QAccessible::HasPopup; st.hasPopup = true;
#endif #endif
return st; return st;
} }
@ -588,16 +588,16 @@ QAccessible::State QAccessibleLineEdit::state() const
QLineEdit *l = lineEdit(); QLineEdit *l = lineEdit();
if (l->isReadOnly()) if (l->isReadOnly())
state |= QAccessible::ReadOnly; state.readOnly = true;
if (l->echoMode() != QLineEdit::Normal) if (l->echoMode() != QLineEdit::Normal)
state |= QAccessible::Protected; state.passwordEdit = true;
state |= QAccessible::Selectable; state.selectable = true;
if (l->hasSelectedText()) if (l->hasSelectedText())
state |= QAccessible::Selected; state.selected = true;
if (l->contextMenuPolicy() != Qt::NoContextMenu if (l->contextMenuPolicy() != Qt::NoContextMenu
&& l->contextMenuPolicy() != Qt::PreventContextMenu) && l->contextMenuPolicy() != Qt::PreventContextMenu)
state |= QAccessible::HasPopup; state.hasPopup = true;
return state; return state;
} }

View File

@ -704,7 +704,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accNavigate(long navDir, VARIANT v
QAccessibleInterface *sibling = 0; QAccessibleInterface *sibling = 0;
sibling = pIface->child(i); sibling = pIface->child(i);
Q_ASSERT(sibling); Q_ASSERT(sibling);
if ((accessible->relationTo(sibling) & QAccessible::Self) || (sibling->state() & QAccessible::Invisible)) { if ((accessible->relationTo(sibling) & QAccessible::Self) || sibling->state().invisible) {
//ignore ourself and invisible siblings //ignore ourself and invisible siblings
delete sibling; delete sibling;
continue; continue;
@ -1058,8 +1058,62 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accState(VARIANT varID, VARIAN
state = accessible->state(); state = accessible->state();
} }
LONG st = 0;
if (state.animated)
st |= STATE_SYSTEM_ANIMATED;
if (state.busy)
st |= STATE_SYSTEM_BUSY;
if (state.checked)
st |= STATE_SYSTEM_CHECKED;
if (state.collapsed)
st |= STATE_SYSTEM_COLLAPSED;
if (state.defaultButton)
st |= STATE_SYSTEM_DEFAULT;
if (state.expanded)
st |= STATE_SYSTEM_EXPANDED;
if (state.extSelectable)
st |= STATE_SYSTEM_EXTSELECTABLE;
if (state.focusable)
st |= STATE_SYSTEM_FOCUSABLE;
if (state.focused)
st |= STATE_SYSTEM_FOCUSED;
if (state.hasPopup)
st |= STATE_SYSTEM_HASPOPUP;
if (state.hotTracked)
st |= STATE_SYSTEM_HOTTRACKED;
if (state.invisible)
st |= STATE_SYSTEM_INVISIBLE;
if (state.linked)
st |= STATE_SYSTEM_LINKED;
if (state.marqueed)
st |= STATE_SYSTEM_MARQUEED;
if (state.mixed)
st |= STATE_SYSTEM_MIXED;
if (state.movable)
st |= STATE_SYSTEM_MOVEABLE;
if (state.multiSelectable)
st |= STATE_SYSTEM_MULTISELECTABLE;
if (state.offscreen)
st |= STATE_SYSTEM_OFFSCREEN;
if (state.pressed)
st |= STATE_SYSTEM_PRESSED;
if (state.passwordEdit)
st |= STATE_SYSTEM_PROTECTED;
if (state.readOnly)
st |= STATE_SYSTEM_READONLY;
if (state.selectable)
st |= STATE_SYSTEM_SELECTABLE;
if (state.selected)
st |= STATE_SYSTEM_SELECTED;
if (state.selfVoicing)
st |= STATE_SYSTEM_SELFVOICING;
if (state.sizeable)
st |= STATE_SYSTEM_SIZEABLE;
if (state.traversed)
st |= STATE_SYSTEM_TRAVERSED;
(*pvarState).vt = VT_I4; (*pvarState).vt = VT_I4;
(*pvarState).lVal = state; (*pvarState).lVal = st;
return S_OK; return S_OK;
} }
@ -1169,7 +1223,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accSelection(VARIANT *pvarChil
bool isSelected = false; bool isSelected = false;
QAccessibleInterface *child = accessible->child(i); QAccessibleInterface *child = accessible->child(i);
if (child) { if (child) {
isSelected = child->state() & QAccessible::Selected; isSelected = child->state().selected;
delete child; delete child;
} }
if (isSelected) if (isSelected)

View File

@ -373,7 +373,7 @@ QAccessible::Relation QAccessibleWidget::relationTo(const QAccessibleInterface *
if (wg.intersects(sg)) { if (wg.intersects(sg)) {
QAccessibleInterface *pIface = 0; QAccessibleInterface *pIface = 0;
pIface = sibIface->parent(); pIface = sibIface->parent();
if (pIface && !((sibIface->state() | state()) & QAccessible::Invisible)) { if (pIface && !(sibIface->state().invisible | state().invisible)) {
int wi = pIface->indexOfChild(this); int wi = pIface->indexOfChild(this);
int si = pIface->indexOfChild(sibIface); int si = pIface->indexOfChild(sibIface);
@ -430,7 +430,7 @@ int QAccessibleWidget::navigate(QAccessible::RelationFlag relation, int entry,
QAccessibleInterface *sibling = 0; QAccessibleInterface *sibling = 0;
for (int i = pIface->indexOfChild(this) + 1; i <= sibCount && entry; ++i) { for (int i = pIface->indexOfChild(this) + 1; i <= sibCount && entry; ++i) {
sibling = pIface->child(i - 1); sibling = pIface->child(i - 1);
if (!sibling || (sibling->state() & QAccessible::Invisible)) { if (!sibling || (sibling->state().invisible)) {
delete sibling; delete sibling;
sibling = 0; sibling = 0;
continue; continue;
@ -460,7 +460,7 @@ int QAccessibleWidget::navigate(QAccessible::RelationFlag relation, int entry,
for (int i = 1; i < index && entry; ++i) { for (int i = 1; i < index && entry; ++i) {
sibling = pIface->child(i - 1); sibling = pIface->child(i - 1);
Q_ASSERT(sibling); Q_ASSERT(sibling);
if (!sibling || (sibling->state() & QAccessible::Invisible)) { if (!sibling || (sibling->state().invisible)) {
delete sibling; delete sibling;
sibling = 0; sibling = 0;
continue; continue;
@ -690,22 +690,22 @@ QAccessible::Role QAccessibleWidget::role() const
/*! \reimp */ /*! \reimp */
QAccessible::State QAccessibleWidget::state() const QAccessible::State QAccessibleWidget::state() const
{ {
QAccessible::State state = QAccessible::Normal; QAccessible::State state;
QWidget *w = widget(); QWidget *w = widget();
if (w->testAttribute(Qt::WA_WState_Visible) == false) if (w->testAttribute(Qt::WA_WState_Visible) == false)
state |= QAccessible::Invisible; state.invisible = true;
if (w->focusPolicy() != Qt::NoFocus && w->isActiveWindow()) if (w->focusPolicy() != Qt::NoFocus && w->isActiveWindow())
state |= QAccessible::Focusable; state.focusable = true;
if (w->hasFocus()) if (w->hasFocus())
state |= QAccessible::Focused; state.focused = true;
if (!w->isEnabled()) if (!w->isEnabled())
state |= QAccessible::Unavailable; state.unavailable = true;
if (w->isWindow()) { if (w->isWindow()) {
if (w->windowFlags() & Qt::WindowSystemMenuHint) if (w->windowFlags() & Qt::WindowSystemMenuHint)
state |= QAccessible::Movable; state.movable = true;
if (w->minimumSize() != w->maximumSize()) if (w->minimumSize() != w->maximumSize())
state |= QAccessible::Sizeable; state.sizeable = true;
} }
return state; return state;

View File

@ -230,6 +230,7 @@ private slots:
void customWidget(); void customWidget();
void deletedWidget(); void deletedWidget();
void statesStructTest();
void navigateHierarchy(); void navigateHierarchy();
void sliderTest(); void sliderTest();
void navigateCovered(); void navigateCovered();
@ -329,7 +330,7 @@ QAccessible::State state(QWidget * const widget)
QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(widget); QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(widget);
if (!iface) if (!iface)
qWarning() << "Cannot get QAccessibleInterface for widget"; qWarning() << "Cannot get QAccessibleInterface for widget";
QAccessible::State state = (iface ? iface->state() : static_cast<QAccessible::State>(0)); QAccessible::State state = (iface ? iface->state() : QAccessible::State());
delete iface; delete iface;
return state; return state;
} }
@ -462,6 +463,26 @@ void tst_QAccessibility::deletedWidget()
delete iface; delete iface;
} }
void tst_QAccessibility::statesStructTest()
{
QAccessible::State s1;
QVERIFY(s1.unavailable == 0);
QVERIFY(s1.focusable == 0);
QVERIFY(s1.modal == 0);
QAccessible::State s2;
QVERIFY(s2 == s1);
s2.busy = true;
QVERIFY(!(s2 == s1));
s1.busy = true;
QVERIFY(s2 == s1);
s1 = QAccessible::State();
QVERIFY(!(s2 == s1));
s1 = s2;
QVERIFY(s2 == s1);
QVERIFY(s1.busy == 1);
}
void tst_QAccessibility::sliderTest() void tst_QAccessibility::sliderTest()
{ {
{ {
@ -583,9 +604,9 @@ void tst_QAccessibility::navigateCovered()
w1->raise(); w1->raise();
QVERIFY(iface1->relationTo(iface2) & QAccessible::Covers); QVERIFY(iface1->relationTo(iface2) & QAccessible::Covers);
QVERIFY(iface2->relationTo(iface1) & QAccessible::Covered); QVERIFY(iface2->relationTo(iface1) & QAccessible::Covered);
QVERIFY(!(iface1->state() & QAccessible::Invisible)); QVERIFY(!iface1->state().invisible);
w1->hide(); w1->hide();
QVERIFY(iface1->state() & QAccessible::Invisible); QVERIFY(iface1->state().invisible);
QVERIFY(!(iface1->relationTo(iface2) & QAccessible::Covers)); QVERIFY(!(iface1->relationTo(iface2) & QAccessible::Covers));
QVERIFY(!(iface2->relationTo(iface1) & QAccessible::Covered)); QVERIFY(!(iface2->relationTo(iface1) & QAccessible::Covered));
QCOMPARE(iface2->navigate(QAccessible::Covered, 1, &iface3), -1); QCOMPARE(iface2->navigate(QAccessible::Covered, 1, &iface3), -1);
@ -809,23 +830,23 @@ void tst_QAccessibility::hideShowTest()
QWidget * const window = new QWidget(); QWidget * const window = new QWidget();
QWidget * const child = new QWidget(window); QWidget * const child = new QWidget(window);
QVERIFY(state(window) & QAccessible::Invisible); QVERIFY(state(window).invisible);
QVERIFY(state(child) & QAccessible::Invisible); QVERIFY(state(child).invisible);
QTestAccessibility::clearEvents(); QTestAccessibility::clearEvents();
// show() and veryfy that both window and child are not invisible and get ObjectShow events. // show() and veryfy that both window and child are not invisible and get ObjectShow events.
window->show(); window->show();
QVERIFY(state(window) ^ QAccessible::Invisible); QVERIFY(!state(window).invisible);
QVERIFY(state(child) ^ QAccessible::Invisible); QVERIFY(!state(child).invisible);
QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(window, 0, QAccessible::ObjectShow))); QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(window, 0, QAccessible::ObjectShow)));
QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(child, 0, QAccessible::ObjectShow))); QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(child, 0, QAccessible::ObjectShow)));
QTestAccessibility::clearEvents(); QTestAccessibility::clearEvents();
// hide() and veryfy that both window and child are invisible and get ObjectHide events. // hide() and veryfy that both window and child are invisible and get ObjectHide events.
window->hide(); window->hide();
QVERIFY(state(window) & QAccessible::Invisible); QVERIFY(state(window).invisible);
QVERIFY(state(child) & QAccessible::Invisible); QVERIFY(state(child).invisible);
QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(window, 0, QAccessible::ObjectHide))); QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(window, 0, QAccessible::ObjectHide)));
QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(child, 0, QAccessible::ObjectHide))); QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(child, 0, QAccessible::ObjectHide)));
QTestAccessibility::clearEvents(); QTestAccessibility::clearEvents();
@ -987,12 +1008,12 @@ void tst_QAccessibility::buttonTest()
QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::checkAction() << QAccessibleActionInterface::setFocusAction()); QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::checkAction() << QAccessibleActionInterface::setFocusAction());
QCOMPARE(actionInterface->localizedActionDescription(QAccessibleActionInterface::checkAction()), QString("Checks the checkbox")); QCOMPARE(actionInterface->localizedActionDescription(QAccessibleActionInterface::checkAction()), QString("Checks the checkbox"));
QVERIFY(!toggleButton.isChecked()); QVERIFY(!toggleButton.isChecked());
QVERIFY((interface->state() & QAccessible::Checked) == 0); QVERIFY(!interface->state().checked);
actionInterface->doAction(QAccessibleActionInterface::checkAction()); actionInterface->doAction(QAccessibleActionInterface::checkAction());
QTest::qWait(500); QTest::qWait(500);
QVERIFY(toggleButton.isChecked()); QVERIFY(toggleButton.isChecked());
QCOMPARE(actionInterface->actionNames().at(0), QAccessibleActionInterface::uncheckAction()); QCOMPARE(actionInterface->actionNames().at(0), QAccessibleActionInterface::uncheckAction());
QVERIFY(interface->state() & QAccessible::Checked); QVERIFY(interface->state().checked);
delete interface; delete interface;
{ {
@ -1006,7 +1027,7 @@ void tst_QAccessibility::buttonTest()
menuButton.show(); menuButton.show();
QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&menuButton); QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&menuButton);
QCOMPARE(interface->role(), QAccessible::ButtonMenu); QCOMPARE(interface->role(), QAccessible::ButtonMenu);
QVERIFY(interface->state() & QAccessible::HasPopup); QVERIFY(interface->state().hasPopup);
QCOMPARE(interface->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::showMenuAction() << QAccessibleActionInterface::setFocusAction()); QCOMPARE(interface->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::showMenuAction() << QAccessibleActionInterface::setFocusAction());
// showing the menu enters a new event loop... // showing the menu enters a new event loop...
// interface->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction()); // interface->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
@ -1020,11 +1041,11 @@ void tst_QAccessibility::buttonTest()
actionInterface = interface->actionInterface(); actionInterface = interface->actionInterface();
QCOMPARE(interface->role(), QAccessible::CheckBox); QCOMPARE(interface->role(), QAccessible::CheckBox);
QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::checkAction() << QAccessibleActionInterface::setFocusAction()); QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::checkAction() << QAccessibleActionInterface::setFocusAction());
QVERIFY((interface->state() & QAccessible::Checked) == 0); QVERIFY(!interface->state().checked);
actionInterface->doAction(QAccessibleActionInterface::checkAction()); actionInterface->doAction(QAccessibleActionInterface::checkAction());
QTest::qWait(500); QTest::qWait(500);
QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::uncheckAction() << QAccessibleActionInterface::setFocusAction()); QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::uncheckAction() << QAccessibleActionInterface::setFocusAction());
QVERIFY(interface->state() & QAccessible::Checked); QVERIFY(interface->state().checked);
QVERIFY(checkBox.isChecked()); QVERIFY(checkBox.isChecked());
delete interface; delete interface;
@ -1033,11 +1054,11 @@ void tst_QAccessibility::buttonTest()
actionInterface = interface->actionInterface(); actionInterface = interface->actionInterface();
QCOMPARE(interface->role(), QAccessible::RadioButton); QCOMPARE(interface->role(), QAccessible::RadioButton);
QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::checkAction() << QAccessibleActionInterface::setFocusAction()); QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::checkAction() << QAccessibleActionInterface::setFocusAction());
QVERIFY((interface->state() & QAccessible::Checked) == 0); QVERIFY(!interface->state().checked);
actionInterface->doAction(QAccessibleActionInterface::checkAction()); actionInterface->doAction(QAccessibleActionInterface::checkAction());
QTest::qWait(500); QTest::qWait(500);
QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::checkAction() << QAccessibleActionInterface::setFocusAction()); QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::checkAction() << QAccessibleActionInterface::setFocusAction());
QVERIFY(interface->state() & QAccessible::Checked); QVERIFY(interface->state().checked);
QVERIFY(checkBox.isChecked()); QVERIFY(checkBox.isChecked());
delete interface; delete interface;
@ -1098,15 +1119,15 @@ void tst_QAccessibility::scrollBarTest()
QScrollBar *scrollBar = new QScrollBar(Qt::Horizontal); QScrollBar *scrollBar = new QScrollBar(Qt::Horizontal);
QAccessibleInterface * const scrollBarInterface = QAccessible::queryAccessibleInterface(scrollBar); QAccessibleInterface * const scrollBarInterface = QAccessible::queryAccessibleInterface(scrollBar);
QVERIFY(scrollBarInterface); QVERIFY(scrollBarInterface);
QVERIFY(scrollBarInterface->state() & QAccessible::Invisible); QVERIFY(scrollBarInterface->state().invisible);
scrollBar->resize(200, 50); scrollBar->resize(200, 50);
scrollBar->show(); scrollBar->show();
QVERIFY(scrollBarInterface->state() ^ QAccessible::Invisible); QVERIFY(!scrollBarInterface->state().invisible);
QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(scrollBar, 0, QAccessible::ObjectShow))); QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(scrollBar, 0, QAccessible::ObjectShow)));
QTestAccessibility::clearEvents(); QTestAccessibility::clearEvents();
scrollBar->hide(); scrollBar->hide();
QVERIFY(scrollBarInterface->state() & QAccessible::Invisible); QVERIFY(scrollBarInterface->state().invisible);
QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(scrollBar, 0, QAccessible::ObjectHide))); QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(scrollBar, 0, QAccessible::ObjectHide)));
QTestAccessibility::clearEvents(); QTestAccessibility::clearEvents();
@ -1150,7 +1171,7 @@ void tst_QAccessibility::tabTest()
// and cleared correctly. // and cleared correctly.
QAccessibleInterface *leftButton = interface->child(0); QAccessibleInterface *leftButton = interface->child(0);
QCOMPARE(leftButton->role(), QAccessible::PushButton); QCOMPARE(leftButton->role(), QAccessible::PushButton);
QVERIFY(leftButton->state() & QAccessible::Invisible); QVERIFY(leftButton->state().invisible);
delete leftButton; delete leftButton;
const int lots = 5; const int lots = 5;
@ -1164,13 +1185,13 @@ void tst_QAccessibility::tabTest()
QVERIFY(child2); QVERIFY(child2);
QCOMPARE(child2->role(), QAccessible::PageTab); QCOMPARE(child2->role(), QAccessible::PageTab);
QVERIFY((child1->state() & QAccessible::Invisible) == false); QVERIFY((child1->state().invisible) == false);
tabBar->hide(); tabBar->hide();
QCoreApplication::processEvents(); QCoreApplication::processEvents();
QTest::qWait(100); QTest::qWait(100);
QVERIFY(child1->state() & QAccessible::Invisible); QVERIFY(child1->state().invisible);
tabBar->show(); tabBar->show();
tabBar->setCurrentIndex(0); tabBar->setCurrentIndex(0);
@ -1767,28 +1788,32 @@ void tst_QAccessibility::mdiSubWindowTest()
mdiArea.setActiveSubWindow(testWindow); mdiArea.setActiveSubWindow(testWindow);
// state // state
QAccessible::State state = QAccessible::Normal | QAccessible::Focusable | QAccessible::Focused QAccessible::State state;
| QAccessible::Movable | QAccessible::Sizeable; state.focusable = true;
state.focused = true;
state.movable = true;
state.sizeable = true;
QCOMPARE(interface->state(), state); QCOMPARE(interface->state(), state);
const QRect originalGeometry = testWindow->geometry(); const QRect originalGeometry = testWindow->geometry();
testWindow->showMaximized(); testWindow->showMaximized();
state &= (uint)~QAccessible::Sizeable; state.sizeable = false;
state &= (uint)~QAccessible::Movable; state.movable = false;
QCOMPARE(interface->state(), state); QCOMPARE(interface->state(), state);
testWindow->showNormal(); testWindow->showNormal();
testWindow->move(-10, 0); testWindow->move(-10, 0);
QVERIFY(interface->state() & QAccessible::Offscreen); QVERIFY(interface->state().offscreen);
testWindow->setVisible(false); testWindow->setVisible(false);
QVERIFY(interface->state() & QAccessible::Invisible); QVERIFY(interface->state().invisible);
testWindow->setVisible(true); testWindow->setVisible(true);
testWindow->setEnabled(false); testWindow->setEnabled(false);
QVERIFY(interface->state() & QAccessible::Unavailable); QVERIFY(interface->state().unavailable);
testWindow->setEnabled(true); testWindow->setEnabled(true);
qApp->setActiveWindow(&mdiArea); qApp->setActiveWindow(&mdiArea);
mdiArea.setActiveSubWindow(testWindow); mdiArea.setActiveSubWindow(testWindow);
testWindow->setFocus(); testWindow->setFocus();
QVERIFY(testWindow->isAncestorOf(qApp->focusWidget())); QVERIFY(testWindow->isAncestorOf(qApp->focusWidget()));
QVERIFY(interface->state() & QAccessible::Focused); QVERIFY(interface->state().focused);
testWindow->setGeometry(originalGeometry); testWindow->setGeometry(originalGeometry);
if (isSubWindowsPlacedNextToEachOther) { if (isSubWindowsPlacedNextToEachOther) {
@ -1848,41 +1873,41 @@ void tst_QAccessibility::lineEditTest()
QApplication::processEvents(); QApplication::processEvents();
QCOMPARE(iface->childCount(), 0); QCOMPARE(iface->childCount(), 0);
QVERIFY(iface->state() & QAccessible::Sizeable); QVERIFY(iface->state().sizeable);
QVERIFY(iface->state() & QAccessible::Movable); QVERIFY(iface->state().movable);
QCOMPARE(bool(iface->state() & QAccessible::Focusable), le->isActiveWindow()); QCOMPARE(bool(iface->state().focusable), le->isActiveWindow());
QVERIFY(iface->state() & QAccessible::Selectable); QVERIFY(iface->state().selectable);
QVERIFY(iface->state() & QAccessible::HasPopup); QVERIFY(iface->state().hasPopup);
QCOMPARE(bool(iface->state() & QAccessible::Focused), le->hasFocus()); QCOMPARE(bool(iface->state().focused), le->hasFocus());
QString secret(QLatin1String("secret")); QString secret(QLatin1String("secret"));
le->setText(secret); le->setText(secret);
le->setEchoMode(QLineEdit::Normal); le->setEchoMode(QLineEdit::Normal);
QVERIFY(!(iface->state() & QAccessible::Protected)); QVERIFY(!(iface->state().passwordEdit));
QCOMPARE(iface->text(QAccessible::Value), secret); QCOMPARE(iface->text(QAccessible::Value), secret);
le->setEchoMode(QLineEdit::NoEcho); le->setEchoMode(QLineEdit::NoEcho);
QVERIFY(iface->state() & QAccessible::Protected); QVERIFY(iface->state().passwordEdit);
QVERIFY(iface->text(QAccessible::Value).isEmpty()); QVERIFY(iface->text(QAccessible::Value).isEmpty());
le->setEchoMode(QLineEdit::Password); le->setEchoMode(QLineEdit::Password);
QVERIFY(iface->state() & QAccessible::Protected); QVERIFY(iface->state().passwordEdit);
QVERIFY(iface->text(QAccessible::Value).isEmpty()); QVERIFY(iface->text(QAccessible::Value).isEmpty());
le->setEchoMode(QLineEdit::PasswordEchoOnEdit); le->setEchoMode(QLineEdit::PasswordEchoOnEdit);
QVERIFY(iface->state() & QAccessible::Protected); QVERIFY(iface->state().passwordEdit);
QVERIFY(iface->text(QAccessible::Value).isEmpty()); QVERIFY(iface->text(QAccessible::Value).isEmpty());
le->setEchoMode(QLineEdit::Normal); le->setEchoMode(QLineEdit::Normal);
QVERIFY(!(iface->state() & QAccessible::Protected)); QVERIFY(!(iface->state().passwordEdit));
QCOMPARE(iface->text(QAccessible::Value), secret); QCOMPARE(iface->text(QAccessible::Value), secret);
QWidget *toplevel = new QWidget; QWidget *toplevel = new QWidget;
le->setParent(toplevel); le->setParent(toplevel);
toplevel->show(); toplevel->show();
QApplication::processEvents(); QApplication::processEvents();
QVERIFY(!(iface->state() & QAccessible::Sizeable)); QVERIFY(!(iface->state().sizeable));
QVERIFY(!(iface->state() & QAccessible::Movable)); QVERIFY(!(iface->state().movable));
QCOMPARE(bool(iface->state() & QAccessible::Focusable), le->isActiveWindow()); QCOMPARE(bool(iface->state().focusable), le->isActiveWindow());
QVERIFY(iface->state() & QAccessible::Selectable); QVERIFY(iface->state().selectable);
QVERIFY(iface->state() & QAccessible::HasPopup); QVERIFY(iface->state().hasPopup);
QCOMPARE(bool(iface->state() & QAccessible::Focused), le->hasFocus()); QCOMPARE(bool(iface->state().focused), le->hasFocus());
QLineEdit *le2 = new QLineEdit(toplevel); QLineEdit *le2 = new QLineEdit(toplevel);
le2->show(); le2->show();
@ -2422,13 +2447,13 @@ void tst_QAccessibility::listTest()
QCOMPARE(QAIPtr(cellInterface->table())->object(), listView); QCOMPARE(QAIPtr(cellInterface->table())->object(), listView);
listView->clearSelection(); listView->clearSelection();
QVERIFY(!(cell4->state() & QAccessible::Expandable)); QVERIFY(!(cell4->state().expandable));
QVERIFY( (cell4->state() & QAccessible::Selectable)); QVERIFY( (cell4->state().selectable));
QVERIFY(!(cell4->state() & QAccessible::Selected)); QVERIFY(!(cell4->state().selected));
table2->selectRow(3); table2->selectRow(3);
QCOMPARE(listView->selectedItems().size(), 1); QCOMPARE(listView->selectedItems().size(), 1);
QCOMPARE(listView->selectedItems().at(0)->text(), QLatin1String("Munich")); QCOMPARE(listView->selectedItems().at(0)->text(), QLatin1String("Munich"));
QVERIFY(cell4->state() & QAccessible::Selected); QVERIFY(cell4->state().selected);
QVERIFY(cellInterface->isSelected()); QVERIFY(cellInterface->isSelected());
QVERIFY(table2->cellAt(-1, 0) == 0); QVERIFY(table2->cellAt(-1, 0) == 0);
@ -2500,7 +2525,7 @@ void tst_QAccessibility::treeTest()
QCOMPARE(iface->indexOfChild(child1), 3); QCOMPARE(iface->indexOfChild(child1), 3);
QCOMPARE(child1->text(QAccessible::Name), QString("Spain")); QCOMPARE(child1->text(QAccessible::Name), QString("Spain"));
QCOMPARE(child1->role(), QAccessible::TreeItem); QCOMPARE(child1->role(), QAccessible::TreeItem);
QVERIFY(!(child1->state() & QAccessible::Expanded)); QVERIFY(!(child1->state().expanded));
delete child1; delete child1;
QAccessibleInterface *child2 = 0; QAccessibleInterface *child2 = 0;
@ -2526,9 +2551,9 @@ void tst_QAccessibility::treeTest()
QCOMPARE(cell2->role(), QAccessible::TreeItem); QCOMPARE(cell2->role(), QAccessible::TreeItem);
QCOMPARE(cell2->tableCellInterface()->rowIndex(), 1); QCOMPARE(cell2->tableCellInterface()->rowIndex(), 1);
QCOMPARE(cell2->tableCellInterface()->columnIndex(), 0); QCOMPARE(cell2->tableCellInterface()->columnIndex(), 0);
QVERIFY(cell2->state() & QAccessible::Expandable); QVERIFY(cell2->state().expandable);
QCOMPARE(iface->indexOfChild(cell2), 5); QCOMPARE(iface->indexOfChild(cell2), 5);
QVERIFY(!(cell2->state() & QAccessible::Expanded)); QVERIFY(!(cell2->state().expanded));
QCOMPARE(table2->columnDescription(1), QString("Work")); QCOMPARE(table2->columnDescription(1), QString("Work"));
delete cell2; delete cell2;
delete cell1; delete cell1;
@ -2550,7 +2575,7 @@ void tst_QAccessibility::treeTest()
QCOMPARE(cell2->role(), QAccessible::TreeItem); QCOMPARE(cell2->role(), QAccessible::TreeItem);
QCOMPARE(cell2->tableCellInterface()->rowIndex(), 4); QCOMPARE(cell2->tableCellInterface()->rowIndex(), 4);
QCOMPARE(cell2->tableCellInterface()->columnIndex(), 0); QCOMPARE(cell2->tableCellInterface()->columnIndex(), 0);
QVERIFY(!(cell2->state() & QAccessible::Expandable)); QVERIFY(!(cell2->state().expandable));
QCOMPARE(iface->indexOfChild(cell2), 11); QCOMPARE(iface->indexOfChild(cell2), 11);
QCOMPARE(table2->columnDescription(0), QString("Artist")); QCOMPARE(table2->columnDescription(0), QString("Artist"));
@ -2602,7 +2627,7 @@ void tst_QAccessibility::tableTest()
QCOMPARE(iface->indexOfChild(child1), 3); QCOMPARE(iface->indexOfChild(child1), 3);
QCOMPARE(child1->text(QAccessible::Name), QString("h2")); QCOMPARE(child1->text(QAccessible::Name), QString("h2"));
QCOMPARE(child1->role(), QAccessible::ColumnHeader); QCOMPARE(child1->role(), QAccessible::ColumnHeader);
QVERIFY(!(child1->state() & QAccessible::Expanded)); QVERIFY(!(child1->state().expanded));
delete child1; delete child1;
QAccessibleInterface *child2 = iface->child(10); QAccessibleInterface *child2 = iface->child(10);