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