From 97eb525c51691107c65f7501249f429a5267f56f Mon Sep 17 00:00:00 2001 From: "aaronl%netscape.com" Date: Tue, 25 Sep 2001 08:34:42 +0000 Subject: [PATCH] Bug 100498. Active accessibility: Clear, consistent events for page load busy states. r=jgaunt, sr=waterson. --- .../public/nsIAccessibleEventReceiver.idl | 2 +- accessible/src/base/nsRootAccessible.cpp | 249 +++++++++++------- accessible/src/base/nsRootAccessible.h | 32 ++- .../src/html/nsHTMLIFrameRootAccessible.cpp | 6 +- accessible/src/nsHTMLIFrameRootAccessible.cpp | 6 +- accessible/src/nsRootAccessible.cpp | 249 +++++++++++------- accessible/src/nsRootAccessible.h | 32 ++- widget/src/windows/Accessible.cpp | 2 +- widget/src/windows/nsWindow.cpp | 65 +++-- widget/src/windows/nsWindow.h | 2 + 10 files changed, 408 insertions(+), 237 deletions(-) diff --git a/accessible/public/nsIAccessibleEventReceiver.idl b/accessible/public/nsIAccessibleEventReceiver.idl index 252a1f6638a3..604756956605 100644 --- a/accessible/public/nsIAccessibleEventReceiver.idl +++ b/accessible/public/nsIAccessibleEventReceiver.idl @@ -28,5 +28,5 @@ interface nsIAccessibleEventReceiver : nsISupports { void addAccessibleEventListener(in nsIAccessibleEventListener aListener); - void removeAccessibleEventListener(in nsIAccessibleEventListener aListener); + void removeAccessibleEventListener(); }; diff --git a/accessible/src/base/nsRootAccessible.cpp b/accessible/src/base/nsRootAccessible.cpp index 4ef79e2fb0a5..a40a6d92771a 100644 --- a/accessible/src/base/nsRootAccessible.cpp +++ b/accessible/src/base/nsRootAccessible.cpp @@ -48,6 +48,7 @@ #include "nsIDOMEventTarget.h" #include "nsIDOMElement.h" #include "nsIDOMEventReceiver.h" +#include "nsIDOMEventListener.h" #include "nsReadableUtils.h" #include "nsILink.h" #include "nsHTMLFormControlAccessible.h" @@ -68,12 +69,19 @@ #include "nsIServiceManager.h" #include "nsHTMLSelectListAccessible.h" #include "nsIDOMHTMLSelectElement.h" +#include "nsIWebProgress.h" +#include "nsCURILoader.h" +#include "nsIInterfaceRequestorUtils.h" + NS_INTERFACE_MAP_BEGIN(nsRootAccessible) NS_INTERFACE_MAP_ENTRY(nsIAccessibleDocument) NS_INTERFACE_MAP_ENTRY(nsIAccessibleEventReceiver) 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_AMBIGUOUS(nsISupports, nsIDOMFormListener) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener, nsIDOMFormListener) NS_INTERFACE_MAP_END_INHERITING(nsAccessible) @@ -86,7 +94,8 @@ NS_IMPL_RELEASE_INHERITED(nsRootAccessible, nsAccessible); // construction //----------------------------------------------------- nsRootAccessible::nsRootAccessible(nsIWeakReference* aShell):nsAccessible(nsnull,aShell), - nsDocAccessibleMixin(aShell), mAccService(do_GetService("@mozilla.org/accessibilityService;1")) + nsDocAccessibleMixin(aShell), mAccService(do_GetService("@mozilla.org/accessibilityService;1")), + mBusy(eBusyStateUninitialized) { mListener = nsnull; nsCOMPtr shell(do_QueryReferent(mPresShell)); @@ -104,7 +113,7 @@ nsRootAccessible::nsRootAccessible(nsIWeakReference* aShell):nsAccessible(nsnull nsRootAccessible::~nsRootAccessible() { nsLayoutAtoms::ReleaseAtoms(); - RemoveAccessibleEventListener(mListener); + RemoveAccessibleEventListener(); } /* attribute wstring accName; */ @@ -174,81 +183,128 @@ NS_IMETHODIMP nsRootAccessible::GetAccRole(PRUint32 *aAccRole) */ *aAccRole = ROLE_PANE; - return NS_OK; + return NS_OK; } NS_IMETHODIMP nsRootAccessible::GetAccState(PRUint32 *aAccState) { - return nsDocAccessibleMixin::GetAccState(aAccState); + *aAccState = STATE_FOCUSABLE; + if (mBusy == eBusyStateLoading) + *aAccState |= STATE_BUSY; + return NS_OK; } - NS_IMETHODIMP nsRootAccessible::GetAccValue(nsAWritableString& aAccValue) { return GetURL(aAccValue); } +void nsRootAccessible::Notify(nsITimer *timer) +{ + // Short timer is finished + if (mBusy != eBusyStateDone) { + mBusy = eBusyStateDone; + if (mListener) + mListener->HandleEvent(nsIAccessibleEventListener::EVENT_STATE_CHANGE, this); + } +} + +NS_IMETHODIMP nsRootAccessible::StartDocReadyTimer() +{ + nsresult rv; + if (!mTimer) + mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv); + if (NS_SUCCEEDED(rv)) { + const PRUint32 kUpdateTimerDelay = 1; + rv = mTimer->Init(NS_STATIC_CAST(nsITimerCallback*, this), kUpdateTimerDelay); + } + + return rv; +} + /* void addAccessibleEventListener (in nsIAccessibleEventListener aListener); */ NS_IMETHODIMP nsRootAccessible::AddAccessibleEventListener(nsIAccessibleEventListener *aListener) { - if (!mListener) - { - // add an event listener to the document - nsCOMPtr shell(do_QueryReferent(mPresShell)); - if (!shell) - return NS_ERROR_FAILURE; + if (mListener) + return NS_OK; - nsCOMPtr document; - shell->GetDocument(getter_AddRefs(document)); + mListener = aListener; - // use AddEventListener from the nsIDOMEventTarget interface - nsCOMPtr target; - if (NS_SUCCEEDED(document->QueryInterface(NS_GET_IID(nsIDOMEventTarget), getter_AddRefs(target))) && target) - { - nsresult rv = NS_OK; - // we're a DOMEventListener now!! - nsCOMPtr listener; - rv = this->QueryInterface( NS_GET_IID(nsIDOMEventListener), getter_AddRefs(listener) ); - NS_ASSERTION(NS_SUCCEEDED(rv), "failed to QI"); - // capture DOM focus events - rv = target->AddEventListener( NS_LITERAL_STRING("focus") , listener, PR_TRUE ); - NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register listener"); - // capture Form change events - rv = target->AddEventListener( NS_LITERAL_STRING("change") , listener, PR_TRUE ); - NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register listener"); - // add ourself as a CheckboxStateChange listener ( custom event fired in nsHTMLInputElement.cpp ) - rv = target->AddEventListener( NS_LITERAL_STRING("CheckboxStateChange") , listener, PR_TRUE ); - NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register listener"); - // add ourself as a RadiobuttonStateChange listener ( custom event fired in nsHTMLInputElement.cpp ) - rv = target->AddEventListener( NS_LITERAL_STRING("RadiobuttonStateChange") , listener, PR_TRUE ); - NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register listener"); - } + // add an event listener to the document + nsCOMPtr shell(do_QueryReferent(mPresShell)); + if (!shell) + return NS_ERROR_FAILURE; + + nsCOMPtr document; + shell->GetDocument(getter_AddRefs(document)); + if (!document) + return NS_ERROR_FAILURE; + + // use AddEventListener from the nsIDOMEventTarget interface + nsCOMPtr target(do_QueryInterface(document)); + if (target) { + // capture DOM focus events + nsresult rv = target->AddEventListener(NS_LITERAL_STRING("focus"), NS_STATIC_CAST(nsIDOMFocusListener*, this), PR_TRUE); + NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register listener"); + rv = target->AddEventListener(NS_LITERAL_STRING("blur"), NS_STATIC_CAST(nsIDOMFocusListener*, this), PR_TRUE); + NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register listener"); + + // capture Form change events + rv = target->AddEventListener(NS_LITERAL_STRING("change"), NS_STATIC_CAST(nsIDOMFormListener*, this), PR_TRUE); + NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register listener"); + // add ourself as a CheckboxStateChange listener (custom event fired in nsHTMLInputElement.cpp) + rv = target->AddEventListener(NS_LITERAL_STRING("CheckboxStateChange"), NS_STATIC_CAST(nsIDOMFormListener*, this), PR_TRUE); + NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register listener"); + // add ourself as a RadiobuttonStateChange listener (custom event fired in nsHTMLInputElement.cpp) + rv = target->AddEventListener(NS_LITERAL_STRING("RadiobuttonStateChange"), NS_STATIC_CAST(nsIDOMFormListener*, this), PR_TRUE); + NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register listener"); + + // Extremely short timer, after which we announce that pane is finished loading + // By waiting until after this short time, we know that the 3rd party accessibility software + // has received it's accessible, and can handle events on it. + StartDocReadyTimer(); } - // create a weak reference to the listener - mListener = aListener; + nsCOMPtr presShell(do_QueryReferent(mPresShell)); + NS_ASSERTION(shell,"Shell is gone!!! What are we doing here?"); + + if (presShell) { + nsCOMPtr context; + presShell->GetPresContext(getter_AddRefs(context)); + if (context) { + nsCOMPtr container; + context->GetContainer(getter_AddRefs(container)); + if (container) { + nsCOMPtr docShell(do_QueryInterface(container)); + if (docShell) { + nsCOMPtr webProgress(do_GetInterface(docShell)); + if (webProgress) { + webProgress->AddProgressListener(this); + } + } + } + } + } return NS_OK; } -/* void removeAccessibleEventListener (in nsIAccessibleEventListener aListener); */ -NS_IMETHODIMP nsRootAccessible::RemoveAccessibleEventListener(nsIAccessibleEventListener *aListener) +/* void removeAccessibleEventListener (); */ +NS_IMETHODIMP nsRootAccessible::RemoveAccessibleEventListener() { - if (mListener) - { - nsCOMPtr shell(do_QueryReferent(mPresShell)); - nsCOMPtr document; - if (!shell) - return NS_OK; - - shell->GetDocument(getter_AddRefs(document)); - - nsCOMPtr erP; - if (NS_SUCCEEDED(document->QueryInterface(NS_GET_IID(nsIDOMEventReceiver), getter_AddRefs(erP))) && erP) - { - nsresult rv = erP->RemoveEventListenerByIID(NS_STATIC_CAST(nsIDOMFocusListener *, this), NS_GET_IID(nsIDOMFocusListener)); - NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register listener"); - } + if (mListener) { + nsCOMPtr shell(do_QueryReferent(mPresShell)); + nsCOMPtr document; + if (shell) { + shell->GetDocument(getter_AddRefs(document)); + nsCOMPtr eventReceiver(do_QueryInterface(document)); + if (eventReceiver) { + nsresult rv = eventReceiver->RemoveEventListenerByIID(NS_STATIC_CAST(nsIDOMFocusListener *, this), NS_GET_IID(nsIDOMFocusListener)); + NS_ASSERTION(NS_SUCCEEDED(rv), "failed to unregister listener"); + rv = eventReceiver->RemoveEventListenerByIID(NS_STATIC_CAST(nsIDOMFormListener *, this), NS_GET_IID(nsIDOMFormListener)); + NS_ASSERTION(NS_SUCCEEDED(rv), "failed to unregister listener"); + } + } } mListener = nsnull; @@ -278,13 +334,13 @@ NS_IMETHODIMP nsRootAccessible::HandleEvent(nsIDOMEvent* aEvent) nsCOMPtr accessible; if (NS_SUCCEEDED(mAccService->GetAccessibleFor(targetNode, getter_AddRefs(accessible)))) { - if ( eventType.EqualsIgnoreCase("focus") ) { + if (eventType.EqualsIgnoreCase("focus")) { if (mCurrentFocus != targetNode) { mListener->HandleEvent(nsIAccessibleEventListener::EVENT_FOCUS, accessible); mCurrentFocus = targetNode; } } - else if ( eventType.EqualsIgnoreCase("change") ) { + else if (eventType.EqualsIgnoreCase("change")) { if (optionTargetNode) { // Set to current option only for HTML selects mListener->HandleEvent(nsIAccessibleEventListener::EVENT_SELECTION, accessible); if (mCurrentFocus != optionTargetNode && @@ -296,12 +352,10 @@ NS_IMETHODIMP nsRootAccessible::HandleEvent(nsIDOMEvent* aEvent) else mListener->HandleEvent(nsIAccessibleEventListener::EVENT_STATE_CHANGE, accessible); } - else if ( eventType.EqualsIgnoreCase("CheckboxStateChange") ) { + else if (eventType.EqualsIgnoreCase("CheckboxStateChange")) mListener->HandleEvent(nsIAccessibleEventListener::EVENT_STATE_CHANGE, accessible); - } - else if ( eventType.EqualsIgnoreCase("RadiobuttonStateChange") ) { + else if (eventType.EqualsIgnoreCase("RadiobuttonStateChange")) mListener->HandleEvent(nsIAccessibleEventListener::EVENT_STATE_CHANGE, accessible); - } } } return NS_OK; @@ -381,6 +435,49 @@ NS_IMETHODIMP nsRootAccessible::GetDocument(nsIDocument **doc) return nsDocAccessibleMixin::GetDocument(doc); } +NS_IMETHODIMP nsRootAccessible::OnStateChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, PRInt32 aStateFlags, PRUint32 aStatus) +{ + if (!mListener) + return NS_ERROR_FAILURE; + + if (mBusy != eBusyStateLoading && (aStateFlags & STATE_START)) { + mBusy = eBusyStateLoading; + mListener->HandleEvent(nsIAccessibleEventListener::EVENT_STATE_CHANGE, this); + } + + 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) +{ + 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 + 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) +{ + return NS_OK; +} + +/* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long state); */ +NS_IMETHODIMP nsRootAccessible::OnSecurityChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, PRInt32 state) +{ + return NS_OK; +} nsDocAccessibleMixin::nsDocAccessibleMixin(nsIDocument *aDoc):mDocument(aDoc) { @@ -452,7 +549,6 @@ NS_IMETHODIMP nsDocAccessibleMixin::GetNameSpaceURIForID(PRInt16 aNameSpaceID, n return NS_ERROR_FAILURE; } - NS_IMETHODIMP nsDocAccessibleMixin::GetDocument(nsIDocument **doc) { *doc = mDocument; @@ -463,35 +559,4 @@ NS_IMETHODIMP nsDocAccessibleMixin::GetDocument(nsIDocument **doc) return NS_ERROR_FAILURE; } -NS_IMETHODIMP nsDocAccessibleMixin::GetAccState(PRUint32 *aAccState) -{ - // Screen readers need to know when the document is finished loading (STATE_BUSY flag) - // We do it this way, rather than via nsIWebProgressListener, because - // if accessibility was turned on after a document already finished loading, - // we would get no state changes from nsIWebProgressListener. - // The GetBusyFlags method, however, always has the current busy state information for us. - *aAccState = 0; - if (mDocument) { - nsCOMPtr presShell; - mDocument->GetShellAt(0, getter_AddRefs(presShell)); - if (presShell) { - nsCOMPtr context; - presShell->GetPresContext(getter_AddRefs(context)); - if (context) { - nsCOMPtr container; - context->GetContainer(getter_AddRefs(container)); - if (container) { - nsCOMPtr docShell(do_QueryInterface(container)); - if (docShell) { - PRUint32 busyFlags; - docShell->GetBusyFlags(&busyFlags); - if (busyFlags != nsIDocShell::BUSY_FLAGS_NONE) - *aAccState = nsIAccessible::STATE_BUSY; - } - } - } - } - } - return NS_OK; -} diff --git a/accessible/src/base/nsRootAccessible.h b/accessible/src/base/nsRootAccessible.h index b250dbb0a962..6d3acba2138a 100644 --- a/accessible/src/base/nsRootAccessible.h +++ b/accessible/src/base/nsRootAccessible.h @@ -47,6 +47,11 @@ #include "nsIDOMFocusListener.h" #include "nsIDocument.h" #include "nsIAccessibilityService.h" +#include "nsIWebProgressListener.h" +#include "nsIWeakReference.h" +#include "nsITimer.h" +#include "nsITimerCallback.h" + class nsDocAccessibleMixin { @@ -57,9 +62,8 @@ class nsDocAccessibleMixin NS_DECL_NSIACCESSIBLEDOCUMENT - NS_IMETHOD GetAccState(PRUint32 *aAccState); - protected: + PRBool mTopLevelDocument; nsCOMPtr mDocument; }; @@ -68,12 +72,18 @@ class nsRootAccessible : public nsAccessible, public nsIAccessibleDocument, public nsIAccessibleEventReceiver, public nsIDOMFocusListener, - public nsIDOMFormListener + public nsIDOMFormListener, + public nsIWebProgressListener, + public nsITimerCallback, + public nsSupportsWeakReference + { NS_DECL_ISUPPORTS_INHERITED public: + enum EBusyState {eBusyStateUninitialized, eBusyStateLoading, eBusyStateDone}; + nsRootAccessible(nsIWeakReference* aShell); virtual ~nsRootAccessible(); @@ -87,10 +97,10 @@ class nsRootAccessible : public nsAccessible, // ----- nsIAccessibleEventReceiver ------------------- NS_IMETHOD AddAccessibleEventListener(nsIAccessibleEventListener *aListener); - NS_IMETHOD RemoveAccessibleEventListener(nsIAccessibleEventListener *aListener); + NS_IMETHOD RemoveAccessibleEventListener(); // ----- nsIDOMEventListener -------------------------- - NS_IMETHOD HandleEvent(nsIDOMEvent* anEvent); + NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent); // ----- nsIDOMFocusListener -------------------------- NS_IMETHOD Focus(nsIDOMEvent* aEvent); @@ -103,19 +113,27 @@ class nsRootAccessible : public nsAccessible, NS_IMETHOD Select(nsIDOMEvent* aEvent); NS_IMETHOD Input(nsIDOMEvent* aEvent); + NS_IMETHOD_(void) Notify(nsITimer *timer); + NS_IMETHOD StartDocReadyTimer(); + NS_DECL_NSIACCESSIBLEDOCUMENT + NS_DECL_NSIWEBPROGRESSLISTENER protected: NS_IMETHOD GetTargetNode(nsIDOMEvent *aEvent, nsCOMPtr& aTargetNode); virtual void GetBounds(nsRect& aRect, nsIFrame** aRelativeFrame); virtual nsIFrame* GetFrame(); - // not a com pointer. We don't own the listener + // 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 - nsIAccessibleEventListener* mListener; + // We don't need a weak reference, because we're owned by this listener + nsIAccessibleEventListener *mListener; + + nsCOMPtr mTimer; nsCOMPtr mCurrentFocus; nsCOMPtr mAccService; + EBusyState mBusy; }; diff --git a/accessible/src/html/nsHTMLIFrameRootAccessible.cpp b/accessible/src/html/nsHTMLIFrameRootAccessible.cpp index e9aaec36d15e..037a29495272 100644 --- a/accessible/src/html/nsHTMLIFrameRootAccessible.cpp +++ b/accessible/src/html/nsHTMLIFrameRootAccessible.cpp @@ -53,10 +53,6 @@ #include "nsReadableUtils.h" NS_INTERFACE_MAP_BEGIN(nsHTMLIFrameRootAccessible) - NS_INTERFACE_MAP_ENTRY(nsIDOMFocusListener) - NS_INTERFACE_MAP_ENTRY(nsIDOMFormListener) - NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMFormListener) - NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener, nsIDOMFormListener) NS_INTERFACE_MAP_END_INHERITING(nsRootAccessible) NS_IMPL_ADDREF_INHERITED(nsHTMLIFrameRootAccessible, nsRootAccessible); @@ -124,7 +120,7 @@ NS_IMETHODIMP nsHTMLIFrameAccessible::GetAccRole(PRUint32 *_retval) NS_IMETHODIMP nsHTMLIFrameAccessible::GetAccState(PRUint32 *aAccState) { - return nsDocAccessibleMixin::GetAccState(aAccState); + return nsAccessible::GetAccState(aAccState); } NS_IMETHODIMP nsHTMLIFrameAccessible::GetURL(nsAWritableString& aURL) diff --git a/accessible/src/nsHTMLIFrameRootAccessible.cpp b/accessible/src/nsHTMLIFrameRootAccessible.cpp index e9aaec36d15e..037a29495272 100644 --- a/accessible/src/nsHTMLIFrameRootAccessible.cpp +++ b/accessible/src/nsHTMLIFrameRootAccessible.cpp @@ -53,10 +53,6 @@ #include "nsReadableUtils.h" NS_INTERFACE_MAP_BEGIN(nsHTMLIFrameRootAccessible) - NS_INTERFACE_MAP_ENTRY(nsIDOMFocusListener) - NS_INTERFACE_MAP_ENTRY(nsIDOMFormListener) - NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMFormListener) - NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener, nsIDOMFormListener) NS_INTERFACE_MAP_END_INHERITING(nsRootAccessible) NS_IMPL_ADDREF_INHERITED(nsHTMLIFrameRootAccessible, nsRootAccessible); @@ -124,7 +120,7 @@ NS_IMETHODIMP nsHTMLIFrameAccessible::GetAccRole(PRUint32 *_retval) NS_IMETHODIMP nsHTMLIFrameAccessible::GetAccState(PRUint32 *aAccState) { - return nsDocAccessibleMixin::GetAccState(aAccState); + return nsAccessible::GetAccState(aAccState); } NS_IMETHODIMP nsHTMLIFrameAccessible::GetURL(nsAWritableString& aURL) diff --git a/accessible/src/nsRootAccessible.cpp b/accessible/src/nsRootAccessible.cpp index 4ef79e2fb0a5..a40a6d92771a 100644 --- a/accessible/src/nsRootAccessible.cpp +++ b/accessible/src/nsRootAccessible.cpp @@ -48,6 +48,7 @@ #include "nsIDOMEventTarget.h" #include "nsIDOMElement.h" #include "nsIDOMEventReceiver.h" +#include "nsIDOMEventListener.h" #include "nsReadableUtils.h" #include "nsILink.h" #include "nsHTMLFormControlAccessible.h" @@ -68,12 +69,19 @@ #include "nsIServiceManager.h" #include "nsHTMLSelectListAccessible.h" #include "nsIDOMHTMLSelectElement.h" +#include "nsIWebProgress.h" +#include "nsCURILoader.h" +#include "nsIInterfaceRequestorUtils.h" + NS_INTERFACE_MAP_BEGIN(nsRootAccessible) NS_INTERFACE_MAP_ENTRY(nsIAccessibleDocument) NS_INTERFACE_MAP_ENTRY(nsIAccessibleEventReceiver) 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_AMBIGUOUS(nsISupports, nsIDOMFormListener) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener, nsIDOMFormListener) NS_INTERFACE_MAP_END_INHERITING(nsAccessible) @@ -86,7 +94,8 @@ NS_IMPL_RELEASE_INHERITED(nsRootAccessible, nsAccessible); // construction //----------------------------------------------------- nsRootAccessible::nsRootAccessible(nsIWeakReference* aShell):nsAccessible(nsnull,aShell), - nsDocAccessibleMixin(aShell), mAccService(do_GetService("@mozilla.org/accessibilityService;1")) + nsDocAccessibleMixin(aShell), mAccService(do_GetService("@mozilla.org/accessibilityService;1")), + mBusy(eBusyStateUninitialized) { mListener = nsnull; nsCOMPtr shell(do_QueryReferent(mPresShell)); @@ -104,7 +113,7 @@ nsRootAccessible::nsRootAccessible(nsIWeakReference* aShell):nsAccessible(nsnull nsRootAccessible::~nsRootAccessible() { nsLayoutAtoms::ReleaseAtoms(); - RemoveAccessibleEventListener(mListener); + RemoveAccessibleEventListener(); } /* attribute wstring accName; */ @@ -174,81 +183,128 @@ NS_IMETHODIMP nsRootAccessible::GetAccRole(PRUint32 *aAccRole) */ *aAccRole = ROLE_PANE; - return NS_OK; + return NS_OK; } NS_IMETHODIMP nsRootAccessible::GetAccState(PRUint32 *aAccState) { - return nsDocAccessibleMixin::GetAccState(aAccState); + *aAccState = STATE_FOCUSABLE; + if (mBusy == eBusyStateLoading) + *aAccState |= STATE_BUSY; + return NS_OK; } - NS_IMETHODIMP nsRootAccessible::GetAccValue(nsAWritableString& aAccValue) { return GetURL(aAccValue); } +void nsRootAccessible::Notify(nsITimer *timer) +{ + // Short timer is finished + if (mBusy != eBusyStateDone) { + mBusy = eBusyStateDone; + if (mListener) + mListener->HandleEvent(nsIAccessibleEventListener::EVENT_STATE_CHANGE, this); + } +} + +NS_IMETHODIMP nsRootAccessible::StartDocReadyTimer() +{ + nsresult rv; + if (!mTimer) + mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv); + if (NS_SUCCEEDED(rv)) { + const PRUint32 kUpdateTimerDelay = 1; + rv = mTimer->Init(NS_STATIC_CAST(nsITimerCallback*, this), kUpdateTimerDelay); + } + + return rv; +} + /* void addAccessibleEventListener (in nsIAccessibleEventListener aListener); */ NS_IMETHODIMP nsRootAccessible::AddAccessibleEventListener(nsIAccessibleEventListener *aListener) { - if (!mListener) - { - // add an event listener to the document - nsCOMPtr shell(do_QueryReferent(mPresShell)); - if (!shell) - return NS_ERROR_FAILURE; + if (mListener) + return NS_OK; - nsCOMPtr document; - shell->GetDocument(getter_AddRefs(document)); + mListener = aListener; - // use AddEventListener from the nsIDOMEventTarget interface - nsCOMPtr target; - if (NS_SUCCEEDED(document->QueryInterface(NS_GET_IID(nsIDOMEventTarget), getter_AddRefs(target))) && target) - { - nsresult rv = NS_OK; - // we're a DOMEventListener now!! - nsCOMPtr listener; - rv = this->QueryInterface( NS_GET_IID(nsIDOMEventListener), getter_AddRefs(listener) ); - NS_ASSERTION(NS_SUCCEEDED(rv), "failed to QI"); - // capture DOM focus events - rv = target->AddEventListener( NS_LITERAL_STRING("focus") , listener, PR_TRUE ); - NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register listener"); - // capture Form change events - rv = target->AddEventListener( NS_LITERAL_STRING("change") , listener, PR_TRUE ); - NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register listener"); - // add ourself as a CheckboxStateChange listener ( custom event fired in nsHTMLInputElement.cpp ) - rv = target->AddEventListener( NS_LITERAL_STRING("CheckboxStateChange") , listener, PR_TRUE ); - NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register listener"); - // add ourself as a RadiobuttonStateChange listener ( custom event fired in nsHTMLInputElement.cpp ) - rv = target->AddEventListener( NS_LITERAL_STRING("RadiobuttonStateChange") , listener, PR_TRUE ); - NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register listener"); - } + // add an event listener to the document + nsCOMPtr shell(do_QueryReferent(mPresShell)); + if (!shell) + return NS_ERROR_FAILURE; + + nsCOMPtr document; + shell->GetDocument(getter_AddRefs(document)); + if (!document) + return NS_ERROR_FAILURE; + + // use AddEventListener from the nsIDOMEventTarget interface + nsCOMPtr target(do_QueryInterface(document)); + if (target) { + // capture DOM focus events + nsresult rv = target->AddEventListener(NS_LITERAL_STRING("focus"), NS_STATIC_CAST(nsIDOMFocusListener*, this), PR_TRUE); + NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register listener"); + rv = target->AddEventListener(NS_LITERAL_STRING("blur"), NS_STATIC_CAST(nsIDOMFocusListener*, this), PR_TRUE); + NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register listener"); + + // capture Form change events + rv = target->AddEventListener(NS_LITERAL_STRING("change"), NS_STATIC_CAST(nsIDOMFormListener*, this), PR_TRUE); + NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register listener"); + // add ourself as a CheckboxStateChange listener (custom event fired in nsHTMLInputElement.cpp) + rv = target->AddEventListener(NS_LITERAL_STRING("CheckboxStateChange"), NS_STATIC_CAST(nsIDOMFormListener*, this), PR_TRUE); + NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register listener"); + // add ourself as a RadiobuttonStateChange listener (custom event fired in nsHTMLInputElement.cpp) + rv = target->AddEventListener(NS_LITERAL_STRING("RadiobuttonStateChange"), NS_STATIC_CAST(nsIDOMFormListener*, this), PR_TRUE); + NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register listener"); + + // Extremely short timer, after which we announce that pane is finished loading + // By waiting until after this short time, we know that the 3rd party accessibility software + // has received it's accessible, and can handle events on it. + StartDocReadyTimer(); } - // create a weak reference to the listener - mListener = aListener; + nsCOMPtr presShell(do_QueryReferent(mPresShell)); + NS_ASSERTION(shell,"Shell is gone!!! What are we doing here?"); + + if (presShell) { + nsCOMPtr context; + presShell->GetPresContext(getter_AddRefs(context)); + if (context) { + nsCOMPtr container; + context->GetContainer(getter_AddRefs(container)); + if (container) { + nsCOMPtr docShell(do_QueryInterface(container)); + if (docShell) { + nsCOMPtr webProgress(do_GetInterface(docShell)); + if (webProgress) { + webProgress->AddProgressListener(this); + } + } + } + } + } return NS_OK; } -/* void removeAccessibleEventListener (in nsIAccessibleEventListener aListener); */ -NS_IMETHODIMP nsRootAccessible::RemoveAccessibleEventListener(nsIAccessibleEventListener *aListener) +/* void removeAccessibleEventListener (); */ +NS_IMETHODIMP nsRootAccessible::RemoveAccessibleEventListener() { - if (mListener) - { - nsCOMPtr shell(do_QueryReferent(mPresShell)); - nsCOMPtr document; - if (!shell) - return NS_OK; - - shell->GetDocument(getter_AddRefs(document)); - - nsCOMPtr erP; - if (NS_SUCCEEDED(document->QueryInterface(NS_GET_IID(nsIDOMEventReceiver), getter_AddRefs(erP))) && erP) - { - nsresult rv = erP->RemoveEventListenerByIID(NS_STATIC_CAST(nsIDOMFocusListener *, this), NS_GET_IID(nsIDOMFocusListener)); - NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register listener"); - } + if (mListener) { + nsCOMPtr shell(do_QueryReferent(mPresShell)); + nsCOMPtr document; + if (shell) { + shell->GetDocument(getter_AddRefs(document)); + nsCOMPtr eventReceiver(do_QueryInterface(document)); + if (eventReceiver) { + nsresult rv = eventReceiver->RemoveEventListenerByIID(NS_STATIC_CAST(nsIDOMFocusListener *, this), NS_GET_IID(nsIDOMFocusListener)); + NS_ASSERTION(NS_SUCCEEDED(rv), "failed to unregister listener"); + rv = eventReceiver->RemoveEventListenerByIID(NS_STATIC_CAST(nsIDOMFormListener *, this), NS_GET_IID(nsIDOMFormListener)); + NS_ASSERTION(NS_SUCCEEDED(rv), "failed to unregister listener"); + } + } } mListener = nsnull; @@ -278,13 +334,13 @@ NS_IMETHODIMP nsRootAccessible::HandleEvent(nsIDOMEvent* aEvent) nsCOMPtr accessible; if (NS_SUCCEEDED(mAccService->GetAccessibleFor(targetNode, getter_AddRefs(accessible)))) { - if ( eventType.EqualsIgnoreCase("focus") ) { + if (eventType.EqualsIgnoreCase("focus")) { if (mCurrentFocus != targetNode) { mListener->HandleEvent(nsIAccessibleEventListener::EVENT_FOCUS, accessible); mCurrentFocus = targetNode; } } - else if ( eventType.EqualsIgnoreCase("change") ) { + else if (eventType.EqualsIgnoreCase("change")) { if (optionTargetNode) { // Set to current option only for HTML selects mListener->HandleEvent(nsIAccessibleEventListener::EVENT_SELECTION, accessible); if (mCurrentFocus != optionTargetNode && @@ -296,12 +352,10 @@ NS_IMETHODIMP nsRootAccessible::HandleEvent(nsIDOMEvent* aEvent) else mListener->HandleEvent(nsIAccessibleEventListener::EVENT_STATE_CHANGE, accessible); } - else if ( eventType.EqualsIgnoreCase("CheckboxStateChange") ) { + else if (eventType.EqualsIgnoreCase("CheckboxStateChange")) mListener->HandleEvent(nsIAccessibleEventListener::EVENT_STATE_CHANGE, accessible); - } - else if ( eventType.EqualsIgnoreCase("RadiobuttonStateChange") ) { + else if (eventType.EqualsIgnoreCase("RadiobuttonStateChange")) mListener->HandleEvent(nsIAccessibleEventListener::EVENT_STATE_CHANGE, accessible); - } } } return NS_OK; @@ -381,6 +435,49 @@ NS_IMETHODIMP nsRootAccessible::GetDocument(nsIDocument **doc) return nsDocAccessibleMixin::GetDocument(doc); } +NS_IMETHODIMP nsRootAccessible::OnStateChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, PRInt32 aStateFlags, PRUint32 aStatus) +{ + if (!mListener) + return NS_ERROR_FAILURE; + + if (mBusy != eBusyStateLoading && (aStateFlags & STATE_START)) { + mBusy = eBusyStateLoading; + mListener->HandleEvent(nsIAccessibleEventListener::EVENT_STATE_CHANGE, this); + } + + 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) +{ + 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 + 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) +{ + return NS_OK; +} + +/* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long state); */ +NS_IMETHODIMP nsRootAccessible::OnSecurityChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, PRInt32 state) +{ + return NS_OK; +} nsDocAccessibleMixin::nsDocAccessibleMixin(nsIDocument *aDoc):mDocument(aDoc) { @@ -452,7 +549,6 @@ NS_IMETHODIMP nsDocAccessibleMixin::GetNameSpaceURIForID(PRInt16 aNameSpaceID, n return NS_ERROR_FAILURE; } - NS_IMETHODIMP nsDocAccessibleMixin::GetDocument(nsIDocument **doc) { *doc = mDocument; @@ -463,35 +559,4 @@ NS_IMETHODIMP nsDocAccessibleMixin::GetDocument(nsIDocument **doc) return NS_ERROR_FAILURE; } -NS_IMETHODIMP nsDocAccessibleMixin::GetAccState(PRUint32 *aAccState) -{ - // Screen readers need to know when the document is finished loading (STATE_BUSY flag) - // We do it this way, rather than via nsIWebProgressListener, because - // if accessibility was turned on after a document already finished loading, - // we would get no state changes from nsIWebProgressListener. - // The GetBusyFlags method, however, always has the current busy state information for us. - *aAccState = 0; - if (mDocument) { - nsCOMPtr presShell; - mDocument->GetShellAt(0, getter_AddRefs(presShell)); - if (presShell) { - nsCOMPtr context; - presShell->GetPresContext(getter_AddRefs(context)); - if (context) { - nsCOMPtr container; - context->GetContainer(getter_AddRefs(container)); - if (container) { - nsCOMPtr docShell(do_QueryInterface(container)); - if (docShell) { - PRUint32 busyFlags; - docShell->GetBusyFlags(&busyFlags); - if (busyFlags != nsIDocShell::BUSY_FLAGS_NONE) - *aAccState = nsIAccessible::STATE_BUSY; - } - } - } - } - } - return NS_OK; -} diff --git a/accessible/src/nsRootAccessible.h b/accessible/src/nsRootAccessible.h index b250dbb0a962..6d3acba2138a 100644 --- a/accessible/src/nsRootAccessible.h +++ b/accessible/src/nsRootAccessible.h @@ -47,6 +47,11 @@ #include "nsIDOMFocusListener.h" #include "nsIDocument.h" #include "nsIAccessibilityService.h" +#include "nsIWebProgressListener.h" +#include "nsIWeakReference.h" +#include "nsITimer.h" +#include "nsITimerCallback.h" + class nsDocAccessibleMixin { @@ -57,9 +62,8 @@ class nsDocAccessibleMixin NS_DECL_NSIACCESSIBLEDOCUMENT - NS_IMETHOD GetAccState(PRUint32 *aAccState); - protected: + PRBool mTopLevelDocument; nsCOMPtr mDocument; }; @@ -68,12 +72,18 @@ class nsRootAccessible : public nsAccessible, public nsIAccessibleDocument, public nsIAccessibleEventReceiver, public nsIDOMFocusListener, - public nsIDOMFormListener + public nsIDOMFormListener, + public nsIWebProgressListener, + public nsITimerCallback, + public nsSupportsWeakReference + { NS_DECL_ISUPPORTS_INHERITED public: + enum EBusyState {eBusyStateUninitialized, eBusyStateLoading, eBusyStateDone}; + nsRootAccessible(nsIWeakReference* aShell); virtual ~nsRootAccessible(); @@ -87,10 +97,10 @@ class nsRootAccessible : public nsAccessible, // ----- nsIAccessibleEventReceiver ------------------- NS_IMETHOD AddAccessibleEventListener(nsIAccessibleEventListener *aListener); - NS_IMETHOD RemoveAccessibleEventListener(nsIAccessibleEventListener *aListener); + NS_IMETHOD RemoveAccessibleEventListener(); // ----- nsIDOMEventListener -------------------------- - NS_IMETHOD HandleEvent(nsIDOMEvent* anEvent); + NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent); // ----- nsIDOMFocusListener -------------------------- NS_IMETHOD Focus(nsIDOMEvent* aEvent); @@ -103,19 +113,27 @@ class nsRootAccessible : public nsAccessible, NS_IMETHOD Select(nsIDOMEvent* aEvent); NS_IMETHOD Input(nsIDOMEvent* aEvent); + NS_IMETHOD_(void) Notify(nsITimer *timer); + NS_IMETHOD StartDocReadyTimer(); + NS_DECL_NSIACCESSIBLEDOCUMENT + NS_DECL_NSIWEBPROGRESSLISTENER protected: NS_IMETHOD GetTargetNode(nsIDOMEvent *aEvent, nsCOMPtr& aTargetNode); virtual void GetBounds(nsRect& aRect, nsIFrame** aRelativeFrame); virtual nsIFrame* GetFrame(); - // not a com pointer. We don't own the listener + // 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 - nsIAccessibleEventListener* mListener; + // We don't need a weak reference, because we're owned by this listener + nsIAccessibleEventListener *mListener; + + nsCOMPtr mTimer; nsCOMPtr mCurrentFocus; nsCOMPtr mAccService; + EBusyState mBusy; }; diff --git a/widget/src/windows/Accessible.cpp b/widget/src/windows/Accessible.cpp index 1e0c84db6e66..f75dafdf5fc1 100644 --- a/widget/src/windows/Accessible.cpp +++ b/widget/src/windows/Accessible.cpp @@ -938,7 +938,7 @@ RootAccessible::~RootAccessible() { nsCOMPtr r(do_QueryInterface(mAccessible)); if (r) - r->RemoveAccessibleEventListener(this); + r->RemoveAccessibleEventListener(); // free up accessibles for (int i=0; i < mListCount; i++) diff --git a/widget/src/windows/nsWindow.cpp b/widget/src/windows/nsWindow.cpp index 83a329fe5f15..0edaeb38b5c6 100644 --- a/widget/src/windows/nsWindow.cpp +++ b/widget/src/windows/nsWindow.cpp @@ -142,6 +142,9 @@ UINT nsWindow::uMSH_MOUSEWHEEL = 0; UINT nsWindow::uWM_MSIME_RECONVERT = 0; // reconvert messge for MSIME UINT nsWindow::uWM_MSIME_MOUSE = 0; // mouse messge for MSIME UINT nsWindow::uWM_ATOK_RECONVERT = 0; // reconvert messge for ATOK +#ifdef ACCESSIBILITY +BOOL nsWindow::gIsAccessibilityOn = FALSE; +#endif nsWindow* nsWindow::gCurrentWindow = nsnull; //////////////////////////////////////////////////// @@ -530,8 +533,10 @@ UINT nsWindow::gCurrentKeyboardCP = 0; nsWindow::~nsWindow() { #ifdef ACCESSIBILITY - if (mRootAccessible) + if (mRootAccessible) { mRootAccessible->Release(); + mRootAccessible = nsnull; + } #endif mIsDestroying = PR_TRUE; @@ -3360,6 +3365,11 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT gJustGotActivate = PR_FALSE; result = DispatchFocus(NS_ACTIVATE, isMozWindowTakingFocus); } +#ifdef ACCESSIBILITY + if (nsWindow::gIsAccessibilityOn && !mRootAccessible && mIsTopWidgetWindow) + CreateRootAccessible(); +#endif + break; case WM_KILLFOCUS: @@ -3586,32 +3596,16 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT #ifdef ACCESSIBILITY case WM_GETOBJECT: { - if (lParam == OBJID_CLIENT) { - if (!mRootAccessible) { - nsCOMPtr acc; - DispatchAccessibleEvent(NS_GETACCESSIBLE, getter_AddRefs(acc)); - // create the COM accessible object - if (acc) - { - HWND wnd = GetWindowHandle(); - mRootAccessible = new RootAccessible(acc, wnd); // ref is 0 - mRootAccessible->AddRef(); - } - } - if (mRootAccessible) { - // ask accessible to do this do it loads the library dynamically - LRESULT lAcc = Accessible::LresultFromObject(IID_IAccessible, wParam, mRootAccessible); // ref 1 - if (lAcc == 0) { - *aRetValue = NULL; - return PR_FALSE; - } - *aRetValue = lAcc; - return PR_TRUE; // yes we handled it. - } - } - *aRetValue = NULL; - return PR_FALSE; - } break; + nsWindow::gIsAccessibilityOn = TRUE; + LRESULT lAcc = 0; + if (mIsTopWidgetWindow && !mRootAccessible) + CreateRootAccessible(); + if (lParam == OBJID_CLIENT && mRootAccessible) // oleacc.dll will be loaded dynamically + lAcc = Accessible::LresultFromObject(IID_IAccessible, wParam, mRootAccessible); // ref 1 + + return (*aRetValue = lAcc) != 0; + + } #endif default: { // Handle both flavors of mouse wheel events. @@ -5828,3 +5822,20 @@ VOID CALLBACK nsWindow::HookTimerForPopups( HWND hwnd, UINT uMsg, UINT idEvent, } } + + +#ifdef ACCESSIBILITY +void nsWindow::CreateRootAccessible() +{ + // Create this as early as possible in new window, if accessibility is turned on + // We need it to be created early so it can generate accessibility events right away + nsCOMPtr acc; + DispatchAccessibleEvent(NS_GETACCESSIBLE, getter_AddRefs(acc)); + // create the COM accessible object + if (acc) { + HWND wnd = GetWindowHandle(); + mRootAccessible = new RootAccessible(acc, wnd); // ref is 0 + mRootAccessible->AddRef(); + } +} +#endif diff --git a/widget/src/windows/nsWindow.h b/widget/src/windows/nsWindow.h index b2ee98a3e3ff..f7d294144d5d 100644 --- a/widget/src/windows/nsWindow.h +++ b/widget/src/windows/nsWindow.h @@ -298,6 +298,7 @@ public: virtual PRBool DispatchMouseEvent(PRUint32 aEventType, nsPoint* aPoint = nsnull); #ifdef ACCESSIBILITY virtual PRBool DispatchAccessibleEvent(PRUint32 aEventType, nsIAccessible** aAccessible, nsPoint* aPoint = nsnull); + void CreateRootAccessible(); #endif virtual PRBool AutoErase(); nsPoint* GetLastPoint() { return &mLastPoint; } @@ -473,6 +474,7 @@ protected: #ifdef ACCESSIBILITY IAccessible* mRootAccessible; + static BOOL gIsAccessibilityOn; #endif };