| 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 |