Bug 625454 - Ignore native events on Mac when the run loop is in event tracking mode. r=smichaud a=LegNeato
authorPatrick Walton <pwalton@mozilla.com>
Fri, 21 Jan 2011 15:19:46 -0500
changeset 61113 84ed248b728db45455ebc54179dbb4d314a689cb
parent 61112 ddd42df9beb7d5ed80180f52cd9ba1507f71e4da
child 61114 02d2bfb6af2d1824f54fdb1ce0406ca280de2689
push idunknown
push userunknown
push dateunknown
reviewerssmichaud, LegNeato
bugs625454
milestone2.0b10pre
Bug 625454 - Ignore native events on Mac when the run loop is in event tracking mode. r=smichaud a=LegNeato
widget/src/cocoa/nsAppShell.mm
widget/src/xpwidgets/nsBaseAppShell.cpp
widget/src/xpwidgets/nsBaseAppShell.h
--- a/widget/src/cocoa/nsAppShell.mm
+++ b/widget/src/cocoa/nsAppShell.mm
@@ -389,19 +389,25 @@ nsAppShell::ProcessGeckoEvents(void* aIn
                                     windowNumber:0
                                          context:NULL
                                          subtype:0
                                            data1:0
                                            data2:0]
              atStart:NO];
   }
 
+  // During "event tracking" mode, we're in a nested event loop (and we're
+  // usually in a performance-critical section such as a window resize), so we
+  // block native events.
+  NSString *runLoopMode = [[NSRunLoop currentRunLoop] currentMode];
+  PRBool blockNativeEvents = runLoopMode == NSEventTrackingRunLoopMode;
+
   if (self->mSuspendNativeCount <= 0) {
     ++self->mNativeEventCallbackDepth;
-    self->NativeEventCallback();
+    self->NativeEventCallback(blockNativeEvents);
     --self->mNativeEventCallbackDepth;
   } else {
     self->mSkippedNativeCallback = PR_TRUE;
   }
 
   // Still needed to fix bug 343033 ("5-10 second delay or hang or crash
   // when quitting Cocoa Firefox").
   [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined
--- a/widget/src/xpwidgets/nsBaseAppShell.cpp
+++ b/widget/src/xpwidgets/nsBaseAppShell.cpp
@@ -88,19 +88,20 @@ nsBaseAppShell::Init()
 
   nsCOMPtr<nsIObserverService> obsSvc =
     mozilla::services::GetObserverService();
   if (obsSvc)
     obsSvc->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE);
   return NS_OK;
 }
 
-// Called by nsAppShell's native event callback
+// Called by nsAppShell's native event callback. Set aAlwaysBlockNative to true
+// to always block native events.
 void
-nsBaseAppShell::NativeEventCallback()
+nsBaseAppShell::NativeEventCallback(PRBool aAlwaysBlockNative)
 {
   PRInt32 hasPending = PR_AtomicSet(&mNativeEventPending, 0);
   if (hasPending == 0)
     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
@@ -112,17 +113,19 @@ nsBaseAppShell::NativeEventCallback()
     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();
   PRBool prevBlockNativeEvent = mBlockNativeEvent;
-  if (mEventloopNestingState == eEventloopOther) {
+  if (aAlwaysBlockNative) {
+    mBlockNativeEvent = PR_TRUE;
+  } else 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 = PR_TRUE;
   }
--- a/widget/src/xpwidgets/nsBaseAppShell.h
+++ b/widget/src/xpwidgets/nsBaseAppShell.h
@@ -68,17 +68,17 @@ protected:
    * This method is called by subclasses when the app shell singleton is
    * instantiated.
    */
   nsresult Init();
 
   /**
    * Called by subclasses from a native event. See ScheduleNativeEventCallback.
    */
-  void NativeEventCallback();
+  void NativeEventCallback(PRBool aAlwaysBlockNative = PR_FALSE);
 
   /**
    * Make a decision as to whether or not NativeEventCallback will
    * trigger gecko event processing when there are pending gecko
    * events.
    */
   virtual void DoProcessMoreGeckoEvents();