Issue #1829 - Revert "Issue #1751"

This commit is contained in:
Brian Smith 2022-04-26 11:34:08 -05:00 • committed by roytam1
commit 13fcc4a046
949 changed files with 95662 additions and 444 deletions

View file

@ -35,10 +35,10 @@ EPlatformDisabledState PlatformDisabledState();
void PreInit();
#endif
#if defined(MOZ_ACCESSIBILITY_ATK)
#if defined(MOZ_ACCESSIBILITY_ATK) || defined(XP_MACOSX)
/**
* Is platform accessibility enabled.
* Only used on linux with atk.
* Only used on linux with atk and MacOS for now.
*/
bool ShouldA11yBeEnabled();
#endif

View file

@ -96,6 +96,10 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
'/accessible/windows/ia2',
'/accessible/windows/msaa',
]
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
LOCAL_INCLUDES += [
'/accessible/mac',
]
else:
LOCAL_INCLUDES += [
'/accessible/other',

View file

@ -52,6 +52,10 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
'/accessible/windows/ia2',
'/accessible/windows/msaa',
]
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
LOCAL_INCLUDES += [
'/accessible/mac',
]
else:
LOCAL_INCLUDES += [
'/accessible/other',

View file

@ -32,6 +32,10 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
'/accessible/windows/ia2',
'/accessible/windows/msaa',
]
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
LOCAL_INCLUDES += [
'/accessible/mac',
]
else:
LOCAL_INCLUDES += [
'/accessible/other',

View file

@ -19,6 +19,10 @@ else:
LOCAL_INCLUDES += [
'/accessible/atk',
]
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
LOCAL_INCLUDES += [
'/accessible/mac',
]
else:
LOCAL_INCLUDES += [
'/accessible/other',

View file

@ -28,6 +28,10 @@ if CONFIG['ACCESSIBILITY']:
LOCAL_INCLUDES += [
'/accessible/atk',
]
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
LOCAL_INCLUDES += [
'/accessible/mac',
]
else:
LOCAL_INCLUDES += [
'/accessible/other',

View file

@ -0,0 +1,22 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:expandtab:shiftwidth=2:tabstop=2:
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MOZILLA_A11Y_ARIAGRIDACCESSIBLEWRAP_H
#define MOZILLA_A11Y_ARIAGRIDACCESSIBLEWRAP_H
#include "ARIAGridAccessible.h"
namespace mozilla {
namespace a11y {
typedef class ARIAGridAccessible ARIAGridAccessibleWrap;
typedef class ARIAGridCellAccessible ARIAGridCellAccessibleWrap;
} // namespace a11y
} // namespace mozilla
#endif

View file

@ -0,0 +1,103 @@
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* For documentation of the accessibility architecture,
* see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
*/
#ifndef _AccessibleWrap_H_
#define _AccessibleWrap_H_
#include <objc/objc.h>
#include "Accessible.h"
#include "States.h"
#include "nsCOMPtr.h"
#include "nsTArray.h"
#if defined(__OBJC__)
@class mozAccessible;
#endif
namespace mozilla {
namespace a11y {
class AccessibleWrap : public Accessible
{
public: // construction, destruction
AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc);
virtual ~AccessibleWrap();
/**
* Get the native Obj-C object (mozAccessible).
*/
virtual void GetNativeInterface(void** aOutAccessible) override;
/**
* The objective-c |Class| type that this accessible's native object
* should be instantied with. used on runtime to determine the
* right type for this accessible's associated native object.
*/
virtual Class GetNativeType ();
virtual void Shutdown () override;
virtual bool InsertChildAt(uint32_t aIdx, Accessible* aChild) override;
virtual bool RemoveChild(Accessible* aAccessible) override;
virtual nsresult HandleAccEvent(AccEvent* aEvent) override;
protected:
/**
* Return true if the parent doesn't have children to expose to AT.
*/
bool AncestorIsFlat();
/**
* Get the native object. Create it if needed.
*/
#if defined(__OBJC__)
mozAccessible* GetNativeObject();
#else
id GetNativeObject();
#endif
private:
/**
* Our native object. Private because its creation is done lazily.
* Don't access it directly. Ever. Unless you are GetNativeObject() or
* Shutdown()
*/
#if defined(__OBJC__)
// if we are in Objective-C, we use the actual Obj-C class.
mozAccessible* mNativeObject;
#else
id mNativeObject;
#endif
/**
* We have created our native. This does not mean there is one.
* This can never go back to false.
* We need it because checking whether we need a native object cost time.
*/
bool mNativeInited;
};
#if defined(__OBJC__)
void FireNativeEvent(mozAccessible* aNativeAcc, uint32_t aEventType);
#else
void FireNativeEvent(id aNativeAcc, uint32_t aEventType);
#endif
Class GetTypeFromRole(roles::Role aRole);
} // namespace a11y
} // namespace mozilla
#endif

View file

@ -0,0 +1,256 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "DocAccessible.h"
#include "nsObjCExceptions.h"
#include "Accessible-inl.h"
#include "nsAccUtils.h"
#include "Role.h"
#import "mozAccessible.h"
#import "mozActionElements.h"
#import "mozHTMLAccessible.h"
#import "mozTableAccessible.h"
#import "mozTextAccessible.h"
using namespace mozilla;
using namespace mozilla::a11y;
AccessibleWrap::
AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc) :
Accessible(aContent, aDoc), mNativeObject(nil),
mNativeInited(false)
{
}
AccessibleWrap::~AccessibleWrap()
{
}
mozAccessible*
AccessibleWrap::GetNativeObject()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
if (!mNativeInited && !mNativeObject && !IsDefunct() && !AncestorIsFlat()) {
uintptr_t accWrap = reinterpret_cast<uintptr_t>(this);
mNativeObject = [[GetNativeType() alloc] initWithAccessible:accWrap];
}
mNativeInited = true;
return mNativeObject;
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
void
AccessibleWrap::GetNativeInterface(void** aOutInterface)
{
*aOutInterface = static_cast<void*>(GetNativeObject());
}
// overridden in subclasses to create the right kind of object. by default we create a generic
// 'mozAccessible' node.
Class
AccessibleWrap::GetNativeType ()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
if (IsXULTabpanels())
return [mozPaneAccessible class];
if (IsTable())
return [mozTableAccessible class];
if (IsTableRow())
return [mozTableRowAccessible class];
if (IsTableCell())
return [mozTableCellAccessible class];
return GetTypeFromRole(Role());
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
// this method is very important. it is fired when an accessible object "dies". after this point
// the object might still be around (because some 3rd party still has a ref to it), but it is
// in fact 'dead'.
void
AccessibleWrap::Shutdown ()
{
// this ensure we will not try to re-create the native object.
mNativeInited = true;
// we really intend to access the member directly.
if (mNativeObject) {
[mNativeObject expire];
[mNativeObject release];
mNativeObject = nil;
}
Accessible::Shutdown();
}
nsresult
AccessibleWrap::HandleAccEvent(AccEvent* aEvent)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
nsresult rv = Accessible::HandleAccEvent(aEvent);
NS_ENSURE_SUCCESS(rv, rv);
if (IPCAccessibilityActive()) {
return NS_OK;
}
uint32_t eventType = aEvent->GetEventType();
// ignore everything but focus-changed, value-changed, caret, selection
// and document load complete events for now.
if (eventType != nsIAccessibleEvent::EVENT_FOCUS &&
eventType != nsIAccessibleEvent::EVENT_VALUE_CHANGE &&
eventType != nsIAccessibleEvent::EVENT_TEXT_VALUE_CHANGE &&
eventType != nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED &&
eventType != nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED &&
eventType != nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE)
return NS_OK;
Accessible* accessible = aEvent->GetAccessible();
NS_ENSURE_STATE(accessible);
mozAccessible *nativeAcc = nil;
accessible->GetNativeInterface((void**)&nativeAcc);
if (!nativeAcc)
return NS_ERROR_FAILURE;
FireNativeEvent(nativeAcc, eventType);
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
bool
AccessibleWrap::InsertChildAt(uint32_t aIdx, Accessible* aAccessible)
{
bool inserted = Accessible::InsertChildAt(aIdx, aAccessible);
if (inserted && mNativeObject)
[mNativeObject appendChild:aAccessible];
return inserted;
}
bool
AccessibleWrap::RemoveChild(Accessible* aAccessible)
{
bool removed = Accessible::RemoveChild(aAccessible);
if (removed && mNativeObject)
[mNativeObject invalidateChildren];
return removed;
}
////////////////////////////////////////////////////////////////////////////////
// AccessibleWrap protected
bool
AccessibleWrap::AncestorIsFlat()
{
// We don't create a native object if we're child of a "flat" accessible;
// for example, on OS X buttons shouldn't have any children, because that
// makes the OS confused.
//
// To maintain a scripting environment where the XPCOM accessible hierarchy
// look the same on all platforms, we still let the C++ objects be created
// though.
Accessible* parent = Parent();
while (parent) {
if (nsAccUtils::MustPrune(parent))
return true;
parent = parent->Parent();
}
// no parent was flat
return false;
}
void
a11y::FireNativeEvent(mozAccessible* aNativeAcc, uint32_t aEventType)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
switch (aEventType) {
case nsIAccessibleEvent::EVENT_FOCUS:
[aNativeAcc didReceiveFocus];
break;
case nsIAccessibleEvent::EVENT_VALUE_CHANGE:
case nsIAccessibleEvent::EVENT_TEXT_VALUE_CHANGE:
[aNativeAcc valueDidChange];
break;
case nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED:
case nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED:
[aNativeAcc selectedTextDidChange];
break;
case nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE:
[aNativeAcc documentLoadComplete];
break;
}
NS_OBJC_END_TRY_ABORT_BLOCK;
}
Class
a11y::GetTypeFromRole(roles::Role aRole)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
switch (aRole) {
case roles::COMBOBOX:
case roles::PUSHBUTTON:
case roles::SPLITBUTTON:
case roles::TOGGLE_BUTTON:
{
return [mozButtonAccessible class];
}
case roles::PAGETAB:
return [mozButtonAccessible class];
case roles::CHECKBUTTON:
return [mozCheckboxAccessible class];
case roles::HEADING:
return [mozHeadingAccessible class];
case roles::PAGETABLIST:
return [mozTabsAccessible class];
case roles::ENTRY:
case roles::STATICTEXT:
case roles::CAPTION:
case roles::ACCEL_LABEL:
case roles::PASSWORD_TEXT:
// normal textfield (static or editable)
return [mozTextAccessible class];
case roles::TEXT_LEAF:
return [mozTextLeafAccessible class];
case roles::LINK:
return [mozLinkAccessible class];
default:
return [mozAccessible class];
}
return nil;
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}

