Bug 193802. Implement xp accessibility cache. r=kyle, sr=alecf

This commit is contained in:
aaronl%netscape.com 2003-04-15 08:45:55 +00:00
parent 5b2eb7c2c5
commit 83deafd111
97 changed files with 2983 additions and 2585 deletions

View File

@ -1,2 +1,8 @@
accessibility.dll
accessibility.exp
accessibility.ilk
accessibility.lib
accessibility.pdb
Makefile
module.rc
module.res

View File

@ -21,7 +21,7 @@
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
@ -37,35 +37,34 @@ MODULE_NAME = nsAccessibilityModule
GRE_MODULE = 1
REQUIRES = \
xpcom \
string \
dom \
$(NULL)
xpcom \
string \
dom \
$(NULL)
CPPSRCS = nsAccessibilityFactory.cpp
LOCAL_INCLUDES = -I$(srcdir)/../src
SHARED_LIBRARY_LIBS = \
$(DIST)/lib/$(LIB_PREFIX)accessibility_base_s.$(LIB_SUFFIX) \
$(DIST)/lib/$(LIB_PREFIX)accessibility_html_s.$(LIB_SUFFIX) \
$(DIST)/lib/$(LIB_PREFIX)accessibility_toolkit_s.$(LIB_SUFFIX) \
$(NULL)
$(DIST)/lib/$(LIB_PREFIX)accessibility_base_s.$(LIB_SUFFIX) \
$(DIST)/lib/$(LIB_PREFIX)accessibility_html_s.$(LIB_SUFFIX) \
$(DIST)/lib/$(LIB_PREFIX)accessibility_toolkit_s.$(LIB_SUFFIX) \
$(NULL)
ifdef MOZ_XUL
SHARED_LIBRARY_LIBS += $(DIST)/lib/$(LIB_PREFIX)accessibility_xul_s.$(LIB_SUFFIX)
endif
EXTRA_DSO_LIBS = \
gkconshared_s \
gkgfx \
$(NULL)
gkgfx \
$(NULL)
EXTRA_DSO_LDOPTS = \
$(LIBS_DIR) \
$(EXTRA_DSO_LIBS) \
$(MOZ_COMPONENT_LIBS) \
$(NULL)
$(LIBS_DIR) \
$(EXTRA_DSO_LIBS) \
$(MOZ_COMPONENT_LIBS) \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -42,7 +42,6 @@ XPIDLSRCS = \
nsIAccessibleDocument.idl \
nsIAccessibleEditableText.idl \
nsIAccessibleEventReceiver.idl \
nsIAccessibleEventListener.idl \
nsIAccessibleHyperLink.idl \
nsIAccessibleHyperText.idl \
nsIAccessibleProvider.idl \

View File

@ -18,3 +18,4 @@ ISimpleDOMNode_p.c
ISimpleDOMNode_p.obj
module.rc
module.res
dlldata.c

View File

@ -42,7 +42,8 @@
[scriptable, uuid(46820F9B-3088-4046-AB0F-56FDACDC7A82)]
interface nsIAccessNode : nsISupports
{
[noscript] void init(in nsIAccessibleDocument aAccessibleDocument);
[noscript] void init();
[noscript] void shutdown();
[noscript] readonly attribute voidPtr ownerWindow;
[noscript] readonly attribute voidPtr uniqueID;
};

View File

@ -31,13 +31,18 @@
interface nsIWeakReference;
interface nsIAccessibleEventListener;
interface nsIDocument;
interface nsIPresShell;
interface nsIDOMWindow;
interface nsIAccessNode;
interface nsObjectFrame;
[scriptable, uuid(68D9720A-0984-42b6-A3F5-8237ED925727)]
interface nsIAccessibilityService : nsISupports
{
nsIAccessible createOuterDocAccessible(in nsIDOMNode aNode);
nsIAccessible createRootAccessible(in nsISupports aPresContext);
nsIAccessibleCaret createCaretAccessible(in nsIDOMNode aNode, in nsIAccessibleEventListener aListener);
nsIAccessible createRootAccessible(in nsIPresShell aShell, in nsIDocument aDocument);
nsIAccessibleCaret createCaretAccessible(in nsIDOMNode aNode, in nsIAccessible aRootAccessible);
nsIAccessible createHTML4ButtonAccessible(in nsISupports aFrame);
nsIAccessible createHTMLAreaAccessible(in nsIWeakReference aPresShell, in nsIDOMNode aDOMNode, in nsIAccessible aAccParent);
@ -52,8 +57,7 @@ interface nsIAccessibilityService : nsISupports
nsIAccessible createHTMLImageAccessible(in nsISupports aFrame);
nsIAccessible createHTMLLabelAccessible(in nsISupports aFrame);
nsIAccessible createHTMLListboxAccessible(in nsIDOMNode aNode, in nsISupports aPresShell);
[noscript] nsIAccessible createHTMLNativeWindowAccessible(in nsIDOMNode aDOMNode, in nsIWeakReference aShell, in voidPtr aHWnd);
nsIAccessible createHTMLPluginAccessible(in nsIDOMNode aDOMNode, in nsIWeakReference aShell);
nsIAccessible createHTMLObjectFrameAccessible(in nsObjectFrame aFrame);
nsIAccessible createHTMLRadioButtonAccessible(in nsISupports aFrame);
nsIAccessible createHTMLRadioButtonAccessibleXBL(in nsIDOMNode aNode);
nsIAccessible createHTMLSelectOptionAccessible(in nsIDOMNode aNode, in nsIAccessible aAccParent, in nsISupports aPresShell);
@ -97,7 +101,11 @@ interface nsIAccessibilityService : nsISupports
nsIAccessible createXULTooltipAccessible(in nsIDOMNode aNode);
nsIAccessible getAccessibleFor(in nsIDOMNode aNode);
void Shutdown();
nsIAccessible getAccessibleInWindow(in nsIDOMNode aNode, in nsIDOMWindow aDOMWin);
nsIAccessible getAccessibleInWeakShell(in nsIDOMNode aNode, in nsIWeakReference aPresShell);
nsIAccessible getAccessibleInShell(in nsIDOMNode aNode, in nsIPresShell aPresShell);
[noscript] nsIAccessNode getCachedAccessNode(in nsIDOMNode aNode, in nsIWeakReference aShell);
[noscript] nsIAccessible getCachedAccessible(in nsIDOMNode aNode, in nsIWeakReference aShell);
};

View File

@ -40,7 +40,6 @@ interface nsIAccessible : nsISupports
readonly attribute long accChildCount;
attribute AString accName;
readonly attribute AString accValue;
readonly attribute long accId;
readonly attribute AString accDescription;
readonly attribute AString accKeyboardShortcut;
@ -54,6 +53,7 @@ interface nsIAccessible : nsISupports
readonly attribute nsIAccessible accFocused;
nsIAccessible accGetAt(in long x, in long y);
nsIAccessible getChildAt(in long aChildIndex); // zero-based index
nsIAccessible accNavigateRight();
nsIAccessible accNavigateLeft();
@ -77,11 +77,10 @@ interface nsIAccessible : nsISupports
nsIDOMNode accGetDOMNode();
// Used by Accessible implementation to save data and speed up accessibility tree walking
[noscript] void CacheOptimizations(in nsIAccessible aParent, in PRInt32 aSiblingIndex, in nsIDOMNodeList aSiblingList);
[noscript] void handleEvent(in unsigned long aEvent, in nsIAccessible aTarget, in voidPtr aData);
[noscript] void setAccParent(in nsIAccessible aAccParent);
[noscript] void setAccFirstChild(in nsIAccessible aAccFirstChild);
[noscript] void setAccNextSibling(in nsIAccessible aAccNextSibling);
[noscript] void fireToolkitEvent(in unsigned long aEvent, in nsIAccessible aTarget, in voidPtr aData);
[noscript] void getNativeInterface(out voidPtr aOutAccessible);
// MSAA State flags - used for bitfield. More than 1 allowed.

View File

@ -27,7 +27,9 @@
#include "nsIAccessible.idl"
#include "domstubs.idl"
#include "nsIAccessibleCaret.idl"
interface nsIDocument;
interface nsIAccessNode;
[scriptable, uuid(8781FC88-355F-4439-881F-6504A0A1CEB6)]
interface nsIAccessibleDocument : nsISupports
@ -38,5 +40,7 @@ interface nsIAccessibleDocument : nsISupports
readonly attribute AString docType;
AString getNameSpaceURIForID(in short nameSpaceID);
readonly attribute nsIAccessibleCaret caretAccessible;
[noscript] attribute voidPtr window;
[noscript] readonly attribute voidPtr window;
[noscript] nsIAccessNode getCachedAccessNode(in voidPtr aUniqueID);
[noscript] void cacheAccessNode(in voidPtr aUniqueID, in nsIAccessNode aAccessNode);
};

View File

@ -1,91 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Mozilla browser.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Original Author: Eric D Vaughan (evaughan@netscape.com)
*
* Contributor(s):
*/
#include "nsISupports.idl"
#include "nsIAccessible.idl"
[scriptable, uuid(BEE49E7D-9D06-49bf-8984-1694C697D74F)]
interface nsIAccessibleEventListener : nsISupports
{
// these are set to the values given by MSAA
const unsigned long EVENT_CREATE = 0x8000;
const unsigned long EVENT_DESTROY = 0x8001;
const unsigned long EVENT_SHOW = 0x8002;
const unsigned long EVENT_HIDE = 0x8003;
const unsigned long EVENT_REORDER = 0x8004;
const unsigned long EVENT_FOCUS = 0x8005;
const unsigned long EVENT_STATE_CHANGE = 0x800A;
const unsigned long EVENT_LOCATION_CHANGE = 0x800B;
const unsigned long EVENT_NAME_CHANGE = 0x800C;
const unsigned long EVENT_DESCRIPTIONCHANGE = 0x800D;
const unsigned long EVENT_VALUE_CHANGE = 0x800E;
const unsigned long EVENT_PARENTCHANGE = 0x800F;
const unsigned long EVENT_HELPCHANGE = 0x8010;
const unsigned long EVENT_DEFACTIONCHANGE = 0x8011;
const unsigned long EVENT_ACCELERATORCHANGE = 0x8012;
const unsigned long EVENT_SELECTION = 0x8006;
const unsigned long EVENT_SELECTION_ADD = 0x8007;
const unsigned long EVENT_SELECTION_REMOVE = 0x8008;
const unsigned long EVENT_SELECTION_WITHIN = 0x8009;
const unsigned long EVENT_ALERT = 0x0002;
const unsigned long EVENT_FOREGROUND = 0x0003;
const unsigned long EVENT_MENUSTART = 0x0004;
const unsigned long EVENT_MENUEND = 0x0005;
const unsigned long EVENT_MENUPOPUPSTART = 0x0006;
const unsigned long EVENT_MENUPOPUPEND = 0x0007;
const unsigned long EVENT_CAPTURESTART = 0x0008;
const unsigned long EVENT_CAPTUREEND = 0x0009;
const unsigned long EVENT_MOVESIZESTART = 0x000A;
const unsigned long EVENT_MOVESIZEEND = 0x000B;
const unsigned long EVENT_CONTEXTHELPSTART = 0x000C;
const unsigned long EVENT_CONTEXTHELPEND = 0x000D;
const unsigned long EVENT_DRAGDROPSTART = 0x000E;
const unsigned long EVENT_DRAGDROPEND = 0x000F;
const unsigned long EVENT_DIALOGSTART = 0x0010;
const unsigned long EVENT_DIALOGEND = 0x0011;
const unsigned long EVENT_SCROLLINGSTART = 0x0012;
const unsigned long EVENT_SCROLLINGEND = 0x0013;
const unsigned long EVENT_MINIMIZESTART = 0x0016;
const unsigned long EVENT_MINIMIZEEND = 0x0017;
// the additional events for ATK
const unsigned long EVENT_ATK_PROPERTY_CHANGE = 0x0100;
const unsigned long EVENT_ATK_SELECTION_CHANGE = 0x0101;
const unsigned long EVENT_ATK_TEXT_CHANGE = 0x0102;
const unsigned long EVENT_ATK_TEXT_SELECTION_CHANGE = 0x0103;
const unsigned long EVENT_ATK_TEXT_CARET_MOVE = 0x0104;
const unsigned long EVENT_ATK_VISIBLE_DATA_CHANGE = 0x0105;
const unsigned long EVENT_ATK_TABLE_MODEL_CHANGE = 0x0110;
const unsigned long EVENT_ATK_TABLE_ROW_INSERT = 0x0111;
const unsigned long EVENT_ATK_TABLE_ROW_DELETE = 0x0112;
const unsigned long EVENT_ATK_TABLE_ROW_REORDER = 0x0113;
const unsigned long EVENT_ATK_TABLE_COLUMN_INSERT = 0x0114;
const unsigned long EVENT_ATK_TABLE_COLUMN_DELETE = 0x0115;
const unsigned long EVENT_ATK_TABLE_COLUMN_REORDER = 0x0116;
const unsigned long EVENT_ATK_LINK_SELECTED = 0x0117;
[noscript]
void handleEvent(in unsigned long aEvent, in nsIAccessible aTarget, in voidPtr aData);
};

View File

@ -22,11 +22,68 @@
* Contributor(s):
*/
#include "nsIAccessibleEventListener.idl"
#include "nsISupports.idl"
[scriptable, uuid(AB331E47-4FAA-4a12-9480-9B480DD78B39)]
interface nsIAccessibleEventReceiver : nsISupports
{
void addAccessibleEventListener(in nsIAccessibleEventListener aListener);
void removeAccessibleEventListener();
void addEventListeners();
void removeEventListeners();
// these are set to the values given by MSAA
const unsigned long EVENT_CREATE = 0x8000;
const unsigned long EVENT_DESTROY = 0x8001;
const unsigned long EVENT_SHOW = 0x8002;
const unsigned long EVENT_HIDE = 0x8003;
const unsigned long EVENT_REORDER = 0x8004;
const unsigned long EVENT_FOCUS = 0x8005;
const unsigned long EVENT_STATE_CHANGE = 0x800A;
const unsigned long EVENT_LOCATION_CHANGE = 0x800B;
const unsigned long EVENT_NAME_CHANGE = 0x800C;
const unsigned long EVENT_DESCRIPTIONCHANGE = 0x800D;
const unsigned long EVENT_VALUE_CHANGE = 0x800E;
const unsigned long EVENT_PARENTCHANGE = 0x800F;
const unsigned long EVENT_HELPCHANGE = 0x8010;
const unsigned long EVENT_DEFACTIONCHANGE = 0x8011;
const unsigned long EVENT_ACCELERATORCHANGE = 0x8012;
const unsigned long EVENT_SELECTION = 0x8006;
const unsigned long EVENT_SELECTION_ADD = 0x8007;
const unsigned long EVENT_SELECTION_REMOVE = 0x8008;
const unsigned long EVENT_SELECTION_WITHIN = 0x8009;
const unsigned long EVENT_ALERT = 0x0002;
const unsigned long EVENT_FOREGROUND = 0x0003;
const unsigned long EVENT_MENUSTART = 0x0004;
const unsigned long EVENT_MENUEND = 0x0005;
const unsigned long EVENT_MENUPOPUPSTART = 0x0006;
const unsigned long EVENT_MENUPOPUPEND = 0x0007;
const unsigned long EVENT_CAPTURESTART = 0x0008;
const unsigned long EVENT_CAPTUREEND = 0x0009;
const unsigned long EVENT_MOVESIZESTART = 0x000A;
const unsigned long EVENT_MOVESIZEEND = 0x000B;
const unsigned long EVENT_CONTEXTHELPSTART = 0x000C;
const unsigned long EVENT_CONTEXTHELPEND = 0x000D;
const unsigned long EVENT_DRAGDROPSTART = 0x000E;
const unsigned long EVENT_DRAGDROPEND = 0x000F;
const unsigned long EVENT_DIALOGSTART = 0x0010;
const unsigned long EVENT_DIALOGEND = 0x0011;
const unsigned long EVENT_SCROLLINGSTART = 0x0012;
const unsigned long EVENT_SCROLLINGEND = 0x0013;
const unsigned long EVENT_MINIMIZESTART = 0x0016;
const unsigned long EVENT_MINIMIZEEND = 0x0017;
// the additional events for ATK
const unsigned long EVENT_ATK_PROPERTY_CHANGE = 0x0100;
const unsigned long EVENT_ATK_SELECTION_CHANGE = 0x0101;
const unsigned long EVENT_ATK_TEXT_CHANGE = 0x0102;
const unsigned long EVENT_ATK_TEXT_SELECTION_CHANGE = 0x0103;
const unsigned long EVENT_ATK_TEXT_CARET_MOVE = 0x0104;
const unsigned long EVENT_ATK_VISIBLE_DATA_CHANGE = 0x0105;
const unsigned long EVENT_ATK_TABLE_MODEL_CHANGE = 0x0110;
const unsigned long EVENT_ATK_TABLE_ROW_INSERT = 0x0111;
const unsigned long EVENT_ATK_TABLE_ROW_DELETE = 0x0112;
const unsigned long EVENT_ATK_TABLE_ROW_REORDER = 0x0113;
const unsigned long EVENT_ATK_TABLE_COLUMN_INSERT = 0x0114;
const unsigned long EVENT_ATK_TABLE_COLUMN_DELETE = 0x0115;
const unsigned long EVENT_ATK_TABLE_COLUMN_REORDER = 0x0116;
const unsigned long EVENT_ATK_LINK_SELECTED = 0x0117;
};

View File

@ -0,0 +1 @@
Makefile

View File

@ -51,7 +51,8 @@
// construction
//-----------------------------------------------------
nsAccessNodeWrap::nsAccessNodeWrap(nsIDOMNode *aNode): nsAccessNode(aNode)
nsAccessNodeWrap::nsAccessNodeWrap(nsIDOMNode *aNode, nsIWeakReference* aShell):
nsAccessNode(aNode, aShell)
{
}
@ -62,4 +63,12 @@ nsAccessNodeWrap::~nsAccessNodeWrap()
{
}
void nsAccessNodeWrap::InitAccessibility()
{
nsAccessNode::InitXPAccessibility();
}
void nsAccessNodeWrap::ShutdownAccessibility()
{
nsAccessNode::ShutdownXPAccessibility();
}

View File

@ -48,8 +48,11 @@
class nsAccessNodeWrap : public nsAccessNode
{
public: // construction, destruction
nsAccessNodeWrap(nsIDOMNode *);
nsAccessNodeWrap(nsIDOMNode *aNode, nsIWeakReference* aShell);
virtual ~nsAccessNodeWrap();
static void InitAccessibility();
static void ShutdownAccessibility();
};
#endif

View File

@ -49,3 +49,8 @@ nsDocAccessibleWrap::~nsDocAccessibleWrap()
{
}
NS_IMETHODIMP nsDocAccessibleWrap::FireToolkitEvent(PRUint32 aEvent, nsIAccessible* aAccessible, void* aData)
{
// XXX Bolian fire events from here
return NS_OK;
}

View File

@ -50,6 +50,7 @@ class nsDocAccessibleWrap: public nsDocAccessible
public:
nsDocAccessibleWrap(nsIDOMNode *aNode, nsIWeakReference *aShell);
virtual ~nsDocAccessibleWrap();
NS_IMETHOD FireToolkitEvent(PRUint32 aEvent, nsIAccessible* aAccessible, void* aData);
};
#endif

View File

@ -1 +1,3 @@
accessibility_base_s.lib
accessibility_base_s.pdb
Makefile

View File

@ -1,4 +1,3 @@
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
@ -50,17 +49,19 @@ REQUIRES = content \
$(NULL)
CPPSRCS = \
nsAccessNode.cpp \
nsDocAccessible.cpp \
nsOuterDocAccessible.cpp \
nsAccessibilityAtoms.cpp \
nsAccessibilityService.cpp \
nsAccessible.cpp \
nsAccessibleTreeWalker.cpp \
nsBaseWidgetAccessible.cpp \
nsFormControlAccessible.cpp \
nsHyperTextAccessible.cpp \
nsRootAccessible.cpp \
nsCaretAccessible.cpp \
nsTextAccessible.cpp \
nsAccessNode.cpp \
$(NULL)
EXPORTS = \

View File

@ -7,3 +7,5 @@ en-unix.jar:
en-mac.jar:
locale/en-US/global-platform/accessible.properties

View File

@ -37,11 +37,35 @@
* ***** END LICENSE BLOCK ***** */
#include "nsAccessNode.h"
#include "nsIStringBundle.h"
#include "nsIServiceManager.h"
#include "nsAccessibilityAtoms.h"
#include "nsHashtable.h"
#include "nsIPref.h"
#include "nsIServiceManager.h"
#include "nsIPresShell.h"
#include "nsIPresContext.h"
#include "nsIFrame.h"
/* For documentation of the accessibility architecture,
* see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
*/
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
static NS_DEFINE_CID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
nsIStringBundle *nsAccessNode::gStringBundle = 0;
nsIStringBundle *nsAccessNode::gKeyStringBundle = 0;
nsIDOMNode *nsAccessNode::gLastFocusedNode = 0;
PRBool nsAccessNode::gIsAccessibilityActive = PR_FALSE;
PRBool nsAccessNode::gIsCacheDisabled = PR_FALSE;
#ifdef OLD_HASH
nsSupportsHashtable *nsAccessNode::gGlobalDocAccessibleCache = nsnull;
#else
nsInterfaceHashtable<nsVoidHashKey, nsIAccessNode> *nsAccessNode::gGlobalDocAccessibleCache = nsnull;
#endif
/*
* Class nsAccessNode
@ -50,12 +74,21 @@
//-----------------------------------------------------
// construction
//-----------------------------------------------------
NS_INTERFACE_MAP_BEGIN(nsAccessNode)
NS_INTERFACE_MAP_ENTRY(nsIAccessNode)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
NS_IMPL_ISUPPORTS1(nsAccessNode, nsIAccessNode)
NS_IMPL_ADDREF(nsAccessNode)
NS_IMPL_RELEASE(nsAccessNode)
nsAccessNode::nsAccessNode(nsIDOMNode *aNode):
mDOMNode(aNode), mRootAccessibleDoc(nsnull)
nsAccessNode::nsAccessNode(nsIDOMNode *aNode, nsIWeakReference* aShell):
mDOMNode(aNode), mWeakShell(aShell), mRefCnt(0),
mAccChildCount(eChildCountUninitialized)
{
#ifdef DEBUG
mIsInitialized = PR_FALSE;
#endif
}
//-----------------------------------------------------
@ -63,18 +96,27 @@ nsAccessNode::nsAccessNode(nsIDOMNode *aNode):
//-----------------------------------------------------
nsAccessNode::~nsAccessNode()
{
if (mDOMNode) {
if (mWeakShell) {
Shutdown(); // Otherwise virtual Shutdown() methods could get fired twice
}
}
NS_IMETHODIMP nsAccessNode::Init(nsIAccessibleDocument *aRootAccessibleDoc)
NS_IMETHODIMP nsAccessNode::Init()
{
// XXX aaronl: Temporary approach,
// until we have hash table ready
mRootAccessibleDoc = aRootAccessibleDoc;
// We have to put this here, instead of constructor, otherwise
// we don't have the virtual GetUniqueID() method for the hash key.
// We need that for accessibles that don't have DOM nodes
// Later we can get doc from mDOMNode, and get accessible from that
NS_ASSERTION(!mIsInitialized, "Initialized twice!");
nsCOMPtr<nsIAccessibleDocument> docAccessible(GetDocAccessible());
if (docAccessible) {
void* uniqueID;
GetUniqueID(&uniqueID);
docAccessible->CacheAccessNode(uniqueID, this);
#ifdef DEBUG
mIsInitialized = PR_TRUE;
#endif
}
return NS_OK;
}
@ -82,12 +124,215 @@ NS_IMETHODIMP nsAccessNode::Init(nsIAccessibleDocument *aRootAccessibleDoc)
NS_IMETHODIMP nsAccessNode::Shutdown()
{
mDOMNode = nsnull;
mWeakShell = nsnull;
return NS_OK;
}
NS_IMETHODIMP nsAccessNode::GetUniqueID(void **aUniqueID)
{
*aUniqueID = NS_STATIC_CAST(void*, mDOMNode);
return NS_OK;
}
NS_IMETHODIMP nsAccessNode::GetOwnerWindow(void **aWindow)
{
NS_ASSERTION(mRootAccessibleDoc, "No root accessible pointer back, Init() not called.");
return mRootAccessibleDoc->GetWindow(aWindow);
nsCOMPtr<nsIAccessibleDocument> docAccessible(GetDocAccessible());
NS_ASSERTION(docAccessible, "No root accessible pointer back, Init() not called.");
return docAccessible->GetWindow(aWindow);
}
void nsAccessNode::InitXPAccessibility()
{
if (gIsAccessibilityActive) {
return;
}
nsCOMPtr<nsIStringBundleService> stringBundleService(do_GetService(kStringBundleServiceCID));
if (stringBundleService) {
// Static variables are released in ShutdownAllXPAccessibility();
stringBundleService->CreateBundle(ACCESSIBLE_BUNDLE_URL,
&gStringBundle);
NS_IF_ADDREF(gStringBundle);
stringBundleService->CreateBundle(PLATFORM_KEYS_BUNDLE_URL,
&gKeyStringBundle);
NS_IF_ADDREF(gKeyStringBundle);
}
nsAccessibilityAtoms::AddRefAtoms();
#ifdef OLD_HASH
gGlobalDocAccessibleCache = new nsSupportsHashtable(4);
#else
gGlobalDocAccessibleCache = new nsInterfaceHashtable<nsVoidHashKey, nsIAccessNode>;
gGlobalDocAccessibleCache->Init(4); // Initialize for 4 entries
#endif
nsCOMPtr<nsIPref> prefService(do_GetService(kPrefCID));
if (prefService) {
prefService->GetBoolPref("accessibility.disablecache", &gIsCacheDisabled);
}
gIsAccessibilityActive = PR_TRUE;
}
void nsAccessNode::ShutdownXPAccessibility()
{
// Called by nsAccessibilityService::Shutdown()
// which happens when xpcom is shutting down
// at exit of program
if (!gIsAccessibilityActive) {
return;
}
NS_IF_RELEASE(gStringBundle);
NS_IF_RELEASE(gKeyStringBundle);
NS_IF_RELEASE(gLastFocusedNode);
ClearCache(gGlobalDocAccessibleCache);
delete gGlobalDocAccessibleCache;
gGlobalDocAccessibleCache = nsnull;
gIsAccessibilityActive = PR_FALSE;
}
already_AddRefed<nsIPresShell> nsAccessNode::GetPresShell()
{
nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell));
if (!presShell) {
if (mWeakShell) {
// If our pres shell has died, but we're still holding onto
// a weak reference, our accessibles are no longer relevant
// and should be shut down
Shutdown();
}
return nsnull;
}
nsIPresShell *resultShell = presShell;
NS_IF_ADDREF(resultShell);
return resultShell;
}
already_AddRefed<nsIPresContext> nsAccessNode::GetPresContext()
{
nsCOMPtr<nsIPresShell> presShell(GetPresShell());
if (!presShell) {
return nsnull;
}
nsIPresContext *presContext;
presShell->GetPresContext(&presContext); // Addref'd
return presContext;
}
already_AddRefed<nsIAccessibleDocument> nsAccessNode::GetDocAccessible()
{
nsIAccessibleDocument *docAccessible;
GetDocAccessibleFor(mWeakShell, &docAccessible); // Addref'd
return docAccessible;
}
nsIFrame* nsAccessNode::GetFrame()
{
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mWeakShell));
if (!shell)
return nsnull;
nsIFrame* frame = nsnull;
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
shell->GetPrimaryFrameFor(content, &frame);
return frame;
}
/***************** Hashtable of nsIAccessNode's *****************/
#ifdef OLD_HASH
void nsAccessNode::GetDocAccessibleFor(nsIWeakReference *aPresShell,
nsIAccessibleDocument **aDocAccessible)
{
*aDocAccessible = nsnull;
NS_ASSERTION(gGlobalDocAccessibleCache, "Global doc cache does not exist");
nsVoidKey key(NS_STATIC_CAST(void*, aPresShell));
nsCOMPtr<nsIAccessNode> accessNode = NS_STATIC_CAST(nsIAccessNode*, gGlobalDocAccessibleCache->Get(&key));
nsCOMPtr<nsIAccessibleDocument> accDoc(do_QueryInterface(accessNode));
*aDocAccessible = accDoc; // already addrefed
}
void nsAccessNode::PutCacheEntry(nsSupportsHashtable *aCache, void* aUniqueID,
nsIAccessNode *aAccessNode)
{
nsVoidKey key(aUniqueID);
#ifdef DEBUG
if (aCache->Exists(&key)) {
NS_ASSERTION(PR_FALSE, "This cache entry shouldn't exist already");
nsCOMPtr<nsIAccessNode> oldAccessNode;
GetCacheEntry(aCache, aUniqueID, getter_AddRefs(oldAccessNode));
}
#endif
aCache->Put(&key, aAccessNode);
}
void nsAccessNode::GetCacheEntry(nsSupportsHashtable *aCache, void* aUniqueID,
nsIAccessNode **aAccessNode)
{
nsVoidKey key(aUniqueID);
*aAccessNode = NS_STATIC_CAST(nsIAccessNode*, aCache->Get(&key)); // AddRefs for us
}
PRIntn PR_CALLBACK nsAccessNode::ClearCacheEntry(nsHashKey *aKey, void *aAccessNode,
void* aClosure)
{
nsIAccessNode* accessNode = NS_STATIC_CAST(nsIAccessNode*, aAccessNode);
accessNode->Shutdown();
return PL_DHASH_NEXT;
}
void nsAccessNode::ClearCache(nsSupportsHashtable *aCache)
{
aCache->Enumerate(ClearCacheEntry);
}
#else
void nsAccessNode::GetDocAccessibleFor(nsIWeakReference *aPresShell,
nsIAccessibleDocument **aDocAccessible)
{
*aDocAccessible = nsnull;
NS_ASSERTION(gGlobalDocAccessibleCache, "Global doc cache does not exist");
nsCOMPtr<nsIAccessNode> accessNode;
gGlobalDocAccessibleCache->Get(NS_STATIC_CAST(void*, aPresShell), getter_AddRefs(accessNode));
if (accessNode) {
accessNode->QueryInterface(NS_GET_IID(nsIAccessibleDocument), (void**)aDocAccessible); // addrefs
}
}
void nsAccessNode::PutCacheEntry(nsInterfaceHashtable<nsVoidHashKey, nsIAccessNode> *aCache,
void* aUniqueID,
nsIAccessNode *aAccessNode)
{
aCache->Put(aUniqueID, aAccessNode);
}
void nsAccessNode::GetCacheEntry(nsInterfaceHashtable<nsVoidHashKey, nsIAccessNode> *aCache,
void* aUniqueID,
nsIAccessNode **aAccessNode)
{
aCache->Get(aUniqueID, aAccessNode); // AddRefs for us
}
PLDHashOperator ClearCacheEntry(void *const& aKey, nsCOMPtr<nsIAccessNode> aAccessNode, void* aUserArg)
{
aAccessNode->Shutdown();
return PL_DHASH_REMOVE;
}
void nsAccessNode::ClearCache(nsInterfaceHashtable<nsVoidHashKey, nsIAccessNode> *aCache)
{
//aCache->EnumerateEntries(ClearCacheEntry, nsnull);
aCache->EnumerateRead(ClearCacheEntry, nsnull);
aCache->Clear();
}
#endif

View File

@ -46,21 +46,127 @@
#include "nsCOMPtr.h"
#include "nsIAccessNode.h"
#include "nsIDOMNode.h"
#include "nsIStringBundle.h"
#include "nsWeakReference.h"
#define OLD_HASH 1
#ifdef OLD_HASH
class nsSupportsHashtable;
class nsHashKey;
#include "nsHashtable.h"
#else
#include "nsInterfaceHashtable.h"
#include "pldhash.h"
#endif
class nsIPresShell;
class nsIPresContext;
class nsIAccessibleDocument;
class nsIFrame;
class nsIDOMNodeList;
enum { eChildCountUninitialized = 0xffff };
enum { eSiblingsUninitialized = -1, eSiblingsWalkNormalDOM = -2};
#define ACCESSIBLE_BUNDLE_URL "chrome://global-platform/locale/accessible.properties"
#define PLATFORM_KEYS_BUNDLE_URL "chrome://global-platform/locale/platformKeys.properties"
#ifndef OLD_HASH
/* hashkey wrapper using void* KeyType
*
* @see nsTHashtable::EntryType for specification
*/
class NS_COM nsVoidHashKey : public PLDHashEntryHdr
{
public: typedef void* voidPointer;
typedef const voidPointer& KeyType;
typedef const voidPointer* KeyTypePointer;
const voidPointer mValue;
public:
nsVoidHashKey(KeyTypePointer aKey) : mValue(*aKey) { }
nsVoidHashKey(const nsVoidHashKey& toCopy) : mValue(toCopy.mValue) { }
~nsVoidHashKey() { }
KeyType GetKey() const { return mValue; }
KeyTypePointer GetKeyPointer() const { return &mValue; }
PRBool KeyEquals(KeyTypePointer aKey) const { return *aKey == mValue; }
static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
static PLDHashNumber HashKey(KeyTypePointer aKey) { return NS_PTR_TO_INT32(*aKey) >> 2; }
static PRBool AllowMemMove() { return PR_TRUE; }
};
#endif
class nsAccessNode: public nsIAccessNode
{
public: // construction, destruction
nsAccessNode(nsIDOMNode *);
nsAccessNode(nsIDOMNode *, nsIWeakReference* aShell);
virtual ~nsAccessNode();
NS_DECL_ISUPPORTS
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
NS_IMETHOD_(nsrefcnt) AddRef(void);
NS_IMETHOD_(nsrefcnt) Release(void);
NS_DECL_NSIACCESSNODE
protected:
nsCOMPtr<nsIDOMNode> mDOMNode;
static void InitXPAccessibility();
static void ShutdownXPAccessibility();
// XXX aaronl: we should be able to remove this once we have hash table
nsIAccessibleDocument *mRootAccessibleDoc;
// Static methods for handling per-document cache
#ifdef OLD_HASH
static void PutCacheEntry(nsSupportsHashtable *aCache,
void* aUniqueID, nsIAccessNode *aAccessNode);
static void GetCacheEntry(nsSupportsHashtable *aCache, void* aUniqueID,
nsIAccessNode **aAccessNode);
static void ClearCache(nsSupportsHashtable *aCache);
static PRIntn PR_CALLBACK ClearCacheEntry(nsHashKey *aKey, void *aData,
void* aClosure);
#else
static void PutCacheEntry(nsInterfaceHashtable<nsVoidHashKey, nsIAccessNode> *aCache,
void* aUniqueID, nsIAccessNode *aAccessNode);
static void GetCacheEntry(nsInterfaceHashtable<nsVoidHashKey, nsIAccessNode> *aCache, void* aUniqueID,
nsIAccessNode **aAccessNode);
static void ClearCache(nsInterfaceHashtable<nsVoidHashKey, nsIAccessNode> *aCache);
static PLDHashOperator PR_CALLBACK ClearCacheEntry(void *const& aKey, nsCOMPtr<nsIAccessNode> aAccessNode, void* aUserArg);
#endif
// Static cache methods for global document cache
static void GetDocAccessibleFor(nsIWeakReference *aPresShell,
nsIAccessibleDocument **aDocAccessible);
protected:
already_AddRefed<nsIPresShell> GetPresShell();
already_AddRefed<nsIPresContext> GetPresContext();
already_AddRefed<nsIAccessibleDocument> GetDocAccessible();
nsIFrame* GetFrame();
nsCOMPtr<nsIDOMNode> mDOMNode;
nsCOMPtr<nsIWeakReference> mWeakShell;
PRInt16 mRefCnt;
PRUint16 mAccChildCount;
NS_DECL_OWNINGTHREAD
#ifdef DEBUG
PRBool mIsInitialized;
#endif
// Static data, we do our own refcounting for our static data
static nsIStringBundle *gStringBundle;
static nsIStringBundle *gKeyStringBundle;
static nsIDOMNode *gLastFocusedNode;
static PRBool gIsAccessibilityActive;
static PRBool gIsCacheDisabled;
#ifdef OLD_HASH
static nsSupportsHashtable *gGlobalDocAccessibleCache;
#else
static nsInterfaceHashtable<nsVoidHashKey, nsIAccessNode> *gGlobalDocAccessibleCache;
#endif
};
#endif

View File

@ -0,0 +1,62 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Original Author: Aaron Leventhal (aaronl@netscape.com)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/******
This file contains the list of all accessibility nsIAtoms and their values
It is designed to be used as inline input to nsAccessibilityAtoms.cpp *only*
through the magic of C preprocessing.
All entires must be enclosed in the macro ACCESSIBILITY_ATOM which will have cruel
and unusual things done to it
It is recommended (but not strictly necessary) to keep all entries
in alphabetical order
The first argument to ACCESSIBILITY_ATOM is the C++ identifier of the atom
The second argument is the string value of the atom
******/
// Alphabetical list of frame types
ACCESSIBILITY_ATOM(blockFrame, "BlockFrame")
ACCESSIBILITY_ATOM(inlineFrame, "InlineFrame")
ACCESSIBILITY_ATOM(objectFrame, "ObjectFrame")
ACCESSIBILITY_ATOM(textFrame, "TextFrame")

View File

@ -0,0 +1,58 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Original Author: Aaron Leventhal (aaronl@netscape.com)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsAccessibilityAtoms.h"
#include "nsStaticAtom.h"
#include "nsMemory.h"
// define storage for all atoms
#define ACCESSIBILITY_ATOM(_name, _value) nsIAtom* nsAccessibilityAtoms::_name;
#include "nsAccessibilityAtomList.h"
#undef ACCESSIBILITY_ATOM
static const nsStaticAtom atomInfo[] = {
#define ACCESSIBILITY_ATOM(name_, value_) { value_, &nsAccessibilityAtoms::name_ },
#include "nsAccessibilityAtomList.h"
#undef ACCESSIBILITY_ATOM
};
void nsAccessibilityAtoms::AddRefAtoms()
{
NS_RegisterStaticAtoms(atomInfo, NS_ARRAY_LENGTH(atomInfo));
}

View File

@ -20,7 +20,6 @@
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* John Gaunt (jgaunt@netscape.com)
*
*
* Alternatively, the contents of this file may be used under the terms of
@ -36,26 +35,35 @@
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsAccessibilityAtoms_h___
#define nsAccessibilityAtoms_h___
#include "nsAccessibleWrap.h"
#include "nsIAtom.h"
/**
* This class is used to wrap the window for the plugin. It's only child
* is a shim class that will allow the platform specific layer of our
* accessibility support to get the IAccessible from the plugin itself
* (via the windows call to get he accessible by window).
*/
class nsHTMLPluginAccessible : public nsAccessibleWrap
{
* This class wraps up the creation (and destruction) of the standard
* set of atoms used in the accessibility module. These objects
* are created when the are needed by accessibility is being used and they
* are destroyed when the last nsRootAccessible is destroyed via
* nsRootAccessible::ShutdownAll()
*/
class nsAccessibilityAtoms {
public:
nsHTMLPluginAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell);
NS_IMETHOD GetAccFirstChild(nsIAccessible **_retval);
NS_IMETHOD GetAccLastChild(nsIAccessible **_retval);
NS_IMETHOD GetAccChildCount(PRInt32 *_retval);
NS_IMETHOD GetAccRole(PRUint32 *_retval);
protected:
nsCOMPtr<nsIAccessibilityService> mAccService;
static void AddRefAtoms();
static void ReleaseAtoms();
/* Declare all atoms
The atom names and values are stored in nsAccessibilityAtomList.h and
are brought to you by the magic of C preprocessing
Add new atoms to nsAccessibilityAtomList and all support logic will be auto-generated
*/
#define ACCESSIBILITY_ATOM(_name, _value) static nsIAtom* _name;
#include "nsAccessibilityAtomList.h"
#undef ACCESSIBILITY_ATOM
};
#endif /* nsLayoutAtoms_h___ */

View File

@ -41,19 +41,16 @@
// NOTE: alphabetically ordered
#include "nsAccessibilityService.h"
#include "nsCOMPtr.h"
#include "nsHTMLAreaAccessible.h"
#include "nsHTMLFormControlAccessible.h"
#include "nsHTMLImageAccessible.h"
#include "nsHTMLLinkAccessible.h"
#include "nsHTMLPluginAccessible.h"
#include "nsHTMLSelectAccessible.h"
#include "nsHTMLTableAccessible.h"
#include "nsHTMLTextAccessible.h"
#include "nsIAccessibilityService.h"
#include "nsIAccessibleProvider.h"
#include "nsIContent.h"
#include "nsIDocShellTreeItem.h"
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
#include "nsIDOMHTMLAreaElement.h"
@ -71,9 +68,7 @@
#include "nsIPresContext.h"
#include "nsIPresShell.h"
#include "nsITextContent.h"
#include "nsLayoutAtoms.h"
#include "nsObjectFrame.h"
#include "nsRootAccessible.h"
#include "nsString.h"
#include "nsTextFragment.h"
#ifdef MOZ_XUL
@ -88,6 +83,10 @@
#include "nsRootAccessibleWrap.h"
#include "nsCaretAccessible.h"
#include "nsIAccessibleCaret.h"
#include "nsAccessibilityAtoms.h"
#include "nsIObserverService.h"
#include "nsIWebNavigation.h"
#include "nsIDOMWindow.h"
// For native window support for object/embed/applet tags
#ifdef XP_WIN
@ -100,20 +99,43 @@
#include "nsOuterDocAccessible.h"
/**
* nsAccessibility Service
* nsAccessibilityService
*/
nsAccessibilityService::nsAccessibilityService():mIsActive(PR_TRUE)
nsAccessibilityService::nsAccessibilityService()
{
nsLayoutAtoms::AddRefAtoms();
nsCOMPtr<nsIObserverService> observerService =
do_GetService("@mozilla.org/observer-service;1");
if (!observerService)
return;
observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE);
nsAccessNodeWrap::InitAccessibility();
}
nsAccessibilityService::~nsAccessibilityService()
{
Shutdown();
nsAccessNodeWrap::ShutdownAccessibility();
}
NS_IMPL_THREADSAFE_ISUPPORTS1(nsAccessibilityService, nsIAccessibilityService);
NS_IMPL_THREADSAFE_ISUPPORTS2(nsAccessibilityService, nsIAccessibilityService, nsIObserver);
// nsIObserver
NS_IMETHODIMP
nsAccessibilityService::Observe(nsISupports *aSubject, const char *aTopic,
const PRUnichar *aData)
{
if (!nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
nsCOMPtr<nsIObserverService> observerService =
do_GetService("@mozilla.org/observer-service;1");
if (observerService) {
observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
}
nsAccessNodeWrap::ShutdownAccessibility();
}
return NS_OK;
}
nsresult
nsAccessibilityService::GetInfo(nsISupports* aFrame, nsIFrame** aRealFrame, nsIWeakReference** aShell, nsIDOMNode** aNode)
@ -148,68 +170,9 @@ nsAccessibilityService::GetInfo(nsISupports* aFrame, nsIFrame** aRealFrame, nsIW
return NS_OK;
}
void nsAccessibilityService::GetOwnerFor(nsIPresShell *aPresShell,
nsIPresShell **aOwnerShell,
nsIContent **aOwnerContent)
{
*aOwnerShell = nsnull;
*aOwnerContent = nsnull;
nsCOMPtr<nsIPresContext> presContext;
aPresShell->GetPresContext(getter_AddRefs(presContext));
if (!presContext)
return;
nsCOMPtr<nsIDocument> doc;
aPresShell->GetDocument(getter_AddRefs(doc));
if (!doc)
return;
nsCOMPtr<nsISupports> pcContainer;
presContext->GetContainer(getter_AddRefs(pcContainer));
if (!pcContainer)
return;
nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(pcContainer));
if (!treeItem)
return;
// Get Parent Doc
nsCOMPtr<nsIDocShellTreeItem> treeItemParent;
treeItem->GetParent(getter_AddRefs(treeItemParent));
if (!treeItemParent)
return;
nsCOMPtr<nsIDocShell> parentDS(do_QueryInterface(treeItemParent));
if (!parentDS)
return;
nsCOMPtr<nsIPresShell> parentPresShell;
parentDS->GetPresShell(getter_AddRefs(parentPresShell));
if (!parentPresShell)
return;
nsCOMPtr<nsIDocument> parentDoc;
parentPresShell->GetDocument(getter_AddRefs(parentDoc));
if (!parentDoc)
return;
parentDoc->FindContentForSubDocument(doc, aOwnerContent);
if (*aOwnerContent) {
*aOwnerShell = parentPresShell;
NS_ADDREF(*aOwnerShell);
}
else {
NS_WARNING("Cannot find content for sub document");
}
}
nsresult
nsAccessibilityService::GetShellFromNode(nsIDOMNode *aNode, nsIWeakReference **aWeakShell)
{
nsCOMPtr<nsIDOMDocument> domDoc;
{ nsCOMPtr<nsIDOMDocument> domDoc;
aNode->GetOwnerDocument(getter_AddRefs(domDoc));
nsCOMPtr<nsIDocument> doc(do_QueryInterface(domDoc));
if (!doc)
@ -233,21 +196,13 @@ nsAccessibilityService::GetShellFromNode(nsIDOMNode *aNode, nsIWeakReference **a
* nsIAccessibilityService methods:
*/
NS_IMETHODIMP nsAccessibilityService::Shutdown()
{
if (mIsActive) {
mIsActive = PR_FALSE;
}
return NS_OK;
}
NS_IMETHODIMP
nsAccessibilityService::CreateOuterDocAccessible(nsIDOMNode* aDOMNode, nsIAccessible **_retval)
nsAccessibilityService::CreateOuterDocAccessible(nsIDOMNode* aDOMNode,
nsIAccessible **aOuterDocAccessible)
{
NS_ENSURE_ARG_POINTER(aDOMNode);
*_retval = nsnull;
*aOuterDocAccessible = nsnull;
nsCOMPtr<nsIContent> content(do_QueryInterface(aDOMNode));
if (!content)
@ -280,15 +235,15 @@ nsAccessibilityService::CreateOuterDocAccessible(nsIDOMNode* aDOMNode, nsIAccess
sub_doc->GetShellAt(0, getter_AddRefs(innerPresShell));
if (innerPresShell) {
nsCOMPtr<nsIWeakReference> innerWeakShell =
do_GetWeakReference(innerPresShell);
// In these variable names, "outer" relates to the nsOuterDocAccessible
// as opposed to the nsDocAccessibleWrap which is "inner".
// The outer node is a <browser> or <iframe> tag, whereas the inner node
// corresponds to the inner document root.
nsDocAccessibleWrap *innerDocAccessible =
new nsDocAccessibleWrap(innerNode, innerWeakShell);
// Get innerDocAccessible from cache or create it and store it in cache
nsCOMPtr<nsIAccessible> innerDocAccessible;
GetAccessibleInShell(innerNode, innerPresShell,
getter_AddRefs(innerDocAccessible));
if (innerDocAccessible) {
nsOuterDocAccessible *outerDocAccessible =
@ -296,13 +251,12 @@ nsAccessibilityService::CreateOuterDocAccessible(nsIDOMNode* aDOMNode, nsIAccess
outerWeakShell);
if (outerDocAccessible) {
innerDocAccessible->CacheOptimizations(outerDocAccessible, -1, nsnull); // Save parent
*_retval = outerDocAccessible;
NS_ADDREF(*_retval);
// Saving of parent is now done in innerDocAccessible Init()
// innerDocAccessible->SetAccParent(outerDocAccessible); // Save parent
NS_ADDREF(*aOuterDocAccessible = outerDocAccessible);
return NS_OK;
}
// don't leak the innerRoot
delete innerDocAccessible;
}
}
}
@ -312,67 +266,55 @@ nsAccessibilityService::CreateOuterDocAccessible(nsIDOMNode* aDOMNode, nsIAccess
}
NS_IMETHODIMP
nsAccessibilityService::CreateRootAccessible(nsISupports* aPresContext, nsIAccessible **_retval)
nsAccessibilityService::CreateRootAccessible(nsIPresShell *aShell,
nsIDocument* aDocument,
nsIAccessible **aRootAcc)
{
static PRBool alreadyHere = PR_FALSE;
*aRootAcc = nsnull;
*_retval = nsnull;
nsCOMPtr<nsIDOMNode> rootNode(do_QueryInterface(aDocument));
NS_ENSURE_TRUE(rootNode, NS_ERROR_FAILURE);
if (alreadyHere) {
NS_WARNING("Infinite loop headed off in CreateRootAccessible");
return NS_ERROR_FAILURE;
nsCOMPtr<nsIDocument> parentDoc;
aDocument->GetParentDocument(getter_AddRefs(parentDoc));
nsCOMPtr<nsIPresShell> presShell(aShell);
if (!presShell) {
aDocument->GetShellAt(0, getter_AddRefs(presShell));
}
nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(presShell));
nsCOMPtr<nsIPresContext> presContext(do_QueryInterface(aPresContext));
NS_ASSERTION(presContext,"Error non prescontext passed to accessible factory!!!");
nsCOMPtr<nsIPresShell> presShell;
presContext->GetShell(getter_AddRefs(presShell));
NS_ASSERTION(presShell,"Error no presshell!!");
nsCOMPtr<nsISupports> pcContainer;
presContext->GetContainer(getter_AddRefs(pcContainer));
NS_ASSERTION(pcContainer,"Error no container for pres context!!!");
nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(pcContainer));
NS_ASSERTION(treeItem,"Error no tree item for pres context container!!!");
NS_ENSURE_TRUE(treeItem, NS_ERROR_FAILURE);
nsCOMPtr<nsIDocShellTreeItem> treeItemParent;
treeItem->GetParent(getter_AddRefs(treeItemParent));
nsCOMPtr<nsIDocument> document;
nsCOMPtr<nsIContent> rootContent;
presShell->GetDocument(getter_AddRefs(document));
nsCOMPtr<nsIDOMNode> rootNode(do_QueryInterface(document));
if (!rootNode) {
return NS_ERROR_FAILURE;
}
if (treeItemParent) {
// We only create root accessibles for the true root, othewise create an iframe/iframeroot accessible
alreadyHere = PR_TRUE;
GetAccessibleFor(rootNode, _retval);
alreadyHere = PR_FALSE;
if (parentDoc) {
// We only create root accessibles for the true root, othewise create a
// doc accessible
*aRootAcc = new nsDocAccessibleWrap(rootNode, weakShell);
}
else {
nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(presShell));
*_retval = new nsRootAccessibleWrap(rootNode, weakShell);
NS_IF_ADDREF(*_retval);
*aRootAcc = new nsRootAccessibleWrap(rootNode, weakShell);
}
if (! *_retval)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIAccessibleEventReceiver> eventReceiver =
do_QueryInterface(*aRootAcc);
NS_ASSERTION(eventReceiver, "Doc accessible does not receive events");
eventReceiver->AddEventListeners();
nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(*aRootAcc));
accessNode->Init();
NS_ADDREF(*aRootAcc);
return NS_OK;
}
NS_IMETHODIMP
nsAccessibilityService::CreateCaretAccessible(nsIDOMNode *aNode, nsIAccessibleEventListener *aListener,
nsAccessibilityService::CreateCaretAccessible(nsIDOMNode *aNode,
nsIAccessible *aRootAccessible,
nsIAccessibleCaret **_retval)
{
nsCOMPtr<nsIWeakReference> weakShell;
GetShellFromNode(aNode, getter_AddRefs(weakShell));
*_retval = new nsCaretAccessible(aNode, weakShell, aListener);
*_retval = new nsCaretAccessible(aNode, weakShell, aRootAccessible);
if (! *_retval)
return NS_ERROR_OUT_OF_MEMORY;
@ -597,34 +539,65 @@ nsAccessibilityService::CreateHTMLListboxAccessible(nsIDOMNode* aDOMNode, nsISup
return NS_OK;
}
/**
* We can have several cases here.
* 1) a text or html embedded document where the contentDocument
* variable in the object element holds the content
* 2) web content that uses a plugin, which means we will
* have to go to the plugin to get the accessible content
* 3) An image or imagemap, where the image frame points back to
* the object element DOMNode
*/
NS_IMETHODIMP
nsAccessibilityService::CreateHTMLPluginAccessible(nsIDOMNode *aDOMNode, nsIWeakReference *aShell,
nsIAccessible **_retval)
nsAccessibilityService::CreateHTMLObjectFrameAccessible(nsObjectFrame *aFrame,
nsIAccessible **aAccessible)
{
*_retval = new nsHTMLPluginAccessible(aDOMNode, aShell);
nsCOMPtr<nsIDOMNode> node;
nsCOMPtr<nsIWeakReference> weakShell;
nsIFrame *frame;
nsresult rv = GetInfo(NS_STATIC_CAST(nsIFrame*, aFrame), &frame, getter_AddRefs(weakShell), getter_AddRefs(node));
if (! *_retval)
return NS_ERROR_OUT_OF_MEMORY;
// 1) for object elements containing either HTML or TXT documents
nsCOMPtr<nsIDOMDocument> domDoc;
nsCOMPtr<nsIDOMHTMLObjectElement> obj(do_QueryInterface(node));
if (obj)
obj->GetContentDocument(getter_AddRefs(domDoc));
else
domDoc = do_QueryInterface(node);
if (domDoc)
return CreateOuterDocAccessible(node, aAccessible);
NS_ADDREF(*_retval);
return NS_OK;
}
NS_IMETHODIMP
nsAccessibilityService::CreateHTMLNativeWindowAccessible(nsIDOMNode *aDOMNode, nsIWeakReference *aShell,
void *aHwnd, nsIAccessible **_retval)
{
#ifdef XP_WIN
*_retval = new nsHTMLWin32ObjectAccessible(aDOMNode, aShell, aHwnd);
if (! *_retval)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*_retval);
#else
*_retval = nsnull;
// 2) for plugins
nsCOMPtr<nsIPluginInstance> pluginInstance ;
aFrame->GetPluginInstance(*getter_AddRefs(pluginInstance));
if (pluginInstance) {
HWND pluginPort = nsnull;
aFrame->GetPluginPort(&pluginPort);
if (pluginPort) {
*aAccessible = new nsHTMLWin32ObjectAccessible(node, weakShell, pluginPort);
if (*aAccessible) {
NS_ADDREF(*aAccessible);
return NS_OK;
}
}
}
#endif
return NS_OK;
// 3) for images and imagemaps, or anything else with a child frame
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(weakShell));
if (!shell)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIPresContext> context;
shell->GetPresContext(getter_AddRefs(context));
if (!context)
return NS_ERROR_FAILURE;
// we have the object frame, get the image frame
aFrame->FirstChild(context, nsnull, &frame);
if (frame) {
return frame->GetAccessible(aAccessible);
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
@ -1394,54 +1367,6 @@ NS_IMETHODIMP nsAccessibilityService::CreateXULTooltipAccessible(nsIDOMNode *aNo
return NS_OK;
}
/**
* We can have several cases here.
* 1) a text or html embedded document where the contentDocument
* variable in the object element holds the content
* 2) web content that uses a plugin, which means we will
* have to go to the plugin to get the accessible content
* 3) An image or imagemap, where the image frame points back to
* the object element DOMNode
*/
nsresult
nsAccessibilityService::GetHTMLObjectAccessibleFor(nsIDOMNode *aNode,
nsIPresShell *aShell,
nsObjectFrame *aFrame,
nsIAccessible **_retval)
{
// 1) for object elements containing either HTML or TXT documents
nsCOMPtr<nsIDOMDocument> domDoc;
nsCOMPtr<nsIDOMHTMLObjectElement> obj(do_QueryInterface(aNode));
if (obj)
obj->GetContentDocument(getter_AddRefs(domDoc));
else
domDoc = do_QueryInterface(aNode);
if (domDoc)
return CreateOuterDocAccessible(aNode, _retval);
// 2) for plugins
nsCOMPtr<nsIPluginInstance> pluginInstance ;
aFrame->GetPluginInstance(*getter_AddRefs(pluginInstance));
if (pluginInstance) {
nsCOMPtr<nsIWeakReference> weakShell (do_GetWeakReference(aShell));
CreateHTMLPluginAccessible(aNode, weakShell, _retval);
return NS_OK;
}
// 3) for images and imagemaps
nsCOMPtr<nsIPresContext> context;
aShell->GetPresContext(getter_AddRefs(context));
if (!context)
return NS_ERROR_FAILURE;
// we have the object frame, get the image frame
nsIFrame *frame;
aFrame->FirstChild(context, nsnull, &frame);
CreateHTMLImageAccessible(frame, _retval);
if (*_retval)
return NS_OK;
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsAccessibilityService::CreateXULTreeAccessible(nsIDOMNode *aNode, nsIAccessible **_retval)
{
#ifdef MOZ_XUL
@ -1493,23 +1418,105 @@ NS_IMETHODIMP nsAccessibilityService::CreateXULTreeColumnitemAccessible(nsIDOMNo
return NS_OK;
}
NS_IMETHODIMP nsAccessibilityService::GetCachedAccessible(nsIDOMNode *aNode,
nsIWeakReference *aWeakShell,
nsIAccessible **aAccessible)
{
nsCOMPtr<nsIAccessNode> accessNode;
nsresult rv = GetCachedAccessNode(aNode, aWeakShell, getter_AddRefs(accessNode));
nsCOMPtr<nsIAccessible> accessible(do_QueryInterface(accessNode));
NS_IF_ADDREF(*aAccessible = accessible);
return rv;
}
NS_IMETHODIMP nsAccessibilityService::GetCachedAccessNode(nsIDOMNode *aNode,
nsIWeakReference *aWeakShell,
nsIAccessNode **aAccessNode)
{
nsCOMPtr<nsIAccessibleDocument> accessibleDoc;
nsAccessNode::GetDocAccessibleFor(aWeakShell, getter_AddRefs(accessibleDoc));
if (!accessibleDoc) {
NS_WARNING("No accessible document for this presshell");
*aAccessNode = nsnull;
return NS_ERROR_FAILURE;
}
return accessibleDoc->GetCachedAccessNode(NS_STATIC_CAST(void*, aNode), aAccessNode);
}
/**
* GetAccessibleFor - get an nsIAccessible from a DOM node
*/
NS_IMETHODIMP nsAccessibilityService::GetAccessibleFor(nsIDOMNode *aNode,
nsIAccessible **_retval)
nsIAccessible **aAccessible)
{
*_retval = nsnull;
// It's not ideal to call this -- it will assume shell #0
// Some of our old test scripts still use it
nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
nsCOMPtr<nsIDocument> doc;
if (content) {
content->GetDocument(*getter_AddRefs(doc));
}
else {// Could be document node
doc = do_QueryInterface(aNode);
}
if (!doc)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIPresShell> presShell;
doc->GetShellAt(0, getter_AddRefs(presShell));
return GetAccessibleInShell(aNode, presShell, aAccessible);
}
NS_IMETHODIMP nsAccessibilityService::GetAccessibleInWindow(nsIDOMNode *aNode,
nsIDOMWindow *aWin,
nsIAccessible **aAccessible)
{
nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(aWin));
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(webNav));
if (!docShell)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIPresShell> presShell;
docShell->GetPresShell(getter_AddRefs(presShell));
return GetAccessibleInShell(aNode, presShell, aAccessible);
}
NS_IMETHODIMP nsAccessibilityService::GetAccessibleInShell(nsIDOMNode *aNode,
nsIPresShell *aPresShell,
nsIAccessible **aAccessible)
{
nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(aPresShell));
return GetAccessible(aNode, aPresShell, weakShell, aAccessible);
}
NS_IMETHODIMP nsAccessibilityService::GetAccessibleInWeakShell(nsIDOMNode *aNode,
nsIWeakReference *aWeakShell,
nsIAccessible **aAccessible)
{
nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(aWeakShell));
return GetAccessible(aNode, presShell, aWeakShell, aAccessible);
}
nsresult nsAccessibilityService::GetAccessible(nsIDOMNode *aNode,
nsIPresShell *aPresShell,
nsIWeakReference *aWeakShell,
nsIAccessible **aAccessible)
{
*aAccessible = nsnull;
NS_ASSERTION(aNode, "GetAccessibleFor() called with no node.");
nsCOMPtr<nsIAccessible> newAcc;
NS_ASSERTION(aPresShell, "GetAccessible() called with no pres shell.");
NS_ASSERTION(aWeakShell, "GetAccessible() called with no weak shell.");
#ifdef DEBUG_aaronl
// Please leave this in for now, it's a convenient debugging method
nsAutoString name;
aNode->GetLocalName(name);
if (name.EqualsIgnoreCase("LABEL"))
if (name.EqualsIgnoreCase("object"))
printf("## aaronl debugging tag name\n");
nsAutoString attrib;
@ -1520,12 +1527,30 @@ NS_IMETHODIMP nsAccessibilityService::GetAccessibleFor(nsIDOMNode *aNode,
printf("## aaronl debugging attribute\n");
}
#endif
// Check to see if we already have an accessible for this
// node in the cache
nsCOMPtr<nsIAccessNode> accessNode;
GetCachedAccessNode(aNode, aWeakShell, getter_AddRefs(accessNode));
nsCOMPtr<nsIAccessible> newAcc;
if (accessNode) {
// Retrieved from cache
// QI might not succeed if it's a node that's not accessible
newAcc = do_QueryInterface(accessNode);
NS_IF_ADDREF(*aAccessible = newAcc);
return NS_OK;
}
// No cache entry, so we must create the accessible
// XUL elements may implement nsIAccessibleProvider via XBL
// This allows them to say what kind of accessible to create
nsCOMPtr<nsIAccessibleProvider> accProv(do_QueryInterface(aNode));
if (accProv) {
accProv->GetAccessible(getter_AddRefs(newAcc));
if (! newAcc)
return NS_ERROR_FAILURE;
#ifdef MOZ_ACCESSIBILITY_ATK
PRUint32 role, state;
newAcc->GetAccRole(&role);
// don't create the accessible object for popup widget when it's not visible
@ -1534,9 +1559,10 @@ NS_IMETHODIMP nsAccessibilityService::GetAccessibleFor(nsIDOMNode *aNode,
if (state & (nsIAccessible::STATE_INVISIBLE | nsIAccessible::STATE_OFFSCREEN))
return NS_ERROR_FAILURE;
}
#endif // MOZ_ACCESSIBILITY_ATK
*_retval = newAcc;
NS_ADDREF(*_retval);
accessNode = do_QueryInterface(newAcc);
accessNode->Init(); // Add to cache, etc.
*aAccessible = newAcc;
NS_ADDREF(*aAccessible);
return NS_OK;
}
@ -1561,12 +1587,6 @@ NS_IMETHODIMP nsAccessibilityService::GetAccessibleFor(nsIDOMNode *aNode,
if (!doc)
return NS_ERROR_INVALID_ARG;
// ---- Get the pres shell ----
nsCOMPtr<nsIPresShell> shell;
doc->GetShellAt(0, getter_AddRefs(shell));
if (!shell)
return NS_ERROR_FAILURE;
// ---- Check if area node ----
nsCOMPtr<nsIDOMHTMLAreaElement> areaContent(do_QueryInterface(aNode));
if (areaContent) // Area elements are implemented in nsHTMLImageAccessible as children of the image
@ -1576,43 +1596,28 @@ NS_IMETHODIMP nsAccessibilityService::GetAccessibleFor(nsIDOMNode *aNode,
nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
if (!content && nodeIsDoc) {
// This happens when we're on the document node, which will not QI to an nsIContent,
// When that happens, we try to get the outer, parent document node that contains the document
// For example, a <browser> or <iframe> element
nsCOMPtr<nsIPresShell> ownerShell;
nsCOMPtr<nsIContent> ownerContent;
GetOwnerFor(shell, getter_AddRefs(ownerShell), getter_AddRefs(ownerContent));
if (ownerContent) {
shell = ownerShell;
content = ownerContent;
nsCOMPtr<nsIAccessibleDocument> accessibleDoc;
nsAccessNode::GetDocAccessibleFor(aWeakShell, getter_AddRefs(accessibleDoc));
if (accessibleDoc) {
newAcc = do_QueryInterface(accessibleDoc);
NS_ASSERTION(newAcc, "nsIAccessibleDocument is not an nsIAccessible");
}
else {
// Nothing above us, return the root accessible
doc->GetRootContent(getter_AddRefs(content));
nsIFrame* frame = nsnull;
shell->GetPrimaryFrameFor(content, &frame);
if (!frame)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIPresContext> presContext;
shell->GetPresContext(getter_AddRefs(presContext));
return CreateRootAccessible(presContext, _retval);
CreateRootAccessible(aPresShell, doc, getter_AddRefs(newAcc)); // Does Init() for us
NS_ASSERTION(newAcc, "No root/doc accessible created");
}
NS_ADDREF(*aAccessible = newAcc );
return NS_OK;
}
NS_ASSERTION(content, "GetAccessibleFor() called with no content.");
// ---- Try using frame to get nsIAccessible ----
// ---- Try using frame to get nsIAccessible ----
nsIFrame* frame = nsnull;
shell->GetPrimaryFrameFor(content, &frame);
aPresShell->GetPrimaryFrameFor(content, &frame);
if (!frame)
return NS_ERROR_FAILURE;
// ---- object/embed/applet tags all use nsObjectFrames ----
nsCOMPtr<nsIAtom> frameType;
frame->GetFrameType(getter_AddRefs(frameType));
if (frameType.get() == nsLayoutAtoms::objectFrame) {
nsObjectFrame* objectFrame = NS_STATIC_CAST(nsObjectFrame*, frame);
return GetHTMLObjectAccessibleFor(aNode, shell, objectFrame, _retval);
}
return NS_ERROR_FAILURE;
frame->GetAccessible(getter_AddRefs(newAcc));
@ -1622,8 +1627,7 @@ NS_IMETHODIMP nsAccessibilityService::GetAccessibleFor(nsIDOMNode *aNode,
// is it a link?
nsCOMPtr<nsILink> link(do_QueryInterface(aNode));
if (link) {
nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(shell));
newAcc = new nsHTMLLinkAccessible(aNode, weakShell);
newAcc = new nsHTMLLinkAccessible(aNode, aWeakShell);
}
}
#endif //MOZ_ACCESSIBILITY_ATK
@ -1633,8 +1637,7 @@ NS_IMETHODIMP nsAccessibilityService::GetAccessibleFor(nsIDOMNode *aNode,
if (!newAcc) {
nsCOMPtr<nsIDOMHTMLOptionElement> optionElement(do_QueryInterface(aNode));
if (optionElement) {
nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(shell));
newAcc = new nsHTMLSelectOptionAccessible(aNode, weakShell);
newAcc = new nsHTMLSelectOptionAccessible(aNode, aWeakShell);
}
}
// See if this is an <optgroup>,
@ -1642,16 +1645,18 @@ NS_IMETHODIMP nsAccessibilityService::GetAccessibleFor(nsIDOMNode *aNode,
if (!newAcc) {
nsCOMPtr<nsIDOMHTMLOptGroupElement> optGroupElement(do_QueryInterface(aNode));
if (optGroupElement) {
nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(shell));
newAcc = new nsHTMLSelectOptGroupAccessible(aNode, weakShell);
newAcc = new nsHTMLSelectOptGroupAccessible(aNode, aWeakShell);
}
}
if (!newAcc)
return NS_ERROR_FAILURE;
*_retval = newAcc;
NS_ADDREF(*_retval);
accessNode = do_QueryInterface(newAcc);
accessNode->Init(); // Add to cache, etc.
*aAccessible = newAcc;
NS_ADDREF(*aAccessible);
return NS_OK;
}

View File

@ -40,34 +40,34 @@
#define __nsAccessibilityService_h__
#include "nsIAccessibilityService.h"
#include "nsIContent.h"
#include "nsIPresShell.h"
#include "nsIDocShell.h"
#include "nsObjectFrame.h"
#include "nsIObserver.h"
class nsIFrame;
class nsIWeakReference;
class nsIDOMNode;
class nsObjectFrame;
class nsIDocShell;
class nsIPresShell;
class nsIContent;
class nsAccessibilityService : public nsIAccessibilityService
class nsAccessibilityService : public nsIAccessibilityService, public nsIObserver
{
public:
nsAccessibilityService();
virtual ~nsAccessibilityService();
NS_DECL_ISUPPORTS
// nsIAccessibilityService methods:
NS_DECL_NSIACCESSIBILITYSERVICE
NS_DECL_NSIOBSERVER
static nsresult GetShellFromNode(nsIDOMNode *aNode, nsIWeakReference **weakShell);
private:
nsresult GetHTMLObjectAccessibleFor(nsIDOMNode *aNode, nsIPresShell *aShell, nsObjectFrame *aFrame, nsIAccessible **_retval);
nsresult GetInfo(nsISupports* aFrame, nsIFrame** aRealFrame, nsIWeakReference** aShell, nsIDOMNode** aContent);
void GetOwnerFor(nsIPresShell *aPresShell, nsIPresShell **aOwnerShell, nsIContent **aOwnerContent);
nsIContent* FindContentForDocShell(nsIPresShell* aPresShell, nsIContent* aContent, nsIDocShell* aDocShell);
PRBool mIsActive;
nsresult GetAccessible(nsIDOMNode *aNode, nsIPresShell *aPresShell,
nsIWeakReference *aWeakShell, nsIAccessible **aAccessible);
};
#endif /* __nsIAccessibilityService_h__ */

View File

@ -39,9 +39,8 @@
* ***** END LICENSE BLOCK ***** */
#include "nsAccessible.h"
#include "nsIAccessibilityService.h"
#include "nsCOMPtr.h"
#include "nsIDocument.h"
#include "nsIImageDocument.h"
#include "nsIPresShell.h"
#include "nsIPresContext.h"
#include "nsIContent.h"
@ -52,13 +51,9 @@
#include "nsIDOMDocumentView.h"
#include "nsIDOMAbstractView.h"
#include "nsIDOMWindowInternal.h"
#include "nsRootAccessible.h"
#include "nsPIDOMWindow.h"
#include "nsIDOMElement.h"
#include "nsIEventStateManager.h"
#include "nsHTMLFormControlAccessible.h"
#include "nsHTMLLinkAccessible.h"
#include "nsIDOMHTMLAreaElement.h"
#include "nsISelection.h"
#include "nsISelectionController.h"
#include "nsIServiceManager.h"
@ -66,363 +61,33 @@
#include "nsIDOMComment.h"
#include "nsITextContent.h"
#include "nsIEventStateManager.h"
#include "nsIDOMHTMLImageElement.h"
#include "nsIDOMHTMLInputElement.h"
#include "nsIDOMHTMLBRElement.h"
#include "nsIDOMXULElement.h"
#include "nsIAtom.h"
#include "nsLayoutAtoms.h"
#include "nsAccessibilityAtoms.h"
#include "nsGUIEvent.h"
#include "nsILink.h"
#include "nsStyleConsts.h"
#include "nsReadableUtils.h"
#include "nsIBindingManager.h"
#include "nsFormControlAccessible.h"
#include "nsIDOMHTMLFormElement.h"
#include "nsIDOMHTMLInputElement.h"
#include "nsIDOMHTMLLabelElement.h"
#include "nsIDOMHTMLObjectElement.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMXULButtonElement.h"
#include "nsIDOMXULCheckboxElement.h"
#include "nsIDOMDocument.h"
#include "nsIDOMXULElement.h"
#include "nsIDOMXULLabelElement.h"
#include "nsIDOMXULSelectCntrlEl.h"
#include "nsIDOMXULSelectCntrlItemEl.h"
#include "nsString.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch.h"
// IFrame Helpers
#include "nsIDocShell.h"
#include "nsIWebShell.h"
#include "nsIScriptGlobalObject.h"
#include "nsIDOMHTMLIFrameElement.h"
#include "nsIDOMHTMLFrameElement.h"
#include "nsIDocShellTreeItem.h"
#include "nsIFocusController.h"
#include "nsAccessibleTreeWalker.h"
#ifdef NS_DEBUG
#include "nsIFrameDebug.h"
#include "nsIDOMCharacterData.h"
#endif
//#define DEBUG_LEAKS
nsIStringBundle *nsAccessible::gStringBundle = 0;
nsIStringBundle *nsAccessible::gKeyStringBundle = 0;
static NS_DEFINE_CID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
nsAccessibleTreeWalker::nsAccessibleTreeWalker(nsIWeakReference* aPresShell, nsIDOMNode* aNode, PRInt32 aSiblingIndex, nsIDOMNodeList *aSiblingList, PRBool aWalkAnonContent):
mPresShell(aPresShell), mAccService(do_GetService("@mozilla.org/accessibilityService;1"))
{
mState.domNode = aNode;
mState.siblingIndex = aSiblingIndex;
mState.prevState = nsnull;
mState.siblingList = aSiblingList;
if (mState.siblingIndex < 0)
mState.siblingList = nsnull;
NS_ASSERTION(mState.siblingList || mState.siblingIndex < 0,
"Accessible tree walker initialization error, "
"can't have index into null sibling list");
if (aWalkAnonContent) {
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mPresShell));
if (shell) {
nsCOMPtr<nsIDocument> doc;
shell->GetDocument(getter_AddRefs(doc));
doc->GetBindingManager(getter_AddRefs(mBindingManager));
}
}
MOZ_COUNT_CTOR(nsAccessibleTreeWalker);
mInitialState = mState; // deep copy
}
nsAccessibleTreeWalker::~nsAccessibleTreeWalker()
{
// Clear state stack from memory
while (NS_SUCCEEDED(PopState()))
/* do nothing */ ;
MOZ_COUNT_DTOR(nsAccessibleTreeWalker);
}
// GetFullParentNode gets the parent node in the deep tree
// This might not be the DOM parent in cases where <children/> was used in an XBL binding.
// In that case, this returns the parent in the XBL'ized tree.
NS_IMETHODIMP nsAccessibleTreeWalker::GetFullTreeParentNode(nsIDOMNode *aChildNode, nsIDOMNode **aParentNodeOut)
{
nsCOMPtr<nsIContent> childContent(do_QueryInterface(aChildNode));
nsCOMPtr<nsIContent> bindingParentContent;
nsCOMPtr<nsIDOMNode> parentNode;
if (mState.prevState)
parentNode = mState.prevState->domNode;
else {
if (mBindingManager) {
mBindingManager->GetInsertionParent(childContent, getter_AddRefs(bindingParentContent));
if (bindingParentContent)
parentNode = do_QueryInterface(bindingParentContent);
}
if (!parentNode)
aChildNode->GetParentNode(getter_AddRefs(parentNode));
}
if (parentNode) {
*aParentNodeOut = parentNode;
NS_ADDREF(*aParentNodeOut);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
void nsAccessibleTreeWalker::GetKids(nsIDOMNode *aParentNode)
{
nsCOMPtr<nsIContent> content(do_QueryInterface(aParentNode));
mState.siblingIndex = eSiblingsWalkNormalDOM; // Default value - indicates no sibling list
if (content && mBindingManager) {
mBindingManager->GetXBLChildNodesFor(content, getter_AddRefs(mState.siblingList)); // returns null if no anon nodes
if (mState.siblingList)
mState.siblingIndex = 0; // Indicates our index into the sibling list
}
}
void nsAccessibleTreeWalker::GetSiblings(nsIDOMNode *aOneOfTheSiblings)
{
nsCOMPtr<nsIDOMNode> node;
mState.siblingIndex = eSiblingsWalkNormalDOM; // Default value
if (NS_SUCCEEDED(GetFullTreeParentNode(aOneOfTheSiblings, getter_AddRefs(node)))) {
GetKids(node);
if (mState.siblingList) { // Init index by seeing how far we are into list
if (mState.domNode == mInitialState.domNode)
mInitialState = mState; // deep copy, we'll use sibling info for caching
while (NS_SUCCEEDED(mState.siblingList->Item(mState.siblingIndex, getter_AddRefs(node))) && node != mState.domNode) {
NS_ASSERTION(node, "Something is terribly wrong - the child is not in it's parent's children!");
++mState.siblingIndex;
}
}
}
}
NS_IMETHODIMP nsAccessibleTreeWalker::GetParent()
{
nsCOMPtr<nsIDOMNode> parent;
while (NS_SUCCEEDED(GetFullTreeParentNode(mState.domNode, getter_AddRefs(parent)))) {
if (NS_FAILED(PopState())) {
ClearState();
mState.domNode = parent;
GetAccessible();
}
if (mState.accessible)
return NS_OK;
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsAccessibleTreeWalker::PopState()
{
if (mState.prevState) {
WalkState *toBeDeleted = mState.prevState;
mState = *mState.prevState; // deep copy
delete toBeDeleted;
return NS_OK;
}
return NS_ERROR_FAILURE;
}
void nsAccessibleTreeWalker::ClearState()
{
mState.siblingList = nsnull;
mState.accessible = nsnull;
mState.domNode = nsnull;
mState.siblingIndex = eSiblingsUninitialized;
}
NS_IMETHODIMP nsAccessibleTreeWalker::PushState()
{
// Duplicate mState and put right before end; reset mState; make mState the new end of the stack
WalkState* nextToLastState= new WalkState();
if (!nextToLastState)
return NS_ERROR_OUT_OF_MEMORY;
*nextToLastState = mState; // Deep copy - copy contents of struct to new state that will be added to end of our stack
ClearState();
mState.prevState = nextToLastState; // Link to previous state
return NS_OK;
}
NS_IMETHODIMP nsAccessibleTreeWalker::GetNextSibling()
{
// Make sure mState.siblingIndex and mState.siblingList are initialized
if (mState.siblingIndex == eSiblingsUninitialized)
GetSiblings(mState.domNode);
// get next sibling
nsCOMPtr<nsIDOMNode> next;
while (PR_TRUE) {
if (mState.siblingIndex == eSiblingsWalkNormalDOM)
mState.domNode->GetNextSibling(getter_AddRefs(next));
else
mState.siblingList->Item(++mState.siblingIndex, getter_AddRefs(next));
if (!next) { // Done with siblings
// if no DOM parent or DOM parent is accessible fail
nsCOMPtr<nsIDOMNode> parent;
if (NS_FAILED(GetFullTreeParentNode(mState.domNode, getter_AddRefs(parent))))
break; // Failed - can't get parent node, we're at the top
if (NS_FAILED(PopState())) { // Use parent - go up in stack
ClearState();
mState.domNode = parent;
}
if (mState.siblingIndex == eSiblingsUninitialized)
GetSiblings(mState.domNode);
if (GetAccessible())
break; // Failed - anything after this in the tree is in a new group of siblings
}
else {
// if next is accessible, use it
mState.domNode = next;
if (IsHidden())
continue;
if (GetAccessible())
return NS_OK;
// otherwise call first on next
mState.domNode = next;
if (NS_SUCCEEDED(GetFirstChild()))
return NS_OK;
// If no results, keep recursiom going - call next on next
mState.domNode = next;
}
}
return NS_ERROR_FAILURE;
}
PRBool nsAccessibleTreeWalker::IsHidden()
{
PRBool isHidden = PR_FALSE;
nsCOMPtr<nsIDOMXULElement> xulElt(do_QueryInterface(mState.domNode));
if (xulElt) {
xulElt->GetHidden(&isHidden);
if (!isHidden)
xulElt->GetCollapsed(&isHidden);
}
return isHidden;
}
NS_IMETHODIMP nsAccessibleTreeWalker::GetFirstChild()
{
if (!mState.domNode)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMNode> next, parent(mState.domNode);
PushState(); // Save old state
GetKids(parent); // Side effects change our state
if (mState.siblingIndex == eSiblingsWalkNormalDOM) // Indicates we must use normal DOM calls to traverse here
parent->GetFirstChild(getter_AddRefs(next));
else // Use the sibling list - there are anonymous content nodes in here
mState.siblingList->Item(0, getter_AddRefs(next));
// Recursive loop: depth first search for first accessible child
while (next) {
mState.domNode = next;
if (!IsHidden() && (GetAccessible() || NS_SUCCEEDED(GetFirstChild())))
return NS_OK;
if (mState.siblingIndex == eSiblingsWalkNormalDOM) // Indicates we must use normal DOM calls to traverse here
mState.domNode->GetNextSibling(getter_AddRefs(next));
else
mState.siblingList->Item(++mState.siblingIndex, getter_AddRefs(next));
}
PopState(); // Return to previous state
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsAccessibleTreeWalker::GetChildBefore(nsIDOMNode* aParent, nsIDOMNode* aChild)
{
mState.domNode = aParent;
if (!mState.domNode || NS_FAILED(GetFirstChild()) || mState.domNode == aChild)
return NS_ERROR_FAILURE; // if the first child is us, then we fail, because there is no child before the first
nsCOMPtr<nsIDOMNode> prevDOMNode(mState.domNode);
nsCOMPtr<nsIAccessible> prevAccessible(mState.accessible);
while (mState.domNode && NS_SUCCEEDED(GetNextSibling()) && mState.domNode != aChild) {
prevDOMNode = mState.domNode;
prevAccessible = mState.accessible;
}
mState.accessible = prevAccessible;
mState.domNode = prevDOMNode;
return NS_OK;
}
NS_IMETHODIMP nsAccessibleTreeWalker::GetPreviousSibling()
{
nsCOMPtr<nsIDOMNode> child(mState.domNode);
nsresult rv = GetParent();
if (NS_SUCCEEDED(rv))
rv = GetChildBefore(mState.domNode, child);
return rv;
}
NS_IMETHODIMP nsAccessibleTreeWalker::GetLastChild()
{
return GetChildBefore(mState.domNode, nsnull);
}
PRInt32 nsAccessibleTreeWalker::GetChildCount()
{
PRInt32 count = 0;
if (NS_SUCCEEDED(GetFirstChild())) {
do {
++count; // This loop always iterates at least once
}
while (NS_SUCCEEDED(GetNextSibling()));
}
return count;
}
/**
* If the DOM node's frame has an accessible or the DOMNode
* itself implements nsIAccessible return it.
*/
PRBool nsAccessibleTreeWalker::GetAccessible()
{
mState.accessible = nsnull;
return (mAccService &&
NS_SUCCEEDED(mAccService->GetAccessibleFor(mState.domNode, getter_AddRefs(mState.accessible))) &&
mState.accessible);
}
/*
* Class nsAccessible
*/
@ -430,11 +95,10 @@ PRBool nsAccessibleTreeWalker::GetAccessible()
//-----------------------------------------------------
// construction
//-----------------------------------------------------
NS_IMPL_ISUPPORTS_INHERITED1(nsAccessible, nsAccessNode, nsIAccessible)
nsAccessible::nsAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell): nsAccessNodeWrap(aNode),
mPresShell(aShell), mSiblingIndex(eSiblingsUninitialized)
nsAccessible::nsAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell): nsAccessNodeWrap(aNode, aShell),
mParent(nsnull), mFirstChild(nsnull), mNextSibling(nsnull)
{
#ifdef NS_DEBUG_X
{
@ -453,17 +117,6 @@ nsAccessible::nsAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell): nsAcces
printf("\n");
}
#endif
if (!gStringBundle) {
nsCOMPtr<nsIStringBundleService> stringBundleService(do_GetService(kStringBundleServiceCID));
if (stringBundleService) {
// Static variables are released in nsRootAccessible::ShutdownAll();
stringBundleService->CreateBundle(ACCESSIBLE_BUNDLE_URL, &gStringBundle);
NS_IF_ADDREF(gStringBundle);
stringBundleService->CreateBundle(PLATFORM_KEYS_BUNDLE_URL, &gKeyStringBundle);
NS_IF_ADDREF(gKeyStringBundle);
}
}
}
//-----------------------------------------------------
@ -473,14 +126,6 @@ nsAccessible::~nsAccessible()
{
}
NS_IMETHODIMP nsAccessible::Shutdown()
{
mPresShell = nsnull;
mParent = nsnull;
mSiblingList = nsnull;
return nsAccessNodeWrap::Shutdown();
}
NS_IMETHODIMP nsAccessible::GetAccName(nsAString& _retval)
{
nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(mDOMNode));
@ -546,18 +191,21 @@ NS_IMETHODIMP nsAccessible::GetAccKeyboardShortcut(nsAString& _retval)
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsAccessible::GetAccId(PRInt32 *aAccId)
NS_IMETHODIMP nsAccessible::SetAccParent(nsIAccessible *aParent)
{
*aAccId = - NS_PTR_TO_INT32(mDOMNode.get());
mParent = aParent;
return NS_OK;
}
NS_IMETHODIMP nsAccessible::CacheOptimizations(nsIAccessible *aParent, PRInt32 aSiblingIndex, nsIDOMNodeList *aSiblingList)
NS_IMETHODIMP nsAccessible::SetAccFirstChild(nsIAccessible *aFirstChild)
{
mParent = aParent;
if (aSiblingList)
mSiblingList = aSiblingList;
mSiblingIndex = aSiblingIndex;
mFirstChild = aFirstChild;
return NS_OK;
}
NS_IMETHODIMP nsAccessible::SetAccNextSibling(nsIAccessible *aNextSibling)
{
mNextSibling = aNextSibling? aNextSibling: DEAD_END_ACCESSIBLE;
return NS_OK;
}
@ -571,7 +219,7 @@ NS_IMETHODIMP nsAccessible::GetAccParent(nsIAccessible ** aAccParent)
*aAccParent = nsnull;
// Last argument of PR_TRUE indicates to walk anonymous content
nsAccessibleTreeWalker walker(mPresShell, mDOMNode, mSiblingIndex, mSiblingList, PR_TRUE);
nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, PR_TRUE);
if (NS_SUCCEEDED(walker.GetParent())) {
*aAccParent = mParent = walker.mState.accessible;
NS_ADDREF(*aAccParent);
@ -583,41 +231,42 @@ NS_IMETHODIMP nsAccessible::GetAccParent(nsIAccessible ** aAccParent)
/* readonly attribute nsIAccessible accNextSibling; */
NS_IMETHODIMP nsAccessible::GetAccNextSibling(nsIAccessible * *aAccNextSibling)
{
*aAccNextSibling = nsnull;
if (mNextSibling && mNextSibling != DEAD_END_ACCESSIBLE) {
NS_ADDREF(*aAccNextSibling = mNextSibling);
return NS_OK;
}
*aAccNextSibling = nsnull;
// Last argument of PR_TRUE indicates to walk anonymous content
nsAccessibleTreeWalker walker(mPresShell, mDOMNode, mSiblingIndex, mSiblingList, PR_TRUE);
nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, PR_TRUE);
if (NS_SUCCEEDED(walker.GetNextSibling())) {
*aAccNextSibling = walker.mState.accessible;
NS_ADDREF(*aAccNextSibling);
// Use last walker state to cache data on next accessible
(*aAccNextSibling)->CacheOptimizations(mParent, walker.mState.siblingIndex,
walker.mState.siblingList);
// Use first walker state to cache data on this accessible
CacheOptimizations(mParent, walker.mInitialState.siblingIndex,
walker.mInitialState.siblingList);
(*aAccNextSibling)->SetAccParent(mParent);
mNextSibling = *aAccNextSibling;
}
if (!mNextSibling)
mNextSibling = DEAD_END_ACCESSIBLE;
return NS_OK;
}
/* readonly attribute nsIAccessible accPreviousSibling; */
NS_IMETHODIMP nsAccessible::GetAccPreviousSibling(nsIAccessible * *aAccPreviousSibling)
{
{
*aAccPreviousSibling = nsnull;
// Last argument of PR_TRUE indicates to walk anonymous content
nsAccessibleTreeWalker walker(mPresShell, mDOMNode, mSiblingIndex, mSiblingList, PR_TRUE);
nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, PR_TRUE);
if (NS_SUCCEEDED(walker.GetPreviousSibling())) {
*aAccPreviousSibling = walker.mState.accessible;
NS_ADDREF(*aAccPreviousSibling);
// Use last walker state to cache data on prev accessible
(*aAccPreviousSibling)->CacheOptimizations(mParent, walker.mState.siblingIndex,
walker.mState.siblingList);
// Use first walker state to cache data on this accessible
CacheOptimizations(mParent, walker.mInitialState.siblingIndex,
walker.mInitialState.siblingList);
(*aAccPreviousSibling)->SetAccParent(mParent);
}
return NS_OK;
@ -626,14 +275,10 @@ NS_IMETHODIMP nsAccessible::GetAccPreviousSibling(nsIAccessible * *aAccPreviousS
/* readonly attribute nsIAccessible accFirstChild; */
NS_IMETHODIMP nsAccessible::GetAccFirstChild(nsIAccessible * *aAccFirstChild)
{
*aAccFirstChild = nsnull;
PRInt32 numChildren;
GetAccChildCount(&numChildren); // Make sure we cache all of the children
nsAccessibleTreeWalker walker(mPresShell, mDOMNode, mSiblingIndex, mSiblingList, PR_TRUE);
if (NS_SUCCEEDED(walker.GetFirstChild())) {
*aAccFirstChild = walker.mState.accessible;
NS_ADDREF(*aAccFirstChild);
(*aAccFirstChild)->CacheOptimizations(this, walker.mState.siblingIndex, walker.mState.siblingList);
}
NS_IF_ADDREF(*aAccFirstChild = mFirstChild);
return NS_OK;
}
@ -641,24 +286,57 @@ NS_IMETHODIMP nsAccessible::GetAccFirstChild(nsIAccessible * *aAccFirstChild)
/* readonly attribute nsIAccessible accFirstChild; */
NS_IMETHODIMP nsAccessible::GetAccLastChild(nsIAccessible * *aAccLastChild)
{
*aAccLastChild = nsnull;
GetChildAt(-1, aAccLastChild);
return NS_OK;
}
nsAccessibleTreeWalker walker(mPresShell, mDOMNode, mSiblingIndex, mSiblingList, PR_TRUE);
if (NS_SUCCEEDED(walker.GetLastChild())) {
*aAccLastChild = walker.mState.accessible;
NS_ADDREF(*aAccLastChild);
(*aAccLastChild)->CacheOptimizations(this, walker.mState.siblingIndex, walker.mState.siblingList);
NS_IMETHODIMP nsAccessible::GetChildAt(PRInt32 aChildNum, nsIAccessible **aChild)
{
// aChildNum is a zero-based index
// If aChildNum is out of range, last child is returned
PRInt32 numChildren;
GetAccChildCount(&numChildren);
nsCOMPtr<nsIAccessible> current(mFirstChild), nextSibling;
PRInt32 index = 0;
while (current) {
nextSibling = current;
if (++index > aChildNum) {
break;
}
nextSibling->GetAccNextSibling(getter_AddRefs(current));
}
NS_IF_ADDREF(*aChild = nextSibling);
return NS_OK;
}
void nsAccessible::CacheChildren(PRBool aWalkAnonContent)
{
if (mAccChildCount == eChildCountUninitialized) {
nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, aWalkAnonContent);
nsCOMPtr<nsIAccessible> prevAccessible;
mAccChildCount = 0;
walker.GetFirstChild();
SetAccFirstChild(walker.mState.accessible);
while (walker.mState.accessible) {
walker.mState.accessible->SetAccParent(this);
++mAccChildCount;
prevAccessible = walker.mState.accessible;
walker.GetNextSibling();
prevAccessible->SetAccNextSibling(walker.mState.accessible);
}
}
}
/* readonly attribute long accChildCount; */
NS_IMETHODIMP nsAccessible::GetAccChildCount(PRInt32 *aAccChildCount)
{
nsAccessibleTreeWalker walker(mPresShell, mDOMNode, mSiblingIndex, mSiblingList, PR_TRUE);
*aAccChildCount = walker.GetChildCount();
CacheChildren(PR_TRUE);
*aAccChildCount = mAccChildCount;
return NS_OK;
}
@ -698,9 +376,8 @@ PRBool nsAccessible::IsPartiallyVisible(PRBool *aIsOffscreen)
*aIsOffscreen = PR_FALSE;
const PRUint16 kMinPixels = 12;
// Set up the variables we need, return false if we can't get at them all
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mPresShell));
// Set up the variables we need, return false if we can't get at them all
nsCOMPtr<nsIPresShell> shell(GetPresShell());
if (!shell)
return PR_FALSE;
@ -710,8 +387,8 @@ PRBool nsAccessible::IsPartiallyVisible(PRBool *aIsOffscreen)
return PR_FALSE;
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
if (!content)
return PR_FALSE;
if (!content) // Null means we are on the document node
return PR_TRUE; // Document itself is visible
nsIFrame *frame = nsnull;
shell->GetPrimaryFrameFor(content, &frame);
@ -734,6 +411,7 @@ PRBool nsAccessible::IsPartiallyVisible(PRBool *aIsOffscreen)
// Get the bounds of the current frame, relative to the current view.
// We don't use the more accurate AccGetBounds, because that is more expensive
// and the STATE_OFFSCREEN flag that this is used for only needs to be a rough indicator
nsRect relFrameRect;
nsIView *containingView = nsnull;
nsPoint frameOffset;
@ -849,7 +527,9 @@ NS_IMETHODIMP nsAccessible::GetAccFocused(nsIAccessible **aAccFocused)
nsCOMPtr<nsIDOMNode> focusedNode;
if (accService && NS_SUCCEEDED(GetFocusedNode(getter_AddRefs(focusedNode)))) {
nsCOMPtr<nsIAccessible> accessible;
if (NS_SUCCEEDED(accService->GetAccessibleFor(focusedNode, getter_AddRefs(accessible)))) {
if (NS_SUCCEEDED(accService->GetAccessibleInWeakShell(focusedNode,
mWeakShell,
getter_AddRefs(accessible)))) {
*aAccFocused = accessible;
NS_ADDREF(*aAccFocused);
return NS_OK;
@ -869,6 +549,10 @@ NS_IMETHODIMP nsAccessible::AccGetAt(PRInt32 tx, PRInt32 ty, nsIAccessible **_re
{
nsCOMPtr<nsIAccessible> child;
nsCOMPtr<nsIAccessible> next;
PRInt32 numChildren; // Make sure all children cached first
GetAccChildCount(&numChildren);
GetAccFirstChild(getter_AddRefs(child));
PRInt32 cx,cy,cw,ch;
@ -960,7 +644,7 @@ void nsAccessible::GetScreenOrigin(nsIPresContext *aPresContext, nsIFrame *aFram
void nsAccessible::GetScrollOffset(nsRect *aRect)
{
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mPresShell));
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mWeakShell));
if (shell) {
nsCOMPtr<nsIDocument> doc;
shell->GetDocument(getter_AddRefs(doc));
@ -1008,8 +692,8 @@ void nsAccessible::GetBounds(nsRect& aTotalBounds, nsIFrame** aBoundingFrame)
*aBoundingFrame = ancestorFrame;
// If any other frame type, we only need to deal with the primary frame
// Otherwise, there may be more frames attached to the same content node
if (!IsCorrectFrameType(ancestorFrame, nsLayoutAtoms::inlineFrame) &&
!IsCorrectFrameType(ancestorFrame, nsLayoutAtoms::textFrame))
if (!IsCorrectFrameType(ancestorFrame, nsAccessibilityAtoms::inlineFrame) &&
!IsCorrectFrameType(ancestorFrame, nsAccessibilityAtoms::textFrame))
break;
ancestorFrame->GetParent(&ancestorFrame);
}
@ -1046,12 +730,11 @@ void nsAccessible::GetBounds(nsRect& aTotalBounds, nsIFrame** aBoundingFrame)
nsIFrame *iterNextFrame = nsnull;
if (IsCorrectFrameType(iterFrame, nsLayoutAtoms::inlineFrame)) {
if (IsCorrectFrameType(iterFrame, nsAccessibilityAtoms::inlineFrame)) {
// Only do deeper bounds search if we're on an inline frame
// Inline frames can contain larger frames inside of them
nsCOMPtr<nsIPresContext> presContext;
GetPresContext(getter_AddRefs(presContext));
iterFrame->FirstChild(presContext, nsnull, &iterNextFrame);
iterFrame->FirstChild(nsCOMPtr<nsIPresContext>(GetPresContext()),
nsnull, &iterNextFrame);
}
if (iterNextFrame)
@ -1090,8 +773,7 @@ NS_IMETHODIMP nsAccessible::AccGetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width,
// Another frame, same node
float t2p;
nsCOMPtr<nsIPresContext> presContext;
GetPresContext(getter_AddRefs(presContext));
nsCOMPtr<nsIPresContext> presContext(GetPresContext());
if (!presContext)
{
*x = *y = *width = *height = 0;
@ -1152,32 +834,10 @@ nsIFrame* nsAccessible::GetBoundsFrame()
return GetFrame();
}
nsIFrame* nsAccessible::GetFrame()
{
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mPresShell));
if (!shell)
return nsnull;
nsIFrame* frame = nsnull;
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
shell->GetPrimaryFrameFor(content, &frame);
return frame;
}
void nsAccessible::GetPresContext(nsIPresContext **aContext)
{
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mPresShell));
if (shell) {
shell->GetPresContext(aContext);
} else
aContext = nsnull;
}
/* void accRemoveSelection (); */
NS_IMETHODIMP nsAccessible::AccRemoveSelection()
{
nsCOMPtr<nsISelectionController> control(do_QueryReferent(mPresShell));
nsCOMPtr<nsISelectionController> control(do_QueryReferent(mWeakShell));
if (!control) {
return NS_ERROR_FAILURE;
}
@ -1202,7 +862,7 @@ NS_IMETHODIMP nsAccessible::AccRemoveSelection()
/* void accTakeSelection (); */
NS_IMETHODIMP nsAccessible::AccTakeSelection()
{
nsCOMPtr<nsISelectionController> control(do_QueryReferent(mPresShell));
nsCOMPtr<nsISelectionController> control(do_QueryReferent(mWeakShell));
if (!control)
return NS_ERROR_FAILURE;
@ -1249,14 +909,8 @@ NS_IMETHODIMP nsAccessible::AccTakeSelection()
/* void accTakeFocus (); */
NS_IMETHODIMP nsAccessible::AccTakeFocus()
{
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mPresShell));
if (!shell)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIPresContext> context;
shell->GetPresContext(getter_AddRefs(context));
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
content->SetFocus(context);
content->SetFocus(nsCOMPtr<nsIPresContext>(GetPresContext()));
return NS_OK;
}
@ -1303,7 +957,7 @@ NS_IMETHODIMP nsAccessible::AppendFlatStringFromContentNode(nsIContent *aContent
if (!commentNode) {
PRBool isHTMLBlock = PR_FALSE;
nsIFrame *frame;
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mPresShell));
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mWeakShell));
if (!shell) {
return NS_ERROR_FAILURE;
}
@ -1358,8 +1012,20 @@ NS_IMETHODIMP nsAccessible::AppendFlatStringFromContentNode(nsIContent *aContent
elt->GetAttribute(NS_LITERAL_STRING("alt"), textEquivalent);
if (textEquivalent.IsEmpty())
elt->GetAttribute(NS_LITERAL_STRING("title"), textEquivalent);
else {
// If we're in an image document (an image viewed by itself)
// then the image's alt text is generated text,
// so that an error shows when the image doesn't load.
// We don't want that text.
nsCOMPtr<nsIDocument> doc;
aContent->GetDocument(*getter_AddRefs(doc));
nsCOMPtr<nsIImageDocument> imageDoc(do_QueryInterface(doc));
if (imageDoc) // We don't want this faux error text
textEquivalent.Truncate();
}
if (textEquivalent.IsEmpty() && imageContent) {
nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mPresShell));
nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell));
nsCOMPtr<nsIDOMNode> imageNode(do_QueryInterface(aContent));
if (imageNode && presShell)
presShell->GetImageLocation(imageNode, textEquivalent);
@ -1479,7 +1145,7 @@ NS_IMETHODIMP nsAccessible::AppendLabelFor(nsIContent *aLookNode, const nsAStrin
*/
NS_IMETHODIMP nsAccessible::GetHTMLAccName(nsAString& _retval)
{
if (!mDOMNode) {
if (!mWeakShell || !mDOMNode) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIContent> walkUpContent(do_QueryInterface(mDOMNode));
@ -1620,11 +1286,15 @@ NS_IMETHODIMP nsAccessible::GetXULAccName(nsAString& _retval)
return NS_OK;
}
NS_IMETHODIMP nsAccessible::HandleEvent(PRUint32 aEvent, nsIAccessible *aTarget, void * aData)
NS_IMETHODIMP nsAccessible::FireToolkitEvent(PRUint32 aEvent, nsIAccessible *aTarget, void * aData)
{
nsCOMPtr<nsIAccessible> parent;
GetAccParent(getter_AddRefs(parent));
return parent ? parent->HandleEvent(aEvent, aTarget, aData) : NS_ERROR_NOT_IMPLEMENTED;
nsCOMPtr<nsIAccessibleDocument> docAccessible(GetDocAccessible());
nsCOMPtr<nsIAccessible> eventHandlingAccessible(do_QueryInterface(docAccessible));
if (eventHandlingAccessible) {
return eventHandlingAccessible->FireToolkitEvent(aEvent, aTarget, aData);
}
return NS_ERROR_FAILURE;
}
// Not implemented by this class
@ -1748,7 +1418,7 @@ nsresult nsAccessible::GetParentBlockNode(nsIDOMNode *aCurrentNode, nsIDOMNode *
presShell->GetPrimaryFrameFor(content, &frame);
if (frame)
frame->GetFrameType(getter_AddRefs(frameType));
while (frame && frameType != nsLayoutAtoms::blockFrame) {
while (frame && frameType != nsAccessibilityAtoms::blockFrame) {
nsIFrame* parentFrame = nsnull;
frame->GetParent(&parentFrame);
if (parentFrame)

View File

@ -40,30 +40,21 @@
#ifndef _nsAccessible_H_
#define _nsAccessible_H_
#include "nsCOMPtr.h"
#include "nsAccessNodeWrap.h"
#include "nsIAccessible.h"
#include "nsIAccessibilityService.h"
#include "nsIDOMNode.h"
#include "nsIFocusController.h"
#include "nsIPresContext.h"
#include "nsIPresShell.h"
#include "nsPoint.h"
#include "nsRect.h"
#include "nsWeakReference.h"
#include "nsIDOMNodeList.h"
#include "nsIBindingManager.h"
#include "nsIStringBundle.h"
#define ACCESSIBLE_BUNDLE_URL "chrome://global-platform/locale/accessible.properties"
#define PLATFORM_KEYS_BUNDLE_URL "chrome://global-platform/locale/platformKeys.properties"
#include "nsString.h"
struct nsRect;
class nsIContent;
class nsIDocShell;
class nsIFrame;
class nsIWebShell;
class nsIPresShell;
class nsIDOMNode;
class nsIAtom;
enum { eSiblingsUninitialized = -1, eSiblingsWalkNormalDOM = -2}; // Used in sibling index field as flags
// When mNextSibling is set to this, it indicates there ar eno more siblings
#define DEAD_END_ACCESSIBLE NS_STATIC_CAST(nsIAccessible*, (void*)1)
class nsAccessible : public nsAccessNodeWrap, public nsIAccessible
{
@ -79,20 +70,17 @@ public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIACCESSIBLE
// nsIAccessNode
NS_IMETHOD Shutdown();
NS_IMETHOD GetFocusedNode(nsIDOMNode **aFocusedNode);
#ifdef MOZ_ACCESSIBILITY_ATK
static nsresult GetParentBlockNode(nsIDOMNode *aCurrentNode, nsIDOMNode **aBlockNode);
static nsresult GetParentBlockNode(nsIDOMNode *aCurrentNode, nsIDOMNode **aBlockNode);
#endif
static PRBool IsCorrectFrameType(nsIFrame* aFrame, nsIAtom* aAtom);
protected:
virtual nsIFrame* GetFrame();
virtual nsIFrame* GetBoundsFrame();
virtual void GetBounds(nsRect& aRect, nsIFrame** aRelativeFrame);
virtual void GetPresContext(nsIPresContext **aContext);
PRBool IsPartiallyVisible(PRBool *aIsOffscreen);
NS_IMETHOD AppendLabelText(nsIDOMNode *aLabelNode, nsAString& _retval);
NS_IMETHOD AppendLabelFor(nsIContent *aLookNode, const nsAString *aId, nsAString *aLabel);
@ -101,69 +89,18 @@ protected:
NS_IMETHOD AppendFlatStringFromSubtree(nsIContent *aContent, nsAString *aFlatString);
NS_IMETHOD AppendFlatStringFromContentNode(nsIContent *aContent, nsAString *aFlatString);
NS_IMETHOD AppendStringWithSpaces(nsAString *aFlatString, const nsAString& textEquivalent);
// helper method to verify frames
static PRBool IsCorrectFrameType(nsIFrame* aFrame, nsIAtom* aAtom);
static nsresult GetFullKeyName(const nsAString& aModifierName, const nsAString& aKeyName, nsAString& aStringOut);
static nsresult GetTranslatedString(const nsAString& aKey, nsAString& aStringOut);
void GetScrollOffset(nsRect *aRect);
void GetScreenOrigin(nsIPresContext *aPresContext, nsIFrame *aFrame, nsRect *aRect);
nsresult AppendFlatStringFromSubtreeRecurse(nsIContent *aContent, nsAString *aFlatString);
void CacheChildren(PRBool aWalkNormalDOM);
// Data Members
nsCOMPtr<nsIWeakReference> mPresShell;
nsCOMPtr<nsIAccessible> mParent;
nsCOMPtr<nsIDOMNodeList> mSiblingList; // If some of our computed siblings are anonymous content nodes, cache node list
PRInt32 mSiblingIndex; // Cache where we are in list of kids that we got from nsIBindingManager::GetContentList(parentContent)
static nsIStringBundle *gStringBundle;
static nsIStringBundle *gKeyStringBundle;
};
/** This class is used to walk the DOM tree. It skips
* everything but nodes that either implement nsIAccessible
* or have primary frames that implement "GetAccessible"
*/
struct WalkState {
nsCOMPtr<nsIAccessible> accessible;
nsCOMPtr<nsIDOMNode> domNode;
nsCOMPtr<nsIDOMNodeList> siblingList;
PRInt32 siblingIndex; // Holds a state flag or an index into the siblingList
WalkState *prevState;
};
class nsAccessibleTreeWalker {
public:
nsAccessibleTreeWalker(nsIWeakReference* aShell, nsIDOMNode* aContent,
PRInt32 aCachedSiblingIndex, nsIDOMNodeList *aCachedSiblingList, PRBool mWalkAnonymousContent);
virtual ~nsAccessibleTreeWalker();
NS_IMETHOD GetNextSibling();
NS_IMETHOD GetPreviousSibling();
NS_IMETHOD GetParent();
NS_IMETHOD GetFirstChild();
NS_IMETHOD GetLastChild();
PRInt32 GetChildCount();
WalkState mState;
WalkState mInitialState;
protected:
NS_IMETHOD GetChildBefore(nsIDOMNode* aParent, nsIDOMNode* aChild);
PRBool IsHidden();
PRBool GetAccessible();
NS_IMETHOD GetFullTreeParentNode(nsIDOMNode *aChildNode, nsIDOMNode **aParentNodeOut);
void GetSiblings(nsIDOMNode *aOneOfTheSiblings);
void GetKids(nsIDOMNode *aParent);
void ClearState();
NS_IMETHOD PushState();
NS_IMETHOD PopState();
nsCOMPtr<nsIWeakReference> mPresShell;
nsCOMPtr<nsIAccessibilityService> mAccService;
nsCOMPtr<nsIBindingManager> mBindingManager;
nsIAccessible *mParent, *mFirstChild, *mNextSibling;
};
#endif

View File

@ -0,0 +1,339 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Original Author: Aaron Leventhal (aaronl@netscape.com)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsAccessibleTreeWalker.h"
#include "nsWeakReference.h"
#include "nsAccessNode.h"
#include "nsIServiceManager.h"
#include "nsIContent.h"
#include "nsIDOMXULElement.h"
#include "nsIPresShell.h"
nsAccessibleTreeWalker::nsAccessibleTreeWalker(nsIWeakReference* aPresShell, nsIDOMNode* aNode, PRBool aWalkAnonContent):
mWeakShell(aPresShell),
mAccService(do_GetService("@mozilla.org/accessibilityService;1"))
{
mState.domNode = aNode;
mState.prevState = nsnull;
mState.siblingIndex = eSiblingsUninitialized;
mState.siblingList = nsnull;
if (aWalkAnonContent) {
nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell));
if (presShell) {
nsCOMPtr<nsIDocument> doc;
presShell->GetDocument(getter_AddRefs(doc));
doc->GetBindingManager(getter_AddRefs(mBindingManager));
}
}
MOZ_COUNT_CTOR(nsAccessibleTreeWalker);
mInitialState = mState; // deep copy
}
nsAccessibleTreeWalker::~nsAccessibleTreeWalker()
{
// Clear state stack from memory
while (NS_SUCCEEDED(PopState()))
/* do nothing */ ;
MOZ_COUNT_DTOR(nsAccessibleTreeWalker);
}
// GetFullParentNode gets the parent node in the deep tree
// This might not be the DOM parent in cases where <children/> was used in an XBL binding.
// In that case, this returns the parent in the XBL'ized tree.
NS_IMETHODIMP nsAccessibleTreeWalker::GetFullTreeParentNode(nsIDOMNode *aChildNode, nsIDOMNode **aParentNodeOut)
{
nsCOMPtr<nsIContent> childContent(do_QueryInterface(aChildNode));
nsCOMPtr<nsIContent> bindingParentContent;
nsCOMPtr<nsIDOMNode> parentNode;
if (mState.prevState)
parentNode = mState.prevState->domNode;
else {
if (mBindingManager) {
mBindingManager->GetInsertionParent(childContent, getter_AddRefs(bindingParentContent));
if (bindingParentContent)
parentNode = do_QueryInterface(bindingParentContent);
}
if (!parentNode)
aChildNode->GetParentNode(getter_AddRefs(parentNode));
}
if (parentNode) {
*aParentNodeOut = parentNode;
NS_ADDREF(*aParentNodeOut);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
void nsAccessibleTreeWalker::GetKids(nsIDOMNode *aParentNode)
{
nsCOMPtr<nsIContent> content(do_QueryInterface(aParentNode));
mState.siblingIndex = eSiblingsWalkNormalDOM; // Default value - indicates no sibling list
if (content && mBindingManager) {
mBindingManager->GetXBLChildNodesFor(content, getter_AddRefs(mState.siblingList)); // returns null if no anon nodes
if (mState.siblingList)
mState.siblingIndex = 0; // Indicates our index into the sibling list
}
}
void nsAccessibleTreeWalker::GetSiblings(nsIDOMNode *aOneOfTheSiblings)
{
nsCOMPtr<nsIDOMNode> node;
mState.siblingIndex = eSiblingsWalkNormalDOM; // Default value
if (NS_SUCCEEDED(GetFullTreeParentNode(aOneOfTheSiblings, getter_AddRefs(node)))) {
GetKids(node);
if (mState.siblingList) { // Init index by seeing how far we are into list
if (mState.domNode == mInitialState.domNode)
mInitialState = mState; // deep copy, we'll use sibling info for caching
while (NS_SUCCEEDED(mState.siblingList->Item(mState.siblingIndex, getter_AddRefs(node))) && node != mState.domNode) {
NS_ASSERTION(node, "Something is terribly wrong - the child is not in it's parent's children!");
++mState.siblingIndex;
}
}
}
}
NS_IMETHODIMP nsAccessibleTreeWalker::GetParent()
{
nsCOMPtr<nsIDOMNode> parent;
while (NS_SUCCEEDED(GetFullTreeParentNode(mState.domNode, getter_AddRefs(parent)))) {
if (NS_FAILED(PopState())) {
ClearState();
mState.domNode = parent;
GetAccessible();
}
if (mState.accessible)
return NS_OK;
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsAccessibleTreeWalker::PopState()
{
if (mState.prevState) {
WalkState *toBeDeleted = mState.prevState;
mState = *mState.prevState; // deep copy
delete toBeDeleted;
return NS_OK;
}
return NS_ERROR_FAILURE;
}
void nsAccessibleTreeWalker::ClearState()
{
mState.siblingList = nsnull;
mState.accessible = nsnull;
mState.domNode = nsnull;
mState.siblingIndex = eSiblingsUninitialized;
}
NS_IMETHODIMP nsAccessibleTreeWalker::PushState()
{
// Duplicate mState and put right before end; reset mState; make mState the new end of the stack
WalkState* nextToLastState= new WalkState();
if (!nextToLastState)
return NS_ERROR_OUT_OF_MEMORY;
*nextToLastState = mState; // Deep copy - copy contents of struct to new state that will be added to end of our stack
ClearState();
mState.prevState = nextToLastState; // Link to previous state
return NS_OK;
}
NS_IMETHODIMP nsAccessibleTreeWalker::GetNextSibling()
{
mState.accessible = nsnull;
// Make sure mState.siblingIndex and mState.siblingList are initialized
if (mState.siblingIndex == eSiblingsUninitialized)
GetSiblings(mState.domNode);
// get next sibling
nsCOMPtr<nsIDOMNode> next;
while (PR_TRUE) {
if (mState.siblingIndex == eSiblingsWalkNormalDOM)
mState.domNode->GetNextSibling(getter_AddRefs(next));
else
mState.siblingList->Item(++mState.siblingIndex, getter_AddRefs(next));
if (!next) { // Done with siblings
// if no DOM parent or DOM parent is accessible fail
nsCOMPtr<nsIDOMNode> parent;
if (NS_FAILED(GetFullTreeParentNode(mState.domNode, getter_AddRefs(parent))))
break; // Failed - can't get parent node, we're at the top
if (NS_FAILED(PopState())) { // Use parent - go up in stack
ClearState();
mState.domNode = parent;
}
if (mState.siblingIndex == eSiblingsUninitialized)
GetSiblings(mState.domNode);
if (GetAccessible()) {
mState.accessible = nsnull;
break; // Failed - anything after this in the tree is in a new group of siblings
}
}
else {
// if next is accessible, use it
mState.domNode = next;
if (IsHidden())
continue;
if (GetAccessible())
return NS_OK;
// otherwise call first on next
mState.domNode = next;
if (NS_SUCCEEDED(GetFirstChild()))
return NS_OK;
// If no results, keep recursiom going - call next on next
mState.domNode = next;
}
}
return NS_ERROR_FAILURE;
}
PRBool nsAccessibleTreeWalker::IsHidden()
{
PRBool isHidden = PR_FALSE;
nsCOMPtr<nsIDOMXULElement> xulElt(do_QueryInterface(mState.domNode));
if (xulElt) {
xulElt->GetHidden(&isHidden);
if (!isHidden)
xulElt->GetCollapsed(&isHidden);
}
return isHidden;
}
NS_IMETHODIMP nsAccessibleTreeWalker::GetFirstChild()
{
mState.accessible = nsnull;
if (!mState.domNode)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMNode> next, parent(mState.domNode);
PushState(); // Save old state
GetKids(parent); // Side effects change our state
if (mState.siblingIndex == eSiblingsWalkNormalDOM) // Indicates we must use normal DOM calls to traverse here
parent->GetFirstChild(getter_AddRefs(next));
else // Use the sibling list - there are anonymous content nodes in here
mState.siblingList->Item(0, getter_AddRefs(next));
// Recursive loop: depth first search for first accessible child
while (next) {
mState.domNode = next;
if (!IsHidden() && (GetAccessible() || NS_SUCCEEDED(GetFirstChild())))
return NS_OK;
if (mState.siblingIndex == eSiblingsWalkNormalDOM) // Indicates we must use normal DOM calls to traverse here
mState.domNode->GetNextSibling(getter_AddRefs(next));
else
mState.siblingList->Item(++mState.siblingIndex, getter_AddRefs(next));
}
PopState(); // Return to previous state
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsAccessibleTreeWalker::GetChildBefore(nsIDOMNode* aParent, nsIDOMNode* aChild)
{
mState.accessible = nsnull;
mState.domNode = aParent;
if (!mState.domNode || NS_FAILED(GetFirstChild()) || mState.domNode == aChild)
return NS_ERROR_FAILURE; // if the first child is us, then we fail, because there is no child before the first
nsCOMPtr<nsIDOMNode> prevDOMNode(mState.domNode);
nsCOMPtr<nsIAccessible> prevAccessible(mState.accessible);
while (mState.domNode && NS_SUCCEEDED(GetNextSibling()) && mState.domNode != aChild) {
prevDOMNode = mState.domNode;
prevAccessible = mState.accessible;
}
mState.accessible = prevAccessible;
mState.domNode = prevDOMNode;
return NS_OK;
}
NS_IMETHODIMP nsAccessibleTreeWalker::GetPreviousSibling()
{
nsCOMPtr<nsIDOMNode> child(mState.domNode);
nsresult rv = GetParent();
if (NS_SUCCEEDED(rv))
rv = GetChildBefore(mState.domNode, child);
return rv;
}
NS_IMETHODIMP nsAccessibleTreeWalker::GetLastChild()
{
return GetChildBefore(mState.domNode, nsnull);
}
/**
* If the DOM node's frame has an accessible or the DOMNode
* itself implements nsIAccessible return it.
*/
PRBool nsAccessibleTreeWalker::GetAccessible()
{
mState.accessible = nsnull;
return (mAccService &&
NS_SUCCEEDED(mAccService->GetAccessibleInWeakShell(mState.domNode, mWeakShell,
getter_AddRefs(mState.accessible))) &&
mState.accessible);
}

View File

@ -0,0 +1,97 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Original Author: Aaron Leventhal (aaronl@netscape.com)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef _nsAccessibleTreeWalker_H_
#define _nsAccessibleTreeWalker_H_
/* For documentation of the accessibility architecture, * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
*/
#include "nsCOMPtr.h"
#include "nsIDocument.h"
#include "nsIAccessible.h"
#include "nsIDOMNodeList.h"
#include "nsIAccessibilityService.h"
#include "nsIBindingManager.h"
#include "nsIWeakReference.h"
struct WalkState {
nsCOMPtr<nsIAccessible> accessible;
nsCOMPtr<nsIDOMNode> domNode;
nsCOMPtr<nsIDOMNodeList> siblingList;
PRInt32 siblingIndex; // Holds a state flag or an index into the siblingList
WalkState *prevState;
};
/** This class is used to walk the DOM tree. It skips
* everything but nodes that either implement nsIAccessibleProvider
* or have primary frames that implement "GetAccessible"
*/
class nsAccessibleTreeWalker {
public:
nsAccessibleTreeWalker(nsIWeakReference* aShell, nsIDOMNode* aContent,
PRBool mWalkAnonymousContent);
virtual ~nsAccessibleTreeWalker();
NS_IMETHOD GetNextSibling();
NS_IMETHOD GetPreviousSibling();
NS_IMETHOD GetParent();
NS_IMETHOD GetFirstChild();
NS_IMETHOD GetLastChild();
WalkState mState;
WalkState mInitialState;
protected:
NS_IMETHOD GetChildBefore(nsIDOMNode* aParent, nsIDOMNode* aChild);
PRBool IsHidden();
PRBool GetAccessible();
NS_IMETHOD GetFullTreeParentNode(nsIDOMNode *aChildNode, nsIDOMNode **aParentNodeOut);
void GetSiblings(nsIDOMNode *aOneOfTheSiblings);
void GetKids(nsIDOMNode *aParent);
void ClearState();
NS_IMETHOD PushState();
NS_IMETHOD PopState();
nsCOMPtr<nsIWeakReference> mWeakShell;
nsCOMPtr<nsIAccessibilityService> mAccService;
nsCOMPtr<nsIBindingManager> mBindingManager;
};
#endif

View File

@ -37,13 +37,9 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsAccessibleWrap.h"
#include "nsBaseWidgetAccessible.h"
#include "nsCOMPtr.h"
#include "nsAccessibleWrap.h"
#include "nsGUIEvent.h"
#include "nsIContent.h"
#include "nsIDOMElement.h"
#include "nsIDOMEventReceiver.h"
#include "nsIFrame.h"
#include "nsILink.h"
#include "nsIPresContext.h"
@ -214,12 +210,7 @@ NS_IMPL_ISUPPORTS_INHERITED0(nsLinkableAccessible, nsAccessible)
NS_IMETHODIMP nsLinkableAccessible::AccTakeFocus()
{
if (IsALink()) {
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mPresShell));
if (!shell)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIPresContext> context;
shell->GetPresContext(getter_AddRefs(context));
mLinkContent->SetFocus(context);
mLinkContent->SetFocus(nsCOMPtr<nsIPresContext>(GetPresContext()));
}
return NS_OK;
@ -237,7 +228,7 @@ NS_IMETHODIMP nsLinkableAccessible::GetAccState(PRUint32 *_retval)
}
// Get current selection and find out if current node is in it
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mPresShell));
nsCOMPtr<nsIPresShell> shell(GetPresShell());
if (!shell) {
return NS_ERROR_FAILURE;
}
@ -285,7 +276,7 @@ NS_IMETHODIMP nsLinkableAccessible::GetAccValue(nsAString& _retval)
{
if (IsALink()) {
nsCOMPtr<nsIDOMNode> linkNode(do_QueryInterface(mLinkContent));
nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mPresShell));
nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell));
if (linkNode && presShell)
return presShell->GetLinkLocation(linkNode, _retval);
}
@ -320,12 +311,7 @@ NS_IMETHODIMP nsLinkableAccessible::AccDoAction(PRUint8 index)
// Action 0 (default action): Jump to link
if (index == eAction_Jump) {
if (IsALink()) {
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mPresShell));
if (!shell)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIPresContext> presContext;
shell->GetPresContext(getter_AddRefs(presContext));
nsCOMPtr<nsIPresContext> presContext(GetPresContext());
if (presContext) {
nsMouseEvent linkClickEvent;
linkClickEvent.eventStructType = NS_EVENT;
@ -358,7 +344,8 @@ NS_IMETHODIMP nsLinkableAccessible::GetAccKeyboardShortcut(nsAString& _retval)
nsCOMPtr<nsIAccessible> linkAccessible;
nsCOMPtr<nsIAccessibilityService> accService =
do_GetService("@mozilla.org/accessibilityService;1");
accService->GetAccessibleFor(linkNode, getter_AddRefs(linkAccessible));
accService->GetAccessibleInWeakShell(linkNode, mWeakShell,
getter_AddRefs(linkAccessible));
return linkAccessible->GetAccKeyboardShortcut(_retval);
}
}
@ -391,3 +378,9 @@ PRBool nsLinkableAccessible::IsALink()
mIsALinkCached = PR_TRUE; // Cached that there is no link
return PR_FALSE;
}
NS_IMETHODIMP nsLinkableAccessible::Shutdown()
{
mLinkContent = nsnull;
return nsAccessibleWrap::Shutdown();
}

View File

@ -41,10 +41,9 @@
#define _nsBaseWidgetAccessible_H_
#include "nsAccessibleWrap.h"
#include "nsCOMPtr.h"
#include "nsIContent.h"
#include "nsIDOMNode.h"
#include "nsIDOMXULListener.h"
class nsIDOMNode;
/**
* This file contains a number of classes that are used as base
@ -110,12 +109,13 @@ public:
NS_IMETHOD GetAccValue(nsAString& _retval);
NS_IMETHOD AccTakeFocus();
NS_IMETHOD GetAccKeyboardShortcut(nsAString& _retval);
NS_IMETHOD Shutdown();
protected:
PRBool IsALink();
PRBool mIsALinkCached; // -1 = unknown, 0 = not a link, 1 = is a link
nsCOMPtr<nsIContent> mLinkContent;
PRBool mIsLinkVisited;
PRPackedBool mIsALinkCached; // -1 = unknown, 0 = not a link, 1 = is a link
PRPackedBool mIsLinkVisited;
};
#endif

View File

@ -36,6 +36,7 @@
* ***** END LICENSE BLOCK ***** */
#include "nsAccessibilityService.h"
#include "nsIServiceManagerUtils.h"
#include "nsCaretAccessible.h"
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
@ -46,20 +47,28 @@
#include "nsISelectionController.h"
#include "nsIFrame.h"
#include "nsISelectionPrivate.h"
#include "nsIAccessibleEventListener.h"
#include "nsIViewManager.h"
#include "nsIWidget.h"
#include "nsIPresShell.h"
#include "nsTextAccessible.h"
#include "nsRootAccessible.h"
#include "nsIAccessibleEventReceiver.h"
NS_IMPL_ISUPPORTS_INHERITED2(nsCaretAccessible, nsLeafAccessible, nsIAccessibleCaret, nsISelectionListener)
nsCaretAccessible::nsCaretAccessible(nsIDOMNode* aDocumentNode, nsIWeakReference* aShell, nsIAccessibleEventListener *aListener):
nsLeafAccessible(aDocumentNode, aShell), mVisible(PR_TRUE), mCurrentDOMNode(nsnull), mListener(aListener)
nsCaretAccessible::nsCaretAccessible(nsIDOMNode* aDocumentNode, nsIWeakReference* aShell, nsIAccessible *aRootAccessible):
nsLeafAccessible(aDocumentNode, aShell), mVisible(PR_TRUE), mCurrentDOMNode(nsnull), mRootAccessible(aRootAccessible)
{
}
NS_IMETHODIMP nsCaretAccessible::Shutdown()
{
mDomSelectionWeak = nsnull;
mCurrentDOMNode = nsnull;
RemoveSelectionListener();
return NS_OK;
}
NS_IMETHODIMP nsCaretAccessible::RemoveSelectionListener()
{
nsCOMPtr<nsISelection> prevDomSel(do_QueryReferent(mDomSelectionWeak));
@ -77,22 +86,18 @@ NS_IMETHODIMP nsCaretAccessible::AttachNewSelectionListener(nsIDOMNode *aCurrent
// When focus moves such that the caret is part of a new frame selection
// this removes the old selection listener and attaches a new one for the current focus
nsCOMPtr<nsIDOMDocument> domDoc;
aCurrentNode->GetOwnerDocument(getter_AddRefs(domDoc));
nsCOMPtr<nsIDocument> doc(do_QueryInterface(domDoc));
if (!doc) // we also should try to QI to document instead (necessary to do when node is a document)
doc = do_QueryInterface(aCurrentNode);
if (!doc)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIPresShell> presShell;
doc->GetShellAt(0, getter_AddRefs(presShell));
nsCOMPtr<nsIPresShell> presShell(GetPresShell());
nsCOMPtr<nsIContent> content(do_QueryInterface(aCurrentNode));
if (!content)
doc->GetRootContent(getter_AddRefs(content)); // If node is not content, use root content
if (!presShell || !content)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIDocument> doc;
presShell->GetDocument(getter_AddRefs(doc));
if (!doc) // we also should try to QI to document instead (necessary to do when node is a document)
doc = do_QueryInterface(aCurrentNode);
if (!content)
doc->GetRootContent(getter_AddRefs(content)); // If node is not content, use root content
nsIFrame *frame = nsnull;
presShell->GetPrimaryFrameFor(content, &frame);
nsCOMPtr<nsIPresContext> presContext;
@ -126,12 +131,10 @@ NS_IMETHODIMP nsCaretAccessible::NotifySelectionChanged(nsIDOMDocument *aDoc, ns
return NS_OK;
#endif
nsCOMPtr<nsIDocument> doc(do_QueryInterface(aDoc));
if (!doc)
return NS_OK;
nsCOMPtr<nsIPresShell> presShell;
doc->GetShellAt(0, getter_AddRefs(presShell));
nsCOMPtr<nsIPresShell> presShell(GetPresShell());
if (!presShell)
return NS_ERROR_FAILURE;
nsCOMPtr<nsISelection> domSel(do_QueryReferent(mDomSelectionWeak));
if (!presShell || domSel != aSel)
return NS_OK; // Only listening to selection changes in currently focused frame
@ -150,7 +153,8 @@ NS_IMETHODIMP nsCaretAccessible::NotifySelectionChanged(nsIDOMDocument *aDoc, ns
caret->GetCaretVisible(&visible);
if (visible != mVisible) {
mVisible = visible;
mListener->HandleEvent(mVisible? nsIAccessibleEventListener::EVENT_SHOW: nsIAccessibleEventListener::EVENT_HIDE, this, nsnull);
mRootAccessible->FireToolkitEvent(mVisible? nsIAccessibleEventReceiver::EVENT_SHOW:
nsIAccessibleEventReceiver::EVENT_HIDE, this, nsnull);
}
nsCOMPtr<nsIPresContext> presContext;
@ -182,8 +186,9 @@ NS_IMETHODIMP nsCaretAccessible::NotifySelectionChanged(nsIDOMDocument *aDoc, ns
#endif
#ifndef MOZ_ACCESSIBILITY_ATK
if (visible)
mListener->HandleEvent(nsIAccessibleEventListener::EVENT_LOCATION_CHANGE, this, nsnull);
if (visible) {
mRootAccessible->FireToolkitEvent(nsIAccessibleEventReceiver::EVENT_LOCATION_CHANGE, this, nsnull);
}
#else
nsCOMPtr<nsIDOMNode> focusNode;
nsCOMPtr<nsIDOMHTMLInputElement> inputElement(do_QueryInterface(mCurrentDOMNode));
@ -197,6 +202,8 @@ NS_IMETHODIMP nsCaretAccessible::NotifySelectionChanged(nsIDOMDocument *aDoc, ns
nsAccessible::GetParentBlockNode(focusNode, getter_AddRefs(blockNode));
nsCOMPtr<nsIDOMHTMLBodyElement> body(do_QueryInterface(blockNode));
if (body) {
nsCOMPtr<nsIDocument> doc;
presShell->GetDocument(getter_AddRefs(doc));
nsCOMPtr<nsIDocument> parentDoc;
doc->GetParentDocument(getter_AddRefs(parentDoc));
nsCOMPtr<nsIDOMDocument> xulDoc(do_QueryInterface(parentDoc));
@ -214,16 +221,16 @@ NS_IMETHODIMP nsCaretAccessible::NotifySelectionChanged(nsIDOMDocument *aDoc, ns
nsCOMPtr<nsIAccessible> accessible;
nsCOMPtr<nsIAccessibilityService> accService(do_GetService("@mozilla.org/accessibilityService;1"));
accService->GetAccessibleFor(focusNode, getter_AddRefs(accessible));
accService->GetAccessibleInWeakShell(focusNode, mWeakShell, getter_AddRefs(accessible));
if (accessible) {
if (isCollapsed) {
PRInt32 caretOffset;
domSel->GetFocusOffset(&caretOffset);
mListener->HandleEvent(nsIAccessibleEventListener::EVENT_ATK_TEXT_CARET_MOVE, accessible, &caretOffset);
mRootAccessible->FireToolkitEvent(nsIAccessibleEventReceiver::EVENT_ATK_TEXT_CARET_MOVE, accessible, &caretOffset);
}
else {
//Current text interface doesn't support this event yet
//mListener->HandleEvent(nsIAccessibleEventListener::EVENT_ATK_TEXT_SELECTION_CHANGE, accessible, nsnull);
//mListener->FireToolkitEvent(nsIAccessibleEventReceiver::EVENT_ATK_TEXT_SELECTION_CHANGE, accessible, nsnull);
}
}
#endif
@ -260,7 +267,6 @@ NS_IMETHODIMP nsCaretAccessible::GetAccParent(nsIAccessible **_retval)
*_retval = nsnull;
return NS_OK;
}
NS_IMETHODIMP nsCaretAccessible::GetAccPreviousSibling(nsIAccessible **_retval)
{
*_retval = nsnull;

View File

@ -43,6 +43,8 @@
#include "nsIDOMNode.h"
#include "nsIAccessibleCaret.h"
#include "nsISelectionListener.h"
#include "nsRect.h"
/*
* This special accessibility class is for the caret, which is really the currently focused selection.
* There is only 1 visible caret per top level window (nsRootAccessible)
@ -57,7 +59,7 @@ class nsCaretAccessible : public nsLeafAccessible, public nsIAccessibleCaret, pu
public:
NS_DECL_ISUPPORTS_INHERITED
nsCaretAccessible(nsIDOMNode* aDocumentNode, nsIWeakReference* aShell, nsIAccessibleEventListener *aListener);
nsCaretAccessible(nsIDOMNode* aDocumentNode, nsIWeakReference* aShell, nsIAccessible *aRootAccessible);
/* ----- nsIAccessible ----- */
NS_IMETHOD GetAccParent(nsIAccessible **_retval);
@ -74,13 +76,16 @@ public:
/* ----- nsISelectionListener ---- */
NS_IMETHOD NotifySelectionChanged(nsIDOMDocument *aDoc, nsISelection *aSel, short aReason);
/* ----- nsIAccessNode ----- */
NS_IMETHOD Shutdown();
private:
nsRect mCaretRect;
PRBool mVisible;
nsCOMPtr<nsIDOMNode> mCurrentDOMNode;
// mListener is not a com pointer. It's a copy of the listener in the nsRootAccessible owner.
//See nsRootAccessible.h for details of the lifetime if this listener
nsIAccessibleEventListener *mListener;
nsIAccessible *mRootAccessible;
nsCOMPtr<nsIWeakReference> mDomSelectionWeak;
};

View File

@ -52,6 +52,14 @@
#include "nsIURI.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIServiceManager.h"
#include "nsHashtable.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeItem.h"
#include "nsIScrollableView.h"
#include "nsIAccessibilityService.h"
#ifdef MOZ_ACCESSIBILITY_ATK
#include "nsAccessibleEventData.h"
#endif
//=============================//
// nsDocAccessible //
@ -61,12 +69,37 @@
// construction
//-----------------------------------------------------
nsDocAccessible::nsDocAccessible(nsIDOMNode *aDOMNode, nsIWeakReference* aShell):
nsAccessibleWrap(aDOMNode, aShell), mWnd(nsnull)
nsAccessibleWrap(aDOMNode, aShell),
mAccessNodeCache(nsnull), mWnd(nsnull),
mScrollWatchTimer(nsnull), mDocLoadTimer(nsnull),
mWebProgress(nsnull), mBusy(eBusyStateUninitialized),
mScrollPositionChangedTicks(0), mIsNewDocument(PR_FALSE)
{
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mPresShell));
// Because of the way document loading happens, the new nsIWidget is created before
// the old one is removed. Since it creates the nsDocAccessible, for a brief moment
// there can be 2 nsDocAccessible's for the content area, although for 2 different
// pres shells.
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mWeakShell));
if (shell) {
shell->GetDocument(getter_AddRefs(mDocument));
nsCOMPtr<nsIViewManager> vm;
shell->GetViewManager(getter_AddRefs(vm));
nsCOMPtr<nsIWidget> widget;
vm->GetWidget(getter_AddRefs(widget));
mWnd = widget->GetNativeData(NS_NATIVE_WINDOW);
}
NS_ASSERTION(gGlobalDocAccessibleCache, "No global doc accessible cache");
PutCacheEntry(gGlobalDocAccessibleCache, NS_STATIC_CAST(void*, mWeakShell), this);
// XXX aaronl should we use an algorithm for the initial cache size?
#ifdef OLD_HASH
mAccessNodeCache = new nsSupportsHashtable(kDefaultCacheSize);
#else
mAccessNodeCache = new nsInterfaceHashtable<nsVoidHashKey, nsIAccessNode>;
mAccessNodeCache->Init(kDefaultCacheSize);
#endif
}
//-----------------------------------------------------
@ -76,53 +109,54 @@ nsDocAccessible::~nsDocAccessible()
{
}
NS_IMPL_ISUPPORTS_INHERITED1(nsDocAccessible, nsAccessible, nsIAccessibleDocument);
NS_IMPL_ISUPPORTS_INHERITED5(nsDocAccessible, nsAccessible, nsIAccessibleDocument,
nsIAccessibleEventReceiver, nsIWebProgressListener,
nsIScrollPositionListener, nsISupportsWeakReference)
/* void addAccessibleEventListener (in nsIAccessibleEventListener aListener); */
NS_IMETHODIMP nsDocAccessible::AddAccessibleEventListener(nsIAccessibleEventListener *aListener)
NS_IMETHODIMP nsDocAccessible::AddEventListeners()
{
#ifdef LATER_WHEN_CACHE_IMPLD
NS_ASSERTION(aListener, "Trying to add a null listener!");
if (!mListener) {
mListener = aListener;
AddContentDocListeners();
}
#endif
AddContentDocListeners();
return NS_OK;
}
/* void removeAccessibleEventListener (); */
NS_IMETHODIMP nsDocAccessible::RemoveAccessibleEventListener()
NS_IMETHODIMP nsDocAccessible::RemoveEventListeners()
{
#ifdef LATER_WHEN_CACHE_IMPLD
if (mListener) {
RemoveContentDocListeners();
mListener = nsnull;
}
#endif
RemoveContentDocListeners();
return NS_OK;
}
NS_IMETHODIMP nsDocAccessible::GetAccName(nsAString& aAccName)
{
return GetTitle(aAccName);
}
NS_IMETHODIMP nsDocAccessible::GetAccRole(PRUint32 *_retval)
{
*_retval = ROLE_PANE;
return NS_OK;
}
NS_IMETHODIMP nsDocAccessible::GetAccName(nsAString& aAccName)
{
return NS_OK;
}
NS_IMETHODIMP nsDocAccessible::GetAccValue(nsAString& aAccValue)
{
return GetURL(aAccValue);
}
NS_IMETHODIMP nsDocAccessible::GetAccState(PRUint32 *aAccState)
{
*aAccState = STATE_FOCUSABLE;
if (mBusy == eBusyStateLoading)
*aAccState |= STATE_BUSY;
return NS_OK;
}
// ------- nsIAccessibleDocument Methods (5) ---------------
NS_IMETHODIMP nsDocAccessible::GetURL(nsAString& aURL)
{
if (!mDocument) {
return NS_ERROR_FAILURE; // Document has been shut down
}
nsCOMPtr<nsISupports> container;
mDocument->GetContainer(getter_AddRefs(container));
nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(container));
@ -141,7 +175,7 @@ NS_IMETHODIMP nsDocAccessible::GetURL(nsAString& aURL)
NS_IMETHODIMP nsDocAccessible::GetTitle(nsAString& aTitle)
{
return mDocument->GetDocumentTitle(aTitle);
return mDocument? mDocument->GetDocumentTitle(aTitle): NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsDocAccessible::GetMimeType(nsAString& aMimeType)
@ -196,21 +230,58 @@ NS_IMETHODIMP nsDocAccessible::GetWindow(void **aWindow)
return NS_OK;
}
NS_IMETHODIMP nsDocAccessible::SetWindow(void *aWindow)
NS_IMETHODIMP nsDocAccessible::GetCachedAccessNode(void *aUniqueID, nsIAccessNode **aAccessNode)
{
mWnd = aWindow;
NS_ASSERTION(mAccessNodeCache, "No accessibility cache for document");
GetCacheEntry(mAccessNodeCache, aUniqueID, aAccessNode); // Addrefs for us
return NS_OK;
}
NS_IMETHODIMP nsDocAccessible::CacheAccessNode(void *aUniqueID, nsIAccessNode *aAccessNode)
{
NS_ASSERTION(mAccessNodeCache, "No accessibility cache for document");
PutCacheEntry(mAccessNodeCache, aUniqueID, aAccessNode);
return NS_OK;
}
NS_IMETHODIMP nsDocAccessible::Shutdown()
{
if (!mWeakShell) {
return NS_OK; // Already shutdown
}
void* presShellKey = NS_STATIC_CAST(void*, mWeakShell);
mWeakShell = nsnull; // Avoid reentrancy
RemoveEventListeners();
mScrollWatchTimer = mDocLoadTimer = nsnull;
mWebProgress = nsnull;
if (mAccessNodeCache) {
#ifdef OLD_HASH
nsSupportsHashtable *hashToClear = mAccessNodeCache; // Avoid reentrency
#else
nsInterfaceHashtable<nsVoidHashKey, nsIAccessNode> *hashToClear = mAccessNodeCache; // Avoid reentrency
#endif
mAccessNodeCache = nsnull;
ClearCache(hashToClear);
delete hashToClear;
}
NS_ASSERTION(gGlobalDocAccessibleCache, "Global doc cache does not exist");
#ifdef OLD_HASH
nsVoidKey key(presShellKey);
gGlobalDocAccessibleCache->Remove(&key);
#else
gGlobalDocAccessibleCache->Remove(presShellKey);
#endif
mDocument = nsnull;
return nsAccessibleWrap::Shutdown();
}
nsIFrame* nsDocAccessible::GetFrame()
{
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mPresShell));
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mWeakShell));
nsIFrame* root = nsnull;
if (shell)
@ -226,3 +297,274 @@ void nsDocAccessible::GetBounds(nsRect& aBounds, nsIFrame** aRelativeFrame)
(*aRelativeFrame)->GetRect(aBounds);
}
void nsDocAccessible::AddContentDocListeners()
{
// 1) Set up scroll position listener
// 2) Set up web progress listener - we need to know
// when page loading is finished
// That way we can send the STATE_CHANGE events for
// the MSAA root "pane" object (ROLE_PANE),
// and change the STATE_BUSY bit flag
// Do this only for top level content documents
nsCOMPtr<nsIPresShell> presShell(GetPresShell());
if (!presShell)
return;
AddScrollListener(presShell);
nsCOMPtr<nsISupports> container;
mDocument->GetContainer(getter_AddRefs(container));
nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem(do_QueryInterface(container));
if (!docShellTreeItem)
return;
// Make sure we're a content docshell
// We don't want to listen to chrome progress
PRInt32 itemType;
docShellTreeItem->GetItemType(&itemType);
if (itemType != nsIDocShellTreeItem::typeContent)
return;
// Make sure we're the top content doc shell
// We don't want to listen to iframe progress
nsCOMPtr<nsIDocShellTreeItem> topOfContentTree;
docShellTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(topOfContentTree));
if (topOfContentTree != docShellTreeItem)
return;
nsCOMPtr<nsIPresContext> context;
presShell->GetPresContext(getter_AddRefs(context));
if (!context)
return;
mWebProgress = do_GetInterface(docShellTreeItem);
if (!mWebProgress)
return;
mWebProgress->AddProgressListener(this, nsIWebProgress::NOTIFY_LOCATION |
nsIWebProgress::NOTIFY_STATE_DOCUMENT);
mIsNewDocument = PR_TRUE;
mBusy = eBusyStateLoading;
PRBool isLoading;
mWebProgress->GetIsLoadingDocument(&isLoading);
if (!isLoading) {
// If already loaded, fire "done loading" event after short timeout
// If we fired the event here, we'd get reentrancy problems
// Otherwise it will be fired from OnStateChange when the load is done
mDocLoadTimer = do_CreateInstance("@mozilla.org/timer;1");
if (mDocLoadTimer) {
mDocLoadTimer->InitWithFuncCallback(DocLoadCallback, this, 1,
nsITimer::TYPE_ONE_SHOT);
}
}
}
void nsDocAccessible::RemoveContentDocListeners()
{
// Remove listeners associated with content documents
// Remove web progress listener
if (mWebProgress) {
mWebProgress->RemoveProgressListener(this);
mWebProgress = nsnull;
}
// Remove scroll position listener
nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell));
RemoveScrollListener(presShell);
}
void nsDocAccessible::FireDocLoadFinished()
{
// Hook up our new accessible with our parent
if (!mParent) {
nsCOMPtr<nsIDocument> parentDoc;
mDocument->GetParentDocument(getter_AddRefs(parentDoc));
if (parentDoc) {
nsCOMPtr<nsIContent> ownerContent;
parentDoc->FindContentForSubDocument(mDocument,
getter_AddRefs(ownerContent));
nsCOMPtr<nsIDOMNode> ownerNode(do_QueryInterface(ownerContent));
if (ownerNode) {
nsCOMPtr<nsIAccessibilityService> accService =
do_GetService("@mozilla.org/accessibilityService;1");
if (accService) {
// XXX aaronl: ideally we would traverse the presshell chain
// Since there's no easy way to do that, we cheat and use
// the document hierarchy. GetAccessibleFor() is bad because
// it doesn't support our concept of multiple presshells per doc.
// It should be changed to use GetAccessibleInWeakShell()
nsCOMPtr<nsIAccessible> accParent;
accService->GetAccessibleFor(ownerNode, getter_AddRefs(accParent));
SetAccParent(accParent);
if (accParent) {
accParent->SetAccFirstChild(this);
}
}
}
}
}
if (mIsNewDocument) {
mIsNewDocument = PR_FALSE;
if (mBusy != eBusyStateDone) {
mBusy = eBusyStateDone;
#ifndef MOZ_ACCESSIBILITY_ATK
FireToolkitEvent(nsIAccessibleEventReceiver::EVENT_STATE_CHANGE, this, nsnull);
#endif
}
}
}
void nsDocAccessible::DocLoadCallback(nsITimer *aTimer, void *aClosure)
{
// Doc has finished loading, fire "load finished" event
// This path is only used if the doc was already finished loading
// when the DocAccessible was created.
// Otherwise, ::OnStateChange() fires the event when doc is loaded.
nsDocAccessible *docAcc = NS_REINTERPRET_CAST(nsDocAccessible*, aClosure);
if (docAcc)
docAcc->FireDocLoadFinished();
}
void nsDocAccessible::ScrollTimerCallback(nsITimer *aTimer, void *aClosure)
{
nsDocAccessible *docAcc = NS_REINTERPRET_CAST(nsDocAccessible*, aClosure);
if (docAcc && docAcc->mScrollPositionChangedTicks &&
++docAcc->mScrollPositionChangedTicks > 2) {
// Whenever scroll position changes, mScrollPositionChangeTicks gets reset to 1
// We only want to fire accessibilty scroll event when scrolling stops or pauses
// Therefore, we wait for no scroll events to occur between 2 ticks of this timer
// That indicates a pause in scrolling, so we fire the accessibilty scroll event
docAcc->FireToolkitEvent(nsIAccessibleEventReceiver::EVENT_SCROLLINGEND, docAcc, nsnull);
docAcc->mScrollPositionChangedTicks = 0;
docAcc->mScrollWatchTimer->Cancel();
docAcc->mScrollWatchTimer = nsnull;
}
}
void nsDocAccessible::AddScrollListener(nsIPresShell *aPresShell)
{
nsCOMPtr<nsIViewManager> vm;
if (aPresShell)
aPresShell->GetViewManager(getter_AddRefs(vm));
nsIScrollableView* scrollableView = nsnull;
if (vm)
vm->GetRootScrollableView(&scrollableView);
if (scrollableView)
scrollableView->AddScrollPositionListener(NS_STATIC_CAST(nsIScrollPositionListener *, this));
}
void nsDocAccessible::RemoveScrollListener(nsIPresShell *aPresShell)
{
nsCOMPtr<nsIViewManager> vm;
if (aPresShell)
aPresShell->GetViewManager(getter_AddRefs(vm));
nsIScrollableView* scrollableView = nsnull;
if (vm)
vm->GetRootScrollableView(&scrollableView);
if (scrollableView)
scrollableView->RemoveScrollPositionListener(NS_STATIC_CAST(nsIScrollPositionListener *, this));
}
NS_IMETHODIMP nsDocAccessible::ScrollPositionWillChange(nsIScrollableView *aView, nscoord aX, nscoord aY)
{
return NS_OK;
}
NS_IMETHODIMP nsDocAccessible::ScrollPositionDidChange(nsIScrollableView *aScrollableView, nscoord aX, nscoord aY)
{
// Start new timer, if the timer cycles at least 1 full cycle without more scroll position changes,
// then the ::Notify() method will fire the accessibility event for scroll position changes
const PRUint32 kScrollPosCheckWait = 50;
if (mScrollWatchTimer) {
mScrollWatchTimer->SetDelay(kScrollPosCheckWait); // Create new timer, to avoid leaks
}
else {
mScrollWatchTimer = do_CreateInstance("@mozilla.org/timer;1");
if (mScrollWatchTimer) {
mScrollWatchTimer->InitWithFuncCallback(ScrollTimerCallback, this,
kScrollPosCheckWait,
nsITimer::TYPE_REPEATING_SLACK);
}
}
mScrollPositionChangedTicks = 1;
return NS_OK;
}
NS_IMETHODIMP nsDocAccessible::OnStateChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest, PRUint32 aStateFlags, nsresult aStatus)
{
if ((aStateFlags & STATE_IS_DOCUMENT) && (aStateFlags & STATE_STOP))
FireDocLoadFinished(); // Doc is ready!
return NS_OK;
}
/* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */
NS_IMETHODIMP nsDocAccessible::OnProgressChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress,
PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress)
{
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
return NS_OK;
}
/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */
NS_IMETHODIMP nsDocAccessible::OnLocationChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest, nsIURI *location)
{
// Load has been verified, it will occur, about to commence
// We won't fire a "doc finished loading" event on this nsRootAccessible
// Instead we fire that on the new nsRootAccessible that is created for the new doc
mIsNewDocument = PR_FALSE; // We're a doc that's going away
if (mBusy != eBusyStateLoading) {
mBusy = eBusyStateLoading;
// Fire a "new doc has started to load" event
#ifndef MOZ_ACCESSIBILITY_ATK
FireToolkitEvent(nsIAccessibleEventReceiver::EVENT_STATE_CHANGE, this, nsnull);
#else
AtkChildrenChange childrenData;
childrenData.index = -1;
childrenData.child = 0;
childrenData.add = PR_FALSE;
FireToolkitEvent(nsIAccessibleEventReceiver::EVENT_REORDER , this, &childrenData);
#endif
}
return NS_OK;
}
/* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
NS_IMETHODIMP nsDocAccessible::OnStatusChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage)
{
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
return NS_OK;
}
/* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long state); */
NS_IMETHODIMP nsDocAccessible::OnSecurityChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest, PRUint32 state)
{
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
return NS_OK;
}

View File

@ -35,6 +35,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef _nsDocAccessible_H_
#define _nsDocAccessible_H_
@ -42,13 +43,26 @@
#include "nsIAccessibleDocument.h"
#include "nsIDocument.h"
#include "nsIAccessibleEventReceiver.h"
#include "nsHashtable.h"
#include "nsIWebProgressListener.h"
#include "nsITimer.h"
#include "nsIWebProgress.h"
#include "nsIScrollPositionListener.h"
#include "nsIWeakReference.h"
class nsIWeakReference;
class nsIScrollableView;
const PRUint32 kDefaultCacheSize = 256;
class nsDocAccessible : public nsAccessibleWrap,
public nsIAccessibleDocument,
public nsIAccessibleEventReceiver
public nsIAccessibleEventReceiver,
public nsIWebProgressListener,
public nsIScrollPositionListener,
public nsSupportsWeakReference
{
enum EBusyState {eBusyStateUninitialized, eBusyStateLoading, eBusyStateDone};
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIACCESSIBLEDOCUMENT
NS_DECL_NSIACCESSIBLEEVENTRECEIVER
@ -60,6 +74,13 @@ class nsDocAccessible : public nsAccessibleWrap,
NS_IMETHOD GetAccRole(PRUint32 *aAccRole);
NS_IMETHOD GetAccName(nsAString& aAccName);
NS_IMETHOD GetAccValue(nsAString& aAccValue);
NS_IMETHOD GetAccState(PRUint32 *aAccState);
// ----- nsIScrollPositionListener ---------------------------
NS_IMETHOD ScrollPositionWillChange(nsIScrollableView *aView, nscoord aX, nscoord aY);
NS_IMETHOD ScrollPositionDidChange(nsIScrollableView *aView, nscoord aX, nscoord aY);
NS_DECL_NSIWEBPROGRESSLISTENER
// nsIAccessNode
NS_IMETHOD Shutdown();
@ -67,9 +88,27 @@ class nsDocAccessible : public nsAccessibleWrap,
protected:
virtual void GetBounds(nsRect& aRect, nsIFrame** aRelativeFrame);
virtual nsIFrame* GetFrame();
void AddContentDocListeners();
void RemoveContentDocListeners();
void AddScrollListener(nsIPresShell *aPresShell);
void RemoveScrollListener(nsIPresShell *aPresShell);
void FireDocLoadFinished();
static void DocLoadCallback(nsITimer *aTimer, void *aClosure);
static void ScrollTimerCallback(nsITimer *aTimer, void *aClosure);
nsCOMPtr<nsIDocument> mDocument;
#ifdef OLD_HASH
nsSupportsHashtable *mAccessNodeCache;
#else
nsInterfaceHashtable<nsVoidHashKey, nsIAccessNode> *mAccessNodeCache;
#endif
void *mWnd;
nsCOMPtr<nsIDocument> mDocument;
nsCOMPtr<nsITimer> mScrollWatchTimer;
nsCOMPtr<nsITimer> mDocLoadTimer;
nsCOMPtr<nsIWebProgress> mWebProgress;
EBusyState mBusy;
PRUint16 mScrollPositionChangedTicks; // Used for tracking scroll events
PRPackedBool mIsNewDocument;
};

View File

@ -39,20 +39,10 @@
// NOTE: alphabetically ordered
#include "nsFormControlAccessible.h"
#include "nsIDocument.h"
#include "nsIDOMHTMLFormElement.h"
#include "nsIDOMHTMLInputElement.h"
#include "nsIDOMHTMLLabelElement.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMXULButtonElement.h"
#include "nsIDOMXULCheckboxElement.h"
#include "nsIDOMXULDocument.h"
#include "nsIDOMXULElement.h"
#include "nsIDOMXULLabelElement.h"
#include "nsIDOMXULSelectCntrlEl.h"
#include "nsIDOMXULSelectCntrlItemEl.h"
#include "nsReadableUtils.h"
#include "nsString.h"
#include "nsIDOMXULControlElement.h"
/**
* nsFormControlAccessible

View File

@ -43,7 +43,7 @@
#include "nsHyperTextAccessible.h"
#include "nsIFrame.h"
#include "nsILink.h"
#include "nsLayoutAtoms.h"
#include "nsAccessibilityAtoms.h"
#ifdef MOZ_ACCESSIBILITY_ATK
/*
@ -96,7 +96,7 @@ void nsAccessibleHyperText::GetAllTextChildren(nsIPresShell* aShell, nsIDOMNode*
if (frame) {
nsCOMPtr<nsIAtom> fType;
frame->GetFrameType(getter_AddRefs(fType));
if (fType == nsLayoutAtoms::textFrame) {
if (fType == nsAccessibilityAtoms::textFrame) {
nsRect frameRect;
frame->GetRect(frameRect);
// Skip the empty text frames that usually only consist of "\n"
@ -104,7 +104,7 @@ void nsAccessibleHyperText::GetAllTextChildren(nsIPresShell* aShell, nsIDOMNode*
mTextChildren->AppendElement(childNode);
continue;
}
else if (fType == nsLayoutAtoms::blockFrame) {
else if (fType == nsAccessibilityAtoms::blockFrame) {
// we won't traverse the child blockframe that supposes to be another object
continue;
}
@ -373,8 +373,7 @@ NS_IMETHODIMP nsAccessibleHyperText::RemoveSelection(PRInt32 aSelectionNum)
}
// ------- nsIAccessibleHyperText ---------------
/* readonly attribute long links; */
NS_IMETHODIMP nsAccessibleHyperText::GetLinks(PRInt32 *aLinks)
/* readonly attribute long links; */NS_IMETHODIMP nsAccessibleHyperText::GetLinks(PRInt32 *aLinks)
{
*aLinks = 0;
@ -404,12 +403,14 @@ NS_IMETHODIMP nsAccessibleHyperText::GetLink(PRInt32 aIndex, nsIAccessibleHyperL
domNode->GetParentNode(getter_AddRefs(parentNode));
nsCOMPtr<nsILink> link(do_QueryInterface(parentNode));
if (link) {
if (linkCount++ == aIndex) {
if (linkCount++ == NS_STATIC_CAST(PRUint32, aIndex)) {
nsCOMPtr<nsIWeakReference> weakShell;
nsAccessibilityService::GetShellFromNode(parentNode, getter_AddRefs(weakShell));
NS_ENSURE_TRUE(weakShell, NS_ERROR_FAILURE);
*aLink = new nsHTMLLinkAccessible(parentNode, weakShell);
NS_IF_ADDREF(*aLink);
nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(*aLink));
accessNode->Init();
break;
}
}

View File

@ -43,9 +43,9 @@
#include "nsAccessible.h"
#include "nsIAccessibleHyperText.h"
#include "nsTextAccessible.h"
#include "nsISupportsArray.h"
#ifdef MOZ_ACCESSIBILITY_ATK
class nsAccessibleHyperText : public nsIAccessibleHyperText,
public nsIAccessibleText
{

View File

@ -41,16 +41,24 @@
NS_IMPL_ISUPPORTS_INHERITED0(nsOuterDocAccessible, nsBlockAccessible)
nsOuterDocAccessible::nsOuterDocAccessible(nsIDOMNode* aNode,
nsIAccessible* aDocAccessible,
nsIWeakReference* aShell):
nsBlockAccessible(aNode, aShell), mInnerDocAccessible(aDocAccessible)
nsIAccessible* aDocAccessible,
nsIWeakReference* aShell):
nsBlockAccessible(aNode, aShell)
{
SetAccFirstChild(aDocAccessible); // weak ref
if (aDocAccessible) {
aDocAccessible->SetAccParent(this);
}
mAccChildCount = 1;
}
/* attribute wstring accName; */
NS_IMETHODIMP nsOuterDocAccessible::GetAccName(nsAString& aAccName)
{
nsCOMPtr<nsIAccessibleDocument> accDoc(do_QueryInterface(mInnerDocAccessible));
nsCOMPtr<nsIAccessibleDocument> accDoc(do_QueryInterface(mFirstChild));
if (!accDoc) {
return NS_ERROR_FAILURE;
}
nsresult rv = accDoc->GetTitle(aAccName);
if (NS_FAILED(rv) || aAccName.IsEmpty())
rv = accDoc->GetURL(aAccName);
@ -62,27 +70,6 @@ NS_IMETHODIMP nsOuterDocAccessible::GetAccValue(nsAString& aAccValue)
return NS_OK;
}
/* nsIAccessible getAccFirstChild (); */
NS_IMETHODIMP nsOuterDocAccessible::GetAccFirstChild(nsIAccessible **aChild)
{
NS_IF_ADDREF(*aChild = mInnerDocAccessible);
return NS_OK;
}
/* nsIAccessible getAccLastChild (); */
NS_IMETHODIMP nsOuterDocAccessible::GetAccLastChild(nsIAccessible **aChild)
{
NS_IF_ADDREF(*aChild = mInnerDocAccessible);
return NS_OK;
}
/* long getAccChildCount (); */
NS_IMETHODIMP nsOuterDocAccessible::GetAccChildCount(PRInt32 *aNumChildren)
{
*aNumChildren = 1;
return NS_OK;
}
/* unsigned long getAccRole (); */
NS_IMETHODIMP nsOuterDocAccessible::GetAccRole(PRUint32 *_retval)
{
@ -94,3 +81,4 @@ NS_IMETHODIMP nsOuterDocAccessible::GetAccState(PRUint32 *aAccState)
{
return nsAccessible::GetAccState(aAccState);
}

View File

@ -53,16 +53,10 @@ class nsOuterDocAccessible : public nsBlockAccessible
nsIAccessible* aInnerDocAccessible,
nsIWeakReference* aShell);
NS_IMETHOD GetAccFirstChild(nsIAccessible **_retval);
NS_IMETHOD GetAccLastChild(nsIAccessible **_retval);
NS_IMETHOD GetAccChildCount(PRInt32 *_retval);
NS_IMETHOD GetAccName(nsAString& aAccName);
NS_IMETHOD GetAccValue(nsAString& AccValue);
NS_IMETHOD GetAccRole(PRUint32 *aAccRole);
NS_IMETHOD GetAccState(PRUint32 *aAccState);
protected:
nsCOMPtr<nsIAccessible> mInnerDocAccessible;
};
#endif

View File

@ -51,8 +51,6 @@
#include "nsIDOMNSEvent.h"
#include "nsIDOMXULSelectCntrlEl.h"
#include "nsIDOMXULSelectCntrlItemEl.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeItem.h"
#include "nsIDocument.h"
#include "nsIFrame.h"
#include "nsIInterfaceRequestorUtils.h"
@ -74,44 +72,26 @@
#include "nsIAccessibleCaret.h"
#include "nsIDOMHTMLInputElement.h"
#include "nsAccessibleEventData.h"
#include "nsIDOMDocument.h"
NS_INTERFACE_MAP_BEGIN(nsRootAccessible)
NS_INTERFACE_MAP_ENTRY(nsIAccessibleEventReceiver)
NS_INTERFACE_MAP_ENTRY(nsIDOMFocusListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMFormListener)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
NS_INTERFACE_MAP_ENTRY(nsIScrollPositionListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMFormListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener, nsIDOMFormListener)
NS_INTERFACE_MAP_END_INHERITING(nsDocAccessible)
NS_IMPL_ADDREF_INHERITED(nsRootAccessible, nsDocAccessible);
NS_IMPL_RELEASE_INHERITED(nsRootAccessible, nsDocAccessible);
nsIDOMNode * nsRootAccessible::gLastFocusedNode = 0; // Strong reference
PRUint32 nsRootAccessible::gActiveRootAccessibles = 0;
//#define DEBUG_LEAKS 1 // aaronl debug
//-----------------------------------------------------
// construction
//-----------------------------------------------------
nsRootAccessible::nsRootAccessible(nsIDOMNode *aDOMNode, nsIWeakReference* aShell):
nsDocAccessibleWrap(aDOMNode, aShell),
mListener(nsnull),
mScrollWatchTimer(nsnull), mDocLoadTimer(nsnull), mWebProgress(nsnull),
mAccService(do_GetService("@mozilla.org/accessibilityService;1")),
mBusy(eBusyStateUninitialized), mIsNewDocument(PR_FALSE),
mScrollPositionChangedTicks(0)
mAccService(do_GetService("@mozilla.org/accessibilityService;1"))
{
++gActiveRootAccessibles;
#ifdef DEBUG_LEAKS
printf("=====> %d nsRootAccessible's %x\n", gActiveRootAccessibles, (PRUint32)this);
#endif
}
//-----------------------------------------------------
@ -119,15 +99,6 @@ nsRootAccessible::nsRootAccessible(nsIDOMNode *aDOMNode, nsIWeakReference* aShel
//-----------------------------------------------------
nsRootAccessible::~nsRootAccessible()
{
#ifdef DEBUG_LEAKS
printf("======> %d nsRootAccessible's %x\n", gActiveRootAccessibles, (PRUint32)this);
#endif
}
/* attribute wstring accName; */
NS_IMETHODIMP nsRootAccessible::GetAccName(nsAString& aAccName)
{
return GetTitle(aAccName);
}
// helpers
@ -141,6 +112,10 @@ NS_IMETHODIMP nsRootAccessible::GetAccParent(nsIAccessible * *aAccParent)
/* readonly attribute unsigned long accRole; */
NS_IMETHODIMP nsRootAccessible::GetAccRole(PRUint32 *aAccRole)
{
if (!mDocument) {
return NS_ERROR_FAILURE;
}
*aAccRole = ROLE_PANE;
// If it's a <dialog>, use ROLE_DIALOG instead
@ -159,114 +134,8 @@ NS_IMETHODIMP nsRootAccessible::GetAccRole(PRUint32 *aAccRole)
return NS_OK;
}
NS_IMETHODIMP nsRootAccessible::GetAccState(PRUint32 *aAccState)
NS_IMETHODIMP nsRootAccessible::AddEventListeners()
{
*aAccState = STATE_FOCUSABLE;
if (mBusy == eBusyStateLoading)
*aAccState |= STATE_BUSY;
return NS_OK;
}
NS_IMETHODIMP nsRootAccessible::GetAccValue(nsAString& aAccValue)
{
return GetURL(aAccValue);
}
void nsRootAccessible::DocLoadCallback(nsITimer *aTimer, void *aClosure)
{
// Doc has finished loading, fire "load finished" event
// This path is only used if the doc was already finished loading
// when the RootAccessible was created.
// Otherwise, ::OnStateChange() fires the event when doc is loaded.
nsRootAccessible *rootAcc = NS_REINTERPRET_CAST(nsRootAccessible*, aClosure);
if (rootAcc)
rootAcc->FireDocLoadFinished();
}
void nsRootAccessible::ScrollTimerCallback(nsITimer *aTimer, void *aClosure)
{
nsRootAccessible *rootAcc = NS_REINTERPRET_CAST(nsRootAccessible*, aClosure);
if (rootAcc && rootAcc->mScrollPositionChangedTicks &&
++rootAcc->mScrollPositionChangedTicks > 2) {
// Whenever scroll position changes, mScrollPositionChangeTicks gets reset to 1
// We only want to fire accessibilty scroll event when scrolling stops or pauses
// Therefore, we wait for no scroll events to occur between 2 ticks of this timer
// That indicates a pause in scrolling, so we fire the accessibilty scroll event
rootAcc->HandleEvent(nsIAccessibleEventListener::EVENT_SCROLLINGEND, rootAcc, nsnull);
rootAcc->mScrollPositionChangedTicks = 0;
rootAcc->mScrollWatchTimer->Cancel();
rootAcc->mScrollWatchTimer = nsnull;
}
}
void nsRootAccessible::AddScrollListener(nsIPresShell *aPresShell)
{
nsCOMPtr<nsIViewManager> vm;
if (aPresShell)
aPresShell->GetViewManager(getter_AddRefs(vm));
nsIScrollableView* scrollableView = nsnull;
if (vm)
vm->GetRootScrollableView(&scrollableView);
if (scrollableView)
scrollableView->AddScrollPositionListener(NS_STATIC_CAST(nsIScrollPositionListener *, this));
}
void nsRootAccessible::RemoveScrollListener(nsIPresShell *aPresShell)
{
nsCOMPtr<nsIViewManager> vm;
if (aPresShell)
aPresShell->GetViewManager(getter_AddRefs(vm));
nsIScrollableView* scrollableView = nsnull;
if (vm)
vm->GetRootScrollableView(&scrollableView);
if (scrollableView)
scrollableView->RemoveScrollPositionListener(NS_STATIC_CAST(nsIScrollPositionListener *, this));
}
NS_IMETHODIMP nsRootAccessible::ScrollPositionWillChange(nsIScrollableView *aView, nscoord aX, nscoord aY)
{
return NS_OK;
}
NS_IMETHODIMP nsRootAccessible::ScrollPositionDidChange(nsIScrollableView *aScrollableView, nscoord aX, nscoord aY)
{
if (mListener) {
// Start new timer, if the timer cycles at least 1 full cycle without more scroll position changes,
// then the ::Notify() method will fire the accessibility event for scroll position changes
const PRUint32 kScrollPosCheckWait = 50;
if (mScrollWatchTimer) {
mScrollWatchTimer->SetDelay(kScrollPosCheckWait); // Create new timer, to avoid leaks
}
else {
mScrollWatchTimer = do_CreateInstance("@mozilla.org/timer;1");
if (mScrollWatchTimer) {
mScrollWatchTimer->InitWithFuncCallback(ScrollTimerCallback, this,
kScrollPosCheckWait,
nsITimer::TYPE_REPEATING_SLACK);
}
}
mScrollPositionChangedTicks = 1;
}
return NS_OK;
}
/* void addAccessibleEventListener (in nsIAccessibleEventListener aListener); */
NS_IMETHODIMP nsRootAccessible::AddAccessibleEventListener(nsIAccessibleEventListener *aListener)
{
NS_ASSERTION(aListener, "Trying to add a null listener!");
if (mListener)
return NS_OK;
mListener = aListener;
// use AddEventListener from the nsIDOMEventTarget interface
nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(mDocument));
if (target) {
@ -306,46 +175,40 @@ NS_IMETHODIMP nsRootAccessible::AddAccessibleEventListener(nsIAccessibleEventLis
AddContentDocListeners();
}
if (!mCaretAccessible && mListener)
mAccService->CreateCaretAccessible(mDOMNode, mListener, getter_AddRefs(mCaretAccessible));
if (!mCaretAccessible)
mAccService->CreateCaretAccessible(mDOMNode, this, getter_AddRefs(mCaretAccessible));
return NS_OK;
}
/* void removeAccessibleEventListener (); */
NS_IMETHODIMP nsRootAccessible::RemoveAccessibleEventListener()
NS_IMETHODIMP nsRootAccessible::RemoveEventListeners()
{
if (mListener) {
nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(mDocument));
if (target) {
target->RemoveEventListener(NS_LITERAL_STRING("focus"), NS_STATIC_CAST(nsIDOMFocusListener*, this), PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("select"), NS_STATIC_CAST(nsIDOMFormListener*, this), PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("CheckboxStateChange"), NS_STATIC_CAST(nsIDOMXULListener*, this), PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("RadioStateChange"), NS_STATIC_CAST(nsIDOMXULListener*, this), PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("ListitemStateChange"), NS_STATIC_CAST(nsIDOMXULListener*, this), PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("popupshowing"), NS_STATIC_CAST(nsIDOMXULListener*, this), PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("popuphiding"), NS_STATIC_CAST(nsIDOMXULListener*, this), PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("DOMMenuItemActive"), NS_STATIC_CAST(nsIDOMXULListener*, this), PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("DOMMenuBarActive"), NS_STATIC_CAST(nsIDOMXULListener*, this), PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("DOMMenuBarInactive"), NS_STATIC_CAST(nsIDOMXULListener*, this), PR_TRUE);
}
if (mScrollWatchTimer) {
mScrollWatchTimer->Cancel();
mScrollWatchTimer = nsnull;
}
if (mDocLoadTimer) {
mDocLoadTimer->Cancel();
mDocLoadTimer = nsnull;
}
RemoveContentDocListeners();
mListener = nsnull;
nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(mDocument));
if (target) {
target->RemoveEventListener(NS_LITERAL_STRING("focus"), NS_STATIC_CAST(nsIDOMFocusListener*, this), PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("select"), NS_STATIC_CAST(nsIDOMFormListener*, this), PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("CheckboxStateChange"), NS_STATIC_CAST(nsIDOMXULListener*, this), PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("RadioStateChange"), NS_STATIC_CAST(nsIDOMXULListener*, this), PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("ListitemStateChange"), NS_STATIC_CAST(nsIDOMXULListener*, this), PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("popupshowing"), NS_STATIC_CAST(nsIDOMXULListener*, this), PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("popuphiding"), NS_STATIC_CAST(nsIDOMXULListener*, this), PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("DOMMenuItemActive"), NS_STATIC_CAST(nsIDOMXULListener*, this), PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("DOMMenuBarActive"), NS_STATIC_CAST(nsIDOMXULListener*, this), PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("DOMMenuBarInactive"), NS_STATIC_CAST(nsIDOMXULListener*, this), PR_TRUE);
}
if (mScrollWatchTimer) {
mScrollWatchTimer->Cancel();
mScrollWatchTimer = nsnull;
}
if (mDocLoadTimer) {
mDocLoadTimer->Cancel();
mDocLoadTimer = nsnull;
}
RemoveContentDocListeners();
if (mCaretAccessible) {
mCaretAccessible->RemoveSelectionListener();
mCaretAccessible = nsnull;
@ -366,13 +229,12 @@ NS_IMETHODIMP nsRootAccessible::GetCaretAccessible(nsIAccessibleCaret **aCaretAc
void nsRootAccessible::FireAccessibleFocusEvent(nsIAccessible *focusAccessible, nsIDOMNode *focusNode)
{
if (focusAccessible && focusNode && gLastFocusedNode != focusNode) {
HandleEvent(nsIAccessibleEventListener::EVENT_FOCUS, focusAccessible, nsnull);
focusAccessible->FireToolkitEvent(nsIAccessibleEventReceiver::EVENT_FOCUS, focusAccessible, nsnull);
NS_IF_RELEASE(gLastFocusedNode);
PRUint32 role = ROLE_NOTHING;
focusAccessible->GetAccRole(&role);
if (role == ROLE_MENUITEM || role == ROLE_LISTITEM)
gLastFocusedNode = nsnull; // This makes it report all focus events on menu and list items
else {
if (role != ROLE_MENUITEM && role != ROLE_LISTITEM) {
// It must report all focus events on menu and list items
gLastFocusedNode = focusNode;
NS_IF_ADDREF(gLastFocusedNode);
}
@ -385,177 +247,195 @@ void nsRootAccessible::FireAccessibleFocusEvent(nsIAccessible *focusAccessible,
NS_IMETHODIMP nsRootAccessible::HandleEvent(nsIDOMEvent* aEvent)
{
if (mListener) {
// optionTargetNode is set to current option for HTML selects
nsCOMPtr<nsIDOMNode> targetNode, optionTargetNode;
GetTargetNode(aEvent, getter_AddRefs(targetNode));
if (!targetNode)
return NS_ERROR_FAILURE;
// optionTargetNode is set to current option for HTML selects
nsCOMPtr<nsIDOMNode> targetNode, optionTargetNode;
GetTargetNode(aEvent, getter_AddRefs(targetNode));
if (!targetNode)
return NS_ERROR_FAILURE;
// Check to see if it's a select element. If so, need the currently focused option
nsCOMPtr<nsIDOMHTMLSelectElement> selectElement(do_QueryInterface(targetNode));
if (selectElement) // ----- Target Node is an HTML <select> element ------
nsHTMLSelectOptionAccessible::GetFocusedOptionNode(targetNode, getter_AddRefs(optionTargetNode));
// Check to see if it's a select element. If so, need the currently focused option
nsCOMPtr<nsIDOMHTMLSelectElement> selectElement(do_QueryInterface(targetNode));
if (selectElement) // ----- Target Node is an HTML <select> element ------
nsHTMLSelectOptionAccessible::GetFocusedOptionNode(targetNode, getter_AddRefs(optionTargetNode));
// for focus events on Radio Groups we give the focus to the selected button
nsCOMPtr<nsIDOMXULSelectControlElement> selectControl(do_QueryInterface(targetNode));
if (selectControl) {
nsCOMPtr<nsIDOMXULSelectControlItemElement> selectItem;
selectControl->GetSelectedItem(getter_AddRefs(selectItem));
optionTargetNode = do_QueryInterface(selectItem);
}
// for focus events on Radio Groups we give the focus to the selected button
nsCOMPtr<nsIDOMXULSelectControlElement> selectControl(do_QueryInterface(targetNode));
if (selectControl) {
nsCOMPtr<nsIDOMXULSelectControlItemElement> selectItem;
selectControl->GetSelectedItem(getter_AddRefs(selectItem));
optionTargetNode = do_QueryInterface(selectItem);
}
#ifdef MOZ_ACCESSIBILITY_ATK
nsCOMPtr<nsIDOMHTMLAnchorElement> anchorElement(do_QueryInterface(targetNode));
if (anchorElement) {
nsCOMPtr<nsIDOMNode> blockNode;
// For ATK, we don't create any individual object for hyperlink, use its parent who has block frame instead
nsAccessible::GetParentBlockNode(targetNode, getter_AddRefs(blockNode));
targetNode = blockNode;
}
nsCOMPtr<nsIDOMHTMLAnchorElement> anchorElement(do_QueryInterface(targetNode));
if (anchorElement) {
nsCOMPtr<nsIDOMNode> blockNode;
// For ATK, we don't create any individual object for hyperlink, use its parent who has block frame instead
nsAccessible::GetParentBlockNode(targetNode, getter_AddRefs(blockNode));
targetNode = blockNode;
}
#endif
nsCOMPtr<nsIAccessible> accessible;
if (targetNode == mDOMNode) {
QueryInterface(NS_GET_IID(nsIAccessible), getter_AddRefs(accessible));
}
else if (NS_FAILED(mAccService->GetAccessibleFor(targetNode, getter_AddRefs(accessible))))
return NS_OK;
nsCOMPtr<nsIAccessible> accessible;
// XXX aaronl - this is not ideal.
// We could avoid this whole section and the fallible
// doc->GetShellAt(0, ...) by putting the event handler
// on nsDocAccessible instead.
// The disadvantage would be that we would be seeing some events
// for inner documents that we don't care about.
nsCOMPtr<nsIDOMDocument> domDocument;
targetNode->GetOwnerDocument(getter_AddRefs(domDocument));
nsCOMPtr<nsIDocument> doc(do_QueryInterface(domDocument));
nsCOMPtr<nsIPresShell> eventShell;
if (doc) {
doc->GetShellAt(0, getter_AddRefs(eventShell));
}
if (!eventShell ||
NS_FAILED(mAccService->GetAccessibleInShell(targetNode, eventShell,
getter_AddRefs(accessible))))
return NS_OK;
#ifdef MOZ_XUL
// If it's a tree element, need the currently selected item
PRInt32 treeIndex = -1;
nsCOMPtr<nsITreeBoxObject> treeBox;
nsCOMPtr<nsIAccessible> treeItemAccessible;
nsXULTreeAccessible::GetTreeBoxObject(targetNode, getter_AddRefs(treeBox));
if (treeBox) {
nsCOMPtr<nsITreeSelection> selection;
treeBox->GetSelection(getter_AddRefs(selection));
if (selection) {
selection->GetCurrentIndex(&treeIndex);
if (treeIndex >= 0) {
nsCOMPtr<nsIWeakReference> weakShell;
nsAccessibilityService::GetShellFromNode(targetNode, getter_AddRefs(weakShell));
treeItemAccessible = new nsXULTreeitemAccessible(accessible, targetNode, weakShell, treeIndex);
if (!treeItemAccessible)
return NS_ERROR_OUT_OF_MEMORY;
}
// If it's a tree element, need the currently selected item
PRInt32 treeIndex = -1;
nsCOMPtr<nsITreeBoxObject> treeBox;
nsCOMPtr<nsIAccessible> treeItemAccessible;
nsXULTreeAccessible::GetTreeBoxObject(targetNode, getter_AddRefs(treeBox));
if (treeBox) {
nsCOMPtr<nsITreeSelection> selection;
treeBox->GetSelection(getter_AddRefs(selection));
if (selection) {
selection->GetCurrentIndex(&treeIndex);
if (treeIndex >= 0) {
// XXX todo Kyle - fix bug 201922 so that tree is respohsible for keeping track
// of it's own accessibles. Then we'll ask the tree so we can reuse
// the accessibles already created.
nsCOMPtr<nsIWeakReference> weakEventShell(do_GetWeakReference(eventShell));
treeItemAccessible = new nsXULTreeitemAccessible(accessible, targetNode,
weakEventShell, treeIndex);
if (!treeItemAccessible)
return NS_ERROR_OUT_OF_MEMORY;
}
}
}
#endif
nsAutoString eventType;
aEvent->GetType(eventType);
nsAutoString eventType;
aEvent->GetType(eventType);
#ifndef MOZ_ACCESSIBILITY_ATK
#ifdef MOZ_XUL
// tree event
if (treeItemAccessible &&
(eventType.EqualsIgnoreCase("DOMMenuItemActive") || eventType.EqualsIgnoreCase("select"))) {
HandleEvent(nsIAccessibleEventListener::EVENT_FOCUS, treeItemAccessible, nsnull);
return NS_OK;
}
// tree event
if (treeItemAccessible &&
(eventType.EqualsIgnoreCase("DOMMenuItemActive") || eventType.EqualsIgnoreCase("select"))) {
treeItemAccessible->FireToolkitEvent(nsIAccessibleEventReceiver::EVENT_FOCUS, treeItemAccessible, nsnull);
return NS_OK;
}
#endif
if (eventType.EqualsIgnoreCase("focus") || eventType.EqualsIgnoreCase("DOMMenuItemActive")) {
if (optionTargetNode &&
NS_SUCCEEDED(mAccService->GetAccessibleFor(optionTargetNode, getter_AddRefs(accessible)))) {
if (eventType.EqualsIgnoreCase("focus")) {
nsCOMPtr<nsIAccessible> selectAccessible;
mAccService->GetAccessibleFor(targetNode, getter_AddRefs(selectAccessible));
if (selectAccessible) {
FireAccessibleFocusEvent(selectAccessible, targetNode);
}
if (eventType.EqualsIgnoreCase("focus") || eventType.EqualsIgnoreCase("DOMMenuItemActive")) {
if (optionTargetNode &&
NS_SUCCEEDED(mAccService->GetAccessibleInShell(optionTargetNode, eventShell,
getter_AddRefs(accessible)))) {
if (eventType.EqualsIgnoreCase("focus")) {
nsCOMPtr<nsIAccessible> selectAccessible;
mAccService->GetAccessibleInShell(targetNode, eventShell,
getter_AddRefs(selectAccessible));
if (selectAccessible) {
FireAccessibleFocusEvent(selectAccessible, targetNode);
}
FireAccessibleFocusEvent(accessible, optionTargetNode);
}
else
FireAccessibleFocusEvent(accessible, targetNode);
}
else if (eventType.EqualsIgnoreCase("ListitemStateChange")) {
HandleEvent(nsIAccessibleEventListener::EVENT_STATE_CHANGE, accessible, nsnull);
FireAccessibleFocusEvent(accessible, optionTargetNode);
}
else if (eventType.EqualsIgnoreCase("CheckboxStateChange")) {
HandleEvent(nsIAccessibleEventListener::EVENT_STATE_CHANGE, accessible, nsnull);
}
else if (eventType.EqualsIgnoreCase("RadioStateChange") ) {
// first the XUL radio buttons
if (targetNode &&
NS_SUCCEEDED(mAccService->GetAccessibleFor(targetNode, getter_AddRefs(accessible)))) {
HandleEvent(nsIAccessibleEventListener::EVENT_STATE_CHANGE, accessible, nsnull);
FireAccessibleFocusEvent(accessible, targetNode);
}
else { // for the html radio buttons -- apparently the focus code just works. :-)
HandleEvent(nsIAccessibleEventListener::EVENT_STATE_CHANGE, accessible, nsnull);
}
}
else if (eventType.EqualsIgnoreCase("DOMMenuBarActive"))
HandleEvent(nsIAccessibleEventListener::EVENT_MENUSTART, accessible, nsnull);
else if (eventType.EqualsIgnoreCase("DOMMenuBarInactive")) {
HandleEvent(nsIAccessibleEventListener::EVENT_MENUEND, accessible, nsnull);
GetAccFocused(getter_AddRefs(accessible));
if (accessible) {
accessible->AccGetDOMNode(getter_AddRefs(targetNode));
FireAccessibleFocusEvent(accessible, targetNode);
}
}
else {
// Menu popup events
PRUint32 menuEvent = 0;
if (eventType.EqualsIgnoreCase("popupshowing"))
menuEvent = nsIAccessibleEventListener::EVENT_MENUPOPUPSTART;
else if (eventType.EqualsIgnoreCase("popuphiding"))
menuEvent = nsIAccessibleEventListener::EVENT_MENUPOPUPEND;
if (menuEvent) {
PRUint32 role = ROLE_NOTHING;
accessible->GetAccRole(&role);
if (role == ROLE_MENUPOPUP)
HandleEvent(menuEvent, accessible, nsnull);
}
}
#else
AtkStateChange stateData;
if (eventType.EqualsIgnoreCase("focus") || eventType.EqualsIgnoreCase("DOMMenuItemActive")) {
if (treeItemAccessible) // use focused treeitem
HandleEvent(nsIAccessibleEventListener::EVENT_FOCUS, treeItemAccessible, nsnull);
else if (anchorElement) {
nsCOMPtr<nsIAccessibleHyperText> hyperText(do_QueryInterface(accessible));
if (hyperText) {
PRInt32 selectedLink;
hyperText->GetSelectedLinkIndex(&selectedLink);
HandleEvent(nsIAccessibleEventListener::EVENT_ATK_LINK_SELECTED, accessible, &selectedLink);
}
}
else if (optionTargetNode && // use focused option
NS_SUCCEEDED(mAccService->GetAccessibleFor(optionTargetNode, getter_AddRefs(accessible))))
FireAccessibleFocusEvent(accessible, optionTargetNode);
else
FireAccessibleFocusEvent(accessible, targetNode);
}
else if (eventType.EqualsIgnoreCase("select")) {
if (treeBox && treeIndex >= 0) // it's a XUL <tree>
// use EVENT_FOCUS instead of EVENT_ATK_SELECTION_CHANGE
HandleEvent(nsIAccessibleEventListener::EVENT_FOCUS, treeItemAccessible, nsnull);
}
else if (eventType.EqualsIgnoreCase("ListitemStateChange")) // it's a XUL <listbox>
HandleEvent(nsIAccessibleEventListener::EVENT_FOCUS, accessible, nsnull);
else if (eventType.EqualsIgnoreCase("CheckboxStateChange") || // it's a XUL <checkbox>
eventType.EqualsIgnoreCase("RadioStateChange")) { // it's a XUL <radio>
accessible->GetAccState(&stateData.state);
stateData.enable = (stateData.state & STATE_CHECKED) != 0;
stateData.state = STATE_CHECKED;
HandleEvent(nsIAccessibleEventListener::EVENT_STATE_CHANGE, accessible, &stateData);
if (eventType.EqualsIgnoreCase("RadioStateChange")) {
FireAccessibleFocusEvent(accessible, targetNode);
}
}
else if (eventType.EqualsIgnoreCase("popupshowing"))
else
FireAccessibleFocusEvent(accessible, targetNode);
else if (eventType.EqualsIgnoreCase("popuphiding"))
FireAccessibleFocusEvent(accessible, targetNode);
#endif
}
else if (eventType.EqualsIgnoreCase("ListitemStateChange")) {
accessible->FireToolkitEvent(nsIAccessibleEventReceiver::EVENT_STATE_CHANGE, accessible, nsnull);
FireAccessibleFocusEvent(accessible, optionTargetNode);
}
else if (eventType.EqualsIgnoreCase("CheckboxStateChange")) {
accessible->FireToolkitEvent(nsIAccessibleEventReceiver::EVENT_STATE_CHANGE, accessible, nsnull);
}
else if (eventType.EqualsIgnoreCase("RadioStateChange") ) {
// first the XUL radio buttons
if (targetNode &&
NS_SUCCEEDED(mAccService->GetAccessibleInShell(targetNode, eventShell,
getter_AddRefs(accessible)))) {
accessible->FireToolkitEvent(nsIAccessibleEventReceiver::EVENT_STATE_CHANGE, accessible, nsnull);
FireAccessibleFocusEvent(accessible, targetNode);
}
else { // for the html radio buttons -- apparently the focus code just works. :-)
accessible->FireToolkitEvent(nsIAccessibleEventReceiver::EVENT_STATE_CHANGE, accessible, nsnull);
}
}
else if (eventType.EqualsIgnoreCase("DOMMenuBarActive"))
accessible->FireToolkitEvent(nsIAccessibleEventReceiver::EVENT_MENUSTART, accessible, nsnull);
else if (eventType.EqualsIgnoreCase("DOMMenuBarInactive")) {
accessible->FireToolkitEvent(nsIAccessibleEventReceiver::EVENT_MENUEND, accessible, nsnull);
GetAccFocused(getter_AddRefs(accessible));
if (accessible) {
accessible->AccGetDOMNode(getter_AddRefs(targetNode));
FireAccessibleFocusEvent(accessible, targetNode);
}
}
else {
// Menu popup events
PRUint32 menuEvent = 0;
if (eventType.EqualsIgnoreCase("popupshowing"))
menuEvent = nsIAccessibleEventReceiver::EVENT_MENUPOPUPSTART;
else if (eventType.EqualsIgnoreCase("popuphiding"))
menuEvent = nsIAccessibleEventReceiver::EVENT_MENUPOPUPEND;
if (menuEvent) {
PRUint32 role = ROLE_NOTHING;
accessible->GetAccRole(&role);
if (role == ROLE_MENUPOPUP)
accessible->FireToolkitEvent(menuEvent, accessible, nsnull);
}
}
#else
AtkStateChange stateData;
if (eventType.EqualsIgnoreCase("focus") || eventType.EqualsIgnoreCase("DOMMenuItemActive")) {
if (treeItemAccessible) // use focused treeitem
treeItemAccessible->FireToolkitEvent(nsIAccessibleEventReceiver::EVENT_FOCUS, treeItemAccessible, nsnull);
else if (anchorElement) {
nsCOMPtr<nsIAccessibleHyperText> hyperText(do_QueryInterface(accessible));
if (hyperText) {
PRInt32 selectedLink;
hyperText->GetSelectedLinkIndex(&selectedLink);
accessible->FireToolkitEvent(nsIAccessibleEventReceiver::EVENT_ATK_LINK_SELECTED, accessible, &selectedLink);
}
}
else if (optionTargetNode && // use focused option
NS_SUCCEEDED(mAccService->GetAccessibleInShell(optionTargetNode, eventShell,
getter_AddRefs(accessible))))
FireAccessibleFocusEvent(accessible, optionTargetNode);
else
FireAccessibleFocusEvent(accessible, targetNode);
}
else if (eventType.EqualsIgnoreCase("select")) {
if (treeBox && treeIndex >= 0) // it's a XUL <tree>
// use EVENT_FOCUS instead of EVENT_ATK_SELECTION_CHANGE
treeItemAccessible->FireToolkitEvent(nsIAccessibleEventReceiver::EVENT_FOCUS, treeItemAccessible, nsnull);
}
else if (eventType.EqualsIgnoreCase("ListitemStateChange")) // it's a XUL <listbox>
accessible->FireToolkitEvent(nsIAccessibleEventReceiver::EVENT_FOCUS, accessible, nsnull);
else if (eventType.EqualsIgnoreCase("CheckboxStateChange") || // it's a XUL <checkbox>
eventType.EqualsIgnoreCase("RadioStateChange")) { // it's a XUL <radio>
accessible->GetAccState(&stateData.state);
stateData.enable = (stateData.state & STATE_CHECKED) != 0;
stateData.state = STATE_CHECKED;
accessible->FireToolkitEvent(nsIAccessibleEventReceiver::EVENT_STATE_CHANGE, accessible, &stateData);
if (eventType.EqualsIgnoreCase("RadioStateChange")) {
FireAccessibleFocusEvent(accessible, targetNode);
}
}
else if (eventType.EqualsIgnoreCase("popupshowing"))
FireAccessibleFocusEvent(accessible, targetNode);
else if (eventType.EqualsIgnoreCase("popuphiding"))
FireAccessibleFocusEvent(accessible, targetNode);
#endif
return NS_OK;
}
@ -573,13 +453,6 @@ void nsRootAccessible::GetTargetNode(nsIDOMEvent *aEvent, nsIDOMNode **aTargetNo
}
}
NS_IMETHODIMP nsRootAccessible::HandleEvent(PRUint32 aEvent, nsIAccessible *aTarget, void * aData)
{
if (mListener)
mListener->HandleEvent(aEvent, aTarget, aData);
return NS_OK;
}
// ------- nsIDOMFocusListener Methods (1) -------------
NS_IMETHODIMP nsRootAccessible::Focus(nsIDOMEvent* aEvent)
@ -607,10 +480,10 @@ NS_IMETHODIMP nsRootAccessible::Reset(nsIDOMEvent* aEvent)
NS_IMETHODIMP nsRootAccessible::Change(nsIDOMEvent* aEvent)
{
// get change events when the form elements changes its state, checked->not,
// deleted text, new text, change in selection for list/combo boxes
// deleted text, new text, change in selection for list/combo boxes
// this may be the event that we have the individual Accessible objects
// handle themselves -- have list/combos figure out the change in selection
// have textareas and inputs fire a change of state etc...
// handle themselves -- have list/combos figure out the change in selection
// have textareas and inputs fire a change of state etc...
return NS_OK; // Ignore form change events in MSAA
}
@ -644,192 +517,15 @@ NS_IMETHODIMP nsRootAccessible::Broadcast(nsIDOMEvent* aEvent) { return NS_OK; }
NS_IMETHODIMP nsRootAccessible::CommandUpdate(nsIDOMEvent* aEvent) { return NS_OK; }
void nsRootAccessible::RemoveContentDocListeners()
{
// Remove listeners associated with content documents
// Remove web progress listener
if (mWebProgress) {
mWebProgress->RemoveProgressListener(this);
mWebProgress = nsnull;
}
// Remove scroll position listener
nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mPresShell));
RemoveScrollListener(presShell);
}
void nsRootAccessible::AddContentDocListeners()
{
// 1) Set up scroll position listener
// 2) Set up web progress listener - we need to know
// when page loading is finished
// That way we can send the STATE_CHANGE events for
// the MSAA root "pane" object (ROLE_PANE),
// and change the STATE_BUSY bit flag
// Do this only for top level content documents
nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mPresShell));
if (!presShell)
return;
AddScrollListener(presShell);
nsCOMPtr<nsISupports> container;
mDocument->GetContainer(getter_AddRefs(container));
nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem(do_QueryInterface(container));
if (!docShellTreeItem)
return;
// Make sure we're a content docshell
// We don't want to listen to chrome progress
PRInt32 itemType;
docShellTreeItem->GetItemType(&itemType);
if (itemType != nsIDocShellTreeItem::typeContent)
return;
// Make sure we're the top content doc shell
// We don't want to listen to iframe progress
nsCOMPtr<nsIDocShellTreeItem> topOfContentTree;
docShellTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(topOfContentTree));
if (topOfContentTree != docShellTreeItem)
return;
nsCOMPtr<nsIPresContext> context;
presShell->GetPresContext(getter_AddRefs(context));
if (!context)
return;
mWebProgress = do_GetInterface(docShellTreeItem);
if (!mWebProgress)
return;
mWebProgress->AddProgressListener(this, nsIWebProgress::NOTIFY_LOCATION |
nsIWebProgress::NOTIFY_STATE_DOCUMENT);
mIsNewDocument = PR_TRUE;
mBusy = eBusyStateLoading;
PRBool isLoading;
mWebProgress->GetIsLoadingDocument(&isLoading);
if (!isLoading) {
// If already loaded, fire "done loading" event after short timeout
// If we fired the event here, we'd get reentrancy problems
// Otherwise it will be fired from OnStateChange when the load is done
mDocLoadTimer = do_CreateInstance("@mozilla.org/timer;1");
if (mDocLoadTimer) {
mDocLoadTimer->InitWithFuncCallback(DocLoadCallback, this, 1,
nsITimer::TYPE_ONE_SHOT);
}
}
}
void nsRootAccessible::FireDocLoadFinished()
{
if (mIsNewDocument) {
mIsNewDocument = PR_FALSE;
if (mBusy != eBusyStateDone) {
mBusy = eBusyStateDone;
#ifndef MOZ_ACCESSIBILITY_ATK
HandleEvent(nsIAccessibleEventListener::EVENT_STATE_CHANGE, this, nsnull);
#endif
}
}
}
NS_IMETHODIMP nsRootAccessible::OnStateChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest, PRUint32 aStateFlags, nsresult aStatus)
{
if ((aStateFlags & STATE_IS_DOCUMENT) && (aStateFlags & STATE_STOP))
FireDocLoadFinished(); // Doc is ready!
return NS_OK;
}
/* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */
NS_IMETHODIMP nsRootAccessible::OnProgressChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress,
PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress)
{
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
return NS_OK;
}
/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */
NS_IMETHODIMP nsRootAccessible::OnLocationChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest, nsIURI *location)
{
// Load has been verified, it will occur, about to commence
// We won't fire a "doc finished loading" event on this nsRootAccessible
// Instead we fire that on the new nsRootAccessible that is created for the new doc
mIsNewDocument = PR_FALSE; // We're a doc that's going away
if (mBusy != eBusyStateLoading) {
mBusy = eBusyStateLoading;
// Fire a "new doc has started to load" event
#ifndef MOZ_ACCESSIBILITY_ATK
HandleEvent(nsIAccessibleEventListener::EVENT_STATE_CHANGE, this, nsnull);
#else
AtkChildrenChange childrenData;
childrenData.index = -1;
childrenData.child = 0;
childrenData.add = PR_FALSE;
HandleEvent(nsIAccessibleEventListener::EVENT_REORDER , this, &childrenData);
#endif
}
return NS_OK;
}
/* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
NS_IMETHODIMP nsRootAccessible::OnStatusChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage)
{
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
return NS_OK;
}
/* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long state); */
NS_IMETHODIMP nsRootAccessible::OnSecurityChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest, PRUint32 state)
{
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
return NS_OK;
}
NS_IMETHODIMP nsRootAccessible::Shutdown()
{
// Called manually or by nsAccessNode::~nsAccessNode()
if (mDOMNode) {
RemoveAccessibleEventListener();
if (--gActiveRootAccessibles == 0) // Last root accessible.
ShutdownAll();
if (!mWeakShell) {
return NS_OK; // Already shutdown
}
mCaretAccessible = nsnull;
mAccService = nsnull;
return nsDocAccessibleWrap::Shutdown();
}
void nsRootAccessible::ShutdownAll()
{
// Turn accessibility support off and destroy all objects rather
// than waiting until shutdown otherwise there will be crashes when
// releases occur in modules that are no longer loaded
NS_IF_RELEASE(gLastFocusedNode);
NS_IF_RELEASE(nsAccessible::gStringBundle);
NS_IF_RELEASE(nsAccessible::gKeyStringBundle);
// Shutdown accessibility service
nsCOMPtr<nsIAccessibilityService> accService =
do_GetService("@mozilla.org/accessibilityService;1");
if (accService) {
accService->Shutdown();
}
}

View File

@ -41,47 +41,33 @@
#include "nsDocAccessibleWrap.h"
#include "nsIAccessibleEventReceiver.h"
#include "nsIAccessibleEventListener.h"
#include "nsIAccessibleDocument.h"
#include "nsIDOMFormListener.h"
#include "nsIDOMXULListener.h"
#include "nsIDOMFocusListener.h"
#include "nsIDocument.h"
#include "nsIAccessibilityService.h"
#include "nsIWebProgressListener.h"
#include "nsIWeakReference.h"
#include "nsITimer.h"
#include "nsIWebProgress.h"
#include "nsIScrollPositionListener.h"
#include "nsIScrollableView.h"
#include "nsHashtable.h"
class nsIAccessibleEventListener;
const PRInt32 SCROLL_HASH_START_SIZE = 6;
class nsRootAccessible : public nsDocAccessibleWrap,
public nsIDOMFocusListener,
public nsIDOMFormListener,
public nsIDOMXULListener,
public nsIWebProgressListener,
public nsIScrollPositionListener,
public nsSupportsWeakReference
public nsIDOMXULListener
{
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIACCESSIBLEEVENTRECEIVER
public:
enum EBusyState {eBusyStateUninitialized, eBusyStateLoading, eBusyStateDone};
nsRootAccessible(nsIDOMNode *aDOMNode, nsIWeakReference* aShell);
virtual ~nsRootAccessible();
/* attribute wstring accName; */
NS_IMETHOD GetAccName(nsAString& aAccName);
NS_IMETHOD GetAccValue(nsAString& aAccValue);
NS_IMETHOD GetAccParent(nsIAccessible * *aAccParent);
NS_IMETHOD GetAccRole(PRUint32 *aAccRole);
NS_IMETHOD GetAccState(PRUint32 *aAccState);
NS_IMETHOD HandleEvent(PRUint32 aEvent, nsIAccessible *aTarget, void * aData);
// ----- nsIDOMEventListener --------------------------
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
@ -107,50 +93,18 @@ class nsRootAccessible : public nsDocAccessibleWrap,
NS_IMETHOD Broadcast(nsIDOMEvent* aEvent);
NS_IMETHOD CommandUpdate(nsIDOMEvent* aEvent);
// ----- nsIScrollPositionListener ---------------------------
NS_IMETHOD ScrollPositionWillChange(nsIScrollableView *aView, nscoord aX, nscoord aY);
NS_IMETHOD ScrollPositionDidChange(nsIScrollableView *aView, nscoord aX, nscoord aY);
NS_DECL_NSIWEBPROGRESSLISTENER
// nsIAccessibleDocument
NS_IMETHOD GetCaretAccessible(nsIAccessibleCaret **aAccessibleCaret);
// nsIAccessNode
NS_IMETHOD Shutdown();
void ShutdownAll();
protected:
void GetTargetNode(nsIDOMEvent *aEvent, nsIDOMNode **aTargetNode);
void FireAccessibleFocusEvent(nsIAccessible *focusAccessible, nsIDOMNode *focusNode);
void AddScrollListener(nsIPresShell *aPresShell);
void RemoveScrollListener(nsIPresShell *aPresShell);
void AddContentDocListeners();
void RemoveContentDocListeners();
void FireDocLoadFinished();
void ShutdownAll();
static void DocLoadCallback(nsITimer *aTimer, void *aClosure);
static void ScrollTimerCallback(nsITimer *aTimer, void *aClosure);
static PRUint32 gActiveRootAccessibles;
// mListener is not a com pointer. We don't own the listener
// it is the callers responsibility to remove the listener
// otherwise we will get into circular referencing problems
// We don't need a weak reference, because we're owned by this listener
nsIAccessibleEventListener *mListener;
static nsIDOMNode * gLastFocusedNode; // we do our own refcounting for this
nsCOMPtr<nsITimer> mScrollWatchTimer;
nsCOMPtr<nsITimer> mDocLoadTimer;
nsCOMPtr<nsIWebProgress> mWebProgress;
nsCOMPtr<nsIAccessibilityService> mAccService;
EBusyState mBusy;
PRPackedBool mIsNewDocument;
// Used for tracking scroll events
PRUint32 mScrollPositionChangedTicks;
nsCOMPtr<nsIAccessibleCaret> mCaretAccessible;
};

View File

@ -41,7 +41,6 @@
// NOTE: alphabetically ordered
#include "nsContentCID.h"
#include "nsIAccessibleEditableText.h"
#include "nsIAccessibleEventListener.h"
#include "nsIClipboard.h"
#include "nsIDOMAbstractView.h"
#include "nsIDOMCharacterData.h"
@ -67,6 +66,7 @@
#include "nsStyleStruct.h"
#include "nsTextAccessible.h"
#include "nsTextFragment.h"
#include "nsIAccessibleEventReceiver.h"
#ifdef MOZ_ACCESSIBILITY_ATK
@ -905,6 +905,7 @@ nsAccessibleEditableText::nsAccessibleEditableText()
nsAccessibleEditableText::~nsAccessibleEditableText()
{
// XXX todo bolian, needs to do this at shutdown, and set mEditor = nsnull
if (mEditor)
mEditor->RemoveEditActionListener(this);
}
@ -930,8 +931,10 @@ nsresult nsAccessibleEditableText::FireTextChangeEvent(AtkTextChange *aTextData)
{
nsCOMPtr<nsIAccessible> accessible(do_QueryInterface(NS_STATIC_CAST(nsIAccessibleText*, this)));
if (accessible) {
#ifdef DEBUG
printf(" [start=%d, length=%d, add=%d]\n", aTextData->start, aTextData->length, aTextData->add);
accessible->HandleEvent(nsIAccessibleEventListener::EVENT_ATK_TEXT_CHANGE, accessible, aTextData);
#endif
accessible->FireToolkitEvent(nsIAccessibleEventReceiver::EVENT_ATK_TEXT_CHANGE, accessible, aTextData);
}
return NS_OK;

View File

@ -1 +1,3 @@
accessibility_html_s.lib
accessibility_html_s.pdb
Makefile

View File

@ -55,7 +55,6 @@ CPPSRCS = \
nsHTMLFormControlAccessible.cpp \
nsHTMLImageAccessible.cpp \
nsHTMLLinkAccessible.cpp \
nsHTMLPluginAccessible.cpp \
nsHTMLSelectAccessible.cpp \
nsHTMLTableAccessible.cpp \
nsHTMLTextAccessible.cpp \

View File

@ -38,9 +38,6 @@
* ***** END LICENSE BLOCK ***** */
#include "nsHTMLAreaAccessible.h"
#include "nsReadableUtils.h"
#include "nsString.h"
#include "nsAccessible.h"
#include "nsIAccessibilityService.h"
#include "nsIServiceManager.h"
#include "nsIDOMElement.h"
@ -53,8 +50,10 @@
// --- area -----
nsHTMLAreaAccessible::nsHTMLAreaAccessible(nsIDOMNode *aDomNode, nsIAccessible *aAccParent, nsIWeakReference* aShell):
nsLinkableAccessible(aDomNode, aShell), mAccParent(aAccParent)
nsLinkableAccessible(aDomNode, aShell)
{
Init(); // Make sure we're in cache
mParent = aAccParent;
}
/* wstring getAccName (); */
@ -112,17 +111,20 @@ NS_IMETHODIMP nsHTMLAreaAccessible::GetAccChildCount(PRInt32 *_retval)
NS_IMETHODIMP nsHTMLAreaAccessible::GetAccParent(nsIAccessible * *aAccParent)
{
*aAccParent = mAccParent;
*aAccParent = mParent;
NS_IF_ADDREF(*aAccParent);
return NS_OK;
}
nsIAccessible *nsHTMLAreaAccessible::CreateAreaAccessible(nsIDOMNode *aDOMNode)
nsIAccessible *nsHTMLAreaAccessible::GetAreaAccessible(nsIDOMNode *aDOMNode)
{
nsCOMPtr<nsIAccessibilityService> accService(do_GetService("@mozilla.org/accessibilityService;1"));
if (accService) {
nsIAccessible* acc = nsnull;
accService->CreateHTMLAreaAccessible(mPresShell, aDOMNode, mAccParent, &acc);
accService->GetCachedAccessible(aDOMNode, mWeakShell, &acc);
if (!acc) {
accService->CreateHTMLAreaAccessible(mWeakShell, aDOMNode, mParent, &acc);
}
return acc;
}
return nsnull;
@ -135,7 +137,7 @@ NS_IMETHODIMP nsHTMLAreaAccessible::GetAccNextSibling(nsIAccessible * *aAccNextS
nsCOMPtr<nsIDOMNode> nextNode;
mDOMNode->GetNextSibling(getter_AddRefs(nextNode));
if (nextNode)
*aAccNextSibling = CreateAreaAccessible(nextNode);
*aAccNextSibling = GetAreaAccessible(nextNode);
return NS_OK;
}
@ -146,7 +148,7 @@ NS_IMETHODIMP nsHTMLAreaAccessible::GetAccPreviousSibling(nsIAccessible * *aAccP
nsCOMPtr<nsIDOMNode> prevNode;
mDOMNode->GetPreviousSibling(getter_AddRefs(prevNode));
if (prevNode)
*aAccPrevSibling = CreateAreaAccessible(prevNode);
*aAccPrevSibling = GetAreaAccessible(prevNode);
return NS_OK;
}
@ -158,7 +160,7 @@ NS_IMETHODIMP nsHTMLAreaAccessible::AccGetBounds(PRInt32 *x, PRInt32 *y, PRInt32
*x = *y = *width = *height = 0;
nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mPresShell));
nsCOMPtr<nsIPresShell> presShell(GetPresShell());
NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
nsCOMPtr<nsIPresContext> presContext;

View File

@ -62,8 +62,7 @@ public:
NS_IMETHOD AccGetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height);
protected:
nsIAccessible *CreateAreaAccessible(nsIDOMNode *aDOMNode);
nsCOMPtr<nsIAccessible> mAccParent;
nsIAccessible *GetAreaAccessible(nsIDOMNode *aDOMNode);
};
#endif

View File

@ -38,20 +38,12 @@
* ***** END LICENSE BLOCK ***** */
// NOTE: alphabetically ordered
#include "nsAccessibleWrap.h"
#include "nsFormControlAccessible.h"
#include "nsHTMLFormControlAccessible.h"
#include "nsIDOMHTMLButtonElement.h"
#include "nsIDOMHTMLFormElement.h"
#include "nsIDOMHTMLInputElement.h"
#include "nsIDOMNSHTMLButtonElement.h"
#include "nsIDOMHTMLLabelElement.h"
#include "nsIDOMHTMLTextAreaElement.h"
#include "nsIDOMXULCheckboxElement.h"
#include "nsIDOMXULButtonElement.h"
#include "nsIDOMXULSelectCntrlItemEl.h"
#include "nsIDOMXULSelectCntrlEl.h"
#include "nsIFrame.h"
#include "nsISelectionController.h"
// --- checkbox -----
@ -311,7 +303,7 @@ nsFormControlAccessible(aNode, aShell)
#ifdef MOZ_ACCESSIBILITY_ATK
SetTextNode(aNode);
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mPresShell));
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mWeakShell));
if (shell) {
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
nsIFrame *frame = nsnull;
@ -379,16 +371,16 @@ NS_IMETHODIMP nsHTMLTextFieldAccessible::GetAccState(PRUint32 *_retval)
*_retval |= STATE_READONLY;
// Get current selection and find out if current node is in it
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mPresShell));
nsCOMPtr<nsIPresShell> shell(GetPresShell());
if (!shell) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIPresContext> context;
shell->GetPresContext(getter_AddRefs(context));
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
nsIFrame *frame = nsnull;
if (content && NS_SUCCEEDED(shell->GetPrimaryFrameFor(content, &frame)) && frame) {
nsCOMPtr<nsIPresContext> context;
shell->GetPresContext(getter_AddRefs(context));
nsCOMPtr<nsISelectionController> selCon;
frame->GetSelectionController(context,getter_AddRefs(selCon));
if (selCon) {

View File

@ -40,12 +40,9 @@
#ifndef _nsHTMLFormControlAccessible_H_
#define _nsHTMLFormControlAccessible_H_
#include "nsBaseWidgetAccessible.h"
#include "nsFormControlAccessible.h"
#include "nsTextAccessible.h"
class nsICheckboxControlFrame;
class nsHTMLCheckboxAccessible : public nsFormControlAccessible
{
@ -100,6 +97,7 @@ class nsHTMLTextFieldAccessible : public nsFormControlAccessible,
public nsAccessibleEditableText
#endif
{
public:
NS_DECL_ISUPPORTS_INHERITED

View File

@ -38,8 +38,8 @@
* ***** END LICENSE BLOCK ***** */
#include "nsHTMLImageAccessible.h"
#include "nsReadableUtils.h"
#include "nsIHTMLDocument.h"
#include "nsIPresShell.h"
#include "nsIDocument.h"
#include "nsIDOMHTMLCollection.h"
#include "nsIAccessibilityService.h"
@ -56,7 +56,7 @@ nsLinkableAccessible(aDOMNode, aShell)
{
nsCOMPtr<nsIDOMElement> element(do_QueryInterface(aDOMNode));
nsCOMPtr<nsIDocument> doc;
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mPresShell));
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mWeakShell));
if (!shell)
return;
@ -129,7 +129,7 @@ NS_IMETHODIMP nsHTMLImageAccessible::GetAccRole(PRUint32 *_retval)
}
nsIAccessible *nsHTMLImageAccessible::CreateAreaAccessible(PRUint32 areaNum)
nsIAccessible *nsHTMLImageAccessible::CreateAreaAccessible(PRInt32 areaNum)
{
if (!mMapElement)
return nsnull;
@ -157,7 +157,10 @@ nsIAccessible *nsHTMLImageAccessible::CreateAreaAccessible(PRUint32 areaNum)
return nsnull;
if (accService) {
nsIAccessible* acc = nsnull;
accService->CreateHTMLAreaAccessible(mPresShell, domNode, this, &acc);
accService->GetCachedAccessible(domNode, mWeakShell, &acc);
if (!acc) {
accService->CreateHTMLAreaAccessible(mWeakShell, domNode, this, &acc);
}
return acc;
}
return nsnull;
@ -179,14 +182,14 @@ NS_IMETHODIMP nsHTMLImageAccessible::GetAccLastChild(nsIAccessible **_retval)
return NS_OK;
}
#ifdef NEVER
/* long getAccChildCount (); */
NS_IMETHODIMP nsHTMLImageAccessible::GetAccChildCount(PRInt32 *_retval)
{
*_retval = 0;
if (mMapElement) {
nsIDOMHTMLCollection *mapAreas;
mMapElement->GetAreas(&mapAreas);
nsCOMPtr<nsIDOMHTMLCollection> mapAreas;
mMapElement->GetAreas(getter_AddRefs(mapAreas));
if (mapAreas) {
PRUint32 length;
mapAreas->GetLength(&length);
@ -196,6 +199,7 @@ NS_IMETHODIMP nsHTMLImageAccessible::GetAccChildCount(PRInt32 *_retval)
return NS_OK;
}
#endif
// Image map hyperlink
NS_IMPL_ISUPPORTS_INHERITED1(nsHTMLImageMapAccessible, nsHTMLImageAccessible, nsIAccessibleHyperLink)

View File

@ -42,8 +42,6 @@
#include "nsBaseWidgetAccessible.h"
#include "nsIAccessibleHyperLink.h"
#include "nsIFrame.h"
#include "nsIImageFrame.h"
#include "nsIDOMHTMLMapElement.h"
/* Accessible for supporting images
@ -61,10 +59,9 @@ public:
NS_IMETHOD GetAccRole(PRUint32 *_retval);
NS_IMETHOD GetAccFirstChild(nsIAccessible **_retval);
NS_IMETHOD GetAccLastChild(nsIAccessible **_retval);
NS_IMETHOD GetAccChildCount(PRInt32 *_retval);
protected:
nsIAccessible *CreateAreaAccessible(PRUint32 areaNum);
nsIAccessible *CreateAreaAccessible(PRInt32 areaNum);
nsCOMPtr<nsIDOMHTMLMapElement> mMapElement;
};

View File

@ -38,17 +38,9 @@
* ***** END LICENSE BLOCK ***** */
#include "nsHTMLLinkAccessible.h"
#include "nsWeakReference.h"
#include "nsIFrame.h"
#include "nsILink.h"
#include "nsILinkHandler.h"
#include "nsISelection.h"
#include "nsISelectionController.h"
#include "nsIPresContext.h"
#include "nsIURI.h"
#include "nsNetUtil.h"
#include "nsReadableUtils.h"
#include "nsIDOMElement.h"
NS_IMPL_ISUPPORTS_INHERITED1(nsHTMLLinkAccessible, nsLinkableAccessible, nsIAccessibleHyperLink)
@ -110,7 +102,7 @@ NS_IMETHODIMP nsHTMLLinkAccessible::GetEndIndex(PRInt32 *aEndIndex)
/* nsIURI getURI (in long i); */
NS_IMETHODIMP nsHTMLLinkAccessible::GetURI(PRInt32 i, nsIURI **aURI)
{
//I do not know why we have to retrun a nsIURI instead of
//I do not know why we have to return a nsIURI instead of
//nsILink or just a string of url. Anyway, maybe nsIURI is
//more powerful for the future.
*aURI = nsnull;

View File

@ -1,98 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* John Gaunt (jgaunt@netscape.com)
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsHTMLPluginAccessible.h"
#include "nsIContent.h"
#include "nsObjectFrame.h"
#include "nsplugindefs.h"
#include "nsAccessibilityService.h"
nsHTMLPluginAccessible::nsHTMLPluginAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell):
nsAccessibleWrap(aNode, aShell), mAccService(do_GetService("@mozilla.org/accessibilityService;1"))
{
}
NS_IMETHODIMP
nsHTMLPluginAccessible::GetAccFirstChild(nsIAccessible **_retval)
{
*_retval = nsnull;
nsIFrame* frame = nsnull;
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mPresShell));
shell->GetPrimaryFrameFor(content, &frame);
if (!frame)
return NS_ERROR_FAILURE;
nsObjectFrame* objectFrame = NS_STATIC_CAST(nsObjectFrame*, frame);
#ifdef XP_WIN
HWND pluginPort = nsnull;
objectFrame->GetPluginPort(&pluginPort);
if (pluginPort) {
if (mAccService)
mAccService->CreateHTMLNativeWindowAccessible(mDOMNode, mPresShell,
NS_REINTERPRET_CAST(void*, pluginPort),
_retval);
}
#else
*_retval = nsnull;
#endif
NS_IF_ADDREF(*_retval);
return NS_OK;
}
NS_IMETHODIMP
nsHTMLPluginAccessible::GetAccLastChild(nsIAccessible **_retval)
{
return GetAccFirstChild(_retval);
}
NS_IMETHODIMP
nsHTMLPluginAccessible::GetAccChildCount(PRInt32 *_retval)
{
*_retval = 1;
return NS_OK;
}
NS_IMETHODIMP
nsHTMLPluginAccessible::GetAccRole(PRUint32 *_retval)
{
*_retval = ROLE_WINDOW;
return NS_OK;
}

View File

@ -73,12 +73,13 @@
/** ------------------------------------------------------ */
// Helper class
nsHTMLSelectableAccessible::iterator::iterator(nsHTMLSelectableAccessible *aParent) : mParent(aParent)
nsHTMLSelectableAccessible::iterator::iterator(nsHTMLSelectableAccessible *aParent, nsIWeakReference *aWeakShell):
mWeakShell(aWeakShell), mParentSelect(aParent)
{
mLength = mIndex = 0;
mSelCount = 0;
nsCOMPtr<nsIDOMHTMLSelectElement> htmlSelect(do_QueryInterface(mParent->mDOMNode));
nsCOMPtr<nsIDOMHTMLSelectElement> htmlSelect(do_QueryInterface(mParentSelect->mDOMNode));
if (htmlSelect) {
htmlSelect->GetOptions(getter_AddRefs(mOptions));
if (mOptions)
@ -120,8 +121,10 @@ void nsHTMLSelectableAccessible::iterator::AddAccessibleIfSelected(nsIAccessibil
if (mOption) {
mOption->GetSelected(&isSelected);
if (isSelected)
aAccService->CreateHTMLSelectOptionAccessible(mOption, mParent, aContext, getter_AddRefs(tempAccess));
if (isSelected) {
nsCOMPtr<nsIDOMNode> optionNode(do_QueryInterface(mOption));
aAccService->GetAccessibleInWeakShell(optionNode, mWeakShell, getter_AddRefs(tempAccess));
}
}
if (tempAccess)
@ -131,20 +134,18 @@ void nsHTMLSelectableAccessible::iterator::AddAccessibleIfSelected(nsIAccessibil
PRBool nsHTMLSelectableAccessible::iterator::GetAccessibleIfSelected(PRInt32 aIndex,
nsIAccessibilityService *aAccService,
nsIPresContext *aContext,
nsIAccessible **_retval)
nsIAccessible **aAccessible)
{
PRBool isSelected = PR_FALSE;
nsCOMPtr<nsIAccessible> tempAccess;
*_retval = nsnull;
*aAccessible = nsnull;
if (mOption) {
mOption->GetSelected(&isSelected);
if (isSelected) {
if (mSelCount == aIndex) {
aAccService->CreateHTMLSelectOptionAccessible(mOption, mParent, aContext, getter_AddRefs(tempAccess));
*_retval = tempAccess;
NS_IF_ADDREF(*_retval);
nsCOMPtr<nsIDOMNode> optionNode(do_QueryInterface(mOption));
aAccService->GetAccessibleInWeakShell(optionNode, mWeakShell, aAccessible);
return PR_TRUE;
}
mSelCount++;
@ -210,12 +211,11 @@ NS_IMETHODIMP nsHTMLSelectableAccessible::GetSelectedChildren(nsISupportsArray *
if (!selectedAccessibles)
return NS_ERROR_OUT_OF_MEMORY;
nsCOMPtr<nsIPresContext> context;
GetPresContext(getter_AddRefs(context));
nsCOMPtr<nsIPresContext> context(GetPresContext());
if (!context)
return NS_ERROR_FAILURE;
nsHTMLSelectableAccessible::iterator iter(this);
nsHTMLSelectableAccessible::iterator iter(this, mWeakShell);
while (iter.Advance())
iter.AddAccessibleIfSelected(accService, selectedAccessibles, context);
@ -237,12 +237,11 @@ NS_IMETHODIMP nsHTMLSelectableAccessible::RefSelection(PRInt32 aIndex, nsIAccess
if (!accService)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIPresContext> context;
GetPresContext(getter_AddRefs(context));
nsCOMPtr<nsIPresContext> context(GetPresContext());
if (!context)
return NS_ERROR_FAILURE;
nsHTMLSelectableAccessible::iterator iter(this);
nsHTMLSelectableAccessible::iterator iter(this, mWeakShell);
while (iter.Advance())
if (iter.GetAccessibleIfSelected(aIndex, accService, context, _retval))
return NS_OK;
@ -255,7 +254,7 @@ NS_IMETHODIMP nsHTMLSelectableAccessible::GetSelectionCount(PRInt32 *aSelectionC
{
*aSelectionCount = 0;
nsHTMLSelectableAccessible::iterator iter(this);
nsHTMLSelectableAccessible::iterator iter(this, mWeakShell);
while (iter.Advance())
iter.CalcSelectionCount(aSelectionCount);
return NS_OK;
@ -281,7 +280,7 @@ NS_IMETHODIMP nsHTMLSelectableAccessible::IsChildSelected(PRInt32 aIndex, PRBool
NS_IMETHODIMP nsHTMLSelectableAccessible::ClearSelection()
{
nsHTMLSelectableAccessible::iterator iter(this);
nsHTMLSelectableAccessible::iterator iter(this, mWeakShell);
while (iter.Advance())
iter.Select(PR_FALSE);
return NS_OK;
@ -297,7 +296,7 @@ NS_IMETHODIMP nsHTMLSelectableAccessible::SelectAllSelection(PRBool *_retval)
htmlSelect->GetMultiple(_retval);
if (*_retval) {
nsHTMLSelectableAccessible::iterator iter(this);
nsHTMLSelectableAccessible::iterator iter(this, mWeakShell);
while (iter.Advance())
iter.Select(PR_TRUE);
}
@ -343,20 +342,32 @@ NS_IMETHODIMP nsHTMLSelectListAccessible::GetAccRole(PRUint32 *_retval)
}
/**
* Gets the first child of the DOM node and creates and returns
* a nsHTMLSelectOptionAccessible.
*/
NS_IMETHODIMP nsHTMLSelectListAccessible::GetAccFirstChild(nsIAccessible **aAccFirstChild)
{
nsCOMPtr<nsIDOMNode> first;
mDOMNode->GetFirstChild(getter_AddRefs(first));
nsCOMPtr<nsIAccessibilityService> accService(do_GetService("@mozilla.org/accessibilityService;1"));
nsresult rv = accService->GetAccessibleInWeakShell(first, mWeakShell, aAccFirstChild);
mFirstChild = *aAccFirstChild;
return rv;
}
/**
* Gets the last child of the DOM node and creates and returns
* a nsHTMLSelectOptionAccessible.
*/
NS_IMETHODIMP nsHTMLSelectListAccessible::GetAccLastChild(nsIAccessible **_retval)
NS_IMETHODIMP nsHTMLSelectListAccessible::GetAccLastChild(nsIAccessible **aAccLastChild)
{
nsCOMPtr<nsIDOMNode> last;
mDOMNode->GetLastChild(getter_AddRefs(last));
*_retval = new nsHTMLSelectOptionAccessible(last, mPresShell);
if ( ! *_retval )
return NS_ERROR_FAILURE;
NS_ADDREF(*_retval);
return NS_OK;
nsCOMPtr<nsIAccessibilityService> accService(do_GetService("@mozilla.org/accessibilityService;1"));
return accService->GetAccessibleInWeakShell(last, mWeakShell, aAccLastChild);
}
/**
@ -397,7 +408,6 @@ NS_IMETHODIMP nsHTMLSelectListAccessible::GetAccChildCount(PRInt32 *aAccChildCou
} // endWhile next
*aAccChildCount = countChild;
return NS_OK;
}
/** ----- nsHTMLSelectOptionAccessible ----- */
@ -416,7 +426,7 @@ nsLeafAccessible(aDOMNode, aShell)
// GetAccParent would normally return. This is because the
// nsHTMLComboboxListAccessible is inserted into the accessible hierarchy
// where there is no DOM node for it.
accService->GetAccessibleFor(parentNode, getter_AddRefs(parentAccessible));
accService->GetAccessibleInWeakShell(parentNode, mWeakShell, getter_AddRefs(parentAccessible));
if (parentAccessible) {
PRUint32 role;
parentAccessible->GetAccRole(&role);
@ -426,7 +436,7 @@ nsLeafAccessible(aDOMNode, aShell)
}
}
}
mParent = parentAccessible;
SetAccParent(parentAccessible);
}
/** We are a ListItem */
@ -447,16 +457,16 @@ NS_IMETHODIMP nsHTMLSelectOptionAccessible::GetAccParent(nsIAccessible **aParent
* Gets the next accessible sibling of the mDOMNode and creates and returns
* a nsHTMLSelectOptionAccessible or nsHTMLSelectOptGroupAccessible.
*/
NS_IMETHODIMP nsHTMLSelectOptionAccessible::GetAccNextSibling(nsIAccessible **_retval)
NS_IMETHODIMP nsHTMLSelectOptionAccessible::GetAccNextSibling(nsIAccessible **aAccNextSibling)
{
// Get next sibling and if found create and return an accessible for it
// When getting the next sibling of an SelectOption we could be working with
// either an optgroup or an option. We process this tree as flat.
*_retval = nsnull;
*aAccNextSibling = nsnull;
nsCOMPtr<nsIDOMNode> next = mDOMNode, currentNode;
nsCOMPtr<nsIAccessibilityService> accService(do_GetService("@mozilla.org/accessibilityService;1"));
while (!*_retval && next) {
while (!*aAccNextSibling && next) {
currentNode = next;
next = nsnull;
@ -469,7 +479,7 @@ NS_IMETHODIMP nsHTMLSelectOptionAccessible::GetAccNextSibling(nsIAccessible **_r
currentNode->GetNextSibling(getter_AddRefs(next)); // See if there is another <optgroup>
if (next) {
accService->GetAccessibleFor(next, _retval);
accService->GetAccessibleInWeakShell(next, mWeakShell, aAccNextSibling);
continue;
}
// else No child then or child is not a <option> nor an <optgroup>
@ -477,22 +487,19 @@ NS_IMETHODIMP nsHTMLSelectOptionAccessible::GetAccNextSibling(nsIAccessible **_r
nsCOMPtr<nsIDOMNode> parent, parentNextSib;
currentNode->GetParentNode(getter_AddRefs(parent));
if (!parent)
return NS_OK;
next = nsnull;
nsCOMPtr<nsIDOMNode> selectNode;
mParent->AccGetDOMNode(getter_AddRefs(selectNode));
if (parent == selectNode)
return NS_OK; // End search for options at subtree's start
parent->GetNextSibling(getter_AddRefs(next));
if (!next)
return NS_OK; // done
// We have a parent that is an option or option group
// get accessible for either one and return it
accService->GetAccessibleFor(next, _retval);
if (parent && parent != selectNode) { // End search for options at subtree's start
parent->GetNextSibling(getter_AddRefs(next));
if (next) {
// We have a parent that is an option or option group
// get accessible for either one and return it
accService->GetAccessibleInWeakShell(next, mWeakShell, aAccNextSibling);
}
}
}
SetAccNextSibling(*aAccNextSibling);
return NS_OK;
}
@ -544,9 +551,10 @@ NS_IMETHODIMP nsHTMLSelectOptionAccessible::GetAccPreviousSibling(nsIAccessible
nsCOMPtr<nsIAccessibilityService> accService(do_GetService("@mozilla.org/accessibilityService;1"));
nsCOMPtr<nsIAccessible> thisAcc, selectListAcc, nextSiblingAcc;
accService->GetAccessibleFor(mDOMNode, getter_AddRefs(thisAcc));
accService->GetAccessibleInWeakShell(mDOMNode, mWeakShell, getter_AddRefs(thisAcc));
// The accessible parent of an <option> or <optgroup> is always the SelectListAcc - see GetAccessibleFor()
// The accessible parent of an <option> or <optgroup>
// is always the SelectListAcc - see GetAccessibleInShell()
thisAcc->GetAccParent(getter_AddRefs(selectListAcc));
if (!selectListAcc) {
@ -664,7 +672,7 @@ NS_IMETHODIMP nsHTMLSelectOptionAccessible::AccDoAction(PRUint8 index)
thisNode = testSelectNode;
} while (testSelectNode);
nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mPresShell));
nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell));
nsCOMPtr<nsIContent> selectContent(do_QueryInterface(testSelectNode));
nsCOMPtr<nsIDOMHTMLOptionElement> option(do_QueryInterface(mDOMNode));
@ -810,6 +818,33 @@ NS_IMETHODIMP nsHTMLComboboxAccessible::GetAccRole(PRUint32 *_retval)
return NS_OK;
}
NS_IMETHODIMP nsHTMLComboboxAccessible::Shutdown()
{
mComboboxTextFieldAccessible = nsnull;
mComboboxButtonAccessible = nsnull;
mComboboxListAccessible = nsnull;
nsHTMLSelectableAccessible::Shutdown();
return NS_OK;
}
NS_IMETHODIMP nsHTMLComboboxAccessible::Init()
{
// Hold references
GetAccFirstChild(getter_AddRefs(mComboboxTextFieldAccessible));
if (mComboboxTextFieldAccessible) {
mComboboxTextFieldAccessible->GetAccNextSibling(getter_AddRefs(mComboboxButtonAccessible));
}
if (mComboboxButtonAccessible) {
mComboboxButtonAccessible->GetAccNextSibling(getter_AddRefs(mComboboxListAccessible));
}
nsHTMLSelectableAccessible::Init();
return NS_OK;
}
/**
* We always have 3 children: TextField, Button, Window. In that order
*/
@ -841,33 +876,43 @@ NS_IMETHODIMP nsHTMLComboboxAccessible::GetAccState(PRUint32 *_retval)
if (comboFrame)
comboFrame->IsDroppedDown(&isOpen);
*_retval |= isOpen ? STATE_EXPANDED : STATE_COLLAPSED;
if (isOpen)
*_retval |= STATE_EXPANDED;
else
*_retval |= STATE_COLLAPSED;
*_retval |= STATE_HASPOPUP | STATE_READONLY | STATE_FOCUSABLE;
return NS_OK;
}
/**
* Our last child is an nsHTMLComboboxListAccessible object
* Our last child is an nsHTMLComboboxListAccessible object, is also the third child
*/
NS_IMETHODIMP nsHTMLComboboxAccessible::GetAccLastChild(nsIAccessible **_retval)
NS_IMETHODIMP nsHTMLComboboxAccessible::GetAccLastChild(nsIAccessible **aAccLastChild)
{
*_retval = new nsHTMLComboboxListAccessible(this, mDOMNode, mPresShell);
if (! *_retval)
return NS_ERROR_FAILURE;
NS_ADDREF(*_retval);
return NS_OK;
// It goes: textfield, button, list. We're returning the list.
return GetChildAt(2, aAccLastChild);
}
/**
* Our last child is an nsHTMLComboboxTextFieldAccessible object
* Our first child is an nsHTMLComboboxTextFieldAccessible object
*/
NS_IMETHODIMP nsHTMLComboboxAccessible::GetAccFirstChild(nsIAccessible **_retval)
NS_IMETHODIMP nsHTMLComboboxAccessible::GetAccFirstChild(nsIAccessible **aAccFirstChild)
{
*_retval = new nsHTMLComboboxTextFieldAccessible(this, mDOMNode, mPresShell);
if (! *_retval)
return NS_ERROR_FAILURE;
NS_ADDREF(*_retval);
if (mFirstChild) {
*aAccFirstChild = mFirstChild;
}
else {
*aAccFirstChild = new nsHTMLComboboxTextFieldAccessible(this, mDOMNode, mWeakShell);
if (! *aAccFirstChild)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(*aAccFirstChild));
accessNode->Init();
SetAccFirstChild(*aAccFirstChild);
}
NS_ADDREF(*aAccFirstChild);
return NS_OK;
}
@ -889,24 +934,31 @@ NS_IMETHODIMP nsHTMLComboboxAccessible::GetAccValue(nsAString& _retval)
/** Constructor */
nsHTMLComboboxTextFieldAccessible::nsHTMLComboboxTextFieldAccessible(nsIAccessible* aParent,
nsIDOMNode* aDOMNode,
nsIWeakReference* aShell):
nsLeafAccessible(aDOMNode, aShell), mParent(aParent)
nsIDOMNode* aDOMNode,
nsIWeakReference* aShell):
nsLeafAccessible(aDOMNode, aShell)
{
// There is no cache entry for this item.
// It's generated and ref'd by nsHTMLComboboxAccessible
SetAccParent(aParent);
}
/**
* Our next sibling is an nsHTMLComboboxButtonAccessible object
*/
NS_IMETHODIMP nsHTMLComboboxTextFieldAccessible::GetAccNextSibling(nsIAccessible **_retval)
NS_IMETHODIMP nsHTMLComboboxTextFieldAccessible::GetAccNextSibling(nsIAccessible **aAccNextSibling)
{
nsCOMPtr<nsIAccessible> parent;
GetAccParent(getter_AddRefs(parent));
*_retval = new nsHTMLComboboxButtonAccessible(parent, mDOMNode, mPresShell);
if (! *_retval)
return NS_ERROR_FAILURE;
NS_ADDREF(*_retval);
if (mNextSibling) {
*aAccNextSibling = mNextSibling;
}
else {
*aAccNextSibling = new nsHTMLComboboxButtonAccessible(mParent, mDOMNode, mWeakShell);
if (!*aAccNextSibling)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(*aAccNextSibling));
accessNode->Init();
}
NS_ADDREF(*aAccNextSibling);
return NS_OK;
}
@ -918,8 +970,7 @@ NS_IMETHODIMP nsHTMLComboboxTextFieldAccessible::GetAccNextSibling(nsIAccessible
NS_IMETHODIMP nsHTMLComboboxTextFieldAccessible::GetAccValue(nsAString& _retval)
{
nsIFrame* frame = nsAccessible::GetBoundsFrame();
nsCOMPtr<nsIPresContext> context;
GetPresContext(getter_AddRefs(context));
nsCOMPtr<nsIPresContext> context(GetPresContext());
if (!frame || !context)
return NS_ERROR_FAILURE;
@ -937,6 +988,13 @@ NS_IMETHODIMP nsHTMLComboboxTextFieldAccessible::GetAccValue(nsAString& _retval)
return NS_OK;
}
NS_IMETHODIMP nsHTMLComboboxTextFieldAccessible::GetUniqueID(void **aUniqueID)
{
// Since mDOMNode is same for all tree item, use |this| pointer as the unique Id
*aUniqueID = NS_STATIC_CAST(void*, this);
return NS_OK;
}
/**
* Gets the bounds for the BlockFrame.
* Walks the Frame tree and checks for proper frames.
@ -945,8 +1003,7 @@ void nsHTMLComboboxTextFieldAccessible::GetBounds(nsRect& aBounds, nsIFrame** aB
{
// get our first child's frame
nsIFrame* frame = nsAccessible::GetBoundsFrame();
nsCOMPtr<nsIPresContext> context;
GetPresContext(getter_AddRefs(context));
nsCOMPtr<nsIPresContext> context(GetPresContext());
if (!frame || !context)
return;
@ -1006,8 +1063,11 @@ NS_IMETHODIMP nsHTMLComboboxTextFieldAccessible::GetAccState(PRUint32 *_retval)
nsHTMLComboboxButtonAccessible::nsHTMLComboboxButtonAccessible(nsIAccessible* aParent,
nsIDOMNode* aDOMNode,
nsIWeakReference* aShell):
nsLeafAccessible(aDOMNode, aShell), mParent(aParent)
nsLeafAccessible(aDOMNode, aShell)
{
// There is no cache entry for this item.
// It's generated and ref'd by nsHTMLComboboxAccessible
SetAccParent(aParent);
}
/** Just one action ( click ). */
@ -1025,13 +1085,11 @@ NS_IMETHODIMP nsHTMLComboboxButtonAccessible::GetAccNumActions(PRUint8 *aNumActi
NS_IMETHODIMP nsHTMLComboboxButtonAccessible::AccDoAction(PRUint8 aIndex)
{
nsIFrame* frame = nsAccessible::GetBoundsFrame();
nsCOMPtr<nsIPresContext> context;
GetPresContext(getter_AddRefs(context));
if (!context)
nsCOMPtr<nsIPresContext> context(GetPresContext());
if (!frame || !context)
return NS_ERROR_FAILURE;
frame->FirstChild(context, nsnull, &frame);
frame->GetNextSibling(&frame);
nsCOMPtr<nsIContent> content;
@ -1073,6 +1131,13 @@ NS_IMETHODIMP nsHTMLComboboxButtonAccessible::GetAccActionName(PRUint8 aIndex, n
return NS_OK;
}
NS_IMETHODIMP nsHTMLComboboxButtonAccessible::GetUniqueID(void **aUniqueID)
{
// Since mDOMNode is same for all tree item, use |this| pointer as the unique Id
*aUniqueID = NS_STATIC_CAST(void*, this);
return NS_OK;
}
/**
* Gets the bounds for the gfxButtonControlFrame.
* Walks the Frame tree and checks for proper frames.
@ -1080,13 +1145,13 @@ NS_IMETHODIMP nsHTMLComboboxButtonAccessible::GetAccActionName(PRUint8 aIndex, n
void nsHTMLComboboxButtonAccessible::GetBounds(nsRect& aBounds, nsIFrame** aBoundingFrame)
{
// get our second child's frame
nsIFrame* frame = nsAccessible::GetBoundsFrame();
nsCOMPtr<nsIPresContext> context;
GetPresContext(getter_AddRefs(context));
if (!context)
// bounding frame is the ComboboxControlFrame
nsIFrame *frame = nsAccessible::GetBoundsFrame();
*aBoundingFrame = frame;
nsCOMPtr<nsIPresContext> context(GetPresContext());
if (!frame || !context)
return;
*aBoundingFrame = frame; // bounding frame is the ComboboxControlFrame
frame->FirstChild(context, nsnull, &frame); // first frame is for the textfield
frame->GetNextSibling(&frame); // sibling frame is for the button
@ -1146,31 +1211,28 @@ NS_IMETHODIMP nsHTMLComboboxButtonAccessible::GetAccState(PRUint32 *_retval)
/**
* Our next sibling is an nsHTMLComboboxListAccessible object
*/
NS_IMETHODIMP nsHTMLComboboxButtonAccessible::GetAccNextSibling(nsIAccessible **_retval)
NS_IMETHODIMP nsHTMLComboboxButtonAccessible::GetAccNextSibling(nsIAccessible **aAccNextSibling)
{
nsCOMPtr<nsIAccessible> parent;
GetAccParent(getter_AddRefs(parent));
*_retval = new nsHTMLComboboxListAccessible(parent, mDOMNode, mPresShell);
if (! *_retval)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*_retval);
if (mNextSibling) {
*aAccNextSibling = mNextSibling;
}
else {
*aAccNextSibling = new nsHTMLComboboxListAccessible(mParent, mDOMNode, mWeakShell);
if (!*aAccNextSibling)
return NS_ERROR_OUT_OF_MEMORY;
nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(*aAccNextSibling));
accessNode->Init();
}
NS_ADDREF(*aAccNextSibling);
return NS_OK;
}
/**
* Our next sibling is an nsHTMLComboboxTextFieldAccessible object
* Our prev sibling is an nsHTMLComboboxTextFieldAccessible object
*/
NS_IMETHODIMP nsHTMLComboboxButtonAccessible::GetAccPreviousSibling(nsIAccessible **_retval)
NS_IMETHODIMP nsHTMLComboboxButtonAccessible::GetAccPreviousSibling(nsIAccessible **aAccPrevSibling)
{
nsCOMPtr<nsIAccessible> parent;
GetAccParent(getter_AddRefs(parent));
*_retval = new nsHTMLComboboxTextFieldAccessible(parent, mDOMNode, mPresShell);
if (! *_retval)
return NS_ERROR_FAILURE;
NS_ADDREF(*_retval);
return NS_OK;
return mParent->GetAccFirstChild(aAccPrevSibling);
}
@ -1179,8 +1241,11 @@ NS_IMETHODIMP nsHTMLComboboxButtonAccessible::GetAccPreviousSibling(nsIAccessibl
nsHTMLComboboxListAccessible::nsHTMLComboboxListAccessible(nsIAccessible *aParent,
nsIDOMNode* aDOMNode,
nsIWeakReference* aShell):
nsHTMLSelectListAccessible(aDOMNode, aShell), mParent(aParent)
nsHTMLSelectListAccessible(aDOMNode, aShell)
{
// There is no cache entry for this item.
// It's generated and ref'd by nsHTMLComboboxAccessible
SetAccParent(aParent);
}
/**
@ -1203,7 +1268,10 @@ NS_IMETHODIMP nsHTMLComboboxListAccessible::GetAccState(PRUint32 *aAccState)
if (!comboFrame)
return NS_ERROR_FAILURE;
comboFrame->IsDroppedDown(&isOpen);
*aAccState |= (isOpen? STATE_FLOATING: STATE_INVISIBLE) | STATE_FOCUSABLE;
if (isOpen)
*aAccState |= STATE_FLOATING | STATE_FOCUSABLE;
else
*aAccState |= STATE_INVISIBLE | STATE_FOCUSABLE;
return NS_OK;
}
@ -1215,6 +1283,18 @@ NS_IMETHODIMP nsHTMLComboboxListAccessible::GetAccParent(nsIAccessible **aParent
return NS_OK;
}
NS_IMETHODIMP nsHTMLComboboxListAccessible::GetAccPreviousSibling(nsIAccessible **aAccPrevSibling)
{
return mParent->GetChildAt(1, aAccPrevSibling);
}
NS_IMETHODIMP nsHTMLComboboxListAccessible::GetUniqueID(void **aUniqueID)
{
// Since mDOMNode is same for all tree item, use |this| pointer as the unique Id
*aUniqueID = NS_STATIC_CAST(void*, this);
return NS_OK;
}
/**
* Gets the bounds for the areaFrame.
* Walks the Frame tree and checks for proper frames.
@ -1226,7 +1306,7 @@ void nsHTMLComboboxListAccessible::GetBounds(nsRect& aBounds, nsIFrame** aBoundi
mDOMNode->GetFirstChild(getter_AddRefs(child));
// now get its frame
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mPresShell));
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mWeakShell));
if (!shell) {
*aBoundingFrame = nsnull;
return;

View File

@ -22,6 +22,7 @@
* Original Author: Eric Vaughan (evaughan@netscape.com)
*
* Contributor(s):
* Aaron Leventhal (aaronl@netscape.com)
* Kyle Yuan (kyle.yuan@sun.com)
*
* Alternatively, the contents of this file may be used under the terms of
@ -40,12 +41,12 @@
#ifndef __nsHTMLSelectAccessible_h__
#define __nsHTMLSelectAccessible_h__
#include "nsCOMPtr.h"
#include "nsIAccessibleSelectable.h"
#include "nsIDOMHTMLOptionsCollection.h"
#include "nsIDOMHTMLOptionElement.h"
#include "nsIDOMNode.h"
#include "nsFormControlAccessible.h"
#include "nsIAccessibilityService.h"
/**
* Selects, Listboxes and Comboboxes, are made up of a number of different
@ -69,7 +70,7 @@
/** ------------------------------------------------------ */
/*
* The basic implemetation of nsIAccessibleSelectable.
* The HTML implementation of nsIAccessibleSelectable.
*/
class nsHTMLSelectableAccessible : public nsAccessibleWrap,
public nsIAccessibleSelectable
@ -92,12 +93,14 @@ protected:
PRUint32 mLength;
PRUint32 mIndex;
PRInt32 mSelCount;
nsHTMLSelectableAccessible *mParent;
nsCOMPtr<nsIDOMHTMLOptionsCollection> mOptions;
nsCOMPtr<nsIDOMHTMLOptionElement> mOption;
nsCOMPtr<nsIWeakReference> mWeakShell;
nsHTMLSelectableAccessible *mParentSelect;
public:
iterator(nsHTMLSelectableAccessible *aParent);
void Shutdown();
iterator(nsHTMLSelectableAccessible *aParent, nsIWeakReference *aWeakShell);
void CalcSelectionCount(PRInt32 *aSelectionCount);
void Select(PRBool aSelect);
@ -123,9 +126,9 @@ public:
/* ----- nsIAccessible ----- */
NS_IMETHOD GetAccRole(PRUint32 *aAccRole);
NS_IMETHOD GetAccState(PRUint32 *_retval);
NS_IMETHOD GetAccLastChild(nsIAccessible **_retval);
NS_IMETHOD GetAccFirstChild(nsIAccessible **aAccFirstChild);
NS_IMETHOD GetAccLastChild(nsIAccessible **aAccFirstChild);
NS_IMETHOD GetAccChildCount(PRInt32 *aAccChildCount) ;
};
/*
@ -190,6 +193,15 @@ public:
NS_IMETHOD GetAccLastChild(nsIAccessible **_retval);
NS_IMETHOD GetAccFirstChild(nsIAccessible **_retval);
NS_IMETHOD GetAccValue(nsAString& _retval);
NS_IMETHOD Shutdown();
NS_IMETHOD Init();
protected:
// Hold references to our generated children
// So that we can shut them down when we need to
nsCOMPtr<nsIAccessible> mComboboxTextFieldAccessible;
nsCOMPtr<nsIAccessible> mComboboxButtonAccessible;
nsCOMPtr<nsIAccessible> mComboboxListAccessible;
};
/*
@ -210,11 +222,9 @@ public:
NS_IMETHOD GetAccRole(PRUint32 *_retval);
NS_IMETHOD GetAccValue(nsAString& _retval);
NS_IMETHOD GetAccState(PRUint32 *_retval);
NS_IMETHOD GetUniqueID(void **aUniqueID);
virtual void GetBounds(nsRect& aBounds, nsIFrame** aBoundingFrame);
protected:
nsCOMPtr<nsIAccessible> mParent;
};
/**
@ -238,11 +248,9 @@ public:
NS_IMETHOD GetAccName(nsAString& _retval);
NS_IMETHOD GetAccRole(PRUint32 *_retval);
NS_IMETHOD GetAccState(PRUint32 *_retval);
NS_IMETHOD GetUniqueID(void **aUniqueID);
virtual void GetBounds(nsRect& aBounds, nsIFrame** aBoundingFrame);
protected:
nsCOMPtr<nsIAccessible> mParent;
};
/*
@ -262,11 +270,10 @@ public:
/* ----- nsIAccessible ----- */
NS_IMETHOD GetAccState(PRUint32 *aAccState);
NS_IMETHOD GetAccParent(nsIAccessible **aParent);
NS_IMETHOD GetUniqueID(void **aUniqueID);
NS_IMETHOD GetAccPreviousSibling(nsIAccessible **aAccPrevSibling);
virtual void GetBounds(nsRect& aBounds, nsIFrame** aBoundingFrame);
protected:
nsCOMPtr<nsIAccessible> mParent;
};
#endif

View File

@ -38,8 +38,19 @@
* ***** END LICENSE BLOCK ***** */
#include "nsHTMLTableAccessible.h"
#include "nsWeakReference.h"
#include "nsReadableUtils.h"
#include "nsIServiceManager.h"
#include "nsIDocument.h"
#include "nsIDOMElement.h"
#include "nsIDOMHTMLTableElement.h"
#include "nsIDOMHTMLTableCaptionElem.h"
#include "nsIDOMHTMLTableRowElement.h"
#include "nsIDOMHTMLTableCellElement.h"
#include "nsIDOMHTMLTableSectionElem.h"
#include "nsIDOMHTMLCollection.h"
#include "nsITableLayout.h"
#include "nsHyperTextAccessible.h"
#include "nsIAccessibilityService.h"
#include "nsIPresShell.h"
#ifndef MOZ_ACCESSIBILITY_ATK
@ -83,6 +94,7 @@ nsHTMLTableCaptionAccessible::nsHTMLTableCaptionAccessible
(nsIDOMNode* aDomNode, nsIWeakReference* aShell):
nsAccessibleWrap(aDomNode, aShell)
{
Init(); // Make sure this generated accessible of the table is cached
}
NS_IMETHODIMP
@ -155,6 +167,7 @@ NS_IMETHODIMP nsHTMLTableAccessible::GetAccName(nsAString& aResult)
NS_IMETHODIMP
nsHTMLTableAccessible::GetCaption(nsIAccessible **aCaption)
{
*aCaption = nsnull;
nsresult rv = NS_OK;
nsCOMPtr<nsIDOMHTMLTableElement> table(do_QueryInterface(mDOMNode));
@ -171,6 +184,10 @@ nsHTMLTableAccessible::GetCaption(nsIAccessible **aCaption)
accService(do_GetService("@mozilla.org/accessibilityService;1"));
NS_ENSURE_TRUE(accService, NS_ERROR_FAILURE);
accService->GetCachedAccessible(captionNode, mWeakShell, aCaption);
if (*aCaption)
return NS_OK;
return accService->CreateHTMLTableCaptionAccessible(captionNode, aCaption);
}
@ -243,8 +260,16 @@ nsHTMLTableAccessible::GetColumnHeader(nsIAccessibleTable **aColumnHeader)
NS_ENSURE_TRUE(accService, NS_ERROR_FAILURE);
nsCOMPtr<nsIAccessible> accHead;
rv = accService->CreateHTMLTableHeadAccessible(section,
getter_AddRefs(accHead));
nsCOMPtr<nsIDOMNode> sectionNode(do_QueryInterface(section));
if (sectionNode) {
rv = accService->GetCachedAccessible(sectionNode, mWeakShell,
getter_AddRefs(accHead));
}
if (!accHead) {
rv = accService->CreateHTMLTableHeadAccessible(section,
getter_AddRefs(accHead));
}
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIAccessibleTable> accTableHead(do_QueryInterface(accHead));
@ -359,7 +384,7 @@ nsHTMLTableAccessible::GetSelectedRows(PRUint32 *aNumRows, PRInt32 **aRows)
NS_IMETHODIMP
nsHTMLTableAccessible::CellRefAt(PRInt32 aRow, PRInt32 aColumn,
nsIAccessible **_retval)
nsIAccessible **aTableCellAccessible)
{
nsresult rv = NS_OK;
@ -371,7 +396,8 @@ nsHTMLTableAccessible::CellRefAt(PRInt32 aRow, PRInt32 aColumn,
accService(do_GetService("@mozilla.org/accessibilityService;1"));
NS_ENSURE_TRUE(accService, NS_ERROR_FAILURE);
return accService->GetAccessibleFor(cellElement, _retval);
return accService->GetAccessibleInWeakShell(cellElement, mWeakShell,
aTableCellAccessible);
}
NS_IMETHODIMP
@ -610,6 +636,7 @@ nsHTMLTableHeadAccessible::nsHTMLTableHeadAccessible(nsIDOMNode *aDomNode,
nsIWeakReference *aShell):
nsHTMLTableAccessible(aDomNode, aShell)
{
Init(); // Make sure this generated accessible of the table is cached
}
NS_IMETHODIMP

View File

@ -40,21 +40,12 @@
#ifndef _nsHTMLTableAccessible_H_
#define _nsHTMLTableAccessible_H_
#include "nsAccessibleWrap.h"
#include "nsBaseWidgetAccessible.h"
#include "nsIAccessibleTable.h"
#include "nsIServiceManager.h"
#include "nsIDocument.h"
#include "nsIDOMElement.h"
#include "nsIDOMHTMLTableElement.h"
#include "nsIDOMHTMLTableCaptionElem.h"
#include "nsIDOMHTMLTableRowElement.h"
#include "nsIDOMHTMLTableCellElement.h"
#include "nsIDOMHTMLTableSectionElem.h"
#include "nsIDOMHTMLCollection.h"
#include "nsITableLayout.h"
#include "nsHyperTextAccessible.h"
class nsITableLayout;
#ifndef MOZ_ACCESSIBILITY_ATK
class nsHTMLTableCellAccessible : public nsBlockAccessible
#else

View File

@ -51,7 +51,8 @@
// construction
//-----------------------------------------------------
nsAccessNodeWrap::nsAccessNodeWrap(nsIDOMNode *aNode): nsAccessNode(aNode)
nsAccessNodeWrap::nsAccessNodeWrap(nsIDOMNode *aNode, nsIWeakReference* aShell):
nsAccessNode(aNode, aShell)
{
}
@ -63,3 +64,13 @@ nsAccessNodeWrap::~nsAccessNodeWrap()
}
void nsAccessNodeWrap::InitAccessibility()
{
nsAccessNode::InitXPAccessibility();
}
void nsAccessNodeWrap::ShutdownAccessibility()
{
nsAccessNode::ShutdownXPAccessibility();
}

View File

@ -48,8 +48,11 @@
class nsAccessNodeWrap : public nsAccessNode
{
public: // construction, destruction
nsAccessNodeWrap(nsIDOMNode *);
nsAccessNodeWrap(nsIDOMNode *aNode, nsIWeakReference* aShell);
virtual ~nsAccessNodeWrap();
static void InitAccessibility();
static void ShutdownAccessibility();
};
#endif

View File

@ -49,3 +49,7 @@ nsDocAccessibleWrap::~nsDocAccessibleWrap()
{
}
NS_IMETHODIMP nsDocAccessibleWrap::FireToolkitEvent(PRUint32 aEvent, nsIAccessible* aAccessible, void* aData)
{
return NS_OK;
}

View File

@ -50,6 +50,7 @@ class nsDocAccessibleWrap: public nsDocAccessible
public:
nsDocAccessibleWrap(nsIDOMNode *aNode, nsIWeakReference *aShell);
virtual ~nsDocAccessibleWrap();
NS_IMETHOD FireToolkitEvent(PRUint32 aEvent, nsIAccessible* aAccessible, void* aData);
};
#endif

View File

@ -0,0 +1,3 @@
accessibility_toolkit_s.lib
accessibility_toolkit_s.pdb
Makefile

View File

@ -36,10 +36,8 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsIAccessible.h"
#include "nsAccessNodeWrap.h"
#include "ISimpleDOMNode_i.c"
#include "ISimpleDOMDocument_i.c"
#include "nsIAccessible.h"
#include "nsIFrame.h"
#include "nsIDocument.h"
#include "nsIPresShell.h"
@ -51,6 +49,19 @@
#include "nsIServiceManager.h"
#include "nsINameSpaceManager.h"
#include "nsAccessibleWrap.h"
#include "ISimpleDOMNode_i.c"
#include "nsIPref.h"
#include "nsIServiceManager.h"
/// the accessible library and cached methods
HINSTANCE nsAccessNodeWrap::gmAccLib = nsnull;
HINSTANCE nsAccessNodeWrap::gmUserLib = nsnull;
LPFNACCESSIBLEOBJECTFROMWINDOW nsAccessNodeWrap::gmAccessibleObjectFromWindow = nsnull;
LPFNNOTIFYWINEVENT nsAccessNodeWrap::gmNotifyWinEvent = nsnull;
LPFNGETGUITHREADINFO nsAccessNodeWrap::gmGetGUIThreadInfo = nsnull;
PRBool nsAccessNodeWrap::gIsEnumVariantSupportDisabled = 0;
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
/* For documentation of the accessibility architecture,
* see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
@ -64,7 +75,8 @@
// construction
//-----------------------------------------------------
nsAccessNodeWrap::nsAccessNodeWrap(nsIDOMNode *aNode): nsAccessNode(aNode)
nsAccessNodeWrap::nsAccessNodeWrap(nsIDOMNode *aNode, nsIWeakReference* aShell):
nsAccessNode(aNode, aShell)
{
}
@ -117,8 +129,10 @@ STDMETHODIMP nsAccessNodeWrap::get_nodeInfo(
/* [out] */ unsigned int __RPC_FAR *aUniqueID,
/* [out] */ unsigned short __RPC_FAR *aNodeType)
{
if (!mDOMNode)
return E_FAIL;
*aNodeName = nsnull;
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(mDOMNode));
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
PRUint16 nodeType = 0;
@ -168,9 +182,8 @@ STDMETHODIMP nsAccessNodeWrap::get_attributes(
{
*aNumAttribs = 0;
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(mDOMNode));
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
if (!content || !domElement)
if (!content)
return E_FAIL;
PRInt32 numAttribs;
@ -283,6 +296,9 @@ STDMETHODIMP nsAccessNodeWrap::get_computedStyle(
/* [length_is][size_is][out] */ BSTR __RPC_FAR *aStyleValues,
/* [out] */ unsigned short __RPC_FAR *aNumStyleProperties)
{
if (!mDOMNode)
return E_FAIL;
*aNumStyleProperties = 0;
PRUint32 length;
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
@ -312,6 +328,9 @@ STDMETHODIMP nsAccessNodeWrap::get_computedStyleForProperties(
/* [length_is][size_is][in] */ BSTR __RPC_FAR *aStyleProperties,
/* [length_is][size_is][out] */ BSTR __RPC_FAR *aStyleValues)
{
if (!mDOMNode)
return E_FAIL;
PRUint32 length = 0;
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
nsresult rv = GetComputedStyleDeclaration(getter_AddRefs(cssDecl), &length);
@ -331,24 +350,13 @@ STDMETHODIMP nsAccessNodeWrap::get_computedStyleForProperties(
STDMETHODIMP nsAccessNodeWrap::scrollTo(/* [in] */ boolean aScrollTopLeft)
{
// XXX aaronl - we could move nsIAccessible::GetFrame down and
// save some code by using that
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
nsCOMPtr<nsIDocument> doc;
if (content)
content->GetDocument(*getter_AddRefs(doc));
nsCOMPtr<nsIPresShell> shell;
if (doc)
doc->GetShellAt(0, getter_AddRefs(shell));
nsIFrame *frame = nsnull;
if (shell) {
shell->GetPrimaryFrameFor(content, &frame);
nsCOMPtr<nsIPresShell> shell(GetPresShell());
if (!mDOMNode || !shell) {
return E_FAIL;
}
nsIFrame *frame = GetFrame();
if (frame) {
PRInt32 percent = NS_PRESSHELL_SCROLL_ANYWHERE;
if (aScrollTopLeft)
@ -360,9 +368,8 @@ STDMETHODIMP nsAccessNodeWrap::scrollTo(/* [in] */ boolean aScrollTopLeft)
}
ISimpleDOMNode* nsAccessNodeWrap::MakeSimpleDOMNode(nsIDOMNode *node)
ISimpleDOMNode* nsAccessNodeWrap::MakeAccessNode(nsIDOMNode *node)
{
// aaronl this needs to be rewritten for new accessibility architecture
if (!node)
return NULL;
@ -376,6 +383,7 @@ ISimpleDOMNode* nsAccessNodeWrap::MakeSimpleDOMNode(nsIDOMNode *node)
else {
// Get the document via QueryInterface, since there is no content node
doc = do_QueryInterface(node);
content = do_QueryInterface(node);
}
if (!doc)
@ -385,86 +393,120 @@ ISimpleDOMNode* nsAccessNodeWrap::MakeSimpleDOMNode(nsIDOMNode *node)
if (!accService)
return NULL;
ISimpleDOMNode *iNode = NULL;
nsCOMPtr<nsIAccessible> nsAcc;
accService->GetAccessibleFor(node, getter_AddRefs(nsAcc));
accService->GetAccessibleInWeakShell(node, mWeakShell, getter_AddRefs(nsAcc));
if (nsAcc) {
nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(nsAcc));
NS_ASSERTION(accessNode, "nsIAccessible impl does not inherit from nsIAccessNode");
IAccessible *msaaAccessible;
nsAcc->GetNativeInterface((void**)&msaaAccessible); // addrefs
ISimpleDOMNode *iNode;
msaaAccessible->QueryInterface(IID_ISimpleDOMNode, (void**)&iNode); // addrefs
msaaAccessible->Release(); // Release IAccessible
return iNode;
}
else if (!content) { // We're on a the root frame
// We'll have to use the root dom node to get this accessible
/*
IAccessible * pAcc = NULL;
HRESULT hr = AccessibleObjectFromWindow( mWnd, OBJID_CLIENT, IID_IAccessible, (void **) &pAcc );
if (pAcc) {
ISimpleDOMNode *testNode;
pAcc->QueryInterface(IID_ISimpleDOMNode, (void**)&testNode);
newNode = NS_STATIC_CAST(nsAccessNodeWrap*, testNode);
pAcc->Release();
}
*/
}
else
newNode = new nsAccessNodeWrap(node);
if (newNode) {
newNode->Init(mRootAccessibleDoc);
ISimpleDOMNode *iNode = NS_STATIC_CAST(ISimpleDOMNode*, newNode);
else {
newNode = new nsAccessNodeWrap(node, mWeakShell);
newNode->Init();
iNode = NS_STATIC_CAST(ISimpleDOMNode*, newNode);
iNode->AddRef();
return iNode;
}
return NULL;
return iNode;
}
STDMETHODIMP nsAccessNodeWrap::get_parentNode(ISimpleDOMNode __RPC_FAR *__RPC_FAR *aNode)
{
if (!mDOMNode)
return E_FAIL;
nsCOMPtr<nsIDOMNode> node;
mDOMNode->GetParentNode(getter_AddRefs(node));
*aNode = MakeSimpleDOMNode(node);
*aNode = MakeAccessNode(node);
return S_OK;
}
STDMETHODIMP nsAccessNodeWrap::get_firstChild(ISimpleDOMNode __RPC_FAR *__RPC_FAR *aNode)
{
if (!mDOMNode)
return E_FAIL;
nsCOMPtr<nsIDOMNode> node;
mDOMNode->GetFirstChild(getter_AddRefs(node));
*aNode = MakeSimpleDOMNode(node);
*aNode = MakeAccessNode(node);
return S_OK;
}
STDMETHODIMP nsAccessNodeWrap::get_lastChild(ISimpleDOMNode __RPC_FAR *__RPC_FAR *aNode)
{
if (!mDOMNode)
return E_FAIL;
nsCOMPtr<nsIDOMNode> node;
mDOMNode->GetLastChild(getter_AddRefs(node));
*aNode = MakeSimpleDOMNode(node);
*aNode = MakeAccessNode(node);
return S_OK;
}
STDMETHODIMP nsAccessNodeWrap::get_previousSibling(ISimpleDOMNode __RPC_FAR *__RPC_FAR *aNode)
{
if (!mDOMNode)
return E_FAIL;
nsCOMPtr<nsIDOMNode> node;
mDOMNode->GetPreviousSibling(getter_AddRefs(node));
*aNode = MakeSimpleDOMNode(node);
*aNode = MakeAccessNode(node);
return S_OK;
}
STDMETHODIMP nsAccessNodeWrap::get_nextSibling(ISimpleDOMNode __RPC_FAR *__RPC_FAR *aNode)
{
if (!mDOMNode)
return E_FAIL;
nsCOMPtr<nsIDOMNode> node;
mDOMNode->GetNextSibling(getter_AddRefs(node));
*aNode = MakeSimpleDOMNode(node);
*aNode = MakeAccessNode(node);
return S_OK;
}
void nsAccessNodeWrap::InitAccessibility()
{
if (gIsAccessibilityActive) {
return;
}
nsCOMPtr<nsIPref> prefService(do_GetService(kPrefCID));
if (prefService) {
prefService->GetBoolPref("accessibility.disableenumvariant", &gIsEnumVariantSupportDisabled);
}
if (!gmUserLib) {
gmUserLib =::LoadLibrary("USER32.DLL");
}
if (gmUserLib) {
if (!gmNotifyWinEvent)
gmNotifyWinEvent = (LPFNNOTIFYWINEVENT)GetProcAddress(gmUserLib,"NotifyWinEvent");
if (!gmGetGUIThreadInfo)
gmGetGUIThreadInfo = (LPFNGETGUITHREADINFO)GetProcAddress(gmUserLib,"GetGUIThreadInfo");
}
nsAccessNode::InitXPAccessibility();
}
void nsAccessNodeWrap::ShutdownAccessibility()
{
if (!gIsAccessibilityActive) {
return;
}
nsAccessNode::ShutdownXPAccessibility();
}

View File

@ -49,11 +49,18 @@
#include "nsIDOMElement.h"
#include "nsIContent.h"
#include "nsAccessNode.h"
#include "OLEIDL.H"
#include "OLEACC.H"
#include "winable.h"
#undef ERROR /// Otherwise we can't include nsIDOMNSEvent.h if we include this
typedef LRESULT (STDAPICALLTYPE *LPFNNOTIFYWINEVENT)(DWORD event,HWND hwnd,LONG idObjectType,LONG idObject);
typedef LRESULT (STDAPICALLTYPE *LPFNGETGUITHREADINFO)(DWORD idThread, GUITHREADINFO* pgui);
class nsAccessNodeWrap : public nsAccessNode, public ISimpleDOMNode
{
public: // construction, destruction
nsAccessNodeWrap(nsIDOMNode *);
nsAccessNodeWrap(nsIDOMNode *, nsIWeakReference* aShell);
virtual ~nsAccessNodeWrap();
// IUnknown methods - see iunknown.h for documentation
@ -105,10 +112,22 @@ class nsAccessNodeWrap : public nsAccessNode, public ISimpleDOMNode
virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_previousSibling(ISimpleDOMNode __RPC_FAR *__RPC_FAR *node);
virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_nextSibling(ISimpleDOMNode __RPC_FAR *__RPC_FAR *node);
static void InitAccessibility();
static void ShutdownAccessibility();
/// the accessible library and cached methods
static HINSTANCE gmAccLib;
static HINSTANCE gmUserLib;
static LPFNACCESSIBLEOBJECTFROMWINDOW gmAccessibleObjectFromWindow;
static LPFNNOTIFYWINEVENT gmNotifyWinEvent;
static LPFNGETGUITHREADINFO gmGetGUIThreadInfo;
protected:
void GetAccessibleFor(nsIDOMNode *node, nsIAccessible **newAcc);
ISimpleDOMNode* MakeSimpleDOMNode(nsIDOMNode *node);
ISimpleDOMNode* MakeAccessNode(nsIDOMNode *node);
NS_IMETHOD GetComputedStyleDeclaration(nsIDOMCSSStyleDeclaration **aCssDecl, PRUint32 *aLength);
static PRBool gIsEnumVariantSupportDisabled;
};
#endif

View File

@ -47,7 +47,7 @@ extern CComModule _Module;
#define _ATLCOM_IMPL
#include <atlcom.h>
/* For documentation of the accessibility architecture,
/* For documentation of the accessibility architecture,
* see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
*/
@ -58,7 +58,7 @@ static gAccessibles = 0;
#endif
CComModule _Module;
EXTERN_C GUID CDECL CLSID_Accessible =
{ 0x61044601, 0xa811, 0x4e2b, { 0xbb, 0xba, 0x17, 0xbf, 0xab, 0xd3, 0x29, 0xd7 } };
@ -70,7 +70,7 @@ EXTERN_C GUID CDECL CLSID_Accessible =
// construction
//-----------------------------------------------------
nsAccessibleWrap::nsAccessibleWrap(nsIDOMNode* aNode, nsIWeakReference *aShell):
nsAccessible(aNode, aShell), mCachedChildCount(-1), mEnumVARIANTPosition(0)
nsAccessible(aNode, aShell)
{
}
@ -81,8 +81,6 @@ nsAccessibleWrap::~nsAccessibleWrap()
{
}
// Microsoft COM QueryInterface
//-----------------------------------------------------
// IUnknown interface methods - see iunknown.h for documentation
//-----------------------------------------------------
@ -96,6 +94,7 @@ STDMETHODIMP_(ULONG) nsAccessibleWrap::Release()
return nsAccessNode::Release();
}
// Microsoft COM QueryInterface
STDMETHODIMP nsAccessibleWrap::QueryInterface(REFIID iid, void** ppv)
{
*ppv = NULL;
@ -103,8 +102,9 @@ STDMETHODIMP nsAccessibleWrap::QueryInterface(REFIID iid, void** ppv)
if (IID_IUnknown == iid || IID_IDispatch == iid || IID_IAccessible == iid)
*ppv = NS_STATIC_CAST(IAccessible*, this);
else if (IID_IEnumVARIANT == iid && !gIsEnumVariantSupportDisabled) {
CacheMSAAChildren();
if (mCachedChildCount > 0) // Don't support this interface for leaf elements
PRInt32 numChildren;
GetAccChildCount(&numChildren);
if (numChildren > 0) // Don't support this interface for leaf elements
*ppv = NS_STATIC_CAST(IEnumVARIANT*, this);
}
else if (IID_IServiceProvider == iid) {
@ -156,6 +156,10 @@ STDMETHODIMP nsAccessibleWrap::NotifyWinEvent(DWORD event,
STDMETHODIMP nsAccessibleWrap::get_accParent( IDispatch __RPC_FAR *__RPC_FAR *ppdispParent)
{
*ppdispParent = NULL;
if (!mWeakShell)
return E_FAIL; // We've been shut down
nsCOMPtr<nsIAccessible> xpParentAccessible;
GetAccParent(getter_AddRefs(xpParentAccessible));
@ -164,8 +168,6 @@ STDMETHODIMP nsAccessibleWrap::get_accParent( IDispatch __RPC_FAR *__RPC_FAR *pp
return S_OK;
}
*ppdispParent = NULL;
// If we have a widget but no parent nsIAccessible then we might have a native
// widget parent that could give us a IAccessible. Lets check.
@ -190,18 +192,11 @@ STDMETHODIMP nsAccessibleWrap::get_accParent( IDispatch __RPC_FAR *__RPC_FAR *pp
return E_FAIL;
}
void nsAccessibleWrap::CacheMSAAChildren()
{
mCachedChildCount = -1; // Don't use old info
if (mCachedChildCount < 0)
GetCachedChild(-1); // This caches the children and sets mCachedChildCount
}
STDMETHODIMP nsAccessibleWrap::get_accChildCount( long __RPC_FAR *pcountChildren)
{
CacheMSAAChildren();
*pcountChildren = mCachedChildCount;
PRInt32 numChildren;
GetAccChildCount(&numChildren);
*pcountChildren = numChildren;
return S_OK;
}
@ -212,18 +207,18 @@ STDMETHODIMP nsAccessibleWrap::get_accChild(
{
*ppdispChild = NULL;
if (varChild.vt != VT_I4)
if (!mWeakShell || varChild.vt != VT_I4)
return E_FAIL;
if (varChild.lVal == CHILDID_SELF) {
*ppdispChild = this;
*ppdispChild = NS_STATIC_CAST(IDispatch*, this);
AddRef();
return S_OK;
}
CacheMSAAChildren();
*ppdispChild = GetCachedChild(varChild.lVal - 1); // already addrefed
nsCOMPtr<nsIAccessible> childAccessible;
GetChildAt(varChild.lVal - 1, getter_AddRefs(childAccessible));
*ppdispChild = NativeAccessible(childAccessible);
return (*ppdispChild)? S_OK: E_FAIL;
}
@ -241,6 +236,7 @@ STDMETHODIMP nsAccessibleWrap::get_accName(
return S_FALSE;
*pszName = ::SysAllocString(name.get());
NS_ASSERTION(mIsInitialized, "Access node was not initialized");
}
return S_OK;
@ -424,7 +420,6 @@ STDMETHODIMP nsAccessibleWrap::get_accSelection(VARIANT __RPC_FAR *pvarChildren)
nsCOMPtr<nsIAccessibleSelectable> select;
nsAccessNode::QueryInterface(NS_GET_IID(nsIAccessibleSelectable), getter_AddRefs(select));
//nsCOMPtr<nsIAccessibleSelectable> select(do_QueryInterface(this)); // aaronl is this correct?
if (select) { // do we have an nsIAccessibleSelectable?
// we have an accessible that can have children selected
@ -532,29 +527,6 @@ STDMETHODIMP nsAccessibleWrap::accLocation(
return E_FAIL;
}
IAccessible *
nsAccessibleWrap::GetCachedChild(long aChildNum)
{
// aChildNum of -1 just counts up the children
// and stores the value in mCachedChildCount
VARIANT varStart, varResult;
VariantInit(&varStart);
varStart.lVal = CHILDID_SELF;
varStart.vt = VT_I4;
accNavigate(NAVDIR_FIRSTCHILD, varStart, &varResult);
for (long index = 0; varResult.vt == VT_DISPATCH; ++index) {
IAccessible *msaaAccessible = NS_STATIC_CAST(IAccessible*, varResult.pdispVal);
if (aChildNum == index)
return msaaAccessible;
msaaAccessible->accNavigate(NAVDIR_NEXT, varStart, &varResult);
msaaAccessible->Release();
}
if (mCachedChildCount < 0)
mCachedChildCount = index;
return nsnull;
}
STDMETHODIMP nsAccessibleWrap::accNavigate(
/* [in] */ long navDir,
/* [optional][in] */ VARIANT varStart,
@ -562,14 +534,11 @@ STDMETHODIMP nsAccessibleWrap::accNavigate(
{
nsCOMPtr<nsIAccessible> xpAccessibleStart, xpAccessibleResult;
GetXPAccessibleFor(varStart, getter_AddRefs(xpAccessibleStart));
nsCOMPtr<nsIAccessible> xpAccessibleThis(NS_STATIC_CAST(nsIAccessible*, this));
PRBool isNavigatingFromSelf = (xpAccessibleStart == xpAccessibleThis);
if (!xpAccessibleStart)
return E_FAIL;
VariantInit(pvarEndUpAt);
IAccessible* msaaAccessible = nsnull;
switch(navDir) {
case NAVDIR_DOWN:
xpAccessibleStart->AccNavigateDown(getter_AddRefs(xpAccessibleResult));
@ -632,9 +601,9 @@ STDMETHODIMP nsAccessibleWrap::accHitTest(
pvarChild->pdispVal = NativeAccessible(xpAccessible);
}
} else {
// no child at that point
pvarChild->vt = VT_EMPTY;
return E_FAIL;
// no child at that point
pvarChild->vt = VT_EMPTY;
return E_FAIL;
}
return S_OK;
@ -684,11 +653,18 @@ nsAccessibleWrap::QueryService(REFGUID guidService, REFIID iid, void** ppv)
STDMETHODIMP
nsAccessibleWrap::Next(ULONG aNumElementsRequested, VARIANT FAR* pvar, ULONG FAR* aNumElementsFetched)
{
CacheMSAAChildren();
// If there are two clients using this at the same time, and they are
// each using a different mEnumVariant position it would be bad, because
// we have only 1 object and can only keep of mEnumVARIANT position once
// Children already cached via QI to IEnumVARIANT
*aNumElementsFetched = 0;
PRInt32 numChildren;
GetAccChildCount(&numChildren);
if (aNumElementsRequested <= 0 || !pvar ||
mEnumVARIANTPosition >= mCachedChildCount) {
mEnumVARIANTPosition >= numChildren) {
return E_FAIL;
}
@ -720,13 +696,14 @@ nsAccessibleWrap::Next(ULONG aNumElementsRequested, VARIANT FAR* pvar, ULONG FAR
STDMETHODIMP
nsAccessibleWrap::Skip(ULONG aNumElements)
{
CacheMSAAChildren();
mEnumVARIANTPosition += aNumElements;
if (mEnumVARIANTPosition > mCachedChildCount)
PRInt32 numChildren;
GetAccChildCount(&numChildren);
if (mEnumVARIANTPosition > numChildren)
{
mEnumVARIANTPosition = mCachedChildCount;
mEnumVARIANTPosition = numChildren;
return S_FALSE;
}
return NOERROR;
@ -745,12 +722,10 @@ nsAccessibleWrap::Clone(IEnumVARIANT FAR* FAR* ppenum)
// Clone could be bad, the cloned items aren't tracked for shutdown
// Then again, as long as the client releases the items in time, we're okay
*ppenum = nsnull;
CacheMSAAChildren();
nsAccessibleWrap *accessibleWrap = new nsAccessibleWrap(mDOMNode, mPresShell);
nsAccessibleWrap *accessibleWrap = new nsAccessibleWrap(mDOMNode, mWeakShell);
if (!accessibleWrap)
return E_FAIL;
accessibleWrap->Init(mRootAccessibleDoc);
IAccessible *msaaAccessible = NS_STATIC_CAST(IAccessible*, accessibleWrap);
msaaAccessible->AddRef();
@ -798,7 +773,7 @@ STDMETHODIMP nsAccessibleWrap::Invoke(DISPID dispIdMember, REFIID riid,
NS_IMETHODIMP nsAccessibleWrap::GetNativeInterface(void **aOutAccessible)
{
*aOutAccessible = NS_STATIC_CAST(IAccessible*, this);
NS_ADDREF_THIS();
NS_STATIC_CAST(IAccessible*, this)->AddRef();
return NS_OK;
}
@ -820,7 +795,6 @@ IDispatch *nsAccessibleWrap::NativeAccessible(nsIAccessible *aXPAccessible)
}
nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(aXPAccessible));
accessNode->Init(mRootAccessibleDoc);
IAccessible *msaaAccessible;
aXPAccessible->GetNativeInterface((void**)&msaaAccessible);
@ -829,12 +803,14 @@ IDispatch *nsAccessibleWrap::NativeAccessible(nsIAccessible *aXPAccessible)
}
void nsAccessibleWrap::GetXPAccessibleFor(VARIANT varChild, nsIAccessible **aXPAccessible)
void nsAccessibleWrap::GetXPAccessibleFor(const VARIANT& aVarChild, nsIAccessible **aXPAccessible)
{
*aXPAccessible = nsnull;
if (!mWeakShell)
return; // Fail, we don't want to do anything after we've shut down
// if its us real easy - this seems to always be the case
if (varChild.lVal == CHILDID_SELF) {
if (aVarChild.lVal == CHILDID_SELF) {
*aXPAccessible = NS_STATIC_CAST(nsIAccessible*, this);
}
else {
@ -845,7 +821,7 @@ void nsAccessibleWrap::GetXPAccessibleFor(VARIANT varChild, nsIAccessible **aXPA
nsCOMPtr<nsIAccessible> xpAccessible, nextAccessible;
GetAccFirstChild(getter_AddRefs(xpAccessible));
for (PRInt32 index = 0; xpAccessible; index ++) {
if (varChild.lVal == index) {
if (aVarChild.lVal == index) {
*aXPAccessible = xpAccessible;
break;
}

View File

@ -43,24 +43,9 @@
#ifndef _nsAccessibleWrap_H_
#define _nsAccessibleWrap_H_
#include "OLEIDL.H"
#include "OLEACC.H"
#include "winable.h"
#undef ERROR /// Otherwise we can't include nsIDOMNSEvent.h if we include this
#include "nsCOMPtr.h"
#include "nsAccessible.h"
typedef LRESULT (STDAPICALLTYPE *LPFNNOTIFYWINEVENT)(DWORD event,HWND hwnd,LONG idObjectType,LONG idObject);
typedef LRESULT (STDAPICALLTYPE *LPFNGETGUITHREADINFO)(DWORD idThread, GUITHREADINFO* pgui);
/// the accessible library and cached methods
static HINSTANCE gmAccLib;
static HINSTANCE gmUserLib;
static LPFNACCESSIBLEOBJECTFROMWINDOW gmAccessibleObjectFromWindow;
static LPFNNOTIFYWINEVENT gmNotifyWinEvent;
static LPFNGETGUITHREADINFO gmGetGUIThreadInfo;
static PRBool gIsEnumVariantSupportDisabled = PR_FALSE;
class nsAccessibleWrap : public nsAccessible,
public IAccessible,
public IEnumVARIANT,
@ -192,7 +177,7 @@ class nsAccessibleWrap : public nsAccessible,
LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr);
virtual void GetXPAccessibleFor(VARIANT varChild, nsIAccessible **aXPAccessible);
virtual void GetXPAccessibleFor(const VARIANT& aVarChild, nsIAccessible **aXPAccessible);
NS_IMETHOD GetNativeInterface(void **aOutAccessible);
// NT4 does not have the oleacc that defines these methods. So we define copies here that automatically
@ -201,21 +186,12 @@ class nsAccessibleWrap : public nsAccessible,
static STDMETHODIMP NotifyWinEvent(DWORD event,HWND hwnd,LONG idObjectType,LONG idObject);
protected:
long mCachedChildCount;
// mEnumVARIANTPosition not the current accessible's position, but a "cursor" of
// where we are in the current list of children, with respect to
// nsIEnumVariant::Reset(), Skip() and Next().
long mEnumVARIANTPosition;
PRUint16 mEnumVARIANTPosition;
IDispatch *NativeAccessible(nsIAccessible *aXPAccessible);
// Most IAccessible methods are not optimized to use the cache
// when CHILDID_SELF is mot used in the VARIANT struct.
// For this reason, a child number of CHILDID_SELF is recommended,
// rather than using the child number you need in the VARIANT
// This is what most assistive tech tends to do, so it shouldn't be a problem.
void CacheMSAAChildren();
IAccessible *GetCachedChild(long aChildNum);
};
#endif

View File

@ -38,8 +38,12 @@
#include "nsDocAccessibleWrap.h"
#include "ISimpleDOMDocument_i.c"
#include "nsIAccessibleEventReceiver.h"
#include "nsIPresShell.h"
#include "nsIViewManager.h"
#include "nsIWidget.h"
/* For documentation of the accessibility architecture,
/* For documentation of the accessibility architecture,
* see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
*/
@ -54,8 +58,20 @@ nsDocAccessibleWrap::~nsDocAccessibleWrap()
{
}
NS_IMPL_ISUPPORTS_INHERITED0(nsDocAccessibleWrap, nsDocAccessible)
//-----------------------------------------------------
// IUnknown interface methods - see iunknown.h for documentation
//-----------------------------------------------------
STDMETHODIMP_(ULONG) nsDocAccessibleWrap::AddRef()
{
return nsAccessNode::AddRef();
}
STDMETHODIMP_(ULONG) nsDocAccessibleWrap::Release()
{
return nsAccessNode::Release();
}
// Microsoft COM QueryInterface
STDMETHODIMP nsDocAccessibleWrap::QueryInterface(REFIID iid, void** ppv)
{
*ppv = NULL;
@ -70,6 +86,156 @@ STDMETHODIMP nsDocAccessibleWrap::QueryInterface(REFIID iid, void** ppv)
return S_OK;
}
void nsDocAccessibleWrap::GetXPAccessibleFor(const VARIANT& aVarChild, nsIAccessible **aXPAccessible)
{
*aXPAccessible = nsnull;
if (!mWeakShell)
return; // This document has been shut down
if (aVarChild.lVal < 0) {
// Get from hash table
void *uniqueID = (void*)(-aVarChild.lVal); // Convert child ID back to unique ID
nsCOMPtr<nsIAccessNode> accessNode;
GetCachedAccessNode(uniqueID, getter_AddRefs(accessNode));
nsCOMPtr<nsIAccessible> accessible(do_QueryInterface(accessNode));
NS_IF_ADDREF(*aXPAccessible = accessible);
return;
}
nsDocAccessible::GetXPAccessibleFor(aVarChild, aXPAccessible);
}
STDMETHODIMP nsDocAccessibleWrap::get_accChild(
/* [in] */ VARIANT varChild,
/* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppdispChild)
{
*ppdispChild = NULL;
if (varChild.vt == VT_I4 && varChild.lVal < 0) {
// AccessibleObjectFromEvent() being called
// that's why the lVal < 0
nsCOMPtr<nsIAccessible> xpAccessible;
GetXPAccessibleFor(varChild, getter_AddRefs(xpAccessible));
if (xpAccessible) {
IAccessible *msaaAccessible;
xpAccessible->GetNativeInterface((void**)&msaaAccessible);
*ppdispChild = NS_STATIC_CAST(IDispatch*, msaaAccessible);
return S_OK;
}
else {
// If child ID from event can't be found in this window, ask parent.
// This is especially relevant for times when a xul menu item
// has focus, but the system thinks the content window has focus.
nsCOMPtr<nsIDocument> parentDoc;
mDocument->GetParentDocument(getter_AddRefs(parentDoc));
if (parentDoc) {
nsCOMPtr<nsIPresShell> parentShell;
parentDoc->GetShellAt(0, getter_AddRefs(parentShell));
nsCOMPtr<nsIWeakReference> weakParentShell(do_GetWeakReference(parentShell));
if (weakParentShell) {
nsCOMPtr<nsIAccessibleDocument> parentDocAccessible;
nsAccessNode::GetDocAccessibleFor(weakParentShell,
getter_AddRefs(parentDocAccessible));
nsCOMPtr<nsIAccessible> accessible(do_QueryInterface(parentDocAccessible));
IAccessible *msaaParentDoc;
accessible->GetNativeInterface((void**)&msaaParentDoc);
HRESULT rv = msaaParentDoc->get_accChild(varChild, ppdispChild);
msaaParentDoc->Release();
return rv;
}
}
}
return E_FAIL;
}
// Otherwise, the normal get_accChild() will do
return nsAccessibleWrap::get_accChild(varChild, ppdispChild);
}
NS_IMETHODIMP nsDocAccessibleWrap::FireToolkitEvent(PRUint32 aEvent, nsIAccessible* aAccessible, void* aData)
{
if (!mWeakShell) { // Means we're not active
return NS_ERROR_FAILURE;
}
#ifdef SWALLOW_DOC_FOCUS_EVENTS
// Remove this until we can figure out which focus events are coming at
// the same time as native window focus events, although
// perhaps 2 duplicate focus events on the window isn't really a problem
if (aEvent == EVENT_FOCUS) {
// Don't fire accessible focus event for documents,
// Microsoft Windows will generate those from native window focus events
nsCOMPtr<nsIAccessibleDocument> accessibleDoc(do_QueryInterface(aAccessible));
if (accessibleDoc)
return NS_OK;
}
#endif
PRInt32 childID, worldID = OBJID_CLIENT;
PRUint32 role = ROLE_SYSTEM_TEXT; // Default value
if (NS_SUCCEEDED(aAccessible->GetAccRole(&role)) && role == ROLE_SYSTEM_CARET) {
childID = CHILDID_SELF;
worldID = OBJID_CARET;
}
else
childID = GetChildIDFor(aAccessible); // get the id for the accessible
if (role == ROLE_SYSTEM_PANE && aEvent == EVENT_STATE_CHANGE) {
// Something on the document has changed
// Clear out the cache in this subtree
}
if (role == EVENT_OBJECT_REORDER) {
// Probably need to do this somewhere else so simple dom nodes get shutdown
nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(aAccessible));
accessNode->Shutdown();
}
HWND hWnd;
if (gmGetGUIThreadInfo && (aEvent == EVENT_FOCUS ||
aEvent == EVENT_MENUPOPUPSTART ||
aEvent == EVENT_MENUPOPUPEND)) {
GUITHREADINFO guiInfo;
guiInfo.cbSize = sizeof(GUITHREADINFO);
if (gmGetGUIThreadInfo(NULL, &guiInfo)) {
hWnd = guiInfo.hwndFocus;
}
#ifdef DEBUG
if (hWnd != NS_REINTERPRET_CAST(HWND, mWnd)) {
// Probably a menu item
printf("\n*** The focused window is %x, the accessible's window is %x\n", (void*)hWnd, (void*)mWnd);
}
//NS_ASSERTION(hWnd == NS_REINTERPRET_CAST(HWND, mWnd), "We need to figure out when the system focus window"
// "is different from the window that the focused accessible thinks it's in");
//hWnd = NS_REINTERPRET_CAST(HWND, mWnd);
}
#endif
else {
hWnd = NS_REINTERPRET_CAST(HWND, mWnd);
}
// notify the window system
NotifyWinEvent(aEvent, hWnd, worldID, childID);
return NS_OK;
}
PRInt32 nsDocAccessibleWrap::GetChildIDFor(nsIAccessible* aAccessible)
{
// A child ID of the window is required, when we use NotifyWinEvent, so that the 3rd party application
// can call back and get the IAccessible the event occured on.
// We use the unique ID exposed through nsIContent::GetContentID()
void *uniqueID;
nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(aAccessible));
accessNode->GetUniqueID(&uniqueID);
// Yes, this means we're only compatibible with 32 bit
// MSAA is only available for 32 bit windows, so it's okay
return - NS_PTR_TO_INT32(uniqueID);
}
STDMETHODIMP nsDocAccessibleWrap::get_URL(/* [out] */ BSTR __RPC_FAR *aURL)
{
*aURL = NULL;

View File

@ -43,23 +43,24 @@
#ifndef _nsDocAccessibleWrap_H_
#define _nsDocAccessibleWrap_H_
#include "nsCOMPtr.h"
#include "ISimpleDOMDocument.h"
#include "nsDocAccessible.h"
class nsDocAccessibleWrap: public nsDocAccessible,
public ISimpleDOMDocument
public ISimpleDOMDocument
{
public:
nsDocAccessibleWrap(nsIDOMNode *aNode, nsIWeakReference *aShell);
virtual ~nsDocAccessibleWrap();
// IUnknown
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
STDMETHODIMP QueryInterface(REFIID, void**);
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
static PRInt32 GetChildIDFor(nsIAccessible* aAccessible);
void GetXPAccessibleFor(const VARIANT& varChild, nsIAccessible **aXPAccessible);
// ISimpleDOMDocument
virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_URL(
/* [out] */ BSTR __RPC_FAR *url);
@ -79,6 +80,14 @@ public:
virtual /* [id] */ HRESULT STDMETHODCALLTYPE put_alternateViewMediaTypes(
/* [in] */ BSTR __RPC_FAR *commaSeparatedMediaTypes);
// IAccessible
// Overrid get_accChild so that it can get any child via the unique ID
virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_accChild(
/* [in] */ VARIANT varChild,
/* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppdispChild);
NS_IMETHOD FireToolkitEvent(PRUint32 aEvent, nsIAccessible* aAccessible, void* aData);
};
#endif

View File

@ -47,156 +47,14 @@
* see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
*/
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
//----- nsRootAccessibleWrap -----
nsRootAccessibleWrap::nsRootAccessibleWrap(nsIDOMNode *aDOMNode, nsIWeakReference *aShell):
nsRootAccessible(aDOMNode, aShell)
{
// XXX aaronl: we should be able to simplify event handling
// now that we have 1 accessible class hierarchy.
// Why should we have to call Add/Remove accesible event listener anymore?
static PRBool prefsInitialized;
if (!prefsInitialized) {
nsCOMPtr<nsIPref> prefService(do_GetService(kPrefCID));
if (prefService) {
//prefService->GetBoolPref("accessibility.disablecache", &gIsCacheDisabled);
prefService->GetBoolPref("accessibility.disableenumvariant", &gIsEnumVariantSupportDisabled);
}
prefsInitialized = PR_TRUE;
}
if (!gmUserLib) {
gmUserLib =::LoadLibrary("USER32.DLL");
}
if (gmUserLib) {
if (!gmNotifyWinEvent)
gmNotifyWinEvent = (LPFNNOTIFYWINEVENT)GetProcAddress(gmUserLib,"NotifyWinEvent");
if (!gmGetGUIThreadInfo)
gmGetGUIThreadInfo = (LPFNGETGUITHREADINFO)GetProcAddress(gmUserLib,"GetGUIThreadInfo");
}
}
nsRootAccessibleWrap::~nsRootAccessibleWrap()
{
}
NS_IMPL_ISUPPORTS_INHERITED1(nsRootAccessibleWrap, nsRootAccessible, nsIAccessibleEventListener)
void nsRootAccessibleWrap::GetXPAccessibleFor(VARIANT varChild, nsIAccessible **aXPAccessible)
{
*aXPAccessible = nsnull;
if (varChild.lVal < 0) {
// Get from hash table
// Not implemented yet
NS_IF_ADDREF(*aXPAccessible);
return;
}
nsRootAccessible::GetXPAccessibleFor(varChild, aXPAccessible);
}
STDMETHODIMP nsRootAccessibleWrap::get_accChild(
/* [in] */ VARIANT varChild,
/* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppdispChild)
{
*ppdispChild = NULL;
if (varChild.vt == VT_I4 && varChild.lVal < 0) {
// AccessibleObjectFromEvent() being called
// that's why the lVal < 0
nsCOMPtr<nsIAccessible> xpAccessible;
GetXPAccessibleFor(varChild, getter_AddRefs(xpAccessible));
if (xpAccessible) {
IAccessible *msaaAccessible;
xpAccessible->GetNativeInterface((void**)&msaaAccessible);
varChild.pdispVal = NS_STATIC_CAST(IDispatch*, msaaAccessible);
return S_OK;
}
return E_FAIL;
}
// Otherwise, the normal get_accChild() will do
return nsAccessibleWrap::get_accChild(varChild, ppdispChild);
}
NS_IMETHODIMP nsRootAccessibleWrap::HandleEvent(PRUint32 aEvent, nsIAccessible* aAccessible, void* aData)
{
if (!mDOMNode) { // Means we're not active
return NS_ERROR_FAILURE;
}
#ifdef SWALLOW_DOC_FOCUS_EVENTS
// Remove this until we can figure out which focus events are coming at
// the same time as native window focus events, although
// perhaps 2 duplicate focus events on the window isn't really a problem
if (aEvent == EVENT_FOCUS) {
// Don't fire accessible focus event for documents,
// Microsoft Windows will generate those from native window focus events
nsCOMPtr<nsIAccessibleDocument> accessibleDoc(do_QueryInterface(aAccessible));
if (accessibleDoc)
return NS_OK;
}
#endif
PRInt32 childID, worldID = OBJID_CLIENT;
PRUint32 role = ROLE_SYSTEM_TEXT; // Default value
if (NS_SUCCEEDED(aAccessible->GetAccRole(&role)) && role == ROLE_SYSTEM_CARET) {
childID = CHILDID_SELF;
worldID = OBJID_CARET;
}
else
childID = GetIdFor(aAccessible); // get the id for the accessible
if (role == ROLE_SYSTEM_PANE && aEvent == EVENT_STATE_CHANGE) {
// Something on the document has changed
// Clear out the cache in this subtree
}
if (role == EVENT_OBJECT_REORDER) {
// Probably need to do this somewhere else so simple dom nodes get shutdown
nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(aAccessible));
accessNode->Shutdown();
}
HWND hWnd; //= mWnd; // aaronl we're a sibling now, how to we get that data
if (gmGetGUIThreadInfo && (aEvent == EVENT_FOCUS ||
aEvent == EVENT_MENUPOPUPSTART ||
aEvent == EVENT_MENUPOPUPEND)) {
GUITHREADINFO guiInfo;
guiInfo.cbSize = sizeof(GUITHREADINFO);
if (gmGetGUIThreadInfo(NULL, &guiInfo)) {
hWnd = guiInfo.hwndFocus;
}
}
else {
void *wnd;
GetOwnerWindow(&wnd);
hWnd = NS_REINTERPRET_CAST(HWND, wnd);
}
// notify the window system
//NotifyWinEvent(aEvent, hWnd, worldID, childID);
return NS_OK;
}
PRUint32 nsRootAccessibleWrap::GetIdFor(nsIAccessible* aAccessible)
{
// A child ID of the window is required, when we use NotifyWinEvent, so that the 3rd party application
// can call back and get the IAccessible the event occured on.
// We use the unique ID exposed through nsIContent::GetContentID()
PRInt32 uniqueID;
aAccessible->GetAccId(&uniqueID);
return uniqueID;
}

View File

@ -46,27 +46,11 @@
#include "nsCOMPtr.h"
#include "nsRootAccessible.h"
class nsRootAccessibleWrap: public nsIAccessibleEventListener,
public nsRootAccessible
class nsRootAccessibleWrap: public nsRootAccessible
{
public:
public:
nsRootAccessibleWrap(nsIDOMNode *aNode, nsIWeakReference *aShell);
virtual ~nsRootAccessibleWrap();
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
// IAccessible
// Overrid get_accChild so that it can get any child via the unique ID
virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_accChild(
/* [in] */ VARIANT varChild,
/* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppdispChild);
// nsIAccessibleEventListener
NS_DECL_NSIACCESSIBLEEVENTLISTENER
PRUint32 GetIdFor(nsIAccessible* aAccessible);
virtual void GetXPAccessibleFor(VARIANT varChild, nsIAccessible **aXPAccessible);
};
#endif

View File

@ -51,7 +51,8 @@
// construction
//-----------------------------------------------------
nsAccessNodeWrap::nsAccessNodeWrap(nsIDOMNode *aNode): nsAccessNode(aNode)
nsAccessNodeWrap::nsAccessNodeWrap(nsIDOMNode *aNode, nsIWeakReference* aShell):
nsAccessNode(aNode, aShell)
{
}
@ -62,4 +63,13 @@ nsAccessNodeWrap::~nsAccessNodeWrap()
{
}
void nsAccessNodeWrap::InitAccessibility()
{
nsAccessNode::InitXPAccessibility();
}
void nsAccessNodeWrap::ShutdownAccessibility()
{
nsAccessNode::ShutdownXPAccessibility();
}

View File

@ -48,7 +48,7 @@
class nsAccessNodeWrap : public nsAccessNode
{
public: // construction, destruction
nsAccessNodeWrap(nsIDOMNode *);
nsAccessNodeWrap(nsIDOMNode *aNode, nsIWeakReference* aShell);
virtual ~nsAccessNodeWrap();
};

View File

@ -49,3 +49,7 @@ nsDocAccessibleWrap::~nsDocAccessibleWrap()
{
}
NS_IMETHODIMP nsDocAccessibleWrap::FireToolkitEvent(PRUint32 aEvent, nsIAccessible* aAccessible, void* aData)
{
return NS_OK;
}

View File

@ -50,6 +50,7 @@ class nsDocAccessibleWrap: public nsDocAccessible
public:
nsDocAccessibleWrap(nsIDOMNode *aNode, nsIWeakReference *aShell);
virtual ~nsDocAccessibleWrap();
NS_IMETHOD FireToolkitEvent(PRUint32 aEvent, nsIAccessible* aAccessible, void* aData);
};
#endif

View File

@ -1 +1,3 @@
accessibility_xul_s.lib
accessibility_xul_s.pdb
Makefile

View File

@ -39,9 +39,6 @@
// NOTE: alphabetically ordered
#include "nsXULColorPickerAccessible.h"
#include "nsReadableUtils.h"
#include "nsString.h"
#include "nsXULFormControlAccessible.h"
#include "nsIDOMElement.h"

View File

@ -39,20 +39,12 @@
* ***** END LICENSE BLOCK ***** */
// NOTE: alphabetically ordered
#include "nsIDocument.h"
#include "nsIDOMNodeList.h"
#include "nsXULFormControlAccessible.h"
#include "nsIDOMXULButtonElement.h"
#include "nsIDOMXULCheckboxElement.h"
#include "nsIDOMXULDocument.h"
#include "nsIDOMXULLabelElement.h"
#include "nsIDOMXULMenuListElement.h"
#include "nsIDOMXULSelectCntrlEl.h"
#include "nsIDOMXULSelectCntrlItemEl.h"
#include "nsReadableUtils.h"
#include "nsString.h"
#include "nsXULFormControlAccessible.h"
#include "nsIAccessibilityService.h"
#include "nsIServiceManager.h"
#include "nsAccessibleTreeWalker.h"
/**
* XUL Button: can contain arbitrary HTML content
@ -167,22 +159,25 @@ NS_IMETHODIMP nsXULButtonAccessible::GetAccState(PRUint32 *_retval)
*/
NS_IMETHODIMP nsXULButtonAccessible::GetAccFirstChild(nsIAccessible **aResult)
{
*aResult = nsnull;
if (!mFirstChild) {
nsAccessibleTreeWalker walker(mWeakShell, mDOMNode, PR_TRUE);
walker.GetLastChild();
nsCOMPtr<nsIAccessible> testAccessible;
nsAccessible::GetAccLastChild(getter_AddRefs(testAccessible));
// If the anonymous tree walker can find accessible children,
// and the last one is a push button, then use it as the only accessible
// child -- because this is the scenario where we have a dropmarker child
// If the anonymous tree walker can find accessible children, and the last one is a push button,
// then use it as the only accessible child -- because this is the scenario where we have a dropmarker child
if (testAccessible) {
PRUint32 role;
if (NS_SUCCEEDED(testAccessible->GetAccRole(&role)) && role == ROLE_PUSHBUTTON) {
*aResult = testAccessible;
NS_ADDREF(*aResult);
if (walker.mState.accessible) {
PRUint32 role;
if (NS_SUCCEEDED(walker.mState.accessible->GetAccRole(&role)) && role == ROLE_PUSHBUTTON) {
mFirstChild = walker.mState.accessible;
mFirstChild->SetAccNextSibling(nsnull);
}
}
}
mAccChildCount = (mFirstChild != nsnull);
NS_IF_ADDREF(*aResult = mFirstChild);
return NS_OK;
}
@ -193,12 +188,9 @@ NS_IMETHODIMP nsXULButtonAccessible::GetAccLastChild(nsIAccessible **aResult)
NS_IMETHODIMP nsXULButtonAccessible::GetAccChildCount(PRInt32 *aResult)
{
*aResult = 0;
nsCOMPtr<nsIAccessible> accessible;
GetAccFirstChild(getter_AddRefs(accessible));
if (accessible)
*aResult = 1;
*aResult = mAccChildCount;
return NS_OK;
}
@ -352,7 +344,6 @@ NS_IMETHODIMP nsXULCheckboxAccessible::GetAccActionName(PRUint8 index, nsAString
NS_IMETHODIMP nsXULCheckboxAccessible::AccDoAction(PRUint8 index)
{
if (index == eAction_Click) {
PRBool checked = PR_FALSE;
nsCOMPtr<nsIDOMXULCheckboxElement> xulCheckboxElement(do_QueryInterface(mDOMNode));
if (xulCheckboxElement) {
xulCheckboxElement->Click();
@ -575,7 +566,7 @@ NS_IMETHODIMP nsXULRadioButtonAccessible::GetAccParent(nsIAccessible ** aAccPar
nsCOMPtr<nsIAccessible> tempParent;
nsAccessible::GetAccParent(getter_AddRefs(tempParent));
if (tempParent)
tempParent->GetAccParent(getter_AddRefs(mParent));
tempParent->GetAccParent(&mParent); // mParent is a weak pointer
}
NS_ASSERTION(mParent,"Whoa! This RadioButtonAcc doesn't have a parent! Better find out why.");
*aAccParent = mParent;

View File

@ -42,9 +42,7 @@
#define _nsXULFormControlAccessible_H_
// NOTE: alphabetically ordered
#include "nsBaseWidgetAccessible.h"
#include "nsFormControlAccessible.h"
#include "nsHTMLFormControlAccessible.h"
#include "nsIAccessibleValue.h"
class nsXULButtonAccessible : public nsAccessibleWrap

View File

@ -38,8 +38,6 @@
* ***** END LICENSE BLOCK ***** */
#include "nsXULMenuAccessible.h"
#include "nsAccessibleWrap.h"
#include "nsIAccessible.h"
#include "nsIDOMElement.h"
#include "nsIDOMXULElement.h"
#include "nsIDOMXULSelectCntrlItemEl.h"
@ -179,40 +177,11 @@ NS_IMETHODIMP nsXULMenuitemAccessible::GetAccRole(PRUint32 *_retval)
return NS_OK;
}
NS_IMETHODIMP nsXULMenuitemAccessible::GetAccFirstChild(nsIAccessible **aAccFirstChild)
{
*aAccFirstChild = nsnull;
// Last argument of PR_FALSE indicates we don't walk anonymous children for menuitems
nsAccessibleTreeWalker walker(mPresShell, mDOMNode, mSiblingIndex, mSiblingList, PR_FALSE);
if (NS_SUCCEEDED(walker.GetFirstChild())) {
*aAccFirstChild = walker.mState.accessible;
NS_ADDREF(*aAccFirstChild);
}
return NS_OK;
}
NS_IMETHODIMP nsXULMenuitemAccessible::GetAccLastChild(nsIAccessible **aAccLastChild)
{
*aAccLastChild = nsnull;
// Last argument of PR_FALSE indicates we don't walk anonymous children for menuitems
nsAccessibleTreeWalker walker(mPresShell, mDOMNode, mSiblingIndex, mSiblingList, PR_FALSE);
if (NS_SUCCEEDED(walker.GetLastChild())) {
*aAccLastChild = walker.mState.accessible;
NS_ADDREF(*aAccLastChild);
}
return NS_OK;
}
NS_IMETHODIMP nsXULMenuitemAccessible::GetAccChildCount(PRInt32 *aAccChildCount)
{
// Last argument of PR_FALSE indicates we don't walk anonymous children for menuitems
nsAccessibleTreeWalker walker(mPresShell, mDOMNode, mSiblingIndex, mSiblingList, PR_FALSE);
*aAccChildCount = walker.GetChildCount();
// Argument of PR_FALSE indicates we don't walk anonymous children for menuitems
CacheChildren(PR_FALSE);
*aAccChildCount = mAccChildCount;
return NS_OK;
}

View File

@ -41,6 +41,7 @@
#define _nsXULMenuAccessible_H_
#include "nsAccessibleWrap.h"
#include "nsAccessibleTreeWalker.h"
/* Accessible for supporting XUL menus
*/
@ -54,8 +55,6 @@ public:
NS_IMETHOD GetAccKeybinding(nsAString& _retval);
NS_IMETHOD GetAccState(PRUint32 *_retval);
NS_IMETHOD GetAccRole(PRUint32 *_retval);
NS_IMETHOD GetAccFirstChild(nsIAccessible **aAccFirstChild);
NS_IMETHOD GetAccLastChild(nsIAccessible **aAccLastChild);
NS_IMETHOD GetAccChildCount(PRInt32 *aAccChildCount);
NS_IMETHOD AccDoAction(PRUint8 index);
NS_IMETHOD GetAccActionName(PRUint8 index, nsAString& _retval);

View File

@ -37,17 +37,12 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsCOMPtr.h"
#include "nsXULSelectAccessible.h"
#include "nsIAccessibilityService.h"
#include "nsIDOMEventReceiver.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMXULMenuListElement.h"
#include "nsIDOMXULMultSelectCntrlEl.h"
#include "nsIDOMXULSelectCntrlItemEl.h"
#include "nsIDOMXULSelectCntrlEl.h"
#include "nsIServiceManager.h"
#include "nsLayoutAtoms.h"
/**
* Selects, Listboxes and Comboboxes, are made up of a number of different
@ -147,7 +142,7 @@ NS_IMETHODIMP nsXULSelectableAccessible::GetSelectedChildren(nsISupportsArray **
nsCOMPtr<nsIDOMXULSelectControlItemElement> tempNode;
xulMultiSelect->GetSelectedItem(index, getter_AddRefs(tempNode));
nsCOMPtr<nsIDOMNode> tempDOMNode (do_QueryInterface(tempNode));
accService->CreateXULListitemAccessible(tempDOMNode, getter_AddRefs(tempAccessible));
accService->GetAccessibleInWeakShell(tempDOMNode, mWeakShell, getter_AddRefs(tempAccessible));
if (tempAccessible)
selectedAccessibles->AppendElement(tempAccessible);
}
@ -183,7 +178,7 @@ NS_IMETHODIMP nsXULSelectableAccessible::RefSelection(PRInt32 aIndex, nsIAccessi
if (tempDOMNode) {
nsCOMPtr<nsIAccessible> tempAccess;
accService->CreateXULListitemAccessible(tempDOMNode, getter_AddRefs(tempAccess));
accService->GetAccessibleInWeakShell(tempDOMNode, mWeakShell, getter_AddRefs(tempAccess));
*_retval = tempAccess;
NS_ADDREF(*_retval);
return NS_OK;
@ -491,15 +486,6 @@ NS_IMETHODIMP nsXULComboboxAccessible::GetAccRole(PRUint32 *_retval)
return NS_OK;
}
/**
* We always have 3 children: TextField, Button, Window. In that order
*/
NS_IMETHODIMP nsXULComboboxAccessible::GetAccChildCount(PRInt32 *_retval)
{
*_retval = 3;
return NS_OK;
}
/**
* As a nsComboboxAccessible we can have the following states:
* STATE_FOCUSED

View File

@ -42,10 +42,10 @@
#include "nsCOMPtr.h"
#include "nsIAccessibleSelectable.h"
#include "nsIDOMNode.h"
#include "nsIWeakReference.h"
#include "nsXULMenuAccessible.h"
class nsIWeakReference;
/**
* Selects, Listboxes and Comboboxes, are made up of a number of different
* widgets, some of which are shared between the two. This file contains
@ -115,8 +115,6 @@ public:
/* ----- nsIAccessible ----- */
NS_IMETHOD GetAccRole(PRUint32 *_retval);
NS_IMETHOD GetAccState(PRUint32 *_retval);
static nsresult GetFocusedOptionNode(nsIWeakReference *aPresShell, nsIDOMNode *aListNode, nsCOMPtr<nsIDOMNode>& aFocusedOptionNode);
};
/** ------------------------------------------------------ */
@ -175,7 +173,6 @@ public:
/* ----- nsIAccessible ----- */
NS_IMETHOD GetAccRole(PRUint32 *_retval);
NS_IMETHOD GetAccChildCount(PRInt32 *_retval);
NS_IMETHOD GetAccState(PRUint32 *_retval);
NS_IMETHOD GetAccValue(nsAString& _retval);

View File

@ -38,21 +38,12 @@
* ***** END LICENSE BLOCK ***** */
// NOTE: alphabetically ordered
#include "nsAccessibilityService.h"
#include "nsXULTabAccessible.h"
#include "nsIContentViewer.h"
#include "nsIDocShell.h"
#include "nsIDocument.h"
#include "nsIFrame.h"
#include "nsIDOMDocument.h"
#include "nsIDOMXULSelectCntrlEl.h"
#include "nsIDOMXULSelectCntrlItemEl.h"
#include "nsIFrame.h"
#include "nsIPluginViewer.h"
#include "nsIScriptGlobalObject.h"
#include "nsIWebShell.h"
#include "nsIWebShellWindow.h"
#include "nsplugindefs.h"
#include "nsPluginViewer.h"
/**
* XUL Tab
@ -127,7 +118,7 @@ NS_IMETHODIMP nsXULTabAccessible::GetAccState(PRUint32 *_retval)
// Check style for -moz-user-focus: normal to see if it's focusable
*_retval &= ~STATE_FOCUSABLE;
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mPresShell));
nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell));
if (presShell && content) {
nsIFrame *frame = nsnull;
const nsStyleUserInterface* ui;
@ -156,7 +147,7 @@ nsAccessibleWrap(aNode, aShell)
/** We are a window*/
NS_IMETHODIMP nsXULTabBoxAccessible::GetAccRole(PRUint32 *_retval)
{
*_retval = ROLE_WINDOW;
*_retval = ROLE_PANE;
return NS_OK;
}
@ -167,12 +158,14 @@ NS_IMETHODIMP nsXULTabBoxAccessible::GetAccState(PRUint32 *_retval)
return NS_OK;
}
#ifdef NEVER
/** 2 children, tabs, tabpanels */
NS_IMETHODIMP nsXULTabBoxAccessible::GetAccChildCount(PRInt32 *_retval)
{
*_retval = 2;
return NS_OK;
}
#endif
/**
* XUL TabPanels
@ -189,7 +182,7 @@ NS_IMETHODIMP nsXULTabBoxAccessible::GetAccChildCount(PRInt32 *_retval)
/** Constructor */
nsXULTabPanelsAccessible::nsXULTabPanelsAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell):
nsAccessibleWrap(aNode, aShell), mAccService(do_GetService("@mozilla.org/accessibilityService;1"))
nsAccessibleWrap(aNode, aShell)
{
}
@ -221,99 +214,6 @@ NS_IMETHODIMP nsXULTabPanelsAccessible::GetAccName(nsAString& _retval)
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsXULTabPanelsAccessible::GetAccFirstChild(nsIAccessible **_retval)
{
nsAccessible::GetAccFirstChild(_retval);
if (*_retval == nsnull)
GetAccPluginChild(_retval);
return NS_OK;
}
NS_IMETHODIMP nsXULTabPanelsAccessible::GetAccLastChild(nsIAccessible **_retval)
{
nsAccessible::GetAccLastChild(_retval);
if (*_retval == nsnull)
GetAccPluginChild(_retval);
return NS_OK;
}
NS_IMETHODIMP nsXULTabPanelsAccessible::GetAccChildCount(PRInt32 *_retval)
{
nsAccessible::GetAccChildCount(_retval);
if (*_retval == 0) {
*_retval = 1;
}
return NS_OK;
}
nsresult nsXULTabPanelsAccessible::GetAccPluginChild(nsIAccessible **_retval)
{
// this big mess eventually gets the HWND for the full
// page plugin, and creates the shim class so we can
// get the IAccessible from the system in the widget/src code
*_retval = nsnull;
#ifndef XP_WIN
return NS_ERROR_NOT_IMPLEMENTED;
#else
if (!mAccService)
return NS_ERROR_NOT_AVAILABLE;
nsCOMPtr<nsIDOMDocument> domDoc;
mDOMNode->GetOwnerDocument(getter_AddRefs(domDoc));
nsCOMPtr<nsIDocument> doc(do_QueryInterface(domDoc));
if (!doc)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIScriptGlobalObject> globalObj;
doc->GetScriptGlobalObject(getter_AddRefs(globalObj));
if (!globalObj)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIDocShell> docShell;
globalObj->GetDocShell(getter_AddRefs(docShell));
nsCOMPtr<nsIWebShell> webShell(do_QueryInterface(docShell));
if (!webShell)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIWebShellContainer> container;
webShell->GetContainer(*getter_AddRefs(container));
nsCOMPtr<nsIWebShellWindow> wsWin(do_QueryInterface(container));
if (!wsWin)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIWebShell> contentShell;
wsWin->GetContentWebShell(getter_AddRefs(contentShell));
nsCOMPtr<nsIDocShell> contentDocShell(do_QueryInterface(contentShell));
if (!contentDocShell)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIContentViewer> contentViewer;
contentDocShell->GetContentViewer(getter_AddRefs(contentViewer));
nsCOMPtr<nsIPluginViewer> pluginViewer (do_QueryInterface(contentViewer));
if (!pluginViewer)
return NS_ERROR_FAILURE;
#endif
#ifdef XP_WIN
nsIPluginViewer *pViewer = pluginViewer.get();
PluginViewerImpl *viewer = NS_STATIC_CAST(PluginViewerImpl*, pViewer);
// Plugin code tends to be very platform specific, need to rev this
// when linux/mac plugins come into the picture HWND == windows
HWND pluginPort = nsnull;
viewer->GetPluginPort(&pluginPort);
if (!pluginPort)
return NS_ERROR_FAILURE;
mAccService->CreateHTMLNativeWindowAccessible(mDOMNode, mPresShell,
NS_REINTERPRET_CAST(void*, pluginPort),
_retval);
return NS_OK;
#endif
}
/**
* XUL Tabs - the s really stands for strip. this is a collection of tab objects
*/

View File

@ -42,8 +42,6 @@
// NOTE: alphabetically ordered
#include "nsBaseWidgetAccessible.h"
#include "nsFormControlAccessible.h"
#include "nsHTMLFormControlAccessible.h"
/** An individual tab */
class nsXULTabAccessible : public nsLeafAccessible
@ -69,7 +67,7 @@ public:
nsXULTabBoxAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell);
NS_IMETHOD GetAccRole(PRUint32 *_retval);
NS_IMETHOD GetAccState(PRUint32 *_retval);
NS_IMETHOD GetAccChildCount(PRInt32 *_retval);
//NS_IMETHOD GetAccChildCount(PRInt32 *_retval); // aaronl remove this?
};
/**
@ -80,9 +78,6 @@ class nsXULTabPanelsAccessible : public nsAccessibleWrap
{
public:
nsXULTabPanelsAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell);
NS_IMETHOD GetAccChildCount(PRInt32 *_retval);
NS_IMETHOD GetAccFirstChild(nsIAccessible **_retval);
NS_IMETHOD GetAccLastChild(nsIAccessible **_retval);
NS_IMETHOD GetAccRole(PRUint32 *_retval);
NS_IMETHOD GetAccName(nsAString& _retval);
NS_IMETHOD GetAccState(PRUint32 *_retval);
@ -93,7 +88,6 @@ protected:
// data members
nsCOMPtr<nsIDOMNode> mGParentDOMNode;
nsCOMPtr<nsIDOMNode> mParentDOMNode;
nsCOMPtr<nsIAccessibilityService> mAccService;
};
/** merely a container of tab obejcts */

View File

@ -40,7 +40,6 @@
// NOTE: alphabetically ordered
#include "nsIDOMXULDescriptionElement.h"
#include "nsWeakReference.h"
#include "nsXULTextAccessible.h"
/**

View File

@ -37,15 +37,10 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsCOMPtr.h"
#include "nsIAccessibilityService.h"
#include "nsXULTreeAccessible.h"
#include "nsIBoxObject.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMXULElement.h"
#include "nsITreeSelection.h"
#include "nsITreeView.h"
#include "nsXULAtoms.h"
#include "nsXULTreeAccessible.h"
// ---------- nsXULTreeAccessible ----------
@ -126,7 +121,7 @@ NS_IMETHODIMP nsXULTreeAccessible::GetAccFirstChild(nsIAccessible **aAccFirstChi
PRInt32 rowCount;
mTreeView->GetRowCount(&rowCount);
if (rowCount > 0) {
*aAccFirstChild = new nsXULTreeitemAccessible(this, mDOMNode, mPresShell, 0);
*aAccFirstChild = new nsXULTreeitemAccessible(this, mDOMNode, mWeakShell, 0);
if (! *aAccFirstChild)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aAccFirstChild);
@ -143,7 +138,7 @@ NS_IMETHODIMP nsXULTreeAccessible::GetAccLastChild(nsIAccessible **aAccLastChild
PRInt32 rowCount;
mTreeView->GetRowCount(&rowCount);
if (rowCount > 0) {
*aAccLastChild = new nsXULTreeitemAccessible(this, mDOMNode, mPresShell, rowCount - 1);
*aAccLastChild = new nsXULTreeitemAccessible(this, mDOMNode, mWeakShell, rowCount - 1);
if (! *aAccLastChild)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aAccLastChild);
@ -191,7 +186,7 @@ NS_IMETHODIMP nsXULTreeAccessible::GetSelectedChildren(nsISupportsArray **_retva
selection->IsSelected(rowIndex, &isSelected);
if (isSelected) {
nsCOMPtr<nsIAccessible> tempAccess;
tempAccess = new nsXULTreeitemAccessible(this, mDOMNode, mPresShell, rowIndex);
tempAccess = new nsXULTreeitemAccessible(this, mDOMNode, mWeakShell, rowIndex);
if (!tempAccess)
return NS_ERROR_OUT_OF_MEMORY;
selectedAccessibles->AppendElement(tempAccess);
@ -287,7 +282,7 @@ NS_IMETHODIMP nsXULTreeAccessible::RefSelection(PRInt32 aIndex, nsIAccessible **
if (isSelected) {
if (selCount == aIndex) {
nsCOMPtr<nsIAccessible> tempAccess;
tempAccess = new nsXULTreeitemAccessible(this, mDOMNode, mPresShell, rowIndex);
tempAccess = new nsXULTreeitemAccessible(this, mDOMNode, mWeakShell, rowIndex);
if (!tempAccess)
return NS_ERROR_OUT_OF_MEMORY;
*_retval = tempAccess;
@ -523,7 +518,7 @@ NS_IMETHODIMP nsXULTreeAccessible::CellRefAt(PRInt32 aRow, PRInt32 aColumn, nsIA
rv = mTree->GetColumnIndex(id.get(), &realColumn);
NS_ENSURE_SUCCESS(rv, rv);
*_retval = new nsXULTreeitemAccessible(this, mDOMNode, mPresShell, aRow, realColumn);
*_retval = new nsXULTreeitemAccessible(this, mDOMNode, mWeakShell, aRow, realColumn);
NS_ENSURE_TRUE(*_retval, NS_ERROR_OUT_OF_MEMORY);
NS_IF_ADDREF(*_retval);
@ -644,7 +639,8 @@ NS_IMETHODIMP nsXULTreeAccessible::IsCellSelected(PRInt32 aRow, PRInt32 aColumn,
nsXULTreeitemAccessible::nsXULTreeitemAccessible(nsIAccessible *aParent, nsIDOMNode *aDOMNode, nsIWeakReference *aShell, PRInt32 aRow, PRInt32 aColumn):
nsLeafAccessible(aDOMNode, aShell)
{
mParent = aParent;
Init(); // Add ourselves to cache using GetUniqueID() override
mParent = aParent; // xxx todo: do we need this? We already have mParent on nsAccessible
nsXULTreeAccessible::GetTreeBoxObject(aDOMNode, getter_AddRefs(mTree));
if (mTree)
@ -688,10 +684,10 @@ NS_IMETHODIMP nsXULTreeitemAccessible::GetAccValue(nsAString& _retval)
return NS_OK;
}
NS_IMETHODIMP nsXULTreeitemAccessible::GetAccId(PRInt32 *aAccId)
NS_IMETHODIMP nsXULTreeitemAccessible::GetUniqueID(void **aUniqueID)
{
// Since mDOMNode is same for all tree item, use |this| pointer as the unique Id
*aAccId = - NS_PTR_TO_INT32(this);
*aUniqueID = NS_STATIC_CAST(void*, this);
return NS_OK;
}
@ -803,7 +799,7 @@ NS_IMETHODIMP nsXULTreeitemAccessible::GetAccNextSibling(nsIAccessible **aAccNex
if (mColumnIndex < 0) {
if (mRow < rowCount - 1) {
*aAccNextSibling = new nsXULTreeitemAccessible(mParent, mDOMNode, mPresShell, mRow + 1);
*aAccNextSibling = new nsXULTreeitemAccessible(mParent, mDOMNode, mWeakShell, mRow + 1);
if (! *aAccNextSibling)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aAccNextSibling);
@ -827,7 +823,7 @@ NS_IMETHODIMP nsXULTreeitemAccessible::GetAccNextSibling(nsIAccessible **aAccNex
row++;
}
*aAccNextSibling = new nsXULTreeitemAccessible(mParent, mDOMNode, mPresShell, row, column);
*aAccNextSibling = new nsXULTreeitemAccessible(mParent, mDOMNode, mWeakShell, row, column);
NS_ENSURE_TRUE(*aAccNextSibling, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(*aAccNextSibling);
@ -844,7 +840,7 @@ NS_IMETHODIMP nsXULTreeitemAccessible::GetAccPreviousSibling(nsIAccessible **aAc
NS_ENSURE_TRUE(mTree && mTreeView, NS_ERROR_FAILURE);
if (mRow > 0 && mColumnIndex < 0) {
*aAccPreviousSibling = new nsXULTreeitemAccessible(mParent, mDOMNode, mPresShell, mRow - 1);
*aAccPreviousSibling = new nsXULTreeitemAccessible(mParent, mDOMNode, mWeakShell, mRow - 1);
if (! *aAccPreviousSibling)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aAccPreviousSibling);
@ -867,7 +863,7 @@ NS_IMETHODIMP nsXULTreeitemAccessible::GetAccPreviousSibling(nsIAccessible **aAc
row--;
}
*aAccPreviousSibling = new nsXULTreeitemAccessible(mParent, mDOMNode, mPresShell, row, column);
*aAccPreviousSibling = new nsXULTreeitemAccessible(mParent, mDOMNode, mWeakShell, row, column);
NS_ENSURE_TRUE(*aAccPreviousSibling, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(*aAccPreviousSibling);
@ -1035,7 +1031,7 @@ NS_IMETHODIMP nsXULTreeColumnsAccessible::GetAccNextSibling(nsIAccessible **aAcc
PRInt32 rowCount;
treeView->GetRowCount(&rowCount);
if (rowCount > 0) {
*aAccNextSibling = new nsXULTreeitemAccessible(mParent, mDOMNode, mPresShell, 0);
*aAccNextSibling = new nsXULTreeitemAccessible(mParent, mDOMNode, mWeakShell, 0);
if (! *aAccNextSibling)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aAccNextSibling);

View File

@ -39,15 +39,11 @@
#ifndef __nsXULTreeAccessible_h__
#define __nsXULTreeAccessible_h__
#include "nsAccessibleWrap.h"
#include "nsBaseWidgetAccessible.h"
#include "nsCOMPtr.h"
#include "nsIDOMNode.h"
#include "nsIWeakReference.h"
#include "nsITreeBoxObject.h"
#include "nsITreeView.h"
#include "nsXULSelectAccessible.h"
#include "nsIAccessibleTable.h"
#include "nsXULSelectAccessible.h"
/*
* A class the represents the XUL Tree widget.
@ -97,7 +93,6 @@ public:
/* ----- nsIAccessible ----- */
NS_IMETHOD GetAccName(nsAString& _retval);
NS_IMETHOD GetAccValue(nsAString& _retval);
NS_IMETHOD GetAccId(PRInt32 *_retval);
NS_IMETHOD GetAccRole(PRUint32 *_retval);
NS_IMETHOD GetAccState(PRUint32 *_retval);
NS_IMETHOD GetAccNumActions(PRUint8 *_retval);
@ -113,6 +108,9 @@ public:
NS_IMETHOD AccTakeSelection(void);
NS_IMETHOD AccTakeFocus(void);
/* ------ nsIAccessNode ----- */
NS_IMETHOD GetUniqueID(void **aUniqueID);
private:
nsCOMPtr<nsITreeBoxObject> mTree;
nsCOMPtr<nsITreeView> mTreeView;

View File

@ -157,6 +157,10 @@
#include "nsIFormControl.h"
#include "nsITimer.h"
#include "nsITimerInternal.h"
#ifdef ACCESSIBILITY
#include "nsIAccessibilityService.h"
#include "nsIAccessible.h"
#endif
// For style data reconstruction
#include "nsStyleChangeList.h"
@ -6293,12 +6297,19 @@ PresShell::HandleEventInternal(nsEvent* aEvent, nsIView *aView, PRUint32 aFlags,
#ifdef ACCESSIBILITY
if (aEvent->eventStructType == NS_ACCESSIBLE_EVENT)
{
void* clientData;
aView->GetClientData(clientData);
nsIFrame* frame = (nsIFrame *)clientData;
if (!frame)
return NS_ERROR_FAILURE;
return frame->HandleEvent(mPresContext, (nsGUIEvent*)aEvent, aStatus);
nsCOMPtr<nsIAccessibilityService> accService =
do_GetService("@mozilla.org/accessibilityService;1");
if (accService) {
nsIAccessible* acc;
nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(mDocument));
NS_ASSERTION(domNode, "No dom node for doc");
accService->GetAccessibleInShell(domNode, this, &acc);
// Addref this - it's not a COM Ptr
// We'll make sure the right number of Addref's occur before
// handing this back to the accessibility client
NS_STATIC_CAST(nsAccessibleEvent*, aEvent)->accessible = acc;
return NS_OK;
}
}
#endif

View File

@ -59,7 +59,6 @@
#include "nsIFrameManager.h"
#include "nsCSSRendering.h"
#ifdef ACCESSIBILITY
#include "nsIAccessibilityService.h"
#include "nsIAccessible.h"
#endif
@ -1017,24 +1016,6 @@ nsFrame::HandleEvent(nsIPresContext* aPresContext,
if (NS_SUCCEEDED(rv))
HandleRelease(aPresContext, aEvent, aEventStatus);
} break;
#ifdef ACCESSIBILITY
case NS_GETACCESSIBLE:
{
// get the accessible
// if(content) {
//nsCOMPtr<nsIDOMNode> node = do_QueryInterface(content);
nsresult rv = NS_OK;
nsCOMPtr<nsIAccessibilityService> accService =
do_GetService("@mozilla.org/accessibilityService;1", &rv);
if (accService) {
// get an accessible for the dom node
nsIAccessible* acc;
accService->CreateRootAccessible(aPresContext, &acc);
NS_STATIC_CAST(nsAccessibleEvent*, aEvent)->accessible = acc;
}
//}
} break;
#endif
default:
break;
}//end switch

View File

@ -438,8 +438,7 @@ NS_IMETHODIMP nsObjectFrame::GetAccessible(nsIAccessible** aAccessible)
nsCOMPtr<nsIAccessibilityService> accService = do_GetService("@mozilla.org/accessibilityService;1");
if (accService) {
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(mContent);
return accService->CreateOuterDocAccessible(node, aAccessible);
return accService->CreateHTMLObjectFrameAccessible(this, aAccessible);
}
return NS_ERROR_FAILURE;

View File

@ -59,7 +59,6 @@
#include "nsIFrameManager.h"
#include "nsCSSRendering.h"
#ifdef ACCESSIBILITY
#include "nsIAccessibilityService.h"
#include "nsIAccessible.h"
#endif
@ -1017,24 +1016,6 @@ nsFrame::HandleEvent(nsIPresContext* aPresContext,
if (NS_SUCCEEDED(rv))
HandleRelease(aPresContext, aEvent, aEventStatus);
} break;
#ifdef ACCESSIBILITY
case NS_GETACCESSIBLE:
{
// get the accessible
// if(content) {
//nsCOMPtr<nsIDOMNode> node = do_QueryInterface(content);
nsresult rv = NS_OK;
nsCOMPtr<nsIAccessibilityService> accService =
do_GetService("@mozilla.org/accessibilityService;1", &rv);
if (accService) {
// get an accessible for the dom node
nsIAccessible* acc;
accService->CreateRootAccessible(aPresContext, &acc);
NS_STATIC_CAST(nsAccessibleEvent*, aEvent)->accessible = acc;
}
//}
} break;
#endif
default:
break;
}//end switch

View File

@ -438,8 +438,7 @@ NS_IMETHODIMP nsObjectFrame::GetAccessible(nsIAccessible** aAccessible)
nsCOMPtr<nsIAccessibilityService> accService = do_GetService("@mozilla.org/accessibilityService;1");
if (accService) {
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(mContent);
return accService->CreateOuterDocAccessible(node, aAccessible);
return accService->CreateHTMLObjectFrameAccessible(this, aAccessible);
}
return NS_ERROR_FAILURE;

View File

@ -157,6 +157,10 @@
#include "nsIFormControl.h"
#include "nsITimer.h"
#include "nsITimerInternal.h"
#ifdef ACCESSIBILITY
#include "nsIAccessibilityService.h"
#include "nsIAccessible.h"
#endif
// For style data reconstruction
#include "nsStyleChangeList.h"
@ -6293,12 +6297,19 @@ PresShell::HandleEventInternal(nsEvent* aEvent, nsIView *aView, PRUint32 aFlags,
#ifdef ACCESSIBILITY
if (aEvent->eventStructType == NS_ACCESSIBLE_EVENT)
{
void* clientData;
aView->GetClientData(clientData);
nsIFrame* frame = (nsIFrame *)clientData;
if (!frame)
return NS_ERROR_FAILURE;
return frame->HandleEvent(mPresContext, (nsGUIEvent*)aEvent, aStatus);
nsCOMPtr<nsIAccessibilityService> accService =
do_GetService("@mozilla.org/accessibilityService;1");
if (accService) {
nsIAccessible* acc;
nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(mDocument));
NS_ASSERTION(domNode, "No dom node for doc");
accService->GetAccessibleInShell(domNode, this, &acc);
// Addref this - it's not a COM Ptr
// We'll make sure the right number of Addref's occur before
// handing this back to the accessibility client
NS_STATIC_CAST(nsAccessibleEvent*, aEvent)->accessible = acc;
return NS_OK;
}
}
#endif

View File

@ -42,7 +42,8 @@
#include "nsMaiObject.h"
#include "nsMaiUtil.h"
#include "nsMaiCache.h"
#include "nsIAccessibleEventListener.h"
#include "nsIAccessible.h"
#include "nsIAccessNode.h"
#include "nsString.h"
#ifdef MAI_LOGGING
@ -292,9 +293,10 @@ GetNSAccessibleUniqueID(nsIAccessible *aObj)
{
g_return_val_if_fail(aObj != NULL, 0);
PRInt32 accId = 0;
aObj->GetAccId(&accId);
return accId;
void* accId = 0;
nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(aObj));
accessNode->GetUniqueID(&accId);
return (guint)accId;
}
/* static functions for ATK callbacks */

View File

@ -72,7 +72,8 @@ static char * pAtkPropertyNameArray[PROP_LAST] = {
#endif
/* Implementation file */
NS_IMPL_ISUPPORTS1(MaiTopLevel, nsIAccessibleEventListener)
//NS_IMPL_ISUPPORTS1(MaiTopLevel, nsIAccessibleEventListener)
NS_IMPL_ISUPPORTS0(MaiTopLevel)
MaiTopLevel::MaiTopLevel(nsIAccessible *aAcc):MaiWidget(aAcc)
{
@ -81,27 +82,30 @@ MaiTopLevel::MaiTopLevel(nsIAccessible *aAcc):MaiWidget(aAcc)
#endif
MAI_LOG_DEBUG(("MaiTopLevel+++>%d, mycount=%d, acc=0x%x\n",
sMaiTopCount, mRefCnt.get(), aAcc));
#ifdef OLD
nsCOMPtr<nsIAccessibleEventReceiver>
receiver(do_QueryInterface(mAccessible));
if (receiver)
receiver->AddAccessibleEventListener(this);
#endif
}
MaiTopLevel::~MaiTopLevel()
{
#ifdef OLD
nsCOMPtr<nsIAccessibleEventReceiver>
receiver(do_QueryInterface(mAccessible));
#endif
#ifdef MAI_LOGGING
--sMaiTopCount;
#endif
MAI_LOG_DEBUG(("MaiTopLevel--->%d, mycount=%d, acc=0x%x\n",
sMaiTopCount, mRefCnt.get(), GetNSAccessible()));
#ifdef OLD
if (receiver)
receiver->RemoveAccessibleEventListener();
#endif
}
void
@ -176,6 +180,7 @@ MaiTopLevel::CreateAndCache(nsIAccessible *aAcc)
return retWidget;
}
#ifdef OLD
NS_IMETHODIMP
MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
void * aEventData)
@ -502,6 +507,7 @@ MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
g_object_unref(pMaiObject->GetAtkObject());
return rv;
}
#endif
/******************************************************************
* MaiWidget *

View File

@ -42,8 +42,8 @@
#ifndef __MAI_TOP_LEVEL_H__
#define __MAI_TOP_LEVEL_H__
#include "nsIAccessibleEventListener.h"
#include "nsMaiWidget.h"
#include "nsISupports.h"
/* MaiTopLevel is the MaiObject class for toplevel Window. The instance of
* MaiTopLevel will be child of MaiRoot instance. It is added into root when
@ -51,7 +51,7 @@
* window is destroyed.
*/
class MaiTopLevel: public MaiWidget, public nsIAccessibleEventListener
class MaiTopLevel: public MaiWidget, public nsISupports
{
public:
MaiTopLevel(nsIAccessible *aAcc);
@ -64,8 +64,6 @@ public:
static MaiTopLevel * Create(nsIAccessible *aAcc);
NS_DECL_ISUPPORTS
// nsIAccessibleEventListener
NS_DECL_NSIACCESSIBLEEVENTLISTENER
static MaiTopLevel *CreateAndCache(nsIAccessible *aAcc);

View File

@ -86,8 +86,6 @@
#include "winable.h"
#include "nsIAccessible.h"
#include "nsIAccessibleDocument.h"
#include "nsIAccessibleEventReceiver.h"
#include "nsIAccessibleEventListener.h"
#include "nsIAccessNode.h"
#ifndef WM_GETOBJECT
#define WM_GETOBJECT 0x03d
@ -1895,6 +1893,7 @@ NS_METHOD nsWindow::Show(PRBool bState)
}
}
mIsVisible = bState;
return NS_OK;
}
@ -4315,8 +4314,8 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT
result = DispatchFocus(NS_ACTIVATE, isMozWindowTakingFocus);
}
#ifdef ACCESSIBILITY
if (nsWindow::gIsAccessibilityOn && !mRootAccessible &&
mIsTopWidgetWindow)
if (nsWindow::gIsAccessibilityOn && !mRootAccessible &&
mIsTopWidgetWindow)
CreateRootAccessible();
#endif
break;
@ -7301,25 +7300,6 @@ void nsWindow::CreateRootAccessible()
if (!mRootAccessible) {
DispatchAccessibleEvent(NS_GETACCESSIBLE, &mRootAccessible);
if (!mRootAccessible)
return; // No root accessible created
nsCOMPtr<nsIAccessibleDocument> accessibleDoc(do_QueryInterface(mRootAccessible));
NS_ASSERTION(accessibleDoc, "No nsIAccessibleDocument for root accessible");
accessibleDoc->SetWindow(NS_REINTERPRET_CAST(void*, GetWindowHandle()));
nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(mRootAccessible));
NS_ASSERTION(accessNode, "No nsIAccessNode for root accessible");
accessNode->Init(accessibleDoc);
// XXX aaron this should be simplfied soon
nsCOMPtr<nsIAccessibleEventReceiver> eventReceiver =
do_QueryInterface(mRootAccessible);
nsCOMPtr<nsIAccessibleEventListener> eventListener =
do_QueryInterface(mRootAccessible);
if (eventReceiver && eventListener) {
eventReceiver->AddAccessibleEventListener(eventListener);
}
}
}