Accessibility: childAt returns interface

childAt used to return an integer.
Return an interface instead.

Not requiring a direct child to be returned allows optimizing
by bypassing iterating through the hierarchy of accessibles.
For QtQuick this is the only sensible way of implementing this.

The bridges are still responsible for finding the top-most element.

The default implementation in QAccessibleObject is sufficient
to return direct children. The implementation in
QAccessibleApplication is therfore no longer needed.

Change-Id: Id7100dd5bcc3a98de516a7f4a12eaaa41cb46d26
Reviewed-by: Morten Johan Sørvig <morten.sorvig@nokia.com>
This commit is contained in:
Frederik Gladhorn 2011-11-22 18:08:05 +01:00 committed by Qt by Nokia
parent 7e12d2d30f
commit 74c9f9d83f
22 changed files with 142 additions and 201 deletions

View File

@ -740,8 +740,11 @@ void QAccessible::updateAccessibility(QObject *o, int who, Event reason)
The functions childCount() and indexOfChild() return the number of The functions childCount() and indexOfChild() return the number of
children of an accessible object and the index a child object has children of an accessible object and the index a child object has
in its parent. The childAt() function returns the index of a child in its parent. The childAt() function returns a child QAccessibleInterface
at a given position. that is found at a position. The child does not have to be a direct
child. This allows bypassing intermediate layers when the parent already knows the
top-most child. childAt() is used for hit testing (finding the object
under the mouse).
The relationTo() function provides information about how two The relationTo() function provides information about how two
different objects relate to each other, and navigate() allows different objects relate to each other, and navigate() allows
@ -875,18 +878,21 @@ QVector<QPair<QAccessibleInterface*, QAccessible::Relation> > QAccessibleInterfa
} }
/*! /*!
\fn int QAccessibleInterface::childAt(int x, int y) const \fn QAccessibleInterface *QAccessibleInterface::childAt(int x, int y) const
Returns the 1-based index of the child that contains the screen Returns the QAccessibleInterface of a child that contains the screen coordinates (\a x, \a y).
coordinates (\a x, \a y). This function returns 0 if the point is If there are no children at this position this function returns 0.
positioned on the object itself. If the tested point is outside The returned accessible must be a child, but not necessarily a direct child.
the boundaries of the object this function returns -1.
This function is only relyable for visible objects (invisible This function is only relyable for visible objects (invisible
object might not be laid out correctly). object might not be laid out correctly).
All visual objects provide this information. All visual objects provide this information.
A default implementation is provided for objects inheriting QAccessibleObject. This will iterate
over all children. If the widget manages its children (e.g. a table) it will be more efficient
to write a specialized implementation.
\sa rect() \sa rect()
*/ */

View File

@ -369,7 +369,7 @@ public:
virtual QAccessible::Relation relationTo(const QAccessibleInterface *other) const; virtual QAccessible::Relation relationTo(const QAccessibleInterface *other) const;
virtual QVector<QPair<QAccessibleInterface*, QAccessible::Relation> > relations() const; virtual QVector<QPair<QAccessibleInterface*, QAccessible::Relation> > relations() const;
virtual int childAt(int x, int y) const = 0; virtual QAccessibleInterface *childAt(int x, int y) const = 0;
// navigation, hierarchy // navigation, hierarchy
virtual QAccessibleInterface *parent() const = 0; virtual QAccessibleInterface *parent() const = 0;

View File