View file

@ -0,0 +1,22 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim:expandtab:shiftwidth=4:tabstop=4:
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_a11y_ApplicationAccessibleWrap_h__
#define mozilla_a11y_ApplicationAccessibleWrap_h__
#include "ApplicationAccessible.h"
namespace mozilla {
namespace a11y {
typedef ApplicationAccessible ApplicationAccessibleWrap;
} // namespace a11y
} // namespace mozilla
#endif

View file

@ -0,0 +1,25 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_a11y_DocAccessibleWrap_h__
#define mozilla_a11y_DocAccessibleWrap_h__
#include "DocAccessible.h"
namespace mozilla {
namespace a11y {
class DocAccessibleWrap : public DocAccessible
{
public:
DocAccessibleWrap(nsIDocument* aDocument, nsIPresShell* aPresShell);
virtual ~DocAccessibleWrap();
};
} // namespace a11y
} // namespace mozilla
#endif

View file

@ -0,0 +1,21 @@
/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "DocAccessibleWrap.h"
#import "mozAccessible.h"
using namespace mozilla::a11y;
DocAccessibleWrap::
DocAccessibleWrap(nsIDocument* aDocument, nsIPresShell* aPresShell) :
DocAccessible(aDocument, aPresShell)
{
}
DocAccessibleWrap::~DocAccessibleWrap()
{
}

View file

@ -0,0 +1,24 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:expandtab:shiftwidth=2:tabstop=2:
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_a11y_HTMLTableAccessibleWrap_h__
#define mozilla_a11y_HTMLTableAccessibleWrap_h__
#include "HTMLTableAccessible.h"
namespace mozilla {
namespace a11y {
typedef class HTMLTableAccessible HTMLTableAccessibleWrap;
typedef class HTMLTableCellAccessible HTMLTableCellAccessibleWrap;
typedef class HTMLTableHeaderCellAccessible HTMLTableHeaderCellAccessibleWrap;
} // namespace a11y
} // namespace mozilla
#endif

View file

@ -0,0 +1,20 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_a11y_HyperTextAccessibleWrap_h__
#define mozilla_a11y_HyperTextAccessibleWrap_h__
#include "HyperTextAccessible.h"
namespace mozilla {
namespace a11y {
typedef class HyperTextAccessible HyperTextAccessibleWrap;
} // namespace a11y
} // namespace mozilla
#endif

View file

@ -0,0 +1,22 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:expandtab:shiftwidth=2:tabstop=2:
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_a11y_ImageAccessibleWrap_h__
#define mozilla_a11y_ImageAccessibleWrap_h__
#include "ImageAccessible.h"
namespace mozilla {
namespace a11y {
typedef class ImageAccessible ImageAccessibleWrap;
} // namespace a11y
} // namespace mozilla
#endif

26
accessible/mac/MacUtils.h Normal file
View file

@ -0,0 +1,26 @@
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _MacUtils_H_
#define _MacUtils_H_
@class NSString;
class nsString;
namespace mozilla {
namespace a11y {
namespace utils {
/**
* Get a localized string from the string bundle.
* Return nil if not found.
*/
NSString* LocalizedString(const nsString& aString);
}
}
}
#endif

View file

@ -0,0 +1,32 @@
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#import "MacUtils.h"
#include "Accessible.h"
#include "nsCocoaUtils.h"
namespace mozilla {
namespace a11y {
namespace utils {
/**
* Get a localized string from the a11y string bundle.
* Return nil if not found.
*/
NSString*
LocalizedString(const nsString& aString)
{
nsString text;
Accessible::TranslateString(aString, text);
return text.IsEmpty() ? nil : nsCocoaUtils::ToNSString(text);
}
}
}
}

174
accessible/mac/Platform.mm Normal file
View file

@ -0,0 +1,174 @@
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#import <Cocoa/Cocoa.h>
#include "Platform.h"
#include "ProxyAccessible.h"
#include "DocAccessibleParent.h"
#include "mozTableAccessible.h"
#include "nsAppShell.h"
namespace mozilla {
namespace a11y {
// Mac a11y whitelisting
static bool sA11yShouldBeEnabled = false;
bool
ShouldA11yBeEnabled()
{
EPlatformDisabledState disabledState = PlatformDisabledState();
return (disabledState == ePlatformIsForceEnabled) || ((disabledState == ePlatformIsEnabled) && sA11yShouldBeEnabled);
}
void
PlatformInit()
{
}
void
PlatformShutdown()
{
}
void
ProxyCreated(ProxyAccessible* aProxy, uint32_t)
{
// Pass in dummy state for now as retrieving proxy state requires IPC.
// Note that we can use ProxyAccessible::IsTable* functions here because they
// do not use IPC calls but that might change after bug 1210477.
Class type;
if (aProxy->IsTable())
type = [mozTableAccessible class];
else if (aProxy->IsTableRow())
type = [mozTableRowAccessible class];
else if (aProxy->IsTableCell())
type = [mozTableCellAccessible class];
else
type = GetTypeFromRole(aProxy->Role());
uintptr_t accWrap = reinterpret_cast<uintptr_t>(aProxy) | IS_PROXY;
mozAccessible* mozWrapper = [[type alloc] initWithAccessible:accWrap];
aProxy->SetWrapper(reinterpret_cast<uintptr_t>(mozWrapper));
mozAccessible* nativeParent = nullptr;
if (aProxy->IsDoc() && aProxy->AsDoc()->IsTopLevel()) {
// If proxy is top level, the parent we need to invalidate the children of
// will be a non-remote accessible.
Accessible* outerDoc = aProxy->OuterDocOfRemoteBrowser();
if (outerDoc) {
nativeParent = GetNativeFromGeckoAccessible(outerDoc);
}
} else {
// Non-top level proxies need proxy parents' children invalidated.
ProxyAccessible* parent = aProxy->Parent();
nativeParent = GetNativeFromProxy(parent);
NS_ASSERTION(parent, "a non-top-level proxy is missing a parent?");
}
if (nativeParent) {
[nativeParent invalidateChildren];
}
}
void
ProxyDestroyed(ProxyAccessible* aProxy)
{
mozAccessible* nativeParent = nil;
if (aProxy->IsDoc() && aProxy->AsDoc()->IsTopLevel()) {
// Invalidate native parent in parent process's children on proxy destruction
Accessible* outerDoc = aProxy->OuterDocOfRemoteBrowser();
if (outerDoc) {
nativeParent = GetNativeFromGeckoAccessible(outerDoc);
}
} else {
if (!aProxy->Document()->IsShutdown()) {
// Only do if the document has not been shut down, else parent will return
// garbage since we don't shut down children from top down.
ProxyAccessible* parent = aProxy->Parent();
// Invalidate proxy parent's children.
if (parent) {
nativeParent = GetNativeFromProxy(parent);
}
}
}
mozAccessible* wrapper = GetNativeFromProxy(aProxy);
[wrapper expire];
[wrapper release];
aProxy->SetWrapper(0);
if (nativeParent) {
[nativeParent invalidateChildren];
}
}
void
ProxyEvent(ProxyAccessible* aProxy, uint32_t aEventType)
{
// ignore everything but focus-changed, value-changed, caret and selection
// events for now.
if (aEventType != nsIAccessibleEvent::EVENT_FOCUS &&
aEventType != nsIAccessibleEvent::EVENT_VALUE_CHANGE &&
aEventType != nsIAccessibleEvent::EVENT_TEXT_VALUE_CHANGE &&
aEventType != nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED &&
aEventType != nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED)
return;
mozAccessible* wrapper = GetNativeFromProxy(aProxy);
if (wrapper)
FireNativeEvent(wrapper, aEventType);
}
void
ProxyStateChangeEvent(ProxyAccessible* aProxy, uint64_t, bool)
{
// mac doesn't care about state change events
}
void
ProxyCaretMoveEvent(ProxyAccessible* aTarget, int32_t aOffset)
{
mozAccessible* wrapper = GetNativeFromProxy(aTarget);
if (wrapper)
[wrapper selectedTextDidChange];
}
void
ProxyTextChangeEvent(ProxyAccessible*, const nsString&, int32_t, uint32_t,
bool, bool)
{
}
void
ProxyShowHideEvent(ProxyAccessible*, ProxyAccessible*, bool, bool)
{
}
void
ProxySelectionEvent(ProxyAccessible*, ProxyAccessible*, uint32_t)
{
}
} // namespace a11y
} // namespace mozilla
@interface GeckoNSApplication(a11y)
-(void)accessibilitySetValue:(id)value forAttribute:(NSString*)attribute;
@end
@implementation GeckoNSApplication(a11y)
-(void)accessibilitySetValue:(id)value forAttribute:(NSString*)attribute
{
if ([attribute isEqualToString:@"AXEnhancedUserInterface"])
mozilla::a11y::sA11yShouldBeEnabled = ([value intValue] == 1);
return [super accessibilitySetValue:value forAttribute:attribute];
}
@end

