mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 00:01:50 +00:00
Bug 415069 ARIA alerts triggering events with :system p=aaronleventhal r=ginn.chen a=mtschrep
This commit is contained in:
parent
66d44fb0ab
commit
8fe3f39df3
@ -61,7 +61,7 @@ interface nsIDOMNode;
|
||||
*
|
||||
* @status UNDER_REVIEW
|
||||
*/
|
||||
[scriptable, uuid(98f9e2d4-ec22-4601-b927-b9faf7a63248)]
|
||||
[scriptable, uuid(ba448f0e-a761-48c8-a0f5-1f25e23d4fe4)]
|
||||
interface nsIAccessibleEvent : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -511,7 +511,7 @@ interface nsIAccessibleEvent : nsISupports
|
||||
* Returns true if the event was caused by explicit user input,
|
||||
* as opposed to purely originating from a timer or mouse movement
|
||||
*/
|
||||
readonly attribute boolean isFromUserInput;
|
||||
attribute boolean isFromUserInput;
|
||||
};
|
||||
|
||||
|
||||
|
@ -95,14 +95,14 @@ void nsAccEvent::CaptureIsFromUserInput(PRBool aIsAsynch)
|
||||
return;
|
||||
}
|
||||
|
||||
if (aIsAsynch) {
|
||||
// Cannot calculate, so use previous value
|
||||
gLastEventNodeWeak = eventNode;
|
||||
}
|
||||
else {
|
||||
if (!aIsAsynch) {
|
||||
PrepareForEvent(eventNode);
|
||||
mIsFromUserInput = gLastEventFromUserInput;
|
||||
}
|
||||
|
||||
// For asynch, cannot calculate if from user input.
|
||||
// Don't reset global last input state here, do it
|
||||
// at the end of FlushPendingEvents()
|
||||
|
||||
mIsFromUserInput = gLastEventFromUserInput;
|
||||
}
|
||||
|
||||
@ -113,13 +113,30 @@ nsAccEvent::GetIsFromUserInput(PRBool *aIsFromUserInput)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsAccEvent::PrepareForEvent(nsIAccessibleEvent *aEvent)
|
||||
NS_IMETHODIMP
|
||||
nsAccEvent::SetIsFromUserInput(PRBool aIsFromUserInput)
|
||||
{
|
||||
mIsFromUserInput = aIsFromUserInput;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsAccEvent::PrepareForEvent(nsIAccessibleEvent *aEvent,
|
||||
PRBool aForceIsFromUserInput)
|
||||
{
|
||||
gLastEventFromUserInput = aForceIsFromUserInput;
|
||||
nsCOMPtr<nsIDOMNode> eventNode;
|
||||
aEvent->GetDOMNode(getter_AddRefs(eventNode));
|
||||
PRBool isFromUserInput;
|
||||
aEvent->GetIsFromUserInput(&isFromUserInput);
|
||||
PrepareForEvent(eventNode, isFromUserInput);
|
||||
if (!gLastEventFromUserInput) { // Caller is not forcing user input flag
|
||||
aEvent->GetIsFromUserInput(&gLastEventFromUserInput);
|
||||
if (!gLastEventFromUserInput) {
|
||||
// Event does not have user input flag set to true
|
||||
// One more try -- check to see if we are currently responding to user input
|
||||
PrepareForEvent(eventNode);
|
||||
}
|
||||
}
|
||||
gLastEventNodeWeak = eventNode;
|
||||
// Make sure this event remembers whether it is from user input
|
||||
aEvent->SetIsFromUserInput(gLastEventFromUserInput);
|
||||
}
|
||||
|
||||
void nsAccEvent::PrepareForEvent(nsIDOMNode *aEventNode,
|
||||
@ -154,7 +171,7 @@ void nsAccEvent::PrepareForEvent(nsIDOMNode *aEventNode,
|
||||
|
||||
nsIEventStateManager *esm = presShell->GetPresContext()->EventStateManager();
|
||||
if (!esm) {
|
||||
NS_NOTREACHED("Threre should always be an ESM for an event");
|
||||
NS_NOTREACHED("There should always be an ESM for an event");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -81,11 +81,17 @@ private:
|
||||
static nsIDOMNode* gLastEventNodeWeak;
|
||||
|
||||
public:
|
||||
static void ResetLastInputState()
|
||||
{gLastEventFromUserInput = PR_FALSE; gLastEventNodeWeak = nsnull; }
|
||||
|
||||
/**
|
||||
* Find and cache the last input state. This will be called automatically
|
||||
* for synchronous events. For asynchronous events it should be
|
||||
* called from the synchronous code which is the true source of the event,
|
||||
* before the event is fired.
|
||||
* @param aChangeNode that event will be on
|
||||
* @param aForceIsFromUserInput PR_TRUE if the caller knows that this event was
|
||||
* caused by user input
|
||||
*/
|
||||
static void PrepareForEvent(nsIDOMNode *aChangeNode,
|
||||
PRBool aForceIsFromUserInput = PR_FALSE);
|
||||
@ -95,7 +101,8 @@ public:
|
||||
* so use that state now -- call this when about to flush an event that
|
||||
* was waiting in an event queue
|
||||
*/
|
||||
static void PrepareForEvent(nsIAccessibleEvent *aEvent);
|
||||
static void PrepareForEvent(nsIAccessibleEvent *aEvent,
|
||||
PRBool aForceIsFromUserInput = PR_FALSE);
|
||||
};
|
||||
|
||||
class nsAccStateChangeEvent: public nsAccEvent,
|
||||
|
@ -1389,16 +1389,15 @@ nsresult nsDocAccessible::FireDelayedToolkitEvent(PRUint32 aEvent,
|
||||
PRBool aIsAsynch)
|
||||
{
|
||||
nsCOMPtr<nsIAccessibleEvent> event =
|
||||
new nsAccEvent(aEvent, aDOMNode, PR_TRUE);
|
||||
new nsAccEvent(aEvent, aDOMNode, aIsAsynch);
|
||||
NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
return FireDelayedAccessibleEvent(event, aAllowDupes, aIsAsynch);
|
||||
return FireDelayedAccessibleEvent(event, aAllowDupes);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocAccessible::FireDelayedAccessibleEvent(nsIAccessibleEvent *aEvent,
|
||||
EDupeEventRule aAllowDupes,
|
||||
PRBool aIsAsynch)
|
||||
EDupeEventRule aAllowDupes)
|
||||
{
|
||||
NS_ENSURE_TRUE(aEvent, NS_ERROR_FAILURE);
|
||||
|
||||
@ -1416,13 +1415,6 @@ nsDocAccessible::FireDelayedAccessibleEvent(nsIAccessibleEvent *aEvent,
|
||||
nsCOMPtr<nsIDOMNode> newEventDOMNode;
|
||||
aEvent->GetDOMNode(getter_AddRefs(newEventDOMNode));
|
||||
|
||||
if (!aIsAsynch) {
|
||||
// If already asynchronous don't call PrepareFromEvent() -- it
|
||||
// should only be called while ESM still knows if the event occurred
|
||||
// originally because of user input
|
||||
nsAccEvent::PrepareForEvent(newEventDOMNode);
|
||||
}
|
||||
|
||||
if (numQueuedEvents == 0) {
|
||||
isTimerStarted = PR_FALSE;
|
||||
} else if (aAllowDupes == eCoalesceFromSameSubtree) {
|
||||
@ -1566,9 +1558,7 @@ NS_IMETHODIMP nsDocAccessible::FlushPendingEvents()
|
||||
nsCOMPtr<nsIAccessibleTextChangeEvent> textChangeEvent =
|
||||
CreateTextChangeEventForNode(containerAccessible, domNode, accessible, PR_TRUE, PR_TRUE);
|
||||
if (textChangeEvent) {
|
||||
nsCOMPtr<nsIDOMNode> hyperTextNode;
|
||||
textChangeEvent->GetDOMNode(getter_AddRefs(hyperTextNode));
|
||||
nsAccEvent::PrepareForEvent(hyperTextNode, isFromUserInput);
|
||||
nsAccEvent::PrepareForEvent(textChangeEvent, isFromUserInput);
|
||||
// XXX Queue them up and merge the text change events
|
||||
// XXX We need a way to ignore SplitNode and JoinNode() when they
|
||||
// do not affect the text within the hypertext
|
||||
@ -1640,6 +1630,10 @@ NS_IMETHODIMP nsDocAccessible::FlushPendingEvents()
|
||||
}
|
||||
mEventsToFire.Clear(); // Clear out array
|
||||
NS_RELEASE_THIS(); // Release kung fu death grip
|
||||
|
||||
// After a flood of events, reset so that user input flag is off
|
||||
nsAccEvent::ResetLastInputState();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1964,9 +1958,9 @@ NS_IMETHODIMP nsDocAccessible::InvalidateCacheSubtree(nsIContent *aChild,
|
||||
// from SHOW and HIDE so that they don't fetch extra objects
|
||||
if (childAccessible) {
|
||||
nsCOMPtr<nsIAccessibleEvent> reorderEvent =
|
||||
new nsAccEvent(nsIAccessibleEvent::EVENT_REORDER, containerAccessible, PR_TRUE);
|
||||
new nsAccEvent(nsIAccessibleEvent::EVENT_REORDER, containerAccessible, isAsynch);
|
||||
NS_ENSURE_TRUE(reorderEvent, NS_ERROR_OUT_OF_MEMORY);
|
||||
FireDelayedAccessibleEvent(reorderEvent, eCoalesceFromSameSubtree, isAsynch);
|
||||
FireDelayedAccessibleEvent(reorderEvent, eCoalesceFromSameSubtree);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2045,10 +2039,10 @@ nsDocAccessible::FireShowHideEvents(nsIDOMNode *aDOMNode, PRBool aAvoidOnThisNod
|
||||
new nsAccEvent(aEventType, accessible, isAsynch);
|
||||
NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
|
||||
if (aForceIsFromUserInput) {
|
||||
nsAccEvent::PrepareForEvent(aDOMNode, aForceIsFromUserInput);
|
||||
nsAccEvent::PrepareForEvent(event, aForceIsFromUserInput);
|
||||
}
|
||||
if (aDelay) {
|
||||
return FireDelayedAccessibleEvent(event, eCoalesceFromSameSubtree, isAsynch);
|
||||
return FireDelayedAccessibleEvent(event, eCoalesceFromSameSubtree);
|
||||
}
|
||||
return FireAccessibleEvent(event);
|
||||
}
|
||||
|
@ -114,8 +114,8 @@ class nsDocAccessible : public nsHyperTextAccessibleWrap,
|
||||
* eRemoveDupes (default): events of the same type are discarded
|
||||
* (the last one is used)
|
||||
*
|
||||
* @param aIsAsyn - set to PR_TRUE if this is not being called from code
|
||||
* synchronous with a DOM event
|
||||
* @param aIsAsynch - set to PR_TRUE if this is not being called from code
|
||||
* synchronous with a DOM event
|
||||
*/
|
||||
nsresult FireDelayedToolkitEvent(PRUint32 aEvent, nsIDOMNode *aDOMNode,
|
||||
EDupeEventRule aAllowDupes = eRemoveDupes,
|
||||
@ -128,12 +128,9 @@ class nsDocAccessible : public nsHyperTextAccessibleWrap,
|
||||
* @param aAllowDupes - if false then delayed events of the same type and
|
||||
* for the same DOM node in the event queue won't
|
||||
* be fired.
|
||||
* @param aIsAsych - set to PR_TRUE if this is being called from
|
||||
* an event asynchronous with the DOM
|
||||
*/
|
||||
nsresult FireDelayedAccessibleEvent(nsIAccessibleEvent *aEvent,
|
||||
EDupeEventRule aAllowDupes = eRemoveDupes,
|
||||
PRBool aIsAsynch = PR_FALSE);
|
||||
EDupeEventRule aAllowDupes = eRemoveDupes);
|
||||
|
||||
void ShutdownChildDocuments(nsIDocShellTreeItem *aStart);
|
||||
|
||||
|
@ -519,7 +519,7 @@ PRBool nsRootAccessible::FireAccessibleFocusEvent(nsIAccessible *aAccessible,
|
||||
nsCOMPtr<nsIAccessibleEvent> menuEndEvent =
|
||||
new nsAccEvent(nsIAccessibleEvent::EVENT_MENU_END, mCurrentARIAMenubar, PR_FALSE);
|
||||
if (menuEndEvent) {
|
||||
FireDelayedAccessibleEvent(menuEndEvent, eAllowDupes, PR_FALSE);
|
||||
FireDelayedAccessibleEvent(menuEndEvent, eAllowDupes);
|
||||
}
|
||||
mCurrentARIAMenubar = nsnull;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user