diff options
author | jcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-25 22:05:11 +0000 |
---|---|---|
committer | jcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-25 22:05:11 +0000 |
commit | c9d989b20d74fcd1de89d5aad90f5ad11d11801c (patch) | |
tree | 8e0d7b90a6810033316b54ba57ba4de1417cb309 /chrome/views | |
parent | cdd24e1db2da2fa61261ff78278ce2961a320b84 (diff) | |
download | chromium_src-c9d989b20d74fcd1de89d5aad90f5ad11d11801c.zip chromium_src-c9d989b20d74fcd1de89d5aad90f5ad11d11801c.tar.gz chromium_src-c9d989b20d74fcd1de89d5aad90f5ad11d11801c.tar.bz2 |
Reverting 12498.
Review URL: http://codereview.chromium.org/53073
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@12500 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/views')
-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 | ||||
-rw-r--r-- | chrome/views/views.vcproj | 8 | ||||
-rw-r--r-- | chrome/views/widget/widget_win.cc | 21 | ||||
-rw-r--r-- | chrome/views/widget/widget_win.h | 4 |
6 files changed, 115 insertions, 167 deletions
diff --git a/chrome/views/focus/focus_manager.cc b/chrome/views/focus/focus_manager.cc index d8fb23f..e11d43f 100644 --- a/chrome/views/focus/focus_manager.cc +++ b/chrome/views/focus/focus_manager.cc @@ -43,6 +43,109 @@ 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) { @@ -84,6 +187,10 @@ 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 deleted file mode 100644 index ec77519..0000000 --- a/chrome/views/focus/focus_util_win.cc +++ /dev/null @@ -1,116 +0,0 @@ -// 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 deleted file mode 100644 index b7a8625..0000000 --- a/chrome/views/focus/focus_util_win.h +++ /dev/null @@ -1,26 +0,0 @@ -// 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_ diff --git a/chrome/views/views.vcproj b/chrome/views/views.vcproj index 52ca5af..29cf7bd 100644 --- a/chrome/views/views.vcproj +++ b/chrome/views/views.vcproj @@ -431,14 +431,6 @@ > </File> <File - RelativePath=".\focus\focus_util_win.cc" - > - </File> - <File - RelativePath=".\focus\focus_util_win.h" - > - </File> - <File RelativePath=".\focus\view_storage.cc" > </File> diff --git a/chrome/views/widget/widget_win.cc b/chrome/views/widget/widget_win.cc index d4397c7..2faab37 100644 --- a/chrome/views/widget/widget_win.cc +++ b/chrome/views/widget/widget_win.cc @@ -14,7 +14,6 @@ #include "chrome/views/accessibility/view_accessibility.h" #include "chrome/views/controls/native_control_win.h" #include "chrome/views/fill_layout.h" -#include "chrome/views/focus/focus_util_win.h" #include "chrome/views/widget/aero_tooltip_manager.h" #include "chrome/views/widget/hwnd_notification_source.h" #include "chrome/views/widget/root_view.h" @@ -149,7 +148,6 @@ void WidgetWin::Init(HWND parent, const gfx::Rect& bounds, bounds.height(), parent, NULL, NULL, this); DCHECK(hwnd_); TRACK_HWND_CREATION(hwnd_); - SetWindowSupportsRerouteMouseWheel(hwnd_); // The window procedure should have set the data for us. DCHECK(win_util::GetWindowUserData(hwnd_) == this); @@ -559,19 +557,12 @@ LRESULT WidgetWin::OnMouseLeave(UINT message, WPARAM w_param, LPARAM l_param) { return 0; } -LRESULT WidgetWin::OnMouseWheel(UINT message, WPARAM w_param, LPARAM l_param) { - // Reroute the mouse-wheel to the window under the mouse pointer if - // applicable. - if (message == WM_MOUSEWHEEL && - views::RerouteMouseWheel(hwnd_, w_param, l_param)) { - return 0; - } - - int flags = GET_KEYSTATE_WPARAM(w_param); - short distance = GET_WHEEL_DELTA_WPARAM(w_param); - int x = GET_X_LPARAM(l_param); - int y = GET_Y_LPARAM(l_param); - MouseWheelEvent e(distance, x, y, Event::ConvertWindowsFlags(flags)); +LRESULT WidgetWin::OnMouseWheel(UINT flags, short distance, + const CPoint& point) { + MouseWheelEvent e(distance, + point.x, + point.y, + Event::ConvertWindowsFlags(flags)); return root_view_->ProcessMouseWheelEvent(e) ? 0 : 1; } diff --git a/chrome/views/widget/widget_win.h b/chrome/views/widget/widget_win.h index 38dc730..aa88b08 100644 --- a/chrome/views/widget/widget_win.h +++ b/chrome/views/widget/widget_win.h @@ -162,7 +162,6 @@ class WidgetWin : public Widget, MESSAGE_HANDLER_EX(WM_GETOBJECT, OnGetObject) MESSAGE_HANDLER_EX(WM_NCMOUSELEAVE, OnNCMouseLeave) MESSAGE_HANDLER_EX(WM_MOUSELEAVE, OnMouseLeave) - MESSAGE_HANDLER_EX(WM_MOUSEWHEEL, OnMouseWheel) // This list is in _ALPHABETICAL_ order! OR I WILL HURT YOU. MSG_WM_ACTIVATE(OnActivate) @@ -193,6 +192,7 @@ class WidgetWin : public Widget, MSG_WM_MBUTTONDBLCLK(OnMButtonDblClk) MSG_WM_MOUSEACTIVATE(OnMouseActivate) MSG_WM_MOUSEMOVE(OnMouseMove) + MSG_WM_MOUSEWHEEL(OnMouseWheel) MSG_WM_MOVE(OnMove) MSG_WM_MOVING(OnMoving) MSG_WM_NCACTIVATE(OnNCActivate) @@ -384,9 +384,9 @@ class WidgetWin : public Widget, virtual LRESULT OnMouseActivate(HWND window, UINT hittest_code, UINT message); virtual void OnMouseMove(UINT flags, const CPoint& point); virtual LRESULT OnMouseLeave(UINT message, WPARAM w_param, LPARAM l_param); - virtual LRESULT OnMouseWheel(UINT message, WPARAM w_param, LPARAM l_param); virtual void OnMove(const CPoint& point) { SetMsgHandled(FALSE); } virtual void OnMoving(UINT param, const LPRECT new_bounds) { } + virtual LRESULT OnMouseWheel(UINT flags, short distance, const CPoint& point); virtual LRESULT OnMouseRange(UINT msg, WPARAM w_param, LPARAM l_param); virtual LRESULT OnNCActivate(BOOL active) { SetMsgHandled(FALSE); return 0; } virtual LRESULT OnNCCalcSize(BOOL w_param, LPARAM l_param) { |