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