зеркало из https://github.com/mozilla/gecko-dev.git
Bug 100498. Active accessibility: Clear, consistent events for page load busy states. r=jgaunt, sr=waterson.
This commit is contained in:
Родитель
3558787cfd
Коммит
97eb525c51
|
@ -28,5 +28,5 @@
|
|||
interface nsIAccessibleEventReceiver : nsISupports
|
||||
{
|
||||
void addAccessibleEventListener(in nsIAccessibleEventListener aListener);
|
||||
void removeAccessibleEventListener(in nsIAccessibleEventListener aListener);
|
||||
void removeAccessibleEventListener();
|
||||
};
|
||||
|
|
|
@ -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<nsIPresShell> 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<nsIPresShell> shell(do_QueryReferent(mPresShell));
|
||||
if (!shell)
|
||||
return NS_ERROR_FAILURE;
|
||||
if (mListener)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDocument> document;
|
||||
shell->GetDocument(getter_AddRefs(document));
|
||||
mListener = aListener;
|
||||
|
||||
// use AddEventListener from the nsIDOMEventTarget interface
|
||||
nsCOMPtr<nsIDOMEventTarget> target;
|
||||
if (NS_SUCCEEDED(document->QueryInterface(NS_GET_IID(nsIDOMEventTarget), getter_AddRefs(target))) && target)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
// we're a DOMEventListener now!!
|
||||
nsCOMPtr<nsIDOMEventListener> 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<nsIPresShell> shell(do_QueryReferent(mPresShell));
|
||||
if (!shell)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIDocument> document;
|
||||
shell->GetDocument(getter_AddRefs(document));
|
||||
if (!document)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// use AddEventListener from the nsIDOMEventTarget interface
|
||||
nsCOMPtr<nsIDOMEventTarget> 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<nsIPresShell> presShell(do_QueryReferent(mPresShell));
|
||||
NS_ASSERTION(shell,"Shell is gone!!! What are we doing here?");
|
||||
|
||||
if (presShell) {
|
||||
nsCOMPtr<nsIPresContext> context;
|
||||
presShell->GetPresContext(getter_AddRefs(context));
|
||||
if (context) {
|
||||
nsCOMPtr<nsISupports> container;
|
||||
context->GetContainer(getter_AddRefs(container));
|
||||
if (container) {
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
|
||||
if (docShell) {
|
||||
nsCOMPtr<nsIWebProgress> 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<nsIPresShell> shell(do_QueryReferent(mPresShell));
|
||||
nsCOMPtr<nsIDocument> document;
|
||||
if (!shell)
|
||||
return NS_OK;
|
||||
|
||||
shell->GetDocument(getter_AddRefs(document));
|
||||
|
||||
nsCOMPtr<nsIDOMEventReceiver> 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<nsIPresShell> shell(do_QueryReferent(mPresShell));
|
||||
nsCOMPtr<nsIDocument> document;
|
||||
if (shell) {
|
||||
shell->GetDocument(getter_AddRefs(document));
|
||||
nsCOMPtr<nsIDOMEventReceiver> 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<nsIAccessible> 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<nsIPresShell> presShell;
|
||||
mDocument->GetShellAt(0, getter_AddRefs(presShell));
|
||||
if (presShell) {
|
||||
nsCOMPtr<nsIPresContext> context;
|
||||
presShell->GetPresContext(getter_AddRefs(context));
|
||||
if (context) {
|
||||
nsCOMPtr<nsISupports> container;
|
||||
context->GetContainer(getter_AddRefs(container));
|
||||
if (container) {
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
|
||||
if (docShell) {
|
||||
PRUint32 busyFlags;
|
||||
docShell->GetBusyFlags(&busyFlags);
|
||||
if (busyFlags != nsIDocShell::BUSY_FLAGS_NONE)
|
||||
*aAccState = nsIAccessible::STATE_BUSY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -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<nsIDocument> 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<nsIDOMNode>& 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<nsITimer> mTimer;
|
||||
nsCOMPtr<nsIDOMNode> mCurrentFocus;
|
||||
nsCOMPtr<nsIAccessibilityService> mAccService;
|
||||
EBusyState mBusy;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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<nsIPresShell> 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<nsIPresShell> shell(do_QueryReferent(mPresShell));
|
||||
if (!shell)
|
||||
return NS_ERROR_FAILURE;
|
||||
if (mListener)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDocument> document;
|
||||
shell->GetDocument(getter_AddRefs(document));
|
||||
mListener = aListener;
|
||||
|
||||
// use AddEventListener from the nsIDOMEventTarget interface
|
||||
nsCOMPtr<nsIDOMEventTarget> target;
|
||||
if (NS_SUCCEEDED(document->QueryInterface(NS_GET_IID(nsIDOMEventTarget), getter_AddRefs(target))) && target)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
// we're a DOMEventListener now!!
|
||||
nsCOMPtr<nsIDOMEventListener> 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<nsIPresShell> shell(do_QueryReferent(mPresShell));
|
||||
if (!shell)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIDocument> document;
|
||||
shell->GetDocument(getter_AddRefs(document));
|
||||
if (!document)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// use AddEventListener from the nsIDOMEventTarget interface
|
||||
nsCOMPtr<nsIDOMEventTarget> 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<nsIPresShell> presShell(do_QueryReferent(mPresShell));
|
||||
NS_ASSERTION(shell,"Shell is gone!!! What are we doing here?");
|
||||
|
||||
if (presShell) {
|
||||
nsCOMPtr<nsIPresContext> context;
|
||||
presShell->GetPresContext(getter_AddRefs(context));
|
||||
if (context) {
|
||||
nsCOMPtr<nsISupports> container;
|
||||
context->GetContainer(getter_AddRefs(container));
|
||||
if (container) {
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
|
||||
if (docShell) {
|
||||
nsCOMPtr<nsIWebProgress> 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<nsIPresShell> shell(do_QueryReferent(mPresShell));
|
||||
nsCOMPtr<nsIDocument> document;
|
||||
if (!shell)
|
||||
return NS_OK;
|
||||
|
||||
shell->GetDocument(getter_AddRefs(document));
|
||||
|
||||
nsCOMPtr<nsIDOMEventReceiver> 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<nsIPresShell> shell(do_QueryReferent(mPresShell));
|
||||
nsCOMPtr<nsIDocument> document;
|
||||
if (shell) {
|
||||
shell->GetDocument(getter_AddRefs(document));
|
||||
nsCOMPtr<nsIDOMEventReceiver> 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<nsIAccessible> 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<nsIPresShell> presShell;
|
||||
mDocument->GetShellAt(0, getter_AddRefs(presShell));
|
||||
if (presShell) {
|
||||
nsCOMPtr<nsIPresContext> context;
|
||||
presShell->GetPresContext(getter_AddRefs(context));
|
||||
if (context) {
|
||||
nsCOMPtr<nsISupports> container;
|
||||
context->GetContainer(getter_AddRefs(container));
|
||||
if (container) {
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
|
||||
if (docShell) {
|
||||
PRUint32 busyFlags;
|
||||
docShell->GetBusyFlags(&busyFlags);
|
||||
if (busyFlags != nsIDocShell::BUSY_FLAGS_NONE)
|
||||
*aAccState = nsIAccessible::STATE_BUSY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -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<nsIDocument> 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<nsIDOMNode>& 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<nsITimer> mTimer;
|
||||
nsCOMPtr<nsIDOMNode> mCurrentFocus;
|
||||
nsCOMPtr<nsIAccessibilityService> mAccService;
|
||||
EBusyState mBusy;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -938,7 +938,7 @@ RootAccessible::~RootAccessible()
|
|||
{
|
||||
nsCOMPtr<nsIAccessibleEventReceiver> r(do_QueryInterface(mAccessible));
|
||||
if (r)
|
||||
r->RemoveAccessibleEventListener(this);
|
||||
r->RemoveAccessibleEventListener();
|
||||
|
||||
// free up accessibles
|
||||
for (int i=0; i < mListCount; i++)
|
||||
|
|
|
@ -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<nsIAccessible> 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<nsIAccessible> 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
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче