Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(134)

Side by Side Diff: chrome/views/focus/focus_manager.cc

Issue 42624: Moving the mouse-wheel processing code out of the FocusManager (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <algorithm> 5 #include <algorithm>
6 6
7 #include "base/histogram.h" 7 #include "base/histogram.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/win_util.h" 9 #include "base/win_util.h"
10 #include "chrome/browser/renderer_host/render_widget_host_view_win.h" 10 #include "chrome/browser/renderer_host/render_widget_host_view_win.h"
(...skipping 25 matching lines...) Expand all
36 // Subclassing twice is not a problem if no one is subclassing the HWND between 36 // Subclassing twice is not a problem if no one is subclassing the HWND between
37 // the 2 subclassings (the 2nd subclassing is ignored since the WinProc is the 37 // the 2 subclassings (the 2nd subclassing is ignored since the WinProc is the
38 // same as the current one). However if some other app goes and subclasses the 38 // same as the current one). However if some other app goes and subclasses the
39 // HWND between the 2 subclassings, we will end up subclassing twice. 39 // HWND between the 2 subclassings, we will end up subclassing twice.
40 // This flag lets us test that whether we have or not subclassed yet. 40 // This flag lets us test that whether we have or not subclassed yet.
41 static const wchar_t* const kFocusSubclassInstalled = 41 static const wchar_t* const kFocusSubclassInstalled =
42 L"__FOCUS_SUBCLASS_INSTALLED__"; 42 L"__FOCUS_SUBCLASS_INSTALLED__";
43 43
44 namespace views { 44 namespace views {
45 45
46 static bool IsCompatibleWithMouseWheelRedirection(HWND window) {
47 std::wstring class_name = win_util::GetClassName(window);
48 // Mousewheel redirection to comboboxes is a surprising and
49 // undesireable user behavior.
50 return !(class_name == L"ComboBox" ||
51 class_name == L"ComboBoxEx32");
52 }
53
54 static bool CanRedirectMouseWheelFrom(HWND window) {
55 std::wstring class_name = win_util::GetClassName(window);
56
57 // Older Thinkpad mouse wheel drivers create a window under mouse wheel
58 // pointer. Detect if we are dealing with this window. In this case we
59 // don't need to do anything as the Thinkpad mouse driver will send
60 // mouse wheel messages to the right window.
61 if ((class_name == L"Syn Visual Class") ||
62 (class_name == L"SynTrackCursorWindowClass"))
63 return false;
64
65 return true;
66 }
67
68 bool IsPluginWindow(HWND window) {
69 HWND current_window = window;
70 while (GetWindowLong(current_window, GWL_STYLE) & WS_CHILD) {
71 current_window = GetParent(current_window);
72 if (!IsWindow(current_window))
73 break;
74
75 std::wstring class_name = win_util::GetClassName(current_window);
76 if (class_name == kRenderWidgetHostHWNDClass)
77 return true;
78 }
79
80 return false;
81 }
82
83 // Forwards mouse wheel messages to the window under it.
84 // Windows sends mouse wheel messages to the currently active window.
85 // This causes a window to scroll even if it is not currently under the
86 // mouse wheel. The following code gives mouse wheel messages to the
87 // window under the mouse wheel in order to scroll that window. This
88 // is arguably a better user experience. The returns value says whether
89 // the mouse wheel message was successfully redirected.
90 static bool RerouteMouseWheel(HWND window, WPARAM wParam, LPARAM lParam) {
91 // Since this is called from a subclass for every window, we can get
92 // here recursively. This will happen if, for example, a control
93 // reflects wheel scroll messages to its parent. Bail out if we got
94 // here recursively.
95 static bool recursion_break = false;
96 if (recursion_break)
97 return false;
98 // Check if this window's class has a bad interaction with rerouting.
99 if (!IsCompatibleWithMouseWheelRedirection(window))
100 return false;
101
102 DWORD current_process = GetCurrentProcessId();
103 POINT wheel_location = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
104 HWND window_under_wheel = WindowFromPoint(wheel_location);
105
106 if (!CanRedirectMouseWheelFrom(window_under_wheel))
107 return false;
108
109 // Find the lowest Chrome window in the hierarchy that can be the
110 // target of mouse wheel redirection.
111 while (window != window_under_wheel) {
112 // If window_under_wheel is not a valid Chrome window, then return
113 // true to suppress further processing of the message.
114 if (!::IsWindow(window_under_wheel))
115 return true;
116 DWORD wheel_window_process = 0;
117 GetWindowThreadProcessId(window_under_wheel, &wheel_window_process);
118 if (current_process != wheel_window_process) {
119 if (IsChild(window, window_under_wheel)) {
120 // If this message is reflected from a child window in a different
121 // process (happens with out of process windowed plugins) then
122 // we don't want to reroute the wheel message.
123 return false;
124 } else {
125 // The wheel is scrolling over an unrelated window. If that window
126 // is a plugin window in a different chrome then we can send it a
127 // WM_MOUSEWHEEL. Otherwise, we cannot send random WM_MOUSEWHEEL
128 // messages to arbitrary windows. So just drop the message.
129 if (!IsPluginWindow(window_under_wheel))
130 return true;
131 }
132 }
133
134 // window_under_wheel is a Chrome window. If allowed, redirect.
135 if (IsCompatibleWithMouseWheelRedirection(window_under_wheel)) {
136 recursion_break = true;
137 SendMessage(window_under_wheel, WM_MOUSEWHEEL, wParam, lParam);
138 recursion_break = false;
139 return true;
140 }
141 // If redirection is disallowed, try the parent.
142 window_under_wheel = GetAncestor(window_under_wheel, GA_PARENT);
143 }
144 // If we traversed back to the starting point, we should process
145 // this message normally; return false.
146 return false;
147 }
148
149 // Callback installed via InstallFocusSubclass. 46 // Callback installed via InstallFocusSubclass.
150 static LRESULT CALLBACK FocusWindowCallback(HWND window, UINT message, 47 static LRESULT CALLBACK FocusWindowCallback(HWND window, UINT message,
151 WPARAM wParam, LPARAM lParam) { 48 WPARAM wParam, LPARAM lParam) {
152 if (!::IsWindow(window)) { 49 if (!::IsWindow(window)) {
153 // QEMU has reported crashes when calling GetProp (this seems to happen for 50 // QEMU has reported crashes when calling GetProp (this seems to happen for
154 // some weird messages, not sure what they are). 51 // some weird messages, not sure what they are).
155 // Here we are just trying to avoid the crasher. 52 // Here we are just trying to avoid the crasher.
156 NOTREACHED(); 53 NOTREACHED();
157 return 0; 54 return 0;
158 } 55 }
(...skipping 21 matching lines...) Expand all
180 // FocusManager::OnActivate attempts to restore the focused view, it 77 // FocusManager::OnActivate attempts to restore the focused view, it
181 // needs to be called last so the focus it is setting does not get 78 // needs to be called last so the focus it is setting does not get
182 // overridden. 79 // overridden.
183 LRESULT result = CallWindowProc(original_handler, window, WM_ACTIVATE, 80 LRESULT result = CallWindowProc(original_handler, window, WM_ACTIVATE,
184 wParam, lParam); 81 wParam, lParam);
185 if (!focus_manager->OnPostActivate(window, 82 if (!focus_manager->OnPostActivate(window,
186 LOWORD(wParam), HIWORD(wParam))) 83 LOWORD(wParam), HIWORD(wParam)))
187 return 0; 84 return 0;
188 return result; 85 return result;
189 } 86 }
190 case WM_MOUSEWHEEL:
191 if (RerouteMouseWheel(window, wParam, lParam))
192 return 0;
193 break;
194 case WM_IME_CHAR: 87 case WM_IME_CHAR:
195 // Issue 7707: A rich-edit control may crash when it receives a 88 // Issue 7707: A rich-edit control may crash when it receives a
196 // WM_IME_CHAR message while it is processing a WM_IME_COMPOSITION 89 // WM_IME_CHAR message while it is processing a WM_IME_COMPOSITION
197 // message. Since view controls don't need WM_IME_CHAR messages, 90 // message. Since view controls don't need WM_IME_CHAR messages,
198 // we prevent WM_IME_CHAR messages from being dispatched to view 91 // we prevent WM_IME_CHAR messages from being dispatched to view
199 // controls via the CallWindowProc() call. 92 // controls via the CallWindowProc() call.
200 return 0; 93 return 0;
201 default: 94 default:
202 break; 95 break;
203 } 96 }
(...skipping 638 matching lines...) Expand 10 before | Expand all | Expand 10 after
842 std::find(focus_change_listeners_.begin(), focus_change_listeners_.end(), 735 std::find(focus_change_listeners_.begin(), focus_change_listeners_.end(),
843 listener); 736 listener);
844 if (place == focus_change_listeners_.end()) { 737 if (place == focus_change_listeners_.end()) {
845 NOTREACHED() << "Removing a listener that isn't registered."; 738 NOTREACHED() << "Removing a listener that isn't registered.";
846 return; 739 return;
847 } 740 }
848 focus_change_listeners_.erase(place); 741 focus_change_listeners_.erase(place);
849 } 742 }
850 743
851 } // namespace views 744 } // namespace views
OLDNEW
« no previous file with comments | « chrome/browser/renderer_host/render_widget_host_view_win.cc ('k') | chrome/views/focus/focus_util_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698