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 | |
sky
2012/08/02 21:18:00
Move this comment to 164ish new.
Zachary Kuznia
2012/08/06 05:56:03
Done.
| |
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::IsTrackedContainer(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() && IsTrackedContainer(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 |