Bug 672175 part.11 Move MOZ_WM_MOUSE*WHEEL handler into MouseScrollHandler r=jimm
authorMasayuki Nakano <masayuki@d-toybox.com>
Tue, 06 Mar 2012 12:20:29 +0900
changeset 88353 b1ad777954d39f27445a7f5f9cc5f3a16064af7c
parent 88352 40c7eec54521f637f7bb5bafa376486def1887c2
child 88354 a48199569fee05320d448dece4db9067d988e05a
push id22194
push usermak77@bonardo.net
push dateWed, 07 Mar 2012 09:33:54 +0000
treeherdermozilla-central@8ef88a69f861 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimm
bugs672175
milestone13.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 672175 part.11 Move MOZ_WM_MOUSE*WHEEL handler into MouseScrollHandler r=jimm
widget/windows/WinMouseScrollHandler.cpp
widget/windows/WinMouseScrollHandler.h
widget/windows/nsWindow.cpp
widget/windows/nsWindow.h
--- a/widget/windows/WinMouseScrollHandler.cpp
+++ b/widget/windows/WinMouseScrollHandler.cpp
@@ -134,16 +134,23 @@ MouseScrollHandler::ProcessMessage(nsWin
         return false;
       }
       if (wParam == SPI_SETWHEELSCROLLLINES ||
           wParam == SPI_SETWHEELSCROLLCHARS) {
         sInstance->mSystemSettings.MarkDirty();
       }
       return false;
 
+    case MOZ_WM_MOUSEVWHEEL:
+    case MOZ_WM_MOUSEHWHEEL:
+      GetInstance()->HandleMouseWheelMessage(aWindow, msg, wParam, lParam);
+      // Doesn't need to call next wndproc for internal wheel message.
+      aEatMessage = true;
+      return true;
+
     case WM_KEYDOWN:
     case WM_KEYUP:
       PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS,
         ("MouseScroll::ProcessMessage(): aWindow=%p, "
          "msg=%s(0x%04X), wParam=0x%02X, ::GetMessageTime()=%d",
          aWindow, msg == WM_KEYDOWN ? "WM_KEYDOWN" :
                     msg == WM_KEYUP ? "WM_KEYUP" : "Unknown", msg, wParam,
          ::GetMessageTime()));
@@ -261,16 +268,108 @@ MouseScrollHandler::GetScrollTargetInfo(
      "pixelsPerUnit: %d }",
      aWindow, GetBoolName(result.dispatchPixelScrollEvent),
      GetBoolName(result.reversePixelScrollDirection), result.actualScrollAmount,
      result.actualScrollAction, result.pixelsPerUnit));
 
   return result;
 }
 