@ -154,6 +154,18 @@ void QAccessibleObject::setText(QAccessible::Text, const QString &)
{ {
} }
/*! \reimp */
QAccessibleInterface *QAccessibleObject::childAt(int x, int y) const
{
for (int i = 0; i < childCount(); ++i) {
QAccessibleInterface *childIface = child(i);
if (childIface->rect().contains(x,y)) {
return childIface;
}
}
return 0;
}
/*! /*!
\class QAccessibleApplication \class QAccessibleApplication
\brief The QAccessibleApplication class implements the QAccessibleInterface for QApplication. \brief The QAccessibleApplication class implements the QAccessibleInterface for QApplication.
@ -213,19 +225,6 @@ int QAccessibleApplication::indexOfChild(const QAccessibleInterface *child) cons
return index; return index;
} }
/*! \reimp */
int QAccessibleApplication::childAt(int x, int y) const
{
for (int i = 0; i < childCount(); ++i) {
QAccessibleInterface *childIface = child(i);
QRect geom = childIface->rect();
if (geom.contains(x,y))
return i+1;
delete childIface;
}
return rect().contains(x,y) ? 0 : -1;
}
/*! \reimp */ /*! \reimp */
QAccessible::Relation QAccessibleApplication::relationTo(const QAccessibleInterface *other) const QAccessible::Relation QAccessibleApplication::relationTo(const QAccessibleInterface *other) const
{ {

View File

@ -67,6 +67,7 @@ public:
// properties // properties
QRect rect() const; QRect rect() const;
void setText(QAccessible::Text t, const QString &text); void setText(QAccessible::Text t, const QString &text);
QAccessibleInterface *childAt(int x, int y) const;
protected: protected:
virtual ~QAccessibleObject(); virtual ~QAccessibleObject();
@ -89,7 +90,6 @@ public:
// navigation // navigation
QAccessibleInterface *parent() const; QAccessibleInterface *parent() const;
int childAt(int x, int y) const;
QAccessibleInterface *child(int index) const; QAccessibleInterface *child(int index) const;
int navigate(QAccessible::RelationFlag, int, QAccessibleInterface **) const; int navigate(QAccessible::RelationFlag, int, QAccessibleInterface **) const;

View File

@ -1483,7 +1483,7 @@ public:
bool isValid() const { return true; }// (!m_parent.isNull()) && m_parent->count() > m_index; } bool isValid() const { return true; }// (!m_parent.isNull()) && m_parent->count() > m_index; }
int childAt(int, int) const { return 0; } QAccessibleInterface *childAt(int, int) const { return 0; }
int childCount() const { return 0; } int childCount() const { return 0; }
int indexOfChild(const QAccessibleInterface *) const { return -1; } int indexOfChild(const QAccessibleInterface *) const { return -1; }
@ -1661,7 +1661,7 @@ QComboBox *QAccessibleComboBox::comboBox() const
return qobject_cast<QComboBox*>(object()); return qobject_cast<QComboBox*>(object());
} }
QAccessibleInterface* QAccessibleComboBox::child(int index) const QAccessibleInterface *QAccessibleComboBox::child(int index) const
{ {
if (index == 0) { if (index == 0) {
QAbstractItemView *view = comboBox()->view(); QAbstractItemView *view = comboBox()->view();
@ -1679,10 +1679,10 @@ int QAccessibleComboBox::childCount() const
return comboBox()->isEditable() ? 2 : 1; return comboBox()->isEditable() ? 2 : 1;
} }
int QAccessibleComboBox::childAt(int x, int y) const QAccessibleInterface *QAccessibleComboBox::childAt(int x, int y) const
{ {
if (comboBox()->isEditable() && comboBox()->lineEdit()->rect().contains(x, y)) if (comboBox()->isEditable() && comboBox()->lineEdit()->rect().contains(x, y))
return 1; return child(1);
return 0; return 0;
} }
@ -1925,31 +1925,19 @@ int QAccessibleAbstractScrollArea::navigate(QAccessible::RelationFlag relation,
return *target ? 0: -1; return *target ? 0: -1;
} }
//int QAccessibleAbstractScrollArea::childAt(int x, int y) const QAccessibleInterface *QAccessibleAbstractScrollArea::childAt(int x, int y) const
//{ {
// if (!abstractScrollArea()->isVisible()) if (!abstractScrollArea()->isVisible())
// return -1; return 0;
//#if 0
// const QRect globalSelfGeometry = rect(Self); for (int i = 0; i < childCount(); ++i) {
// if (!globalSelfGeometry.isValid() || !globalSelfGeometry.contains(QPoint(x, y))) QPoint wpos = accessibleChildren().at(i)->mapToGlobal(QPoint(0, 0));
// return -1; QRect rect = QRect(wpos, accessibleChildren().at(i)->size());
// const QWidgetList children = accessibleChildren(); if (rect.contains(x, y))
// for (int i = 0; i < children.count(); ++i) { return child(i);
// const QWidget *child = children.at(i); }
// const QRect globalChildGeometry = QRect(child->mapToGlobal(QPoint(0, 0)), child->size()); return 0;
// if (globalChildGeometry.contains(QPoint(x, y))) { }
// return ++i;
// }
// }
// return 0;
//#else
// for (int i = childCount(); i >= 0; --i) {
// if (rect().contains(x, y))
// return i;
// }
// return -1;
//#endif
//}
QAbstractScrollArea *QAccessibleAbstractScrollArea::abstractScrollArea() const QAbstractScrollArea *QAccessibleAbstractScrollArea::abstractScrollArea() const
{ {

View File

@ -80,7 +80,7 @@ public:
int indexOfChild(const QAccessibleInterface *child) const; int indexOfChild(const QAccessibleInterface *child) const;
bool isValid() const; bool isValid() const;
int navigate(QAccessible::RelationFlag relation, int entry, QAccessibleInterface **target) const; int navigate(QAccessible::RelationFlag relation, int entry, QAccessibleInterface **target) const;
// int childAt(int x, int y) const; QAccessibleInterface *childAt(int x, int y) const;
//protected: //protected:
QAbstractScrollArea *abstractScrollArea() const; QAbstractScrollArea *abstractScrollArea() const;
@ -255,7 +255,7 @@ public:
explicit QAccessibleComboBox(QWidget *w); explicit QAccessibleComboBox(QWidget *w);
int childCount() const; int childCount() const;
int childAt(int x, int y) const; QAccessibleInterface *childAt(int x, int y) const;
int indexOfChild(const QAccessibleInterface *child) const; int indexOfChild(const QAccessibleInterface *child) const;
QAccessibleInterface* child(int index) const; QAccessibleInterface* child(int index) const;

View File

@ -366,7 +366,7 @@ QAccessible::State QAccessibleTable::state() const
return QAccessible::Normal; return QAccessible::Normal;
} }
int QAccessibleTable::childAt(int x, int y) const QAccessibleInterface *QAccessibleTable::childAt(int x, int y) const
{ {
QPoint viewportOffset = view->viewport()->mapTo(view, QPoint(0,0)); QPoint viewportOffset = view->viewport()->mapTo(view, QPoint(0,0));
QPoint indexPosition = view->mapFromGlobal(QPoint(x, y) - viewportOffset); QPoint indexPosition = view->mapFromGlobal(QPoint(x, y) - viewportOffset);
@ -374,9 +374,9 @@ int QAccessibleTable::childAt(int x, int y) const
QModelIndex index = view->indexAt(indexPosition); QModelIndex index = view->indexAt(indexPosition);
if (index.isValid()) { if (index.isValid()) {
return logicalIndex(index); return childFromLogical(logicalIndex(index));
} }
return -1; return 0;
} }
int QAccessibleTable::childCount() const int QAccessibleTable::childCount() const
@ -489,14 +489,14 @@ QModelIndex QAccessibleTree::indexFromLogical(int row, int column) const
return modelIndex; return modelIndex;
} }
int QAccessibleTree::childAt(int x, int y) const QAccessibleInterface *QAccessibleTree::childAt(int x, int y) const
{ {
QPoint viewportOffset = view->viewport()->mapTo(view, QPoint(0,0)); QPoint viewportOffset = view->viewport()->mapTo(view, QPoint(0,0));
QPoint indexPosition = view->mapFromGlobal(QPoint(x, y) - viewportOffset); QPoint indexPosition = view->mapFromGlobal(QPoint(x, y) - viewportOffset);
QModelIndex index = view->indexAt(indexPosition); QModelIndex index = view->indexAt(indexPosition);
if (!index.isValid()) if (!index.isValid())
return -1; return 0;
const QTreeView *treeView = qobject_cast<const QTreeView*>(view); const QTreeView *treeView = qobject_cast<const QTreeView*>(view);
int row = treeView->d_func()->viewIndex(index) + (horizontalHeader() ? 1 : 0); int row = treeView->d_func()->viewIndex(index) + (horizontalHeader() ? 1 : 0);
@ -504,7 +504,7 @@ int QAccessibleTree::childAt(int x, int y) const
int i = row * view->model()->columnCount() + column + 1; int i = row * view->model()->columnCount() + column + 1;
Q_ASSERT(i > view->model()->columnCount()); Q_ASSERT(i > view->model()->columnCount());
return i; return child(i - 1);
} }
int QAccessibleTree::childCount() const int QAccessibleTree::childCount() const

