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

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

Issue 10700057: Add always on top windows to the alt+tab list (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 8 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 | Annotate | Revision Log
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/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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 aura::Window* target, 82 aura::Window* target,
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() : mru_ignore_(false) {
93 Shell::GetInstance()->activation_controller()->AddObserver(this);
86 } 94 }
87 95
88 WindowCycleController::~WindowCycleController() { 96 WindowCycleController::~WindowCycleController() {
97 Shell::GetInstance()->activation_controller()->RemoveObserver(this);
89 StopCycling(); 98 StopCycling();
sky 2012/07/24 03:53:31 Doesn't this need to remove observers from all the
Zachary Kuznia 2012/07/30 07:49:48 No. The containers get the OnWindowDestroying not
90 } 99 }
91 100
92 // static 101 // static
93 bool WindowCycleController::CanCycle() { 102 bool WindowCycleController::CanCycle() {
94 // Don't allow window cycling if the screen is locked or a modal dialog is 103 // Don't allow window cycling if the screen is locked or a modal dialog is
95 // open. 104 // open.
96 return !Shell::GetInstance()->IsScreenLocked() && 105 return !Shell::GetInstance()->IsScreenLocked() &&
97 !Shell::GetInstance()->IsModalWindowOpen(); 106 !Shell::GetInstance()->IsModalWindowOpen();
98 } 107 }
99 108
100 void WindowCycleController::HandleCycleWindow(Direction direction, 109 void WindowCycleController::HandleCycleWindow(Direction direction,
101 bool is_alt_down) { 110 bool is_alt_down) {
102 if (!CanCycle()) 111 if (!CanCycle())
103 return; 112 return;
104 113
105 if (is_alt_down) { 114 if (is_alt_down) {
106 if (!IsCycling()) { 115 if (!IsCycling()) {
116 mru_ignore_ = true;
107 // This is the start of an alt-tab cycle through multiple windows, so 117 // This is the start of an alt-tab cycle through multiple windows, so
108 // listen for the alt key being released to stop cycling. 118 // listen for the alt key being released to stop cycling.
109 StartCycling(); 119 StartCycling();
sky 2012/07/24 03:53:31 Wouldn't it make more sense to set mru_ignore_ in
Zachary Kuznia 2012/07/30 07:49:48 Done.
110 Step(direction); 120 Step(direction);
111 InstallEventFilter(); 121 InstallEventFilter();
112 } else { 122 } else {
113 // We're in the middle of an alt-tab cycle, just step forward. 123 // We're in the middle of an alt-tab cycle, just step forward.
114 Step(direction); 124 Step(direction);
115 } 125 }
116 } else { 126 } else {
117 // This is a simple, single-step window cycle. 127 // This is a simple, single-step window cycle.
118 StartCycling(); 128 StartCycling();
119 Step(direction); 129 Step(direction);
120 StopCycling(); 130 StopCycling();
121 } 131 }
122 } 132 }
123 133
124 void WindowCycleController::AltKeyReleased() { 134 void WindowCycleController::AltKeyReleased() {
125 StopCycling(); 135 StopCycling();
136
137 // Add the currently focused window to the MRU list, and stop ignoring
138 // activations.
139 mru_ignore_ = false;
140 aura::Window* active_window = wm::GetActiveWindow();
141 mru_windows_.remove(active_window);
142 mru_windows_.push_front(active_window);
126 } 143 }
127 144
128 // static 145 // static
129 std::vector<aura::Window*> WindowCycleController::BuildWindowList() { 146 std::vector<aura::Window*> WindowCycleController::BuildWindowList(
147 std::list<aura::Window*>* mru_windows) {
sky 2012/07/24 03:53:31 const std::list&
Zachary Kuznia 2012/07/30 07:49:48 Changed to const. It needs to be a pointer, thoug
148
sky 2012/07/24 03:53:31 remove newline
Zachary Kuznia 2012/07/30 07:49:48 Done.
130 WindowCycleList::WindowList windows; 149 WindowCycleList::WindowList windows;
131 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); 150 Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
132 151
133 for (Shell::RootWindowList::const_iterator iter = root_windows.begin(); 152 for (Shell::RootWindowList::const_iterator iter = root_windows.begin();
134 iter != root_windows.end(); ++iter) { 153 iter != root_windows.end(); ++iter) {
135 if (*iter == Shell::GetActiveRootWindow()) 154 if (*iter == Shell::GetActiveRootWindow())
136 continue; 155 continue;
137 aura::Window* default_container = Shell::GetContainer( 156 for (size_t i = 0; i < arraysize(kContainerIds); ++i) {
138 *iter, internal::kShellWindowId_DefaultContainer); 157 aura::Window* container = Shell::GetContainer(*iter, kContainerIds[i]);
139 WindowCycleList::WindowList children = default_container->children(); 158 WindowCycleList::WindowList children = container->children();
159 windows.insert(windows.end(), children.begin(), children.end());
160 }
161 }
162
163 for (size_t i = 0; i < arraysize(kContainerIds); ++i) {
164 aura::Window* container =
165 Shell::GetContainer(Shell::GetActiveRootWindow(), kContainerIds[i]);
166
167 WindowCycleList::WindowList children = container->children();
140 windows.insert(windows.end(), children.begin(), children.end()); 168 windows.insert(windows.end(), children.begin(), children.end());
141 } 169 }
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 170
151 // Removes unfocusable windows. 171 // Removes unfocusable windows.
152 WindowCycleList::WindowList::iterator last = 172 WindowCycleList::WindowList::iterator last =
153 std::remove_if( 173 std::remove_if(
154 windows.begin(), 174 windows.begin(),
155 windows.end(), 175 windows.end(),
156 std::not1(std::ptr_fun(ash::wm::CanActivateWindow))); 176 std::not1(std::ptr_fun(ash::wm::CanActivateWindow)));
157 windows.erase(last, windows.end()); 177 windows.erase(last, windows.end());
178
179 // Put the windows in the mru_windows list at the head, if it's available.
sky 2012/07/24 03:53:31 Document why this uses a reverse iterator.
Zachary Kuznia 2012/07/30 07:49:48 Done.
180 if (mru_windows) {
181 for (std::list<aura::Window*>::const_reverse_iterator ix =
182 mru_windows->rbegin();
183 ix != mru_windows->rend(); ++ix) {
184 WindowCycleList::WindowList::iterator window =
185 std::find(windows.begin(), windows.end(), *ix);
186 if (window != windows.end()) {
187 windows.erase(window);
188 windows.push_back(*ix);
189 }
190 }
191 }
192
158 // Window cycling expects the topmost window at the front of the list. 193 // Window cycling expects the topmost window at the front of the list.
159 std::reverse(windows.begin(), windows.end()); 194 std::reverse(windows.begin(), windows.end());
195
160 return windows; 196 return windows;
161 } 197 }
162 198
199 void WindowCycleController::OnRootWindowAdded(aura::RootWindow* root_window) {
200 for (size_t i = 0; i < arraysize(kContainerIds); ++i) {
201 aura::Window* container =
202 Shell::GetContainer(root_window, kContainerIds[i]);
203 container->AddObserver(this);
204 }
205 }
206
163 ////////////////////////////////////////////////////////////////////////////// 207 //////////////////////////////////////////////////////////////////////////////
164 // WindowCycleController, private: 208 // WindowCycleController, private:
165 209
166 void WindowCycleController::StartCycling() { 210 void WindowCycleController::StartCycling() {
167 windows_.reset(new WindowCycleList(BuildWindowList())); 211 windows_.reset(new WindowCycleList(BuildWindowList(&mru_windows_)));
168 } 212 }
169 213
170 void WindowCycleController::Step(Direction direction) { 214 void WindowCycleController::Step(Direction direction) {
171 DCHECK(windows_.get()); 215 DCHECK(windows_.get());
172 windows_->Step(direction == FORWARD ? WindowCycleList::FORWARD : 216 windows_->Step(direction == FORWARD ? WindowCycleList::FORWARD :
173 WindowCycleList::BACKWARD); 217 WindowCycleList::BACKWARD);
174 } 218 }
175 219
176 void WindowCycleController::StopCycling() { 220 void WindowCycleController::StopCycling() {
177 windows_.reset(); 221 windows_.reset();
178 // Remove our key event filter. 222 // Remove our key event filter.
179 if (event_filter_.get()) { 223 if (event_filter_.get()) {
180 Shell::GetInstance()->RemoveEnvEventFilter(event_filter_.get()); 224 Shell::GetInstance()->RemoveEnvEventFilter(event_filter_.get());
181 event_filter_.reset(); 225 event_filter_.reset();
182 } 226 }
183 } 227 }
184 228
185 void WindowCycleController::InstallEventFilter() { 229 void WindowCycleController::InstallEventFilter() {
186 event_filter_.reset(new WindowCycleEventFilter()); 230 event_filter_.reset(new WindowCycleEventFilter());
187 Shell::GetInstance()->AddEnvEventFilter(event_filter_.get()); 231 Shell::GetInstance()->AddEnvEventFilter(event_filter_.get());
188 } 232 }
189 233
234 void WindowCycleController::OnWindowActivated(aura::Window* active,
235 aura::Window* old_active) {
236 if (active) {
237 if (!active->parent())
sky 2012/07/24 03:53:31 This code would be easier to read if you made a fu
Zachary Kuznia 2012/07/30 07:49:48 Done.
238 return;
239
240 bool ignore = true;
241 for (size_t i = 0; i < arraysize(kContainerIds); ++i) {
242 if (active->parent()->id() == kContainerIds[i]) {
243 ignore = false;
244 break;
245 }
246 }
247 if (ignore)
248 return;
249
250 if (!mru_ignore_) {
sky 2012/07/24 03:53:31 Move this check early on.
Zachary Kuznia 2012/07/30 07:49:48 Done.
251 mru_windows_.remove(active);
252 mru_windows_.push_front(active);
253 }
254 }
255 }
256
257 void WindowCycleController::OnWillRemoveWindow(aura::Window* window) {
258 mru_windows_.remove(window);
259 }
260
261 void WindowCycleController::OnWindowDestroying(aura::Window* window) {
262 window->RemoveObserver(this);
263 }
264
190 } // namespace ash 265 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698