diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index 4a0f25f396b5..1b2ae391e4c9 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -1813,11 +1813,6 @@ pref("ui.trackpoint_hack.enabled", -1); // some trackpad drivers behave better. pref("ui.window_class_override", ""); -// Enables or disables the Elantech gesture hacks. -1 is autodetect, 0 is off, -// and 1 is on. Set this to 1 if three-finger swipe gestures do not cause -// page back/forward actions, or if pinch-to-zoom does not work. -pref("ui.elantech_gesture_hacks.enabled", -1); - # WINNT #endif diff --git a/widget/src/windows/nsAppShell.cpp b/widget/src/windows/nsAppShell.cpp index 8417864e80df..368b5f2a48eb 100644 --- a/widget/src/windows/nsAppShell.cpp +++ b/widget/src/windows/nsAppShell.cpp @@ -89,35 +89,29 @@ using mozilla::crashreporter::LSPAnnotate; //------------------------------------------------------------------------- -static PRBool PeekUIMessage(MSG* aMsg) +static BOOL PeekKeyAndIMEMessage(LPMSG msg, HWND hwnd) { - MSG keyMsg, imeMsg, mouseMsg, *pMsg = 0; - PRBool haveKeyMsg, haveIMEMsg, haveMouseMsg; - - haveKeyMsg = ::PeekMessageW(&keyMsg, NULL, WM_KEYFIRST, WM_IME_KEYLAST, PM_NOREMOVE); - haveIMEMsg = ::PeekMessageW(&imeMsg, NULL, NS_WM_IMEFIRST, NS_WM_IMELAST, PM_NOREMOVE); - haveMouseMsg = ::PeekMessageW(&mouseMsg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_NOREMOVE); - - if (haveKeyMsg) { - pMsg = &keyMsg; - } - if (haveIMEMsg && (!pMsg || imeMsg.time < pMsg->time)) { - pMsg = &imeMsg; + MSG msg1, msg2, *lpMsg; + BOOL b1, b2; + b1 = ::PeekMessageW(&msg1, NULL, WM_KEYFIRST, WM_IME_KEYLAST, PM_NOREMOVE); + b2 = ::PeekMessageW(&msg2, NULL, NS_WM_IMEFIRST, NS_WM_IMELAST, PM_NOREMOVE); + if (b1 || b2) { + if (b1 && b2) { + if (msg1.time < msg2.time) + lpMsg = &msg1; + else + lpMsg = &msg2; + } else if (b1) + lpMsg = &msg1; + else + lpMsg = &msg2; + if (!nsIMM32Handler::CanOptimizeKeyAndIMEMessages(lpMsg)) { + return false; + } + return ::PeekMessageW(msg, hwnd, lpMsg->message, lpMsg->message, PM_REMOVE); } - if (pMsg && !nsIMM32Handler::CanOptimizeKeyAndIMEMessages(pMsg)) { - return PR_FALSE; - } - - if (haveMouseMsg && (!pMsg || mouseMsg.time < pMsg->time)) { - pMsg = &mouseMsg; - } - - if (!pMsg) { - return PR_FALSE; - } - - return ::PeekMessageW(aMsg, NULL, pMsg->message, pMsg->message, PM_REMOVE); + return false; } /*static*/ LRESULT CALLBACK @@ -327,8 +321,10 @@ nsAppShell::ProcessNextNativeEvent(PRBool mayWait) do { MSG msg; - // Give priority to keyboard and mouse messages. - if (PeekUIMessage(&msg) || + // Give priority to system messages (in particular keyboard, mouse, timer, + // and paint messages). + if (PeekKeyAndIMEMessage(&msg, NULL) || + ::PeekMessageW(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE) || ::PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) { gotMessage = PR_TRUE; if (msg.message == WM_QUIT) { diff --git a/widget/src/windows/nsWindow.cpp b/widget/src/windows/nsWindow.cpp index 8aac38d6f487..7a2147608a82 100644 --- a/widget/src/windows/nsWindow.cpp +++ b/widget/src/windows/nsWindow.cpp @@ -299,8 +299,6 @@ int nsWindow::sTrimOnMinimize = 2; PRBool nsWindow::sDefaultTrackPointHack = PR_FALSE; // Default value for general window class (used when the pref is the empty string). const char* nsWindow::sDefaultMainWindowClass = kClassNameGeneral; -// Whether to enable the Elantech gesture hack. -PRBool nsWindow::sUseElantechGestureHacks = PR_FALSE; // If we're using D3D9, this will not be allowed during initial 5 seconds. bool nsWindow::sAllowD3D9 = false; @@ -472,7 +470,7 @@ nsWindow::nsWindow() : nsBaseWidget() #endif #if !defined(WINCE) - InitInputWorkaroundPrefDefaults(); + InitInputHackDefaults(); #endif // Init titlebar button info for custom frames. @@ -4653,24 +4651,6 @@ nsWindow::ProcessMessageForPlugin(const MSG &aMsg, PRBool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam, LRESULT *aRetValue) { - // For the Elantech Touchpad Zoom Gesture Hack, we should check that the - // system time (32-bit milliseconds) hasn't wrapped around. Otherwise we - // might get into the situation where wheel events for the next 50 days of - // system uptime are assumed to be Ctrl+Wheel events. (It is unlikely that - // we would get into that state, because the system would already need to be - // up for 50 days and the Control key message would need to be processed just - // before the system time overflow and the wheel message just after.) - // - // We also take the chance to reset mAssumeWheelIsZoomUntil if we simply have - // passed that time. - if (mAssumeWheelIsZoomUntil) { - DWORD msgTime = ::GetMessageTime(); - if (mAssumeWheelIsZoomUntil >= 0x80000000 && msgTime < 0x8000000 || - mAssumeWheelIsZoomUntil < msgTime) { - mAssumeWheelIsZoomUntil = 0; - } - } - // (Large blocks of code should be broken out into OnEvent handlers.) if (mWindowHook.Notify(mWnd, msg, wParam, lParam, aRetValue)) return PR_TRUE; @@ -5045,7 +5025,6 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam, case WM_KEYUP: { MSG nativeMsg = InitMSG(msg, wParam, lParam); - nativeMsg.time = ::GetMessageTime(); result = ProcessKeyUpMessage(nativeMsg, nsnull); DispatchPendingEvents(); } @@ -6725,18 +6704,8 @@ PRBool nsWindow::OnMouseWheel(UINT msg, WPARAM wParam, LPARAM lParam, PRBool& ge ::ReplyMessage(isVertical ? 0 : TRUE); #endif - // Assume the Control key is down if the Elantech touchpad has sent the - // mis-ordered WM_KEYDOWN/WM_MOUSEWHEEL messages. (See the comment in - // OnKeyUp.) - PRBool isControl; - if (mAssumeWheelIsZoomUntil && ::GetMessageTime() < mAssumeWheelIsZoomUntil) { - isControl = PR_TRUE; - } else { - isControl = IS_VK_DOWN(NS_VK_CONTROL); - } - scrollEvent.isShift = IS_VK_DOWN(NS_VK_SHIFT); - scrollEvent.isControl = isControl; + scrollEvent.isControl = IS_VK_DOWN(NS_VK_CONTROL); scrollEvent.isMeta = PR_FALSE; scrollEvent.isAlt = IS_VK_DOWN(NS_VK_ALT); InitEvent(scrollEvent); @@ -6784,37 +6753,6 @@ PRBool nsWindow::IsRedirectedKeyDownMessage(const MSG &aMsg) GetScanCode(sRedirectedKeyDown.lParam) == GetScanCode(aMsg.lParam)); } -void -nsWindow::PerformElantechSwipeGestureHack(UINT& aVirtualKeyCode, - nsModifierKeyState& aModKeyState) -{ - // The Elantech touchpad driver understands three-finger swipe left and - // right gestures, and translates them into Page Up and Page Down key - // events for most applications. For Firefox 3.6, it instead sends - // Alt+Left and Alt+Right to trigger browser back/forward actions. As - // with the Thinkpad Driver hack in nsWindow::Create, the change in - // HWND structure makes Firefox not trigger the driver's heuristics - // any longer. - // - // The Elantech driver actually sends these messages for a three-finger - // swipe right: - // - // WM_KEYDOWN virtual_key = 0xCC or 0xFF (depending on driver version) - // WM_KEYDOWN virtual_key = VK_NEXT - // WM_KEYUP virtual_key = VK_NEXT - // WM_KEYUP virtual_key = 0xCC or 0xFF - // - // so we use the 0xCC or 0xFF key modifier to detect whether the Page Down - // is due to the gesture rather than a regular Page Down keypress. We then - // pretend that we were went an Alt+Right keystroke instead. Similarly - // for VK_PRIOR and Alt+Left. - if ((aVirtualKeyCode == VK_NEXT || aVirtualKeyCode == VK_PRIOR) && - (IS_VK_DOWN(0xFF) || IS_VK_DOWN(0xCC))) { - aModKeyState.mIsAltDown = true; - aVirtualKeyCode = aVirtualKeyCode == VK_NEXT ? VK_RIGHT : VK_LEFT; - } -} - /** * nsWindow::OnKeyDown peeks into the message queue and pulls out * WM_CHAR messages for processing. During testing we don't want to @@ -6835,10 +6773,6 @@ LRESULT nsWindow::OnKeyDown(const MSG &aMsg, gKbdLayout.OnKeyDown(virtualKeyCode); #endif - if (sUseElantechGestureHacks) { - PerformElantechSwipeGestureHack(virtualKeyCode, aModKeyState); - } - // Use only DOMKeyCode for XP processing. // Use virtualKeyCode for gKbdLayout and native processing. UINT DOMKeyCode = nsIMM32Handler::IsComposingOn(this) ? @@ -7189,29 +7123,6 @@ LRESULT nsWindow::OnKeyUp(const MSG &aMsg, { UINT virtualKeyCode = aMsg.wParam; - if (sUseElantechGestureHacks) { - PerformElantechSwipeGestureHack(virtualKeyCode, aModKeyState); - - // Version 8 of the Elantech touchpad driver sends these messages for - // zoom gestures: - // - // WM_KEYDOWN virtual_key = 0xCC time = 10 - // WM_KEYDOWN virtual_key = VK_CONTROL time = 10 - // WM_MOUSEWHEEL time = ::GetTickCount() - // WM_KEYUP virtual_key = VK_CONTROL time = 10 - // WM_KEYUP virtual_key = 0xCC time = 10 - // - // The result of this is that we process all of the WM_KEYDOWN/WM_KEYUP - // messages first because their timestamps make them appear to have - // been sent before the WM_MOUSEWHEEL message. To work around this, - // we store the current time when we process the WM_KEYUP message and - // assume that any WM_MOUSEWHEEL message with a timestamp before that - // time is one that should be processed as if the Control key was down. - if (virtualKeyCode == VK_CONTROL && aMsg.time == 10) { - mAssumeWheelIsZoomUntil = ::GetTickCount(); - } - } - PR_LOG(gWindowsLog, PR_LOG_ALWAYS, ("nsWindow::OnKeyUp VK=%d\n", virtualKeyCode)); @@ -7651,125 +7562,6 @@ HWND nsWindow::FindOurProcessWindow(HWND aHWND) return nsnull; } -static PRBool PointInWindow(HWND aHWND, const POINT& aPoint) -{ - RECT bounds; - if (!::GetWindowRect(aHWND, &bounds)) { - return PR_FALSE; - } - - if (aPoint.x < bounds.left - || aPoint.x >= bounds.right - || aPoint.y < bounds.top - || aPoint.y >= bounds.bottom) { - return PR_FALSE; - } - - return PR_TRUE; -} - -static HWND FindTopmostWindowAtPoint(HWND aHWND, const POINT& aPoint) -{ - if (!::IsWindowVisible(aHWND) || !PointInWindow(aHWND, aPoint)) { - return 0; - } - - HWND childWnd = ::GetTopWindow(aHWND); - while (childWnd) { - HWND topmostWnd = FindTopmostWindowAtPoint(childWnd, aPoint); - if (topmostWnd) { - return topmostWnd; - } - childWnd = ::GetNextWindow(childWnd, GW_HWNDNEXT); - } - - return aHWND; -} - -struct FindOurWindowAtPointInfo -{ - POINT mInPoint; - HWND mOutHWND; -}; - -/* static */ -BOOL CALLBACK nsWindow::FindOurWindowAtPointCallback(HWND aHWND, LPARAM aLPARAM) -{ - if (!nsWindow::IsOurProcessWindow(aHWND)) { - // This isn't one of our top-level windows; continue enumerating. - return TRUE; - } - - // Get the top-most child window under the point. If there's no child - // window, and the point is within the top-level window, then the top-level - // window will be returned. (This is the usual case. A child window - // would be returned for plugins.) - FindOurWindowAtPointInfo* info = reinterpret_cast(aLPARAM); - HWND childWnd = FindTopmostWindowAtPoint(aHWND, info->mInPoint); - if (!childWnd) { - // This window doesn't contain the point; continue enumerating. - return TRUE; - } - - // Return the HWND and stop enumerating. - info->mOutHWND = childWnd; - return FALSE; -} - -/* static */ -HWND nsWindow::FindOurWindowAtPoint(const POINT& aPoint) -{ - FindOurWindowAtPointInfo info; - info.mInPoint = aPoint; - info.mOutHWND = 0; - - // This will enumerate all top-level windows in order from top to bottom. - EnumWindows(FindOurWindowAtPointCallback, reinterpret_cast(&info)); - return info.mOutHWND; -} - -typedef DWORD (*GetProcessImageFileNameProc)(HANDLE, LPTSTR, DWORD); - -// Determine whether the given HWND is the handle for the Elantech helper -// window. The helper window cannot be distinguished based on its -// window class, so we need to check if it is owned by the helper process, -// ETDCtrl.exe. -static PRBool IsElantechHelperWindow(HWND aHWND) -{ - static HMODULE hPSAPI = ::LoadLibrary(L"psapi.dll"); - static GetProcessImageFileNameProc pGetProcessImageFileName = - reinterpret_cast(::GetProcAddress(hPSAPI, "GetProcessImageFileNameW")); - - if (!pGetProcessImageFileName) { - return PR_FALSE; - } - - const PRUnichar* filenameSuffix = L"\\etdctrl.exe"; - const int filenameSuffixLength = 12; - - DWORD pid; - ::GetWindowThreadProcessId(aHWND, &pid); - - PRBool result = PR_FALSE; - - HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); - if (hProcess) { - PRUnichar path[256]; - if (pGetProcessImageFileName(hProcess, path, sizeof path)) { - path[255] = 0; - int pathLength = lstrlen(path); - if (pathLength >= filenameSuffixLength) { - if (lstrcmpi(path + pathLength - filenameSuffixLength, filenameSuffix) == 0) { - result = PR_TRUE; - } - } - } - ::CloseHandle(hProcess); - } - - return result; -} - // Scrolling helper function for handling plugins. // Return value indicates whether the calling function should handle this // aHandled indicates whether this was handled at all @@ -7824,14 +7616,6 @@ PRBool nsWindow::HandleScrollingPlugins(UINT aMsg, WPARAM aWParam, // is another app's window or no window under the // pointer. - if (sUseElantechGestureHacks && IsElantechHelperWindow(destWnd)) { - // The Elantech driver places a window right underneath the cursor - // when sending a WM_MOUSEWHEEL event to us as part of a pinch-to-zoom - // gesture. We detect that here, and search for our window that would - // be beneath the cursor if that window wasn't there. - destWnd = FindOurWindowAtPoint(point); - } - if (!destWnd) { // No window is under the pointer return PR_FALSE; // break, but continue processing @@ -9037,28 +8821,13 @@ void nsWindow::GetMainWindowClass(nsAString& aClass) aClass.AssignASCII(sDefaultMainWindowClass); } -/** - * Gets the Boolean value of a pref used to enable or disable an input - * workaround (like the Trackpoint hack). The pref can take values 0 (for - * disabled), 1 (for enabled) or -1 (to automatically detect whether to - * enable the workaround). - * - * @param aPrefName The name of the pref. - * @param aValueIfAutomatic Whether the given input workaround should be - * enabled by default. - */ -PRBool nsWindow::GetInputWorkaroundPref(const char* aPrefName, - PRBool aValueIfAutomatic) +PRBool nsWindow::UseTrackPointHack() { - if (!aPrefName) { - return aValueIfAutomatic; - } - nsresult rv; nsCOMPtr prefs(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv)); if (NS_SUCCEEDED(rv) && prefs) { PRInt32 lHackValue; - rv = prefs->GetIntPref(aPrefName, &lHackValue); + rv = prefs->GetIntPref("ui.trackpoint_hack.enabled", &lHackValue); if (NS_SUCCEEDED(rv)) { switch (lHackValue) { case 0: // disabled @@ -9070,18 +8839,12 @@ PRBool nsWindow::GetInputWorkaroundPref(const char* aPrefName, } } } - return aValueIfAutomatic; -} - -PRBool nsWindow::UseTrackPointHack() -{ - return GetInputWorkaroundPref("ui.trackpoint_hack.enabled", - sDefaultTrackPointHack); + return sDefaultTrackPointHack; } #if !defined(WINCE) static PRBool -HasRegistryKey(HKEY aRoot, PRUnichar* aName) +HasRegistryKey(HKEY aRoot, LPCWSTR aName) { HKEY key; LONG result = ::RegOpenKeyExW(aRoot, aName, 0, KEY_READ, &key); @@ -9091,91 +8854,28 @@ HasRegistryKey(HKEY aRoot, PRUnichar* aName) return PR_TRUE; } -/** - * Gets the value of a string-typed registry value. - * - * @param aRoot The registry root to search in. - * @param aKeyName The name of the registry key to open. - * @param aValueName The name of the registry value in the specified key whose - * value is to be retrieved. Can be null, to retrieve the key's unnamed/ - * default value. - * @param aBuffer The buffer into which to store the string value. Can be null, - * in which case the return value indicates just whether the value exists. - * @param aBufferLength The size of aBuffer, in bytes. - * @return Whether the value exists and is a string. - */ -static PRBool -GetRegistryKey(HKEY aRoot, PRUnichar* aKeyName, PRUnichar* aValueName, PRUnichar* aBuffer, DWORD aBufferLength) -{ - if (!aKeyName) { - return PR_FALSE; - } - - HKEY key; - LONG result = ::RegOpenKeyExW(aRoot, aKeyName, NULL, KEY_READ, &key); - if (result != ERROR_SUCCESS) - return PR_FALSE; - DWORD type; - result = ::RegQueryValueExW(key, aValueName, NULL, &type, (BYTE*) aBuffer, &aBufferLength); - ::RegCloseKey(key); - if (result != ERROR_SUCCESS || type != REG_SZ) - return PR_FALSE; - if (aBuffer) - aBuffer[aBufferLength - 1] = 0; - return PR_TRUE; -} - static PRBool IsObsoleteSynapticsDriver() { - PRUnichar buf[40]; - PRBool foundKey = GetRegistryKey(HKEY_LOCAL_MACHINE, - L"Software\\Synaptics\\SynTP\\Install", - L"DriverVersion", - buf, - sizeof buf); - if (!foundKey) + HKEY key; + LONG result = ::RegOpenKeyExW(HKEY_LOCAL_MACHINE, + L"Software\\Synaptics\\SynTP\\Install", 0, KEY_READ, &key); + if (result != ERROR_SUCCESS) return PR_FALSE; + DWORD type; + PRUnichar buf[40]; + DWORD buflen = sizeof(buf); + result = ::RegQueryValueExW(key, L"DriverVersion", NULL, &type, (BYTE*)buf, &buflen); + ::RegCloseKey(key); + if (result != ERROR_SUCCESS || type != REG_SZ) + return PR_FALSE; + buf[NS_ARRAY_LENGTH(buf) - 1] = 0; int majorVersion = wcstol(buf, NULL, 10); return majorVersion < 15; } -static PRBool -IsObsoleteElantechDriver() -{ - PRUnichar buf[40]; - // The driver version is found in one of these two registry keys. - PRBool foundKey = GetRegistryKey(HKEY_CURRENT_USER, - L"Software\\Elantech\\MainOption", - L"DriverVersion", - buf, - sizeof buf); - if (!foundKey) - foundKey = GetRegistryKey(HKEY_CURRENT_USER, - L"Software\\Elantech", - L"DriverVersion", - buf, - sizeof buf); - - if (!foundKey) - return PR_FALSE; - - // Assume that the major version number can be found just after a space - // or at the start of the string. - for (PRUnichar* p = buf; *p; p++) { - if (*p >= L'0' && *p <= L'9' && (p == buf || *(p - 1) == L' ')) { - int majorVersion = wcstol(p, NULL, 10); - // Versions 7 and 8 need the hack. - if (majorVersion == 7 || majorVersion == 8) - return PR_TRUE; - } - } - - return PR_FALSE; -} - -void nsWindow::InitInputWorkaroundPrefDefaults() +void nsWindow::InitInputHackDefaults() { if (HasRegistryKey(HKEY_CURRENT_USER, L"Software\\Lenovo\\TrackPoint")) { sDefaultTrackPointHack = PR_TRUE; @@ -9188,10 +8888,6 @@ void nsWindow::InitInputWorkaroundPrefDefaults() IsObsoleteSynapticsDriver()) { sDefaultTrackPointHack = PR_TRUE; } - - sUseElantechGestureHacks = - GetInputWorkaroundPref("ui.elantech_gesture_hacks.enabled", - IsObsoleteElantechDriver()); } #endif // #if !defined(WINCE) diff --git a/widget/src/windows/nsWindow.h b/widget/src/windows/nsWindow.h index 85ec5f71cd05..1115a4f37b75 100644 --- a/widget/src/windows/nsWindow.h +++ b/widget/src/windows/nsWindow.h @@ -317,7 +317,6 @@ protected: static BOOL CALLBACK EnumAllThreadWindowProc(HWND aWnd, LPARAM aParam); static void AllowD3D9Callback(nsWindow *aWindow); static void AllowD3D9WithReinitializeCallback(nsWindow *aWindow); - static BOOL CALLBACK FindOurWindowAtPointCallback(HWND aHWND, LPARAM aLPARAM); /** * Window utilities @@ -333,19 +332,16 @@ protected: void InvalidateNonClientRegion(); HRGN ExcludeNonClientFromPaintRegion(HRGN aRegion); #if !defined(WINCE) - static void InitInputWorkaroundPrefDefaults(); + static void InitInputHackDefaults(); #endif - static PRBool GetInputWorkaroundPref(const char* aPrefName, PRBool aValueIfAutomatic); static PRBool UseTrackPointHack(); - static void PerformElantechSwipeGestureHack(UINT& aVirtualKeyCode, nsModifierKeyState& aModKeyState); static void GetMainWindowClass(nsAString& aClass); PRBool HasGlass() const { return mTransparencyMode == eTransparencyGlass || mTransparencyMode == eTransparencyBorderlessGlass; } - static PRBool IsOurProcessWindow(HWND aHWND); - static HWND FindOurProcessWindow(HWND aHWND); - static HWND FindOurWindowAtPoint(const POINT& aPoint); + PRBool IsOurProcessWindow(HWND aHWND); + HWND FindOurProcessWindow(HWND aHWND); /** * Event processing helpers @@ -531,7 +527,6 @@ protected: nsPopupType mPopupType; nsSizeMode mOldSizeMode; WindowHook mWindowHook; - DWORD mAssumeWheelIsZoomUntil; static PRUint32 sInstanceCount; static TriStateBool sCanQuit; static nsWindow* sCurrentWindow; @@ -545,7 +540,6 @@ protected: static int sTrimOnMinimize; static PRBool sDefaultTrackPointHack; static const char* sDefaultMainWindowClass; - static PRBool sUseElantechGestureHacks; static bool sAllowD3D9; #ifdef MOZ_IPC static PRUint32 sOOPPPluginFocusEvent;