зеркало из https://github.com/mozilla/gecko-dev.git
Bug 678454 - coalesce events by accessible tree, r=tbsaunde
This commit is contained in:
Родитель
8cc35a7931
Коммит
334ae7f032
|
@ -35,47 +35,9 @@ AccEvent::AccEvent(uint32_t aEventType, Accessible* aAccessible,
|
|||
CaptureIsFromUserInput(aIsFromUserInput);
|
||||
}
|
||||
|
||||
AccEvent::AccEvent(uint32_t aEventType, nsINode* aNode,
|
||||
EIsFromUserInput aIsFromUserInput, EEventRule aEventRule) :
|
||||
mEventType(aEventType), mEventRule(aEventRule), mNode(aNode)
|
||||
{
|
||||
CaptureIsFromUserInput(aIsFromUserInput);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// AccEvent public methods
|
||||
|
||||
Accessible*
|
||||
AccEvent::GetAccessible()
|
||||
{
|
||||
if (!mAccessible)
|
||||
mAccessible = GetAccessibleForNode();
|
||||
|
||||
return mAccessible;
|
||||
}
|
||||
|
||||
nsINode*
|
||||
AccEvent::GetNode()
|
||||
{
|
||||
if (!mNode && mAccessible)
|
||||
mNode = mAccessible->GetNode();
|
||||
|
||||
return mNode;
|
||||
}
|
||||
|
||||
DocAccessible*
|
||||
AccEvent::GetDocAccessible()
|
||||
{
|
||||
if (mAccessible)
|
||||
return mAccessible->Document();
|
||||
|
||||
nsINode* node = GetNode();
|
||||
if (node)
|
||||
return GetAccService()->GetDocAccessible(node->OwnerDoc());
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
already_AddRefed<nsAccEvent>
|
||||
AccEvent::CreateXPCOMObject()
|
||||
{
|
||||
|
@ -104,56 +66,23 @@ NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AccEvent, Release)
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// AccEvent protected methods
|
||||
|
||||
Accessible*
|
||||
AccEvent::GetAccessibleForNode() const
|
||||
{
|
||||
if (mNode) {
|
||||
DocAccessible* document =
|
||||
GetAccService()->GetDocAccessible(mNode->OwnerDoc());
|
||||
if (document)
|
||||
return document->GetAccessible(mNode);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
AccEvent::CaptureIsFromUserInput(EIsFromUserInput aIsFromUserInput)
|
||||
{
|
||||
nsINode *targetNode = GetNode();
|
||||
|
||||
#ifdef DEBUG
|
||||
if (!targetNode) {
|
||||
// XXX: remove this hack during reorganization of 506907. Meanwhile we
|
||||
// want to get rid an assertion for application accessible events which
|
||||
// don't have DOM node (see bug 506206).
|
||||
|
||||
if (mAccessible != static_cast<nsIAccessible*>(ApplicationAcc()))
|
||||
NS_ASSERTION(targetNode, "There should always be a DOM node for an event");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (aIsFromUserInput != eAutoDetect) {
|
||||
mIsFromUserInput = aIsFromUserInput == eFromUserInput ? true : false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!targetNode)
|
||||
return;
|
||||
|
||||
nsIPresShell *presShell = nsCoreUtils::GetPresShellFor(targetNode);
|
||||
if (!presShell) {
|
||||
NS_NOTREACHED("Threre should always be an pres shell for an event");
|
||||
DocAccessible* document = mAccessible->Document();
|
||||
if (!document) {
|
||||
NS_ASSERTION(mAccessible == ApplicationAcc(),
|
||||
"Accessible other than application should always have a doc!");
|
||||
return;
|
||||
}
|
||||
|
||||
nsEventStateManager *esm = presShell->GetPresContext()->EventStateManager();
|
||||
if (!esm) {
|
||||
NS_NOTREACHED("There should always be an ESM for an event");
|
||||
return;
|
||||
}
|
||||
|
||||
mIsFromUserInput = esm->IsHandlingUserInputExternal();
|
||||
mIsFromUserInput =
|
||||
document->PresContext()->EventStateManager()->IsHandlingUserInputExternal();
|
||||
}
|
||||
|
||||
|
||||
|
@ -161,39 +90,6 @@ AccEvent::CaptureIsFromUserInput(EIsFromUserInput aIsFromUserInput)
|
|||
// AccStateChangeEvent
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Note: we pass in eAllowDupes to the base class because we don't currently
|
||||
// support correct state change coalescence (XXX Bug 569356). Also we need to
|
||||
// decide how to coalesce events created via accessible (instead of node).
|
||||
AccStateChangeEvent::
|
||||
AccStateChangeEvent(Accessible* aAccessible, uint64_t aState,
|
||||
bool aIsEnabled, EIsFromUserInput aIsFromUserInput):
|
||||
AccEvent(nsIAccessibleEvent::EVENT_STATE_CHANGE, aAccessible,
|
||||
aIsFromUserInput, eAllowDupes),
|
||||
mState(aState), mIsEnabled(aIsEnabled)
|
||||
{
|
||||
}
|
||||
|
||||
AccStateChangeEvent::
|
||||
AccStateChangeEvent(nsINode* aNode, uint64_t aState, bool aIsEnabled):
|
||||
AccEvent(::nsIAccessibleEvent::EVENT_STATE_CHANGE, aNode,
|
||||
eAutoDetect, eAllowDupes),
|
||||
mState(aState), mIsEnabled(aIsEnabled)
|
||||
{
|
||||
}
|
||||
|
||||
AccStateChangeEvent::
|
||||
AccStateChangeEvent(nsINode* aNode, uint64_t aState) :
|
||||
AccEvent(::nsIAccessibleEvent::EVENT_STATE_CHANGE, aNode,
|
||||
eAutoDetect, eAllowDupes),
|
||||
mState(aState)
|
||||
{
|
||||
// Use GetAccessibleForNode() because we do not want to store an accessible
|
||||
// since it leads to problems with delayed events in the case when
|
||||
// an accessible gets reorder event before delayed event is processed.
|
||||
Accessible* accessible = GetAccessibleForNode();
|
||||
mIsEnabled = accessible && ((accessible->State() & mState) != 0);
|
||||
}
|
||||
|
||||
already_AddRefed<nsAccEvent>
|
||||
AccStateChangeEvent::CreateXPCOMObject()
|
||||
{
|
||||
|
@ -296,20 +192,6 @@ AccShowEvent::
|
|||
// AccCaretMoveEvent
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AccCaretMoveEvent::
|
||||
AccCaretMoveEvent(Accessible* aAccessible, int32_t aCaretOffset) :
|
||||
AccEvent(::nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED, aAccessible),
|
||||
mCaretOffset(aCaretOffset)
|
||||
{
|
||||
}
|
||||
|
||||
AccCaretMoveEvent::
|
||||
AccCaretMoveEvent(nsINode* aNode) :
|
||||
AccEvent(::nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED, aNode),
|
||||
mCaretOffset(-1)
|
||||
{
|
||||
}
|
||||
|
||||
already_AddRefed<nsAccEvent>
|
||||
AccCaretMoveEvent::CreateXPCOMObject()
|
||||
{
|
||||
|
|
|
@ -38,17 +38,18 @@ public:
|
|||
// Rule for accessible events.
|
||||
// The rule will be applied when flushing pending events.
|
||||
enum EEventRule {
|
||||
// eAllowDupes : More than one event of the same type is allowed.
|
||||
// This event will always be emitted.
|
||||
eAllowDupes,
|
||||
// eAllowDupes : More than one event of the same type is allowed.
|
||||
// This event will always be emitted. This flag is used for events that
|
||||
// don't support coalescence.
|
||||
eAllowDupes,
|
||||
|
||||
// eCoalesceReorder : For reorder events from the same subtree or the same
|
||||
// node, only the umbrella event on the ancestor will be emitted.
|
||||
eCoalesceReorder,
|
||||
eCoalesceReorder,
|
||||
|
||||
// eCoalesceMutationTextChange : coalesce text change events caused by
|
||||
// tree mutations of the same tree level.
|
||||
eCoalesceMutationTextChange,
|
||||
eCoalesceMutationTextChange,
|
||||
|
||||
// eCoalesceOfSameType : For events of the same type, only the newest event
|
||||
// will be processed.
|
||||
|
@ -59,20 +60,16 @@ public:
|
|||
|
||||
// eRemoveDupes : For repeat events, only the newest event in queue
|
||||
// will be emitted.
|
||||
eRemoveDupes,
|
||||
eRemoveDupes,
|
||||
|
||||
// eDoNotEmit : This event is confirmed as a duplicate, do not emit it.
|
||||
eDoNotEmit
|
||||
eDoNotEmit
|
||||
};
|
||||
|
||||
// Initialize with an nsIAccessible
|
||||
AccEvent(uint32_t aEventType, Accessible* aAccessible,
|
||||
EIsFromUserInput aIsFromUserInput = eAutoDetect,
|
||||
EEventRule aEventRule = eRemoveDupes);
|
||||
// Initialize with an nsINode
|
||||
AccEvent(uint32_t aEventType, nsINode* aNode,
|
||||
EIsFromUserInput aIsFromUserInput = eAutoDetect,
|
||||
EEventRule aEventRule = eRemoveDupes);
|
||||
virtual ~AccEvent() {}
|
||||
|
||||
// AccEvent
|
||||
|
@ -80,9 +77,8 @@ public:
|
|||
EEventRule GetEventRule() const { return mEventRule; }
|
||||
bool IsFromUserInput() const { return mIsFromUserInput; }
|
||||
|
||||
Accessible* GetAccessible();
|
||||
DocAccessible* GetDocAccessible();
|
||||
nsINode* GetNode();
|
||||
Accessible* GetAccessible() const { return mAccessible; }
|
||||
DocAccessible* GetDocAccessible() const { return mAccessible->Document(); }
|
||||
|
||||
/**
|
||||
* Create and return an XPCOM object for accessible event object.
|
||||
|
@ -119,10 +115,6 @@ public:
|
|||
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(AccEvent)
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Get an accessible from event target node.
|
||||
*/
|
||||
Accessible* GetAccessibleForNode() const;
|
||||
|
||||
/**
|
||||
* Determine whether the event is from user input by event state manager if
|
||||
|
@ -134,7 +126,6 @@ protected:
|
|||
uint32_t mEventType;
|
||||
EEventRule mEventRule;
|
||||
nsRefPtr<Accessible> mAccessible;
|
||||
nsCOMPtr<nsINode> mNode;
|
||||
|
||||
friend class NotificationController;
|
||||
friend class AccReorderEvent;
|
||||
|
@ -149,11 +140,15 @@ class AccStateChangeEvent: public AccEvent
|
|||
public:
|
||||
AccStateChangeEvent(Accessible* aAccessible, uint64_t aState,
|
||||
bool aIsEnabled,
|
||||
EIsFromUserInput aIsFromUserInput = eAutoDetect);
|
||||
EIsFromUserInput aIsFromUserInput = eAutoDetect) :
|
||||
AccEvent(nsIAccessibleEvent::EVENT_STATE_CHANGE, aAccessible,
|
||||
aIsFromUserInput, eAllowDupes),
|
||||
mState(aState), mIsEnabled(aIsEnabled) { }
|
||||
|
||||
AccStateChangeEvent(nsINode* aNode, uint64_t aState, bool aIsEnabled);
|
||||
|
||||
AccStateChangeEvent(nsINode* aNode, uint64_t aState);
|
||||
AccStateChangeEvent(Accessible* aAccessible, uint64_t aState) :
|
||||
AccEvent(::nsIAccessibleEvent::EVENT_STATE_CHANGE, aAccessible,
|
||||
eAutoDetect, eAllowDupes), mState(aState)
|
||||
{ mIsEnabled = (mAccessible->State() & mState) != 0; }
|
||||
|
||||
// AccEvent
|
||||
virtual already_AddRefed<nsAccEvent> CreateXPCOMObject();
|
||||
|
@ -239,6 +234,7 @@ public:
|
|||
bool IsHide() const { return mEventType == nsIAccessibleEvent::EVENT_HIDE; }
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsINode> mNode;
|
||||
nsRefPtr<Accessible> mParent;
|
||||
nsRefPtr<AccTextChangeEvent> mTextChangeEvent;
|
||||
|
||||
|
@ -350,8 +346,10 @@ protected:
|
|||
class AccCaretMoveEvent: public AccEvent
|
||||
{
|
||||
public:
|
||||
AccCaretMoveEvent(Accessible* aAccessible, int32_t aCaretOffset);
|
||||
AccCaretMoveEvent(nsINode* aNode);
|
||||
AccCaretMoveEvent(Accessible* aAccessible) :
|
||||
AccEvent(::nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED, aAccessible),
|
||||
mCaretOffset(-1) { }
|
||||
virtual ~AccCaretMoveEvent() { }
|
||||
|
||||
// AccEvent
|
||||
virtual already_AddRefed<nsAccEvent> CreateXPCOMObject();
|
||||
|
@ -367,6 +365,8 @@ public:
|
|||
|
||||
private:
|
||||
int32_t mCaretOffset;
|
||||
|
||||
friend class NotificationController;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -219,7 +219,7 @@ FocusManager::DispatchFocusEvent(DocAccessible* aDocument,
|
|||
nsRefPtr<AccEvent> event =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_FOCUS, aTarget,
|
||||
eAutoDetect, AccEvent::eCoalesceOfSameType);
|
||||
aDocument->FireDelayedAccessibleEvent(event);
|
||||
aDocument->FireDelayedEvent(event);
|
||||
|
||||
#ifdef A11Y_LOG
|
||||
if (logging::IsEnabled(logging::eFocus))
|
||||
|
|
|
@ -471,12 +471,9 @@ logging::DocLoadEventHandled(AccEvent* aEvent)
|
|||
|
||||
MsgBegin(sDocEventTitle, "handled '%s' event", strEventType.get());
|
||||
|
||||
nsINode* node = aEvent->GetNode();
|
||||
if (node->IsNodeOfType(nsINode::eDOCUMENT)) {
|
||||
nsIDocument* documentNode = static_cast<nsIDocument*>(node);
|
||||
DocAccessible* document = aEvent->GetDocAccessible();
|
||||
LogDocInfo(documentNode, document);
|
||||
}
|
||||
DocAccessible* document = aEvent->GetAccessible()->AsDoc();
|
||||
if (document)
|
||||
LogDocInfo(document->DocumentNode(), document);
|
||||
|
||||
MsgEnd();
|
||||
}
|
||||
|
|
|
@ -385,7 +385,7 @@ NotificationController::CoalesceEvents()
|
|||
AccEvent* accEvent = mEvents[index];
|
||||
if (accEvent->mEventType == tailEvent->mEventType &&
|
||||
accEvent->mEventRule == tailEvent->mEventRule &&
|
||||
accEvent->mNode == tailEvent->mNode) {
|
||||
accEvent->mAccessible == tailEvent->mAccessible) {
|
||||
tailEvent->mEventRule = AccEvent::eDoNotEmit;
|
||||
return;
|
||||
}
|
||||
|
@ -705,12 +705,11 @@ NotificationController::ProcessEventQueue()
|
|||
|
||||
// Dispatch caret moved and text selection change events.
|
||||
if (event->mEventType == nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED) {
|
||||
AccCaretMoveEvent* caretMoveEvent = downcast_accEvent(event);
|
||||
HyperTextAccessible* hyperText = target->AsHyperText();
|
||||
int32_t caretOffset = -1;
|
||||
if (hyperText &&
|
||||
NS_SUCCEEDED(hyperText->GetCaretOffset(&caretOffset))) {
|
||||
nsRefPtr<AccEvent> caretMoveEvent =
|
||||
new AccCaretMoveEvent(hyperText, caretOffset);
|
||||
NS_SUCCEEDED(hyperText->GetCaretOffset(&caretMoveEvent->mCaretOffset))) {
|
||||
|
||||
nsEventShell::FireEvent(caretMoveEvent);
|
||||
|
||||
// There's a selection so fire selection change as well.
|
||||
|
|
|
@ -78,7 +78,7 @@ private:
|
|||
|
||||
Class* mInstance;
|
||||
Callback mCallback;
|
||||
nsCOMPtr<Arg> mArg;
|
||||
nsRefPtr<Arg> mArg;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -82,14 +82,14 @@ TextUpdater::DoUpdate(const nsAString& aNewText, const nsAString& aOldText,
|
|||
// Fire text change event for removal.
|
||||
nsRefPtr<AccEvent> textRemoveEvent =
|
||||
new AccTextChangeEvent(mHyperText, mTextOffset, str1, false);
|
||||
mDocument->FireDelayedAccessibleEvent(textRemoveEvent);
|
||||
mDocument->FireDelayedEvent(textRemoveEvent);
|
||||
}
|
||||
|
||||
if (strLen2 > 0) {
|
||||
// Fire text change event for insertion.
|
||||
nsRefPtr<AccEvent> textInsertEvent =
|
||||
new AccTextChangeEvent(mHyperText, mTextOffset, str2, true);
|
||||
mDocument->FireDelayedAccessibleEvent(textInsertEvent);
|
||||
mDocument->FireDelayedEvent(textInsertEvent);
|
||||
}
|
||||
|
||||
mDocument->MaybeNotifyOfValueChange(mHyperText);
|
||||
|
@ -135,7 +135,7 @@ TextUpdater::DoUpdate(const nsAString& aNewText, const nsAString& aOldText,
|
|||
|
||||
// Fire events.
|
||||
for (int32_t idx = events.Length() - 1; idx >= 0; idx--)
|
||||
mDocument->FireDelayedAccessibleEvent(events[idx]);
|
||||
mDocument->FireDelayedEvent(events[idx]);
|
||||
|
||||
mDocument->MaybeNotifyOfValueChange(mHyperText);
|
||||
|
||||
|
|
|
@ -400,9 +400,8 @@ nsAccDocManager::CreateDocOrRootAccessible(nsIDocument* aDocument)
|
|||
// the same document.
|
||||
// Note: don't use AccReorderEvent to avoid coalsecense and special reorder
|
||||
// events processing.
|
||||
nsRefPtr<AccEvent> reorderEvent =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_REORDER, ApplicationAcc());
|
||||
docAcc->FireDelayedAccessibleEvent(reorderEvent);
|
||||
docAcc->FireDelayedEvent(nsIAccessibleEvent::EVENT_REORDER,
|
||||
ApplicationAcc());
|
||||
|
||||
} else {
|
||||
parentDocAcc->BindChildDocument(docAcc);
|
||||
|
|
|
@ -243,10 +243,8 @@ nsCaretAccessible::NormalSelectionChanged(nsISelection* aSelection)
|
|||
mLastCaretOffset = caretOffset;
|
||||
mLastTextAccessible = textAcc;
|
||||
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccCaretMoveEvent(mLastTextAccessible->GetNode());
|
||||
if (event)
|
||||
mLastTextAccessible->Document()->FireDelayedAccessibleEvent(event);
|
||||
nsRefPtr<AccEvent> event = new AccCaretMoveEvent(mLastTextAccessible);
|
||||
mLastTextAccessible->Document()->FireDelayedEvent(event);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -258,15 +256,13 @@ nsCaretAccessible::SpellcheckSelectionChanged(nsISelection* aSelection)
|
|||
// misspelled word). If spellchecking is disabled (for example,
|
||||
// @spellcheck="false" on html:body) then we won't fire any event.
|
||||
|
||||
HyperTextAccessible* textAcc =
|
||||
HyperTextAccessible* hyperText =
|
||||
nsAccUtils::GetTextAccessibleFromSelection(aSelection);
|
||||
if (!textAcc)
|
||||
return;
|
||||
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_TEXT_ATTRIBUTE_CHANGED, textAcc);
|
||||
if (event)
|
||||
textAcc->Document()->FireDelayedAccessibleEvent(event);
|
||||
if (hyperText) {
|
||||
hyperText->Document()->
|
||||
FireDelayedEvent(nsIAccessibleEvent::EVENT_TEXT_ATTRIBUTE_CHANGED,
|
||||
hyperText);
|
||||
}
|
||||
}
|
||||
|
||||
nsIntRect
|
||||
|
|
|
@ -22,7 +22,7 @@ nsEventShell::FireEvent(AccEvent* aEvent)
|
|||
Accessible* accessible = aEvent->GetAccessible();
|
||||
NS_ENSURE_TRUE_VOID(accessible);
|
||||
|
||||
nsINode* node = aEvent->GetNode();
|
||||
nsINode* node = accessible->GetNode();
|
||||
if (node) {
|
||||
sEventTargetNode = node;
|
||||
sEventFromUserInput = aEvent->IsFromUserInput();
|
||||
|
|
|
@ -12,9 +12,31 @@
|
|||
#include "NotificationController.h"
|
||||
#include "States.h"
|
||||
|
||||
#ifdef A11Y_LOG
|
||||
#include "Logging.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
inline void
|
||||
DocAccessible::FireDelayedEvent(AccEvent* aEvent)
|
||||
{
|
||||
#ifdef A11Y_LOG
|
||||
if (logging::IsEnabled(logging::eDocLoad))
|
||||
logging::DocLoadEventFired(aEvent);
|
||||
#endif
|
||||
|
||||
mNotificationController->QueueEvent(aEvent);
|
||||
}
|
||||
|
||||
inline void
|
||||
DocAccessible::FireDelayedEvent(uint32_t aEventType, Accessible* aTarget)
|
||||
{
|
||||
nsRefPtr<AccEvent> event = new AccEvent(aEventType, aTarget);
|
||||
FireDelayedEvent(event);
|
||||
}
|
||||
|
||||
inline void
|
||||
DocAccessible::BindChildDocument(DocAccessible* aDocument)
|
||||
{
|
||||
|
@ -54,20 +76,16 @@ DocAccessible::NotifyOfLoad(uint32_t aLoadEventType)
|
|||
if (HasLoadState(eCompletelyLoaded) && IsLoadEventTarget()) {
|
||||
nsRefPtr<AccEvent> stateEvent =
|
||||
new AccStateChangeEvent(this, states::BUSY, false);
|
||||
FireDelayedAccessibleEvent(stateEvent);
|
||||
FireDelayedEvent(stateEvent);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
DocAccessible::MaybeNotifyOfValueChange(Accessible* aAccessible)
|
||||
{
|
||||
mozilla::a11y::role role = aAccessible->Role();
|
||||
if (role == roles::ENTRY || role == roles::COMBOBOX) {
|
||||
nsRefPtr<AccEvent> valueChangeEvent =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE, aAccessible,
|
||||
eAutoDetect, AccEvent::eRemoveDupes);
|
||||
FireDelayedAccessibleEvent(valueChangeEvent);
|
||||
}
|
||||
a11y::role role = aAccessible->Role();
|
||||
if (role == roles::ENTRY || role == roles::COMBOBOX)
|
||||
FireDelayedEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE, aAccessible);
|
||||
}
|
||||
|
||||
} // namespace a11y
|
||||
|
|
|
@ -44,10 +44,6 @@
|
|||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
||||
#ifdef A11Y_LOG
|
||||
#include "Logging.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
#include "nsIXULDocument.h"
|
||||
#endif
|
||||
|
@ -892,7 +888,7 @@ DocAccessible::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
// about this exceptional case.
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccStateChangeEvent(this, states::EDITABLE, true);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
FireDelayedEvent(event);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -987,7 +983,7 @@ DocAccessible::AttributeChanged(nsIDocument* aDocument,
|
|||
|
||||
// Fire accessible events iff there's an accessible, otherwise we consider
|
||||
// the accessible state wasn't changed, i.e. its state is initial state.
|
||||
AttributeChangedImpl(aElement, aNameSpaceID, aAttribute);
|
||||
AttributeChangedImpl(accessible, aNameSpaceID, aAttribute);
|
||||
|
||||
// Update dependent IDs cache. Take care of accessible elements because no
|
||||
// accessible element means either the element is not accessible at all or
|
||||
|
@ -1002,7 +998,8 @@ DocAccessible::AttributeChanged(nsIDocument* aDocument,
|
|||
|
||||
// DocAccessible protected member
|
||||
void
|
||||
DocAccessible::AttributeChangedImpl(nsIContent* aContent, int32_t aNameSpaceID, nsIAtom* aAttribute)
|
||||
DocAccessible::AttributeChangedImpl(Accessible* aAccessible,
|
||||
int32_t aNameSpaceID, nsIAtom* aAttribute)
|
||||
{
|
||||
// Fire accessible event after short timer, because we need to wait for
|
||||
// DOM attribute & resulting layout to actually change. Otherwise,
|
||||
|
@ -1033,14 +1030,12 @@ DocAccessible::AttributeChangedImpl(nsIContent* aContent, int32_t aNameSpaceID,
|
|||
// ARIA's aria-disabled does not affect the disabled state bit.
|
||||
|
||||
nsRefPtr<AccEvent> enabledChangeEvent =
|
||||
new AccStateChangeEvent(aContent, states::ENABLED);
|
||||
|
||||
FireDelayedAccessibleEvent(enabledChangeEvent);
|
||||
new AccStateChangeEvent(aAccessible, states::ENABLED);
|
||||
FireDelayedEvent(enabledChangeEvent);
|
||||
|
||||
nsRefPtr<AccEvent> sensitiveChangeEvent =
|
||||
new AccStateChangeEvent(aContent, states::SENSITIVE);
|
||||
|
||||
FireDelayedAccessibleEvent(sensitiveChangeEvent);
|
||||
new AccStateChangeEvent(aAccessible, states::SENSITIVE);
|
||||
FireDelayedEvent(sensitiveChangeEvent);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1049,7 +1044,7 @@ DocAccessible::AttributeChangedImpl(nsIContent* aContent, int32_t aNameSpaceID,
|
|||
// Check for hyphenated aria-foo property?
|
||||
if (StringBeginsWith(nsDependentAtomString(aAttribute),
|
||||
NS_LITERAL_STRING("aria-"))) {
|
||||
ARIAAttributeChanged(aContent, aAttribute);
|
||||
ARIAAttributeChanged(aAccessible, aAttribute);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1057,75 +1052,69 @@ DocAccessible::AttributeChangedImpl(nsIContent* aContent, int32_t aNameSpaceID,
|
|||
aAttribute == nsGkAtoms::title ||
|
||||
aAttribute == nsGkAtoms::aria_label ||
|
||||
aAttribute == nsGkAtoms::aria_labelledby) {
|
||||
FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE,
|
||||
aContent);
|
||||
FireDelayedEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE, aAccessible);
|
||||
return;
|
||||
}
|
||||
|
||||
if (aAttribute == nsGkAtoms::aria_busy) {
|
||||
bool isOn = aContent->AttrValueIs(aNameSpaceID, aAttribute,
|
||||
nsGkAtoms::_true, eCaseMatters);
|
||||
nsRefPtr<AccEvent> event = new AccStateChangeEvent(aContent, states::BUSY, isOn);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
bool isOn = aAccessible->GetContent()->
|
||||
AttrValueIs(aNameSpaceID, aAttribute, nsGkAtoms::_true, eCaseMatters);
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccStateChangeEvent(aAccessible, states::BUSY, isOn);
|
||||
FireDelayedEvent(event);
|
||||
return;
|
||||
}
|
||||
|
||||
// ARIA or XUL selection
|
||||
if ((aContent->IsXUL() && aAttribute == nsGkAtoms::selected) ||
|
||||
if ((aAccessible->GetContent()->IsXUL() && aAttribute == nsGkAtoms::selected) ||
|
||||
aAttribute == nsGkAtoms::aria_selected) {
|
||||
Accessible* item = GetAccessible(aContent);
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
Accessible* widget =
|
||||
nsAccUtils::GetSelectableContainer(item, item->State());
|
||||
nsAccUtils::GetSelectableContainer(aAccessible, aAccessible->State());
|
||||
if (widget) {
|
||||
nsIContent* elm = aAccessible->GetContent();
|
||||
AccSelChangeEvent::SelChangeType selChangeType =
|
||||
aContent->AttrValueIs(aNameSpaceID, aAttribute,
|
||||
nsGkAtoms::_true, eCaseMatters) ?
|
||||
elm->AttrValueIs(aNameSpaceID, aAttribute, nsGkAtoms::_true, eCaseMatters) ?
|
||||
AccSelChangeEvent::eSelectionAdd : AccSelChangeEvent::eSelectionRemove;
|
||||
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccSelChangeEvent(widget, item, selChangeType);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
new AccSelChangeEvent(widget, aAccessible, selChangeType);
|
||||
FireDelayedEvent(event);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (aAttribute == nsGkAtoms::contenteditable) {
|
||||
nsRefPtr<AccEvent> editableChangeEvent =
|
||||
new AccStateChangeEvent(aContent, states::EDITABLE);
|
||||
FireDelayedAccessibleEvent(editableChangeEvent);
|
||||
new AccStateChangeEvent(aAccessible, states::EDITABLE);
|
||||
FireDelayedEvent(editableChangeEvent);
|
||||
return;
|
||||
}
|
||||
|
||||
if (aAttribute == nsGkAtoms::value) {
|
||||
Accessible* accessible = GetAccessible(aContent);
|
||||
if(accessible && accessible->IsProgress()) {
|
||||
FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE,
|
||||
aContent);
|
||||
}
|
||||
if (aAccessible->IsProgress())
|
||||
FireDelayedEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE, aAccessible);
|
||||
}
|
||||
}
|
||||
|
||||
// DocAccessible protected member
|
||||
void
|
||||
DocAccessible::ARIAAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute)
|
||||
DocAccessible::ARIAAttributeChanged(Accessible* aAccessible, nsIAtom* aAttribute)
|
||||
{
|
||||
// Note: For universal/global ARIA states and properties we don't care if
|
||||
// there is an ARIA role present or not.
|
||||
|
||||
if (aAttribute == nsGkAtoms::aria_required) {
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccStateChangeEvent(aContent, states::REQUIRED);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
new AccStateChangeEvent(aAccessible, states::REQUIRED);
|
||||
FireDelayedEvent(event);
|
||||
return;
|
||||
}
|
||||
|
||||
if (aAttribute == nsGkAtoms::aria_invalid) {
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccStateChangeEvent(aContent, states::INVALID);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
new AccStateChangeEvent(aAccessible, states::INVALID);
|
||||
FireDelayedEvent(event);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1133,8 +1122,8 @@ DocAccessible::ARIAAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute)
|
|||
// to the element with the id that activedescendant points to. Make sure
|
||||
// the tree up to date before processing.
|
||||
if (aAttribute == nsGkAtoms::aria_activedescendant) {
|
||||
mNotificationController->HandleNotification<DocAccessible, nsIContent>
|
||||
(this, &DocAccessible::ARIAActiveDescendantChanged, aContent);
|
||||
mNotificationController->HandleNotification<DocAccessible, Accessible>
|
||||
(this, &DocAccessible::ARIAActiveDescendantChanged, aAccessible);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -1142,8 +1131,8 @@ DocAccessible::ARIAAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute)
|
|||
// We treat aria-expanded as a global ARIA state for historical reasons
|
||||
if (aAttribute == nsGkAtoms::aria_expanded) {
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccStateChangeEvent(aContent, states::EXPANDED);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
new AccStateChangeEvent(aAccessible, states::EXPANDED);
|
||||
FireDelayedEvent(event);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1151,10 +1140,11 @@ DocAccessible::ARIAAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute)
|
|||
// change event; at least until native API comes up with a more meaningful event.
|
||||
uint8_t attrFlags = nsAccUtils::GetAttributeCharacteristics(aAttribute);
|
||||
if (!(attrFlags & ATTR_BYPASSOBJ))
|
||||
FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_OBJECT_ATTRIBUTE_CHANGED,
|
||||
aContent);
|
||||
FireDelayedEvent(nsIAccessibleEvent::EVENT_OBJECT_ATTRIBUTE_CHANGED,
|
||||
aAccessible);
|
||||
|
||||
if (!aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::role)) {
|
||||
nsIContent* elm = aAccessible->GetContent();
|
||||
if (!elm->HasAttr(kNameSpaceID_None, nsGkAtoms::role)) {
|
||||
// We don't care about these other ARIA attribute changes unless there is
|
||||
// an ARIA role set for the element
|
||||
// XXX: we should check the role map to see if the changed property is
|
||||
|
@ -1165,29 +1155,26 @@ DocAccessible::ARIAAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute)
|
|||
// The following ARIA attributes only take affect when dynamic content role is present
|
||||
if (aAttribute == nsGkAtoms::aria_checked ||
|
||||
aAttribute == nsGkAtoms::aria_pressed) {
|
||||
const uint32_t kState = (aAttribute == nsGkAtoms::aria_checked) ?
|
||||
const uint64_t kState = (aAttribute == nsGkAtoms::aria_checked) ?
|
||||
states::CHECKED : states::PRESSED;
|
||||
nsRefPtr<AccEvent> event = new AccStateChangeEvent(aContent, kState);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
nsRefPtr<AccEvent> event = new AccStateChangeEvent(aAccessible, kState);
|
||||
FireDelayedEvent(event);
|
||||
|
||||
Accessible* accessible = event->GetAccessible();
|
||||
if (accessible) {
|
||||
bool wasMixed = (mARIAAttrOldValue == nsGkAtoms::mixed);
|
||||
bool isMixed = aContent->AttrValueIs(kNameSpaceID_None, aAttribute,
|
||||
nsGkAtoms::mixed, eCaseMatters);
|
||||
if (isMixed != wasMixed) {
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccStateChangeEvent(aContent, states::MIXED, isMixed);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
}
|
||||
bool wasMixed = (mARIAAttrOldValue == nsGkAtoms::mixed);
|
||||
bool isMixed = elm->AttrValueIs(kNameSpaceID_None, aAttribute,
|
||||
nsGkAtoms::mixed, eCaseMatters);
|
||||
if (isMixed != wasMixed) {
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccStateChangeEvent(aAccessible, states::MIXED, isMixed);
|
||||
FireDelayedEvent(event);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (aAttribute == nsGkAtoms::aria_readonly) {
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccStateChangeEvent(aContent, states::READONLY);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
new AccStateChangeEvent(aAccessible, states::READONLY);
|
||||
FireDelayedEvent(event);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1195,23 +1182,22 @@ DocAccessible::ARIAAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute)
|
|||
// when aria-valuenow is changed and aria-valuetext is empty
|
||||
if (aAttribute == nsGkAtoms::aria_valuetext ||
|
||||
(aAttribute == nsGkAtoms::aria_valuenow &&
|
||||
(!aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_valuetext) ||
|
||||
aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::aria_valuetext,
|
||||
nsGkAtoms::_empty, eCaseMatters)))) {
|
||||
FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE,
|
||||
aContent);
|
||||
(!elm->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_valuetext) ||
|
||||
elm->AttrValueIs(kNameSpaceID_None, nsGkAtoms::aria_valuetext,
|
||||
nsGkAtoms::_empty, eCaseMatters)))) {
|
||||
FireDelayedEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE, aAccessible);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DocAccessible::ARIAActiveDescendantChanged(nsIContent* aElm)
|
||||
DocAccessible::ARIAActiveDescendantChanged(Accessible* aAccessible)
|
||||
{
|
||||
Accessible* widget = GetAccessible(aElm);
|
||||
if (widget && widget->IsActiveWidget()) {
|
||||
nsIContent* elm = aAccessible->GetContent();
|
||||
if (elm && aAccessible->IsActiveWidget()) {
|
||||
nsAutoString id;
|
||||
if (aElm->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_activedescendant, id)) {
|
||||
dom::Element* activeDescendantElm = aElm->OwnerDoc()->GetElementById(id);
|
||||
if (elm->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_activedescendant, id)) {
|
||||
dom::Element* activeDescendantElm = elm->OwnerDoc()->GetElementById(id);
|
||||
if (activeDescendantElm) {
|
||||
Accessible* activeDescendant = GetAccessible(activeDescendantElm);
|
||||
if (activeDescendant) {
|
||||
|
@ -1240,31 +1226,32 @@ DocAccessible::ContentStateChanged(nsIDocument* aDocument,
|
|||
nsIContent* aContent,
|
||||
nsEventStates aStateMask)
|
||||
{
|
||||
Accessible* accessible = GetAccessible(aContent);
|
||||
if (!accessible)
|
||||
return;
|
||||
|
||||
if (aStateMask.HasState(NS_EVENT_STATE_CHECKED)) {
|
||||
Accessible* item = GetAccessible(aContent);
|
||||
if (item) {
|
||||
Accessible* widget = item->ContainerWidget();
|
||||
if (widget && widget->IsSelect()) {
|
||||
AccSelChangeEvent::SelChangeType selChangeType =
|
||||
aContent->AsElement()->State().HasState(NS_EVENT_STATE_CHECKED) ?
|
||||
AccSelChangeEvent::eSelectionAdd : AccSelChangeEvent::eSelectionRemove;
|
||||
nsRefPtr<AccEvent> event = new AccSelChangeEvent(widget, item,
|
||||
selChangeType);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
}
|
||||
Accessible* widget = accessible->ContainerWidget();
|
||||
if (widget && widget->IsSelect()) {
|
||||
AccSelChangeEvent::SelChangeType selChangeType =
|
||||
aContent->AsElement()->State().HasState(NS_EVENT_STATE_CHECKED) ?
|
||||
AccSelChangeEvent::eSelectionAdd : AccSelChangeEvent::eSelectionRemove;
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccSelChangeEvent(widget, accessible, selChangeType);
|
||||
FireDelayedEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
if (aStateMask.HasState(NS_EVENT_STATE_INVALID)) {
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccStateChangeEvent(aContent, states::INVALID, true);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
new AccStateChangeEvent(accessible, states::INVALID, true);
|
||||
FireDelayedEvent(event);
|
||||
}
|
||||
|
||||
if (aStateMask.HasState(NS_EVENT_STATE_VISITED)) {
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccStateChangeEvent(aContent, states::TRAVERSED, true);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
new AccStateChangeEvent(accessible, states::TRAVERSED, true);
|
||||
FireDelayedEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1542,8 +1529,8 @@ DocAccessible::NotifyOfLoading(bool aIsReloading)
|
|||
// Fire state busy change event. Use delayed event since we don't care
|
||||
// actually if event isn't delivered when the document goes away like a shot.
|
||||
nsRefPtr<AccEvent> stateEvent =
|
||||
new AccStateChangeEvent(mDocument, states::BUSY, true);
|
||||
FireDelayedAccessibleEvent(stateEvent);
|
||||
new AccStateChangeEvent(this, states::BUSY, true);
|
||||
FireDelayedEvent(stateEvent);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1567,7 +1554,7 @@ DocAccessible::DoInitialUpdate()
|
|||
// a problem then consider to keep event processing per tab document.
|
||||
if (!IsRoot()) {
|
||||
nsRefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(Parent());
|
||||
ParentDocument()->FireDelayedAccessibleEvent(reorderEvent);
|
||||
ParentDocument()->FireDelayedEvent(reorderEvent);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1747,36 +1734,6 @@ DocAccessible::UpdateAccessibleOnAttrChange(dom::Element* aElement,
|
|||
return false;
|
||||
}
|
||||
|
||||
// DocAccessible public member
|
||||
nsresult
|
||||
DocAccessible::FireDelayedAccessibleEvent(uint32_t aEventType, nsINode* aNode,
|
||||
AccEvent::EEventRule aAllowDupes,
|
||||
EIsFromUserInput aIsFromUserInput)
|
||||
{
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccEvent(aEventType, aNode, aIsFromUserInput, aAllowDupes);
|
||||
NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
return FireDelayedAccessibleEvent(event);
|
||||
}
|
||||
|
||||
// DocAccessible public member
|
||||
nsresult
|
||||
DocAccessible::FireDelayedAccessibleEvent(AccEvent* aEvent)
|
||||
{
|
||||
NS_ENSURE_ARG(aEvent);
|
||||
|
||||
#ifdef A11Y_LOG
|
||||
if (logging::IsEnabled(logging::eDocLoad))
|
||||
logging::DocLoadEventFired(aEvent);
|
||||
#endif
|
||||
|
||||
if (mNotificationController)
|
||||
mNotificationController->QueueEvent(aEvent);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
DocAccessible::ProcessContentInserted(Accessible* aContainer,
|
||||
const nsTArray<nsCOMPtr<nsIContent> >* aInsertedContent)
|
||||
|
@ -1874,9 +1831,7 @@ DocAccessible::UpdateTree(Accessible* aContainer, nsIContent* aChildNode,
|
|||
Accessible* ancestor = aContainer;
|
||||
while (ancestor) {
|
||||
if (ancestor->ARIARole() == roles::ALERT) {
|
||||
nsRefPtr<AccEvent> alertEvent =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_ALERT, ancestor);
|
||||
FireDelayedAccessibleEvent(alertEvent);
|
||||
FireDelayedEvent(nsIAccessibleEvent::EVENT_ALERT, ancestor);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1892,7 +1847,7 @@ DocAccessible::UpdateTree(Accessible* aContainer, nsIContent* aChildNode,
|
|||
|
||||
// Fire reorder event so the MSAA clients know the children have changed. Also
|
||||
// the event is used internally by MSAA layer.
|
||||
FireDelayedAccessibleEvent(reorderEvent);
|
||||
FireDelayedEvent(reorderEvent);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
|
@ -1916,11 +1871,8 @@ DocAccessible::UpdateTreeInternal(Accessible* aChild, bool aIsInsert,
|
|||
// the changes before our processing and we may miss some menupopup
|
||||
// events. Now we just want to be consistent in content insertion/removal
|
||||
// handling.
|
||||
if (aChild->ARIARole() == roles::MENUPOPUP) {
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_END, aChild);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
}
|
||||
if (aChild->ARIARole() == roles::MENUPOPUP)
|
||||
FireDelayedEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_END, aChild);
|
||||
}
|
||||
|
||||
// Fire show/hide event.
|
||||
|
@ -1930,23 +1882,19 @@ DocAccessible::UpdateTreeInternal(Accessible* aChild, bool aIsInsert,
|
|||
else
|
||||
event = new AccHideEvent(aChild, node);
|
||||
|
||||
FireDelayedAccessibleEvent(event);
|
||||
FireDelayedEvent(event);
|
||||
aReorderEvent->AddSubMutationEvent(event);
|
||||
|
||||
if (aIsInsert) {
|
||||
roles::Role ariaRole = aChild->ARIARole();
|
||||
if (ariaRole == roles::MENUPOPUP) {
|
||||
// Fire EVENT_MENUPOPUP_START if ARIA menu appears.
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_START, aChild);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
FireDelayedEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_START, aChild);
|
||||
|
||||
} else if (ariaRole == roles::ALERT) {
|
||||
// Fire EVENT_ALERT if ARIA alert appears.
|
||||
updateFlags = eAlertAccessible;
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_ALERT, aChild);
|
||||
FireDelayedAccessibleEvent(event);
|
||||
FireDelayedEvent(nsIAccessibleEvent::EVENT_ALERT, aChild);
|
||||
}
|
||||
|
||||
// If focused node has been shown then it means its frame was recreated
|
||||
|
@ -1996,8 +1944,7 @@ DocAccessible::CacheChildrenInSubtree(Accessible* aRoot)
|
|||
if (aRoot->HasARIARole() && !aRoot->IsDoc()) {
|
||||
a11y::role role = aRoot->ARIARole();
|
||||
if (role == roles::DIALOG || role == roles::DOCUMENT)
|
||||
FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE,
|
||||
aRoot->GetContent());
|
||||
FireDelayedEvent(nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE, aRoot);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -173,22 +173,10 @@ public:
|
|||
{ return mChildDocuments.SafeElementAt(aIndex, nullptr); }
|
||||
|
||||
/**
|
||||
* Non-virtual method to fire a delayed event after a 0 length timeout.
|
||||
*
|
||||
* @param aEventType [in] the nsIAccessibleEvent event type
|
||||
* @param aDOMNode [in] DOM node the accesible event should be fired for
|
||||
* @param aAllowDupes [in] rule to process an event (see EEventRule constants)
|
||||
* Fire accessible event asynchronously.
|
||||
*/
|
||||
nsresult FireDelayedAccessibleEvent(uint32_t aEventType, nsINode *aNode,
|
||||
AccEvent::EEventRule aAllowDupes = AccEvent::eRemoveDupes,
|
||||
EIsFromUserInput aIsFromUserInput = eAutoDetect);
|
||||
|
||||
/**
|
||||
* Fire accessible event after timeout.
|
||||
*
|
||||
* @param aEvent [in] the event to fire
|
||||
*/
|
||||
nsresult FireDelayedAccessibleEvent(AccEvent* aEvent);
|
||||
void FireDelayedEvent(AccEvent* aEvent);
|
||||
void FireDelayedEvent(uint32_t aEventType, Accessible* aTarget);
|
||||
|
||||
/**
|
||||
* Fire value change event on the given accessible if applicable.
|
||||
|
@ -398,27 +386,28 @@ protected:
|
|||
bool UpdateAccessibleOnAttrChange(mozilla::dom::Element* aElement,
|
||||
nsIAtom* aAttribute);
|
||||
|
||||
/**
|
||||
* Fires accessible events when attribute is changed.
|
||||
*
|
||||
* @param aContent - node that attribute is changed for
|
||||
* @param aNameSpaceID - namespace of changed attribute
|
||||
* @param aAttribute - changed attribute
|
||||
*/
|
||||
void AttributeChangedImpl(nsIContent* aContent, int32_t aNameSpaceID, nsIAtom* aAttribute);
|
||||
/**
|
||||
* Fire accessible events when attribute is changed.
|
||||
*
|
||||
* @param aAccessible [in] accessible the DOM attribute is changed for
|
||||
* @param aNameSpaceID [in] namespace of changed attribute
|
||||
* @param aAttribute [in] changed attribute
|
||||
*/
|
||||
void AttributeChangedImpl(Accessible* aAccessible,
|
||||
int32_t aNameSpaceID, nsIAtom* aAttribute);
|
||||
|
||||
/**
|
||||
* Fires accessible events when ARIA attribute is changed.
|
||||
*
|
||||
* @param aContent - node that attribute is changed for
|
||||
* @param aAttribute - changed attribute
|
||||
*/
|
||||
void ARIAAttributeChanged(nsIContent* aContent, nsIAtom* aAttribute);
|
||||
/**
|
||||
* Fire accessible events when ARIA attribute is changed.
|
||||
*
|
||||
* @param aAccessible [in] accesislbe the DOM attribute is changed for
|
||||
* @param aAttribute [in] changed attribute
|
||||
*/
|
||||
void ARIAAttributeChanged(Accessible* aAccessible, nsIAtom* aAttribute);
|
||||
|
||||
/**
|
||||
* Process ARIA active-descendant attribute change.
|
||||
*/
|
||||
void ARIAActiveDescendantChanged(nsIContent* aElm);
|
||||
void ARIAActiveDescendantChanged(Accessible* aAccessible);
|
||||
|
||||
/**
|
||||
* Update the accessible tree for inserted content.
|
||||
|
|
|
@ -311,8 +311,6 @@ RootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent)
|
|||
if (!accessible)
|
||||
return;
|
||||
|
||||
nsINode* targetNode = accessible->GetNode();
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
XULTreeAccessible* treeAcc = accessible->AsXULTree();
|
||||
if (treeAcc) {
|
||||
|
@ -383,6 +381,7 @@ RootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent)
|
|||
return;
|
||||
}
|
||||
|
||||
nsINode* targetNode = accessible->GetNode();
|
||||
if (treeItemAcc && eventType.EqualsLiteral("select")) {
|
||||
// XXX: We shouldn't be based on DOM select event which doesn't provide us
|
||||
// any context info. We should integrate into nsTreeSelection instead.
|
||||
|
@ -478,10 +477,10 @@ RootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent)
|
|||
|
||||
//We don't process 'ValueChange' events for progress meters since we listen
|
||||
//@value attribute change for them.
|
||||
if (!accessible->IsProgress())
|
||||
targetDocument->
|
||||
FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE,
|
||||
targetNode);
|
||||
if (!accessible->IsProgress()) {
|
||||
targetDocument->FireDelayedEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE,
|
||||
accessible);
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_DRAGDROPSTART
|
||||
else if (eventType.EqualsLiteral("mouseover")) {
|
||||
|
@ -677,7 +676,7 @@ RootAccessible::HandlePopupHidingEvent(nsINode* aPopupNode)
|
|||
if (notifyOf & kNotifyOfState) {
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccStateChangeEvent(widget, states::EXPANDED, false);
|
||||
document->FireDelayedAccessibleEvent(event);
|
||||
document->FireDelayedEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsARIAMap.h"
|
||||
#include "DocAccessible.h"
|
||||
#include "DocAccessible-inl.h"
|
||||
#include "Role.h"
|
||||
|
||||
#include "nsIDOMHTMLCollection.h"
|
||||
|
@ -95,7 +95,7 @@ HTMLImageMapAccessible::UpdateChildAreas(bool aDoFireEvents)
|
|||
|
||||
if (aDoFireEvents) {
|
||||
nsRefPtr<AccHideEvent> event = new AccHideEvent(area, area->GetContent());
|
||||
mDoc->FireDelayedAccessibleEvent(event);
|
||||
mDoc->FireDelayedEvent(event);
|
||||
reorderEvent->AddSubMutationEvent(event);
|
||||
doReorderEvent = true;
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ HTMLImageMapAccessible::UpdateChildAreas(bool aDoFireEvents)
|
|||
|
||||
if (aDoFireEvents) {
|
||||
nsRefPtr<AccShowEvent> event = new AccShowEvent(area, areaContent);
|
||||
mDoc->FireDelayedAccessibleEvent(event);
|
||||
mDoc->FireDelayedEvent(event);
|
||||
reorderEvent->AddSubMutationEvent(event);
|
||||
doReorderEvent = true;
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ HTMLImageMapAccessible::UpdateChildAreas(bool aDoFireEvents)
|
|||
|
||||
// Fire reorder event if needed.
|
||||
if (doReorderEvent)
|
||||
mDoc->FireDelayedAccessibleEvent(reorderEvent);
|
||||
mDoc->FireDelayedEvent(reorderEvent);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -45,7 +45,7 @@ nsAccEvent::GetDOMNode(nsIDOMNode** aDOMNode)
|
|||
NS_ENSURE_ARG_POINTER(aDOMNode);
|
||||
*aDOMNode = nullptr;
|
||||
|
||||
nsINode* node = mEvent->GetNode();
|
||||
nsINode* node = mEvent->GetAccessible()->GetNode();
|
||||
if (node)
|
||||
CallQueryInterface(node, aDOMNode);
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "XULTreeAccessible.h"
|
||||
|
||||
#include "DocAccessible-inl.h"
|
||||
#include "nsAccCache.h"
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsCoreUtils.h"
|
||||
|
@ -663,7 +664,7 @@ XULTreeAccessible::TreeViewChanged(nsITreeView* aView)
|
|||
// show/hide events on tree items because it can be expensive to fire them for
|
||||
// each tree item.
|
||||
nsRefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(this);
|
||||
Document()->FireDelayedAccessibleEvent(reorderEvent);
|
||||
Document()->FireDelayedEvent(reorderEvent);
|
||||
|
||||
// Clear cache.
|
||||
ClearCache(mAccessibleCache);
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
|
||||
if (!MAC) { // Mac failure is bug 541093
|
||||
var checker =
|
||||
new eventFromInputChecker(EVENT_TEXT_CARET_MOVED, id, "false", noTargetId);
|
||||
new eventFromInputChecker(EVENT_TEXT_CARET_MOVED, id, "true", noTargetId);
|
||||
gQueue.push(new synthHomeKey(id, checker));
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче