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