// Main thread via OnProcessNextEvent below
bool
nsBaseAppShell::DoProcessNextNativeEvent(bool mayWait, uint32_t recursionDepth)
{
    // The next native event to be processed may trigger our NativeEventCallback,
    // in which case we do not want it to process any thread events since we'll
    // do that when this function returns.
    //
    // If the next native event is not our NativeEventCallback, then we may end
    // up recursing into this function.
    //
    // However, if the next native event is not our NativeEventCallback, but it
    // results in another native event loop, then our NativeEventCallback could
    // fire and it will see mEventloopNestingState as eEventloopOther.
    //
    EventloopNestingState prevVal = mEventloopNestingState;
    mEventloopNestingState = eEventloopXPCOM;

    IncrementEventloopNestingLevel();

    bool result = ProcessNextNativeEvent(mayWait);

    // Make sure that any sync sections registered during this most recent event
    // are run now. This is not considered a stable state because we're not back
    // to the event loop yet.
    RunSyncSections(false, recursionDepth);

    DecrementEventloopNestingLevel();

    mEventloopNestingState = prevVal;
    return result;
}
// Called by nsAppShell's native event callback
void
nsBaseAppShell::NativeEventCallback()
{
  if (!mNativeEventPending.exchange(false))
    return;

  // If DoProcessNextNativeEvent is on the stack, then we assume that we can
  // just unwind and let nsThread::ProcessNextEvent process the next event.
  // However, if we are called from a nested native event loop (maybe via some
  // plug-in or library function), then go ahead and process Gecko events now.
  if (mEventloopNestingState == eEventloopXPCOM) {
    mEventloopNestingState = eEventloopOther;
    // XXX there is a tiny risk we will never get a new NativeEventCallback,
    // XXX see discussion in bug 389931.
    return;
  }

  // nsBaseAppShell::Run is not being used to pump events, so this may be
  // our only opportunity to process pending gecko events.

  nsIThread *thread = NS_GetCurrentThread();
  bool prevBlockNativeEvent = mBlockNativeEvent;
  if (mEventloopNestingState == eEventloopOther) {
    if (!NS_HasPendingEvents(thread))
      return;
    // We're in a nested native event loop and have some gecko events to
    // process.  While doing that we block processing native events from the
    // appshell - instead, we want to get back to the nested native event
    // loop ASAP (bug 420148).
    mBlockNativeEvent = true;
  }

  IncrementEventloopNestingLevel();
  EventloopNestingState prevVal = mEventloopNestingState;
  NS_ProcessPendingEvents(thread, THREAD_EVENT_STARVATION_LIMIT);
  mProcessedGeckoEvents = true;
  mEventloopNestingState = prevVal;
  mBlockNativeEvent = prevBlockNativeEvent;

  // Continue processing pending events later (we don't want to starve the
  // embedders event loop).
  if (NS_HasPendingEvents(thread))
    DoProcessMoreGeckoEvents();

  DecrementEventloopNestingLevel();
}
// Main thread via OnProcessNextEvent below
bool
nsBaseAppShell::DoProcessNextNativeEvent(bool mayWait)
{
  // The next native event to be processed may trigger our NativeEventCallback,
  // in which case we do not want it to process any thread events since we'll
  // do that when this function returns.
  //
  // If the next native event is not our NativeEventCallback, then we may end
  // up recursing into this function.
  //
  // However, if the next native event is not our NativeEventCallback, but it
  // results in another native event loop, then our NativeEventCallback could
  // fire and it will see mEventloopNestingState as eEventloopOther.
  //
  EventloopNestingState prevVal = mEventloopNestingState;
  mEventloopNestingState = eEventloopXPCOM;

  IncrementEventloopNestingLevel();
  bool result = ProcessNextNativeEvent(mayWait);
  DecrementEventloopNestingLevel();

  mEventloopNestingState = prevVal;
  return result;
}