View File

@ -71,7 +71,7 @@ public:
QString text(QAccessible::Text t) const; QString text(QAccessible::Text t) const;
QRect rect() const; QRect rect() const;
int childAt(int x, int y) const; QAccessibleInterface *childAt(int x, int y) const;
int childCount() const; int childCount() const;
int indexOfChild(const QAccessibleInterface *) const; int indexOfChild(const QAccessibleInterface *) const;
@ -153,7 +153,7 @@ public:
virtual ~QAccessibleTree() {} virtual ~QAccessibleTree() {}
int childAt(int x, int y) const; QAccessibleInterface *childAt(int x, int y) const;
int childCount() const; int childCount() const;
int indexOfChild(const QAccessibleInterface *) const; int indexOfChild(const QAccessibleInterface *) const;
@ -184,7 +184,7 @@ public:
QRect rect() const; QRect rect() const;
bool isValid() const; bool isValid() const;
int childAt(int, int) const { return 0; } QAccessibleInterface *childAt(int, int) const { return 0; }
int childCount() const { return 0; } int childCount() const { return 0; }
int indexOfChild(const QAccessibleInterface *) const { return -1; } int indexOfChild(const QAccessibleInterface *) const { return -1; }
@ -231,7 +231,7 @@ public:
QRect rect() const; QRect rect() const;
bool isValid() const; bool isValid() const;
int childAt(int, int) const { return 0; } QAccessibleInterface *childAt(int, int) const { return 0; }
int childCount() const { return 0; } int childCount() const { return 0; }
int indexOfChild(const QAccessibleInterface *) const { return -1; } int indexOfChild(const QAccessibleInterface *) const { return -1; }
@ -268,7 +268,7 @@ public:
QRect rect() const { return QRect(); } QRect rect() const { return QRect(); }
bool isValid() const { return true; } bool isValid() const { return true; }
int childAt(int, int) const { return 0; } QAccessibleInterface *childAt(int, int) const { return 0; }
int childCount() const { return 0; } int childCount() const { return 0; }
int indexOfChild(const QAccessibleInterface *) const { return -1; } int indexOfChild(const QAccessibleInterface *) const { return -1; }

View File

