1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef UI_VIEWS_ACCESSIBLE_PANE_VIEW_H_ 6 #define UI_VIEWS_ACCESSIBLE_PANE_VIEW_H_ 7 8 #include <memory> 9 10 #include "base/macros.h" 11 #include "base/memory/weak_ptr.h" 12 #include "ui/base/accelerators/accelerator.h" 13 #include "ui/views/focus/focus_manager.h" 14 #include "ui/views/view.h" 15 16 namespace views { 17 class FocusSearch; 18 class ViewTracker; 19 20 // This class provides keyboard access to any view that extends it, typically 21 // a toolbar. The user sets focus to a control in this view by pressing 22 // F6 to traverse all panes, or by pressing a shortcut that jumps directly 23 // to this pane. 24 class VIEWS_EXPORT AccessiblePaneView : public View, 25 public FocusChangeListener, 26 public FocusTraversable { 27 public: 28 METADATA_HEADER(AccessiblePaneView); 29 30 AccessiblePaneView(); 31 ~AccessiblePaneView() override; 32 33 // Set focus to the pane with complete keyboard access. 34 // Focus will be restored to the last focused view if the user escapes. 35 // If |initial_focus| is not NULL, that control will get 36 // the initial focus, if it's enabled and focusable. Returns true if 37 // the pane was able to receive focus. 38 bool SetPaneFocus(View* initial_focus); 39 pane_has_focus()40 bool pane_has_focus() const { return pane_has_focus_; } 41 42 // Set focus to the pane with complete keyboard access, with the 43 // focus initially set to the default child. Focus will be restored 44 // to the last focused view if the user escapes. 45 // Returns true if the pane was able to receive focus. 46 virtual bool SetPaneFocusAndFocusDefault(); 47 48 // Overridden from View: 49 FocusTraversable* GetPaneFocusTraversable() override; 50 bool AcceleratorPressed(const ui::Accelerator& accelerator) override; 51 void SetVisible(bool flag) override; 52 void GetAccessibleNodeData(ui::AXNodeData* node_data) override; 53 void RequestFocus() override; 54 55 // Overridden from FocusChangeListener: 56 void OnWillChangeFocus(View* focused_before, View* focused_now) override; 57 void OnDidChangeFocus(View* focused_before, View* focused_now) override; 58 59 // Overridden from FocusTraversable: 60 FocusSearch* GetFocusSearch() override; 61 FocusTraversable* GetFocusTraversableParent() override; 62 View* GetFocusTraversableParentView() override; 63 64 // For testing only. home_key()65 const ui::Accelerator& home_key() const { return home_key_; } end_key()66 const ui::Accelerator& end_key() const { return end_key_; } escape_key()67 const ui::Accelerator& escape_key() const { return escape_key_; } left_key()68 const ui::Accelerator& left_key() const { return left_key_; } right_key()69 const ui::Accelerator& right_key() const { return right_key_; } 70 71 protected: 72 // A subclass can override this to provide a default focusable child 73 // other than the first focusable child. 74 virtual View* GetDefaultFocusableChild(); 75 76 // Returns the parent of |v|. Subclasses can override this if 77 // they need custom focus search behavior. 78 View* GetParentForFocusSearch(View* v); 79 80 // Returns true if |v| is contained within the hierarchy rooted at |root| 81 // for the purpose of focus searching. Subclasses can override this if 82 // they need custom focus search behavior. 83 bool ContainsForFocusSearch(View* root, const View* v); 84 85 // Remove pane focus. 86 void RemovePaneFocus(); 87 88 View* GetFirstFocusableChild(); 89 View* GetLastFocusableChild(); 90 focus_manager()91 FocusManager* focus_manager() const { return focus_manager_; } 92 93 // When finishing navigation by pressing ESC, it is allowed to surrender the 94 // focus to another window if if |allow| is set and no previous view can be 95 // found. set_allow_deactivate_on_esc(bool allow)96 void set_allow_deactivate_on_esc(bool allow) { 97 allow_deactivate_on_esc_ = allow; 98 } 99 100 private: 101 bool pane_has_focus_ = false; 102 103 // If true, the panel should be de-activated upon escape when no active view 104 // is known where to return to. 105 bool allow_deactivate_on_esc_ = false; 106 107 // Save the focus manager rather than calling GetFocusManager(), 108 // so that we can remove focus listeners in the destructor. 109 FocusManager* focus_manager_ = nullptr; 110 111 // Our custom focus search implementation that traps focus in this 112 // pane and traverses all views that are focusable for accessibility, 113 // not just those that are normally focusable. 114 std::unique_ptr<FocusSearch> focus_search_; 115 116 // Registered accelerators 117 ui::Accelerator home_key_{ui::VKEY_HOME, ui::EF_NONE}; 118 ui::Accelerator end_key_{ui::VKEY_END, ui::EF_NONE}; 119 ui::Accelerator escape_key_{ui::VKEY_ESCAPE, ui::EF_NONE}; 120 ui::Accelerator left_key_{ui::VKEY_LEFT, ui::EF_NONE}; 121 ui::Accelerator right_key_{ui::VKEY_RIGHT, ui::EF_NONE}; 122 123 // Holds the last focused view that's not within this pane. 124 std::unique_ptr<ViewTracker> last_focused_view_tracker_; 125 126 friend class AccessiblePaneViewFocusSearch; 127 128 base::WeakPtrFactory<AccessiblePaneView> method_factory_{this}; 129 130 DISALLOW_COPY_AND_ASSIGN(AccessiblePaneView); 131 }; 132 133 } // namespace views 134 135 #endif // UI_VIEWS_ACCESSIBLE_PANE_VIEW_H_ 136