зеркало из https://github.com/mozilla/gecko-dev.git
Bug 343136 Support ATK document events
patch by Nian Liu at sun.com r=aaronlev, ginn.chen
This commit is contained in:
Родитель
cd5da0b273
Коммит
d85c8bd9c4
|
@ -59,7 +59,7 @@ interface nsIDOMNode;
|
|||
*
|
||||
* @status UNDER_REVIEW
|
||||
*/
|
||||
[scriptable, uuid(87F29033-C4A6-40a3-AC7A-3BA391F9992D)]
|
||||
[scriptable, uuid(b298afc0-4158-11db-b0de-0800200c9a66)]
|
||||
interface nsIAccessibleEvent : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -127,6 +127,11 @@ interface nsIAccessibleEvent : nsISupports
|
|||
const unsigned long EVENT_SCROLLINGEND = 0x0013;
|
||||
const unsigned long EVENT_MINIMIZESTART = 0x0016;
|
||||
const unsigned long EVENT_MINIMIZEEND = 0x0017;
|
||||
const unsigned long EVENT_DOCUMENT_LOAD_START = 0x0018;
|
||||
const unsigned long EVENT_DOCUMENT_LOAD_COMPLETE = 0x0019;
|
||||
const unsigned long EVENT_DOCUMENT_RELOAD = 0x0020;
|
||||
const unsigned long EVENT_DOCUMENT_LOAD_STOPPED = 0x0021;
|
||||
const unsigned long EVENT_DOCUMENT_ATTRIBUTES_CHANGED = 0x0022;
|
||||
|
||||
// the additional events for ATK
|
||||
const unsigned long EVENT_ATK_PROPERTY_CHANGE = 0x0100;
|
||||
|
|
|
@ -62,6 +62,6 @@ interface nsPIAccessibleDocument : nsISupports
|
|||
void cacheAccessNode(in voidPtr aUniqueID, in nsIAccessNode aAccessNode);
|
||||
void destroy();
|
||||
void flushPendingEvents();
|
||||
void fireDocLoadingEvent(in boolean isFinished);
|
||||
void fireDocLoadEvents(in PRUint32 aEventType);
|
||||
void fireAnchorJumpEvent();
|
||||
};
|
||||
|
|
|
@ -118,34 +118,34 @@ NS_IMETHODIMP nsDocAccessibleWrap::FireToolkitEvent(PRUint32 aEvent,
|
|||
} break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_STATE_CHANGE:
|
||||
AtkStateChange *pAtkStateChange;
|
||||
StateChange *pStateChange;
|
||||
AtkStateType atkState;
|
||||
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_STATE_CHANGE\n"));
|
||||
if (!aEventData)
|
||||
break;
|
||||
|
||||
pAtkStateChange = NS_REINTERPRET_CAST(AtkStateChange *, aEventData);
|
||||
pStateChange = NS_REINTERPRET_CAST(StateChange *, aEventData);
|
||||
|
||||
switch (pAtkStateChange->state) {
|
||||
switch (pStateChange->state) {
|
||||
case nsIAccessible::STATE_INVISIBLE:
|
||||
atkState = ATK_STATE_VISIBLE;
|
||||
pAtkStateChange->enable = !pAtkStateChange->enable;
|
||||
pStateChange->enable = !pStateChange->enable;
|
||||
break;
|
||||
case nsIAccessible::STATE_UNAVAILABLE:
|
||||
atkState = ATK_STATE_ENABLED;
|
||||
pAtkStateChange->enable = !pAtkStateChange->enable;
|
||||
pStateChange->enable = !pStateChange->enable;
|
||||
break;
|
||||
case nsIAccessible::STATE_READONLY:
|
||||
atkState = ATK_STATE_EDITABLE;
|
||||
pAtkStateChange->enable = !pAtkStateChange->enable;
|
||||
pStateChange->enable = !pStateChange->enable;
|
||||
break;
|
||||
default:
|
||||
atkState = TranslateAState(pAtkStateChange->state, pAtkStateChange->extState);
|
||||
atkState = TranslateAState(pStateChange->state, pStateChange->extState);
|
||||
}
|
||||
|
||||
atk_object_notify_state_change(accWrap->GetAtkObject(),
|
||||
atkState, pAtkStateChange->enable);
|
||||
atkState, pStateChange->enable);
|
||||
rv = NS_OK;
|
||||
break;
|
||||
|
||||
|
@ -457,6 +457,38 @@ NS_IMETHODIMP nsDocAccessibleWrap::FireToolkitEvent(PRUint32 aEvent,
|
|||
rv = NS_OK;
|
||||
} break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE:
|
||||
{
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_DOCUMENT_LOAD_COMPLETE\n"));
|
||||
g_signal_emit_by_name (accWrap->GetAtkObject(),
|
||||
"load_complete");
|
||||
rv = NS_OK;
|
||||
} break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_DOCUMENT_RELOAD:
|
||||
{
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_DOCUMENT_RELOAD\n"));
|
||||
g_signal_emit_by_name (accWrap->GetAtkObject(),
|
||||
"reload");
|
||||
rv = NS_OK;
|
||||
} break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED:
|
||||
{
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_DOCUMENT_LOAD_STOPPED\n"));
|
||||
g_signal_emit_by_name (accWrap->GetAtkObject(),
|
||||
"load_stopped");
|
||||
rv = NS_OK;
|
||||
} break;
|
||||
|
||||
case nsIAccessibleEvent::EVENT_DOCUMENT_ATTRIBUTES_CHANGED:
|
||||
{
|
||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_DOCUMENT_ATTRIBUTES_CHANGED\n"));
|
||||
g_signal_emit_by_name (accWrap->GetAtkObject(),
|
||||
"attriubtes_changed");
|
||||
rv = NS_OK;
|
||||
} break;
|
||||
|
||||
default:
|
||||
// Don't transfer others
|
||||
MAI_LOG_DEBUG(("\n\nReceived an unknown event=0x%u\n", aEvent));
|
||||
|
@ -538,19 +570,3 @@ TranslateAState(PRUint32 aState, PRUint32 aExtState)
|
|||
return ATK_STATE_INVALID;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsDocAccessibleWrap::FireDocLoadingEvent(PRBool aIsFinished)
|
||||
{
|
||||
if (!mDocument || !mWeakShell)
|
||||
return NS_OK; // Document has been shut down
|
||||
|
||||
if (!aIsFinished) {
|
||||
// Load has been verified, it will occur, about to commence
|
||||
AtkChildrenChange childrenData;
|
||||
childrenData.index = -1;
|
||||
childrenData.child = 0;
|
||||
childrenData.add = PR_FALSE;
|
||||
FireToolkitEvent(nsIAccessibleEvent::EVENT_REORDER, this, &childrenData);
|
||||
}
|
||||
|
||||
return nsDocAccessible::FireDocLoadingEvent(aIsFinished);
|
||||
}
|
||||
|
|
|
@ -57,7 +57,6 @@ public:
|
|||
virtual ~nsDocAccessibleWrap();
|
||||
NS_IMETHOD FireToolkitEvent(PRUint32 aEvent, nsIAccessible* aAccessible,
|
||||
void* aData);
|
||||
NS_IMETHOD FireDocLoadingEvent(PRBool isFinished);
|
||||
|
||||
protected:
|
||||
PRBool mActivated;
|
||||
|
|
|
@ -141,7 +141,7 @@ nsresult nsRootAccessibleWrap::HandleEventWithTarget(nsIDOMEvent *aEvent,
|
|||
}
|
||||
#endif
|
||||
|
||||
AtkStateChange stateData;
|
||||
StateChange stateData;
|
||||
if (eventType.LowerCaseEqualsLiteral("focus")) {
|
||||
#ifdef MOZ_XUL
|
||||
if (treeItemAccessible) { // use focused treeitem
|
||||
|
|
|
@ -79,6 +79,8 @@
|
|||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsIWebProgress.h"
|
||||
#include "nsNetError.h"
|
||||
#include "nsDocShellLoadTypes.h"
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
#include "nsXULAlertAccessible.h"
|
||||
|
@ -163,7 +165,7 @@ NS_IMETHODIMP nsAccessibilityService::OnStateChange(nsIWebProgress *aWebProgress
|
|||
{
|
||||
NS_ASSERTION(aStateFlags & STATE_IS_DOCUMENT, "Other notifications excluded");
|
||||
|
||||
if (0 == (aStateFlags & (STATE_START | STATE_STOP)) || NS_FAILED(aStatus)) {
|
||||
if (0 == (aStateFlags & (STATE_START | STATE_STOP))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -196,9 +198,31 @@ NS_IMETHODIMP nsAccessibilityService::OnStateChange(nsIWebProgress *aWebProgress
|
|||
nsCOMPtr<nsPIAccessibleDocument> docAccessible =
|
||||
do_QueryInterface(accessible);
|
||||
NS_ENSURE_TRUE(docAccessible, NS_ERROR_FAILURE);
|
||||
PRBool isFinished = !(aStateFlags & STATE_START);
|
||||
|
||||
docAccessible->FireDocLoadingEvent(isFinished);
|
||||
PRUint32 eventType = 0;
|
||||
if ((aStateFlags & STATE_STOP) && NS_SUCCEEDED(aStatus)) {
|
||||
eventType = nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE;
|
||||
} else if ((aStateFlags & STATE_STOP) && (aStatus & NS_BINDING_ABORTED)) {
|
||||
eventType = nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED;
|
||||
} else if (aStateFlags & STATE_START) {
|
||||
eventType = nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_START;
|
||||
nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(domWindow));
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(webNav));
|
||||
NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
|
||||
PRUint32 loadType;
|
||||
docShell->GetLoadType(&loadType);
|
||||
if (loadType == LOAD_RELOAD_NORMAL ||
|
||||
loadType == LOAD_RELOAD_BYPASS_CACHE ||
|
||||
loadType == LOAD_RELOAD_BYPASS_PROXY ||
|
||||
loadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE) {
|
||||
eventType = nsIAccessibleEvent::EVENT_DOCUMENT_RELOAD;
|
||||
}
|
||||
}
|
||||
|
||||
if (eventType == 0)
|
||||
return NS_OK; //no actural event need to be fired
|
||||
|
||||
docAccessible->FireDocLoadEvents(eventType);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -80,11 +80,11 @@ class nsAccessibleEventData: public nsIAccessibleEvent
|
|||
// e.g., nsAccessibleTextChangeEvent: public nsIAccessibleTextChangeEvent
|
||||
//
|
||||
|
||||
struct AtkStateChange {
|
||||
struct StateChange {
|
||||
PRUint32 state;
|
||||
PRUint32 extState;
|
||||
PRBool enable;
|
||||
AtkStateChange() {
|
||||
StateChange() {
|
||||
state = 0;
|
||||
extState = 0;
|
||||
enable = PR_FALSE;
|
||||
|
|
|
@ -382,7 +382,7 @@ void nsDocAccessible::CheckForEditor()
|
|||
if (editor) {
|
||||
// State readonly is now clear
|
||||
#ifdef MOZ_ACCESSIBILITY_ATK
|
||||
AtkStateChange stateData;
|
||||
StateChange stateData;
|
||||
stateData.enable = PR_TRUE;
|
||||
stateData.state = STATE_READONLY; // Will be translated to ATK_STATE_EDITABLE
|
||||
FireToolkitEvent(nsIAccessibleEvent::EVENT_STATE_CHANGE, this, &stateData);
|
||||
|
@ -622,21 +622,61 @@ nsresult nsDocAccessible::RemoveEventListeners()
|
|||
|
||||
NS_IMETHODIMP nsDocAccessible::FireAnchorJumpEvent()
|
||||
{
|
||||
if (!mIsContentLoaded || !mDocument) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsCOMPtr<nsISupports> container = mDocument->GetContainer();
|
||||
nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(container));
|
||||
nsCAutoString theURL;
|
||||
if (webNav) {
|
||||
nsCOMPtr<nsIURI> pURI;
|
||||
webNav->GetCurrentURI(getter_AddRefs(pURI));
|
||||
if (pURI) {
|
||||
pURI->GetSpec(theURL);
|
||||
}
|
||||
}
|
||||
static nsCAutoString lastAnchor;
|
||||
const char kHash = '#';
|
||||
nsCAutoString currentAnchor;
|
||||
PRInt32 hasPosition = theURL.FindChar(kHash);
|
||||
if (hasPosition > 0 && hasPosition < (PRInt32)theURL.Length() - 1) {
|
||||
mIsAnchor = PR_TRUE;
|
||||
currentAnchor.Assign(Substring(theURL,
|
||||
hasPosition+1,
|
||||
(PRInt32)theURL.Length()-hasPosition-1));
|
||||
}
|
||||
|
||||
if (currentAnchor.Equals(lastAnchor)) {
|
||||
mIsAnchorJumped = PR_FALSE;
|
||||
} else {
|
||||
mIsAnchorJumped = PR_TRUE;
|
||||
lastAnchor.Assign(currentAnchor);
|
||||
}
|
||||
|
||||
if (mIsAnchorJumped) {
|
||||
FireToolkitEvent(nsIAccessibleEvent::EVENT_DOCUMENT_ATTRIBUTES_CHANGED,
|
||||
this, nsnull);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsDocAccessible::FireDocLoadingEvent(PRBool aIsFinished)
|
||||
NS_IMETHODIMP nsDocAccessible::FireDocLoadEvents(PRUint32 aEventType)
|
||||
{
|
||||
if (!mDocument || !mWeakShell) {
|
||||
return NS_OK; // Document has been shut down
|
||||
}
|
||||
|
||||
if (mIsContentLoaded == aIsFinished) {
|
||||
PRBool isFinished =
|
||||
(aEventType == nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE ||
|
||||
aEventType == nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED);
|
||||
|
||||
if (mIsContentLoaded == isFinished) {
|
||||
return NS_OK;
|
||||
}
|
||||
mIsContentLoaded = aIsFinished;
|
||||
mIsContentLoaded = isFinished;
|
||||
|
||||
if (aIsFinished) {
|
||||
if (isFinished) {
|
||||
// Need to wait until scrollable view is available
|
||||
AddScrollListener();
|
||||
nsCOMPtr<nsIAccessible> parent;
|
||||
|
@ -646,8 +686,36 @@ NS_IMETHODIMP nsDocAccessible::FireDocLoadingEvent(PRBool aIsFinished)
|
|||
// Make the parent forget about the old document as a child
|
||||
privateAccessible->InvalidateChildren();
|
||||
}
|
||||
// Use short timer before firing state change event for finished doc,
|
||||
// because the window is made visible asynchronously
|
||||
if (!mDocLoadTimer) {
|
||||
mDocLoadTimer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
}
|
||||
if (mDocLoadTimer) {
|
||||
mDocLoadTimer->InitWithFuncCallback(DocLoadCallback, this, 0,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
//fire EVENT_STATE_CHANGE to clear STATE_BUSY
|
||||
StateChange stateData;
|
||||
stateData.state = STATE_BUSY;
|
||||
stateData.enable = PR_FALSE;
|
||||
FireToolkitEvent(nsIAccessibleEvent::EVENT_STATE_CHANGE, this, &stateData);
|
||||
} else {
|
||||
nsCOMPtr<nsIDocShellTreeItem> treeItem = GetDocShellTreeItemFor(mDOMNode);
|
||||
if (!treeItem) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
|
||||
treeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
|
||||
if (sameTypeRoot != treeItem) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
FireToolkitEvent(nsIAccessibleEvent::EVENT_STATE_CHANGE, this, nsnull);
|
||||
}
|
||||
|
||||
FireToolkitEvent(aEventType, this, nsnull);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -992,7 +1060,7 @@ NS_IMETHODIMP nsDocAccessible::FlushPendingEvents()
|
|||
do_QueryInterface(accessible);
|
||||
NS_ASSERTION(docAccessible, "No doc accessible for doc load event");
|
||||
if (docAccessible) {
|
||||
docAccessible->FireDocLoadingEvent(PR_TRUE);
|
||||
docAccessible->FireDocLoadEvents(nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -1267,3 +1335,52 @@ NS_IMETHODIMP nsDocAccessible::FireToolkitEvent(PRUint32 aEvent, nsIAccessible*
|
|||
return obsService->NotifyObservers(accEvent, NS_ACCESSIBLE_EVENT_TOPIC, nsnull);
|
||||
}
|
||||
|
||||
void nsDocAccessible::DocLoadCallback(nsITimer *aTimer, void *aClosure)
|
||||
{
|
||||
// Doc has finished loading, fire "load finished" event
|
||||
// By using short timer we can wait make the window visible,
|
||||
// which it does asynchronously. This avoids confusing the screen reader with a
|
||||
// hidden window. Waiting also allows us to see of the document has focus,
|
||||
// which is important because we only fire doc loaded events for focused documents.
|
||||
|
||||
nsDocAccessible *docAcc =
|
||||
NS_REINTERPRET_CAST(nsDocAccessible*, aClosure);
|
||||
if (!docAcc) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Fire doc finished event
|
||||
nsCOMPtr<nsIDOMNode> docDomNode;
|
||||
docAcc->GetDOMNode(getter_AddRefs(docDomNode));
|
||||
nsCOMPtr<nsIDocument> doc(do_QueryInterface(docDomNode));
|
||||
if (doc) {
|
||||
nsCOMPtr<nsISupports> container = doc->GetContainer();
|
||||
nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = do_QueryInterface(container);
|
||||
if (!docShellTreeItem) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
|
||||
docShellTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
|
||||
if (sameTypeRoot != docShellTreeItem) {
|
||||
// A frame or iframe has finished loading new content
|
||||
docAcc->InvalidateCacheSubtree(nsnull, nsIAccessibleEvent::EVENT_REORDER);
|
||||
return;
|
||||
}
|
||||
|
||||
// Fire STATE_CHANGE event for doc load finish if focus is in same doc tree
|
||||
if (gLastFocusedNode) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> focusedTreeItem =
|
||||
GetDocShellTreeItemFor(gLastFocusedNode);
|
||||
if (focusedTreeItem) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> sameTypeRootOfFocus;
|
||||
focusedTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRootOfFocus));
|
||||
if (sameTypeRoot == sameTypeRootOfFocus) {
|
||||
docAcc->FireToolkitEvent(nsIAccessibleEvent::EVENT_STATE_CHANGE,
|
||||
docAcc, nsnull);
|
||||
docAcc->FireAnchorJumpEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -122,6 +122,14 @@ class nsDocAccessible : public nsHyperTextAccessible,
|
|||
PRPackedBool mIsContentLoaded;
|
||||
nsCOMArray<nsIAccessibleEvent> mEventsToFire;
|
||||
nsCOMPtr<nsIEditor> mEditor;
|
||||
|
||||
protected:
|
||||
PRBool mIsAnchor;
|
||||
PRBool mIsAnchorJumped;
|
||||
|
||||
private:
|
||||
static void DocLoadCallback(nsITimer *aTimer, void *aClosure);
|
||||
nsCOMPtr<nsITimer> mDocLoadTimer;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -336,36 +336,12 @@ NS_IMETHODIMP nsDocAccessibleWrap::FireAnchorJumpEvent()
|
|||
// the can only relate events back to their internal model if it's a leaf.
|
||||
// There is usually an accessible for the focus node, but if it's an empty text node
|
||||
// we have to move forward in the document to get one
|
||||
if (!mIsContentLoaded || !mDocument) {
|
||||
nsDocAccessible::FireAnchorJumpEvent();
|
||||
if (!mIsAnchorJumped)
|
||||
return NS_OK;
|
||||
}
|
||||
nsCOMPtr<nsISupports> container = mDocument->GetContainer();
|
||||
nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(container));
|
||||
nsCAutoString theURL;
|
||||
if (webNav) {
|
||||
nsCOMPtr<nsIURI> pURI;
|
||||
webNav->GetCurrentURI(getter_AddRefs(pURI));
|
||||
if (pURI) {
|
||||
pURI->GetSpec(theURL);
|
||||
}
|
||||
}
|
||||
const char kHash = '#';
|
||||
PRBool hasAnchor = PR_FALSE;
|
||||
PRInt32 hasPosition = theURL.FindChar(kHash);
|
||||
if (hasPosition > 0 && hasPosition < (PRInt32)theURL.Length() - 1) {
|
||||
hasAnchor = PR_TRUE;
|
||||
}
|
||||
|
||||
// mWasAnchor is set when the previous URL included a named anchor.
|
||||
// This way we still know to fire the EVENT_SCROLLINGSTART event when we
|
||||
// move from a named anchor back to the top.
|
||||
if (!mWasAnchor && !hasAnchor) {
|
||||
return NS_OK;
|
||||
}
|
||||
mWasAnchor = hasAnchor;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> focusNode;
|
||||
if (hasAnchor) {
|
||||
if (mIsAnchor) {
|
||||
nsCOMPtr<nsISelectionController> selCon(do_QueryReferent(mWeakShell));
|
||||
if (!selCon) {
|
||||
return NS_OK;
|
||||
|
@ -390,95 +366,6 @@ NS_IMETHODIMP nsDocAccessibleWrap::FireAnchorJumpEvent()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsDocAccessibleWrap::DocLoadCallback(nsITimer *aTimer, void *aClosure)
|
||||
{
|
||||
// Doc has finished loading, fire "load finished" event
|
||||
// By using short timer we can wait for MS Windows to make the window visible,
|
||||
// which it does asynchronously. This avoids confusing the screen reader with a
|
||||
// hidden window. Waiting also allows us to see of the document has focus,
|
||||
// which is important because we only fire doc loaded events for focused documents.
|
||||
|
||||
nsDocAccessibleWrap *docAcc =
|
||||
NS_REINTERPRET_CAST(nsDocAccessibleWrap*, aClosure);
|
||||
if (!docAcc) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Fire doc finished event
|
||||
nsCOMPtr<nsIDOMNode> docDomNode;
|
||||
docAcc->GetDOMNode(getter_AddRefs(docDomNode));
|
||||
nsCOMPtr<nsIDocument> doc(do_QueryInterface(docDomNode));
|
||||
if (doc) {
|
||||
nsCOMPtr<nsISupports> container = doc->GetContainer();
|
||||
nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = do_QueryInterface(container);
|
||||
if (!docShellTreeItem) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
|
||||
docShellTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
|
||||
if (sameTypeRoot != docShellTreeItem) {
|
||||
// A frame or iframe has finished loading new content
|
||||
docAcc->InvalidateCacheSubtree(nsnull, nsIAccessibleEvent::EVENT_REORDER);
|
||||
return;
|
||||
}
|
||||
|
||||
// Fire STATE_CHANGE event for doc load finish if focus is in same doc tree
|
||||
if (gLastFocusedNode) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> focusedTreeItem =
|
||||
GetDocShellTreeItemFor(gLastFocusedNode);
|
||||
if (focusedTreeItem) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> sameTypeRootOfFocus;
|
||||
focusedTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRootOfFocus));
|
||||
if (sameTypeRoot == sameTypeRootOfFocus) {
|
||||
docAcc->FireToolkitEvent(nsIAccessibleEvent::EVENT_STATE_CHANGE,
|
||||
docAcc, nsnull);
|
||||
docAcc->FireAnchorJumpEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsDocAccessibleWrap::FireDocLoadingEvent(PRBool aIsFinished)
|
||||
{
|
||||
if (!mDocument || !mWeakShell)
|
||||
return NS_OK; // Document has been shut down
|
||||
|
||||
if (mIsContentLoaded == aIsFinished) {
|
||||
return NS_OK; // Already fired the event
|
||||
}
|
||||
|
||||
nsDocAccessible::FireDocLoadingEvent(aIsFinished);
|
||||
|
||||
if (aIsFinished) {
|
||||
// Use short timer before firing state change event for finished doc,
|
||||
// because the window is made visible asynchronously by Microsoft Windows
|
||||
if (!mDocLoadTimer) {
|
||||
mDocLoadTimer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
}
|
||||
if (mDocLoadTimer) {
|
||||
mDocLoadTimer->InitWithFuncCallback(DocLoadCallback, this, 0,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<nsIDocShellTreeItem> treeItem = GetDocShellTreeItemFor(mDOMNode);
|
||||
if (!treeItem) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
|
||||
treeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
|
||||
if (sameTypeRoot != treeItem) {
|
||||
return NS_OK; // We only fire MSAA doc loading events for root content frame
|
||||
}
|
||||
|
||||
FireToolkitEvent(nsIAccessibleEvent::EVENT_STATE_CHANGE, this, nsnull);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP nsDocAccessibleWrap::get_URL(/* [out] */ BSTR __RPC_FAR *aURL)
|
||||
{
|
||||
*aURL = NULL;
|
||||
|
|
|
@ -91,14 +91,10 @@ public:
|
|||
|
||||
NS_IMETHOD Shutdown();
|
||||
NS_IMETHOD FireToolkitEvent(PRUint32 aEvent, nsIAccessible* aAccessible, void* aData);
|
||||
NS_IMETHOD FireDocLoadingEvent(PRBool isFinished);
|
||||
NS_IMETHOD FireAnchorJumpEvent();
|
||||
|
||||
private:
|
||||
static void DocLoadCallback(nsITimer *aTimer, void *aClosure);
|
||||
already_AddRefed<nsIAccessible> GetFirstLeafAccessible(nsIDOMNode *aStartNode);
|
||||
nsCOMPtr<nsITimer> mDocLoadTimer;
|
||||
PRPackedBool mWasAnchor;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче