summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-26 20:39:10 +0000
committerjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-26 20:39:10 +0000
commit5fbf4f188d74229eeb6a34b217266f28e05c8c5f (patch)
tree293d4063d3f3c673ae29723c953ab865b5476a68 /ui
parent801df8f5a6aa7370d097bff2db11d6692676d556 (diff)
downloadchromium_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.cc119
-rw-r--r--ui/base/win/mouse_wheel_util.h35
-rw-r--r--ui/ui.gyp2
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_
diff --git a/ui/ui.gyp b/ui/ui.gyp
index 5d473e9..273d63c 100644
--- a/ui/ui.gyp
+++ b/ui/ui.gyp
@@ -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',