View file

@ -0,0 +1,34 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* For documentation of the accessibility architecture,
* see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
*/
#ifndef mozilla_a11y_RootAccessibleWrap_h__
#define mozilla_a11y_RootAccessibleWrap_h__
#include "RootAccessible.h"
namespace mozilla {
namespace a11y {
class RootAccessibleWrap : public RootAccessible
{
public:
RootAccessibleWrap(nsIDocument* aDocument, nsIPresShell* aPresShell);
virtual ~RootAccessibleWrap();
Class GetNativeType ();
// let's our native accessible get in touch with the
// native cocoa view that is our accessible parent.
void GetNativeWidget (void **aOutView);
};
} // namespace a11y
} // namespace mozilla
#endif

View file

@ -0,0 +1,53 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "RootAccessibleWrap.h"
#include "mozDocAccessible.h"
#include "nsCOMPtr.h"
#include "nsObjCExceptions.h"
#include "nsIFrame.h"
#include "nsView.h"
#include "nsIWidget.h"
using namespace mozilla::a11y;
RootAccessibleWrap::
RootAccessibleWrap(nsIDocument* aDocument, nsIPresShell* aPresShell) :
RootAccessible(aDocument, aPresShell)
{
}
RootAccessibleWrap::~RootAccessibleWrap()
{
}
Class
RootAccessibleWrap::GetNativeType()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
return [mozRootAccessible class];
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
void
RootAccessibleWrap::GetNativeWidget(void** aOutView)
{
nsIFrame *frame = GetFrame();
if (frame) {
nsView *view = frame->GetView();
if (view) {
nsIWidget *widget = view->GetWidget();
if (widget) {
*aOutView = (void**)widget->GetNativeData (NS_NATIVE_WIDGET);
NS_ASSERTION (*aOutView,
"Couldn't get the native NSView parent we need to connect the accessibility hierarchy!");
}
}
}
}

View file

@ -0,0 +1,19 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_a11y_TextLeafAccessibleWrap_h__
#define mozilla_a11y_TextLeafAccessibleWrap_h__
#include "TextLeafAccessible.h"
namespace mozilla {
namespace a11y {
typedef class TextLeafAccessible TextLeafAccessibleWrap;
} // namespace a11y
} // namespace mozilla
#endif

View file

@ -0,0 +1,20 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_a11y_XULListboxAccessibleWrap_h__
#define mozilla_a11y_XULListboxAccessibleWrap_h__
#include "XULListboxAccessible.h"
namespace mozilla {
namespace a11y {
typedef class XULListboxAccessible XULListboxAccessibleWrap;
typedef class XULListCellAccessible XULListCellAccessibleWrap;
} // namespace a11y
} // namespace mozilla
#endif

View file

@ -0,0 +1,19 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_a11y_XULMenuAccessibleWrap_h__
#define mozilla_a11y_XULMenuAccessibleWrap_h__
#include "XULMenuAccessible.h"
namespace mozilla {
namespace a11y {
typedef class XULMenuitemAccessible XULMenuitemAccessibleWrap;
} // namespace a11y
} // namespace mozilla
#endif

View file

@ -0,0 +1,20 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_a11y_XULTreeGridAccessibleWrap_h__
#define mozilla_a11y_XULTreeGridAccessibleWrap_h__
#include "XULTreeGridAccessible.h"
namespace mozilla {
namespace a11y {
typedef class XULTreeGridAccessible XULTreeGridAccessibleWrap;
typedef class XULTreeGridCellAccessible XULTreeGridCellAccessibleWrap;
} // namespace a11y
} // namespace mozilla
#endif

44
accessible/mac/moz.build Normal file
View file

@ -0,0 +1,44 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXPORTS += [
'mozAccessibleProtocol.h',
]
EXPORTS.mozilla.a11y += [
'AccessibleWrap.h',
'HyperTextAccessibleWrap.h',
]
SOURCES += [
'AccessibleWrap.mm',
'DocAccessibleWrap.mm',
'MacUtils.mm',
'mozAccessible.mm',
'mozActionElements.mm',
'mozDocAccessible.mm',
'mozHTMLAccessible.mm',
'mozTableAccessible.mm',
'mozTextAccessible.mm',
'Platform.mm',
'RootAccessibleWrap.mm',
]
LOCAL_INCLUDES += [
'/accessible/base',
'/accessible/generic',
'/accessible/html',
'/accessible/ipc',
'/accessible/ipc/other',
'/accessible/xul',
'/layout/generic',
'/layout/xul',
'/widget',
'/widget/cocoa',
]
FINAL_LIBRARY = 'xul'
include('/ipc/chromium/chromium-config.mozbuild')

View file