@ -71,12 +71,12 @@ int QAccessibleMenu::childCount() const
return menu()->actions().count(); return menu()->actions().count();
} }
int QAccessibleMenu::childAt(int x, int y) const QAccessibleInterface *QAccessibleMenu::childAt(int x, int y) const
{ {
QAction *act = menu()->actionAt(menu()->mapFromGlobal(QPoint(x,y))); QAction *act = menu()->actionAt(menu()->mapFromGlobal(QPoint(x,y)));
if(act && act->isSeparator()) if(act && act->isSeparator())
act = 0; act = 0;
return menu()->actions().indexOf(act) + 1; return act ? new QAccessibleMenuItem(menu(), act) : 0;
} }
QString QAccessibleMenu::text(QAccessible::Text t) const QString QAccessibleMenu::text(QAccessible::Text t) const
@ -193,17 +193,16 @@ QAccessibleMenuItem::QAccessibleMenuItem(QWidget *owner, QAction *action)
QAccessibleMenuItem::~QAccessibleMenuItem() QAccessibleMenuItem::~QAccessibleMenuItem()
{} {}
int QAccessibleMenuItem::childAt(int x, int y ) const QAccessibleInterface *QAccessibleMenuItem::childAt(int x, int y ) const
{ {
for (int i = childCount(); i >= 0; --i) { for (int i = childCount(); i >= 0; --i) {
QAccessibleInterface *childInterface = child(i); QAccessibleInterface *childInterface = child(i);
if (childInterface->rect().contains(x,y)) { if (childInterface->rect().contains(x,y)) {
delete childInterface; return childInterface;
return i;
} }
delete childInterface; delete childInterface;
} }
return -1; return 0;
} }
int QAccessibleMenuItem::childCount() const int QAccessibleMenuItem::childCount() const

View File

@ -59,7 +59,7 @@ public:
explicit QAccessibleMenu(QWidget *w); explicit QAccessibleMenu(QWidget *w);
int childCount() const; int childCount() const;
int childAt(int x, int y) const; QAccessibleInterface *childAt(int x, int y) const;
QString text(QAccessible::Text t) const; QString text(QAccessible::Text t) const;
QAccessible::Role role() const; QAccessible::Role role() const;
@ -95,13 +95,13 @@ class QAccessibleMenuItem : public QAccessibleInterface, public QAccessibleActio
public: public:
explicit QAccessibleMenuItem(QWidget *owner, QAction *w); explicit QAccessibleMenuItem(QWidget *owner, QAction *w);
virtual ~QAccessibleMenuItem(); ~QAccessibleMenuItem();
void *interface_cast(QAccessible::InterfaceType t); void *interface_cast(QAccessible::InterfaceType t);
int childAt(int x, int y) const;
int childCount() const; int childCount() const;
int indexOfChild(const QAccessibleInterface * child) const; QAccessibleInterface *childAt(int x, int y) const;
bool isValid() const; bool isValid() const;
int indexOfChild(const QAccessibleInterface * child) const;
QAccessibleInterface *parent() const; QAccessibleInterface *parent() const;
QAccessibleInterface *child(int index) const; QAccessibleInterface *child(int index) const;

View File

