From 6adeee540020ed0e46763c65b782317ea437902d Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Tue, 6 Mar 2012 12:20:29 +0900 Subject: [PATCH] Bug 672175 part.13 Compute cursor position at WM_MOUSEWHEEL and WM_MOUSEHWHEEL in MouseScrollHandler r=jimm --- widget/windows/WinMouseScrollHandler.cpp | 68 ++++++++++++++++++++++++ widget/windows/WinMouseScrollHandler.h | 29 ++++++++++ widget/windows/nsWindow.cpp | 33 +----------- 3 files changed, 99 insertions(+), 31 deletions(-) diff --git a/widget/windows/WinMouseScrollHandler.cpp b/widget/windows/WinMouseScrollHandler.cpp index 947b70750a8..06dfd9f23dd 100644 --- a/widget/windows/WinMouseScrollHandler.cpp +++ b/widget/windows/WinMouseScrollHandler.cpp @@ -65,6 +65,8 @@ bool MouseScrollHandler::Device::Elantech::sUseSwipeHack = false; bool MouseScrollHandler::Device::Elantech::sUsePinchHack = false; DWORD MouseScrollHandler::Device::Elantech::sZoomUntil = 0; +bool MouseScrollHandler::Device::SetPoint::sMightBeUsing = false; + // The duration until timeout of events transaction. The value is 1.5 sec, // it's just a magic number, it was suggested by Logitech's engineer, see // bug 605648 comment 90. @@ -197,6 +199,26 @@ MouseScrollHandler::GetModifierKeyState(UINT aMessage) return result; } +POINT +MouseScrollHandler::ComputeMessagePos(UINT aMessage, + WPARAM aWParam, + LPARAM aLParam) +{ + POINT point; + if (Device::SetPoint::IsGetMessagePosResponseValid(aMessage, + aWParam, aLParam)) { + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::ComputeMessagePos: Using ::GetCursorPos()")); + ::GetCursorPos(&point); + } else { + DWORD dwPoints = ::GetMessagePos(); + point.x = GET_X_LPARAM(dwPoints); + point.y = GET_Y_LPARAM(dwPoints); + } + + return point; +} + MouseScrollHandler::ScrollTargetInfo MouseScrollHandler::GetScrollTargetInfo( nsWindow* aWindow, @@ -1151,5 +1173,51 @@ MouseScrollHandler::Device::UltraNav::IsObsoleteDriverInstalled() return majorVersion < 15 || majorVersion == 15 && minorVersion == 0; } +/****************************************************************************** + * + * Device::SetPoint + * + ******************************************************************************/ + +/* static */ +bool +MouseScrollHandler::Device::SetPoint::IsGetMessagePosResponseValid( + UINT aMessage, + WPARAM aWParam, + LPARAM aLParam) +{ + if (aMessage != WM_MOUSEHWHEEL) { + return false; + } + + DWORD messagePos = ::GetMessagePos(); + + // XXX We should check whether SetPoint is installed or not by registry. + + // SetPoint, Logitech (Logicool) mouse driver, (confirmed with 4.82.11 and + // MX-1100) always sets 0 to the lParam of WM_MOUSEHWHEEL. The driver SENDs + // one message at first time, this time, ::GetMessagePos() works fine. + // Then, we will return 0 (0 means we process it) to the message. Then, the + // driver will POST the same messages continuously during the wheel tilted. + // But ::GetMessagePos() API always returns (0, 0) for them, even if the + // actual mouse cursor isn't 0,0. Therefore, we cannot trust the result of + // ::GetMessagePos API if the sender is SetPoint. + if (!sMightBeUsing && !aLParam && (DWORD)aLParam != messagePos && + ::InSendMessage()) { + sMightBeUsing = true; + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::Device::SetPoint::IsGetMessagePosResponseValid(): " + "Might using SetPoint")); + } else if (sMightBeUsing && aLParam != 0 && ::InSendMessage()) { + // The user has changed the mouse from Logitech's to another one (e.g., + // the user has changed to the touchpad of the notebook. + sMightBeUsing = false; + PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS, + ("MouseScroll::Device::SetPoint::IsGetMessagePosResponseValid(): " + "Might stop using SetPoint")); + } + return (sMightBeUsing && !aLParam && !messagePos); +} + } // namespace widget } // namespace mozilla diff --git a/widget/windows/WinMouseScrollHandler.h b/widget/windows/WinMouseScrollHandler.h index c441c9d9a89..2795239c2b3 100644 --- a/widget/windows/WinMouseScrollHandler.h +++ b/widget/windows/WinMouseScrollHandler.h @@ -35,6 +35,21 @@ public: LRESULT *aRetValue, bool &aEatMessage); + /** + * ComputeMessagePos() computes the cursor position when the message was + * added to the queue. + * + * @param aMessage Handling message. + * @param aWParam Handling message's wParam. + * @param aLParam Handling message's lParam. + * @return Mouse cursor position when the message is added to + * the queue or current cursor position if the result of + * ::GetMessagePos() is broken. + */ + POINT ComputeMessagePos(UINT aMessage, + WPARAM aWParam, + LPARAM aLParam); + private: MouseScrollHandler(); ~MouseScrollHandler(); @@ -367,6 +382,20 @@ public: static bool IsObsoleteDriverInstalled(); }; // class UltraNav + class SetPoint { + public: + /** + * SetPoint, Logitech's mouse driver, may report wrong cursor position + * for WM_MOUSEHWHEEL message. See comment in the implementation for + * the detail. + */ + static bool IsGetMessagePosResponseValid(UINT aMessage, + WPARAM aWParam, + LPARAM aLParam); + private: + static bool sMightBeUsing; + }; + static void Init(); static bool IsFakeScrollableWindowNeeded() diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp index fb5ee58fd5d..cd4bb3470b2 100644 --- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -7042,37 +7042,8 @@ nsWindow::OnMouseWheel(UINT aMsg, WPARAM aWParam, LPARAM aLParam, { *aRetValue = (aMsg != WM_MOUSEHWHEEL) ? TRUE : FALSE; - POINT point; - DWORD dwPoints = ::GetMessagePos(); - point.x = GET_X_LPARAM(dwPoints); - point.y = GET_Y_LPARAM(dwPoints); - - static bool sMayBeUsingLogitechMouse = false; - if (aMsg == WM_MOUSEHWHEEL) { - // Logitech (Logicool) mouse driver (confirmed with 4.82.11 and MX-1100) - // always sets 0 to the lParam of WM_MOUSEHWHEEL. The driver SENDs one - // message at first time, this time, ::GetMessagePos works fine. - // Then, we will return 0 (0 means we process it) to the message. Then, the - // driver will POST the same messages continuously during the wheel tilted. - // But ::GetMessagePos API always returns (0, 0), even if the actual mouse - // cursor isn't 0,0. Therefore, we cannot trust the result of - // ::GetMessagePos API if the sender is the driver. - if (!sMayBeUsingLogitechMouse && aLParam == 0 && (DWORD)aLParam != dwPoints && - ::InSendMessage()) { - sMayBeUsingLogitechMouse = true; - } else if (sMayBeUsingLogitechMouse && aLParam != 0 && ::InSendMessage()) { - // The user has changed the mouse from Logitech's to another one (e.g., - // the user has changed to the touchpad of the notebook. - sMayBeUsingLogitechMouse = false; - } - // If the WM_MOUSEHWHEEL comes from Logitech's mouse driver, and the - // ::GetMessagePos isn't correct, probably, we should use ::GetCursorPos - // instead. - if (sMayBeUsingLogitechMouse && aLParam == 0 && dwPoints == 0) { - ::GetCursorPos(&point); - } - } - + MouseScrollHandler* handler = MouseScrollHandler::GetInstance(); + POINT point = handler->ComputeMessagePos(aMsg, aWParam, aLParam); HWND underCursorWnd = ::WindowFromPoint(point); if (!underCursorWnd) { return;