Accessibility iOS

This lays the foundation for iOS accessibility.
The approach is slightly different from other a11y bridges in
that we completely flaten the hierarchy of wigets/quick items to
a list. This works well with VoiceOver since there are comparatively
few elements. The cache implementation for OS X is re-used.

With this patch VoiceOver on iOS works on many applications out of the box.
For now it sends the screen changed notfification somewhat overzealous,
that will need revisiting and potentially new API in QAccessible.

Device orientation changes are not yet supported.

[ChangeLog][iOS] Accessibility was added to the iOS platform port.
This enables Qt applications to be read by VoiceOver on iOS devices.

Task-number: QTBUG-39097
Change-Id: I441e844652d528cc2fdcc444f43b54ed6fa04f0c
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@digia.com>
This commit is contained in:
Frederik Gladhorn 2014-05-19 12:28:32 +02:00 committed by The Qt Project
parent 0f8d35ff73
commit d707acfc9e
17 changed files with 521 additions and 30 deletions

View File

@ -121,7 +121,7 @@ void QAccessibleCache::deleteInterface(QAccessible::Id id, QObject *obj)
objectToId.remove(obj);
delete iface;
#ifdef Q_OS_MACX
#ifdef Q_OS_MAC
removeCocoaElement(id);
#endif
}

View File

@ -41,27 +41,23 @@
#include "qaccessiblecache_p.h"
#ifdef Q_OS_OSX
QT_BEGIN_NAMESPACE
void QAccessibleCache::insertElement(QAccessible::Id axid, QCocoaAccessibleElement *element) const
void QAccessibleCache::insertElement(QAccessible::Id axid, QMacAccessibilityElement *element) const
{
cocoaElements[axid] = element;
}
void QAccessibleCache::removeCocoaElement(QAccessible::Id axid)
{
QCocoaAccessibleElement *element = elementForId(axid);
QMacAccessibilityElement *element = elementForId(axid);
[element invalidate];
cocoaElements.remove(axid);
}
QCocoaAccessibleElement *QAccessibleCache::elementForId(QAccessible::Id axid) const
QMacAccessibilityElement *QAccessibleCache::elementForId(QAccessible::Id axid) const
{
return cocoaElements.value(axid);
}
QT_END_NAMESPACE
#endif

View File

@ -59,7 +59,9 @@
#include "qaccessible.h"
Q_FORWARD_DECLARE_OBJC_CLASS(QCocoaAccessibleElement);
#ifdef Q_OS_MAC
Q_FORWARD_DECLARE_OBJC_CLASS(QMacAccessibilityElement);
#endif
QT_BEGIN_NAMESPACE
@ -73,9 +75,9 @@ public:
QAccessible::Id insert(QObject *object, QAccessibleInterface *iface) const;
void deleteInterface(QAccessible::Id id, QObject *obj = 0);
#ifdef Q_OS_OSX
QCocoaAccessibleElement *elementForId(QAccessible::Id axid) const;
void insertElement(QAccessible::Id axid, QCocoaAccessibleElement *element) const;
#ifdef Q_OS_MAC
QMacAccessibilityElement *elementForId(QAccessible::Id axid) const;
void insertElement(QAccessible::Id axid, QMacAccessibilityElement *element) const;
#endif
private Q_SLOTS:
@ -87,9 +89,9 @@ private:
mutable QHash<QAccessible::Id, QAccessibleInterface *> idToInterface;
mutable QHash<QObject *, QAccessible::Id> objectToId;
#ifdef Q_OS_OSX
#ifdef Q_OS_MAC
void removeCocoaElement(QAccessible::Id axid);
mutable QHash<QAccessible::Id, QCocoaAccessibleElement *> cocoaElements;
mutable QHash<QAccessible::Id, QMacAccessibilityElement *> cocoaElements;
#endif
friend class QAccessible;

View File

