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/wm/core/focus_controller.h" 6 7 #include "base/auto_reset.h" 8 #include "ui/aura/client/aura_constants.h" 9 #include "ui/aura/client/capture_client.h" 10 #include "ui/aura/client/focus_change_observer.h" 11 #include "ui/aura/env.h" 12 #include "ui/aura/window_tracker.h" 13 #include "ui/base/ime/text_input_focus_manager.h" 14 #include "ui/events/event.h" 15 #include "ui/wm/core/focus_rules.h" 16 #include "ui/wm/core/window_util.h" 17 #include "ui/wm/public/activation_change_observer.h" 18 19 namespace wm { 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 = wm::GetTransientParent(window); 30 while (transient_parent) { 31 transient_parent->parent()->StackChildAtTop(transient_parent); 32 transient_parent = wm::GetTransientParent(transient_parent); 33 } 34 } 35 36 } // namespace 37 38 //////////////////////////////////////////////////////////////////////////////// 39 // FocusController, public: 40 41 FocusController::FocusController(FocusRules* rules) 42 : active_window_(NULL), 43 focused_window_(NULL), 44 updating_focus_(false), 45 updating_activation_(false), 46 rules_(rules), 47 observer_manager_(this) { 48 DCHECK(rules); 49 } 50 51 FocusController::~FocusController() { 52 } 53 54 //////////////////////////////////////////////////////////////////////////////// 55 // FocusController, aura::client::ActivationClient implementation: 56 57 void FocusController::AddObserver( 58 aura::client::ActivationChangeObserver* observer) { 59 activation_observers_.AddObserver(observer); 60 } 61 62 void FocusController::RemoveObserver( 63 aura::client::ActivationChangeObserver* observer) { 64 activation_observers_.RemoveObserver(observer); 65 } 66 67 void FocusController::ActivateWindow(aura::Window* window) { 68 FocusWindow(window); 69 } 70 71 void FocusController::DeactivateWindow(aura::Window* window) { 72 if (window) 73 FocusWindow(rules_->GetNextActivatableWindow(window)); 74 } 75 76 aura::Window* FocusController::GetActiveWindow() { 77 return active_window_; 78 } 79 80 aura::Window* FocusController::GetActivatableWindow(aura::Window* window) { 81 return rules_->GetActivatableWindow(window); 82 } 83 84 aura::Window* FocusController::GetToplevelWindow(aura::Window* window) { 85 return rules_->GetToplevelWindow(window); 86 } 87 88 bool FocusController::OnWillFocusWindow(aura::Window* window, 89 const ui::Event* event) { 90 NOTREACHED(); 91 return false; 92 } 93 94 bool FocusController::CanActivateWindow(aura::Window* window) const { 95 return rules_->CanActivateWindow(window); 96 } 97 98 //////////////////////////////////////////////////////////////////////////////// 99 // FocusController, aura::client::FocusClient implementation: 100 101 void FocusController::AddObserver( 102 aura::client::FocusChangeObserver* observer) { 103 focus_observers_.AddObserver(observer); 104 } 105 106 void FocusController::RemoveObserver( 107 aura::client::FocusChangeObserver* observer) { 108 focus_observers_.RemoveObserver(observer); 109 } 110 111 void FocusController::FocusWindow(aura::Window* window) { 112 if (window && 113 (window->Contains(focused_window_) || window->Contains(active_window_))) { 114 return; 115 } 116 117 // We should not be messing with the focus if the window has capture, unless 118 // no has focus. 119 if (window && (aura::client::GetCaptureWindow(window) == window) && 120 focused_window_) { 121 return; 122 } 123 124 // Focusing a window also activates its containing activatable window. Note 125 // that the rules could redirect activation activation and/or focus. 126 aura::Window* focusable = rules_->GetFocusableWindow(window); 127 aura::Window* activatable = 128 focusable ? rules_->GetActivatableWindow(focusable) : NULL; 129 130 // We need valid focusable/activatable windows in the event we're not clearing 131 // focus. "Clearing focus" is inferred by whether or not |window| passed to 132 // this function is non-NULL. 133 if (window && (!focusable || !activatable)) 134 return; 135 DCHECK((focusable && activatable) || !window); 136 137 // Activation change observers may change the focused window. If this happens 138 // we must not adjust the focus below since this will clobber that change. 139 aura::Window* last_focused_window = focused_window_; 140 if (!updating_activation_) 141 SetActiveWindow(window, activatable); 142 143 // If the window's ActivationChangeObserver shifted focus to a valid window, 144 // we don't want to focus the window we thought would be focused by default. 145 bool activation_changed_focus = last_focused_window != focused_window_; 146 if (!updating_focus_ && (!activation_changed_focus || !focused_window_)) { 147 if (active_window_ && focusable) 148 DCHECK(active_window_->Contains(focusable)); 149 SetFocusedWindow(focusable); 150 } 151 } 152 153 void FocusController::ResetFocusWithinActiveWindow(aura::Window* window) { 154 DCHECK(window); 155 if (!active_window_) 156 return; 157 if (!active_window_->Contains(window)) 158 return; 159 SetFocusedWindow(window); 160 } 161 162 aura::Window* FocusController::GetFocusedWindow() { 163 return focused_window_; 164 } 165 166 //////////////////////////////////////////////////////////////////////////////// 167 // FocusController, ui::EventHandler implementation: 168 void FocusController::OnKeyEvent(ui::KeyEvent* event) { 169 } 170 171 void FocusController::OnMouseEvent(ui::MouseEvent* event) { 172 if (event->type() == ui::ET_MOUSE_PRESSED && !event->handled()) 173 WindowFocusedFromInputEvent(static_cast<aura::Window*>(event->target())); 174 } 175 176 void FocusController::OnScrollEvent(ui::ScrollEvent* event) { 177 } 178 179 void FocusController::OnTouchEvent(ui::TouchEvent* event) { 180 } 181 182 void FocusController::OnGestureEvent(ui::GestureEvent* event) { 183 if (event->type() == ui::ET_GESTURE_BEGIN && 184 event->details().touch_points() == 1 && 185 !event->handled()) { 186 WindowFocusedFromInputEvent(static_cast<aura::Window*>(event->target())); 187 } 188 } 189 190 //////////////////////////////////////////////////////////////////////////////// 191 // FocusController, aura::WindowObserver implementation: 192 193 void FocusController::OnWindowVisibilityChanged(aura::Window* window, 194 bool visible) { 195 if (!visible) 196 WindowLostFocusFromDispositionChange(window, window->parent()); 197 } 198 199 void FocusController::OnWindowDestroying(aura::Window* window) { 200 WindowLostFocusFromDispositionChange(window, window->parent()); 201 } 202 203 void FocusController::OnWindowHierarchyChanging( 204 const HierarchyChangeParams& params) { 205 if (params.receiver == active_window_ && 206 params.target->Contains(params.receiver) && (!params.new_parent || 207 aura::client::GetFocusClient(params.new_parent) != 208 aura::client::GetFocusClient(params.receiver))) { 209 WindowLostFocusFromDispositionChange(params.receiver, params.old_parent); 210 } 211 } 212 213 void FocusController::OnWindowHierarchyChanged( 214 const HierarchyChangeParams& params) { 215 if (params.receiver == focused_window_ && 216 params.target->Contains(params.receiver) && (!params.new_parent || 217 aura::client::GetFocusClient(params.new_parent) != 218 aura::client::GetFocusClient(params.receiver))) { 219 WindowLostFocusFromDispositionChange(params.receiver, params.old_parent); 220 } 221 } 222 223 //////////////////////////////////////////////////////////////////////////////// 224 // FocusController, private: 225 226 void FocusController::SetFocusedWindow(aura::Window* window) { 227 if (updating_focus_ || window == focused_window_) 228 return; 229 DCHECK(rules_->CanFocusWindow(window)); 230 if (window) 231 DCHECK_EQ(window, rules_->GetFocusableWindow(window)); 232 233 base::AutoReset<bool> updating_focus(&updating_focus_, true); 234 aura::Window* lost_focus = focused_window_; 235 236 // |window| is going to get the focus, so reset the text input client. 237 // OnWindowFocused() may set a proper text input client if the implementation 238 // supports text input. 239 ui::TextInputFocusManager* text_input_focus_manager = 240 ui::TextInputFocusManager::GetInstance(); 241 if (window) 242 text_input_focus_manager->FocusTextInputClient(NULL); 243 244 // Allow for the window losing focus to be deleted during dispatch. If it is 245 // deleted pass NULL to observers instead of a deleted window. 246 aura::WindowTracker window_tracker; 247 if (lost_focus) 248 window_tracker.Add(lost_focus); 249 if (focused_window_ && observer_manager_.IsObserving(focused_window_) && 250 focused_window_ != active_window_) { 251 observer_manager_.Remove(focused_window_); 252 } 253 focused_window_ = window; 254 if (focused_window_ && !observer_manager_.IsObserving(focused_window_)) 255 observer_manager_.Add(focused_window_); 256 257 FOR_EACH_OBSERVER(aura::client::FocusChangeObserver, 258 focus_observers_, 259 OnWindowFocused(focused_window_, 260 window_tracker.Contains(lost_focus) ? 261 lost_focus : NULL)); 262 if (window_tracker.Contains(lost_focus)) { 263 aura::client::FocusChangeObserver* observer = 264 aura::client::GetFocusChangeObserver(lost_focus); 265 if (observer) 266 observer->OnWindowFocused(focused_window_, lost_focus); 267 } 268 aura::client::FocusChangeObserver* observer = 269 aura::client::GetFocusChangeObserver(focused_window_); 270 if (observer) { 271 observer->OnWindowFocused( 272 focused_window_, 273 window_tracker.Contains(lost_focus) ? lost_focus : NULL); 274 } 275 276 // Ensure that the text input client is reset when the window loses the focus. 277 if (!window) 278 text_input_focus_manager->FocusTextInputClient(NULL); 279 } 280 281 void FocusController::SetActiveWindow(aura::Window* requested_window, 282 aura::Window* window) { 283 if (updating_activation_) 284 return; 285 286 if (window == active_window_) { 287 if (requested_window) { 288 FOR_EACH_OBSERVER(aura::client::ActivationChangeObserver, 289 activation_observers_, 290 OnAttemptToReactivateWindow(requested_window, 291 active_window_)); 292 } 293 return; 294 } 295 296 DCHECK(rules_->CanActivateWindow(window)); 297 if (window) 298 DCHECK_EQ(window, rules_->GetActivatableWindow(window)); 299 300 base::AutoReset<bool> updating_activation(&updating_activation_, true); 301 aura::Window* lost_activation = active_window_; 302 // Allow for the window losing activation to be deleted during dispatch. If 303 // it is deleted pass NULL to observers instead of a deleted window. 304 aura::WindowTracker window_tracker; 305 if (lost_activation) 306 window_tracker.Add(lost_activation); 307 if (active_window_ && observer_manager_.IsObserving(active_window_) && 308 focused_window_ != active_window_) { 309 observer_manager_.Remove(active_window_); 310 } 311 active_window_ = window; 312 if (active_window_ && !observer_manager_.IsObserving(active_window_)) 313 observer_manager_.Add(active_window_); 314 if (active_window_) { 315 StackTransientParentsBelowModalWindow(active_window_); 316 active_window_->parent()->StackChildAtTop(active_window_); 317 } 318 319 aura::client::ActivationChangeObserver* observer = NULL; 320 if (window_tracker.Contains(lost_activation)) { 321 observer = aura::client::GetActivationChangeObserver(lost_activation); 322 if (observer) 323 observer->OnWindowActivated(active_window_, lost_activation); 324 } 325 observer = aura::client::GetActivationChangeObserver(active_window_); 326 if (observer) { 327 observer->OnWindowActivated( 328 active_window_, 329 window_tracker.Contains(lost_activation) ? lost_activation : NULL); 330 } 331 FOR_EACH_OBSERVER(aura::client::ActivationChangeObserver, 332 activation_observers_, 333 OnWindowActivated(active_window_, 334 window_tracker.Contains(lost_activation) ? 335 lost_activation : NULL)); 336 } 337 338 void FocusController::WindowLostFocusFromDispositionChange( 339 aura::Window* window, 340 aura::Window* next) { 341 // A window's modality state will interfere with focus restoration during its 342 // destruction. 343 window->ClearProperty(aura::client::kModalKey); 344 // TODO(beng): See if this function can be replaced by a call to 345 // FocusWindow(). 346 // Activation adjustments are handled first in the event of a disposition 347 // changed. If an activation change is necessary, focus is reset as part of 348 // that process so there's no point in updating focus independently. 349 if (window == active_window_) { 350 aura::Window* next_activatable = rules_->GetNextActivatableWindow(window); 351 SetActiveWindow(NULL, next_activatable); 352 if (!(active_window_ && active_window_->Contains(focused_window_))) 353 SetFocusedWindow(next_activatable); 354 } else if (window->Contains(focused_window_)) { 355 // Active window isn't changing, but focused window might be. 356 SetFocusedWindow(rules_->GetFocusableWindow(next)); 357 } 358 } 359 360 void FocusController::WindowFocusedFromInputEvent(aura::Window* window) { 361 // Only focus |window| if it or any of its parents can be focused. Otherwise 362 // FocusWindow() will focus the topmost window, which may not be the 363 // currently focused one. 364 if (rules_->CanFocusWindow(GetToplevelWindow(window))) 365 FocusWindow(window); 366 } 367 368 } // namespace wm 369