| OLD | NEW |
| (Empty) |
| 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/widget/desktop_aura/desktop_activation_client.h" | |
| 6 | |
| 7 #include "base/auto_reset.h" | |
| 8 #include "base/compiler_specific.h" | |
| 9 #include "ui/aura/client/activation_delegate.h" | |
| 10 #include "ui/aura/client/activation_change_observer.h" | |
| 11 #include "ui/aura/client/focus_client.h" | |
| 12 #include "ui/aura/root_window.h" | |
| 13 #include "ui/aura/window.h" | |
| 14 | |
| 15 namespace views { | |
| 16 | |
| 17 namespace { | |
| 18 | |
| 19 aura::Window* FindFocusableWindowFor(aura::Window* window) { | |
| 20 while (window && !window->CanFocus()) | |
| 21 window = window->parent(); | |
| 22 return window; | |
| 23 } | |
| 24 | |
| 25 } // namespace | |
| 26 | |
| 27 DesktopActivationClient::DesktopActivationClient(aura::RootWindow* root_window) | |
| 28 : root_window_(root_window), | |
| 29 current_active_(NULL), | |
| 30 updating_activation_(false), | |
| 31 observer_manager_(this) { | |
| 32 aura::client::GetFocusClient(root_window_)->AddObserver(this); | |
| 33 aura::client::SetActivationClient(root_window_, this); | |
| 34 root_window->AddPreTargetHandler(this); | |
| 35 } | |
| 36 | |
| 37 DesktopActivationClient::~DesktopActivationClient() { | |
| 38 root_window_->RemovePreTargetHandler(this); | |
| 39 aura::client::GetFocusClient(root_window_)->RemoveObserver(this); | |
| 40 aura::client::SetActivationClient(root_window_, NULL); | |
| 41 } | |
| 42 | |
| 43 void DesktopActivationClient::AddObserver( | |
| 44 aura::client::ActivationChangeObserver* observer) { | |
| 45 observers_.AddObserver(observer); | |
| 46 } | |
| 47 | |
| 48 void DesktopActivationClient::RemoveObserver( | |
| 49 aura::client::ActivationChangeObserver* observer) { | |
| 50 observers_.RemoveObserver(observer); | |
| 51 } | |
| 52 | |
| 53 void DesktopActivationClient::ActivateWindow(aura::Window* window) { | |
| 54 // Prevent recursion when called from focus. | |
| 55 if (updating_activation_) | |
| 56 return; | |
| 57 | |
| 58 base::AutoReset<bool> in_activate_window(&updating_activation_, true); | |
| 59 // Nothing may actually have changed. | |
| 60 if (current_active_ == window) | |
| 61 return; | |
| 62 // The stacking client may impose rules on what window configurations can be | |
| 63 // activated or deactivated. | |
| 64 if (window && !CanActivateWindow(window)) | |
| 65 return; | |
| 66 // Switch internal focus before we change the activation. Will probably cause | |
| 67 // recursion. | |
| 68 if (window && | |
| 69 !window->Contains(aura::client::GetFocusClient(window)-> | |
| 70 GetFocusedWindow())) { | |
| 71 aura::client::GetFocusClient(window)->FocusWindow(window); | |
| 72 } | |
| 73 | |
| 74 aura::Window* old_active = current_active_; | |
| 75 current_active_ = window; | |
| 76 if (window && !observer_manager_.IsObserving(window)) | |
| 77 observer_manager_.Add(window); | |
| 78 | |
| 79 FOR_EACH_OBSERVER(aura::client::ActivationChangeObserver, | |
| 80 observers_, | |
| 81 OnWindowActivated(window, old_active)); | |
| 82 aura::client::ActivationChangeObserver* observer = | |
| 83 aura::client::GetActivationChangeObserver(old_active); | |
| 84 if (observer) | |
| 85 observer->OnWindowActivated(window, old_active); | |
| 86 observer = aura::client::GetActivationChangeObserver(window); | |
| 87 if (observer) | |
| 88 observer->OnWindowActivated(window, old_active); | |
| 89 } | |
| 90 | |
| 91 void DesktopActivationClient::DeactivateWindow(aura::Window* window) { | |
| 92 if (window == current_active_) | |
| 93 current_active_ = NULL; | |
| 94 } | |
| 95 | |
| 96 aura::Window* DesktopActivationClient::GetActiveWindow() { | |
| 97 return current_active_; | |
| 98 } | |
| 99 | |
| 100 aura::Window* DesktopActivationClient::GetActivatableWindow( | |
| 101 aura::Window* window) { | |
| 102 aura::Window* parent = window->parent(); | |
| 103 aura::Window* child = window; | |
| 104 while (parent) { | |
| 105 if (CanActivateWindow(child)) | |
| 106 return child; | |
| 107 // If |child| isn't activatable, but has transient parent, trace | |
| 108 // that path instead. | |
| 109 if (child->transient_parent()) | |
| 110 return GetActivatableWindow(child->transient_parent()); | |
| 111 parent = parent->parent(); | |
| 112 child = child->parent(); | |
| 113 } | |
| 114 return NULL; | |
| 115 } | |
| 116 | |
| 117 aura::Window* DesktopActivationClient::GetToplevelWindow(aura::Window* window) { | |
| 118 aura::Window* parent = window->parent(); | |
| 119 aura::Window* child = window; | |
| 120 aura::Window* root = child->GetRootWindow(); | |
| 121 while (parent) { | |
| 122 if (parent == root) | |
| 123 return child; | |
| 124 parent = parent->parent(); | |
| 125 child = child->parent(); | |
| 126 } | |
| 127 return NULL; | |
| 128 } | |
| 129 | |
| 130 bool DesktopActivationClient::OnWillFocusWindow(aura::Window* window, | |
| 131 const ui::Event* event) { | |
| 132 return CanActivateWindow(GetActivatableWindow(window)); | |
| 133 } | |
| 134 | |
| 135 void DesktopActivationClient::OnWindowDestroying(aura::Window* window) { | |
| 136 if (current_active_ == window) { | |
| 137 current_active_ = NULL; | |
| 138 FOR_EACH_OBSERVER(aura::client::ActivationChangeObserver, | |
| 139 observers_, | |
| 140 OnWindowActivated(NULL, window)); | |
| 141 | |
| 142 // ash::ActivationController will also activate the next window here; we | |
| 143 // don't do this because that's the desktop environment's job. | |
| 144 } | |
| 145 observer_manager_.Remove(window); | |
| 146 } | |
| 147 | |
| 148 void DesktopActivationClient::OnWindowFocused(aura::Window* gained_focus, | |
| 149 aura::Window* lost_focus) { | |
| 150 if (gained_focus) | |
| 151 ActivateWindow(GetActivatableWindow(gained_focus)); | |
| 152 } | |
| 153 | |
| 154 bool DesktopActivationClient::CanActivateWindow(aura::Window* window) const { | |
| 155 return window && | |
| 156 window->IsVisible() && | |
| 157 (!aura::client::GetActivationDelegate(window) || | |
| 158 aura::client::GetActivationDelegate(window)->ShouldActivate()); | |
| 159 } | |
| 160 | |
| 161 void DesktopActivationClient::OnKeyEvent(ui::KeyEvent* event) { | |
| 162 } | |
| 163 | |
| 164 void DesktopActivationClient::OnMouseEvent(ui::MouseEvent* event) { | |
| 165 if (event->type() == ui::ET_MOUSE_PRESSED) | |
| 166 FocusWindowWithEvent(event); | |
| 167 } | |
| 168 | |
| 169 void DesktopActivationClient::OnScrollEvent(ui::ScrollEvent* event) { | |
| 170 } | |
| 171 | |
| 172 void DesktopActivationClient::OnTouchEvent(ui::TouchEvent* event) { | |
| 173 } | |
| 174 | |
| 175 void DesktopActivationClient::OnGestureEvent(ui::GestureEvent* event) { | |
| 176 if (event->type() == ui::ET_GESTURE_BEGIN && | |
| 177 event->details().touch_points() == 1) { | |
| 178 FocusWindowWithEvent(event); | |
| 179 } | |
| 180 } | |
| 181 | |
| 182 void DesktopActivationClient::FocusWindowWithEvent(const ui::Event* event) { | |
| 183 aura::Window* window = static_cast<aura::Window*>(event->target()); | |
| 184 if (GetActiveWindow() != window) { | |
| 185 aura::client::GetFocusClient(window)->FocusWindow( | |
| 186 FindFocusableWindowFor(window)); | |
| 187 } | |
| 188 } | |
| 189 | |
| 190 } // namespace views | |
| OLD | NEW |