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 #include "ui/views/corewm/focus_controller.h"
7 #include "base/auto_reset.h"
8 #include "ui/aura/client/activation_change_observer.h"
9 #include "ui/aura/client/aura_constants.h"
10 #include "ui/aura/client/capture_client.h"
11 #include "ui/aura/client/focus_change_observer.h"
12 #include "ui/aura/env.h"
13 #include "ui/events/event.h"
14 #include "ui/views/corewm/focus_rules.h"
20 // When a modal window is activated, we bring its entire transient parent chain
21 // to the front. This function must be called before the modal transient is
22 // stacked at the top to ensure correct stacking order.
23 void StackTransientParentsBelowModalWindow(aura::Window* window) {
24 if (window->GetProperty(aura::client::kModalKey) != ui::MODAL_TYPE_WINDOW)
27 aura::Window* transient_parent = window->transient_parent();
28 while (transient_parent) {
29 transient_parent->parent()->StackChildAtTop(transient_parent);
30 transient_parent = transient_parent->transient_parent();
34 // Stack's |window|'s layer above |relative_to|'s layer.
35 void StackWindowLayerAbove(aura::Window* window, aura::Window* relative_to) {
36 // Stack |window| above the last transient child of |relative_to| that shares
38 const aura::Window::Windows& window_transients(
39 relative_to->transient_children());
40 for (aura::Window::Windows::const_iterator i = window_transients.begin();
41 i != window_transients.end(); ++i) {
42 aura::Window* transient = *i;
43 if (transient->parent() == relative_to->parent())
44 relative_to = transient;
46 if (window != relative_to) {
47 window->layer()->parent()->StackAbove(window->layer(),
48 relative_to->layer());
54 ////////////////////////////////////////////////////////////////////////////////
55 // FocusController, public:
57 FocusController::FocusController(FocusRules* rules)
58 : active_window_(NULL),
59 focused_window_(NULL),
60 updating_focus_(false),
61 updating_activation_(false),
63 observer_manager_(this) {
67 FocusController::~FocusController() {
70 ////////////////////////////////////////////////////////////////////////////////
71 // FocusController, aura::client::ActivationClient implementation:
73 void FocusController::AddObserver(
74 aura::client::ActivationChangeObserver* observer) {
75 activation_observers_.AddObserver(observer);
78 void FocusController::RemoveObserver(
79 aura::client::ActivationChangeObserver* observer) {
80 activation_observers_.RemoveObserver(observer);
83 void FocusController::ActivateWindow(aura::Window* window) {
87 void FocusController::DeactivateWindow(aura::Window* window) {
89 FocusWindow(rules_->GetNextActivatableWindow(window));
92 aura::Window* FocusController::GetActiveWindow() {
93 return active_window_;
96 aura::Window* FocusController::GetActivatableWindow(aura::Window* window) {
97 return rules_->GetActivatableWindow(window);
100 aura::Window* FocusController::GetToplevelWindow(aura::Window* window) {
101 return rules_->GetToplevelWindow(window);
104 bool FocusController::OnWillFocusWindow(aura::Window* window,
105 const ui::Event* event) {
110 bool FocusController::CanActivateWindow(aura::Window* window) const {
111 return rules_->CanActivateWindow(window);
114 ////////////////////////////////////////////////////////////////////////////////
115 // FocusController, aura::client::FocusClient implementation:
117 void FocusController::AddObserver(
118 aura::client::FocusChangeObserver* observer) {
119 focus_observers_.AddObserver(observer);
122 void FocusController::RemoveObserver(
123 aura::client::FocusChangeObserver* observer) {
124 focus_observers_.RemoveObserver(observer);
127 void FocusController::FocusWindow(aura::Window* window) {
129 (window->Contains(focused_window_) || window->Contains(active_window_))) {
133 // We should not be messing with the focus if the window has capture, unless
135 if (window && (aura::client::GetCaptureWindow(window) == window) &&
140 // Focusing a window also activates its containing activatable window. Note
141 // that the rules could redirect activation activation and/or focus.
142 aura::Window* focusable = rules_->GetFocusableWindow(window);
143 aura::Window* activatable =
144 focusable ? rules_->GetActivatableWindow(focusable) : NULL;
146 // We need valid focusable/activatable windows in the event we're not clearing
147 // focus. "Clearing focus" is inferred by whether or not |window| passed to
148 // this function is non-NULL.
149 if (window && (!focusable || !activatable))
151 DCHECK((focusable && activatable) || !window);
153 // Activation change observers may change the focused window. If this happens
154 // we must not adjust the focus below since this will clobber that change.
155 aura::Window* last_focused_window = focused_window_;
156 if (!updating_activation_)
157 SetActiveWindow(window, activatable);
159 // If the window's ActivationChangeObserver shifted focus to a valid window,
160 // we don't want to focus the window we thought would be focused by default.
161 bool activation_changed_focus = last_focused_window != focused_window_;
162 if (!updating_focus_ && (!activation_changed_focus || !focused_window_)) {
163 if (active_window_ && focusable)
164 DCHECK(active_window_->Contains(focusable));
165 SetFocusedWindow(focusable);
169 void FocusController::ResetFocusWithinActiveWindow(aura::Window* window) {
173 if (!active_window_->Contains(window))
175 SetFocusedWindow(window);
178 aura::Window* FocusController::GetFocusedWindow() {
179 return focused_window_;
182 ////////////////////////////////////////////////////////////////////////////////
183 // FocusController, ui::EventHandler implementation:
184 void FocusController::OnKeyEvent(ui::KeyEvent* event) {
187 void FocusController::OnMouseEvent(ui::MouseEvent* event) {
188 if (event->type() == ui::ET_MOUSE_PRESSED)
189 WindowFocusedFromInputEvent(static_cast<aura::Window*>(event->target()));
192 void FocusController::OnScrollEvent(ui::ScrollEvent* event) {
195 void FocusController::OnTouchEvent(ui::TouchEvent* event) {
198 void FocusController::OnGestureEvent(ui::GestureEvent* event) {
199 if (event->type() == ui::ET_GESTURE_BEGIN &&
200 event->details().touch_points() == 1) {
201 WindowFocusedFromInputEvent(static_cast<aura::Window*>(event->target()));
205 ////////////////////////////////////////////////////////////////////////////////
206 // FocusController, aura::WindowObserver implementation:
208 void FocusController::OnWindowVisibilityChanged(aura::Window* window,
211 WindowLostFocusFromDispositionChange(window, window->parent());
212 // Despite the focus change, we need to keep the window being hidden
213 // stacked above the new window so it stays open on top as it animates away.
214 aura::Window* next_window = GetActiveWindow();
215 if (next_window && next_window->parent() == window->parent())
216 StackWindowLayerAbove(window, next_window);
220 void FocusController::OnWindowDestroying(aura::Window* window) {
221 WindowLostFocusFromDispositionChange(window, window->parent());
224 void FocusController::OnWindowHierarchyChanging(
225 const HierarchyChangeParams& params) {
226 if (params.receiver == active_window_ &&
227 params.target->Contains(params.receiver) && (!params.new_parent ||
228 aura::client::GetFocusClient(params.new_parent) !=
229 aura::client::GetFocusClient(params.receiver))) {
230 WindowLostFocusFromDispositionChange(params.receiver, params.old_parent);
234 void FocusController::OnWindowHierarchyChanged(
235 const HierarchyChangeParams& params) {
236 if (params.receiver == focused_window_ &&
237 params.target->Contains(params.receiver) && (!params.new_parent ||
238 aura::client::GetFocusClient(params.new_parent) !=
239 aura::client::GetFocusClient(params.receiver))) {
240 WindowLostFocusFromDispositionChange(params.receiver, params.old_parent);
244 ////////////////////////////////////////////////////////////////////////////////
245 // FocusController, private:
247 void FocusController::SetFocusedWindow(aura::Window* window) {
248 if (updating_focus_ || window == focused_window_)
250 DCHECK(rules_->CanFocusWindow(window));
252 DCHECK_EQ(window, rules_->GetFocusableWindow(window));
254 base::AutoReset<bool> updating_focus(&updating_focus_, true);
255 aura::Window* lost_focus = focused_window_;
256 if (focused_window_ && observer_manager_.IsObserving(focused_window_) &&
257 focused_window_ != active_window_) {
258 observer_manager_.Remove(focused_window_);
260 focused_window_ = window;
261 if (focused_window_ && !observer_manager_.IsObserving(focused_window_))
262 observer_manager_.Add(focused_window_);
264 FOR_EACH_OBSERVER(aura::client::FocusChangeObserver,
266 OnWindowFocused(focused_window_, lost_focus));
267 aura::client::FocusChangeObserver* observer =
268 aura::client::GetFocusChangeObserver(lost_focus);
270 observer->OnWindowFocused(focused_window_, lost_focus);
271 observer = aura::client::GetFocusChangeObserver(focused_window_);
273 observer->OnWindowFocused(focused_window_, lost_focus);
276 void FocusController::SetActiveWindow(aura::Window* requested_window,
277 aura::Window* window) {
278 if (updating_activation_)
281 if (window == active_window_) {
282 if (requested_window) {
283 FOR_EACH_OBSERVER(aura::client::ActivationChangeObserver,
284 activation_observers_,
285 OnAttemptToReactivateWindow(requested_window,
291 DCHECK(rules_->CanActivateWindow(window));
293 DCHECK_EQ(window, rules_->GetActivatableWindow(window));
295 base::AutoReset<bool> updating_activation(&updating_activation_, true);
296 aura::Window* lost_activation = active_window_;
297 if (active_window_ && observer_manager_.IsObserving(active_window_) &&
298 focused_window_ != active_window_) {
299 observer_manager_.Remove(active_window_);
301 active_window_ = window;
302 if (active_window_ && !observer_manager_.IsObserving(active_window_))
303 observer_manager_.Add(active_window_);
304 if (active_window_) {
305 StackTransientParentsBelowModalWindow(active_window_);
306 active_window_->parent()->StackChildAtTop(active_window_);
309 aura::client::ActivationChangeObserver* observer =
310 aura::client::GetActivationChangeObserver(lost_activation);
312 observer->OnWindowActivated(active_window_, lost_activation);
313 observer = aura::client::GetActivationChangeObserver(active_window_);
315 observer->OnWindowActivated(active_window_, lost_activation);
316 FOR_EACH_OBSERVER(aura::client::ActivationChangeObserver,
317 activation_observers_,
318 OnWindowActivated(active_window_, lost_activation));
321 void FocusController::WindowLostFocusFromDispositionChange(
322 aura::Window* window,
323 aura::Window* next) {
324 // A window's modality state will interfere with focus restoration during its
326 window->ClearProperty(aura::client::kModalKey);
327 // TODO(beng): See if this function can be replaced by a call to
329 // Activation adjustments are handled first in the event of a disposition
330 // changed. If an activation change is necessary, focus is reset as part of
331 // that process so there's no point in updating focus independently.
332 if (window == active_window_) {
333 aura::Window* next_activatable = rules_->GetNextActivatableWindow(window);
334 SetActiveWindow(NULL, next_activatable);
335 if (!(active_window_ && active_window_->Contains(focused_window_)))
336 SetFocusedWindow(next_activatable);
337 } else if (window->Contains(focused_window_)) {
338 // Active window isn't changing, but focused window might be.
339 SetFocusedWindow(rules_->GetFocusableWindow(next));
343 void FocusController::WindowFocusedFromInputEvent(aura::Window* window) {
344 // Only focus |window| if it or any of its parents can be focused. Otherwise
345 // FocusWindow() will focus the topmost window, which may not be the
346 // currently focused one.
347 if (rules_->CanFocusWindow(GetToplevelWindow(window)))
351 } // namespace corewm