diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-26 20:39:10 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-26 20:39:10 +0000 |
commit | 5fbf4f188d74229eeb6a34b217266f28e05c8c5f (patch) | |
tree | 293d4063d3f3c673ae29723c953ab865b5476a68 /ui | |
parent | 801df8f5a6aa7370d097bff2db11d6692676d556 (diff) | |
download | chromium_src-5fbf4f188d74229eeb6a34b217266f28e05c8c5f.zip chromium_src-5fbf4f188d74229eeb6a34b217266f28e05c8c5f.tar.gz chromium_src-5fbf4f188d74229eeb6a34b217266f28e05c8c5f.tar.bz2 |
Move the mouse wheel utils from views to ui\base\win, to get rid of some views dependencies in content.
Review URL: http://codereview.chromium.org/7753025
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@98479 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r-- | ui/base/win/mouse_wheel_util.cc | 119 | ||||
-rw-r--r-- | ui/base/win/mouse_wheel_util.h | 35 | ||||
-rw-r--r-- | ui/ui.gyp | 2 |
3 files changed, 156 insertions, 0 deletions
diff --git a/ui/base/win/mouse_wheel_util.cc b/ui/base/win/mouse_wheel_util.cc new file mode 100644 index 0000000..6b93e66 --- /dev/null +++ b/ui/base/win/mouse_wheel_util.cc @@ -0,0 +1,119 @@ +// 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 "ui/base/win/mouse_wheel_util.h" + +#include <windowsx.h> + +#include "base/auto_reset.h" +#include "ui/base/view_prop.h" +#include "ui/base/win/hwnd_util.h" + +namespace ui { + +// Property used to indicate the HWND supports having mouse wheel messages +// rerouted to it. +static const char* const kHWNDSupportMouseWheelRerouting = + "__HWND_MW_REROUTE_OK"; + +static bool WindowSupportsRerouteMouseWheel(HWND window) { + while (GetWindowLong(window, GWL_STYLE) & WS_CHILD) { + if (!IsWindow(window)) + break; + + if (reinterpret_cast<bool>( + ViewProp::GetValue(window, kHWNDSupportMouseWheelRerouting))) { + return true; + } + window = GetParent(window); + } + return false; +} + +static bool IsCompatibleWithMouseWheelRedirection(HWND window) { + std::wstring class_name = 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 = 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; +} + +ViewProp* SetWindowSupportsRerouteMouseWheel(HWND hwnd) { + return new ViewProp(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)) { + AutoReset<bool> auto_reset_recursion_break(&recursion_break, true); + SendMessage(window_under_wheel, WM_MOUSEWHEEL, w_param, l_param); + 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 ui diff --git a/ui/base/win/mouse_wheel_util.h b/ui/base/win/mouse_wheel_util.h new file mode 100644 index 0000000..d785265 --- /dev/null +++ b/ui/base/win/mouse_wheel_util.h @@ -0,0 +1,35 @@ +// Copyright (c) 2011 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 UI_BASE_WIN_MOUSE_WHEEL_UTIL_H_ +#define UI_BASE_WIN_MOUSE_WHEEL_UTIL_H_ +#pragma once + +#include <windows.h> + +#include "ui/base/ui_export.h" + +namespace ui { + +class ViewProp; + +// 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). Callers own the returned +// object. +UI_EXPORT ViewProp* 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. +UI_EXPORT bool RerouteMouseWheel(HWND window, WPARAM w_param, + LPARAM l_param); + +} // namespace ui + +#endif // UI_BASE_WIN_MOUSE_WHEEL_UTIL_H_ @@ -197,6 +197,8 @@ 'base/win/hwnd_util.h', 'base/win/ime_input.cc', 'base/win/ime_input.h', + 'base/win/mouse_wheel_util.cc', + 'base/win/mouse_wheel_util.h', 'base/win/shell.cc', 'base/win/shell.h', 'base/win/window_impl.cc', |