OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef VIEWS_FOCUS_FOCUS_MANAGER_H_ | 5 #ifndef VIEWS_FOCUS_FOCUS_MANAGER_H_ |
6 #define VIEWS_FOCUS_FOCUS_MANAGER_H_ | 6 #define VIEWS_FOCUS_FOCUS_MANAGER_H_ |
7 #pragma once | 7 #pragma once |
8 | 8 |
9 #include <list> | 9 #include "ui/views/focus/focus_manager.h" |
10 #include <map> | 10 // TODO(tfarina): remove this file once all includes have been updated. |
11 | |
12 #include "base/basictypes.h" | |
13 #include "base/memory/scoped_ptr.h" | |
14 #include "base/observer_list.h" | |
15 #include "ui/base/models/accelerator.h" | |
16 #include "ui/gfx/native_widget_types.h" | |
17 #include "views/views_export.h" | |
18 #include "views/events/event.h" | |
19 | |
20 // The FocusManager class is used to handle focus traversal, store/restore | |
21 // focused views and handle keyboard accelerators. | |
22 // | |
23 // There are 2 types of focus: | |
24 // - the native focus, which is the focus that an gfx::NativeView has. | |
25 // - the view focus, which is the focus that a views::View has. | |
26 // | |
27 // Each native view must register with their Focus Manager so the focus manager | |
28 // gets notified when they are focused (and keeps track of the native focus) and | |
29 // as well so that the tab key events can be intercepted. | |
30 // They can provide when they register a View that is kept in synch in term of | |
31 // focus. This is used in NativeControl for example, where a View wraps an | |
32 // actual native window. | |
33 // This is already done for you if you subclass the NativeControl class or if | |
34 // you use the NativeViewHost class. | |
35 // | |
36 // When creating a top window (derived from views::Widget) that is not a child | |
37 // window, it creates and owns a FocusManager to manage the focus for itself and | |
38 // all its child windows. | |
39 // | |
40 // The FocusTraversable interface exposes the methods a class should implement | |
41 // in order to be able to be focus traversed when tab key is pressed. | |
42 // RootViews implement FocusTraversable. | |
43 // The FocusManager contains a top FocusTraversable instance, which is the top | |
44 // RootView. | |
45 // | |
46 // If you just use views, then the focus traversal is handled for you by the | |
47 // RootView. The default traversal order is the order in which the views have | |
48 // been added to their container. You can modify this order by using the View | |
49 // method SetNextFocusableView(). | |
50 // | |
51 // If you are embedding a native view containing a nested RootView (for example | |
52 // by adding a NativeControl that contains a NativeWidgetWin as its native | |
53 // component), then you need to: | |
54 // - override the View::GetFocusTraversable() method in your outer component. | |
55 // It should return the RootView of the inner component. This is used when | |
56 // the focus traversal traverse down the focus hierarchy to enter the nested | |
57 // RootView. In the example mentioned above, the NativeControl overrides | |
58 // GetFocusTraversable() and returns hwnd_view_container_->GetRootView(). | |
59 // - call Widget::SetFocusTraversableParent() on the nested RootView and point | |
60 // it to the outer RootView. This is used when the focus goes out of the | |
61 // nested RootView. In the example: | |
62 // hwnd_view_container_->GetWidget()->SetFocusTraversableParent( | |
63 // native_control->GetRootView()); | |
64 // - call RootView::SetFocusTraversableParentView() on the nested RootView with | |
65 // the parent view that directly contains the native window. This is needed | |
66 // when traversing up from the nested RootView to know which view to start | |
67 // with when going to the next/previous view. | |
68 // In our example: | |
69 // hwnd_view_container_->GetWidget()->SetFocusTraversableParent( | |
70 // native_control); | |
71 // | |
72 // Note that FocusTraversable do not have to be RootViews: AccessibleToolbarView | |
73 // is FocusTraversable. | |
74 | |
75 namespace ui { | |
76 class AcceleratorTarget; | |
77 class AcceleratorManager; | |
78 } | |
79 | |
80 namespace views { | |
81 | |
82 class FocusSearch; | |
83 class RootView; | |
84 class View; | |
85 class Widget; | |
86 | |
87 // The FocusTraversable interface is used by components that want to process | |
88 // focus traversal events (due to Tab/Shift-Tab key events). | |
89 class VIEWS_EXPORT FocusTraversable { | |
90 public: | |
91 // Return a FocusSearch object that implements the algorithm to find | |
92 // the next or previous focusable view. | |
93 virtual FocusSearch* GetFocusSearch() = 0; | |
94 | |
95 // Should return the parent FocusTraversable. | |
96 // The top RootView which is the top FocusTraversable returns NULL. | |
97 virtual FocusTraversable* GetFocusTraversableParent() = 0; | |
98 | |
99 // This should return the View this FocusTraversable belongs to. | |
100 // It is used when walking up the view hierarchy tree to find which view | |
101 // should be used as the starting view for finding the next/previous view. | |
102 virtual View* GetFocusTraversableParentView() = 0; | |
103 | |
104 protected: | |
105 virtual ~FocusTraversable() {} | |
106 }; | |
107 | |
108 // This interface should be implemented by classes that want to be notified when | |
109 // the focus is about to change. See the Add/RemoveFocusChangeListener methods. | |
110 class VIEWS_EXPORT FocusChangeListener { | |
111 public: | |
112 // No change to focus state has occurred yet when this function is called. | |
113 virtual void OnWillChangeFocus(View* focused_before, View* focused_now) = 0; | |
114 | |
115 // Called after focus state has changed. | |
116 virtual void OnDidChangeFocus(View* focused_before, View* focused_now) = 0; | |
117 | |
118 protected: | |
119 virtual ~FocusChangeListener() {} | |
120 }; | |
121 | |
122 class VIEWS_EXPORT FocusManager { | |
123 public: | |
124 // The reason why the focus changed. | |
125 enum FocusChangeReason { | |
126 // The focus changed because the user traversed focusable views using | |
127 // keys like Tab or Shift+Tab. | |
128 kReasonFocusTraversal, | |
129 | |
130 // The focus changed due to restoring the focus. | |
131 kReasonFocusRestore, | |
132 | |
133 // The focus changed due to a click or a shortcut to jump directly to | |
134 // a particular view. | |
135 kReasonDirectFocusChange | |
136 }; | |
137 | |
138 explicit FocusManager(Widget* widget); | |
139 virtual ~FocusManager(); | |
140 | |
141 // Processes the passed key event for accelerators and tab traversal. | |
142 // Returns false if the event has been consumed and should not be processed | |
143 // further. | |
144 bool OnKeyEvent(const KeyEvent& event); | |
145 | |
146 // Returns true is the specified is part of the hierarchy of the window | |
147 // associated with this FocusManager. | |
148 bool ContainsView(View* view); | |
149 | |
150 // Advances the focus (backward if reverse is true). | |
151 void AdvanceFocus(bool reverse); | |
152 | |
153 // The FocusManager keeps track of the focused view within a RootView. | |
154 View* GetFocusedView() { return focused_view_; } | |
155 const View* GetFocusedView() const { return focused_view_; } | |
156 | |
157 // Low-level methods to force the focus to change (and optionally provide | |
158 // a reason). If the focus change should only happen if the view is | |
159 // currenty focusable, enabled, and visible, call view->RequestFocus(). | |
160 void SetFocusedViewWithReason(View* view, FocusChangeReason reason); | |
161 void SetFocusedView(View* view) { | |
162 SetFocusedViewWithReason(view, kReasonDirectFocusChange); | |
163 } | |
164 | |
165 // Get the reason why the focus most recently changed. | |
166 FocusChangeReason focus_change_reason() const { | |
167 return focus_change_reason_; | |
168 } | |
169 | |
170 // Clears the focused view. The window associated with the top root view gets | |
171 // the native focus (so we still get keyboard events). | |
172 void ClearFocus(); | |
173 | |
174 // Validates the focused view, clearing it if the window it belongs too is not | |
175 // attached to the window hierarchy anymore. | |
176 void ValidateFocusedView(); | |
177 | |
178 // Stores and restores the focused view. Used when the window becomes | |
179 // active/inactive. | |
180 void StoreFocusedView(); | |
181 void RestoreFocusedView(); | |
182 | |
183 // Clears the stored focused view. | |
184 void ClearStoredFocusedView(); | |
185 | |
186 // Returns true if in the process of changing the focused view. | |
187 bool is_changing_focus() const { return is_changing_focus_; } | |
188 | |
189 // Register a keyboard accelerator for the specified target. If multiple | |
190 // targets are registered for an accelerator, a target registered later has | |
191 // higher priority. | |
192 // Note that we are currently limited to accelerators that are either: | |
193 // - a key combination including Ctrl or Alt | |
194 // - the escape key | |
195 // - the enter key | |
196 // - any F key (F1, F2, F3 ...) | |
197 // - any browser specific keys (as available on special keyboards) | |
198 void RegisterAccelerator(const ui::Accelerator& accelerator, | |
199 ui::AcceleratorTarget* target); | |
200 | |
201 // Unregister the specified keyboard accelerator for the specified target. | |
202 void UnregisterAccelerator(const ui::Accelerator& accelerator, | |
203 ui::AcceleratorTarget* target); | |
204 | |
205 // Unregister all keyboard accelerator for the specified target. | |
206 void UnregisterAccelerators(ui::AcceleratorTarget* target); | |
207 | |
208 // Activate the target associated with the specified accelerator. | |
209 // First, AcceleratorPressed handler of the most recently registered target | |
210 // is called, and if that handler processes the event (i.e. returns true), | |
211 // this method immediately returns. If not, we do the same thing on the next | |
212 // target, and so on. | |
213 // Returns true if an accelerator was activated. | |
214 bool ProcessAccelerator(const ui::Accelerator& accelerator); | |
215 | |
216 // Called by a RootView when a view within its hierarchy is removed | |
217 // from its parent. This will only be called by a RootView in a | |
218 // hierarchy of Widgets that this FocusManager is attached to the | |
219 // parent Widget of. | |
220 void ViewRemoved(View* removed); | |
221 | |
222 // Adds/removes a listener. The FocusChangeListener is notified every time | |
223 // the focused view is about to change. | |
224 void AddFocusChangeListener(FocusChangeListener* listener); | |
225 void RemoveFocusChangeListener(FocusChangeListener* listener); | |
226 | |
227 // Returns the AcceleratorTarget that should be activated for the specified | |
228 // keyboard accelerator, or NULL if no view is registered for that keyboard | |
229 // accelerator. | |
230 ui::AcceleratorTarget* GetCurrentTargetForAccelerator( | |
231 const ui::Accelerator& accelertor) const; | |
232 | |
233 // Sets the focus to the specified native view. | |
234 virtual void FocusNativeView(gfx::NativeView native_view); | |
235 | |
236 // Clears the native view having the focus. | |
237 virtual void ClearNativeFocus(); | |
238 | |
239 // Convenience method that returns true if the passed |key_event| should | |
240 // trigger tab traversal (if it is a TAB key press with or without SHIFT | |
241 // pressed). | |
242 static bool IsTabTraversalKeyEvent(const KeyEvent& key_event); | |
243 | |
244 private: | |
245 // Returns the next focusable view. | |
246 View* GetNextFocusableView(View* starting_view, bool reverse, bool dont_loop); | |
247 | |
248 // Returns the focusable view found in the FocusTraversable specified starting | |
249 // at the specified view. This traverses down along the FocusTraversable | |
250 // hierarchy. | |
251 // Returns NULL if no focusable view were found. | |
252 View* FindFocusableView(FocusTraversable* focus_traversable, | |
253 View* starting_view, | |
254 bool reverse); | |
255 | |
256 // The top-level Widget this FocusManager is associated with. | |
257 Widget* widget_; | |
258 | |
259 // The view that currently is focused. | |
260 View* focused_view_; | |
261 | |
262 // The AcceleratorManager this FocusManager is associated with. | |
263 scoped_ptr<ui::AcceleratorManager> accelerator_manager_; | |
264 | |
265 // The storage id used in the ViewStorage to store/restore the view that last | |
266 // had focus. | |
267 int stored_focused_view_storage_id_; | |
268 | |
269 // The reason why the focus most recently changed. | |
270 FocusChangeReason focus_change_reason_; | |
271 | |
272 // The list of registered FocusChange listeners. | |
273 ObserverList<FocusChangeListener, true> focus_change_listeners_; | |
274 | |
275 // See description above getter. | |
276 bool is_changing_focus_; | |
277 | |
278 DISALLOW_COPY_AND_ASSIGN(FocusManager); | |
279 }; | |
280 | |
281 } // namespace views | |
282 | 11 |
283 #endif // VIEWS_FOCUS_FOCUS_MANAGER_H_ | 12 #endif // VIEWS_FOCUS_FOCUS_MANAGER_H_ |
OLD | NEW |