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 3 // found in the LICENSE file. 4 5 #ifndef UI_VIEWS_FOCUS_FOCUS_MANAGER_H_ 6 #define UI_VIEWS_FOCUS_FOCUS_MANAGER_H_ 7 8 #include <list> 9 #include <map> 10 11 #include "base/basictypes.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "base/observer_list.h" 14 #include "ui/base/accelerators/accelerator.h" 15 #include "ui/base/accelerators/accelerator_manager.h" 16 #include "ui/gfx/native_widget_types.h" 17 #include "ui/views/views_export.h" 18 19 // The FocusManager class is used to handle focus traversal, store/restore 20 // focused views and handle keyboard accelerators. 21 // 22 // There are 2 types of focus: 23 // - the native focus, which is the focus that an gfx::NativeView has. 24 // - the view focus, which is the focus that a views::View has. 25 // 26 // Each native view must register with their Focus Manager so the focus manager 27 // gets notified when they are focused (and keeps track of the native focus) and 28 // as well so that the tab key events can be intercepted. 29 // They can provide when they register a View that is kept in synch in term of 30 // focus. This is used in NativeControl for example, where a View wraps an 31 // actual native window. 32 // This is already done for you if you subclass the NativeControl class or if 33 // you use the NativeViewHost class. 34 // 35 // When creating a top window (derived from views::Widget) that is not a child 36 // window, it creates and owns a FocusManager to manage the focus for itself and 37 // all its child windows. 38 // 39 // The FocusTraversable interface exposes the methods a class should implement 40 // in order to be able to be focus traversed when tab key is pressed. 41 // RootViews implement FocusTraversable. 42 // The FocusManager contains a top FocusTraversable instance, which is the top 43 // RootView. 44 // 45 // If you just use views, then the focus traversal is handled for you by the 46 // RootView. The default traversal order is the order in which the views have 47 // been added to their container. You can modify this order by using the View 48 // method SetNextFocusableView(). 49 // 50 // If you are embedding a native view containing a nested RootView (for example 51 // by adding a NativeControl that contains a NativeWidgetWin as its native 52 // component), then you need to: 53 // - override the View::GetFocusTraversable() method in your outer component. 54 // It should return the RootView of the inner component. This is used when 55 // the focus traversal traverse down the focus hierarchy to enter the nested 56 // RootView. In the example mentioned above, the NativeControl overrides 57 // GetFocusTraversable() and returns hwnd_view_container_->GetRootView(). 58 // - call Widget::SetFocusTraversableParent() on the nested RootView and point 59 // it to the outer RootView. This is used when the focus goes out of the 60 // nested RootView. In the example: 61 // hwnd_view_container_->GetWidget()->SetFocusTraversableParent( 62 // native_control->GetRootView()); 63 // - call RootView::SetFocusTraversableParentView() on the nested RootView with 64 // the parent view that directly contains the native window. This is needed 65 // when traversing up from the nested RootView to know which view to start 66 // with when going to the next/previous view. 67 // In our example: 68 // hwnd_view_container_->GetWidget()->SetFocusTraversableParent( 69 // native_control); 70 // 71 // Note that FocusTraversable do not have to be RootViews: AccessibleToolbarView 72 // is FocusTraversable. 73 74 namespace ui { 75 class AcceleratorTarget; 76 class AcceleratorManager; 77 class KeyEvent; 78 } 79 80 namespace views { 81 82 class FocusManagerDelegate; 83 class FocusSearch; 84 class RootView; 85 class View; 86 class Widget; 87 88 // The FocusTraversable interface is used by components that want to process 89 // focus traversal events (due to Tab/Shift-Tab key events). 90 class VIEWS_EXPORT FocusTraversable { 91 public: 92 // Return a FocusSearch object that implements the algorithm to find 93 // the next or previous focusable view. 94 virtual FocusSearch* GetFocusSearch() = 0; 95 96 // Should return the parent FocusTraversable. 97 // The top RootView which is the top FocusTraversable returns NULL. 98 virtual FocusTraversable* GetFocusTraversableParent() = 0; 99 100 // This should return the View this FocusTraversable belongs to. 101 // It is used when walking up the view hierarchy tree to find which view 102 // should be used as the starting view for finding the next/previous view. 103 virtual View* GetFocusTraversableParentView() = 0; 104 105 protected: 106 virtual ~FocusTraversable() {} 107 }; 108 109 // This interface should be implemented by classes that want to be notified when 110 // the focus is about to change. See the Add/RemoveFocusChangeListener methods. 111 class VIEWS_EXPORT FocusChangeListener { 112 public: 113 // No change to focus state has occurred yet when this function is called. 114 virtual void OnWillChangeFocus(View* focused_before, View* focused_now) = 0; 115 116 // Called after focus state has changed. 117 virtual void OnDidChangeFocus(View* focused_before, View* focused_now) = 0; 118 119 protected: 120 virtual ~FocusChangeListener() {} 121 }; 122 123 class VIEWS_EXPORT FocusManager { 124 public: 125 // The reason why the focus changed. 126 enum FocusChangeReason { 127 // The focus changed because the user traversed focusable views using 128 // keys like Tab or Shift+Tab. 129 kReasonFocusTraversal, 130 131 // The focus changed due to restoring the focus. 132 kReasonFocusRestore, 133 134 // The focus changed due to a click or a shortcut to jump directly to 135 // a particular view. 136 kReasonDirectFocusChange 137 }; 138 139 // TODO: use Direction in place of bool reverse throughout. 140 enum Direction { 141 kForward, 142 kBackward 143 }; 144 145 enum FocusCycleWrappingBehavior { 146 kWrap, 147 kNoWrap 148 }; 149 150 FocusManager(Widget* widget, FocusManagerDelegate* delegate); 151 virtual ~FocusManager(); 152 153 // Processes the passed key event for accelerators and keyboard traversal. 154 // Returns false if the event has been consumed and should not be processed 155 // further. 156 bool OnKeyEvent(const ui::KeyEvent& event); 157 158 // Returns true is the specified is part of the hierarchy of the window 159 // associated with this FocusManager. 160 bool ContainsView(View* view); 161 162 // Advances the focus (backward if reverse is true). 163 void AdvanceFocus(bool reverse); 164 165 // The FocusManager keeps track of the focused view within a RootView. 166 View* GetFocusedView() { return focused_view_; } 167 const View* GetFocusedView() const { return focused_view_; } 168 169 // Low-level methods to force the focus to change (and optionally provide 170 // a reason). If the focus change should only happen if the view is 171 // currenty focusable, enabled, and visible, call view->RequestFocus(). 172 void SetFocusedViewWithReason(View* view, FocusChangeReason reason); 173 void SetFocusedView(View* view) { 174 SetFocusedViewWithReason(view, kReasonDirectFocusChange); 175 } 176 177 // Get the reason why the focus most recently changed. 178 FocusChangeReason focus_change_reason() const { 179 return focus_change_reason_; 180 } 181 182 // Clears the focused view. The window associated with the top root view gets 183 // the native focus (so we still get keyboard events). 184 void ClearFocus(); 185 186 // Validates the focused view, clearing it if the window it belongs too is not 187 // attached to the window hierarchy anymore. 188 void ValidateFocusedView(); 189 190 // Stores the focused view. Used when the widget loses activation. 191 // |clear_native_focus| indicates whether this should invoke ClearFocus(). 192 // Typically |true| should be passed in. 193 void StoreFocusedView(bool clear_native_focus); 194 195 // Restore the view saved with a previous call to StoreFocusedView(). Used 196 // when the widget becomes active. Returns true when the previous view was 197 // successfully refocused - otherwise false. 198 bool RestoreFocusedView(); 199 200 // Sets the |view| to be restored when calling RestoreFocusView. This is used 201 // to set where the focus should go on restoring a Window created without 202 // focus being set. 203 void SetStoredFocusView(View* view); 204 205 // Returns the View that either currently has focus, or if no view has focus 206 // the view that last had focus. 207 View* GetStoredFocusView(); 208 209 // Clears the stored focused view. 210 void ClearStoredFocusedView(); 211 212 // Returns true if in the process of changing the focused view. 213 bool is_changing_focus() const { return is_changing_focus_; } 214 215 // Disable shortcut handling. 216 static void set_shortcut_handling_suspended(bool suspended) { 217 shortcut_handling_suspended_ = suspended; 218 } 219 // Returns whether shortcut handling is currently suspended. 220 bool shortcut_handling_suspended() { return shortcut_handling_suspended_; } 221 222 // Register a keyboard accelerator for the specified target. If multiple 223 // targets are registered for an accelerator, a target registered later has 224 // higher priority. 225 // |accelerator| is the accelerator to register. 226 // |priority| denotes the priority of the handler. 227 // NOTE: In almost all cases, you should specify kNormalPriority for this 228 // parameter. Setting it to kHighPriority prevents Chrome from sending the 229 // shortcut to the webpage if the renderer has focus, which is not desirable 230 // except for very isolated cases. 231 // |target| is the AcceleratorTarget that handles the event once the 232 // accelerator is pressed. 233 // Note that we are currently limited to accelerators that are either: 234 // - a key combination including Ctrl or Alt 235 // - the escape key 236 // - the enter key 237 // - any F key (F1, F2, F3 ...) 238 // - any browser specific keys (as available on special keyboards) 239 void RegisterAccelerator(const ui::Accelerator& accelerator, 240 ui::AcceleratorManager::HandlerPriority priority, 241 ui::AcceleratorTarget* target); 242 243 // Unregister the specified keyboard accelerator for the specified target. 244 void UnregisterAccelerator(const ui::Accelerator& accelerator, 245 ui::AcceleratorTarget* target); 246 247 // Unregister all keyboard accelerator for the specified target. 248 void UnregisterAccelerators(ui::AcceleratorTarget* target); 249 250 // Activate the target associated with the specified accelerator. 251 // First, AcceleratorPressed handler of the most recently registered target 252 // is called, and if that handler processes the event (i.e. returns true), 253 // this method immediately returns. If not, we do the same thing on the next 254 // target, and so on. 255 // Returns true if an accelerator was activated. 256 bool ProcessAccelerator(const ui::Accelerator& accelerator); 257 258 // Resets menu key state if |event| is not menu key release. 259 // This is effective only on x11. 260 void MaybeResetMenuKeyState(const ui::KeyEvent& key); 261 262 // Called by a RootView when a view within its hierarchy is removed 263 // from its parent. This will only be called by a RootView in a 264 // hierarchy of Widgets that this FocusManager is attached to the 265 // parent Widget of. 266 void ViewRemoved(View* removed); 267 268 // Adds/removes a listener. The FocusChangeListener is notified every time 269 // the focused view is about to change. 270 void AddFocusChangeListener(FocusChangeListener* listener); 271 void RemoveFocusChangeListener(FocusChangeListener* listener); 272 273 // Returns the AcceleratorTarget that should be activated for the specified 274 // keyboard accelerator, or NULL if no view is registered for that keyboard 275 // accelerator. 276 ui::AcceleratorTarget* GetCurrentTargetForAccelerator( 277 const ui::Accelerator& accelertor) const; 278 279 // Whether the given |accelerator| has a priority handler associated with it. 280 bool HasPriorityHandler(const ui::Accelerator& accelerator) const; 281 282 // Clears the native view having the focus. 283 virtual void ClearNativeFocus(); 284 285 // Focuses the next keyboard-accessible pane, taken from the list of 286 // views returned by WidgetDelegate::GetAccessiblePanes(). If there are 287 // no panes, the widget's root view is treated as a single pane. 288 // A keyboard-accessible pane should subclass from AccessiblePaneView in 289 // order to trap keyboard focus within that pane. If |wrap| is kWrap, 290 // it keeps cycling within this widget, otherwise it returns false after 291 // reaching the last pane so that focus can cycle to another widget. 292 bool RotatePaneFocus(Direction direction, FocusCycleWrappingBehavior wrap); 293 294 // Convenience method that returns true if the passed |key_event| should 295 // trigger tab traversal (if it is a TAB key press with or without SHIFT 296 // pressed). 297 static bool IsTabTraversalKeyEvent(const ui::KeyEvent& key_event); 298 299 // Sets whether arrow key traversal is enabled. When enabled, right/down key 300 // behaves like tab and left/up key behaves like shift-tab. Note when this 301 // is enabled, the arrow key movement within grouped views are disabled. 302 static void set_arrow_key_traversal_enabled(bool enabled) { 303 arrow_key_traversal_enabled_ = enabled; 304 } 305 // Returns whether arrow key traversal is enabled. 306 static bool arrow_key_traversal_enabled() { 307 return arrow_key_traversal_enabled_; 308 } 309 310 private: 311 // Returns the next focusable view. 312 View* GetNextFocusableView(View* starting_view, bool reverse, bool dont_loop); 313 314 // Returns the focusable view found in the FocusTraversable specified starting 315 // at the specified view. This traverses down along the FocusTraversable 316 // hierarchy. 317 // Returns NULL if no focusable view were found. 318 View* FindFocusableView(FocusTraversable* focus_traversable, 319 View* starting_view, 320 bool reverse); 321 322 // Process arrow key traversal. Returns true if the event has been consumed 323 // and should not be processed further. 324 bool ProcessArrowKeyTraversal(const ui::KeyEvent& event); 325 326 // Keeps track of whether shortcut handling is currently suspended. 327 static bool shortcut_handling_suspended_; 328 329 // Whether arrow key traversal is enabled. 330 static bool arrow_key_traversal_enabled_; 331 332 // The top-level Widget this FocusManager is associated with. 333 Widget* widget_; 334 335 // The object which handles an accelerator when |accelerator_manager_| doesn't 336 // handle it. 337 scoped_ptr<FocusManagerDelegate> delegate_; 338 339 // The view that currently is focused. 340 View* focused_view_; 341 342 // The AcceleratorManager this FocusManager is associated with. 343 scoped_ptr<ui::AcceleratorManager> accelerator_manager_; 344 345 // The storage id used in the ViewStorage to store/restore the view that last 346 // had focus. 347 int stored_focused_view_storage_id_; 348 349 // The reason why the focus most recently changed. 350 FocusChangeReason focus_change_reason_; 351 352 // The list of registered FocusChange listeners. 353 ObserverList<FocusChangeListener, true> focus_change_listeners_; 354 355 // See description above getter. 356 bool is_changing_focus_; 357 358 DISALLOW_COPY_AND_ASSIGN(FocusManager); 359 }; 360 361 } // namespace views 362 363 #endif // UI_VIEWS_FOCUS_FOCUS_MANAGER_H_ 364