void EventQueue::CoalesceEvents() { NS_ASSERTION(mEvents.Length(), "There should be at least one pending event!"); uint32_t tail = mEvents.Length() - 1; AccEvent* tailEvent = mEvents[tail]; switch(tailEvent->mEventRule) { case AccEvent::eCoalesceReorder: { DebugOnly<Accessible*> target = tailEvent->mAccessible.get(); MOZ_ASSERT(target->IsApplication() || target->IsOuterDoc() || target->IsXULTree(), "Only app or outerdoc accessible reorder events are in the queue"); MOZ_ASSERT(tailEvent->GetEventType() == nsIAccessibleEvent::EVENT_REORDER, "only reorder events should be queued"); break; // case eCoalesceReorder } case AccEvent::eCoalesceOfSameType: { // Coalesce old events by newer event. for (uint32_t index = tail - 1; index < tail; index--) { AccEvent* accEvent = mEvents[index]; if (accEvent->mEventType == tailEvent->mEventType && accEvent->mEventRule == tailEvent->mEventRule) { accEvent->mEventRule = AccEvent::eDoNotEmit; return; } } break; // case eCoalesceOfSameType } case AccEvent::eCoalesceSelectionChange: { AccSelChangeEvent* tailSelChangeEvent = downcast_accEvent(tailEvent); for (uint32_t index = tail - 1; index < tail; index--) { AccEvent* thisEvent = mEvents[index]; if (thisEvent->mEventRule == tailEvent->mEventRule) { AccSelChangeEvent* thisSelChangeEvent = downcast_accEvent(thisEvent); // Coalesce selection change events within same control. if (tailSelChangeEvent->mWidget == thisSelChangeEvent->mWidget) { CoalesceSelChangeEvents(tailSelChangeEvent, thisSelChangeEvent, index); return; } } } break; // eCoalesceSelectionChange } case AccEvent::eCoalesceStateChange: { // If state change event is duped then ignore previous event. If state // change event is opposite to previous event then no event is emitted // (accessible state wasn't changed). for (uint32_t index = tail - 1; index < tail; index--) { AccEvent* thisEvent = mEvents[index]; if (thisEvent->mEventRule != AccEvent::eDoNotEmit && thisEvent->mEventType == tailEvent->mEventType && thisEvent->mAccessible == tailEvent->mAccessible) { AccStateChangeEvent* thisSCEvent = downcast_accEvent(thisEvent); AccStateChangeEvent* tailSCEvent = downcast_accEvent(tailEvent); if (thisSCEvent->mState == tailSCEvent->mState) { thisEvent->mEventRule = AccEvent::eDoNotEmit; if (thisSCEvent->mIsEnabled != tailSCEvent->mIsEnabled) tailEvent->mEventRule = AccEvent::eDoNotEmit; } } } break; // eCoalesceStateChange } case AccEvent::eCoalesceTextSelChange: { // Coalesce older event by newer event for the same selection or target. // Events for same selection may have different targets and vice versa one // target may be pointed by different selections (for latter see // bug 927159). for (uint32_t index = tail - 1; index < tail; index--) { AccEvent* thisEvent = mEvents[index]; if (thisEvent->mEventRule != AccEvent::eDoNotEmit && thisEvent->mEventType == tailEvent->mEventType) { AccTextSelChangeEvent* thisTSCEvent = downcast_accEvent(thisEvent); AccTextSelChangeEvent* tailTSCEvent = downcast_accEvent(tailEvent); if (thisTSCEvent->mSel == tailTSCEvent->mSel || thisEvent->mAccessible == tailEvent->mAccessible) thisEvent->mEventRule = AccEvent::eDoNotEmit; } } break; // eCoalesceTextSelChange } case AccEvent::eRemoveDupes: { // Check for repeat events, coalesce newly appended event by more older // event. for (uint32_t index = tail - 1; index < tail; index--) { AccEvent* accEvent = mEvents[index]; if (accEvent->mEventType == tailEvent->mEventType && accEvent->mEventRule == tailEvent->mEventRule && accEvent->mAccessible == tailEvent->mAccessible) { tailEvent->mEventRule = AccEvent::eDoNotEmit; return; } } break; // case eRemoveDupes } default: break; // case eAllowDupes, eDoNotEmit } // switch }