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:
parent
0f8d35ff73
commit
d707acfc9e
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
60
src/plugins/platforms/ios/qiosplatformaccessibility.h
Normal file
60
src/plugins/platforms/ios/qiosplatformaccessibility.h
Normal 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
|
85
src/plugins/platforms/ios/qiosplatformaccessibility.mm
Normal file
85
src/plugins/platforms/ios/qiosplatformaccessibility.mm
Normal 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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
@ -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
|
||||
|
58
src/plugins/platforms/ios/quiaccessibilityelement.h
Normal file
58
src/plugins/platforms/ios/quiaccessibilityelement.h
Normal 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
|
194
src/plugins/platforms/ios/quiaccessibilityelement.mm
Normal file
194
src/plugins/platforms/ios/quiaccessibilityelement.mm
Normal 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
|
@ -57,6 +57,8 @@
|
||||
int m_nextTouchId;
|
||||
QString m_markedText;
|
||||
BOOL m_inSendEventToFocusObject;
|
||||
|
||||
NSMutableArray *m_accessibleElements;
|
||||
}
|
||||
|
||||
@property(nonatomic, assign) id<UITextInputDelegate> inputDelegate;
|
||||
|
Loading…
x
Reference in New Issue
Block a user