Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10)

Side by Side Diff: ui/views/corewm/focus_controller.cc

Issue 194843004: Move files from ui/views/corewm to ui/wm/core (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ui/views/corewm/focus_controller.h ('k') | ui/views/corewm/focus_controller_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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/aura/window_tracker.h"
14 #include "ui/events/event.h"
15 #include "ui/views/corewm/focus_rules.h"
16 #include "ui/views/corewm/window_util.h"
17
18 namespace views {
19 namespace corewm {
20 namespace {
21
22 // When a modal window is activated, we bring its entire transient parent chain
23 // to the front. This function must be called before the modal transient is
24 // stacked at the top to ensure correct stacking order.
25 void StackTransientParentsBelowModalWindow(aura::Window* window) {
26 if (window->GetProperty(aura::client::kModalKey) != ui::MODAL_TYPE_WINDOW)
27 return;
28
29 aura::Window* transient_parent = views::corewm::GetTransientParent(window);
30 while (transient_parent) {
31 transient_parent->parent()->StackChildAtTop(transient_parent);
32 transient_parent = views::corewm::GetTransientParent(transient_parent);
33 }
34 }
35
36 // Stack's |window|'s layer above |relative_to|'s layer.
37 void StackWindowLayerAbove(aura::Window* window, aura::Window* relative_to) {
38 // Stack |window| above the last transient child of |relative_to| that shares
39 // the same parent.
40 const aura::Window::Windows& window_transients(
41 GetTransientChildren(relative_to));
42 for (aura::Window::Windows::const_iterator i = window_transients.begin();
43 i != window_transients.end(); ++i) {
44 aura::Window* transient = *i;
45 if (transient->parent() == relative_to->parent())
46 relative_to = transient;
47 }
48 if (window != relative_to) {
49 window->layer()->parent()->StackAbove(window->layer(),
50 relative_to->layer());
51 }
52 }
53
54 } // namespace
55
56 ////////////////////////////////////////////////////////////////////////////////
57 // FocusController, public:
58
59 FocusController::FocusController(FocusRules* rules)
60 : active_window_(NULL),
61 focused_window_(NULL),
62 updating_focus_(false),
63 updating_activation_(false),
64 rules_(rules),
65 observer_manager_(this) {
66 DCHECK(rules);
67 }
68
69 FocusController::~FocusController() {
70 }
71
72 ////////////////////////////////////////////////////////////////////////////////
73 // FocusController, aura::client::ActivationClient implementation:
74
75 void FocusController::AddObserver(
76 aura::client::ActivationChangeObserver* observer) {
77 activation_observers_.AddObserver(observer);
78 }
79
80 void FocusController::RemoveObserver(
81 aura::client::ActivationChangeObserver* observer) {
82 activation_observers_.RemoveObserver(observer);
83 }
84
85 void FocusController::ActivateWindow(aura::Window* window) {
86 FocusWindow(window);
87 }
88
89 void FocusController::DeactivateWindow(aura::Window* window) {
90 if (window)
91 FocusWindow(rules_->GetNextActivatableWindow(window));
92 }
93
94 aura::Window* FocusController::GetActiveWindow() {
95 return active_window_;
96 }
97
98 aura::Window* FocusController::GetActivatableWindow(aura::Window* window) {
99 return rules_->GetActivatableWindow(window);
100 }
101
102 aura::Window* FocusController::GetToplevelWindow(aura::Window* window) {
103 return rules_->GetToplevelWindow(window);
104 }
105
106 bool FocusController::OnWillFocusWindow(aura::Window* window,
107 const ui::Event* event) {
108 NOTREACHED();
109 return false;
110 }
111
112 bool FocusController::CanActivateWindow(aura::Window* window) const {
113 return rules_->CanActivateWindow(window);
114 }
115
116 ////////////////////////////////////////////////////////////////////////////////
117 // FocusController, aura::client::FocusClient implementation:
118
119 void FocusController::AddObserver(
120 aura::client::FocusChangeObserver* observer) {
121 focus_observers_.AddObserver(observer);
122 }
123
124 void FocusController::RemoveObserver(
125 aura::client::FocusChangeObserver* observer) {
126 focus_observers_.RemoveObserver(observer);
127 }
128
129 void FocusController::FocusWindow(aura::Window* window) {
130 if (window &&
131 (window->Contains(focused_window_) || window->Contains(active_window_))) {
132 return;
133 }
134
135 // We should not be messing with the focus if the window has capture, unless
136 // no has focus.
137 if (window && (aura::client::GetCaptureWindow(window) == window) &&
138 focused_window_) {
139 return;
140 }
141
142 // Focusing a window also activates its containing activatable window. Note
143 // that the rules could redirect activation activation and/or focus.
144 aura::Window* focusable = rules_->GetFocusableWindow(window);
145 aura::Window* activatable =
146 focusable ? rules_->GetActivatableWindow(focusable) : NULL;
147
148 // We need valid focusable/activatable windows in the event we're not clearing
149 // focus. "Clearing focus" is inferred by whether or not |window| passed to
150 // this function is non-NULL.
151 if (window && (!focusable || !activatable))
152 return;
153 DCHECK((focusable && activatable) || !window);
154
155 // Activation change observers may change the focused window. If this happens
156 // we must not adjust the focus below since this will clobber that change.
157 aura::Window* last_focused_window = focused_window_;
158 if (!updating_activation_)
159 SetActiveWindow(window, activatable);
160
161 // If the window's ActivationChangeObserver shifted focus to a valid window,
162 // we don't want to focus the window we thought would be focused by default.
163 bool activation_changed_focus = last_focused_window != focused_window_;
164 if (!updating_focus_ && (!activation_changed_focus || !focused_window_)) {
165 if (active_window_ && focusable)
166 DCHECK(active_window_->Contains(focusable));
167 SetFocusedWindow(focusable);
168 }
169 }
170
171 void FocusController::ResetFocusWithinActiveWindow(aura::Window* window) {
172 DCHECK(window);
173 if (!active_window_)
174 return;
175 if (!active_window_->Contains(window))
176 return;
177 SetFocusedWindow(window);
178 }
179
180 aura::Window* FocusController::GetFocusedWindow() {
181 return focused_window_;
182 }
183
184 ////////////////////////////////////////////////////////////////////////////////
185 // FocusController, ui::EventHandler implementation:
186 void FocusController::OnKeyEvent(ui::KeyEvent* event) {
187 }
188
189 void FocusController::OnMouseEvent(ui::MouseEvent* event) {
190 if (event->type() == ui::ET_MOUSE_PRESSED)
191 WindowFocusedFromInputEvent(static_cast<aura::Window*>(event->target()));
192 }
193
194 void FocusController::OnScrollEvent(ui::ScrollEvent* event) {
195 }
196
197 void FocusController::OnTouchEvent(ui::TouchEvent* event) {
198 }
199
200 void FocusController::OnGestureEvent(ui::GestureEvent* event) {
201 if (event->type() == ui::ET_GESTURE_BEGIN &&
202 event->details().touch_points() == 1) {
203 WindowFocusedFromInputEvent(static_cast<aura::Window*>(event->target()));
204 }
205 }
206
207 ////////////////////////////////////////////////////////////////////////////////
208 // FocusController, aura::WindowObserver implementation:
209
210 void FocusController::OnWindowVisibilityChanged(aura::Window* window,
211 bool visible) {
212 if (!visible) {
213 WindowLostFocusFromDispositionChange(window, window->parent());
214 // Despite the focus change, we need to keep the window being hidden
215 // stacked above the new window so it stays open on top as it animates away.
216 aura::Window* next_window = GetActiveWindow();
217 if (next_window && next_window->parent() == window->parent())
218 StackWindowLayerAbove(window, next_window);
219 }
220 }
221
222 void FocusController::OnWindowDestroying(aura::Window* window) {
223 WindowLostFocusFromDispositionChange(window, window->parent());
224 }
225
226 void FocusController::OnWindowHierarchyChanging(
227 const HierarchyChangeParams& params) {
228 if (params.receiver == active_window_ &&
229 params.target->Contains(params.receiver) && (!params.new_parent ||
230 aura::client::GetFocusClient(params.new_parent) !=
231 aura::client::GetFocusClient(params.receiver))) {
232 WindowLostFocusFromDispositionChange(params.receiver, params.old_parent);
233 }
234 }
235
236 void FocusController::OnWindowHierarchyChanged(
237 const HierarchyChangeParams& params) {
238 if (params.receiver == focused_window_ &&
239 params.target->Contains(params.receiver) && (!params.new_parent ||
240 aura::client::GetFocusClient(params.new_parent) !=
241 aura::client::GetFocusClient(params.receiver))) {
242 WindowLostFocusFromDispositionChange(params.receiver, params.old_parent);
243 }
244 }
245
246 ////////////////////////////////////////////////////////////////////////////////
247 // FocusController, private:
248
249 void FocusController::SetFocusedWindow(aura::Window* window) {
250 if (updating_focus_ || window == focused_window_)
251 return;
252 DCHECK(rules_->CanFocusWindow(window));
253 if (window)
254 DCHECK_EQ(window, rules_->GetFocusableWindow(window));
255
256 base::AutoReset<bool> updating_focus(&updating_focus_, true);
257 aura::Window* lost_focus = focused_window_;
258 // Allow for the window losing focus to be deleted during dispatch. If it is
259 // deleted pass NULL to observers instead of a deleted window.
260 aura::WindowTracker window_tracker;
261 if (lost_focus)
262 window_tracker.Add(lost_focus);
263 if (focused_window_ && observer_manager_.IsObserving(focused_window_) &&
264 focused_window_ != active_window_) {
265 observer_manager_.Remove(focused_window_);
266 }
267 focused_window_ = window;
268 if (focused_window_ && !observer_manager_.IsObserving(focused_window_))
269 observer_manager_.Add(focused_window_);
270
271 FOR_EACH_OBSERVER(aura::client::FocusChangeObserver,
272 focus_observers_,
273 OnWindowFocused(focused_window_,
274 window_tracker.Contains(lost_focus) ?
275 lost_focus : NULL));
276 if (window_tracker.Contains(lost_focus)) {
277 aura::client::FocusChangeObserver* observer =
278 aura::client::GetFocusChangeObserver(lost_focus);
279 if (observer)
280 observer->OnWindowFocused(focused_window_, lost_focus);
281 }
282 aura::client::FocusChangeObserver* observer =
283 aura::client::GetFocusChangeObserver(focused_window_);
284 if (observer) {
285 observer->OnWindowFocused(
286 focused_window_,
287 window_tracker.Contains(lost_focus) ? lost_focus : NULL);
288 }
289 }
290
291 void FocusController::SetActiveWindow(aura::Window* requested_window,
292 aura::Window* window) {
293 if (updating_activation_)
294 return;
295
296 if (window == active_window_) {
297 if (requested_window) {
298 FOR_EACH_OBSERVER(aura::client::ActivationChangeObserver,
299 activation_observers_,
300 OnAttemptToReactivateWindow(requested_window,
301 active_window_));
302 }
303 return;
304 }
305
306 DCHECK(rules_->CanActivateWindow(window));
307 if (window)
308 DCHECK_EQ(window, rules_->GetActivatableWindow(window));
309
310 base::AutoReset<bool> updating_activation(&updating_activation_, true);
311 aura::Window* lost_activation = active_window_;
312 // Allow for the window losing activation to be deleted during dispatch. If
313 // it is deleted pass NULL to observers instead of a deleted window.
314 aura::WindowTracker window_tracker;
315 if (lost_activation)
316 window_tracker.Add(lost_activation);
317 if (active_window_ && observer_manager_.IsObserving(active_window_) &&
318 focused_window_ != active_window_) {
319 observer_manager_.Remove(active_window_);
320 }
321 active_window_ = window;
322 if (active_window_ && !observer_manager_.IsObserving(active_window_))
323 observer_manager_.Add(active_window_);
324 if (active_window_) {
325 StackTransientParentsBelowModalWindow(active_window_);
326 active_window_->parent()->StackChildAtTop(active_window_);
327 }
328
329 aura::client::ActivationChangeObserver* observer = NULL;
330 if (window_tracker.Contains(lost_activation)) {
331 observer = aura::client::GetActivationChangeObserver(lost_activation);
332 if (observer)
333 observer->OnWindowActivated(active_window_, lost_activation);
334 }
335 observer = aura::client::GetActivationChangeObserver(active_window_);
336 if (observer) {
337 observer->OnWindowActivated(
338 active_window_,
339 window_tracker.Contains(lost_activation) ? lost_activation : NULL);
340 }
341 FOR_EACH_OBSERVER(aura::client::ActivationChangeObserver,
342 activation_observers_,
343 OnWindowActivated(active_window_,
344 window_tracker.Contains(lost_activation) ?
345 lost_activation : NULL));
346 }
347
348 void FocusController::WindowLostFocusFromDispositionChange(
349 aura::Window* window,
350 aura::Window* next) {
351 // A window's modality state will interfere with focus restoration during its
352 // destruction.
353 window->ClearProperty(aura::client::kModalKey);
354 // TODO(beng): See if this function can be replaced by a call to
355 // FocusWindow().
356 // Activation adjustments are handled first in the event of a disposition
357 // changed. If an activation change is necessary, focus is reset as part of
358 // that process so there's no point in updating focus independently.
359 if (window == active_window_) {
360 aura::Window* next_activatable = rules_->GetNextActivatableWindow(window);
361 SetActiveWindow(NULL, next_activatable);
362 if (!(active_window_ && active_window_->Contains(focused_window_)))
363 SetFocusedWindow(next_activatable);
364 } else if (window->Contains(focused_window_)) {
365 // Active window isn't changing, but focused window might be.
366 SetFocusedWindow(rules_->GetFocusableWindow(next));
367 }
368 }
369
370 void FocusController::WindowFocusedFromInputEvent(aura::Window* window) {
371 // Only focus |window| if it or any of its parents can be focused. Otherwise
372 // FocusWindow() will focus the topmost window, which may not be the
373 // currently focused one.
374 if (rules_->CanFocusWindow(GetToplevelWindow(window)))
375 FocusWindow(window);
376 }
377
378 } // namespace corewm
379 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/corewm/focus_controller.h ('k') | ui/views/corewm/focus_controller_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698