+void
+MouseScrollHandler::HandleMouseWheelMessage(nsWindow* aWindow,
+                                            UINT aMessage,
+                                            WPARAM aWParam,
+                                            LPARAM aLParam)
+{
+  NS_ABORT_IF_FALSE(
+    (aMessage == MOZ_WM_MOUSEVWHEEL || aMessage == MOZ_WM_MOUSEHWHEEL),
+    "HandleMouseWheelMessage must be called with "
+    "MOZ_WM_MOUSEVWHEEL or MOZ_WM_MOUSEHWHEEL");
+
+  PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS,
+    ("MouseScroll::HandleMouseWheelMessage: aWindow=%p, "
+     "aMessage=MOZ_WM_MOUSE%sWHEEL, aWParam=0x%08X, aLParam=0x%08X",
+     aWindow, aMessage == MOZ_WM_MOUSEVWHEEL ? "V" : "H",
+     aWParam, aLParam));
+
+  EventInfo eventInfo(aWindow, WinUtils::GetNativeMessage(aMessage),
+                      aWParam, aLParam);
+  if (!eventInfo.CanDispatchMouseScrollEvent()) {
+    PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS,
+      ("MouseScroll::HandleMouseWheelMessage: Cannot dispatch the events"));
+    mLastEventInfo.ResetTransaction();
+    return;
+  }
+
+  // Discard the remaining delta if current wheel message and last one are
+  // received by different window or to scroll different direction or
+  // different unit scroll.  Furthermore, if the last event was too old.
+  if (!mLastEventInfo.CanContinueTransaction(eventInfo)) {
+    mLastEventInfo.ResetTransaction();
+  }
+
+  mLastEventInfo.RecordEvent(eventInfo);
+
+  nsModifierKeyState modKeyState = GetModifierKeyState();
+
+  // Before dispatching line scroll event, we should get the current scroll
+  // event target information for pixel scroll.
+  ScrollTargetInfo scrollTargetInfo =
+    GetScrollTargetInfo(aWindow, eventInfo, modKeyState);
+
+  // Grab the widget, it might be destroyed by a DOM event handler.
+  nsRefPtr<nsWindow> kungFuDethGrip(aWindow);
+
+  nsMouseScrollEvent scrollEvent(true, NS_MOUSE_SCROLL, aWindow);
+  if (mLastEventInfo.InitMouseScrollEvent(aWindow, scrollEvent,
+                                          scrollTargetInfo, modKeyState)) {
+    PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS,
+      ("MouseScroll::HandleMouseWheelMessage: dispatching "
+       "NS_MOUSE_SCROLL event"));
+    DispatchEvent(aWindow, scrollEvent);
+    if (aWindow->Destroyed()) {
+      PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS,
+        ("MouseScroll::HandleMouseWheelMessage: The window was destroyed "
+         "by NS_MOUSE_SCROLL event"));
+      mLastEventInfo.ResetTransaction();
+      return;
+    }
+  }
+#ifdef PR_LOGGING
+  else {
+    PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS,
+      ("MouseScroll::HandleMouseWheelMessage: NS_MOUSE_SCROLL event is not "
+       "dispatched"));
+  }
+#endif
+
+  nsMouseScrollEvent pixelEvent(true, NS_MOUSE_PIXEL_SCROLL, aWindow);
+  if (mLastEventInfo.InitMousePixelScrollEvent(aWindow, pixelEvent,
+                                               scrollTargetInfo, modKeyState)) {
+    PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS,
+      ("MouseScroll::HandleMouseWheelMessage: dispatching "
+       "NS_MOUSE_PIXEL_SCROLL event"));
+    DispatchEvent(aWindow, pixelEvent);
+    if (aWindow->Destroyed()) {
+      PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS,
+        ("MouseScroll::HandleMouseWheelMessage: The window was destroyed "
+         "by NS_MOUSE_PIXEL_SCROLL event"));
+      mLastEventInfo.ResetTransaction();
+      return;
+    }
+  }
+#ifdef PR_LOGGING
+  else {
+    PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS,
+      ("MouseScroll::HandleMouseWheelMessage: NS_MOUSE_PIXEL_SCROLL event is "
+       "not dispatched"));
+  }
+#endif
+}
+
 /******************************************************************************
  *
  * EventInfo
  *
  ******************************************************************************/
 
 MouseScrollHandler::EventInfo::EventInfo(nsWindow* aWindow,
                                          UINT aMessage,
--- a/widget/windows/WinMouseScrollHandler.h
+++ b/widget/windows/WinMouseScrollHandler.h
@@ -30,37 +30,50 @@ public:
 
   static bool ProcessMessage(nsWindow* aWindow,
                              UINT msg,
                              WPARAM wParam,
                              LPARAM lParam,
                              LRESULT *aRetValue,
                              bool &aEatMessage);
 
-  /**
-   * GetModifierKeyState() returns current modifier key state.
-   * Note that some devices need some hack for the modifier key state.
-   * This method does it automatically.
-   */
-  static nsModifierKeyState GetModifierKeyState();
-
 private:
   MouseScrollHandler();
   ~MouseScrollHandler();
 
   static MouseScrollHandler* sInstance;
 
   /**
    * DispatchEvent() dispatches aEvent on aWindow.
    *
    * @return TRUE if the event was consumed.  Otherwise, FALSE.
    */
   static bool DispatchEvent(nsWindow* aWindow, nsGUIEvent& aEvent);
 
-public:
+  /**
+   * GetModifierKeyState() returns current modifier key state.
+   * Note that some devices need some hack for the modifier key state.
+   * This method does it automatically.
+   */
+  static nsModifierKeyState GetModifierKeyState();
+
+  /**
+   * HandleMouseWheelMessage() processes MOZ_WM_MOUSEVWHEEL and
+   * MOZ_WM_MOUSEHWHEEL which are posted when one of our windows received
+   * WM_MOUSEWHEEL or WM_MOUSEHWHEEL for avoiding deadlock with OOPP.
+   *
+   * @param aWindow     A window which receives the wheel message.
+   * @param aMessage    MOZ_WM_MOUSEWHEEL or MOZ_WM_MOUSEHWHEEL.
+   * @param aWParam     The wParam value of the original message.
+   * @param aLParam     The lParam value of the original message.
+   */
+  void HandleMouseWheelMessage(nsWindow* aWindow,
+                               UINT aMessage,
+                               WPARAM aWParam,
+                               LPARAM aLParam);
 
   class EventInfo;
   /**
    * GetScrollTargetInfo() returns scroll target information which is
    * computed from the result of NS_QUERY_SCROLL_TARGET_INFO event.
    *
    * @param aWindow           An nsWindow which is handling the event.
    * @param aEventInfo        The EventInfo which is being handled.
@@ -97,21 +110,16 @@ public:
 
     PRInt32 GetNativeDelta() const { return mDelta; }
     HWND GetWindowHandle() const { return mWnd; }
     const TimeStamp& GetTimeStamp() const { return mTimeStamp; }
     bool IsVertical() const { return mIsVertical; }
     bool IsPositive() const { return (mDelta > 0); }
     bool IsPage() const { return mIsPage; }
 
-    LRESULT ComputeMessageResult(bool aWeProcessed) const
-    {
-      return IsVertical() ? !aWeProcessed : aWeProcessed;
-    }
-
     /**
      * @return          Number of lines or pages scrolled per WHEEL_DELTA.
      */
     PRInt32 GetScrollAmount() const;
 
     /**
      * @return          One or more values of
      *                  nsMouseScrollEvent::nsMouseScrollFlags.
@@ -203,22 +211,18 @@ public:
     static PRInt32 RoundDelta(double aDelta);
 
     // The remaining native delta value (i.e., not handled by previous
     // message handler).
     PRInt32 mRemainingDeltaForScroll;
     PRInt32 mRemainingDeltaForPixel;
   };
 
-  LastEventInfo& GetLastEventInfo() { return mLastEventInfo; }
-
-private:
   LastEventInfo mLastEventInfo;
 
-public:
   class SystemSettings {
   public:
     SystemSettings() : mInitialized(false) {}
 
     void Init();
     void MarkDirty();
 
     PRInt32 GetScrollAmount(bool aForVertical) const
@@ -235,22 +239,16 @@ public:
     }
 
   private:
     bool mInitialized;
     PRInt32 mScrollLines;
     PRInt32 mScrollChars;
   };
 
-  SystemSettings& GetSystemSettings()
-  {
-    return mSystemSettings;
-  }
-
-private:
   SystemSettings mSystemSettings;
 
 public:
   class UserPrefs {
   public:
     UserPrefs();
     ~UserPrefs();
 
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -5216,31 +5216,16 @@ bool nsWindow::ProcessMessage(UINT msg, 
   case WM_MOUSEWHEEL:
   case WM_MOUSEHWHEEL:
     OnMouseWheel(msg, wParam, lParam, aRetValue);
     // We don't need to call next wndproc WM_MOUSEWHEEL and WM_MOUSEHWHEEL.
     // We should consume them always.  If the messages would be handled by
     // our window again, it causes making infinite message loop.
     return true;
 
-  case MOZ_WM_MOUSEVWHEEL:
-  case MOZ_WM_MOUSEHWHEEL:
-    {
-      UINT nativeMessage = WinUtils::GetNativeMessage(msg);
-      // If OnMouseWheel returns true, the event was forwarded directly to another
-      // mozilla window message handler (ProcessMessage). In this case the return
-      // value of the forwarded event is in 'result' which we should return immediately.
-      // If OnMouseWheel returns false, OnMouseWheel processed the event internally.
-      // 'result' and 'aRetValue' will be set based on what we did with the event, so
-      // we should fall through.
-      OnMouseWheelInternal(nativeMessage, wParam, lParam, aRetValue);
-      // Doesn't need to call next wndproc for internal message.
-      return true;
-    }
-
   case WM_DWMCOMPOSITIONCHANGED:
     // First, update the compositor state to latest one. All other methods
     // should use same state as here for consistency painting.
     nsUXThemeData::CheckForCompositor(true);
 
     UpdateNonClientMargins();
     RemovePropW(mWnd, kManageWindowInfoProperty);
     BroadcastMsg(mWnd, WM_DWMCOMPOSITIONCHANGED);
@@ -6253,77 +6238,16 @@ bool nsWindow::OnGesture(WPARAM wParam, 
   }
 
   // Only close this if we process and return true.
   mGesture.CloseGestureInfoHandle((HGESTUREINFO)lParam);
 
   return true; // Handled
 }
 
-/**
- * OnMouseWheelInternal - mouse wheel event processing.
- * aMessage may be WM_MOUSEWHEEL or WM_MOUSEHWHEEL but this is called when
- * ProcessMessage() handles MOZ_WM_MOUSEVWHEEL or MOZ_WM_MOUSEHWHEEL.
- */
-void
-nsWindow::OnMouseWheelInternal(UINT aMessage, WPARAM aWParam, LPARAM aLParam,
-                               LRESULT *aRetValue)
-{
-  MouseScrollHandler* handler = MouseScrollHandler::GetInstance();
-  MouseScrollHandler::EventInfo eventInfo(this, aMessage, aWParam, aLParam);
-  if (!eventInfo.CanDispatchMouseScrollEvent()) {
-    handler->GetLastEventInfo().ResetTransaction();
-    *aRetValue = eventInfo.ComputeMessageResult(false);
-    return;
-  }
-
-  MouseScrollHandler::LastEventInfo& lastEventInfo =
-                                       handler->GetLastEventInfo();
-
-  // Discard the remaining delta if current wheel message and last one are
-  // received by different window or to scroll different direction or
-  // different unit scroll.  Furthermore, if the last event was too old.
-  if (!lastEventInfo.CanContinueTransaction(eventInfo)) {
-    lastEventInfo.ResetTransaction();
-  }
-
-  lastEventInfo.RecordEvent(eventInfo);
-
-  // means we process this message
-  *aRetValue = eventInfo.ComputeMessageResult(true);
-
-  nsModifierKeyState modKeyState = MouseScrollHandler::GetModifierKeyState();
-
-  // Before dispatching line scroll event, we should get the current scroll
-  // event target information for pixel scroll.
-  MouseScrollHandler::ScrollTargetInfo scrollTargetInfo =
-    handler->GetScrollTargetInfo(this, eventInfo, modKeyState);
-
-  nsMouseScrollEvent scrollEvent(true, NS_MOUSE_SCROLL, this);
-  if (lastEventInfo.InitMouseScrollEvent(this, scrollEvent,
-                                         scrollTargetInfo, modKeyState)) {
-    DispatchWindowEvent(&scrollEvent);
-    if (mOnDestroyCalled) {
-      lastEventInfo.ResetTransaction();
-      return;
-    }
-  }
-
-  nsMouseScrollEvent pixelEvent(true, NS_MOUSE_PIXEL_SCROLL, this);
-  if (lastEventInfo.InitMousePixelScrollEvent(this, pixelEvent,
-                                              scrollTargetInfo, modKeyState)) {
-    DispatchWindowEvent(&pixelEvent);
-    if (mOnDestroyCalled) {
-      lastEventInfo.ResetTransaction();
-      return;
-    }
-  }
-  return;
-}
-
 static bool
 StringCaseInsensitiveEquals(const PRUnichar* aChars1, const PRUint32 aNumChars1,
                             const PRUnichar* aChars2, const PRUint32 aNumChars2)
 {
   if (aNumChars1 != aNumChars2)
     return false;
 
   nsCaseInsensitiveStringComparator comp;
--- a/widget/windows/nsWindow.h
+++ b/widget/windows/nsWindow.h
@@ -402,19 +402,16 @@ protected:
   bool                    OnGesture(WPARAM wParam, LPARAM lParam);
   bool                    OnTouch(WPARAM wParam, LPARAM lParam);
   bool                    OnHotKey(WPARAM wParam, LPARAM lParam);
   BOOL                    OnInputLangChange(HKL aHKL);
   bool                    OnPaint(HDC aDC, PRUint32 aNestingLevel);
   void                    OnWindowPosChanged(WINDOWPOS *wp, bool& aResult);
   void                    OnMouseWheel(UINT aMsg, WPARAM aWParam,
                                        LPARAM aLParam, LRESULT *aRetValue);
-  void                    OnMouseWheelInternal(UINT aMessage, WPARAM aWParam,
-                                               LPARAM aLParam,
-                                               LRESULT *aRetValue);
   void                    OnWindowPosChanging(LPWINDOWPOS& info);
   void                    OnSysColorChanged();
 
   /**
    * Function that registers when the user has been active (used for detecting
    * when the user is idle).
    */
   void                    UserActivity();