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.
5 #ifndef UI_VIEWS_FOCUS_FOCUS_MANAGER_H_
6 #define UI_VIEWS_FOCUS_FOCUS_MANAGER_H_
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"
19 // The FocusManager class is used to handle focus traversal, store/restore
20 // focused views and handle keyboard accelerators.
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.
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.
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.
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
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().
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.
68 // hwnd_view_container_->GetWidget()->SetFocusTraversableParent(
71 // Note that FocusTraversable do not have to be RootViews: AccessibleToolbarView
72 // is FocusTraversable.
75 class AcceleratorManager
;
76 class AcceleratorTarget
;
83 class FocusManagerDelegate
;
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
{
92 // Return a FocusSearch object that implements the algorithm to find
93 // the next or previous focusable view.
94 virtual FocusSearch
* GetFocusSearch() = 0;
96 // Should return the parent FocusTraversable.
97 // The top RootView which is the top FocusTraversable returns NULL.
98 virtual FocusTraversable
* GetFocusTraversableParent() = 0;
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;
106 virtual ~FocusTraversable() {}
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
{
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;
116 // Called after focus state has changed.
117 virtual void OnDidChangeFocus(View
* focused_before
, View
* focused_now
) = 0;
120 virtual ~FocusChangeListener() {}
123 class VIEWS_EXPORT FocusManager
{
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
,
131 // The focus changed due to restoring the focus.
134 // The focus changed due to a click or a shortcut to jump directly to
135 // a particular view.
136 kReasonDirectFocusChange
139 // TODO: use Direction in place of bool reverse throughout.
145 enum FocusCycleWrappingBehavior
{
150 FocusManager(Widget
* widget
, FocusManagerDelegate
* delegate
);
151 virtual ~FocusManager();
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
156 bool OnKeyEvent(const ui::KeyEvent
& event
);
158 // Returns true is the specified is part of the hierarchy of the window
159 // associated with this FocusManager.
160 bool ContainsView(View
* view
);
162 // Advances the focus (backward if reverse is true).
163 void AdvanceFocus(bool reverse
);
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_
; }
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
);
177 // Get the reason why the focus most recently changed.
178 FocusChangeReason
focus_change_reason() const {
179 return focus_change_reason_
;
182 // Clears the focused view. The window associated with the top root view gets
183 // the native focus (so we still get keyboard events).
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();
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();
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
);
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();
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
207 void SetStoredFocusView(View
* view
);
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();
213 // Clears the stored focused view.
214 void ClearStoredFocusedView();
216 // Returns true if in the process of changing the focused view.
217 bool is_changing_focus() const { return is_changing_focus_
; }
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
);
224 // Moves the text input focus into/out from |view|.
225 void FocusTextInputClient(View
* view
);
226 void BlurTextInputClient(View
* view
);
228 // Disable shortcut handling.
229 void set_shortcut_handling_suspended(bool suspended
) {
230 shortcut_handling_suspended_
= suspended
;
232 // Returns whether shortcut handling is currently suspended.
233 bool shortcut_handling_suspended() { return shortcut_handling_suspended_
; }
235 // Register a keyboard accelerator for the specified target. If multiple
236 // targets are registered for an accelerator, a target registered later has
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
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
);
256 // Unregister the specified keyboard accelerator for the specified target.
257 void UnregisterAccelerator(const ui::Accelerator
& accelerator
,
258 ui::AcceleratorTarget
* target
);
260 // Unregister all keyboard accelerator for the specified target.
261 void UnregisterAccelerators(ui::AcceleratorTarget
* target
);
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
);
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
);
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
279 void ViewRemoved(View
* removed
);
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
);
286 // Returns the AcceleratorTarget that should be activated for the specified
287 // keyboard accelerator, or NULL if no view is registered for that keyboard
289 ui::AcceleratorTarget
* GetCurrentTargetForAccelerator(
290 const ui::Accelerator
& accelerator
) const;
292 // Whether the given |accelerator| has a priority handler associated with it.
293 bool HasPriorityHandler(const ui::Accelerator
& accelerator
) const;
295 // Clears the native view having the focus.
296 virtual void ClearNativeFocus();
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
);
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
310 static bool IsTabTraversalKeyEvent(const ui::KeyEvent
& key_event
);
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
;
318 // Returns whether arrow key traversal is enabled.
319 static bool arrow_key_traversal_enabled() {
320 return arrow_key_traversal_enabled_
;
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
329 View
* GetNextFocusableView(View
* starting_view
,
330 Widget
* starting_widget
,
335 // Returns the focusable view found in the FocusTraversable specified starting
336 // at the specified view. This traverses down along the FocusTraversable
338 // Returns NULL if no focusable view were found.
339 View
* FindFocusableView(FocusTraversable
* focus_traversable
,
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
);
347 // Whether arrow key traversal is enabled.
348 static bool arrow_key_traversal_enabled_
;
350 // The top-level Widget this FocusManager is associated with.
353 // The object which handles an accelerator when |accelerator_manager_| doesn't
355 scoped_ptr
<FocusManagerDelegate
> delegate_
;
357 // The view that currently is focused.
360 // The AcceleratorManager this FocusManager is associated with.
361 scoped_ptr
<ui::AcceleratorManager
> accelerator_manager_
;
363 // Keeps track of whether shortcut handling is currently suspended.
364 bool shortcut_handling_suspended_
;
366 // The storage id used in the ViewStorage to store/restore the view that last
368 int stored_focused_view_storage_id_
;
370 // The reason why the focus most recently changed.
371 FocusChangeReason focus_change_reason_
;
373 // The list of registered FocusChange listeners.
374 ObserverList
<FocusChangeListener
, true> focus_change_listeners_
;
376 // See description above getter.
377 bool is_changing_focus_
;
379 DISALLOW_COPY_AND_ASSIGN(FocusManager
);
384 #endif // UI_VIEWS_FOCUS_FOCUS_MANAGER_H_