diff options
author | jcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-25 21:55:15 +0000 |
---|---|---|
committer | jcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-25 21:55:15 +0000 |
commit | 11c49d070cd2b1468a8224aabfabef24a094a488 (patch) | |
tree | 9d4d1ec43fdd406c8c19961b4b8f72da67e79215 /chrome/views/focus | |
parent | 9441db29eee516da2f6409c7b31d056b726078ed (diff) | |
download | chromium_src-11c49d070cd2b1468a8224aabfabef24a094a488.zip chromium_src-11c49d070cd2b1468a8224aabfabef24a094a488.tar.gz chromium_src-11c49d070cd2b1468a8224aabfabef24a094a488.tar.bz2 |
Moving the mouse-wheel message rerouting code out of the focus manager.
This is part of the effort of making the focus manager not window specific.
BUG=None
TEST=Make sure mouse-wheel scrolls the Chrome window under the cursor (try with a Chrome window, the option window, the task manager table) when it is active and when it is inactive. Also try using the mouse-wheel on a plugin with a scroll-view (for example http://java.sun.com/products/plugin/1.4/demos/plugin/jfc/SwingSet2/SwingSet2.html) when the browser window is not active, the plugin should scroll.
Review URL: http://codereview.chromium.org/53037
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@12498 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/views/focus')
-rw-r--r-- | chrome/views/focus/focus_manager.cc | 107 | ||||
-rw-r--r-- | chrome/views/focus/focus_util_win.cc | 116 | ||||
-rw-r--r-- | chrome/views/focus/focus_util_win.h | 26 |
3 files changed, 142 insertions, 107 deletions
diff --git a/chrome/views/focus/focus_manager.cc b/chrome/views/focus/focus_manager.cc index e11d43f..d8fb23f 100644 --- a/chrome/views/focus/focus_manager.cc +++ b/chrome/views/focus/focus_manager.cc @@ -43,109 +43,6 @@ static const wchar_t* const kFocusSubclassInstalled = namespace views { -static bool IsCompatibleWithMouseWheelRedirection(HWND window) { - std::wstring class_name = win_util::GetClassName(window); - // Mousewheel redirection to comboboxes is a surprising and - // undesireable user behavior. - return !(class_name == L"ComboBox" || - class_name == L"ComboBoxEx32"); -} - -static bool CanRedirectMouseWheelFrom(HWND window) { - std::wstring class_name = win_util::GetClassName(window); - - // Older Thinkpad mouse wheel drivers create a window under mouse wheel - // pointer. Detect if we are dealing with this window. In this case we - // don't need to do anything as the Thinkpad mouse driver will send - // mouse wheel messages to the right window. - if ((class_name == L"Syn Visual Class") || - (class_name == L"SynTrackCursorWindowClass")) - return false; - - return true; -} - -bool IsPluginWindow(HWND window) { - HWND current_window = window; - while (GetWindowLong(current_window, GWL_STYLE) & WS_CHILD) { - current_window = GetParent(current_window); - if (!IsWindow(current_window)) - break; - - std::wstring class_name = win_util::GetClassName(current_window); - if (class_name == kRenderWidgetHostHWNDClass) - return true; - } - - return false; -} - -// Forwards mouse wheel messages to the window under it. -// Windows sends mouse wheel messages to the currently active window. -// This causes a window to scroll even if it is not currently under the -// mouse wheel. The following code gives mouse wheel messages to the -// window under the mouse wheel in order to scroll that window. This -// is arguably a better user experience. The returns value says whether -// the mouse wheel message was successfully redirected. -static bool RerouteMouseWheel(HWND window, WPARAM wParam, LPARAM lParam) { - // Since this is called from a subclass for every window, we can get - // here recursively. This will happen if, for example, a control - // reflects wheel scroll messages to its parent. Bail out if we got - // here recursively. - static bool recursion_break = false; - if (recursion_break) - return false; - // Check if this window's class has a bad interaction with rerouting. - if (!IsCompatibleWithMouseWheelRedirection(window)) - return false; - - DWORD current_process = GetCurrentProcessId(); - POINT wheel_location = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; - HWND window_under_wheel = WindowFromPoint(wheel_location); - - if (!CanRedirectMouseWheelFrom(window_under_wheel)) - return false; - - // Find the lowest Chrome window in the hierarchy that can be the - // target of mouse wheel redirection. - while (window != window_under_wheel) { - // If window_under_wheel is not a valid Chrome window, then return - // true to suppress further processing of the message. - if (!::IsWindow(window_under_wheel)) - return true; - DWORD wheel_window_process = 0; - GetWindowThreadProcessId(window_under_wheel, &wheel_window_process); - if (current_process != wheel_window_process) { - if (IsChild(window, window_under_wheel)) { - // If this message is reflected from a child window in a different - // process (happens with out of process windowed plugins) then - // we don't want to reroute the wheel message. - return false; - } else { - // The wheel is scrolling over an unrelated window. If that window - // is a plugin window in a different chrome then we can send it a - // WM_MOUSEWHEEL. Otherwise, we cannot send random WM_MOUSEWHEEL - // messages to arbitrary windows. So just drop the message. - if (!IsPluginWindow(window_under_wheel)) - return true; - } - } - - // window_under_wheel is a Chrome window. If allowed, redirect. - if (IsCompatibleWithMouseWheelRedirection(window_under_wheel)) { - recursion_break = true; - SendMessage(window_under_wheel, WM_MOUSEWHEEL, wParam, lParam); - recursion_break = false; - return true; - } - // If redirection is disallowed, try the parent. - window_under_wheel = GetAncestor(window_under_wheel, GA_PARENT); - } - // If we traversed back to the starting point, we should process - // this message normally; return false. - return false; -} - // Callback installed via InstallFocusSubclass. static LRESULT CALLBACK FocusWindowCallback(HWND window, UINT message, WPARAM wParam, LPARAM lParam) { @@ -187,10 +84,6 @@ static LRESULT CALLBACK FocusWindowCallback(HWND window, UINT message, return 0; return result; } - case WM_MOUSEWHEEL: - if (RerouteMouseWheel(window, wParam, lParam)) - return 0; - break; case WM_IME_CHAR: // Issue 7707: A rich-edit control may crash when it receives a // WM_IME_CHAR message while it is processing a WM_IME_COMPOSITION diff --git a/chrome/views/focus/focus_util_win.cc b/chrome/views/focus/focus_util_win.cc new file mode 100644 index 0000000..ec77519 --- /dev/null +++ b/chrome/views/focus/focus_util_win.cc @@ -0,0 +1,116 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/views/focus/focus_util_win.h" + +#include "base/win_util.h" + +namespace views { + +// Property used to indicate the HWND supports having mouse wheel messages +// rerouted to it. +static const wchar_t* const kHWNDSupportMouseWheelRerouting = + L"__HWND_MW_REROUTE_OK"; + +static bool WindowSupportsRerouteMouseWheel(HWND window) { + while (GetWindowLong(window, GWL_STYLE) & WS_CHILD) { + if (!IsWindow(window)) + break; + + if (reinterpret_cast<bool>(GetProp(window, + kHWNDSupportMouseWheelRerouting))) { + return true; + } + window = GetParent(window); + } + return false; +} + +static bool IsCompatibleWithMouseWheelRedirection(HWND window) { + std::wstring class_name = win_util::GetClassName(window); + // Mousewheel redirection to comboboxes is a surprising and + // undesireable user behavior. + return !(class_name == L"ComboBox" || + class_name == L"ComboBoxEx32"); +} + +static bool CanRedirectMouseWheelFrom(HWND window) { + std::wstring class_name = win_util::GetClassName(window); + + // Older Thinkpad mouse wheel drivers create a window under mouse wheel + // pointer. Detect if we are dealing with this window. In this case we + // don't need to do anything as the Thinkpad mouse driver will send + // mouse wheel messages to the right window. + if ((class_name == L"Syn Visual Class") || + (class_name == L"SynTrackCursorWindowClass")) + return false; + + return true; +} + +void SetWindowSupportsRerouteMouseWheel(HWND hwnd) { + SetProp(hwnd, kHWNDSupportMouseWheelRerouting, + reinterpret_cast<HANDLE>(true)); +} + +bool RerouteMouseWheel(HWND window, WPARAM w_param, LPARAM l_param) { + // Since this is called from a subclass for every window, we can get + // here recursively. This will happen if, for example, a control + // reflects wheel scroll messages to its parent. Bail out if we got + // here recursively. + static bool recursion_break = false; + if (recursion_break) + return false; + // Check if this window's class has a bad interaction with rerouting. + if (!IsCompatibleWithMouseWheelRedirection(window)) + return false; + + DWORD current_process = GetCurrentProcessId(); + POINT wheel_location = { GET_X_LPARAM(l_param), GET_Y_LPARAM(l_param) }; + HWND window_under_wheel = WindowFromPoint(wheel_location); + + if (!CanRedirectMouseWheelFrom(window_under_wheel)) + return false; + + // Find the lowest Chrome window in the hierarchy that can be the + // target of mouse wheel redirection. + while (window != window_under_wheel) { + // If window_under_wheel is not a valid Chrome window, then return true to + // suppress further processing of the message. + if (!::IsWindow(window_under_wheel)) + return true; + DWORD wheel_window_process = 0; + GetWindowThreadProcessId(window_under_wheel, &wheel_window_process); + if (current_process != wheel_window_process) { + if (IsChild(window, window_under_wheel)) { + // If this message is reflected from a child window in a different + // process (happens with out of process windowed plugins) then + // we don't want to reroute the wheel message. + return false; + } else { + // The wheel is scrolling over an unrelated window. Make sure that we + // have marked that window as supporting mouse wheel rerouting. + // Otherwise, we cannot send random WM_MOUSEWHEEL messages to arbitrary + // windows. So just drop the message. + if (!WindowSupportsRerouteMouseWheel(window_under_wheel)) + return true; + } + } + + // window_under_wheel is a Chrome window. If allowed, redirect. + if (IsCompatibleWithMouseWheelRedirection(window_under_wheel)) { + recursion_break = true; + SendMessage(window_under_wheel, WM_MOUSEWHEEL, w_param, l_param); + recursion_break = false; + return true; + } + // If redirection is disallowed, try the parent. + window_under_wheel = GetAncestor(window_under_wheel, GA_PARENT); + } + // If we traversed back to the starting point, we should process + // this message normally; return false. + return false; +} + +} // namespace views diff --git a/chrome/views/focus/focus_util_win.h b/chrome/views/focus/focus_util_win.h new file mode 100644 index 0000000..b7a8625 --- /dev/null +++ b/chrome/views/focus/focus_util_win.h @@ -0,0 +1,26 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_VIEWS_FOCUS_FOCUS_UTIL_WIN_H_ +#define CHROME_VIEWS_FOCUS_FOCUS_UTIL_WIN_H_ + +namespace views { + +// Marks the passed |hwnd| as supporting mouse-wheel message rerouting. +// We reroute the mouse wheel messages to such HWND when they are under the +// mouse pointer (but are not the active window) +void SetWindowSupportsRerouteMouseWheel(HWND hwnd); + +// Forwards mouse wheel messages to the window under it. +// Windows sends mouse wheel messages to the currently active window. +// This causes a window to scroll even if it is not currently under the mouse +// wheel. The following code gives mouse wheel messages to the window under the +// mouse wheel in order to scroll that window. This is arguably a better user +// experience. The returns value says whether the mouse wheel message was +// successfully redirected. +bool RerouteMouseWheel(HWND window, WPARAM w_param, LPARAM l_param); + +} // namespace views + +#endif // CHROME_VIEWS_FOCUS_FOCUS_UTIL_WIN_H_ |