Bug 288503. Framesets not working with screen readers. r=biesi, sr=dougt

This commit is contained in:
aaronleventhal%moonset.net 2005-04-04 17:26:57 +00:00
Родитель 82cd73aa7b
Коммит 27e54013f7
14 изменённых файлов: 126 добавлений и 122 удалений

Просмотреть файл

@ -43,8 +43,11 @@
#include "nsIAccessibilityService.h"
#include "nsIAccessibleDocument.h"
#include "nsPIAccessibleDocument.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeItem.h"
#include "nsIDocument.h"
#include "nsIDOMCSSStyleDeclaration.h"
#include "nsIDOMDocument.h"
#include "nsIDOMElement.h"
#include "nsIDOMNSHTMLElement.h"
#include "nsIDOMViewCSS.h"
@ -242,12 +245,9 @@ nsPresContext* nsAccessNode::GetPresContext()
already_AddRefed<nsIAccessibleDocument> nsAccessNode::GetDocAccessible()
{
nsIAccessibleDocument *docAccessible;
GetDocAccessibleFor(mWeakShell, &docAccessible); // Addref'd
return docAccessible;
return GetDocAccessibleFor(mWeakShell); // Addref'd
}
nsIFrame* nsAccessNode::GetFrame()
{
nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mWeakShell));
@ -294,7 +294,7 @@ nsAccessNode::GetNumChildren(PRInt32 *aNumChildren)
NS_IMETHODIMP
nsAccessNode::GetAccessibleDocument(nsIAccessibleDocument **aDocAccessible)
{
GetDocAccessibleFor(mWeakShell, aDocAccessible);
*aDocAccessible = GetDocAccessibleFor(mWeakShell).get();
return NS_OK;
}
@ -437,18 +437,76 @@ nsAccessNode::GetComputedStyleValue(const nsAString& aPseudoElt, const nsAString
/***************** Hashtable of nsIAccessNode's *****************/
void nsAccessNode::GetDocAccessibleFor(nsIWeakReference *aPresShell,
nsIAccessibleDocument **aDocAccessible)
already_AddRefed<nsIAccessibleDocument>
nsAccessNode::GetDocAccessibleFor(nsIWeakReference *aPresShell)
{
*aDocAccessible = nsnull;
nsIAccessibleDocument *docAccessible = nsnull;
nsCOMPtr<nsIAccessNode> accessNode;
gGlobalDocAccessibleCache.Get(NS_STATIC_CAST(void*, aPresShell), getter_AddRefs(accessNode));
if (accessNode) {
CallQueryInterface(accessNode, aDocAccessible);
CallQueryInterface(accessNode, &docAccessible);
}
return docAccessible;
}
already_AddRefed<nsIAccessibleDocument>
nsAccessNode::GetDocAccessibleFor(nsISupports *aContainer)
{
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aContainer));
NS_ASSERTION(docShell, "This method currently only supports docshells");
nsCOMPtr<nsIPresShell> presShell;
docShell->GetPresShell(getter_AddRefs(presShell));
nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(presShell));
return weakShell ? GetDocAccessibleFor(weakShell) : nsnull;
}
already_AddRefed<nsIAccessibleDocument>
nsAccessNode::GetDocAccessibleFor(nsIDOMNode *aNode)
{
nsCOMPtr<nsIPresShell> eventShell = GetPresShellFor(aNode);
nsCOMPtr<nsIWeakReference> weakEventShell(do_GetWeakReference(eventShell));
return weakEventShell? GetDocAccessibleFor(weakEventShell) : nsnull;
}
already_AddRefed<nsIPresShell>
nsAccessNode::GetPresShellFor(nsIDOMNode *aNode)
{
nsCOMPtr<nsIDOMDocument> domDocument;
aNode->GetOwnerDocument(getter_AddRefs(domDocument));
nsCOMPtr<nsIDocument> doc(do_QueryInterface(domDocument));
if (!doc) { // This is necessary when the node is the document node
doc = do_QueryInterface(aNode);
}
nsIPresShell *presShell = nsnull;
if (doc) {
presShell = doc->GetShellAt(0);
NS_IF_ADDREF(presShell);
}
return presShell;
}
already_AddRefed<nsIDocShellTreeItem>
nsAccessNode::GetSameTypeRootFor(nsIDOMNode *aStartNode)
{
nsCOMPtr<nsIDOMDocument> domDoc;
aStartNode->GetOwnerDocument(getter_AddRefs(domDoc));
nsCOMPtr<nsIDocument> doc(do_QueryInterface(domDoc));
if (!doc) {
doc = do_QueryInterface(aStartNode);
}
NS_ASSERTION(doc, "No document for node passed in");
nsCOMPtr<nsISupports> container = doc->GetContainer();
nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem(do_QueryInterface(container));
NS_ENSURE_TRUE(docShellTreeItem, nsnull);
nsIDocShellTreeItem *topOfDocShellTree = nsnull;
docShellTreeItem->GetSameTypeRootTreeItem(&topOfDocShellTree);
NS_ASSERTION(topOfDocShellTree, "No same type root tree item for doc shell");
return topOfDocShellTree;
}
void nsAccessNode::PutCacheEntry(nsInterfaceHashtable<nsVoidHashKey, nsIAccessNode> &aCache,
void* aUniqueID,
nsIAccessNode *aAccessNode)