@ -0,0 +1,181 @@
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "AccessibleWrap.h"
#include "ProxyAccessible.h"
#import <Cocoa/Cocoa.h>
#import "mozAccessibleProtocol.h"
@class mozRootAccessible;
/**
* All mozAccessibles are either abstract objects (that correspond to XUL
* widgets, HTML frames, etc) or are attached to a certain view; for example
* a document view. When we hand an object off to an AT, we always want
* to give it the represented view, in the latter case.
*/
namespace mozilla {
namespace a11y {
inline id <mozAccessible>
GetObjectOrRepresentedView(id <mozAccessible> aObject)
{
return [aObject hasRepresentedView] ? [aObject representedView] : aObject;
}
inline mozAccessible*
GetNativeFromGeckoAccessible(Accessible* aAccessible)
{
mozAccessible* native = nil;
aAccessible->GetNativeInterface((void**)&native);
return native;
}
inline mozAccessible*
GetNativeFromProxy(const ProxyAccessible* aProxy)
{
return reinterpret_cast<mozAccessible*>(aProxy->GetWrapper());
}
} // a11y
} // mozilla
// This is OR'd with the Accessible owner to indicate the wrap-ee is a proxy.
static const uintptr_t IS_PROXY = 1;
@interface mozAccessible : NSObject <mozAccessible>
{
/**
* Weak reference; it owns us.
*/
uintptr_t mGeckoAccessible;
/**
* Strong ref to array of children
*/
NSMutableArray* mChildren;
/**
* Weak reference to the parent
*/
mozAccessible* mParent;
/**
* The role of our gecko accessible.
*/
mozilla::a11y::role mRole;
}
// return the Accessible for this mozAccessible if it exists.
- (mozilla::a11y::AccessibleWrap*)getGeckoAccessible;
// return the ProxyAccessible for this mozAccessible if it exists.
- (mozilla::a11y::ProxyAccessible*)getProxyAccessible;
// inits with the gecko owner.
- (id)initWithAccessible:(uintptr_t)aGeckoObj;
// our accessible parent (AXParent)
- (id <mozAccessible>)parent;
// a lazy cache of our accessible children (AXChildren). updated
- (NSArray*)children;
// returns the size of this accessible.
- (NSValue*)size;
// returns the position, in cocoa coordinates.
- (NSValue*)position;
// can be overridden to report another role name.
- (NSString*)role;
// a subrole is a more specialized variant of the role. for example,
// the role might be "textfield", while the subrole is "password textfield".
- (NSString*)subrole;
// Return the role description, as there are a few exceptions.
- (NSString*)roleDescription;
// returns the native window we're inside.
- (NSWindow*)window;
// the value of this element.
- (id)value;
// name that is associated with this accessible (for buttons, etc)
- (NSString*)title;
// the accessible description (help text) of this particular instance.
- (NSString*)help;
- (BOOL)isEnabled;
// information about focus.
- (BOOL)isFocused;
- (BOOL)canBeFocused;
// returns NO if for some reason we were unable to focus the element.
- (BOOL)focus;
// notifications sent out to listening accessible providers.
- (void)didReceiveFocus;
- (void)valueDidChange;
- (void)selectedTextDidChange;
- (void)documentLoadComplete;
// internal method to retrieve a child at a given index.
- (id)childAt:(uint32_t)i;
#pragma mark -
// invalidates and removes all our children from our cached array.
- (void)invalidateChildren;
/**
* Append a child if they are already cached.
*/
- (void)appendChild:(mozilla::a11y::Accessible*)aAccessible;
// makes ourselves "expired". after this point, we might be around if someone
// has retained us (e.g., a third-party), but we really contain no information.
- (void)expire;
- (BOOL)isExpired;
#ifdef DEBUG
- (void)printHierarchy;
- (void)printHierarchyWithLevel:(unsigned)numSpaces;
- (void)sanityCheckChildren;
- (void)sanityCheckChildren:(NSArray*)theChildren;
#endif
// ---- NSAccessibility methods ---- //
// whether to skip this element when traversing the accessibility
// hierarchy.
- (BOOL)accessibilityIsIgnored;
// called by third-parties to determine the deepest child element under the mouse
- (id)accessibilityHitTest:(NSPoint)point;
// returns the deepest unignored focused accessible element
- (id)accessibilityFocusedUIElement;
// a mozAccessible needs to at least provide links to its parent and
// children.
- (NSArray*)accessibilityAttributeNames;
// value for the specified attribute
- (id)accessibilityAttributeValue:(NSString*)attribute;
- (BOOL)accessibilityIsAttributeSettable:(NSString*)attribute;
- (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attribute;
@end

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,69 @@
/* -*- Mode: Objective-C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#import <Cocoa/Cocoa.h>
#import "mozView.h"
/* This protocol's primary use is so widget/cocoa can talk back to us
properly.
ChildView owns the topmost mozRootAccessible, and needs to take care of setting up
that parent/child relationship.
This protocol is thus used to make sure it knows it's talking to us, and not
just some random |id|.
*/
@protocol mozAccessible
// returns whether this accessible is the root accessible. there is one
// root accessible per window.
- (BOOL)isRoot;
// some mozAccessibles implement accessibility support in place of another object. for example,
// ChildView gets its support from us.
//
// instead of returning a mozAccessible to the OS when it wants an object, we need to pass the view we represent, so the
// OS doesn't get confused and think we return some random object.
- (BOOL)hasRepresentedView;
- (id)representedView;
#ifdef DEBUG
// debug utility that will print the native accessibility tree, starting
// at this node.
- (void)printHierarchy;
#endif
/*** general ***/
// returns the accessible at the specified point.
- (id)accessibilityHitTest:(NSPoint)point;
// whether this element is flagged as ignored.
- (BOOL)accessibilityIsIgnored;
// currently focused UI element (possibly a child accessible)
- (id)accessibilityFocusedUIElement;
/*** attributes ***/
// all supported attributes
- (NSArray*)accessibilityAttributeNames;
// value for given attribute.
- (id)accessibilityAttributeValue:(NSString*)attribute;
// whether a particular attribute can be modified
- (BOOL)accessibilityIsAttributeSettable:(NSString*)attribute;
/*** actions ***/
- (NSArray*)accessibilityActionNames;
- (NSString*)accessibilityActionDescription:(NSString*)action;
- (void)accessibilityPerformAction:(NSString*)action;
@end

View file

@ -0,0 +1,37 @@
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#import <Cocoa/Cocoa.h>
#import "mozAccessible.h"
/* Simple subclasses for things like checkboxes, buttons, etc. */
@interface mozButtonAccessible : mozAccessible
{
}
- (BOOL)hasPopup;
- (void)click;
- (BOOL)isTab;
@end
@interface mozCheckboxAccessible : mozButtonAccessible
// returns one of the constants defined in CheckboxValue
- (int)isChecked;
@end
/* Class for tabs - not individual tabs */
@interface mozTabsAccessible : mozAccessible
{
NSMutableArray* mTabs;
}
-(id)tabs;
@end
/**
* Accessible for a PANE
*/
@interface mozPaneAccessible : mozAccessible
@end

View file

@ -0,0 +1,340 @@
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#import "mozActionElements.h"
#import "MacUtils.h"
#include "Accessible-inl.h"
#include "DocAccessible.h"
#include "XULTabAccessible.h"
#include "nsDeckFrame.h"
#include "nsObjCExceptions.h"
using namespace mozilla::a11y;
enum CheckboxValue {
// these constants correspond to the values in the OS
kUnchecked = 0,
kChecked = 1,
kMixed = 2
};
@implementation mozButtonAccessible
- (NSArray*)accessibilityAttributeNames
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
static NSArray *attributes = nil;
if (!attributes) {
attributes = [[NSArray alloc] initWithObjects:NSAccessibilityParentAttribute, // required
NSAccessibilityRoleAttribute, // required
NSAccessibilityRoleDescriptionAttribute,
NSAccessibilityPositionAttribute, // required
NSAccessibilitySizeAttribute, // required
NSAccessibilityWindowAttribute, // required
NSAccessibilityPositionAttribute, // required
NSAccessibilityTopLevelUIElementAttribute, // required
NSAccessibilityHelpAttribute,
NSAccessibilityEnabledAttribute, // required
NSAccessibilityFocusedAttribute, // required
NSAccessibilityTitleAttribute, // required
NSAccessibilityChildrenAttribute,
NSAccessibilityDescriptionAttribute,
#if DEBUG
@"AXMozDescription",
#endif
nil];
}
return attributes;
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
- (id)accessibilityAttributeValue:(NSString *)attribute
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {
if ([self hasPopup])
return [self children];
return nil;
}
if ([attribute isEqualToString:NSAccessibilityRoleDescriptionAttribute]) {
if ([self isTab])
return utils::LocalizedString(NS_LITERAL_STRING("tab"));
return NSAccessibilityRoleDescription([self role], nil);
}
return [super accessibilityAttributeValue:attribute];
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
- (BOOL)accessibilityIsIgnored
{
return ![self getGeckoAccessible] && ![self getProxyAccessible];
}
- (NSArray*)accessibilityActionNames
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
if ([self isEnabled]) {
if ([self hasPopup])
return [NSArray arrayWithObjects:NSAccessibilityPressAction,
NSAccessibilityShowMenuAction,
nil];
return [NSArray arrayWithObject:NSAccessibilityPressAction];
}
return nil;
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
- (NSString*)accessibilityActionDescription:(NSString*)action
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
if ([action isEqualToString:NSAccessibilityPressAction]) {
if ([self isTab])
return utils::LocalizedString(NS_LITERAL_STRING("switch"));
return @"press button"; // XXX: localize this later?
}
if ([self hasPopup]) {
if ([action isEqualToString:NSAccessibilityShowMenuAction])
return @"show menu";
}
return nil;
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
- (void)accessibilityPerformAction:(NSString*)action
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
if ([self isEnabled] && [action isEqualToString:NSAccessibilityPressAction]) {
// TODO: this should bring up the menu, but currently doesn't.
// once msaa and atk have merged better, they will implement
// the action needed to show the menu.
[self click];
}
NS_OBJC_END_TRY_ABORT_BLOCK;
}
- (void)click
{
// both buttons and checkboxes have only one action. we should really stop using arbitrary
// arrays with actions, and define constants for these actions.
if (AccessibleWrap* accWrap = [self getGeckoAccessible])
accWrap->DoAction(0);
else if (ProxyAccessible* proxy = [self getProxyAccessible])
proxy->DoAction(0);
}
- (BOOL)isTab
{
if (AccessibleWrap* accWrap = [self getGeckoAccessible])
return accWrap->Role() == roles::PAGETAB;
if (ProxyAccessible* proxy = [self getProxyAccessible])
return proxy->Role() == roles::PAGETAB;
return false;
}
- (BOOL)hasPopup
{
if (AccessibleWrap* accWrap = [self getGeckoAccessible])
return accWrap->NativeState() & states::HASPOPUP;
if (ProxyAccessible* proxy = [self getProxyAccessible])
return proxy->NativeState() & states::HASPOPUP;
return false;
}
@end
@implementation mozCheckboxAccessible
- (NSString*)accessibilityActionDescription:(NSString*)action
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
if ([action isEqualToString:NSAccessibilityPressAction]) {
if ([self isChecked] != kUnchecked)
return @"uncheck checkbox"; // XXX: localize this later?
return @"check checkbox"; // XXX: localize this later?
}
return nil;
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
- (int)isChecked
{
uint64_t state = 0;
if (AccessibleWrap* accWrap = [self getGeckoAccessible])
state = accWrap->NativeState();
else if (ProxyAccessible* proxy = [self getProxyAccessible])
state = proxy->NativeState();
// check if we're checked or in a mixed state
if (state & states::CHECKED) {
return (state & states::MIXED) ? kMixed : kChecked;
}
return kUnchecked;
}
- (id)value
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
return [NSNumber numberWithInt:[self isChecked]];
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
@end
@implementation mozTabsAccessible
- (void)dealloc
{
[mTabs release];
[super dealloc];
}
- (NSArray*)accessibilityAttributeNames
{
// standard attributes that are shared and supported by root accessible (AXMain) elements.
static NSMutableArray* attributes = nil;
if (!attributes) {
attributes = [[super accessibilityAttributeNames] mutableCopy];
[attributes addObject:NSAccessibilityContentsAttribute];
[attributes addObject:NSAccessibilityTabsAttribute];
}
return attributes;
}
- (id)accessibilityAttributeValue:(NSString *)attribute
{
if ([attribute isEqualToString:NSAccessibilityContentsAttribute])
return [super children];
if ([attribute isEqualToString:NSAccessibilityTabsAttribute])
return [self tabs];
return [super accessibilityAttributeValue:attribute];
}
/**
* Returns the selected tab (the mozAccessible)
*/
- (id)value
{
mozAccessible* nativeAcc = nil;
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
if (Accessible* accTab = accWrap->GetSelectedItem(0)) {
accTab->GetNativeInterface((void**)&nativeAcc);
}
} else if (ProxyAccessible* proxy = [self getProxyAccessible]) {
if (ProxyAccessible* proxyTab = proxy->GetSelectedItem(0)) {
nativeAcc = GetNativeFromProxy(proxyTab);
}
}
return nativeAcc;
}
/**
* Return the mozAccessibles that are the tabs.
*/
- (id)tabs
{
if (mTabs)
return mTabs;
NSArray* children = [self children];
NSEnumerator* enumerator = [children objectEnumerator];
mTabs = [[NSMutableArray alloc] init];
id obj;
while ((obj = [enumerator nextObject]))
if ([obj isTab])
[mTabs addObject:obj];
return mTabs;
}
- (void)invalidateChildren
{
[super invalidateChildren];
[mTabs release];
mTabs = nil;
}
@end
@implementation mozPaneAccessible
- (NSUInteger)accessibilityArrayAttributeCount:(NSString*)attribute
{
AccessibleWrap* accWrap = [self getGeckoAccessible];
ProxyAccessible* proxy = [self getProxyAccessible];
if (!accWrap && !proxy)
return 0;
// By default this calls -[[mozAccessible children] count].
// Since we don't cache mChildren. This is faster.
if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {
if (accWrap)
return accWrap->ChildCount() ? 1 : 0;
return proxy->ChildrenCount() ? 1 : 0;
}
return [super accessibilityArrayAttributeCount:attribute];
}
- (NSArray*)children
{
if (![self getGeckoAccessible])
return nil;
nsDeckFrame* deckFrame = do_QueryFrame([self getGeckoAccessible]->GetFrame());
nsIFrame* selectedFrame = deckFrame ? deckFrame->GetSelectedBox() : nullptr;
Accessible* selectedAcc = nullptr;
if (selectedFrame) {
nsINode* node = selectedFrame->GetContent();
selectedAcc = [self getGeckoAccessible]->Document()->GetAccessible(node);
}
if (selectedAcc) {
mozAccessible *curNative = GetNativeFromGeckoAccessible(selectedAcc);
if (curNative)
return [NSArray arrayWithObjects:GetObjectOrRepresentedView(curNative), nil];
}
return nil;
}
@end

