| OLD | NEW |
| (Empty) |
| 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 AcceleratorManager; | |
| 76 class AcceleratorTarget; | |
| 77 class EventHandler; | |
| 78 class KeyEvent; | |
| 79 } | |
| 80 | |
| 81 namespace views { | |
| 82 | |
| 83 class FocusManagerDelegate; | |
| 84 class FocusSearch; | |
| 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 // Tries to advance focus if the focused view has become unfocusable. If there | |
| 187 // is no view available to advance focus to, focus will be cleared. | |
| 188 void AdvanceFocusIfNecessary(); | |
| 189 | |
| 190 // Validates the focused view, clearing it if the window it belongs too is not | |
| 191 // attached to the window hierarchy anymore. | |
| 192 void ValidateFocusedView(); | |
| 193 | |
| 194 // Stores the focused view. Used when the widget loses activation. | |
| 195 // |clear_native_focus| indicates whether this should invoke ClearFocus(). | |
| 196 // Typically |true| should be passed in. | |
| 197 void StoreFocusedView(bool clear_native_focus); | |
| 198 | |
| 199 // Restore the view saved with a previous call to StoreFocusedView(). Used | |
| 200 // when the widget becomes active. Returns true when the previous view was | |
| 201 // successfully refocused - otherwise false. | |
| 202 bool RestoreFocusedView(); | |
| 203 | |
| 204 // Sets the |view| to be restored when calling RestoreFocusView. This is used | |
| 205 // to set where the focus should go on restoring a Window created without | |
| 206 // focus being set. | |
| 207 void SetStoredFocusView(View* view); | |
| 208 | |
| 209 // Returns the View that either currently has focus, or if no view has focus | |
| 210 // the view that last had focus. | |
| 211 View* GetStoredFocusView(); | |
| 212 | |
| 213 // Clears the stored focused view. | |
| 214 void ClearStoredFocusedView(); | |
| 215 | |
| 216 // Returns true if in the process of changing the focused view. | |
| 217 bool is_changing_focus() const { return is_changing_focus_; } | |
| 218 | |
| 219 // Changes the text input focus to |view->GetTextInputClient()| iff |view| | |
| 220 // is focused. Views must call this method when their internal | |
| 221 // TextInputClient instance changes. | |
| 222 void OnTextInputClientChanged(View* view); | |
| 223 | |
| 224 // Moves the text input focus into/out from |view|. | |
| 225 void FocusTextInputClient(View* view); | |
| 226 void BlurTextInputClient(View* view); | |
| 227 | |
| 228 // Disable shortcut handling. | |
| 229 static void set_shortcut_handling_suspended(bool suspended) { | |
| 230 shortcut_handling_suspended_ = suspended; | |
| 231 } | |
| 232 // Returns whether shortcut handling is currently suspended. | |
| 233 bool shortcut_handling_suspended() { return shortcut_handling_suspended_; } | |
| 234 | |
| 235 // Register a keyboard accelerator for the specified target. If multiple | |
| 236 // targets are registered for an accelerator, a target registered later has | |
| 237 // higher priority. | |
| 238 // |accelerator| is the accelerator to register. | |
| 239 // |priority| denotes the priority of the handler. | |
| 240 // NOTE: In almost all cases, you should specify kNormalPriority for this | |
| 241 // parameter. Setting it to kHighPriority prevents Chrome from sending the | |
| 242 // shortcut to the webpage if the renderer has focus, which is not desirable | |
| 243 // except for very isolated cases. | |
| 244 // |target| is the AcceleratorTarget that handles the event once the | |
| 245 // accelerator is pressed. | |
| 246 // Note that we are currently limited to accelerators that are either: | |
| 247 // - a key combination including Ctrl or Alt | |
| 248 // - the escape key | |
| 249 // - the enter key | |
| 250 // - any F key (F1, F2, F3 ...) | |
| 251 // - any browser specific keys (as available on special keyboards) | |
| 252 void RegisterAccelerator(const ui::Accelerator& accelerator, | |
| 253 ui::AcceleratorManager::HandlerPriority priority, | |
| 254 ui::AcceleratorTarget* target); | |
| 255 | |
| 256 // Unregister the specified keyboard accelerator for the specified target. | |
| 257 void UnregisterAccelerator(const ui::Accelerator& accelerator, | |
| 258 ui::AcceleratorTarget* target); | |
| 259 | |
| 260 // Unregister all keyboard accelerator for the specified target. | |
| 261 void UnregisterAccelerators(ui::AcceleratorTarget* target); | |
| 262 | |
| 263 // Activate the target associated with the specified accelerator. | |
| 264 // First, AcceleratorPressed handler of the most recently registered target | |
| 265 // is called, and if that handler processes the event (i.e. returns true), | |
| 266 // this method immediately returns. If not, we do the same thing on the next | |
| 267 // target, and so on. | |
| 268 // Returns true if an accelerator was activated. | |
| 269 bool ProcessAccelerator(const ui::Accelerator& accelerator); | |
| 270 | |
| 271 // Resets menu key state if |event| is not menu key release. | |
| 272 // This is effective only on x11. | |
| 273 void MaybeResetMenuKeyState(const ui::KeyEvent& key); | |
| 274 | |
| 275 // Called by a RootView when a view within its hierarchy is removed | |
| 276 // from its parent. This will only be called by a RootView in a | |
| 277 // hierarchy of Widgets that this FocusManager is attached to the | |
| 278 // parent Widget of. | |
| 279 void ViewRemoved(View* removed); | |
| 280 | |
| 281 // Adds/removes a listener. The FocusChangeListener is notified every time | |
| 282 // the focused view is about to change. | |
| 283 void AddFocusChangeListener(FocusChangeListener* listener); | |
| 284 void RemoveFocusChangeListener(FocusChangeListener* listener); | |
| 285 | |
| 286 // Returns the AcceleratorTarget that should be activated for the specified | |
| 287 // keyboard accelerator, or NULL if no view is registered for that keyboard | |
| 288 // accelerator. | |
| 289 ui::AcceleratorTarget* GetCurrentTargetForAccelerator( | |
| 290 const ui::Accelerator& accelertor) const; | |
| 291 | |
| 292 // Whether the given |accelerator| has a priority handler associated with it. | |
| 293 bool HasPriorityHandler(const ui::Accelerator& accelerator) const; | |
| 294 | |
| 295 // Clears the native view having the focus. | |
| 296 virtual void ClearNativeFocus(); | |
| 297 | |
| 298 // Focuses the next keyboard-accessible pane, taken from the list of | |
| 299 // views returned by WidgetDelegate::GetAccessiblePanes(). If there are | |
| 300 // no panes, the widget's root view is treated as a single pane. | |
| 301 // A keyboard-accessible pane should subclass from AccessiblePaneView in | |
| 302 // order to trap keyboard focus within that pane. If |wrap| is kWrap, | |
| 303 // it keeps cycling within this widget, otherwise it returns false after | |
| 304 // reaching the last pane so that focus can cycle to another widget. | |
| 305 bool RotatePaneFocus(Direction direction, FocusCycleWrappingBehavior wrap); | |
| 306 | |
| 307 // Convenience method that returns true if the passed |key_event| should | |
| 308 // trigger tab traversal (if it is a TAB key press with or without SHIFT | |
| 309 // pressed). | |
| 310 static bool IsTabTraversalKeyEvent(const ui::KeyEvent& key_event); | |
| 311 | |
| 312 // Sets whether arrow key traversal is enabled. When enabled, right/down key | |
| 313 // behaves like tab and left/up key behaves like shift-tab. Note when this | |
| 314 // is enabled, the arrow key movement within grouped views are disabled. | |
| 315 static void set_arrow_key_traversal_enabled(bool enabled) { | |
| 316 arrow_key_traversal_enabled_ = enabled; | |
| 317 } | |
| 318 // Returns whether arrow key traversal is enabled. | |
| 319 static bool arrow_key_traversal_enabled() { | |
| 320 return arrow_key_traversal_enabled_; | |
| 321 } | |
| 322 | |
| 323 // Returns the next focusable view. Traversal starts at |starting_view|. If | |
| 324 // |starting_view| is NULL |starting_widget| is consuled to determine which | |
| 325 // Widget to start from. See | |
| 326 // WidgetDelegate::ShouldAdvanceFocusToTopLevelWidget() for details. If both | |
| 327 // |starting_view| and |starting_widget| are NULL, traversal starts at | |
| 328 // |widget_|. | |
| 329 View* GetNextFocusableView(View* starting_view, | |
| 330 Widget* starting_widget, | |
| 331 bool reverse, | |
| 332 bool dont_loop); | |
| 333 | |
| 334 private: | |
| 335 // Returns the focusable view found in the FocusTraversable specified starting | |
| 336 // at the specified view. This traverses down along the FocusTraversable | |
| 337 // hierarchy. | |
| 338 // Returns NULL if no focusable view were found. | |
| 339 View* FindFocusableView(FocusTraversable* focus_traversable, | |
| 340 View* starting_view, | |
| 341 bool reverse); | |
| 342 | |
| 343 // Process arrow key traversal. Returns true if the event has been consumed | |
| 344 // and should not be processed further. | |
| 345 bool ProcessArrowKeyTraversal(const ui::KeyEvent& event); | |
| 346 | |
| 347 // Keeps track of whether shortcut handling is currently suspended. | |
| 348 static bool shortcut_handling_suspended_; | |
| 349 | |
| 350 // Whether arrow key traversal is enabled. | |
| 351 static bool arrow_key_traversal_enabled_; | |
| 352 | |
| 353 // The top-level Widget this FocusManager is associated with. | |
| 354 Widget* widget_; | |
| 355 | |
| 356 // The object which handles an accelerator when |accelerator_manager_| doesn't | |
| 357 // handle it. | |
| 358 scoped_ptr<FocusManagerDelegate> delegate_; | |
| 359 | |
| 360 // The view that currently is focused. | |
| 361 View* focused_view_; | |
| 362 | |
| 363 // The AcceleratorManager this FocusManager is associated with. | |
| 364 scoped_ptr<ui::AcceleratorManager> accelerator_manager_; | |
| 365 | |
| 366 // The storage id used in the ViewStorage to store/restore the view that last | |
| 367 // had focus. | |
| 368 int stored_focused_view_storage_id_; | |
| 369 | |
| 370 // The reason why the focus most recently changed. | |
| 371 FocusChangeReason focus_change_reason_; | |
| 372 | |
| 373 // The list of registered FocusChange listeners. | |
| 374 ObserverList<FocusChangeListener, true> focus_change_listeners_; | |
| 375 | |
| 376 // See description above getter. | |
| 377 bool is_changing_focus_; | |
| 378 | |
| 379 DISALLOW_COPY_AND_ASSIGN(FocusManager); | |
| 380 }; | |
| 381 | |
| 382 } // namespace views | |
| 383 | |
| 384 #endif // UI_VIEWS_FOCUS_FOCUS_MANAGER_H_ | |
| OLD | NEW |