focus_manager.h revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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 74namespace ui { 75class AcceleratorTarget; 76class AcceleratorManager; 77class KeyEvent; 78} 79 80namespace views { 81 82class FocusManagerDelegate; 83class FocusSearch; 84class RootView; 85class View; 86class 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). 90class 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. 111class 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 123class 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 FocusManager(Widget* widget, FocusManagerDelegate* delegate); 140 virtual ~FocusManager(); 141 142 // Processes the passed key event for accelerators and tab traversal. 143 // Returns false if the event has been consumed and should not be processed 144 // further. 145 bool OnKeyEvent(const ui::KeyEvent& event); 146 147 // Returns true is the specified is part of the hierarchy of the window 148 // associated with this FocusManager. 149 bool ContainsView(View* view); 150 151 // Advances the focus (backward if reverse is true). 152 void AdvanceFocus(bool reverse); 153 154 // The FocusManager keeps track of the focused view within a RootView. 155 View* GetFocusedView() { return focused_view_; } 156 const View* GetFocusedView() const { return focused_view_; } 157 158 // Low-level methods to force the focus to change (and optionally provide 159 // a reason). If the focus change should only happen if the view is 160 // currenty focusable, enabled, and visible, call view->RequestFocus(). 161 void SetFocusedViewWithReason(View* view, FocusChangeReason reason); 162 void SetFocusedView(View* view) { 163 SetFocusedViewWithReason(view, kReasonDirectFocusChange); 164 } 165 166 // Get the reason why the focus most recently changed. 167 FocusChangeReason focus_change_reason() const { 168 return focus_change_reason_; 169 } 170 171 // Clears the focused view. The window associated with the top root view gets 172 // the native focus (so we still get keyboard events). 173 void ClearFocus(); 174 175 // Validates the focused view, clearing it if the window it belongs too is not 176 // attached to the window hierarchy anymore. 177 void ValidateFocusedView(); 178 179 // Stores the focused view. Used when the widget loses activation. 180 // |clear_native_focus| indicates whether this should invoke ClearFocus(). 181 // Typically |true| should be passed in. 182 void StoreFocusedView(bool clear_native_focus); 183 184 // Restore the view saved with a previous call to StoreFocusedView(). Used 185 // when the widget becomes active. Returns true when the previous view was 186 // successfully refocused - otherwise false. 187 bool RestoreFocusedView(); 188 189 // Clears the stored focused view. 190 void ClearStoredFocusedView(); 191 192 // Returns true if in the process of changing the focused view. 193 bool is_changing_focus() const { return is_changing_focus_; } 194 195 // Disable shortcut handling. 196 static void set_shortcut_handling_suspended(bool suspended) { 197 shortcut_handling_suspended_ = suspended; 198 } 199 // Returns whether shortcut handling is currently suspended. 200 bool shortcut_handling_suspended() { return shortcut_handling_suspended_; } 201 202 // Register a keyboard accelerator for the specified target. If multiple 203 // targets are registered for an accelerator, a target registered later has 204 // higher priority. 205 // |accelerator| is the accelerator to register. 206 // |priority| denotes the priority of the handler. 207 // NOTE: In almost all cases, you should specify kNormalPriority for this 208 // parameter. Setting it to kHighPriority prevents Chrome from sending the 209 // shortcut to the webpage if the renderer has focus, which is not desirable 210 // except for very isolated cases. 211 // |target| is the AcceleratorTarget that handles the event once the 212 // accelerator is pressed. 213 // Note that we are currently limited to accelerators that are either: 214 // - a key combination including Ctrl or Alt 215 // - the escape key 216 // - the enter key 217 // - any F key (F1, F2, F3 ...) 218 // - any browser specific keys (as available on special keyboards) 219 void RegisterAccelerator(const ui::Accelerator& accelerator, 220 ui::AcceleratorManager::HandlerPriority priority, 221 ui::AcceleratorTarget* target); 222 223 // Unregister the specified keyboard accelerator for the specified target. 224 void UnregisterAccelerator(const ui::Accelerator& accelerator, 225 ui::AcceleratorTarget* target); 226 227 // Unregister all keyboard accelerator for the specified target. 228 void UnregisterAccelerators(ui::AcceleratorTarget* target); 229 230 // Activate the target associated with the specified accelerator. 231 // First, AcceleratorPressed handler of the most recently registered target 232 // is called, and if that handler processes the event (i.e. returns true), 233 // this method immediately returns. If not, we do the same thing on the next 234 // target, and so on. 235 // Returns true if an accelerator was activated. 236 bool ProcessAccelerator(const ui::Accelerator& accelerator); 237 238 // Resets menu key state if |event| is not menu key release. 239 // This is effective only on x11. 240 void MaybeResetMenuKeyState(const ui::KeyEvent& key); 241 242 // Called by a RootView when a view within its hierarchy is removed 243 // from its parent. This will only be called by a RootView in a 244 // hierarchy of Widgets that this FocusManager is attached to the 245 // parent Widget of. 246 void ViewRemoved(View* removed); 247 248 // Adds/removes a listener. The FocusChangeListener is notified every time 249 // the focused view is about to change. 250 void AddFocusChangeListener(FocusChangeListener* listener); 251 void RemoveFocusChangeListener(FocusChangeListener* listener); 252 253 // Returns the AcceleratorTarget that should be activated for the specified 254 // keyboard accelerator, or NULL if no view is registered for that keyboard 255 // accelerator. 256 ui::AcceleratorTarget* GetCurrentTargetForAccelerator( 257 const ui::Accelerator& accelertor) const; 258 259 // Whether the given |accelerator| has a priority handler associated with it. 260 bool HasPriorityHandler(const ui::Accelerator& accelerator) const; 261 262 // Clears the native view having the focus. 263 virtual void ClearNativeFocus(); 264 265 // Convenience method that returns true if the passed |key_event| should 266 // trigger tab traversal (if it is a TAB key press with or without SHIFT 267 // pressed). 268 static bool IsTabTraversalKeyEvent(const ui::KeyEvent& key_event); 269 270 private: 271 // Returns the next focusable view. 272 View* GetNextFocusableView(View* starting_view, bool reverse, bool dont_loop); 273 274 // Returns the focusable view found in the FocusTraversable specified starting 275 // at the specified view. This traverses down along the FocusTraversable 276 // hierarchy. 277 // Returns NULL if no focusable view were found. 278 View* FindFocusableView(FocusTraversable* focus_traversable, 279 View* starting_view, 280 bool reverse); 281 282 // Keeps track of whether shortcut handling is currently suspended. 283 static bool shortcut_handling_suspended_; 284 285 // The top-level Widget this FocusManager is associated with. 286 Widget* widget_; 287 288 // The object which handles an accelerator when |accelerator_manager_| doesn't 289 // handle it. 290 scoped_ptr<FocusManagerDelegate> delegate_; 291 292 // The view that currently is focused. 293 View* focused_view_; 294 295 // The AcceleratorManager this FocusManager is associated with. 296 scoped_ptr<ui::AcceleratorManager> accelerator_manager_; 297 298 // The storage id used in the ViewStorage to store/restore the view that last 299 // had focus. 300 int stored_focused_view_storage_id_; 301 302 // The reason why the focus most recently changed. 303 FocusChangeReason focus_change_reason_; 304 305 // The list of registered FocusChange listeners. 306 ObserverList<FocusChangeListener, true> focus_change_listeners_; 307 308 // See description above getter. 309 bool is_changing_focus_; 310 311 DISALLOW_COPY_AND_ASSIGN(FocusManager); 312}; 313 314} // namespace views 315 316#endif // UI_VIEWS_FOCUS_FOCUS_MANAGER_H_ 317