From 39a052c66479c6d7bd13c4f583fecf6a895b2948 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Thu, 5 Jan 2012 13:57:33 +0100 Subject: Accessiblity State as bit field. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- src/gui/accessible/qaccessible.cpp | 8 ++- src/gui/accessible/qaccessible.h | 83 +++++++++++----------- src/gui/accessible/qaccessibleobject.cpp | 2 +- src/plugins/accessible/widgets/itemviews.cpp | 26 +++---- src/plugins/accessible/widgets/itemviews.h | 2 +- src/plugins/accessible/widgets/qaccessiblemenu.cpp | 14 ++-- .../accessible/widgets/qaccessiblewidgets.cpp | 27 +++---- src/plugins/accessible/widgets/simplewidgets.cpp | 26 +++---- .../platforms/windows/qwindowsaccessibility.cpp | 60 +++++++++++++++- src/widgets/accessible/qaccessiblewidget.cpp | 20 +++--- 10 files changed, 165 insertions(+), 103 deletions(-) (limited to 'src') diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp index 59dbcf4bef..d1397921b0 100644 --- a/src/gui/accessible/qaccessible.cpp +++ b/src/gui/accessible/qaccessible.cpp @@ -1197,6 +1197,11 @@ const char *qAccessibleEventString(QAccessible::Event 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 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()) { d << "obj=" << iface->object(); } - bool invisible = iface->state() & QAccessible::Invisible; - if (invisible) { + if (iface->state().invisible) { d << "invisible"; } else { d << "rect=" << iface->rect(); diff --git a/src/gui/accessible/qaccessible.h b/src/gui/accessible/qaccessible.h index 949c67c4ca..11815378d5 100644 --- a/src/gui/accessible/qaccessible.h +++ b/src/gui/accessible/qaccessible.h @@ -148,46 +148,47 @@ public: AcceleratorChanged = 0x80C0 }; - - enum StateFlag { - Normal = 0x00000000, - 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 - + // 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; + + State() { + qMemSet(this, 0, sizeof(State)); + } }; - Q_DECLARE_FLAGS(State, StateFlag) - enum Role { NoRole = 0x00000000, @@ -334,7 +335,8 @@ private: 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) QT_END_NAMESPACE Q_DECLARE_METATYPE(QSet) @@ -377,7 +379,6 @@ public: virtual QRect rect() const = 0; virtual QAccessible::Role role() const = 0; virtual QAccessible::State state() const = 0; - // FIXME virtual QSet states() const = 0; virtual QColor foregroundColor() const; virtual QColor backgroundColor() const; diff --git a/src/gui/accessible/qaccessibleobject.cpp b/src/gui/accessible/qaccessibleobject.cpp index 8dfe5f3b02..cde375aaa5 100644 --- a/src/gui/accessible/qaccessibleobject.cpp +++ b/src/gui/accessible/qaccessibleobject.cpp @@ -304,7 +304,7 @@ QAccessible::Role QAccessibleApplication::role() const /*! \reimp */ QAccessible::State QAccessibleApplication::state() const { - return QGuiApplication::activeWindow() ? QAccessible::Focused : QAccessible::Normal; + return QAccessible::State(); } diff --git a/src/plugins/accessible/widgets/itemviews.cpp b/src/plugins/accessible/widgets/itemviews.cpp index a12036b52d..ec575371db 100644 --- a/src/plugins/accessible/widgets/itemviews.cpp +++ b/src/plugins/accessible/widgets/itemviews.cpp @@ -363,7 +363,7 @@ QAccessible::Role QAccessibleTable::role() const QAccessible::State QAccessibleTable::state() const { - return QAccessible::Normal; + return QAccessible::State(); } QAccessibleInterface *QAccessibleTable::childAt(int x, int y) const @@ -701,34 +701,34 @@ QAccessible::Role QAccessibleTableCell::role() const QAccessible::State QAccessibleTableCell::state() const { - QAccessible::State st = QAccessible::Normal; + QAccessible::State st; QRect globalRect = view->rect(); globalRect.translate(view->mapToGlobal(QPoint(0,0))); if (!globalRect.intersects(rect())) - st |= QAccessible::Invisible; + st.invisible = true; if (view->selectionModel()->isSelected(m_index)) - st |= QAccessible::Selected; + st.selected = true; if (view->selectionModel()->currentIndex() == m_index) - st |= QAccessible::Focused; + st.focused = true; if (m_index.model()->data(m_index, Qt::CheckStateRole).toInt() == Qt::Checked) - st |= QAccessible::Checked; + st.checked = true; Qt::ItemFlags flags = m_index.flags(); if (flags & Qt::ItemIsSelectable) { - st |= QAccessible::Selectable; - st |= QAccessible::Focusable; + st.selectable = true; + st.focusable = true; if (view->selectionMode() == QAbstractItemView::MultiSelection) - st |= QAccessible::MultiSelectable; + st.multiSelectable = true; if (view->selectionMode() == QAbstractItemView::ExtendedSelection) - st |= QAccessible::ExtSelectable; + st.extSelectable = true; } if (m_role == QAccessible::TreeItem) { const QTreeView *treeView = qobject_cast(view); if (treeView->model()->hasChildren(m_index)) - st |= QAccessible::Expandable; + st.expandable = true; if (treeView->isExpanded(m_index)) - st |= QAccessible::Expanded; + st.expanded = true; } return st; } @@ -840,7 +840,7 @@ QAccessible::Role QAccessibleTableHeaderCell::role() const QAccessible::State QAccessibleTableHeaderCell::state() const { - return QAccessible::Normal; + return QAccessible::State(); } QRect QAccessibleTableHeaderCell::rect() const diff --git a/src/plugins/accessible/widgets/itemviews.h b/src/plugins/accessible/widgets/itemviews.h index 3a2f5a8cb1..5ba75ce1b0 100644 --- a/src/plugins/accessible/widgets/itemviews.h +++ b/src/plugins/accessible/widgets/itemviews.h @@ -264,7 +264,7 @@ public: QObject *object() const { return 0; } 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(); } bool isValid() const { return true; } diff --git a/src/plugins/accessible/widgets/qaccessiblemenu.cpp b/src/plugins/accessible/widgets/qaccessiblemenu.cpp index d3a7fe0fe6..9771f23881 100644 --- a/src/plugins/accessible/widgets/qaccessiblemenu.cpp +++ b/src/plugins/accessible/widgets/qaccessiblemenu.cpp @@ -282,28 +282,28 @@ void QAccessibleMenuItem::setText(QAccessible::Text /*t*/, const QString & /*tex QAccessible::State QAccessibleMenuItem::state() const { - QAccessible::State s = QAccessible::Normal; + QAccessible::State s; QWidget *own = owner(); if (own->testAttribute(Qt::WA_WState_Visible) == false || m_action->isVisible() == false) { - s |= QAccessible::Invisible; + s.invisible = true; } if (QMenu *menu = qobject_cast(own)) { if (menu->activeAction() == m_action) - s |= QAccessible::Focused; + s.focused = true; #ifndef QT_NO_MENUBAR } else if (QMenuBar *menuBar = qobject_cast(own)) { if (menuBar->activeAction() == m_action) - s |= QAccessible::Focused; + s.focused = true; #endif } if (own->style()->styleHint(QStyle::SH_Menu_MouseTracking)) - s |= QAccessible::HotTracked; + s.hotTracked = true; if (m_action->isSeparator() || !m_action->isEnabled()) - s |= QAccessible::Unavailable; + s.unavailable = true; if (m_action->isChecked()) - s |= QAccessible::Checked; + s.checked = true; return s; } diff --git a/src/plugins/accessible/widgets/qaccessiblewidgets.cpp b/src/plugins/accessible/widgets/qaccessiblewidgets.cpp index 182a85dfc7..6598582e2a 100644 --- a/src/plugins/accessible/widgets/qaccessiblewidgets.cpp +++ b/src/plugins/accessible/widgets/qaccessiblewidgets.cpp @@ -845,18 +845,21 @@ void QAccessibleMdiSubWindow::setText(QAccessible::Text textType, const QString QAccessible::State QAccessibleMdiSubWindow::state() const { - QAccessible::State state = QAccessible::Normal | QAccessible::Focusable; - if (!mdiSubWindow()->isMaximized()) - state |= (QAccessible::Movable | QAccessible::Sizeable); + QAccessible::State state; + state.focusable = true; + if (!mdiSubWindow()->isMaximized()) { + state.movable = true; + state.sizeable = true; + } if (mdiSubWindow()->isAncestorOf(QApplication::focusWidget()) || QApplication::focusWidget() == mdiSubWindow()) - state |= QAccessible::Focused; + state.focused = true; if (!mdiSubWindow()->isVisible()) - state |= QAccessible::Invisible; + state.invisible = true; if (!mdiSubWindow()->parentWidget()->contentsRect().contains(mdiSubWindow()->geometry())) - state |= QAccessible::Offscreen; + state.offscreen = true; if (!mdiSubWindow()->isEnabled()) - state |= QAccessible::Unavailable; + state.unavailable = true; return state; } @@ -1256,17 +1259,17 @@ QString QAccessibleTitleBar::text(QAccessible::Text t) const QAccessible::State QAccessibleTitleBar::state() const { - QAccessible::State state = QAccessible::Normal; + QAccessible::State state; QDockWidget *w = dockWidget(); if (w->testAttribute(Qt::WA_WState_Visible) == false) - state |= QAccessible::Invisible; + state.invisible = true; if (w->focusPolicy() != Qt::NoFocus && w->isActiveWindow()) - state |= QAccessible::Focusable; + state.focusable = true; if (w->hasFocus()) - state |= QAccessible::Focused; + state.focused = true; if (!w->isEnabled()) - state |= QAccessible::Unavailable; + state.unavailable = true; return state; } diff --git a/src/plugins/accessible/widgets/simplewidgets.cpp b/src/plugins/accessible/widgets/simplewidgets.cpp index b05b917c21..74e9645693 100644 --- a/src/plugins/accessible/widgets/simplewidgets.cpp +++ b/src/plugins/accessible/widgets/simplewidgets.cpp @@ -140,18 +140,18 @@ QAccessible::State QAccessibleButton::state() const QAbstractButton *b = button(); QCheckBox *cb = qobject_cast(b); if (b->isChecked()) - state |= QAccessible::Checked; + state.checked = true; else if (cb && cb->checkState() == Qt::PartiallyChecked) - state |= QAccessible::Mixed; + state.mixed = true; if (b->isDown()) - state |= QAccessible::Pressed; + state.pressed = true; QPushButton *pb = qobject_cast(b); if (pb) { if (pb->isDefault()) - state |= QAccessible::DefaultButton; + state.defaultButton = true; #ifndef QT_NO_MENU if (pb->menu()) - state |= QAccessible::HasPopup; + state.hasPopup = true; #endif } @@ -171,7 +171,7 @@ QStringList QAccessibleButton::actionNames() const break; default: if (button()->isCheckable()) { - if (state() & QAccessible::Checked) { + if (state().checked) { names << uncheckAction(); } else { // FIXME @@ -263,10 +263,10 @@ QAccessible::State QAccessibleToolButton::state() const { QAccessible::State st = QAccessibleButton::state(); if (toolButton()->autoRaise()) - st |= QAccessible::HotTracked; + st.hotTracked = true; #ifndef QT_NO_MENU if (toolButton()->menu()) - st |= QAccessible::HasPopup; + st.hasPopup = true; #endif return st; } @@ -588,16 +588,16 @@ QAccessible::State QAccessibleLineEdit::state() const QLineEdit *l = lineEdit(); if (l->isReadOnly()) - state |= QAccessible::ReadOnly; + state.readOnly = true; if (l->echoMode() != QLineEdit::Normal) - state |= QAccessible::Protected; - state |= QAccessible::Selectable; + state.passwordEdit = true; + state.selectable = true; if (l->hasSelectedText()) - state |= QAccessible::Selected; + state.selected = true; if (l->contextMenuPolicy() != Qt::NoContextMenu && l->contextMenuPolicy() != Qt::PreventContextMenu) - state |= QAccessible::HasPopup; + state.hasPopup = true; return state; } diff --git a/src/plugins/platforms/windows/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/qwindowsaccessibility.cpp index 14d4a6bbba..afd92701f7 100644 --- a/src/plugins/platforms/windows/qwindowsaccessibility.cpp +++ b/src/plugins/platforms/windows/qwindowsaccessibility.cpp @@ -704,7 +704,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accNavigate(long navDir, VARIANT v QAccessibleInterface *sibling = 0; sibling = pIface->child(i); 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 delete sibling; continue; @@ -1058,8 +1058,62 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accState(VARIANT varID, VARIAN 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).lVal = state; + (*pvarState).lVal = st; return S_OK; } @@ -1169,7 +1223,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accSelection(VARIANT *pvarChil bool isSelected = false; QAccessibleInterface *child = accessible->child(i); if (child) { - isSelected = child->state() & QAccessible::Selected; + isSelected = child->state().selected; delete child; } if (isSelected) diff --git a/src/widgets/accessible/qaccessiblewidget.cpp b/src/widgets/accessible/qaccessiblewidget.cpp index 5498e70744..d9734f8d11 100644 --- a/src/widgets/accessible/qaccessiblewidget.cpp +++ b/src/widgets/accessible/qaccessiblewidget.cpp @@ -373,7 +373,7 @@ QAccessible::Relation QAccessibleWidget::relationTo(const QAccessibleInterface * if (wg.intersects(sg)) { QAccessibleInterface *pIface = 0; pIface = sibIface->parent(); - if (pIface && !((sibIface->state() | state()) & QAccessible::Invisible)) { + if (pIface && !(sibIface->state().invisible | state().invisible)) { int wi = pIface->indexOfChild(this); int si = pIface->indexOfChild(sibIface); @@ -430,7 +430,7 @@ int QAccessibleWidget::navigate(QAccessible::RelationFlag relation, int entry, QAccessibleInterface *sibling = 0; for (int i = pIface->indexOfChild(this) + 1; i <= sibCount && entry; ++i) { sibling = pIface->child(i - 1); - if (!sibling || (sibling->state() & QAccessible::Invisible)) { + if (!sibling || (sibling->state().invisible)) { delete sibling; sibling = 0; continue; @@ -460,7 +460,7 @@ int QAccessibleWidget::navigate(QAccessible::RelationFlag relation, int entry, for (int i = 1; i < index && entry; ++i) { sibling = pIface->child(i - 1); Q_ASSERT(sibling); - if (!sibling || (sibling->state() & QAccessible::Invisible)) { + if (!sibling || (sibling->state().invisible)) { delete sibling; sibling = 0; continue; @@ -690,22 +690,22 @@ QAccessible::Role QAccessibleWidget::role() const /*! \reimp */ QAccessible::State QAccessibleWidget::state() const { - QAccessible::State state = QAccessible::Normal; + QAccessible::State state; QWidget *w = widget(); if (w->testAttribute(Qt::WA_WState_Visible) == false) - state |= QAccessible::Invisible; + state.invisible = true; if (w->focusPolicy() != Qt::NoFocus && w->isActiveWindow()) - state |= QAccessible::Focusable; + state.focusable = true; if (w->hasFocus()) - state |= QAccessible::Focused; + state.focused = true; if (!w->isEnabled()) - state |= QAccessible::Unavailable; + state.unavailable = true; if (w->isWindow()) { if (w->windowFlags() & Qt::WindowSystemMenuHint) - state |= QAccessible::Movable; + state.movable = true; if (w->minimumSize() != w->maximumSize()) - state |= QAccessible::Sizeable; + state.sizeable = true; } return state; -- cgit v1.2.3