Просмотреть файл

@ -46,10 +46,10 @@
#include "nsCOMPtr.h"
#include "nsIAccessNode.h"
#include "nsPIAccessNode.h"
#include "nsIDocShellTreeItem.h"
#include "nsIDOMNode.h"
#include "nsIStringBundle.h"
#include "nsWeakReference.h"
#include "nsInterfaceHashtable.h"
class nsIPresShell;
@ -115,9 +115,13 @@ class nsAccessNode: public nsIAccessNode, public nsPIAccessNode
static PLDHashOperator PR_CALLBACK ClearCacheEntry(const void* aKey, nsCOMPtr<nsIAccessNode>& aAccessNode, void* aUserArg);
// Static cache methods for global document cache
static void GetDocAccessibleFor(nsIWeakReference *aPresShell,
nsIAccessibleDocument **aDocAccessible);
static already_AddRefed<nsIAccessibleDocument> GetDocAccessibleFor(nsIWeakReference *aPresShell);
static already_AddRefed<nsIAccessibleDocument> GetDocAccessibleFor(nsISupports *aContainer);
static already_AddRefed<nsIAccessibleDocument> GetDocAccessibleFor(nsIDOMNode *aNode);
static already_AddRefed<nsIDocShellTreeItem> GetSameTypeRootFor(nsIDOMNode *aStartNode);
static already_AddRefed<nsIPresShell> GetPresShellFor(nsIDOMNode *aStartNode);
static nsIDOMNode *gLastFocusedNode;
protected:

Просмотреть файл

