Implement EditableText accessibility for Mac.

Change-Id: Ibe03975bafc5a6a420b3bd69dfaa93dbf65c9958
Reviewed-by: Frederik Gladhorn <frederik.gladhorn@digia.com>
This commit is contained in:
Morten Johan Sorvig 2012-11-01 12:59:11 +01:00 committed by The Qt Project
parent 2ca6606dca
commit 65866bcff5
4 changed files with 121 additions and 5 deletions

View File

@ -44,6 +44,18 @@
#include <Cocoa/Cocoa.h>
#include <QtGui>
#include <qpa/qplatformaccessibility.h>
class QCococaAccessibility : public QPlatformAccessibility
{
public:
QCococaAccessibility();
~QCococaAccessibility();
void notifyAccessibilityUpdate(QAccessibleEvent *event);
void setRootObject(QObject *o);
void initialize();
void cleanup();
};
namespace QCocoaAccessible {
@ -52,9 +64,9 @@ namespace QCocoaAccessible {
Cocoa accessibility is implemented in the following files:
- qcocoaaccessibility (this file) : QCocoaAccessibility "plugin", conversion and helper functions.
- qnsviewaccessibility : Root accessibility implementation for QNSView
- qcocoaaccessibilityelement : Cocoa accessibility protocol wrapper for QAccessibleInterface
- qcocoaaccessibility (this file) : Conversion and helper functions.
The accessibility implementation wraps QAccessibleInterfaces in QCocoaAccessibleElements, which
implements the cocoa accessibility protocol. The root QAccessibleInterface (the one returned
@ -70,6 +82,8 @@ bool shouldBeIgnrored(QAccessibleInterface *interface);
NSString *getTranslatedAction(const QString &qtAction);
NSMutableArray *createTranslatedActionsList(const QStringList &qtActions);
QString translateAction(NSString *nsAction);
bool hasValueAttribute(QAccessibleInterface *interface);
id getValueAttribute(QAccessibleInterface *interface);
}

View File

@ -39,6 +39,58 @@
**
****************************************************************************/
#include "qcocoaaccessibility.h"
#include "qcocoaaccessibilityelement.h"
#include <qaccessible.h>
#include <qaccessible2.h>
#include <private/qcore_mac_p.h>
QCococaAccessibility::QCococaAccessibility()
{
}
QCococaAccessibility::~QCococaAccessibility()
{
}
void QCococaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event)
{
QObject *object = event->object();
if (!object)
return;
QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(object);
if (!interface)
return;
switch (event->type()) {
case QAccessible::TextInserted :
case QAccessible::TextRemoved :
case QAccessible::TextUpdated : {
QCocoaAccessibleElement *element = [QCocoaAccessibleElement elementWithInterface : interface parent : nil];
NSAccessibilityPostNotification(element, NSAccessibilityValueChangedNotification);
break; }
default:
delete interface;
break;
}
}
void QCococaAccessibility::setRootObject(QObject *o)
{
Q_UNUSED(o)
}
void QCococaAccessibility::initialize()
{
}
void QCococaAccessibility::cleanup()
{
}
namespace QCocoaAccessible {
@ -218,4 +270,38 @@ QString translateAction(NSString *nsAction)
return QString();
}
bool hasValueAttribute(QAccessibleInterface *interface)
{
const QAccessible::Role qtrole = interface->role();
if (qtrole == QAccessible::EditableText) {
return true;
}
return false;
}
id getValueAttribute(QAccessibleInterface *interface)
{
const QAccessible::Role qtrole = interface->role();
if (qtrole == QAccessible::EditableText) {
if (QAccessibleTextInterface *textInterface = interface->textInterface()) {
// VoiceOver will read out the entire text string at once when returning
// text as a value. For large text edits the size of the returned string
// needs to be limited and text range attributes need to be used instead.
// NSTextEdit returns the first sentence as the value, Do the same here:
int begin = 0;
int end = textInterface->characterCount();
// ### call to textAfterOffset hangs. Booo!
//if (textInterface->characterCount() > 0)
// textInterface->textAfterOffset(0, QAccessible2::SentenceBoundary, &begin, &end);
QString text = textInterface->text(begin, end);
//qDebug() << "text" << begin << end << text;
return QCFString::toNSString(text);
}
}
return nil;
}
} // namespace QCocoaAccessible

View File

@ -96,9 +96,9 @@ static QAccessibleInterface *acast(void *ptr)
// attributes
- (NSArray *)accessibilityAttributeNames {
static NSArray *attributes = nil;
if (attributes == nil) {
attributes = [[NSArray alloc] initWithObjects:
static NSArray *defaultAttributes = nil;
if (defaultAttributes == nil) {
defaultAttributes = [[NSArray alloc] initWithObjects:
NSAccessibilityRoleAttribute,
NSAccessibilityRoleDescriptionAttribute,
NSAccessibilityChildrenAttribute,
@ -112,6 +112,14 @@ static QAccessibleInterface *acast(void *ptr)
NSAccessibilityEnabledAttribute,
nil];
}
NSMutableArray *attributes = [[NSMutableArray alloc] initWithCapacity : [defaultAttributes count]];
[attributes addObjectsFromArray : defaultAttributes];
if (QCocoaAccessible::hasValueAttribute(acast(accessibleInterface))) {
[attributes addObject : NSAccessibilityValueAttribute];
}
return attributes;
}
@ -153,6 +161,13 @@ static QAccessibleInterface *acast(void *ptr)
return QCFString::toNSString(acast(accessibleInterface)->text(QAccessible::Name));
} else if ([attribute isEqualToString:NSAccessibilityEnabledAttribute]) {
return [NSNumber numberWithBool:!acast(accessibleInterface)->state().disabled];
} else if ([attribute isEqualToString:NSAccessibilityValueAttribute]) {
// VoiceOver asks for the value attribute for all elements. Return nil
// if we don't want the element to have a value attribute.
if (!QCocoaAccessible::hasValueAttribute(acast(accessibleInterface)))
return nil;
return QCocoaAccessible::getValueAttribute(acast(accessibleInterface));
}
return nil;

View File

@ -53,6 +53,7 @@
#include "qcocoatheme.h"
#include "qcocoainputcontext.h"
#include "qmacmime.h"
#include "qcocoaaccessibility.h"
#include <qpa/qplatformaccessibility.h>
#include <QtCore/qcoreapplication.h>
@ -180,7 +181,7 @@ QCocoaIntegration::QCocoaIntegration()
, mEventDispatcher(new QCocoaEventDispatcher())
, mInputContext(new QCocoaInputContext)
#ifndef QT_NO_ACCESSIBILITY
, mAccessibility(new QPlatformAccessibility)
, mAccessibility(new QCococaAccessibility)
#endif
, mCocoaClipboard(new QCocoaClipboard)
, mCocoaDrag(new QCocoaDrag)