2006-09-11 15:44:00 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2012-05-21 11:12:37 +00:00
|
|
|
/* 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/. */
|
2006-09-11 15:44:00 +00:00
|
|
|
|
2012-05-27 09:01:40 +00:00
|
|
|
#include "DocAccessible.h"
|
2008-02-22 20:13:17 +00:00
|
|
|
#include "nsObjCExceptions.h"
|
2006-11-15 11:08:14 +00:00
|
|
|
|
2012-04-13 14:17:03 +00:00
|
|
|
#include "Accessible-inl.h"
|
2012-01-12 03:07:35 +00:00
|
|
|
#include "Role.h"
|
|
|
|
|
2006-09-11 15:44:00 +00:00
|
|
|
#import "mozAccessible.h"
|
2006-11-15 11:08:14 +00:00
|
|
|
#import "mozActionElements.h"
|
2012-01-23 22:37:21 +00:00
|
|
|
#import "mozHTMLAccessible.h"
|
2006-11-15 11:08:14 +00:00
|
|
|
#import "mozTextAccessible.h"
|
2006-09-11 15:44:00 +00:00
|
|
|
|
2012-01-12 03:07:35 +00:00
|
|
|
using namespace mozilla::a11y;
|
|
|
|
|
2010-06-11 08:23:18 +00:00
|
|
|
nsAccessibleWrap::
|
2012-05-27 09:01:40 +00:00
|
|
|
nsAccessibleWrap(nsIContent* aContent, DocAccessible* aDoc) :
|
2012-02-07 22:38:54 +00:00
|
|
|
nsAccessible(aContent, aDoc), mNativeObject(nil),
|
2011-12-15 14:47:04 +00:00
|
|
|
mNativeInited(false)
|
2006-09-11 15:44:00 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
nsAccessibleWrap::~nsAccessibleWrap()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2011-12-15 14:47:04 +00:00
|
|
|
mozAccessible*
|
|
|
|
nsAccessibleWrap::GetNativeObject()
|
2006-09-11 15:44:00 +00:00
|
|
|
{
|
2011-12-13 14:17:59 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
2011-12-15 14:47:04 +00:00
|
|
|
|
|
|
|
if (!mNativeInited && !mNativeObject && !IsDefunct() && !AncestorIsFlat())
|
2011-12-13 14:17:59 +00:00
|
|
|
mNativeObject = [[GetNativeType() alloc] initWithAccessible:this];
|
|
|
|
|
2011-12-15 14:47:04 +00:00
|
|
|
mNativeInited = true;
|
|
|
|
|
|
|
|
return mNativeObject;
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
2006-09-11 15:44:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsAccessibleWrap::GetNativeInterface (void **aOutInterface)
|
|
|
|
{
|
2011-12-13 14:17:59 +00:00
|
|
|
NS_ENSURE_ARG_POINTER(aOutInterface);
|
|
|
|
|
2011-12-15 14:47:04 +00:00
|
|
|
*aOutInterface = static_cast<void*>(GetNativeObject());
|
|
|
|
|
|
|
|
return *aOutInterface ? NS_OK : NS_ERROR_FAILURE;
|
2006-09-11 15:44:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// overridden in subclasses to create the right kind of object. by default we create a generic
|
|
|
|
// 'mozAccessible' node.
|
2011-05-17 14:00:30 +00:00
|
|
|
Class
|
2006-09-11 15:44:00 +00:00
|
|
|
nsAccessibleWrap::GetNativeType ()
|
|
|
|
{
|
2008-02-22 20:13:17 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
|
|
|
|
2012-01-12 03:07:35 +00:00
|
|
|
roles::Role role = Role();
|
2006-11-15 11:08:14 +00:00
|
|
|
switch (role) {
|
2012-01-12 03:07:35 +00:00
|
|
|
case roles::PUSHBUTTON:
|
|
|
|
case roles::SPLITBUTTON:
|
|
|
|
case roles::TOGGLE_BUTTON:
|
2006-12-11 09:37:01 +00:00
|
|
|
{
|
|
|
|
// if this button may show a popup, let's make it of the popupbutton type.
|
2012-01-12 03:07:35 +00:00
|
|
|
return HasPopup() ? [mozPopupButtonAccessible class] :
|
|
|
|
[mozButtonAccessible class];
|
2006-12-11 09:37:01 +00:00
|
|
|
}
|
2006-11-15 11:08:14 +00:00
|
|
|
|
2012-01-27 06:14:09 +00:00
|
|
|
case roles::PAGETAB:
|
|
|
|
return [mozButtonAccessible class];
|
|
|
|
|
2012-01-12 03:07:35 +00:00
|
|
|
case roles::CHECKBUTTON:
|
2006-11-15 11:08:14 +00:00
|
|
|
return [mozCheckboxAccessible class];
|
|
|
|
|
2012-01-23 22:37:21 +00:00
|
|
|
case roles::HEADING:
|
|
|
|
return [mozHeadingAccessible class];
|
|
|
|
|
2012-01-27 06:14:09 +00:00
|
|
|
case roles::PAGETABLIST:
|
|
|
|
return [mozTabsAccessible class];
|
|
|
|
|
2012-01-12 03:07:35 +00:00
|
|
|
case roles::ENTRY:
|
|
|
|
case roles::STATICTEXT:
|
|
|
|
case roles::CAPTION:
|
|
|
|
case roles::ACCEL_LABEL:
|
|
|
|
case roles::TEXT_LEAF:
|
2012-04-12 18:02:25 +00:00
|
|
|
case roles::PASSWORD_TEXT:
|
2006-12-18 13:57:37 +00:00
|
|
|
// normal textfield (static or editable)
|
|
|
|
return [mozTextAccessible class];
|
2012-01-27 15:50:04 +00:00
|
|
|
|
|
|
|
case roles::LINK:
|
|
|
|
return [mozLinkAccessible class];
|
|
|
|
|
2012-01-12 03:07:35 +00:00
|
|
|
case roles::COMBOBOX:
|
2006-12-06 13:35:56 +00:00
|
|
|
return [mozPopupButtonAccessible class];
|
|
|
|
|
2006-11-15 11:08:14 +00:00
|
|
|
default:
|
|
|
|
return [mozAccessible class];
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil;
|
2008-02-22 20:13:17 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
2006-09-11 15:44:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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'.
|
2010-06-12 04:04:35 +00:00
|
|
|
void
|
2006-09-11 15:44:00 +00:00
|
|
|
nsAccessibleWrap::Shutdown ()
|
|
|
|
{
|
2011-12-15 14:47:04 +00:00
|
|
|
// this ensure we will not try to re-create the native object.
|
|
|
|
mNativeInited = true;
|
|
|
|
|
|
|
|
// we really intend to access the member directly.
|
2011-12-13 14:17:59 +00:00
|
|
|
if (mNativeObject) {
|
|
|
|
[mNativeObject expire];
|
|
|
|
[mNativeObject release];
|
|
|
|
mNativeObject = nil;
|
2006-09-11 15:44:00 +00:00
|
|
|
}
|
2011-12-15 14:47:04 +00:00
|
|
|
|
2010-06-12 04:04:35 +00:00
|
|
|
nsAccessible::Shutdown();
|
2006-09-11 15:44:00 +00:00
|
|
|
}
|
|
|
|
|
2009-06-18 07:37:38 +00:00
|
|
|
nsresult
|
2010-08-25 02:08:28 +00:00
|
|
|
nsAccessibleWrap::HandleAccEvent(AccEvent* aEvent)
|
2007-07-05 16:02:55 +00:00
|
|
|
{
|
2008-02-22 20:13:17 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2010-01-19 04:23:44 +00:00
|
|
|
nsresult rv = nsAccessible::HandleAccEvent(aEvent);
|
2007-07-05 16:02:55 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2008-06-16 06:16:18 +00:00
|
|
|
return FirePlatformEvent(aEvent);
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2010-08-25 02:08:28 +00:00
|
|
|
nsAccessibleWrap::FirePlatformEvent(AccEvent* aEvent)
|
2008-06-16 06:16:18 +00:00
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2010-01-19 04:23:44 +00:00
|
|
|
PRUint32 eventType = aEvent->GetEventType();
|
2007-07-05 16:02:55 +00:00
|
|
|
|
2012-04-02 17:15:00 +00:00
|
|
|
// ignore everything but focus-changed, value-changed, caret and selection
|
|
|
|
// events for now.
|
2007-07-05 16:02:55 +00:00
|
|
|
if (eventType != nsIAccessibleEvent::EVENT_FOCUS &&
|
2012-04-02 17:15:00 +00:00
|
|
|
eventType != nsIAccessibleEvent::EVENT_VALUE_CHANGE &&
|
|
|
|
eventType != nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED &&
|
|
|
|
eventType != nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED)
|
2007-07-05 16:02:55 +00:00
|
|
|
return NS_OK;
|
|
|
|
|
2010-06-12 04:04:24 +00:00
|
|
|
nsAccessible *accessible = aEvent->GetAccessible();
|
2007-07-05 16:02:55 +00:00
|
|
|
NS_ENSURE_STATE(accessible);
|
|
|
|
|
|
|
|
mozAccessible *nativeAcc = nil;
|
|
|
|
accessible->GetNativeInterface((void**)&nativeAcc);
|
|
|
|
if (!nativeAcc)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
switch (eventType) {
|
|
|
|
case nsIAccessibleEvent::EVENT_FOCUS:
|
|
|
|
[nativeAcc didReceiveFocus];
|
|
|
|
break;
|
|
|
|
case nsIAccessibleEvent::EVENT_VALUE_CHANGE:
|
|
|
|
[nativeAcc valueDidChange];
|
|
|
|
break;
|
2012-04-02 17:15:00 +00:00
|
|
|
case nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED:
|
|
|
|
case nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED:
|
|
|
|
[nativeAcc selectedTextDidChange];
|
|
|
|
break;
|
2007-07-05 16:02:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
2008-02-22 20:13:17 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2007-07-05 16:02:55 +00:00
|
|
|
}
|
|
|
|
|
2009-06-18 07:37:38 +00:00
|
|
|
void
|
|
|
|
nsAccessibleWrap::InvalidateChildren()
|
2006-09-11 15:44:00 +00:00
|
|
|
{
|
2009-06-18 08:14:16 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
2008-02-22 20:13:17 +00:00
|
|
|
|
2011-12-15 14:47:04 +00:00
|
|
|
[GetNativeObject() invalidateChildren];
|
2011-12-13 14:17:59 +00:00
|
|
|
|
2009-06-18 07:37:38 +00:00
|
|
|
nsAccessible::InvalidateChildren();
|
2008-02-22 20:13:17 +00:00
|
|
|
|
2009-06-18 08:14:16 +00:00
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2006-11-15 11:08:14 +00:00
|
|
|
}
|
|
|
|
|
2011-12-22 22:31:06 +00:00
|
|
|
bool
|
|
|
|
nsAccessibleWrap::AppendChild(nsAccessible *aAccessible)
|
|
|
|
{
|
|
|
|
bool appended = nsAccessible::AppendChild(aAccessible);
|
|
|
|
|
|
|
|
if (appended && mNativeObject)
|
|
|
|
[mNativeObject appendChild:aAccessible];
|
|
|
|
|
|
|
|
return appended;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
nsAccessibleWrap::RemoveChild(nsAccessible *aAccessible)
|
|
|
|
{
|
|
|
|
bool removed = nsAccessible::RemoveChild(aAccessible);
|
|
|
|
|
|
|
|
if (removed && mNativeObject)
|
|
|
|
[mNativeObject invalidateChildren];
|
|
|
|
|
|
|
|
return removed;
|
|
|
|
}
|
|
|
|
|
2006-12-01 10:53:52 +00:00
|
|
|
// if we for some reason have no native accessible, we should be skipped over (and traversed)
|
|
|
|
// when fetching all unignored children, etc. when counting unignored children, we will not be counted.
|
2011-09-29 06:19:26 +00:00
|
|
|
bool
|
2006-12-01 10:53:52 +00:00
|
|
|
nsAccessibleWrap::IsIgnored()
|
|
|
|
{
|
2011-12-13 14:17:59 +00:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
|
|
|
|
2011-12-15 14:47:04 +00:00
|
|
|
mozAccessible* nativeObject = GetNativeObject();
|
|
|
|
return (!nativeObject) || [nativeObject accessibilityIsIgnored];
|
2011-12-13 14:17:59 +00:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
|
2006-12-01 10:53:52 +00:00
|
|
|
}
|
|
|
|
|
2006-11-15 11:08:14 +00:00
|
|
|
void
|
2012-04-03 09:54:07 +00:00
|
|
|
nsAccessibleWrap::GetUnignoredChildren(nsTArray<nsAccessible*>* aChildrenArray)
|
2006-11-15 11:08:14 +00:00
|
|
|
{
|
|
|
|
// we're flat; there are no children.
|
2008-10-17 10:10:43 +00:00
|
|
|
if (nsAccUtils::MustPrune(this))
|
2006-11-15 11:08:14 +00:00
|
|
|
return;
|
2010-04-19 13:39:57 +00:00
|
|
|
|
2012-05-25 10:53:45 +00:00
|
|
|
PRUint32 childCount = ChildCount();
|
|
|
|
for (PRUint32 childIdx = 0; childIdx < childCount; childIdx++) {
|
2010-04-19 13:39:57 +00:00
|
|
|
nsAccessibleWrap *childAcc =
|
|
|
|
static_cast<nsAccessibleWrap*>(GetChildAt(childIdx));
|
|
|
|
|
2012-04-03 09:54:07 +00:00
|
|
|
// If element is ignored, then add its children as substitutes.
|
2010-04-19 13:39:57 +00:00
|
|
|
if (childAcc->IsIgnored()) {
|
2012-04-03 09:54:07 +00:00
|
|
|
childAcc->GetUnignoredChildren(aChildrenArray);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
aChildrenArray->AppendElement(childAcc);
|
2006-11-15 11:08:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-02 08:25:29 +00:00
|
|
|
nsAccessible*
|
|
|
|
nsAccessibleWrap::GetUnignoredParent() const
|
2006-11-15 11:08:14 +00:00
|
|
|
{
|
2012-04-02 08:25:29 +00:00
|
|
|
// Go up the chain to find a parent that is not ignored.
|
2011-07-23 08:38:33 +00:00
|
|
|
nsAccessibleWrap* parentWrap = static_cast<nsAccessibleWrap*>(Parent());
|
2012-04-02 08:25:29 +00:00
|
|
|
while (parentWrap && parentWrap->IsIgnored())
|
|
|
|
parentWrap = static_cast<nsAccessibleWrap*>(parentWrap->Parent());
|
2006-11-15 11:08:14 +00:00
|
|
|
|
2012-04-02 08:25:29 +00:00
|
|
|
return parentWrap;
|
2006-11-15 11:08:14 +00:00
|
|
|
}
|
2010-04-27 06:52:03 +00:00
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// nsAccessibleWrap protected
|
|
|
|
|
2011-09-29 06:19:26 +00:00
|
|
|
bool
|
2010-04-27 06:52:03 +00:00
|
|
|
nsAccessibleWrap::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.
|
|
|
|
|
2011-07-23 08:38:33 +00:00
|
|
|
nsAccessible* parent = Parent();
|
2010-04-27 06:52:03 +00:00
|
|
|
while (parent) {
|
|
|
|
if (nsAccUtils::MustPrune(parent))
|
2011-10-17 14:59:28 +00:00
|
|
|
return true;
|
2010-04-27 06:52:03 +00:00
|
|
|
|
2011-07-23 08:38:33 +00:00
|
|
|
parent = parent->Parent();
|
2010-04-27 06:52:03 +00:00
|
|
|
}
|
|
|
|
// no parent was flat
|
2011-10-17 14:59:28 +00:00
|
|
|
return false;
|
2010-04-27 06:52:03 +00:00
|
|
|
}
|