@ -1569,8 +1569,8 @@ NS_IMETHODIMP nsAccessibilityService::GetCachedAccessNode(nsIDOMNode *aNode,
nsIWeakReference *aWeakShell,
nsIAccessNode **aAccessNode)
{
nsCOMPtr<nsIAccessibleDocument> accessibleDoc;
nsAccessNode::GetDocAccessibleFor(aWeakShell, getter_AddRefs(accessibleDoc));
nsCOMPtr<nsIAccessibleDocument> accessibleDoc =
nsAccessNode::GetDocAccessibleFor(aWeakShell);
if (!accessibleDoc) {
*aAccessNode = nsnull;
@ -1715,8 +1715,8 @@ NS_IMETHODIMP nsAccessibilityService::GetAccessible(nsIDOMNode *aNode,
return NS_ERROR_FAILURE; // No content, and not doc node
}
// This happens when we're on the document node, which will not QI to an nsIContent,
nsCOMPtr<nsIAccessibleDocument> accessibleDoc;
nsAccessNode::GetDocAccessibleFor(aWeakShell, getter_AddRefs(accessibleDoc));
nsCOMPtr<nsIAccessibleDocument> accessibleDoc =
nsAccessNode::GetDocAccessibleFor(aWeakShell);
if (accessibleDoc) {
newAcc = do_QueryInterface(accessibleDoc);
NS_ASSERTION(newAcc, "nsIAccessibleDocument is not an nsIAccessible");

Просмотреть файл

@ -63,6 +63,7 @@ NS_IMPL_ISUPPORTS_INHERITED2(nsCaretAccessible, nsLeafAccessible, nsIAccessibleC
nsCaretAccessible::nsCaretAccessible(nsIDOMNode* aDocumentNode, nsIWeakReference* aShell, nsRootAccessible *aRootAccessible):
nsLeafAccessible(aDocumentNode, aShell), mVisible(PR_TRUE), mCurrentDOMNode(nsnull), mRootAccessible(aRootAccessible)
{
Init();
}
NS_IMETHODIMP nsCaretAccessible::Shutdown()
@ -90,8 +91,8 @@ 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<nsIPresShell> presShell;
nsRootAccessible::GetEventShell(aCurrentNode, getter_AddRefs(presShell));
nsCOMPtr<nsIPresShell> presShell =
nsRootAccessible::GetPresShellFor(aCurrentNode);
if (!presShell)
return NS_ERROR_FAILURE;
@ -134,8 +135,7 @@ NS_IMETHODIMP nsCaretAccessible::NotifySelectionChanged(nsIDOMDocument *aDoc, ns
return NS_OK;
#endif
nsCOMPtr<nsIPresShell> presShell;
nsRootAccessible::GetEventShell(mCurrentDOMNode, getter_AddRefs(presShell));
nsCOMPtr<nsIPresShell> presShell = GetPresShellFor(mCurrentDOMNode);
nsCOMPtr<nsISelection> domSel(do_QueryReferent(mDomSelectionWeak));
if (!presShell || domSel != aSel)
return NS_OK; // Only listening to selection changes in currently focused frame

Просмотреть файл

@ -79,6 +79,7 @@ public:
NS_DECL_NSISELECTIONLISTENER
/* ----- nsIAccessNode ----- */
NS_IMETHOD Init() { mIsInitialized = PR_TRUE; return NS_OK; }
NS_IMETHOD Shutdown();
private:

Просмотреть файл

@ -630,18 +630,6 @@ void nsDocAccessible::FireDocLoadFinished()
}
}
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);
@ -730,24 +718,32 @@ NS_IMETHODIMP nsDocAccessible::OnStateChange(nsIWebProgress *aWebProgress,
if (!mWeakShell || !mDocument) {
return NS_OK;
}
nsCOMPtr<nsIDOMWindow> domWin;
aWebProgress->GetDOMWindow(getter_AddRefs(domWin));
nsCOMPtr<nsIDOMDocument> domDoc;
domWin->GetDocument(getter_AddRefs(domDoc));
if (!SameCOMIdentity(mDocument, domDoc)) {
return NS_OK;
}
if (aStateFlags & STATE_STOP) {
if (!mDocLoadTimer) {
mDocLoadTimer = do_CreateInstance("@mozilla.org/timer;1");
}
if (mDocLoadTimer) {
mDocLoadTimer->InitWithFuncCallback(DocLoadCallback, this, 4,
nsITimer::TYPE_ONE_SHOT);
}
FireDocLoadFinished();
return NS_OK;
}
// STATE_START
if (!mIsNewDocument) {
return NS_OK; // Already fired for this document
}
if (gLastFocusedNode) {
nsCOMPtr<nsIDOMDocument> focusedDOMDoc;
gLastFocusedNode->GetOwnerDocument(getter_AddRefs(focusedDOMDoc));
if (!SameCOMIdentity(focusedDOMDoc, mDocument)) {
// Load is not occuring in the currently focused pane, so don't fire
nsCOMPtr<nsIDocShellTreeItem> topOfLoadingContentTree =
GetSameTypeRootFor(mDOMNode);
nsCOMPtr<nsIDocShellTreeItem> topOfFocusedContentTree =
GetSameTypeRootFor(gLastFocusedNode);
if (topOfLoadingContentTree != topOfFocusedContentTree) {
// Load is not occuring in the currently focused tab, so don't fire
// doc load event there, otherwise assistive technology may become confused
return NS_OK;
}
@ -761,7 +757,7 @@ NS_IMETHODIMP nsDocAccessible::OnStateChange(nsIWebProgress *aWebProgress,
if (mBusy != eBusyStateLoading) {
mBusy = eBusyStateLoading;
// Fire a "new doc has started to load" event
// Fire a "new doc has started to load" event if at top of content tree
#ifndef MOZ_ACCESSIBILITY_ATK
FireToolkitEvent(nsIAccessibleEvent::EVENT_STATE_CHANGE, this, nsnull);
#else
@ -819,37 +815,6 @@ NS_IMETHODIMP nsDocAccessible::Observe(nsISupports *aSubject, const char *aTopic
return NS_OK;
}
void nsDocAccessible::GetEventShell(nsIDOMNode *aNode, nsIPresShell **aEventShell)
{
// 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.
*aEventShell = nsnull;
nsCOMPtr<nsIDOMDocument> domDocument;
aNode->GetOwnerDocument(getter_AddRefs(domDocument));
nsCOMPtr<nsIDocument> doc(do_QueryInterface(domDocument));
if (doc) {
*aEventShell = doc->GetShellAt(0);
NS_IF_ADDREF(*aEventShell);
}
}
void nsDocAccessible::GetEventDocAccessible(nsIDOMNode *aNode,
nsIAccessibleDocument **aAccessibleDoc)
{
*aAccessibleDoc = nsnull;
nsCOMPtr<nsIPresShell> eventShell;
GetEventShell(aNode, getter_AddRefs(eventShell));
nsCOMPtr<nsIWeakReference> weakEventShell(do_GetWeakReference(eventShell));
if (!weakEventShell) {
return;
}
GetDocAccessibleFor(weakEventShell, aAccessibleDoc);
}
// ---------- Mutation event listeners ------------
NS_IMETHODIMP nsDocAccessible::NodeInserted(nsIDOMEvent* aEvent)
{
@ -1144,8 +1109,7 @@ void nsDocAccessible::HandleMutationEvent(nsIDOMEvent *aEvent, PRUint32 aAccessi
subTreeToInvalidate = targetNode; // targetNode is parent for DOMNodeRemoved event
}
nsCOMPtr<nsIAccessibleDocument> docAccessible;
GetEventDocAccessible(subTreeToInvalidate, getter_AddRefs(docAccessible));
nsCOMPtr<nsIAccessibleDocument> docAccessible = GetDocAccessibleFor(subTreeToInvalidate);
if (!docAccessible)
return;

Просмотреть файл

@ -118,11 +118,7 @@ class nsDocAccessible : public nsBlockAccessible,
void RemoveScrollListener();
virtual void FireDocLoadFinished();
void HandleMutationEvent(nsIDOMEvent *aEvent, PRUint32 aEventType);
static void DocLoadCallback(nsITimer *aTimer, void *aClosure);
static void ScrollTimerCallback(nsITimer *aTimer, void *aClosure);
void GetEventShell(nsIDOMNode *aNode, nsIPresShell **aEventShell);
void GetEventDocAccessible(nsIDOMNode *aNode,
nsIAccessibleDocument **aAccessibleDoc);
virtual void CheckForEditor();
nsInterfaceHashtable<nsVoidHashKey, nsIAccessNode> mAccessNodeCache;

Просмотреть файл

@ -502,8 +502,7 @@ void nsRootAccessible::FireCurrentFocusEvent()
return; // Could not get a focused document either
}
}
nsCOMPtr<nsIPresShell> eventShell;
GetEventShell(focusedNode, getter_AddRefs(eventShell));
nsCOMPtr<nsIPresShell> eventShell = GetPresShellFor(focusedNode);
NS_ASSERTION(eventShell, "No presshell for focused node");
nsCOMPtr<nsIAccessible> accessible;
@ -514,26 +513,6 @@ void nsRootAccessible::FireCurrentFocusEvent()
}
}
void nsRootAccessible::GetEventShell(nsIDOMNode *aNode, nsIPresShell **aEventShell)
{
// 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;
aNode->GetOwnerDocument(getter_AddRefs(domDocument));
nsCOMPtr<nsIDocument> doc(do_QueryInterface(domDocument));
if (!doc) { // This is necessary when the node is the document node
doc = do_QueryInterface(aNode);
}
if (doc) {
*aEventShell = doc->GetShellAt(0);
NS_IF_ADDREF(*aEventShell);
}
}
// --------------- nsIDOMEventListener Methods (3) ------------------------
NS_IMETHODIMP nsRootAccessible::HandleEvent(nsIDOMEvent* aEvent)
@ -560,8 +539,7 @@ NS_IMETHODIMP nsRootAccessible::HandleEvent(nsIDOMEvent* aEvent)
}
#endif
nsCOMPtr<nsIPresShell> eventShell;
GetEventShell(targetNode, getter_AddRefs(eventShell));
nsCOMPtr<nsIPresShell> eventShell = GetPresShellFor(targetNode);
#ifdef MOZ_ACCESSIBILITY_ATK
nsCOMPtr<nsIDOMHTMLAnchorElement> anchorElement(do_QueryInterface(targetNode));
@ -581,8 +559,8 @@ NS_IMETHODIMP nsRootAccessible::HandleEvent(nsIDOMEvent* aEvent)
// Only get cached accessible for unload -- so that we don't create it
// just to destroy it.
nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(eventShell));
nsCOMPtr<nsIAccessibleDocument> accessibleDoc;
nsAccessNode::GetDocAccessibleFor(weakShell, getter_AddRefs(accessibleDoc));
nsCOMPtr<nsIAccessibleDocument> accessibleDoc =
nsAccessNode::GetDocAccessibleFor(weakShell);
nsCOMPtr<nsPIAccessibleDocument> privateAccDoc = do_QueryInterface(accessibleDoc);
if (privateAccDoc) {
privateAccDoc->Destroy();

Просмотреть файл

@ -100,8 +100,6 @@ class nsRootAccessible : public nsDocAccessibleWrap,
void ShutdownAll();
static void GetEventShell(nsIDOMNode *aNode, nsIPresShell **aEventShell);
protected:
nsresult AddEventListeners();
nsresult RemoveEventListeners();

Просмотреть файл

@ -48,6 +48,7 @@ LIBRARY_NAME = accessibility_html_s
LIBXUL_LIBRARY = 1
REQUIRES = content \
docshell \
dom \
gfx \
imglib2 \

Просмотреть файл

@ -46,6 +46,7 @@ LIBRARY_NAME = accessibility_toolkit_s
LIBXUL_LIBRARY = 1
REQUIRES = content \
docshell \
dom \
editor \
gfx \

Просмотреть файл

@ -40,6 +40,8 @@
#include "ISimpleDOMDocument_i.c"
#include "nsIAccessibilityService.h"
#include "nsIAccessibleEvent.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeNode.h"
#include "nsIDOMDocumentTraversal.h"
#include "nsIDOMNodeFilter.h"
#include "nsIDOMTreeWalker.h"
@ -141,9 +143,8 @@ STDMETHODIMP nsDocAccessibleWrap::get_accChild(
nsIPresShell *parentShell = parentDoc->GetShellAt(0);
nsCOMPtr<nsIWeakReference> weakParentShell(do_GetWeakReference(parentShell));
if (weakParentShell) {
nsCOMPtr<nsIAccessibleDocument> parentDocAccessible;
nsAccessNode::GetDocAccessibleFor(weakParentShell,
getter_AddRefs(parentDocAccessible));
nsCOMPtr<nsIAccessibleDocument> parentDocAccessible =
nsAccessNode::GetDocAccessibleFor(weakParentShell);
nsCOMPtr<nsIAccessible> accessible(do_QueryInterface(parentDocAccessible));
IAccessible *msaaParentDoc;
if (accessible) {
@ -335,17 +336,17 @@ void nsDocAccessibleWrap::FireDocLoadFinished()
return; // Don't consider load finished until window unhidden
}
if (mIsNewDocument) {
mIsNewDocument = PR_FALSE;
// Cache decision before nsDocAccessible::FireDocLoadFinished
// changes mIsNewDocument and mBusy
PRBool fireStateChange = mIsNewDocument && mBusy != eBusyStateDone;
if (mBusy != eBusyStateDone) {
mBusy = eBusyStateDone; // before event callback so STATE_BUSY is not reported
FireToolkitEvent(nsIAccessibleEvent::EVENT_STATE_CHANGE, this, nsnull);
FireAnchorJumpEvent();
}
nsDocAccessible::FireDocLoadFinished();
if (fireStateChange) {
FireToolkitEvent(nsIAccessibleEvent::EVENT_STATE_CHANGE,
this, nsnull);
}
mBusy = eBusyStateDone;
FireAnchorJumpEvent();
}
NS_IMETHODIMP nsDocAccessibleWrap::OnLocationChange(nsIWebProgress *aWebProgress,

Просмотреть файл

@ -45,6 +45,7 @@
#include "ISimpleDOMDocument.h"
#include "nsDocAccessible.h"
#include "nsIDocShellTreeItem.h"
class nsDocAccessibleWrap: public nsDocAccessible,
public ISimpleDOMDocument

Просмотреть файл

@ -48,6 +48,7 @@ LIBRARY_NAME = accessibility_xul_s
LIBXUL_LIBRARY = 1
REQUIRES = content \
docshell \
dom \
gfx \
intl \