@ -722,17 +722,17 @@ QVariant QAccessibleStackedWidget::invokeMethod(QAccessible::Method, const QVari
} }
int QAccessibleStackedWidget::childAt(int x, int y) const QAccessibleInterface *QAccessibleStackedWidget::childAt(int x, int y) const
{ {
if (!stackedWidget()->isVisible()) if (!stackedWidget()->isVisible())
return -1; return 0;
QWidget *currentWidget = stackedWidget()->currentWidget(); QWidget *currentWidget = stackedWidget()->currentWidget();
if (!currentWidget) if (!currentWidget)
return -1; return 0;
QPoint position = currentWidget->mapFromGlobal(QPoint(x, y)); QPoint position = currentWidget->mapFromGlobal(QPoint(x, y));
if (currentWidget->rect().contains(position)) if (currentWidget->rect().contains(position))
return 1; return child(stackedWidget()->currentIndex());
return -1; return 0;
} }
int QAccessibleStackedWidget::childCount() const int QAccessibleStackedWidget::childCount() const
@ -953,25 +953,6 @@ QRect QAccessibleMdiSubWindow::rect() const
return QRect(pos, mdiSubWindow()->size()); return QRect(pos, mdiSubWindow()->size());
} }
int QAccessibleMdiSubWindow::childAt(int x, int y) const
{
if (!mdiSubWindow()->isVisible())
return -1;
if (!mdiSubWindow()->parent())
return QAccessibleWidget::childAt(x, y);
const QRect globalGeometry = rect();
if (!globalGeometry.isValid())
return -1;
QAccessibleInterface *childIface = child(0);
const QRect globalChildGeometry = childIface->rect();
delete childIface;
if (globalChildGeometry.isValid() && globalChildGeometry.contains(QPoint(x, y)))
return 1;
if (globalGeometry.contains(QPoint(x, y)))
return 0;
return -1;
}
QMdiSubWindow *QAccessibleMdiSubWindow::mdiSubWindow() const QMdiSubWindow *QAccessibleMdiSubWindow::mdiSubWindow() const
{ {
return static_cast<QMdiSubWindow *>(object()); return static_cast<QMdiSubWindow *>(object());
@ -1344,17 +1325,16 @@ QRect QAccessibleTitleBar::rect() const
return rect; return rect;
} }
int QAccessibleTitleBar::childAt(int x, int y) const QAccessibleInterface *QAccessibleTitleBar::childAt(int x, int y) const
{ {
for (int i = childCount(); i >= 0; --i) { for (int i = 0; i < childCount(); ++i) {
QAccessibleInterface *childIface = child(i - 1); QAccessibleInterface *childIface = child(i);
if (childIface->rect().contains(x,y)) { if (childIface->rect().contains(x,y)) {
delete childIface; return childIface;
return i;
} }
delete childIface; delete childIface;
} }
return -1; return 0;
} }
QObject *QAccessibleTitleBar::object() const QObject *QAccessibleTitleBar::object() const
@ -1463,21 +1443,21 @@ int QAccessibleMainWindow::indexOfChild(const QAccessibleInterface *iface) const
return childIndex == -1 ? -1 : ++childIndex; return childIndex == -1 ? -1 : ++childIndex;
} }
int QAccessibleMainWindow::childAt(int x, int y) const QAccessibleInterface *QAccessibleMainWindow::childAt(int x, int y) const
{ {
QWidget *w = widget(); QWidget *w = widget();
if (!w->isVisible()) if (!w->isVisible())
return -1; return 0;
QPoint gp = w->mapToGlobal(QPoint(0, 0)); QPoint gp = w->mapToGlobal(QPoint(0, 0));
if (!QRect(gp.x(), gp.y(), w->width(), w->height()).contains(x, y)) if (!QRect(gp.x(), gp.y(), w->width(), w->height()).contains(x, y))
return -1; return 0;
QWidgetList kids = childWidgets(mainWindow(), true); QWidgetList kids = childWidgets(mainWindow(), true);
QPoint rp = mainWindow()->mapFromGlobal(QPoint(x, y)); QPoint rp = mainWindow()->mapFromGlobal(QPoint(x, y));
for (int i = 0; i < kids.size(); ++i) { for (int i = 0; i < kids.size(); ++i) {
QWidget *child = kids.at(i); QWidget *child = kids.at(i);
if (!child->isWindow() && !child->isHidden() && child->geometry().contains(rp)) { if (!child->isWindow() && !child->isHidden() && child->geometry().contains(rp)) {
return i + 1; return QAccessible::queryAccessibleInterface(child);
} }
} }
return 0; return 0;

View File

@ -122,7 +122,7 @@ public:
explicit QAccessibleStackedWidget(QWidget *widget); explicit QAccessibleStackedWidget(QWidget *widget);
QVariant invokeMethod(QAccessible::Method method, const QVariantList &params); QVariant invokeMethod(QAccessible::Method method, const QVariantList &params);
int childAt(int x, int y) const; QAccessibleInterface *childAt(int x, int y) const;
int childCount() const; int childCount() const;
int indexOfChild(const QAccessibleInterface *child) const; int indexOfChild(const QAccessibleInterface *child) const;
QAccessibleInterface *child(int index) const; QAccessibleInterface *child(int index) const;
@ -173,7 +173,6 @@ public:
int indexOfChild(const QAccessibleInterface *child) const; int indexOfChild(const QAccessibleInterface *child) const;
int navigate(QAccessible::RelationFlag relation, int entry, QAccessibleInterface **target) const; int navigate(QAccessible::RelationFlag relation, int entry, QAccessibleInterface **target) const;
QRect rect() const; QRect rect() const;
int childAt(int x, int y) const;
protected: protected:
QMdiSubWindow *mdiSubWindow() const; QMdiSubWindow *mdiSubWindow() const;
@ -261,12 +260,12 @@ public:
int indexOfChild(const QAccessibleInterface *child) const; int indexOfChild(const QAccessibleInterface *child) const;
int childCount() const; int childCount() const;
QAccessible::Relation relationTo(const QAccessibleInterface *other) const; QAccessible::Relation relationTo(const QAccessibleInterface *other) const;
QAccessibleInterface *childAt(int x, int y) const;
void setText(QAccessible::Text t, const QString &text); void setText(QAccessible::Text t, const QString &text);
QString text(QAccessible::Text t) const; QString text(QAccessible::Text t) const;
QAccessible::Role role() const; QAccessible::Role role() const;
QRect rect () const; QRect rect () const;
QAccessible::State state() const; QAccessible::State state() const;
int childAt(int x, int y) const;
QObject *object() const; QObject *object() const;
bool isValid() const; bool isValid() const;
@ -287,7 +286,7 @@ public:
QAccessibleInterface *child(int index) const; QAccessibleInterface *child(int index) const;
int childCount() const; int childCount() const;
int indexOfChild(const QAccessibleInterface *iface) const; int indexOfChild(const QAccessibleInterface *iface) const;
int childAt(int x, int y) const; QAccessibleInterface *childAt(int x, int y) const;
QMainWindow *mainWindow() const; QMainWindow *mainWindow() const;
QVariant invokeMethod(QAccessible::Method method, const QVariantList &params); QVariant invokeMethod(QAccessible::Method method, const QVariantList &params);

View File

@ -197,21 +197,19 @@ static QAccessibleInterface *acast(void *ptr)
} }
- (id)accessibilityHitTest:(NSPoint)point { - (id)accessibilityHitTest:(NSPoint)point {
int index = acast(accessibleInterface)->childAt(point.x, qt_mac_flipYCoordinate(point.y));
// hit outside if (!accessibleInterface)
if (index == -1) { return NSAccessibilityUnignoredAncestor(self);
return 0; QAccessibleInterface *childInterface = acast(accessibleInterface)->childAt(point.x, qt_mac_flipYCoordinate(point.y));
}
// hit this element // No child found, meaning we hit this element.
if (index == 0) { if (!childInterface) {
return NSAccessibilityUnignoredAncestor(self); return NSAccessibilityUnignoredAncestor(self);
} }
// hit a child, forward to child accessible interface. // hit a child, forward to child accessible interface.
QAccessibleInterface *childInterface = acast(accessibleInterface)->child(index - 1); int childIndex = acast(accessibleInterface)->indexOfChild(childInterface);
QCocoaAccessibleElement *accessibleElement = [QCocoaAccessibleElement elementWithIndex:index - 1 parent:self accessibleInterface: childInterface]; QCocoaAccessibleElement *accessibleElement = [QCocoaAccessibleElement elementWithIndex:childIndex -1 parent:self accessibleInterface: childInterface];
return [accessibleElement accessibilityHitTest:point]; return [accessibleElement accessibilityHitTest:point];
} }

