// 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; }