OLD | NEW |
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/logging.h" | 8 #include "base/logging.h" |
8 #include "base/win_util.h" | 9 #include "base/win_util.h" |
9 #include "chrome/browser/render_widget_host_view_win.h" | 10 #include "chrome/browser/render_widget_host_view_win.h" |
10 #include "chrome/common/notification_types.h" | 11 #include "chrome/common/notification_types.h" |
11 #include "chrome/views/accelerator.h" | 12 #include "chrome/views/accelerator.h" |
12 #include "chrome/views/focus_manager.h" | 13 #include "chrome/views/focus_manager.h" |
13 #include "chrome/views/root_view.h" | 14 #include "chrome/views/root_view.h" |
14 #include "chrome/views/view.h" | 15 #include "chrome/views/view.h" |
15 #include "chrome/views/view_storage.h" | 16 #include "chrome/views/view_storage.h" |
16 #include "chrome/views/widget.h" | 17 #include "chrome/views/widget.h" |
17 | 18 |
18 // The following keys are used in SetProp/GetProp to associate additional | 19 // The following keys are used in SetProp/GetProp to associate additional |
19 // information needed for focus tracking with a window. | 20 // information needed for focus tracking with a window. |
20 | 21 |
21 // Maps to the FocusManager instance for a top level window. See | 22 // Maps to the FocusManager instance for a top level window. See |
22 // CreateFocusManager/DestoryFocusManager for usage. | 23 // CreateFocusManager/DestoryFocusManager for usage. |
23 static const wchar_t* const kFocusManagerKey = L"__VIEW_CONTAINER__"; | 24 static const wchar_t* const kFocusManagerKey = L"__VIEW_CONTAINER__"; |
24 | 25 |
25 // Maps to the View associated with a window. | 26 // Maps to the View associated with a window. |
26 // We register views with window so we can: | 27 // We register views with window so we can: |
27 // - keep in sync the native focus with the view focus (when the native | 28 // - keep in sync the native focus with the view focus (when the native |
28 // component gets the focus, we get the WM_SETFOCUS event and we can focus the | 29 // component gets the focus, we get the WM_SETFOCUS event and we can focus the |
29 // associated view). | 30 // associated view). |
30 // - prevent tab key events from being sent to views. | 31 // - prevent tab key events from being sent to views. |
31 static const wchar_t* const kViewKey = L"__CHROME_VIEW__"; | 32 static const wchar_t* const kViewKey = L"__CHROME_VIEW__"; |
32 | 33 |
| 34 // A property set to 1 to indicate whether the focus manager has subclassed that |
| 35 // window. We are doing this to ensure we are not subclassing several times. |
| 36 // Subclassing twice is not a problem if no one is subclassing the HWND between |
| 37 // the 2 subclassing (the 2 subclassing is ignored since the WinProc is the same |
| 38 // as the current one). However if some other app goes and subclasses the HWND |
| 39 // between the 2 subclassing, we will end up subclassing twice. |
| 40 // This flag lets us test that whether we have or not subclassed yet. |
| 41 static const wchar_t* const kSubclassed = L"__FOCUS_SUBCLASS_INSTALLED__"; |
| 42 |
33 namespace views { | 43 namespace views { |
34 | 44 |
35 static bool IsCompatibleWithMouseWheelRedirection(HWND window) { | 45 static bool IsCompatibleWithMouseWheelRedirection(HWND window) { |
36 std::wstring class_name = win_util::GetClassName(window); | 46 std::wstring class_name = win_util::GetClassName(window); |
37 // Mousewheel redirection to comboboxes is a surprising and | 47 // Mousewheel redirection to comboboxes is a surprising and |
38 // undesireable user behavior. | 48 // undesireable user behavior. |
39 return !(class_name == L"ComboBox" || | 49 return !(class_name == L"ComboBox" || |
40 class_name == L"ComboBoxEx32"); | 50 class_name == L"ComboBoxEx32"); |
41 } | 51 } |
42 | 52 |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 // keep references to invalidated views. | 212 // keep references to invalidated views. |
203 NotificationService::current()->AddObserver( | 213 NotificationService::current()->AddObserver( |
204 focus_manager, NOTIFY_VIEW_REMOVED, NotificationService::AllSources()); | 214 focus_manager, NOTIFY_VIEW_REMOVED, NotificationService::AllSources()); |
205 | 215 |
206 return focus_manager; | 216 return focus_manager; |
207 } | 217 } |
208 | 218 |
209 // static | 219 // static |
210 void FocusManager::InstallFocusSubclass(HWND window, View* view) { | 220 void FocusManager::InstallFocusSubclass(HWND window, View* view) { |
211 DCHECK(window); | 221 DCHECK(window); |
212 win_util::Subclass(window, &FocusWindowCallback); | 222 |
| 223 bool already_subclassed = reinterpret_cast<bool>(GetProp(window, |
| 224 kSubclassed)); |
| 225 if (already_subclassed && |
| 226 !win_util::IsSubclassed(window, &FocusWindowCallback)) { |
| 227 NOTREACHED() << " FocusManager sub-classed twice"; |
| 228 // Track in UMA so we know if this case happens. |
| 229 UMA_HISTOGRAM_COUNTS(L"FocusManager.MultipleSubclass", 1); |
| 230 } else { |
| 231 bool success = win_util::Subclass(window, &FocusWindowCallback); |
| 232 DCHECK(success); |
| 233 SetProp(window, kSubclassed, reinterpret_cast<HANDLE>(true)); |
| 234 } |
213 if (view) | 235 if (view) |
214 SetProp(window, kViewKey, view); | 236 SetProp(window, kViewKey, view); |
215 } | 237 } |
216 | 238 |
217 void FocusManager::UninstallFocusSubclass(HWND window) { | 239 void FocusManager::UninstallFocusSubclass(HWND window) { |
218 DCHECK(window); | 240 DCHECK(window); |
219 if (win_util::Unsubclass(window, &FocusWindowCallback)) | 241 if (win_util::Unsubclass(window, &FocusWindowCallback)) { |
220 RemoveProp(window, kViewKey); | 242 RemoveProp(window, kViewKey); |
| 243 RemoveProp(window, kSubclassed); |
| 244 } |
221 } | 245 } |
222 | 246 |
223 // static | 247 // static |
224 FocusManager* FocusManager::GetFocusManager(HWND window) { | 248 FocusManager* FocusManager::GetFocusManager(HWND window) { |
225 DCHECK(window); | 249 DCHECK(window); |
226 FocusManager* focus_manager = | 250 FocusManager* focus_manager = |
227 reinterpret_cast<FocusManager*>(GetProp(window, kFocusManagerKey)); | 251 reinterpret_cast<FocusManager*>(GetProp(window, kFocusManagerKey)); |
228 HWND parent = GetParent(window); | 252 HWND parent = GetParent(window); |
229 while (!focus_manager && parent) { | 253 while (!focus_manager && parent) { |
230 focus_manager = | 254 focus_manager = |
(...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
803 listener); | 827 listener); |
804 if (place == focus_change_listeners_.end()) { | 828 if (place == focus_change_listeners_.end()) { |
805 NOTREACHED() << "Removing a listener that isn't registered."; | 829 NOTREACHED() << "Removing a listener that isn't registered."; |
806 return; | 830 return; |
807 } | 831 } |
808 focus_change_listeners_.erase(place); | 832 focus_change_listeners_.erase(place); |
809 } | 833 } |
810 | 834 |
811 } // namespace views | 835 } // namespace views |
812 | 836 |
OLD | NEW |