View File

@ -83,34 +83,19 @@
} }
- (id)accessibilityHitTest:(NSPoint)point { - (id)accessibilityHitTest:(NSPoint)point {
if (!m_accessibleRoot)
return [super accessibilityHitTest:point];
NSPoint windowPoint = [[self window] convertScreenToBase:point]; NSPoint windowPoint = [[self window] convertScreenToBase:point];
NSPoint localPoint = [self convertPoint:windowPoint fromView:nil];
int index = -1; QAccessibleInterface *childInterface = m_accessibleRoot->childAt(point.x, qt_mac_flipYCoordinate(point.y));
if (m_accessibleRoot) { // No child found, meaning we hit the NSView
index = m_accessibleRoot->childAt(point.x, qt_mac_flipYCoordinate(point.y)); if (!childInterface) {
// qDebug() << "root rect" << m_accessibleRoot->rect();
// qDebug() << "hit screen" << point.x << qt_mac_flipYCoordinate(point.y) << index;
// if (index > 0) {
// qDebug() << "child name" << m_accessibleRoot->child(index - 1)->text(QAccessible::Name);
// qDebug() << "child rect" << m_accessibleRoot->child(index - 1)->rect();
// }
}
// hit outside
if (index == -1) {
return [super accessibilityHitTest:point]; return [super accessibilityHitTest:point];
} }
// hit the NSView / top-level window // Hit a child, forward to child accessible interface.
if (index == 0) { int childIndex = m_accessibleRoot->indexOfChild(childInterface);
QCocoaAccessibleElement *accessibleElement = [QCocoaAccessibleElement elementWithIndex:index parent:self accessibleInterface:(void*)m_accessibleRoot]; QCocoaAccessibleElement *accessibleElement = [QCocoaAccessibleElement elementWithIndex:childIndex -1 parent:self accessibleInterface: childInterface];
return [accessibleElement accessibilityHitTest:point];
}
// hit a child, forward to child accessible interface.
QCocoaAccessibleElement *accessibleElement = [QCocoaAccessibleElement elementWithIndex:index - 1 parent:self accessibleInterface:(void*)m_accessibleRoot->child(index -1)];
return [accessibleElement accessibilityHitTest:point]; return [accessibleElement accessibilityHitTest:point];
} }

View File

