OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 #include "ui/wm/core/focus_controller.h" | 5 #include "ui/wm/core/focus_controller.h" |
6 | 6 |
7 #include "base/auto_reset.h" | 7 #include "base/auto_reset.h" |
8 #include "ui/aura/client/aura_constants.h" | 8 #include "ui/aura/client/aura_constants.h" |
9 #include "ui/aura/client/capture_client.h" | 9 #include "ui/aura/client/capture_client.h" |
10 #include "ui/aura/client/focus_change_observer.h" | 10 #include "ui/aura/client/focus_change_observer.h" |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
96 aura::client::FocusChangeObserver* observer) { | 96 aura::client::FocusChangeObserver* observer) { |
97 focus_observers_.AddObserver(observer); | 97 focus_observers_.AddObserver(observer); |
98 } | 98 } |
99 | 99 |
100 void FocusController::RemoveObserver( | 100 void FocusController::RemoveObserver( |
101 aura::client::FocusChangeObserver* observer) { | 101 aura::client::FocusChangeObserver* observer) { |
102 focus_observers_.RemoveObserver(observer); | 102 focus_observers_.RemoveObserver(observer); |
103 } | 103 } |
104 | 104 |
105 void FocusController::FocusWindow(aura::Window* window) { | 105 void FocusController::FocusWindow(aura::Window* window) { |
106 if (window && | 106 FocusAndActivateWindow(aura::client::ActivationChangeObserver:: |
107 (window->Contains(focused_window_) || window->Contains(active_window_))) { | 107 ActivationReason::ACTIVATION_CLIENT, |
108 return; | 108 window); |
109 } | |
110 | |
111 // Focusing a window also activates its containing activatable window. Note | |
112 // that the rules could redirect activation activation and/or focus. | |
113 aura::Window* focusable = rules_->GetFocusableWindow(window); | |
114 aura::Window* activatable = | |
115 focusable ? rules_->GetActivatableWindow(focusable) : NULL; | |
116 | |
117 // We need valid focusable/activatable windows in the event we're not clearing | |
118 // focus. "Clearing focus" is inferred by whether or not |window| passed to | |
119 // this function is non-NULL. | |
120 if (window && (!focusable || !activatable)) | |
121 return; | |
122 DCHECK((focusable && activatable) || !window); | |
123 | |
124 // Activation change observers may change the focused window. If this happens | |
125 // we must not adjust the focus below since this will clobber that change. | |
126 aura::Window* last_focused_window = focused_window_; | |
127 if (!updating_activation_) | |
128 SetActiveWindow(window, activatable); | |
129 | |
130 // If the window's ActivationChangeObserver shifted focus to a valid window, | |
131 // we don't want to focus the window we thought would be focused by default. | |
132 bool activation_changed_focus = last_focused_window != focused_window_; | |
133 if (!updating_focus_ && (!activation_changed_focus || !focused_window_)) { | |
134 if (active_window_ && focusable) | |
135 DCHECK(active_window_->Contains(focusable)); | |
136 SetFocusedWindow(focusable); | |
137 } | |
138 } | 109 } |
139 | 110 |
140 void FocusController::ResetFocusWithinActiveWindow(aura::Window* window) { | 111 void FocusController::ResetFocusWithinActiveWindow(aura::Window* window) { |
141 DCHECK(window); | 112 DCHECK(window); |
142 if (!active_window_) | 113 if (!active_window_) |
143 return; | 114 return; |
144 if (!active_window_->Contains(window)) | 115 if (!active_window_->Contains(window)) |
145 return; | 116 return; |
146 SetFocusedWindow(window); | 117 SetFocusedWindow(window); |
147 } | 118 } |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 params.target->Contains(params.receiver) && (!params.new_parent || | 177 params.target->Contains(params.receiver) && (!params.new_parent || |
207 aura::client::GetFocusClient(params.new_parent) != | 178 aura::client::GetFocusClient(params.new_parent) != |
208 aura::client::GetFocusClient(params.receiver))) { | 179 aura::client::GetFocusClient(params.receiver))) { |
209 WindowLostFocusFromDispositionChange(params.receiver, params.old_parent); | 180 WindowLostFocusFromDispositionChange(params.receiver, params.old_parent); |
210 } | 181 } |
211 } | 182 } |
212 | 183 |
213 //////////////////////////////////////////////////////////////////////////////// | 184 //////////////////////////////////////////////////////////////////////////////// |
214 // FocusController, private: | 185 // FocusController, private: |
215 | 186 |
| 187 void FocusController::FocusAndActivateWindow( |
| 188 aura::client::ActivationChangeObserver::ActivationReason reason, |
| 189 aura::Window* window) { |
| 190 if (window && |
| 191 (window->Contains(focused_window_) || window->Contains(active_window_))) { |
| 192 return; |
| 193 } |
| 194 |
| 195 // Focusing a window also activates its containing activatable window. Note |
| 196 // that the rules could redirect activation activation and/or focus. |
| 197 aura::Window* focusable = rules_->GetFocusableWindow(window); |
| 198 aura::Window* activatable = |
| 199 focusable ? rules_->GetActivatableWindow(focusable) : NULL; |
| 200 |
| 201 // We need valid focusable/activatable windows in the event we're not clearing |
| 202 // focus. "Clearing focus" is inferred by whether or not |window| passed to |
| 203 // this function is non-NULL. |
| 204 if (window && (!focusable || !activatable)) |
| 205 return; |
| 206 DCHECK((focusable && activatable) || !window); |
| 207 |
| 208 // Activation change observers may change the focused window. If this happens |
| 209 // we must not adjust the focus below since this will clobber that change. |
| 210 aura::Window* last_focused_window = focused_window_; |
| 211 if (!updating_activation_) |
| 212 SetActiveWindow(reason, window, activatable); |
| 213 |
| 214 // If the window's ActivationChangeObserver shifted focus to a valid window, |
| 215 // we don't want to focus the window we thought would be focused by default. |
| 216 bool activation_changed_focus = last_focused_window != focused_window_; |
| 217 if (!updating_focus_ && (!activation_changed_focus || !focused_window_)) { |
| 218 if (active_window_ && focusable) |
| 219 DCHECK(active_window_->Contains(focusable)); |
| 220 SetFocusedWindow(focusable); |
| 221 } |
| 222 } |
| 223 |
216 void FocusController::SetFocusedWindow(aura::Window* window) { | 224 void FocusController::SetFocusedWindow(aura::Window* window) { |
217 if (updating_focus_ || window == focused_window_) | 225 if (updating_focus_ || window == focused_window_) |
218 return; | 226 return; |
219 DCHECK(rules_->CanFocusWindow(window)); | 227 DCHECK(rules_->CanFocusWindow(window)); |
220 if (window) | 228 if (window) |
221 DCHECK_EQ(window, rules_->GetFocusableWindow(window)); | 229 DCHECK_EQ(window, rules_->GetFocusableWindow(window)); |
222 | 230 |
223 base::AutoReset<bool> updating_focus(&updating_focus_, true); | 231 base::AutoReset<bool> updating_focus(&updating_focus_, true); |
224 aura::Window* lost_focus = focused_window_; | 232 aura::Window* lost_focus = focused_window_; |
225 | 233 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
261 observer->OnWindowFocused( | 269 observer->OnWindowFocused( |
262 focused_window_, | 270 focused_window_, |
263 window_tracker.Contains(lost_focus) ? lost_focus : NULL); | 271 window_tracker.Contains(lost_focus) ? lost_focus : NULL); |
264 } | 272 } |
265 | 273 |
266 // Ensure that the text input client is reset when the window loses the focus. | 274 // Ensure that the text input client is reset when the window loses the focus. |
267 if (!window) | 275 if (!window) |
268 text_input_focus_manager->FocusTextInputClient(NULL); | 276 text_input_focus_manager->FocusTextInputClient(NULL); |
269 } | 277 } |
270 | 278 |
271 void FocusController::SetActiveWindow(aura::Window* requested_window, | 279 void FocusController::SetActiveWindow( |
272 aura::Window* window) { | 280 aura::client::ActivationChangeObserver::ActivationReason reason, |
| 281 aura::Window* requested_window, |
| 282 aura::Window* window) { |
273 if (updating_activation_) | 283 if (updating_activation_) |
274 return; | 284 return; |
275 | 285 |
276 if (window == active_window_) { | 286 if (window == active_window_) { |
277 if (requested_window) { | 287 if (requested_window) { |
278 FOR_EACH_OBSERVER(aura::client::ActivationChangeObserver, | 288 FOR_EACH_OBSERVER(aura::client::ActivationChangeObserver, |
279 activation_observers_, | 289 activation_observers_, |
280 OnAttemptToReactivateWindow(requested_window, | 290 OnAttemptToReactivateWindow(requested_window, |
281 active_window_)); | 291 active_window_)); |
282 } | 292 } |
(...skipping 20 matching lines...) Expand all Loading... |
303 observer_manager_.Add(active_window_); | 313 observer_manager_.Add(active_window_); |
304 if (active_window_) { | 314 if (active_window_) { |
305 StackTransientParentsBelowModalWindow(active_window_); | 315 StackTransientParentsBelowModalWindow(active_window_); |
306 active_window_->parent()->StackChildAtTop(active_window_); | 316 active_window_->parent()->StackChildAtTop(active_window_); |
307 } | 317 } |
308 | 318 |
309 aura::client::ActivationChangeObserver* observer = NULL; | 319 aura::client::ActivationChangeObserver* observer = NULL; |
310 if (window_tracker.Contains(lost_activation)) { | 320 if (window_tracker.Contains(lost_activation)) { |
311 observer = aura::client::GetActivationChangeObserver(lost_activation); | 321 observer = aura::client::GetActivationChangeObserver(lost_activation); |
312 if (observer) | 322 if (observer) |
313 observer->OnWindowActivated(active_window_, lost_activation); | 323 observer->OnWindowActivated(reason, active_window_, lost_activation); |
314 } | 324 } |
315 observer = aura::client::GetActivationChangeObserver(active_window_); | 325 observer = aura::client::GetActivationChangeObserver(active_window_); |
316 if (observer) { | 326 if (observer) { |
317 observer->OnWindowActivated( | 327 observer->OnWindowActivated( |
318 active_window_, | 328 reason, active_window_, |
319 window_tracker.Contains(lost_activation) ? lost_activation : NULL); | 329 window_tracker.Contains(lost_activation) ? lost_activation : NULL); |
320 } | 330 } |
321 FOR_EACH_OBSERVER(aura::client::ActivationChangeObserver, | 331 FOR_EACH_OBSERVER( |
322 activation_observers_, | 332 aura::client::ActivationChangeObserver, activation_observers_, |
323 OnWindowActivated(active_window_, | 333 OnWindowActivated( |
324 window_tracker.Contains(lost_activation) ? | 334 reason, active_window_, |
325 lost_activation : NULL)); | 335 window_tracker.Contains(lost_activation) ? lost_activation : NULL)); |
326 } | 336 } |
327 | 337 |
328 void FocusController::WindowLostFocusFromDispositionChange( | 338 void FocusController::WindowLostFocusFromDispositionChange( |
329 aura::Window* window, | 339 aura::Window* window, |
330 aura::Window* next) { | 340 aura::Window* next) { |
331 // TODO(beng): See if this function can be replaced by a call to | 341 // TODO(beng): See if this function can be replaced by a call to |
332 // FocusWindow(). | 342 // FocusWindow(). |
333 // Activation adjustments are handled first in the event of a disposition | 343 // Activation adjustments are handled first in the event of a disposition |
334 // changed. If an activation change is necessary, focus is reset as part of | 344 // changed. If an activation change is necessary, focus is reset as part of |
335 // that process so there's no point in updating focus independently. | 345 // that process so there's no point in updating focus independently. |
336 if (window == active_window_) { | 346 if (window == active_window_) { |
337 aura::Window* next_activatable = rules_->GetNextActivatableWindow(window); | 347 aura::Window* next_activatable = rules_->GetNextActivatableWindow(window); |
338 SetActiveWindow(NULL, next_activatable); | 348 SetActiveWindow(aura::client::ActivationChangeObserver::ActivationReason:: |
| 349 WINDOW_DISPOSITION_CHANGED, |
| 350 NULL, next_activatable); |
339 if (!(active_window_ && active_window_->Contains(focused_window_))) | 351 if (!(active_window_ && active_window_->Contains(focused_window_))) |
340 SetFocusedWindow(next_activatable); | 352 SetFocusedWindow(next_activatable); |
341 } else if (window->Contains(focused_window_)) { | 353 } else if (window->Contains(focused_window_)) { |
342 // Active window isn't changing, but focused window might be. | 354 // Active window isn't changing, but focused window might be. |
343 SetFocusedWindow(rules_->GetFocusableWindow(next)); | 355 SetFocusedWindow(rules_->GetFocusableWindow(next)); |
344 } | 356 } |
345 } | 357 } |
346 | 358 |
347 void FocusController::WindowFocusedFromInputEvent(aura::Window* window) { | 359 void FocusController::WindowFocusedFromInputEvent(aura::Window* window) { |
348 // Only focus |window| if it or any of its parents can be focused. Otherwise | 360 // Only focus |window| if it or any of its parents can be focused. Otherwise |
349 // FocusWindow() will focus the topmost window, which may not be the | 361 // FocusWindow() will focus the topmost window, which may not be the |
350 // currently focused one. | 362 // currently focused one. |
351 if (rules_->CanFocusWindow(GetToplevelWindow(window))) | 363 if (rules_->CanFocusWindow(GetToplevelWindow(window))) { |
352 FocusWindow(window); | 364 FocusAndActivateWindow( |
| 365 aura::client::ActivationChangeObserver::ActivationReason::INPUT_EVENT, |
| 366 window); |
| 367 } |
353 } | 368 } |
354 | 369 |
355 } // namespace wm | 370 } // namespace wm |
OLD | NEW |