- add sources.
[platform/framework/web/crosswalk.git] / src / ui / views / corewm / focus_controller.cc
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 #include "ui/views/corewm/focus_controller.h"
6
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"
15
16 namespace views {
17 namespace corewm {
18 namespace {
19
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)
25     return;
26
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();
31   }
32 }
33
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
37   // the same parent.
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;
45   }
46   if (window != relative_to) {
47     window->layer()->parent()->StackAbove(window->layer(),
48                                           relative_to->layer());
49   }
50 }
51
52 }  // namespace
53
54 ////////////////////////////////////////////////////////////////////////////////
55 // FocusController, public:
56
57 FocusController::FocusController(FocusRules* rules)
58     : active_window_(NULL),
59       focused_window_(NULL),
60       updating_focus_(false),
61       updating_activation_(false),
62       rules_(rules),
63       observer_manager_(this) {
64   DCHECK(rules);
65 }
66
67 FocusController::~FocusController() {
68 }
69
70 ////////////////////////////////////////////////////////////////////////////////
71 // FocusController, aura::client::ActivationClient implementation:
72
73 void FocusController::AddObserver(
74     aura::client::ActivationChangeObserver* observer) {
75   activation_observers_.AddObserver(observer);
76 }
77
78 void FocusController::RemoveObserver(
79     aura::client::ActivationChangeObserver* observer) {
80   activation_observers_.RemoveObserver(observer);
81 }
82
83 void FocusController::ActivateWindow(aura::Window* window) {
84   FocusWindow(window);
85 }
86
87 void FocusController::DeactivateWindow(aura::Window* window) {
88   if (window)
89     FocusWindow(rules_->GetNextActivatableWindow(window));
90 }
91
92 aura::Window* FocusController::GetActiveWindow() {
93   return active_window_;
94 }
95
96 aura::Window* FocusController::GetActivatableWindow(aura::Window* window) {
97   return rules_->GetActivatableWindow(window);
98 }
99
100 aura::Window* FocusController::GetToplevelWindow(aura::Window* window) {
101   return rules_->GetToplevelWindow(window);
102 }
103
104 bool FocusController::OnWillFocusWindow(aura::Window* window,
105                                         const ui::Event* event) {
106   NOTREACHED();
107   return false;
108 }
109
110 bool FocusController::CanActivateWindow(aura::Window* window) const {
111   return rules_->CanActivateWindow(window);
112 }
113
114 ////////////////////////////////////////////////////////////////////////////////
115 // FocusController, aura::client::FocusClient implementation:
116
117 void FocusController::AddObserver(
118     aura::client::FocusChangeObserver* observer) {
119   focus_observers_.AddObserver(observer);
120 }
121
122 void FocusController::RemoveObserver(
123     aura::client::FocusChangeObserver* observer) {
124   focus_observers_.RemoveObserver(observer);
125 }
126
127 void FocusController::FocusWindow(aura::Window* window) {
128   if (window &&
129       (window->Contains(focused_window_) || window->Contains(active_window_))) {
130     return;
131   }
132
133   // We should not be messing with the focus if the window has capture, unless
134   // no has focus.
135   if (window && (aura::client::GetCaptureWindow(window) == window) &&
136       focused_window_) {
137     return;
138   }
139
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;
145
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))
150     return;
151   DCHECK((focusable && activatable) || !window);
152
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);
158
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);
166   }
167 }
168
169 void FocusController::ResetFocusWithinActiveWindow(aura::Window* window) {
170   DCHECK(window);
171   if (!active_window_)
172     return;
173   if (!active_window_->Contains(window))
174     return;
175   SetFocusedWindow(window);
176 }
177
178 aura::Window* FocusController::GetFocusedWindow() {
179   return focused_window_;
180 }
181
182 ////////////////////////////////////////////////////////////////////////////////
183 // FocusController, ui::EventHandler implementation:
184 void FocusController::OnKeyEvent(ui::KeyEvent* event) {
185 }
186
187 void FocusController::OnMouseEvent(ui::MouseEvent* event) {
188   if (event->type() == ui::ET_MOUSE_PRESSED)
189     WindowFocusedFromInputEvent(static_cast<aura::Window*>(event->target()));
190 }
191
192 void FocusController::OnScrollEvent(ui::ScrollEvent* event) {
193 }
194
195 void FocusController::OnTouchEvent(ui::TouchEvent* event) {
196 }
197
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()));
202   }
203 }
204
205 ////////////////////////////////////////////////////////////////////////////////
206 // FocusController, aura::WindowObserver implementation:
207
208 void FocusController::OnWindowVisibilityChanged(aura::Window* window,
209                                                 bool visible) {
210   if (!visible) {
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);
217   }
218 }
219
220 void FocusController::OnWindowDestroying(aura::Window* window) {
221   WindowLostFocusFromDispositionChange(window, window->parent());
222 }
223
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);
231   }
232 }
233
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);
241   }
242 }
243
244 ////////////////////////////////////////////////////////////////////////////////
245 // FocusController, private:
246
247 void FocusController::SetFocusedWindow(aura::Window* window) {
248   if (updating_focus_ || window == focused_window_)
249     return;
250   DCHECK(rules_->CanFocusWindow(window));
251   if (window)
252     DCHECK_EQ(window, rules_->GetFocusableWindow(window));
253
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_);
259   }
260   focused_window_ = window;
261   if (focused_window_ && !observer_manager_.IsObserving(focused_window_))
262     observer_manager_.Add(focused_window_);
263
264   FOR_EACH_OBSERVER(aura::client::FocusChangeObserver,
265                     focus_observers_,
266                     OnWindowFocused(focused_window_, lost_focus));
267   aura::client::FocusChangeObserver* observer =
268       aura::client::GetFocusChangeObserver(lost_focus);
269   if (observer)
270     observer->OnWindowFocused(focused_window_, lost_focus);
271   observer = aura::client::GetFocusChangeObserver(focused_window_);
272   if (observer)
273     observer->OnWindowFocused(focused_window_, lost_focus);
274 }
275
276 void FocusController::SetActiveWindow(aura::Window* requested_window,
277                                       aura::Window* window) {
278   if (updating_activation_)
279     return;
280
281   if (window == active_window_) {
282     if (requested_window) {
283       FOR_EACH_OBSERVER(aura::client::ActivationChangeObserver,
284                         activation_observers_,
285                         OnAttemptToReactivateWindow(requested_window,
286                                                     active_window_));
287     }
288     return;
289   }
290
291   DCHECK(rules_->CanActivateWindow(window));
292   if (window)
293     DCHECK_EQ(window, rules_->GetActivatableWindow(window));
294
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_);
300   }
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_);
307   }
308
309   aura::client::ActivationChangeObserver* observer =
310       aura::client::GetActivationChangeObserver(lost_activation);
311   if (observer)
312     observer->OnWindowActivated(active_window_, lost_activation);
313   observer = aura::client::GetActivationChangeObserver(active_window_);
314   if (observer)
315     observer->OnWindowActivated(active_window_, lost_activation);
316   FOR_EACH_OBSERVER(aura::client::ActivationChangeObserver,
317                     activation_observers_,
318                     OnWindowActivated(active_window_, lost_activation));
319 }
320
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
325   // destruction.
326   window->ClearProperty(aura::client::kModalKey);
327   // TODO(beng): See if this function can be replaced by a call to
328   //             FocusWindow().
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));
340   }
341 }
342
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)))
348     FocusWindow(window);
349 }
350
351 }  // namespace corewm
352 }  // namespace views