nsBaseAppShell.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  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/. */
  5. #ifndef nsBaseAppShell_h__
  6. #define nsBaseAppShell_h__
  7. #include "mozilla/Atomics.h"
  8. #include "nsIAppShell.h"
  9. #include "nsIThreadInternal.h"
  10. #include "nsIObserver.h"
  11. #include "nsIRunnable.h"
  12. #include "nsCOMPtr.h"
  13. #include "nsTArray.h"
  14. #include "prinrval.h"
  15. /**
  16. * A singleton that manages the UI thread's event queue. Subclass this class
  17. * to enable platform-specific event queue support.
  18. */
  19. class nsBaseAppShell : public nsIAppShell, public nsIThreadObserver,
  20. public nsIObserver
  21. {
  22. public:
  23. NS_DECL_THREADSAFE_ISUPPORTS
  24. NS_DECL_NSIAPPSHELL
  25. NS_DECL_NSITHREADOBSERVER
  26. NS_DECL_NSIOBSERVER
  27. nsBaseAppShell();
  28. protected:
  29. virtual ~nsBaseAppShell();
  30. /**
  31. * This method is called by subclasses when the app shell singleton is
  32. * instantiated.
  33. */
  34. nsresult Init();
  35. /**
  36. * Called by subclasses from a native event. See ScheduleNativeEventCallback.
  37. */
  38. void NativeEventCallback();
  39. /**
  40. * Make a decision as to whether or not NativeEventCallback will
  41. * trigger gecko event processing when there are pending gecko
  42. * events.
  43. */
  44. virtual void DoProcessMoreGeckoEvents();
  45. /**
  46. * Implemented by subclasses. Invoke NativeEventCallback from a native
  47. * event. This method may be called on any thread.
  48. */
  49. virtual void ScheduleNativeEventCallback() = 0;
  50. /**
  51. * Implemented by subclasses. Process the next native event. Only wait for
  52. * the next native event if mayWait is true. This method is only called on
  53. * the main application thread.
  54. *
  55. * @param mayWait
  56. * If "true", then this method may wait if necessary for the next available
  57. * native event. DispatchNativeEvent may be called to unblock a call to
  58. * ProcessNextNativeEvent that is waiting.
  59. * @return
  60. * This method returns "true" if a native event was processed.
  61. */
  62. virtual bool ProcessNextNativeEvent(bool mayWait) = 0;
  63. int32_t mSuspendNativeCount;
  64. uint32_t mEventloopNestingLevel;
  65. private:
  66. bool DoProcessNextNativeEvent(bool mayWait);
  67. bool DispatchDummyEvent(nsIThread* target);
  68. void IncrementEventloopNestingLevel();
  69. void DecrementEventloopNestingLevel();
  70. nsCOMPtr<nsIRunnable> mDummyEvent;
  71. /**
  72. * mBlockedWait points back to a slot that controls the wait loop in
  73. * an outer OnProcessNextEvent invocation. Nested calls always set
  74. * it to false to unblock an outer loop, since all events may
  75. * have been consumed by the inner event loop(s).
  76. */
  77. bool *mBlockedWait;
  78. int32_t mFavorPerf;
  79. mozilla::Atomic<bool> mNativeEventPending;
  80. PRIntervalTime mStarvationDelay;
  81. PRIntervalTime mSwitchTime;
  82. PRIntervalTime mLastNativeEventTime;
  83. enum EventloopNestingState {
  84. eEventloopNone, // top level thread execution
  85. eEventloopXPCOM, // innermost native event loop is ProcessNextNativeEvent
  86. eEventloopOther // innermost native event loop is a native library/plugin etc
  87. };
  88. EventloopNestingState mEventloopNestingState;
  89. bool mRunning;
  90. bool mExiting;
  91. /**
  92. * mBlockNativeEvent blocks the appshell from processing native events.
  93. * It is set to true while a nested native event loop (eEventloopOther)
  94. * is processing gecko events in NativeEventCallback(), thus queuing up
  95. * native events until we return to that loop (bug 420148).
  96. * We force mBlockNativeEvent to false in case handling one of the gecko
  97. * events spins up a nested XPCOM event loop (eg. modal window) which would
  98. * otherwise lead to a "deadlock" where native events aren't processed at all.
  99. */
  100. bool mBlockNativeEvent;
  101. /**
  102. * Tracks whether we have processed any gecko events in NativeEventCallback so
  103. * that we can avoid erroneously entering a blocking loop waiting for gecko
  104. * events to show up during OnProcessNextEvent. This is required because on
  105. * OS X ProcessGeckoEvents may be invoked inside the context of
  106. * ProcessNextNativeEvent and may result in NativeEventCallback being invoked
  107. * and in turn invoking NS_ProcessPendingEvents. Because
  108. * ProcessNextNativeEvent may be invoked prior to the NS_HasPendingEvents
  109. * waiting loop, this is the only way to make the loop aware that events may
  110. * have been processed.
  111. *
  112. * This variable is set to false in OnProcessNextEvent prior to the first
  113. * call to DoProcessNextNativeEvent. It is set to true by
  114. * NativeEventCallback after calling NS_ProcessPendingEvents.
  115. */
  116. bool mProcessedGeckoEvents;
  117. };
  118. #endif // nsBaseAppShell_h__