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