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 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
75 aura::Window* target, | 76 aura::Window* target, |
76 aura::GestureEvent* event) { | 77 aura::GestureEvent* event) { |
77 return ui::GESTURE_STATUS_UNKNOWN; // Not handled. | 78 return ui::GESTURE_STATUS_UNKNOWN; // Not handled. |
78 } | 79 } |
79 | 80 |
80 } // namespace | 81 } // namespace |
81 | 82 |
82 ////////////////////////////////////////////////////////////////////////////// | 83 ////////////////////////////////////////////////////////////////////////////// |
83 // WindowCycleController, public: | 84 // WindowCycleController, public: |
84 | 85 |
85 WindowCycleController::WindowCycleController() { | 86 WindowCycleController::WindowCycleController() : mru_ignore_(false) { |
87 Shell::GetInstance()->activation_controller()->AddObserver(this); | |
86 } | 88 } |
87 | 89 |
88 WindowCycleController::~WindowCycleController() { | 90 WindowCycleController::~WindowCycleController() { |
91 Shell::GetInstance()->activation_controller()->RemoveObserver(this); | |
89 StopCycling(); | 92 StopCycling(); |
90 } | 93 } |
91 | 94 |
92 // static | 95 // static |
93 bool WindowCycleController::CanCycle() { | 96 bool WindowCycleController::CanCycle() { |
94 // Don't allow window cycling if the screen is locked or a modal dialog is | 97 // Don't allow window cycling if the screen is locked or a modal dialog is |
95 // open. | 98 // open. |
96 return !Shell::GetInstance()->IsScreenLocked() && | 99 return !Shell::GetInstance()->IsScreenLocked() && |
97 !Shell::GetInstance()->IsModalWindowOpen(); | 100 !Shell::GetInstance()->IsModalWindowOpen(); |
98 } | 101 } |
99 | 102 |
100 void WindowCycleController::HandleCycleWindow(Direction direction, | 103 void WindowCycleController::HandleCycleWindow(Direction direction, |
101 bool is_alt_down) { | 104 bool is_alt_down) { |
102 if (!CanCycle()) | 105 if (!CanCycle()) |
103 return; | 106 return; |
104 | 107 |
105 if (is_alt_down) { | 108 if (is_alt_down) { |
106 if (!IsCycling()) { | 109 if (!IsCycling()) { |
110 mru_ignore_ = true; | |
107 // This is the start of an alt-tab cycle through multiple windows, so | 111 // This is the start of an alt-tab cycle through multiple windows, so |
108 // listen for the alt key being released to stop cycling. | 112 // listen for the alt key being released to stop cycling. |
109 StartCycling(); | 113 StartCycling(); |
110 Step(direction); | 114 Step(direction); |
111 InstallEventFilter(); | 115 InstallEventFilter(); |
112 } else { | 116 } else { |
113 // We're in the middle of an alt-tab cycle, just step forward. | 117 // We're in the middle of an alt-tab cycle, just step forward. |
114 Step(direction); | 118 Step(direction); |
115 } | 119 } |
116 } else { | 120 } else { |
117 // This is a simple, single-step window cycle. | 121 // This is a simple, single-step window cycle. |
118 StartCycling(); | 122 StartCycling(); |
119 Step(direction); | 123 Step(direction); |
120 StopCycling(); | 124 StopCycling(); |
121 } | 125 } |
122 } | 126 } |
123 | 127 |
124 void WindowCycleController::AltKeyReleased() { | 128 void WindowCycleController::AltKeyReleased() { |
125 StopCycling(); | 129 StopCycling(); |
130 | |
131 // Add the currently focused window to the MRU list, and stop ignoring | |
132 // activations. | |
133 mru_ignore_ = false; | |
134 aura::Window* active_window = wm::GetActiveWindow(); | |
135 mru_windows_.remove(active_window); | |
136 mru_windows_.push_front(active_window); | |
126 } | 137 } |
127 | 138 |
128 // static | 139 // static |
129 std::vector<aura::Window*> WindowCycleController::BuildWindowList() { | 140 std::vector<aura::Window*> WindowCycleController::BuildWindowList( |
141 std::list<aura::Window*>* mru_windows) { | |
142 const int kContainerIds[] = { | |
143 internal::kShellWindowId_DefaultContainer, | |
144 internal::kShellWindowId_AlwaysOnTopContainer | |
145 }; | |
146 | |
130 WindowCycleList::WindowList windows; | 147 WindowCycleList::WindowList windows; |
131 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); | 148 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); |
132 | 149 |
133 for (Shell::RootWindowList::const_iterator iter = root_windows.begin(); | 150 for (Shell::RootWindowList::const_iterator iter = root_windows.begin(); |
134 iter != root_windows.end(); ++iter) { | 151 iter != root_windows.end(); ++iter) { |
135 if (*iter == Shell::GetActiveRootWindow()) | 152 if (*iter == Shell::GetActiveRootWindow()) |
136 continue; | 153 continue; |
137 aura::Window* default_container = Shell::GetContainer( | 154 for (size_t i = 0; i < arraysize(kContainerIds); ++i) { |
138 *iter, internal::kShellWindowId_DefaultContainer); | 155 aura::Window* container = Shell::GetContainer(*iter, kContainerIds[i]); |
139 WindowCycleList::WindowList children = default_container->children(); | 156 WindowCycleList::WindowList children = container->children(); |
157 windows.insert(windows.end(), children.begin(), children.end()); | |
158 } | |
159 } | |
160 | |
161 for (size_t i = 0; i < arraysize(kContainerIds); ++i) { | |
162 aura::Window* container = | |
163 Shell::GetContainer(Shell::GetActiveRootWindow(), kContainerIds[i]); | |
164 | |
165 WindowCycleList::WindowList children = container->children(); | |
140 windows.insert(windows.end(), children.begin(), children.end()); | 166 windows.insert(windows.end(), children.begin(), children.end()); |
141 } | 167 } |
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 | 168 |
151 // Removes unfocusable windows. | 169 // Removes unfocusable windows. |
152 WindowCycleList::WindowList::iterator last = | 170 WindowCycleList::WindowList::iterator last = |
153 std::remove_if( | 171 std::remove_if( |
154 windows.begin(), | 172 windows.begin(), |
155 windows.end(), | 173 windows.end(), |
156 std::not1(std::ptr_fun(ash::wm::CanActivateWindow))); | 174 std::not1(std::ptr_fun(ash::wm::CanActivateWindow))); |
157 windows.erase(last, windows.end()); | 175 windows.erase(last, windows.end()); |
176 | |
177 // Put the windows in the mru_windows list at the head, if it's available. | |
178 if (mru_windows) { | |
179 for (std::list<aura::Window*>::const_reverse_iterator ix = | |
180 mru_windows->rbegin(); | |
181 ix != mru_windows->rend(); ++ix) { | |
182 WindowCycleList::WindowList::iterator window = | |
183 std::find(windows.begin(), windows.end(), *ix); | |
184 if (window != windows.end()) { | |
185 windows.erase(window); | |
186 windows.push_back(*ix); | |
187 } | |
188 } | |
189 } | |
190 | |
158 // Window cycling expects the topmost window at the front of the list. | 191 // Window cycling expects the topmost window at the front of the list. |
159 std::reverse(windows.begin(), windows.end()); | 192 std::reverse(windows.begin(), windows.end()); |
193 | |
160 return windows; | 194 return windows; |
161 } | 195 } |
162 | 196 |
163 ////////////////////////////////////////////////////////////////////////////// | 197 ////////////////////////////////////////////////////////////////////////////// |
164 // WindowCycleController, private: | 198 // WindowCycleController, private: |
165 | 199 |
166 void WindowCycleController::StartCycling() { | 200 void WindowCycleController::StartCycling() { |
167 windows_.reset(new WindowCycleList(BuildWindowList())); | 201 windows_.reset(new WindowCycleList(BuildWindowList(&mru_windows_))); |
168 } | 202 } |
169 | 203 |
170 void WindowCycleController::Step(Direction direction) { | 204 void WindowCycleController::Step(Direction direction) { |
171 DCHECK(windows_.get()); | 205 DCHECK(windows_.get()); |
172 windows_->Step(direction == FORWARD ? WindowCycleList::FORWARD : | 206 windows_->Step(direction == FORWARD ? WindowCycleList::FORWARD : |
173 WindowCycleList::BACKWARD); | 207 WindowCycleList::BACKWARD); |
174 } | 208 } |
175 | 209 |
176 void WindowCycleController::StopCycling() { | 210 void WindowCycleController::StopCycling() { |
177 windows_.reset(); | 211 windows_.reset(); |
178 // Remove our key event filter. | 212 // Remove our key event filter. |
179 if (event_filter_.get()) { | 213 if (event_filter_.get()) { |
180 Shell::GetInstance()->RemoveEnvEventFilter(event_filter_.get()); | 214 Shell::GetInstance()->RemoveEnvEventFilter(event_filter_.get()); |
181 event_filter_.reset(); | 215 event_filter_.reset(); |
182 } | 216 } |
183 } | 217 } |
184 | 218 |
185 void WindowCycleController::InstallEventFilter() { | 219 void WindowCycleController::InstallEventFilter() { |
186 event_filter_.reset(new WindowCycleEventFilter()); | 220 event_filter_.reset(new WindowCycleEventFilter()); |
187 Shell::GetInstance()->AddEnvEventFilter(event_filter_.get()); | 221 Shell::GetInstance()->AddEnvEventFilter(event_filter_.get()); |
188 } | 222 } |
189 | 223 |
224 void WindowCycleController::OnWindowActivated(aura::Window* active, | |
225 aura::Window* old_active) { | |
226 if (active) { | |
sky
2012/07/19 16:41:15
Only add windows that are children of the containe
Zachary Kuznia
2012/07/23 22:44:33
Done.
| |
227 if (!mru_ignore_) { | |
228 mru_windows_.remove(active); | |
229 mru_windows_.push_front(active); | |
230 } | |
231 } else { | |
232 mru_windows_.remove(old_active); | |
233 } | |
234 } | |
235 | |
190 } // namespace ash | 236 } // namespace ash |
OLD | NEW |