| 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 |