OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "ui/views/focus/focus_manager.h" | 5 #include "ui/views/focus/focus_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "build/build_config.h" | 11 #include "build/build_config.h" |
12 #include "ui/base/accelerators/accelerator.h" | 12 #include "ui/base/accelerators/accelerator.h" |
13 #include "ui/base/keycodes/keyboard_codes.h" | 13 #include "ui/base/keycodes/keyboard_codes.h" |
| 14 #include "ui/views/focus/focus_manager_delegate.h" |
14 #include "ui/views/focus/focus_search.h" | 15 #include "ui/views/focus/focus_search.h" |
15 #include "ui/views/focus/view_storage.h" | 16 #include "ui/views/focus/view_storage.h" |
16 #include "ui/views/focus/widget_focus_manager.h" | 17 #include "ui/views/focus/widget_focus_manager.h" |
17 #include "ui/views/view.h" | 18 #include "ui/views/view.h" |
18 #include "ui/views/widget/root_view.h" | 19 #include "ui/views/widget/root_view.h" |
19 #include "ui/views/widget/widget.h" | 20 #include "ui/views/widget/widget.h" |
20 | 21 |
21 namespace views { | 22 namespace views { |
22 | 23 |
23 FocusManager::FocusManager(Widget* widget) | 24 FocusManager::FocusManager(Widget* widget, FocusManagerDelegate* delegate) |
24 : widget_(widget), | 25 : widget_(widget), |
| 26 delegate_(delegate), |
25 focused_view_(NULL), | 27 focused_view_(NULL), |
26 accelerator_manager_(new ui::AcceleratorManager), | 28 accelerator_manager_(new ui::AcceleratorManager), |
27 focus_change_reason_(kReasonDirectFocusChange), | 29 focus_change_reason_(kReasonDirectFocusChange), |
28 #if defined(USE_X11) | 30 #if defined(USE_X11) |
29 should_handle_menu_key_release_(false), | 31 should_handle_menu_key_release_(false), |
30 #endif | 32 #endif |
31 is_changing_focus_(false) { | 33 is_changing_focus_(false) { |
32 DCHECK(widget_); | 34 DCHECK(widget_); |
33 stored_focused_view_storage_id_ = | 35 stored_focused_view_storage_id_ = |
34 ViewStorage::GetInstance()->CreateStorageID(); | 36 ViewStorage::GetInstance()->CreateStorageID(); |
(...skipping 12 matching lines...) Expand all Loading... |
47 // Always reset |should_handle_menu_key_release_| unless we are handling a | 49 // Always reset |should_handle_menu_key_release_| unless we are handling a |
48 // VKEY_MENU key release event. It ensures that VKEY_MENU accelerator can only | 50 // VKEY_MENU key release event. It ensures that VKEY_MENU accelerator can only |
49 // be activated when handling a VKEY_MENU key release event which is preceded | 51 // be activated when handling a VKEY_MENU key release event which is preceded |
50 // by an un-handled VKEY_MENU key press event. | 52 // by an un-handled VKEY_MENU key press event. |
51 if (key_code != ui::VKEY_MENU || event.type() != ui::ET_KEY_RELEASED) | 53 if (key_code != ui::VKEY_MENU || event.type() != ui::ET_KEY_RELEASED) |
52 should_handle_menu_key_release_ = false; | 54 should_handle_menu_key_release_ = false; |
53 | 55 |
54 if (event.type() == ui::ET_KEY_PRESSED) { | 56 if (event.type() == ui::ET_KEY_PRESSED) { |
55 // VKEY_MENU is triggered by key release event. | 57 // VKEY_MENU is triggered by key release event. |
56 // FocusManager::OnKeyEvent() returns false when the key has been consumed. | 58 // FocusManager::OnKeyEvent() returns false when the key has been consumed. |
57 if (key_code == ui::VKEY_MENU) { | 59 if ((key_code == ui::VKEY_MENU) && |
| 60 (event.flags() & ~ui::EF_ALT_DOWN) == 0) { |
58 should_handle_menu_key_release_ = true; | 61 should_handle_menu_key_release_ = true; |
59 return false; | 62 return false; |
60 } | 63 } |
61 // Pass through to the reset of OnKeyEvent. | 64 // Pass through to the rest of OnKeyEvent. |
62 } else if (key_code == ui::VKEY_MENU && should_handle_menu_key_release_ && | 65 } else if (key_code == ui::VKEY_MENU && should_handle_menu_key_release_ && |
63 (event.flags() & ~ui::EF_ALT_DOWN) == 0) { | 66 (event.flags() & ~ui::EF_ALT_DOWN) == 0) { |
64 // Trigger VKEY_MENU when only this key is pressed and released, and both | 67 // Trigger VKEY_MENU when only this key is pressed and released, and both |
65 // press and release events are not handled by others. | 68 // press and release events are not handled by others. |
66 ui::Accelerator accelerator(ui::VKEY_MENU, false, false, false); | 69 ui::Accelerator accelerator(ui::VKEY_MENU, false, false, false); |
67 return ProcessAccelerator(accelerator); | 70 return ProcessAccelerator(accelerator); |
68 } else { | 71 } else if (event.type() != ui::ET_KEY_RELEASED) { |
69 return false; | 72 return false; |
70 } | 73 } |
71 #else | 74 #else |
72 if (event.type() != ui::ET_KEY_PRESSED) | 75 if (event.type() != ui::ET_KEY_PRESSED && event.type() != ui::ET_KEY_RELEASED) |
73 return false; | 76 return false; |
74 #endif | 77 #endif |
75 | 78 |
76 ui::Accelerator accelerator(event.key_code(), | 79 ui::Accelerator accelerator(event.key_code(), |
77 event.IsShiftDown(), | 80 event.IsShiftDown(), |
78 event.IsControlDown(), | 81 event.IsControlDown(), |
79 event.IsAltDown()); | 82 event.IsAltDown()); |
| 83 accelerator.set_type(event.type()); |
80 | 84 |
| 85 if (event.type() == ui::ET_KEY_PRESSED) { |
81 #if defined(OS_WIN) | 86 #if defined(OS_WIN) |
82 // If the focused view wants to process the key event as is, let it be. | 87 // If the focused view wants to process the key event as is, let it be. |
83 // This is not used for linux/aura. | 88 // This is not used for linux/aura. |
84 if (focused_view_ && focused_view_->SkipDefaultKeyEventProcessing(event) && | 89 if (focused_view_ && focused_view_->SkipDefaultKeyEventProcessing(event) && |
85 !accelerator_manager_->HasPriorityHandler(accelerator)) | 90 !accelerator_manager_->HasPriorityHandler(accelerator)) |
86 return true; | 91 return true; |
87 #endif | 92 #endif |
88 | 93 |
89 // Intercept Tab related messages for focus traversal. | 94 // Intercept Tab related messages for focus traversal. |
90 // Note that we don't do focus traversal if the root window is not part of the | 95 // Note that we don't do focus traversal if the root window is not part of |
91 // active window hierarchy as this would mean we have no focused view and | 96 // the active window hierarchy as this would mean we have no focused view |
92 // would focus the first focusable view. | 97 // and would focus the first focusable view. |
93 #if defined(OS_WIN) && !defined(USE_AURA) | 98 #if defined(OS_WIN) && !defined(USE_AURA) |
94 HWND top_window = widget_->GetNativeView(); | 99 HWND top_window = widget_->GetNativeView(); |
95 HWND active_window = ::GetActiveWindow(); | 100 HWND active_window = ::GetActiveWindow(); |
96 if ((active_window == top_window || ::IsChild(active_window, top_window)) && | 101 if ((active_window == top_window || ::IsChild(active_window, top_window)) && |
97 IsTabTraversalKeyEvent(event)) { | 102 IsTabTraversalKeyEvent(event)) { |
98 AdvanceFocus(event.IsShiftDown()); | 103 AdvanceFocus(event.IsShiftDown()); |
99 return false; | 104 return false; |
100 } | 105 } |
101 #else | 106 #else |
102 if (IsTabTraversalKeyEvent(event)) { | 107 if (IsTabTraversalKeyEvent(event)) { |
103 AdvanceFocus(event.IsShiftDown()); | 108 AdvanceFocus(event.IsShiftDown()); |
104 return false; | 109 return false; |
105 } | 110 } |
106 #endif | 111 #endif |
107 | 112 |
108 // Intercept arrow key messages to switch between grouped views. | 113 // Intercept arrow key messages to switch between grouped views. |
109 if (focused_view_ && focused_view_->GetGroup() != -1 && | 114 if (focused_view_ && focused_view_->GetGroup() != -1 && |
110 (key_code == ui::VKEY_UP || key_code == ui::VKEY_DOWN || | 115 (key_code == ui::VKEY_UP || key_code == ui::VKEY_DOWN || |
111 key_code == ui::VKEY_LEFT || key_code == ui::VKEY_RIGHT)) { | 116 key_code == ui::VKEY_LEFT || key_code == ui::VKEY_RIGHT)) { |
112 bool next = (key_code == ui::VKEY_RIGHT || key_code == ui::VKEY_DOWN); | 117 bool next = (key_code == ui::VKEY_RIGHT || key_code == ui::VKEY_DOWN); |
113 View::Views views; | 118 View::Views views; |
114 focused_view_->parent()->GetViewsInGroup(focused_view_->GetGroup(), &views); | 119 focused_view_->parent()->GetViewsInGroup(focused_view_->GetGroup(), |
115 View::Views::const_iterator i( | 120 &views); |
116 std::find(views.begin(), views.end(), focused_view_)); | 121 View::Views::const_iterator i( |
117 DCHECK(i != views.end()); | 122 std::find(views.begin(), views.end(), focused_view_)); |
118 int index = static_cast<int>(i - views.begin()); | 123 DCHECK(i != views.end()); |
119 index += next ? 1 : -1; | 124 int index = static_cast<int>(i - views.begin()); |
120 if (index < 0) { | 125 index += next ? 1 : -1; |
121 index = static_cast<int>(views.size()) - 1; | 126 if (index < 0) { |
122 } else if (index >= static_cast<int>(views.size())) { | 127 index = static_cast<int>(views.size()) - 1; |
123 index = 0; | 128 } else if (index >= static_cast<int>(views.size())) { |
| 129 index = 0; |
| 130 } |
| 131 SetFocusedViewWithReason(views[index], kReasonFocusTraversal); |
| 132 return false; |
124 } | 133 } |
125 SetFocusedViewWithReason(views[index], kReasonFocusTraversal); | |
126 return false; | |
127 } | 134 } |
128 | 135 |
129 // Process keyboard accelerators. | 136 // Process keyboard accelerators. |
130 // If the key combination matches an accelerator, the accelerator is | 137 // If the key combination matches an accelerator, the accelerator is |
131 // triggered, otherwise the key event is processed as usual. | 138 // triggered, otherwise the key event is processed as usual. |
132 if (ProcessAccelerator(accelerator)) { | 139 if (ProcessAccelerator(accelerator)) { |
133 // If a shortcut was activated for this keydown message, do not propagate | 140 // If a shortcut was activated for this keydown message, do not propagate |
134 // the event further. | 141 // the event further. |
135 return false; | 142 return false; |
136 } | 143 } |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
413 void FocusManager::UnregisterAccelerator(const ui::Accelerator& accelerator, | 420 void FocusManager::UnregisterAccelerator(const ui::Accelerator& accelerator, |
414 ui::AcceleratorTarget* target) { | 421 ui::AcceleratorTarget* target) { |
415 accelerator_manager_->Unregister(accelerator, target); | 422 accelerator_manager_->Unregister(accelerator, target); |
416 } | 423 } |
417 | 424 |
418 void FocusManager::UnregisterAccelerators(ui::AcceleratorTarget* target) { | 425 void FocusManager::UnregisterAccelerators(ui::AcceleratorTarget* target) { |
419 accelerator_manager_->UnregisterAll(target); | 426 accelerator_manager_->UnregisterAll(target); |
420 } | 427 } |
421 | 428 |
422 bool FocusManager::ProcessAccelerator(const ui::Accelerator& accelerator) { | 429 bool FocusManager::ProcessAccelerator(const ui::Accelerator& accelerator) { |
423 return accelerator_manager_->Process(accelerator); | 430 if (accelerator_manager_->Process(accelerator)) |
| 431 return true; |
| 432 if (delegate_.get()) |
| 433 return delegate_->ProcessAccelerator(accelerator); |
| 434 return false; |
424 } | 435 } |
425 | 436 |
426 void FocusManager::MaybeResetMenuKeyState(const KeyEvent& key) { | 437 void FocusManager::MaybeResetMenuKeyState(const KeyEvent& key) { |
427 #if defined(USE_X11) | 438 #if defined(USE_X11) |
428 // Always reset |should_handle_menu_key_release_| unless we are handling a | 439 // Always reset |should_handle_menu_key_release_| unless we are handling a |
429 // VKEY_MENU key release event. It ensures that VKEY_MENU accelerator can only | 440 // VKEY_MENU key release event. It ensures that VKEY_MENU accelerator can only |
430 // be activated when handling a VKEY_MENU key release event which is preceded | 441 // be activated when handling a VKEY_MENU key release event which is preceded |
431 // by an unhandled VKEY_MENU key press event. See also HandleKeyboardEvent(). | 442 // by an unhandled VKEY_MENU key press event. See also HandleKeyboardEvent(). |
432 if (key.key_code() != ui::VKEY_MENU || key.type() != ui::ET_KEY_RELEASED) | 443 if (key.key_code() != ui::VKEY_MENU || key.type() != ui::ET_KEY_RELEASED) |
433 should_handle_menu_key_release_ = false; | 444 should_handle_menu_key_release_ = false; |
434 #endif | 445 #endif |
435 } | 446 } |
436 | 447 |
437 ui::AcceleratorTarget* FocusManager::GetCurrentTargetForAccelerator( | 448 ui::AcceleratorTarget* FocusManager::GetCurrentTargetForAccelerator( |
438 const ui::Accelerator& accelerator) const { | 449 const ui::Accelerator& accelerator) const { |
439 return accelerator_manager_->GetCurrentTarget(accelerator); | 450 ui::AcceleratorTarget* target = |
| 451 accelerator_manager_->GetCurrentTarget(accelerator); |
| 452 if (!target && delegate_.get()) |
| 453 target = delegate_->GetCurrentTargetForAccelerator(accelerator); |
| 454 return target; |
440 } | 455 } |
441 | 456 |
442 bool FocusManager::HasPriorityHandler( | 457 bool FocusManager::HasPriorityHandler( |
443 const ui::Accelerator& accelerator) const { | 458 const ui::Accelerator& accelerator) const { |
444 return accelerator_manager_->HasPriorityHandler(accelerator); | 459 return accelerator_manager_->HasPriorityHandler(accelerator); |
445 } | 460 } |
446 | 461 |
447 // static | 462 // static |
448 bool FocusManager::IsTabTraversalKeyEvent(const KeyEvent& key_event) { | 463 bool FocusManager::IsTabTraversalKeyEvent(const KeyEvent& key_event) { |
449 return key_event.key_code() == ui::VKEY_TAB && !key_event.IsControlDown(); | 464 return key_event.key_code() == ui::VKEY_TAB && !key_event.IsControlDown(); |
(...skipping 10 matching lines...) Expand all Loading... |
460 | 475 |
461 void FocusManager::AddFocusChangeListener(FocusChangeListener* listener) { | 476 void FocusManager::AddFocusChangeListener(FocusChangeListener* listener) { |
462 focus_change_listeners_.AddObserver(listener); | 477 focus_change_listeners_.AddObserver(listener); |
463 } | 478 } |
464 | 479 |
465 void FocusManager::RemoveFocusChangeListener(FocusChangeListener* listener) { | 480 void FocusManager::RemoveFocusChangeListener(FocusChangeListener* listener) { |
466 focus_change_listeners_.RemoveObserver(listener); | 481 focus_change_listeners_.RemoveObserver(listener); |
467 } | 482 } |
468 | 483 |
469 } // namespace views | 484 } // namespace views |
OLD | NEW |