summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/ios
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/ios')
-rw-r--r--src/plugins/platforms/ios/ios.pro8
-rw-r--r--src/plugins/platforms/ios/qiosintegration.h3
-rw-r--r--src/plugins/platforms/ios/qiosintegration.mm12
-rw-r--r--src/plugins/platforms/ios/qiosplatformaccessibility.h60
-rw-r--r--src/plugins/platforms/ios/qiosplatformaccessibility.mm85
-rw-r--r--src/plugins/platforms/ios/qioswindow.h2
-rw-r--r--src/plugins/platforms/ios/qioswindow.mm73
-rw-r--r--src/plugins/platforms/ios/quiaccessibilityelement.h58
-rw-r--r--src/plugins/platforms/ios/quiaccessibilityelement.mm194
-rw-r--r--src/plugins/platforms/ios/quiview.h2
10 files changed, 495 insertions, 2 deletions
diff --git a/src/plugins/platforms/ios/ios.pro b/src/plugins/platforms/ios/ios.pro
index ffc4ff9b12..57d4ac1770 100644
--- a/src/plugins/platforms/ios/ios.pro
+++ b/src/plugins/platforms/ios/ios.pro
@@ -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
diff --git a/src/plugins/platforms/ios/qiosintegration.h b/src/plugins/platforms/ios/qiosintegration.h
index 956c112399..733c8dc270 100644
--- a/src/plugins/platforms/ios/qiosintegration.h
+++ b/src/plugins/platforms/ios/qiosintegration.h
@@ -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
diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm
index 0fe7adff9f..3334e3a094 100644
--- a/src/plugins/platforms/ios/qiosintegration.mm
+++ b/src/plugins/platforms/ios/qiosintegration.mm
@@ -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
diff --git a/src/plugins/platforms/ios/qiosplatformaccessibility.h b/src/plugins/platforms/ios/qiosplatformaccessibility.h
new file mode 100644
index 0000000000..beb0d006e1
--- /dev/null
+++ b/src/plugins/platforms/ios/qiosplatformaccessibility.h
@@ -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
diff --git a/src/plugins/platforms/ios/qiosplatformaccessibility.mm b/src/plugins/platforms/ios/qiosplatformaccessibility.mm
new file mode 100644
index 0000000000..db579ba559
--- /dev/null
+++ b/src/plugins/platforms/ios/qiosplatformaccessibility.mm
@@ -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;
+ }
+}
diff --git a/src/plugins/platforms/ios/qioswindow.h b/src/plugins/platforms/ios/qioswindow.h
index 6b6892e6e4..bcff3e202c 100644
--- a/src/plugins/platforms/ios/qioswindow.h
+++ b/src/plugins/platforms/ios/qioswindow.h
@@ -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);
diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm
index 6f5c96cfc1..3ed2bbe1a1 100644
--- a/src/plugins/platforms/ios/qioswindow.mm
+++ b/src/plugins/platforms/ios/qioswindow.mm
@@ -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
diff --git a/src/plugins/platforms/ios/quiaccessibilityelement.h b/src/plugins/platforms/ios/quiaccessibilityelement.h
new file mode 100644
index 0000000000..7c5a930e86
--- /dev/null
+++ b/src/plugins/platforms/ios/quiaccessibilityelement.h
@@ -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
diff --git a/src/plugins/platforms/ios/quiaccessibilityelement.mm b/src/plugins/platforms/ios/quiaccessibilityelement.mm
new file mode 100644
index 0000000000..c9e9e34cbd
--- /dev/null
+++ b/src/plugins/platforms/ios/quiaccessibilityelement.mm
@@ -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
diff --git a/src/plugins/platforms/ios/quiview.h b/src/plugins/platforms/ios/quiview.h
index 575dedab89..91c4fc9dde 100644
--- a/src/plugins/platforms/ios/quiview.h
+++ b/src/plugins/platforms/ios/quiview.h
@@ -57,6 +57,8 @@
int m_nextTouchId;
QString m_markedText;
BOOL m_inSendEventToFocusObject;
+
+ NSMutableArray *m_accessibleElements;
}
@property(nonatomic, assign) id<UITextInputDelegate> inputDelegate;