• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 RootView;
86 class View;
87 class Widget;
88 
89 // The FocusTraversable interface is used by components that want to process
90 // focus traversal events (due to Tab/Shift-Tab key events).
91 class VIEWS_EXPORT FocusTraversable {
92  public:
93   // Return a FocusSearch object that implements the algorithm to find
94   // the next or previous focusable view.
95   virtual FocusSearch* GetFocusSearch() = 0;
96 
97   // Should return the parent FocusTraversable.
98   // The top RootView which is the top FocusTraversable returns NULL.
99   virtual FocusTraversable* GetFocusTraversableParent() = 0;
100 
101   // This should return the View this FocusTraversable belongs to.
102   // It is used when walking up the view hierarchy tree to find which view
103   // should be used as the starting view for finding the next/previous view.
104   virtual View* GetFocusTraversableParentView() = 0;
105 
106  protected:
~FocusTraversable()107   virtual ~FocusTraversable() {}
108 };
109 
110 // This interface should be implemented by classes that want to be notified when
111 // the focus is about to change.  See the Add/RemoveFocusChangeListener methods.
112 class VIEWS_EXPORT FocusChangeListener {
113  public:
114   // No change to focus state has occurred yet when this function is called.
115   virtual void OnWillChangeFocus(View* focused_before, View* focused_now) = 0;
116 
117   // Called after focus state has changed.
118   virtual void OnDidChangeFocus(View* focused_before, View* focused_now) = 0;
119 
120  protected:
~FocusChangeListener()121   virtual ~FocusChangeListener() {}
122 };
123 
124 class VIEWS_EXPORT FocusManager {
125  public:
126   // The reason why the focus changed.
127   enum FocusChangeReason {
128     // The focus changed because the user traversed focusable views using
129     // keys like Tab or Shift+Tab.
130     kReasonFocusTraversal,
131 
132     // The focus changed due to restoring the focus.
133     kReasonFocusRestore,
134 
135     // The focus changed due to a click or a shortcut to jump directly to
136     // a particular view.
137     kReasonDirectFocusChange
138   };
139 
140   // TODO: use Direction in place of bool reverse throughout.
141   enum Direction {
142     kForward,
143     kBackward
144   };
145 
146   enum FocusCycleWrappingBehavior {
147     kWrap,
148     kNoWrap
149   };
150 
151   FocusManager(Widget* widget, FocusManagerDelegate* delegate);
152   virtual ~FocusManager();
153 
154   // Processes the passed key event for accelerators and keyboard traversal.
155   // Returns false if the event has been consumed and should not be processed
156   // further.
157   bool OnKeyEvent(const ui::KeyEvent& event);
158 
159   // Returns true is the specified is part of the hierarchy of the window
160   // associated with this FocusManager.
161   bool ContainsView(View* view);
162 
163   // Advances the focus (backward if reverse is true).
164   void AdvanceFocus(bool reverse);
165 
166   // The FocusManager keeps track of the focused view within a RootView.
GetFocusedView()167   View* GetFocusedView() { return focused_view_; }
GetFocusedView()168   const View* GetFocusedView() const { return focused_view_; }
169 
170   // Low-level methods to force the focus to change (and optionally provide
171   // a reason). If the focus change should only happen if the view is
172   // currenty focusable, enabled, and visible, call view->RequestFocus().
173   void SetFocusedViewWithReason(View* view, FocusChangeReason reason);
SetFocusedView(View * view)174   void SetFocusedView(View* view) {
175     SetFocusedViewWithReason(view, kReasonDirectFocusChange);
176   }
177 
178   // Get the reason why the focus most recently changed.
focus_change_reason()179   FocusChangeReason focus_change_reason() const {
180     return focus_change_reason_;
181   }
182 
183   // Clears the focused view. The window associated with the top root view gets
184   // the native focus (so we still get keyboard events).
185   void ClearFocus();
186 
187   // Validates the focused view, clearing it if the window it belongs too is not
188   // attached to the window hierarchy anymore.
189   void ValidateFocusedView();
190 
191   // Stores the focused view. Used when the widget loses activation.
192   // |clear_native_focus| indicates whether this should invoke ClearFocus().
193   // Typically |true| should be passed in.
194   void StoreFocusedView(bool clear_native_focus);
195 
196   // Restore the view saved with a previous call to StoreFocusedView(). Used
197   // when the widget becomes active. Returns true when the previous view was
198   // successfully refocused - otherwise false.
199   bool RestoreFocusedView();
200 
201   // Sets the |view| to be restored when calling RestoreFocusView. This is used
202   // to set where the focus should go on restoring a Window created without
203   // focus being set.
204   void SetStoredFocusView(View* view);
205 
206   // Returns the View that either currently has focus, or if no view has focus
207   // the view that last had focus.
208   View* GetStoredFocusView();
209 
210   // Clears the stored focused view.
211   void ClearStoredFocusedView();
212 
213   // Returns true if in the process of changing the focused view.
is_changing_focus()214   bool is_changing_focus() const { return is_changing_focus_; }
215 
216   // Changes the text input focus to |view->GetTextInputClient()| iff |view|
217   // is focused.  Views must call this method when their internal
218   // TextInputClient instance changes.
219   void OnTextInputClientChanged(View* view);
220 
221   // Moves the text input focus into/out from |view|.
222   void FocusTextInputClient(View* view);
223   void BlurTextInputClient(View* view);
224 
225   // Disable shortcut handling.
set_shortcut_handling_suspended(bool suspended)226   static void set_shortcut_handling_suspended(bool suspended) {
227     shortcut_handling_suspended_ = suspended;
228   }
229   // Returns whether shortcut handling is currently suspended.
shortcut_handling_suspended()230   bool shortcut_handling_suspended() { return shortcut_handling_suspended_; }
231 
232   // Register a keyboard accelerator for the specified target. If multiple
233   // targets are registered for an accelerator, a target registered later has
234   // higher priority.
235   // |accelerator| is the accelerator to register.
236   // |priority| denotes the priority of the handler.
237   // NOTE: In almost all cases, you should specify kNormalPriority for this
238   // parameter. Setting it to kHighPriority prevents Chrome from sending the
239   // shortcut to the webpage if the renderer has focus, which is not desirable
240   // except for very isolated cases.
241   // |target| is the AcceleratorTarget that handles the event once the
242   // accelerator is pressed.
243   // Note that we are currently limited to accelerators that are either:
244   // - a key combination including Ctrl or Alt
245   // - the escape key
246   // - the enter key
247   // - any F key (F1, F2, F3 ...)
248   // - any browser specific keys (as available on special keyboards)
249   void RegisterAccelerator(const ui::Accelerator& accelerator,
250                            ui::AcceleratorManager::HandlerPriority priority,
251                            ui::AcceleratorTarget* target);
252 
253   // Unregister the specified keyboard accelerator for the specified target.
254   void UnregisterAccelerator(const ui::Accelerator& accelerator,
255                              ui::AcceleratorTarget* target);
256 
257   // Unregister all keyboard accelerator for the specified target.
258   void UnregisterAccelerators(ui::AcceleratorTarget* target);
259 
260   // Activate the target associated with the specified accelerator.
261   // First, AcceleratorPressed handler of the most recently registered target
262   // is called, and if that handler processes the event (i.e. returns true),
263   // this method immediately returns. If not, we do the same thing on the next
264   // target, and so on.
265   // Returns true if an accelerator was activated.
266   bool ProcessAccelerator(const ui::Accelerator& accelerator);
267 
268   // Resets menu key state if |event| is not menu key release.
269   // This is effective only on x11.
270   void MaybeResetMenuKeyState(const ui::KeyEvent& key);
271 
272   // Called by a RootView when a view within its hierarchy is removed
273   // from its parent. This will only be called by a RootView in a
274   // hierarchy of Widgets that this FocusManager is attached to the
275   // parent Widget of.
276   void ViewRemoved(View* removed);
277 
278   // Adds/removes a listener.  The FocusChangeListener is notified every time
279   // the focused view is about to change.
280   void AddFocusChangeListener(FocusChangeListener* listener);
281   void RemoveFocusChangeListener(FocusChangeListener* listener);
282 
283   // Returns the AcceleratorTarget that should be activated for the specified
284   // keyboard accelerator, or NULL if no view is registered for that keyboard
285   // accelerator.
286   ui::AcceleratorTarget* GetCurrentTargetForAccelerator(
287       const ui::Accelerator& accelertor) const;
288 
289   // Whether the given |accelerator| has a priority handler associated with it.
290   bool HasPriorityHandler(const ui::Accelerator& accelerator) const;
291 
292   // Clears the native view having the focus.
293   virtual void ClearNativeFocus();
294 
295   // Focuses the next keyboard-accessible pane, taken from the list of
296   // views returned by WidgetDelegate::GetAccessiblePanes(). If there are
297   // no panes, the widget's root view is treated as a single pane.
298   // A keyboard-accessible pane should subclass from AccessiblePaneView in
299   // order to trap keyboard focus within that pane. If |wrap| is kWrap,
300   // it keeps cycling within this widget, otherwise it returns false after
301   // reaching the last pane so that focus can cycle to another widget.
302   bool RotatePaneFocus(Direction direction, FocusCycleWrappingBehavior wrap);
303 
304   // Convenience method that returns true if the passed |key_event| should
305   // trigger tab traversal (if it is a TAB key press with or without SHIFT
306   // pressed).
307   static bool IsTabTraversalKeyEvent(const ui::KeyEvent& key_event);
308 
309   // Sets whether arrow key traversal is enabled. When enabled, right/down key
310   // behaves like tab and left/up key behaves like shift-tab. Note when this
311   // is enabled, the arrow key movement within grouped views are disabled.
set_arrow_key_traversal_enabled(bool enabled)312   static void set_arrow_key_traversal_enabled(bool enabled) {
313     arrow_key_traversal_enabled_ = enabled;
314   }
315   // Returns whether arrow key traversal is enabled.
arrow_key_traversal_enabled()316   static bool arrow_key_traversal_enabled() {
317     return arrow_key_traversal_enabled_;
318   }
319 
320   // Returns the next focusable view. Traversal starts at |starting_view|. If
321   // |starting_view| is NULL |starting_widget| is consuled to determine which
322   // Widget to start from. See
323   // WidgetDelegate::ShouldAdvanceFocusToTopLevelWidget() for details. If both
324   // |starting_view| and |starting_widget| are NULL, traversal starts at
325   // |widget_|.
326   View* GetNextFocusableView(View* starting_view,
327                              Widget* starting_widget,
328                              bool reverse,
329                              bool dont_loop);
330 
331  private:
332   // Returns the focusable view found in the FocusTraversable specified starting
333   // at the specified view. This traverses down along the FocusTraversable
334   // hierarchy.
335   // Returns NULL if no focusable view were found.
336   View* FindFocusableView(FocusTraversable* focus_traversable,
337                           View* starting_view,
338                           bool reverse);
339 
340   // Process arrow key traversal. Returns true if the event has been consumed
341   // and should not be processed further.
342   bool ProcessArrowKeyTraversal(const ui::KeyEvent& event);
343 
344   // Keeps track of whether shortcut handling is currently suspended.
345   static bool shortcut_handling_suspended_;
346 
347   // Whether arrow key traversal is enabled.
348   static bool arrow_key_traversal_enabled_;
349 
350   // The top-level Widget this FocusManager is associated with.
351   Widget* widget_;
352 
353   // The object which handles an accelerator when |accelerator_manager_| doesn't
354   // handle it.
355   scoped_ptr<FocusManagerDelegate> delegate_;
356 
357   // The view that currently is focused.
358   View* focused_view_;
359 
360   // The AcceleratorManager this FocusManager is associated with.
361   scoped_ptr<ui::AcceleratorManager> accelerator_manager_;
362 
363   // The storage id used in the ViewStorage to store/restore the view that last
364   // had focus.
365   int stored_focused_view_storage_id_;
366 
367   // The reason why the focus most recently changed.
368   FocusChangeReason focus_change_reason_;
369 
370   // The list of registered FocusChange listeners.
371   ObserverList<FocusChangeListener, true> focus_change_listeners_;
372 
373   // See description above getter.
374   bool is_changing_focus_;
375 
376   DISALLOW_COPY_AND_ASSIGN(FocusManager);
377 };
378 
379 }  // namespace views
380 
381 #endif  // UI_VIEWS_FOCUS_FOCUS_MANAGER_H_
382