View file

@ -0,0 +1,31 @@
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#import <Cocoa/Cocoa.h>
#import "mozAccessible.h"
// our protocol that we implement (so cocoa widgets can talk to us)
#import "mozAccessibleProtocol.h"
/*
The root accessible. There is one per window.
Created by the RootAccessibleWrap.
*/
@interface mozRootAccessible : mozAccessible
{
// the mozView that we're representing.
// all outside communication goes through the mozView.
// in reality, it's just piping all calls to us, and we're
// doing its dirty work!
//
// whenever someone asks who we are (e.g., a child asking
// for its parent, or our parent asking for its child), we'll
// respond the mozView. it is absolutely necessary for third-
// party tools that we do this!
//
// /hwaara
id <mozView, mozAccessible> mParallelView; // weak ref
}
@end

View file

@ -0,0 +1,111 @@
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "RootAccessibleWrap.h"
#import "mozDocAccessible.h"
#import "mozView.h"
// This must be included last:
#include "nsObjCExceptions.h"
using namespace mozilla::a11y;
static id <mozAccessible, mozView>
getNativeViewFromRootAccessible(Accessible* aAccessible)
{
RootAccessibleWrap* root =
static_cast<RootAccessibleWrap*>(aAccessible->AsRoot());
id <mozAccessible, mozView> nativeView = nil;
root->GetNativeWidget ((void**)&nativeView);
return nativeView;
}
#pragma mark -
@implementation mozRootAccessible
- (NSArray*)accessibilityAttributeNames
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
// if we're expired, we don't support any attributes.
if (![self getGeckoAccessible])
return [NSArray array];
// standard attributes that are shared and supported by root accessible (AXMain) elements.
static NSMutableArray* attributes = nil;
if (!attributes) {
attributes = [[super accessibilityAttributeNames] mutableCopy];
[attributes addObject:NSAccessibilityMainAttribute];
[attributes addObject:NSAccessibilityMinimizedAttribute];
}
return attributes;
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
- (id)accessibilityAttributeValue:(NSString *)attribute
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
if ([attribute isEqualToString:NSAccessibilityMainAttribute])
return [NSNumber numberWithBool:[[self window] isMainWindow]];
if ([attribute isEqualToString:NSAccessibilityMinimizedAttribute])
return [NSNumber numberWithBool:[[self window] isMiniaturized]];
return [super accessibilityAttributeValue:attribute];
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
// return the AXParent that our parallell NSView tells us about.
- (id)parent
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
if (!mParallelView)
mParallelView = (id<mozView, mozAccessible>)[self representedView];
if (mParallelView)
return [mParallelView accessibilityAttributeValue:NSAccessibilityParentAttribute];
NSAssert(mParallelView, @"we're a root accessible w/o native view?");
return [super parent];
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
- (BOOL)hasRepresentedView
{
return YES;
}
// this will return our parallell NSView. see mozDocAccessible.h
- (id)representedView
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
if (mParallelView)
return (id)mParallelView;
mParallelView = getNativeViewFromRootAccessible ([self getGeckoAccessible]);
NSAssert(mParallelView, @"can't return root accessible's native parallel view.");
return mParallelView;
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
- (BOOL)isRoot
{
return YES;
}
@end

View file

@ -0,0 +1,16 @@
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:expandtab:shiftwidth=2:tabstop=2:
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#import "mozAccessible.h"
@interface mozHeadingAccessible : mozAccessible
@end
@interface mozLinkAccessible : mozAccessible
@end

View file

@ -0,0 +1,141 @@
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:expandtab:shiftwidth=2:tabstop=2:
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#import "mozHTMLAccessible.h"
#import "Accessible-inl.h"
#import "HyperTextAccessible.h"
#import "nsCocoaUtils.h"
using namespace mozilla::a11y;
@implementation mozHeadingAccessible
- (NSString*)title
{
nsAutoString title;
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
mozilla::ErrorResult rv;
// XXX use the flattening API when there are available
// see bug 768298
accWrap->GetContent()->GetTextContent(title, rv);
} else if (ProxyAccessible* proxy = [self getProxyAccessible]) {
proxy->Title(title);
}
return nsCocoaUtils::ToNSString(title);
}
- (id)value
{
uint32_t level = 0;
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
level = accWrap->GetLevelInternal();
} else if (ProxyAccessible* proxy = [self getProxyAccessible]) {
level = proxy->GetLevelInternal();
}
return [NSNumber numberWithInt:level];
}
@end
@interface mozLinkAccessible ()
-(NSURL*)url;
@end
@implementation mozLinkAccessible
- (NSArray*)accessibilityAttributeNames
{
// if we're expired, we don't support any attributes.
if (![self getGeckoAccessible] && ![self getProxyAccessible])
return [NSArray array];
static NSMutableArray* attributes = nil;
if (!attributes) {
attributes = [[super accessibilityAttributeNames] mutableCopy];
[attributes addObject:NSAccessibilityURLAttribute];
}
return attributes;
}
- (id)accessibilityAttributeValue:(NSString *)attribute
{
if ([attribute isEqualToString:NSAccessibilityURLAttribute])
return [self url];
return [super accessibilityAttributeValue:attribute];
}
- (NSArray*)accessibilityActionNames
{
// if we're expired, we don't support any attributes.
if (![self getGeckoAccessible] && ![self getProxyAccessible])
return [NSArray array];
static NSArray* actionNames = nil;
if (!actionNames) {
actionNames = [[NSArray alloc] initWithObjects:NSAccessibilityPressAction,
nil];
}
return actionNames;
}
- (void)accessibilityPerformAction:(NSString*)action
{
AccessibleWrap* accWrap = [self getGeckoAccessible];
ProxyAccessible* proxy = [self getProxyAccessible];
if (!accWrap && !proxy) {
return;
}
if ([action isEqualToString:NSAccessibilityPressAction]) {
if (accWrap) {
accWrap->DoAction(0);
} else if (proxy) {
proxy->DoAction(0);
}
return;
}
[super accessibilityPerformAction:action];
}
- (NSString*)customDescription
{
return @"";
}
- (NSString*)value
{
return @"";
}
- (NSURL*)url
{
nsAutoString value;
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
accWrap->Value(value);
} else if (ProxyAccessible* proxy = [self getProxyAccessible]) {
proxy->Value(value);
}
NSString* urlString = value.IsEmpty() ? nil : nsCocoaUtils::ToNSString(value);
if (!urlString)
return nil;
return [NSURL URLWithString:urlString];
}
@end

View file

@ -0,0 +1,28 @@
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:expandtab:shiftwidth=2:tabstop=2:
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#import "mozAccessible.h"
@interface mozTablePartAccessible : mozAccessible
- (BOOL)isLayoutTablePart;
- (NSString*)role;
@end
@interface mozTableAccessible : mozTablePartAccessible
- (NSArray*)additionalAccessibilityAttributeNames;
- (id)accessibilityAttributeValue:(NSString*)attribute;
@end
@interface mozTableRowAccessible : mozTablePartAccessible
- (NSArray*)additionalAccessibilityAttributeNames;
- (id)accessibilityAttributeValue:(NSString*)attribute;
@end
@interface mozTableCellAccessible : mozTablePartAccessible
- (NSArray*)additionalAccessibilityAttributeNames;
- (id)accessibilityAttributeValue:(NSString*)attribute;
@end

