Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Side by Side Diff: ash/wm/window_cycle_controller.cc

Issue 20708005: Refactor most recently used window tracking into a separate class. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/session_state_delegate.h" 9 #include "ash/session_state_delegate.h"
10 #include "ash/shell.h" 10 #include "ash/shell.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/mru_window_tracker.h"
13 #include "ash/wm/window_cycle_list.h" 13 #include "ash/wm/window_cycle_list.h"
14 #include "ash/wm/window_util.h" 14 #include "ash/wm/window_util.h"
15 #include "ash/wm/workspace_controller.h" 15 #include "ash/wm/workspace_controller.h"
16 #include "ui/aura/root_window.h" 16 #include "ui/aura/root_window.h"
17 #include "ui/base/events/event.h" 17 #include "ui/base/events/event.h"
18 #include "ui/base/events/event_handler.h" 18 #include "ui/base/events/event_handler.h"
19 19
20 namespace ash { 20 namespace ash {
21 21
22 namespace { 22 namespace {
23 23
24 // List of containers whose children we will cycle through.
25 const int kContainerIds[] = {
26 internal::kShellWindowId_DefaultContainer,
27 internal::kShellWindowId_AlwaysOnTopContainer
28 };
29
30 // Filter to watch for the termination of a keyboard gesture to cycle through 24 // Filter to watch for the termination of a keyboard gesture to cycle through
31 // multiple windows. 25 // multiple windows.
32 class WindowCycleEventFilter : public ui::EventHandler { 26 class WindowCycleEventFilter : public ui::EventHandler {
33 public: 27 public:
34 WindowCycleEventFilter(); 28 WindowCycleEventFilter();
35 virtual ~WindowCycleEventFilter(); 29 virtual ~WindowCycleEventFilter();
36 30
37 // Overridden from ui::EventHandler: 31 // Overridden from ui::EventHandler:
38 virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE; 32 virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE;
39 private: 33 private:
40 DISALLOW_COPY_AND_ASSIGN(WindowCycleEventFilter); 34 DISALLOW_COPY_AND_ASSIGN(WindowCycleEventFilter);
41 }; 35 };
42 36
43 // Watch for all keyboard events by filtering the root window. 37 // Watch for all keyboard events by filtering the root window.
44 WindowCycleEventFilter::WindowCycleEventFilter() { 38 WindowCycleEventFilter::WindowCycleEventFilter() {
45 } 39 }
46 40
47 WindowCycleEventFilter::~WindowCycleEventFilter() { 41 WindowCycleEventFilter::~WindowCycleEventFilter() {
48 } 42 }
49 43
50 void WindowCycleEventFilter::OnKeyEvent(ui::KeyEvent* event) { 44 void WindowCycleEventFilter::OnKeyEvent(ui::KeyEvent* event) {
51 // Views uses VKEY_MENU for both left and right Alt keys. 45 // Views uses VKEY_MENU for both left and right Alt keys.
52 if (event->key_code() == ui::VKEY_MENU && 46 if (event->key_code() == ui::VKEY_MENU &&
53 event->type() == ui::ET_KEY_RELEASED) { 47 event->type() == ui::ET_KEY_RELEASED) {
54 Shell::GetInstance()->window_cycle_controller()->AltKeyReleased(); 48 Shell::GetInstance()->window_cycle_controller()->AltKeyReleased();
55 // Warning: |this| will be deleted from here on. 49 // Warning: |this| will be deleted from here on.
56 } 50 }
57 } 51 }
58 52
59 // Adds all the children of |window| to |windows|.
60 void AddAllChildren(aura::Window* window,
61 WindowCycleList::WindowList* windows) {
62 const WindowCycleList::WindowList& children(window->children());
63 windows->insert(windows->end(), children.begin(), children.end());
64 }
65
66 // Adds all the children of all of |window|s children to |windows|.
67 void AddWorkspaceChildren(aura::Window* window,
68 WindowCycleList::WindowList* windows) {
69 for (size_t i = 0; i < window->children().size(); ++i)
70 AddAllChildren(window->children()[i], windows);
71 }
72
73 // Adds the windows that can be cycled through for the specified window id to
74 // |windows|.
75 void AddCycleWindows(aura::RootWindow* root,
76 int container_id,
77 WindowCycleList::WindowList* windows) {
78 aura::Window* container = Shell::GetContainer(root, container_id);
79 if (container_id == internal::kShellWindowId_DefaultContainer)
80 AddWorkspaceChildren(container, windows);
81 else
82 AddAllChildren(container, windows);
83 }
84
85 } // namespace 53 } // namespace
86 54
87 ////////////////////////////////////////////////////////////////////////////// 55 //////////////////////////////////////////////////////////////////////////////
88 // WindowCycleController, public: 56 // WindowCycleController, public:
89 57
90 WindowCycleController::WindowCycleController( 58 WindowCycleController::WindowCycleController() {
91 aura::client::ActivationClient* activation_client)
92 : activation_client_(activation_client) {
93 activation_client_->AddObserver(this);
94 } 59 }
95 60
96 WindowCycleController::~WindowCycleController() { 61 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 aura::Window* default_container =
106 Shell::GetContainer(*iter, internal::kShellWindowId_DefaultContainer);
107 if (default_container) {
108 for (size_t i = 0; i < default_container->children().size(); ++i) {
109 aura::Window* workspace_window = default_container->children()[i];
110 DCHECK_EQ(internal::kShellWindowId_WorkspaceContainer,
111 workspace_window->id());
112 workspace_window->RemoveObserver(this);
113 }
114 }
115 }
116
117 activation_client_->RemoveObserver(this);
118 StopCycling(); 62 StopCycling();
119 } 63 }
120 64
121 // static 65 // static
122 bool WindowCycleController::CanCycle() { 66 bool WindowCycleController::CanCycle() {
123 // Don't allow window cycling if the screen is locked or a modal dialog is 67 // Don't allow window cycling if the screen is locked or a modal dialog is
124 // open. 68 // open.
125 return !Shell::GetInstance()->session_state_delegate()->IsScreenLocked() && 69 return !Shell::GetInstance()->session_state_delegate()->IsScreenLocked() &&
126 !Shell::GetInstance()->IsSystemModalWindowOpen(); 70 !Shell::GetInstance()->IsSystemModalWindowOpen();
127 } 71 }
(...skipping 21 matching lines...) Expand all
149 StopCycling(); 93 StopCycling();
150 } 94 }
151 } 95 }
152 96
153 void WindowCycleController::HandleLinearCycleWindow() { 97 void WindowCycleController::HandleLinearCycleWindow() {
154 if (!CanCycle() || IsCycling()) 98 if (!CanCycle() || IsCycling())
155 return; 99 return;
156 100
157 // Use the reversed list of windows to prevent a 2-cycle of the most recent 101 // Use the reversed list of windows to prevent a 2-cycle of the most recent
158 // windows occurring. 102 // windows occurring.
159 WindowCycleList cycle_list(BuildWindowList(NULL,true)); 103 WindowCycleList cycle_list(MruWindowTracker::BuildWindowList(NULL,true));
sky 2013/07/29 15:31:05 nit: space after 'NULL,'
flackr 2013/07/29 22:49:11 NULL removed.
160 cycle_list.Step(WindowCycleList::FORWARD); 104 cycle_list.Step(WindowCycleList::FORWARD);
161 } 105 }
162 106
163 void WindowCycleController::AltKeyReleased() { 107 void WindowCycleController::AltKeyReleased() {
164 StopCycling(); 108 StopCycling();
165 } 109 }
166 110
167 // static
168 std::vector<aura::Window*> WindowCycleController::BuildWindowList(
169 const std::list<aura::Window*>* mru_windows,
170 bool top_most_at_end) {
171 WindowCycleList::WindowList windows;
172 Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
173
174 aura::RootWindow* active_root = Shell::GetActiveRootWindow();
175 for (Shell::RootWindowList::const_iterator iter = root_windows.begin();
176 iter != root_windows.end(); ++iter) {
177 if (*iter == active_root)
178 continue;
179 for (size_t i = 0; i < arraysize(kContainerIds); ++i)
180 AddCycleWindows(*iter, kContainerIds[i], &windows);
181 }
182
183 // Add windows in the active root windows last so that the topmost window
184 // in the active root window becomes the front of the list.
185 for (size_t i = 0; i < arraysize(kContainerIds); ++i)
186 AddCycleWindows(active_root, kContainerIds[i], &windows);
187
188 // Removes unfocusable windows.
189 WindowCycleList::WindowList::iterator last =
190 std::remove_if(
191 windows.begin(),
192 windows.end(),
193 std::not1(std::ptr_fun(ash::wm::CanActivateWindow)));
194 windows.erase(last, windows.end());
195
196 // Put the windows in the mru_windows list at the head, if it's available.
197 if (mru_windows) {
198 // Iterate through the list backwards, so that we can move each window to
199 // the front of the windows list as we find them.
200 for (std::list<aura::Window*>::const_reverse_iterator ix =
201 mru_windows->rbegin();
202 ix != mru_windows->rend(); ++ix) {
203 WindowCycleList::WindowList::iterator window =
204 std::find(windows.begin(), windows.end(), *ix);
205 if (window != windows.end()) {
206 windows.erase(window);
207 windows.push_back(*ix);
208 }
209 }
210 }
211
212 // Window cycling expects the topmost window at the front of the list.
213 if (!top_most_at_end)
214 std::reverse(windows.begin(), windows.end());
215
216 return windows;
217 }
218
219 void WindowCycleController::OnRootWindowAdded(aura::RootWindow* root_window) {
220 for (size_t i = 0; i < arraysize(kContainerIds); ++i) {
221 aura::Window* container =
222 Shell::GetContainer(root_window, kContainerIds[i]);
223 container->AddObserver(this);
224 }
225
226 aura::Window* default_container =
227 Shell::GetContainer(root_window,
228 internal::kShellWindowId_DefaultContainer);
229 for (size_t i = 0; i < default_container->children().size(); ++i) {
230 aura::Window* workspace_window = default_container->children()[i];
231 DCHECK_EQ(internal::kShellWindowId_WorkspaceContainer,
232 workspace_window->id());
233 workspace_window->AddObserver(this);
234 }
235 }
236
237 ////////////////////////////////////////////////////////////////////////////// 111 //////////////////////////////////////////////////////////////////////////////
238 // WindowCycleController, private: 112 // WindowCycleController, private:
239 113
240 void WindowCycleController::StartCycling() { 114 void WindowCycleController::StartCycling() {
241 windows_.reset(new WindowCycleList(BuildWindowList(&mru_windows_, false))); 115 windows_.reset(new WindowCycleList(ash::Shell::GetInstance()->
116 mru_window_tracker()->BuildMruWindowList(false)));
242 } 117 }
243 118
244 void WindowCycleController::Step(Direction direction) { 119 void WindowCycleController::Step(Direction direction) {
245 DCHECK(windows_.get()); 120 DCHECK(windows_.get());
246 windows_->Step(direction == FORWARD ? WindowCycleList::FORWARD : 121 windows_->Step(direction == FORWARD ? WindowCycleList::FORWARD :
247 WindowCycleList::BACKWARD); 122 WindowCycleList::BACKWARD);
248 } 123 }
249 124
250 void WindowCycleController::StopCycling() { 125 void WindowCycleController::StopCycling() {
251 windows_.reset(); 126 windows_.reset();
252 // Remove our key event filter. 127 // Remove our key event filter.
253 if (event_handler_) { 128 if (event_handler_) {
254 Shell::GetInstance()->RemovePreTargetHandler(event_handler_.get()); 129 Shell::GetInstance()->RemovePreTargetHandler(event_handler_.get());
255 event_handler_.reset(); 130 event_handler_.reset();
256 } 131 }
257
258 // Add the currently focused window to the MRU list
259 aura::Window* active_window = wm::GetActiveWindow();
260 mru_windows_.remove(active_window);
261 mru_windows_.push_front(active_window);
262 }
263
264 // static
265 bool WindowCycleController::IsTrackedContainer(aura::Window* window) {
266 if (!window)
267 return false;
268 for (size_t i = 0; i < arraysize(kContainerIds); ++i) {
269 if (window->id() == kContainerIds[i]) {
270 return true;
271 }
272 }
273 return window->id() == internal::kShellWindowId_WorkspaceContainer;
274 } 132 }
275 133
276 void WindowCycleController::InstallEventFilter() { 134 void WindowCycleController::InstallEventFilter() {
277 event_handler_.reset(new WindowCycleEventFilter()); 135 event_handler_.reset(new WindowCycleEventFilter());
278 Shell::GetInstance()->AddPreTargetHandler(event_handler_.get()); 136 Shell::GetInstance()->AddPreTargetHandler(event_handler_.get());
279 } 137 }
280 138
281 void WindowCycleController::OnWindowActivated(aura::Window* gained_active,
282 aura::Window* lost_active) {
283 if (gained_active && !IsCycling() &&
284 IsTrackedContainer(gained_active->parent())) {
285 mru_windows_.remove(gained_active);
286 mru_windows_.push_front(gained_active);
287 }
288 }
289
290 void WindowCycleController::OnWindowAdded(aura::Window* window) {
291 if (window->id() == internal::kShellWindowId_WorkspaceContainer)
292 window->AddObserver(this);
293 }
294
295 void WindowCycleController::OnWillRemoveWindow(aura::Window* window) {
296 mru_windows_.remove(window);
297 if (window->id() == internal::kShellWindowId_WorkspaceContainer)
298 window->RemoveObserver(this);
299 }
300
301 void WindowCycleController::OnWindowDestroying(aura::Window* window) {
302 window->RemoveObserver(this);
303 }
304
305 } // namespace ash 139 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698