@ -55,7 +55,7 @@ QCocoaAccessibility::~QCocoaAccessibility()
void QCocoaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event)
{
QCocoaAccessibleElement *element = [QCocoaAccessibleElement elementWithId: event->uniqueId()];
QMacAccessibilityElement *element = [QMacAccessibilityElement elementWithId: event->uniqueId()];
if (!element) {
qWarning() << "QCocoaAccessibility::notifyAccessibilityUpdate: invalid element";
return;
@ -244,7 +244,7 @@ NSArray *unignoredChildren(QAccessibleInterface *interface)
QAccessible::Id childId = QAccessible::uniqueId(child);
//qDebug() << " kid: " << childId << child;
QCocoaAccessibleElement *element = [QCocoaAccessibleElement elementWithId: childId];
QMacAccessibilityElement *element = [QMacAccessibilityElement elementWithId: childId];
if (element)
[kids addObject: element];
else

View File

@ -48,15 +48,15 @@
#import <qaccessible.h>
@class QCocoaAccessibleElement;
Q_FORWARD_DECLARE_OBJC_CLASS(QMacAccessibilityElement);
@interface QCocoaAccessibleElement : NSObject {
@interface QMacAccessibilityElement : NSObject {
NSString *role;
QAccessible::Id axid;
}
- (id)initWithId:(QAccessible::Id)anId;
+ (QCocoaAccessibleElement *)elementWithId:(QAccessible::Id)anId;
+ (QMacAccessibilityElement *)elementWithId:(QAccessible::Id)anId;
@end

View File

@ -48,7 +48,7 @@
#import <AppKit/NSAccessibility.h>
@implementation QCocoaAccessibleElement
@implementation QMacAccessibilityElement
- (id)initWithId:(QAccessible::Id)anId
{
@ -72,7 +72,7 @@
QAccessibleCache *cache = QAccessibleCache::instance();
QCocoaAccessibleElement *element = cache->elementForId(anId);
QMacAccessibilityElement *element = cache->elementForId(anId);
if (!element) {
QAccessibleInterface *iface = QAccessible::accessibleInterface(anId);
Q_ASSERT(iface);
@ -95,8 +95,8 @@
}
- (BOOL)isEqual:(id)object {
if ([object isKindOfClass:[QCocoaAccessibleElement class]]) {
QCocoaAccessibleElement *other = object;
if ([object isKindOfClass:[QMacAccessibilityElement class]]) {
QMacAccessibilityElement *other = object;
return other->axid == axid;
} else {
return NO;
@ -196,7 +196,7 @@
}
QAccessible::Id parentId = QAccessible::uniqueId(parent);
return [QCocoaAccessibleElement elementWithId: parentId];
return [QMacAccessibilityElement elementWithId: parentId];
}
@ -345,7 +345,7 @@
}
if ([attribute isEqualToString: NSAccessibilityLineForIndexParameterizedAttribute]) {
int index = [parameter intValue];
NSNumber *ln = [QCocoaAccessibleElement lineNumberForIndex: index forText: iface->text(QAccessible::Value)];
NSNumber *ln = [QMacAccessibilityElement lineNumberForIndex: index forText: iface->text(QAccessible::Value)];
return ln;
}
if ([attribute isEqualToString: NSAccessibilityRangeForLineParameterizedAttribute]) {
@ -504,7 +504,7 @@
QAccessible::Id childId = QAccessible::uniqueId(childInterface);
// hit a child, forward to child accessible interface.
QCocoaAccessibleElement *accessibleElement = [QCocoaAccessibleElement elementWithId:childId];
QMacAccessibilityElement *accessibleElement = [QMacAccessibilityElement elementWithId:childId];
if (accessibleElement)
return NSAccessibilityUnignoredAncestor(accessibleElement);
return NSAccessibilityUnignoredAncestor(self);
@ -521,7 +521,7 @@
QAccessibleInterface *childInterface = iface->focusChild();
if (childInterface) {
QAccessible::Id childAxid = QAccessible::uniqueId(childInterface);
QCocoaAccessibleElement *accessibleElement = [QCocoaAccessibleElement elementWithId:childAxid];
QMacAccessibilityElement *accessibleElement = [QMacAccessibilityElement elementWithId:childAxid];
return NSAccessibilityUnignoredAncestor(accessibleElement);
}

View File

@ -59,7 +59,7 @@
return nil;
QAccessible::Id childId = QAccessible::uniqueId(m_window->accessibleRoot());
return [QCocoaAccessibleElement elementWithId: childId];
return [QMacAccessibilityElement elementWithId: childId];
}
// The QNSView is a container that the user does not interact directly with:

View File

@ -23,7 +23,9 @@ OBJECTIVE_SOURCES = \
qiostheme.mm \
qiosglobal.mm \
qiosservices.mm \
qiosclipboard.mm
qiosclipboard.mm \
quiaccessibilityelement.mm \
qiosplatformaccessibility.mm \
HEADERS = \
qiosintegration.h \
@ -40,7 +42,9 @@ HEADERS = \
qiosglobal.h \
qiosservices.h \
quiview.h \
qiosclipboard.h
qiosclipboard.h \
quiaccessibilityelement.h \
qiosplatformaccessibility.h \
OTHER_FILES = \
quiview_textinput.mm

View File

@ -82,6 +82,8 @@ public:
void *nativeResourceForWindow(const QByteArray &resource, QWindow *window);
QTouchDevice *touchDevice();
QPlatformAccessibility *accessibility() const Q_DECL_OVERRIDE;
private:
QPlatformFontDatabase *m_fontDatabase;
QPlatformClipboard *m_clipboard;
@ -90,6 +92,7 @@ private:
QTouchDevice *m_touchDevice;
QIOSApplicationState m_applicationState;
QIOSServices *m_platformServices;
mutable QPlatformAccessibility *m_accessibility;
};
QT_END_NAMESPACE

View File

@ -45,6 +45,7 @@
#include "qioswindow.h"
#include "qiosbackingstore.h"
#include "qiosscreen.h"
#include "qiosplatformaccessibility.h"
#include "qioscontext.h"
#include "qiosclipboard.h"
#include "qiosinputcontext.h"
@ -67,6 +68,7 @@ QIOSIntegration::QIOSIntegration()
, m_inputContext(new QIOSInputContext)
, m_screen(new QIOSScreen(QIOSScreen::MainScreen))
, m_platformServices(new QIOSServices)
, m_accessibility(0)
{
if (![UIApplication sharedApplication]) {
qWarning()
@ -106,6 +108,9 @@ QIOSIntegration::~QIOSIntegration()
delete m_platformServices;
m_platformServices = 0;
delete m_accessibility;
m_accessibility = 0;
}
bool QIOSIntegration::hasCapability(Capability cap) const
@ -229,4 +234,11 @@ QTouchDevice *QIOSIntegration::touchDevice()
return m_touchDevice;
}
QPlatformAccessibility *QIOSIntegration::accessibility() const
{
if (!m_accessibility)
m_accessibility = new QIOSPlatformAccessibility;
return m_accessibility;
}
QT_END_NAMESPACE

View File

@ -0,0 +1,60 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QIOSPLATFORMACCESSIBILITY_H
#define QIOSPLATFORMACCESSIBILITY_H
#include <qpa/qplatformaccessibility.h>
QT_BEGIN_NAMESPACE
class QIOSPlatformAccessibility: public QPlatformAccessibility
{
public:
QIOSPlatformAccessibility();
~QIOSPlatformAccessibility();
virtual void notifyAccessibilityUpdate(QAccessibleEvent *event);
};
QT_END_NAMESPACE
#endif

View File

@ -0,0 +1,85 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qiosplatformaccessibility.h"
#include <QtGui/QtGui>
#include "qioswindow.h"
QIOSPlatformAccessibility::QIOSPlatformAccessibility()
{}
QIOSPlatformAccessibility::~QIOSPlatformAccessibility()
{}
void invalidateCache(QAccessibleInterface *iface)
{
if (!iface || !iface->isValid()) {
qWarning() << "invalid accessible interface: " << iface;
return;
}
QWindow *win = 0;
QAccessibleInterface *parent = iface;
do {
win = parent->window();
parent = parent->parent();
} while (!win && parent);
Q_ASSERT(win && win->handle());
QIOSWindow *window = static_cast<QIOSWindow*>(win->handle());
window->clearAccessibleCache();
}
void QIOSPlatformAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event)
{
switch (event->type()) {
case QAccessible::ObjectCreated:
case QAccessible::ObjectShow:
case QAccessible::ObjectHide:
case QAccessible::ObjectDestroyed:
invalidateCache(event->accessibleInterface());
break;
default:
break;
}
}

View File

@ -87,6 +87,8 @@ public:
WId winId() const { return WId(m_view); };
void clearAccessibleCache();
private:
void applicationStateChanged(Qt::ApplicationState state);
void applyGeometry(const QRect &rect);

View File

@ -52,6 +52,9 @@
#include <QtGui/private/qwindow_p.h>
#include <qpa/qplatformintegration.h>
#include "qiosplatformaccessibility.h"
#import "quiaccessibilityelement.h"
#import <QuartzCore/CAEAGLLayer.h>
#include <QtGui/QKeyEvent>
@ -82,9 +85,74 @@
if (self = [self initWithFrame:toCGRect(window->geometry())])
m_qioswindow = window;
m_accessibleElements = [[NSMutableArray alloc] init];
return self;
}
- (void)createAccessibleElement:(QAccessibleInterface *)iface
{
if (!iface || iface->state().invisible)
return;
QAccessible::Id accessibleId = QAccessible::uniqueId(iface);
UIAccessibilityElement *elem = [[QMacAccessibilityElement alloc] initWithId: accessibleId withAccessibilityContainer: self];
[m_accessibleElements addObject: elem];
}
- (void)createAccessibleContainer:(QAccessibleInterface *)iface
{
if (!iface)
return;
if (iface->childCount() == 0) {
[self createAccessibleElement: iface];
} else {
for (int i = 0; i < iface->childCount(); ++i)
[self createAccessibleContainer: iface->child(i)];
}
}
- (void)initAccessibility
{
static bool init = false;
if (!init)
QGuiApplicationPrivate::platformIntegration()->accessibility()->setActive(true);
init = true;
if ([m_accessibleElements count])
return;
QWindow *win = m_qioswindow->window();
QAccessibleInterface *iface = win->accessibleRoot();
if (iface)
[self createAccessibleContainer: iface];
}
- (void)clearAccessibleCache
{
[m_accessibleElements removeAllObjects];
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, @"");
}
// this is a container, returning yes here means the functions below will never be called
- (BOOL)isAccessibilityElement {
return NO;
}
- (NSInteger)accessibilityElementCount {
[self initAccessibility];
return [m_accessibleElements count];
}
- (id)accessibilityElementAtIndex:(NSInteger)index {
[self initAccessibility];
return m_accessibleElements[index];
}
- (NSInteger)indexOfAccessibilityElement:(id)element {
[self initAccessibility];
return [m_accessibleElements indexOfObject:element];
}
- (id)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame])) {
@ -634,6 +702,11 @@ qreal QIOSWindow::devicePixelRatio() const
return m_view.contentScaleFactor;
}
void QIOSWindow::clearAccessibleCache()
{
[m_view clearAccessibleCache];
}
#include "moc_qioswindow.cpp"
QT_END_NAMESPACE

