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 "views/focus/focus_manager.h" | 5 #include "views/focus/focus_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "build/build_config.h" | 9 #include "build/build_config.h" |
10 | 10 |
11 #if defined(OS_LINUX) | 11 #if defined(OS_LINUX) |
12 #include <gtk/gtk.h> | 12 #include <gtk/gtk.h> |
13 #endif | 13 #endif |
14 | 14 |
| 15 #include "base/keyboard_codes.h" |
15 #include "base/logging.h" | 16 #include "base/logging.h" |
16 #include "views/accelerator.h" | 17 #include "views/accelerator.h" |
17 #include "views/focus/view_storage.h" | 18 #include "views/focus/view_storage.h" |
18 #include "views/view.h" | 19 #include "views/view.h" |
19 #include "views/widget/root_view.h" | 20 #include "views/widget/root_view.h" |
20 #include "views/widget/widget.h" | 21 #include "views/widget/widget.h" |
21 | 22 |
22 #if defined(OS_WIN) | |
23 #include "base/win_util.h" | |
24 #endif | |
25 | |
26 namespace views { | 23 namespace views { |
27 | 24 |
28 // FocusManager ----------------------------------------------------- | 25 // FocusManager ----------------------------------------------------- |
29 | 26 |
30 FocusManager::FocusManager(Widget* widget) | 27 FocusManager::FocusManager(Widget* widget) |
31 : widget_(widget), | 28 : widget_(widget), |
32 focused_view_(NULL) { | 29 focused_view_(NULL) { |
33 DCHECK(widget_); | 30 DCHECK(widget_); |
34 stored_focused_view_storage_id_ = | 31 stored_focused_view_storage_id_ = |
35 ViewStorage::GetSharedInstance()->CreateStorageID(); | 32 ViewStorage::GetSharedInstance()->CreateStorageID(); |
36 } | 33 } |
37 | 34 |
38 FocusManager::~FocusManager() { | 35 FocusManager::~FocusManager() { |
39 // If there are still registered FocusChange listeners, chances are they were | 36 // If there are still registered FocusChange listeners, chances are they were |
40 // leaked so warn about them. | 37 // leaked so warn about them. |
41 DCHECK(focus_change_listeners_.empty()); | 38 DCHECK(focus_change_listeners_.empty()); |
42 } | 39 } |
43 | 40 |
44 #if defined(OS_WIN) | 41 bool FocusManager::OnKeyEvent(const KeyEvent& event) { |
45 // Message handlers. | |
46 bool FocusManager::OnKeyDown(HWND window, UINT message, WPARAM wparam, | |
47 LPARAM lparam) { | |
48 DCHECK((message == WM_KEYDOWN) || (message == WM_SYSKEYDOWN)); | |
49 HWND hwnd = widget_->GetNativeView(); | |
50 | |
51 if (!IsWindowVisible(hwnd)) { | |
52 // We got a message for a hidden window. Because WidgetWin::Close hides the | |
53 // window, then destroys it, it it possible to get a message after we've | |
54 // hidden the window. If we allow the message to be dispatched chances are | |
55 // we'll crash in some weird place. By returning false we make sure the | |
56 // message isn't dispatched. | |
57 return false; | |
58 } | |
59 | |
60 int virtual_key_code = static_cast<int>(wparam); | |
61 int repeat_count = LOWORD(lparam); | |
62 int flags = HIWORD(lparam); | |
63 KeyEvent key_event(Event::ET_KEY_PRESSED, | |
64 virtual_key_code, repeat_count, flags); | |
65 | |
66 // If the focused view wants to process the key event as is, let it be. | 42 // If the focused view wants to process the key event as is, let it be. |
67 if (focused_view_ && focused_view_->SkipDefaultKeyEventProcessing(key_event)) | 43 if (focused_view_ && focused_view_->SkipDefaultKeyEventProcessing(event)) |
68 return true; | 44 return true; |
69 | 45 |
70 // Intercept Tab related messages for focus traversal. | 46 // Intercept Tab related messages for focus traversal. |
71 // Note that we don't do focus traversal if the root window is not part of the | 47 // Note that we don't do focus traversal if the root window is not part of the |
72 // active window hierarchy as this would mean we have no focused view and | 48 // active window hierarchy as this would mean we have no focused view and |
73 // would focus the first focusable view. | 49 // would focus the first focusable view. |
| 50 #if defined(OS_WIN) |
74 HWND top_window = widget_->GetNativeView(); | 51 HWND top_window = widget_->GetNativeView(); |
75 HWND active_window = ::GetActiveWindow(); | 52 HWND active_window = ::GetActiveWindow(); |
76 if ((active_window == top_window || ::IsChild(active_window, top_window)) && | 53 if ((active_window == top_window || ::IsChild(active_window, top_window)) && |
77 IsTabTraversalKeyEvent(key_event)) { | 54 IsTabTraversalKeyEvent(event)) { |
78 AdvanceFocus(win_util::IsShiftPressed()); | 55 AdvanceFocus(event.IsShiftDown()); |
79 return false; | 56 return false; |
80 } | 57 } |
| 58 #else |
| 59 if (IsTabTraversalKeyEvent(event)) { |
| 60 AdvanceFocus(event.IsShiftDown()); |
| 61 return false; |
| 62 } |
| 63 #endif |
81 | 64 |
82 // Intercept arrow key messages to switch between grouped views. | 65 // Intercept arrow key messages to switch between grouped views. |
| 66 int key_code = event.GetCharacter(); |
83 if (focused_view_ && focused_view_->GetGroup() != -1 && | 67 if (focused_view_ && focused_view_->GetGroup() != -1 && |
84 (virtual_key_code == VK_UP || virtual_key_code == VK_DOWN || | 68 (key_code == base::VKEY_UP || key_code == base::VKEY_DOWN || |
85 virtual_key_code == VK_LEFT || virtual_key_code == VK_RIGHT)) { | 69 key_code == base::VKEY_LEFT || key_code == base::VKEY_RIGHT)) { |
86 bool next = (virtual_key_code == VK_RIGHT || virtual_key_code == VK_DOWN); | 70 bool next = (key_code == base::VKEY_RIGHT || key_code == base::VKEY_DOWN); |
87 std::vector<View*> views; | 71 std::vector<View*> views; |
88 focused_view_->GetParent()->GetViewsWithGroup(focused_view_->GetGroup(), | 72 focused_view_->GetParent()->GetViewsWithGroup(focused_view_->GetGroup(), |
89 &views); | 73 &views); |
90 std::vector<View*>::const_iterator iter = std::find(views.begin(), | 74 std::vector<View*>::const_iterator iter = std::find(views.begin(), |
91 views.end(), | 75 views.end(), |
92 focused_view_); | 76 focused_view_); |
93 DCHECK(iter != views.end()); | 77 DCHECK(iter != views.end()); |
94 int index = static_cast<int>(iter - views.begin()); | 78 int index = static_cast<int>(iter - views.begin()); |
95 index += next ? 1 : -1; | 79 index += next ? 1 : -1; |
96 if (index < 0) { | 80 if (index < 0) { |
97 index = static_cast<int>(views.size()) - 1; | 81 index = static_cast<int>(views.size()) - 1; |
98 } else if (index >= static_cast<int>(views.size())) { | 82 } else if (index >= static_cast<int>(views.size())) { |
99 index = 0; | 83 index = 0; |
100 } | 84 } |
101 views[index]->RequestFocus(); | 85 views[index]->RequestFocus(); |
102 return false; | 86 return false; |
103 } | 87 } |
104 | 88 |
105 // Process keyboard accelerators. | 89 // Process keyboard accelerators. |
106 // We process accelerators here as we have no way of knowing if a HWND has | 90 // If the key combination matches an accelerator, the accelerator is |
107 // really processed a key event. If the key combination matches an | 91 // triggered, otherwise the key event is proceed as usual. |
108 // accelerator, the accelerator is triggered, otherwise we forward the | 92 Accelerator accelerator(event.GetCharacter(), |
109 // event to the HWND. | 93 event.IsShiftDown(), |
110 Accelerator accelerator(Accelerator(static_cast<int>(virtual_key_code), | 94 event.IsControlDown(), |
111 win_util::IsShiftPressed(), | 95 event.IsAltDown()); |
112 win_util::IsCtrlPressed(), | |
113 win_util::IsAltPressed())); | |
114 if (ProcessAccelerator(accelerator)) { | 96 if (ProcessAccelerator(accelerator)) { |
115 // If a shortcut was activated for this keydown message, do not propagate | 97 // If a shortcut was activated for this keydown message, do not propagate |
116 // the message further. | 98 // the event further. |
117 return false; | 99 return false; |
118 } | 100 } |
119 return true; | 101 return true; |
120 } | 102 } |
121 #endif | |
122 | 103 |
123 void FocusManager::ValidateFocusedView() { | 104 void FocusManager::ValidateFocusedView() { |
124 if (focused_view_) { | 105 if (focused_view_) { |
125 if (!ContainsView(focused_view_)) | 106 if (!ContainsView(focused_view_)) |
126 ClearFocus(); | 107 ClearFocus(); |
127 } | 108 } |
128 } | 109 } |
129 | 110 |
130 // Tests whether a view is valid, whether it still belongs to the window | 111 // Tests whether a view is valid, whether it still belongs to the window |
131 // hierarchy of the FocusManager. | 112 // hierarchy of the FocusManager. |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 if (map_iter != accelerators_.end()) { | 384 if (map_iter != accelerators_.end()) { |
404 // We have to copy the target list here, because an AcceleratorPressed | 385 // We have to copy the target list here, because an AcceleratorPressed |
405 // event handler may modify the list. | 386 // event handler may modify the list. |
406 AcceleratorTargetList targets(map_iter->second); | 387 AcceleratorTargetList targets(map_iter->second); |
407 for (AcceleratorTargetList::iterator iter = targets.begin(); | 388 for (AcceleratorTargetList::iterator iter = targets.begin(); |
408 iter != targets.end(); ++iter) { | 389 iter != targets.end(); ++iter) { |
409 if ((*iter)->AcceleratorPressed(accelerator)) | 390 if ((*iter)->AcceleratorPressed(accelerator)) |
410 return true; | 391 return true; |
411 } | 392 } |
412 } | 393 } |
413 | |
414 return false; | 394 return false; |
415 } | 395 } |
416 | 396 |
417 AcceleratorTarget* FocusManager::GetCurrentTargetForAccelerator( | 397 AcceleratorTarget* FocusManager::GetCurrentTargetForAccelerator( |
418 const views::Accelerator& accelerator) const { | 398 const views::Accelerator& accelerator) const { |
419 AcceleratorMap::const_iterator map_iter = accelerators_.find(accelerator); | 399 AcceleratorMap::const_iterator map_iter = accelerators_.find(accelerator); |
420 if (map_iter == accelerators_.end() || map_iter->second.empty()) | 400 if (map_iter == accelerators_.end() || map_iter->second.empty()) |
421 return NULL; | 401 return NULL; |
422 return map_iter->second.front(); | 402 return map_iter->second.front(); |
423 } | 403 } |
424 | 404 |
425 // static | 405 // static |
426 bool FocusManager::IsTabTraversalKeyEvent(const KeyEvent& key_event) { | 406 bool FocusManager::IsTabTraversalKeyEvent(const KeyEvent& key_event) { |
427 #if defined(OS_WIN) | 407 return key_event.GetCharacter() == base::VKEY_TAB && |
428 return key_event.GetCharacter() == VK_TAB && !win_util::IsCtrlPressed(); | 408 !key_event.IsControlDown(); |
429 #else | |
430 NOTIMPLEMENTED(); | |
431 return false; | |
432 #endif | |
433 } | 409 } |
434 | 410 |
435 void FocusManager::ViewRemoved(View* parent, View* removed) { | 411 void FocusManager::ViewRemoved(View* parent, View* removed) { |
436 if (focused_view_ && focused_view_ == removed) | 412 if (focused_view_ && focused_view_ == removed) |
437 ClearFocus(); | 413 ClearFocus(); |
438 } | 414 } |
439 | 415 |
440 void FocusManager::AddFocusChangeListener(FocusChangeListener* listener) { | 416 void FocusManager::AddFocusChangeListener(FocusChangeListener* listener) { |
441 DCHECK(std::find(focus_change_listeners_.begin(), | 417 DCHECK(std::find(focus_change_listeners_.begin(), |
442 focus_change_listeners_.end(), listener) == | 418 focus_change_listeners_.end(), listener) == |
443 focus_change_listeners_.end()) << "Adding a listener twice."; | 419 focus_change_listeners_.end()) << "Adding a listener twice."; |
444 focus_change_listeners_.push_back(listener); | 420 focus_change_listeners_.push_back(listener); |
445 } | 421 } |
446 | 422 |
447 void FocusManager::RemoveFocusChangeListener(FocusChangeListener* listener) { | 423 void FocusManager::RemoveFocusChangeListener(FocusChangeListener* listener) { |
448 FocusChangeListenerList::iterator place = | 424 FocusChangeListenerList::iterator place = |
449 std::find(focus_change_listeners_.begin(), focus_change_listeners_.end(), | 425 std::find(focus_change_listeners_.begin(), focus_change_listeners_.end(), |
450 listener); | 426 listener); |
451 if (place == focus_change_listeners_.end()) { | 427 if (place == focus_change_listeners_.end()) { |
452 NOTREACHED() << "Removing a listener that isn't registered."; | 428 NOTREACHED() << "Removing a listener that isn't registered."; |
453 return; | 429 return; |
454 } | 430 } |
455 focus_change_listeners_.erase(place); | 431 focus_change_listeners_.erase(place); |
456 } | 432 } |
457 | 433 |
458 } // namespace views | 434 } // namespace views |
OLD | NEW |