OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/overview/window_selector.h" | 5 #include "ash/wm/overview/window_selector.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "ash/shell.h" | 9 #include "ash/shell.h" |
10 #include "ash/wm/mru_window_tracker.h" | 10 #include "ash/wm/mru_window_tracker.h" |
11 #include "ash/wm/overview/window_overview.h" | 11 #include "ash/wm/overview/window_overview.h" |
12 #include "ash/wm/overview/window_selector_delegate.h" | 12 #include "ash/wm/overview/window_selector_delegate.h" |
| 13 #include "ash/wm/overview/window_selector_panels.h" |
13 #include "ash/wm/overview/window_selector_window.h" | 14 #include "ash/wm/overview/window_selector_window.h" |
| 15 #include "ash/wm/window_settings.h" |
14 #include "base/auto_reset.h" | 16 #include "base/auto_reset.h" |
15 #include "base/timer/timer.h" | 17 #include "base/timer/timer.h" |
16 #include "ui/aura/client/activation_client.h" | 18 #include "ui/aura/client/activation_client.h" |
17 #include "ui/aura/client/focus_client.h" | 19 #include "ui/aura/client/focus_client.h" |
18 #include "ui/aura/root_window.h" | 20 #include "ui/aura/root_window.h" |
19 #include "ui/aura/window.h" | 21 #include "ui/aura/window.h" |
20 #include "ui/base/events/event.h" | 22 #include "ui/base/events/event.h" |
21 #include "ui/base/events/event_handler.h" | 23 #include "ui/base/events/event_handler.h" |
22 | 24 |
23 namespace ash { | 25 namespace ash { |
24 | 26 |
25 namespace { | 27 namespace { |
26 | 28 |
27 const int kOverviewDelayOnCycleMilliseconds = 300; | 29 const int kOverviewDelayOnCycleMilliseconds = 300; |
28 | 30 |
29 // A comparator for locating a given target window. | 31 // A comparator for locating a given target window. |
30 struct WindowSelectorWindowComparator | 32 struct WindowSelectorItemComparator |
31 : public std::unary_function<WindowSelectorWindow*, bool> { | 33 : public std::unary_function<WindowSelectorItem*, bool> { |
32 explicit WindowSelectorWindowComparator(const aura::Window* target_window) | 34 explicit WindowSelectorItemComparator(const aura::Window* target_window) |
33 : target(target_window) { | 35 : target(target_window) { |
34 } | 36 } |
35 | 37 |
36 bool operator()(const WindowSelectorWindow* window) const { | 38 bool operator()(const WindowSelectorItem* window) const { |
37 return target == window->window(); | 39 return window->TargetedWindow(target) != NULL; |
38 } | 40 } |
39 | 41 |
40 const aura::Window* target; | 42 const aura::Window* target; |
41 }; | 43 }; |
42 | 44 |
| 45 // A comparator for locating a selector item for a given root. |
| 46 struct WindowSelectorItemForRoot |
| 47 : public std::unary_function<WindowSelectorItem*, bool> { |
| 48 explicit WindowSelectorItemForRoot(const aura::RootWindow* root) |
| 49 : root_window(root) { |
| 50 } |
| 51 |
| 52 bool operator()(const WindowSelectorItem* item) const { |
| 53 return item->GetRootWindow() == root_window; |
| 54 } |
| 55 |
| 56 const aura::RootWindow* root_window; |
| 57 }; |
| 58 |
43 // Filter to watch for the termination of a keyboard gesture to cycle through | 59 // Filter to watch for the termination of a keyboard gesture to cycle through |
44 // multiple windows. | 60 // multiple windows. |
45 class WindowSelectorEventFilter : public ui::EventHandler { | 61 class WindowSelectorEventFilter : public ui::EventHandler { |
46 public: | 62 public: |
47 WindowSelectorEventFilter(WindowSelector* selector); | 63 WindowSelectorEventFilter(WindowSelector* selector); |
48 virtual ~WindowSelectorEventFilter(); | 64 virtual ~WindowSelectorEventFilter(); |
49 | 65 |
50 // Overridden from ui::EventHandler: | 66 // Overridden from ui::EventHandler: |
51 virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE; | 67 virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE; |
52 | 68 |
(...skipping 30 matching lines...) Expand all Loading... |
83 WindowSelectorDelegate* delegate) | 99 WindowSelectorDelegate* delegate) |
84 : mode_(mode), | 100 : mode_(mode), |
85 start_overview_timer_(FROM_HERE, | 101 start_overview_timer_(FROM_HERE, |
86 base::TimeDelta::FromMilliseconds(kOverviewDelayOnCycleMilliseconds), | 102 base::TimeDelta::FromMilliseconds(kOverviewDelayOnCycleMilliseconds), |
87 this, &WindowSelector::StartOverview), | 103 this, &WindowSelector::StartOverview), |
88 delegate_(delegate), | 104 delegate_(delegate), |
89 selected_window_(0), | 105 selected_window_(0), |
90 restore_focus_window_(NULL), | 106 restore_focus_window_(NULL), |
91 restoring_focus_(false) { | 107 restoring_focus_(false) { |
92 DCHECK(delegate_); | 108 DCHECK(delegate_); |
| 109 std::vector<WindowSelectorPanels*> panels_items; |
| 110 for (size_t i = 0; i < windows.size(); ++i) { |
| 111 windows[i]->AddObserver(this); |
| 112 observed_windows_.insert(windows[i]); |
| 113 |
| 114 if (windows[i]->type() == aura::client::WINDOW_TYPE_PANEL && |
| 115 wm::GetWindowSettings(windows[i])->panel_attached()) { |
| 116 // Attached panel windows are grouped into a single overview item per |
| 117 // root window (display). |
| 118 std::vector<WindowSelectorPanels*>::iterator iter = |
| 119 std::find_if(panels_items.begin(), panels_items.end(), |
| 120 WindowSelectorItemForRoot(windows[i]->GetRootWindow())); |
| 121 WindowSelectorPanels* panels_item = NULL; |
| 122 if (iter == panels_items.end()) { |
| 123 panels_item = new WindowSelectorPanels(); |
| 124 panels_items.push_back(panels_item); |
| 125 windows_.push_back(panels_item); |
| 126 } else { |
| 127 panels_item = *iter; |
| 128 } |
| 129 panels_item->AddWindow(windows[i]); |
| 130 } else { |
| 131 windows_.push_back(new WindowSelectorWindow(windows[i])); |
| 132 } |
| 133 } |
93 RemoveFocusAndSetRestoreWindow(); | 134 RemoveFocusAndSetRestoreWindow(); |
94 for (size_t i = 0; i < windows.size(); ++i) { | |
95 // restore_focus_window_ is already observed from the call to | |
96 // RemoveFocusAndSetRestoreWindow. | |
97 if (windows[i] != restore_focus_window_) | |
98 windows[i]->AddObserver(this); | |
99 windows_.push_back(new WindowSelectorWindow(windows[i])); | |
100 } | |
101 | 135 |
102 // Observe window activations and switchable containers on all root windows | 136 // Observe window activations and switchable containers on all root windows |
103 // for newly created windows during overview. | 137 // for newly created windows during overview. |
104 Shell::GetInstance()->activation_client()->AddObserver(this); | 138 Shell::GetInstance()->activation_client()->AddObserver(this); |
105 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); | 139 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); |
106 for (Shell::RootWindowList::const_iterator iter = root_windows.begin(); | 140 for (Shell::RootWindowList::const_iterator iter = root_windows.begin(); |
107 iter != root_windows.end(); ++iter) { | 141 iter != root_windows.end(); ++iter) { |
108 for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { | 142 for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { |
109 Shell::GetContainer(*iter, | 143 Shell::GetContainer(*iter, |
110 kSwitchableWindowContainerIds[i])->AddObserver(this); | 144 kSwitchableWindowContainerIds[i])->AddObserver(this); |
111 } | 145 } |
112 } | 146 } |
113 | 147 |
114 if (mode == WindowSelector::CYCLE) { | 148 if (mode == WindowSelector::CYCLE) { |
115 event_handler_.reset(new WindowSelectorEventFilter(this)); | 149 event_handler_.reset(new WindowSelectorEventFilter(this)); |
116 start_overview_timer_.Reset(); | 150 start_overview_timer_.Reset(); |
117 } else { | 151 } else { |
118 StartOverview(); | 152 StartOverview(); |
119 } | 153 } |
120 } | 154 } |
121 | 155 |
122 WindowSelector::~WindowSelector() { | 156 WindowSelector::~WindowSelector() { |
123 ResetFocusRestoreWindow(true); | 157 ResetFocusRestoreWindow(true); |
124 for (size_t i = 0; i < windows_.size(); i++) { | 158 for (std::set<aura::Window*>::iterator iter = observed_windows_.begin(); |
125 windows_[i]->window()->RemoveObserver(this); | 159 iter != observed_windows_.end(); ++iter) { |
| 160 (*iter)->RemoveObserver(this); |
126 } | 161 } |
127 Shell::GetInstance()->activation_client()->RemoveObserver(this); | 162 Shell::GetInstance()->activation_client()->RemoveObserver(this); |
128 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); | 163 Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); |
129 for (Shell::RootWindowList::const_iterator iter = root_windows.begin(); | 164 for (Shell::RootWindowList::const_iterator iter = root_windows.begin(); |
130 iter != root_windows.end(); ++iter) { | 165 iter != root_windows.end(); ++iter) { |
131 for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { | 166 for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { |
132 Shell::GetContainer(*iter, | 167 Shell::GetContainer(*iter, |
133 kSwitchableWindowContainerIds[i])->RemoveObserver(this); | 168 kSwitchableWindowContainerIds[i])->RemoveObserver(this); |
134 } | 169 } |
135 } | 170 } |
136 } | 171 } |
137 | 172 |
138 void WindowSelector::Step(WindowSelector::Direction direction) { | 173 void WindowSelector::Step(WindowSelector::Direction direction) { |
139 DCHECK_EQ(CYCLE, mode_); | 174 DCHECK_EQ(CYCLE, mode_); |
140 DCHECK(!windows_.empty()); | 175 DCHECK(!windows_.empty()); |
141 selected_window_ = (selected_window_ + windows_.size() + | 176 selected_window_ = (selected_window_ + windows_.size() + |
142 (direction == WindowSelector::FORWARD ? 1 : -1)) % windows_.size(); | 177 (direction == WindowSelector::FORWARD ? 1 : -1)) % windows_.size(); |
143 if (window_overview_) { | 178 if (window_overview_) { |
144 window_overview_->SetSelection(selected_window_); | 179 window_overview_->SetSelection(selected_window_); |
145 } else { | 180 } else { |
146 aura::Window* current_window = windows_[selected_window_]->window(); | 181 aura::Window* current_window = |
| 182 windows_[selected_window_]->SelectionWindow(); |
147 current_window->Show(); | 183 current_window->Show(); |
148 current_window->SetTransform(gfx::Transform()); | 184 current_window->SetTransform(gfx::Transform()); |
149 current_window->parent()->StackChildAtTop(current_window); | 185 current_window->parent()->StackChildAtTop(current_window); |
150 start_overview_timer_.Reset(); | 186 start_overview_timer_.Reset(); |
151 } | 187 } |
152 } | 188 } |
153 | 189 |
154 void WindowSelector::SelectWindow() { | 190 void WindowSelector::SelectWindow() { |
155 ResetFocusRestoreWindow(false); | 191 ResetFocusRestoreWindow(false); |
156 SelectWindow(windows_[selected_window_]->window()); | 192 SelectWindow(windows_[selected_window_]->SelectionWindow()); |
157 } | 193 } |
158 | 194 |
159 void WindowSelector::SelectWindow(aura::Window* window) { | 195 void WindowSelector::SelectWindow(aura::Window* window) { |
160 ScopedVector<WindowSelectorWindow>::iterator iter = | 196 ScopedVector<WindowSelectorItem>::iterator iter = |
161 std::find_if(windows_.begin(), windows_.end(), | 197 std::find_if(windows_.begin(), windows_.end(), |
162 WindowSelectorWindowComparator(window)); | 198 WindowSelectorItemComparator(window)); |
163 DCHECK(iter != windows_.end()); | 199 DCHECK(iter != windows_.end()); |
164 // The selected window should not be minimized when window selection is | 200 // The selected window should not be minimized when window selection is |
165 // ended. | 201 // ended. |
166 (*iter)->RestoreWindowOnExit(); | 202 (*iter)->RestoreWindowOnExit(window); |
167 delegate_->OnWindowSelected(window); | 203 delegate_->OnWindowSelected(window); |
168 } | 204 } |
169 | 205 |
170 void WindowSelector::CancelSelection() { | 206 void WindowSelector::CancelSelection() { |
171 delegate_->OnSelectionCanceled(); | 207 delegate_->OnSelectionCanceled(); |
172 } | 208 } |
173 | 209 |
174 void WindowSelector::OnWindowAdded(aura::Window* new_window) { | 210 void WindowSelector::OnWindowAdded(aura::Window* new_window) { |
175 if (new_window->type() != aura::client::WINDOW_TYPE_NORMAL && | 211 if (new_window->type() != aura::client::WINDOW_TYPE_NORMAL && |
176 new_window->type() != aura::client::WINDOW_TYPE_PANEL) { | 212 new_window->type() != aura::client::WINDOW_TYPE_PANEL) { |
177 return; | 213 return; |
178 } | 214 } |
179 | 215 |
180 for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { | 216 for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { |
181 if (new_window->parent()->id() == kSwitchableWindowContainerIds[i] && | 217 if (new_window->parent()->id() == kSwitchableWindowContainerIds[i] && |
182 !new_window->transient_parent()) { | 218 !new_window->transient_parent()) { |
183 // The new window is in one of the switchable containers, abort overview. | 219 // The new window is in one of the switchable containers, abort overview. |
184 CancelSelection(); | 220 CancelSelection(); |
185 return; | 221 return; |
186 } | 222 } |
187 } | 223 } |
188 } | 224 } |
189 | 225 |
190 void WindowSelector::OnWindowDestroyed(aura::Window* window) { | 226 void WindowSelector::OnWindowDestroyed(aura::Window* window) { |
191 ScopedVector<WindowSelectorWindow>::iterator iter = | 227 ScopedVector<WindowSelectorItem>::iterator iter = |
192 std::find_if(windows_.begin(), windows_.end(), | 228 std::find_if(windows_.begin(), windows_.end(), |
193 WindowSelectorWindowComparator(window)); | 229 WindowSelectorItemComparator(window)); |
194 DCHECK(window == restore_focus_window_ || iter != windows_.end()); | 230 DCHECK(window == restore_focus_window_ || iter != windows_.end()); |
195 window->RemoveObserver(this); | 231 window->RemoveObserver(this); |
196 if (window == restore_focus_window_) | 232 if (window == restore_focus_window_) |
197 restore_focus_window_ = NULL; | 233 restore_focus_window_ = NULL; |
198 if (iter == windows_.end()) | 234 if (iter == windows_.end()) |
199 return; | 235 return; |
200 | 236 |
| 237 observed_windows_.erase(window); |
| 238 (*iter)->RemoveWindow(window); |
| 239 // If there are still windows in this selector entry then the overview is |
| 240 // still active and the active selection remains the same. |
| 241 if (!(*iter)->empty()) |
| 242 return; |
| 243 |
201 size_t deleted_index = iter - windows_.begin(); | 244 size_t deleted_index = iter - windows_.begin(); |
202 (*iter)->OnWindowDestroyed(); | |
203 windows_.erase(iter); | 245 windows_.erase(iter); |
204 if (windows_.empty()) { | 246 if (windows_.empty()) { |
205 CancelSelection(); | 247 CancelSelection(); |
206 return; | 248 return; |
207 } | 249 } |
208 window_overview_->OnWindowsChanged(); | 250 if (window_overview_) |
| 251 window_overview_->OnWindowsChanged(); |
209 if (mode_ == CYCLE && selected_window_ >= deleted_index) { | 252 if (mode_ == CYCLE && selected_window_ >= deleted_index) { |
210 if (selected_window_ > deleted_index) | 253 if (selected_window_ > deleted_index) |
211 selected_window_--; | 254 selected_window_--; |
212 selected_window_ = selected_window_ % windows_.size(); | 255 selected_window_ = selected_window_ % windows_.size(); |
213 if (window_overview_) | 256 if (window_overview_) |
214 window_overview_->SetSelection(selected_window_); | 257 window_overview_->SetSelection(selected_window_); |
215 } | 258 } |
216 } | 259 } |
217 | 260 |
218 void WindowSelector::OnWindowActivated(aura::Window* gained_active, | 261 void WindowSelector::OnWindowActivated(aura::Window* gained_active, |
(...skipping 22 matching lines...) Expand all Loading... |
241 window_overview_->SetSelection(selected_window_); | 284 window_overview_->SetSelection(selected_window_); |
242 } | 285 } |
243 | 286 |
244 void WindowSelector::RemoveFocusAndSetRestoreWindow() { | 287 void WindowSelector::RemoveFocusAndSetRestoreWindow() { |
245 aura::client::FocusClient* focus_client = aura::client::GetFocusClient( | 288 aura::client::FocusClient* focus_client = aura::client::GetFocusClient( |
246 Shell::GetPrimaryRootWindow()); | 289 Shell::GetPrimaryRootWindow()); |
247 DCHECK(!restore_focus_window_); | 290 DCHECK(!restore_focus_window_); |
248 restore_focus_window_ = focus_client->GetFocusedWindow(); | 291 restore_focus_window_ = focus_client->GetFocusedWindow(); |
249 if (restore_focus_window_) { | 292 if (restore_focus_window_) { |
250 focus_client->FocusWindow(NULL); | 293 focus_client->FocusWindow(NULL); |
251 restore_focus_window_->AddObserver(this); | 294 if (observed_windows_.find(restore_focus_window_) == |
| 295 observed_windows_.end()) { |
| 296 restore_focus_window_->AddObserver(this); |
| 297 } |
252 } | 298 } |
253 } | 299 } |
254 | 300 |
255 void WindowSelector::ResetFocusRestoreWindow(bool focus) { | 301 void WindowSelector::ResetFocusRestoreWindow(bool focus) { |
256 if (!restore_focus_window_) | 302 if (!restore_focus_window_) |
257 return; | 303 return; |
258 if (focus) { | 304 if (focus) { |
259 base::AutoReset<bool> restoring_focus(&restoring_focus_, true); | 305 base::AutoReset<bool> restoring_focus(&restoring_focus_, true); |
260 restore_focus_window_->Focus(); | 306 restore_focus_window_->Focus(); |
261 } | 307 } |
262 // If the window is in the windows_ list it needs to continue to be observed. | 308 // If the window is in the observed_windows_ list it needs to continue to be |
263 if (std::find_if(windows_.begin(), windows_.end(), | 309 // observed. |
264 WindowSelectorWindowComparator(restore_focus_window_)) == | 310 if (observed_windows_.find(restore_focus_window_) == |
265 windows_.end()) { | 311 observed_windows_.end()) { |
266 restore_focus_window_->RemoveObserver(this); | 312 restore_focus_window_->RemoveObserver(this); |
267 } | 313 } |
268 restore_focus_window_ = NULL; | 314 restore_focus_window_ = NULL; |
269 } | 315 } |
270 | 316 |
271 } // namespace ash | 317 } // namespace ash |
OLD | NEW |