@ -753,21 +753,23 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accHitTest(long xLeft, long yTop,
if (!accessible->isValid()) if (!accessible->isValid())
return E_FAIL; return E_FAIL;
int control = accessible->childAt(xLeft, yTop); QAccessibleInterface *child = accessible->childAt(xLeft, yTop);
if (control == -1) { if (child == 0) {
// no child found, return this item if it contains the coordinates
if (accessible->rect().contains(xLeft, yTop)) {
IDispatch *iface = 0;
QueryInterface(IID_IDispatch, (void**)&iface);
if (iface) {
(*pvarID).vt = VT_DISPATCH;
(*pvarID).pdispVal = iface;
return S_OK;
}
}
(*pvarID).vt = VT_EMPTY; (*pvarID).vt = VT_EMPTY;
return S_FALSE; return S_FALSE;
} }
QAccessibleInterface *acc = 0;
if (control)
accessible->navigate(QAccessible::Child, control, &acc);
if (!acc) {
(*pvarID).vt = VT_I4;
(*pvarID).lVal = control;
return S_OK;
}
QWindowsAccessible* wacc = new QWindowsAccessible(acc); QWindowsAccessible* wacc = new QWindowsAccessible(child);
IDispatch *iface = 0; IDispatch *iface = 0;
wacc->QueryInterface(IID_IDispatch, (void**)&iface); wacc->QueryInterface(IID_IDispatch, (void**)&iface);
if (iface) { if (iface) {

View File

@ -221,28 +221,6 @@ QObject *QAccessibleWidget::parentObject() const
return parent; return parent;
} }
/*! \reimp */
int QAccessibleWidget::childAt(int x, int y) const
{
QWidget *w = widget();
if (!w->isVisible())
return -1;
QPoint gp = w->mapToGlobal(QPoint(0, 0));
if (!QRect(gp.x(), gp.y(), w->width(), w->height()).contains(x, y))
return -1;
for (int i = 0; i < childCount(); ++i) {
QAccessibleInterface *childIface = child(i);
bool found = false;
if (childIface->rect().contains(x, y))
found = true;
delete childIface;
if (found)
return i + 1;
}
return 0;
}
/*! \reimp */ /*! \reimp */
QRect QAccessibleWidget::rect() const QRect QAccessibleWidget::rect() const
{ {

View File

@ -64,7 +64,6 @@ public:
int indexOfChild(const QAccessibleInterface *child) const; int indexOfChild(const QAccessibleInterface *child) const;
QAccessible::Relation relationTo(const QAccessibleInterface *other) const; QAccessible::Relation relationTo(const QAccessibleInterface *other) const;
int childAt(int x, int y) const;
QRect rect() const; QRect rect() const;
QAccessibleInterface *parent() const; QAccessibleInterface *parent() const;

View File

@ -89,7 +89,6 @@ static inline bool verifyChild(QWidget *child, QAccessibleInterface *interface,
// QAccessibleInterface::indexOfChild(): // QAccessibleInterface::indexOfChild():
// Verify that indexOfChild() returns an index equal to the index passed in // Verify that indexOfChild() returns an index equal to the index passed in
int indexFromIndexOfChild = interface->indexOfChild(childInterface); int indexFromIndexOfChild = interface->indexOfChild(childInterface);
delete childInterface;
if (indexFromIndexOfChild != index) { if (indexFromIndexOfChild != index) {
qWarning("tst_QAccessibility::verifyChild (indexOfChild()):"); qWarning("tst_QAccessibility::verifyChild (indexOfChild()):");
qWarning() << "Expected:" << index; qWarning() << "Expected:" << index;
@ -109,13 +108,21 @@ static inline bool verifyChild(QWidget *child, QAccessibleInterface *interface,
// Calculate global child position and check that the interface // Calculate global child position and check that the interface
// returns the correct index for that position. // returns the correct index for that position.
QPoint globalChildPos = child->mapToGlobal(QPoint(0, 0)); QPoint globalChildPos = child->mapToGlobal(QPoint(0, 0));
int indexFromChildAt = interface->childAt(globalChildPos.x(), globalChildPos.y()); QAccessibleInterface *childAtInterface = interface->childAt(globalChildPos.x(), globalChildPos.y());
if (indexFromChildAt != index) { if (!childAtInterface) {
qWarning("tst_QAccessibility::verifyChild (childAt()):"); qWarning("tst_QAccessibility::verifyChild (childAt()):");
qWarning() << "Expected:" << index; qWarning() << "Expected:" << childInterface;
qWarning() << "Actual: " << indexFromChildAt; qWarning() << "Actual: no child";
return false; return false;
} }
if (childAtInterface->object() != childInterface->object()) {
qWarning("tst_QAccessibility::verifyChild (childAt()):");
qWarning() << "Expected:" << childInterface;
qWarning() << "Actual: " << childAtInterface;
return false;
}
delete childInterface;
delete childAtInterface;
// QAccessibleInterface::rect(): // QAccessibleInterface::rect():
// Calculate global child geometry and check that the interface // Calculate global child geometry and check that the interface
@ -1931,11 +1938,14 @@ void tst_QAccessibility::mdiSubWindowTest()
QCOMPARE(childRect(interface), QRect(globalWidgetPos, widgetGeometry.size())); QCOMPARE(childRect(interface), QRect(globalWidgetPos, widgetGeometry.size()));
// childAt // childAt
QCOMPARE(interface->childAt(-10, 0), -1); QCOMPARE(interface->childAt(-10, 0), static_cast<QAccessibleInterface*>(0));
QCOMPARE(interface->childAt(globalPos.x(), globalPos.y()), 0); QCOMPARE(interface->childAt(globalPos.x(), globalPos.y()), static_cast<QAccessibleInterface*>(0));
QCOMPARE(interface->childAt(globalWidgetPos.x(), globalWidgetPos.y()), 1); QAccessibleInterface *child = interface->childAt(globalWidgetPos.x(), globalWidgetPos.y());
QCOMPARE(child->role(), QAccessible::PushButton);
QCOMPARE(child->text(QAccessible::Name), QString("QAccessibilityTest"));
delete child;
testWindow->widget()->hide(); testWindow->widget()->hide();
QCOMPARE(interface->childAt(globalWidgetPos.x(), globalWidgetPos.y()), 0); QCOMPARE(interface->childAt(globalWidgetPos.x(), globalWidgetPos.y()), static_cast<QAccessibleInterface*>(0));
} }
QTestAccessibility::clearEvents(); QTestAccessibility::clearEvents();
@ -2288,7 +2298,7 @@ void tst_QAccessibility::abstractScrollAreaTest()
QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&abstractScrollArea); QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&abstractScrollArea);
QVERIFY(interface); QVERIFY(interface);
QVERIFY(!interface->rect().isValid()); QVERIFY(!interface->rect().isValid());
QCOMPARE(interface->childAt(200, 200), -1); QCOMPARE(interface->childAt(200, 200), static_cast<QAccessibleInterface*>(0));
abstractScrollArea.resize(400, 400); abstractScrollArea.resize(400, 400);
abstractScrollArea.show(); abstractScrollArea.show();
@ -2767,7 +2777,7 @@ void tst_QAccessibility::calendarWidgetTest()
QVERIFY(interface); QVERIFY(interface);
QCOMPARE(interface->role(), QAccessible::Table); QCOMPARE(interface->role(), QAccessible::Table);
QVERIFY(!interface->rect().isValid()); QVERIFY(!interface->rect().isValid());
QCOMPARE(interface->childAt(200, 200), -1); QCOMPARE(interface->childAt(200, 200), static_cast<QAccessibleInterface*>(0));
calendarWidget.resize(400, 300); calendarWidget.resize(400, 300);
calendarWidget.show(); calendarWidget.show();
@ -2903,9 +2913,11 @@ void tst_QAccessibility::dockWidgetTest()
QPoint globalPos = dock1->mapToGlobal(QPoint(0,0)); QPoint globalPos = dock1->mapToGlobal(QPoint(0,0));
globalPos.rx()+=5; //### query style globalPos.rx()+=5; //### query style
globalPos.ry()+=5; globalPos.ry()+=5;
int entry = accDock1->childAt(globalPos.x(), globalPos.y()); //### QAccessibleInterface *childAt = accDock1->childAt(globalPos.x(), globalPos.y()); //###
QCOMPARE(entry, 1); QCOMPARE(childAt->role(), QAccessible::TitleBar);
QAccessibleInterface *accTitleBar = accDock1->child(entry - 1); int index = accDock1->indexOfChild(childAt);
delete childAt;
QAccessibleInterface *accTitleBar = accDock1->child(index - 1);
QCOMPARE(accTitleBar->role(), QAccessible::TitleBar); QCOMPARE(accTitleBar->role(), QAccessible::TitleBar);
QCOMPARE(accDock1->indexOfChild(accTitleBar), 1); QCOMPARE(accDock1->indexOfChild(accTitleBar), 1);

View File

@ -67,9 +67,6 @@ void accessibilityUpdateHandler(QObject *object, int who, QAccessible::Event rea
if (updateHandlerRecursion) if (updateHandlerRecursion)
return; return;
if (!qobject_cast<QQuickItem *>(object))
return;
updateHandlerRecursion = true; updateHandlerRecursion = true;
if (sceneManager) { if (sceneManager) {

View File

@ -64,8 +64,6 @@ public:
void saveWindowGeometry(); void saveWindowGeometry();
signals: signals:
public slots:
private: private:
OptionsWidget *optionsWidget; OptionsWidget *optionsWidget;
MouseInterceptingGraphicsScene *accessibilityScene; MouseInterceptingGraphicsScene *accessibilityScene;

View File

@ -158,7 +158,7 @@ void AccessibilitySceneManager::handleUpdate(QObject *object, QAccessible::Event
m_animatedObjects.clear(); m_animatedObjects.clear();
} else { } else {
qDebug() << "other update" << object; // qDebug() << "other update" << object;
} }
} }
@ -273,7 +273,7 @@ QGraphicsRectItem * AccessibilitySceneManager::processInterface(QAccessibleInter
if (!m_rootItem) if (!m_rootItem)
m_rootItem = item; m_rootItem = item;
QString name = interface->text(QAccessibleInterface::Name); QString name = interface->text(QAccessible::Name);
QString description; // = interface->text(QAccessibleInterface::Description, child); QString description; // = interface->text(QAccessibleInterface::Description, child);
QString role = translateRole(interface->role()); QString role = translateRole(interface->role());
int childCount = interface->childCount(); int childCount = interface->childCount();

View File

@ -103,7 +103,7 @@ void ScreenReader::processTouchPoint()
qDebug() << "touchPoint exit recursion overflow"; qDebug() << "touchPoint exit recursion overflow";
return; // outside return; // outside
} }
/*
hit = currentInterface->childAt(m_currentTouchPoint.x(), m_currentTouchPoint.y()); hit = currentInterface->childAt(m_currentTouchPoint.x(), m_currentTouchPoint.y());
//qDebug() << "hit" << hit; //qDebug() << "hit" << hit;
if (hit == -1) { if (hit == -1) {
@ -121,6 +121,7 @@ void ScreenReader::processTouchPoint()
delete currentInterface; delete currentInterface;
currentInterface = childInterface; currentInterface = childInterface;
} }
*/
} }
m_selectedInterface = currentInterface; m_selectedInterface = currentInterface;