View File

@ -0,0 +1,58 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QUIACCESSIBILITYELEMENT_H
#define QUIACCESSIBILITYELEMENT_H
#import <UIKit/UIKit.h>
#import <QtGui/QtGui>
@interface QMacAccessibilityElement : UIAccessibilityElement
{}
@property (readonly) QAccessible::Id axid;
- (id) initWithId: (QAccessible::Id) anId withAccessibilityContainer: (id) view;
+ (QMacAccessibilityElement *) elementWithId: (QAccessible::Id) anId withAccessibilityContainer: (id) view;
@end
#endif

View File

@ -0,0 +1,194 @@
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "quiaccessibilityelement.h"
#include "private/qaccessiblecache_p.h"
@implementation QMacAccessibilityElement
- (id) initWithId: (QAccessible::Id) anId withAccessibilityContainer: (id) view
{
Q_ASSERT((int)anId < 0);
self = [super initWithAccessibilityContainer: view];
if (self)
_axid = anId;
return self;
}
+ (id) elementWithId: (QAccessible::Id) anId withAccessibilityContainer: (id) view
{
Q_ASSERT(anId);
if (!anId)
return nil;
QAccessibleCache *cache = QAccessibleCache::instance();
QMacAccessibilityElement *element = cache->elementForId(anId);
if (!element) {
QAccessibleInterface *iface = QAccessible::accessibleInterface(anId);
Q_ASSERT(iface);
element = [[self alloc] initWithId:anId withAccessibilityContainer: view];
cache->insertElement(anId, element);
}
return element;
}
- (void) invalidate
{
[self release];
}
- (BOOL) isAccessibilityElement
{
return YES;
}
- (NSString*) accessibilityLabel
{
QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
if (!iface) {
qWarning() << "invalid accessible interface for: " << self.axid;
return @"";
}
return iface->text(QAccessible::Name).toNSString();
}
- (NSString*) accessibilityHint
{
QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
if (!iface) {
qWarning() << "invalid accessible interface for: " << self.axid;
return @"";
}
return iface->text(QAccessible::Description).toNSString();
}
- (NSString*) accessibilityValue
{
QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
if (!iface) {
qWarning() << "invalid accessible interface for: " << self.axid;
return @"";
}
QAccessible::State state = iface->state();
if (state.checkable)
return state.checked ? @"checked" : @"unchecked"; // FIXME: translation
QAccessibleValueInterface *val = iface->valueInterface();
if (val) {
return val->currentValue().toString().toNSString();
} else if (QAccessibleTextInterface *text = iface->textInterface()) {
// FIXME doesn't work?
return text->text(0, text->characterCount() - 1).toNSString();
}
return [super accessibilityHint];
}
- (CGRect) accessibilityFrame
{
QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
if (!iface) {
qWarning() << "invalid accessible interface for: " << self.axid;
return CGRect();
}
QRect rect = iface->rect();
return CGRectMake(rect.x(), rect.y(), rect.width(), rect.height());
}
- (UIAccessibilityTraits) accessibilityTraits
{
UIAccessibilityTraits traits = UIAccessibilityTraitNone;
QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
if (!iface) {
qWarning() << "invalid accessible interface for: " << self.axid;
return traits;
}
QAccessible::State state = iface->state();
if (state.disabled)
traits |= UIAccessibilityTraitNotEnabled;
if (iface->role() == QAccessible::Button)
traits |= UIAccessibilityTraitButton;
if (iface->valueInterface())
traits |= UIAccessibilityTraitAdjustable;
return traits;
}
- (BOOL) accessibilityActivate
{
QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
if (QAccessibleActionInterface *action = iface->actionInterface()) {
if (action->actionNames().contains(QAccessibleActionInterface::pressAction())) {
action->doAction(QAccessibleActionInterface::pressAction());
return YES;
} else if (action->actionNames().contains(QAccessibleActionInterface::showMenuAction())) {
action->doAction(QAccessibleActionInterface::showMenuAction());
return YES;
}
}
return NO; // fall back to sending mouse clicks
}
- (void) accessibilityIncrement
{
QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
if (QAccessibleActionInterface *action = iface->actionInterface())
action->doAction(QAccessibleActionInterface::increaseAction());
}
- (void) accessibilityDecrement
{
QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
if (QAccessibleActionInterface *action = iface->actionInterface())
action->doAction(QAccessibleActionInterface::decreaseAction());
}
@end

View File

@ -57,6 +57,8 @@
int m_nextTouchId;
QString m_markedText;
BOOL m_inSendEventToFocusObject;
NSMutableArray *m_accessibleElements;
}
@property(nonatomic, assign) id<UITextInputDelegate> inputDelegate;