View file

@ -0,0 +1,281 @@
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:expandtab:shiftwidth=2:tabstop=2:
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#import "Accessible-inl.h"
#import "mozTableAccessible.h"
#import "TableAccessible.h"
#import "TableCellAccessible.h"
#import "nsCocoaUtils.h"
using namespace mozilla::a11y;
// convert an array of Gecko accessibles to an NSArray of native accessibles
static inline NSMutableArray*
ConvertToNSArray(nsTArray<Accessible*>& aArray)
{
NSMutableArray* nativeArray = [[NSMutableArray alloc] init];
// iterate through the list, and get each native accessible.
size_t totalCount = aArray.Length();
for (size_t i = 0; i < totalCount; i++) {
Accessible* curAccessible = aArray.ElementAt(i);
mozAccessible* curNative = GetNativeFromGeckoAccessible(curAccessible);
if (curNative)
[nativeArray addObject:GetObjectOrRepresentedView(curNative)];
}
return nativeArray;
}
// convert an array of Gecko proxy accessibles to an NSArray of native accessibles
static inline NSMutableArray*
ConvertToNSArray(nsTArray<ProxyAccessible*>& aArray)
{
NSMutableArray* nativeArray = [[NSMutableArray alloc] init];
// iterate through the list, and get each native accessible.
size_t totalCount = aArray.Length();
for (size_t i = 0; i < totalCount; i++) {
ProxyAccessible* curAccessible = aArray.ElementAt(i);
mozAccessible* curNative = GetNativeFromProxy(curAccessible);
if (curNative)
[nativeArray addObject:GetObjectOrRepresentedView(curNative)];
}
return nativeArray;
}
@implementation mozTablePartAccessible
- (BOOL)isLayoutTablePart;
{
if (Accessible* accWrap = [self getGeckoAccessible]) {
while (accWrap) {
if (accWrap->IsTable()) {
return accWrap->AsTable()->IsProbablyLayoutTable();
}
accWrap = accWrap->Parent();
}
return false;
}
if (ProxyAccessible* proxy = [self getProxyAccessible]) {
while (proxy) {
if (proxy->IsTable()) {
return proxy->TableIsProbablyForLayout();
}
proxy = proxy->Parent();
}
}
return false;
}
- (NSString*)role
{
return [self isLayoutTablePart] ? NSAccessibilityGroupRole : [super role];
}
@end
@implementation mozTableAccessible
- (NSArray*)additionalAccessibilityAttributeNames
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
NSArray* additionalAttributes = [super additionalAccessibilityAttributeNames];
if ([self isLayoutTablePart]) {
return additionalAttributes;
}
static NSArray* tableAttrs = nil;
if (!tableAttrs) {
NSMutableArray* tempArray = [NSMutableArray new];
[tempArray addObject:NSAccessibilityRowCountAttribute];
[tempArray addObject:NSAccessibilityColumnCountAttribute];
[tempArray addObject:NSAccessibilityRowsAttribute];
tableAttrs = [[NSArray alloc] initWithArray:tempArray];
[tempArray release];
}
return [additionalAttributes arrayByAddingObjectsFromArray:tableAttrs];
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
- (id)accessibilityAttributeValue:(NSString*)attribute
{
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
TableAccessible* table = accWrap->AsTable();
if ([attribute isEqualToString:NSAccessibilityRowCountAttribute])
return @(table->RowCount());
if ([attribute isEqualToString:NSAccessibilityColumnCountAttribute])
return @(table->ColCount());
if ([attribute isEqualToString:NSAccessibilityRowsAttribute]) {
// Create a new array with the list of table rows.
NSMutableArray* nativeArray = [[NSMutableArray alloc] init];
uint32_t totalCount = accWrap->ChildCount();
for (uint32_t i = 0; i < totalCount; i++) {
if (accWrap->GetChildAt(i)->IsTableRow()) {
mozAccessible* curNative =
GetNativeFromGeckoAccessible(accWrap->GetChildAt(i));
if (curNative)
[nativeArray addObject:GetObjectOrRepresentedView(curNative)];
}
}
return nativeArray;
}
} else if (ProxyAccessible* proxy = [self getProxyAccessible]) {
if ([attribute isEqualToString:NSAccessibilityRowCountAttribute])
return @(proxy->TableRowCount());
if ([attribute isEqualToString:NSAccessibilityColumnCountAttribute])
return @(proxy->TableColumnCount());
if ([attribute isEqualToString:NSAccessibilityRowsAttribute]) {
// Create a new array with the list of table rows.
NSMutableArray* nativeArray = [[NSMutableArray alloc] init];
uint32_t totalCount = proxy->ChildrenCount();
for (uint32_t i = 0; i < totalCount; i++) {
if (proxy->ChildAt(i)->IsTableRow()) {
mozAccessible* curNative =
GetNativeFromProxy(proxy->ChildAt(i));
if (curNative)
[nativeArray addObject:GetObjectOrRepresentedView(curNative)];
}
}
return nativeArray;
}
}
return [super accessibilityAttributeValue:attribute];
}
@end
@implementation mozTableRowAccessible
- (NSArray*)additionalAccessibilityAttributeNames
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
NSArray* additionalAttributes = [super additionalAccessibilityAttributeNames];
if ([self isLayoutTablePart]) {
return additionalAttributes;
}
static NSArray* tableRowAttrs = nil;
if (!tableRowAttrs) {
NSMutableArray* tempArray = [NSMutableArray new];
[tempArray addObject:NSAccessibilityIndexAttribute];
tableRowAttrs = [[NSArray alloc] initWithArray:tempArray];
[tempArray release];
}
return [additionalAttributes arrayByAddingObjectsFromArray:tableRowAttrs];
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
- (id)accessibilityAttributeValue:(NSString*)attribute
{
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
if ([attribute isEqualToString:NSAccessibilityIndexAttribute]) {
// Count the number of rows before that one to obtain the row index.
uint32_t index = 0;
Accessible* parent = accWrap->Parent();
if (parent) {
for (int32_t i = accWrap->IndexInParent() - 1; i >= 0; i--) {
if (parent->GetChildAt(i)->IsTableRow()) {
index++;
}
}
}
return [NSNumber numberWithUnsignedInteger:index];
}
} else if (ProxyAccessible* proxy = [self getProxyAccessible]) {
if ([attribute isEqualToString:NSAccessibilityIndexAttribute]) {
// Count the number of rows before that one to obtain the row index.
uint32_t index = 0;
ProxyAccessible* parent = proxy->Parent();
if (parent) {
for (int32_t i = proxy->IndexInParent() - 1; i >= 0; i--) {
if (parent->ChildAt(i)->IsTableRow()) {
index++;
}
}
}
return [NSNumber numberWithUnsignedInteger:index];
}
}
return [super accessibilityAttributeValue:attribute];
}
@end
@implementation mozTableCellAccessible
- (NSArray*)additionalAccessibilityAttributeNames
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
NSArray* additionalAttributes = [super additionalAccessibilityAttributeNames];
if ([self isLayoutTablePart]) {
return additionalAttributes;
}
static NSArray* tableCellAttrs = nil;
if (!tableCellAttrs) {
NSMutableArray* tempArray = [NSMutableArray new];
[tempArray addObject:NSAccessibilityRowIndexRangeAttribute];
[tempArray addObject:NSAccessibilityColumnIndexRangeAttribute];
[tempArray addObject:NSAccessibilityRowHeaderUIElementsAttribute];
[tempArray addObject:NSAccessibilityColumnHeaderUIElementsAttribute];
tableCellAttrs = [[NSArray alloc] initWithArray:tempArray];
[tempArray release];
}
return [additionalAttributes arrayByAddingObjectsFromArray:tableCellAttrs];
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
- (id)accessibilityAttributeValue:(NSString*)attribute
{
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
TableCellAccessible* cell = accWrap->AsTableCell();
if ([attribute isEqualToString:NSAccessibilityRowIndexRangeAttribute])
return [NSValue valueWithRange:NSMakeRange(cell->RowIdx(),
cell->RowExtent())];
if ([attribute isEqualToString:NSAccessibilityColumnIndexRangeAttribute])
return [NSValue valueWithRange:NSMakeRange(cell->ColIdx(),
cell->ColExtent())];
if ([attribute isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute]) {
AutoTArray<Accessible*, 10> headerCells;
cell->RowHeaderCells(&headerCells);
return ConvertToNSArray(headerCells);
}
if ([attribute isEqualToString:NSAccessibilityColumnHeaderUIElementsAttribute]) {
AutoTArray<Accessible*, 10> headerCells;
cell->ColHeaderCells(&headerCells);
return ConvertToNSArray(headerCells);
}
} else if (ProxyAccessible* proxy = [self getProxyAccessible]) {
if ([attribute isEqualToString:NSAccessibilityRowIndexRangeAttribute])
return [NSValue valueWithRange:NSMakeRange(proxy->RowIdx(),
proxy->RowExtent())];
if ([attribute isEqualToString:NSAccessibilityColumnIndexRangeAttribute])
return [NSValue valueWithRange:NSMakeRange(proxy->ColIdx(),
proxy->ColExtent())];
if ([attribute isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute]) {
nsTArray<ProxyAccessible*> headerCells;
proxy->RowHeaderCells(&headerCells);
return ConvertToNSArray(headerCells);
}
if ([attribute isEqualToString:NSAccessibilityColumnHeaderUIElementsAttribute]) {
nsTArray<ProxyAccessible*> headerCells;
proxy->ColHeaderCells(&headerCells);
return ConvertToNSArray(headerCells);
}
}
return [super accessibilityAttributeValue:attribute];
}
@end

