widget/xpwidgets/nsBaseAppShell.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #ifndef nsBaseAppShell_h__
     7 #define nsBaseAppShell_h__
     9 #include "mozilla/Atomics.h"
    10 #include "nsIAppShell.h"
    11 #include "nsIThreadInternal.h"
    12 #include "nsIObserver.h"
    13 #include "nsIRunnable.h"
    14 #include "nsCOMPtr.h"
    15 #include "nsTArray.h"
    16 #include "prinrval.h"
    18 /**
    19  * A singleton that manages the UI thread's event queue.  Subclass this class
    20  * to enable platform-specific event queue support.
    21  */
    22 class nsBaseAppShell : public nsIAppShell, public nsIThreadObserver,
    23                        public nsIObserver
    24 {
    25 public:
    26   NS_DECL_THREADSAFE_ISUPPORTS
    27   NS_DECL_NSIAPPSHELL
    28   NS_DECL_NSITHREADOBSERVER
    29   NS_DECL_NSIOBSERVER
    31   nsBaseAppShell();
    33 protected:
    34   virtual ~nsBaseAppShell();
    36   /**
    37    * This method is called by subclasses when the app shell singleton is
    38    * instantiated.
    39    */
    40   nsresult Init();
    42   /**
    43    * Called by subclasses from a native event. See ScheduleNativeEventCallback.
    44    */
    45   void NativeEventCallback();
    47   /**
    48    * Make a decision as to whether or not NativeEventCallback will
    49    * trigger gecko event processing when there are pending gecko
    50    * events.
    51    */
    52   virtual void DoProcessMoreGeckoEvents();
    54   /**
    55    * Implemented by subclasses.  Invoke NativeEventCallback from a native
    56    * event.  This method may be called on any thread.
    57    */
    58   virtual void ScheduleNativeEventCallback() = 0;
    60   /**
    61    * Implemented by subclasses.  Process the next native event.  Only wait for
    62    * the next native event if mayWait is true.  This method is only called on
    63    * the main application thread.
    64    *
    65    * @param mayWait
    66    *   If "true", then this method may wait if necessary for the next available
    67    *   native event.  DispatchNativeEvent may be called to unblock a call to
    68    *   ProcessNextNativeEvent that is waiting.
    69    * @return
    70    *   This method returns "true" if a native event was processed.
    71    */
    72   virtual bool ProcessNextNativeEvent(bool mayWait) = 0;
    74   int32_t mSuspendNativeCount;
    75   uint32_t mEventloopNestingLevel;
    77 private:
    78   bool DoProcessNextNativeEvent(bool mayWait, uint32_t recursionDepth);
    80   bool DispatchDummyEvent(nsIThread* target);
    82   void IncrementEventloopNestingLevel();
    83   void DecrementEventloopNestingLevel();
    85   /**
    86    * Runs all synchronous sections which are queued up in mSyncSections.
    87    */
    88   void RunSyncSectionsInternal(bool stable, uint32_t threadRecursionLevel);
    90   void RunSyncSections(bool stable, uint32_t threadRecursionLevel)
    91   {
    92     if (!mSyncSections.IsEmpty()) {
    93       RunSyncSectionsInternal(stable, threadRecursionLevel);
    94     }
    95   }
    97   void ScheduleSyncSection(nsIRunnable* runnable, bool stable);
    99   struct SyncSection {
   100     SyncSection()
   101     : mStable(false), mEventloopNestingLevel(0), mThreadRecursionLevel(0)
   102     { }
   104     void Forget(SyncSection* other) {
   105       other->mStable = mStable;
   106       other->mEventloopNestingLevel = mEventloopNestingLevel;
   107       other->mThreadRecursionLevel = mThreadRecursionLevel;
   108       other->mRunnable = mRunnable.forget();
   109     }
   111     bool mStable;
   112     uint32_t mEventloopNestingLevel;
   113     uint32_t mThreadRecursionLevel;
   114     nsCOMPtr<nsIRunnable> mRunnable;
   115   };
   117   nsCOMPtr<nsIRunnable> mDummyEvent;
   118   /**
   119    * mBlockedWait points back to a slot that controls the wait loop in
   120    * an outer OnProcessNextEvent invocation.  Nested calls always set
   121    * it to false to unblock an outer loop, since all events may
   122    * have been consumed by the inner event loop(s).
   123    */
   124   bool *mBlockedWait;
   125   int32_t mFavorPerf;
   126   mozilla::Atomic<bool> mNativeEventPending;
   127   PRIntervalTime mStarvationDelay;
   128   PRIntervalTime mSwitchTime;
   129   PRIntervalTime mLastNativeEventTime;
   130   enum EventloopNestingState {
   131     eEventloopNone,  // top level thread execution
   132     eEventloopXPCOM, // innermost native event loop is ProcessNextNativeEvent
   133     eEventloopOther  // innermost native event loop is a native library/plugin etc
   134   };
   135   EventloopNestingState mEventloopNestingState;
   136   nsTArray<SyncSection> mSyncSections;
   137   bool mRunning;
   138   bool mExiting;
   139   /**
   140    * mBlockNativeEvent blocks the appshell from processing native events.
   141    * It is set to true while a nested native event loop (eEventloopOther)
   142    * is processing gecko events in NativeEventCallback(), thus queuing up
   143    * native events until we return to that loop (bug 420148).
   144    * We force mBlockNativeEvent to false in case handling one of the gecko
   145    * events spins up a nested XPCOM event loop (eg. modal window) which would
   146    * otherwise lead to a "deadlock" where native events aren't processed at all.
   147    */
   148   bool mBlockNativeEvent;
   149   /**
   150    * Tracks whether we have processed any gecko events in NativeEventCallback so
   151    * that we can avoid erroneously entering a blocking loop waiting for gecko
   152    * events to show up during OnProcessNextEvent.  This is required because on
   153    * OS X ProcessGeckoEvents may be invoked inside the context of
   154    * ProcessNextNativeEvent and may result in NativeEventCallback being invoked
   155    * and in turn invoking NS_ProcessPendingEvents.  Because
   156    * ProcessNextNativeEvent may be invoked prior to the NS_HasPendingEvents
   157    * waiting loop, this is the only way to make the loop aware that events may
   158    * have been processed.
   159    *
   160    * This variable is set to false in OnProcessNextEvent prior to the first
   161    * call to DoProcessNextNativeEvent.  It is set to true by
   162    * NativeEventCallback after calling NS_ProcessPendingEvents.
   163    */
   164   bool mProcessedGeckoEvents;
   165 };
   167 #endif // nsBaseAppShell_h__

mercurial