예제 #1
0
void
EventTree::Process()
{
  while (mFirst) {
    // Skip a node and its subtree if its container is not in the document.
    if (mFirst->mContainer->IsInDocument()) {
      mFirst->Process();
    }
    mFirst = mFirst->mNext.forget();
  }

  MOZ_ASSERT(mContainer || mDependentEvents.IsEmpty(),
             "No container, no events");
  MOZ_ASSERT(!mContainer || !mContainer->IsDefunct(),
             "Processing events for defunct container");

  // Fire mutation events.
  uint32_t eventsCount = mDependentEvents.Length();
  for (uint32_t jdx = 0; jdx < eventsCount; jdx++) {
    AccMutationEvent* mtEvent = mDependentEvents[jdx];
    MOZ_ASSERT(mtEvent->mEventRule != AccEvent::eDoNotEmit,
               "The event shouldn't be presented in the tree");

    nsEventShell::FireEvent(mtEvent);
    if (mtEvent->mTextChangeEvent) {
      nsEventShell::FireEvent(mtEvent->mTextChangeEvent);
    }

    if (mtEvent->IsHide()) {
      // Fire menupopup end event before a hide event if a menu goes away.

      // XXX: We don't look into children of hidden subtree to find hiding
      // menupopup (as we did prior bug 570275) because we don't do that when
      // menu is showing (and that's impossible until bug 606924 is fixed).
      // Nevertheless we should do this at least because layout coalesces
      // 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 (mtEvent->mAccessible->ARIARole() == roles::MENUPOPUP) {
        nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_END,
                                mtEvent->mAccessible);
      }

      AccHideEvent* hideEvent = downcast_accEvent(mtEvent);
      if (hideEvent->NeedsShutdown()) {
        mtEvent->GetDocAccessible()->ShutdownChildrenInSubtree(mtEvent->mAccessible);
      }
    }
  }

  // Fire reorder event at last.
  if (mFireReorder) {
    MOZ_ASSERT(mContainer);
    nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_REORDER, mContainer);
    mContainer->Document()->MaybeNotifyOfValueChange(mContainer);
  }

  mDependentEvents.Clear();
}
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:
        CoalesceReorderEvents(tailEvent);
        break; // case eCoalesceReorder

    case AccEvent::eCoalesceMutationTextChange:
    {
        for (uint32_t index = tail - 1; index < tail; index--) {
            AccEvent* thisEvent = mEvents[index];
            if (thisEvent->mEventRule != tailEvent->mEventRule)
                continue;

            // We don't currently coalesce text change events from show/hide events.
            if (thisEvent->mEventType != tailEvent->mEventType)
                continue;

            // Show events may be duped because of reinsertion (removal is ignored
            // because initial insertion is not processed). Ignore initial
            // insertion.
            if (thisEvent->mAccessible == tailEvent->mAccessible)
                thisEvent->mEventRule = AccEvent::eDoNotEmit;

            AccMutationEvent* tailMutationEvent = downcast_accEvent(tailEvent);
            AccMutationEvent* thisMutationEvent = downcast_accEvent(thisEvent);
            if (tailMutationEvent->mParent != thisMutationEvent->mParent)
                continue;

            // Coalesce text change events for hide and show events.
            if (thisMutationEvent->IsHide()) {
                AccHideEvent* tailHideEvent = downcast_accEvent(tailEvent);
                AccHideEvent* thisHideEvent = downcast_accEvent(thisEvent);
                CoalesceTextChangeEventsFor(tailHideEvent, thisHideEvent);
                break;
            }

            AccShowEvent* tailShowEvent = downcast_accEvent(tailEvent);
            AccShowEvent* thisShowEvent = downcast_accEvent(thisEvent);
            CoalesceTextChangeEventsFor(tailShowEvent, thisShowEvent);
            break;
        }
    }
    break; // case eCoalesceMutationTextChange

    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::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
}
void
NotificationController::CoalesceEvents()
{
  uint32_t numQueuedEvents = mEvents.Length();
  int32_t tail = numQueuedEvents - 1;
  AccEvent* tailEvent = mEvents[tail];

  switch(tailEvent->mEventRule) {
    case AccEvent::eCoalesceReorder:
      CoalesceReorderEvents(tailEvent);
      break; // case eCoalesceReorder

    case AccEvent::eCoalesceMutationTextChange:
    {
      for (uint32_t index = tail - 1; index < tail; index--) {
        AccEvent* thisEvent = mEvents[index];
        if (thisEvent->mEventRule != tailEvent->mEventRule)
          continue;

        // We don't currently coalesce text change events from show/hide events.
        if (thisEvent->mEventType != tailEvent->mEventType)
          continue;

        // Show events may be duped because of reinsertion (removal is ignored
        // because initial insertion is not processed). Ignore initial
        // insertion.
        if (thisEvent->mAccessible == tailEvent->mAccessible)
          thisEvent->mEventRule = AccEvent::eDoNotEmit;

        AccMutationEvent* tailMutationEvent = downcast_accEvent(tailEvent);
        AccMutationEvent* thisMutationEvent = downcast_accEvent(thisEvent);
        if (tailMutationEvent->mParent != thisMutationEvent->mParent)
          continue;

        // Coalesce text change events for hide and show events.
        if (thisMutationEvent->IsHide()) {
          AccHideEvent* tailHideEvent = downcast_accEvent(tailEvent);
          AccHideEvent* thisHideEvent = downcast_accEvent(thisEvent);
          CoalesceTextChangeEventsFor(tailHideEvent, thisHideEvent);
          break;
        }

        AccShowEvent* tailShowEvent = downcast_accEvent(tailEvent);
        AccShowEvent* thisShowEvent = downcast_accEvent(thisEvent);
        CoalesceTextChangeEventsFor(tailShowEvent, thisShowEvent);
        break;
      }
    } break; // case eCoalesceMutationTextChange

    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::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->mNode == tailEvent->mNode) {
          tailEvent->mEventRule = AccEvent::eDoNotEmit;
          return;
        }
      }
    } break; // case eRemoveDupes

    case AccEvent::eCoalesceSelectionChange:
    {
      AccSelChangeEvent* tailSelChangeEvent = downcast_accEvent(tailEvent);
      int32_t index = tail - 1;
      for (; index >= 0; 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

    default:
      break; // case eAllowDupes, eDoNotEmit
  } // switch
}