View file

@ -0,0 +1,17 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#import "mozAccessible.h"
#import "HyperTextAccessible.h"
@interface mozTextAccessible : mozAccessible
{
}
@end
@interface mozTextLeafAccessible : mozAccessible
{
}
@end

View file

@ -0,0 +1,627 @@
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "Accessible-inl.h"
#include "HyperTextAccessible-inl.h"
#include "TextLeafAccessible.h"
#include "nsCocoaUtils.h"
#include "nsObjCExceptions.h"
#import "mozTextAccessible.h"
using namespace mozilla;
using namespace mozilla::a11y;
inline bool
ToNSRange(id aValue, NSRange* aRange)
{
NS_PRECONDITION(aRange, "aRange is nil");
if ([aValue isKindOfClass:[NSValue class]] &&
strcmp([(NSValue*)aValue objCType], @encode(NSRange)) == 0) {
*aRange = [aValue rangeValue];
return true;
}
return false;
}
inline NSString*
ToNSString(id aValue)
{
if ([aValue isKindOfClass:[NSString class]]) {
return aValue;
}
return nil;
}
@interface mozTextAccessible ()
- (NSString*)subrole;
- (NSString*)selectedText;
- (NSValue*)selectedTextRange;
- (NSValue*)visibleCharacterRange;
- (long)textLength;
- (BOOL)isReadOnly;
- (NSNumber*)caretLineNumber;
- (void)setText:(NSString*)newText;
- (NSString*)text;
- (NSString*)stringFromRange:(NSRange*)range;
@end
@implementation mozTextAccessible
- (BOOL)accessibilityIsIgnored
{
return ![self getGeckoAccessible] && ![self getProxyAccessible];
}
- (NSArray*)accessibilityAttributeNames
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
static NSMutableArray* supportedAttributes = nil;
if (!supportedAttributes) {
// text-specific attributes to supplement the standard one
supportedAttributes = [[NSMutableArray alloc] initWithObjects:
NSAccessibilitySelectedTextAttribute, // required
NSAccessibilitySelectedTextRangeAttribute, // required
NSAccessibilityNumberOfCharactersAttribute, // required
NSAccessibilityVisibleCharacterRangeAttribute, // required
NSAccessibilityInsertionPointLineNumberAttribute,
@"AXRequired",
@"AXInvalid",
nil
];
[supportedAttributes addObjectsFromArray:[super accessibilityAttributeNames]];
}
return supportedAttributes;
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
- (id)accessibilityAttributeValue:(NSString*)attribute
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
if ([attribute isEqualToString:NSAccessibilityNumberOfCharactersAttribute])
return [NSNumber numberWithInt:[self textLength]];
if ([attribute isEqualToString:NSAccessibilityInsertionPointLineNumberAttribute])
return [self caretLineNumber];
if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute])
return [self selectedTextRange];
if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute])
return [self selectedText];
if ([attribute isEqualToString:NSAccessibilityTitleAttribute])
return @"";
if ([attribute isEqualToString:NSAccessibilityValueAttribute]) {
// Apple's SpeechSynthesisServer expects AXValue to return an AXStaticText
// object's AXSelectedText attribute. See bug 674612 for details.
// Also if there is no selected text, we return the full text.
// See bug 369710 for details.
if ([[self role] isEqualToString:NSAccessibilityStaticTextRole]) {
NSString* selectedText = [self selectedText];
return (selectedText && [selectedText length]) ? selectedText : [self text];
}
return [self text];
}
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
if ([attribute isEqualToString:@"AXRequired"]) {
return [NSNumber numberWithBool:!!(accWrap->State() & states::REQUIRED)];
}
if ([attribute isEqualToString:@"AXInvalid"]) {
return [NSNumber numberWithBool:!!(accWrap->State() & states::INVALID)];
}
} else if (ProxyAccessible* proxy = [self getProxyAccessible]) {
if ([attribute isEqualToString:@"AXRequired"]) {
return [NSNumber numberWithBool:!!(proxy->State() & states::REQUIRED)];
}
if ([attribute isEqualToString:@"AXInvalid"]) {
return [NSNumber numberWithBool:!!(proxy->State() & states::INVALID)];
}
}
if ([attribute isEqualToString:NSAccessibilityVisibleCharacterRangeAttribute])
return [self visibleCharacterRange];
// let mozAccessible handle all other attributes
return [super accessibilityAttributeValue:attribute];
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
- (NSArray*)accessibilityParameterizedAttributeNames
{
static NSArray* supportedParametrizedAttributes = nil;
// text specific parametrized attributes
if (!supportedParametrizedAttributes) {
supportedParametrizedAttributes = [[NSArray alloc] initWithObjects:
NSAccessibilityStringForRangeParameterizedAttribute,
NSAccessibilityLineForIndexParameterizedAttribute,
NSAccessibilityRangeForLineParameterizedAttribute,
NSAccessibilityAttributedStringForRangeParameterizedAttribute,
NSAccessibilityBoundsForRangeParameterizedAttribute,
#if DEBUG
NSAccessibilityRangeForPositionParameterizedAttribute,
NSAccessibilityRangeForIndexParameterizedAttribute,
NSAccessibilityRTFForRangeParameterizedAttribute,
NSAccessibilityStyleRangeForIndexParameterizedAttribute,
#endif
nil
];
}
return supportedParametrizedAttributes;
}
- (id)accessibilityAttributeValue:(NSString*)attribute forParameter:(id)parameter
{
AccessibleWrap* accWrap = [self getGeckoAccessible];
ProxyAccessible* proxy = [self getProxyAccessible];
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
if (!textAcc && !proxy)
return nil;
if ([attribute isEqualToString:NSAccessibilityStringForRangeParameterizedAttribute]) {
NSRange range;
if (!ToNSRange(parameter, &range)) {
#if DEBUG
NSLog(@"%@: range not set", attribute);
#endif
return @"";
}
return [self stringFromRange:&range];
}
if ([attribute isEqualToString:NSAccessibilityRangeForLineParameterizedAttribute]) {
// XXX: actually get the integer value for the line #
return [NSValue valueWithRange:NSMakeRange(0, [self textLength])];
}
if ([attribute isEqualToString:NSAccessibilityAttributedStringForRangeParameterizedAttribute]) {
NSRange range;
if (!ToNSRange(parameter, &range)) {
#if DEBUG
NSLog(@"%@: range not set", attribute);
#endif
return @"";
}
return [[[NSAttributedString alloc] initWithString:[self stringFromRange:&range]] autorelease];
}
if ([attribute isEqualToString:NSAccessibilityLineForIndexParameterizedAttribute]) {
// XXX: actually return the line #
return [NSNumber numberWithInt:0];
}
if ([attribute isEqualToString:NSAccessibilityBoundsForRangeParameterizedAttribute]) {
NSRange range;
if (!ToNSRange(parameter, &range)) {
#if DEBUG
NSLog(@"%@:no range", attribute);
#endif
return nil;
}
int32_t start = range.location;
int32_t end = start + range.length;
DesktopIntRect bounds;
if (textAcc) {
bounds =
DesktopIntRect::FromUnknownRect(textAcc->TextBounds(start, end));
} else if (proxy) {
bounds =
DesktopIntRect::FromUnknownRect(proxy->TextBounds(start, end));
}
return [NSValue valueWithRect:nsCocoaUtils::GeckoRectToCocoaRect(bounds)];
}
#if DEBUG
NSLog(@"unhandled attribute:%@ forParameter:%@", attribute, parameter);
#endif
return nil;
}
- (BOOL)accessibilityIsAttributeSettable:(NSString*)attribute
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
if ([attribute isEqualToString:NSAccessibilityValueAttribute])
return ![self isReadOnly];
if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute] ||
[attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute] ||
[attribute isEqualToString:NSAccessibilityVisibleCharacterRangeAttribute])
return YES;
return [super accessibilityIsAttributeSettable:attribute];
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO);
}
- (void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
AccessibleWrap* accWrap = [self getGeckoAccessible];
ProxyAccessible* proxy = [self getProxyAccessible];
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
if (!textAcc && !proxy)
return;
if ([attribute isEqualToString:NSAccessibilityValueAttribute]) {
[self setText:ToNSString(value)];
return;
}
if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute]) {
NSString* stringValue = ToNSString(value);
if (!stringValue)
return;
int32_t start = 0, end = 0;
nsString text;
if (textAcc) {
textAcc->SelectionBoundsAt(0, &start, &end);
textAcc->DeleteText(start, end - start);
nsCocoaUtils::GetStringForNSString(stringValue, text);
textAcc->InsertText(text, start);
} else if (proxy) {
nsString data;
proxy->SelectionBoundsAt(0, data, &start, &end);
proxy->DeleteText(start, end - start);
nsCocoaUtils::GetStringForNSString(stringValue, text);
proxy->InsertText(text, start);
}
}
if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) {
NSRange range;
if (!ToNSRange(value, &range))
return;
if (textAcc) {
textAcc->SetSelectionBoundsAt(0, range.location,
range.location + range.length);
} else if (proxy) {
proxy->SetSelectionBoundsAt(0, range.location,
range.location + range.length);
}
return;
}
if ([attribute isEqualToString:NSAccessibilityVisibleCharacterRangeAttribute]) {
NSRange range;
if (!ToNSRange(value, &range))
return;
if (textAcc) {
textAcc->ScrollSubstringTo(range.location, range.location + range.length,
nsIAccessibleScrollType::SCROLL_TYPE_TOP_EDGE);
} else if (proxy) {
proxy->ScrollSubstringTo(range.location, range.location + range.length,
nsIAccessibleScrollType::SCROLL_TYPE_TOP_EDGE);
}
return;
}
[super accessibilitySetValue:value forAttribute:attribute];
NS_OBJC_END_TRY_ABORT_BLOCK;
}
- (NSString*)subrole
{
if(mRole == roles::PASSWORD_TEXT)
return NSAccessibilitySecureTextFieldSubrole;
return nil;
}
#pragma mark -
- (BOOL)isReadOnly
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
if ([[self role] isEqualToString:NSAccessibilityStaticTextRole])
return YES;
AccessibleWrap* accWrap = [self getGeckoAccessible];
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
if (textAcc)
return (accWrap->State() & states::READONLY) == 0;
if (ProxyAccessible* proxy = [self getProxyAccessible])
return (proxy->State() & states::READONLY) == 0;
return NO;
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO);
}
- (NSNumber*)caretLineNumber
{
AccessibleWrap* accWrap = [self getGeckoAccessible];
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
int32_t lineNumber = -1;
if (textAcc) {
lineNumber = textAcc->CaretLineNumber() - 1;
} else if (ProxyAccessible* proxy = [self getProxyAccessible]) {
lineNumber = proxy->CaretLineNumber() - 1;
}
return (lineNumber >= 0) ? [NSNumber numberWithInt:lineNumber] : nil;
}
- (void)setText:(NSString*)aNewString
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
AccessibleWrap* accWrap = [self getGeckoAccessible];
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
nsString text;
nsCocoaUtils::GetStringForNSString(aNewString, text);
if (textAcc) {
textAcc->ReplaceText(text);
} else if (ProxyAccessible* proxy = [self getProxyAccessible]) {
proxy->ReplaceText(text);
}
NS_OBJC_END_TRY_ABORT_BLOCK;
}
- (NSString*)text
{
AccessibleWrap* accWrap = [self getGeckoAccessible];
ProxyAccessible* proxy = [self getProxyAccessible];
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
if (!textAcc && !proxy)
return nil;
// A password text field returns an empty value
if (mRole == roles::PASSWORD_TEXT)
return @"";
nsAutoString text;
if (textAcc) {
textAcc->TextSubstring(0, nsIAccessibleText::TEXT_OFFSET_END_OF_TEXT, text);
} else if (proxy) {
proxy->TextSubstring(0, nsIAccessibleText::TEXT_OFFSET_END_OF_TEXT, text);
}
return nsCocoaUtils::ToNSString(text);
}
- (long)textLength
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
AccessibleWrap* accWrap = [self getGeckoAccessible];
ProxyAccessible* proxy = [self getProxyAccessible];
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
if (!textAcc && !proxy)
return 0;
return textAcc ? textAcc->CharacterCount() : proxy->CharacterCount();
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0);
}
- (long)selectedTextLength
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
AccessibleWrap* accWrap = [self getGeckoAccessible];
ProxyAccessible* proxy = [self getProxyAccessible];
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
if (!textAcc && !proxy)
return 0;
int32_t start = 0, end = 0;
if (textAcc) {
textAcc->SelectionBoundsAt(0, &start, &end);
} else if (proxy) {
nsString data;
proxy->SelectionBoundsAt(0, data, &start, &end);
}
return (end - start);
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(0);
}
- (NSString*)selectedText
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
AccessibleWrap* accWrap = [self getGeckoAccessible];
ProxyAccessible* proxy = [self getProxyAccessible];
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
if (!textAcc && !proxy)
return nil;
int32_t start = 0, end = 0;
nsAutoString selText;
if (textAcc) {
textAcc->SelectionBoundsAt(0, &start, &end);
if (start != end) {
textAcc->TextSubstring(start, end, selText);
}
} else if (proxy) {
proxy->SelectionBoundsAt(0, selText, &start, &end);
}
return nsCocoaUtils::ToNSString(selText);
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
- (NSValue*)selectedTextRange
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
AccessibleWrap* accWrap = [self getGeckoAccessible];
ProxyAccessible* proxy = [self getProxyAccessible];
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
int32_t start = 0;
int32_t end = 0;
int32_t count = 0;
if (textAcc) {
count = textAcc->SelectionCount();
if (count) {
textAcc->SelectionBoundsAt(0, &start, &end);
return [NSValue valueWithRange:NSMakeRange(start, end - start)];
}
start = textAcc->CaretOffset();
return [NSValue valueWithRange:NSMakeRange(start != -1 ? start : 0, 0)];
}
if (proxy) {
count = proxy->SelectionCount();
if (count) {
nsString data;
proxy->SelectionBoundsAt(0, data, &start, &end);
return [NSValue valueWithRange:NSMakeRange(start, end - start)];
}
start = proxy->CaretOffset();
return [NSValue valueWithRange:NSMakeRange(start != -1 ? start : 0, 0)];
}
return [NSValue valueWithRange:NSMakeRange(0, 0)];
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
- (NSValue*)visibleCharacterRange
{
// XXX this won't work with Textarea and such as we actually don't give
// the visible character range.
AccessibleWrap* accWrap = [self getGeckoAccessible];
ProxyAccessible* proxy = [self getProxyAccessible];
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
if (!textAcc && !proxy)
return 0;
return [NSValue valueWithRange:
NSMakeRange(0, textAcc ?
textAcc->CharacterCount() : proxy->CharacterCount())];
}
- (void)valueDidChange
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
NSAccessibilityPostNotification(GetObjectOrRepresentedView(self),
NSAccessibilityValueChangedNotification);
NS_OBJC_END_TRY_ABORT_BLOCK;
}
- (void)selectedTextDidChange
{
NSAccessibilityPostNotification(GetObjectOrRepresentedView(self),
NSAccessibilitySelectedTextChangedNotification);
}
- (NSString*)stringFromRange:(NSRange*)range
{
NS_PRECONDITION(range, "no range");
AccessibleWrap* accWrap = [self getGeckoAccessible];
ProxyAccessible* proxy = [self getProxyAccessible];
HyperTextAccessible* textAcc = accWrap? accWrap->AsHyperText() : nullptr;
if (!textAcc && !proxy)
return nil;
nsAutoString text;
if (textAcc) {
textAcc->TextSubstring(range->location,
range->location + range->length, text);
} else if (proxy) {
proxy->TextSubstring(range->location,
range->location + range->length, text);
}
return nsCocoaUtils::ToNSString(text);
}
@end
@implementation mozTextLeafAccessible
- (NSArray*)accessibilityAttributeNames
{
static NSMutableArray* supportedAttributes = nil;
if (!supportedAttributes) {
supportedAttributes = [[super accessibilityAttributeNames] mutableCopy];
[supportedAttributes removeObject:NSAccessibilityChildrenAttribute];
}
return supportedAttributes;
}
- (id)accessibilityAttributeValue:(NSString*)attribute
{
if ([attribute isEqualToString:NSAccessibilityTitleAttribute])
return @"";
if ([attribute isEqualToString:NSAccessibilityValueAttribute])
return [self text];
return [super accessibilityAttributeValue:attribute];
}
- (NSString*)text
{
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
return nsCocoaUtils::ToNSString(accWrap->AsTextLeaf()->Text());
}
if (ProxyAccessible* proxy = [self getProxyAccessible]) {
nsString text;
proxy->Text(&text);
return nsCocoaUtils::ToNSString(text);
}
return nil;
}
- (long)textLength
{
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
return accWrap->AsTextLeaf()->Text().Length();
}
if (ProxyAccessible* proxy = [self getProxyAccessible]) {
nsString text;
proxy->Text(&text);
return text.Length();
}
return 0;
}
@end

View file

@ -9,6 +9,8 @@ if 'gtk' in toolkit:
DIRS += ['atk']
elif toolkit == 'windows':
DIRS += ['windows']
elif toolkit == 'cocoa':
DIRS += ['mac']
else:
DIRS += ['other']

View file

@ -42,6 +42,10 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
LOCAL_INCLUDES += [
'/accessible/windows/msaa',
]
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
LOCAL_INCLUDES += [
'/accessible/mac',
]
else:
LOCAL_INCLUDES += [
'/accessible/other',

View file

@ -37,6 +37,10 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
'/accessible/windows/ia2',
'/accessible/windows/msaa',
]
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
LOCAL_INCLUDES += [
'/accessible/mac',
]
else:
LOCAL_INCLUDES += [
'/accessible/other',