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 "ash/wm/window_cycle_controller.h" | 5 #include "ash/wm/window_cycle_controller.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "ash/shell.h" | |
10 #include "ash/shell_delegate.h" | 9 #include "ash/shell_delegate.h" |
11 #include "ash/shell_window_ids.h" | 10 #include "ash/shell_window_ids.h" |
| 11 #include "ash/wm/activation_controller.h" |
12 #include "ash/wm/window_cycle_list.h" | 12 #include "ash/wm/window_cycle_list.h" |
13 #include "ash/wm/window_util.h" | 13 #include "ash/wm/window_util.h" |
14 #include "ui/aura/event.h" | 14 #include "ui/aura/event.h" |
15 #include "ui/aura/event_filter.h" | 15 #include "ui/aura/event_filter.h" |
16 #include "ui/aura/root_window.h" | 16 #include "ui/aura/root_window.h" |
17 | 17 |
18 namespace ash { | 18 namespace ash { |
19 | 19 |
20 namespace { | 20 namespace { |
21 | 21 |
| 22 // List of containers whose children we will cycle through. |
| 23 const int kContainerIds[] = { |
| 24 internal::kShellWindowId_DefaultContainer, |
| 25 internal::kShellWindowId_AlwaysOnTopContainer |
| 26 }; |
| 27 |
22 // Filter to watch for the termination of a keyboard gesture to cycle through | 28 // Filter to watch for the termination of a keyboard gesture to cycle through |
23 // multiple windows. | 29 // multiple windows. |
24 class WindowCycleEventFilter : public aura::EventFilter { | 30 class WindowCycleEventFilter : public aura::EventFilter { |
25 public: | 31 public: |
26 WindowCycleEventFilter(); | 32 WindowCycleEventFilter(); |
27 virtual ~WindowCycleEventFilter(); | 33 virtual ~WindowCycleEventFilter(); |
28 | 34 |
29 // Overridden from aura::EventFilter: | 35 // Overridden from aura::EventFilter: |
30 virtual bool PreHandleKeyEvent(aura::Window* target, | 36 virtual bool PreHandleKeyEvent(aura::Window* target, |
31 aura::KeyEvent* event) OVERRIDE; | 37 aura::KeyEvent* event) OVERRIDE; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 aura::Window* target, | 81 aura::Window* target, |
76 aura::GestureEvent* event) { | 82 aura::GestureEvent* event) { |
77 return ui::GESTURE_STATUS_UNKNOWN; // Not handled. | 83 return ui::GESTURE_STATUS_UNKNOWN; // Not handled. |
78 } | 84 } |
79 | 85 |
80 } // namespace | 86 } // namespace |
81 | 87 |
82 ////////////////////////////////////////////////////////////////////////////// | 88 ////////////////////////////////////////////////////////////////////////////// |
83 // WindowCycleController, public: | 89 // WindowCycleController, public: |
84 | 90 |
85 WindowCycleController::WindowCycleController() { | 91 WindowCycleController::WindowCycleController( |
| 92 internal::ActivationController* activation_controller) |
| 93 : activation_controller_(activation_controller) { |
| 94 activation_controller_->AddObserver(this); |
86 } | 95 } |
87 | 96 |
88 WindowCycleController::~WindowCycleController() { | 97 WindowCycleController::~WindowCycleController() { |
| 98 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); |
| 99 for (Shell::RootWindowList::const_iterator iter = root_windows.begin(); |
| 100 iter != root_windows.end(); ++iter) { |
| 101 for (size_t i = 0; i < arraysize(kContainerIds); ++i) { |
| 102 aura::Window* container = Shell::GetContainer(*iter, kContainerIds[i]); |
| 103 if (container) |
| 104 container->RemoveObserver(this); |
| 105 } |
| 106 } |
| 107 |
| 108 activation_controller_->RemoveObserver(this); |
89 StopCycling(); | 109 StopCycling(); |
90 } | 110 } |
91 | 111 |
92 // static | 112 // static |
93 bool WindowCycleController::CanCycle() { | 113 bool WindowCycleController::CanCycle() { |
94 // Don't allow window cycling if the screen is locked or a modal dialog is | 114 // Don't allow window cycling if the screen is locked or a modal dialog is |
95 // open. | 115 // open. |
96 return !Shell::GetInstance()->IsScreenLocked() && | 116 return !Shell::GetInstance()->IsScreenLocked() && |
97 !Shell::GetInstance()->IsModalWindowOpen(); | 117 !Shell::GetInstance()->IsModalWindowOpen(); |
98 } | 118 } |
(...skipping 20 matching lines...) Expand all Loading... |
119 Step(direction); | 139 Step(direction); |
120 StopCycling(); | 140 StopCycling(); |
121 } | 141 } |
122 } | 142 } |
123 | 143 |
124 void WindowCycleController::AltKeyReleased() { | 144 void WindowCycleController::AltKeyReleased() { |
125 StopCycling(); | 145 StopCycling(); |
126 } | 146 } |
127 | 147 |
128 // static | 148 // static |
129 std::vector<aura::Window*> WindowCycleController::BuildWindowList() { | 149 std::vector<aura::Window*> WindowCycleController::BuildWindowList( |
| 150 const std::list<aura::Window*>* mru_windows) { |
130 WindowCycleList::WindowList windows; | 151 WindowCycleList::WindowList windows; |
131 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); | 152 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); |
132 | 153 |
133 for (Shell::RootWindowList::const_iterator iter = root_windows.begin(); | 154 for (Shell::RootWindowList::const_iterator iter = root_windows.begin(); |
134 iter != root_windows.end(); ++iter) { | 155 iter != root_windows.end(); ++iter) { |
135 if (*iter == Shell::GetActiveRootWindow()) | 156 if (*iter == Shell::GetActiveRootWindow()) |
136 continue; | 157 continue; |
137 aura::Window* default_container = Shell::GetContainer( | 158 for (size_t i = 0; i < arraysize(kContainerIds); ++i) { |
138 *iter, internal::kShellWindowId_DefaultContainer); | 159 aura::Window* container = Shell::GetContainer(*iter, kContainerIds[i]); |
139 WindowCycleList::WindowList children = default_container->children(); | 160 WindowCycleList::WindowList children = container->children(); |
| 161 windows.insert(windows.end(), children.begin(), children.end()); |
| 162 } |
| 163 } |
| 164 |
| 165 // Add windows in the active root windows last so that the topmost window |
| 166 // in the active root window becomes the front of the list. |
| 167 for (size_t i = 0; i < arraysize(kContainerIds); ++i) { |
| 168 aura::Window* container = |
| 169 Shell::GetContainer(Shell::GetActiveRootWindow(), kContainerIds[i]); |
| 170 |
| 171 WindowCycleList::WindowList children = container->children(); |
140 windows.insert(windows.end(), children.begin(), children.end()); | 172 windows.insert(windows.end(), children.begin(), children.end()); |
141 } | 173 } |
142 // Add windows in the active root windows last so that the topmost window | |
143 // in the active root window becomes the front of the list. | |
144 aura::Window* default_container = Shell::GetContainer( | |
145 Shell::GetActiveRootWindow(), | |
146 internal::kShellWindowId_DefaultContainer); | |
147 | |
148 WindowCycleList::WindowList children = default_container->children(); | |
149 windows.insert(windows.end(), children.begin(), children.end()); | |
150 | 174 |
151 // Removes unfocusable windows. | 175 // Removes unfocusable windows. |
152 WindowCycleList::WindowList::iterator last = | 176 WindowCycleList::WindowList::iterator last = |
153 std::remove_if( | 177 std::remove_if( |
154 windows.begin(), | 178 windows.begin(), |
155 windows.end(), | 179 windows.end(), |
156 std::not1(std::ptr_fun(ash::wm::CanActivateWindow))); | 180 std::not1(std::ptr_fun(ash::wm::CanActivateWindow))); |
157 windows.erase(last, windows.end()); | 181 windows.erase(last, windows.end()); |
| 182 |
| 183 // Put the windows in the mru_windows list at the head, if it's available. |
| 184 if (mru_windows) { |
| 185 // Iterate through the list backwards, so that we can move each window to |
| 186 // the front of the windows list as we find them. |
| 187 for (std::list<aura::Window*>::const_reverse_iterator ix = |
| 188 mru_windows->rbegin(); |
| 189 ix != mru_windows->rend(); ++ix) { |
| 190 WindowCycleList::WindowList::iterator window = |
| 191 std::find(windows.begin(), windows.end(), *ix); |
| 192 if (window != windows.end()) { |
| 193 windows.erase(window); |
| 194 windows.push_back(*ix); |
| 195 } |
| 196 } |
| 197 } |
| 198 |
158 // Window cycling expects the topmost window at the front of the list. | 199 // Window cycling expects the topmost window at the front of the list. |
159 std::reverse(windows.begin(), windows.end()); | 200 std::reverse(windows.begin(), windows.end()); |
| 201 |
160 return windows; | 202 return windows; |
161 } | 203 } |
162 | 204 |
| 205 void WindowCycleController::OnRootWindowAdded(aura::RootWindow* root_window) { |
| 206 for (size_t i = 0; i < arraysize(kContainerIds); ++i) { |
| 207 aura::Window* container = |
| 208 Shell::GetContainer(root_window, kContainerIds[i]); |
| 209 container->AddObserver(this); |
| 210 } |
| 211 } |
| 212 |
163 ////////////////////////////////////////////////////////////////////////////// | 213 ////////////////////////////////////////////////////////////////////////////// |
164 // WindowCycleController, private: | 214 // WindowCycleController, private: |
165 | 215 |
166 void WindowCycleController::StartCycling() { | 216 void WindowCycleController::StartCycling() { |
167 windows_.reset(new WindowCycleList(BuildWindowList())); | 217 windows_.reset(new WindowCycleList(BuildWindowList(&mru_windows_))); |
168 } | 218 } |
169 | 219 |
170 void WindowCycleController::Step(Direction direction) { | 220 void WindowCycleController::Step(Direction direction) { |
171 DCHECK(windows_.get()); | 221 DCHECK(windows_.get()); |
172 windows_->Step(direction == FORWARD ? WindowCycleList::FORWARD : | 222 windows_->Step(direction == FORWARD ? WindowCycleList::FORWARD : |
173 WindowCycleList::BACKWARD); | 223 WindowCycleList::BACKWARD); |
174 } | 224 } |
175 | 225 |
176 void WindowCycleController::StopCycling() { | 226 void WindowCycleController::StopCycling() { |
177 windows_.reset(); | 227 windows_.reset(); |
178 // Remove our key event filter. | 228 // Remove our key event filter. |
179 if (event_filter_.get()) { | 229 if (event_filter_.get()) { |
180 Shell::GetInstance()->RemoveEnvEventFilter(event_filter_.get()); | 230 Shell::GetInstance()->RemoveEnvEventFilter(event_filter_.get()); |
181 event_filter_.reset(); | 231 event_filter_.reset(); |
182 } | 232 } |
| 233 |
| 234 // Add the currently focused window to the MRU list |
| 235 aura::Window* active_window = wm::GetActiveWindow(); |
| 236 mru_windows_.remove(active_window); |
| 237 mru_windows_.push_front(active_window); |
| 238 } |
| 239 |
| 240 // static |
| 241 bool WindowCycleController::IsTrackedContainer(aura::Window* window) { |
| 242 if (!window) |
| 243 return false; |
| 244 for (size_t i = 0; i < arraysize(kContainerIds); ++i) { |
| 245 if (window->id() == kContainerIds[i]) { |
| 246 return true; |
| 247 } |
| 248 } |
| 249 return false; |
183 } | 250 } |
184 | 251 |
185 void WindowCycleController::InstallEventFilter() { | 252 void WindowCycleController::InstallEventFilter() { |
186 event_filter_.reset(new WindowCycleEventFilter()); | 253 event_filter_.reset(new WindowCycleEventFilter()); |
187 Shell::GetInstance()->AddEnvEventFilter(event_filter_.get()); | 254 Shell::GetInstance()->AddEnvEventFilter(event_filter_.get()); |
188 } | 255 } |
189 | 256 |
| 257 void WindowCycleController::OnWindowActivated(aura::Window* active, |
| 258 aura::Window* old_active) { |
| 259 if (active && !IsCycling() && IsTrackedContainer(active->parent())) { |
| 260 mru_windows_.remove(active); |
| 261 mru_windows_.push_front(active); |
| 262 } |
| 263 } |
| 264 |
| 265 void WindowCycleController::OnWillRemoveWindow(aura::Window* window) { |
| 266 mru_windows_.remove(window); |
| 267 } |
| 268 |
| 269 void WindowCycleController::OnWindowDestroying(aura::Window* window) { |
| 270 window->RemoveObserver(this); |
| 271 } |
| 272 |
190 } // namespace ash | 273 } // namespace ash |
OLD | NEW |