From c254a77eed328391b0e7f77ba1ad0be56c267f7f Mon Sep 17 00:00:00 2001 From: "aaronl%netscape.com" <aaronl%netscape.com> Date: Wed, 30 Oct 2002 07:46:34 +0000 Subject: [PATCH] Bug 175842. Sending MSAA STATE_CHANGE event on old window, should be on new one. r=kyle, sr=jst, a=roc+moz --- .../src/base/nsAccessibilityService.cpp | 1 + accessible/src/base/nsRootAccessible.cpp | 307 +++++++++--------- accessible/src/base/nsRootAccessible.h | 17 +- .../src/html/nsHTMLIFrameRootAccessible.cpp | 40 ++- .../src/html/nsHTMLIFrameRootAccessible.h | 10 + 5 files changed, 208 insertions(+), 167 deletions(-) diff --git a/accessible/src/base/nsAccessibilityService.cpp b/accessible/src/base/nsAccessibilityService.cpp index 811c2c212949..4f80175f98be 100644 --- a/accessible/src/base/nsAccessibilityService.cpp +++ b/accessible/src/base/nsAccessibilityService.cpp @@ -348,6 +348,7 @@ nsAccessibilityService::CreateRootAccessible(nsISupports* aPresContext, nsISuppo 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)); diff --git a/accessible/src/base/nsRootAccessible.cpp b/accessible/src/base/nsRootAccessible.cpp index 2efd05dc148c..a1520f96cecc 100644 --- a/accessible/src/base/nsRootAccessible.cpp +++ b/accessible/src/base/nsRootAccessible.cpp @@ -92,7 +92,6 @@ NS_INTERFACE_MAP_BEGIN(nsRootAccessible) NS_INTERFACE_MAP_ENTRY(nsIDOMFocusListener) NS_INTERFACE_MAP_ENTRY(nsIDOMFormListener) NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) - NS_INTERFACE_MAP_ENTRY(nsITimerCallback) NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener) NS_INTERFACE_MAP_ENTRY(nsIScrollPositionListener) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMFormListener) @@ -115,8 +114,10 @@ PRUint32 nsRootAccessible::gInstanceCount = 0; //----------------------------------------------------- nsRootAccessible::nsRootAccessible(nsIWeakReference* aShell):nsAccessible(nsnull,aShell), nsDocAccessibleMixin(aShell), mListener(nsnull), + mScrollWatchTimer(nsnull), mDocLoadTimer(nsnull), mWebProgress(nsnull), mAccService(do_GetService("@mozilla.org/accessibilityService;1")), - mBusy(eBusyStateUninitialized), mScrollPositionChangedTicks(0), mScrollablePresShells(nsnull) + mBusy(eBusyStateUninitialized), mIsNewDocument(PR_FALSE), + mScrollPositionChangedTicks(0) { nsCOMPtr<nsIPresShell> shell(do_QueryReferent(mPresShell)); if (shell) { @@ -141,8 +142,6 @@ nsRootAccessible::~nsRootAccessible() #endif RemoveAccessibleEventListener(); - if (mScrollablePresShells) - delete mScrollablePresShells; } /* attribute wstring accName; */ @@ -241,38 +240,36 @@ NS_IMETHODIMP nsRootAccessible::GetAccValue(nsAString& aAccValue) return GetURL(aAccValue); } - -NS_IMETHODIMP nsRootAccessible::Notify(nsITimer *timer) +void nsRootAccessible::DocLoadCallback(nsITimer *aTimer, void *aClosure) { - if (mScrollPositionChangedTicks) { - if (++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 - nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mLastScrolledPresShell)); - if (mListener && presShell) { - nsCOMPtr<nsIAccessible> docAccessible; - if (mPresShell == mLastScrolledPresShell) - docAccessible = this; // Fast way, don't need to create new accessible to fire event on the root - else { - // Need to create accessible for document that had scrolling occur in it - nsCOMPtr<nsIDocument> doc; - presShell->GetDocument(getter_AddRefs(doc)); - nsCOMPtr<nsIDOMNode> docNode(do_QueryInterface(doc)); - mAccService->GetAccessibleFor(docNode, getter_AddRefs(docAccessible)); - } + // 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. - if (docAccessible) - mListener->HandleEvent(nsIAccessibleEventListener::EVENT_SCROLLINGEND, docAccessible, nsnull); - } - mScrollPositionChangedTicks = 0; - mLastScrolledPresShell = nsnull; - } - } - return NS_OK; + 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 + if (rootAcc->mListener) + rootAcc->mListener->HandleEvent(nsIAccessibleEventListener::EVENT_SCROLLINGEND, rootAcc, nsnull); + rootAcc->mScrollPositionChangedTicks = 0; + rootAcc->mScrollWatchTimer->Cancel(); + rootAcc->mScrollWatchTimer = nsnull; + } +} + void nsRootAccessible::AddScrollListener(nsIPresShell *aPresShell) { nsCOMPtr<nsIViewManager> vm; @@ -284,26 +281,8 @@ void nsRootAccessible::AddScrollListener(nsIPresShell *aPresShell) if (vm) vm->GetRootScrollableView(&scrollableView); - if (!scrollableView) - return; - - if (!mScrollablePresShells) - mScrollablePresShells = new nsSupportsHashtable(SCROLL_HASH_START_SIZE, PR_TRUE); // PR_TRUE = thread safe hash table - - if (mScrollablePresShells) { - nsISupportsKey key(scrollableView); - nsCOMPtr<nsISupports> supports(dont_AddRef(NS_STATIC_CAST(nsISupports*, mScrollablePresShells->Get(&key)))); - if (supports) // This scroll view is already being listened to, remove it. We will re-add it w/ current pres shell - RemoveScrollListener(aPresShell); - - // Add to hash table, so we can retrieve correct pres shell later - nsCOMPtr<nsIWeakReference> weakShell; - weakShell = do_GetWeakReference(aPresShell); - mScrollablePresShells->Put(&key, weakShell); - - // Add listener + if (scrollableView) scrollableView->AddScrollPositionListener(NS_STATIC_CAST(nsIScrollPositionListener *, this)); - } } void nsRootAccessible::RemoveScrollListener(nsIPresShell *aPresShell) @@ -319,34 +298,6 @@ void nsRootAccessible::RemoveScrollListener(nsIPresShell *aPresShell) if (scrollableView) scrollableView->RemoveScrollPositionListener(NS_STATIC_CAST(nsIScrollPositionListener *, this)); - - if (mScrollablePresShells) { - nsISupportsKey key(scrollableView); - nsCOMPtr<nsISupports> supp; - mScrollablePresShells->Remove(&key, getter_AddRefs(supp)); - } -} - -PRBool PR_CALLBACK -RemoveScrollListenerEnum(nsHashKey *aKey, void *aData, void* aClosure) -{ - nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(NS_STATIC_CAST(nsIWeakReference*, aData))); - - // If presShell gone, then our nsIScrollPositionListener will also already be gone - if (presShell) { - nsCOMPtr<nsIViewManager> vm; - if (presShell) - presShell->GetViewManager(getter_AddRefs(vm)); - - nsIScrollableView* scrollableView = nsnull; - if (vm) - vm->GetRootScrollableView(&scrollableView); - - if (scrollableView) - scrollableView->RemoveScrollPositionListener(NS_STATIC_CAST(nsIScrollPositionListener *, aClosure)); - } - - return PR_TRUE; } NS_IMETHODIMP nsRootAccessible::ScrollPositionWillChange(nsIScrollableView *aView, nscoord aX, nscoord aY) @@ -357,29 +308,21 @@ NS_IMETHODIMP nsRootAccessible::ScrollPositionWillChange(nsIScrollableView *aVie NS_IMETHODIMP nsRootAccessible::ScrollPositionDidChange(nsIScrollableView *aScrollableView, nscoord aX, nscoord aY) { if (mListener) { - if (!mScrollablePresShells) - return NS_OK; - nsISupportsKey key(aScrollableView); - nsCOMPtr<nsIWeakReference> weakShell(dont_AddRef(NS_STATIC_CAST(nsIWeakReference*, mScrollablePresShells->Get(&key)))); - if (!weakShell) - return NS_OK; - if (mTimer && (mBusy != eBusyStateDone || (mScrollPositionChangedTicks && mLastScrolledPresShell != weakShell))) { - // We need to say finish up our current time work and start a new timer - // either because we haven't yet fired our finished loading event, or - // a scroll event from another pres shell is still waiting to be fired - Notify(mTimer); - mTimer->Cancel(); - } // 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 - nsresult rv; - mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv); - if (NS_SUCCEEDED(rv)) { - const PRUint32 kScrollPosCheckWait = 50; - mTimer->InitWithCallback(NS_STATIC_CAST(nsITimerCallback*, this), kScrollPosCheckWait, nsITimer::TYPE_REPEATING_SLACK); + 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; - mLastScrolledPresShell = weakShell; } return NS_OK; } @@ -430,24 +373,7 @@ NS_IMETHODIMP nsRootAccessible::AddAccessibleEventListener(nsIAccessibleEventLis rv = target->AddEventListener(NS_LITERAL_STRING("DOMMenuBarInactive"), NS_STATIC_CAST(nsIDOMXULListener*, this), PR_TRUE); NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register listener"); - // 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 - nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mPresShell)); - if (presShell) { - nsCOMPtr<nsIPresContext> context; - presShell->GetPresContext(getter_AddRefs(context)); - if (context) { - nsCOMPtr<nsISupports> container; context->GetContainer(getter_AddRefs(container)); - nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container)); - if (docShell) { - mWebProgress = do_GetInterface(docShell); - mWebProgress->AddProgressListener(this, nsIWebProgress::NOTIFY_LOCATION | - nsIWebProgress::NOTIFY_STATE_DOCUMENT); - } - } - } - NS_ASSERTION(mWebProgress, "Could not get nsIWebProgress for nsRootAccessible"); + AddContentDocListeners(); } if (!mCaretAccessible && mListener) @@ -474,18 +400,17 @@ NS_IMETHODIMP nsRootAccessible::RemoveAccessibleEventListener() target->RemoveEventListener(NS_LITERAL_STRING("ListitemStateChange"), NS_STATIC_CAST(nsIDOMXULListener*, this), PR_TRUE); } - if (mTimer) { - mTimer->Cancel(); - mTimer = nsnull; + if (mScrollWatchTimer) { + mScrollWatchTimer->Cancel(); + mScrollWatchTimer = nsnull; } - if (mWebProgress) { - mWebProgress->RemoveProgressListener(this); - mWebProgress = nsnull; + if (mDocLoadTimer) { + mDocLoadTimer->Cancel(); + mDocLoadTimer = nsnull; } - if (mScrollablePresShells) - mScrollablePresShells->Enumerate(RemoveScrollListenerEnum, NS_STATIC_CAST(nsIScrollPositionListener*, this)); + RemoveContentDocListeners(); mListener = nsnull; } @@ -809,11 +734,94 @@ NS_IMETHODIMP nsRootAccessible::GetDocument(nsIDocument **doc) return nsDocAccessibleMixin::GetDocument(doc); } -NS_IMETHODIMP nsRootAccessible::OnStateChange(nsIWebProgress *aWebProgress, - nsIRequest *aRequest, PRUint32 aStateFlags, nsresult aStatus) +void nsRootAccessible::RemoveContentDocListeners() { - if ((aStateFlags & STATE_IS_DOCUMENT) && (aStateFlags & STATE_STOP)) { - // Doc is ready! + // 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 @@ -821,21 +829,14 @@ NS_IMETHODIMP nsRootAccessible::OnStateChange(nsIWebProgress *aWebProgress, mListener->HandleEvent(nsIAccessibleEventListener::EVENT_STATE_CHANGE, this, nsnull); #endif } - - // Set up scroll position listener - nsCOMPtr<nsIDOMWindow> domWin; - aWebProgress->GetDOMWindow(getter_AddRefs(domWin)); - if (domWin) { - nsCOMPtr<nsIDOMDocument> domDoc; - domWin->GetDocument(getter_AddRefs(domDoc)); - nsCOMPtr<nsIDocument> doc(do_QueryInterface(domDoc)); - if (doc) { - nsCOMPtr<nsIPresShell> presShell; - doc->GetShellAt(0, getter_AddRefs(presShell)); - AddScrollListener(presShell); - } - } } +} + +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; } @@ -854,8 +855,14 @@ 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 if (mListener) mListener->HandleEvent(nsIAccessibleEventListener::EVENT_STATE_CHANGE, this, nsnull); @@ -868,20 +875,6 @@ NS_IMETHODIMP nsRootAccessible::OnLocationChange(nsIWebProgress *aWebProgress, mListener->HandleEvent(nsIAccessibleEventListener::EVENT_REORDER , this, (AccessibleEventData*)&childrenData); } #endif - - // Document is going away, remove its scroll position listener - nsCOMPtr<nsIDOMWindow> domWin; - aWebProgress->GetDOMWindow(getter_AddRefs(domWin)); - if (domWin) { - nsCOMPtr<nsIDOMDocument> domDoc; - domWin->GetDocument(getter_AddRefs(domDoc)); - nsCOMPtr<nsIDocument> doc(do_QueryInterface(domDoc)); - if (doc) { - nsCOMPtr<nsIPresShell> presShell; - doc->GetShellAt(0, getter_AddRefs(presShell)); - RemoveScrollListener(presShell); - } - } } return NS_OK; diff --git a/accessible/src/base/nsRootAccessible.h b/accessible/src/base/nsRootAccessible.h index a7cc956395c3..16f89677c181 100644 --- a/accessible/src/base/nsRootAccessible.h +++ b/accessible/src/base/nsRootAccessible.h @@ -80,7 +80,6 @@ class nsRootAccessible : public nsAccessible, public nsIDOMFormListener, public nsIDOMXULListener, public nsIWebProgressListener, - public nsITimerCallback, public nsIScrollPositionListener, public nsSupportsWeakReference @@ -132,9 +131,6 @@ class nsRootAccessible : public nsAccessible, NS_IMETHOD ScrollPositionWillChange(nsIScrollableView *aView, nscoord aX, nscoord aY); NS_IMETHOD ScrollPositionDidChange(nsIScrollableView *aView, nscoord aX, nscoord aY); - // ----- nsITimerCallback ------------------------------------ - NS_DECL_NSITIMERCALLBACK - NS_DECL_NSIACCESSIBLEDOCUMENT NS_DECL_NSIWEBPROGRESSLISTENER @@ -145,7 +141,12 @@ class nsRootAccessible : public nsAccessible, void FireAccessibleFocusEvent(nsIAccessible *focusAccessible, nsIDOMNode *focusNode); void AddScrollListener(nsIPresShell *aPresShell); void RemoveScrollListener(nsIPresShell *aPresShell); - friend PRBool PR_CALLBACK RemoveScrollListenerEnum(nsHashKey *aKey, void *aData, void* aClosure); + void AddContentDocListeners(); + void RemoveContentDocListeners(); + void FireDocLoadFinished(); + + static void DocLoadCallback(nsITimer *aTimer, void *aClosure); + static void ScrollTimerCallback(nsITimer *aTimer, void *aClosure); static PRUint32 gInstanceCount; @@ -157,15 +158,15 @@ class nsRootAccessible : public nsAccessible, static nsIDOMNode * gLastFocusedNode; // we do our own refcounting for this - nsCOMPtr<nsITimer> mTimer; + nsCOMPtr<nsITimer> mScrollWatchTimer; + nsCOMPtr<nsITimer> mDocLoadTimer; nsCOMPtr<nsIWebProgress> mWebProgress; nsCOMPtr<nsIAccessibilityService> mAccService; EBusyState mBusy; + PRPackedBool mIsNewDocument; // Used for tracking scroll events PRUint32 mScrollPositionChangedTicks; - nsSupportsHashtable *mScrollablePresShells; - nsCOMPtr<nsIWeakReference> mLastScrolledPresShell; nsCOMPtr<nsIAccessibleCaret> mCaretAccessible; }; diff --git a/accessible/src/html/nsHTMLIFrameRootAccessible.cpp b/accessible/src/html/nsHTMLIFrameRootAccessible.cpp index 7c84a3354f31..ef3ad3585c9e 100644 --- a/accessible/src/html/nsHTMLIFrameRootAccessible.cpp +++ b/accessible/src/html/nsHTMLIFrameRootAccessible.cpp @@ -51,7 +51,7 @@ NS_INTERFACE_MAP_END_INHERITING(nsRootAccessible) NS_IMPL_ADDREF_INHERITED(nsHTMLIFrameRootAccessible, nsRootAccessible); NS_IMPL_RELEASE_INHERITED(nsHTMLIFrameRootAccessible, nsRootAccessible); -NS_IMPL_ISUPPORTS_INHERITED2(nsHTMLIFrameAccessible, nsBlockAccessible, nsIAccessibleDocument, nsIAccessibleHyperText) +NS_IMPL_ISUPPORTS_INHERITED3(nsHTMLIFrameAccessible, nsBlockAccessible, nsIAccessibleDocument, nsIAccessibleHyperText, nsIAccessibleEventReceiver) nsHTMLIFrameAccessible::nsHTMLIFrameAccessible(nsIDOMNode* aNode, nsIAccessible* aRoot, nsIWeakReference* aShell, nsIDocument *aDoc): nsBlockAccessible(aNode, aShell), nsDocAccessibleMixin(aDoc), mRootAccessible(aRoot) @@ -323,11 +323,25 @@ nsresult nsHTMLIFrameAccessible::GetLinkIndexFromAccNode(nsIAccessible *aAccNode return NS_ERROR_INVALID_ARG; } +NS_IMETHODIMP nsHTMLIFrameAccessible::AddAccessibleEventListener(nsIAccessibleEventListener *aListener) +{ + nsCOMPtr<nsIAccessibleEventReceiver> rootReceiver(do_QueryInterface(mRootAccessible)); + NS_ENSURE_TRUE(rootReceiver, NS_OK); + return rootReceiver->AddAccessibleEventListener(aListener); +} + +NS_IMETHODIMP nsHTMLIFrameAccessible::RemoveAccessibleEventListener() +{ + nsCOMPtr<nsIAccessibleEventReceiver> rootReceiver(do_QueryInterface(mRootAccessible)); + NS_ENSURE_TRUE(rootReceiver, NS_OK); + return rootReceiver->RemoveAccessibleEventListener(); +} + + //=============================// // nsHTMLIFrameRootAccessible // //=============================// - //----------------------------------------------------- // construction //----------------------------------------------------- @@ -393,3 +407,25 @@ NS_IMETHODIMP nsHTMLIFrameRootAccessible::GetAccPreviousSibling(nsIAccessible ** Init(); return mOuterAccessible->GetAccPreviousSibling(_retval); } + +/* void addAccessibleEventListener (in nsIAccessibleEventListener aListener); */ +NS_IMETHODIMP nsHTMLIFrameRootAccessible::AddAccessibleEventListener(nsIAccessibleEventListener *aListener) +{ + NS_ASSERTION(aListener, "Trying to add a null listener!"); + if (!mListener) { + mListener = aListener; + AddContentDocListeners(); + } + return NS_OK; +} + +/* void removeAccessibleEventListener (); */ +NS_IMETHODIMP nsHTMLIFrameRootAccessible::RemoveAccessibleEventListener() +{ + if (mListener) { + RemoveContentDocListeners(); + mListener = nsnull; + } + return NS_OK; +} + diff --git a/accessible/src/html/nsHTMLIFrameRootAccessible.h b/accessible/src/html/nsHTMLIFrameRootAccessible.h index 84199b74cde1..514dec31bc9f 100644 --- a/accessible/src/html/nsHTMLIFrameRootAccessible.h +++ b/accessible/src/html/nsHTMLIFrameRootAccessible.h @@ -44,6 +44,7 @@ #include "nsAccessible.h" #include "nsIAccessibleDocument.h" #include "nsIAccessibleHyperText.h" +#include "nsIAccessibleEventReceiver.h" class nsIWebShell; class nsIWeakReference; @@ -51,6 +52,7 @@ class nsIWeakReference; class nsHTMLIFrameAccessible : public nsBlockAccessible, public nsIAccessibleDocument, public nsIAccessibleHyperText, + public nsIAccessibleEventReceiver, public nsDocAccessibleMixin { NS_DECL_ISUPPORTS_INHERITED @@ -68,6 +70,10 @@ class nsHTMLIFrameAccessible : public nsBlockAccessible, NS_IMETHOD GetAccRole(PRUint32 *aAccRole); NS_IMETHOD GetAccState(PRUint32 *aAccState); + // ----- nsIAccessibleEventReceiver ------------------- + NS_IMETHOD AddAccessibleEventListener(nsIAccessibleEventListener *aListener); + NS_IMETHOD RemoveAccessibleEventListener(); + protected: nsCOMPtr<nsIAccessible> mRootAccessible; @@ -99,6 +105,10 @@ class nsHTMLIFrameRootAccessible : public nsRootAccessible /* nsIAccessible getAccPreviousSibling (); */ NS_IMETHOD GetAccPreviousSibling(nsIAccessible **_retval); + // ----- nsIAccessibleEventReceiver ------------------- + NS_IMETHOD AddAccessibleEventListener(nsIAccessibleEventListener *aListener); + NS_IMETHOD RemoveAccessibleEventListener(); + protected: void Init();