diff --git a/accessible/src/base/AccEvent.cpp b/accessible/src/base/AccEvent.cpp index 9b299c727906..66cad558fa24 100644 --- a/accessible/src/base/AccEvent.cpp +++ b/accessible/src/base/AccEvent.cpp @@ -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 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(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 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 AccCaretMoveEvent::CreateXPCOMObject() { diff --git a/accessible/src/base/AccEvent.h b/accessible/src/base/AccEvent.h index 2d1d4f12020e..ddce278fc32d 100644 --- a/accessible/src/base/AccEvent.h +++ b/accessible/src/base/AccEvent.h @@ -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 mAccessible; - nsCOMPtr 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 CreateXPCOMObject(); @@ -239,6 +234,7 @@ public: bool IsHide() const { return mEventType == nsIAccessibleEvent::EVENT_HIDE; } protected: + nsCOMPtr mNode; nsRefPtr mParent; nsRefPtr 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 CreateXPCOMObject(); @@ -367,6 +365,8 @@ public: private: int32_t mCaretOffset; + + friend class NotificationController; }; diff --git a/accessible/src/base/FocusManager.cpp b/accessible/src/base/FocusManager.cpp index 72d561390848..c3dd87dcf2bc 100644 --- a/accessible/src/base/FocusManager.cpp +++ b/accessible/src/base/FocusManager.cpp @@ -219,7 +219,7 @@ FocusManager::DispatchFocusEvent(DocAccessible* aDocument, nsRefPtr event = new AccEvent(nsIAccessibleEvent::EVENT_FOCUS, aTarget, eAutoDetect, AccEvent::eCoalesceOfSameType); - aDocument->FireDelayedAccessibleEvent(event); + aDocument->FireDelayedEvent(event); #ifdef A11Y_LOG if (logging::IsEnabled(logging::eFocus)) diff --git a/accessible/src/base/Logging.cpp b/accessible/src/base/Logging.cpp index 2f1ba9a7b6bd..dbecdf7aea13 100644 --- a/accessible/src/base/Logging.cpp +++ b/accessible/src/base/Logging.cpp @@ -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(node); - DocAccessible* document = aEvent->GetDocAccessible(); - LogDocInfo(documentNode, document); - } + DocAccessible* document = aEvent->GetAccessible()->AsDoc(); + if (document) + LogDocInfo(document->DocumentNode(), document); MsgEnd(); } diff --git a/accessible/src/base/NotificationController.cpp b/accessible/src/base/NotificationController.cpp index b4057533be8a..899e2ba3e86d 100644 --- a/accessible/src/base/NotificationController.cpp +++ b/accessible/src/base/NotificationController.cpp @@ -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 caretMoveEvent = - new AccCaretMoveEvent(hyperText, caretOffset); + NS_SUCCEEDED(hyperText->GetCaretOffset(&caretMoveEvent->mCaretOffset))) { + nsEventShell::FireEvent(caretMoveEvent); // There's a selection so fire selection change as well. diff --git a/accessible/src/base/NotificationController.h b/accessible/src/base/NotificationController.h index 757b682758a7..d9e253084dbe 100644 --- a/accessible/src/base/NotificationController.h +++ b/accessible/src/base/NotificationController.h @@ -78,7 +78,7 @@ private: Class* mInstance; Callback mCallback; - nsCOMPtr mArg; + nsRefPtr mArg; }; /** diff --git a/accessible/src/base/TextUpdater.cpp b/accessible/src/base/TextUpdater.cpp index e503aeeb514f..866d7a502680 100644 --- a/accessible/src/base/TextUpdater.cpp +++ b/accessible/src/base/TextUpdater.cpp @@ -82,14 +82,14 @@ TextUpdater::DoUpdate(const nsAString& aNewText, const nsAString& aOldText, // Fire text change event for removal. nsRefPtr textRemoveEvent = new AccTextChangeEvent(mHyperText, mTextOffset, str1, false); - mDocument->FireDelayedAccessibleEvent(textRemoveEvent); + mDocument->FireDelayedEvent(textRemoveEvent); } if (strLen2 > 0) { // Fire text change event for insertion. nsRefPtr 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); diff --git a/accessible/src/base/nsAccDocManager.cpp b/accessible/src/base/nsAccDocManager.cpp index cbbbc18200b7..0317bfdbe0fc 100644 --- a/accessible/src/base/nsAccDocManager.cpp +++ b/accessible/src/base/nsAccDocManager.cpp @@ -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 reorderEvent = - new AccEvent(nsIAccessibleEvent::EVENT_REORDER, ApplicationAcc()); - docAcc->FireDelayedAccessibleEvent(reorderEvent); + docAcc->FireDelayedEvent(nsIAccessibleEvent::EVENT_REORDER, + ApplicationAcc()); } else { parentDocAcc->BindChildDocument(docAcc); diff --git a/accessible/src/base/nsCaretAccessible.cpp b/accessible/src/base/nsCaretAccessible.cpp index f52479590c8f..a1a7b26ea268 100644 --- a/accessible/src/base/nsCaretAccessible.cpp +++ b/accessible/src/base/nsCaretAccessible.cpp @@ -243,10 +243,8 @@ nsCaretAccessible::NormalSelectionChanged(nsISelection* aSelection) mLastCaretOffset = caretOffset; mLastTextAccessible = textAcc; - nsRefPtr event = - new AccCaretMoveEvent(mLastTextAccessible->GetNode()); - if (event) - mLastTextAccessible->Document()->FireDelayedAccessibleEvent(event); + nsRefPtr 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 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 diff --git a/accessible/src/base/nsEventShell.cpp b/accessible/src/base/nsEventShell.cpp index 6a589fb1645f..06a7084b3f72 100644 --- a/accessible/src/base/nsEventShell.cpp +++ b/accessible/src/base/nsEventShell.cpp @@ -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(); diff --git a/accessible/src/generic/DocAccessible-inl.h b/accessible/src/generic/DocAccessible-inl.h index 5236f81fbcb5..6ae0a371ac03 100644 --- a/accessible/src/generic/DocAccessible-inl.h +++ b/accessible/src/generic/DocAccessible-inl.h @@ -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 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 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 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 diff --git a/accessible/src/generic/DocAccessible.cpp b/accessible/src/generic/DocAccessible.cpp index d3d15bcd7b8a..4b4b4c1dc782 100644 --- a/accessible/src/generic/DocAccessible.cpp +++ b/accessible/src/generic/DocAccessible.cpp @@ -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 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 enabledChangeEvent = - new AccStateChangeEvent(aContent, states::ENABLED); - - FireDelayedAccessibleEvent(enabledChangeEvent); + new AccStateChangeEvent(aAccessible, states::ENABLED); + FireDelayedEvent(enabledChangeEvent); nsRefPtr 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 event = new AccStateChangeEvent(aContent, states::BUSY, isOn); - FireDelayedAccessibleEvent(event); + bool isOn = aAccessible->GetContent()-> + AttrValueIs(aNameSpaceID, aAttribute, nsGkAtoms::_true, eCaseMatters); + nsRefPtr 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 event = - new AccSelChangeEvent(widget, item, selChangeType); - FireDelayedAccessibleEvent(event); + new AccSelChangeEvent(widget, aAccessible, selChangeType); + FireDelayedEvent(event); } + return; } if (aAttribute == nsGkAtoms::contenteditable) { nsRefPtr 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 event = - new AccStateChangeEvent(aContent, states::REQUIRED); - FireDelayedAccessibleEvent(event); + new AccStateChangeEvent(aAccessible, states::REQUIRED); + FireDelayedEvent(event); return; } if (aAttribute == nsGkAtoms::aria_invalid) { nsRefPtr 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 - (this, &DocAccessible::ARIAActiveDescendantChanged, aContent); + mNotificationController->HandleNotification + (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 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 event = new AccStateChangeEvent(aContent, kState); - FireDelayedAccessibleEvent(event); + nsRefPtr 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 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 event = + new AccStateChangeEvent(aAccessible, states::MIXED, isMixed); + FireDelayedEvent(event); } return; } if (aAttribute == nsGkAtoms::aria_readonly) { nsRefPtr 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 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 event = + new AccSelChangeEvent(widget, accessible, selChangeType); + FireDelayedEvent(event); } } if (aStateMask.HasState(NS_EVENT_STATE_INVALID)) { nsRefPtr 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 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 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 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 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 >* aInsertedContent) @@ -1874,9 +1831,7 @@ DocAccessible::UpdateTree(Accessible* aContainer, nsIContent* aChildNode, Accessible* ancestor = aContainer; while (ancestor) { if (ancestor->ARIARole() == roles::ALERT) { - nsRefPtr 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 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 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 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); } } diff --git a/accessible/src/generic/DocAccessible.h b/accessible/src/generic/DocAccessible.h index ee222d03a433..8b8fbf9dd85f 100644 --- a/accessible/src/generic/DocAccessible.h +++ b/accessible/src/generic/DocAccessible.h @@ -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. diff --git a/accessible/src/generic/RootAccessible.cpp b/accessible/src/generic/RootAccessible.cpp index 6a69285d1cc8..af1c1aaa98b7 100644 --- a/accessible/src/generic/RootAccessible.cpp +++ b/accessible/src/generic/RootAccessible.cpp @@ -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 event = new AccStateChangeEvent(widget, states::EXPANDED, false); - document->FireDelayedAccessibleEvent(event); + document->FireDelayedEvent(event); } } diff --git a/accessible/src/html/HTMLImageMapAccessible.cpp b/accessible/src/html/HTMLImageMapAccessible.cpp index 55789b1502e2..925bd2dd5eef 100644 --- a/accessible/src/html/HTMLImageMapAccessible.cpp +++ b/accessible/src/html/HTMLImageMapAccessible.cpp @@ -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 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 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); } //////////////////////////////////////////////////////////////////////////////// diff --git a/accessible/src/xpcom/nsAccEvent.cpp b/accessible/src/xpcom/nsAccEvent.cpp index a181b1342e8c..0cb5f4682fff 100644 --- a/accessible/src/xpcom/nsAccEvent.cpp +++ b/accessible/src/xpcom/nsAccEvent.cpp @@ -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); diff --git a/accessible/src/xul/XULTreeAccessible.cpp b/accessible/src/xul/XULTreeAccessible.cpp index c1a353d67a55..8e0f285118c5 100644 --- a/accessible/src/xul/XULTreeAccessible.cpp +++ b/accessible/src/xul/XULTreeAccessible.cpp @@ -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 reorderEvent = new AccReorderEvent(this); - Document()->FireDelayedAccessibleEvent(reorderEvent); + Document()->FireDelayedEvent(reorderEvent); // Clear cache. ClearCache(mAccessibleCache); diff --git a/accessible/tests/mochitest/events/test_attrs.html b/accessible/tests/mochitest/events/test_attrs.html index 7a515ebd1771..1d5577572ee9 100644 --- a/accessible/tests/mochitest/events/test_attrs.html +++ b/accessible/tests/mochitest/events/test_attrs.html @@ -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)); }