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