Bug 1219150 - EventStateManager::{LatestUserInputStart, UserInputCount};r=smaug
authorDavid Rajchenbach-Teller <dteller@mozilla.com>
Thu, 03 Dec 2015 17:40:45 -0800
changeset 275540 badf9e19d881a54c7aa577414c4b9fb067de96b2
parent 275539 5b034080510801588fa0fe9455022172a26d990e
child 275541 6ad057f8152042a39dc3a92371352121ee67f30c
push id16555
push usermozilla@noorenberghe.ca
push dateFri, 04 Dec 2015 01:43:46 +0000
treeherderfx-team@badf9e19d881 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1219150
milestone45.0a1
Bug 1219150 - EventStateManager::{LatestUserInputStart, UserInputCount};r=smaug To detect slow behaviors, it is useful to find out whether a user input was handled between two instants. This patch introduces EventStateManager::UserInputCount, which lets client code determine whether user input was handled between two points of execution, and EventStateManager::LatestUserInputStart, which lets client code find out when the altest user input was handled.
dom/events/EventStateManager.cpp
dom/events/EventStateManager.h
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -259,31 +259,33 @@ NS_INTERFACE_MAP_END
 
 /******************************************************************/
 /* mozilla::EventStateManager                                     */
 /******************************************************************/
 
 static uint32_t sESMInstanceCount = 0;
 static bool sPointerEventEnabled = false;
 
+uint64_t EventStateManager::sUserInputCounter = 0;
 int32_t EventStateManager::sUserInputEventDepth = 0;
 bool EventStateManager::sNormalLMouseEventInProcess = false;
 EventStateManager* EventStateManager::sActiveESM = nullptr;
 nsIDocument* EventStateManager::sMouseOverDocument = nullptr;
 nsWeakFrame EventStateManager::sLastDragOverFrame = nullptr;
 LayoutDeviceIntPoint EventStateManager::sLastRefPoint = kInvalidRefPoint;
 CSSIntPoint EventStateManager::sLastScreenPoint = CSSIntPoint(0, 0);
 LayoutDeviceIntPoint EventStateManager::sSynthCenteringPoint = kInvalidRefPoint;
 CSSIntPoint EventStateManager::sLastClientPoint = CSSIntPoint(0, 0);
 bool EventStateManager::sIsPointerLocked = false;
 // Reference to the pointer locked element.
 nsWeakPtr EventStateManager::sPointerLockedElement;
 // Reference to the document which requested pointer lock.
 nsWeakPtr EventStateManager::sPointerLockedDoc;
 nsCOMPtr<nsIContent> EventStateManager::sDragOverContent = nullptr;
+TimeStamp EventStateManager::sLatestUserInputStart;
 TimeStamp EventStateManager::sHandlingInputStart;
 
 EventStateManager::WheelPrefs*
   EventStateManager::WheelPrefs::sInstance = nullptr;
 EventStateManager::DeltaAccumulator*
   EventStateManager::DeltaAccumulator::sInstance = nullptr;
 
 EventStateManager::EventStateManager()
--- a/dom/events/EventStateManager.h
+++ b/dom/events/EventStateManager.h
@@ -190,41 +190,63 @@ public:
 
   nsresult SetCursor(int32_t aCursor, imgIContainer* aContainer,
                      bool aHaveHotspot, float aHotspotX, float aHotspotY,
                      nsIWidget* aWidget, bool aLockCursor); 
 
   static void StartHandlingUserInput()
   {
     ++sUserInputEventDepth;
+    ++sUserInputCounter;
     if (sUserInputEventDepth == 1) {
-      sHandlingInputStart = TimeStamp::Now();
+      sLatestUserInputStart = sHandlingInputStart = TimeStamp::Now();
     }
   }
 
   static void StopHandlingUserInput()
   {
     --sUserInputEventDepth;
     if (sUserInputEventDepth == 0) {
       sHandlingInputStart = TimeStamp();
     }
   }
 
   /**
-   * Returns true if the current code is being executed as a result of user input.
-   * This includes timers or anything else that is initiated from user input.
-   * However, mouse over events are not counted as user input, nor are
-   * page load events. If this method is called from asynchronously executed code,
-   * such as during layout reflows, it will return false. If more time has elapsed
-   * since the user input than is specified by the
-   * dom.event.handling-user-input-time-limit pref (default 1 second), this
-   * function also returns false.
+   * Returns true if the current code is being executed as a result of
+   * user input.  This includes anything that is initiated by user,
+   * with the exception of page load events or mouse over events. If
+   * this method is called from asynchronously executed code, such as
+   * during layout reflows, it will return false. If more time has
+   * elapsed since the user input than is specified by the
+   * dom.event.handling-user-input-time-limit pref (default 1 second),
+   * this function also returns false.
    */
   static bool IsHandlingUserInput();
 
+  /**
+   * Get the number of user inputs handled since process start. This
+   * includes anything that is initiated by user, with the exception
+   * of page load events or mouse over events.
+   */
+  static uint64_t UserInputCount()
+  {
+    return sUserInputCounter;
+  }
+
+  /**
+   * Get the timestamp at which the latest user input was handled.
+   *
+   * Guaranteed to be monotonic. Until the first user input, return
+   * the epoch.
+   */
+  static TimeStamp LatestUserInputStart()
+  {
+    return sLatestUserInputStart;
+  }
+
   nsPresContext* GetPresContext() { return mPresContext; }
 
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(EventStateManager,
                                            nsIObserver)
 
   static nsIDocument* sMouseOverDocument;
 
   static EventStateManager* GetActiveEventStateManager() { return sActiveESM; }
@@ -916,27 +938,42 @@ private:
   RefPtr<IMEContentObserver> mIMEContentObserver;
 
   uint32_t mLClickCount;
   uint32_t mMClickCount;
   uint32_t mRClickCount;
 
   bool m_haveShutdown;
 
-  // Time at which we began handling user input.
+  // Time at which we began handling user input. Reset to the epoch
+  // once we have finished handling user input.
   static TimeStamp sHandlingInputStart;
 
+  // Time at which we began handling the latest user input. Not reset
+  // at the end of the input.
+  static TimeStamp sLatestUserInputStart;
+
   RefPtr<OverOutElementsWrapper> mMouseEnterLeaveHelper;
   nsRefPtrHashtable<nsUint32HashKey, OverOutElementsWrapper> mPointersEnterLeaveHelper;
 
 public:
   static nsresult UpdateUserActivityTimer(void);
   // Array for accesskey support
   nsCOMArray<nsIContent> mAccessKeys;
 
+  // The number of user inputs handled since process start. This
+  // includes anything that is initiated by user, with the exception
+  // of page load events or mouse over events.
+  static uint64_t sUserInputCounter;
+
+  // The current depth of user inputs. This includes anything that is
+  // initiated by user, with the exception of page load events or
+  // mouse over events. Incremented whenever we start handling a user
+  // input, decremented when we have finished handling a user
+  // input. This depth is *not* reset in case of nested event loops.
   static int32_t sUserInputEventDepth;
   
   static bool sNormalLMouseEventInProcess;
 
   static EventStateManager* sActiveESM;
   
   static void ClearGlobalActiveContent(EventStateManager* aClearer);