EventTree* EventTree::FindOrInsert(Accessible* aContainer) { if (!mFirst) { mFirst.reset(new EventTree(aContainer, true)); return mFirst.get(); } EventTree* prevNode = nullptr; EventTree* node = mFirst.get(); do { MOZ_ASSERT(!node->mContainer->IsApplication(), "No event for application accessible is expected here"); MOZ_ASSERT(!node->mContainer->IsDefunct(), "An event target has to be alive"); // Case of same target. if (node->mContainer == aContainer) { return node; } // Check if the given container is contained by a current node Accessible* top = mContainer ? mContainer : aContainer->Document(); Accessible* parent = aContainer; while (parent) { // Reached a top, no match for a current event. if (parent == top) { break; } // We got a match. if (parent->Parent() == node->mContainer) { return node->FindOrInsert(aContainer); } parent = parent->Parent(); MOZ_ASSERT(parent, "Wrong tree"); } // If the given container contains a current node // then // if show or hide of the given node contains a grand parent of the current node // then ignore the current node and its show and hide events // otherwise ignore the current node, but not its show and hide events Accessible* curParent = node->mContainer; while (curParent && !curParent->IsDoc()) { if (curParent->Parent() != aContainer) { curParent = curParent->Parent(); continue; } // Insert the tail node into the hierarchy between the current node and // its parent. node->mFireReorder = false; UniquePtr<EventTree>& nodeOwnerRef = prevNode ? prevNode->mNext : mFirst; UniquePtr<EventTree> newNode(new EventTree(aContainer, mDependentEvents.IsEmpty())); newNode->mFirst = Move(nodeOwnerRef); nodeOwnerRef = Move(newNode); nodeOwnerRef->mNext = Move(node->mNext); // Check if a next node is contained by the given node too, and move them // under the given node if so. prevNode = nodeOwnerRef.get(); node = nodeOwnerRef->mNext.get(); UniquePtr<EventTree>* nodeRef = &nodeOwnerRef->mNext; EventTree* insNode = nodeOwnerRef->mFirst.get(); while (node) { Accessible* curParent = node->mContainer; while (curParent && !curParent->IsDoc()) { if (curParent->Parent() != aContainer) { curParent = curParent->Parent(); continue; } MOZ_ASSERT(!insNode->mNext); node->mFireReorder = false; insNode->mNext = Move(*nodeRef); insNode = insNode->mNext.get(); prevNode->mNext = Move(node->mNext); node = prevNode; break; } prevNode = node; nodeRef = &node->mNext; node = node->mNext.get(); } return nodeOwnerRef.get(); } prevNode = node; } while ((node = node->mNext.get())); MOZ_ASSERT(prevNode, "Nowhere to insert"); MOZ_ASSERT(!prevNode->mNext, "Taken by another node"); // If 'this' node contains the given container accessible, then // do not emit a reorder event for the container // if a dependent show event target contains the given container then do not // emit show / hide events (see Process() method) prevNode->mNext.reset(new EventTree(aContainer, mDependentEvents.IsEmpty())); return prevNode->mNext.get(); }
EventTree* EventTree::FindOrInsert(Accessible* aContainer) { if (!mFirst) { mFirst.reset(new EventTree(aContainer, mDependentEvents.IsEmpty())); return mFirst.get(); } EventTree* prevNode = nullptr; EventTree* node = mFirst.get(); do { MOZ_ASSERT(!node->mContainer->IsApplication(), "No event for application accessible is expected here"); MOZ_ASSERT(!node->mContainer->IsDefunct(), "An event target has to be alive"); // Case of same target. if (node->mContainer == aContainer) { return node; } // Check if the given container is contained by a current node Accessible* top = mContainer ? mContainer : aContainer->Document(); Accessible* parent = aContainer; while (parent) { // Reached a top, no match for a current event. if (parent == top) { break; } // We got a match. if (parent->Parent() == node->mContainer) { // Reject the node if it's contained by a show/hide event target uint32_t evCount = node->mDependentEvents.Length(); for (uint32_t idx = 0; idx < evCount; idx++) { AccMutationEvent* ev = node->mDependentEvents[idx]; if (ev->GetAccessible() == parent) { #ifdef A11Y_LOG if (logging::IsEnabled(logging::eEventTree)) { logging::MsgBegin("EVENTS_TREE", "Rejecting node contained by show/hide"); logging::AccessibleInfo("Node", aContainer); logging::MsgEnd(); } #endif // If the node is rejected, then check if it has related hide event // on stack, and if so, then connect it to the parent show event. if (ev->IsShow()) { AccShowEvent* showEv = downcast_accEvent(ev); Controller(aContainer)-> WithdrawPrecedingEvents(&showEv->mPrecedingEvents); } return nullptr; } } return node->FindOrInsert(aContainer); } parent = parent->Parent(); MOZ_ASSERT(parent, "Wrong tree"); } // If the given container contains a current node // then // if show or hide of the given node contains a grand parent of the current node // then ignore the current node and its show and hide events // otherwise ignore the current node, but not its show and hide events Accessible* curParent = node->mContainer; while (curParent && !curParent->IsDoc()) { if (curParent->Parent() != aContainer) { curParent = curParent->Parent(); continue; } // Insert the tail node into the hierarchy between the current node and // its parent. node->mFireReorder = false; UniquePtr<EventTree>& nodeOwnerRef = prevNode ? prevNode->mNext : mFirst; UniquePtr<EventTree> newNode(new EventTree(aContainer, mDependentEvents.IsEmpty())); newNode->mFirst = Move(nodeOwnerRef); nodeOwnerRef = Move(newNode); nodeOwnerRef->mNext = Move(node->mNext); // Check if a next node is contained by the given node too, and move them // under the given node if so. prevNode = nodeOwnerRef.get(); node = nodeOwnerRef->mNext.get(); UniquePtr<EventTree>* nodeRef = &nodeOwnerRef->mNext; EventTree* insNode = nodeOwnerRef->mFirst.get(); while (node) { Accessible* curParent = node->mContainer; while (curParent && !curParent->IsDoc()) { if (curParent->Parent() != aContainer) { curParent = curParent->Parent(); continue; } MOZ_ASSERT(!insNode->mNext); node->mFireReorder = false; insNode->mNext = Move(*nodeRef); insNode = insNode->mNext.get(); prevNode->mNext = Move(node->mNext); node = prevNode; break; } prevNode = node; nodeRef = &node->mNext; node = node->mNext.get(); } return nodeOwnerRef.get(); } prevNode = node; } while ((node = node->mNext.get())); MOZ_ASSERT(prevNode, "Nowhere to insert"); MOZ_ASSERT(!prevNode->mNext, "Taken by another node"); // If 'this' node contains the given container accessible, then // do not emit a reorder event for the container // if a dependent show event target contains the given container then do not // emit show / hide events (see Process() method) prevNode->mNext.reset(new EventTree(aContainer, mDependentEvents.IsEmpty())); return prevNode->mNext.get(); }